File: settings.cpp

package info (click to toggle)
pineapple-pictures 1.3.0-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 2,424 kB
  • sloc: cpp: 3,794; xml: 339; sh: 8; makefile: 2
file content (256 lines) | stat: -rw-r--r-- 7,818 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
// SPDX-FileCopyrightText: 2022 Gary Wang <wzc782970009@gmail.com>
//
// SPDX-License-Identifier: MIT

#include "settings.h"

#include <QApplication>
#include <QStandardPaths>
#include <QDebug>
#include <QDir>
#include <QAction>
#include <QWidget>
#include <QKeySequence>
#include <QMetaEnum>

namespace QEnumHelper
{
    template <typename E>
    E fromString(const QString &text, const E defaultValue)
    {
        bool ok;
        E result = static_cast<E>(QMetaEnum::fromType<E>().keyToValue(text.toUtf8(), &ok));
        if (!ok) {
            return defaultValue;
        }
        return result;
    }

    template <typename E>
    QString toString(E value)
    {
        const int intValue = static_cast<int>(value);
        return QString::fromUtf8(QMetaEnum::fromType<E>().valueToKey(intValue));
    }
}

Settings *Settings::m_settings_instance = nullptr;

Settings *Settings::instance()
{
    if (!m_settings_instance) {
        m_settings_instance = new Settings;
    }

    return m_settings_instance;
}

bool Settings::stayOnTop() const
{
    return m_qsettings->value("stay_on_top", true).toBool();
}

bool Settings::useBuiltInCloseAnimation() const
{
    return m_qsettings->value("use_built_in_close_animation", true).toBool();
}

bool Settings::useLightCheckerboard() const
{
    return m_qsettings->value("use_light_checkerboard", false).toBool();
}

bool Settings::loopGallery() const
{
    return m_qsettings->value("loop_gallery", true).toBool();
}

bool Settings::autoLongImageMode() const
{
    return m_qsettings->value("auto_long_image_mode", true).toBool();
}

bool Settings::svgTiny12Only() const
{
    // Qt 6.7.0's SVG support is terrible caused by huge memory usage, see QTBUG-124287
    // Qt 6.7.1's is somewhat better, memory issue seems fixed, but still laggy when zoom in, see QTBUG-126771.
    // Qt 6.9.3 and Qt 6.10.1 seems no longer have the laggy issue, so let's make the default value different
    // based on Qt version.
#if QT_VERSION < QT_VERSION_CHECK(6, 9, 3)
    return m_qsettings->value("svg_tiny12_only", true).toBool();
#else
    return m_qsettings->value("svg_tiny12_only", false).toBool();
#endif // QT_VERSION < QT_VERSION_CHECK(6, 9, 3)
}

Settings::DoubleClickBehavior Settings::doubleClickBehavior() const
{
    QString result = m_qsettings->value("double_click_behavior", "Close").toString();

    return QEnumHelper::fromString<DoubleClickBehavior>(result, DoubleClickBehavior::Close);
}

Settings::MouseWheelBehavior Settings::mouseWheelBehavior() const
{
    QString result = m_qsettings->value("mouse_wheel_behavior", "Zoom").toString();

    return QEnumHelper::fromString<MouseWheelBehavior>(result, MouseWheelBehavior::Zoom);
}

Settings::WindowSizeBehavior Settings::initWindowSizeBehavior() const
{
    QString result = m_qsettings->value("init_window_size_behavior", "Auto").toString();

    return QEnumHelper::fromString<WindowSizeBehavior>(result, WindowSizeBehavior::Auto);
}

Qt::HighDpiScaleFactorRoundingPolicy Settings::hiDpiScaleFactorBehavior() const
{
    QString result = m_qsettings->value("hidpi_scale_factor_behavior", "PassThrough").toString();

    return QEnumHelper::fromString<Qt::HighDpiScaleFactorRoundingPolicy>(result, Qt::HighDpiScaleFactorRoundingPolicy::PassThrough);
}

void Settings::setStayOnTop(bool on)
{
    m_qsettings->setValue("stay_on_top", on);
    m_qsettings->sync();
}

void Settings::setUseBuiltInCloseAnimation(bool on)
{
    m_qsettings->setValue("use_built_in_close_animation", on);
    m_qsettings->sync();
}

void Settings::setUseLightCheckerboard(bool light)
{
    m_qsettings->setValue("use_light_checkerboard", light);
    m_qsettings->sync();
}

void Settings::setLoopGallery(bool on)
{
    m_qsettings->setValue("loop_gallery", on);
    m_qsettings->sync();
}

void Settings::setAutoLongImageMode(bool on)
{
    m_qsettings->setValue("auto_long_image_mode", on);
    m_qsettings->sync();
}

void Settings::setSvgTiny12Only(bool on)
{
    m_qsettings->setValue("svg_tiny12_only", on);
    m_qsettings->sync();
}

void Settings::setDoubleClickBehavior(DoubleClickBehavior dcb)
{
    m_qsettings->setValue("double_click_behavior", QEnumHelper::toString(dcb));
    m_qsettings->sync();
}

void Settings::setMouseWheelBehavior(MouseWheelBehavior mwb)
{
    m_qsettings->setValue("mouse_wheel_behavior", QEnumHelper::toString(mwb));
    m_qsettings->sync();
}

void Settings::setInitWindowSizeBehavior(WindowSizeBehavior wsb)
{
    m_qsettings->setValue("init_window_size_behavior", QEnumHelper::toString(wsb));
    m_qsettings->sync();
}

void Settings::setHiDpiScaleFactorBehavior(Qt::HighDpiScaleFactorRoundingPolicy hidpi)
{
    m_qsettings->setValue("hidpi_scale_factor_behavior", QEnumHelper::toString(hidpi));
    m_qsettings->sync();
}

void Settings::applyUserShortcuts(QWidget *widget)
{
    m_qsettings->beginGroup("shortcuts");
    const QStringList shortcutNames = m_qsettings->allKeys();
    for (const QString & name : shortcutNames) {
        QList<QKeySequence> shortcuts = m_qsettings->value(name).value<QList<QKeySequence>>();
        setShortcutsForAction(widget, name, shortcuts, false);
    }
    m_qsettings->endGroup();
}

bool Settings::setShortcutsForAction(QWidget *widget, const QString &objectName,
                                     QList<QKeySequence> shortcuts, bool writeConfig)
{
    QAction * targetAction = nullptr;
    for (QAction * action : widget->actions()) {
        if (action->objectName() == objectName) {
            targetAction = action;
        } else {
            for (const QKeySequence & shortcut : std::as_const(shortcuts)) {
                if (action->shortcuts().contains(shortcut)) {
                    return false;
                }
            }
        }
    }

    if (targetAction) {
        targetAction->setShortcuts(shortcuts);
    }

    if (targetAction && writeConfig) {
        m_qsettings->beginGroup("shortcuts");
        m_qsettings->setValue(objectName, QVariant::fromValue(shortcuts));
        m_qsettings->endGroup();
        m_qsettings->sync();
    }

    return true;
}

#if defined(FLAG_PORTABLE_MODE_SUPPORT) && defined(Q_OS_WIN)
#include <windows.h>
// QCoreApplication::applicationDirPath() parses the "applicationDirPath" from arg0, which...
// 1. rely on a QApplication object instance
//    but we need to call QGuiApplication::setHighDpiScaleFactorRoundingPolicy() before QApplication get created
// 2. arg0 is NOT garanteed to be the path of execution
//    see also: https://stackoverflow.com/questions/383973/is-args0-guaranteed-to-be-the-path-of-execution
// This function is here mainly for #1.
QString getApplicationDirPath()
{
    WCHAR buffer[MAX_PATH];
    GetModuleFileNameW(NULL, buffer, MAX_PATH);
    QString appPath = QString::fromWCharArray(buffer);

    return appPath.left(appPath.lastIndexOf('\\'));
}
#endif // defined(FLAG_PORTABLE_MODE_SUPPORT) && defined(Q_OS_WIN)

Settings::Settings()
    : QObject(qApp)
{
    QString configPath;

#if defined(FLAG_PORTABLE_MODE_SUPPORT) && defined(Q_OS_WIN)
    QString portableConfigDirPath = QDir(getApplicationDirPath()).absoluteFilePath("data");
    QFileInfo portableConfigDirInfo(portableConfigDirPath);
    if (portableConfigDirInfo.exists() && portableConfigDirInfo.isDir() && portableConfigDirInfo.isWritable()) {
        // we can use it.
        configPath = portableConfigDirPath;
    }
#endif // defined(FLAG_PORTABLE_MODE_SUPPORT) && defined(Q_OS_WIN)

    if (configPath.isEmpty()) {
        // Should be %LOCALAPPDATA%\<APPNAME> under Windows, ~/.config/<APPNAME> under Linux.
        configPath = QStandardPaths::writableLocation(QStandardPaths::AppConfigLocation);
    }

    m_qsettings = new QSettings(QDir(configPath).absoluteFilePath("config.ini"), QSettings::IniFormat, this);

    qRegisterMetaType<QList<QKeySequence>>();
}