From c5ed279da0e74adb79c6c2a3e485cb9668b1c130 Mon Sep 17 00:00:00 2001 From: aqua Date: Wed, 24 Aug 2022 16:38:49 +0300 Subject: SettingsDialog: save settings when changed - connect Restore Defaults button --- src/application.cpp | 9 +++++ src/main.cpp | 5 +++ src/settings/CMakeLists.txt | 2 +- src/settings/settingsdialog.cpp | 36 +++++++++++++++-- src/settings/settingsdialog.h | 5 +++ src/settings/settingsdialog.ui | 32 --------------- src/settings/settingswidget.cpp | 81 +++++++++++++++++++++++++++++++++++++ src/settings/settingswidgets.hpp | 29 +++++-------- src/settings/test/test_settings.cpp | 37 +++++++++++++---- 9 files changed, 172 insertions(+), 64 deletions(-) create mode 100644 src/settings/settingswidget.cpp (limited to 'src') diff --git a/src/application.cpp b/src/application.cpp index 814bfab8..a2031de4 100644 --- a/src/application.cpp +++ b/src/application.cpp @@ -14,6 +14,7 @@ #include "plugins/rplugininterface.hpp" #include "rekonqwindow.h" #include "settings/settings.hpp" +#include "settings/settingsdialog.h" #include #include #include @@ -33,6 +34,14 @@ Application::Application(int &argc, char *argv[]) : SingleApplication(argc, argv spdlog::info("Loading rekonq configuration: {}", qUtf8Printable(settingsPath)); m_settings = new Settings(settingsPath, this); + if (m_settings->value("FirstRun", true).toBool()) { + spdlog::info("First run"); + if ((new SettingsDialog(m_settings, nullptr))->exec()) { + spdlog::info("new settings saved"); + m_settings->setValue("FirstRun", false); + } + } + // load default plugins for (const auto &location : QStandardPaths::standardLocations(QStandardPaths::AppLocalDataLocation)) { QDir dir(location + "/plugins"); diff --git a/src/main.cpp b/src/main.cpp index 1d6e30da..51e68716 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -10,9 +10,14 @@ * ============================================================ */ #include "application.hpp" +#include int main(int argc, char **argv) { +#ifdef QT_DEBUG + spdlog::set_level(spdlog::level::debug); +#endif + // When loading QtWebEngine from a plugin, set Qt::AA_ShareOpenGLContexts using QCoreApplication::setAttribute QCoreApplication::setAttribute(Qt::AA_ShareOpenGLContexts, true); diff --git a/src/settings/CMakeLists.txt b/src/settings/CMakeLists.txt index f597cfb9..29a011c1 100644 --- a/src/settings/CMakeLists.txt +++ b/src/settings/CMakeLists.txt @@ -18,7 +18,7 @@ add_custom_command(OUTPUT shortcutssettingswidget.cpp DEPENDS ${PROJECT_SOURCE_D add_library(settings STATIC ${PROJECT_SOURCE_DIR}/include/rsettings.hpp settings.cpp settings.hpp settingsdialog.cpp settingsdialog.h settingsdialog.ui - settingswidgets.hpp helpers.hpp + settingswidgets.hpp settingswidget.cpp helpers.hpp generalsettingswidget.cpp appearancesettingswidget.cpp networksettingswidget.cpp shortcutssettingswidget.cpp ) target_link_libraries(settings PUBLIC Qt6::Widgets) diff --git a/src/settings/settingsdialog.cpp b/src/settings/settingsdialog.cpp index 0c54856e..68fa7a26 100644 --- a/src/settings/settingsdialog.cpp +++ b/src/settings/settingsdialog.cpp @@ -13,17 +13,45 @@ #include "settingsdialog.h" #include "settingswidgets.hpp" #include "ui_settingsdialog.h" +#include SettingsDialog::SettingsDialog(RekonqSettings *settings, QWidget *parent) : QDialog(parent), ui(new Ui::SettingsDialog) { ui->setupUi(this); + saveBtn = ui->buttonBox->button(QDialogButtonBox::Save); + Q_CHECK_PTR(saveBtn); + restoreDefaultsBtn = ui->buttonBox->button(QDialogButtonBox::RestoreDefaults); + Q_CHECK_PTR(restoreDefaultsBtn); - 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)); + if (!settings->value("FirstRun", true).toBool()) saveBtn->setEnabled(false); + + addPage(new GeneralSettingsWidget(settings, this)); + addPage(new AppearanceSettingsWidget(settings, this)); + addPage(new NetworkSettingsWidget(settings, this)); + addPage(new ShortcutsSettingsWidget(settings, this)); connect(ui->listWidget, &QListWidget::currentRowChanged, ui->stackedWidget, &QStackedWidget::setCurrentIndex); + + connect(restoreDefaultsBtn, &QPushButton::clicked, this, [this]() { + for (auto *w : ui->stackedWidget->findChildren(QString(), Qt::FindDirectChildrenOnly)) { + w->reset(); + } + }); + + connect(this, &QDialog::accepted, this, [this]() { + for (auto *w : ui->stackedWidget->findChildren(QString(), Qt::FindDirectChildrenOnly)) { + w->save(); + } + }); } SettingsDialog::~SettingsDialog() { delete ui; } + +void SettingsDialog::addPage(SettingsWidget *page) +{ + auto *item = new QListWidgetItem(page->objectName(), ui->listWidget); + item->setTextAlignment(Qt::AlignHCenter | Qt::AlignVCenter); + ui->stackedWidget->addWidget(page); + + connect(page, &SettingsWidget::changed, this, [this]() { saveBtn->setEnabled(true); }); +} \ No newline at end of file diff --git a/src/settings/settingsdialog.h b/src/settings/settingsdialog.h index 0c793f9e..433857b3 100644 --- a/src/settings/settingsdialog.h +++ b/src/settings/settingsdialog.h @@ -15,6 +15,7 @@ #include class RekonqSettings; +class SettingsWidget; namespace Ui { class SettingsDialog; @@ -28,5 +29,9 @@ public: ~SettingsDialog() override; private: + void addPage(SettingsWidget *page); + Ui::SettingsDialog *ui; + QPushButton *saveBtn; + QPushButton *restoreDefaultsBtn; }; diff --git a/src/settings/settingsdialog.ui b/src/settings/settingsdialog.ui index 1c19380d..14ab30ef 100644 --- a/src/settings/settingsdialog.ui +++ b/src/settings/settingsdialog.ui @@ -33,38 +33,6 @@ Qt::AlignVCenter - - - General - - - AlignCenter - - - - - Appearance - - - AlignCenter - - - - - Network - - - AlignCenter - - - - - Shortcuts - - - AlignCenter - - diff --git a/src/settings/settingswidget.cpp b/src/settings/settingswidget.cpp new file mode 100644 index 00000000..b5a2432c --- /dev/null +++ b/src/settings/settingswidget.cpp @@ -0,0 +1,81 @@ +#include "settingswidgets.hpp" + +#include +#include +#include +#include +#include + +void SettingsWidget::save() +{ + if (objectName() != QLatin1String("General")) m_settings->beginGroup(objectName()); + + // Int + for (const auto *spinbox : findChildren(QString(), Qt::FindDirectChildrenOnly)) { + m_settings->setValue(spinbox->objectName(), spinbox->value()); + } + + // Bool + for (const auto *checkbox : findChildren(QString(), Qt::FindDirectChildrenOnly)) { + m_settings->setValue(checkbox->objectName(), checkbox->isChecked()); + } + + // String + for (const auto *lineedit : findChildren(QString(), Qt::FindDirectChildrenOnly)) { + m_settings->setValue(lineedit->objectName(), lineedit->text()); + } + + // Font + for (const auto *font : findChildren(QString(), Qt::FindDirectChildrenOnly)) { + m_settings->setValue(font->objectName(), font->currentFont().family()); + } + + // Shortcut + for (const auto *shortcut : findChildren(QString(), Qt::FindDirectChildrenOnly)) { + m_settings->setValue(shortcut->objectName(), shortcut->keySequence()); + } + + if (objectName() != QLatin1String("General")) m_settings->endGroup(); +} + +void SettingsWidget::reset() +{ + if (objectName() != QLatin1String("General")) m_settings->beginGroup(objectName()); + + // Int + for (auto *spinbox : findChildren(QString(), Qt::FindDirectChildrenOnly)) { + const auto value = spinbox->property("defaultValue"); + spinbox->setValue(value.toInt()); + m_settings->setValue(spinbox->objectName(), value); + } + + // Bool + for (auto *checkbox : findChildren(QString(), Qt::FindDirectChildrenOnly)) { + const auto value = checkbox->property("defaultValue"); + checkbox->setChecked(value.toBool()); + m_settings->setValue(checkbox->objectName(), value); + } + + // String + for (auto *lineedit : findChildren(QString(), Qt::FindDirectChildrenOnly)) { + const auto value = lineedit->property("defaultValue"); + lineedit->setText(value.toString()); + m_settings->setValue(lineedit->objectName(), value); + } + + // Font + for (auto *font : findChildren(QString(), Qt::FindDirectChildrenOnly)) { + const auto value = font->property("defaultValue"); + font->setFont(QFont(value.toString())); + m_settings->setValue(font->objectName(), value); + } + + // Shortcut + for (auto *shortcut : findChildren(QString(), Qt::FindDirectChildrenOnly)) { + const auto value = shortcut->property("defaultValue"); + shortcut->setKeySequence(value.toString()); + m_settings->setValue(shortcut->objectName(), value); + } + + if (objectName() != QLatin1String("General")) m_settings->endGroup(); +} \ No newline at end of file diff --git a/src/settings/settingswidgets.hpp b/src/settings/settingswidgets.hpp index 27ebe8a2..25fbe0a4 100644 --- a/src/settings/settingswidgets.hpp +++ b/src/settings/settingswidgets.hpp @@ -16,51 +16,42 @@ class SettingsWidget : public QWidget { Q_OBJECT public: - explicit SettingsWidget(RekonqSettings *, QWidget *parent = nullptr) : QWidget(parent) {} + explicit SettingsWidget(RekonqSettings *settings, QWidget *parent = nullptr) : QWidget(parent) + { + m_settings = settings; + } signals: void changed(); + public slots: - virtual void save() = 0; - virtual void reset() = 0; + void save(); + void reset(); + +protected: + RekonqSettings *m_settings; }; class GeneralSettingsWidget final : public SettingsWidget { Q_OBJECT public: explicit GeneralSettingsWidget(RekonqSettings *, QWidget *parent = nullptr); - -public slots: - void save() override; - void reset() override; }; class AppearanceSettingsWidget final : public SettingsWidget { Q_OBJECT public: explicit AppearanceSettingsWidget(RekonqSettings *, QWidget *parent = nullptr); - -public slots: - void save() override; - void reset() override; }; class NetworkSettingsWidget final : public SettingsWidget { Q_OBJECT public: explicit NetworkSettingsWidget(RekonqSettings *, QWidget *parent = nullptr); - -public slots: - void save() override; - void reset() override; }; class ShortcutsSettingsWidget final : public SettingsWidget { Q_OBJECT public: explicit ShortcutsSettingsWidget(RekonqSettings *, QWidget *parent = nullptr); - -public slots: - void save() override; - void reset() override; }; diff --git a/src/settings/test/test_settings.cpp b/src/settings/test/test_settings.cpp index 2ca5ba1a..fdb976f6 100644 --- a/src/settings/test/test_settings.cpp +++ b/src/settings/test/test_settings.cpp @@ -7,22 +7,34 @@ #include #include +#include #include #include -#include - // Software under Test #include "../helpers.hpp" #include "../settings.hpp" #include "../settingsdialog.h" #include "settings_mock.hpp" +using ::testing::_; using ::testing::AtLeast; +using ::testing::ContainerEq; using ::testing::ReturnArg; const char *settingsFile = nullptr; +MATCHER_P(QStringEq, a, "") +{ + *result_listener << "where the arg is " << qUtf8Printable(arg); + return arg.compare(a) == 0; +} +MATCHER_P(QVariantEq, a, "") +{ + *result_listener << "where the arg is " << qUtf8Printable(arg.toString()); + return arg.toString().compare(a) == 0; +} + TEST(settings, getFont) { const auto serif = getFont(QFont::Serif); @@ -60,12 +72,21 @@ TEST(settings, Settings) 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); + MockSettings mockSettings; + // There are 4 groups in total, but General should not be calling beginGroup/endGroup + // beginGroup/endGroup are called twice: during the ctor and when accepted + EXPECT_CALL(mockSettings, beginGroup).Times(3 * 2); + EXPECT_CALL(mockSettings, endGroup).Times(3 * 2); + // There are 35 settings in total, one of which is hidden and won't be set by the dialog + EXPECT_CALL(mockSettings, value).Times(35).WillRepeatedly(ReturnArg<1>()); + EXPECT_CALL(mockSettings, setValue(_, _)).Times(33); + EXPECT_CALL(mockSettings, setValue(QStringEq("homepage"), QVariantEq("about:blank"))); + + SettingsDialog dlg(&mockSettings); + auto *homepage = dlg.findChild("homepage"); + EXPECT_TRUE(homepage->text() == QLatin1String("http://www.kde.org/")) << qUtf8Printable(homepage->text()); + homepage->setText("about:blank"); + dlg.accept(); } int main(int argc, char **argv) -- cgit v1.2.1