~ubuntu-branches/ubuntu/utopic/kde-workspace/utopic-proposed

« back to all changes in this revision

Viewing changes to plasma/netbook/containments/sal/sal.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Michał Zając
  • Date: 2011-07-09 08:31:15 UTC
  • Revision ID: james.westby@ubuntu.com-20110709083115-ohyxn6z93mily9fc
Tags: upstream-4.6.90
Import upstream version 4.6.90

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 *   Copyright 2009 by Aaron Seigo <aseigo@kde.org>
 
3
 *   Copyright 2009 by Artur Duque de Souza <asouza@kde.org>
 
4
 *   Copyright 2009 by Marco Martin <notmart@gmail.com>
 
5
 *
 
6
 *   This program is free software; you can redistribute it and/or modify
 
7
 *   it under the terms of the GNU Library General Public License version 2,
 
8
 *   or (at your option) any later version.
 
9
 *
 
10
 *   This program is distributed in the hope that it will be useful,
 
11
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
 
12
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
13
 *   GNU General Public License for more details
 
14
 *
 
15
 *   You should have received a copy of the GNU Library General Public
 
16
 *   License along with this program; if not, write to the
 
17
 *   Free Software Foundation, Inc.,
 
18
 *   51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 
19
 */
 
20
 
 
21
#include "sal.h"
 
22
#include "stripwidget.h"
 
23
#include "itemview.h"
 
24
#include "runnersconfig.h"
 
25
#include "../common/linearappletoverlay.h"
 
26
#include "../common/appletmovespacer.h"
 
27
#include "iconactioncollection.h"
 
28
#include "models/commonmodel.h"
 
29
#include "models/kservicemodel.h"
 
30
 
 
31
#include <QAction>
 
32
#include <QTimer>
 
33
#include <QGraphicsSceneMouseEvent>
 
34
#include <QGraphicsAnchorLayout>
 
35
#include <QGraphicsView>
 
36
#include <QListView>
 
37
#include <QVBoxLayout>
 
38
 
 
39
#include <KAction>
 
40
#include <KDebug>
 
41
#include <KIcon>
 
42
#include <KIconLoader>
 
43
#include <KService>
 
44
#include <KConfigDialog>
 
45
#include <KRun>
 
46
#include <KLineEdit>
 
47
#include <KKeySequenceWidget>
 
48
 
 
49
#include <Plasma/AbstractToolBox>
 
50
#include <Plasma/Theme>
 
51
#include <Plasma/Frame>
 
52
#include <Plasma/Corona>
 
53
#include <Plasma/LineEdit>
 
54
#include <Plasma/IconWidget>
 
55
#include <Plasma/RunnerManager>
 
56
#include <Plasma/ScrollWidget>
 
57
#include <Plasma/ToolButton>
 
58
 
 
59
 
 
60
SearchLaunch::SearchLaunch(QObject *parent, const QVariantList &args)
 
61
    : Containment(parent, args),
 
62
      m_runnerModel(0),
 
63
      m_backButton(0),
 
64
      m_queryCounter(0),
 
65
      m_maxColumnWidth(0),
 
66
      m_searchField(0),
 
67
      m_resultsView(0),
 
68
      m_orientation(Qt::Vertical),
 
69
      m_firstItem(0),
 
70
      m_appletsLayout(0),
 
71
      m_appletOverlay(0),
 
72
      m_iconActionCollection(0),
 
73
      m_stripUninitialized(true)
 
74
{
 
75
    setContainmentType(Containment::CustomContainment);
 
76
    m_iconActionCollection = new IconActionCollection(this, this);
 
77
    setHasConfigurationInterface(true);
 
78
    setFocusPolicy(Qt::StrongFocus);
 
79
    setFlag(QGraphicsItem::ItemIsFocusable, true);
 
80
    m_background = new Plasma::FrameSvg(this);
 
81
    m_background->setImagePath("widgets/frame");
 
82
    m_background->setElementPrefix("raised");
 
83
    m_background->setEnabledBorders(Plasma::FrameSvg::BottomBorder);
 
84
}
 
85
 
 
86
SearchLaunch::~SearchLaunch()
 
87
{
 
88
    KConfigGroup cg = config();
 
89
    m_stripWidget->save(cg);
 
90
    config().writeEntry("orientation", (int)m_orientation);
 
91
}
 
92
 
 
93
void SearchLaunch::init()
 
94
{
 
95
    Containment::init();
 
96
    connect(this, SIGNAL(appletAdded(Plasma::Applet*,QPointF)),
 
97
            this, SLOT(layoutApplet(Plasma::Applet*,QPointF)));
 
98
    connect(this, SIGNAL(appletRemoved(Plasma::Applet*)),
 
99
            this, SLOT(appletRemoved(Plasma::Applet*)));
 
100
 
 
101
    connect(this, SIGNAL(toolBoxVisibilityChanged(bool)), this, SLOT(updateConfigurationMode(bool)));
 
102
 
 
103
 
 
104
    setToolBox(Plasma::AbstractToolBox::load(corona()->preferredToolBoxPlugin(Plasma::Containment::DesktopContainment), QVariantList(), this));
 
105
 
 
106
    QAction *a = action("add widgets");
 
107
    if (a) {
 
108
        addToolBoxAction(a);
 
109
    }
 
110
 
 
111
 
 
112
    if (toolBox()) {
 
113
        connect(toolBox(), SIGNAL(toggled()), this, SIGNAL(toolBoxToggled()));
 
114
        connect(toolBox(), SIGNAL(visibilityChanged(bool)), this, SIGNAL(toolBoxVisibilityChanged(bool)));
 
115
        toolBox()->show();
 
116
    }
 
117
 
 
118
    a = action("configure");
 
119
    if (a) {
 
120
        addToolBoxAction(a);
 
121
        a->setText(i18n("Configure Search and Launch"));
 
122
    }
 
123
 
 
124
 
 
125
    QAction *lockAction = 0;
 
126
    if (corona()) {
 
127
        lockAction = corona()->action("lock widgets");
 
128
    }
 
129
 
 
130
    if (!lockAction || !lockAction->isEnabled()) {
 
131
        lockAction = new QAction(this);
 
132
        addAction("lock page", lockAction);
 
133
        lockAction->setText(i18n("Lock Page"));
 
134
        lockAction->setIcon(KIcon("object-locked"));
 
135
        QObject::connect(lockAction, SIGNAL(triggered(bool)), this, SLOT(toggleImmutability()));
 
136
    }
 
137
 
 
138
    addToolBoxAction(lockAction);
 
139
 
 
140
    //FIXME: two different use cases for the desktop and the newspaper, another reason to move the toolbox management out of here
 
141
    QAction *activityAction = 0;
 
142
    if (corona()) {
 
143
        activityAction = corona()->action("manage activities");
 
144
    }
 
145
    if (activityAction) {
 
146
        addToolBoxAction(activityAction);
 
147
    }
 
148
 
 
149
    a = new QAction(i18n("Next activity"), this);
 
150
    addAction("next containment", a);
 
151
    a = new QAction(i18n("Previous activity"), this);
 
152
    addAction("previous containment", a);
 
153
 
 
154
    if (corona()) {
 
155
        connect(corona(), SIGNAL(availableScreenRegionChanged()), this, SLOT(availableScreenRegionChanged()));
 
156
        availableScreenRegionChanged();
 
157
    }
 
158
 
 
159
    Plasma::FormFactor form = formFactor();
 
160
    Qt::Orientation layoutOtherDirection = form == Plasma::Vertical ? \
 
161
            Qt::Horizontal : Qt::Vertical;
 
162
 
 
163
    // create main layout
 
164
    m_mainLayout = new QGraphicsLinearLayout();
 
165
    m_mainLayout->setOrientation(layoutOtherDirection);
 
166
    m_mainLayout->setContentsMargins(0, 0, 0, 0);
 
167
    m_mainLayout->setSizePolicy(QSizePolicy(QSizePolicy::Expanding,
 
168
                                            QSizePolicy::Expanding));
 
169
    setLayout(m_mainLayout);
 
170
 
 
171
    // create launch grid and make it centered
 
172
    m_resultsLayout = new QGraphicsLinearLayout;
 
173
 
 
174
 
 
175
    m_resultsView = new ItemView(this);
 
176
 
 
177
    m_resultsView->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
 
178
    m_resultsView->setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded);
 
179
    m_resultsLayout->addItem(m_resultsView);
 
180
 
 
181
    connect(m_resultsView, SIGNAL(dragStartRequested(QModelIndex)), this, SLOT(resultsViewRequestedDrag(QModelIndex)));
 
182
    connect(m_resultsView, SIGNAL(itemActivated(QModelIndex)), this, SLOT(launch(QModelIndex)));
 
183
    connect(m_resultsView, SIGNAL(addActionTriggered(const QModelIndex &)), this, SLOT(addFavourite(const QModelIndex &)));
 
184
 
 
185
 
 
186
    //TODO how to do the strip widget?
 
187
    m_stripWidget = new StripWidget(this);
 
188
    m_stripWidget->setImmutability(immutability());
 
189
    connect(m_stripWidget, SIGNAL(saveNeeded()), this, SLOT(saveFavourites()));
 
190
 
 
191
    //load all config, only at this point we are sure it won't crash
 
192
    configChanged();
 
193
 
 
194
    m_appletsLayout = new QGraphicsLinearLayout(Qt::Horizontal);
 
195
    m_appletsLayout->setPreferredHeight(KIconLoader::SizeMedium);
 
196
    m_appletsLayout->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred);
 
197
    QGraphicsWidget *leftSpacer = new QGraphicsWidget(this);
 
198
    QGraphicsWidget *rightSpacer = new QGraphicsWidget(this);
 
199
    m_appletsLayout->addItem(leftSpacer);
 
200
    m_appletsLayout->addItem(rightSpacer);
 
201
 
 
202
    m_backButton = new Plasma::IconWidget(this);
 
203
    m_backButton->setIcon(KIcon("go-previous"));
 
204
    m_backButton->setText(i18n("Back"));
 
205
    m_backButton->setOrientation(Qt::Horizontal);
 
206
    m_backButton->setPreferredSize(m_backButton->sizeFromIconSize(KIconLoader::SizeSmallMedium));
 
207
    connect(m_backButton, SIGNAL(clicked()), this, SLOT(reset()));
 
208
    connect(m_resultsView, SIGNAL(resetRequested()), this, SLOT(reset()));
 
209
 
 
210
    QGraphicsAnchorLayout *searchLayout = new QGraphicsAnchorLayout();
 
211
    searchLayout->setSpacing(10);
 
212
 
 
213
    m_searchField = new Plasma::LineEdit(this);
 
214
    m_searchField->setPreferredWidth(200);
 
215
    m_searchField->nativeWidget()->setClearButtonShown(true);
 
216
    m_searchField->nativeWidget()->setClickMessage(i18n("Search..."));
 
217
    connect(m_searchField, SIGNAL(returnPressed()), this, SLOT(searchReturnPressed()));
 
218
    connect(m_searchField->nativeWidget(), SIGNAL(textEdited(const QString &)), this, SLOT(delayedQuery()));
 
219
    m_searchTimer = new QTimer(this);
 
220
    m_searchTimer->setSingleShot(true);
 
221
    connect(m_searchTimer, SIGNAL(timeout()), this, SLOT(query()));
 
222
    searchLayout->addAnchor(m_searchField, Qt::AnchorHorizontalCenter, searchLayout, Qt::AnchorHorizontalCenter);
 
223
    searchLayout->addAnchors(m_searchField, searchLayout, Qt::Vertical);
 
224
    searchLayout->addAnchors(m_backButton, searchLayout, Qt::Vertical);
 
225
    searchLayout->addAnchor(m_backButton, Qt::AnchorRight, m_searchField, Qt::AnchorLeft);
 
226
 
 
227
 
 
228
    // add our layouts to main vertical layout
 
229
    m_mainLayout->addItem(m_stripWidget);
 
230
    m_mainLayout->addItem(searchLayout);
 
231
    m_mainLayout->addItem(m_resultsLayout);
 
232
 
 
233
 
 
234
    // correctly set margins
 
235
    m_mainLayout->activate();
 
236
    m_mainLayout->updateGeometry();
 
237
 
 
238
    setTabOrder(m_stripWidget, m_searchField);
 
239
    setTabOrder(m_searchField, m_resultsView);
 
240
    setFormFactorFromLocation(location());
 
241
 
 
242
    if (action("remove")) {
 
243
        addToolBoxAction(action("remove"));
 
244
    }
 
245
}
 
246
 
 
247
void SearchLaunch::launchPackageManager()
 
248
{
 
249
    if (toolBox()) {
 
250
        toolBox()->setShowing(false);
 
251
    }
 
252
    KRun::run(*m_packageManagerService.data(), KUrl::List(), 0);
 
253
}
 
254
 
 
255
void SearchLaunch::configChanged()
 
256
{
 
257
    setOrientation((Qt::Orientation)config().readEntry("Orientation", (int)Qt::Vertical));
 
258
 
 
259
    m_stripWidget->setIconSize(config().readEntry("FavouritesIconSize", (int)KIconLoader::SizeLarge));
 
260
 
 
261
    m_resultsView->setIconSize(config().readEntry("ResultsIconSize", (int)KIconLoader::SizeHuge));
 
262
 
 
263
    QString packageManagerName = config().readEntry("PackageManager", "kpackagekit");
 
264
 
 
265
    if (!packageManagerName.isEmpty()) {
 
266
        m_packageManagerService = KService::serviceByDesktopName(packageManagerName);
 
267
 
 
268
        if (!action("add applications") && m_packageManagerService && !m_packageManagerService->exec().isEmpty()) {
 
269
            KAction *addApplicationsAction = new KAction(this);
 
270
            addAction("add applications", addApplicationsAction);
 
271
            addApplicationsAction->setText(i18n("Add applications"));
 
272
            addApplicationsAction->setIcon(KIcon("applications-other"));
 
273
            addToolBoxAction(addApplicationsAction);
 
274
 
 
275
            connect(addApplicationsAction, SIGNAL(triggered()), this, SLOT(launchPackageManager()));
 
276
        }
 
277
    }
 
278
}
 
279
 
 
280
void SearchLaunch::availableScreenRegionChanged()
 
281
{
 
282
    if (!corona()) {
 
283
        return;
 
284
    }
 
285
 
 
286
    QRect maxRect;
 
287
    int maxArea = 0;
 
288
    //we don't want the bounding rect (that could include panels too), but the maximumone representing the desktop
 
289
    foreach (const QRect &rect, corona()->availableScreenRegion(screen()).rects()) {
 
290
        int area = rect.width() * rect.height();
 
291
        if (area > maxArea) {
 
292
            maxRect = rect;
 
293
            maxArea = area;
 
294
        }
 
295
    }
 
296
 
 
297
    QGraphicsView *ownView = view();
 
298
 
 
299
    //FIXME: the second check is a workaround to a qt bug: when a qwidget has just been created, maptoglobal and mapfromglobal aren't symmetryc. remove as soon as the bug is fixed
 
300
    if (ownView && (ownView->mapFromGlobal(QPoint(0,0)) == -ownView->mapToGlobal(QPoint(0,0)))) {
 
301
        maxRect.moveTopLeft(ownView->mapFromGlobal(maxRect.topLeft()));
 
302
    }
 
303
 
 
304
    maxRect.moveTopLeft(QPoint(qMax(0, maxRect.left()), qMax(0, maxRect.top())));
 
305
 
 
306
    setContentsMargins(maxRect.left(), maxRect.top(), qMax((qreal)0.0, size().width() - maxRect.right()), qMax((qreal)0.0, size().height() - maxRect.bottom()));
 
307
}
 
308
 
 
309
void SearchLaunch::toggleImmutability()
 
310
{
 
311
    if (immutability() == Plasma::UserImmutable) {
 
312
        setImmutability(Plasma::Mutable);
 
313
    } else if (immutability() == Plasma::Mutable) {
 
314
        setImmutability(Plasma::UserImmutable);
 
315
    }
 
316
}
 
317
 
 
318
void SearchLaunch::doSearch(const QString &query, const QString &runner)
 
319
{
 
320
    if (!query.isEmpty()) {
 
321
        m_resultsView->setModel(m_runnerModel);
 
322
    } else {
 
323
        m_resultsView->setModel(m_serviceModel);
 
324
        m_serviceModel->setPath("/");
 
325
    }
 
326
 
 
327
    m_runnerModel->setQuery(query, runner);
 
328
    m_lastQuery = query;
 
329
    //enable or disable drag and drop
 
330
    if (immutability() == Plasma::Mutable && (m_resultsView->model() != m_serviceModel || m_serviceModel->path() != "/")) {
 
331
        m_resultsView->setDragAndDropMode(ItemContainer::CopyDragAndDrop);
 
332
    } else {
 
333
        m_resultsView->setDragAndDropMode(ItemContainer::NoDragAndDrop);
 
334
    }
 
335
}
 
336
 
 
337
void SearchLaunch::reset()
 
338
{
 
339
    if (m_resultsView->model() != m_serviceModel || m_serviceModel->path() != "/") {
 
340
        m_searchField->setText(QString());
 
341
        doSearch(QString());
 
342
        m_serviceModel->setPath("/");
 
343
        m_resultsView->setModel(m_serviceModel);
 
344
    }
 
345
}
 
346
 
 
347
void SearchLaunch::launch(QModelIndex index)
 
348
{
 
349
    KUrl url(index.data(CommonModel::Url).value<QString>());
 
350
 
 
351
    if (m_resultsView->model() == m_runnerModel) {
 
352
        KRunnerItemHandler::openUrl(url);
 
353
        reset();
 
354
        emit releaseVisualFocus();
 
355
    } else {
 
356
        QString id = url.path();
 
357
        if (id.startsWith(QLatin1Char('/'))) {
 
358
            id = id.remove(0, 1);
 
359
        }
 
360
        if (url.protocol() == "kservicegroup") {
 
361
            m_serviceModel->setPath(id);
 
362
        } else if (url.protocol() == "krunner") {
 
363
            m_resultsView->setModel(m_runnerModel);
 
364
            m_runnerModel->setQuery(id, url.host());
 
365
        } else {
 
366
            KServiceItemHandler::openUrl(url);
 
367
            reset();
 
368
            emit releaseVisualFocus();
 
369
        }
 
370
    }
 
371
 
 
372
    //enable or disable drag and drop
 
373
    if (immutability() == Plasma::Mutable && (m_resultsView->model() != m_serviceModel || m_serviceModel->path() != "/")) {
 
374
        m_resultsView->setDragAndDropMode(ItemContainer::CopyDragAndDrop);
 
375
    } else {
 
376
        m_resultsView->setDragAndDropMode(ItemContainer::NoDragAndDrop);
 
377
    }
 
378
}
 
379
 
 
380
void SearchLaunch::addFavourite(const QModelIndex &index)
 
381
{
 
382
    QMimeData *mimeData = m_resultsView->model()->mimeData(QModelIndexList()<<index);
 
383
    if (mimeData && !mimeData->urls().isEmpty()) {
 
384
        m_stripWidget->add(mimeData->urls().first());
 
385
    }
 
386
}
 
387
 
 
388
void SearchLaunch::layoutApplet(Plasma::Applet* applet, const QPointF &pos)
 
389
{
 
390
    Q_UNUSED(pos);
 
391
 
 
392
    if (!m_appletsLayout) {
 
393
        return;
 
394
    }
 
395
 
 
396
    if (m_appletsLayout->count() == 2) {
 
397
        m_mainLayout->removeItem(m_appletsLayout);
 
398
        m_mainLayout->addItem(m_appletsLayout);
 
399
    }
 
400
 
 
401
    Plasma::FormFactor f = formFactor();
 
402
    int insertIndex = -1;
 
403
 
 
404
    //if pos is (-1,-1) insert at the end of the panel
 
405
    if (pos != QPoint(-1, -1)) {
 
406
        for (int i = 1; i < m_appletsLayout->count()-1; ++i) {
 
407
            if (!dynamic_cast<Plasma::Applet *>(m_appletsLayout->itemAt(i)) &&
 
408
                !dynamic_cast<AppletMoveSpacer *>(m_appletsLayout->itemAt(i))) {
 
409
                continue;
 
410
            }
 
411
 
 
412
            QRectF siblingGeometry = m_appletsLayout->itemAt(i)->geometry();
 
413
            if (f == Plasma::Horizontal) {
 
414
                qreal middle = (siblingGeometry.left() + siblingGeometry.right()) / 2.0;
 
415
                if (pos.x() < middle) {
 
416
                    insertIndex = i;
 
417
                    break;
 
418
                } else if (pos.x() <= siblingGeometry.right()) {
 
419
                    insertIndex = i + 1;
 
420
                    break;
 
421
                }
 
422
            } else { // Plasma::Vertical
 
423
                qreal middle = (siblingGeometry.top() + siblingGeometry.bottom()) / 2.0;
 
424
                if (pos.y() < middle) {
 
425
                    insertIndex = i;
 
426
                    break;
 
427
                } else if (pos.y() <= siblingGeometry.bottom()) {
 
428
                    insertIndex = i + 1;
 
429
                    break;
 
430
                }
 
431
            }
 
432
        }
 
433
    }
 
434
 
 
435
    if (insertIndex != -1) {
 
436
        m_appletsLayout->insertItem(insertIndex, applet);
 
437
    } else {
 
438
        m_appletsLayout->insertItem(m_appletsLayout->count()-1, applet);
 
439
    }
 
440
 
 
441
    applet->setBackgroundHints(NoBackground);
 
442
}
 
443
 
 
444
void SearchLaunch::appletRemoved(Plasma::Applet* applet)
 
445
{
 
446
    Q_UNUSED(applet)
 
447
 
 
448
    if (!m_appletOverlay && m_appletsLayout->count() == 3) {
 
449
        m_mainLayout->removeItem(m_appletsLayout);
 
450
    }
 
451
}
 
452
 
 
453
void SearchLaunch::constraintsEvent(Plasma::Constraints constraints)
 
454
{
 
455
    //kDebug() << "constraints updated with" << constraints << "!!!!!!";
 
456
 
 
457
    if (constraints & Plasma::FormFactorConstraint ||
 
458
        constraints & Plasma::StartupCompletedConstraint) {
 
459
 
 
460
         // create the models
 
461
        if (!m_runnerModel) {
 
462
            m_runnerModel = new KRunnerModel(this);
 
463
            m_serviceModel = new KServiceModel(config(), this);
 
464
            m_resultsView->setModel(m_serviceModel);
 
465
        }
 
466
 
 
467
        resize(corona()->screenGeometry(screen()).size());
 
468
    }
 
469
 
 
470
    if (constraints & Plasma::LocationConstraint) {
 
471
        setFormFactorFromLocation(location());
 
472
    }
 
473
 
 
474
    if (constraints & Plasma::SizeConstraint) {
 
475
        availableScreenRegionChanged();
 
476
        if (m_appletsLayout) {
 
477
            m_appletsLayout->setMaximumHeight(size().height()/4);
 
478
        }
 
479
        if (m_appletOverlay) {
 
480
            m_appletOverlay->resize(size());
 
481
        }
 
482
    }
 
483
 
 
484
    if (constraints & Plasma::StartupCompletedConstraint) {
 
485
        Plasma::DataEngine *engine = dataEngine("searchlaunch");
 
486
        engine->connectSource("query", this);
 
487
    }
 
488
 
 
489
    if (constraints & Plasma::ScreenConstraint) {
 
490
        if (screen() != -1 && m_searchField) {
 
491
            m_searchField->setFocus();
 
492
        }
 
493
    }
 
494
 
 
495
    if (constraints & Plasma::ImmutableConstraint) {
 
496
        //update lock button
 
497
        QAction *a = action("lock page");
 
498
        if (a) {
 
499
            switch (immutability()) {
 
500
                case Plasma::SystemImmutable:
 
501
                    a->setEnabled(false);
 
502
                    a->setVisible(false);
 
503
                    break;
 
504
 
 
505
                case Plasma::UserImmutable:
 
506
                    a->setText(i18n("Unlock Page"));
 
507
                    a->setIcon(KIcon("object-unlocked"));
 
508
                    a->setEnabled(true);
 
509
                    a->setVisible(true);
 
510
                    break;
 
511
 
 
512
                case Plasma::Mutable:
 
513
                    a->setText(i18n("Lock Page"));
 
514
                    a->setIcon(KIcon("object-locked"));
 
515
                    a->setEnabled(true);
 
516
                    a->setVisible(true);
 
517
                    break;
 
518
            }
 
519
        }
 
520
 
 
521
        //kill or create the config overlay if needed
 
522
        if (immutability() == Plasma::Mutable && !m_appletOverlay && toolBox() && toolBox()->isShowing()) {
 
523
            m_appletOverlay = new LinearAppletOverlay(this, m_appletsLayout);
 
524
            m_appletOverlay->resize(size());
 
525
        } else if (immutability() != Plasma::Mutable && m_appletOverlay && toolBox() && toolBox()->isShowing()) {
 
526
            m_appletOverlay->deleteLater();
 
527
            m_appletOverlay = 0;
 
528
        }
 
529
 
 
530
        //enable or disable drag and drop
 
531
        if (immutability() == Plasma::Mutable && (m_resultsView->model() != m_serviceModel || m_serviceModel->path() != "/")) {
 
532
            m_resultsView->setDragAndDropMode(ItemContainer::CopyDragAndDrop);
 
533
        } else {
 
534
            m_resultsView->setDragAndDropMode(ItemContainer::NoDragAndDrop);
 
535
        }
 
536
        m_stripWidget->setImmutability(immutability());
 
537
    }
 
538
}
 
539
 
 
540
void SearchLaunch::setOrientation(Qt::Orientation orientation)
 
541
{
 
542
    if (m_orientation == orientation) {
 
543
        return;
 
544
    }
 
545
 
 
546
    m_orientation = orientation;
 
547
    m_resultsView->setOrientation(orientation);
 
548
}
 
549
 
 
550
void SearchLaunch::setFormFactorFromLocation(Plasma::Location loc)
 
551
{
 
552
    switch (loc) {
 
553
    case Plasma::BottomEdge:
 
554
    case Plasma::TopEdge:
 
555
        //kDebug() << "setting horizontal form factor";
 
556
        setFormFactor(Plasma::Horizontal);
 
557
        break;
 
558
    case Plasma::RightEdge:
 
559
    case Plasma::LeftEdge:
 
560
        //kDebug() << "setting vertical form factor";
 
561
        setFormFactor(Plasma::Vertical);
 
562
        break;
 
563
    default:
 
564
        setFormFactor(Plasma::Horizontal);
 
565
    }
 
566
}
 
567
 
 
568
void SearchLaunch::restoreStrip()
 
569
{
 
570
    KConfigGroup cg = config();
 
571
    m_stripWidget->restore(cg);
 
572
    reset();
 
573
}
 
574
 
 
575
void SearchLaunch::updateConfigurationMode(bool config)
 
576
{
 
577
 
 
578
    if (config && !m_appletOverlay && immutability() == Plasma::Mutable) {
 
579
        if (m_appletsLayout->count() == 2) {
 
580
            m_mainLayout->addItem(m_appletsLayout);
 
581
        }
 
582
        m_appletOverlay = new LinearAppletOverlay(this, m_appletsLayout);
 
583
        m_appletOverlay->resize(size());
 
584
        connect (m_appletOverlay, SIGNAL(dropRequested(QGraphicsSceneDragDropEvent *)),
 
585
                 this, SLOT(overlayRequestedDrop(QGraphicsSceneDragDropEvent *)));
 
586
    } else if (!config) {
 
587
        delete m_appletOverlay;
 
588
        m_appletOverlay = 0;
 
589
        if (m_appletsLayout->count() == 2) {
 
590
            m_mainLayout->removeItem(m_appletsLayout);
 
591
        }
 
592
    }
 
593
}
 
594
 
 
595
void SearchLaunch::overlayRequestedDrop(QGraphicsSceneDragDropEvent *event)
 
596
{
 
597
    dropEvent(event);
 
598
}
 
599
 
 
600
 
 
601
void SearchLaunch::resultsViewRequestedDrag(QModelIndex index)
 
602
{
 
603
    if (!m_resultsView->model()) {
 
604
        return;
 
605
    }
 
606
 
 
607
 
 
608
    QModelIndexList list;
 
609
    list.append(index);
 
610
    QMimeData *mimeData = m_resultsView->model()->mimeData(list);
 
611
 
 
612
    QDrag *drag = new QDrag(view());
 
613
    drag->setMimeData(mimeData);
 
614
    drag->setPixmap(index.data(Qt::DecorationRole).value<QIcon>().pixmap(KIconLoader::SizeHuge, KIconLoader::SizeHuge));
 
615
 
 
616
    drag->exec(Qt::CopyAction);
 
617
}
 
618
 
 
619
void SearchLaunch::paintInterface(QPainter *painter, const QStyleOptionGraphicsItem *, const QRect &)
 
620
{
 
621
    if (m_stripUninitialized) {
 
622
        m_stripUninitialized = false;
 
623
        QTimer::singleShot(100, this, SLOT(restoreStrip()));
 
624
    } else {
 
625
        m_background->resizeFrame(QSizeF(size().width(), m_stripWidget->geometry().bottom()));
 
626
        m_background->paintFrame(painter);
 
627
    }
 
628
}
 
629
 
 
630
void SearchLaunch::delayedQuery()
 
631
{
 
632
    m_searchTimer->start(500);
 
633
}
 
634
 
 
635
void SearchLaunch::query()
 
636
{
 
637
    QString query = m_searchField->text();
 
638
    doSearch(query);
 
639
    m_lastQuery = query;
 
640
}
 
641
 
 
642
void SearchLaunch::searchReturnPressed()
 
643
{
 
644
    QString query = m_searchField->text();
 
645
    //by pressing enter  do a query or
 
646
    if (query == m_lastQuery && !query.isEmpty()) {
 
647
        launch(m_resultsView->model()->index(0, 0, QModelIndex()));
 
648
        reset();
 
649
    } else {
 
650
        doSearch(query);
 
651
        m_lastQuery = query;
 
652
    }
 
653
}
 
654
 
 
655
void SearchLaunch::dataUpdated(const QString &sourceName, const Plasma::DataEngine::Data &data)
 
656
{
 
657
    Q_UNUSED(sourceName);
 
658
 
 
659
    const QString query(data["query"].toString());
 
660
    //Take ownership of the screen if we don't have one
 
661
    //FIXME: hardcoding 0 is bad: maybe pass the screen from the dataengine?
 
662
    if (!query.isEmpty()) {
 
663
        if (screen() < 0) {
 
664
            setScreen(0);
 
665
        }
 
666
        emit activate();
 
667
    }
 
668
 
 
669
    doSearch(query);
 
670
    if (m_searchField) {
 
671
        m_searchField->setText(query);
 
672
    }
 
673
}
 
674
 
 
675
void SearchLaunch::focusInEvent(QFocusEvent *event)
 
676
{
 
677
    if (m_searchField) {
 
678
        m_searchField->setFocus();
 
679
    }
 
680
    if (screen() < 0) {
 
681
        setScreen(0);
 
682
    }
 
683
    Containment::focusInEvent(event);
 
684
}
 
685
 
 
686
void SearchLaunch::changeEvent(QEvent *event)
 
687
{
 
688
    if (event->type() == QEvent::ContentsRectChange) {
 
689
 
 
690
        if (toolBox() && toolBox()->isShowing()) {
 
691
            updateConfigurationMode(true);
 
692
        }
 
693
    }
 
694
    Plasma::Containment::changeEvent(event);
 
695
}
 
696
 
 
697
void SearchLaunch::createConfigurationInterface(KConfigDialog *parent)
 
698
{
 
699
    RunnersConfig *runnersConfig = new RunnersConfig(m_runnerModel->runnerManager(), parent);
 
700
    parent->addPage(runnersConfig, i18nc("Title of the page that lets the user choose the loaded krunner plugins", "Search plugins"), "edit-find");
 
701
 
 
702
    connect(parent, SIGNAL(applyClicked()), runnersConfig, SLOT(accept()));
 
703
    connect(parent, SIGNAL(okClicked()), runnersConfig, SLOT(accept()));
 
704
 
 
705
    QListView *enabledEntries = new QListView(parent);
 
706
    enabledEntries->setModel(m_serviceModel->allRootEntriesModel());
 
707
    enabledEntries->setModelColumn(0);
 
708
    parent->addPage(enabledEntries, i18nc("Title of the page that lets the user choose what entries will be allowed in the main menu", "Main menu"), "view-list-icons");
 
709
 
 
710
    QWidget *page = new QWidget;
 
711
    QVBoxLayout *layout = new QVBoxLayout(page);
 
712
 
 
713
    if (!m_shortcutEditor) {
 
714
        m_shortcutEditor = new KKeySequenceWidget(page);
 
715
        connect(parent, SIGNAL(applyClicked()), this, SLOT(configDialogFinished()));
 
716
        connect(parent, SIGNAL(okClicked()), this, SLOT(configDialogFinished()));
 
717
    }
 
718
 
 
719
    m_shortcutEditor.data()->setKeySequence(globalShortcut().primary());
 
720
    layout->addWidget(m_shortcutEditor.data());
 
721
    layout->addStretch();
 
722
    parent->addPage(page, i18n("Keyboard Shortcut"), "preferences-desktop-keyboard");
 
723
 
 
724
    connect(parent, SIGNAL(applyClicked()), m_serviceModel, SLOT(saveConfig()));
 
725
    connect(parent, SIGNAL(okClicked()), m_serviceModel, SLOT(saveConfig()));
 
726
}
 
727
 
 
728
void SearchLaunch::configDialogFinished()
 
729
{
 
730
    if (m_shortcutEditor) {
 
731
        QKeySequence sequence = m_shortcutEditor.data()->keySequence();
 
732
        if (sequence != globalShortcut().primary()) {
 
733
            setGlobalShortcut(KShortcut(sequence));
 
734
            emit configNeedsSaving();
 
735
        }
 
736
    }
 
737
}
 
738
 
 
739
void SearchLaunch::saveFavourites()
 
740
{
 
741
    KConfigGroup cg = config();
 
742
    m_stripWidget->save(cg);
 
743
}
 
744
 
 
745
K_EXPORT_PLASMA_APPLET(sal, SearchLaunch)
 
746
 
 
747
#include "sal.moc"
 
748