SVN commit 997990 by mart: add a configuration ui for adding plasmoids into the systray: only ones marked X-Plasma-NotificationArea=true in their desktop file will show up in the list M +1 -0 battery/plasma-battery-default.desktop M +1 -0 devicenotifier/plasma-applet-devicenotifier.desktop M +2 -1 systemtray/CMakeLists.txt M +16 -1 systemtray/core/manager.cpp M +6 -0 systemtray/core/manager.h M +3 -1 systemtray/protocols/plasmoid/plasmoidtask.cpp M +30 -0 systemtray/protocols/plasmoid/plasmoidtaskprotocol.cpp M +5 -0 systemtray/protocols/plasmoid/plasmoidtaskprotocol.h M +40 -0 systemtray/ui/applet.cpp A systemtray/ui/plasmoidtasks.ui M +32 -2 tasks/taskgroupitem.cpp --- trunk/KDE/kdebase/workspace/plasma/applets/battery/plasma-battery-default.desktop #997989:997990 @@ -151,4 +151,5 @@ X-Plasma-Requires-FileDialog=Unused X-Plasma-Requires-LaunchApp=Optional +X-Plasma-NotificationArea=true --- trunk/KDE/kdebase/workspace/plasma/applets/devicenotifier/plasma-applet-devicenotifier.desktop #997989:997990 @@ -135,4 +135,5 @@ X-Plasma-Requires-FileDialog=Unused X-Plasma-Requires-LaunchApp=Required +X-Plasma-NotificationArea=true --- trunk/KDE/kdebase/workspace/plasma/applets/systemtray/CMakeLists.txt #997989:997990 @@ -42,7 +42,8 @@ kde4_add_ui_files(systemtray_SRCS ui/protocols.ui - ui/autohide.ui ) + ui/autohide.ui + ui/plasmoidtasks.ui) add_subdirectory(notificationitemwatcher) --- trunk/KDE/kdebase/workspace/plasma/applets/systemtray/core/manager.cpp #997989:997990 @@ -241,10 +241,25 @@ void Manager::loadApplets(const KConfigGroup &cg, Plasma::Applet *parent) { - d->plasmoidProtocol->loadFromConfig(cg, parent); + d->plasmoidProtocol->loadFromConfig(cg, parent); } +void Manager::addApplet(const QString appletName, Plasma::Applet *parent) +{ + d->plasmoidProtocol->addApplet(appletName, parent); } +void Manager::removeApplet(const QString appletName, Plasma::Applet *parent) +{ + d->plasmoidProtocol->removeApplet(appletName, parent); +} +QStringList Manager::applets() const +{ + return d->plasmoidProtocol->applets(); +} + +} + + #include "manager.moc" --- trunk/KDE/kdebase/workspace/plasma/applets/systemtray/core/manager.h #997989:997990 @@ -102,6 +102,12 @@ void loadApplets(const KConfigGroup &cg, Plasma::Applet *parent); + void addApplet(const QString appletName, Plasma::Applet *parent); + + void removeApplet(const QString appletName, Plasma::Applet *parent); + + QStringList applets() const; + signals: /** * Emitted when a new task has been added --- trunk/KDE/kdebase/workspace/plasma/applets/systemtray/protocols/plasmoid/plasmoidtask.cpp #997989:997990 @@ -104,7 +104,7 @@ QGraphicsWidget* PlasmoidTask::createWidget(Plasma::Applet *host) { - if (host != d->host) { + if (host != d->host || !d->applet) { return 0; } @@ -112,6 +112,8 @@ d->applet->setParent(host); d->applet->setParentItem(host); d->applet->init(); + d->applet->updateConstraints(Plasma::StartupCompletedConstraint); + d->applet->flushPendingConstraintsEvents(); d->applet->updateConstraints(Plasma::AllConstraints); d->applet->flushPendingConstraintsEvents(); --- trunk/KDE/kdebase/workspace/plasma/applets/systemtray/protocols/plasmoid/plasmoidtaskprotocol.cpp #997989:997990 @@ -80,13 +80,43 @@ } } +void PlasmoidProtocol::addApplet(const QString appletName, Plasma::Applet *parent) +{ + kDebug() << "Registering task with the manager" << appletName; + PlasmoidTask *task = new PlasmoidTask(appletName, 0, this, parent); + + if (!task->isValid()) { + // we failed to load our applet *sob* + delete task; + return; + } + + m_tasks[appletName] = task; + connect(task, SIGNAL(taskDeleted(QString)), this, SLOT(cleanupTask(QString))); + emit taskCreated(task); +} + +void PlasmoidProtocol::removeApplet(const QString appletName, Plasma::Applet *parent) +{ + Plasma::Applet *applet = qobject_cast(m_tasks[appletName]->widget(parent, true)); + + if (applet) { + applet->destroy(); + } +} + void PlasmoidProtocol::cleanupTask(QString typeId) { kDebug() << "task with typeId" << typeId << "removed"; m_tasks.remove(typeId); } +QStringList PlasmoidProtocol::applets() const +{ + return m_tasks.keys(); } +} + #include "plasmoidtaskprotocol.moc" --- trunk/KDE/kdebase/workspace/plasma/applets/systemtray/protocols/plasmoid/plasmoidtaskprotocol.h #997989:997990 @@ -28,6 +28,7 @@ #include #include +#include namespace SystemTray { @@ -46,11 +47,15 @@ void forwardConstraintsEvent(Plasma::Constraints constraints); void loadFromConfig(const KConfigGroup &cg, Plasma::Applet *parent); + void addApplet(const QString appletName, Plasma::Applet *parent); + void removeApplet(const QString appletName, Plasma::Applet *parent); + QStringList applets() const; private slots: void cleanupTask(QString typeId); private: + //FIXME: applets must be indicized by name -and- parent QHash m_tasks; }; --- trunk/KDE/kdebase/workspace/plasma/applets/systemtray/ui/applet.cpp #997989:997990 @@ -34,6 +34,7 @@ #include #include + #include #include @@ -62,6 +63,7 @@ #include "ui_protocols.h" #include "ui_autohide.h" +#include "ui_plasmoidtasks.h" namespace SystemTray { @@ -107,6 +109,7 @@ TaskArea *taskArea; QPointer notificationInterface; QPointer autoHideInterface; + QPointer plasmoidTasksInterface; QList jobs; QSet shownCategories; QDateTime lastActivity; @@ -121,6 +124,7 @@ Ui::ProtocolsConfig notificationUi; Ui::AutoHideConfig autoHideUi; + Ui::PlasmoidTasksConfig plasmoidTasksUi; }; Manager *Applet::Private::s_manager = 0; @@ -464,6 +468,7 @@ KConfigGroup globalCg = globalConfig(); d->notificationInterface = new QWidget(); d->autoHideInterface = new QWidget(); + d->plasmoidTasksInterface = new QWidget(); d->notificationUi.setupUi(d->notificationInterface); @@ -478,6 +483,9 @@ d->autoHideUi.setupUi(d->autoHideInterface); d->autoHideUi.autoHide->setChecked(config().readEntry("AutoHidePopup", true)); + d->plasmoidTasksUi.setupUi(d->plasmoidTasksInterface); + + connect(parent, SIGNAL(applyClicked()), this, SLOT(configAccepted())); connect(parent, SIGNAL(okClicked()), this, SLOT(configAccepted())); @@ -485,9 +493,11 @@ "preferences-desktop-notification", i18n("Choose which information to show")); parent->addPage(d->autoHideInterface, i18n("Auto Hide"), "window-suppressed"); + parent->addPage(d->plasmoidTasksInterface, i18n("Plasma widgets"), "plasma"); } d->autoHideUi.icons->clear(); + d->plasmoidTasksUi.applets->clear(); QMultiMap sortedTasks; foreach (const Task *task, Private::s_manager->tasks()) { @@ -511,6 +521,20 @@ listItem->setCheckState((task->hidden() & Task::UserHidden) ? Qt::Unchecked : Qt::Checked); d->autoHideUi.icons->addItem(listItem); } + + foreach (const KPluginInfo &info, Plasma::Applet::listAppletInfo()) { + KService::Ptr service = info.service(); + if (service->property("X-Plasma-NotificationArea", QVariant::Bool).toBool()) { + QListWidgetItem *listItem = new QListWidgetItem(); + listItem->setText(service->name()); + listItem->setIcon(KIcon(service->icon())); + listItem->setFlags(Qt::ItemIsUserCheckable | Qt::ItemIsEnabled); + listItem->setData(Qt::UserRole, info.pluginName()); + listItem->setCheckState((Private::s_manager->applets().contains(info.pluginName())) ? Qt::Checked : Qt::Unchecked); + d->plasmoidTasksUi.applets->addItem(listItem); + } + } + } void Applet::configAccepted() @@ -594,6 +618,22 @@ d->shownCategories.insert(Task::UnknownCategory); d->taskArea->syncTasks(manager()->tasks()); + + QStringList applets = Private::s_manager->applets(); + for (int i = 0; i < d->plasmoidTasksUi.applets->count(); ++i) { + QListWidgetItem * item = d->plasmoidTasksUi.applets->item(i); + QString appletName = item->data(Qt::UserRole).toString(); + + if (item->checkState() == Qt::Checked) { + applets.removeAll(appletName); + Private::s_manager->addApplet(appletName, this); + } + } + + foreach (QString appletName, applets) { + Private::s_manager->removeApplet(appletName, this); + } + emit configNeedsSaving(); } --- trunk/KDE/kdebase/workspace/plasma/applets/tasks/taskgroupitem.cpp #997989:997990 @@ -29,6 +29,8 @@ #include #include #include +#include +#include // KDE #include @@ -284,8 +286,8 @@ } data.setWindowsToPreview(windows); - data.setClickable(true); + Plasma::ToolTipManager::self()->setContent(this, data); } @@ -538,7 +540,35 @@ void TaskGroupItem::mousePressEvent(QGraphicsSceneMouseEvent *event) { //TODO add delay so we can still drag group items - if ((event->buttons() & Qt::LeftButton) && !m_popupLostFocus) { + if ((event->buttons() & Qt::LeftButton) && (event->modifiers() & Qt::Key_Control)) { + #ifdef Q_WS_X11 + QList ids; + foreach (AbstractGroupableItem *groupable, m_group->members()) { + if (groupable->isGroupItem()) { + //TODO: recurse through sub-groups? + } else { + TaskItem * item = dynamic_cast(groupable); + if (item) { + ids << item->task()->info().win(); + } + } + } + const int numWindows = ids.count(); + QVarLengthArray data(numWindows); + + for (int i = 0; i < numWindows; ++i) { + data[i] = ids[i]; + } + + if (!data.isEmpty()) { + Display *dpy = QX11Info::display(); + const WId winId = data[0]; + Atom atom = XInternAtom(dpy, "_KDE_PRESENT_WINDOWS_GROUP", False); + XChangeProperty(dpy, winId, atom, atom, 32, PropModeReplace, + reinterpret_cast(data.data()), data.size()); + } +#endif + } else if ((event->buttons() & Qt::LeftButton) && !m_popupLostFocus) { if (m_applet->groupManager().sortingStrategy() == TaskManager::GroupManager::ManualSorting || m_applet->groupManager().groupingStrategy() == TaskManager::GroupManager::ManualGrouping) { if (!m_popupMenuTimer) {