From f7ccea7bca79f1dc21e497872a419446f20d211e Mon Sep 17 00:00:00 2001 From: aqua Date: Sat, 20 Aug 2022 16:37:42 +0300 Subject: Add Setting and MockSettings - rename Settings to RekonqSettings --- scripts/rekonf.py | 81 +++++++++++++++++++++---------- src/settings/CMakeLists.txt | 16 ++++-- src/settings/settings.cpp | 28 +++++++++++ src/settings/settings.hpp | 30 ++++++++++++ src/settings/settingsdialog.cpp | 10 ++-- src/settings/settingsdialog.h | 5 +- src/settings/settingswidgets.hpp | 11 +++-- src/settings/test/dialog.cpp | 12 ----- src/settings/test/fonts.cpp | 31 ------------ src/settings/test/settings_mock.hpp | 18 +++++++ src/settings/test/test_settings.cpp | 71 +++++++++++++++++++++++++++ src/settings/test/test_settingsdialog.cpp | 20 ++++++++ 12 files changed, 248 insertions(+), 85 deletions(-) create mode 100644 src/settings/settings.cpp create mode 100644 src/settings/settings.hpp delete mode 100644 src/settings/test/dialog.cpp delete mode 100644 src/settings/test/fonts.cpp create mode 100644 src/settings/test/settings_mock.hpp create mode 100644 src/settings/test/test_settings.cpp create mode 100644 src/settings/test/test_settingsdialog.cpp diff --git a/scripts/rekonf.py b/scripts/rekonf.py index 56ded374..48706c3d 100755 --- a/scripts/rekonf.py +++ b/scripts/rekonf.py @@ -15,45 +15,52 @@ from xml.etree import ElementTree def write_int_entry(entry): '''Add a QSpinBox connected to an Int entry''' - print(f' // { entry.attrib["name"] }') - print(f' auto* { entry.attrib["key"] } = new QSpinBox(this);') - print(f' { entry.attrib["key"] }->setValue({ entry.find("{*}default").text });') - print(f' formLayout->addRow(tr("{ entry.attrib["name"] }"), { entry.attrib["key"] });') + obj = entry.attrib['key'] + default = entry.find('{*}default').text + print(f' auto* { obj } = new QSpinBox(this);') + print(f' { obj }->setValue(s->value("{ obj }", { default }).toInt());') + print(f' formLayout->addRow(tr("{ entry.attrib["name"] }"), { obj });') def write_bool_entry(entry): '''Add a QCheckBox connected to a Bool entry''' - print(f' // { entry.attrib["name"] }') - print(f' auto* { entry.attrib["key"] } = new QCheckBox(tr("{ entry.attrib["name"] }"), this);') - print(f' { entry.attrib["key"] }->setChecked({ entry.find("{*}default").text });') - print(f' formLayout->addRow(QString(), { entry.attrib["key"] });') + obj = entry.attrib['key'] + default = entry.find('{*}default').text + print(f' auto* { obj } = new QCheckBox(tr("{ entry.attrib["name"] }"), this);') + print(f' { obj }->setChecked(s->value("{ obj }", { default }).toBool());') + print(f' formLayout->addRow(QString(), { obj });') def write_string_entry(entry): '''Add a QLineEdit connected to a String entry''' - print(f' // { entry.attrib["name"] }') - print(f' auto* { entry.attrib["key"] } = new QLineEdit(this);') - print(f' { entry.attrib["key"] }->setText("{ entry.find("{*}default").text }");') - print(f' formLayout->addRow(tr("{ entry.attrib["name"] }"), { entry.attrib["key"] });') + obj = entry.attrib['key'] + default = entry.find('{*}default').text + print(f' auto* {obj} = new QLineEdit(this);') + print(f' {obj}->setText(s->value("{ obj }", "{ default }").toString());') + print(f' formLayout->addRow(tr("{ entry.attrib["name"] }"), { obj });') def write_font_entry(entry): '''Add a QFontComboBox connected to a Font entry''' - print(f' // { entry.attrib["name"] }') - print(f' auto* { entry.attrib["key"] } = new QFontComboBox(this);') - print(f' { entry.attrib["key"] }->setCurrentFont({ entry.find("{*}default").text });') - print(f' formLayout->addRow(tr("{ entry.attrib["name"] }"), { entry.attrib["key"] });') + obj = entry.attrib['key'] + default = entry.find('{*}default').text + print(f' auto* { obj } = new QFontComboBox(this);') + print(f' { obj }->setCurrentFont(s->value("{ obj }", "{ default }").toString());') + print(f' formLayout->addRow(tr("{ entry.attrib["name"] }"), { obj });') def write_shortcut_entry(entry): '''Add a QKeySequenceEdit connected to a Shortcut entry''' - print(f' // { entry.attrib["name"] }') - print(f' auto* { entry.attrib["key"] } = new QKeySequenceEdit({{ "{entry.find("{*}default").text}" }}, this);') - print(f' formLayout->addRow(tr("{ entry.attrib["name"] }"), { entry.attrib["key"] });') + obj = entry.attrib['key'] + default = entry.find('{*}default').text + print(f' auto* { entry.attrib["key"] } = new QKeySequenceEdit(this);') + print(f' { obj }->setKeySequence(s->value("{ obj }", "{ default }").toString());') + print(f' formLayout->addRow(tr("{ entry.attrib["name"] }"), { obj });') def generate_group_widget(root, group): '''Generate a class based on the group name''' + class_group = group.attrib["name"].replace(' ', '') class_name = group.attrib["name"].replace(' ', '') + 'SettingsWidget' # includes @@ -71,7 +78,8 @@ def generate_group_widget(root, group): print(f'#include <{ include.text }>') print('') - print(f'{ class_name }::{ class_name }(QWidget *parent) : SettingsWidget(parent) {{') + print(f'{ class_name }::{ class_name }(RekonqSettings *s, QWidget *parent) : SettingsWidget(s, parent) {{') + print(f' s->beginGroup("{ class_group }");') print(' auto *formLayout = new QFormLayout;') print(' setLayout(formLayout);') print('') @@ -94,13 +102,26 @@ def generate_group_widget(root, group): print(f'#error entry with unknown type { entry.attrib["type"] }') print('') + print(' s->endGroup();') print('}\n') print(f'void { class_name }::save() {{ }}') print(f'void { class_name }::reset() {{ }}') -if __name__ == '__main__': +def generate_group_ini(root, group): + group_name = group.attrib["name"].replace(' ', '') + print(f'[{ group_name }]') + for entry in group.findall('{http://www.kde.org/standards/kcfg/1.0}entry'): + if entry.find('{*}default').get('code') == 'true': + continue + entry_key = entry.attrib['key'] + entry_val = entry.find('{*}default').text + print(f'{ entry_key }={ entry_val }') + print('') + + +def main(): parser = argparse.ArgumentParser(description='Generate SettingsWidgets') parser.add_argument('file', type=str, help='kcfg file') parser.add_argument('--group', type=str, required=True, help='Group') @@ -111,8 +132,16 @@ if __name__ == '__main__': tree = ElementTree.parse(args.file) root = tree.getroot() - # groups - for group in root.findall('{http://www.kde.org/standards/kcfg/1.0}group'): - if group.attrib["name"] == args.group: - print('// This is an automatically generated file') - generate_group_widget(root, group) + if args.group == 'all': + for group in root.findall('{http://www.kde.org/standards/kcfg/1.0}group'): + generate_group_ini(root, group) + else: + for group in root.findall('{http://www.kde.org/standards/kcfg/1.0}group'): + if group.attrib["name"] == args.group: + print('// This is an automatically generated file') + generate_group_widget(root, group) + break + + +if __name__ == '__main__': + main() diff --git a/src/settings/CMakeLists.txt b/src/settings/CMakeLists.txt index 91d8e5d6..f597cfb9 100644 --- a/src/settings/CMakeLists.txt +++ b/src/settings/CMakeLists.txt @@ -16,6 +16,7 @@ add_custom_command(OUTPUT shortcutssettingswidget.cpp DEPENDS ${PROJECT_SOURCE_D ${PROJECT_SOURCE_DIR}/src/rekonq.kcfg) add_library(settings STATIC + ${PROJECT_SOURCE_DIR}/include/rsettings.hpp settings.cpp settings.hpp settingsdialog.cpp settingsdialog.h settingsdialog.ui settingswidgets.hpp helpers.hpp generalsettingswidget.cpp appearancesettingswidget.cpp networksettingswidget.cpp shortcutssettingswidget.cpp @@ -23,10 +24,15 @@ add_library(settings STATIC target_link_libraries(settings PUBLIC Qt6::Widgets) IF(TESTING) - add_executable(test_settingsdialog test/dialog.cpp) - target_link_libraries(test_settingsdialog settings) + add_executable(test_settingsdialog test/test_settingsdialog.cpp test/settings_mock.hpp) + target_link_libraries(test_settingsdialog GTest::gmock settings) - add_executable(test_fonts test/fonts.cpp) - target_link_libraries(test_fonts GTest::gtest Qt6::Gui) - gtest_discover_tests(test_fonts) + # test config file + add_custom_command(OUTPUT rekonqrc DEPENDS ${PROJECT_SOURCE_DIR}/src/rekonq.kcfg + COMMAND python3 ${PROJECT_SOURCE_DIR}/scripts/rekonf.py + --group=all --output=rekonqrc ${PROJECT_SOURCE_DIR}/src/rekonq.kcfg) + + add_executable(test_settings test/test_settings.cpp test/settings_mock.hpp rekonqrc) + target_link_libraries(test_settings GTest::gtest GTest::gmock settings) + gtest_discover_tests(test_settings EXTRA_ARGS rekonqrc) endif() diff --git a/src/settings/settings.cpp b/src/settings/settings.cpp new file mode 100644 index 00000000..1ffa14cb --- /dev/null +++ b/src/settings/settings.cpp @@ -0,0 +1,28 @@ +/* ============================================================ + * The rekonq project + * ============================================================ + * SPDX-License-Identifier: GPL-3.0-only + * Copyright (C) 2022 aqua + * ============================================================ + * Description: Application Settings + * ============================================================ */ + +#include "settings.hpp" +#include + +Settings::Settings(const QString &path, QObject *parent) : RekonqSettings(parent) +{ + d = new QSettings(path, QSettings::IniFormat, this); +} + +void Settings::beginGroup(const QString &prefix) { d->beginGroup(prefix); } + +void Settings::endGroup() { d->endGroup(); } + +void Settings::setValue(const QString &key, const QVariant &value) +{ + d->setValue(key, value); + emit changed(key, value); +} + +QVariant Settings::value(const QString &key, const QVariant &defaultValue) const { return d->value(key, defaultValue); } diff --git a/src/settings/settings.hpp b/src/settings/settings.hpp new file mode 100644 index 00000000..c595e981 --- /dev/null +++ b/src/settings/settings.hpp @@ -0,0 +1,30 @@ +/* ============================================================ + * The rekonq project + * ============================================================ + * SPDX-License-Identifier: GPL-3.0-only + * Copyright (C) 2022 aqua + * ============================================================ + * Description: Application Settings + * ============================================================ */ + +#pragma once + +#include + +class QSettings; +class Settings final : public RekonqSettings { + Q_OBJECT + +public: + explicit Settings(const QString &path, QObject *parent = nullptr); + ~Settings() = default; + + void beginGroup(const QString &prefix) override; + void endGroup() override; + + void setValue(const QString &key, const QVariant &value) override; + QVariant value(const QString &key, const QVariant &defaultValue = QVariant()) const override; + +private: + QSettings *d; +}; diff --git a/src/settings/settingsdialog.cpp b/src/settings/settingsdialog.cpp index e869fe10..0c54856e 100644 --- a/src/settings/settingsdialog.cpp +++ b/src/settings/settingsdialog.cpp @@ -14,14 +14,14 @@ #include "settingswidgets.hpp" #include "ui_settingsdialog.h" -SettingsDialog::SettingsDialog(QWidget *parent) : QDialog(parent), ui(new Ui::SettingsDialog) +SettingsDialog::SettingsDialog(RekonqSettings *settings, QWidget *parent) : QDialog(parent), ui(new Ui::SettingsDialog) { ui->setupUi(this); - ui->stackedWidget->addWidget(new GeneralSettingsWidget); - ui->stackedWidget->addWidget(new AppearanceSettingsWidget); - ui->stackedWidget->addWidget(new NetworkSettingsWidget); - ui->stackedWidget->addWidget(new ShortcutsSettingsWidget); + ui->stackedWidget->addWidget(new GeneralSettingsWidget(settings, this)); + ui->stackedWidget->addWidget(new AppearanceSettingsWidget(settings, this)); + ui->stackedWidget->addWidget(new NetworkSettingsWidget(settings, this)); + ui->stackedWidget->addWidget(new ShortcutsSettingsWidget(settings, this)); connect(ui->listWidget, &QListWidget::currentRowChanged, ui->stackedWidget, &QStackedWidget::setCurrentIndex); } diff --git a/src/settings/settingsdialog.h b/src/settings/settingsdialog.h index 3f191e1e..0c793f9e 100644 --- a/src/settings/settingsdialog.h +++ b/src/settings/settingsdialog.h @@ -14,14 +14,17 @@ #include +class RekonqSettings; + namespace Ui { class SettingsDialog; } + class SettingsDialog : public QDialog { Q_OBJECT public: - explicit SettingsDialog(QWidget *parent = nullptr); + explicit SettingsDialog(RekonqSettings *settings, QWidget *parent = nullptr); ~SettingsDialog() override; private: diff --git a/src/settings/settingswidgets.hpp b/src/settings/settingswidgets.hpp index 31cd4580..27ebe8a2 100644 --- a/src/settings/settingswidgets.hpp +++ b/src/settings/settingswidgets.hpp @@ -10,12 +10,13 @@ #pragma once #include +#include class SettingsWidget : public QWidget { Q_OBJECT public: - explicit SettingsWidget(QWidget *parent = nullptr) : QWidget(parent) {} + explicit SettingsWidget(RekonqSettings *, QWidget *parent = nullptr) : QWidget(parent) {} signals: void changed(); @@ -27,7 +28,7 @@ public slots: class GeneralSettingsWidget final : public SettingsWidget { Q_OBJECT public: - explicit GeneralSettingsWidget(QWidget *parent = nullptr); + explicit GeneralSettingsWidget(RekonqSettings *, QWidget *parent = nullptr); public slots: void save() override; @@ -37,7 +38,7 @@ public slots: class AppearanceSettingsWidget final : public SettingsWidget { Q_OBJECT public: - explicit AppearanceSettingsWidget(QWidget *parent = nullptr); + explicit AppearanceSettingsWidget(RekonqSettings *, QWidget *parent = nullptr); public slots: void save() override; @@ -47,7 +48,7 @@ public slots: class NetworkSettingsWidget final : public SettingsWidget { Q_OBJECT public: - explicit NetworkSettingsWidget(QWidget *parent = nullptr); + explicit NetworkSettingsWidget(RekonqSettings *, QWidget *parent = nullptr); public slots: void save() override; @@ -57,7 +58,7 @@ public slots: class ShortcutsSettingsWidget final : public SettingsWidget { Q_OBJECT public: - explicit ShortcutsSettingsWidget(QWidget *parent = nullptr); + explicit ShortcutsSettingsWidget(RekonqSettings *, QWidget *parent = nullptr); public slots: void save() override; diff --git a/src/settings/test/dialog.cpp b/src/settings/test/dialog.cpp deleted file mode 100644 index 2bc9ffe0..00000000 --- a/src/settings/test/dialog.cpp +++ /dev/null @@ -1,12 +0,0 @@ -#include "../settingsdialog.h" -#include - -int main(int argc, char **argv) -{ - QApplication app(argc, argv); - - SettingsDialog dlg; - dlg.show(); - - return QApplication::exec(); -} \ No newline at end of file diff --git a/src/settings/test/fonts.cpp b/src/settings/test/fonts.cpp deleted file mode 100644 index 65cc7229..00000000 --- a/src/settings/test/fonts.cpp +++ /dev/null @@ -1,31 +0,0 @@ -#include "../helpers.hpp" -#include -#include -#include -#include - -TEST(Settings, getFont) -{ - const auto serif = getFont(QFont::Serif); - EXPECT_EQ(serif.styleHint(), QFont::Serif) << qUtf8Printable(serif.toString()); - - const auto fixed = getFont(QFont::Monospace); - EXPECT_EQ(fixed.styleHint(), QFont::Monospace) << qUtf8Printable(fixed.toString()); -} - -int main(int argc, char **argv) -{ - ::testing::InitGoogleTest(&argc, argv); - - // handling fonts requires a QGuiApplication - // The proper platform name needs to be added to the argument list before the QGuiApplication constructor is called - // This needs to be done here for gtest_discover_tests to work - QList args; - for (int i = 0; i < argc; ++i) args.append(argv[i]); - args.append({"-platform", "offscreen"}); - int args_count = args.count(); - - QGuiApplication app(args_count, args.data()); - - return RUN_ALL_TESTS(); -} diff --git a/src/settings/test/settings_mock.hpp b/src/settings/test/settings_mock.hpp new file mode 100644 index 00000000..ec792ff5 --- /dev/null +++ b/src/settings/test/settings_mock.hpp @@ -0,0 +1,18 @@ +#pragma once + +#include +#include + +class MockSettings : public RekonqSettings { + Q_OBJECT + +public: + explicit MockSettings() : RekonqSettings(nullptr) {} + ~MockSettings() = default; + + MOCK_METHOD(void, beginGroup, (const QString &), (override)); + MOCK_METHOD(void, endGroup, (), (override)); + + MOCK_METHOD(void, setValue, (const QString &, const QVariant &), (override)); + MOCK_METHOD(QVariant, value, (const QString &, const QVariant &), (const, override)); +}; diff --git a/src/settings/test/test_settings.cpp b/src/settings/test/test_settings.cpp new file mode 100644 index 00000000..72582bc7 --- /dev/null +++ b/src/settings/test/test_settings.cpp @@ -0,0 +1,71 @@ +#include +#include + +#include + +// Software under Test +#include "../helpers.hpp" +#include "../settings.hpp" +#include "../settingsdialog.h" +#include "settings_mock.hpp" + +using ::testing::AtLeast; +using ::testing::ReturnArg; + +const char *settingsFile = nullptr; + +TEST(settings, getFont) +{ + const auto serif = getFont(QFont::Serif); + EXPECT_EQ(serif.styleHint(), QFont::Serif) << qUtf8Printable(serif.toString()); + + const auto fixed = getFont(QFont::Monospace); + EXPECT_EQ(fixed.styleHint(), QFont::Monospace) << qUtf8Printable(fixed.toString()); +} + +TEST(settings, Settings) +{ + Settings settings(settingsFile); + + const auto FirstRun = settings.value("FirstRun"); + EXPECT_TRUE(FirstRun.isValid()); + EXPECT_TRUE(FirstRun.toBool()); + + settings.beginGroup("Network"); + const auto downloadPathAsk = settings.value("downloadPathAsk"); + EXPECT_TRUE(downloadPathAsk.isValid()); + EXPECT_TRUE(downloadPathAsk.toBool()); + settings.endGroup(); + + const auto searchUrl = settings.value("searchUrl"); + EXPECT_TRUE(searchUrl.isValid()); + EXPECT_EQ(searchUrl.toString(), QString("https://duckduckgo.com/?q=%1")); +} + +TEST(settings, SettingsDialog) +{ + MockSettings settings; + EXPECT_CALL(settings, beginGroup).Times(4); + EXPECT_CALL(settings, endGroup).Times(4); + EXPECT_CALL(settings, value).Times(AtLeast(4)).WillRepeatedly(ReturnArg<1>()); + + SettingsDialog dlg(&settings); +} + +int main(int argc, char **argv) +{ + ::testing::InitGoogleTest(&argc, argv); + if (argc > 1) settingsFile = argv[argc - 1]; + + // handling fonts requires a QGuiApplication + // The proper platform name needs to be added to the argument list before the QGuiApplication constructor is called + // This needs to be done here for gtest_discover_tests to work + QList args; + for (int i = 0; i < argc; ++i) args.append(argv[i]); + args.append({"-platform", "offscreen"}); + int args_count = args.count(); + + QApplication app(args_count, args.data()); + + return RUN_ALL_TESTS(); +} diff --git a/src/settings/test/test_settingsdialog.cpp b/src/settings/test/test_settingsdialog.cpp new file mode 100644 index 00000000..b70c6dda --- /dev/null +++ b/src/settings/test/test_settingsdialog.cpp @@ -0,0 +1,20 @@ +#include "../settingsdialog.h" +#include "settings_mock.hpp" +#include + +using ::testing::AtLeast; +using ::testing::NiceMock; +using ::testing::ReturnArg; + +int main(int argc, char **argv) +{ + QApplication app(argc, argv); + + NiceMock settings; + EXPECT_CALL(settings, value).WillRepeatedly(ReturnArg<1>()); + + SettingsDialog dlg(&settings); + dlg.show(); + + return QApplication::exec(); +} -- cgit v1.2.1