From 1c52cf72be6a97f743c8be7d36842167ed4b937d Mon Sep 17 00:00:00 2001 From: Evgeniy Alekseev Date: Wed, 21 Sep 2016 01:02:21 +0300 Subject: [PATCH] initial import of custom keys support (#101) It will use the configuration file `$AWHOME/custom.ini`, group `[Custom]`. One custom key per string, key is custom key, value is any of available standard data. Formatters will be defined by using standard way. --- .../awesome-widget/plugin/awcustomkeys.cpp | 210 ++++++++++++++++++ sources/awesome-widget/plugin/awcustomkeys.h | 64 ++++++ sources/awesome-widget/plugin/awcustomkeys.ui | 93 ++++++++ .../plugin/awformatterconfig.cpp | 2 + 4 files changed, 369 insertions(+) create mode 100644 sources/awesome-widget/plugin/awcustomkeys.cpp create mode 100644 sources/awesome-widget/plugin/awcustomkeys.h create mode 100644 sources/awesome-widget/plugin/awcustomkeys.ui diff --git a/sources/awesome-widget/plugin/awcustomkeys.cpp b/sources/awesome-widget/plugin/awcustomkeys.cpp new file mode 100644 index 0000000..4d63d10 --- /dev/null +++ b/sources/awesome-widget/plugin/awcustomkeys.cpp @@ -0,0 +1,210 @@ +/*************************************************************************** + * This file is part of awesome-widgets * + * * + * awesome-widgets 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 3 of the * + * License, or (at your option) any later version. * + * * + * awesome-widgets 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 awesome-widgets. If not, see http://www.gnu.org/licenses/ * + ***************************************************************************/ + +#include "awcustomkeys.h" +#include "ui_awcustomkeys.h" + +#include +#include +#include + +#include "awabstractselector.h" +#include "awdebug.h" + + +AWCustomKeys::AWCustomKeys(QWidget *parent, const QStringList sources) + : QDialog(parent) + , ui(new Ui::AWCustomKeys) + , m_sources(sources) +{ + qCDebug(LOG_AW) << __PRETTY_FUNCTION__; + + m_filePath = QString("awesomewidgets/custom.ini"); + ui->setupUi(this); + initKeys(); + + connect(ui->buttonBox, SIGNAL(accepted()), this, SLOT(accept())); + connect(ui->buttonBox, SIGNAL(rejected()), this, SLOT(reject())); +} + + +AWCustomKeys::~AWCustomKeys() +{ + qCDebug(LOG_AW) << __PRETTY_FUNCTION__; + + clearSelectors(); + delete ui; +} + + +QStringList AWCustomKeys::customKeys() const +{ + return m_keys.keys(); +} + + +void AWCustomKeys::showDialog() +{ + // update dialog + updateDialog(); + // exec dialog + return execDialog(); +} + + +QVariant AWCustomKeys::valueForKey(const QString &key, const QVariantHash &data) +{ + qCDebug(LOG_AW) << "Find value for key" << key << "in data"; + + return data[m_keys[key]]; +} + + +QStringList AWCustomKeys::usedSources() const +{ + return QSet::fromList(m_keys.values()).toList(); +} + + +void AWCustomKeys::updateUi() +{ + QPair current + = static_cast(sender())->current(); + int index + = m_selectors.indexOf(static_cast(sender())); + + if ((current.first.isEmpty()) && (current.second.isEmpty())) { + // remove current selector if it is empty and does not last + if (sender() == m_selectors.last()) + return; + AWAbstractSelector *selector = m_selectors.takeAt(index); + ui->verticalLayout->removeWidget(selector); + selector->deleteLater(); + } else { + // add new selector if something changed + if (sender() != m_selectors.last()) + return; + addSelector(QPair()); + } +} + + +void AWCustomKeys::addSelector(const QPair ¤t) +{ + qCDebug(LOG_AW) << "Add selector with current values" << current; + + AWAbstractSelector *selector + = new AWAbstractSelector(ui->scrollAreaWidgetContents, {true, false}); + selector->init(QStringList(), m_sources, current); + ui->verticalLayout->insertWidget(ui->verticalLayout->count() - 1, selector); + connect(selector, SIGNAL(selectionChanged()), this, SLOT(updateUi())); + m_selectors.append(selector); +} + + +void AWCustomKeys::clearSelectors() +{ + for (auto selector : m_selectors) { + disconnect(selector, SIGNAL(selectionChanged()), this, + SLOT(updateUi())); + ui->verticalLayout->removeWidget(selector); + selector->deleteLater(); + } + m_selectors.clear(); +} + + +void AWCustomKeys::execDialog() +{ + int ret = exec(); + m_keys.clear(); + for (auto selector : m_selectors) { + QPair select = selector->current(); + if (select.first.isEmpty()) + continue; + m_keys[select.first] = select.second; + } + + // save configuration if required + switch (ret) { + case 0: + break; + case 1: + default: + writeKeys(); + break; + } +} + + +void AWCustomKeys::initKeys() +{ + m_keys.clear(); + + QStringList configs = QStandardPaths::locateAll( + QStandardPaths::GenericDataLocation, m_filePath); + + for (auto fileName : configs) { + QSettings settings(fileName, QSettings::IniFormat); + qCInfo(LOG_AW) << "Configuration file" << settings.fileName(); + + settings.beginGroup(QString("Custom")); + QStringList keys = settings.childKeys(); + for (auto key : keys) { + QString source = settings.value(key).toString(); + qCInfo(LOG_AW) << "Found custom key" << key << "for source" + << source << "in" << settings.fileName(); + if (source.isEmpty()) { + qCInfo(LOG_AW) << "Skip empty source for" << key; + continue; + } + m_keys[key] = source; + } + settings.endGroup(); + } +} + + +void AWCustomKeys::updateDialog() +{ + clearSelectors(); + + for (auto key : m_keys.keys()) + addSelector(QPair(key, m_keys[key])); + // empty one + addSelector(QPair()); +} + + +bool AWCustomKeys::writeKeys() const +{ + QString fileName = QString("%1/%2") + .arg(QStandardPaths::writableLocation( + QStandardPaths::GenericDataLocation)) + .arg(m_filePath); + QSettings settings(fileName, QSettings::IniFormat); + qCInfo(LOG_AW) << "Configuration file" << fileName; + + settings.beginGroup(QString("Custom")); + for (auto key : m_keys.keys()) + settings.setValue(key, m_keys[key]); + settings.endGroup(); + + settings.sync(); + + return (settings.status() == QSettings::NoError); +} diff --git a/sources/awesome-widget/plugin/awcustomkeys.h b/sources/awesome-widget/plugin/awcustomkeys.h new file mode 100644 index 0000000..67e2cd2 --- /dev/null +++ b/sources/awesome-widget/plugin/awcustomkeys.h @@ -0,0 +1,64 @@ +/*************************************************************************** + * This file is part of awesome-widgets * + * * + * awesome-widgets 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 3 of the * + * License, or (at your option) any later version. * + * * + * awesome-widgets 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 awesome-widgets. If not, see http://www.gnu.org/licenses/ * + ***************************************************************************/ + + +#ifndef AWCUSTOMKEYS_H +#define AWCUSTOMKEYS_H + +#include + + +class AWAbstractSelector; +namespace Ui +{ +class AWCustomKeys; +} + +class AWCustomKeys : public QDialog +{ + Q_OBJECT + +public: + explicit AWCustomKeys(QWidget *parent = nullptr, + const QStringList sources = QStringList()); + virtual ~AWCustomKeys(); + Q_INVOKABLE QStringList customKeys() const; + Q_INVOKABLE void showDialog(); + QVariant valueForKey(const QString &key, const QVariantHash &data); + Q_INVOKABLE QStringList usedSources() const; + +private slots: + void updateUi(); + +private: + Ui::AWCustomKeys *ui = nullptr; + QList m_selectors; + // properties + QString m_filePath; + QHash m_keys; + QStringList m_sources; + // methods + void addSelector(const QPair ¤t); + void clearSelectors(); + void execDialog(); + void initKeys(); + void updateDialog(); + bool writeKeys() const; +}; + + +#endif /* AWCUSTOMKEYS_H */ diff --git a/sources/awesome-widget/plugin/awcustomkeys.ui b/sources/awesome-widget/plugin/awcustomkeys.ui new file mode 100644 index 0000000..765039a --- /dev/null +++ b/sources/awesome-widget/plugin/awcustomkeys.ui @@ -0,0 +1,93 @@ + + + AWCustomKeys + + + + 0 + 0 + 400 + 300 + + + + + + + true + + + + + 0 + 0 + 384 + 249 + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + + + + Qt::Horizontal + + + QDialogButtonBox::Close|QDialogButtonBox::Ok + + + + + + + + + buttonBox + accepted() + AWCustomKeys + accept() + + + 248 + 254 + + + 157 + 274 + + + + + buttonBox + rejected() + AWCustomKeys + reject() + + + 316 + 260 + + + 286 + 274 + + + + + diff --git a/sources/awesome-widget/plugin/awformatterconfig.cpp b/sources/awesome-widget/plugin/awformatterconfig.cpp index aa52bcb..d91f66b 100644 --- a/sources/awesome-widget/plugin/awformatterconfig.cpp +++ b/sources/awesome-widget/plugin/awformatterconfig.cpp @@ -80,12 +80,14 @@ void AWFormatterConfig::updateUi() = m_selectors.indexOf(static_cast(sender())); if ((current.first.isEmpty()) && (current.second.isEmpty())) { + // remove current selector if it is empty and does not last if (sender() == m_selectors.last()) return; AWAbstractSelector *selector = m_selectors.takeAt(index); ui->verticalLayout->removeWidget(selector); selector->deleteLater(); } else { + // add new selector if something changed if (sender() != m_selectors.last()) return; auto keys = initKeys();