• Skip to content
  • Skip to link menu
KDE 4.2 API Reference
  • KDE API Reference
  • API Reference
  • Sitemap
  • Contact Us
 

Applets

applet.cpp

Go to the documentation of this file.
00001 /***************************************************************************
00002  *   applet.cpp                                                            *
00003  *                                                                         *
00004  *   Copyright (C) 2008 Jason Stubbs <jasonbstubbs@gmail.com>              *
00005  *   Copyright (C) 2008 Sebastian Sauer                                    *
00006  *                                                                         *
00007  *   This program is free software; you can redistribute it and/or modify  *
00008  *   it under the terms of the GNU General Public License as published by  *
00009  *   the Free Software Foundation; either version 2 of the License, or     *
00010  *   (at your option) any later version.                                   *
00011  *                                                                         *
00012  *   This program is distributed in the hope that it will be useful,       *
00013  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
00014  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
00015  *   GNU General Public License for more details.                          *
00016  *                                                                         *
00017  *   You should have received a copy of the GNU General Public License     *
00018  *   along with this program; if not, write to the                         *
00019  *   Free Software Foundation, Inc.,                                       *
00020  *   51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA .        *
00021  ***************************************************************************/
00022 
00023 #include "applet.h"
00024 #include "jobwidget.h"
00025 #include "notificationwidget.h"
00026 #include "taskarea.h"
00027 
00028 #include <QtGui/QApplication>
00029 #include <QtGui/QGraphicsLayout>
00030 #include <QtGui/QIcon>
00031 #include <QtGui/QListWidget>
00032 #include <QtGui/QPainter>
00033 
00034 #include <KActionSelector>
00035 #include <KConfigDialog>
00036 
00037 #include <Solid/Device>
00038 
00039 #include <plasma/extender.h>
00040 #include <plasma/extenderitem.h>
00041 #include <plasma/framesvg.h>
00042 #include <plasma/theme.h>
00043 
00044 #include "../core/manager.h"
00045 #include "../core/task.h"
00046 #include "extendertask.h"
00047 
00048 
00049 namespace SystemTray
00050 {
00051 
00052 K_EXPORT_PLASMA_APPLET(systemtray, Applet)
00053 
00054 
00055 class Applet::Private
00056 {
00057 public:
00058     Private(Applet *q)
00059         : q(q),
00060           taskArea(0),
00061           configInterface(0),
00062           background(0),
00063           extenderTask(0)
00064     {
00065         if (!s_manager) {
00066             s_manager = new SystemTray::Manager();
00067         }
00068 
00069         ++s_managerUsage;
00070     }
00071 
00072     ~Private()
00073     {
00074         --s_managerUsage;
00075         if (s_managerUsage < 1) {
00076             delete s_manager;
00077             s_manager = 0;
00078             s_managerUsage = 0;
00079         }
00080     }
00081 
00082     void setTaskAreaGeometry();
00083 
00084     Applet *q;
00085 
00086     TaskArea *taskArea;
00087     QPointer<KActionSelector> configInterface;
00088 
00089     Plasma::FrameSvg *background;
00090     SystemTray::ExtenderTask *extenderTask;
00091     static SystemTray::Manager *s_manager;
00092     static int s_managerUsage;
00093 };
00094 
00095 Manager *Applet::Private::s_manager = 0;
00096 int Applet::Private::s_managerUsage = 0;
00097 
00098 Applet::Applet(QObject *parent, const QVariantList &arguments)
00099     : Plasma::PopupApplet(parent, arguments),
00100       d(new Private(this))
00101 {
00102     d->background = new Plasma::FrameSvg(this);
00103     d->background->setImagePath("widgets/systemtray");
00104     d->background->setCacheAllRenderedFrames(true);
00105     d->taskArea = new TaskArea(this);
00106 
00107     setPopupIcon(QIcon());
00108     setPassivePopup(true);
00109     setAspectRatioMode(Plasma::IgnoreAspectRatio);
00110     setBackgroundHints(NoBackground);
00111     setHasConfigurationInterface(true);
00112 }
00113 
00114 Applet::~Applet()
00115 {
00116     //destroy any item in the systray, since it doesn't make sense for not detached notifications
00117     //and jobs to stay around after a plasma reboot
00118     foreach (Plasma::ExtenderItem *item, extender()->attachedItems()) {
00119         item->destroy();
00120     }
00121 
00122     delete d;
00123 }
00124 
00125 void Applet::init()
00126 {
00127     KConfigGroup cg = config();
00128     QStringList hiddenTypes = cg.readEntry("hidden", QStringList());
00129 
00130     d->setTaskAreaGeometry();
00131     connect(Private::s_manager, SIGNAL(taskAdded(SystemTray::Task*)),
00132             d->taskArea, SLOT(addTask(SystemTray::Task*)));
00133     connect(Private::s_manager, SIGNAL(taskChanged(SystemTray::Task*)),
00134             d->taskArea, SLOT(addTask(SystemTray::Task*)));
00135     connect(Private::s_manager, SIGNAL(taskRemoved(SystemTray::Task*)),
00136             d->taskArea, SLOT(removeTask(SystemTray::Task*)));
00137 
00138     d->taskArea->setHiddenTypes(hiddenTypes);
00139     connect(d->taskArea, SIGNAL(sizeHintChanged(Qt::SizeHint)),
00140             this, SLOT(propogateSizeHintChange(Qt::SizeHint)));
00141 
00142     connect(Plasma::Theme::defaultTheme(), SIGNAL(themeChanged()),
00143             this, SLOT(checkSizes()));
00144     checkSizes();
00145 
00146     d->taskArea->syncTasks(Private::s_manager->tasks());
00147 
00148     extender()->setEmptyExtenderMessage(i18n("No notifications and no jobs"));
00149 
00150     KConfigGroup globalCg = globalConfig();
00151     if (globalCg.readEntry("ShowJobs", true)) {
00152         Private::s_manager->registerJobProtocol();
00153         connect(Private::s_manager, SIGNAL(jobAdded(SystemTray::Job*)),
00154                 this, SLOT(addJob(SystemTray::Job*)));
00155     }
00156 
00157     if (globalCg.readEntry("ShowNotifications", true)) {
00158         Private::s_manager->registerNotificationProtocol();
00159         connect(Private::s_manager, SIGNAL(notificationAdded(SystemTray::Notification*)),
00160                 this, SLOT(addNotification(SystemTray::Notification*)));
00161     }
00162 }
00163 
00164 void Applet::constraintsEvent(Plasma::Constraints constraints)
00165 {
00166     setBackgroundHints(NoBackground);
00167     if (constraints & Plasma::FormFactorConstraint) {
00168         QSizePolicy policy(QSizePolicy::Preferred, QSizePolicy::Preferred);
00169         policy.setHeightForWidth(true);
00170         bool vertical = formFactor() == Plasma::Vertical;
00171 
00172         if (!vertical) {
00173             policy.setVerticalPolicy(QSizePolicy::Expanding);
00174         } else {
00175             policy.setHorizontalPolicy(QSizePolicy::Expanding);
00176         }
00177 
00178         setSizePolicy(policy);
00179         d->taskArea->setSizePolicy(policy);
00180         d->taskArea->setOrientation(vertical ? Qt::Vertical : Qt::Horizontal);
00181     }
00182 
00183     if (constraints & Plasma::SizeConstraint) {
00184         checkSizes();
00185     }
00186 }
00187 
00188 
00189 SystemTray::Manager *Applet::manager() const
00190 {
00191     return d->s_manager;
00192 }
00193 
00194 
00195 void Applet::setGeometry(const QRectF &rect)
00196 {
00197     Plasma::Applet::setGeometry(rect);
00198 
00199     if (d->taskArea) {
00200         d->setTaskAreaGeometry();
00201     }
00202 }
00203 
00204 
00205 void Applet::checkSizes()
00206 {
00207     d->taskArea->checkSizes();
00208 
00209     qreal leftMargin, topMargin, rightMargin, bottomMargin;
00210     d->background->getMargins(leftMargin, topMargin, rightMargin, bottomMargin);
00211     setContentsMargins(leftMargin, topMargin, rightMargin, bottomMargin);
00212 
00213     QSizeF preferredSize = d->taskArea->effectiveSizeHint(Qt::PreferredSize);
00214     preferredSize.setWidth(preferredSize.width() + leftMargin + rightMargin);
00215     preferredSize.setHeight(preferredSize.height() + topMargin + bottomMargin);
00216     setPreferredSize(preferredSize);
00217 
00218     QSizeF actualSize = size();
00219     Plasma::FormFactor f = formFactor();
00220 
00221     if (f == Plasma::Horizontal) {
00222         setMinimumSize(preferredSize.width(), 0);
00223     } else if (f == Plasma::Vertical) {
00224         setMinimumSize(0, preferredSize.height());
00225     } else if (actualSize.width() < preferredSize.width() ||
00226                actualSize.height() < preferredSize.height()) {
00227         setMinimumSize(22, 22);
00228 
00229         QSizeF constraint;
00230         if (actualSize.width() > actualSize.height()) {
00231             constraint = QSize(actualSize.width() - leftMargin - rightMargin, -1);
00232         } else {
00233             constraint = QSize(-1, actualSize.height() - topMargin - bottomMargin);
00234         }
00235 
00236         preferredSize = d->taskArea->effectiveSizeHint(Qt::PreferredSize, constraint);
00237         preferredSize.setWidth(qMax(actualSize.width(), preferredSize.width()));
00238         preferredSize.setHeight(qMax(actualSize.height(), preferredSize.height()));
00239 
00240         resize(preferredSize);
00241     }
00242 }
00243 
00244 
00245 void Applet::Private::setTaskAreaGeometry()
00246 {
00247     qreal leftMargin, topMargin, rightMargin, bottomMargin;
00248     q->getContentsMargins(&leftMargin, &topMargin, &rightMargin, &bottomMargin);
00249 
00250     QRectF taskAreaRect(q->rect());
00251     taskAreaRect.moveLeft(leftMargin);
00252     taskAreaRect.moveTop(topMargin);
00253     taskAreaRect.setWidth(taskAreaRect.width() - leftMargin - rightMargin);
00254     taskAreaRect.setHeight(taskAreaRect.height() - topMargin - bottomMargin);
00255 
00256     taskArea->setGeometry(taskAreaRect);
00257 }
00258 
00259 
00260 void Applet::paintInterface(QPainter *painter, const QStyleOptionGraphicsItem *option, const QRect &contentsRect)
00261 {
00262     Q_UNUSED(option)
00263     Q_UNUSED(contentsRect)
00264 
00265     QRect normalRect = rect().toRect();
00266     QRect lastRect(normalRect);
00267     d->background->setElementPrefix("lastelements");
00268 
00269     if (formFactor() == Plasma::Vertical) {
00270         const int rightEasement = d->taskArea->rightEasement() + d->background->marginSize(Plasma::BottomMargin);
00271         normalRect.setY(d->taskArea->leftEasement());
00272         normalRect.setBottom(normalRect.bottom() - rightEasement);
00273 
00274         lastRect.setY(normalRect.bottom() + 1);
00275         lastRect.setHeight(rightEasement);
00276     } else if (QApplication::layoutDirection() == Qt::RightToLeft) {
00277         const int rightEasement = d->taskArea->rightEasement() + d->background->marginSize(Plasma::LeftMargin);
00278         normalRect.setWidth(normalRect.width() - d->taskArea->leftEasement());
00279         normalRect.setLeft(rightEasement);
00280 
00281         lastRect.setWidth(rightEasement);
00282     } else {
00283         const int rightEasement = d->taskArea->rightEasement() + d->background->marginSize(Plasma::RightMargin);
00284         normalRect.setX(d->taskArea->leftEasement());
00285         normalRect.setWidth(normalRect.width() - rightEasement);
00286 
00287         lastRect.setX(normalRect.right() + 1);
00288         lastRect.setWidth(rightEasement);
00289     }
00290 
00291     QRect r = normalRect.united(lastRect);
00292 
00293     painter->save();
00294 
00295     d->background->setElementPrefix(QString());
00296     d->background->resizeFrame(r.size());
00297     if (d->taskArea->rightEasement() > 0) {
00298         painter->setClipRect(normalRect);
00299     }
00300     d->background->paintFrame(painter, r, QRectF(QPointF(0, 0), r.size()));
00301 
00302     if (d->taskArea->rightEasement() > 0) {
00303         d->background->setElementPrefix("lastelements");
00304         d->background->resizeFrame(r.size());
00305         painter->setClipRect(lastRect);
00306         d->background->paintFrame(painter, r, QRectF(QPointF(0, 0), r.size()));
00307     }
00308 
00309     painter->restore();
00310 }
00311 
00312 
00313 void Applet::propogateSizeHintChange(Qt::SizeHint which)
00314 {
00315     checkSizes();
00316     emit sizeHintChanged(which);
00317 }
00318 
00319 
00320 void Applet::createConfigurationInterface(KConfigDialog *parent)
00321 {
00322     if (!d->configInterface) {
00323         d->configInterface = new KActionSelector();
00324         d->configInterface->setAvailableLabel(i18n("Visible icons:"));
00325         d->configInterface->setSelectedLabel(i18n("Hidden icons:"));
00326         d->configInterface->setShowUpDownButtons(false);
00327 
00328         connect(parent, SIGNAL(applyClicked()), this, SLOT(configAccepted()));
00329         connect(parent, SIGNAL(okClicked()), this, SLOT(configAccepted()));
00330 
00331         parent->addPage(d->configInterface, i18n("Auto Hide"));
00332     }
00333 
00334     QListWidget *visibleList = d->configInterface->availableListWidget();
00335     QListWidget *hiddenList = d->configInterface->selectedListWidget();
00336 
00337     visibleList->clear();
00338     hiddenList->clear();
00339 
00340     foreach (Task *task, Private::s_manager->tasks()) {
00341         if (!task->isHideable()) {
00342             continue;
00343         }
00344 
00345         QListWidgetItem *listItem = new QListWidgetItem();
00346         listItem->setText(task->name());
00347         listItem->setIcon(task->icon());
00348         listItem->setData(Qt::UserRole, task->typeId());
00349 
00350         if (d->taskArea->isHiddenType(task->typeId(), false)) {
00351             hiddenList->addItem(listItem);
00352         } else {
00353             visibleList->addItem(listItem);
00354         }
00355     }
00356 }
00357 
00358 
00359 void Applet::configAccepted()
00360 {
00361     QStringList hiddenTypes;
00362 
00363     QListWidget *hiddenList = d->configInterface->selectedListWidget();
00364     for (int i = 0; i < hiddenList->count(); ++i) {
00365         hiddenTypes << hiddenList->item(i)->data(Qt::UserRole).toString();
00366     }
00367 
00368     d->taskArea->setHiddenTypes(hiddenTypes);
00369     d->taskArea->syncTasks(Private::s_manager->tasks());
00370 
00371     KConfigGroup cg = config();
00372     cg.writeEntry("hidden", hiddenTypes);
00373    
00374     emit configNeedsSaving();
00375 }
00376 
00377 
00378 void Applet::addNotification(Notification *notification)
00379 {
00380     Plasma::ExtenderItem *extenderItem = new Plasma::ExtenderItem(extender());
00381     extenderItem->config().writeEntry("type", "notification");
00382     extenderItem->setWidget(new NotificationWidget(notification, extenderItem));
00383 
00384     connect(extenderItem, SIGNAL(destroyed()), this, SLOT(hidePopupIfEmpty()));
00385 
00386     showPopup();
00387 }
00388 
00389 void Applet::addJob(Job *job)
00390 {
00391     Plasma::ExtenderItem *extenderItem = new Plasma::ExtenderItem(extender());
00392     extenderItem->config().writeEntry("type", "job");
00393     extenderItem->setWidget(new JobWidget(job, extenderItem));
00394 
00395     connect(extenderItem, SIGNAL(destroyed()), this, SLOT(hidePopupIfEmpty()));
00396 
00397     showPopup(5000);
00398 }
00399 
00400 void Applet::initExtenderItem(Plasma::ExtenderItem *extenderItem)
00401 {
00402     if (extenderItem->config().readEntry("type", "") == "notification") {
00403         extenderItem->setWidget(new NotificationWidget(0, extenderItem));
00404     } else {
00405         extenderItem->setWidget(new JobWidget(0, extenderItem));
00406     }
00407 }
00408 
00409 void Applet::hidePopupIfEmpty()
00410 {
00411     if (d->extenderTask && extender()->attachedItems().isEmpty()) {
00412         hidePopup();
00413 
00414         // even though there is code to do this in popupEvent... we may need to delete
00415         // here anyways because the popup may already be hidden, resultin gin no
00416         // popupEvent
00417         delete d->extenderTask;
00418         d->extenderTask = 0;
00419     }
00420 }
00421 
00422 void Applet::popupEvent(bool visibility)
00423 {
00424     kDebug() << visibility << extender()->attachedItems().isEmpty();
00425     if (extender()->attachedItems().isEmpty()) {
00426         delete d->extenderTask;
00427         d->extenderTask = 0;
00428     } else {
00429         if (!d->extenderTask) {
00430             d->extenderTask = new SystemTray::ExtenderTask(this);
00431             d->extenderTask->setIcon("help-about");
00432         }
00433 
00434         Private::s_manager->addTask(d->extenderTask);
00435     }
00436 }
00437 
00438 
00439 }
00440 
00441 #include "applet.moc"

Applets

Skip menu "Applets"
  • Main Page
  • Namespace List
  • Class Hierarchy
  • Alphabetical List
  • Class List
  • File List
  • Namespace Members
  • Class Members

API Reference

Skip menu "API Reference"
  • KWin
  •   KWin Libraries
  • Libraries
  •   libkworkspace
  •   libsolidcontrol
  •   libtaskmanager
  • Plasma
  •   Animators
  •   Applets
  •   Engines
  • Solid Modules
Generated for API Reference by doxygen 1.5.7
This website is maintained by Adriaan de Groot and Allen Winter.
KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal