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>
This commit is contained in:
Haris Gušić
2021-09-15 18:56:01 +02:00
committed by GitHub
parent a7e88e60de
commit d1428889b9
35 changed files with 1665 additions and 859 deletions

View File

@@ -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=

View File

@@ -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);

View File

@@ -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*);

View File

@@ -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();
});
}

View File

@@ -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);
};

View File

@@ -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());
}

View File

@@ -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);
});
}

View File

@@ -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;
};

View File

@@ -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)
{

View File

@@ -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

View File

@@ -37,8 +37,8 @@ UIcolorEditor::UIcolorEditor(QWidget* parent)
void UIcolorEditor::updateComponents()
{
ConfigHandler config;
m_uiColor = config.uiMainColorValue();
m_contrastColor = config.uiContrastColorValue();
m_uiColor = config.uiColor();
m_contrastColor = config.contrastUiColor();
m_buttonContrast->setColor(m_contrastColor);
m_buttonMainColor->setColor(m_uiColor);
if (m_lastButtonPressed == m_buttonMainColor) {
@@ -53,9 +53,9 @@ void UIcolorEditor::updateUIcolor()
{
ConfigHandler config;
if (m_lastButtonPressed == m_buttonMainColor) {
config.setUIMainColor(m_uiColor);
config.setUiColor(m_uiColor);
} else {
config.setUIContrastColor(m_contrastColor);
config.setContrastUiColor(m_contrastColor);
}
}

View File

@@ -21,7 +21,7 @@ void VisualsEditor::updateComponents()
{
m_buttonList->updateComponents();
m_colorEditor->updateComponents();
int opacity = ConfigHandler().contrastOpacityValue();
int opacity = ConfigHandler().contrastOpacity();
m_opacitySlider->setMapedValue(0, opacity, 255);
}
@@ -50,7 +50,7 @@ void VisualsEditor::initOpacitySlider()
m_layout->addWidget(label);
m_layout->addLayout(localLayout);
int opacity = ConfigHandler().contrastOpacityValue();
int opacity = ConfigHandler().contrastOpacity();
m_opacitySlider->setMapedValue(0, opacity, 255);
}

View File

@@ -66,7 +66,7 @@ Controller::Controller()
// init tray icon
#if defined(Q_OS_LINUX) || defined(Q_OS_UNIX)
if (!ConfigHandler().disabledTrayIconValue()) {
if (!ConfigHandler().disabledTrayIcon()) {
enableTrayIcon();
}
#elif defined(Q_OS_WIN)

View File

@@ -165,6 +165,8 @@ int main(int argc, char* argv[])
{ "a", "autostart" },
QObject::tr("Enable or disable run at startup"),
QStringLiteral("bool"));
CommandOption checkOption(
"check", QObject::tr("Check the configuration for errors"));
CommandOption showHelpOption(
{ "s", "showhelp" },
QObject::tr("Show the help message in the capture mode"),
@@ -270,7 +272,8 @@ int main(int argc, char* argv[])
trayOption,
showHelpOption,
mainColorOption,
contrastColorOption },
contrastColorOption,
checkOption },
configArgument);
// Parse
if (!parser.parse(app.arguments())) {
@@ -447,8 +450,19 @@ int main(int argc, char* argv[])
bool help = parser.isSet(showHelpOption);
bool mainColor = parser.isSet(mainColorOption);
bool contrastColor = parser.isSet(contrastColorOption);
bool check = parser.isSet(checkOption);
bool someFlagSet =
(filename || tray || help || mainColor || contrastColor);
(filename || tray || help || mainColor || contrastColor || check);
if (check) {
QTextStream stream(stderr);
bool ok = ConfigHandler(true).checkForErrors(&stream);
if (ok) {
stream << QStringLiteral("No errors detected.\n");
goto finish;
} else {
return 1;
}
}
ConfigHandler config;
if (autostart) {
QDBusMessage m = QDBusMessage::createMethodCall(
@@ -506,12 +520,12 @@ int main(int argc, char* argv[])
if (mainColor) {
QString colorCode = parser.value(mainColorOption);
QColor parsedColor(colorCode);
config.setUIMainColor(parsedColor);
config.setUiColor(parsedColor);
}
if (contrastColor) {
QString colorCode = parser.value(contrastColorOption);
QColor parsedColor(colorCode);
config.setUIContrastColor(parsedColor);
config.setContrastUiColor(parsedColor);
}
// Open gui when no options

View File

@@ -47,7 +47,7 @@ ImgurUploader::ImgurUploader(const QPixmap& capture, QWidget* parent)
#endif
m_spinner = new LoadSpinner(this);
m_spinner->setColor(ConfigHandler().uiMainColorValue());
m_spinner->setColor(ConfigHandler().uiColor());
m_spinner->start();
m_infoLabel = new QLabel(tr("Uploading Image"));
@@ -94,7 +94,7 @@ void ImgurUploader::handleReply(QNetworkReply* reply)
imageName = history.packFileName("imgur", deleteToken, imageName);
history.save(m_pixmap, imageName);
if (ConfigHandler().copyAndCloseAfterUploadEnabled()) {
if (ConfigHandler().copyAndCloseAfterUpload()) {
SystemNotification().sendMessage(
QObject::tr("URL copied to clipboard."));
QApplication::clipboard()->setText(m_imageURL.toString());

View File

@@ -42,7 +42,7 @@ AppLauncherWidget::AppLauncherWidget(const QPixmap& p, QWidget* parent)
setWindowIcon(QIcon(":img/app/flameshot.svg"));
setWindowTitle(tr("Open With"));
m_keepOpen = ConfigHandler().keepOpenAppLauncherValue();
m_keepOpen = ConfigHandler().keepOpenAppLauncher();
QString dirLocal = QDir::homePath() + "/.local/share/applications/";
QDir appsDirLocal(dirLocal);
@@ -57,7 +57,7 @@ AppLauncherWidget::AppLauncherWidget(const QPixmap& p, QWidget* parent)
m_terminalCheckbox = new QCheckBox(tr("Launch in terminal"), this);
m_keepOpenCheckbox = new QCheckBox(tr("Keep open after selection"), this);
m_keepOpenCheckbox->setChecked(ConfigHandler().keepOpenAppLauncherValue());
m_keepOpenCheckbox->setChecked(ConfigHandler().keepOpenAppLauncher());
connect(m_keepOpenCheckbox,
&QCheckBox::clicked,
this,

View File

@@ -19,8 +19,8 @@ PinWidget::PinWidget(const QPixmap& pixmap, QWidget* parent)
setAttribute(Qt::WA_TranslucentBackground);
ConfigHandler conf;
m_baseColor = conf.uiMainColorValue();
m_hoverColor = conf.uiContrastColorValue();
m_baseColor = conf.uiColor();
m_hoverColor = conf.contrastUiColor();
m_layout = new QVBoxLayout(this);
const int margin = this->margin();

View File

@@ -5,7 +5,7 @@ target_sources(
filenamehandler.h
screengrabber.h
systemnotification.h
configshortcuts.h
valuehandler.h
request.h
strfparse.h
)
@@ -16,6 +16,7 @@ target_sources(
screengrabber.cpp
confighandler.cpp
systemnotification.cpp
valuehandler.cpp
screenshotsaver.cpp
dbusutils.cpp
globalvalues.cpp
@@ -24,7 +25,6 @@ target_sources(
pathinfo.cpp
colorutils.cpp
history.cpp
configshortcuts.cpp
strfparse.cpp
request.cpp
)

File diff suppressed because it is too large Load Diff

View File

@@ -9,121 +9,141 @@
#include <QVariant>
#include <QVector>
class ConfigHandler
class QFileSystemWatcher;
class ValueHandler;
template<class T>
class QSharedPointer;
class QTextStream;
/**
* Declare and implement a getter for a config option. `KEY` is the option key
* as it appears in the config file, `TYPE` is the C++ type. At the same time
* `KEY` is the name of the generated getter function.
*/
#define CONFIG_GETTER(KEY, TYPE) \
TYPE KEY() { return value(QStringLiteral(#KEY)).value<TYPE>(); }
/**
* Declare and implement a setter for a config option. `FUNC` is the name of the
* generated function, `KEY` is the option key as it appears in the config file
* and `TYPE` is the C++ type.
*/
#define CONFIG_SETTER(FUNC, KEY, TYPE) \
void FUNC(const TYPE& value) \
{ \
setValue(QStringLiteral(#KEY), QVariant::fromValue(value)); \
}
/**
* Combines the functionality of `CONFIG_GETTER` and `CONFIG_SETTER`. `GETFUNC`
* is simultaneously the name of the getter function and the option key as it
* appears in the config file. `SETFUNC` is the name of the setter function.
* `TYPE` is the C++ type of the value.
*/
#define CONFIG_GETTER_SETTER(GETFUNC, SETFUNC, TYPE) \
CONFIG_GETTER(GETFUNC, TYPE) \
CONFIG_SETTER(SETFUNC, GETFUNC, TYPE)
class ConfigHandler : public QObject
{
Q_OBJECT
public:
explicit ConfigHandler();
explicit ConfigHandler(bool skipInitialErrorCheck = false);
QVector<CaptureToolButton::ButtonType> getButtons();
void setButtons(const QVector<CaptureToolButton::ButtonType>&);
static ConfigHandler* getInstance();
QVector<QColor> getUserColors();
// Definitions of getters and setters for config options
// Some special cases are implemented regularly, without the macro
// NOTE: When adding new options, make sure to add an entry in
// recognizedGeneralOptions in the cpp file.
CONFIG_GETTER_SETTER(userColors, setUserColors, QVector<QColor>);
CONFIG_GETTER_SETTER(savePath, setSavePath, QString)
CONFIG_GETTER_SETTER(savePathFixed, setSavePathFixed, bool)
CONFIG_GETTER_SETTER(uiColor, setUiColor, QColor)
CONFIG_GETTER_SETTER(contrastUiColor, setContrastUiColor, QColor)
CONFIG_GETTER_SETTER(drawColor, setDrawColor, QColor)
CONFIG_GETTER_SETTER(fontFamily, setFontFamily, QString)
CONFIG_GETTER_SETTER(showHelp, setShowHelp, bool)
CONFIG_GETTER_SETTER(showSidePanelButton, setShowSidePanelButton, bool)
CONFIG_GETTER_SETTER(showDesktopNotification,
setShowDesktopNotification,
bool)
CONFIG_GETTER_SETTER(filenamePattern, setFilenamePattern, QString)
CONFIG_GETTER_SETTER(disabledTrayIcon, setDisabledTrayIcon, bool)
CONFIG_GETTER_SETTER(drawThickness, setDrawThickness, int)
CONFIG_GETTER_SETTER(drawFontSize, setDrawFontSize, int)
CONFIG_GETTER_SETTER(keepOpenAppLauncher, setKeepOpenAppLauncher, bool)
CONFIG_GETTER_SETTER(checkForUpdates, setCheckForUpdates, bool)
CONFIG_GETTER_SETTER(showStartupLaunchMessage,
setShowStartupLaunchMessage,
bool)
CONFIG_GETTER_SETTER(contrastOpacity, setContrastOpacity, int)
CONFIG_GETTER_SETTER(copyAndCloseAfterUpload,
setCopyAndCloseAfterUpload,
bool)
CONFIG_GETTER_SETTER(historyConfirmationToDelete,
setHistoryConfirmationToDelete,
bool)
CONFIG_GETTER_SETTER(uploadHistoryMax, setUploadHistoryMax, int)
CONFIG_GETTER_SETTER(saveAfterCopy, setSaveAfterCopy, bool)
CONFIG_GETTER_SETTER(copyPathAfterSave, setCopyPathAfterSave, bool)
CONFIG_GETTER_SETTER(useJpgForClipboard, setUseJpgForClipboard, bool)
CONFIG_GETTER_SETTER(ignoreUpdateToVersion,
setIgnoreUpdateToVersion,
QString)
CONFIG_GETTER_SETTER(undoLimit, setUndoLimit, int)
CONFIG_GETTER_SETTER(buttons,
setButtons,
QList<CaptureToolButton::ButtonType>)
QString savePath();
void setSavePath(const QString&);
bool savePathFixed();
void setSavePathFixed(bool);
QColor uiMainColorValue();
void setUIMainColor(const QColor&);
QColor uiContrastColorValue();
void setUIContrastColor(const QColor&);
QColor drawColorValue();
void setDrawColor(const QColor&);
void setFontFamily(const QString&);
const QString& fontFamily();
bool showHelpValue();
void setShowHelp(const bool);
bool showSidePanelButtonValue();
void setShowSidePanelButton(const bool);
bool desktopNotificationValue();
void setDesktopNotification(const bool);
QString filenamePatternDefault();
QString filenamePatternValue();
void setFilenamePattern(const QString&);
bool disabledTrayIconValue();
void setDisabledTrayIcon(const bool);
int drawThicknessValue();
void setDrawThickness(const int);
int drawFontSizeValue();
void setDrawFontSize(const int);
bool keepOpenAppLauncherValue();
void setKeepOpenAppLauncher(const bool);
bool checkForUpdates();
void setCheckForUpdates(const bool);
bool verifyLaunchFile();
bool startupLaunchValue();
// SPECIAL CASES
bool startupLaunch();
void setStartupLaunch(const bool);
bool showStartupLaunchMessage();
void setShowStartupLaunchMessage(const bool);
int contrastOpacityValue();
void setContrastOpacity(const int);
bool copyAndCloseAfterUploadEnabled();
void setCopyAndCloseAfterUploadEnabled(const bool);
bool historyConfirmationToDelete();
void setHistoryConfirmationToDelete(const bool save);
int uploadHistoryMaxSizeValue();
void setUploadHistoryMaxSize(const int);
bool saveAfterCopyValue();
void setSaveAfterCopy(const bool);
bool copyPathAfterSaveEnabled();
void setCopyPathAfterSaveEnabled(const bool);
bool useJpgForClipboard() const;
void setUseJpgForClipboard(const bool);
void setSaveAsFileExtension(const QString& extension);
QString getSaveAsFileExtension();
void setDefaultSettings();
QString saveAsFileExtension();
CONFIG_SETTER(setSaveAsFileExtension, setSaveAsFileExtension, QString)
void setAllTheButtons();
void setIgnoreUpdateToVersion(const QString& text);
QString ignoreUpdateToVersion();
void setUndoLimit(int value);
int undoLimit();
bool setShortcut(const QString&, const QString&);
const QString& shortcut(const QString&);
// DEFAULTS
QString filenamePatternDefault();
void setDefaultSettings();
QString configFilePath() const;
void setValue(const QString& group,
const QString& key,
const QVariant& value);
QVariant& value(const QString& group, const QString& key);
// GENERIC GETTERS AND SETTERS
bool setShortcut(const QString&, const QString&);
QString shortcut(const QString&);
void setValue(const QString& key, const QVariant& value);
QVariant value(const QString& key) const;
// INFO
const QSet<QString>& recognizedGeneralOptions() const;
const QSet<QString>& recognizedShortcutNames() const;
QSet<QString> keysFromGroup(const QString& group) const;
// ERROR HANDLING
bool checkForErrors(QTextStream* log = nullptr) const;
bool checkUnrecognizedSettings(QTextStream* log = nullptr) const;
bool checkShortcutConflicts(QTextStream* log = nullptr) const;
bool checkSemantics(QTextStream* log = nullptr) const;
void checkAndHandleError() const;
void setErrorState(bool error) const;
bool hasError() const;
QString errorMessage() const;
signals:
void error() const;
void errorResolved() const;
void fileChanged() const;
private:
QString m_strRes;
QVariant m_varRes;
QSettings m_settings;
QVector<QStringList> m_shortcuts;
mutable QSettings m_settings;
bool normalizeButtons(QVector<int>&);
static bool m_hasError, m_errorCheckPending, m_skipNextErrorCheck;
static QSharedPointer<QFileSystemWatcher> m_configWatcher;
QVector<CaptureToolButton::ButtonType> fromIntToButton(
const QVector<int>& l);
QVector<int> fromButtonToInt(
const QVector<CaptureToolButton::ButtonType>& l);
void ensureFileWatched() const;
QSharedPointer<ValueHandler> valueHandler(const QString& key) const;
void assertKeyRecognized(const QString& key) const;
bool isShortcut(const QString& key) const;
QString baseName(QString key) const;
};

View File

@@ -1,26 +0,0 @@
#ifndef CONFIGSHORTCUTS_H
#define CONFIGSHORTCUTS_H
#include "src/widgets/capture/capturetoolbutton.h"
#include <QKeySequence>
#include <QString>
#include <QStringList>
#include <QVector>
class ConfigShortcuts
{
public:
ConfigShortcuts();
const QVector<QStringList>& captureShortcutsDefault(
const QVector<CaptureToolButton::ButtonType>& buttons);
const QKeySequence& captureShortcutDefault(const QString& buttonType);
private:
QVector<QStringList> m_shortcuts;
QKeySequence m_ks;
void addShortcut(const QString& shortcutName, const QString& description);
};
#endif // CONFIGSHORTCUTS_H

View File

@@ -27,7 +27,7 @@ FileNameHandler::FileNameHandler(QObject* parent)
QString FileNameHandler::parsedPattern()
{
return parseFilename(ConfigHandler().filenamePatternValue());
return parseFilename(ConfigHandler().filenamePattern());
}
QString FileNameHandler::parseFilename(const QString& name)

View File

@@ -57,7 +57,7 @@ const QList<QString>& History::history()
QDir::Files,
QDir::Time);
int cnt = 0;
int max = ConfigHandler().uploadHistoryMaxSizeValue();
int max = ConfigHandler().uploadHistoryMax();
m_thumbs.clear();
foreach (QString fileName, images) {
if (++cnt <= max) {

View File

@@ -58,7 +58,7 @@ void ScreenshotSaver::saveToClipboard(const QPixmap& capture)
{
// If we are able to properly save the file, save the file and copy to
// clipboard.
if ((ConfigHandler().saveAfterCopyValue()) &&
if ((ConfigHandler().saveAfterCopy()) &&
(!ConfigHandler().savePath().isEmpty())) {
saveToFilesystem(capture,
ConfigHandler().savePath(),
@@ -126,7 +126,7 @@ QString ScreenshotSaver::ShowSaveFileDialog(QWidget* parent,
mimeTypeList.append(mimeType);
dialog.setMimeTypeFilters(mimeTypeList);
QString suffix = ConfigHandler().getSaveAsFileExtension();
QString suffix = ConfigHandler().saveAsFileExtension();
QString defaultMimeType =
QMimeDatabase().mimeTypeForFile("image" + suffix).name();
dialog.selectMimeTypeFilter(defaultMimeType);
@@ -179,7 +179,7 @@ bool ScreenshotSaver::saveToFilesystemGUI(const QPixmap& capture)
QString msg = QObject::tr("Capture saved as ") + savePath;
if (config.copyPathAfterSaveEnabled()) {
if (config.copyPathAfterSave()) {
msg =
QObject::tr("Capture is saved and copied to the clipboard as ") +
savePath;
@@ -190,7 +190,7 @@ bool ScreenshotSaver::saveToFilesystemGUI(const QPixmap& capture)
Controller::getInstance()->sendCaptureSaved(
m_id, QFileInfo(savePath).canonicalFilePath());
if (config.copyPathAfterSaveEnabled()) {
if (config.copyPathAfterSave()) {
QApplication::clipboard()->setText(savePath);
}

View File

@@ -35,7 +35,7 @@ void SystemNotification::sendMessage(const QString& text,
const QString& savePath,
const int timeout)
{
if (!ConfigHandler().desktopNotificationValue()) {
if (!ConfigHandler().showDesktopNotification()) {
return;
}

413
src/utils/valuehandler.cpp Normal file
View File

@@ -0,0 +1,413 @@
#include "valuehandler.h"
#include "confighandler.h"
#include <QColor>
#include <QFileInfo>
#include <QStandardPaths>
#include <QVariant>
// VALUE HANDLER
QVariant ValueHandler::value(const QVariant& val)
{
if (!val.isValid() || !check(val)) {
return fallback();
} else {
return process(val);
}
}
QVariant ValueHandler::fallback()
{
return QVariant();
}
QVariant ValueHandler::representation(const QVariant& val)
{
return val.toString();
}
QString ValueHandler::expected()
{
return {};
}
QVariant ValueHandler::process(const QVariant& val)
{
return val;
}
// BOOL
Bool::Bool(bool def)
: m_def(def)
{}
bool Bool::check(const QVariant& val)
{
QString str = val.toString();
if (str != "true" && str != "false") {
return false;
}
return true;
}
QVariant Bool::fallback()
{
return m_def;
}
QString Bool::expected()
{
return QStringLiteral("true or false");
}
// STRING
String::String(const QString& def)
: m_def(def)
{}
bool String::check(const QVariant&)
{
return true;
}
QVariant String::fallback()
{
return m_def;
}
QString String::expected()
{
return QStringLiteral("string");
}
// COLOR
Color::Color(const QColor& def)
: m_def(def)
{}
bool Color::check(const QVariant& val)
{
QString str = val.toString();
// Disable #RGB, #RRRGGGBBB and #RRRRGGGGBBBB formats that QColor supports
return QColor::isValidColor(str) &&
(str[0] != '#' ||
(str.length() != 4 && str.length() != 10 && str.length() != 13));
}
QVariant Color::process(const QVariant& val)
{
QString str = val.toString();
QColor color(str);
if (str.length() == 9 && str[0] == '#') {
// Convert #RRGGBBAA (flameshot) to #AARRGGBB (QColor)
int blue = color.blue();
color.setBlue(color.green());
color.setGreen(color.red());
color.setRed(color.alpha());
color.setAlpha(blue);
}
return color;
}
QVariant Color::fallback()
{
return m_def;
}
QVariant Color::representation(const QVariant& val)
{
QString str = val.toString();
QColor color(str);
if (str.length() == 9 && str[0] == '#') {
// Convert #AARRGGBB (QColor) to #RRGGBBAA (flameshot)
int alpha = color.alpha();
color.setAlpha(color.red());
color.setRed(color.green());
color.setGreen(color.blue());
color.setBlue(alpha);
}
return color.name();
}
QString Color::expected()
{
return QStringLiteral("color name or hex value");
}
// BOUNDED INT
BoundedInt::BoundedInt(int min, int max, int def)
: m_min(min)
, m_max(max)
, m_def(def)
{}
bool BoundedInt::check(const QVariant& val)
{
QString str = val.toString();
bool conversionOk;
int num = str.toInt(&conversionOk);
return conversionOk && (m_max < m_min || num <= m_max);
}
QVariant BoundedInt::fallback()
{
return m_def;
}
QString BoundedInt::expected()
{
return QStringLiteral("number between %1 and %2").arg(m_min).arg(m_max);
}
// LOWER BOUNDED INT
LowerBoundedInt::LowerBoundedInt(int min, int def)
: m_min(min)
, m_def(def)
{}
bool LowerBoundedInt::check(const QVariant& val)
{
QString str = val.toString();
bool conversionOk;
int num = str.toInt(&conversionOk);
return conversionOk && num >= m_min;
}
QVariant LowerBoundedInt::fallback()
{
return m_def;
}
QString LowerBoundedInt::expected()
{
return QStringLiteral("number >= %1").arg(m_min);
}
// KEY SEQUENCE
KeySequence::KeySequence(const QKeySequence& fallback)
: m_fallback(fallback)
{}
bool KeySequence::check(const QVariant& val)
{
QString str = val.toString();
if (!str.isEmpty() && QKeySequence(str).toString().isEmpty()) {
return false;
}
return true;
}
QVariant KeySequence::fallback()
{
return m_fallback;
}
QString KeySequence::expected()
{
return QStringLiteral("keyboard shortcut");
}
// EXISTING DIR
bool ExistingDir::check(const QVariant& val)
{
if (!val.canConvert(QVariant::String) || val.toString().isEmpty()) {
return false;
}
QFileInfo info(val.toString());
return info.isDir() && info.exists();
}
QVariant ExistingDir::fallback()
{
using SP = QStandardPaths;
for (auto location :
{ SP::PicturesLocation, SP::HomeLocation, SP::TempLocation }) {
QString path = SP::writableLocation(location);
if (QFileInfo(path).isDir()) {
return path;
}
}
return {};
}
QString ExistingDir::expected()
{
return QStringLiteral("existing directory");
}
// FILENAME PATTERN
bool FilenamePattern::check(const QVariant&)
{
return true;
}
QVariant FilenamePattern::fallback()
{
return ConfigHandler().filenamePatternDefault();
}
QVariant FilenamePattern::process(const QVariant& val)
{
QString str = val.toString();
return !str.isEmpty() ? val : fallback();
}
QString FilenamePattern::expected()
{
return QStringLiteral("please edit using the GUI");
}
// BUTTON LIST
using BType = CaptureToolButton::ButtonType;
using BList = QList<BType>;
bool ButtonList::check(const QVariant& val)
{
using CTB = CaptureToolButton;
auto allButtons = CTB::getIterableButtonTypes();
for (int btn : val.value<QList<int>>()) {
if (!allButtons.contains(static_cast<CTB::ButtonType>(btn))) {
return false;
}
}
return true;
}
// Helper
void sortButtons(BList& buttons)
{
std::sort(buttons.begin(), buttons.end(), [](BType a, BType b) {
return CaptureToolButton::getPriorityByButton(a) <
CaptureToolButton::getPriorityByButton(b);
});
}
QVariant ButtonList::process(const QVariant& val)
{
QList<int> intButtons = val.value<QList<int>>();
auto buttons = ButtonList::fromIntList(intButtons);
sortButtons(buttons);
return QVariant::fromValue(buttons);
}
QVariant ButtonList::fallback()
{
auto buttons = CaptureToolButton::getIterableButtonTypes();
buttons.removeOne(CaptureToolButton::TYPE_SIZEDECREASE);
buttons.removeOne(CaptureToolButton::TYPE_SIZEINCREASE);
sortButtons(buttons);
return QVariant::fromValue(buttons);
}
QVariant ButtonList::representation(const QVariant& val)
{
auto intList = toIntList(val.value<BList>());
normalizeButtons(intList);
return QVariant::fromValue(intList);
}
QString ButtonList::expected()
{
return QStringLiteral("please don't edit by hand");
}
QList<CaptureToolButton::ButtonType> ButtonList::fromIntList(
const QList<int>& l)
{
QList<CaptureToolButton::ButtonType> buttons;
buttons.reserve(l.size());
for (auto const i : l)
buttons << static_cast<CaptureToolButton::ButtonType>(i);
return buttons;
}
QList<int> ButtonList::toIntList(const QList<CaptureToolButton::ButtonType>& l)
{
QList<int> buttons;
buttons.reserve(l.size());
for (auto const i : l)
buttons << static_cast<int>(i);
return buttons;
}
bool ButtonList::normalizeButtons(QList<int>& buttons)
{
QList<int> listTypesInt =
toIntList(CaptureToolButton::getIterableButtonTypes());
bool hasChanged = false;
for (int i = 0; i < buttons.size(); i++) {
if (!listTypesInt.contains(buttons.at(i))) {
buttons.removeAt(i);
hasChanged = true;
}
}
return hasChanged;
}
// USER COLORS
bool UserColors::check(const QVariant& val)
{
if (!val.isValid()) {
return true;
}
if (!val.canConvert(QVariant::StringList)) {
return false;
}
for (const QString& str : val.toStringList()) {
if (!QColor::isValidColor(str) && str != "picker") {
return false;
}
}
return true;
}
QVariant UserColors::process(const QVariant& val)
{
QStringList strColors = val.toStringList();
if (strColors.isEmpty()) {
return fallback();
}
QVector<QColor> colors;
colors.reserve(strColors.size());
for (const QString& str : strColors) {
if (str != "picker") {
colors.append(QColor(str));
} else {
colors.append(QColor());
}
}
return QVariant::fromValue(colors);
}
QVariant UserColors::fallback()
{
return QVariant::fromValue(QVector<QColor>{ Qt::darkRed,
Qt::red,
Qt::yellow,
Qt::green,
Qt::darkGreen,
Qt::cyan,
Qt::blue,
Qt::magenta,
Qt::darkMagenta,
QColor() });
}
QString UserColors::expected()
{
return QStringLiteral("list of colors separated by comma");
}

197
src/utils/valuehandler.h Normal file
View File

@@ -0,0 +1,197 @@
#pragma once
#include "src/widgets/capture/capturetoolbutton.h"
#include <QColor>
#include <QList>
#include <QString>
class QVariant;
/**
* @brief Handles the value of a configuration option (abstract class).
*
* Each configuration option is represented as a `QVariant`. If the option was
* not specified in a config file, the `QVariant` will be invalid.
*
* Each option will usually be handled in three different ways:
* - have its value checked for semantic errors (type, format, etc).
* @see ValueHandler::check
* - have its value (that was taken from the config file) adapted for proper
* use.
* @see ValueHandler::value
* - provided a fallback value in case: the config does not explicitly specify
* it, or the config contains an error and is globally falling back to
* defaults.
* @see ValueHandler::fallback.
* - some options may want to be stored in the config file in a different way
* than the default one provided by `QVariant`.
* @see ValueHandler::representation
*
* @note Please see the documentation of the functions to learn when you should
* override each.
*
*/
class ValueHandler
{
public:
/**
* @brief Check the value semantically.
* @param val The value that was read from the config file
* @return Whether the value is correct
* @note The function should presume that `val.isValid()` is true.
*/
virtual bool check(const QVariant& val) = 0;
/**
* @brief Adapt the value for proper use.
* @param val The value that was read from the config file
* @return The modified value
*
* If the value is invalid (unspecified in the config) or does not pass
* `check`, the fallback will be returned. Otherwise the value is processed
* by `process` and then returned.
*
* @note Cannot be overriden
* @see fallback, process
*/
QVariant value(const QVariant& val);
/**
* @brief Fallback value (default value).
*/
virtual QVariant fallback();
/**
* @brief Return the representaion of the value in the config file.
*
* Override this if you want to write the value in a different format than
* the one provided by `QVariant`.
*/
virtual QVariant representation(const QVariant& val);
/**
* @brief The expected value (descriptive).
* Used when reporting configuration errors.
*/
virtual QString expected();
protected:
/**
* @brief Process a value, presuming it is a valid `QVariant`.
* @param val The value that was read from the config file
* @return The processed value
* @note You will usually want to override this. In rare cases, you may want
* to override `value`.
*/
virtual QVariant process(const QVariant& val);
};
class Bool : public ValueHandler
{
public:
Bool(bool def);
bool check(const QVariant& val) override;
QVariant fallback() override;
QString expected() override;
private:
bool m_def;
};
class String : public ValueHandler
{
public:
String(const QString& def);
bool check(const QVariant&) override;
QVariant fallback() override;
QString expected() override;
private:
QString m_def;
};
class Color : public ValueHandler
{
public:
Color(const QColor& def);
bool check(const QVariant& val) override;
QVariant process(const QVariant& val) override;
QVariant fallback() override;
QVariant representation(const QVariant& val) override;
QString expected() override;
private:
QColor m_def;
};
class BoundedInt : public ValueHandler
{
public:
BoundedInt(int min, int max, int def);
bool check(const QVariant& val) override;
virtual QVariant fallback() override;
QString expected() override;
private:
int m_min, m_max, m_def;
};
class LowerBoundedInt : public ValueHandler
{
public:
LowerBoundedInt(int min, int def);
bool check(const QVariant& val) override;
QVariant fallback() override;
QString expected() override;
private:
int m_min, m_def;
};
class KeySequence : public ValueHandler
{
public:
KeySequence(const QKeySequence& fallback = {});
bool check(const QVariant& val) override;
QVariant fallback() override;
QString expected() override;
private:
QKeySequence m_fallback;
};
class ExistingDir : public ValueHandler
{
bool check(const QVariant& val) override;
QVariant fallback() override;
QString expected() override;
};
class FilenamePattern : public ValueHandler
{
bool check(const QVariant&) override;
QVariant fallback() override;
QVariant process(const QVariant&) override;
QString expected() override;
};
class ButtonList : public ValueHandler
{
public:
bool check(const QVariant& val) override;
QVariant process(const QVariant& val) override;
QVariant fallback() override;
QVariant representation(const QVariant& val) override;
QString expected() override;
// UTILITY FUNCTIONS
static QList<CaptureToolButton::ButtonType> fromIntList(const QList<int>&);
static QList<int> toIntList(const QList<CaptureToolButton::ButtonType>& l);
static bool normalizeButtons(QList<int>& buttons);
};
class UserColors : public ValueHandler
{
bool check(const QVariant& val) override;
QVariant process(const QVariant& val) override;
QVariant fallback() override;
QString expected() override;
};

View File

@@ -72,4 +72,4 @@ void CaptureButton::setColor(const QColor& c)
setStyleSheet(styleSheet());
}
QColor CaptureButton::m_mainColor = ConfigHandler().uiMainColorValue();
QColor CaptureButton::m_mainColor = ConfigHandler().uiColor();

View File

@@ -81,8 +81,7 @@ void CaptureToolButton::updateIcon()
setIconSize(size() * 0.6);
}
QVector<CaptureToolButton::ButtonType>
CaptureToolButton::getIterableButtonTypes()
QList<CaptureToolButton::ButtonType> CaptureToolButton::getIterableButtonTypes()
{
return iterableButtonTypes;
}
@@ -123,7 +122,7 @@ void CaptureToolButton::setColor(const QColor& c)
updateIcon();
}
QColor CaptureToolButton::m_mainColor = ConfigHandler().uiMainColorValue();
QColor CaptureToolButton::m_mainColor = ConfigHandler().uiColor();
static std::map<CaptureToolButton::ButtonType, int> buttonTypeOrder
{
@@ -163,31 +162,30 @@ int CaptureToolButton::getPriorityByButton(CaptureToolButton::ButtonType b)
: it->second;
}
QVector<CaptureToolButton::ButtonType>
CaptureToolButton::iterableButtonTypes = {
CaptureToolButton::TYPE_PENCIL,
CaptureToolButton::TYPE_DRAWER,
CaptureToolButton::TYPE_ARROW,
CaptureToolButton::TYPE_SELECTION,
CaptureToolButton::TYPE_RECTANGLE,
CaptureToolButton::TYPE_CIRCLE,
CaptureToolButton::TYPE_MARKER,
CaptureToolButton::TYPE_TEXT,
CaptureToolButton::TYPE_PIXELATE,
CaptureToolButton::TYPE_INVERT,
CaptureToolButton::TYPE_CIRCLECOUNT,
CaptureToolButton::TYPE_SELECTIONINDICATOR,
CaptureToolButton::TYPE_MOVESELECTION,
CaptureToolButton::TYPE_UNDO,
CaptureToolButton::TYPE_REDO,
CaptureToolButton::TYPE_COPY,
CaptureToolButton::TYPE_SAVE,
CaptureToolButton::TYPE_EXIT,
CaptureToolButton::TYPE_IMAGEUPLOADER,
QList<CaptureToolButton::ButtonType> CaptureToolButton::iterableButtonTypes = {
CaptureToolButton::TYPE_PENCIL,
CaptureToolButton::TYPE_DRAWER,
CaptureToolButton::TYPE_ARROW,
CaptureToolButton::TYPE_SELECTION,
CaptureToolButton::TYPE_RECTANGLE,
CaptureToolButton::TYPE_CIRCLE,
CaptureToolButton::TYPE_MARKER,
CaptureToolButton::TYPE_TEXT,
CaptureToolButton::TYPE_PIXELATE,
CaptureToolButton::TYPE_INVERT,
CaptureToolButton::TYPE_SELECTIONINDICATOR,
CaptureToolButton::TYPE_MOVESELECTION,
CaptureToolButton::TYPE_UNDO,
CaptureToolButton::TYPE_REDO,
CaptureToolButton::TYPE_COPY,
CaptureToolButton::TYPE_SAVE,
CaptureToolButton::TYPE_EXIT,
CaptureToolButton::TYPE_IMAGEUPLOADER,
#if !defined(Q_OS_MACOS)
CaptureToolButton::TYPE_OPEN_APP,
CaptureToolButton::TYPE_OPEN_APP,
#endif
CaptureToolButton::TYPE_PIN,
CaptureToolButton::TYPE_SIZEINCREASE,
CaptureToolButton::TYPE_SIZEDECREASE,
};
CaptureToolButton::TYPE_PIN,
CaptureToolButton::TYPE_CIRCLECOUNT,
CaptureToolButton::TYPE_SIZEINCREASE,
CaptureToolButton::TYPE_SIZEDECREASE,
};

View File

@@ -51,7 +51,7 @@ public:
explicit CaptureToolButton(const ButtonType, QWidget* parent = nullptr);
~CaptureToolButton();
static QVector<CaptureToolButton::ButtonType> getIterableButtonTypes();
static QList<CaptureToolButton::ButtonType> getIterableButtonTypes();
static int getPriorityByButton(CaptureToolButton::ButtonType);
QString name() const;
@@ -64,7 +64,7 @@ public:
protected:
void mousePressEvent(QMouseEvent* e) override;
static QVector<ButtonType> iterableButtonTypes;
static QList<ButtonType> iterableButtonTypes;
CaptureTool* m_tool;

View File

@@ -29,6 +29,8 @@
#include <QApplication>
#include <QDateTime>
#include <QDesktopWidget>
#include <QFontMetrics>
#include <QLabel>
#include <QPaintEvent>
#include <QPainter>
#include <QScreen>
@@ -56,6 +58,8 @@ CaptureWidget::CaptureWidget(uint id,
, m_captureDone(false)
, m_previewEnabled(true)
, m_adjustmentButtonPressed(false)
, m_configError(false)
, m_configErrorResolved(false)
, m_activeButton(nullptr)
, m_activeTool(nullptr)
, m_toolWidget(nullptr)
@@ -85,9 +89,9 @@ CaptureWidget::CaptureWidget(uint id,
this,
&CaptureWidget::childLeave);
setAttribute(Qt::WA_DeleteOnClose);
m_opacity = m_config.contrastOpacityValue();
m_uiColor = m_config.uiMainColorValue();
m_contrastUiColor = m_config.uiContrastColorValue();
m_opacity = m_config.contrastOpacity();
m_uiColor = m_config.uiColor();
m_contrastUiColor = m_config.contrastUiColor();
setMouseTracking(true);
initContext(savePath, fullScreen);
initShortcuts();
@@ -200,10 +204,25 @@ CaptureWidget::CaptureWidget(uint id,
initPanel();
m_config.checkAndHandleError();
if (m_config.hasError()) {
m_configError = true;
}
connect(ConfigHandler::getInstance(), &ConfigHandler::error, this, [=]() {
m_configError = true;
m_configErrorResolved = false;
update();
});
connect(
ConfigHandler::getInstance(), &ConfigHandler::errorResolved, this, [=]() {
m_configError = false;
m_configErrorResolved = true;
update();
});
OverlayMessage::init(this,
QGuiAppCurrentScreen().currentScreen()->geometry());
if (m_config.showHelpValue()) {
if (m_config.showHelp()) {
OverlayMessage::push(
tr("Select an area with the mouse, or press Esc to exit."
"\nPress Enter to capture the screen."
@@ -225,7 +244,7 @@ CaptureWidget::~CaptureWidget()
void CaptureWidget::initButtons()
{
auto allButtonTypes = CaptureToolButton::getIterableButtonTypes();
auto visibleButtonTypes = m_config.getButtons();
auto visibleButtonTypes = m_config.buttons();
QVector<CaptureToolButton*> vectorButtons;
// Add all buttons but hide those that were disabled in the Interface config
@@ -376,6 +395,10 @@ void CaptureWidget::paintEvent(QPaintEvent* paintEvent)
// draw inactive region
drawInactiveRegion(&painter);
if (m_configError || m_configErrorResolved) {
drawConfigErrorMessage(&painter);
}
}
void CaptureWidget::showColorPicker(const QPoint& pos)
@@ -683,8 +706,7 @@ void CaptureWidget::mouseMoveEvent(QMouseEvent* e)
m_buttonHandler->show();
}
}
} else if (m_activeButton && m_activeButton->tool() &&
m_activeButton->tool()->showMousePreview()) {
} else if (m_activeButton && m_activeButton->tool()) {
update();
} else {
if (!m_selection->isVisible()) {
@@ -705,7 +727,7 @@ void CaptureWidget::mouseReleaseEvent(QMouseEvent* e)
}
m_colorPicker->hide();
if (!m_context.color.isValid()) {
m_context.color = ConfigHandler().drawColorValue();
m_context.color = ConfigHandler().drawColor();
m_panel->show();
}
} else if (m_mouseIsClicked) {
@@ -907,11 +929,11 @@ void CaptureWidget::moveEvent(QMoveEvent* e)
void CaptureWidget::initContext(const QString& savePath, bool fullscreen)
{
m_context.color = m_config.drawColorValue();
m_context.color = m_config.drawColor();
m_context.savePath = savePath;
m_context.widgetOffset = mapToGlobal(QPoint(0, 0));
m_context.mousePos = mapFromGlobal(QCursor::pos());
m_context.thickness = m_config.drawThicknessValue();
m_context.thickness = m_config.drawThickness();
m_context.fullscreen = fullscreen;
}
@@ -934,7 +956,7 @@ void CaptureWidget::initPanel()
#endif
}
if (ConfigHandler().showSidePanelButtonValue()) {
if (ConfigHandler().showSidePanelButton()) {
auto* panelToggleButton =
new OrientablePushButton(tr("Tool Settings"), this);
makeChild(panelToggleButton);
@@ -1107,9 +1129,9 @@ void CaptureWidget::loadDrawThickness()
if ((m_activeButton && m_activeButton->tool() &&
m_activeButton->tool()->type() == ToolType::TEXT) ||
(m_activeTool && m_activeTool->type() == ToolType::TEXT)) {
m_context.thickness = m_config.drawFontSizeValue();
m_context.thickness = m_config.drawFontSize();
} else {
m_context.thickness = m_config.drawThicknessValue();
m_context.thickness = m_config.drawThickness();
}
emit m_sidePanel->thicknessChanged(m_context.thickness);
}
@@ -1670,6 +1692,28 @@ QRect CaptureWidget::extendedRect(const QRect& r) const
r.height() * devicePixelRatio);
}
void CaptureWidget::drawConfigErrorMessage(QPainter* painter)
{
QString msg;
if (m_configError) {
msg = ConfigHandler().errorMessage();
} else if (m_configErrorResolved) {
msg = tr("Configuration error resolved. Launch `flameshot "
"gui` again to apply it.");
}
auto textRect = painter->fontMetrics().boundingRect(msg);
int w = textRect.width(), h = textRect.height();
textRect = { size().width() - w, size().height() - h, w + 100, h + 100 };
QScreen* currentScreen = QGuiAppCurrentScreen().currentScreen();
if (!textRect.contains(QCursor::pos(currentScreen))) {
QColor textColor(Qt::white);
painter->setPen(textColor);
painter->drawText(textRect, msg);
}
}
void CaptureWidget::drawInactiveRegion(QPainter* painter)
{
QColor overlayColor(0, 0, 0, m_opacity);

View File

@@ -22,6 +22,7 @@
#include <QUndoStack>
#include <QWidget>
class QLabel;
class QPaintEvent;
class QResizeEvent;
class QMouseEvent;
@@ -131,6 +132,7 @@ private:
QRect extendedSelection() const;
QRect extendedRect(const QRect& r) const;
void drawConfigErrorMessage(QPainter* painter);
void drawInactiveRegion(QPainter* painter);
void drawToolsData(bool updateLayersPanel = true,
bool drawSelection = false);
@@ -161,6 +163,8 @@ private:
bool m_captureDone;
bool m_previewEnabled;
bool m_adjustmentButtonPressed;
bool m_configError;
bool m_configErrorResolved;
UpdateNotificationWidget* m_updateNotificationWidget;
quint64 m_lastMouseWheel;

View File

@@ -11,12 +11,12 @@ ColorPicker::ColorPicker(QWidget* parent)
: QWidget(parent)
{
ConfigHandler config;
m_colorList = config.getUserColors();
m_colorList = config.userColors();
m_colorAreaSize = GlobalValues::buttonBaseSize() * 0.6;
setMouseTracking(true);
// save the color values in member variables for faster access
m_uiColor = config.uiMainColorValue();
m_drawColor = config.drawColorValue();
m_uiColor = config.uiColor();
m_drawColor = config.drawColor();
// extraSize represents the extra space needed for the highlight of the
// selected color.
const int extraSize = 6;

View File

@@ -16,7 +16,7 @@ NotifierBox::NotifierBox(QWidget* parent)
m_timer->setSingleShot(true);
m_timer->setInterval(600);
connect(m_timer, &QTimer::timeout, this, &NotifierBox::hide);
m_bgColor = ConfigHandler().uiMainColorValue();
m_bgColor = ConfigHandler().uiColor();
m_foregroundColor =
(ColorUtils::colorIsDark(m_bgColor) ? Qt::white : Qt::black);
m_bgColor.setAlpha(180);

View File

@@ -66,7 +66,7 @@ void OverlayMessage::paintEvent(QPaintEvent*)
QRectF bRect = boundingRect();
bRect.moveTo(0, 0);
QColor rectColor(ConfigHandler().uiMainColorValue());
QColor rectColor(ConfigHandler().uiColor());
rectColor.setAlpha(180);
QColor textColor(
(ColorUtils::colorIsDark(rectColor) ? Qt::white : Qt::black));