Browse Source

Implement config checking (#1859)

* Add error handling functions to ConfigHandler

Refurbished functions setValue and value which were previously unused.
These functions now set/get a setting with error handling.
Currently recognizes only errors recognizable by QSettings.

* Make use of value and setValue in ConfigHandler

Signed-off-by: Haris Gušić <harisgusic.dev@gmail.com>

* Add checker for unrecognized general options

Extraneous config options in [General] will be reported as errors.
Added some placeholder functions to be implemented in future commits.

* Introduce keysFromGroup function

Signed-off-by: Haris Gušić <harisgusic.dev@gmail.com>

* Check shortcut names for duplicates

Signed-off-by: Haris Gušić <harisgusic.dev@gmail.com>

* Fix notification spam

Signed-off-by: Haris Gušić <harisgusic.dev@gmail.com>

* Implement shortcut conflict checking

Signed-off-by: Haris Gušić <harisgusic.dev@gmail.com>

* Fix reading of fallbacks on error

If there is a config error, some values would not be loaded correctly.
Using the newly implemented function ConfigHandler::contains instead of
QSettings::contains solves this issue.

These changes reveal u bug that causes a crash on startup.

Signed-off-by: Haris Gušić <harisgusic.dev@gmail.com>

* Fix crashes introduced in previous commit

Because ConfigHandler is a dependency of most other classes,
calling functions from those classes inside ConfigHandler caused
infinite recursions in some cases.

Signed-off-by: Haris Gušić <harisgusic.dev@gmail.com>

* Add config file watcher

Signed-off-by: Haris Gušić <harisgusic.dev@gmail.com>

* Add missing config options

Signed-off-by: Haris Gušić <harisgusic.dev@gmail.com>

* Fix bug in shortcut conflict detection

Signed-off-by: Haris Gušić <harisgusic.dev@gmail.com>

* Add error resolved notification

Signed-off-by: Haris Gušić <harisgusic.dev@gmail.com>

* Add GUI error message overlay

Signed-off-by: Haris Gušić <harisgusic.dev@gmail.com>

* Add indicator in config window

Signed-off-by: Haris Gušić <harisgusic.dev@gmail.com>

* Use ConfigHandler::fileChanged in ConfigWindow

Signed-off-by: Haris Gušić <harisgusic.dev@gmail.com>

* Fix watcher sometimes not firing

Signed-off-by: Haris Gušić <harisgusic.dev@gmail.com>

* Improve config file watching performance

Signed-off-by: Haris Gušić <harisgusic.dev@gmail.com>

* Add new way to handle config

This is only a fundamental implementation. Future commits will replace
everything with this new paradigm.

Signed-off-by: Haris Gušić <harisgusic.dev@gmail.com>

* Fix getButtons and related functions

Also refactored related code to use QList instead of QVector because
QSettings does not work well with QVector.

Signed-off-by: Haris Gušić <harisgusic.dev@gmail.com>

* Make good use of the new way

* Implement proper checking for basic types

Everything is covered, apart from KeySequence.

* Move fallback path to ExistingDir value handler

Signed-off-by: Haris Gušić <harisgusic.dev@gmail.com>

* Use consistent naming scheme in ConfigHandler

Signed-off-by: Haris Gušić <harisgusic.dev@gmail.com>

* Implement config getters/setters via macro

Signed-off-by: Haris Gušić <harisgusic.dev@gmail.com>

* Surround text with tr and clang-format

Signed-off-by: Haris Gušić <harisgusic.dev@gmail.com>

* Fix colors being saved obfuscated

Signed-off-by: Haris Gušić <harisgusic.dev@gmail.com>

* Add ValueHandler::represenation

Signed-off-by: Haris Gušić <harisgusic.dev@gmail.com>

* Move ValueHandler to separate files

Signed-off-by: Haris Gušić <harisgusic.dev@gmail.com>

* confighandler.cpp: rename macro CUSTOM to OPTION

Signed-off-by: Haris Gušić <harisgusic.dev@gmail.com>

* Fix bug with shortcut conflict checker

Signed-off-by: Haris Gušić <harisgusic.dev@gmail.com>

* Update docs and fix setAllTheButtons

Signed-off-by: Haris Gušić <harisgusic.dev@gmail.com>

* Handle filenamePattern properly

Signed-off-by: Haris Gušić <harisgusic.dev@gmail.com>

* Fix failing build due to wrong function name

Signed-off-by: Haris Gušić <harisgusic.dev@gmail.com>

* Fix QSet error due to Qt version mismatch

Signed-off-by: Haris Gušić <harisgusic.dev@gmail.com>

* Replace QSharedPointer::get with data for older Qt versions

Signed-off-by: Haris Gušić <harisgusic.dev@gmail.com>

* Fix failing build on MacOS and ubuntu 18.04

Signed-off-by: Haris Gušić <harisgusic.dev@gmail.com>

* Add column headers to recognizedGeneralOptions map

Signed-off-by: Haris Gušić <harisgusic.dev@gmail.com>

* Fix ubuntu 18.04 error

Signed-off-by: Haris Gušić <harisgusic.dev@gmail.com>

* Fix false positive when shortcuts empty

Signed-off-by: Haris Gušić <harisgusic.dev@gmail.com>

* Fix wrong shortcut group prefix

Signed-off-by: Haris Gušić <harisgusic.dev@gmail.com>

* Implement proper shortcut checking

Signed-off-by: Haris Gušić <harisgusic.dev@gmail.com>

* Add shortcut map in ConfigHandler

Signed-off-by: Haris Gušić <harisgusic.dev@gmail.com>

* Move ConfigShortcuts functions to ShortcutsWidget

Signed-off-by: Haris Gušić <harisgusic.dev@gmail.com>

* Fix minor bugs

Signed-off-by: Haris Gušić <harisgusic.dev@gmail.com>

* Add fallback scheme: Pictures, HOME, TMP

Signed-off-by: Haris Gušić <harisgusic.dev@gmail.com>

* Add config --check CLI option

Signed-off-by: Haris Gušić <harisgusic.dev@gmail.com>

* Add config error log to GUI

Signed-off-by: Haris Gušić <harisgusic.dev@gmail.com>

* Rename ValueHandler::description to expected

* Convert Qt's #AARRGGBB to #RRGGBBAA and vice versa

Signed-off-by: Haris Gušić <harisgusic.dev@gmail.com>

* Remove obsolete `saveAfterCopyPath`

Signed-off-by: Haris Gušić <harisgusic.dev@gmail.com>

* Fix errors in example config

Also added an additional ; in front of actual comments to differentiate
them from commented options.

Signed-off-by: Haris Gušić <harisgusic.dev@gmail.com>

* Allow special value 'picker' in userColors

Signed-off-by: Haris Gušić <harisgusic.dev@gmail.com>

* Allow only name, #RRGGBB, and #RRGGBBAA color formats

Signed-off-by: Haris Gušić <harisgusic.dev@gmail.com>
Haris Gušić 3 years ago
parent
commit
d1428889b9

+ 54 - 54
flameshot.example.ini

@@ -1,73 +1,73 @@
-[General]
-; Configure which buttons to show after drawing a selection
-; Not easy to set by hand
+;[General]
+;; Configure which buttons to show after drawing a selection
+;; Not easy to set by hand
 ;buttons=@Variant(\0\0\0\x7f\0\0\0\vQList<int>\0\0\0\0\x14\0\0\0\0\0\0\0\x1\0\0\0\x2\0\0\0\x3\0\0\0\x4\0\0\0\x5\0\0\0\x6\0\0\0\x12\0\0\0\xf\0\0\0\x13\0\0\0\a\0\0\0\b\0\0\0\t\0\0\0\x10\0\0\0\n\0\0\0\v\0\0\0\f\0\0\0\r\0\0\0\xe\0\0\0\x11)
-
-; List of colors for color picker
-; The colors are arranged counter-clockwise with the first being set to the right of the cursor
-; Colors are any valid hex code or W3C color name
-; "picker" adds a custom color picker
+;
+;; List of colors for color picker
+;; The colors are arranged counter-clockwise with the first being set to the right of the cursor
+;; Colors are any valid hex code or W3C color name
+;; "picker" adds a custom color picker
 ;userColors=#800000, #ff0000, #ffff00, #00ff00, #008000, #00ffff, #0000ff, #ff00ff, #800080, picker
-
-; Image Save Path
-;savePath=
-
-; Whether the savePath is a fixed path (bool)
+;
+;; Image Save Path
+;savePath=/tmp
+;
+;; Whether the savePath is a fixed path (bool)
 ;savePathFixed=false
-
-; Main UI color
-; Color is any valid hex code or W3C color name
+;
+;; Main UI color
+;; Color is any valid hex code or W3C color name
 ;uiColor=#740096
-
-; Contrast UI color
-; Color is any valid hex code or W3C color name
+;
+;; Contrast UI color
+;; Color is any valid hex code or W3C color name
 ;contrastUiColor=#270032
-
-; Last used color
-; Color is any valid hex code or W3C color name
-;drawColor=
-
-; Show the help screen on startup (bool)
+;
+;; Last used color
+;; Color is any valid hex code or W3C color name
+;drawColor=#ff0000
+;
+;; Show the help screen on startup (bool)
 ;showHelp=true
-
-; Show the side panel button (bool)
+;
+;; Show the side panel button (bool)
 ;showSidePanelButton=true
-
-; Ignore updates to versions less than this value
+;
+;; Ignore updates to versions less than this value
 ;ignoreUpdateToVersion=
-
-; Show desktop notifications (bool)
+;
+;; Show desktop notifications (bool)
 ;showDesktopNotification=true
-
-; Filename pattern using C++ strftime formatting
+;
+;; Filename pattern using C++ strftime formatting
 ;filenamePattern=%F_%H-%M
-
-; Whether the tray icon is disabled (bool)
+;
+;; Whether the tray icon is disabled (bool)
 ;disabledTrayIcon=false
-
-; Last used tool thickness (int)
-;drawThickness=0
-
-; Keep the App Launcher open after selecting an app (bool)
+;
+;; Last used tool thickness (int)
+;drawThickness=1
+;
+;; Keep the App Launcher open after selecting an app (bool)
 ;keepOpenAppLauncher=false
-
-; Launch at startup (bool)
-;startupLaunch=
-
-; Opacity of area outside selection (int in range 0-255)
+;
+;; Launch at startup (bool)
+;startupLaunch=true
+;
+;; Opacity of area outside selection (int in range 0-255)
 ;contrastOpacity=190
-
-; Save image after copy (bool)
+;
+;; Save image after copy (bool)
 ;saveAfterCopy=false
-
-; Copy path to image after save (bool)
+;
+;; Copy path to image after save (bool)
 ;copyPathAfterSave=false
-
-; Use JPG format instead of PNG (bool)
+;
+;; Use JPG format instead of PNG (bool)
 ;useJpgForClipboard=false
-
-; Shortcut Settings for all tools
-[Shortcuts]
+;
+;; Shortcut Settings for all tools
+;[Shortcuts]
 ;TYPE_ARROW=A
 ;TYPE_CIRCLE=C
 ;TYPE_CIRCLECOUNT=

+ 2 - 2
src/config/buttonlistview.cpp

@@ -59,7 +59,7 @@ void ButtonListView::updateActiveButtons(QListWidgetItem* item)
                    CaptureToolButton::getPriorityByButton(b);
         });
     } else {
-        m_listButtons.remove(m_listButtons.indexOf(bType));
+        m_listButtons.removeOne(bType);
     }
     ConfigHandler().setButtons(m_listButtons);
 }
@@ -85,7 +85,7 @@ void ButtonListView::selectAll()
 
 void ButtonListView::updateComponents()
 {
-    m_listButtons = ConfigHandler().getButtons();
+    m_listButtons = ConfigHandler().buttons();
     auto listTypes = CaptureToolButton::getIterableButtonTypes();
     for (int i = 0; i < this->count(); ++i) {
         QListWidgetItem* item = this->item(i);

+ 1 - 1
src/config/buttonlistview.h

@@ -22,7 +22,7 @@ protected:
     void initButtonList();
 
 private:
-    QVector<CaptureToolButton::ButtonType> m_listButtons;
+    QList<CaptureToolButton::ButtonType> m_listButtons;
     QMap<QString, CaptureToolButton::ButtonType> m_buttonTypeByName;
 
     void updateActiveButtons(QListWidgetItem*);

+ 126 - 23
src/config/configwindow.cpp

@@ -11,10 +11,17 @@
 #include "src/utils/confighandler.h"
 #include "src/utils/globalvalues.h"
 #include "src/utils/pathinfo.h"
+#include <QApplication>
+#include <QDialog>
+#include <QDialogButtonBox>
 #include <QFileSystemWatcher>
 #include <QIcon>
 #include <QKeyEvent>
+#include <QLabel>
+#include <QSizePolicy>
 #include <QTabBar>
+#include <QTextEdit>
+#include <QTextStream>
 #include <QVBoxLayout>
 
 // ConfigWindow contains the menus where you can configure the application
@@ -24,25 +31,18 @@ ConfigWindow::ConfigWindow(QWidget* parent)
 {
     // We wrap QTabWidget in a QWidget because of a Qt bug
     auto layout = new QVBoxLayout(this);
-    m_tabs = new QTabWidget(this);
-    m_tabs->tabBar()->setUsesScrollButtons(false);
-    layout->addWidget(m_tabs);
+    m_tabWidget = new QTabWidget(this);
+    m_tabWidget->tabBar()->setUsesScrollButtons(false);
+    layout->addWidget(m_tabWidget);
 
     setAttribute(Qt::WA_DeleteOnClose);
     setWindowIcon(QIcon(":img/app/flameshot.svg"));
     setWindowTitle(tr("Configuration"));
 
-    auto changedSlot = [this](QString s) {
-        QStringList files = m_configWatcher->files();
-        if (!files.contains(s)) {
-            this->m_configWatcher->addPath(s);
-        }
-        emit updateChildren();
-    };
-    m_configWatcher = new QFileSystemWatcher(this);
-    m_configWatcher->addPath(ConfigHandler().configFilePath());
-    connect(
-      m_configWatcher, &QFileSystemWatcher::fileChanged, this, changedSlot);
+    connect(ConfigHandler::getInstance(),
+            &ConfigHandler::fileChanged,
+            this,
+            &ConfigWindow::updateChildren);
 
     QColor background = this->palette().window().color();
     bool isDark = ColorUtils::colorIsDark(background);
@@ -51,24 +51,40 @@ ConfigWindow::ConfigWindow(QWidget* parent)
 
     // visuals
     m_visuals = new VisualsEditor();
-    m_tabs->addTab(
-      m_visuals, QIcon(modifier + "graphics.svg"), tr("Interface"));
+    m_visualsTab = new QWidget();
+    QVBoxLayout* visualsLayout = new QVBoxLayout(m_visualsTab);
+    m_visualsTab->setLayout(visualsLayout);
+    visualsLayout->addWidget(m_visuals);
+    m_tabWidget->addTab(
+      m_visualsTab, QIcon(modifier + "graphics.svg"), tr("Interface"));
 
     // filename
     m_filenameEditor = new FileNameEditor();
-    m_tabs->addTab(m_filenameEditor,
-                   QIcon(modifier + "name_edition.svg"),
-                   tr("Filename Editor"));
+    m_filenameEditorTab = new QWidget();
+    QVBoxLayout* filenameEditorLayout = new QVBoxLayout(m_filenameEditorTab);
+    m_filenameEditorTab->setLayout(filenameEditorLayout);
+    filenameEditorLayout->addWidget(m_filenameEditor);
+    m_tabWidget->addTab(m_filenameEditorTab,
+                        QIcon(modifier + "name_edition.svg"),
+                        tr("Filename Editor"));
 
     // general
     m_generalConfig = new GeneralConf();
-    m_tabs->addTab(
-      m_generalConfig, QIcon(modifier + "config.svg"), tr("General"));
+    m_generalConfigTab = new QWidget();
+    QVBoxLayout* generalConfigLayout = new QVBoxLayout(m_generalConfigTab);
+    m_generalConfigTab->setLayout(generalConfigLayout);
+    generalConfigLayout->addWidget(m_generalConfig);
+    m_tabWidget->addTab(
+      m_generalConfigTab, QIcon(modifier + "config.svg"), tr("General"));
 
     // shortcuts
     m_shortcuts = new ShortcutsWidget();
-    m_tabs->addTab(
-      m_shortcuts, QIcon(modifier + "shortcut.svg"), tr("Shortcuts"));
+    m_shortcutsTab = new QWidget();
+    QVBoxLayout* shortcutsLayout = new QVBoxLayout(m_shortcutsTab);
+    m_shortcutsTab->setLayout(shortcutsLayout);
+    shortcutsLayout->addWidget(m_shortcuts);
+    m_tabWidget->addTab(
+      m_shortcutsTab, QIcon(modifier + "shortcut.svg"), tr("Shortcuts"));
 
     // connect update sigslots
     connect(this,
@@ -83,6 +99,12 @@ ConfigWindow::ConfigWindow(QWidget* parent)
             &ConfigWindow::updateChildren,
             m_generalConfig,
             &GeneralConf::updateComponents);
+
+    // Error indicator (this must come last)
+    initErrorIndicator(m_visualsTab, m_visuals);
+    initErrorIndicator(m_filenameEditorTab, m_filenameEditor);
+    initErrorIndicator(m_generalConfigTab, m_generalConfig);
+    initErrorIndicator(m_shortcutsTab, m_shortcuts);
 }
 
 void ConfigWindow::keyPressEvent(QKeyEvent* e)
@@ -91,3 +113,84 @@ void ConfigWindow::keyPressEvent(QKeyEvent* e)
         close();
     }
 }
+
+void ConfigWindow::initErrorIndicator(QWidget* tab, QWidget* widget)
+{
+    QLabel* label = new QLabel(tab);
+    QPushButton* btnShowErrors = new QPushButton("Show errors", tab);
+    QHBoxLayout* btnLayout = new QHBoxLayout(tab);
+
+    // Set up label
+    label->setText(tr(
+      "<b>Configuration file has errors. Resolve them before continuing.</b>"));
+    label->setStyleSheet(QStringLiteral(":disabled { color: %1; }")
+                           .arg(qApp->palette().color(QPalette::Text).name()));
+    label->setVisible(ConfigHandler().hasError());
+
+    // Set up "Show errors" button
+    btnShowErrors->setSizePolicy(QSizePolicy::Maximum, QSizePolicy::Fixed);
+    btnLayout->addWidget(btnShowErrors);
+    btnShowErrors->setVisible(ConfigHandler().hasError());
+
+    widget->setEnabled(!ConfigHandler().hasError());
+
+    // Add label and button to the parent widget's layout
+    QBoxLayout* layout = static_cast<QBoxLayout*>(tab->layout());
+    if (layout != nullptr) {
+        layout->insertWidget(0, label);
+        layout->insertLayout(1, btnLayout);
+    } else {
+        widget->layout()->addWidget(label);
+        widget->layout()->addWidget(btnShowErrors);
+    }
+
+    // Sigslots
+    connect(ConfigHandler::getInstance(), &ConfigHandler::error, widget, [=]() {
+        widget->setEnabled(false);
+        label->show();
+        btnShowErrors->show();
+    });
+    connect(ConfigHandler::getInstance(),
+            &ConfigHandler::errorResolved,
+            widget,
+            [=]() {
+                widget->setEnabled(true);
+                label->hide();
+                btnShowErrors->hide();
+            });
+    connect(btnShowErrors, &QPushButton::clicked, this, [this]() {
+        // Generate error log message
+        QString str;
+        QTextStream stream(&str);
+        ConfigHandler().checkForErrors(&stream);
+
+        // Set up dialog
+        QDialog dialog;
+        dialog.setWindowTitle(QStringLiteral("Configuration errors"));
+        dialog.setLayout(new QVBoxLayout(&dialog));
+
+        // Add text display
+        QTextEdit* textDisplay = new QTextEdit(&dialog);
+        textDisplay->setPlainText(str);
+        textDisplay->setReadOnly(true);
+        dialog.layout()->addWidget(textDisplay);
+
+        // Add Ok button
+        using BBox = QDialogButtonBox;
+        BBox* buttons = new BBox(BBox::Ok);
+        dialog.layout()->addWidget(buttons);
+        connect(buttons, &QDialogButtonBox::clicked, this, [&dialog]() {
+            dialog.close();
+        });
+
+        dialog.show();
+
+        qApp->processEvents();
+        QPoint center = dialog.geometry().center();
+        QRect dialogRect(0, 0, 400, 400);
+        dialogRect.moveCenter(center);
+        dialog.setGeometry(dialogRect);
+
+        dialog.exec();
+    });
+}

+ 12 - 2
src/config/configwindow.h

@@ -10,6 +10,7 @@ class ShortcutsWidget;
 class GeneralConf;
 class QFileSystemWatcher;
 class VisualsEditor;
+class QWidget;
 
 class ConfigWindow : public QWidget
 {
@@ -24,10 +25,19 @@ protected:
     void keyPressEvent(QKeyEvent*);
 
 private:
-    QTabWidget* m_tabs;
+    QTabWidget* m_tabWidget;
+
     FileNameEditor* m_filenameEditor;
+    QWidget* m_filenameEditorTab;
+
     ShortcutsWidget* m_shortcuts;
+    QWidget* m_shortcutsTab;
+
     GeneralConf* m_generalConfig;
+    QWidget* m_generalConfigTab;
+
     VisualsEditor* m_visuals;
-    QFileSystemWatcher* m_configWatcher;
+    QWidget* m_visualsTab;
+
+    void initErrorIndicator(QWidget* tab, QWidget* widget);
 };

+ 2 - 2
src/config/filenameeditor.cpp

@@ -103,7 +103,7 @@ void FileNameEditor::showParsedPattern(const QString& p)
 
 void FileNameEditor::resetName()
 {
-    m_nameEditor->setText(ConfigHandler().filenamePatternValue());
+    m_nameEditor->setText(ConfigHandler().filenamePattern());
 }
 
 void FileNameEditor::addToNameEditor(QString s)
@@ -114,6 +114,6 @@ void FileNameEditor::addToNameEditor(QString s)
 
 void FileNameEditor::updateComponents()
 {
-    m_nameEditor->setText(ConfigHandler().filenamePatternValue());
+    m_nameEditor->setText(ConfigHandler().filenamePattern());
     m_outputLabel->setText(m_nameHandler->parsedPattern());
 }

+ 22 - 34
src/config/generalconf.cpp

@@ -42,7 +42,7 @@ GeneralConf::GeneralConf(QWidget* parent)
     initCopyPathAfterSave();
     initUseJpgForClipboard();
     initSaveAfterCopy();
-    initUploadHistoryMaxSize();
+    inituploadHistoryMax();
     initUndoLimit();
 
     m_layout->addStretch();
@@ -55,31 +55,27 @@ GeneralConf::GeneralConf(QWidget* parent)
 void GeneralConf::_updateComponents(bool allowEmptySavePath)
 {
     ConfigHandler config;
-    m_helpMessage->setChecked(config.showHelpValue());
-    m_sidePanelButton->setChecked(config.showSidePanelButtonValue());
-    m_sysNotifications->setChecked(config.desktopNotificationValue());
-    m_autostart->setChecked(config.startupLaunchValue());
-    m_copyAndCloseAfterUpload->setChecked(
-      config.copyAndCloseAfterUploadEnabled());
-    m_saveAfterCopy->setChecked(config.saveAfterCopyValue());
-    m_copyPathAfterSave->setChecked(config.copyPathAfterSaveEnabled());
+    m_helpMessage->setChecked(config.showHelp());
+    m_sidePanelButton->setChecked(config.showSidePanelButton());
+    m_sysNotifications->setChecked(config.showDesktopNotification());
+    m_autostart->setChecked(config.startupLaunch());
+    m_copyAndCloseAfterUpload->setChecked(config.copyAndCloseAfterUpload());
+    m_saveAfterCopy->setChecked(config.saveAfterCopy());
+    m_copyPathAfterSave->setChecked(config.copyPathAfterSave());
     m_useJpgForClipboard->setChecked(config.useJpgForClipboard());
     m_historyConfirmationToDelete->setChecked(
       config.historyConfirmationToDelete());
     m_checkForUpdates->setChecked(config.checkForUpdates());
     m_showStartupLaunchMessage->setChecked(config.showStartupLaunchMessage());
     m_screenshotPathFixedCheck->setChecked(config.savePathFixed());
-    m_uploadHistoryMaxSize->setValue(config.uploadHistoryMaxSizeValue());
+    m_uploadHistoryMax->setValue(config.uploadHistoryMax());
     m_undoLimit->setValue(config.undoLimit());
 
     if (allowEmptySavePath || !config.savePath().isEmpty()) {
         m_savePath->setText(config.savePath());
-    } else {
-        ConfigHandler().setSavePath(
-          QStandardPaths::writableLocation(QStandardPaths::PicturesLocation));
     }
 #if defined(Q_OS_LINUX) || defined(Q_OS_UNIX)
-    m_showTray->setChecked(!config.disabledTrayIconValue());
+    m_showTray->setChecked(!config.disabledTrayIcon());
 #endif
 }
 
@@ -100,7 +96,7 @@ void GeneralConf::showSidePanelButtonChanged(bool checked)
 
 void GeneralConf::showDesktopNotificationChanged(bool checked)
 {
-    ConfigHandler().setDesktopNotification(checked);
+    ConfigHandler().setShowDesktopNotification(checked);
 }
 
 void GeneralConf::showTrayIconChanged(bool checked)
@@ -344,7 +340,7 @@ void GeneralConf::initCopyAndCloseAfterUpload()
     m_scrollAreaLayout->addWidget(m_copyAndCloseAfterUpload);
 
     connect(m_copyAndCloseAfterUpload, &QCheckBox::clicked, [](bool checked) {
-        ConfigHandler().setCopyAndCloseAfterUploadEnabled(checked);
+        ConfigHandler().setCopyAndCloseAfterUpload(checked);
     });
 }
 
@@ -368,10 +364,6 @@ void GeneralConf::initSaveAfterCopy()
     QHBoxLayout* pathLayout = new QHBoxLayout();
 
     QString path = ConfigHandler().savePath();
-    if (path.isEmpty()) {
-        path =
-          QStandardPaths::writableLocation(QStandardPaths::PicturesLocation);
-    }
     m_savePath = new QLineEdit(path, this);
     m_savePath->setDisabled(true);
     QString foreground = this->palette().windowText().color().name();
@@ -401,7 +393,7 @@ void GeneralConf::historyConfirmationToDelete(bool checked)
     ConfigHandler().setHistoryConfirmationToDelete(checked);
 }
 
-void GeneralConf::initUploadHistoryMaxSize()
+void GeneralConf::inituploadHistoryMax()
 {
     QGroupBox* box = new QGroupBox(tr("Latest Uploads Max Size"));
     box->setFlat(true);
@@ -410,22 +402,22 @@ void GeneralConf::initUploadHistoryMaxSize()
     QVBoxLayout* vboxLayout = new QVBoxLayout();
     box->setLayout(vboxLayout);
 
-    m_uploadHistoryMaxSize = new QSpinBox(this);
-    m_uploadHistoryMaxSize->setMaximum(50);
+    m_uploadHistoryMax = new QSpinBox(this);
+    m_uploadHistoryMax->setMaximum(50);
     QString foreground = this->palette().windowText().color().name();
-    m_uploadHistoryMaxSize->setStyleSheet(
+    m_uploadHistoryMax->setStyleSheet(
       QStringLiteral("color: %1").arg(foreground));
 
-    connect(m_uploadHistoryMaxSize,
+    connect(m_uploadHistoryMax,
             SIGNAL(valueChanged(int)),
             this,
-            SLOT(uploadHistoryMaxSizeChanged(int)));
-    vboxLayout->addWidget(m_uploadHistoryMaxSize);
+            SLOT(uploadHistoryMaxChanged(int)));
+    vboxLayout->addWidget(m_uploadHistoryMax);
 }
 
-void GeneralConf::uploadHistoryMaxSizeChanged(int max)
+void GeneralConf::uploadHistoryMaxChanged(int max)
 {
-    ConfigHandler().setUploadHistoryMaxSize(max);
+    ConfigHandler().setUploadHistoryMax(max);
 }
 
 void GeneralConf::initUndoLimit()
@@ -479,10 +471,6 @@ void GeneralConf::saveAfterCopyChanged(bool checked)
 void GeneralConf::changeSavePath()
 {
     QString path = ConfigHandler().savePath();
-    if (path.isEmpty()) {
-        path =
-          QStandardPaths::writableLocation(QStandardPaths::PicturesLocation);
-    }
     path = chooseFolder(path);
     if (!path.isEmpty()) {
         m_savePath->setText(path);
@@ -496,7 +484,7 @@ void GeneralConf::initCopyPathAfterSave()
     m_copyPathAfterSave->setToolTip(tr("Copy file path after save"));
     m_scrollAreaLayout->addWidget(m_copyPathAfterSave);
     connect(m_copyPathAfterSave, &QCheckBox::clicked, [](bool checked) {
-        ConfigHandler().setCopyPathAfterSaveEnabled(checked);
+        ConfigHandler().setCopyPathAfterSave(checked);
     });
 }
 

+ 3 - 3
src/config/generalconf.h

@@ -30,7 +30,7 @@ private slots:
     void checkForUpdatesChanged(bool checked);
     void autostartChanged(bool checked);
     void historyConfirmationToDelete(bool checked);
-    void uploadHistoryMaxSizeChanged(int max);
+    void uploadHistoryMaxChanged(int max);
     void undoLimit(int limit);
     void saveAfterCopyChanged(bool checked);
     void changeSavePath();
@@ -49,7 +49,7 @@ private:
     void initShowDesktopNotification();
     void initShowTrayIcon();
     void initHistoryConfirmationToDelete();
-    void initUploadHistoryMaxSize();
+    void inituploadHistoryMax();
     void initUndoLimit();
     void initConfigButtons();
     void initCheckForUpdates();
@@ -84,6 +84,6 @@ private:
     QCheckBox* m_screenshotPathFixedCheck;
     QCheckBox* m_historyConfirmationToDelete;
     QCheckBox* m_useJpgForClipboard;
-    QSpinBox* m_uploadHistoryMaxSize;
+    QSpinBox* m_uploadHistoryMax;
     QSpinBox* m_undoLimit;
 };

+ 68 - 4
src/config/shortcutswidget.cpp

@@ -2,9 +2,9 @@
 // SPDX-FileCopyrightText: 2020 Yurii Puchkov at Namecheap & Contributors
 
 #include "shortcutswidget.h"
+#include "capturetool.h"
 #include "setshortcutwidget.h"
 #include "src/core/qguiappcurrentscreen.h"
-#include "src/utils/configshortcuts.h"
 #include <QHeaderView>
 #include <QIcon>
 #include <QKeyEvent>
@@ -37,13 +37,12 @@ ShortcutsWidget::ShortcutsWidget(QWidget* parent)
     m_layout = new QVBoxLayout(this);
     m_layout->setAlignment(Qt::AlignHCenter | Qt::AlignVCenter);
 
-    m_shortcuts = ConfigShortcuts().captureShortcutsDefault(
-      CaptureToolButton::getIterableButtonTypes());
+    initShortcuts();
     initInfoTable();
     show();
 }
 
-const QVector<QStringList>& ShortcutsWidget::shortcuts()
+const QList<QStringList>& ShortcutsWidget::shortcuts()
 {
     return m_shortcuts;
 }
@@ -158,6 +157,71 @@ void ShortcutsWidget::slotShortcutCellClicked(int row, int col)
     }
 }
 
+void ShortcutsWidget::initShortcuts()
+{
+    auto buttons = CaptureToolButton::getIterableButtonTypes();
+
+    // get shortcuts names from capture buttons
+    for (const CaptureToolButton::ButtonType& t : buttons) {
+        CaptureToolButton* b = new CaptureToolButton(t, nullptr);
+        QString shortcutName = QVariant::fromValue(t).toString();
+        if (shortcutName != "TYPE_IMAGEUPLOADER") {
+            appendShortcut(shortcutName, b->tool()->description());
+        }
+        delete b;
+    }
+
+    // additional tools that don't have their own buttons
+    appendShortcut("TYPE_TOGGLE_PANEL", "Toggle side panel");
+    appendShortcut("TYPE_RESIZE_LEFT", "Resize selection left 1px");
+    appendShortcut("TYPE_RESIZE_RIGHT", "Resize selection right 1px");
+    appendShortcut("TYPE_RESIZE_UP", "Resize selection up 1px");
+    appendShortcut("TYPE_RESIZE_DOWN", "Resize selection down 1px");
+    appendShortcut("TYPE_SELECT_ALL", "Select entire screen");
+    appendShortcut("TYPE_MOVE_LEFT", "Move selection left 1px");
+    appendShortcut("TYPE_MOVE_RIGHT", "Move selection right 1px");
+    appendShortcut("TYPE_MOVE_UP", "Move selection up 1px");
+    appendShortcut("TYPE_MOVE_DOWN", "Move selection down 1px");
+    appendShortcut("TYPE_COMMIT_CURRENT_TOOL", "Commit text in text area");
+    appendShortcut("TYPE_DELETE_CURRENT_TOOL", "Delete current tool");
+
+    // non-editable shortcuts have an empty shortcut name
+
+    m_shortcuts << (QStringList() << "" << QObject::tr("Quit capture")
+                                  << QKeySequence(Qt::Key_Escape).toString());
+
+    // Global hotkeys
+#if defined(Q_OS_MACOS)
+    m_shortcuts << (QStringList()
+                    << "" << QObject::tr("Screenshot history") << "⇧⌘⌥H");
+    m_shortcuts << (QStringList()
+                    << "" << QObject::tr("Capture screen") << "⇧⌘⌥4");
+#elif defined(Q_OS_WIN)
+    m_shortcuts << (QStringList() << "" << QObject::tr("Screenshot history")
+                                  << "Shift+Print Screen");
+    m_shortcuts << (QStringList()
+                    << "" << QObject::tr("Capture screen") << "Print Screen");
+#else
+    // TODO - Linux doesn't support global shortcuts for (XServer and Wayland),
+    // possibly it will be solved in the QHotKey library later. So it is
+    // disabled for now.
+#endif
+    m_shortcuts << (QStringList()
+                    << "" << QObject::tr("Show color picker") << "Right Click");
+    m_shortcuts << (QStringList()
+                    << "" << QObject::tr("Change the tool's thickness")
+                    << "Mouse Wheel");
+}
+
+void ShortcutsWidget::appendShortcut(const QString& shortcutName,
+                                     const QString& description)
+{
+    m_shortcuts << (QStringList()
+                    << shortcutName
+                    << QObject::tr(description.toStdString().c_str())
+                    << ConfigHandler().shortcut(shortcutName));
+}
+
 #if defined(Q_OS_MACOS)
 const QString& ShortcutsWidget::nativeOSHotKeyText(const QString& text)
 {

+ 6 - 2
src/config/shortcutswidget.h

@@ -18,7 +18,7 @@ class ShortcutsWidget : public QWidget
     Q_OBJECT
 public:
     explicit ShortcutsWidget(QWidget* parent = nullptr);
-    const QVector<QStringList>& shortcuts();
+    const QList<QStringList>& shortcuts();
 
 private:
     void initInfoTable();
@@ -38,7 +38,11 @@ private:
     ConfigHandler m_config;
     QTableWidget* m_table;
     QVBoxLayout* m_layout;
-    QVector<QStringList> m_shortcuts;
+    QList<QStringList> m_shortcuts;
+
+    void initShortcuts();
+    void appendShortcut(const QString& shortcutName,
+                        const QString& description);
 };
 
 #endif // HOTKEYSCONFIG_H

Some files were not shown because too many files changed in this diff