rssguard/src/miscellaneous/settings.cpp
Martin Rotter c97e052a1f Fixed #77.
2017-02-16 13:04:33 +01:00

396 lines
16 KiB
C++
Executable File

// This file is part of RSS Guard.
//
// Copyright (C) 2011-2016 by Martin Rotter <rotter.martinos@gmail.com>
//
// RSS Guard is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// RSS Guard is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with RSS Guard. If not, see <http://www.gnu.org/licenses/>.
#include "miscellaneous/settings.h"
#include "miscellaneous/application.h"
#include "miscellaneous/iofactory.h"
#include <QDebug>
#include <QDir>
#include <QPointer>
#include <QLocale>
// Feeds.
DKEY Feeds::ID = "feeds";
DKEY Feeds::UpdateTimeout = "feed_update_timeout";
DVALUE(int) Feeds::UpdateTimeoutDef = DOWNLOAD_TIMEOUT;
DKEY Feeds::CountFormat = "count_format";
DVALUE(char*) Feeds::CountFormatDef = "(%unread)";
DKEY Feeds::AutoUpdateInterval = "auto_update_interval";
DVALUE(int) Feeds::AutoUpdateIntervalDef = DEFAULT_AUTO_UPDATE_INTERVAL;
DKEY Feeds::AutoUpdateEnabled = "auto_update_enabled";
DVALUE(bool) Feeds::AutoUpdateEnabledDef = false;
DKEY Feeds::FeedsUpdateOnStartup = "feeds_update_on_startup";
DVALUE(bool) Feeds::FeedsUpdateOnStartupDef = false;
DKEY Feeds::ShowOnlyUnreadFeeds = "show_only_unread_feeds";
DVALUE(bool) Feeds::ShowOnlyUnreadFeedsDef = false;
// Messages.
DKEY Messages::ID = "messages";
DKEY Messages::MessageHeadImageHeight = "message_head_image_height";
DVALUE(int) Messages::MessageHeadImageHeightDef = 36;
DKEY Messages::UseCustomDate = "use_custom_date";
DVALUE(bool) Messages::UseCustomDateDef = false;
DKEY Messages::CustomDateFormat = "custom_date_format";
DVALUE(char*) Messages::CustomDateFormatDef = "";
DKEY Messages::ClearReadOnExit = "clear_read_on_exit";
DVALUE(bool) Messages::ClearReadOnExitDef = false;
DKEY Messages::KeepCursorInCenter = "keep_cursor_center";
DVALUE(bool) Messages::KeepCursorInCenterDef = false;
DKEY Messages::PreviewerFontStandard = "previewer_font_standard";
NON_CONST_DVALUE(QString) Messages::PreviewerFontStandardDef = QFont(QFont().family(), 12).toString();
// GUI.
DKEY GUI::ID = "gui";
DKEY GUI::SplitterFeeds = "splitter_feeds";
DVALUE(char*) GUI::SplitterFeedsDef = "";
DKEY GUI::SplitterMessages = "splitter_messages";
DVALUE(char*) GUI::SplitterMessagesDef = "";
DKEY GUI::ToolbarStyle = "toolbar_style";
DVALUE(Qt::ToolButtonStyle) GUI::ToolbarStyleDef = Qt::ToolButtonIconOnly;
DKEY GUI::FeedsToolbarActions = "feeds_toolbar";
DVALUE(char*) GUI::FeedsToolbarActionsDef = "m_actionUpdateAllItems,m_actionStopRunningItemsUpdate,m_actionMarkAllItemsRead";
DKEY GUI::StatusbarActions = "status_bar";
DVALUE(char*) GUI::StatusbarActionsDef = "m_lblProgressFeedsAction,m_barProgressFeedsAction,m_actionUpdateAllItems,m_actionUpdateSelectedItems,m_actionStopRunningItemsUpdate,m_actionFullscreen,m_actionQuit";
DKEY GUI::MainWindowInitialSize = "window_size";
DKEY GUI::MainWindowInitialPosition = "window_position";
DKEY GUI::IsMainWindowMaximizedBeforeFullscreen = "is_window_maximized_before_fullscreen";
DVALUE(bool) GUI::IsMainWindowMaximizedBeforeFullscreenDef = false;
DKEY GUI::MainWindowStartsFullscreen = "start_in_fullscreen";
DVALUE(bool) GUI::MainWindowStartsFullscreenDef = false;
DKEY GUI::MainWindowStartsHidden = "start_hidden";
DVALUE(bool) GUI::MainWindowStartsHiddenDef = false;
DKEY GUI::MainWindowStartsMaximized = "window_is_maximized";
DVALUE(bool) GUI::MainWindowStartsMaximizedDef = false;
DKEY GUI::MainMenuVisible = "main_menu_visible";
DVALUE(bool) GUI::MainMenuVisibleDef = false;
DKEY GUI::ToolbarsVisible = "enable_toolbars";
DVALUE(bool) GUI::ToolbarsVisibleDef = true;
DKEY GUI::ListHeadersVisible = "enable_list_headers";
DVALUE(bool) GUI::ListHeadersVisibleDef = true;
DKEY GUI::StatusBarVisible = "enable_status_bar";
DVALUE(bool) GUI::StatusBarVisibleDef = true;
DKEY GUI::HideMainWindowWhenMinimized = "hide_when_minimized";
DVALUE(bool) GUI::HideMainWindowWhenMinimizedDef = false;
DKEY GUI::UseTrayIcon = "use_tray_icon";
DVALUE(bool) GUI::UseTrayIconDef = true;
DKEY GUI::EnableNotifications = "enable_notifications";
DVALUE(bool) GUI::EnableNotificationsDef = true;
DKEY GUI::TabCloseMiddleClick = "tab_close_mid_button";
DVALUE(bool) GUI::TabCloseMiddleClickDef = true;
DKEY GUI::TabCloseDoubleClick = "tab_close_double_button";
DVALUE(bool) GUI::TabCloseDoubleClickDef = true;
DKEY GUI::TabNewDoubleClick = "tab_new_double_button";
DVALUE(bool) GUI::TabNewDoubleClickDef = true;
DKEY GUI::HideTabBarIfOnlyOneTab = "hide_tabbar_one_tab";
DVALUE(bool) GUI::HideTabBarIfOnlyOneTabDef = false;
DKEY GUI::MessagesToolbarDefaultButtons = "messages_toolbar";
DVALUE(char*) GUI::MessagesToolbarDefaultButtonsDef = "m_actionMarkSelectedMessagesAsRead,m_actionMarkSelectedMessagesAsUnread,m_actionSwitchImportanceOfSelectedMessages,separator,highlighter,spacer,search";
DKEY GUI::DefaultSortColumnMessages = "default_sort_column_messages";
DVALUE(int) GUI::DefaultSortColumnMessagesDef = MSG_DB_DCREATED_INDEX;
DKEY GUI::DefaultSortOrderMessages = "default_sort_order_messages";
DVALUE(Qt::SortOrder) GUI::DefaultSortOrderMessagesDef = Qt::DescendingOrder;
DKEY GUI::DefaultSortColumnFeeds = "default_sort_column_feeds";
DVALUE(int) GUI::DefaultSortColumnFeedsDef = FDS_MODEL_TITLE_INDEX;
DKEY GUI::DefaultSortOrderFeeds = "default_sort_order_feeds";
DVALUE(Qt::SortOrder) GUI::DefaultSortOrderFeedsDef = Qt::AscendingOrder;
DKEY GUI::IconTheme = "icon_theme_name";
DVALUE(char*) GUI::IconThemeDef = APP_THEME_DEFAULT;
DKEY GUI::Skin = "skin";
DVALUE(char*) GUI::SkinDef = APP_SKIN_DEFAULT;
DKEY GUI::Style = "style";
DVALUE(char*) GUI::StyleDef = APP_STYLE_DEFAULT;
// General.
DKEY General::ID = "main";
DKEY General::UpdateOnStartup = "update_on_start";
DVALUE(bool) General::UpdateOnStartupDef = true;
DKEY General::RemoveTrolltechJunk = "remove_trolltech_junk";
DVALUE(bool) General::RemoveTrolltechJunkDef = false;
DKEY General::FirstRun = "first_run";
DVALUE(bool) General::FirstRunDef = true;
DKEY General::Language = "language";
DVALUE(QString) General::LanguageDef = QLocale::system().name();
// Downloads.
DKEY Downloads::ID = "download_manager";
DKEY Downloads::AlwaysPromptForFilename = "prompt_for_filename";
DVALUE(bool) Downloads::AlwaysPromptForFilenameDef = false;
DKEY Downloads::TargetDirectory = "target_directory";
DVALUE(QString) Downloads::TargetDirectoryDef = IOFactory::getSystemFolder(QStandardPaths::DesktopLocation);
DKEY Downloads::RemovePolicy = "remove_policy";
DVALUE(int) Downloads::RemovePolicyDef = DownloadManager::Never;
DKEY Downloads::TargetExplicitDirectory = "target_explicit_directory";
DVALUE(QString) Downloads::TargetExplicitDirectoryDef = IOFactory::getSystemFolder(QStandardPaths::DesktopLocation);
DKEY Downloads::ShowDownloadsWhenNewDownloadStarts = "show_downloads_on_new_download_start";
DVALUE(bool) Downloads::ShowDownloadsWhenNewDownloadStartsDef = true;
DKEY Downloads::ItemUrl = "download_%1_url";
DKEY Downloads::ItemLocation = "download_%1_location";
DKEY Downloads::ItemDone = "download_%1_done";
// Proxy.
DKEY Proxy::ID = "proxy";
DKEY Proxy::Type = "proxy_type";
DVALUE(QNetworkProxy::ProxyType) Proxy::TypeDef = QNetworkProxy::NoProxy;
DKEY Proxy::Host = "host";
DVALUE(QString) Proxy::HostDef = QString();
DKEY Proxy::Username = "username";
DVALUE(QString) Proxy::UsernameDef = QString();
DKEY Proxy::Password = "password";
DVALUE(QString) Proxy::PasswordDef = QString();
DKEY Proxy::Port = "port";
DVALUE(int) Proxy::PortDef = 80;
// Database.
DKEY Database::ID = "database";
DKEY Database::UseTransactions = "use_transactions";
DVALUE(bool) Database::UseTransactionsDef = false;
DKEY Database::UseInMemory = "use_in_memory_db";
DVALUE(bool) Database::UseInMemoryDef = false;
DKEY Database::MySQLHostname = "mysql_hostname";
DVALUE(QString) Database::MySQLHostnameDef = QString();
DKEY Database::MySQLUsername = "mysql_username";
DVALUE(QString) Database::MySQLUsernameDef = QString();
DKEY Database::MySQLPassword = "mysql_password";
DVALUE(QString) Database::MySQLPasswordDef = QString();
DKEY Database::MySQLDatabase = "mysql_database";
DVALUE(char*) Database::MySQLDatabaseDef = APP_LOW_NAME;
DKEY Database::MySQLPort = "mysql_port";
DVALUE(int) Database::MySQLPortDef = APP_DB_MYSQL_PORT;
DKEY Database::ActiveDriver = "database_driver";
DVALUE(char*) Database::ActiveDriverDef = APP_DB_SQLITE_DRIVER;
// Keyboard.
DKEY Keyboard::ID = "keyboard";
// Web browser.
DKEY Browser::ID = "browser";
DKEY Browser::CustomExternalBrowserEnabled = "custom_external_browser";
DVALUE(bool) Browser::CustomExternalBrowserEnabledDef = false;
DKEY Browser::CustomExternalBrowserExecutable = "external_browser_executable";
DVALUE(QString) Browser::CustomExternalBrowserExecutableDef = QString();
DKEY Browser::CustomExternalBrowserArguments = "external_browser_arguments";
DVALUE(char*) Browser::CustomExternalBrowserArgumentsDef = "%1";
DKEY Browser::CustomExternalEmailEnabled = "custom_external_email";
DVALUE(bool) Browser::CustomExternalEmailEnabledDef = false;
DKEY Browser::CustomExternalEmailExecutable = "external_email_executable";
DVALUE(QString) Browser::CustomExternalEmailExecutableDef = QString();
DKEY Browser::CustomExternalEmailArguments = "external_email_arguments";
DVALUE(char*) Browser::CustomExternalEmailArgumentsDef = "";
// Categories.
DKEY CategoriesExpandStates::ID = "categories_expand_states";
Settings::Settings(const QString &file_name, Format format, const SettingsProperties::SettingsType &status, QObject *parent)
: QSettings(file_name, format, parent), m_initializationStatus(status) {
}
Settings::~Settings() {
}
QString Settings::userSettingsRootFolder() const {
if (qApp->settings()->type() == SettingsProperties::Portable) {
return getAppPathUserFolder();
}
else {
return getHomeUserFolder();
}
}
QString Settings::pathName() const {
return QFileInfo(fileName()).absolutePath();
}
QSettings::Status Settings::checkSettings() {
qDebug("Syncing settings.");
sync();
return status();
}
bool Settings::initiateRestoration(const QString &settings_backup_file_path) {
return IOFactory::copyFile(settings_backup_file_path,
QFileInfo(fileName()).absolutePath() + QDir::separator() +
BACKUP_NAME_SETTINGS + BACKUP_SUFFIX_SETTINGS);
}
void Settings::finishRestoration(const QString &desired_settings_file_path) {
const QString backup_settings_file = QFileInfo(desired_settings_file_path).absolutePath() + QDir::separator() +
BACKUP_NAME_SETTINGS + BACKUP_SUFFIX_SETTINGS;
if (QFile::exists(backup_settings_file)) {
qWarning("Backup settings file '%s' was detected. Restoring it.", qPrintable(QDir::toNativeSeparators(backup_settings_file)));
if (IOFactory::copyFile(backup_settings_file, desired_settings_file_path)) {
QFile::remove(backup_settings_file);
qDebug("Settings file was restored successully.");
}
else {
qCritical("Settings file was NOT restored due to error when copying the file.");
}
}
}
QString Settings::getAppPathUserFolder() {
return qApp->applicationDirPath() + QDir::separator() + QSL("data");
}
QString Settings::getHomeUserFolder() {
#if defined(Q_OS_LINUX)
QString home_folder = qApp->homeFolderPath() + QDir::separator() + QString(APP_LOW_H_NAME) + QDir::separator() + QSL("data");
if (QDir().exists(home_folder)) {
return home_folder;
}
else {
return qApp->getXdgConfigHomePath() + QDir::separator() + QString(APP_LOW_NAME);
}
#else
return qApp->homeFolderPath() + QDir::separator() + QString(APP_LOW_H_NAME) + QDir::separator() + QSL("data");
#endif
}
Settings *Settings::setupSettings(QObject *parent) {
Settings *new_settings;
// If settings file exists (and is writable) in executable file working directory
// (in subdirectory APP_CFG_PATH), then use it (portable settings).
// Otherwise use settings file stored in home path.
const SettingsProperties properties = determineProperties();
finishRestoration(properties.m_absoluteSettingsFileName);
// Portable settings are available, use them.
new_settings = new Settings(properties.m_absoluteSettingsFileName, QSettings::IniFormat, properties.m_type, parent);
// Check if portable settings are available.
if (properties.m_type == SettingsProperties::Portable) {
qDebug("Initializing settings in '%s' (portable way).", qPrintable(QDir::toNativeSeparators(properties.m_absoluteSettingsFileName)));
}
else {
qDebug("Initializing settings in '%s' (non-portable way).", qPrintable(QDir::toNativeSeparators(properties.m_absoluteSettingsFileName)));
}
return new_settings;
}
SettingsProperties Settings::determineProperties() {
SettingsProperties properties;
properties.m_settingsSuffix = QDir::separator() + QString(APP_CFG_PATH) + QDir::separator() + QString(APP_CFG_FILE);
const QString exe_path = qApp->applicationDirPath();
const QString app_path = getAppPathUserFolder();
const QString home_path = getHomeUserFolder();
const QString home_path_file = home_path + properties.m_settingsSuffix;
const bool portable_settings_available = IOFactory::isFolderWritable(exe_path);
const bool non_portable_settings_exist = QFile::exists(home_path_file);
// We will use PORTABLE settings only and only if it is available and NON-PORTABLE
// settings was not initialized before.
const bool will_we_use_portable_settings = portable_settings_available && !non_portable_settings_exist;
if (will_we_use_portable_settings) {
properties.m_type = SettingsProperties::Portable;
properties.m_baseDirectory = app_path;
}
else {
properties.m_type = SettingsProperties::NonPortable;
properties.m_baseDirectory = home_path;
}
properties.m_absoluteSettingsFileName = properties.m_baseDirectory + properties.m_settingsSuffix;
return properties;
}