00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
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
00117
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
00415
00416
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"