Commit e8702822 authored by Konrad Materka's avatar Konrad Materka
Browse files

[applets/systemtray] Use QAbstractListModel

Rewrite model to use QAbstractListModel instead of QStandardItemModel
parent b529ec7a
......@@ -30,5 +30,6 @@ install(TARGETS org.kde.plasma.private.systemtray DESTINATION ${KDE_INSTALL_PLUG
add_subdirectory(container)
if(BUILD_TESTING)
add_subdirectory(autotests)
add_subdirectory(tests)
endif()
include(ECMAddTests)
set(systemtraymodel_test_SRCS
../systemtraymodel.cpp
../sortedsystemtraymodel.cpp
)
ecm_qt_declare_logging_category(systemtraymodel_test_SRCS HEADER debug.h
IDENTIFIER SYSTEM_TRAY
CATEGORY_NAME kde.systemtray
DEFAULT_SEVERITY Info)
add_library(systemtraymodel_test STATIC ${systemtraymodel_test_SRCS})
target_link_libraries(systemtraymodel_test
Qt5::Core
Qt5::Quick
KF5::Plasma
KF5::I18n
KF5::ItemModels
KF5::CoreAddons
)
ecm_add_tests(systemtraymodeltest.cpp
LINK_LIBRARIES systemtraymodel_test
Qt5::Test
)
[Desktop Entry]
Name=Device Notifier
Name[pl]=Powiadomienia o urządzeniach
Comment=Notifications and access for new devices
Comment[pl]=Powiadamia i daje dostęp do nowych urządzeń
Icon=device-notifier
Type=Service
X-KDE-ServiceTypes=Plasma/Applet
X-Plasma-API=declarativeappletscript
X-Plasma-MainScript=ui/devicenotifier.qml
X-Plasma-NotificationArea=true
X-Plasma-NotificationAreaCategory=Hardware
X-Plasma-Provides=org.kde.plasma.removabledevices
X-KDE-PluginInfo-Author=Viranch Mehta, Jacopo De Simoi
X-KDE-PluginInfo-Email=wilderkde@gmail.com
X-KDE-PluginInfo-Name=org.kde.plasma.devicenotifier.test
X-KDE-PluginInfo-Version=1.0
X-KDE-PluginInfo-Website=https://userbase.kde.org/Plasma/DeviceNotifier
X-KDE-PluginInfo-Category=System Information
X-KDE-PluginInfo-Depends=
X-KDE-PluginInfo-License=GPL-2.0+
X-KDE-PluginInfo-EnabledByDefault=true
[Desktop Entry]
Name=Media Player
Name[pl]=Odtwarzacz multimedialny
Comment=Media Player Controls
Comment[pl]=Obsługa odtwarzacza multimedialnego
Icon=applications-multimedia
Type=Service
X-KDE-ServiceTypes=Plasma/Applet
X-KDE-PluginInfo-Author=Sebastian Kügler
X-KDE-PluginInfo-Category=Multimedia
X-KDE-PluginInfo-Depends=
X-KDE-PluginInfo-Email=sebas@kde.org
X-KDE-PluginInfo-EnabledByDefault=true
X-KDE-PluginInfo-License=GPL-2.0+
X-KDE-PluginInfo-Name=org.kde.plasma.mediacontroller.test
X-KDE-PluginInfo-Version=1.0
X-KDE-PluginInfo-Website=https://www.kde.org/plasma-desktop
X-Plasma-StandAloneApp=true
X-Plasma-API=declarativeappletscript
X-Plasma-MainScript=ui/main.qml
X-Plasma-NotificationArea=true
X-Plasma-NotificationAreaCategory=ApplicationStatus
X-Plasma-Provides=org.kde.plasma.multimediacontrols
X-Plasma-DBusActivationService=org.mpris.MediaPlayer2.*
/*
* Copyright 2020 Konrad Materka <materka@gmail.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) version 3, or any
* later version accepted by the membership of KDE e.V. (or its
* successor approved by the membership of KDE e.V.), which shall
* act as a proxy defined in Section 6 of version 3 of the license.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
#include <QtTest>
#include <Plasma/Applet>
#include <Plasma/DataEngine>
#include <Plasma/PluginLoader>
#include "../systemtraymodel.h"
class SystemTrayModelTest : public QObject
{
Q_OBJECT
private Q_SLOTS:
void init();
void testPlasmoidModel();
};
void SystemTrayModelTest::init()
{
QLocale::setDefault(QLocale("en_US"));
qunsetenv("LANGUAGE");
qunsetenv("LC_ALL");
qunsetenv("LC_MESSAGES");
qunsetenv("LANG");
}
void SystemTrayModelTest::testPlasmoidModel()
{
//given: sample plugin meta data
QList<KPluginMetaData> list;
list.append(KPluginMetaData(QFINDTESTDATA("data/mediacontroller/metadata.desktop")));
list.append(KPluginMetaData(QFINDTESTDATA("data/devicenotifier/metadata.desktop")));
//when: model is initialized
PlasmoidModel *model = new PlasmoidModel();
model->init(list);
//expect: passes consistency tests
new QAbstractItemModelTester(model, QAbstractItemModelTester::FailureReportingMode::Fatal);
//and expect: correct model size
QCOMPARE(model->rowCount(), 2);
QCOMPARE(model->roleNames().size(), 10);
//and expect: correct data returned
QModelIndex idx = model->index(0, 0);
QCOMPARE(model->data(idx, Qt::DisplayRole).toString(), "Media Player (Automatic load)");
QVERIFY(model->data(idx, Qt::DecorationRole).isValid());
QCOMPARE(model->data(idx, static_cast<int>(BaseModel::BaseRole::ItemType)).toString(), "Plasmoid");
QCOMPARE(model->data(idx, static_cast<int>(BaseModel::BaseRole::ItemId)).toString(), "org.kde.plasma.mediacontroller.test");
QVERIFY(!model->data(idx, static_cast<int>(BaseModel::BaseRole::CanRender)).toBool());
QCOMPARE(model->data(idx, static_cast<int>(BaseModel::BaseRole::Category)).toString(), "ApplicationStatus");
QCOMPARE(model->data(idx, static_cast<int>(BaseModel::BaseRole::Status)), QVariant(Plasma::Types::ItemStatus::UnknownStatus));
QCOMPARE(model->data(idx, static_cast<int>(BaseModel::BaseRole::EffectiveStatus)), QVariant(Plasma::Types::ItemStatus::HiddenStatus));
QVERIFY(!model->data(idx, static_cast<int>(PlasmoidModel::Role::HasApplet)).toBool());
idx = model->index(1, 0);
QCOMPARE(model->data(idx, Qt::DisplayRole).toString(), "Device Notifier");
QVERIFY(model->data(idx, Qt::DecorationRole).isValid());
QCOMPARE(model->data(idx, static_cast<int>(BaseModel::BaseRole::ItemType)).toString(), "Plasmoid");
QCOMPARE(model->data(idx, static_cast<int>(BaseModel::BaseRole::ItemId)).toString(), "org.kde.plasma.devicenotifier.test");
QVERIFY(!model->data(idx, static_cast<int>(BaseModel::BaseRole::CanRender)).toBool());
QCOMPARE(model->data(idx, static_cast<int>(BaseModel::BaseRole::Category)).toString(), "Hardware");
QCOMPARE(model->data(idx, static_cast<int>(BaseModel::BaseRole::Status)), QVariant(Plasma::Types::ItemStatus::UnknownStatus));
QCOMPARE(model->data(idx, static_cast<int>(BaseModel::BaseRole::EffectiveStatus)), QVariant(Plasma::Types::ItemStatus::HiddenStatus));
QVERIFY(!model->data(idx, static_cast<int>(PlasmoidModel::Role::HasApplet)).toBool());
//when: language is changed
QLocale::setDefault(QLocale("pl_PL"));
qputenv("LANG", "pl_PL.UTF-8");
qputenv("LC_MESSAGES", "pl_PL.UTF-8");
//then expect: translated data returned
QCOMPARE(model->data(idx, Qt::DisplayRole).toString(), "Powiadomienia o urz\u0105dzeniach");
//when: applet added
model->addApplet(new Plasma::Applet(list.at(1)));
//then: applet can be rendered
QVERIFY(model->data(idx, static_cast<int>(BaseModel::BaseRole::CanRender)).toBool());
QVERIFY(model->data(idx, static_cast<int>(PlasmoidModel::Role::HasApplet)).toBool());
QCOMPARE(model->data(idx, static_cast<int>(BaseModel::BaseRole::EffectiveStatus)), QVariant(Plasma::Types::ItemStatus::ActiveStatus));
//and when: applet removed
model->removeApplet(new Plasma::Applet(list.at(1)));
//then: applet cannot be rendered anymore
QVERIFY(!model->data(idx, static_cast<int>(BaseModel::BaseRole::CanRender)).toBool());
QVERIFY(!model->data(idx, static_cast<int>(PlasmoidModel::Role::HasApplet)).toBool());
//and when: invalid index
idx = model->index(4, 0);
//then: empty value
QVERIFY(model->data(idx, static_cast<int>(BaseModel::BaseRole::ItemType)).isNull());
QVERIFY(!model->data(idx, static_cast<int>(BaseModel::BaseRole::ItemType)).isValid());
idx = model->index(1, 1);
QVERIFY(model->data(idx, static_cast<int>(BaseModel::BaseRole::ItemType)).isNull());
QVERIFY(!model->data(idx, static_cast<int>(BaseModel::BaseRole::ItemType)).isValid());
delete model;
}
QTEST_MAIN(SystemTrayModelTest)
#include "systemtraymodeltest.moc"
......@@ -54,10 +54,10 @@ AbstractItem {
onClicked: {
var pos = plasmoid.nativeInterface.popupPosition(taskIcon, mouse.x, mouse.y);
var service = model.Service;
switch (mouse.button) {
case Qt.LeftButton:
var service = plasmoid.nativeInterface.serviceForSource(model.DataEngineSource);
var operation = service.operationDescription("Activate");
operation.x = pos.x;
operation.y = pos.y;
......@@ -76,7 +76,6 @@ AbstractItem {
break;
case Qt.MiddleButton:
var service = plasmoid.nativeInterface.serviceForSource(model.DataEngineSource);
var operation = service.operationDescription("SecondaryActivate");
operation.x = pos.x;
......@@ -88,7 +87,7 @@ AbstractItem {
}
function openContextMenu(pos) {
var service = plasmoid.nativeInterface.serviceForSource(model.DataEngineSource);
var service = model.Service;
var operation = service.operationDescription("ContextMenu");
operation.x = pos.x;
operation.y = pos.y;
......@@ -102,14 +101,14 @@ AbstractItem {
onWheel: {
//don't send activateVertScroll with a delta of 0, some clients seem to break (kmix)
if (wheel.angleDelta.y !== 0) {
var service = plasmoid.nativeInterface.serviceForSource(model.DataEngineSource);
var service = model.Service;
var operation = service.operationDescription("Scroll");
operation.delta =wheel.angleDelta.y;
operation.direction = "Vertical";
service.startOperationCall(operation);
}
if (wheel.angleDelta.x !== 0) {
var service = plasmoid.nativeInterface.serviceForSource(model.DataEngineSource);
var service = model.Service;
var operation = service.operationDescription("Scroll");
operation.delta =wheel.angleDelta.x;
operation.direction = "Horizontal";
......
......@@ -303,11 +303,6 @@ bool SystemTray::isSystemTrayApplet(const QString &appletId)
return m_systrayApplets.contains(appletId);
}
Plasma::Service *SystemTray::serviceForSource(const QString &source)
{
return m_statusNotifierModel->serviceForSource(source);
}
void SystemTray::restoreContents(KConfigGroup &group)
{
QStringList newKnownItems;
......@@ -436,6 +431,7 @@ SystemTrayModel *SystemTray::systemTrayModel()
m_systemTrayModel = new SystemTrayModel(this);
PlasmoidModel *currentPlasmoidsModel = new PlasmoidModel(m_systemTrayModel);
currentPlasmoidsModel->init(Plasma::PluginLoader::self()->listAppletMetaData(QString()));
connect(this, &SystemTray::appletAdded, currentPlasmoidsModel, &PlasmoidModel::addApplet);
connect(this, &SystemTray::appletRemoved, currentPlasmoidsModel, &PlasmoidModel::removeApplet);
connect(this, &SystemTray::configurationChanged, currentPlasmoidsModel, &PlasmoidModel::onConfigurationChanged);
......
......@@ -87,12 +87,6 @@ public:
Q_INVOKABLE bool isSystemTrayApplet(const QString &appletId);
/**
* @returns a Plasma::Service given a source name
* @param source source name we want a service of
*/
Q_INVOKABLE Plasma::Service *serviceForSource(const QString &source);
private Q_SLOTS:
void serviceNameFetchFinished(QDBusPendingCallWatcher* watcher);
......
This diff is collapsed.
......@@ -20,17 +20,20 @@
#ifndef SYSTEMTRAYMODEL_H
#define SYSTEMTRAYMODEL_H
#include <QStandardItemModel>
#include <QAbstractListModel>
#include <QList>
#include <KCoreAddons/KPluginMetaData>
#include <KItemModels/KConcatenateRowsProxyModel>
#include <Plasma/DataEngineConsumer>
#include <Plasma/DataEngine>
namespace Plasma {
class Applet;
class PluginLoader;
}
class BaseModel: public QStandardItemModel
class BaseModel: public QAbstractListModel
{
Q_OBJECT
public:
......@@ -51,15 +54,10 @@ public:
public slots:
void onConfigurationChanged(const KConfigGroup &config);
private slots:
void onRowsInserted(const QModelIndex &parent, int first, int last);
void onDataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight, const QVector<int> &roles);
protected:
Plasma::Types::ItemStatus calculateEffectiveStatus(bool canRender, Plasma::Types::ItemStatus status, QString itemId) const;
private:
void updateEffectiveStatus(QStandardItem *dataItem);
Plasma::Types::ItemStatus calculateEffectiveStatus(QStandardItem *dataItem);
Plasma::Types::ItemStatus readStatus(QStandardItem *dataItem) const;
bool m_showAllItems;
QStringList m_shownItems;
QStringList m_hiddenItems;
......@@ -76,11 +74,26 @@ public:
explicit PlasmoidModel(QObject *parent = nullptr);
void init(const QList<KPluginMetaData> appletMetaDataList);
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
int rowCount(const QModelIndex &parent = QModelIndex()) const override;
QHash<int, QByteArray> roleNames() const override;
public slots:
void addApplet(Plasma::Applet *applet);
void removeApplet(Plasma::Applet *applet);
private:
struct Item {
KPluginMetaData pluginMetaData;
Plasma::Applet *applet = nullptr;
};
void appendRow(const KPluginMetaData &pluginMetaData);
int indexOfPluginId(const QString &pluginId) const;
QVector<Item> m_items;
};
class StatusNotifierModel : public BaseModel, public Plasma::DataEngineConsumer {
......@@ -88,6 +101,7 @@ class StatusNotifierModel : public BaseModel, public Plasma::DataEngineConsumer
public:
enum class Role {
DataEngineSource = static_cast<int>(BaseModel::BaseRole::LastBaseRole) + 100,
Service,
AttentionIcon,
AttentionIconName,
AttentionMovieName,
......@@ -105,23 +119,27 @@ public:
WindowId
};
StatusNotifierModel(QObject* parent);
StatusNotifierModel(QObject* parent = nullptr);
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
int rowCount(const QModelIndex &parent = QModelIndex()) const override;
QHash<int, QByteArray> roleNames() const override;
Plasma::Service *serviceForSource(const QString &source);
public slots:
void addSource(const QString &source);
void removeSource(const QString &source);
void dataUpdated(const QString &sourceName, const Plasma::DataEngine::Data &data);
private:
void updateItemData(QStandardItem *dataItem, const Plasma::DataEngine::Data &data, const Role role);
struct Item {
QString source;
Plasma::Service *service = nullptr;
};
int indexOfSource(const QString &source) const;
Plasma::DataEngine *m_dataEngine = nullptr;
QStringList m_sources;
QHash<QString, Plasma::Service *> m_services;
QVector<Item> m_items;
};
class SystemTrayModel : public KConcatenateRowsProxyModel
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment