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

« back to all changes in this revision

Viewing changes to libs/plasmagenericshell/widgetsexplorer/widgetexplorer.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 (C) 2007 by Ivan Cukic <ivan.cukic+kde@gmail.com>
 
3
 *   Copyright (C) 2009 by Ana Cecília Martins <anaceciliamb@gmail.com>
 
4
 *
 
5
 *   This program is free software; you can redistribute it and/or modify
 
6
 *   it under the terms of the GNU Library/Lesser General Public License
 
7
 *   version 2, or (at your option) any later version, as published by the
 
8
 *   Free Software Foundation
 
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/Lesser 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 "widgetexplorer.h"
 
22
 
 
23
#include <kaction.h>
 
24
#include <kconfig.h>
 
25
#include <kconfiggroup.h>
 
26
#include <kmenu.h>
 
27
#include <kpushbutton.h>
 
28
#include <kservicetypetrader.h>
 
29
#include <kstandardaction.h>
 
30
#include <kaboutdata.h>
 
31
#include <kaboutapplicationdialog.h>
 
32
#include <kcomponentdata.h>
 
33
#include <kpluginloader.h>
 
34
#include <klineedit.h>
 
35
 
 
36
#include <plasma/applet.h>
 
37
#include <plasma/corona.h>
 
38
#include <plasma/containment.h>
 
39
#include <plasma/widgets/toolbutton.h>
 
40
#include <plasma/widgets/lineedit.h>
 
41
 
 
42
#include "kcategorizeditemsviewmodels_p.h"
 
43
#include "plasmaappletitemmodel_p.h"
 
44
#include "appletslist.h"
 
45
#include "appletsfiltering.h"
 
46
 
 
47
//getting the user local
 
48
//KGlobal::dirs()->localkdedir();
 
49
//Compare it to the entryPath of the KPluginInfo
 
50
//and see if it can be uninstalled
 
51
 
 
52
using namespace KCategorizedItemsViewModels;
 
53
 
 
54
namespace Plasma
 
55
{
 
56
 
 
57
class WidgetExplorerPrivate
 
58
{
 
59
 
 
60
public:
 
61
    WidgetExplorerPrivate(WidgetExplorer *w)
 
62
        : q(w),
 
63
          containment(0),
 
64
          itemModel(w),
 
65
          filterModel(w),
 
66
          iconSize(16)
 
67
    {
 
68
    }
 
69
 
 
70
    void initFilters();
 
71
    void init(Plasma::Location loc);
 
72
    void initRunningApplets();
 
73
    void containmentDestroyed();
 
74
    void setLocation(Plasma::Location loc);
 
75
 
 
76
    /**
 
77
     * Tracks a new running applet
 
78
     */
 
79
    void appletAdded(Plasma::Applet *applet);
 
80
 
 
81
    /**
 
82
     * A running applet is no more
 
83
     */
 
84
    void appletRemoved(Plasma::Applet *applet);
 
85
 
 
86
    //this orientation is just for convenience, is the location that is important
 
87
    Qt::Orientation orientation;
 
88
    Plasma::Location location;
 
89
    WidgetExplorer *q;
 
90
    QString application;
 
91
    Plasma::Containment *containment;
 
92
 
 
93
    QHash<QString, int> runningApplets; // applet name => count
 
94
    //extra hash so we can look up the names of deleted applets
 
95
    QHash<Plasma::Applet *,QString> appletNames;
 
96
 
 
97
    PlasmaAppletItemModel itemModel;
 
98
    KCategorizedItemsViewModels::DefaultFilterModel filterModel;
 
99
 
 
100
    /**
 
101
     * Widget that lists the applets
 
102
     */
 
103
    AppletsListWidget *appletsListWidget;
 
104
 
 
105
    /**
 
106
     * Widget that contains the search and categories filters
 
107
     */
 
108
    FilteringWidget *filteringWidget;
 
109
    QGraphicsLinearLayout *mainLayout;
 
110
    int iconSize;
 
111
};
 
112
 
 
113
void WidgetExplorerPrivate::initFilters()
 
114
{
 
115
    filterModel.addFilter(i18n("All Widgets"),
 
116
                          KCategorizedItemsViewModels::Filter(), KIcon("plasma"));
 
117
 
 
118
    // Filters: Special
 
119
    filterModel.addFilter(i18n("Running"),
 
120
                          KCategorizedItemsViewModels::Filter("running", true),
 
121
                          KIcon("dialog-ok"));
 
122
 
 
123
    filterModel.addSeparator(i18n("Categories:"));
 
124
 
 
125
    typedef QPair<QString, QString> catPair;
 
126
    QMap<QString, catPair > categories;
 
127
    QSet<QString> existingCategories = itemModel.categories();
 
128
    foreach (const QString &category, Plasma::Applet::listCategories(application)) {
 
129
        const QString lowerCaseCat = category.toLower();
 
130
        if (existingCategories.contains(lowerCaseCat)) {
 
131
            const QString trans = i18n(category.toLocal8Bit());
 
132
            categories.insert(trans.toLower(), qMakePair(trans, lowerCaseCat));
 
133
        }
 
134
    }
 
135
 
 
136
    foreach (const catPair &category, categories) {
 
137
        filterModel.addFilter(category.first,
 
138
                              KCategorizedItemsViewModels::Filter("category", category.second));
 
139
    }
 
140
 
 
141
    filteringWidget->setModel(&filterModel);
 
142
    appletsListWidget->setFilterModel(&filterModel);
 
143
}
 
144
 
 
145
void WidgetExplorerPrivate::init(Plasma::Location loc)
 
146
{
 
147
    q->setFocusPolicy(Qt::StrongFocus);
 
148
 
 
149
    //init widgets
 
150
    location = loc;
 
151
    orientation = ((location == Plasma::LeftEdge || location == Plasma::RightEdge)?Qt::Vertical:Qt::Horizontal);
 
152
    mainLayout = new QGraphicsLinearLayout(Qt::Vertical);
 
153
    mainLayout->setContentsMargins(0, 4, 0, 0);
 
154
    mainLayout->setSpacing(0);
 
155
    filteringWidget = new FilteringWidget(orientation, q);
 
156
    appletsListWidget = new AppletsListWidget(location);
 
157
 
 
158
    //connect
 
159
    QObject::connect(appletsListWidget, SIGNAL(appletDoubleClicked(PlasmaAppletItem*)), q, SLOT(addApplet(PlasmaAppletItem*)));
 
160
    QObject::connect(filteringWidget->textSearch(), SIGNAL(textChanged(QString)), appletsListWidget, SLOT(searchTermChanged(QString)));
 
161
    QObject::connect(filteringWidget, SIGNAL(filterChanged(int)), appletsListWidget, SLOT(filterChanged(int)));
 
162
    QObject::connect(filteringWidget, SIGNAL(closeClicked()), q, SIGNAL(closeClicked()));
 
163
 
 
164
    mainLayout->addItem(filteringWidget);
 
165
    mainLayout->addItem(appletsListWidget);
 
166
    appletsListWidget->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
 
167
    mainLayout->setAlignment(appletsListWidget, Qt::AlignTop | Qt::AlignHCenter);
 
168
 
 
169
    if (orientation == Qt::Vertical) {
 
170
        mainLayout->setAlignment(filteringWidget, Qt::AlignTop | Qt::AlignHCenter);
 
171
        mainLayout->setStretchFactor(appletsListWidget, 10);
 
172
    }
 
173
 
 
174
    //filters & models
 
175
    appletsListWidget->setItemModel(&itemModel);
 
176
    initRunningApplets();
 
177
 
 
178
    q->setLayout(mainLayout);
 
179
}
 
180
 
 
181
void WidgetExplorerPrivate::setLocation(const Plasma::Location loc)
 
182
{
 
183
    if (location == loc) {
 
184
        return;
 
185
    }
 
186
 
 
187
    location = loc;
 
188
    orientation = ((location == Plasma::LeftEdge || location == Plasma::RightEdge)?Qt::Vertical:Qt::Horizontal);
 
189
    filteringWidget->setListOrientation(orientation);
 
190
    appletsListWidget->setLocation(loc);
 
191
    if (orientation == Qt::Vertical) {
 
192
        mainLayout->setAlignment(filteringWidget, Qt::AlignTop | Qt::AlignHCenter);
 
193
        mainLayout->setStretchFactor(appletsListWidget, 10);
 
194
    }
 
195
}
 
196
 
 
197
void WidgetExplorerPrivate::initRunningApplets()
 
198
{
 
199
    //get applets from corona, count them, send results to model
 
200
    if (!containment) {
 
201
        return;
 
202
    }
 
203
 
 
204
    Plasma::Corona *c = containment->corona();
 
205
 
 
206
    //we've tried our best to get a corona
 
207
    //we don't want just one containment, we want them all
 
208
    if (!c) {
 
209
        kDebug() << "can't happen";
 
210
        return;
 
211
    }
 
212
 
 
213
    appletNames.clear();
 
214
    runningApplets.clear();
 
215
    QList<Containment*> containments = c->containments();
 
216
    foreach (Containment *containment, containments) {
 
217
        QObject::connect(containment, SIGNAL(appletAdded(Plasma::Applet*,QPointF)), q, SLOT(appletAdded(Plasma::Applet*)));
 
218
        QObject::connect(containment, SIGNAL(appletRemoved(Plasma::Applet*)), q, SLOT(appletRemoved(Plasma::Applet*)));
 
219
 
 
220
        foreach (Applet *applet, containment->applets()) {
 
221
            runningApplets[applet->pluginName()]++;
 
222
        }
 
223
    }
 
224
 
 
225
    //kDebug() << runningApplets;
 
226
    itemModel.setRunningApplets(runningApplets);
 
227
}
 
228
 
 
229
void WidgetExplorerPrivate::containmentDestroyed()
 
230
{
 
231
    containment = 0;
 
232
}
 
233
 
 
234
void WidgetExplorerPrivate::appletAdded(Plasma::Applet *applet)
 
235
{
 
236
    QString name = applet->pluginName();
 
237
 
 
238
    runningApplets[name]++;
 
239
    appletNames.insert(applet, name);
 
240
    itemModel.setRunningApplets(name, runningApplets[name]);
 
241
}
 
242
 
 
243
void WidgetExplorerPrivate::appletRemoved(Plasma::Applet *applet)
 
244
{
 
245
    Plasma::Applet *a = (Plasma::Applet *)applet; //don't care if it's valid, just need the address
 
246
 
 
247
    QString name = appletNames.take(a);
 
248
 
 
249
    int count = 0;
 
250
    if (runningApplets.contains(name)) {
 
251
        count = runningApplets[name] - 1;
 
252
 
 
253
        if (count < 1) {
 
254
            runningApplets.remove(name);
 
255
        } else {
 
256
            runningApplets[name] = count;
 
257
        }
 
258
    }
 
259
 
 
260
    itemModel.setRunningApplets(name, count);
 
261
}
 
262
 
 
263
//WidgetExplorer
 
264
 
 
265
WidgetExplorer::WidgetExplorer(Plasma::Location loc, QGraphicsItem *parent)
 
266
        :QGraphicsWidget(parent),
 
267
        d(new WidgetExplorerPrivate(this))
 
268
{
 
269
    d->init(loc);
 
270
}
 
271
 
 
272
WidgetExplorer::WidgetExplorer(QGraphicsItem *parent)
 
273
        :QGraphicsWidget(parent),
 
274
        d(new WidgetExplorerPrivate(this))
 
275
{
 
276
    d->init(Plasma::BottomEdge);
 
277
}
 
278
 
 
279
WidgetExplorer::~WidgetExplorer()
 
280
{
 
281
     delete d;
 
282
}
 
283
 
 
284
void WidgetExplorer::setLocation(Plasma::Location loc)
 
285
{
 
286
    d->setLocation(loc);
 
287
    emit(locationChanged(loc));
 
288
}
 
289
 
 
290
Plasma::Location WidgetExplorer::location() const
 
291
{
 
292
    return d->location;
 
293
}
 
294
 
 
295
void WidgetExplorer::setIconSize(int size)
 
296
{
 
297
    d->appletsListWidget->setIconSize(size);
 
298
    adjustSize();
 
299
}
 
300
 
 
301
int WidgetExplorer::iconSize() const
 
302
{
 
303
    return d->appletsListWidget->iconSize();
 
304
}
 
305
 
 
306
void WidgetExplorer::populateWidgetList(const QString &app)
 
307
{
 
308
    d->application = app;
 
309
    d->itemModel.setApplication(app);
 
310
    d->initFilters();
 
311
    //d->appletsListWidget->setFilterModel(&d->filterModel);
 
312
 
 
313
    //FIXME: AFAIK this shouldn't be necessary ... but here it is. need to find out what in that
 
314
    //       maze of models and views is screwing up
 
315
    d->appletsListWidget->setItemModel(&d->itemModel);
 
316
    d->itemModel.setRunningApplets(d->runningApplets);
 
317
}
 
318
 
 
319
QString WidgetExplorer::application()
 
320
{
 
321
    return d->application;
 
322
}
 
323
 
 
324
void WidgetExplorer::setContainment(Plasma::Containment *containment)
 
325
{
 
326
    if (d->containment != containment) {
 
327
        if (d->containment) {
 
328
            d->containment->disconnect(this);
 
329
        }
 
330
 
 
331
        d->containment = containment;
 
332
 
 
333
        if (d->containment) {
 
334
            connect(d->containment, SIGNAL(destroyed(QObject*)), this, SLOT(containmentDestroyed()));
 
335
            connect(d->containment, SIGNAL(immutabilityChanged(Plasma::ImmutabilityType)), this, SLOT(immutabilityChanged(Plasma::ImmutabilityType)));
 
336
 
 
337
            setLocation(containment->location());
 
338
        }
 
339
 
 
340
        d->initRunningApplets();
 
341
    }
 
342
}
 
343
 
 
344
Containment *WidgetExplorer::containment() const
 
345
{
 
346
    return d->containment;
 
347
}
 
348
 
 
349
Plasma::Corona *WidgetExplorer::corona() const
 
350
{
 
351
    if (d->containment) {
 
352
        return d->containment->corona();
 
353
    }
 
354
 
 
355
    return 0;
 
356
}
 
357
 
 
358
void WidgetExplorer::addApplet()
 
359
{
 
360
    if (!d->containment) {
 
361
        return;
 
362
    }
 
363
 
 
364
    foreach (AbstractItem *item, d->appletsListWidget->selectedItems()) {
 
365
        PlasmaAppletItem *selectedItem = (PlasmaAppletItem *) item;
 
366
        kDebug() << "Adding applet " << selectedItem->name() << "to containment";
 
367
        d->containment->addApplet(selectedItem->pluginName());
 
368
    }
 
369
}
 
370
 
 
371
void WidgetExplorer::addApplet(PlasmaAppletItem *appletItem)
 
372
{
 
373
    if (!d->containment || !appletItem) {
 
374
        return;
 
375
    }
 
376
 
 
377
    kDebug() << appletItem->pluginName();
 
378
    d->containment->addApplet(appletItem->pluginName());
 
379
}
 
380
 
 
381
void WidgetExplorer::immutabilityChanged(Plasma::ImmutabilityType type)
 
382
{
 
383
    if (type != Plasma::Mutable) {
 
384
        emit closeClicked();
 
385
    }
 
386
}
 
387
 
 
388
void WidgetExplorer::keyPressEvent(QKeyEvent *event)
 
389
{
 
390
    if (event->key() == Qt::Key_Escape) {
 
391
        // have to treat escape specially, as it makes text() return " "
 
392
        QGraphicsWidget::keyPressEvent(event);
 
393
        return;
 
394
    }
 
395
 
 
396
    Plasma::LineEdit *lineEdit = d->filteringWidget->textSearch();
 
397
    const QString newText = event->text();
 
398
    if (newText.isEmpty()) {
 
399
        QGraphicsWidget::keyPressEvent(event);
 
400
    } else {
 
401
        lineEdit->setText(lineEdit->text() + event->text());
 
402
        lineEdit->nativeWidget()->setCursorPosition(lineEdit->text().length());
 
403
        lineEdit->setFocus();
 
404
    }
 
405
}
 
406
 
 
407
bool WidgetExplorer::event(QEvent *event)
 
408
{
 
409
    switch (event->type()) {
 
410
        case QEvent::ActionAdded:
 
411
        case QEvent::ActionChanged:
 
412
        case QEvent::ActionRemoved:
 
413
            d->filteringWidget->updateActions(actions());
 
414
            break;
 
415
        default:
 
416
            break;
 
417
    }
 
418
 
 
419
    return QGraphicsWidget::event(event);
 
420
}
 
421
 
 
422
void WidgetExplorer::focusInEvent(QFocusEvent* event)
 
423
{
 
424
    Q_UNUSED(event);
 
425
    d->filteringWidget->textSearch()->setFocus();
 
426
}
 
427
 
 
428
 
 
429
} // namespace Plasma
 
430
 
 
431
#include "widgetexplorer.moc"