diff --git a/faces/SensorFace.cpp b/faces/SensorFace.cpp index d405d8c..f5080a7 100644 --- a/faces/SensorFace.cpp +++ b/faces/SensorFace.cpp @@ -1,102 +1,104 @@ /* Copyright (C) 2020 Marco Martin This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "SensorFace_p.h" #include "SensorFaceController.h" #include +using namespace KSysGuard; + class SensorFace::Private { public: QPointer contentItem; SensorFaceController *controller = nullptr; FormFactor formFactor = Planar; }; SensorFace::SensorFace(QQuickItem *parent) : QQuickItem(parent), d(std::make_unique()) { } SensorFace::~SensorFace() { } SensorFaceController *SensorFace::controller() const { return d->controller; } // Not writable from QML void SensorFace::setController(SensorFaceController *controller) { d->controller = controller; } SensorFace::FormFactor SensorFace::formFactor() const { return d->formFactor; } void SensorFace::setFormFactor(SensorFace::FormFactor formFactor) { if (d->formFactor == formFactor) { return; } d->formFactor = formFactor; emit formFactorChanged(); } QQuickItem * SensorFace::contentItem() const { return d->contentItem; } void SensorFace::setContentItem(QQuickItem *item) { if (d->contentItem == item) { return; } d->contentItem = item; if (d->contentItem) { d->contentItem->setParentItem(this); d->contentItem->setX(0); d->contentItem->setY(0); d->contentItem->setSize(size()); } emit contentItemChanged(); } void SensorFace::geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry) { if (d->contentItem) { d->contentItem->setX(0); d->contentItem->setY(0); d->contentItem->setSize(newGeometry.size()); } QQuickItem::geometryChanged(newGeometry, oldGeometry); } #include "moc_SensorFace_p.cpp" diff --git a/faces/SensorFaceController.cpp b/faces/SensorFaceController.cpp index 02f890f..5eafdf4 100644 --- a/faces/SensorFaceController.cpp +++ b/faces/SensorFaceController.cpp @@ -1,678 +1,680 @@ /* Copyright (C) 2020 Marco Martin This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "SensorFaceController.h" #include "SensorFaceController_p.h" #include "SensorFace_p.h" #include #include #include #include #include #include #include #include +using namespace KSysGuard; + FacesModel::FacesModel(QObject *parent) : QStandardItemModel(parent) { reload(); } void FacesModel::reload() { clear(); auto list = KPackage::PackageLoader::self()->listPackages(QStringLiteral("KSysguard/SensorFace")); // NOTE: This will disable completely the internal in-memory cache KPackage::Package p; p.install(QString(), QString()); for (auto plugin : list) { QStandardItem *item = new QStandardItem(plugin.name()); item->setData(plugin.pluginId(), FacesModel::PluginIdRole); appendRow(item); } } QString FacesModel::pluginId(int row) { return data(index(row, 0), PluginIdRole).toString(); } QHash FacesModel::roleNames() const { QHash roles = QAbstractItemModel::roleNames(); roles[PluginIdRole] = "pluginId"; return roles; } PresetsModel::PresetsModel(QObject *parent) : QStandardItemModel(parent) { reload(); } void PresetsModel::reload() { clear(); QList plugins = KPackage::PackageLoader::self()->findPackages(QStringLiteral("Plasma/Applet"), QString(), [](const KPluginMetaData &plugin) { return plugin.value(QStringLiteral("X-Plasma-RootPath")) == QStringLiteral("org.kde.plasma.systemmonitor"); }); QSet usedNames; // We iterate backwards because packages under ~/.local are listed first, while we want them last auto it = plugins.rbegin(); for (; it != plugins.rend(); ++it) { const auto &plugin = *it; KPackage::Package p = KPackage::PackageLoader::self()->loadPackage(QStringLiteral("Plasma/Applet"), plugin.pluginId()); KDesktopFile df(p.path() + QStringLiteral("metadata.desktop")); QString baseName = df.readName(); QString name = baseName; int id = 0; while (usedNames.contains(name)) { name = baseName + QStringLiteral(" (") + QString::number(++id) + QStringLiteral(")"); } usedNames << name; QStandardItem *item = new QStandardItem(baseName); // TODO config QVariantMap config; KConfigGroup configGroup(df.group("Config")); const QStringList keys = configGroup.keyList(); for (const QString &key : keys) { // all strings for now, type conversion happens in QML side when we have the config property map config.insert(key, configGroup.readEntry(key)); } item->setData(plugin.pluginId(), PresetsModel::PluginIdRole); item->setData(config, PresetsModel::ConfigRole); item->setData(QFileInfo(p.path() + QStringLiteral("metadata.desktop")).isWritable(), PresetsModel::WritableRole); appendRow(item); } } QHash PresetsModel::roleNames() const { QHash roles = QAbstractItemModel::roleNames(); roles[PluginIdRole] = "pluginId"; roles[ConfigRole] = "config"; roles[WritableRole] = "writable"; return roles; } class SensorFaceController::Private { public: Private(); SensorFace *createGui(const QString &qmlPath); QQuickItem *createConfigUi(const QString &file, const QVariantMap &initialProperties); SensorFaceController *q; QString title; QQmlEngine *engine; KDesktopFile *faceMetadata = nullptr; KDeclarative::ConfigPropertyMap *faceConfiguration = nullptr; KConfigLoader *faceConfigLoader = nullptr; bool configNeedsSave = false; KPackage::Package facePackage; QString faceId; KConfigGroup configGroup; KConfigGroup appearanceGroup; KConfigGroup sensorsGroup; QPointer fullRepresentation; QPointer compactRepresentation; QPointer faceConfigUi; QPointer appearanceConfigUi; QPointer sensorsConfigUi; QTimer *syncTimer; FacesModel *availableFacesModel = nullptr; PresetsModel *availablePresetsModel = nullptr; }; SensorFaceController::Private::Private() {} SensorFace *SensorFaceController::Private::createGui(const QString &qmlPath) { QQmlComponent *component = new QQmlComponent(engine, qmlPath, nullptr); // TODO: eventually support async components? (only useful for qml files from http, we probably don't want that) if (component->status() != QQmlComponent::Ready) { qCritical() << "Error creating component:"; for (auto err : component->errors()) { qWarning() << err.toString(); } component->deleteLater(); return nullptr; } //TODO: add i18n context object QQmlContext *context = new QQmlContext(engine); QObject *guiObject = component->beginCreate(context); SensorFace *gui = qobject_cast(guiObject); if (!gui) { qWarning()<<"ERROR: QML gui" << guiObject << "not a SensorFace instance"; guiObject->deleteLater(); context->deleteLater(); return nullptr; } // context->setParent(gui); gui->setController(q); component->completeCreate(); component->deleteLater(); return gui; } QQuickItem *SensorFaceController::Private::createConfigUi(const QString &file, const QVariantMap &initialProperties) { QQmlComponent *component = new QQmlComponent(engine, file, nullptr); // TODO: eventually support async components? (only useful for qml files from http, we probably don't want that) if (component->status() != QQmlComponent::Ready) { qCritical() << "Error creating component:"; for (auto err : component->errors()) { qWarning() << err.toString(); } component->deleteLater(); return nullptr; } //TODO: add i18n context object QQmlContext *context = new QQmlContext(engine); QObject *guiObject = component->createWithInitialProperties( initialProperties, context); QQuickItem *gui = qobject_cast(guiObject); Q_ASSERT(gui); component->deleteLater(); return gui; } SensorFaceController::SensorFaceController(KConfigGroup &config, QQmlEngine *engine) : QObject(engine), d(std::make_unique()) { d->q = this; d->configGroup = config; d->appearanceGroup = KConfigGroup(&config, "Appearance"); d->sensorsGroup = KConfigGroup(&config, "Sensors"); d->engine = engine; d->syncTimer = new QTimer(this); d->syncTimer->setSingleShot(true); d->syncTimer->setInterval(5000); connect(d->syncTimer, &QTimer::timeout, this, [this]() { d->appearanceGroup.sync(); d->sensorsGroup.sync(); }); setFaceId(d->appearanceGroup.readEntry("chartFace", QStringLiteral("org.kde.ksysguard.piechart"))); } SensorFaceController::~SensorFaceController() { } QString SensorFaceController::title() const { return d->appearanceGroup.readEntry("title", name()); } void SensorFaceController::setTitle(const QString &title) { if (title == SensorFaceController::title()) { return; } d->appearanceGroup.writeEntry("title", title); d->syncTimer->start(); emit titleChanged(); } QString SensorFaceController::totalSensor() const { return d->sensorsGroup.readEntry("totalSensor", QString()); } void SensorFaceController::setTotalSensor(const QString &totalSensor) { if (totalSensor == SensorFaceController::totalSensor()) { return; } d->sensorsGroup.writeEntry("totalSensor", totalSensor); d->syncTimer->start(); emit totalSensorChanged(); } QStringList SensorFaceController::sensorIds() const { return d->sensorsGroup.readEntry("sensorIds", QStringList()); } void SensorFaceController::setSensorIds(const QStringList &sensorIds) { if (sensorIds == SensorFaceController::sensorIds()) { return; } d->sensorsGroup.writeEntry("sensorIds", sensorIds); d->syncTimer->start(); emit sensorIdsChanged(); } QStringList SensorFaceController::sensorColors() const { return d->sensorsGroup.readEntry("sensorColors", QStringList()); } void SensorFaceController::setSensorColors(const QStringList &sensorColors) { if (sensorColors == SensorFaceController::sensorColors()) { return; } d->sensorsGroup.writeEntry("sensorColors", sensorColors); d->syncTimer->start(); emit sensorColorsChanged(); } QStringList SensorFaceController::textOnlySensorIds() const { return d->sensorsGroup.readEntry("textOnlySensorIds", QStringList()); } void SensorFaceController::setTextOnlySensorIds(const QStringList &textOnlySensorIds) { if (textOnlySensorIds == SensorFaceController::textOnlySensorIds()) { return; } d->sensorsGroup.writeEntry("textOnlySensorIds", textOnlySensorIds); d->syncTimer->start(); emit textOnlySensorIdsChanged(); } // from face config, immutable by the user QString SensorFaceController::name() const { if (!d->faceMetadata) { return QString(); } return d->faceMetadata->readName(); } const QString SensorFaceController::icon() const { if (!d->faceMetadata) { return QString(); } return d->faceMetadata->readIcon(); } bool SensorFaceController::supportsSensorsColors() const { if (!d->faceMetadata) { return false; } KConfigGroup cg(d->faceMetadata, QStringLiteral("Config")); return cg.readEntry("SupportsSensorsColors", false); } bool SensorFaceController::supportsTotalSensor() const { if (!d->faceMetadata) { return false; } KConfigGroup cg(d->faceMetadata, QStringLiteral("Config")); return cg.readEntry("SupportsTotalSensor", false); } bool SensorFaceController::supportsTextOnlySensors() const { if (!d->faceMetadata) { return false; } KConfigGroup cg(d->faceMetadata, QStringLiteral("Config")); return cg.readEntry("SupportsTextOnlySensors", false); } void SensorFaceController::setFaceId(const QString &face) { if (d->faceId == face) { return; } if (d->fullRepresentation) { d->fullRepresentation->deleteLater(); } if (d->compactRepresentation) { d->compactRepresentation->deleteLater(); } d->faceId = face; d->facePackage = KPackage::PackageLoader::self()->loadPackage(QStringLiteral("KSysguard/SensorFace"), face); delete d->faceMetadata; d->faceMetadata = nullptr; if (d->faceConfiguration) { d->faceConfiguration->deleteLater(); d->faceConfiguration = nullptr; } if (d->faceConfigLoader) { d->faceConfigLoader ->deleteLater(); d->faceConfigLoader = nullptr; } if (!d->facePackage.isValid()) { emit faceIdChanged(); return; } - d->faceMetadata = new KDesktopFile(d->facePackage.path() + QStringLiteral("metadata.desktop")); + d->faceMetadata = new KDesktopFile(d->facePackage.filePath("metadata")); const QString xmlPath = d->facePackage.filePath("mainconfigxml"); if (!xmlPath.isEmpty()) { QFile file(xmlPath); KConfigGroup cg(&d->configGroup, d->faceId); d->faceConfigLoader = new KConfigLoader(cg, &file, this); d->faceConfiguration = new KDeclarative::ConfigPropertyMap(d->faceConfigLoader, this); } d->appearanceGroup.writeEntry("chartFace", face); d->syncTimer->start(); emit faceIdChanged(); return; } QString SensorFaceController::faceId() const { return d->faceId; } KDeclarative::ConfigPropertyMap *SensorFaceController::faceConfiguration() const { return d->faceConfiguration; } QQuickItem *SensorFaceController::compactRepresentation() { if (!d->facePackage.isValid()) { return nullptr; } else if (d->compactRepresentation) { return d->compactRepresentation; } d->fullRepresentation = d->createGui(d->facePackage.filePath("ui", QStringLiteral("CompactRepresentation.qml"))); return d->compactRepresentation; } QQuickItem *SensorFaceController::fullRepresentation() { if (!d->facePackage.isValid()) { return nullptr; } else if (d->fullRepresentation) { return d->fullRepresentation; } d->fullRepresentation = d->createGui(d->facePackage.filePath("ui", QStringLiteral("FullRepresentation.qml"))); return d->fullRepresentation; } QQuickItem *SensorFaceController::faceConfigUi() { if (!d->facePackage.isValid()) { return nullptr; } else if (d->faceConfigUi) { return d->faceConfigUi; } d->faceConfigUi = d->createConfigUi(QStringLiteral(":/FaceDetailsConfig.qml"), {{QStringLiteral("controller"), QVariant::fromValue(this)}, {QStringLiteral("source"), d->facePackage.filePath("ui", QStringLiteral("Config.qml"))}}); return d->faceConfigUi; } QQuickItem *SensorFaceController::appearanceConfigUi() { if (d->appearanceConfigUi) { return d->appearanceConfigUi; } d->appearanceConfigUi = d->createConfigUi(QStringLiteral(":/ConfigAppearance.qml"), {{QStringLiteral("controller"), QVariant::fromValue(this)}}); return d->appearanceConfigUi; } QQuickItem *SensorFaceController::sensorsConfigUi() { if (d->sensorsConfigUi) { return d->sensorsConfigUi; } d->sensorsConfigUi = d->createConfigUi(QStringLiteral(":/ConfigSensors.qml"), {{QStringLiteral("controller"), QVariant::fromValue(this)}}); return d->sensorsConfigUi; } QAbstractItemModel *SensorFaceController::availableFacesModel() { if (d->availableFacesModel) { return d->availableFacesModel; } d->availableFacesModel = new FacesModel(this); return d->availableFacesModel; } QAbstractItemModel *SensorFaceController::availablePresetsModel() { if (d->availablePresetsModel) { return d->availablePresetsModel; } d->availablePresetsModel = new PresetsModel(this); return d->availablePresetsModel; } void SensorFaceController::reloadConfig() { if (d->faceConfigLoader) { d->faceConfigLoader->load(); } //Force to re-read all the values setFaceId(d->appearanceGroup.readEntry("chartFace", QStringLiteral("org.kde.ksysguard.piechart"))); titleChanged(); totalSensorChanged(); sensorIdsChanged(); sensorColorsChanged(); textOnlySensorIdsChanged(); } void SensorFaceController::loadPreset(const QString &preset) { if (preset.isEmpty()) { return; } auto presetPackage = KPackage::PackageLoader::self()->loadPackage(QStringLiteral("Plasma/Applet")); presetPackage.setPath(preset); if (!presetPackage.isValid()) { return; } if (presetPackage.metadata().value(QStringLiteral("X-Plasma-RootPath")) != QStringLiteral("org.kde.plasma.systemmonitor")) { return; } KDesktopFile df(presetPackage.path() + QStringLiteral("metadata.desktop")); KConfigGroup presetGroup(df.group("Config")); // Load the title setTitle(df.readName()); //Remove the "custon" value from presets models if (d->availablePresetsModel && d->availablePresetsModel->data(d->availablePresetsModel->index(0, 0), PresetsModel::PluginIdRole).toString().isEmpty()) { d->availablePresetsModel->removeRow(0); } auto loadSensors = [this](const QStringList &partialEntries) { QStringList sensors; for (const QString &id : partialEntries) { KSysGuard::SensorQuery query{id}; query.execute(); query.waitForFinished(); sensors.append(query.sensorIds()); } return sensors; }; setTotalSensor(presetGroup.readEntry(QStringLiteral("totalSensor"), QString())); setSensorIds(loadSensors(presetGroup.readEntry(QStringLiteral("sensorIds"), QStringList()))); setTextOnlySensorIds(loadSensors(presetGroup.readEntry(QStringLiteral("textOnlySensorIds"), QStringList()))); setSensorColors(presetGroup.readEntry(QStringLiteral("sensorColors"), QStringList())); setFaceId(presetGroup.readEntry(QStringLiteral("chartFace"), QStringLiteral("org.kde.ksysguard.piechart"))); if (d->faceConfigLoader) { presetGroup = KConfigGroup(df.group("FaceConfig")); for (const QString &key : presetGroup.keyList()) { KConfigSkeletonItem *item = d->faceConfigLoader->findItemByName(key); if (item) { if (item->property().type() == QVariant::StringList) { item->setProperty(presetGroup.readEntry(key, QStringList())); } else { item->setProperty(presetGroup.readEntry(key)); } d->faceConfigLoader->save(); d->faceConfigLoader->read(); } } } } void SensorFaceController::savePreset() { QString pluginName = QStringLiteral("org.kde.plasma.systemmonitor.") + title().simplified().replace(QLatin1Char(' '), QChar()).toLower(); int suffix = 0; auto presetPackage = KPackage::PackageLoader::self()->loadPackage(QStringLiteral("Plasma/Applet")); presetPackage.setPath(pluginName); if (presetPackage.isValid()) { do { presetPackage.setPath(QString()); presetPackage.setPath(pluginName + QString::number(++suffix)); } while (presetPackage.isValid()); pluginName += QString::number(suffix); } QTemporaryDir dir; if (!dir.isValid()) { return; } KConfig c(dir.path() % QLatin1Literal("/metadata.desktop")); KConfigGroup cg(&c, "Desktop Entry"); cg.writeEntry("Name", title()); cg.writeEntry("Icon", "ksysguardd"); cg.writeEntry("X-Plasma-API", "declarativeappletscript"); cg.writeEntry("X-Plasma-MainScript", "ui/main.qml"); cg.writeEntry("X-Plasma-Provides", "org.kde.plasma.systemmonitor"); cg.writeEntry("X-Plasma-RootPath", "org.kde.plasma.systemmonitor"); cg.writeEntry("X-KDE-PluginInfo-Name", pluginName); cg.writeEntry("X-KDE-ServiceTypes", "Plasma/Applet"); cg.writeEntry("X-KDE-PluginInfo-Category", "System Information"); cg.writeEntry("X-KDE-PluginInfo-License", "LGPL 2.1+"); cg.writeEntry("X-KDE-PluginInfo-EnabledByDefault", "true"); cg.writeEntry("X-KDE-PluginInfo-Version", "0.1"); cg.sync(); KConfigGroup configGroup(&c, "Config"); configGroup.writeEntry(QStringLiteral("totalSensor"), totalSensor()); configGroup.writeEntry(QStringLiteral("sensorIds"), sensorIds()); configGroup.writeEntry(QStringLiteral("textOnlySensorIds"), textOnlySensorIds()); configGroup.writeEntry(QStringLiteral("sensorColors"), sensorColors()); auto *job = presetPackage.install(dir.path()); connect(job, &KJob::finished, this, [this, pluginName] () { d->availablePresetsModel->reload(); }); } void SensorFaceController::uninstallPreset(const QString &pluginId) { auto presetPackage = KPackage::PackageLoader::self()->loadPackage(QStringLiteral("Plasma/Applet"), pluginId); if (presetPackage.metadata().value(QStringLiteral("X-Plasma-RootPath")) != QStringLiteral("org.kde.plasma.systemmonitor")) { return; } QDir root(presetPackage.path()); root.cdUp(); auto *job = presetPackage.uninstall(pluginId, root.path()); connect(job, &KJob::finished, this, [this] () { d->availablePresetsModel->reload(); }); } #include "moc_SensorFaceController.cpp" diff --git a/faces/SensorFaceController.h b/faces/SensorFaceController.h index 8b24d4e..805c94c 100644 --- a/faces/SensorFaceController.h +++ b/faces/SensorFaceController.h @@ -1,125 +1,128 @@ /* Copyright (C) 2020 Marco Martin This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #pragma once #include #include #include #include #include #include "sensorfaces_export.h" namespace KDeclarative { class ConfigPropertyMap; } class QQmlEngine; class KDesktopFile; class KConfigLoader; + +namespace KSysGuard { + class SensorFace; class SENSORFACES_EXPORT SensorFaceController : public QObject { Q_OBJECT Q_PROPERTY(QString title READ title WRITE setTitle NOTIFY titleChanged) Q_PROPERTY(QString faceId READ faceId WRITE setFaceId NOTIFY faceIdChanged) Q_PROPERTY(QString totalSensor READ totalSensor WRITE setTotalSensor NOTIFY totalSensorChanged) Q_PROPERTY(QStringList sensorIds READ sensorIds WRITE setSensorIds NOTIFY sensorIdsChanged) Q_PROPERTY(QStringList sensorColors READ sensorColors WRITE setSensorColors NOTIFY sensorColorsChanged) Q_PROPERTY(QStringList textOnlySensorIds READ textOnlySensorIds WRITE setTextOnlySensorIds NOTIFY textOnlySensorIdsChanged) Q_PROPERTY(QString name READ name NOTIFY faceIdChanged) Q_PROPERTY(QString icon READ icon NOTIFY faceIdChanged) Q_PROPERTY(bool supportsSensorsColors READ supportsSensorsColors NOTIFY faceIdChanged) Q_PROPERTY(bool supportsTotalSensor READ supportsTotalSensor NOTIFY faceIdChanged) Q_PROPERTY(bool supportsTextOnlySensors READ supportsTextOnlySensors NOTIFY faceIdChanged) Q_PROPERTY(KDeclarative::ConfigPropertyMap *faceConfiguration READ faceConfiguration NOTIFY faceIdChanged) Q_PROPERTY(QQuickItem *fullRepresentation READ fullRepresentation NOTIFY faceIdChanged) Q_PROPERTY(QQuickItem *compactRepresentation READ compactRepresentation NOTIFY faceIdChanged) Q_PROPERTY(QQuickItem *faceConfigUi READ faceConfigUi NOTIFY faceIdChanged) Q_PROPERTY(QQuickItem *appearanceConfigUi READ appearanceConfigUi NOTIFY faceIdChanged) Q_PROPERTY(QQuickItem *sensorsConfigUi READ sensorsConfigUi NOTIFY faceIdChanged) Q_PROPERTY(QAbstractItemModel *availableFacesModel READ availableFacesModel CONSTANT) Q_PROPERTY(QAbstractItemModel *availablePresetsModel READ availablePresetsModel CONSTANT) public: SensorFaceController(KConfigGroup &config, QQmlEngine *engine); ~SensorFaceController(); void setFaceId(const QString &face); QString faceId() const; - //TODO: just QQuickItem QQuickItem *fullRepresentation(); QQuickItem *compactRepresentation(); QQuickItem *faceConfigUi(); QQuickItem *appearanceConfigUi(); QQuickItem *sensorsConfigUi(); KDeclarative::ConfigPropertyMap *faceConfiguration() const; QString title() const; void setTitle(const QString &title); QString totalSensor() const; void setTotalSensor(const QString &sensor); QStringList sensorIds() const; void setSensorIds(const QStringList &ids); QStringList sensorColors() const; void setSensorColors(const QStringList &colors); QStringList textOnlySensorIds() const; void setTextOnlySensorIds(const QStringList &ids); // from face config, immutable by the user QString name() const; const QString icon() const; bool supportsSensorsColors() const; bool supportsTotalSensor() const; bool supportsTextOnlySensors() const; QAbstractItemModel *availableFacesModel(); QAbstractItemModel *availablePresetsModel(); Q_INVOKABLE void reloadConfig(); Q_INVOKABLE void loadPreset(const QString &preset); Q_INVOKABLE void savePreset(); Q_INVOKABLE void uninstallPreset(const QString &pluginId); Q_SIGNALS: void faceIdChanged(); void titleChanged(); void totalSensorChanged(); void sensorIdsChanged(); void sensorColorsChanged(); void textOnlySensorIdsChanged(); private: class Private; const std::unique_ptr d; }; +} diff --git a/faces/SensorFaceController_p.h b/faces/SensorFaceController_p.h index 218bde9..420a8f0 100644 --- a/faces/SensorFaceController_p.h +++ b/faces/SensorFaceController_p.h @@ -1,64 +1,67 @@ /* Copyright (C) 2020 Marco Martin This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #pragma once #include #include -class SensorFaceController; class QQmlEngine; +namespace KSysGuard { + +class SensorFaceController; + class FacesModel : public QStandardItemModel { Q_OBJECT public: enum AdditionalRoles { PluginIdRole = Qt::UserRole + 1, }; Q_ENUM(AdditionalRoles) FacesModel(QObject *parent = nullptr); ~FacesModel() = default; Q_INVOKABLE void reload(); Q_INVOKABLE QString pluginId(int row); QHash roleNames() const override; }; class PresetsModel : public QStandardItemModel { Q_OBJECT public: enum AdditionalRoles { PluginIdRole = Qt::UserRole + 1, ConfigRole, WritableRole }; Q_ENUM(AdditionalRoles) PresetsModel(QObject *parent = nullptr); ~PresetsModel() = default; Q_INVOKABLE void reload(); QHash roleNames() const override; }; - +} diff --git a/faces/SensorFace_p.h b/faces/SensorFace_p.h index 622df39..e7c6b76 100644 --- a/faces/SensorFace_p.h +++ b/faces/SensorFace_p.h @@ -1,66 +1,69 @@ /* Copyright (C) 2020 Marco Martin This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #pragma once #include #include "sensorfaces_export.h" +namespace KSysGuard { + class SensorFaceController; class SENSORFACES_EXPORT SensorFace : public QQuickItem { Q_OBJECT Q_PROPERTY(SensorFaceController *controller READ controller CONSTANT) Q_PROPERTY(SensorFace::FormFactor formFactor READ formFactor WRITE setFormFactor NOTIFY formFactorChanged) Q_PROPERTY(QQuickItem *contentItem READ contentItem WRITE setContentItem NOTIFY contentItemChanged) public: enum FormFactor { Planar, Vertical, Horizontal }; Q_ENUM(FormFactor) SensorFace(QQuickItem *parent = nullptr); ~SensorFace(); SensorFaceController *controller() const; // Not writable from QML void setController(SensorFaceController *controller); SensorFace::FormFactor formFactor() const; void setFormFactor(SensorFace::FormFactor formFactor); QQuickItem * contentItem() const; void setContentItem(QQuickItem *item); Q_SIGNALS: void formFactorChanged(); void contentItemChanged(); protected: void geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry) override; private: class Private; const std::unique_ptr d; }; +} diff --git a/faces/facepackages/barchart/contents/ui/Config.qml b/faces/facepackages/barchart/contents/ui/Config.qml index a19ab06..eb7d85e 100644 --- a/faces/facepackages/barchart/contents/ui/Config.qml +++ b/faces/facepackages/barchart/contents/ui/Config.qml @@ -1,63 +1,68 @@ /* * Copyright 2019 Marco Martin * Copyrigth 2019 Kai Uwe Broulik * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Library General Public License as * published by the Free Software Foundation; either version 2, or * (at your option) any later version. * * This program 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 General Public License for more details * * You should have received a copy of the GNU Library General Public * License along with this program; if not, write to the * Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ import QtQuick 2.9 import QtQuick.Layouts 1.1 import QtQuick.Controls 2.2 as Controls import org.kde.kirigami 2.8 as Kirigami import org.kde.ksysguard.sensors 1.0 as Sensors import org.kde.ksysguard.faces 1.0 as Faces Kirigami.FormLayout { id: root property alias cfg_showLegend: showSensorsLegendCheckbox.checked property alias cfg_barChartStacked: stackedCheckbox.checked property alias cfg_rangeAuto: rangeAutoCheckbox.checked property alias cfg_rangeFrom: rangeFromSpin.value property alias cfg_rangeTo: rangeToSpin.value Controls.CheckBox { id: showSensorsLegendCheckbox text: i18n("Show Sensors Legend") } Controls.CheckBox { id: stackedCheckbox text: i18n("Stacked Bars") } Controls.CheckBox { id: rangeAutoCheckbox text: i18n("Automatic Data Range") } Controls.SpinBox { id: rangeFromSpin + editable: true + from: -99999 + to: 99999 Kirigami.FormData.label: i18n("From:") enabled: !rangeAutoCheckbox.checked } Controls.SpinBox { id: rangeToSpin + editable: true + from: -99999 to: 99999 Kirigami.FormData.label: i18n("To:") enabled: !rangeAutoCheckbox.checked } } diff --git a/faces/facepackages/barchart/contents/ui/FullRepresentation.qml b/faces/facepackages/barchart/contents/ui/FullRepresentation.qml index 578f4d7..83c61ed 100644 --- a/faces/facepackages/barchart/contents/ui/FullRepresentation.qml +++ b/faces/facepackages/barchart/contents/ui/FullRepresentation.qml @@ -1,74 +1,74 @@ /* * Copyright 2019 Marco Martin * Copyright 2019 David Edmundson * Copyright 2019 Arjen Hiemstra * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Library General Public License as * published by the Free Software Foundation; either version 2, or * (at your option) any later version. * * This program 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 General Public License for more details * * You should have received a copy of the GNU Library General Public * License along with this program; if not, write to the * Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ import QtQuick 2.9 import QtQuick.Layouts 1.1 import org.kde.kirigami 2.8 as Kirigami import org.kde.ksysguard.sensors 1.0 as Sensors import org.kde.ksysguard.faces 1.0 as Faces import org.kde.quickcharts 1.0 as Charts import org.kde.quickcharts.controls 1.0 as ChartControls Faces.SensorFace { id: root - readonly property bool showLegend: plasmoid.nativeInterface.faceConfiguration.showLegend + readonly property bool showLegend: controller.faceConfiguration.showLegend // Arbitrary minimumWidth to make easier to align plasmoids in a predictable way Layout.minimumWidth: Kirigami.Units.gridUnit * 8 contentItem: ColumnLayout { Kirigami.Heading { Layout.fillWidth: true horizontalAlignment: Text.AlignHCenter elide: Text.ElideRight text: root.controller.title visible: text.length > 0 level: 2 } BarChart { id: compactRepresentation Layout.fillWidth: true Layout.fillHeight: true Layout.minimumHeight: 5 * Kirigami.Units.gridUnit Layout.preferredHeight: 8 * Kirigami.Units.gridUnit Layout.maximumHeight: Math.max(root.width, Layout.minimumHeight) } Faces.ExtendedLegend { Layout.fillWidth: true Layout.fillHeight: true visible: root.showLegend chart: compactRepresentation sourceModel: root.showLegend ? compactRepresentation.sensorsModel : null colorSource: globalColorSource textOnlySensorIds: root.showLegend ? root.controller.textOnlySensorIds : [] } Item { Layout.fillHeight: true } } } diff --git a/faces/facepackages/linechart/contents/ui/Config.qml b/faces/facepackages/linechart/contents/ui/Config.qml index 43cadab..188cb5d 100644 --- a/faces/facepackages/linechart/contents/ui/Config.qml +++ b/faces/facepackages/linechart/contents/ui/Config.qml @@ -1,101 +1,112 @@ /* * Copyright 2019 Marco Martin * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Library General Public License as * published by the Free Software Foundation; either version 2, or * (at your option) any later version. * * This program 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 General Public License for more details * * You should have received a copy of the GNU Library General Public * License along with this program; if not, write to the * Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ import QtQuick 2.9 import QtQuick.Layouts 1.1 import QtQuick.Controls 2.2 as Controls import org.kde.kirigami 2.8 as Kirigami import org.kde.ksysguard.sensors 1.0 as Sensors import org.kde.ksysguard.faces 1.0 as Faces Kirigami.FormLayout { id: root property alias cfg_showLegend: showSensorsLegendCheckbox.checked property alias cfg_lineChartStacked: stackedCheckbox.checked property alias cfg_lineChartFillOpacity: fillOpacitySpin.value property alias cfg_lineChartSmooth: smoothCheckbox.checked property alias cfg_rangeAutoY: rangeAutoYCheckbox.checked property alias cfg_rangeFromY: rangeFromYSpin.value property alias cfg_rangeToY: rangeToYSpin.value property alias cfg_rangeAutoX: rangeAutoXCheckbox.checked property alias cfg_rangeFromX: rangeFromXSpin.value property alias cfg_rangeToX: rangeToXSpin.value Item { Kirigami.FormData.label: i18n("Appearance") Kirigami.FormData.isSection: true } Controls.CheckBox { id: showSensorsLegendCheckbox text: i18n("Show Sensors Legend") } Controls.CheckBox { id: stackedCheckbox text: i18n("Stacked Charts") } Controls.CheckBox { id: smoothCheckbox text: i18n("Smooth Lines") } Controls.SpinBox { id: fillOpacitySpin Kirigami.FormData.label: i18n("Fill Opacity:") + editable: true from: 0 to: 100 } Item { Kirigami.FormData.label: i18n("Data Ranges") Kirigami.FormData.isSection: true } Controls.CheckBox { id: rangeAutoYCheckbox text: i18n("Automatic Y Data Range") } Controls.SpinBox { id: rangeFromYSpin Kirigami.FormData.label: i18n("From (Y):") enabled: !rangeAutoYCheckbox.checked + editable: true + from: -99999 + to: 99999 } Controls.SpinBox { id: rangeToYSpin + editable: true + from: -99999 to: 99999 Kirigami.FormData.label: i18n("To (Y):") enabled: !rangeAutoYCheckbox.checked } Controls.CheckBox { id: rangeAutoXCheckbox text: i18n("Automatic X Data Range") } Controls.SpinBox { id: rangeFromXSpin + editable: true + from: -99999 + to: 99999 Kirigami.FormData.label: i18n("From (X):") enabled: !rangeAutoXCheckbox.checked } Controls.SpinBox { id: rangeToXSpin + editable: true + from: -99999 to: 99999 Kirigami.FormData.label: i18n("To (X):") enabled: !rangeAutoXCheckbox.checked } } diff --git a/faces/facepackages/piechart/contents/ui/Config.qml b/faces/facepackages/piechart/contents/ui/Config.qml index cdd37d0..c8d4fdf 100644 --- a/faces/facepackages/piechart/contents/ui/Config.qml +++ b/faces/facepackages/piechart/contents/ui/Config.qml @@ -1,93 +1,94 @@ /* * Copyright 2019 Marco Martin * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Library General Public License as * published by the Free Software Foundation; either version 2, or * (at your option) any later version. * * This program 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 General Public License for more details * * You should have received a copy of the GNU Library General Public * License along with this program; if not, write to the * Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ import QtQuick 2.9 import QtQuick.Layouts 1.1 import QtQuick.Controls 2.2 as Controls import org.kde.kirigami 2.8 as Kirigami import org.kde.ksysguard.sensors 1.0 as Sensors import org.kde.ksysguard.faces 1.0 as Faces Kirigami.FormLayout { id: root property alias cfg_showLegend: showSensorsLegendCheckbox.checked property alias cfg_fromAngle: fromAngleSpin.value property alias cfg_toAngle: toAngleSpin.value property alias cfg_smoothEnds: smoothEndsCheckbox.checked property alias cfg_rangeAuto: rangeAutoCheckbox.checked property alias cfg_rangeFrom: rangeFromSpin.value property alias cfg_rangeTo: rangeToSpin.value Controls.CheckBox { id: showSensorsLegendCheckbox text: i18n("Show Sensors Legend") } Controls.SpinBox { id: fromAngleSpin Kirigami.FormData.label: i18n("Start from Angle") from: -180 to: 180 editable: true textFromValue: function(value, locale) { return i18nc("angle degrees", "%1°", value + 180); } valueFromText: function(text, locale) { return Number.fromLocaleString(locale, text.replace(i18nc("angle degrees", "°"), "")) - 180; } } Controls.SpinBox { id: toAngleSpin Kirigami.FormData.label: i18n("Total Pie Angle") from: 0 to: 360 editable: true textFromValue: function(value, locale) { return i18nc("angle", "%1°", value); } valueFromText: function(text, locale) { return Number.fromLocaleString(locale, text.replace(i18nc("angle degrees", "°"), "")); } } Controls.CheckBox { id: smoothEndsCheckbox text: i18n("Rounded Lines") } Controls.CheckBox { id: rangeAutoCheckbox text: i18n("Automatic Data Range") } Controls.SpinBox { id: rangeFromSpin editable: true Kirigami.FormData.label: i18n("From:") enabled: !rangeAutoCheckbox.checked } Controls.SpinBox { id: rangeToSpin + from: -99999 to: 99999 editable: true Kirigami.FormData.label: i18n("To:") enabled: !rangeAutoCheckbox.checked } } diff --git a/faces/facepackages/table/contents/ui/CompactRepresentation.qml b/faces/facepackages/table/contents/ui/CompactRepresentation.qml index deb5974..a244e9a 100644 --- a/faces/facepackages/table/contents/ui/CompactRepresentation.qml +++ b/faces/facepackages/table/contents/ui/CompactRepresentation.qml @@ -1,59 +1,59 @@ /* * Copyright 2019 Marco Martin * Copyright 2019 David Edmundson * Copyright 2019 Arjen Hiemstra * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Library General Public License as * published by the Free Software Foundation; either version 2, or * (at your option) any later version. * * This program 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 General Public License for more details * * You should have received a copy of the GNU Library General Public * License along with this program; if not, write to the * Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ import QtQuick 2.9 import QtQuick.Layouts 1.1 import org.kde.kirigami 2.8 as Kirigami import org.kde.ksysguard.sensors 1.0 as Sensors import org.kde.ksysguard.faces 1.0 as Faces import org.kde.quickcharts 1.0 as Charts Faces.SensorFace { id: root Layout.minimumWidth: Kirigami.Units.gridUnit * 8 contentItem: Charts.LineChart { fillOpacity: 0 xRange { from: 0; to: 50; automatic: false } yRange { from: 0; to: 100; automatic: false } - visible: plasmoid.configuration.totalSensor !== "" + visible: root.controller.totalSensor !== "" colorSource: Charts.SingleValueSource { value: Kirigami.Theme.textColor} lineWidth: 1 direction: Charts.XYChart.ZeroAtEnd valueSources: [ Charts.ModelHistorySource { - model: Sensors2.SensorDataModel { sensors: [ plasmoid.configuration.totalSensor ] } + model: Sensors2.SensorDataModel { sensors: [ root.controller.totalSensor ] } column: 0; row: 0 roleName: "Value"; maximumHistory: 50 } ] } } diff --git a/faces/facepackages/table/contents/ui/Config.qml b/faces/facepackages/table/contents/ui/Config.qml index 0c28a1f..be25826 100644 --- a/faces/facepackages/table/contents/ui/Config.qml +++ b/faces/facepackages/table/contents/ui/Config.qml @@ -1,62 +1,63 @@ /* * Copyright 2019 Marco Martin * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Library General Public License as * published by the Free Software Foundation; either version 2, or * (at your option) any later version. * * This program 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 General Public License for more details * * You should have received a copy of the GNU Library General Public * License along with this program; if not, write to the * Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ import QtQuick 2.9 import QtQuick.Layouts 1.1 import QtQuick.Controls 2.2 as Controls import org.kde.ksysguard.faces 1.0 as Faces import org.kde.kirigami 2.8 as Kirigami import org.kde.ksysguard.sensors 1.0 as Sensors Kirigami.FormLayout { id: root property alias cfg_showTableHeaders: showTableHeadersCheckbox.checked property alias cfg_sortColumn: sortColumnCombo.currentIndex property alias cfg_sortDescending: sortDescendingCheckBox.checked RowLayout { Kirigami.FormData.label: i18n("Sort by:") Controls.ComboBox { id: sortColumnCombo textRole: "display" model: Sensors.HeadingHelperModel { sourceModel: Sensors.SensorDataModel { - sensors: plasmoid.configuration.sensorIds + // FIXME: unqualified property + sensors: controller.sensorIds } } } Controls.CheckBox { id: sortDescendingCheckBox // or do a ComboBox like in Dolphin with pretty names "highest first"<->"lowest first"? text: i18nc("Sort descending", "Descending") } } Controls.CheckBox { id: showTableHeadersCheckbox text: i18n("Show table headers") } } diff --git a/faces/facepackages/table/contents/ui/FullRepresentation.qml b/faces/facepackages/table/contents/ui/FullRepresentation.qml index dd6869e..7adaf90 100644 --- a/faces/facepackages/table/contents/ui/FullRepresentation.qml +++ b/faces/facepackages/table/contents/ui/FullRepresentation.qml @@ -1,169 +1,169 @@ /* * Copyright 2019 Marco Martin * Copyright 2019 David Edmundson * Copyright 2019 Arjen Hiemstra * * 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 the Free Software Foundation; either version 2 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 14 of version 3 of the license. * * This program 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ import QtQuick 2.12 import QtQuick.Controls 2.2 import QtQuick.Layouts 1.2 import QtQml.Models 2.12 import org.kde.kirigami 2.2 as Kirigami import org.kde.ksysguard.sensors 1.0 as Sensors import org.kde.ksysguard.faces 1.0 as Faces import org.kde.plasma.core 2.0 as PlasmaCore import org.kde.quickcharts 1.0 as Charts Faces.SensorFace { id: root Layout.minimumWidth: Kirigami.Units.gridUnit * 8 Layout.minimumHeight: Kirigami.Units.gridUnit * 4 Layout.preferredWidth: Kirigami.Units.gridUnit * 16 Layout.preferredHeight: Kirigami.Units.gridUnit * 18 opacity: y + height <= parent.height contentItem: ColumnLayout { RowLayout { Layout.fillHeight: false Kirigami.Heading { id: heading - text: plasmoid.configuration.title + text: root.controller.title level: 2 elide: Text.ElideRight Layout.fillHeight: true } Charts.LineChart { Layout.fillWidth: true Layout.fillHeight: true fillOpacity: 0 xRange { from: 0; to: 50; automatic: false } yRange { from: 0; to: 100; automatic: false } - visible: plasmoid.configuration.totalSensor !== "" + visible: root.controller.totalSensor !== "" smooth: true colorSource: Charts.SingleValueSource { value: root.Kirigami.Theme.textColor} lineWidth: 1 direction: Charts.XYChart.ZeroAtEnd valueSources: [ Charts.ModelHistorySource { - model: Sensors.SensorDataModel { sensors: [ plasmoid.configuration.totalSensor ] } + model: Sensors.SensorDataModel { sensors: [ root.controller.totalSensor ] } column: 0; row: 0 roleName: "Value"; maximumHistory: 50 } ] } } RowLayout { id: header y: -height Layout.fillWidth: true visible: plasmoid.nativeInterface.faceConfiguration.showTableHeaders Repeater { model: Sensors.HeadingHelperModel { id: headingHelperModel sourceModel: tableView.model } Kirigami.Heading { id: heading level: 4 Layout.fillWidth: true //FIXME: why +2 is necessary? Layout.preferredWidth: metrics.width+2 Layout.maximumWidth: x > 0 ? metrics.width+2 : -1 TextMetrics{ id: metrics font: heading.font text: heading.text } text: model.display elide: Text.ElideRight horizontalAlignment: index > 0 ? Text.AlignRight : Text.AlignLeft } } } TableView { id: tableView Layout.fillHeight: true Layout.fillWidth: true model: topModel interactive: false columnSpacing: Kirigami.Units.smallSpacing clip: true property int dataColumnWidth: Kirigami.Units.gridUnit * 5 columnWidthProvider: function (column) { return header.children[column].width; } delegate: Label { // Not visible to not change contentHeight opacity: y + height <= tableView.height text: model.display != undefined ? model.display : "" horizontalAlignment: model.alignment == (Text.AlignRight + Text.AlignVCenter) ? Text.AlignRight : Text.AlignLeft elide: Text.ElideRight verticalAlignment: Text.AlignVCenter } //See https://codereview.qt-project.org/c/qt/qtdeclarative/+/262876 onWidthChanged: Qt.callLater(function() {if (tableView.columns > 0) { tableView.forceLayout() }}); KItemModels.KSortFilterProxyModel { id: topModel filterKeyColumn: 0 // name filterRegExp: ".+" sortColumn: plasmoid.nativeInterface.faceConfiguration.sortColumn sortRole: "Value" sortOrder: plasmoid.nativeInterface.faceConfiguration.sortDescending ? Qt.DescendingOrder : Qt.AscendingOrder sourceModel: Sensors.SensorDataModel { id: dataModel - sensors: plasmoid.configuration.sensorIds + sensors: root.controller.sensorIds onSensorsChanged: { //note: this re sets the models in order to make the table work with any new role tableView.model = null; topModel.sourceModel = null; topModel.sourceModel = dataModel; tableView.model = topModel; } } } } } } diff --git a/faces/facepackages/textonly/contents/ui/CompactRepresentation.qml b/faces/facepackages/textonly/contents/ui/CompactRepresentation.qml index 5e30acb..722f4f0 100644 --- a/faces/facepackages/textonly/contents/ui/CompactRepresentation.qml +++ b/faces/facepackages/textonly/contents/ui/CompactRepresentation.qml @@ -1,64 +1,64 @@ /* * Copyright 2019 Marco Martin * Copyright 2019 David Edmundson * Copyright 2019 Arjen Hiemstra * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Library General Public License as * published by the Free Software Foundation; either version 2, or * (at your option) any later version. * * This program 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 General Public License for more details * * You should have received a copy of the GNU Library General Public * License along with this program; if not, write to the * Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ import QtQuick 2.9 import QtQuick.Layouts 1.1 import org.kde.kirigami 2.8 as Kirigami import org.kde.ksysguard.sensors 1.0 as Sensors import org.kde.ksysguard.faces 1.0 as Faces import org.kde.quickcharts 1.0 as Charts import org.kde.quickcharts.controls 1.0 as ChartsControls Faces.SensorFace { id: root - Layout.minimumWidth: plasmoid.formFactor == Faces.SensorFace.Vertical ? Kirigami.Units.gridUnit : Kirigami.Units.gridUnit * 2 + Layout.minimumWidth: root.formFactor == Faces.SensorFace.Vertical ? Kirigami.Units.gridUnit : Kirigami.Units.gridUnit * 2 contentItem: ColumnLayout { Repeater { model: root.controller.sensorIds ChartsControls.LegendDelegate { Layout.fillWidth: true name: sensor.shortName value: sensor.formattedValue colorVisible: false colorWidth: 0 layoutWidth: root.width valueWidth: Kirigami.Units.gridUnit * 2 Sensors.Sensor { id: sensor sensorId: modelData } } } Item { Layout.fillWidth: true; Layout.fillHeight: true } } } diff --git a/sensors/CMakeLists.txt b/sensors/CMakeLists.txt index b639234..bd8364f 100644 --- a/sensors/CMakeLists.txt +++ b/sensors/CMakeLists.txt @@ -1,70 +1,69 @@ set(KSYSGUARD_SENSORS_SOVERSION 1) add_subdirectory(declarative) add_definitions(-DTRANSLATION_DOMAIN=\"ksysguard_sensors\") set(sensors_LIB_SRCS Sensor.cpp SensorDataModel.cpp SensorTreeModel.cpp SensorQuery.cpp SensorDaemonInterface.cpp ) set(sensors_LIB_HEADERS Sensor.h SensorDataModel.h SensorTreeModel.h SensorQuery.h SensorInfo_p.h ) ecm_qt_declare_logging_category(sensors_LIB_SRCS HEADER sensors_logging.h IDENTIFIER LIBKSYSGUARD_SENSORS CATEGORY_NAME org.kde.libksysguard.sensors ) set_source_files_properties(org.kde.KSysGuardDaemon.xml PROPERTIES INCLUDE SensorInfo_p.h) qt5_add_dbus_interface(sensors_LIB_SRCS org.kde.KSysGuardDaemon.xml ksysguarddaemon) add_library(Sensors ${sensors_LIB_SRCS}) add_library(KSysGuard::Sensors ALIAS Sensors) target_include_directories(Sensors PUBLIC "$" "$" ) generate_export_header(Sensors) target_link_libraries(Sensors PUBLIC Qt5::Qml Qt5::Quick KSysGuard::Formatter PRIVATE Qt5::Core Qt5::DBus KF5::I18n - KF5::Package KF5::ConfigCore KF5::ConfigGui KF5::Declarative ) set_target_properties(Sensors PROPERTIES LIBRARY_OUTPUT_NAME KSysGuardSensors VERSION ${KSYSGUARD_VERSION_STRING} SOVERSION ${KSYSGUARD_SENSORS_SOVERSION} ) install(TARGETS Sensors EXPORT libksysguardLibraryTargets ${KDE_INSTALL_TARGETS_DEFAULT_ARGS}) install(FILES ${sensors_LIB_HEADERS} ${CMAKE_CURRENT_BINARY_DIR}/sensors_export.h DESTINATION ${KDE_INSTALL_INCLUDEDIR}/ksysguard/sensors COMPONENT Devel ) diff --git a/sensors/declarative/CMakeLists.txt b/sensors/declarative/CMakeLists.txt index f830748..293aaff 100644 --- a/sensors/declarative/CMakeLists.txt +++ b/sensors/declarative/CMakeLists.txt @@ -1,8 +1,8 @@ include_directories(${CMAKE_CURRENT_BINARY_DIR}/.. ${CMAKE_CURRENT_SOURCE_DIR}/..) add_library(SensorsPlugin SHARED SensorsPlugin.cpp) -target_link_libraries(SensorsPlugin Qt5::Qml KSysGuard::Sensors KF5::ProcessCore KF5::Package KF5::ConfigCore KF5::ConfigGui) +target_link_libraries(SensorsPlugin Qt5::Qml KSysGuard::Sensors KF5::ProcessCore) install(TARGETS SensorsPlugin DESTINATION ${KDE_INSTALL_QMLDIR}/org/kde/ksysguard/sensors) install(FILES qmldir DESTINATION ${KDE_INSTALL_QMLDIR}/org/kde/ksysguard/sensors)