1 // For license of this file, see <project-root-folder>/LICENSE.md.
2
3 #include "gui/settings/settingsgui.h"
4
5 #include "core/feedsmodel.h"
6 #include "gui/dialogs/formmain.h"
7 #include "gui/feedmessageviewer.h"
8 #include "gui/systemtrayicon.h"
9 #include "gui/tabwidget.h"
10 #include "gui/toolbars/feedstoolbar.h"
11 #include "gui/toolbars/messagestoolbar.h"
12 #include "gui/toolbars/statusbar.h"
13 #include "miscellaneous/application.h"
14 #include "miscellaneous/iconfactory.h"
15 #include "miscellaneous/settings.h"
16
17 #include <QDropEvent>
18 #include <QStyleFactory>
19
SettingsGui(Settings * settings,QWidget * parent)20 SettingsGui::SettingsGui(Settings* settings, QWidget* parent) : SettingsPanel(settings, parent), m_ui(new Ui::SettingsGui) {
21 m_ui->setupUi(this);
22 m_ui->m_editorMessagesToolbar->activeItemsWidget()->viewport()->installEventFilter(this);
23 m_ui->m_editorFeedsToolbar->activeItemsWidget()->viewport()->installEventFilter(this);
24 m_ui->m_editorMessagesToolbar->availableItemsWidget()->viewport()->installEventFilter(this);
25 m_ui->m_editorFeedsToolbar->availableItemsWidget()->viewport()->installEventFilter(this);
26 m_ui->m_treeSkins->setColumnCount(3);
27 m_ui->m_treeSkins->setHeaderHidden(false);
28 m_ui->m_treeSkins->setHeaderLabels(QStringList()
29 << /*: Skin list name column. */ tr("Name")
30 << /*: Version column of skin list. */ tr("Version")
31 << tr("Author"));
32
33 // Setup skins.
34 m_ui->m_treeSkins->header()->setSectionResizeMode(0, QHeaderView::ResizeMode::ResizeToContents);
35 m_ui->m_treeSkins->header()->setSectionResizeMode(1, QHeaderView::ResizeMode::ResizeToContents);
36 m_ui->m_treeSkins->header()->setSectionResizeMode(2, QHeaderView::ResizeMode::ResizeToContents);
37
38 connect(m_ui->m_cmbIconTheme, static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged), this, &SettingsGui::requireRestart);
39 connect(m_ui->m_cmbIconTheme, static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged), this,
40 &SettingsGui::dirtifySettings);
41 connect(m_ui->m_treeSkins, &QTreeWidget::currentItemChanged, this, &SettingsGui::dirtifySettings);
42 connect(m_ui->m_grpTray, &QGroupBox::toggled, this, &SettingsGui::dirtifySettings);
43 connect(m_ui->m_checkHidden, &QCheckBox::toggled, this, &SettingsGui::dirtifySettings);
44 connect(m_ui->m_checkMonochromeIcons, &QCheckBox::toggled, this, &SettingsGui::dirtifySettings);
45 connect(m_ui->m_checkCountUnreadMessages, &QCheckBox::toggled, this, &SettingsGui::dirtifySettings);
46 connect(m_ui->m_checkHideWhenMinimized, &QCheckBox::toggled, this, &SettingsGui::dirtifySettings);
47 connect(m_ui->m_checkHideTabBarIfOneTabVisible, &QCheckBox::toggled, this, &SettingsGui::dirtifySettings);
48 connect(m_ui->m_checkCloseTabsDoubleClick, &QCheckBox::toggled, this, &SettingsGui::dirtifySettings);
49 connect(m_ui->m_checkCloseTabsMiddleClick, &QCheckBox::toggled, this, &SettingsGui::dirtifySettings);
50 connect(m_ui->m_checkNewTabDoubleClick, &QCheckBox::toggled, this, &SettingsGui::dirtifySettings);
51 connect(m_ui->m_grbCloseTabs, &QGroupBox::toggled, this, &SettingsGui::dirtifySettings);
52 connect(m_ui->m_cmbToolbarButtonStyle, static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged), this,
53 &SettingsGui::dirtifySettings);
54 connect(m_ui->m_editorFeedsToolbar, &ToolBarEditor::setupChanged, this, &SettingsGui::dirtifySettings);
55 connect(m_ui->m_editorMessagesToolbar, &ToolBarEditor::setupChanged, this, &SettingsGui::dirtifySettings);
56 connect(m_ui->m_editorStatusbar, &ToolBarEditor::setupChanged, this, &SettingsGui::dirtifySettings);
57 connect(m_ui->m_editorStatusbar, &ToolBarEditor::setupChanged, this, &SettingsGui::requireRestart);
58 connect(m_ui->m_cmbStyles, static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged), this, &SettingsGui::dirtifySettings);
59 connect(m_ui->m_cmbSelectToolBar, static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged), m_ui->m_stackedToolbars,
60 &QStackedWidget::setCurrentIndex);
61 }
62
~SettingsGui()63 SettingsGui::~SettingsGui() {
64 delete m_ui;
65 }
66
eventFilter(QObject * obj,QEvent * e)67 bool SettingsGui::eventFilter(QObject* obj, QEvent* e) {
68 Q_UNUSED(obj)
69
70 if (e->type() == QEvent::Type::Drop) {
71 auto* drop_event = static_cast<QDropEvent*>(e);
72
73 if (drop_event->keyboardModifiers() != Qt::KeyboardModifier::NoModifier) {
74 drop_event->setDropAction(Qt::DropAction::MoveAction);
75 }
76 }
77
78 return false;
79 }
80
loadSettings()81 void SettingsGui::loadSettings() {
82 onBeginLoadSettings();
83
84 // Load settings of tray icon.
85 m_ui->m_grpTray->setChecked(settings()->value(GROUP(GUI), SETTING(GUI::UseTrayIcon)).toBool());
86
87 if (!SystemTrayIcon::isSystemTrayAreaAvailable()) {
88 m_ui->m_grpTray->setTitle(m_ui->m_grpTray->title() + QL1C(' ') + tr("(Your OS does not support tray icons at the moment.)"));
89 m_ui->m_grpTray->setEnabled(false);
90 }
91
92 m_ui->m_checkHidden->setChecked(settings()->value(GROUP(GUI), SETTING(GUI::MainWindowStartsHidden)).toBool());
93 m_ui->m_checkHideWhenMinimized->setChecked(settings()->value(GROUP(GUI), SETTING(GUI::HideMainWindowWhenMinimized)).toBool());
94
95 // Load settings of icon theme.
96 const QString current_theme = qApp->icons()->currentIconTheme();
97 auto icons = qApp->icons()->installedIconThemes();
98
99 for (const QString& icon_theme_name : qAsConst(icons)) {
100 if (icon_theme_name == QSL(APP_NO_THEME)) {
101 // Add just "no theme" on other systems.
102 //: Label for disabling icon theme.
103 #if defined(Q_OS_UNIX)
104 m_ui->m_cmbIconTheme->addItem(tr("system icon theme"), APP_NO_THEME);
105 #else
106 m_ui->m_cmbIconTheme->addItem(tr("no icon theme"), APP_NO_THEME);
107 #endif
108 }
109 else {
110 m_ui->m_cmbIconTheme->addItem(icon_theme_name, icon_theme_name);
111 }
112 }
113
114 m_ui->m_checkMonochromeIcons->setChecked(settings()->value(GROUP(GUI), SETTING(GUI::MonochromeTrayIcon)).toBool());
115 m_ui->m_checkCountUnreadMessages->setChecked(settings()->value(GROUP(GUI), SETTING(GUI::UnreadNumbersInTrayIcon)).toBool());
116
117 // Mark active theme.
118 if (current_theme == QL1S(APP_NO_THEME)) {
119 // Because "no icon theme" lies at the index 0.
120 m_ui->m_cmbIconTheme->setCurrentIndex(0);
121 }
122 else {
123 m_ui->m_cmbIconTheme->setCurrentText(current_theme);
124 }
125
126 // Load skin.
127 const QString selected_skin = qApp->skins()->selectedSkinName();
128 auto skins = qApp->skins()->installedSkins();
129
130 for (const Skin& skin : qAsConst(skins)) {
131 QTreeWidgetItem* new_item = new QTreeWidgetItem(QStringList() <<
132 skin.m_visibleName <<
133 skin.m_version <<
134 skin.m_author);
135
136 new_item->setData(0, Qt::UserRole, QVariant::fromValue(skin));
137
138 // Add this skin and mark it as active if its active now.
139 m_ui->m_treeSkins->addTopLevelItem(new_item);
140
141 if (skin.m_baseName == selected_skin) {
142 m_ui->m_treeSkins->setCurrentItem(new_item);
143 }
144 }
145
146 if (m_ui->m_treeSkins->currentItem() == nullptr &&
147 m_ui->m_treeSkins->topLevelItemCount() > 0) {
148 // Currently active skin is NOT available, select another one as selected
149 // if possible.
150 m_ui->m_treeSkins->setCurrentItem(m_ui->m_treeSkins->topLevelItem(0));
151 }
152
153 // Load styles.
154 auto styles = QStyleFactory::keys();
155
156 for (const QString& style_name : qAsConst(styles)) {
157 m_ui->m_cmbStyles->addItem(style_name);
158 }
159
160 int item_style = m_ui->m_cmbStyles->findText(settings()->value(GROUP(GUI), SETTING(GUI::Style)).toString(),
161 Qt::MatchFlag::MatchFixedString);
162
163 if (item_style >= 0) {
164 m_ui->m_cmbStyles->setCurrentIndex(item_style);
165 }
166
167 // Load tab settings.
168 m_ui->m_checkCloseTabsMiddleClick->setChecked(settings()->value(GROUP(GUI), SETTING(GUI::TabCloseMiddleClick)).toBool());
169 m_ui->m_checkCloseTabsDoubleClick->setChecked(settings()->value(GROUP(GUI), SETTING(GUI::TabCloseDoubleClick)).toBool());
170 m_ui->m_checkNewTabDoubleClick->setChecked(settings()->value(GROUP(GUI), SETTING(GUI::TabNewDoubleClick)).toBool());
171 m_ui->m_checkHideTabBarIfOneTabVisible->setChecked(settings()->value(GROUP(GUI), SETTING(GUI::HideTabBarIfOnlyOneTab)).toBool());
172
173 // Load toolbar button style.
174 m_ui->m_cmbToolbarButtonStyle->addItem(tr("Icon only"), Qt::ToolButtonStyle::ToolButtonIconOnly);
175 m_ui->m_cmbToolbarButtonStyle->addItem(tr("Text only"), Qt::ToolButtonStyle::ToolButtonTextOnly);
176 m_ui->m_cmbToolbarButtonStyle->addItem(tr("Text beside icon"), Qt::ToolButtonStyle::ToolButtonTextBesideIcon);
177 m_ui->m_cmbToolbarButtonStyle->addItem(tr("Text under icon"), Qt::ToolButtonStyle::ToolButtonTextUnderIcon);
178 m_ui->m_cmbToolbarButtonStyle->addItem(tr("Follow OS style"), Qt::ToolButtonStyle::ToolButtonFollowStyle);
179 m_ui->m_cmbToolbarButtonStyle->setCurrentIndex(m_ui->m_cmbToolbarButtonStyle->findData(settings()->value(GROUP(GUI),
180 SETTING(
181 GUI::ToolbarStyle)).toInt()));
182
183 // Load toolbars.
184 m_ui->m_editorFeedsToolbar->loadFromToolBar(qApp->mainForm()->tabWidget()->feedMessageViewer()->feedsToolBar());
185 m_ui->m_editorMessagesToolbar->loadFromToolBar(qApp->mainForm()->tabWidget()->feedMessageViewer()->messagesToolBar());
186 m_ui->m_editorStatusbar->loadFromToolBar(qApp->mainForm()->statusBar());
187 onEndLoadSettings();
188 }
189
saveSettings()190 void SettingsGui::saveSettings() {
191 onBeginSaveSettings();
192
193 // Save toolbar.
194 settings()->setValue(GROUP(GUI), GUI::ToolbarStyle,
195 m_ui->m_cmbToolbarButtonStyle->itemData(m_ui->m_cmbToolbarButtonStyle->currentIndex()));
196
197 // Save tray icon.
198 if (SystemTrayIcon::isSystemTrayAreaAvailable()) {
199 settings()->setValue(GROUP(GUI), GUI::UseTrayIcon, m_ui->m_grpTray->isChecked());
200
201 if (m_ui->m_grpTray->isChecked()) {
202 qApp->showTrayIcon();
203 }
204 else {
205 qApp->deleteTrayIcon();
206 }
207 }
208
209 auto old_monochrome = settings()->value(GROUP(GUI), SETTING(GUI::MonochromeTrayIcon)).toBool();
210
211 if (old_monochrome != m_ui->m_checkMonochromeIcons->isChecked()) {
212 requireRestart();
213 settings()->setValue(GROUP(GUI), GUI::MonochromeTrayIcon, m_ui->m_checkMonochromeIcons->isChecked());
214 }
215
216 settings()->setValue(GROUP(GUI), GUI::UnreadNumbersInTrayIcon, m_ui->m_checkCountUnreadMessages->isChecked());
217 settings()->setValue(GROUP(GUI), GUI::MainWindowStartsHidden, m_ui->m_checkHidden->isChecked());
218 settings()->setValue(GROUP(GUI), GUI::HideMainWindowWhenMinimized, m_ui->m_checkHideWhenMinimized->isChecked());
219
220 // Make sure that number of unread messages is shown in tray icon as requested.
221 qApp->feedReader()->feedsModel()->notifyWithCounts();
222
223 // Save selected icon theme.
224 QString selected_icon_theme = m_ui->m_cmbIconTheme->itemData(m_ui->m_cmbIconTheme->currentIndex()).toString();
225 QString original_icon_theme = qApp->icons()->currentIconTheme();
226
227 qApp->icons()->setCurrentIconTheme(selected_icon_theme);
228
229 // Check if icon theme was changed.
230 if (selected_icon_theme != original_icon_theme) {
231 requireRestart();
232 }
233
234 // Save and activate new skin.
235 if (!m_ui->m_treeSkins->selectedItems().isEmpty()) {
236 const Skin active_skin = m_ui->m_treeSkins->currentItem()->data(0, Qt::ItemDataRole::UserRole).value<Skin>();
237
238 if (qApp->skins()->selectedSkinName() != active_skin.m_baseName) {
239 qApp->skins()->setCurrentSkinName(active_skin.m_baseName);
240 requireRestart();
241 }
242 }
243
244 // Set new style.
245 if (m_ui->m_cmbStyles->currentIndex() >= 0) {
246 const QString new_style = m_ui->m_cmbStyles->currentText();
247 const QString old_style = qApp->settings()->value(GROUP(GUI), SETTING(GUI::Style)).toString();
248
249 if (old_style != new_style) {
250 requireRestart();
251 }
252
253 qApp->settings()->setValue(GROUP(GUI), GUI::Style, new_style);
254 }
255
256 // Save tab settings.
257 settings()->setValue(GROUP(GUI), GUI::TabCloseMiddleClick, m_ui->m_checkCloseTabsMiddleClick->isChecked());
258 settings()->setValue(GROUP(GUI), GUI::TabCloseDoubleClick, m_ui->m_checkCloseTabsDoubleClick->isChecked());
259 settings()->setValue(GROUP(GUI), GUI::TabNewDoubleClick, m_ui->m_checkNewTabDoubleClick->isChecked());
260 settings()->setValue(GROUP(GUI), GUI::HideTabBarIfOnlyOneTab, m_ui->m_checkHideTabBarIfOneTabVisible->isChecked());
261 m_ui->m_editorFeedsToolbar->saveToolBar();
262 m_ui->m_editorMessagesToolbar->saveToolBar();
263 m_ui->m_editorStatusbar->saveToolBar();
264 qApp->mainForm()->tabWidget()->checkTabBarVisibility();
265 qApp->mainForm()->tabWidget()->feedMessageViewer()->refreshVisualProperties();
266 onEndSaveSettings();
267 }
268