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

« back to all changes in this revision

Viewing changes to plasma/generic/applets/systemtray/ui/applet.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
 *   applet.cpp                                                            *
 
3
 *                                                                         *
 
4
 *   Copyright (C) 2008 Jason Stubbs <jasonbstubbs@gmail.com>              *
 
5
 *   Copyright (C) 2008 Sebastian Sauer                                    *
 
6
 *   Copyright (C) 2010 Marco Martin <notmart@gmail.com>                   *
 
7
 *                                                                         *
 
8
 *   This program is free software; you can redistribute it and/or modify  *
 
9
 *   it under the terms of the GNU General Public License as published by  *
 
10
 *   the Free Software Foundation; either version 2 of the License, or     *
 
11
 *   (at your option) any later version.                                   *
 
12
 *                                                                         *
 
13
 *   This program is distributed in the hope that it will be useful,       *
 
14
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
 
15
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
 
16
 *   GNU General Public License for more details.                          *
 
17
 *                                                                         *
 
18
 *   You should have received a copy of the GNU General Public License     *
 
19
 *   along with this program; if not, write to the                         *
 
20
 *   Free Software Foundation, Inc.,                                       *
 
21
 *   51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA .        *
 
22
 ***************************************************************************/
 
23
 
 
24
#include "applet.h"
 
25
 
 
26
#include <QtCore/QProcess>
 
27
#include <QtCore/QTimer>
 
28
#include <QtGui/QApplication>
 
29
#include <QtGui/QGraphicsLayout>
 
30
#include <QtGui/QGraphicsLinearLayout>
 
31
#include <QtGui/QVBoxLayout>
 
32
#include <QtGui/QIcon>
 
33
#include <QtGui/QLabel>
 
34
#include <QtGui/QListWidget>
 
35
#include <QtGui/QTreeWidget>
 
36
#include <QtGui/QCheckBox>
 
37
#include <QtGui/QPainter>
 
38
#include <QtGui/QX11Info>
 
39
#include <QStandardItemModel>
 
40
#include <QStyledItemDelegate>
 
41
 
 
42
 
 
43
#include <KAction>
 
44
#include <KConfigDialog>
 
45
#include <KComboBox>
 
46
#include <KWindowSystem>
 
47
#include <KCategorizedView>
 
48
#include <KCategorizedSortFilterProxyModel>
 
49
#include <KCategoryDrawer>
 
50
#include <KKeySequenceWidget>
 
51
 
 
52
#include <Solid/Device>
 
53
 
 
54
#include <plasma/extender.h>
 
55
#include <plasma/extenderitem.h>
 
56
#include <plasma/extendergroup.h>
 
57
#include <plasma/framesvg.h>
 
58
#include <plasma/widgets/label.h>
 
59
#include <plasma/theme.h>
 
60
#include <plasma/dataenginemanager.h>
 
61
#include <plasma/dataengine.h>
 
62
#include <Plasma/TabBar>
 
63
#include <Plasma/Containment>
 
64
#include <Plasma/Corona>
 
65
#include <Plasma/IconWidget>
 
66
#include <Plasma/Dialog>
 
67
#include <Plasma/WindowEffects>
 
68
 
 
69
#include "config.h"
 
70
 
 
71
#include "../core/manager.h"
 
72
#include "taskarea.h"
 
73
 
 
74
static const bool DEFAULT_SHOW_APPS = true;
 
75
static const bool DEFAULT_SHOW_COMMUNICATION = true;
 
76
static const bool DEFAULT_SHOW_SERVICES = true;
 
77
static const bool DEFAULT_SHOW_HARDWARE = true;
 
78
static const bool DEFAULT_SHOW_UNKNOWN = true;
 
79
 
 
80
namespace SystemTray
 
81
{
 
82
 
 
83
 
 
84
K_EXPORT_PLASMA_APPLET(systemtray, Applet)
 
85
 
 
86
 
 
87
Manager *Applet::s_manager = 0;
 
88
int Applet::s_managerUsage = 0;
 
89
 
 
90
Applet::Applet(QObject *parent, const QVariantList &arguments)
 
91
    : Plasma::PopupApplet(parent, arguments),
 
92
      m_taskArea(0),
 
93
      m_background(0),
 
94
      m_separator(0),
 
95
      m_firstRun(true)
 
96
{
 
97
    if (!s_manager) {
 
98
        s_manager = new SystemTray::Manager();
 
99
    }
 
100
 
 
101
    ++s_managerUsage;
 
102
 
 
103
    QGraphicsLinearLayout *lay = new QGraphicsLinearLayout(this);
 
104
    lay->setContentsMargins(0, 0, 0, 0);
 
105
    m_background = new Plasma::FrameSvg(this);
 
106
    m_background->setImagePath("widgets/systemtray");
 
107
    m_background->setCacheAllRenderedFrames(true);
 
108
    m_separator = new Plasma::FrameSvg(this);
 
109
    m_separator->setImagePath("widgets/line");
 
110
    m_separator->setCacheAllRenderedFrames(true);
 
111
    m_taskArea = new TaskArea(this);
 
112
    lay->addItem(m_taskArea);
 
113
    connect(m_taskArea, SIGNAL(toggleHiddenItems()), this, SLOT(togglePopup()));
 
114
 
 
115
    m_icons = new Plasma::Svg(this);
 
116
    m_icons->setImagePath("widgets/configuration-icons");
 
117
 
 
118
    setPopupIcon(QIcon());
 
119
    setPassivePopup(false);
 
120
    setPopupAlignment(Qt::AlignRight);
 
121
    setAspectRatioMode(Plasma::IgnoreAspectRatio);
 
122
    setHasConfigurationInterface(true);
 
123
 
 
124
    connect(s_manager, SIGNAL(taskAdded(SystemTray::Task*)),
 
125
            m_taskArea, SLOT(addTask(SystemTray::Task*)));
 
126
    //TODO: we re-add the task when it changed: slightly silly!
 
127
    connect(s_manager, SIGNAL(taskChanged(SystemTray::Task*)),
 
128
            m_taskArea, SLOT(addTask(SystemTray::Task*)));
 
129
    connect(s_manager, SIGNAL(taskRemoved(SystemTray::Task*)),
 
130
            m_taskArea, SLOT(removeTask(SystemTray::Task*)));
 
131
 
 
132
    connect(m_taskArea, SIGNAL(sizeHintChanged(Qt::SizeHint)),
 
133
            this, SLOT(propogateSizeHintChange(Qt::SizeHint)));
 
134
 
 
135
    connect(Plasma::Theme::defaultTheme(), SIGNAL(themeChanged()),
 
136
            this, SLOT(themeChanged()));
 
137
}
 
138
 
 
139
Applet::~Applet()
 
140
{
 
141
    // stop listening to the manager
 
142
    disconnect(s_manager, 0, this, 0);
 
143
 
 
144
    // remove the taskArea so we can delete the widgets without it going nuts on us
 
145
    delete m_taskArea;
 
146
 
 
147
    foreach (Task *task, s_manager->tasks()) {
 
148
        // we don't care about the task updates anymore
 
149
        disconnect(task, 0, this, 0);
 
150
 
 
151
        // delete our widget (if any); some widgets (such as the extender info one)
 
152
        // may rely on the applet being around, so we need to delete them here and now
 
153
        // while we're still kicking
 
154
        delete task->widget(this, false);
 
155
    }
 
156
 
 
157
    --s_managerUsage;
 
158
    if (s_managerUsage < 1) {
 
159
        delete s_manager;
 
160
        s_manager = 0;
 
161
        s_managerUsage = 0;
 
162
    }
 
163
}
 
164
 
 
165
void Applet::init()
 
166
{
 
167
}
 
168
 
 
169
bool Applet::isFirstRun()
 
170
{
 
171
    return m_firstRun;
 
172
}
 
173
 
 
174
QGraphicsWidget *Applet::graphicsWidget()
 
175
{
 
176
    return m_taskArea->hiddenTasksWidget();
 
177
}
 
178
 
 
179
void Applet::configChanged()
 
180
{
 
181
    KConfigGroup gcg = globalConfig();
 
182
    KConfigGroup cg = config();
 
183
 
 
184
    const QStringList hiddenTypes = cg.readEntry("hidden", QStringList());
 
185
    const QStringList alwaysShownTypes = cg.readEntry("alwaysShown", QStringList());
 
186
    m_taskArea->setHiddenTypes(hiddenTypes);
 
187
    m_taskArea->setAlwaysShownTypes(alwaysShownTypes);
 
188
 
 
189
    m_shownCategories.clear();
 
190
 
 
191
    if (cg.readEntry("ShowApplicationStatus", gcg.readEntry("ShowApplicationStatus", DEFAULT_SHOW_APPS))) {
 
192
        m_shownCategories.insert(Task::ApplicationStatus);
 
193
    }
 
194
 
 
195
    if (cg.readEntry("ShowCommunications", gcg.readEntry("ShowCommunications", DEFAULT_SHOW_COMMUNICATION))) {
 
196
        m_shownCategories.insert(Task::Communications);
 
197
    }
 
198
 
 
199
    if (cg.readEntry("ShowSystemServices", gcg.readEntry("ShowSystemServices", DEFAULT_SHOW_SERVICES))) {
 
200
        m_shownCategories.insert(Task::SystemServices);
 
201
    }
 
202
 
 
203
    if (cg.readEntry("ShowHardware", gcg.readEntry("ShowHardware", DEFAULT_SHOW_HARDWARE))) {
 
204
        m_shownCategories.insert(Task::Hardware);
 
205
    }
 
206
 
 
207
    if (cg.readEntry("ShowUnknown", gcg.readEntry("ShowUnknown", DEFAULT_SHOW_UNKNOWN))) {
 
208
        m_shownCategories.insert(Task::UnknownCategory);
 
209
    }
 
210
 
 
211
    s_manager->loadApplets(this);
 
212
    m_taskArea->syncTasks(s_manager->tasks());
 
213
    checkSizes();
 
214
}
 
215
 
 
216
void Applet::popupEvent(bool)
 
217
{
 
218
    m_taskArea->updateUnhideToolIcon();
 
219
}
 
220
 
 
221
bool Applet::isPopupShowing() const
 
222
{
 
223
    if (PopupApplet::isPopupShowing()) {
 
224
        return true;
 
225
    }
 
226
 
 
227
    foreach (Task *task, s_manager->tasks()) {
 
228
        Plasma::Applet *applet = qobject_cast<Plasma::Applet*>(task->widget(const_cast<Applet *>(this), false));
 
229
        if (applet) {
 
230
            if (applet->isPopupShowing()) {
 
231
                return true;
 
232
            }
 
233
        }
 
234
    }
 
235
 
 
236
    return false;
 
237
}
 
238
 
 
239
void Applet::constraintsEvent(Plasma::Constraints constraints)
 
240
{
 
241
    if (constraints & Plasma::FormFactorConstraint) {
 
242
        QSizePolicy policy(QSizePolicy::Preferred, QSizePolicy::Preferred);
 
243
        policy.setHeightForWidth(true);
 
244
        bool vertical = formFactor() == Plasma::Vertical;
 
245
 
 
246
        if (!vertical) {
 
247
            policy.setVerticalPolicy(QSizePolicy::Expanding);
 
248
        } else {
 
249
            policy.setHorizontalPolicy(QSizePolicy::Expanding);
 
250
        }
 
251
 
 
252
        setSizePolicy(policy);
 
253
        m_taskArea->setSizePolicy(policy);
 
254
        m_taskArea->setOrientation(vertical ? Qt::Vertical : Qt::Horizontal);
 
255
    }
 
256
 
 
257
    if (constraints & Plasma::LocationConstraint) {
 
258
        m_taskArea->setLocation(location());
 
259
    }
 
260
 
 
261
    if (constraints & Plasma::SizeConstraint) {
 
262
        checkSizes();
 
263
    }
 
264
 
 
265
    if (constraints & Plasma::ImmutableConstraint) {
 
266
        if (m_visibleItemsInterface) {
 
267
            bool visible = (immutability() == Plasma::UserImmutable);
 
268
            m_visibleItemsUi.visibleItemsView->setEnabled(immutability() == Plasma::Mutable);
 
269
            m_visibleItemsUi.unlockLabel->setVisible(visible);
 
270
            m_visibleItemsUi.unlockButton->setVisible(visible);
 
271
        }
 
272
    }
 
273
 
 
274
    if (constraints & Plasma::StartupCompletedConstraint) {
 
275
        QTimer::singleShot(0, this, SLOT(checkDefaultApplets()));
 
276
        configChanged();
 
277
    }
 
278
 
 
279
    s_manager->forwardConstraintsEvent(constraints, this);
 
280
}
 
281
 
 
282
SystemTray::Manager *Applet::manager() const
 
283
{
 
284
    return s_manager;
 
285
}
 
286
 
 
287
QSet<Task::Category> Applet::shownCategories() const
 
288
{
 
289
    return m_shownCategories;
 
290
}
 
291
 
 
292
void Applet::themeChanged()
 
293
{
 
294
    checkSizes();
 
295
    update();
 
296
}
 
297
 
 
298
void Applet::checkSizes()
 
299
{
 
300
    Plasma::FormFactor f = formFactor();
 
301
    qreal leftMargin, topMargin, rightMargin, bottomMargin;
 
302
    m_background->setElementPrefix(QString());
 
303
    m_background->setEnabledBorders(Plasma::FrameSvg::AllBorders);
 
304
    m_background->getMargins(leftMargin, topMargin, rightMargin, bottomMargin);
 
305
 
 
306
    QSizeF minSize = m_taskArea->effectiveSizeHint(Qt::MinimumSize);
 
307
    if (f == Plasma::Horizontal && minSize.height() > size().height() - topMargin - bottomMargin) {
 
308
        m_background->setEnabledBorders(Plasma::FrameSvg::LeftBorder | Plasma::FrameSvg::RightBorder);
 
309
        layout()->setContentsMargins(leftMargin, 0, rightMargin, 0);
 
310
    } else if (f == Plasma::Vertical && minSize.width() > size().width() - leftMargin - rightMargin) {
 
311
        m_background->setEnabledBorders(Plasma::FrameSvg::TopBorder | Plasma::FrameSvg::BottomBorder);
 
312
        layout()->setContentsMargins(0, topMargin, 0, bottomMargin);
 
313
    } else {
 
314
        layout()->setContentsMargins(leftMargin, topMargin, rightMargin, bottomMargin);
 
315
    }
 
316
 
 
317
    static_cast<QGraphicsLayoutItem*>(m_taskArea)->updateGeometry();
 
318
 
 
319
    QSizeF preferredSize = m_taskArea->effectiveSizeHint(Qt::PreferredSize);
 
320
 
 
321
    preferredSize.setWidth(preferredSize.width() + leftMargin + rightMargin);
 
322
    preferredSize.setHeight(preferredSize.height() + topMargin + bottomMargin);
 
323
    setPreferredSize(preferredSize);
 
324
 
 
325
    QSizeF actualSize = size();
 
326
 
 
327
    setMaximumSize(QWIDGETSIZE_MAX, QWIDGETSIZE_MAX);
 
328
    if (f == Plasma::Horizontal) {
 
329
        setMinimumSize(preferredSize.width(), 0);
 
330
        setMaximumSize(preferredSize.width(), QWIDGETSIZE_MAX);
 
331
    } else if (f == Plasma::Vertical) {
 
332
        setMinimumSize(0, preferredSize.height());
 
333
        setMaximumSize(QWIDGETSIZE_MAX, preferredSize.height());
 
334
    } else if (f == Plasma::Planar) {
 
335
        setMinimumSize(preferredSize);
 
336
    }
 
337
}
 
338
 
 
339
 
 
340
void Applet::paintInterface(QPainter *painter, const QStyleOptionGraphicsItem *option, const QRect &contentsRect)
 
341
{
 
342
    Q_UNUSED(option)
 
343
 
 
344
    QRect normalRect = contentsRect;
 
345
    m_background->setElementPrefix(QString());
 
346
 
 
347
    const int leftEasement = m_taskArea->leftEasement();
 
348
    if(leftEasement > 0)
 
349
    {
 
350
        QRect firstRect(normalRect);
 
351
 
 
352
        if (formFactor() == Plasma::Vertical) {
 
353
            int margin = m_background->marginSize(Plasma::TopMargin);
 
354
            firstRect.setHeight(leftEasement + margin);
 
355
            normalRect.setY(firstRect.bottom() + 1);
 
356
        } else if (QApplication::layoutDirection() == Qt::RightToLeft) {
 
357
            int margin = m_background->marginSize(Plasma::RightMargin);
 
358
            normalRect.setWidth(normalRect.width() - leftEasement - margin);
 
359
            firstRect.setX(normalRect.right() + 1);
 
360
        } else {
 
361
            int margin = m_background->marginSize(Plasma::LeftMargin);
 
362
            firstRect.setWidth(leftEasement + margin);
 
363
            normalRect.setX(firstRect.right() + 1);
 
364
        }
 
365
 
 
366
        if (m_background->hasElementPrefix("firstelements")) {
 
367
            m_background->setElementPrefix("firstelements");
 
368
        } else {
 
369
            m_background->setElementPrefix("lastelements");
 
370
        }
 
371
        m_background->resizeFrame(contentsRect.size());
 
372
 
 
373
        painter->save();
 
374
        painter->setClipRect(firstRect, Qt::IntersectClip);
 
375
        m_background->paintFrame(painter, contentsRect, QRectF(QPointF(0, 0), contentsRect.size()));
 
376
        painter->restore();
 
377
    }
 
378
 
 
379
    const int rightEasement = m_taskArea->rightEasement();
 
380
    if(rightEasement > 0)
 
381
    {
 
382
        QRect lastRect(normalRect);
 
383
 
 
384
        if (formFactor() == Plasma::Vertical) {
 
385
            int margin = m_background->marginSize(Plasma::BottomMargin);
 
386
            normalRect.setHeight(normalRect.height() - rightEasement - margin);
 
387
            lastRect.setY(normalRect.bottom() + 1);
 
388
        } else if (QApplication::layoutDirection() == Qt::RightToLeft) {
 
389
            int margin = m_background->marginSize(Plasma::LeftMargin);
 
390
            lastRect.setWidth(rightEasement + margin);
 
391
            normalRect.setX(lastRect.right() + 1);
 
392
        } else {
 
393
            int margin = m_background->marginSize(Plasma::RightMargin);
 
394
            normalRect.setWidth(normalRect.width() - rightEasement - margin);
 
395
            lastRect.setX(normalRect.right() + 1);
 
396
        }
 
397
 
 
398
        m_background->setElementPrefix("lastelements");
 
399
        m_background->resizeFrame(contentsRect.size());
 
400
 
 
401
        painter->save();
 
402
        painter->setClipRect(lastRect, Qt::IntersectClip);
 
403
        m_background->paintFrame(painter, contentsRect, QRectF(QPointF(0, 0), contentsRect.size()));
 
404
        painter->restore();
 
405
    }
 
406
 
 
407
    m_background->setElementPrefix(QString());
 
408
    m_background->resizeFrame(contentsRect.size());
 
409
 
 
410
    painter->save();
 
411
    painter->setClipRect(normalRect, Qt::IntersectClip);
 
412
    m_background->paintFrame(painter, contentsRect, QRectF(QPointF(0, 0), contentsRect.size()));
 
413
    painter->restore();
 
414
 
 
415
    if (leftEasement > 0) {
 
416
        if (formFactor() == Plasma::Vertical) {
 
417
            if (m_separator->hasElement("horizontal-line")) {
 
418
                QSize s = m_separator->elementRect("horizontal-line").size().toSize();
 
419
                m_separator->paint(painter, QRect(normalRect.topLeft() - QPoint(0, s.height() / 2),
 
420
                                    QSize(normalRect.width(), s.height())), "horizontal-line");
 
421
            }
 
422
        } else if (m_separator->hasElement("vertical-line")) {
 
423
            QSize s = m_separator->elementRect("vertical-line").size().toSize();
 
424
            if (QApplication::layoutDirection() == Qt::RightToLeft) {
 
425
                m_separator->paint(painter, QRect(normalRect.topRight() - QPoint(s.width() / 2, 0),
 
426
                                    QSize(s.width(), normalRect.height())), "vertical-line");
 
427
            } else {
 
428
                m_separator->paint(painter, QRect(normalRect.topLeft() - QPoint(s.width() / 2, 0),
 
429
                                    QSize(s.width(), normalRect.height())), "vertical-line");
 
430
            }
 
431
        }
 
432
    }
 
433
}
 
434
 
 
435
 
 
436
void Applet::propogateSizeHintChange(Qt::SizeHint which)
 
437
{
 
438
    checkSizes();
 
439
    emit sizeHintChanged(which);
 
440
}
 
441
 
 
442
void Applet::createConfigurationInterface(KConfigDialog *parent)
 
443
{
 
444
    if (!m_autoHideInterface) {
 
445
        m_autoHideInterface = new QWidget();
 
446
        m_visibleItemsInterface = new QWidget();
 
447
 
 
448
        m_autoHideUi.setupUi(m_autoHideInterface.data());
 
449
 
 
450
        m_visibleItemsUi.setupUi(m_visibleItemsInterface.data());
 
451
 
 
452
        QAction *unlockAction = 0;
 
453
        if (containment() && containment()->corona()) {
 
454
            unlockAction = containment()->corona()->action("lock widgets");
 
455
        }
 
456
 
 
457
        if (unlockAction) {
 
458
            disconnect(m_visibleItemsUi.unlockButton, SIGNAL(clicked()), this, SLOT(unlockContainment()));
 
459
            connect(m_visibleItemsUi.unlockButton, SIGNAL(clicked()), unlockAction, SLOT(trigger()), Qt::UniqueConnection);
 
460
        } else {
 
461
            disconnect(m_visibleItemsUi.unlockButton, SIGNAL(clicked()), unlockAction, SLOT(trigger()));
 
462
            connect(m_visibleItemsUi.unlockButton, SIGNAL(clicked()), this, SLOT(unlockContainment()), Qt::UniqueConnection);
 
463
        }
 
464
 
 
465
 
 
466
        connect(parent, SIGNAL(applyClicked()), this, SLOT(configAccepted()));
 
467
        connect(parent, SIGNAL(okClicked()), this, SLOT(configAccepted()));
 
468
 
 
469
        parent->addPage(m_visibleItemsInterface.data(), i18n("Display"),
 
470
                        "preferences-desktop-notification",
 
471
                        i18n("Choose which information to show"));
 
472
        parent->addPage(m_autoHideInterface.data(), i18n("Entries"), "configure-toolbars");
 
473
 
 
474
        bool visible = (immutability() == Plasma::UserImmutable);
 
475
        //FIXME: always showing the scrollbar is due to a bug somewhere in QAbstractScrollArea,
 
476
        //QListView and/or KCategorizedView; without it, under certain circumstances it will
 
477
        //go into an infinite loop. too many people are running into this problem, so we are
 
478
        //working around the problem rather than waiting for an upstream fix, which is against
 
479
        //our usual policy.
 
480
        //to determine if this line is no longer needed in the future, comment it out, lock
 
481
        //widgets, then call up the configuration dialog for a system tray applet and click
 
482
        //on the "unlock widgets" button.
 
483
        m_visibleItemsUi.visibleItemsView->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOn);
 
484
        m_visibleItemsUi.visibleItemsView->setEnabled(immutability() == Plasma::Mutable);
 
485
        m_visibleItemsUi.unlockLabel->setVisible(visible);
 
486
        m_visibleItemsUi.unlockButton->setVisible(visible);
 
487
 
 
488
        m_visibleItemsUi.visibleItemsView->setCategoryDrawer(new KCategoryDrawerV3(m_visibleItemsUi.visibleItemsView));
 
489
        m_visibleItemsUi.visibleItemsView->setMouseTracking(true);
 
490
        m_visibleItemsUi.visibleItemsView->setVerticalScrollMode(QListView::ScrollPerPixel);
 
491
 
 
492
        KCategorizedSortFilterProxyModel *visibleItemsModel = new KCategorizedSortFilterProxyModel(m_visibleItemsUi.visibleItemsView);
 
493
        visibleItemsModel->setCategorizedModel(true);
 
494
 
 
495
        m_visibleItemsSourceModel = new QStandardItemModel(m_visibleItemsUi.visibleItemsView);
 
496
        visibleItemsModel->setSourceModel(m_visibleItemsSourceModel.data());
 
497
 
 
498
        m_visibleItemsUi.visibleItemsView->setModel(visibleItemsModel);
 
499
    }
 
500
 
 
501
    m_autoHideUi.icons->clear();
 
502
    if (m_visibleItemsSourceModel) {
 
503
        m_visibleItemsSourceModel.data()->clear();
 
504
    }
 
505
 
 
506
    QMultiMap<QString, Task *> sortedTasks;
 
507
    foreach (Task *task, s_manager->tasks()) {
 
508
        if (!m_shownCategories.contains(task->category())) {
 
509
            continue;
 
510
        }
 
511
 
 
512
        if (!task->widget(this, false)) {
 
513
            // it is not being used by this widget
 
514
            continue;
 
515
        }
 
516
 
 
517
        sortedTasks.insert(task->name(), task);
 
518
    }
 
519
 
 
520
    KConfigGroup gcg = globalConfig();
 
521
    KConfigGroup cg = config();
 
522
    KConfigGroup shortcutsConfig = KConfigGroup(&cg, "Shortcuts");
 
523
 
 
524
    foreach (Task *task, sortedTasks) {
 
525
        QTreeWidgetItem *listItem = new QTreeWidgetItem(m_autoHideUi.icons);
 
526
        KComboBox *itemCombo = new KComboBox(m_autoHideUi.icons);
 
527
        listItem->setText(0, task->name());
 
528
        listItem->setIcon(0, task->icon());
 
529
        listItem->setFlags(Qt::ItemIsEnabled);
 
530
        listItem->setData(0, Qt::UserRole, task->typeId());
 
531
 
 
532
        itemCombo->addItem(i18nc("Item will be automatically shown or hidden from the systray", "Auto"));
 
533
        itemCombo->addItem(i18nc("Item is never visible in the systray", "Hidden"));
 
534
        itemCombo->addItem(i18nc("Item is always visible in the systray", "Always Visible"));
 
535
 
 
536
        if (task->hidden() & Task::UserHidden) {
 
537
            itemCombo->setCurrentIndex(1);
 
538
        } else if (m_taskArea->alwaysShownTypes().contains(task->typeId())) {
 
539
            itemCombo->setCurrentIndex(2);
 
540
        } else {
 
541
            itemCombo->setCurrentIndex(0);
 
542
        }
 
543
        m_autoHideUi.icons->setItemWidget(listItem, 1, itemCombo);
 
544
 
 
545
        KKeySequenceWidget *button = new KKeySequenceWidget(m_autoHideUi.icons);
 
546
 
 
547
        Plasma::IconWidget *icon = qobject_cast<Plasma::IconWidget *>(task->widget(this));
 
548
        Plasma::Applet *applet = qobject_cast<Plasma::Applet *>(task->widget(this));
 
549
 
 
550
        if (task && icon) {
 
551
            QString shortcutText = shortcutsConfig.readEntryUntranslated(icon->action()->objectName(), QString());
 
552
            button->setKeySequence(shortcutText);
 
553
        } else if (task && applet) {
 
554
            button->setKeySequence(applet->globalShortcut().primary());
 
555
        //no way to have a shortcut for the fdo protocol
 
556
        } else {
 
557
            button->setEnabled(false);
 
558
        }
 
559
        m_autoHideUi.icons->setItemWidget(listItem, 2, button);
 
560
        m_autoHideUi.icons->addTopLevelItem(listItem);
 
561
 
 
562
        // try to make sure we have enough width!
 
563
        int totalWidth = 0;
 
564
        for (int i = 0; i < m_autoHideUi.icons->header()->count(); ++i) {
 
565
            totalWidth += m_autoHideUi.icons->columnWidth(i);
 
566
        }
 
567
        m_autoHideUi.icons->setMinimumWidth(totalWidth + style()->pixelMetric(QStyle::PM_ScrollBarExtent));
 
568
 
 
569
        connect(itemCombo, SIGNAL(currentIndexChanged(int)), parent, SLOT(settingsModified()));
 
570
        connect(button, SIGNAL(keySequenceChanged(QKeySequence)), parent, SLOT(settingsModified()));
 
571
    }
 
572
 
 
573
 
 
574
    const QString itemCategories = i18nc("Categories of items in the systemtray that will be shown or hidden", "Shown Item Categories");
 
575
 
 
576
    QStandardItem *applicationStatusItem = new QStandardItem();
 
577
    applicationStatusItem->setText(i18nc("Systemtray items that describe the status of a generic application", "Application status"));
 
578
    applicationStatusItem->setFlags(Qt::ItemIsUserCheckable | Qt::ItemIsEnabled);
 
579
    bool checked = cg.readEntry("ShowApplicationStatus",
 
580
                                gcg.readEntry("ShowApplicationStatus", DEFAULT_SHOW_APPS));
 
581
    applicationStatusItem->setCheckState(checked ? Qt::Checked : Qt::Unchecked);
 
582
    applicationStatusItem->setData(itemCategories, KCategorizedSortFilterProxyModel::CategoryDisplayRole);
 
583
    applicationStatusItem->setData("ShowApplicationStatus", Qt::UserRole+1);
 
584
    m_visibleItemsSourceModel.data()->appendRow(applicationStatusItem);
 
585
 
 
586
    QStandardItem *communicationsItem = new QStandardItem();
 
587
    communicationsItem->setText(i18nc("Items communication related, such as chat or email clients", "Communications"));
 
588
    communicationsItem->setFlags(Qt::ItemIsUserCheckable | Qt::ItemIsEnabled);
 
589
    checked = cg.readEntry("ShowCommunications",
 
590
                           gcg.readEntry("ShowCommunications", DEFAULT_SHOW_COMMUNICATION));
 
591
    communicationsItem->setCheckState(checked ? Qt::Checked : Qt::Unchecked);
 
592
    communicationsItem->setData(itemCategories, KCategorizedSortFilterProxyModel::CategoryDisplayRole);
 
593
    communicationsItem->setData("ShowCommunications", Qt::UserRole+1);
 
594
    m_visibleItemsSourceModel.data()->appendRow(communicationsItem);
 
595
 
 
596
    QStandardItem *systemServicesItem = new QStandardItem();
 
597
    systemServicesItem->setText(i18nc("Items about the status of the system, such as a filesystem indexer", "System services"));
 
598
    systemServicesItem->setFlags(Qt::ItemIsUserCheckable | Qt::ItemIsEnabled);
 
599
    checked = cg.readEntry("ShowSystemServices",
 
600
                           gcg.readEntry("ShowSystemServices", DEFAULT_SHOW_SERVICES));
 
601
    systemServicesItem->setCheckState(checked ? Qt::Checked : Qt::Unchecked);
 
602
    systemServicesItem->setData(itemCategories, KCategorizedSortFilterProxyModel::CategoryDisplayRole);
 
603
    systemServicesItem->setData("ShowSystemServices", Qt::UserRole+1);
 
604
    m_visibleItemsSourceModel.data()->appendRow(systemServicesItem);
 
605
 
 
606
    QStandardItem *hardwareControlItem = new QStandardItem();
 
607
    hardwareControlItem->setText(i18nc("Items about hardware, such as battery or volume control", "Hardware control"));
 
608
    hardwareControlItem->setFlags(Qt::ItemIsUserCheckable | Qt::ItemIsEnabled);
 
609
    checked = cg.readEntry("ShowHardware",
 
610
                           gcg.readEntry("ShowHardware", DEFAULT_SHOW_HARDWARE));
 
611
    hardwareControlItem->setCheckState(checked ? Qt::Checked : Qt::Unchecked);
 
612
    hardwareControlItem->setData(itemCategories, KCategorizedSortFilterProxyModel::CategoryDisplayRole);
 
613
    hardwareControlItem->setData("ShowHardware", Qt::UserRole+1);
 
614
    m_visibleItemsSourceModel.data()->appendRow(hardwareControlItem);
 
615
 
 
616
    QStandardItem *unknownItem = new QStandardItem();
 
617
    unknownItem->setText(i18nc("Other uncategorized systemtray items", "Miscellaneous"));
 
618
    unknownItem->setFlags(Qt::ItemIsUserCheckable | Qt::ItemIsEnabled);
 
619
    checked = cg.readEntry("ShowUnknown",
 
620
                           gcg.readEntry("ShowUnknown", DEFAULT_SHOW_UNKNOWN));
 
621
    unknownItem->setCheckState(checked ? Qt::Checked : Qt::Unchecked);
 
622
    unknownItem->setData(itemCategories, KCategorizedSortFilterProxyModel::CategoryDisplayRole);
 
623
    unknownItem->setData("ShowUnknown", Qt::UserRole+1);
 
624
    m_visibleItemsSourceModel.data()->appendRow(unknownItem);
 
625
 
 
626
    QStringList ownApplets = s_manager->applets(this);
 
627
 
 
628
    foreach (const KPluginInfo &info, Plasma::Applet::listAppletInfo()) {
 
629
        KService::Ptr service = info.service();
 
630
        if (service->property("X-Plasma-NotificationArea", QVariant::Bool).toBool()) {
 
631
            QStandardItem *item = new QStandardItem();
 
632
            item->setText(service->name());
 
633
            item->setIcon(KIcon(service->icon()));
 
634
            item->setCheckable(true);
 
635
            item->setCheckState(ownApplets.contains(info.pluginName()) ? Qt::Checked : Qt::Unchecked);
 
636
            item->setData(i18nc("Extra items to be manually added in the systray, such as little Plasma widgets", "Extra Items"), KCategorizedSortFilterProxyModel::CategoryDisplayRole);
 
637
            item->setData(info.pluginName(), Qt::UserRole+2);
 
638
            m_visibleItemsSourceModel.data()->appendRow(item);
 
639
        }
 
640
    }
 
641
 
 
642
    connect(m_visibleItemsSourceModel.data(), SIGNAL(itemChanged(QStandardItem*)), parent, SLOT(settingsModified()));
 
643
}
 
644
 
 
645
//not always the corona lock action is available: netbook locks per-containment
 
646
void Applet::unlockContainment()
 
647
{
 
648
    if (containment() && containment()->immutability() == Plasma::UserImmutable) {
 
649
        containment()->setImmutability(Plasma::Mutable);
 
650
    }
 
651
}
 
652
 
 
653
void Applet::configAccepted()
 
654
{
 
655
    KConfigGroup cg = config();
 
656
    KConfigGroup shortcutsConfig = KConfigGroup(&cg, "Shortcuts");
 
657
 
 
658
    QStringList hiddenTypes;
 
659
    QStringList alwaysShownTypes;
 
660
    QTreeWidget *hiddenList = m_autoHideUi.icons;
 
661
    for (int i = 0; i < hiddenList->topLevelItemCount(); ++i) {
 
662
        QTreeWidgetItem *item = hiddenList->topLevelItem(i);
 
663
        KComboBox *itemCombo = static_cast<KComboBox *>(hiddenList->itemWidget(item, 1));
 
664
        //kDebug() << (item->checkState() == Qt::Checked) << item->data(Qt::UserRole).toString();
 
665
        const QString taskTypeId = item->data(0, Qt::UserRole).toString();
 
666
        if (itemCombo->currentIndex() == 1) {
 
667
            //Always hidden
 
668
            hiddenTypes << taskTypeId;
 
669
        } else if (itemCombo->currentIndex() == 2) {
 
670
            //Always visible
 
671
            alwaysShownTypes << taskTypeId;
 
672
        }
 
673
 
 
674
        KKeySequenceWidget *keySeq = static_cast<KKeySequenceWidget *>(hiddenList->itemWidget(item, 2));
 
675
        QKeySequence seq = keySeq->keySequence();
 
676
        Task *task = 0;
 
677
        //FIXME: terribly inefficient
 
678
        foreach (Task *candidateTask, s_manager->tasks()) {
 
679
            if (candidateTask->typeId() == taskTypeId) {
 
680
                task = candidateTask;
 
681
                break;
 
682
            }
 
683
        }
 
684
 
 
685
        if (task) {
 
686
            QGraphicsWidget *widget = task->widget(this);
 
687
 
 
688
            if (widget) {
 
689
                Plasma::Applet *applet = qobject_cast<Plasma::Applet *>(widget);
 
690
                Plasma::IconWidget *icon = qobject_cast<Plasma::IconWidget *>(widget);
 
691
                if (applet) {
 
692
                    applet->setGlobalShortcut(KShortcut(seq));
 
693
                } else if (icon) {
 
694
                    KAction *action = qobject_cast<KAction *>(icon->action());
 
695
                    if (action && !seq.isEmpty()) {
 
696
                        action->setGlobalShortcut(KShortcut(seq),
 
697
                            KAction::ShortcutTypes(KAction::ActiveShortcut | KAction::DefaultShortcut),
 
698
                            KAction::NoAutoloading);
 
699
                        shortcutsConfig.writeEntry(action->objectName(), seq.toString());
 
700
                    } else if (seq.isEmpty()) {
 
701
                        action->forgetGlobalShortcut();
 
702
                        shortcutsConfig.deleteEntry(action->objectName());
 
703
                    }
 
704
                }
 
705
            }
 
706
        }
 
707
    }
 
708
 
 
709
    cg.writeEntry("hidden", hiddenTypes);
 
710
    cg.writeEntry("alwaysShown", alwaysShownTypes);
 
711
 
 
712
    QStringList applets = s_manager->applets(this);
 
713
 
 
714
    for (int i = 0; i <= m_visibleItemsSourceModel.data()->rowCount() - 1; i++) {
 
715
        QModelIndex index = m_visibleItemsSourceModel.data()->index(i, 0);
 
716
        QString itemCategory = index.data(Qt::UserRole+1).toString();
 
717
        QString appletName = index.data(Qt::UserRole+2).toString();
 
718
        if (!itemCategory.isEmpty()) {
 
719
            QStandardItem *item = m_visibleItemsSourceModel.data()->itemFromIndex(index);
 
720
            cg.writeEntry(itemCategory, (item->checkState() == Qt::Checked));
 
721
        } else if (!appletName.isEmpty()){
 
722
            QStandardItem *item = m_visibleItemsSourceModel.data()->itemFromIndex(index);
 
723
 
 
724
            if (item->checkState() != Qt::Unchecked && !applets.contains(appletName)) {
 
725
                s_manager->addApplet(appletName, this);
 
726
            }
 
727
 
 
728
            if (item->checkState() == Qt::Checked) {
 
729
                applets.removeAll(appletName);
 
730
            }
 
731
        }
 
732
    }
 
733
 
 
734
    foreach (const QString &appletName, applets) {
 
735
        s_manager->removeApplet(appletName, this);
 
736
    }
 
737
 
 
738
    emit configNeedsSaving();
 
739
}
 
740
 
 
741
void Applet::checkDefaultApplets()
 
742
{
 
743
    if (config().readEntry("DefaultAppletsAdded", false)) {
 
744
        m_firstRun = false;
 
745
        return;
 
746
    }
 
747
 
 
748
 
 
749
    QStringList applets = s_manager->applets(this);
 
750
    if (!applets.contains("org.kde.networkmanagement")) {
 
751
        s_manager->addApplet("org.kde.networkmanagement", this);
 
752
    }
 
753
 
 
754
    if (!applets.contains("notifier")) {
 
755
        s_manager->addApplet("notifier", this);
 
756
    }
 
757
 
 
758
    if (!applets.contains("notifications")) {
 
759
        s_manager->addApplet("notifications", this);
 
760
    }
 
761
 
 
762
    if (!applets.contains("battery")) {
 
763
        Plasma::DataEngineManager *engines = Plasma::DataEngineManager::self();
 
764
        Plasma::DataEngine *power = engines->loadEngine("powermanagement");
 
765
        if (power) {
 
766
            const QStringList &batteries = power->query("Battery")["Sources"].toStringList();
 
767
            if (!batteries.isEmpty()) {
 
768
                s_manager->addApplet("battery", this);
 
769
            }
 
770
        }
 
771
        engines->unloadEngine("powermanagement");
 
772
    }
 
773
 
 
774
    config().writeEntry("DefaultAppletsAdded", true);
 
775
}
 
776
 
 
777
}
 
778
 
 
779
#include "applet.moc"