From b76ce364c2f9e8a39720e89e9ea3e64b0fdbc4f3 Mon Sep 17 00:00:00 2001
From: Martin Rotter <rotter@praktik.cz>
Date: Wed, 2 Feb 2022 14:34:34 +0100
Subject: [PATCH] lazy load of categories of settings to speed up settings
 dialog opening

---
 src/librssguard/gui/dialogs/formsettings.cpp  | 15 ++++--
 src/librssguard/gui/dialogs/formsettings.h    |  2 +-
 src/librssguard/gui/dialogs/formsettings.ui   | 19 +------
 .../gui/settings/settingsnodejs.cpp           | 49 ++++++++++++++++++-
 src/librssguard/gui/settings/settingsnodejs.h |  2 +
 .../gui/settings/settingspanel.cpp            |  8 ++-
 src/librssguard/gui/settings/settingspanel.h  |  3 ++
 7 files changed, 74 insertions(+), 24 deletions(-)

diff --git a/src/librssguard/gui/dialogs/formsettings.cpp b/src/librssguard/gui/dialogs/formsettings.cpp
index 10adb6f30..f1b3ef7c2 100644
--- a/src/librssguard/gui/dialogs/formsettings.cpp
+++ b/src/librssguard/gui/dialogs/formsettings.cpp
@@ -39,6 +39,7 @@ FormSettings::FormSettings(QWidget& parent)
   connect(m_ui.m_buttonBox, &QDialogButtonBox::accepted, this, &FormSettings::saveSettings);
   connect(m_ui.m_buttonBox, &QDialogButtonBox::rejected, this, &FormSettings::cancelSettings);
   connect(m_btnApply, &QPushButton::clicked, this, &FormSettings::applySettings);
+  connect(m_ui.m_listSettings, &QListWidget::currentRowChanged, this, &FormSettings::openSettingsCategory);
 
   addSettingsPanel(new SettingsGeneral(&m_settings, this));
   addSettingsPanel(new SettingsDatabase(&m_settings, this));
@@ -61,6 +62,16 @@ FormSettings::~FormSettings() {
   qDebugNN << LOGSEC_GUI << "Destroying FormSettings distance.";
 }
 
+void FormSettings::openSettingsCategory(int category) {
+  if (category >=0 && category < m_panels.size()) {
+    if (!m_panels.at(category)->isLoaded()) {
+      m_panels.at(category)->loadSettings();
+    }
+  }
+
+  m_ui.m_stackedSettings->setCurrentIndex(category);
+}
+
 void FormSettings::saveSettings() {
   applySettings();
   accept();
@@ -72,7 +83,7 @@ void FormSettings::applySettings() {
   QStringList panels_for_restart;
 
   for (SettingsPanel* panel : qAsConst(m_panels)) {
-    if (panel->isDirty()) {
+    if (panel->isDirty() && panel->isLoaded()) {
       panel->saveSettings();
     }
 
@@ -150,8 +161,6 @@ void FormSettings::addSettingsPanel(SettingsPanel* panel) {
 
   m_ui.m_stackedSettings->addWidget(scr);
 
-  panel->loadSettings();
-
   connect(panel, &SettingsPanel::settingsChanged, this, [this]() {
     m_btnApply->setEnabled(true);
   });
diff --git a/src/librssguard/gui/dialogs/formsettings.h b/src/librssguard/gui/dialogs/formsettings.h
index 091d46e3f..f30324c48 100644
--- a/src/librssguard/gui/dialogs/formsettings.h
+++ b/src/librssguard/gui/dialogs/formsettings.h
@@ -20,6 +20,7 @@ class FormSettings : public QDialog {
     virtual ~FormSettings();
 
   private slots:
+    void openSettingsCategory(int category);
 
     // Saves settings into global configuration.
     void saveSettings();
@@ -31,7 +32,6 @@ class FormSettings : public QDialog {
 
     Ui::FormSettings m_ui;
     QPushButton* m_btnApply;
-
     QList<SettingsPanel*> m_panels;
     Settings& m_settings;
 };
diff --git a/src/librssguard/gui/dialogs/formsettings.ui b/src/librssguard/gui/dialogs/formsettings.ui
index b46e345b6..9947651f0 100644
--- a/src/librssguard/gui/dialogs/formsettings.ui
+++ b/src/librssguard/gui/dialogs/formsettings.ui
@@ -62,22 +62,5 @@
   <tabstop>m_listSettings</tabstop>
  </tabstops>
  <resources/>
- <connections>
-  <connection>
-   <sender>m_listSettings</sender>
-   <signal>currentRowChanged(int)</signal>
-   <receiver>m_stackedSettings</receiver>
-   <slot>setCurrentIndex(int)</slot>
-   <hints>
-    <hint type="sourcelabel">
-     <x>83</x>
-     <y>162</y>
-    </hint>
-    <hint type="destinationlabel">
-     <x>370</x>
-     <y>162</y>
-    </hint>
-   </hints>
-  </connection>
- </connections>
+ <connections/>
 </ui>
diff --git a/src/librssguard/gui/settings/settingsnodejs.cpp b/src/librssguard/gui/settings/settingsnodejs.cpp
index 4dbbc545c..af0dc5ba1 100644
--- a/src/librssguard/gui/settings/settingsnodejs.cpp
+++ b/src/librssguard/gui/settings/settingsnodejs.cpp
@@ -8,6 +8,7 @@
 #include "miscellaneous/nodejs.h"
 
 #include <QDir>
+#include <QFileDialog>
 
 SettingsNodejs::SettingsNodejs(Settings* settings, QWidget* parent) : SettingsPanel(settings, parent) {
   m_ui.setupUi(this);
@@ -32,21 +33,67 @@ SettingsNodejs::SettingsNodejs(Settings* settings, QWidget* parent) : SettingsPa
   connect(m_ui.m_tbPackageFolder->lineEdit(), &BaseLineEdit::textChanged,
           this, &SettingsNodejs::testPackageFolder);
 
+  connect(m_ui.m_tbNodeExecutable->lineEdit(), &BaseLineEdit::textChanged,
+          this, &SettingsNodejs::dirtifySettings);
+  connect(m_ui.m_tbNpmExecutable->lineEdit(), &BaseLineEdit::textChanged,
+          this, &SettingsNodejs::dirtifySettings);
+  connect(m_ui.m_tbPackageFolder->lineEdit(), &BaseLineEdit::textChanged,
+          this, &SettingsNodejs::dirtifySettings);
+
+  connect(m_ui.m_btnPackageFolder, &QPushButton::clicked, this, [this]() {
+    changeFileFolder(m_ui.m_tbPackageFolder, true);
+  });
+  connect(m_ui.m_btnNodeExecutable, &QPushButton::clicked, this, [this]() {
+    changeFileFolder(m_ui.m_tbPackageFolder, false, QSL("Node.js (node*)"));
+  });
+  connect(m_ui.m_btnNpmExecutable, &QPushButton::clicked, this, [this]() {
+    changeFileFolder(m_ui.m_tbPackageFolder, false, QSL("NPM (npm*)"));
+  });
+
   // FOR ME: npm install --prefix "složka"
   // NODE_PATH="složka" node.exe....
 }
 
+void SettingsNodejs::changeFileFolder(LineEditWithStatus* tb, bool directory_select, const QString& file_filter) {
+  QFileDialog d(this);
+
+  d.setFileMode(directory_select ? QFileDialog::FileMode::Directory : QFileDialog::FileMode::ExistingFile);
+
+  if (directory_select) {
+    d.setOption(QFileDialog::Option::ShowDirsOnly);
+  }
+  else {
+    d.setNameFilter(file_filter);
+  }
+
+  QString current = qApp->replaceDataUserDataFolderPlaceholder(tb->lineEdit()->text());
+
+  d.selectFile(current);
+
+  if (d.exec() == QDialog::DialogCode::Accepted && !d.selectedFiles().isEmpty()) {
+    tb->lineEdit()->setText(QDir::toNativeSeparators(d.selectedFiles().at(0)));
+  }
+}
+
 QString SettingsNodejs::title() const {
   return QSL("Node.js");
 }
 
 void SettingsNodejs::loadSettings() {
+  onBeginLoadSettings();
+
   m_ui.m_tbNodeExecutable->lineEdit()->setText(qApp->nodejs()->nodeJsExecutable());
   m_ui.m_tbNpmExecutable->lineEdit()->setText(qApp->nodejs()->npmExecutable());
   m_ui.m_tbPackageFolder->lineEdit()->setText(qApp->nodejs()->packageFolder());
+
+  onEndLoadSettings();
 }
 
-void SettingsNodejs::saveSettings() {}
+void SettingsNodejs::saveSettings() {
+  onBeginSaveSettings();
+
+  onEndSaveSettings();
+}
 
 void SettingsNodejs::testNodejs() {
   try {
diff --git a/src/librssguard/gui/settings/settingsnodejs.h b/src/librssguard/gui/settings/settingsnodejs.h
index 22a2ecc36..7747841b6 100644
--- a/src/librssguard/gui/settings/settingsnodejs.h
+++ b/src/librssguard/gui/settings/settingsnodejs.h
@@ -22,6 +22,8 @@ class SettingsNodejs : public SettingsPanel {
     void testNpm();
     void testPackageFolder();
 
+    void changeFileFolder(LineEditWithStatus* tb, bool directory_select, const QString& file_filter = {});
+
   private:
     Ui::SettingsNodejs m_ui;
 };
diff --git a/src/librssguard/gui/settings/settingspanel.cpp b/src/librssguard/gui/settings/settingspanel.cpp
index 6b2f2199a..ca9ba219c 100644
--- a/src/librssguard/gui/settings/settingspanel.cpp
+++ b/src/librssguard/gui/settings/settingspanel.cpp
@@ -5,7 +5,7 @@
 #include "miscellaneous/settings.h"
 
 SettingsPanel::SettingsPanel(Settings* settings, QWidget* parent)
-  : QWidget(parent), m_requiresRestart(false), m_isDirty(false), m_isLoading(false), m_settings(settings) {}
+  : QWidget(parent), m_requiresRestart(false), m_isDirty(false), m_isLoading(false), m_isLoaded(false), m_settings(settings) {}
 
 void SettingsPanel::onBeginLoadSettings() {
   m_isLoading = true;
@@ -13,6 +13,8 @@ void SettingsPanel::onBeginLoadSettings() {
 
 void SettingsPanel::onEndLoadSettings() {
   m_isLoading = false;
+  m_isLoaded = true;
+
   setRequiresRestart(false);
   setIsDirty(false);
 }
@@ -42,6 +44,10 @@ void SettingsPanel::requireRestart() {
   setRequiresRestart(true);
 }
 
+bool SettingsPanel::isLoaded() const {
+  return m_isLoaded;
+}
+
 bool SettingsPanel::isDirty() const {
   return m_isDirty;
 }
diff --git a/src/librssguard/gui/settings/settingspanel.h b/src/librssguard/gui/settings/settingspanel.h
index 4323b5a4d..b40728e28 100644
--- a/src/librssguard/gui/settings/settingspanel.h
+++ b/src/librssguard/gui/settings/settingspanel.h
@@ -23,6 +23,8 @@ class SettingsPanel : public QWidget {
     void setIsDirty(bool is_dirty);
     void setRequiresRestart(bool requiresRestart);
 
+    bool isLoaded() const;
+
   protected:
     void onBeginLoadSettings();
     void onEndLoadSettings();
@@ -43,6 +45,7 @@ class SettingsPanel : public QWidget {
     bool m_requiresRestart;
     bool m_isDirty;
     bool m_isLoading;
+    bool m_isLoaded;
     Settings* m_settings;
 };