From a22d2f01391c3d1fb9ec8c8ebf29f00008557a9c Mon Sep 17 00:00:00 2001 From: Eugene Shalygin Date: Wed, 5 Jul 2017 12:19:58 +0200 Subject: [PATCH] Implement enum support in CachedSettingValue Enums are stored as strings, that improves configuration file readability and maintainability. String values are obtained via QMetaEnum, and since with Qt 5.5 QMetaEnum::fromType() includes a static_assert, this has to be a safe method. --- src/base/settingvalue.h | 45 +++++++++++++++++++++++++++++++---- src/base/torrentfileguard.cpp | 21 ++++++---------- src/base/torrentfileguard.h | 10 ++++---- src/gui/search/searchtab.cpp | 35 ++++++++++----------------- src/gui/search/searchtab.h | 9 ++++--- 5 files changed, 71 insertions(+), 49 deletions(-) diff --git a/src/base/settingvalue.h b/src/base/settingvalue.h index 80ab0b19a..2f86bcc43 100644 --- a/src/base/settingvalue.h +++ b/src/base/settingvalue.h @@ -30,7 +30,10 @@ #define SETTINGVALUE_H #include +#include +#include #include +#include #include "settingsstorage.h" @@ -42,16 +45,14 @@ class CachedSettingValue public: explicit CachedSettingValue(const char *keyName, const T &defaultValue = T()) : m_keyName(QLatin1String(keyName)) - , m_value(SettingsStorage::instance()->loadValue( - m_keyName, defaultValue).template value()) + , m_value(loadValue(defaultValue)) { } explicit CachedSettingValue(const char *keyName, const T &defaultValue , const ProxyFunc &proxyFunc) : m_keyName(QLatin1String(keyName)) - , m_value(proxyFunc(SettingsStorage::instance()->loadValue( - m_keyName, defaultValue).template value())) + , m_value(proxyFunc(loadValue(defaultValue))) { } @@ -68,11 +69,45 @@ public: CachedSettingValue &operator=(const T &newValue) { m_value = newValue; - SettingsStorage::instance()->storeValue(m_keyName, m_value); + storeValue(m_value); return *this; } private: + // regular load/save pair + template ::value, int>::type = 0> + U loadValue(const U &defaultValue) + { + return SettingsStorage::instance()->loadValue(m_keyName, defaultValue).template value(); + } + + template ::value, int>::type = 0> + void storeValue(const U &value) + { + SettingsStorage::instance()->storeValue(m_keyName, value); + } + + // load/save pair for enum + // saves literal value of the enum constant, obtained from QMetaEnum + template ::value, int>::type = 0> + U loadValue(const U &defaultValue) + { + static_assert(std::is_same::type>::value, + "Enumeration underlying type has to be int"); + + bool ok = false; + const U res = static_cast(QMetaEnum::fromType().keyToValue( + SettingsStorage::instance()->loadValue(m_keyName, QString()).toString().toLatin1().constData(), &ok)); + return ok ? res : defaultValue; + } + + template ::value, int>::type = 0> + void storeValue(const U &value) + { + SettingsStorage::instance()->storeValue(m_keyName, + QString::fromLatin1(QMetaEnum::fromType().valueToKey(static_cast(value)))); + } + const QString m_keyName; T m_value; }; diff --git a/src/base/torrentfileguard.cpp b/src/base/torrentfileguard.cpp index 5369ea510..1a39196e5 100644 --- a/src/base/torrentfileguard.cpp +++ b/src/base/torrentfileguard.cpp @@ -28,15 +28,9 @@ #include "torrentfileguard.h" -#include -#include "settingsstorage.h" +#include "settingvalue.h" #include "utils/fs.h" -namespace -{ - const QLatin1String KEY_AUTO_DELETE_ENABLED ("Core/AutoDeleteAddedTorrentFile"); -} - FileGuard::FileGuard(const QString &path) : m_path {path} , m_remove {true} @@ -79,18 +73,17 @@ void TorrentFileGuard::markAsAddedToSession() TorrentFileGuard::AutoDeleteMode TorrentFileGuard::autoDeleteMode() { - QMetaEnum meta {modeMetaEnum()}; - return static_cast(meta.keyToValue(SettingsStorage::instance()->loadValue( - KEY_AUTO_DELETE_ENABLED, meta.valueToKey(Never)).toByteArray())); + return autoDeleteModeSetting(); } void TorrentFileGuard::setAutoDeleteMode(TorrentFileGuard::AutoDeleteMode mode) { - QMetaEnum meta {modeMetaEnum()}; - SettingsStorage::instance()->storeValue(KEY_AUTO_DELETE_ENABLED, meta.valueToKey(mode)); + autoDeleteModeSetting() = mode; } -QMetaEnum TorrentFileGuard::modeMetaEnum() +CachedSettingValue &TorrentFileGuard::autoDeleteModeSetting() { - return QMetaEnum::fromType(); + static CachedSettingValue setting("Core/AutoDeleteAddedTorrentFile", AutoDeleteMode::Never); + return setting; } + diff --git a/src/base/torrentfileguard.h b/src/base/torrentfileguard.h index b89651592..30ec3138d 100644 --- a/src/base/torrentfileguard.h +++ b/src/base/torrentfileguard.h @@ -29,10 +29,11 @@ #ifndef TOFFENTFILEGURAD_H #define TOFFENTFILEGURAD_H +#include #include -#include -class QMetaEnum; +template class CachedSettingValue; + /// Utility class to defer file deletion class FileGuard { @@ -62,7 +63,7 @@ public: void markAsAddedToSession(); using FileGuard::setAutoRemove; - enum AutoDeleteMode // do not change these names: they are stored in config file + enum AutoDeleteMode: int // do not change these names: they are stored in config file { Never, IfAdded, @@ -74,9 +75,8 @@ public: static void setAutoDeleteMode(AutoDeleteMode mode); private: - static QMetaEnum modeMetaEnum(); - TorrentFileGuard(const QString &path, AutoDeleteMode mode); + static CachedSettingValue &autoDeleteModeSetting(); Q_ENUM(AutoDeleteMode) AutoDeleteMode m_mode; diff --git a/src/gui/search/searchtab.cpp b/src/gui/search/searchtab.cpp index f52150ec0..f4dfebc6a 100644 --- a/src/gui/search/searchtab.cpp +++ b/src/gui/search/searchtab.cpp @@ -31,7 +31,6 @@ #include #include #include -#include #include #include #include @@ -43,7 +42,7 @@ #include "base/utils/misc.h" #include "base/preferences.h" -#include "base/settingsstorage.h" +#include "base/settingvalue.h" #include "guiiconprovider.h" #include "searchsortmodel.h" #include "searchlistdelegate.h" @@ -51,13 +50,6 @@ #include "searchtab.h" #include "ui_searchtab.h" -namespace -{ -#define SETTINGS_KEY(name) "Search/" name - - const QString KEY_FILTER_MODE_SETTING_NAME = SETTINGS_KEY("FilteringMode"); -} - SearchTab::SearchTab(SearchWidget *parent) : QWidget(parent) , m_ui(new Ui::SearchTab()) @@ -216,15 +208,14 @@ void SearchTab::updateFilter() { using Utils::Misc::SizeUnit; SearchSortModel* filterModel = getCurrentSearchListProxy(); - filterModel->enableNameFilter(filteringMode() == OnlyNames); + filterModel->enableNameFilter(filteringMode() == NameFilteringMode::OnlyNames); // we update size and seeds filter parameters in the model even if they are disabled filterModel->setSeedsFilter(m_ui->minSeeds->value(), m_ui->maxSeeds->value()); filterModel->setSizeFilter( sizeInBytes(m_ui->minSize->value(), static_cast(m_ui->minSizeUnit->currentIndex())), sizeInBytes(m_ui->maxSize->value(), static_cast(m_ui->maxSizeUnit->currentIndex()))); - SettingsStorage::instance()->storeValue(KEY_FILTER_MODE_SETTING_NAME, - m_ui->filterMode->itemData(m_ui->filterMode->currentIndex())); + nameFilteringModeSetting() = filteringMode(); filterModel->invalidate(); updateResultsCount(); @@ -255,14 +246,10 @@ void SearchTab::fillFilterComboBoxes() m_ui->filterMode->clear(); - QMetaEnum nameFilteringModeEnum = - this->metaObject()->enumerator(this->metaObject()->indexOfEnumerator("NameFilteringMode")); + m_ui->filterMode->addItem(tr("Torrent names only"), static_cast(NameFilteringMode::OnlyNames)); + m_ui->filterMode->addItem(tr("Everywhere"), static_cast(NameFilteringMode::Everywhere)); - m_ui->filterMode->addItem(tr("Torrent names only"), nameFilteringModeEnum.valueToKey(OnlyNames)); - m_ui->filterMode->addItem(tr("Everywhere"), nameFilteringModeEnum.valueToKey(Everywhere)); - - QVariant selectedMode = SettingsStorage::instance()->loadValue( - KEY_FILTER_MODE_SETTING_NAME, nameFilteringModeEnum.valueToKey(OnlyNames)); + QVariant selectedMode = static_cast(nameFilteringModeSetting().value()); int index = m_ui->filterMode->findData(selectedMode); m_ui->filterMode->setCurrentIndex(index == -1 ? 0 : index); } @@ -305,9 +292,7 @@ QString SearchTab::statusIconName(SearchTab::Status st) SearchTab::NameFilteringMode SearchTab::filteringMode() const { - QMetaEnum metaEnum = - this->metaObject()->enumerator(this->metaObject()->indexOfEnumerator("NameFilteringMode")); - return static_cast(metaEnum.keyToValue(m_ui->filterMode->itemData(m_ui->filterMode->currentIndex()).toByteArray())); + return static_cast(m_ui->filterMode->itemData(m_ui->filterMode->currentIndex()).toInt()); } void SearchTab::loadSettings() @@ -355,3 +340,9 @@ void SearchTab::displayToggleColumnsMenu(const QPoint&) saveSettings(); } } + +CachedSettingValue &SearchTab::nameFilteringModeSetting() +{ + static CachedSettingValue setting("Search/FilteringMode", NameFilteringMode::OnlyNames); + return setting; +} diff --git a/src/gui/search/searchtab.h b/src/gui/search/searchtab.h index 2322f82da..c573deef3 100644 --- a/src/gui/search/searchtab.h +++ b/src/gui/search/searchtab.h @@ -31,7 +31,6 @@ #ifndef SEARCHTAB_H #define SEARCHTAB_H -#include // I don't know why is not enought for Qt's 4.8.7 moc #include #define ENGINE_URL_COLUMN 4 @@ -44,6 +43,8 @@ class QHeaderView; class QStandardItemModel; class QVBoxLayout; +template class CachedSettingValue; + class SearchSortModel; class SearchListDelegate; class SearchWidget; @@ -59,13 +60,13 @@ class SearchTab: public QWidget public: - enum NameFilteringMode + enum class NameFilteringMode { Everywhere, OnlyNames }; - Q_ENUMS(NameFilteringMode) + Q_ENUM(NameFilteringMode) explicit SearchTab(SearchWidget *parent); ~SearchTab(); @@ -106,6 +107,8 @@ private: static QString statusText(Status st); static QString statusIconName(Status st); + static CachedSettingValue& nameFilteringModeSetting(); + Ui::SearchTab *m_ui; QTreeView *m_resultsBrowser; QStandardItemModel *m_searchListModel;