diff --git a/applets/systemtray/CMakeLists.txt b/applets/systemtray/CMakeLists.txt --- a/applets/systemtray/CMakeLists.txt +++ b/applets/systemtray/CMakeLists.txt @@ -21,6 +21,7 @@ Qt5::Gui Qt5::Quick Qt5::DBus + KF5::IconThemes KF5::Plasma KF5::XmlGui KF5::I18n diff --git a/applets/systemtray/package/contents/ui/items/StatusNotifierItem.qml b/applets/systemtray/package/contents/ui/items/StatusNotifierItem.qml --- a/applets/systemtray/package/contents/ui/items/StatusNotifierItem.qml +++ b/applets/systemtray/package/contents/ui/items/StatusNotifierItem.qml @@ -27,7 +27,7 @@ text: model.Title mainText: model.ToolTipTitle !== "" ? model.ToolTipTitle : model.Title subText: model.ToolTipSubTitle - icon: model.ToolTipIcon !== "" ? model.ToolTipIcon : model.Icon ? model.Icon : model.IconName + icon: model.ToolTipIcon !== "" ? model.ToolTipIcon : model.Icon textFormat: Text.AutoText PlasmaCore.IconItem { @@ -37,17 +37,42 @@ source: { if (model.status === PlasmaCore.Types.NeedsAttentionStatus) { - if (model.AttentionIcon) { - return model.AttentionIcon - } - if (model.AttentionIconName) { - return model.AttentionIconName - } + return model.AttentionIcon ? model.AttentionIcon : model.Icon } - return model.Icon ? model.Icon : model.IconName + return model.Icon } active: taskIcon.containsMouse } + // IconItem.overlays only supports names so we need a second item for the overlay, using the same + // positioning that KIconLoader::drawOverlays uses that IconItem uses internally + PlasmaCore.IconItem { + id: overlayIconItem + parent: iconItem.parent + source: model.OverlayIcon ? model.OverlayIcon : "" + + width: { + if (iconItem.width < units.iconSizes.medium) { + return units.iconSizes.small / 2; + } + if (iconItem.width <= units.iconSizes.large) { + return units.iconSizes.small + } + if (iconItem.width <= 96) { + return units.iconSizes.smallMedium + } + if (iconItem.width < 256) { + return units.iconSizes.medium + } + return units.iconSizes.large; + } + height: width + anchors { + right: iconItem.right + bottom: iconItem.bottom + bottomMargin: Math.floor(0.05 * iconItem.width) + rightMargin: anchors.bottomMargin + } + } onContextMenu: { openContextMenu(plasmoid.nativeInterface.popupPosition(taskIcon, mouse.x, mouse.y)) diff --git a/applets/systemtray/systemtraymodel.h b/applets/systemtray/systemtraymodel.h --- a/applets/systemtray/systemtraymodel.h +++ b/applets/systemtray/systemtraymodel.h @@ -88,16 +88,14 @@ enum class Role { DataEngineSource = static_cast(BaseModel::BaseRole::LastBaseRole) + 100, AttentionIcon, - AttentionIconName, AttentionMovieName, Category, Icon, - IconName, IconThemePath, IconsChanged, Id, ItemIsMenu, - OverlayIconName, + OverlayIcon, Status, StatusChanged, Title, diff --git a/applets/systemtray/systemtraymodel.cpp b/applets/systemtray/systemtraymodel.cpp --- a/applets/systemtray/systemtraymodel.cpp +++ b/applets/systemtray/systemtraymodel.cpp @@ -27,6 +27,8 @@ #include #include +#include +#include #include BaseModel::BaseModel(QObject *parent) @@ -236,16 +238,14 @@ roles.insert(static_cast(Role::DataEngineSource), QByteArrayLiteral("DataEngineSource")); roles.insert(static_cast(Role::AttentionIcon), QByteArrayLiteral("AttentionIcon")); - roles.insert(static_cast(Role::AttentionIconName), QByteArrayLiteral("AttentionIconName")); roles.insert(static_cast(Role::AttentionMovieName), QByteArrayLiteral("AttentionMovieName")); roles.insert(static_cast(Role::Category), QByteArrayLiteral("Category")); roles.insert(static_cast(Role::Icon), QByteArrayLiteral("Icon")); - roles.insert(static_cast(Role::IconName), QByteArrayLiteral("IconName")); roles.insert(static_cast(Role::IconThemePath), QByteArrayLiteral("IconThemePath")); roles.insert(static_cast(Role::IconsChanged), QByteArrayLiteral("IconsChanged")); roles.insert(static_cast(Role::Id), QByteArrayLiteral("Id")); roles.insert(static_cast(Role::ItemIsMenu), QByteArrayLiteral("ItemIsMenu")); - roles.insert(static_cast(Role::OverlayIconName), QByteArrayLiteral("OverlayIconName")); + roles.insert(static_cast(Role::OverlayIcon), QByteArrayLiteral("OverlayIcon")); roles.insert(static_cast(Role::Status), QByteArrayLiteral("Status")); roles.insert(static_cast(Role::StatusChanged), QByteArrayLiteral("StatusChanged")); roles.insert(static_cast(Role::Title), QByteArrayLiteral("Title")); @@ -325,18 +325,33 @@ dataItem->setData(Plasma::Types::ItemStatus::PassiveStatus, static_cast(BaseModel::BaseRole::Status)); } + const QString iconThemePath = data.value("IconThemePath").toString(); + KIconLoader *loader; + if (!iconThemePath.isEmpty()) { + loader = new KIconLoader(sourceName, {iconThemePath}); + loader->addAppDir(sourceName, iconThemePath); + } + for (auto role : {Role::Icon, Role::AttentionIcon, Role::OverlayIcon}) { + const QByteArray roleName = roleNames().value(static_cast(role)); + const QString iconName = data.value(roleName + "Name").toString(); + if (!iconName.isEmpty() ) { + if(iconThemePath.isEmpty()) { + dataItem->setData(iconName, static_cast(role)); + } else { + dataItem->setData(QIcon(new KIconEngine(iconName, loader)), static_cast(role)); + } + } else { + dataItem->setData(data.value(roleName + "Pixmap"), static_cast(role)); + } + } + dataItem->setData(sourceName, static_cast(Role::DataEngineSource)); - updateItemData(dataItem, data, Role::AttentionIcon); - updateItemData(dataItem, data, Role::AttentionIconName); updateItemData(dataItem, data, Role::AttentionMovieName); updateItemData(dataItem, data, Role::Category); - updateItemData(dataItem, data, Role::Icon); - updateItemData(dataItem, data, Role::IconName); updateItemData(dataItem, data, Role::IconThemePath); updateItemData(dataItem, data, Role::IconsChanged); updateItemData(dataItem, data, Role::Id); updateItemData(dataItem, data, Role::ItemIsMenu); - updateItemData(dataItem, data, Role::OverlayIconName); updateItemData(dataItem, data, Role::Status); updateItemData(dataItem, data, Role::StatusChanged); updateItemData(dataItem, data, Role::Title); diff --git a/applets/systemtray/tests/statusnotifier/statusnotifiertest.cpp b/applets/systemtray/tests/statusnotifier/statusnotifiertest.cpp --- a/applets/systemtray/tests/statusnotifier/statusnotifiertest.cpp +++ b/applets/systemtray/tests/statusnotifier/statusnotifiertest.cpp @@ -63,6 +63,7 @@ connect(updateButton, &QPushButton::clicked, this, &StatusNotifierTest::updateNotifier); connect(jobEnabledCheck, &QCheckBox::toggled, this, &StatusNotifierTest::enableJob); updateUi(); + iconName->setText(QStringLiteral("plasma")); show(); raise(); log(QStringLiteral("started")); @@ -126,7 +127,6 @@ statusPassive->setEnabled(!statusAuto->isChecked()); statusNeedsAttention->setEnabled(!statusAuto->isChecked()); - iconName->setText(d->systemNotifier->iconName()); tooltipText->setText(d->systemNotifier->toolTipTitle()); tooltipSubtext->setText(d->systemNotifier->toolTipSubTitle()); @@ -163,7 +163,12 @@ } d->systemNotifier->setStatus(s); - d->systemNotifier->setIconByName(iconName->text()); + iconPixmapCheckbox->isChecked() ? d->systemNotifier->setIconByPixmap(QIcon::fromTheme(iconName->text())) + : d->systemNotifier->setIconByName(iconName->text()); + overlayIconPixmapCheckbox->isChecked() ? d->systemNotifier->setOverlayIconByPixmap(QIcon::fromTheme(overlayIconName->text())) + : d->systemNotifier->setOverlayIconByName(overlayIconName->text()); + attentionIconPixmapCheckbox->isChecked() ? d->systemNotifier->setAttentionIconByPixmap(QIcon::fromTheme(attentionIconName->text())) + : d->systemNotifier->setAttentionIconByName(attentionIconName->text()); d->systemNotifier->setToolTip(iconName->text(), tooltipText->text(), tooltipSubtext->text()); diff --git a/applets/systemtray/tests/statusnotifier/statusnotifiertest.ui b/applets/systemtray/tests/statusnotifier/statusnotifiertest.ui --- a/applets/systemtray/tests/statusnotifier/statusnotifiertest.ui +++ b/applets/systemtray/tests/statusnotifier/statusnotifiertest.ui @@ -6,8 +6,8 @@ 0 0 - 434 - 572 + 471 + 692 @@ -21,14 +21,13 @@ - - + .. - 1 + 0 @@ -110,10 +109,7 @@ - - - - + <b>ToolTip</b> @@ -126,16 +122,80 @@ - - - Update + + + + + + Icon + + + + + + + AttentionIcon + + + + + + + OverlayIcon + + + + + + + + + + + + Use Pixmap + + + + + + + + + + + + + + Use Pixmap + + + + + + + + + + + + + + Use Pixmap + + + + + + + diff --git a/dataengines/statusnotifieritem/statusnotifieritemsource.cpp b/dataengines/statusnotifieritem/statusnotifieritemsource.cpp --- a/dataengines/statusnotifieritem/statusnotifieritemsource.cpp +++ b/dataengines/statusnotifieritem/statusnotifieritemsource.cpp @@ -87,17 +87,21 @@ //this means it does not re-evaluate what bindings exist (watchedRoleIds) - and we get properties that don't bind and thus system tray icons //by setting everything up-front so that we have all role names when we call the first checkForUpdate() + // TODO Plasma 6 remove combined "*Icon" properties and only expose the raw "*IconName" and "*IconPixmap" properties setData(QStringLiteral("AttentionIcon"), QIcon()); setData(QStringLiteral("AttentionIconName"), QString()); + setData(QStringLiteral("AttentionIconPixmap"), QIcon()); setData(QStringLiteral("AttentionMovieName"), QString()); setData(QStringLiteral("Category"), QString()); setData(QStringLiteral("Icon"), QIcon()); setData(QStringLiteral("IconName"), QString()); + setData(QStringLiteral("IconPixmap"), QIcon()); setData(QStringLiteral("IconsChanged"), false); setData(QStringLiteral("IconThemePath"), QString()); setData(QStringLiteral("Id"), QString()); setData(QStringLiteral("ItemIsMenu"), false); setData(QStringLiteral("OverlayIconName"), QString()); + setData(QStringLiteral("OverlayIconPixmap"), QIcon()); setData(QStringLiteral("StatusChanged"), false); setData(QStringLiteral("Status"), QString()); setData(QStringLiteral("TitleChanged"), false); @@ -273,58 +277,59 @@ { KDbusImageVector image; QIcon icon; - QString iconName; - + QString overlayIconName = properties[QStringLiteral("OverlayIconName")].toString(); + setData(QStringLiteral("OverlayIconName"), overlayIconName); properties[QStringLiteral("OverlayIconPixmap")].value() >> image; if (image.isEmpty()) { - QString iconName = properties[QStringLiteral("OverlayIconName")].toString(); - setData(QStringLiteral("OverlayIconName"), iconName); - if (!iconName.isEmpty()) { - overlayNames << iconName; - overlay = QIcon(new KIconEngine(iconName, iconLoader())); + if (!overlayIconName.isEmpty()) { + overlayNames << overlayIconName; + overlay = QIcon(new KIconEngine(overlayIconName, iconLoader())); + setData(QStringLiteral("OverlayIconPixmap"), QVariant()); } } else { overlay = imageVectorToPixmap(image); + setData(QStringLiteral("OverlayIconPixmap"), overlay); } - + QString iconName = properties[QStringLiteral("IconName")].toString(); + setData(QStringLiteral("IconName"), iconName); properties[QStringLiteral("IconPixmap")].value() >> image; if (image.isEmpty()) { - iconName = properties[QStringLiteral("IconName")].toString(); if (!iconName.isEmpty()) { icon = QIcon(new KIconEngine(iconName, iconLoader(), overlayNames)); - if (overlayNames.isEmpty() && !overlay.isNull()) { overlayIcon(&icon, &overlay); } } + setData(QStringLiteral("IconPixmap"), QVariant()); } else { icon = imageVectorToPixmap(image); + setData(QStringLiteral("IconPixmap"), icon); if (!icon.isNull() && !overlay.isNull()) { overlayIcon(&icon, &overlay); } } setData(QStringLiteral("Icon"), icon.isNull() ? QVariant() : icon); - setData(QStringLiteral("IconName"), iconName); } //Attention icon { KDbusImageVector image; QIcon attentionIcon; - + QString attentionIconName = properties[QStringLiteral("AttentionIconName")].toString(); + setData(QStringLiteral("AttentionIconName"), attentionIconName); properties[QStringLiteral("AttentionIconPixmap")].value() >> image; if (image.isEmpty()) { QString iconName = properties[QStringLiteral("AttentionIconName")].toString(); - setData(QStringLiteral("AttentionIconName"), iconName); if (!iconName.isEmpty()) { attentionIcon = QIcon(new KIconEngine(iconName, iconLoader(), overlayNames)); - if (overlayNames.isEmpty() && !overlay.isNull()) { overlayIcon(&attentionIcon, &overlay); } } + setData(QStringLiteral("AttentionIconPixmap"), QVariant()); } else { attentionIcon = imageVectorToPixmap(image); + setData(QStringLiteral("AttentionIconPixmap"), attentionIcon); if (!attentionIcon.isNull() && !overlay.isNull()) { overlayIcon(&attentionIcon, &overlay); } @@ -377,7 +382,6 @@ } } } - checkForUpdate(); call->deleteLater(); }