diff --git a/CMakeLists.txt b/CMakeLists.txt
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -70,6 +70,7 @@
)
find_package(LibKWorkspace 5.14.90 CONFIG REQUIRED)
+find_package(LibNotificationManager 5.15.80 CONFIG REQUIRED)
find_package(LibTaskManager 5.14.90 CONFIG REQUIRED)
find_package(LibNotificationManager 5.14.90 CONFIG REQUIRED)
find_package(LibColorCorrect 5.14.90 CONFIG REQUIRED)
diff --git a/applets/taskmanager/CMakeLists.txt b/applets/taskmanager/CMakeLists.txt
--- a/applets/taskmanager/CMakeLists.txt
+++ b/applets/taskmanager/CMakeLists.txt
@@ -29,6 +29,7 @@
KF5::KIOFileWidgets # KFilePlacesModel
KF5::Plasma
KF5::Service
- KF5::WindowSystem)
+ KF5::WindowSystem
+ PW::LibNotificationManager)
install(TARGETS taskmanagerplugin DESTINATION ${KDE_INSTALL_QMLDIR}/org/kde/plasma/private/taskmanager)
diff --git a/applets/taskmanager/package/contents/config/main.xml b/applets/taskmanager/package/contents/config/main.xml
--- a/applets/taskmanager/package/contents/config/main.xml
+++ b/applets/taskmanager/package/contents/config/main.xml
@@ -87,10 +87,6 @@
0
-
-
- true
-
true
diff --git a/applets/taskmanager/package/contents/ui/ConfigAppearance.qml b/applets/taskmanager/package/contents/ui/ConfigAppearance.qml
--- a/applets/taskmanager/package/contents/ui/ConfigAppearance.qml
+++ b/applets/taskmanager/package/contents/ui/ConfigAppearance.qml
@@ -34,7 +34,6 @@
property alias cfg_showToolTips: showToolTips.checked
property alias cfg_highlightWindows: highlightWindows.checked
- property alias cfg_smartLaunchersEnabled: smartLaunchers.checked
property bool cfg_indicateAudioStreams
property alias cfg_iconSize: iconSize.value
property alias cfg_maxStripes: maxStripes.value
@@ -55,11 +54,6 @@
text: i18n("Highlight windows when hovering over tasks")
}
- CheckBox {
- id: smartLaunchers
- text: i18n("Show progress and status information in task buttons")
- }
-
CheckBox {
id: indicateAudioStreams
text: i18n("Mark applications that play audio")
diff --git a/applets/taskmanager/package/contents/ui/Task.qml b/applets/taskmanager/package/contents/ui/Task.qml
--- a/applets/taskmanager/package/contents/ui/Task.qml
+++ b/applets/taskmanager/package/contents/ui/Task.qml
@@ -55,7 +55,7 @@
property int pressY: -1
property QtObject contextMenu: null
property int wheelDelta: 0
- readonly property bool smartLauncherEnabled: plasmoid.configuration.smartLaunchersEnabled && !inPopup && model.IsStartup !== true
+ readonly property bool smartLauncherEnabled: !inPopup && model.IsStartup !== true
property QtObject smartLauncherItem: null
property alias toolTipAreaItem: toolTipArea
@@ -381,7 +381,7 @@
});
toolTipDelegate.smartLauncherCountVisible = Qt.binding(function() {
- return plasmoid.configuration.smartLaunchersEnabled && task.smartLauncherItem && task.smartLauncherItem.countVisible;
+ return task.smartLauncherItem && task.smartLauncherItem.countVisible;
});
toolTipDelegate.smartLauncherCount = Qt.binding(function() {
return toolTipDelegate.smartLauncherCountVisible ? task.smartLauncherItem.count : 0;
@@ -395,7 +395,7 @@
anchors.fill: frame
asynchronous: true
source: "TaskProgressOverlay.qml"
- active: plasmoid.configuration.smartLaunchersEnabled && task.smartLauncherItem && task.smartLauncherItem.progressVisible
+ active: task.smartLauncherItem && task.smartLauncherItem.progressVisible
}
Item {
@@ -448,7 +448,7 @@
height: parent.height
asynchronous: true
source: "TaskBadgeOverlay.qml"
- active: plasmoid.configuration.smartLaunchersEnabled && height >= units.iconSizes.small
+ active: height >= units.iconSizes.small
&& task.smartLauncherItem && task.smartLauncherItem.countVisible
}
diff --git a/applets/taskmanager/plugin/smartlaunchers/smartlauncherbackend.h b/applets/taskmanager/plugin/smartlaunchers/smartlauncherbackend.h
--- a/applets/taskmanager/plugin/smartlaunchers/smartlauncherbackend.h
+++ b/applets/taskmanager/plugin/smartlaunchers/smartlauncherbackend.h
@@ -1,5 +1,5 @@
/***************************************************************************
- * Copyright (C) 2016 Kai Uwe Broulik *
+ * Copyright (C) 2016, 2019 Kai Uwe Broulik *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
@@ -25,13 +25,14 @@
#include
#include
-#include
+#include
class QDBusServiceWatcher;
class QString;
-namespace Plasma {
-class DataEngineConsumer;
+namespace NotificationManager
+{
+class Settings;
}
namespace SmartLauncher {
@@ -53,7 +54,6 @@
explicit Backend(QObject *parent = nullptr);
~Backend() override;
- bool available() const;
bool hasLauncher(const QString &storageId) const;
int count(const QString &uri) const;
@@ -64,49 +64,52 @@
QHash unityMappingRules() const;
-public slots:
- void dataUpdated(const QString &sourceName, const Plasma::DataEngine::Data &data);
-
signals:
void countChanged(const QString &uri, int count);
void countVisibleChanged(const QString &uri, bool countVisible);
void progressChanged(const QString &uri, int progress);
void progressVisibleChanged(const QString &uri, bool progressVisible);
void urgentChanged(const QString &uri, bool urgent);
+ void reloadRequested(const QString &uri);
void launcherRemoved(const QString &uri);
private slots:
void update(const QString &uri, const QMap &properties);
private:
- bool setupUnity();
- bool setupApplicationJobs();
+ void reload();
+ void setupUnity();
+ void setupApplicationJobs();
void onServiceUnregistered(const QString &service);
template
void updateLauncherProperty(const QString &storageId, // our KService storage id
const QVariantMap &properties, // the map of properties we're given by DBus
const QString &property, // the property we're looking for
T *entryMember, // the member variable we're going to write our result in
+ // the getter for this property which might return something different from the raw value
+ T (Backend::*getter)(const QString &) const,
// the change signal that will be emitted if the property has changed
void (Backend::*changeSignal)(const QString &, T))
{
auto foundProperty = properties.constFind(property);
if (foundProperty != properties.constEnd()) {
+ const T oldSanitizedValue = ((this)->*getter)(storageId);
+
T newValue = foundProperty->value();
+ *entryMember = newValue;
- if (newValue != *entryMember) {
- *entryMember = newValue;
- emit ((this)->*changeSignal)(storageId, newValue);
+ const T newSanitizedValue = ((this)->*getter)(storageId);
+
+ if (newSanitizedValue != oldSanitizedValue) {
+ emit ((this)->*changeSignal)(storageId, newSanitizedValue);
}
}
}
- void onApplicationJobAdded(const QString &source);
- void onApplicationJobRemoved(const QString &source);
- void updateApplicationJobPercent(const QString &storageId, Entry *entry);
+ bool doNotDisturbMode() const;
// Unity Launchers
QDBusServiceWatcher *m_watcher;
@@ -118,14 +121,14 @@
QHash m_unityMappingRules;
// Application Jobs
- Plasma::DataEngineConsumer *m_dataEngineConsumer;
- Plasma::DataEngine *m_dataEngine;
- QHash m_dataSourceToStorageId; //
- QHash m_storageIdToJobs; // >
- QHash m_jobProgress; //
+ NotificationManager::JobsModel::Ptr m_jobsModel;
+
+ NotificationManager::Settings *m_settings = nullptr;
QHash m_launchers;
+ QStringList m_badgeBlacklist;
+
bool m_available = false;
};
diff --git a/applets/taskmanager/plugin/smartlaunchers/smartlauncherbackend.cpp b/applets/taskmanager/plugin/smartlaunchers/smartlauncherbackend.cpp
--- a/applets/taskmanager/plugin/smartlaunchers/smartlauncherbackend.cpp
+++ b/applets/taskmanager/plugin/smartlaunchers/smartlauncherbackend.cpp
@@ -1,5 +1,5 @@
/***************************************************************************
- * Copyright (C) 2016 Kai Uwe Broulik *
+ * Copyright (C) 2016, 2019 Kai Uwe Broulik *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
@@ -24,47 +24,69 @@
#include
#include
-#include
-#include
-
+#include
#include
#include
+#include
+
+#include
+#include
+
using namespace SmartLauncher;
+using namespace NotificationManager;
Backend::Backend(QObject *parent)
: QObject(parent)
, m_watcher(new QDBusServiceWatcher(this))
- , m_dataEngineConsumer(new Plasma::DataEngineConsumer)
- , m_dataEngine(m_dataEngineConsumer->dataEngine(QStringLiteral("applicationjobs")))
+ , m_settings(new Settings(this))
{
- m_available = setupUnity();
- m_available = setupApplicationJobs() || m_available;
+ setupUnity();
+
+ reload();
+ connect(m_settings, &Settings::settingsChanged, this, &Backend::reload);
}
-Backend::~Backend()
+Backend::~Backend() = default;
+
+void Backend::reload()
{
- delete m_dataEngineConsumer;
+ m_badgeBlacklist = m_settings->badgeBlacklistedApplications();
+
+ // Unity Launcher API operates on storage IDs ("foo.desktop"), whereas settings return desktop entries "foo"
+ std::transform(m_badgeBlacklist.begin(), m_badgeBlacklist.end(), m_badgeBlacklist.begin(), [](const QString &desktopEntry) {
+ return desktopEntry + QStringLiteral(".desktop");
+ });
+
+ setupApplicationJobs();
+
+ emit reloadRequested(QString() /*all*/);
+}
+
+bool Backend::doNotDisturbMode() const
+{
+ return m_settings->notificationsInhibitedByApplication()
+ || (m_settings->notificationsInhibitedUntil().isValid() && m_settings->notificationsInhibitedUntil() > QDateTime::currentDateTimeUtc());
}
-bool Backend::setupUnity()
+void Backend::setupUnity()
{
auto sessionBus = QDBusConnection::sessionBus();
if (!sessionBus.connect({}, {}, QStringLiteral("com.canonical.Unity.LauncherEntry"),
QStringLiteral("Update"), this, SLOT(update(QString,QMap)))) {
qWarning() << "failed to register Update signal";
- return false;
+ return;
}
if (!sessionBus.registerObject(QStringLiteral("/Unity"), this)) {
qWarning() << "Failed to register unity object";
- return false;
+ return;
}
if (!sessionBus.registerService(QStringLiteral("com.canonical.Unity"))) {
qWarning() << "Failed to register unity service";
- return false;
+ // In case an external process uses this (e.g. Latte Dock), let it just listen.
}
KConfigGroup grp(KSharedConfig::openConfig(QStringLiteral("taskmanagerrulesrc")), QStringLiteral("Unity Launcher Mapping"));
@@ -77,31 +99,16 @@
m_unityMappingRules.insert(key, value);
}
-
- return true;
}
-bool Backend::setupApplicationJobs()
+void Backend::setupApplicationJobs()
{
- if (!m_dataEngine->isValid()) {
- qWarning() << "Failed to setup application jobs, data engine is not valid";
- return false;
- }
-
- const QStringList &sources = m_dataEngine->sources();
- for (const QString &source : sources) {
- onApplicationJobAdded(source);
+ if (m_settings->jobsInTaskManager() && !m_jobsModel) {
+ m_jobsModel = JobsModel::createJobsModel();
+ m_jobsModel->init();
+ } else if (!m_settings->jobsInTaskManager() && m_jobsModel) {
+ m_jobsModel = nullptr;
}
-
- connect(m_dataEngine, &Plasma::DataEngine::sourceAdded, this, &Backend::onApplicationJobAdded);
- connect(m_dataEngine, &Plasma::DataEngine::sourceRemoved, this, &Backend::onApplicationJobRemoved);
-
- return true;
-}
-
-bool Backend::available() const
-{
- return m_available;
}
bool Backend::hasLauncher(const QString &storageId) const
@@ -111,21 +118,37 @@
int Backend::count(const QString &uri) const
{
+ if (!m_settings->badgesInTaskManager()
+ || doNotDisturbMode()
+ || m_badgeBlacklist.contains(uri)) {
+ return 0;
+ }
return m_launchers.value(uri).count;
}
bool Backend::countVisible(const QString &uri) const
{
+ if (!m_settings->badgesInTaskManager()
+ || doNotDisturbMode()
+ || m_badgeBlacklist.contains(uri)) {
+ return false;
+ }
return m_launchers.value(uri).countVisible;
}
int Backend::progress(const QString &uri) const
{
+ if (!m_settings->jobsInTaskManager()) {
+ return 0;
+ }
return m_launchers.value(uri).progress;
}
bool Backend::progressVisible(const QString &uri) const
{
+ if (!m_settings->jobsInTaskManager()) {
+ return false;
+ }
return m_launchers.value(uri).progressVisible;
}
@@ -192,22 +215,26 @@
}
}
- updateLauncherProperty(storageId, properties, QStringLiteral("count"), &foundEntry->count, &Backend::countChanged);
- updateLauncherProperty(storageId, properties, QStringLiteral("count-visible"), &foundEntry->countVisible, &Backend::countVisibleChanged);
+ updateLauncherProperty(storageId, properties, QStringLiteral("count"), &foundEntry->count, &Backend::count, &Backend::countChanged);
+ updateLauncherProperty(storageId, properties, QStringLiteral("count-visible"), &foundEntry->countVisible, &Backend::countVisible, &Backend::countVisibleChanged);
// the API gives us progress as 0..1 double but we'll use percent to avoid unnecessary
// changes when it just changed a fraction of a percent, hence not using our fancy updateLauncherProperty method
auto foundProgress = properties.constFind(QStringLiteral("progress"));
if (foundProgress != propertiesEnd) {
- int newProgress = qRound(foundProgress->toDouble() * 100);
- if (newProgress != foundEntry->progress) {
- foundEntry->progress = newProgress;
- emit progressChanged(storageId, newProgress);
+ const int oldSanitizedProgress = progress(storageId);
+
+ foundEntry->progress = qRound(foundProgress->toDouble() * 100);
+
+ const int newSanitizedProgress = progress(storageId);
+
+ if (oldSanitizedProgress != newSanitizedProgress) {
+ emit progressChanged(storageId, newSanitizedProgress);
}
}
- updateLauncherProperty(storageId, properties, QStringLiteral("progress-visible"), &foundEntry->progressVisible, &Backend::progressVisibleChanged);
- updateLauncherProperty(storageId, properties, QStringLiteral("urgent"), &foundEntry->urgent, &Backend::urgentChanged);
+ updateLauncherProperty(storageId, properties, QStringLiteral("progress-visible"), &foundEntry->progressVisible, &Backend::progressVisible, &Backend::progressVisibleChanged);
+ updateLauncherProperty(storageId, properties, QStringLiteral("urgent"), &foundEntry->urgent, &Backend::urgent, &Backend::urgentChanged);
}
void Backend::onServiceUnregistered(const QString &service)
@@ -225,129 +252,3 @@
m_launchers.remove(storageId);
emit launcherRemoved(storageId);
}
-
-void Backend::onApplicationJobAdded(const QString &source)
-{
- m_dataEngine->connectSource(source, this);
-}
-
-void Backend::onApplicationJobRemoved(const QString &source)
-{
- m_dataEngine->disconnectSource(source, this);
-
- const QString &storageId = m_dataSourceToStorageId.take(source);
- if (storageId.isEmpty()) {
- return;
- }
-
- // remove job, calculate new percentage, or remove launcher if gone altogether
- auto &jobs = m_storageIdToJobs[storageId];
- jobs.removeOne(source);
- if (jobs.isEmpty()) {
- m_storageIdToJobs.remove(storageId);
- }
-
- m_jobProgress.remove(source);
-
- auto foundEntry = m_launchers.find(storageId);
- if (foundEntry == m_launchers.end()) {
- qWarning() << "Cannot remove application job" << source << "as we don't know" << storageId;
- return;
- }
-
- updateApplicationJobPercent(storageId, &*foundEntry);
-
- if (!foundEntry->progressVisible && !foundEntry->progress) {
- // no progress anymore whatsoever, remove entire launcher
- m_launchers.remove(storageId);
- emit launcherRemoved(storageId);
- }
-}
-
-void Backend::dataUpdated(const QString &sourceName, const Plasma::DataEngine::Data &data)
-{
- QString storageId;
-
- auto foundStorageId = m_dataSourceToStorageId.constFind(sourceName);
- if (foundStorageId == m_dataSourceToStorageId.constEnd()) { // we don't know this one, register
- QString appName = data.value(QStringLiteral("appName")).toString();
- if (appName.isEmpty()) {
- qWarning() << "Application jobs got update for" << sourceName << "without app name";
- return;
- }
-
- KService::Ptr service = KService::serviceByStorageId(appName);
- if (!service) {
- appName.prepend(QLatin1String("org.kde."));
- // HACK try to find a service with org.kde. notation
- service = KService::serviceByStorageId(appName);
- if (!service) {
- qWarning() << "Could not find service for job" << sourceName << "with app name" << appName;
- return;
- }
- }
-
- storageId = service->storageId();
- m_dataSourceToStorageId.insert(sourceName, storageId);
- } else {
- storageId = *foundStorageId;
- }
-
- auto foundEntry = m_launchers.find(storageId);
- if (foundEntry == m_launchers.end()) { // we don't have it yet, create new Entry
- Entry entry;
- foundEntry = m_launchers.insert(storageId, entry);
- }
-
- int percent = data.value(QStringLiteral("percentage"), 0).toInt();
-
- // setup everything and calculate new percentage
- auto &jobs = m_storageIdToJobs[storageId];
- if (!jobs.contains(sourceName)) {
- jobs.append(sourceName);
- }
-
- m_jobProgress.insert(sourceName, percent); // insert() overrides if exist
-
- updateApplicationJobPercent(storageId, &*foundEntry);
-}
-
-void Backend::updateApplicationJobPercent(const QString &storageId, Entry *entry)
-{
- // basically get all jobs for the given storageId and calculate an average progress
-
- const auto &jobs = m_storageIdToJobs.value(storageId);
- qreal jobCount = jobs.count();
-
- int totalProgress = 0;
- for (const QString &job : jobs) {
- totalProgress += m_jobProgress.value(job, 0);
- }
-
- int progress = 0;
- if (jobCount > 0) {
- progress = qRound(totalProgress / jobCount);
- }
-
- bool visible = (jobCount > 0);
-
- if (entry->count != jobCount) {
- entry->count = jobCount;
- emit countChanged(storageId, jobCount);
- }
-
- if (entry->countVisible != visible) {
- entry->countVisible = visible;
- emit countVisibleChanged(storageId, visible);
- }
-
- if (entry->progress != progress) {
- entry->progress = progress;
- emit progressChanged(storageId, progress);
- }
-
- if (entry->progressVisible != visible) {
- entry->progressVisible = visible;
- emit progressVisibleChanged(storageId, visible);
- }
-}
diff --git a/applets/taskmanager/plugin/smartlaunchers/smartlauncheritem.h b/applets/taskmanager/plugin/smartlaunchers/smartlauncheritem.h
--- a/applets/taskmanager/plugin/smartlaunchers/smartlauncheritem.h
+++ b/applets/taskmanager/plugin/smartlaunchers/smartlauncheritem.h
@@ -1,5 +1,5 @@
/***************************************************************************
- * Copyright (C) 2016 Kai Uwe Broulik *
+ * Copyright (C) 2016, 2019 Kai Uwe Broulik *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
@@ -35,8 +35,6 @@
Q_PROPERTY(QUrl launcherUrl READ launcherUrl WRITE setLauncherUrl NOTIFY launcherUrlChanged)
- Q_PROPERTY(bool available READ available NOTIFY availableChanged)
-
Q_PROPERTY(int count READ count NOTIFY countChanged)
Q_PROPERTY(bool countVisible READ countVisible NOTIFY countVisibleChanged)
Q_PROPERTY(int progress READ progress NOTIFY progressChanged)
@@ -50,8 +48,6 @@
QUrl launcherUrl() const;
void setLauncherUrl(const QUrl &launcherUrl);
- bool available() const;
-
int count() const;
bool countVisible() const;
int progress() const;
@@ -61,8 +57,6 @@
signals:
void launcherUrlChanged(const QUrl &launcherUrl);
- void availableChanged(bool available);
-
void countChanged(int count);
void countVisibleChanged(bool countVisible);
void progressChanged(int progress);
@@ -88,7 +82,6 @@
QUrl m_launcherUrl;
QString m_storageId;
- bool m_available = false;
bool m_inited = false;
int m_count = 0;
diff --git a/applets/taskmanager/plugin/smartlaunchers/smartlauncheritem.cpp b/applets/taskmanager/plugin/smartlaunchers/smartlauncheritem.cpp
--- a/applets/taskmanager/plugin/smartlaunchers/smartlauncheritem.cpp
+++ b/applets/taskmanager/plugin/smartlaunchers/smartlauncheritem.cpp
@@ -1,5 +1,5 @@
/***************************************************************************
- * Copyright (C) 2016 Kai Uwe Broulik *
+ * Copyright (C) 2016, 2019 Kai Uwe Broulik *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
@@ -38,53 +38,58 @@
void Item::init()
{
- if (m_inited || m_storageId.isEmpty() || !m_backendPtr || !m_backendPtr->available()) {
+ if (m_inited || m_storageId.isEmpty() || !m_backendPtr) {
return;
}
+ connect(m_backendPtr.data(), &Backend::reloadRequested, this, [this](const QString &uri) {
+ if (uri.isEmpty() || m_storageId == uri) {
+ populate();
+ }
+ });
+
connect(m_backendPtr.data(), &Backend::launcherRemoved, this, [this](const QString &uri) {
- if (m_storageId == uri) {
+ if (uri.isEmpty() || m_storageId == uri) {
clear();
}
});
connect(m_backendPtr.data(), &Backend::countChanged, this, [this](const QString &uri, int count) {
- if (m_storageId == uri) {
+ if (uri.isEmpty() || m_storageId == uri) {
setCount(count);
}
});
connect(m_backendPtr.data(), &Backend::countVisibleChanged, this, [this](const QString &uri, bool countVisible) {
- if (m_storageId == uri) {
+ if (uri.isEmpty() || m_storageId == uri) {
setCountVisible(countVisible);
}
});
connect(m_backendPtr.data(), &Backend::progressChanged, this, [this](const QString &uri, int progress) {
- if (m_storageId == uri) {
+ if (uri.isEmpty() || m_storageId == uri) {
setProgress(progress);
}
});
connect(m_backendPtr.data(), &Backend::progressVisibleChanged, this, [this](const QString &uri, bool progressVisible) {
- if (m_storageId == uri) {
+ if (uri.isEmpty() || m_storageId == uri) {
setProgressVisible(progressVisible);
}
});
connect(m_backendPtr.data(), &Backend::urgentChanged, this, [this](const QString &uri, bool urgent) {
- if (m_storageId == uri) {
+ if (uri.isEmpty() || m_storageId == uri) {
setUrgent(urgent);
}
});
- m_available = true;
- emit availableChanged(m_available);
+ m_inited = true;
}
void Item::populate()
{
- if (!m_backendPtr || !m_backendPtr->available() || m_storageId.isEmpty()) {
+ if (!m_backendPtr || m_storageId.isEmpty()) {
return;
}
@@ -156,10 +161,6 @@
}
}
-bool Item::available() const
-{
- return m_available;
-}
int Item::count() const
{