1 // For license of this file, see <project-root-folder>/LICENSE.md.
2 
3 #include "gui/settings/settingsfeedsmessages.h"
4 
5 #include "definitions/definitions.h"
6 #include "gui/dialogs/formmain.h"
7 #include "gui/feedmessageviewer.h"
8 #include "gui/feedsview.h"
9 #include "gui/guiutilities.h"
10 #include "gui/messagesview.h"
11 #include "gui/reusable/timespinbox.h"
12 #include "miscellaneous/application.h"
13 #include "miscellaneous/feedreader.h"
14 
15 #include <QFontDialog>
16 #include <QLocale>
17 #include <QStringList>
18 
SettingsFeedsMessages(Settings * settings,QWidget * parent)19 SettingsFeedsMessages::SettingsFeedsMessages(Settings* settings, QWidget* parent)
20   : SettingsPanel(settings, parent), m_ui(new Ui::SettingsFeedsMessages) {
21   m_ui->setupUi(this);
22 
23   m_ui->m_spinStartupUpdateDelay->setMode(TimeSpinBox::Mode::MinutesSeconds);
24 
25   initializeMessageDateFormats();
26   GuiUtilities::setLabelAsNotice(*m_ui->label_9, false);
27 
28 #if defined(USE_WEBENGINE)
29   m_ui->m_tabMessages->layout()->removeWidget(m_ui->m_checkDisplayPlaceholders);
30   m_ui->m_checkDisplayPlaceholders->hide();
31 
32   connect(m_ui->m_cbShowEnclosuresDirectly, &QCheckBox::toggled, this, &SettingsFeedsMessages::dirtifySettings);
33   connect(m_ui->m_spinHeightImageAttachments, static_cast<void (QSpinBox::*)(int)>(&QSpinBox::valueChanged),
34           this, &SettingsFeedsMessages::dirtifySettings);
35 #else
36   m_ui->m_tabMessages->layout()->removeWidget(m_ui->m_cbShowEnclosuresDirectly);
37   m_ui->m_cbShowEnclosuresDirectly->hide();
38 
39   m_ui->m_tabMessages->layout()->removeWidget(m_ui->m_spinHeightImageAttachments);
40   m_ui->m_spinHeightImageAttachments->hide();
41 
42   connect(m_ui->m_checkDisplayPlaceholders, &QCheckBox::toggled, this, &SettingsFeedsMessages::dirtifySettings);
43 #endif
44 
45   connect(m_ui->m_spinHeightRowsMessages, static_cast<void (QSpinBox::*)(int)>(&QSpinBox::valueChanged),
46           this, &SettingsFeedsMessages::requireRestart);
47   connect(m_ui->m_spinHeightRowsFeeds, static_cast<void (QSpinBox::*)(int)>(&QSpinBox::valueChanged),
48           this, &SettingsFeedsMessages::requireRestart);
49 
50   connect(m_ui->m_cbListsRestrictedShortcuts, &QCheckBox::toggled, this, &SettingsFeedsMessages::dirtifySettings);
51   connect(m_ui->m_cmbIgnoreContentsChanges, &QCheckBox::toggled, this, &SettingsFeedsMessages::dirtifySettings);
52   connect(m_ui->m_cbHideCountsIfNoUnread, &QCheckBox::toggled, this, &SettingsFeedsMessages::dirtifySettings);
53   connect(m_ui->m_checkAutoUpdate, &QCheckBox::toggled, this, &SettingsFeedsMessages::dirtifySettings);
54   connect(m_ui->m_checkAutoUpdateOnlyUnfocused, &QCheckBox::toggled, this, &SettingsFeedsMessages::dirtifySettings);
55   connect(m_ui->m_checkDisplayFeedIcons, &QCheckBox::toggled, this, &SettingsFeedsMessages::dirtifySettings);
56   connect(m_ui->m_checkKeppMessagesInTheMiddle, &QCheckBox::toggled, this, &SettingsFeedsMessages::dirtifySettings);
57   connect(m_ui->m_checkMessagesDateTimeFormat, &QCheckBox::toggled, this, &SettingsFeedsMessages::dirtifySettings);
58   connect(m_ui->m_checkMessagesDateTimeFormat, &QCheckBox::toggled, m_ui->m_cmbMessagesDateTimeFormat, &QComboBox::setEnabled);
59   connect(m_ui->m_checkRemoveReadMessagesOnExit, &QCheckBox::toggled, this, &SettingsFeedsMessages::dirtifySettings);
60   connect(m_ui->m_checkBringToForegroundAfterMsgOpened, &QCheckBox::toggled, this, &SettingsFeedsMessages::dirtifySettings);
61   connect(m_ui->m_checkUpdateAllFeedsOnStartup, &QCheckBox::toggled, this, &SettingsFeedsMessages::dirtifySettings);
62   connect(m_ui->m_spinAutoUpdateInterval, static_cast<void (QDoubleSpinBox::*)(double)>(&QDoubleSpinBox::valueChanged),
63           this, &SettingsFeedsMessages::dirtifySettings);
64   connect(m_ui->m_spinStartupUpdateDelay, static_cast<void (QDoubleSpinBox::*)(double)>(&QDoubleSpinBox::valueChanged),
65           this, &SettingsFeedsMessages::dirtifySettings);
66   connect(m_ui->m_spinHeightRowsMessages, static_cast<void (QSpinBox::*)(int)>(&QSpinBox::valueChanged),
67           this, &SettingsFeedsMessages::dirtifySettings);
68   connect(m_ui->m_spinHeightRowsFeeds, static_cast<void (QSpinBox::*)(int)>(&QSpinBox::valueChanged),
69           this, &SettingsFeedsMessages::dirtifySettings);
70   connect(m_ui->m_checkAutoUpdate, &QCheckBox::toggled, m_ui->m_spinAutoUpdateInterval, &TimeSpinBox::setEnabled);
71   connect(m_ui->m_checkUpdateAllFeedsOnStartup, &QCheckBox::toggled, m_ui->m_spinStartupUpdateDelay, &TimeSpinBox::setEnabled);
72   connect(m_ui->m_spinFeedUpdateTimeout, static_cast<void (QSpinBox::*)(int)>(&QSpinBox::valueChanged), this,
73           &SettingsFeedsMessages::dirtifySettings);
74   connect(m_ui->m_cmbMessagesDateTimeFormat, static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged), this,
75           &SettingsFeedsMessages::dirtifySettings);
76   connect(m_ui->m_cmbCountsFeedList, &QComboBox::currentTextChanged, this, &SettingsFeedsMessages::dirtifySettings);
77   connect(m_ui->m_cmbCountsFeedList, static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged), this,
78           &SettingsFeedsMessages::dirtifySettings);
79   connect(m_ui->m_checkShowTooltips, &QCheckBox::toggled, this, &SettingsFeedsMessages::dirtifySettings);
80 
81   connect(m_ui->m_btnChangeMessagesFont, &QPushButton::clicked, this, [&]() {
82     changeFont(*m_ui->m_lblMessagesFont);
83   });
84 
85   connect(m_ui->m_btnChangeFeedListFont, &QPushButton::clicked, this, [&]() {
86     changeFont(*m_ui->m_lblFeedListFont);
87   });
88 
89   connect(m_ui->m_btnChangeMessageListFont, &QPushButton::clicked, this, [&]() {
90     changeFont(*m_ui->m_lblMessageListFont);
91   });
92 
93   if (!m_ui->m_spinFeedUpdateTimeout->suffix().startsWith(' ')) {
94     m_ui->m_spinFeedUpdateTimeout->setSuffix(QSL(" ") + m_ui->m_spinFeedUpdateTimeout->suffix());
95   }
96 }
97 
~SettingsFeedsMessages()98 SettingsFeedsMessages::~SettingsFeedsMessages() {
99   delete m_ui;
100 }
101 
initializeMessageDateFormats()102 void SettingsFeedsMessages::initializeMessageDateFormats() {
103   QStringList best_formats;
104   const QDateTime current_dt = QDateTime::currentDateTime();
105   const QLocale current_locale = qApp->localization()->loadedLocale();
106   auto installed_languages = qApp->localization()->installedLanguages();
107 
108   for (const Language& lang : qAsConst(installed_languages)) {
109     QLocale locale(lang.m_code);
110 
111     best_formats << locale.dateTimeFormat(QLocale::FormatType::LongFormat)
112                  << locale.dateTimeFormat(QLocale::FormatType::ShortFormat)
113                  << locale.dateTimeFormat(QLocale::FormatType::NarrowFormat);
114   }
115 
116   best_formats.removeDuplicates();
117 
118   for (const QString& format : qAsConst(best_formats)) {
119     m_ui->m_cmbMessagesDateTimeFormat->addItem(current_locale.toString(current_dt, format), format);
120   }
121 }
122 
changeFont(QLabel & lbl)123 void SettingsFeedsMessages::changeFont(QLabel& lbl) {
124   bool ok;
125   QFont new_font = QFontDialog::getFont(&ok, lbl.font(),
126                                         this, tr("Select new font"),
127                                         QFontDialog::DontUseNativeDialog);
128 
129   if (ok) {
130     lbl.setFont(new_font);
131     dirtifySettings();
132   }
133 }
134 
loadSettings()135 void SettingsFeedsMessages::loadSettings() {
136   onBeginLoadSettings();
137 
138   m_ui->m_spinHeightRowsMessages->setValue(settings()->value(GROUP(GUI), SETTING(GUI::HeightRowMessages)).toInt());
139   m_ui->m_spinHeightRowsFeeds->setValue(settings()->value(GROUP(GUI), SETTING(GUI::HeightRowFeeds)).toInt());
140 
141   m_ui->m_cbListsRestrictedShortcuts->setChecked(settings()->value(GROUP(Feeds),
142                                                                    SETTING(Feeds::OnlyBasicShortcutsInLists)).toBool());
143   m_ui->m_cbHideCountsIfNoUnread->setChecked(settings()->value(GROUP(Feeds), SETTING(Feeds::HideCountsIfNoUnread)).toBool());
144   m_ui->m_checkDisplayFeedIcons->setChecked(settings()->value(GROUP(Messages), SETTING(Messages::DisplayFeedIconsInList)).toBool());
145   m_ui->m_checkBringToForegroundAfterMsgOpened->setChecked(settings()->value(GROUP(Messages),
146                                                                              SETTING(Messages::BringAppToFrontAfterMessageOpenedExternally)).toBool());
147   m_ui->m_checkKeppMessagesInTheMiddle->setChecked(settings()->value(GROUP(Messages), SETTING(Messages::KeepCursorInCenter)).toBool());
148   m_ui->m_checkRemoveReadMessagesOnExit->setChecked(settings()->value(GROUP(Messages), SETTING(Messages::ClearReadOnExit)).toBool());
149   m_ui->m_checkAutoUpdate->setChecked(settings()->value(GROUP(Feeds), SETTING(Feeds::AutoUpdateEnabled)).toBool());
150   m_ui->m_checkAutoUpdateOnlyUnfocused->setChecked(settings()->value(GROUP(Feeds), SETTING(Feeds::AutoUpdateOnlyUnfocused)).toBool());
151   m_ui->m_spinAutoUpdateInterval->setValue(settings()->value(GROUP(Feeds), SETTING(Feeds::AutoUpdateInterval)).toInt());
152   m_ui->m_spinFeedUpdateTimeout->setValue(settings()->value(GROUP(Feeds), SETTING(Feeds::UpdateTimeout)).toInt());
153   m_ui->m_checkUpdateAllFeedsOnStartup->setChecked(settings()->value(GROUP(Feeds), SETTING(Feeds::FeedsUpdateOnStartup)).toBool());
154   m_ui->m_spinStartupUpdateDelay->setValue(settings()->value(GROUP(Feeds), SETTING(Feeds::FeedsUpdateStartupDelay)).toDouble());
155   m_ui->m_cmbCountsFeedList->addItems({ QSL("(%unread)"), QSL("[%unread]"), QSL("%unread/%all"),
156                                         QSL("%unread-%all"), QSL("[%unread|%all]") });
157   m_ui->m_cmbCountsFeedList->setEditText(settings()->value(GROUP(Feeds), SETTING(Feeds::CountFormat)).toString());
158   m_ui->m_checkShowTooltips->setChecked(settings()->value(GROUP(Feeds), SETTING(Feeds::EnableTooltipsFeedsMessages)).toBool());
159   m_ui->m_cmbIgnoreContentsChanges->setChecked(settings()->value(GROUP(Messages),
160                                                                  SETTING(Messages::IgnoreContentsChanges)).toBool());
161 
162 #if !defined (USE_WEBENGINE)
163   m_ui->m_checkDisplayPlaceholders->setChecked(settings()->value(GROUP(Messages), SETTING(Messages::DisplayImagePlaceholders)).toBool());
164 #else
165   m_ui->m_spinHeightImageAttachments->setValue(settings()->value(GROUP(Messages),
166                                                                  SETTING(Messages::MessageHeadImageHeight)).toInt());
167   m_ui->m_cbShowEnclosuresDirectly->setChecked(settings()->value(GROUP(Messages),
168                                                                  SETTING(Messages::DisplayEnclosuresInMessage)).toBool());
169 #endif
170 
171   m_ui->m_checkMessagesDateTimeFormat->setChecked(settings()->value(GROUP(Messages), SETTING(Messages::UseCustomDate)).toBool());
172   const int index_format = m_ui->m_cmbMessagesDateTimeFormat->findData(settings()->value(GROUP(Messages),
173                                                                                          SETTING(Messages::CustomDateFormat)).toString());
174 
175   if (index_format >= 0) {
176     m_ui->m_cmbMessagesDateTimeFormat->setCurrentIndex(index_format);
177   }
178 
179   QFont fon;
180 
181   fon.fromString(settings()->value(GROUP(Messages),
182                                    SETTING(Messages::PreviewerFontStandard)).toString());
183   m_ui->m_lblMessagesFont->setFont(fon);
184 
185   QFont fon2;
186 
187   // Keep in sync with void MessagesModel::setupFonts().
188   fon2.fromString(settings()->value(GROUP(Messages),
189                                     Messages::ListFont,
190                                     Application::font("MessagesView").toString()).toString());
191   m_ui->m_lblMessageListFont->setFont(fon2);
192 
193   QFont fon3;
194 
195   // Keep in sync with void FeedsModel::setupFonts().
196   fon3.fromString(settings()->value(GROUP(Feeds),
197                                     Feeds::ListFont,
198                                     Application::font("FeedsView").toString()).toString());
199   m_ui->m_lblFeedListFont->setFont(fon3);
200 
201   onEndLoadSettings();
202 }
203 
saveSettings()204 void SettingsFeedsMessages::saveSettings() {
205   onBeginSaveSettings();
206 
207   settings()->setValue(GROUP(GUI), GUI::HeightRowMessages, m_ui->m_spinHeightRowsMessages->value());
208   settings()->setValue(GROUP(GUI), GUI::HeightRowFeeds, m_ui->m_spinHeightRowsFeeds->value());
209 
210   settings()->setValue(GROUP(Feeds), Feeds::OnlyBasicShortcutsInLists,
211                        m_ui->m_cbListsRestrictedShortcuts->isChecked());
212 
213   settings()->setValue(GROUP(Feeds), Feeds::HideCountsIfNoUnread, m_ui->m_cbHideCountsIfNoUnread->isChecked());
214   settings()->setValue(GROUP(Messages), Messages::DisplayFeedIconsInList, m_ui->m_checkDisplayFeedIcons->isChecked());
215   settings()->setValue(GROUP(Messages), Messages::BringAppToFrontAfterMessageOpenedExternally,
216                        m_ui->m_checkBringToForegroundAfterMsgOpened->isChecked());
217   settings()->setValue(GROUP(Messages), Messages::KeepCursorInCenter, m_ui->m_checkKeppMessagesInTheMiddle->isChecked());
218   settings()->setValue(GROUP(Messages), Messages::ClearReadOnExit, m_ui->m_checkRemoveReadMessagesOnExit->isChecked());
219   settings()->setValue(GROUP(Feeds), Feeds::AutoUpdateEnabled, m_ui->m_checkAutoUpdate->isChecked());
220   settings()->setValue(GROUP(Feeds), Feeds::AutoUpdateOnlyUnfocused, m_ui->m_checkAutoUpdateOnlyUnfocused->isChecked());
221   settings()->setValue(GROUP(Feeds), Feeds::AutoUpdateInterval, m_ui->m_spinAutoUpdateInterval->value());
222   settings()->setValue(GROUP(Feeds), Feeds::UpdateTimeout, m_ui->m_spinFeedUpdateTimeout->value());
223   settings()->setValue(GROUP(Feeds), Feeds::FeedsUpdateOnStartup, m_ui->m_checkUpdateAllFeedsOnStartup->isChecked());
224   settings()->setValue(GROUP(Feeds), Feeds::FeedsUpdateStartupDelay, m_ui->m_spinStartupUpdateDelay->value());
225   settings()->setValue(GROUP(Feeds), Feeds::CountFormat, m_ui->m_cmbCountsFeedList->currentText());
226   settings()->setValue(GROUP(Messages), Messages::UseCustomDate, m_ui->m_checkMessagesDateTimeFormat->isChecked());
227   settings()->setValue(GROUP(Feeds), Feeds::EnableTooltipsFeedsMessages, m_ui->m_checkShowTooltips->isChecked());
228   settings()->setValue(GROUP(Messages), Messages::IgnoreContentsChanges, m_ui->m_cmbIgnoreContentsChanges->isChecked());
229 
230 #if !defined (USE_WEBENGINE)
231   settings()->setValue(GROUP(Messages), Messages::DisplayImagePlaceholders, m_ui->m_checkDisplayPlaceholders->isChecked());
232 #else
233   settings()->setValue(GROUP(Messages), Messages::MessageHeadImageHeight, m_ui->m_spinHeightImageAttachments->value());
234   settings()->setValue(GROUP(Messages),
235                        Messages::DisplayEnclosuresInMessage,
236                        m_ui->m_cbShowEnclosuresDirectly->isChecked());
237 #endif
238 
239   settings()->setValue(GROUP(Messages), Messages::CustomDateFormat,
240                        m_ui->m_cmbMessagesDateTimeFormat->itemData(m_ui->m_cmbMessagesDateTimeFormat->currentIndex()).toString());
241 
242   // Save fonts.
243   settings()->setValue(GROUP(Messages), Messages::PreviewerFontStandard, m_ui->m_lblMessagesFont->font().toString());
244   settings()->setValue(GROUP(Messages), Messages::ListFont, m_ui->m_lblMessageListFont->font().toString());
245   settings()->setValue(GROUP(Feeds), Feeds::ListFont, m_ui->m_lblFeedListFont->font().toString());
246 
247   qApp->mainForm()->tabWidget()->feedMessageViewer()->loadMessageViewerFonts();
248 
249   qApp->feedReader()->updateAutoUpdateStatus();
250   qApp->feedReader()->feedsModel()->reloadWholeLayout();
251 
252   qApp->feedReader()->messagesModel()->updateDateFormat();
253   qApp->feedReader()->messagesModel()->updateFeedIconsDisplay();
254   qApp->feedReader()->messagesModel()->reloadWholeLayout();
255 
256   onEndSaveSettings();
257 }
258