From 0e1b10170358283a665cdbf6ca6d35e756dcee4b Mon Sep 17 00:00:00 2001 From: arcan1s Date: Fri, 16 Oct 2015 07:22:03 +0300 Subject: [PATCH] * initial implementation of configuration export and import feature (#68) * drop mediators in data transition --- .gitignore | 3 - sources/.idea/.name | 1 + sources/.idea/misc.xml | 15 + sources/.idea/modules.xml | 8 + sources/.idea/sources.iml | 119 ++++++ sources/.idea/vcs.xml | 10 + sources/.idea/workspace.xml | 344 ++++++++++++++++++ .../package/contents/ui/advanced.qml | 31 +- sources/awesome-widget/plugin/awactions.cpp | 184 ++++++++++ sources/awesome-widget/plugin/awactions.h | 3 + .../plugin/awdataengineaggregator.cpp | 32 +- .../plugin/awdataengineaggregator.h | 7 - sources/awesome-widget/plugin/awkeys.cpp | 16 +- sources/awesome-widget/plugin/awkeys.h | 7 +- 14 files changed, 734 insertions(+), 46 deletions(-) create mode 100644 sources/.idea/.name create mode 100644 sources/.idea/misc.xml create mode 100644 sources/.idea/modules.xml create mode 100644 sources/.idea/sources.iml create mode 100644 sources/.idea/vcs.xml create mode 100644 sources/.idea/workspace.xml diff --git a/.gitignore b/.gitignore index fbca663..d4af69a 100644 --- a/.gitignore +++ b/.gitignore @@ -44,6 +44,3 @@ build src pkg -# idea -.idea - diff --git a/sources/.idea/.name b/sources/.idea/.name new file mode 100644 index 0000000..0b21f40 --- /dev/null +++ b/sources/.idea/.name @@ -0,0 +1 @@ +sources \ No newline at end of file diff --git a/sources/.idea/misc.xml b/sources/.idea/misc.xml new file mode 100644 index 0000000..9601a91 --- /dev/null +++ b/sources/.idea/misc.xml @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/sources/.idea/modules.xml b/sources/.idea/modules.xml new file mode 100644 index 0000000..62028aa --- /dev/null +++ b/sources/.idea/modules.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/sources/.idea/sources.iml b/sources/.idea/sources.iml new file mode 100644 index 0000000..bf5769c --- /dev/null +++ b/sources/.idea/sources.iml @@ -0,0 +1,119 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/sources/.idea/vcs.xml b/sources/.idea/vcs.xml new file mode 100644 index 0000000..320b995 --- /dev/null +++ b/sources/.idea/vcs.xml @@ -0,0 +1,10 @@ + + + + + + + + + + \ No newline at end of file diff --git a/sources/.idea/workspace.xml b/sources/.idea/workspace.xml new file mode 100644 index 0000000..94aa0b9 --- /dev/null +++ b/sources/.idea/workspace.xml @@ -0,0 +1,344 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1444961890223 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/sources/awesome-widget/package/contents/ui/advanced.qml b/sources/awesome-widget/package/contents/ui/advanced.qml index 1160a3f..67f3abe 100644 --- a/sources/awesome-widget/package/contents/ui/advanced.qml +++ b/sources/awesome-widget/package/contents/ui/advanced.qml @@ -352,12 +352,41 @@ Item { width: parent.width * 2 / 5 } QtControls.Button { - id: selectFont width: parent.width * 3 / 5 text: i18n("Drop key cache") onClicked: awActions.dropCache() } } + + Row { + height: implicitHeight + width: parent.width + QtControls.Label { + height: parent.height + width: parent.width * 2 / 5 + } + QtControls.Button { + width: parent.width * 3 / 5 + text: i18n("Export configuration") + onClicked: awActions.exportConfiguration(plasmoid.configuration) + } + } + + Row { + height: implicitHeight + width: parent.width + QtControls.Label { + height: parent.height + width: parent.width * 2 / 5 + } + QtControls.Button { + width: parent.width * 3 / 5 + text: i18n("Import configuration") + onClicked: { + console.log(awActions.importConfiguration()) + } + } + } } diff --git a/sources/awesome-widget/plugin/awactions.cpp b/sources/awesome-widget/plugin/awactions.cpp index 210c3b4..d36bb6f 100644 --- a/sources/awesome-widget/plugin/awactions.cpp +++ b/sources/awesome-widget/plugin/awactions.cpp @@ -20,8 +20,10 @@ #include #include +#include #include #include +#include #include #include #include @@ -30,8 +32,10 @@ #include #include #include +#include #include #include +#include #include @@ -109,6 +113,78 @@ void AWActions::showReadme() const } +void AWActions::exportConfiguration(QObject *nativeConfig) const +{ + qCDebug(LOG_AW); + + // get file path and init settings object + QString fileName = QFileDialog::getSaveFileName(nullptr, i18n("Export")); + if (fileName.isEmpty()) + return; + qCInfo(LOG_AW) << "Selected filename" << fileName; + QSettings settings(fileName, QSettings::IniFormat); + // additional parameters + QString baseDir = QString("%1/awesomewidgets"). + arg(QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation)); + QStringList dirs = QStringList() << QString("desktops") << QString("quotes") + << QString("scripts") << QString("upgrade") << QString("weather"); + + // plasmoid configuration + QQmlPropertyMap *configuration = static_cast(nativeConfig); + settings.beginGroup(QString("plasmoid")); + foreach(QString key, configuration->keys()) { + QVariant value = configuration->value(key); + if (!value.isValid()) + continue; + settings.setValue(key, value); + } + settings.endGroup(); + + // extenstions + foreach(QString item, dirs) { + QStringList items = QDir(QString("%1/%2").arg(baseDir).arg(item)).entryList( + QStringList() << QString("*.desktop"), QDir::Files); + settings.beginGroup(item); + foreach(QString it, items) { + qCInfo(LOG_AW) << "Processing file" << it; + settings.beginGroup(it); + QSettings itemSettings(QString("%1/%2/%3").arg(baseDir).arg(item).arg(it), QSettings::IniFormat); + itemSettings.beginGroup(QString("Desktop Entry")); + foreach(QString key, itemSettings.childKeys()) + settings.setValue(key, itemSettings.value(key)); + itemSettings.endGroup(); + settings.endGroup(); + } + settings.endGroup(); + } + + // additional files + settings.beginGroup(QString("json")); + // script filters + QFile filterFile(QString("%1/scripts/awesomewidgets-extscripts-filters.json").arg(baseDir)); + if (filterFile.open(QIODevice::ReadOnly | QIODevice::Text)) { + QString filterText = filterFile.readAll(); + filterFile.close(); + settings.setValue(QString("filters"), filterText); + } else { + qCWarning(LOG_LIB) << "Could not open" << filterFile.fileName(); + } + // weather icon settings + QFile weatherIdFile(QString("%1/weather/awesomewidgets-extweather-ids.json").arg(baseDir)); + if (weatherIdFile.open(QIODevice::ReadOnly | QIODevice::Text)) { + QString weatherIdText = weatherIdFile.readAll(); + weatherIdFile.close(); + settings.setValue(QString("weathers"), weatherIdText); + } else { + qCWarning(LOG_LIB) << "Could not open" << weatherIdFile.fileName(); + } + settings.endGroup(); + + // sync settings + settings.sync(); +} + + // HACK: this method uses variables from version.h QString AWActions::getAboutText(const QString type) const { @@ -171,6 +247,114 @@ QVariantMap AWActions::getFont(const QVariantMap defaultFont) const } +QQmlPropertyMap* AWActions::importConfiguration() const +{ + qCDebug(LOG_AW); + + QQmlPropertyMap *configuration = new QQmlPropertyMap(); + // get file path and init settings object + QString fileName = QFileDialog::getOpenFileName(nullptr, i18n("Import")); + if (fileName.isEmpty()) + return configuration; + qCInfo(LOG_AW) << "Selected filename" << fileName; + QSettings settings(fileName, QSettings::IniFormat); + // additional parameters + QString baseDir = QString("%1/awesomewidgets"). + arg(QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation)); + QStringList dirs = QStringList() << QString("desktops") << QString("quotes") + << QString("scripts") << QString("upgrade") << QString("weather"); + + // check what should be exported + QDialog *dialog = new QDialog(nullptr); + QCheckBox *importPlasmoidSettings = new QCheckBox(i18n("Import plasmoid settings"), dialog); + QCheckBox *importExtensionsSettings = new QCheckBox(i18n("Import extenstions"), dialog); + QCheckBox *importAddsSettings = new QCheckBox(i18n("Import additional files"), dialog); + QDialogButtonBox *dialogButtons = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel, + Qt::Horizontal, dialog); + QVBoxLayout *layout = new QVBoxLayout(dialog); + layout->addWidget(importPlasmoidSettings); + layout->addWidget(importExtensionsSettings); + layout->addWidget(importAddsSettings); + layout->addWidget(dialogButtons); + connect(dialogButtons, SIGNAL(accepted()), dialog, SLOT(accept())); + connect(dialogButtons, SIGNAL(rejected()), dialog, SLOT(reject())); + // get parameters + bool importPlasmoid = false; + bool importExtensions = false; + bool importAdds = false; + switch(int ret = dialog->exec()) { + case QDialog::Accepted: + importPlasmoid = importPlasmoidSettings->isChecked(); + importExtensions = importExtensionsSettings->isChecked(); + importAdds = importAddsSettings->isChecked(); + break; + case QDialog::Rejected: + default: + break; + } + dialog->deleteLater(); + + // extenstions + if (importExtensions) { + foreach(QString item, dirs) { + settings.beginGroup(item); + qDebug() << settings.childGroups(); + foreach(QString it, settings.childGroups()) { + qCInfo(LOG_AW) << "Processing file" << it; + settings.beginGroup(it); + QSettings itemSettings(QString("%1/%2/%3").arg(baseDir).arg(item).arg(it), QSettings::IniFormat); + itemSettings.beginGroup(QString("Desktop Entry")); + foreach(QString key, settings.childKeys()) + itemSettings.setValue(key, settings.value(key)); + itemSettings.endGroup(); + itemSettings.sync(); + settings.endGroup(); + } + settings.endGroup(); + } + } + + // additional files + if (importAdds) { + settings.beginGroup(QString("json")); + // script filters + if (settings.contains(QString("filters"))) { + QFile filterFile(QString("%1/scripts/awesomewidgets-extscripts-filters.json").arg(baseDir)); + if (filterFile.open(QIODevice::WriteOnly | QIODevice::Text)) { + QDataStream out(&filterFile); + out << settings.value(QString("filters")).toString(); + filterFile.close(); + } else { + qCWarning(LOG_LIB) << "Could not open" << filterFile.fileName(); + } + } + // weather icon settings + if (settings.contains(QString("weathers"))) { + QFile weatherIdFile(QString("%1/weather/awesomewidgets-extweather-ids.json").arg(baseDir)); + if (weatherIdFile.open(QIODevice::WriteOnly | QIODevice::Text)) { + QDataStream out(&weatherIdFile); + out << settings.value(QString("weathers")).toString(); + weatherIdFile.close(); + } else { + qCWarning(LOG_LIB) << "Could not open" << weatherIdFile.fileName(); + } + } + settings.endGroup(); + } + + // plasmoid configuration + if (importPlasmoid) { + settings.beginGroup(QString("plasmoid")); + foreach(QString key, settings.childKeys()) + configuration->insert(key, settings.value(key)); + configuration->insert(QString("valid"), true); + settings.endGroup(); + } + + return configuration; +} + + QVariantMap AWActions::readDataEngineConfiguration() const { qCDebug(LOG_AW); diff --git a/sources/awesome-widget/plugin/awactions.h b/sources/awesome-widget/plugin/awactions.h index 44c6be7..0ff0910 100644 --- a/sources/awesome-widget/plugin/awactions.h +++ b/sources/awesome-widget/plugin/awactions.h @@ -23,6 +23,7 @@ class QNetworkReply; +class QQmlPropertyMap; class AWActions : public QObject { @@ -37,8 +38,10 @@ public: Q_INVOKABLE bool runCmd(const QString cmd = QString("/usr/bin/true")) const; Q_INVOKABLE void showReadme() const; // configuration slots + Q_INVOKABLE void exportConfiguration(QObject *nativeConfig) const; Q_INVOKABLE QString getAboutText(const QString type = QString("header")) const; Q_INVOKABLE QVariantMap getFont(const QVariantMap defaultFont) const; + Q_INVOKABLE QQmlPropertyMap *importConfiguration() const; // dataengine Q_INVOKABLE QVariantMap readDataEngineConfiguration() const; Q_INVOKABLE void writeDataEngineConfiguration(const QVariantMap configuration) const; diff --git a/sources/awesome-widget/plugin/awdataengineaggregator.cpp b/sources/awesome-widget/plugin/awdataengineaggregator.cpp index 60db3a8..adca03a 100644 --- a/sources/awesome-widget/plugin/awdataengineaggregator.cpp +++ b/sources/awesome-widget/plugin/awdataengineaggregator.cpp @@ -57,8 +57,8 @@ void AWDataEngineAggregator::dropSource(const QString source) // FIXME there is no possiblibity to check to which dataengine source connected // we will try to disconnect it from systemmonitor and extsysmon - m_dataEngines[QString("systemmonitor")]->disconnectSource(source, this); - m_dataEngines[QString("extsysmon")]->disconnectSource(source, this); + m_dataEngines[QString("systemmonitor")]->disconnectSource(source, parent()); + m_dataEngines[QString("extsysmon")]->disconnectSource(source, parent()); } @@ -66,26 +66,9 @@ void AWDataEngineAggregator::reconnectSources() { qCDebug(LOG_AW); - m_dataEngines[QString("systemmonitor")]->connectAllSources(this, m_interval); - m_dataEngines[QString("extsysmon")]->connectAllSources(this, m_interval); - m_dataEngines[QString("time")]->connectSource(QString("Local"), this, 1000); -} - - -void AWDataEngineAggregator::dataUpdated(const QString sourceName, const Plasma::DataEngine::Data data) -{ - qCDebug(LOG_AW); - qCDebug(LOG_AW) << "Source" << sourceName; - qCDebug(LOG_AW) << "Data" << data; - - // HACK "deep copy" of data to avoid plasma crash on Data object destruction - QString units = data[QString("units")].toString(); - // HACK workaround for time values which are stored in the different path - QVariant value = sourceName == QString("Local") - ? data[QString("DateTime")] - : data[QString("value")]; - - emit(updateData(sourceName, value, units)); + m_dataEngines[QString("systemmonitor")]->connectAllSources(parent(), m_interval); + m_dataEngines[QString("extsysmon")]->connectAllSources(parent(), m_interval); + m_dataEngines[QString("time")]->connectSource(QString("Local"), parent(), 1000); } @@ -102,9 +85,6 @@ void AWDataEngineAggregator::initDataEngines() connect(m_dataEngines[QString("systemmonitor")], &Plasma::DataEngine::sourceAdded, [this](const QString source) { static_cast(parent())->addDevice(source); - m_dataEngines[QString("systemmonitor")]->connectSource(source, this, m_interval); + m_dataEngines[QString("systemmonitor")]->connectSource(source, parent(), m_interval); }); - - connect(this, SIGNAL(updateData(QString, QVariant, QString)), - parent(), SLOT(dataUpdated(QString, QVariant, QString))); } diff --git a/sources/awesome-widget/plugin/awdataengineaggregator.h b/sources/awesome-widget/plugin/awdataengineaggregator.h index f1ae2cb..79c58f2 100644 --- a/sources/awesome-widget/plugin/awdataengineaggregator.h +++ b/sources/awesome-widget/plugin/awdataengineaggregator.h @@ -34,16 +34,9 @@ public: // properties void setInterval(const int _interval); -signals: - void updateData(const QString sourceName, const QVariant value, const QString units); - public slots: void dropSource(const QString source); void reconnectSources(); - // data engines operations - void dataUpdated(const QString sourceName, const Plasma::DataEngine::Data data); - // dummy method required by DataEngine connections - void modelChanged(QString, QAbstractItemModel *) {}; private: void initDataEngines(); diff --git a/sources/awesome-widget/plugin/awkeys.cpp b/sources/awesome-widget/plugin/awkeys.cpp index 0499e5a..1947fd1 100644 --- a/sources/awesome-widget/plugin/awkeys.cpp +++ b/sources/awesome-widget/plugin/awkeys.cpp @@ -392,20 +392,20 @@ void AWKeys::addDevice(const QString source) } -void AWKeys::dataUpdated(const QString sourceName, const QVariant value, const QString units) +void AWKeys::dataUpdated(const QString &sourceName, const Plasma::DataEngine::Data &data) { qCDebug(LOG_AW); qCDebug(LOG_AW) << "Source" << sourceName; - qCDebug(LOG_AW) << "Data" << value << units; + qCDebug(LOG_AW) << "Data" << data; if (sourceName == QString("update")) return emit(needToBeUpdated()); #ifdef BUILD_FUTURE // run concurrent data update - QtConcurrent::run(m_threadPool, this, &AWKeys::setDataBySource, sourceName, value, units); + QtConcurrent::run(m_threadPool, this, &AWKeys::setDataBySource, sourceName, data); #else /* BUILD_FUTURE */ - return setDataBySource(sourceName, value, units); + return setDataBySource(sourceName, data); #endif /* BUILD_FUTURE */ } @@ -686,16 +686,16 @@ QString AWKeys::parsePattern(QString pattern) const } -void AWKeys::setDataBySource(const QString sourceName, const QVariant value, const QString units) +void AWKeys::setDataBySource(const QString &sourceName, const QVariantMap &data) { qCDebug(LOG_AW); qCDebug(LOG_AW) << "Source" << sourceName; - qCDebug(LOG_AW) << "Data" << value << units; + qCDebug(LOG_AW) << "Data" << data; // first list init QStringList tags = aggregator->keysFromSource(sourceName); if (tags.isEmpty()) - tags = aggregator->registerSource(sourceName, units); + tags = aggregator->registerSource(sourceName, data[QString("units")].toString()); // update data or drop source if there are no matches if (tags.isEmpty()) { @@ -705,6 +705,8 @@ void AWKeys::setDataBySource(const QString sourceName, const QVariant value, con #ifdef BUILD_FUTURE m_mutex.lock(); #endif /* BUILD_FUTURE */ + // HACK workaround for time values which are stored in the different path + QVariant value = sourceName == QString("Local") ? data[QString("DateTime")] : data[QString("value")]; std::for_each(tags.cbegin(), tags.cend(), [this, value](const QString tag) { values[tag] = aggregator->formater(value, tag); }); diff --git a/sources/awesome-widget/plugin/awkeys.h b/sources/awesome-widget/plugin/awkeys.h index 80f8cc3..31451c9 100644 --- a/sources/awesome-widget/plugin/awkeys.h +++ b/sources/awesome-widget/plugin/awkeys.h @@ -19,6 +19,7 @@ #ifndef AWKEYS_H #define AWKEYS_H +#include #include #include @@ -60,7 +61,9 @@ public: public slots: void addDevice(const QString source); - void dataUpdated(const QString sourceName, const QVariant value, const QString units); + void dataUpdated(const QString &sourceName, const Plasma::DataEngine::Data &data); + // dummy method required by DataEngine connections + void modelChanged(QString, QAbstractItemModel *) {}; signals: void dropSourceFromDataengine(const QString source); @@ -78,7 +81,7 @@ private: void addKeyToCache(const QString type, const QString key = QString("")); void calculateValues(); QString parsePattern(QString pattern) const; - void setDataBySource(const QString sourceName, const QVariant value, const QString units); + void setDataBySource(const QString &sourceName, const QVariantMap &data); // objects AWDataAggregator *dataAggregator = nullptr; AWDataEngineAggregator *dataEngineAggregator = nullptr;