2
* Copyright (C) 2007 by Ivan Cukic <ivan.cukic+kde@gmail.com>
3
* Copyright (C) 2009 by Ana Cecília Martins <anaceciliamb@gmail.com>
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
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
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.
21
#include "widgetexplorer.h"
25
#include <kconfiggroup.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>
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>
42
#include "kcategorizeditemsviewmodels_p.h"
43
#include "plasmaappletitemmodel_p.h"
44
#include "appletslist.h"
45
#include "appletsfiltering.h"
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
52
using namespace KCategorizedItemsViewModels;
57
class WidgetExplorerPrivate
61
WidgetExplorerPrivate(WidgetExplorer *w)
71
void init(Plasma::Location loc);
72
void initRunningApplets();
73
void containmentDestroyed();
74
void setLocation(Plasma::Location loc);
77
* Tracks a new running applet
79
void appletAdded(Plasma::Applet *applet);
82
* A running applet is no more
84
void appletRemoved(Plasma::Applet *applet);
86
//this orientation is just for convenience, is the location that is important
87
Qt::Orientation orientation;
88
Plasma::Location location;
91
Plasma::Containment *containment;
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;
97
PlasmaAppletItemModel itemModel;
98
KCategorizedItemsViewModels::DefaultFilterModel filterModel;
101
* Widget that lists the applets
103
AppletsListWidget *appletsListWidget;
106
* Widget that contains the search and categories filters
108
FilteringWidget *filteringWidget;
109
QGraphicsLinearLayout *mainLayout;
113
void WidgetExplorerPrivate::initFilters()
115
filterModel.addFilter(i18n("All Widgets"),
116
KCategorizedItemsViewModels::Filter(), KIcon("plasma"));
119
filterModel.addFilter(i18n("Running"),
120
KCategorizedItemsViewModels::Filter("running", true),
123
filterModel.addSeparator(i18n("Categories:"));
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));
136
foreach (const catPair &category, categories) {
137
filterModel.addFilter(category.first,
138
KCategorizedItemsViewModels::Filter("category", category.second));
141
filteringWidget->setModel(&filterModel);
142
appletsListWidget->setFilterModel(&filterModel);
145
void WidgetExplorerPrivate::init(Plasma::Location loc)
147
q->setFocusPolicy(Qt::StrongFocus);
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);
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()));
164
mainLayout->addItem(filteringWidget);
165
mainLayout->addItem(appletsListWidget);
166
appletsListWidget->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
167
mainLayout->setAlignment(appletsListWidget, Qt::AlignTop | Qt::AlignHCenter);
169
if (orientation == Qt::Vertical) {
170
mainLayout->setAlignment(filteringWidget, Qt::AlignTop | Qt::AlignHCenter);
171
mainLayout->setStretchFactor(appletsListWidget, 10);
175
appletsListWidget->setItemModel(&itemModel);
176
initRunningApplets();
178
q->setLayout(mainLayout);
181
void WidgetExplorerPrivate::setLocation(const Plasma::Location loc)
183
if (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);
197
void WidgetExplorerPrivate::initRunningApplets()
199
//get applets from corona, count them, send results to model
204
Plasma::Corona *c = containment->corona();
206
//we've tried our best to get a corona
207
//we don't want just one containment, we want them all
209
kDebug() << "can't happen";
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*)));
220
foreach (Applet *applet, containment->applets()) {
221
runningApplets[applet->pluginName()]++;
225
//kDebug() << runningApplets;
226
itemModel.setRunningApplets(runningApplets);
229
void WidgetExplorerPrivate::containmentDestroyed()
234
void WidgetExplorerPrivate::appletAdded(Plasma::Applet *applet)
236
QString name = applet->pluginName();
238
runningApplets[name]++;
239
appletNames.insert(applet, name);
240
itemModel.setRunningApplets(name, runningApplets[name]);
243
void WidgetExplorerPrivate::appletRemoved(Plasma::Applet *applet)
245
Plasma::Applet *a = (Plasma::Applet *)applet; //don't care if it's valid, just need the address
247
QString name = appletNames.take(a);
250
if (runningApplets.contains(name)) {
251
count = runningApplets[name] - 1;
254
runningApplets.remove(name);
256
runningApplets[name] = count;
260
itemModel.setRunningApplets(name, count);
265
WidgetExplorer::WidgetExplorer(Plasma::Location loc, QGraphicsItem *parent)
266
:QGraphicsWidget(parent),
267
d(new WidgetExplorerPrivate(this))
272
WidgetExplorer::WidgetExplorer(QGraphicsItem *parent)
273
:QGraphicsWidget(parent),
274
d(new WidgetExplorerPrivate(this))
276
d->init(Plasma::BottomEdge);
279
WidgetExplorer::~WidgetExplorer()
284
void WidgetExplorer::setLocation(Plasma::Location loc)
287
emit(locationChanged(loc));
290
Plasma::Location WidgetExplorer::location() const
295
void WidgetExplorer::setIconSize(int size)
297
d->appletsListWidget->setIconSize(size);
301
int WidgetExplorer::iconSize() const
303
return d->appletsListWidget->iconSize();
306
void WidgetExplorer::populateWidgetList(const QString &app)
308
d->application = app;
309
d->itemModel.setApplication(app);
311
//d->appletsListWidget->setFilterModel(&d->filterModel);
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);
319
QString WidgetExplorer::application()
321
return d->application;
324
void WidgetExplorer::setContainment(Plasma::Containment *containment)
326
if (d->containment != containment) {
327
if (d->containment) {
328
d->containment->disconnect(this);
331
d->containment = containment;
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)));
337
setLocation(containment->location());
340
d->initRunningApplets();
344
Containment *WidgetExplorer::containment() const
346
return d->containment;
349
Plasma::Corona *WidgetExplorer::corona() const
351
if (d->containment) {
352
return d->containment->corona();
358
void WidgetExplorer::addApplet()
360
if (!d->containment) {
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());
371
void WidgetExplorer::addApplet(PlasmaAppletItem *appletItem)
373
if (!d->containment || !appletItem) {
377
kDebug() << appletItem->pluginName();
378
d->containment->addApplet(appletItem->pluginName());
381
void WidgetExplorer::immutabilityChanged(Plasma::ImmutabilityType type)
383
if (type != Plasma::Mutable) {
388
void WidgetExplorer::keyPressEvent(QKeyEvent *event)
390
if (event->key() == Qt::Key_Escape) {
391
// have to treat escape specially, as it makes text() return " "
392
QGraphicsWidget::keyPressEvent(event);
396
Plasma::LineEdit *lineEdit = d->filteringWidget->textSearch();
397
const QString newText = event->text();
398
if (newText.isEmpty()) {
399
QGraphicsWidget::keyPressEvent(event);
401
lineEdit->setText(lineEdit->text() + event->text());
402
lineEdit->nativeWidget()->setCursorPosition(lineEdit->text().length());
403
lineEdit->setFocus();
407
bool WidgetExplorer::event(QEvent *event)
409
switch (event->type()) {
410
case QEvent::ActionAdded:
411
case QEvent::ActionChanged:
412
case QEvent::ActionRemoved:
413
d->filteringWidget->updateActions(actions());
419
return QGraphicsWidget::event(event);
422
void WidgetExplorer::focusInEvent(QFocusEvent* event)
425
d->filteringWidget->textSearch()->setFocus();
429
} // namespace Plasma
431
#include "widgetexplorer.moc"