mirror of
https://github.com/arcan1s/awesome-widgets.git
synced 2025-07-10 04:15:51 +00:00
* initial implementation of configuration export and import feature (#68)
* drop mediators in data transition
This commit is contained in:
@ -20,8 +20,10 @@
|
||||
#include <KI18n/KLocalizedString>
|
||||
#include <KNotifications/KNotification>
|
||||
|
||||
#include <QCheckBox>
|
||||
#include <QDesktopServices>
|
||||
#include <QDir>
|
||||
#include <QFileDialog>
|
||||
#include <QJsonDocument>
|
||||
#include <QJsonParseError>
|
||||
#include <QMessageBox>
|
||||
@ -30,8 +32,10 @@
|
||||
#include <QNetworkReply>
|
||||
#include <QProcess>
|
||||
#include <QProcessEnvironment>
|
||||
#include <QQmlPropertyMap>
|
||||
#include <QSettings>
|
||||
#include <QStandardPaths>
|
||||
#include <QVBoxLayout>
|
||||
|
||||
#include <fontdialog/fontdialog.h>
|
||||
|
||||
@ -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<QQmlPropertyMap *>(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);
|
||||
|
@ -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;
|
||||
|
@ -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<AWKeys *>(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)));
|
||||
}
|
||||
|
@ -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();
|
||||
|
@ -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);
|
||||
});
|
||||
|
@ -19,6 +19,7 @@
|
||||
#ifndef AWKEYS_H
|
||||
#define AWKEYS_H
|
||||
|
||||
#include <Plasma/DataEngine>
|
||||
#include <QMutex>
|
||||
#include <QObject>
|
||||
|
||||
@ -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;
|
||||
|
Reference in New Issue
Block a user