Files
sqlitebrowser/src/Settings.cpp
mgrojo 2a830e5a3a Update QDarkStyleSheet to v3.0.rc and add new light style
Thanks to a new light style provided by QDarkStyleSheet in v3.0.rc
(9eea545) we can add a new light style option.

`qdarkstyle/dark/style.qrc` had to be renamed to
`qdarkstyle/dark/darkstyle.qrc` and `qdarkstyle/light/style.qrc` to
`qdarkstyle/light/lightstyle.qrc` in order to include both as resources.

See issues:
- https://github.com/ColinDuquesnoy/QDarkStyleSheet/issues/240
- https://github.com/ColinDuquesnoy/QDarkStyleSheet/issues/273
- #2558
2021-03-30 23:54:55 +02:00

649 lines
20 KiB
C++

#include "Settings.h"
#include <QApplication>
#include <QDebug>
#include <QDir>
#include <QSettings>
#include <QColor>
#include <QFontInfo>
#include <QLocale>
#include <QStandardPaths>
#include <QPalette>
QString Settings::userSettingsFile;
QSettings* Settings::settings;
std::unordered_map<std::string, QVariant> Settings::m_hCache;
int Settings::m_defaultFontSize;
static bool ends_with(const std::string& str, const std::string& with)
{
return str.rfind(with) == str.size() - with.size();
}
void Settings::setUserSettingsFile(const QString& userSettingsFileArg)
{
userSettingsFile = userSettingsFileArg;
}
bool Settings::isVaildSettingsFile(const QString& userSettingsFile)
{
/*
Variable that stores whether or not the settings file requested by the user is a normal settings file
If the file does not exist and is newly created, the if statement below is not executed, so the default value is set to true
*/
bool isNormalUserSettingsFile = true;
// Code that verifies that the settings file requested by the user is a normal settings file
if(userSettingsFile != nullptr)
{
QFile *file = new QFile;
file->setFileName(userSettingsFile);
if(file->open(QIODevice::ReadOnly))
{
if(file->exists() &&
QString::compare(QString::fromStdString("[%General]\n"), file->readLine(), Qt::CaseInsensitive) != 0)
isNormalUserSettingsFile = false;
}
file->close();
}
return isNormalUserSettingsFile;
}
void Settings::setSettingsObject()
{
// If an object has already been created, it is terminated to reduce overhead
if(settings)
return;
const bool isNormalUserSettingsFile = isVaildSettingsFile(userSettingsFile);
if(userSettingsFile == nullptr)
{
settings = new QSettings(QCoreApplication::organizationName(), QCoreApplication::organizationName());
} else {
if(isNormalUserSettingsFile)
{
settings = new QSettings(userSettingsFile, QSettings::IniFormat);
// Code to verify that the user does not have access to the requested settings file
if(settings->status() == QSettings::AccessError) {
qWarning() << qPrintable("The given settings file can NOT access. Please check the permission for the file.");
qWarning() << qPrintable("So, the -S/--settings option is ignored.");
// Since you do not have permission to the file, delete the existing assignment and assign the standard
delete settings;
settings = new QSettings(QCoreApplication::organizationName(), QCoreApplication::organizationName());
}
} else {
qWarning() << qPrintable("The given settings file is not a normal settings file. Please check again.");
qWarning() << qPrintable("So, the -S/--settings option is ignored.");
settings = new QSettings(QCoreApplication::organizationName(), QCoreApplication::organizationName());
}
}
}
QVariant Settings::getValue(const std::string& group, const std::string& name)
{
// Have a look in the cache first
auto cacheIndex = m_hCache.find(group + name);
if(cacheIndex != m_hCache.end())
{
return cacheIndex->second;
} else {
// Nothing found in the cache, so get the value from the settings file or get the default value if there is no value set yet
setSettingsObject();
QVariant value = settings->value(QString::fromStdString(group + "/" + name), getDefaultValue(group, name));
// Store this value in the cache for further usage and return it afterwards
m_hCache.insert({group + name, value});
return value;
}
}
void Settings::setValue(const std::string& group, const std::string& name, const QVariant& value, bool save_to_disk)
{
// Sometime the value has to be saved for the current session only but get discarded when the application exits.
// In order to achieve this this flag can be set which disables the save to disk mechanism and only leaves the save to cache part active.
if(save_to_disk)
{
setSettingsObject();
// Set the group and save the given value
settings->beginGroup(QString::fromStdString(group));
settings->setValue(QString::fromStdString(name), value);
settings->endGroup();
}
// Also change it in the cache
m_hCache[group + name] = value;
}
QVariant Settings::getDefaultValue(const std::string& group, const std::string& name)
{
// db/defaultencoding?
if(group == "db" && name == "defaultencoding")
return "UTF-8";
// db/savedefaultlocation?
if(group == "db" && name == "savedefaultlocation")
return 2;
// db/defaultlocation?
if(group == "db" && name == "defaultlocation")
return QDir::homePath();
// db/lastlocation?
if(group == "db" && name == "lastlocation")
return getValue("db", "defaultlocation");
// db/hideschemalinebreaks?
if(group == "db" && name == "hideschemalinebreaks")
return true;
// db/foreignkeys?
if(group == "db" && name == "foreignkeys")
return true;
// db/prefetchsize?
if(group == "db" && name == "prefetchsize")
return 50000U;
// db/defaultsqltext?
if(group == "db" && name == "defaultsqltext")
return QString();
// db/fontsize?
if(group == "db" && name == "fontsize")
return 10;
// exportcsv/firstrowheader?
if(group == "exportcsv" && name == "firstrowheader")
return true;
// exportcsv/separator?
if(group == "exportcsv" && name == "separator")
return ',';
// exportcsv/quotecharacter?
if(group == "exportcsv" && name == "quotecharacter")
return '"';
// importcsv group?
if(group == "importcsv")
{
if(name == "firstrowheader")
return false;
if(name == "trimfields")
return true;
if(name == "separatetables")
return false;
if(name == "separator")
return ',';
if(name == "quotecharacter")
return '"';
if(name == "encoding")
return "UTF-8";
if(name == "localconventions")
return false;
}
// exportsql group?
if(group == "exportsql")
{
if(name == "insertcolnames" || name == "insertmultiple")
return false;
if(name == "oldschema")
return 0;
}
// newline character
if (group == "exportcsv" && name == "newlinecharacters")
#ifdef Q_OS_WIN
return "\r\n";
#else
return "\n";
#endif
// exportjson/prettyprint?
if(group == "exportjson" && name == "prettyprint")
return true;
// MainWindow/geometry?
if(group == "MainWindow" && name == "geometry")
return QString();
// MainWindow/windowState?
if(group == "MainWindow" && name == "windowState")
return QString();
// MainWindow/openTabs?
if(group == "MainWindow" && name == "openTabs")
return QString();
// SQLLogDock/Log?
if(group == "SQLLogDock" && name == "Log")
return "Application";
// General/recentFileList?
if(group == "General" && name == "recentFileList")
return QStringList();
// General/maxRecentFiles?
if(group == "General" && name == "maxRecentFiles")
return 5;
// General/language?
if(group == "General" && name == "language")
return QLocale::system().name();
// General/appStyle
if(group == "General" && name == "appStyle")
return static_cast<int>(FollowDesktopStyle);
// General/toolbarStyle
if(group == "General" && name == "toolbarStyle")
return static_cast<int>(Qt::ToolButtonTextBesideIcon);
// General/toolbarStyleStructure
if(group == "General" && name == "toolbarStyleStructure")
return static_cast<int>(Qt::ToolButtonTextBesideIcon);
// General/toolbarStyleBrowse
if(group == "General" && name == "toolbarStyleBrowse")
return static_cast<int>(Qt::ToolButtonIconOnly);
// General/toolbarStyleSql
if(group == "General" && name == "toolbarStyleSql")
return static_cast<int>(Qt::ToolButtonIconOnly);
// General/toolbarStyleEditCell
if(group == "General" && name == "toolbarStyleEditCell")
return static_cast<int>(Qt::ToolButtonIconOnly);
if(group == "General" && name == "DBFileExtensions")
return QObject::tr("SQLite database files (*.db *.sqlite *.sqlite3 *.db3)");
// General/fontsize
if(group == "General" && name == "fontsize")
return m_defaultFontSize;
// General/promptsqltabsinnewproject
if(group == "General" && name == "promptsqltabsinnewproject")
return true;
// checkversion group?
if(group == "checkversion")
{
if(name == "enabled")
return true;
if(name == "ignmajor")
return 999;
if(name == "ignminor" || name == "ignpatch")
return 0;
}
// Data Browser/NULL Fields
if(group == "databrowser")
{
if(name == "font")
return QFont().defaultFamily();
if(name == "fontsize")
return 10;
if(name == "symbol_limit")
return 5000;
if(name == "complete_threshold")
return 1000;
if(name == "image_preview")
return false;
if(name == "indent_compact")
return false;
if(name == "auto_switch_mode")
return true;
if(name == "editor_word_wrap")
return true;
if(name == "null_text")
return "NULL";
if(name == "blob_text")
return "BLOB";
if(name == "filter_escape")
return "\\";
if(name == "filter_delay")
return 200;
if(ends_with(name, "colour"))
return getDefaultColorValue(group, name, FollowDesktopStyle);
}
// syntaxhighlighter?
if(group == "syntaxhighlighter")
{
// Bold? Only tables, functions and keywords are bold by default
if(ends_with(name, "bold"))
return name == "keyword_bold" || name == "table_bold" || name == "function_bold";
// Italic? Nothing by default
if(ends_with(name, "italic"))
return false;
// Underline? Nothing by default
if(ends_with(name, "underline"))
return false;
// Colour?
if(ends_with(name, "colour"))
return getDefaultColorValue(group, name, FollowDesktopStyle);
}
// editor/font?
if(group == "editor" && name == "font")
{
QFont font("Monospace");
font.setStyleHint(QFont::TypeWriter);
return QFontInfo(font).family();
}
// editor/fontsize or log/fontsize?
if((group == "editor" || group == "log") && name == "fontsize")
#ifdef Q_OS_MAC
// Use 12 pt size as the default on macOS
return 12;
#else
return 9;
#endif
if(group == "editor")
{
if(name == "tabsize")
{
return 4;
}
}
// editor/wrap_lines
if(group == "editor" && name == "wrap_lines")
return 0; // QsciScintilla::WrapNone
// editor/identifier_quotes
if(group == "editor" && name == "identifier_quotes")
return 0; // sqlb::DoubleQuotes
// editor/auto_completion?
if(group == "editor" && name == "auto_completion")
return true;
// editor/upper_keywords?
if(group == "editor" && name == "upper_keywords")
return true;
// editor/error_indicators?
if(group == "editor" && name == "error_indicators")
return true;
// editor/horizontal_tiling?
if(group == "editor" && name == "horizontal_tiling")
return false;
// editor/splitter1_sizes?
if(group == "editor" && name == "splitter1_sizes")
return QVariant();
// editor/splitter2_sizes?
if(group == "editor" && name == "splitter2_sizes")
return QVariant();
// editor/close_button_on_tabs?
if(group == "editor" && name == "close_button_on_tabs")
return true;
// extensions/list?
if(group == "extensions" && name == "list")
return QStringList();
// extensions/disableregex?
if(group == "extension" && name == "disableregex")
return false;
// extensions/enable_load_extension?
if(group == "extension" && name == "enable_load_extension")
return false;
// PlotDock/lineType or pointShape?
if(group == "PlotDock")
{
// QCPGraph::lsLine
if(name == "lineType")
return 1;
// QCPScatterStyle::ssDisk
if(name == "pointShape")
return 4;
}
// SchemaDock Drag & drop settings
if(group == "SchemaDock")
{
if(name == "dropQualifiedNames")
return false;
if(name == "dropEnquotedNames")
return true;
}
// Remote settings?
if(group == "remote")
{
// Enable the File → Remote menu by default
if(name == "active")
return true;
// Clone directory
if(name == "clonedirectory")
#if QT_VERSION >= QT_VERSION_CHECK(5, 4, 0)
return QStandardPaths::writableLocation(QStandardPaths::AppDataLocation);
#else
return QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation);
#endif
}
// Proxy settings
if(group == "proxy")
{
// Use system settings by default
if(name == "type")
return "system";
}
// Unknown combination of group and name? Return an invalid QVariant!
return QVariant();
}
QColor Settings::getDefaultColorValue(const std::string& group, const std::string& name, AppStyle style)
{
// Data Browser/NULL & Binary Fields
if(group == "databrowser")
{
switch (style) {
case FollowDesktopStyle :
if(name == "null_fg_colour")
return QColor(Qt::lightGray).name();
if(name == "null_bg_colour")
return QPalette().color(QPalette::Active, QPalette::Base).name();
if(name == "reg_fg_colour")
return QPalette().color(QPalette::Active, QPalette::Text).name();
if(name == "reg_bg_colour")
return QPalette().color(QPalette::Active, QPalette::Base).name();
if(name == "bin_fg_colour")
return QColor(Qt::lightGray).name();
if(name == "bin_bg_colour")
return QPalette().color(QPalette::Active, QPalette::Base).name();
break;
case DarkStyle :
if(name == "null_fg_colour")
return QColor(0x78, 0x78, 0x78);
if(name == "null_bg_colour")
return QColor(0x19, 0x23, 0x2D);
if(name == "reg_fg_colour")
return QColor(0xF0, 0xF0, 0xF0);
if(name == "reg_bg_colour")
return QColor(0x19, 0x23, 0x2D);
if(name == "bin_fg_colour")
return QColor(0x78, 0x78, 0x78);
if(name == "bin_bg_colour")
return QColor(0x19, 0x23, 0x2D);
break;
case LightStyle :
if(name == "null_fg_colour" || name == "bin_fg_colour")
return QColor("#A5A9AC");
if(name == "null_bg_colour" || name == "bin_bg_colour")
return QColor("#FAFAFA");
if(name == "reg_fg_colour")
return QColor("#000000");
if(name == "reg_bg_colour")
return QColor("#FAFAFA");
break;
}
}
// syntaxhighlighter?
if(group == "syntaxhighlighter")
{
// Colour?
if(ends_with(name, "colour"))
{
QColor backgroundColour;
QColor foregroundColour;
switch (style) {
case FollowDesktopStyle :
backgroundColour = QPalette().color(QPalette::Active, QPalette::Base);
foregroundColour = QPalette().color(QPalette::Active, QPalette::Text);
break;
case DarkStyle :
foregroundColour = QColor(0xF0, 0xF0, 0xF0);
backgroundColour = QColor(0x19, 0x23, 0x2D);
break;
case LightStyle :
foregroundColour = QColor("#000000");
backgroundColour = QColor("#FAFAFA");
break;
}
if(name == "foreground_colour")
return foregroundColour;
else if(name == "background_colour")
return backgroundColour;
else if(name == "selected_fg_colour")
return QPalette().color(QPalette::Active, QPalette::HighlightedText);
else if(name == "selected_bg_colour")
return QPalette().color(QPalette::Active, QPalette::Highlight);
// Detect and provide sensible defaults for dark themes
if (backgroundColour.value() < foregroundColour.value()) {
if(name == "keyword_colour")
return QColor(82, 148, 226);
else if(name == "function_colour")
return QColor(Qt::yellow);
else if(name == "table_colour")
return QColor(Qt::cyan);
else if(name == "comment_colour")
return QColor(Qt::green);
else if(name == "identifier_colour")
return QColor(221, 160, 221);
else if(name == "string_colour")
return QColor(Qt::lightGray);
else if(name == "currentline_colour")
return backgroundColour.lighter(150);
else if(name == "highlight_colour")
return QColor(79, 148, 205);
} else {
if(name == "keyword_colour")
return QColor(Qt::darkBlue);
else if(name == "function_colour")
return QColor(Qt::blue);
else if(name == "table_colour")
return QColor(Qt::darkCyan);
else if(name == "comment_colour")
return QColor(Qt::darkGreen);
else if(name == "identifier_colour")
return QColor(Qt::darkMagenta);
else if(name == "string_colour")
return QColor(Qt::red);
else if(name == "currentline_colour")
return QColor(236, 236, 245);
else if(name == "highlight_colour")
return QColor(Qt::cyan);
}
}
}
// Unknown combination of group and name? Return an invalid QColor!
return QColor();
}
void Settings::clearValue(const std::string& group, const std::string& name)
{
setSettingsObject();
settings->beginGroup(QString::fromStdString(group));
settings->remove(QString::fromStdString(name));
settings->endGroup();
m_hCache.clear();
}
void Settings::restoreDefaults ()
{
setSettingsObject();
settings->clear();
m_hCache.clear();
}
void Settings::exportSettings(const QString& fileName)
{
QSettings* exportSettings = new QSettings(fileName, QSettings::IniFormat);
const QStringList groups = settings->childGroups();
for(const QString& currentGroup : groups)
{
settings->beginGroup(currentGroup);
const QStringList keys = settings->childKeys();
for(const QString& currentKey : keys)
{
exportSettings->beginGroup(currentGroup);
exportSettings->setValue(currentKey, getValue((currentGroup.toStdString()), (currentKey.toStdString())));
exportSettings->endGroup();
}
settings->endGroup();
}
}
bool Settings::importSettings(const QString& fileName)
{
if(!isVaildSettingsFile(fileName))
return false;
QSettings* importSettings = new QSettings(fileName, QSettings::IniFormat);
const QStringList groups = importSettings->childGroups();
for(const QString& currentGroup : groups)
{
importSettings->beginGroup(currentGroup);
const QStringList keys = importSettings->childKeys();
for(const QString& currentKey : keys)
{
settings->beginGroup(currentGroup);
settings->setValue(currentKey, importSettings->value(currentKey));
settings->endGroup();
}
importSettings->endGroup();
}
m_hCache.clear();
return true;
}
void Settings::sync()
{
settings->sync();
}