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

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