support forced styles, custom alt. palette and force palette for skins
This commit is contained in:
		
							parent
							
								
									8902594059
								
							
						
					
					
						commit
						900c8fa0d6
					
				
					 5 changed files with 221 additions and 113 deletions
				
			
		|  | @ -2,6 +2,7 @@ | ||||||
| 
 | 
 | ||||||
| #include "gui/settings/settingsgui.h" | #include "gui/settings/settingsgui.h" | ||||||
| 
 | 
 | ||||||
|  | #include "3rd-party/boolinq/boolinq.h" | ||||||
| #include "core/feedsmodel.h" | #include "core/feedsmodel.h" | ||||||
| #include "gui/dialogs/formmain.h" | #include "gui/dialogs/formmain.h" | ||||||
| #include "gui/feedmessageviewer.h" | #include "gui/feedmessageviewer.h" | ||||||
|  | @ -27,12 +28,9 @@ SettingsGui::SettingsGui(Settings* settings, QWidget* parent) : SettingsPanel(se | ||||||
|   m_ui->m_editorFeedsToolbar->activeItemsWidget()->viewport()->installEventFilter(this); |   m_ui->m_editorFeedsToolbar->activeItemsWidget()->viewport()->installEventFilter(this); | ||||||
|   m_ui->m_editorMessagesToolbar->availableItemsWidget()->viewport()->installEventFilter(this); |   m_ui->m_editorMessagesToolbar->availableItemsWidget()->viewport()->installEventFilter(this); | ||||||
|   m_ui->m_editorFeedsToolbar->availableItemsWidget()->viewport()->installEventFilter(this); |   m_ui->m_editorFeedsToolbar->availableItemsWidget()->viewport()->installEventFilter(this); | ||||||
|   m_ui->m_treeSkins->setColumnCount(3); |   m_ui->m_treeSkins->setColumnCount(5); | ||||||
|   m_ui->m_treeSkins->setHeaderHidden(false); |   m_ui->m_treeSkins->setHeaderHidden(false); | ||||||
|   m_ui->m_treeSkins->setHeaderLabels(QStringList() |   m_ui->m_treeSkins->setHeaderLabels({ tr("Name"), tr("Version"), tr("Author"), tr("Forced styles"), tr("Forced alternative palette") }); | ||||||
|                                      << /*: Skin list name column. */ tr("Name") |  | ||||||
|                                      << /*: Version column of skin list. */ tr("Version") |  | ||||||
|                                      << tr("Author")); |  | ||||||
| 
 | 
 | ||||||
|   m_ui->m_tabUi->setTabVisible(m_ui->m_tabUi->indexOf(m_ui->m_tabTaskBar), |   m_ui->m_tabUi->setTabVisible(m_ui->m_tabUi->indexOf(m_ui->m_tabTaskBar), | ||||||
| #if (defined(Q_OS_UNIX) && !defined(Q_OS_MACOS)) || defined(Q_OS_WIN) | #if (defined(Q_OS_UNIX) && !defined(Q_OS_MACOS)) || defined(Q_OS_WIN) | ||||||
|  | @ -48,20 +46,21 @@ SettingsGui::SettingsGui(Settings* settings, QWidget* parent) : SettingsPanel(se | ||||||
|   m_ui->m_treeSkins->header()->setSectionResizeMode(0, QHeaderView::ResizeMode::ResizeToContents); |   m_ui->m_treeSkins->header()->setSectionResizeMode(0, QHeaderView::ResizeMode::ResizeToContents); | ||||||
|   m_ui->m_treeSkins->header()->setSectionResizeMode(1, QHeaderView::ResizeMode::ResizeToContents); |   m_ui->m_treeSkins->header()->setSectionResizeMode(1, QHeaderView::ResizeMode::ResizeToContents); | ||||||
|   m_ui->m_treeSkins->header()->setSectionResizeMode(2, QHeaderView::ResizeMode::ResizeToContents); |   m_ui->m_treeSkins->header()->setSectionResizeMode(2, QHeaderView::ResizeMode::ResizeToContents); | ||||||
|  |   m_ui->m_treeSkins->header()->setSectionResizeMode(3, QHeaderView::ResizeMode::ResizeToContents); | ||||||
|  |   m_ui->m_treeSkins->header()->setSectionResizeMode(4, QHeaderView::ResizeMode::ResizeToContents); | ||||||
| 
 | 
 | ||||||
|   connect(m_ui->m_cmbStyles, &QComboBox::currentTextChanged, this, [this](const QString& txt) { |   connect(m_ui->m_cmbStyles, &QComboBox::currentTextChanged, this, &SettingsGui::updateSkinOptions); | ||||||
|     m_ui->m_checkForceDarkFusion->setVisible(qApp->skins()->isStyleGoodForDarkVariant(txt)); |  | ||||||
|   }); |  | ||||||
| 
 | 
 | ||||||
|   connect(m_ui->m_cmbIconTheme, static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged), |   connect(m_ui->m_cmbIconTheme, static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged), | ||||||
|           this, &SettingsGui::requireRestart); |           this, &SettingsGui::requireRestart); | ||||||
|   connect(m_ui->m_cmbIconTheme, static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged), this, |   connect(m_ui->m_cmbIconTheme, static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged), this, | ||||||
|           &SettingsGui::dirtifySettings); |           &SettingsGui::dirtifySettings); | ||||||
|   connect(m_ui->m_treeSkins, &QTreeWidget::currentItemChanged, this, &SettingsGui::dirtifySettings); |   connect(m_ui->m_treeSkins, &QTreeWidget::currentItemChanged, this, &SettingsGui::dirtifySettings); | ||||||
|  |   connect(m_ui->m_treeSkins, &QTreeWidget::currentItemChanged, this, &SettingsGui::updateSkinOptions); | ||||||
|   connect(m_ui->m_grpTray, &QGroupBox::toggled, this, &SettingsGui::dirtifySettings); |   connect(m_ui->m_grpTray, &QGroupBox::toggled, this, &SettingsGui::dirtifySettings); | ||||||
|   connect(m_ui->m_checkHidden, &QCheckBox::toggled, this, &SettingsGui::dirtifySettings); |   connect(m_ui->m_checkHidden, &QCheckBox::toggled, this, &SettingsGui::dirtifySettings); | ||||||
|   connect(m_ui->m_checkForceDarkFusion, &QCheckBox::toggled, this, &SettingsGui::dirtifySettings); |   connect(m_ui->m_checkForceAlternativePalette, &QCheckBox::toggled, this, &SettingsGui::dirtifySettings); | ||||||
|   connect(m_ui->m_checkForceDarkFusion, &QCheckBox::toggled, this, &SettingsGui::requireRestart); |   connect(m_ui->m_checkForceAlternativePalette, &QCheckBox::toggled, this, &SettingsGui::requireRestart); | ||||||
|   connect(m_ui->m_checkMonochromeIcons, &QCheckBox::toggled, this, &SettingsGui::dirtifySettings); |   connect(m_ui->m_checkMonochromeIcons, &QCheckBox::toggled, this, &SettingsGui::dirtifySettings); | ||||||
|   connect(m_ui->m_checkCountUnreadMessages, &QCheckBox::toggled, this, &SettingsGui::dirtifySettings); |   connect(m_ui->m_checkCountUnreadMessages, &QCheckBox::toggled, this, &SettingsGui::dirtifySettings); | ||||||
|   connect(m_ui->m_checkHideWhenMinimized, &QCheckBox::toggled, this, &SettingsGui::dirtifySettings); |   connect(m_ui->m_checkHideWhenMinimized, &QCheckBox::toggled, this, &SettingsGui::dirtifySettings); | ||||||
|  | @ -116,6 +115,24 @@ bool SettingsGui::eventFilter(QObject* obj, QEvent* e) { | ||||||
|   return false; |   return false; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | void SettingsGui::updateSkinOptions() { | ||||||
|  |   auto* it = m_ui->m_treeSkins->currentItem(); | ||||||
|  | 
 | ||||||
|  |   if (it == nullptr) { | ||||||
|  |     return; | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   const Skin skin = it->data(0, Qt::ItemDataRole::UserRole).value<Skin>(); | ||||||
|  |   const bool skin_has_palette = !skin.m_stylePalette.isEmpty(); | ||||||
|  |   const bool skin_forces_palette = skin.m_forcedStylePalette; | ||||||
|  |   const bool skin_forces_style = skin.m_forcedStyles.isEmpty(); | ||||||
|  | 
 | ||||||
|  |   m_ui->m_cmbStyles->setEnabled(!qApp->skins()->styleIsFrozen() && skin_forces_style); | ||||||
|  |   m_ui->m_checkForceAlternativePalette->setEnabled(skin_has_palette | ||||||
|  |                                                    ? !skin_forces_palette | ||||||
|  |                                                    : qApp->skins()->isStyleGoodForAlternativeStylePalette(m_ui->m_cmbStyles->currentText())); | ||||||
|  | } | ||||||
|  | 
 | ||||||
| void SettingsGui::loadSettings() { | void SettingsGui::loadSettings() { | ||||||
|   onBeginLoadSettings(); |   onBeginLoadSettings(); | ||||||
| 
 | 
 | ||||||
|  | @ -130,9 +147,6 @@ void SettingsGui::loadSettings() { | ||||||
|   m_ui->m_checkHidden->setChecked(settings()->value(GROUP(GUI), SETTING(GUI::MainWindowStartsHidden)).toBool()); |   m_ui->m_checkHidden->setChecked(settings()->value(GROUP(GUI), SETTING(GUI::MainWindowStartsHidden)).toBool()); | ||||||
|   m_ui->m_checkHideWhenMinimized->setChecked(settings()->value(GROUP(GUI), SETTING(GUI::HideMainWindowWhenMinimized)).toBool()); |   m_ui->m_checkHideWhenMinimized->setChecked(settings()->value(GROUP(GUI), SETTING(GUI::HideMainWindowWhenMinimized)).toBool()); | ||||||
| 
 | 
 | ||||||
|   m_ui->m_checkForceDarkFusion->setChecked(settings()->value(GROUP(GUI), |  | ||||||
|                                                              SETTING(GUI::ForceDarkFusion)).toBool()); |  | ||||||
| 
 |  | ||||||
|   // Load settings of icon theme.
 |   // Load settings of icon theme.
 | ||||||
|   const QString current_theme = qApp->icons()->currentIconTheme(); |   const QString current_theme = qApp->icons()->currentIconTheme(); | ||||||
|   auto icons = qApp->icons()->installedIconThemes(); |   auto icons = qApp->icons()->installedIconThemes(); | ||||||
|  | @ -159,7 +173,7 @@ void SettingsGui::loadSettings() { | ||||||
|   m_ui->m_displayUnreadMessageCountOnTaskBar->setChecked(settings()->value(GROUP(GUI), SETTING(GUI::UnreadNumbersOnTaskBar)).toBool()); |   m_ui->m_displayUnreadMessageCountOnTaskBar->setChecked(settings()->value(GROUP(GUI), SETTING(GUI::UnreadNumbersOnTaskBar)).toBool()); | ||||||
| #endif | #endif | ||||||
| 
 | 
 | ||||||
|   // Mark active theme.
 |   // Mark active icon theme.
 | ||||||
|   if (current_theme == QL1S(APP_NO_THEME)) { |   if (current_theme == QL1S(APP_NO_THEME)) { | ||||||
|     // Because "no icon theme" lies at the index 0.
 |     // Because "no icon theme" lies at the index 0.
 | ||||||
|     m_ui->m_cmbIconTheme->setCurrentIndex(0); |     m_ui->m_cmbIconTheme->setCurrentIndex(0); | ||||||
|  | @ -168,15 +182,32 @@ void SettingsGui::loadSettings() { | ||||||
|     m_ui->m_cmbIconTheme->setCurrentText(current_theme); |     m_ui->m_cmbIconTheme->setCurrentText(current_theme); | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|  |   // Load styles.
 | ||||||
|  |   auto styles = QStyleFactory::keys(); | ||||||
|  | 
 | ||||||
|  |   for (const QString& style_name : qAsConst(styles)) { | ||||||
|  |     m_ui->m_cmbStyles->addItem(style_name); | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   int item_style = m_ui->m_cmbStyles->findText(qApp->skins()->currentStyle(), Qt::MatchFlag::MatchFixedString); | ||||||
|  | 
 | ||||||
|  |   if (item_style >= 0) { | ||||||
|  |     m_ui->m_cmbStyles->setCurrentIndex(item_style); | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   m_ui->m_checkForceAlternativePalette->setChecked(settings()->value(GROUP(GUI), SETTING(GUI::ForceDarkFusion)).toBool()); | ||||||
|  | 
 | ||||||
|   // Load skin.
 |   // Load skin.
 | ||||||
|   const QString selected_skin = qApp->skins()->selectedSkinName(); |   const QString selected_skin = qApp->skins()->selectedSkinName(); | ||||||
|   auto skins = qApp->skins()->installedSkins(); |   auto skins = qApp->skins()->installedSkins(); | ||||||
| 
 | 
 | ||||||
|   for (const Skin& skin : qAsConst(skins)) { |   for (const Skin& skin : qAsConst(skins)) { | ||||||
|     QTreeWidgetItem* new_item = new QTreeWidgetItem(QStringList() << |     QTreeWidgetItem* new_item = new QTreeWidgetItem({ | ||||||
|                                                     skin.m_visibleName << |       skin.m_visibleName, | ||||||
|                                                     skin.m_version << |       skin.m_version, | ||||||
|                                                     skin.m_author); |       skin.m_author, | ||||||
|  |       skin.m_forcedStyles.isEmpty() ? QChar(10007) : skin.m_forcedStyles.join(QSL(", ")), | ||||||
|  |       skin.m_forcedStylePalette ? QChar(10003) : QChar(10007) }); | ||||||
| 
 | 
 | ||||||
|     new_item->setData(0, Qt::UserRole, QVariant::fromValue(skin)); |     new_item->setData(0, Qt::UserRole, QVariant::fromValue(skin)); | ||||||
| 
 | 
 | ||||||
|  | @ -195,25 +226,6 @@ void SettingsGui::loadSettings() { | ||||||
|     m_ui->m_treeSkins->setCurrentItem(m_ui->m_treeSkins->topLevelItem(0)); |     m_ui->m_treeSkins->setCurrentItem(m_ui->m_treeSkins->topLevelItem(0)); | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   // Load styles.
 |  | ||||||
|   auto styles = QStyleFactory::keys(); |  | ||||||
| 
 |  | ||||||
|   for (const QString& style_name : qAsConst(styles)) { |  | ||||||
|     m_ui->m_cmbStyles->addItem(style_name); |  | ||||||
|   } |  | ||||||
| 
 |  | ||||||
|   int item_style = m_ui->m_cmbStyles->findText(qApp->skins()->currentStyle(), Qt::MatchFlag::MatchFixedString); |  | ||||||
| 
 |  | ||||||
|   if (item_style >= 0) { |  | ||||||
|     m_ui->m_cmbStyles->setCurrentIndex(item_style); |  | ||||||
|   } |  | ||||||
| 
 |  | ||||||
|   if (qApp->skins()->styleIsFrozen()) { |  | ||||||
|     m_ui->m_cmbStyles->setEnabled(false); |  | ||||||
|     m_ui->m_cmbStyles->setToolTip(tr("You cannot change style because it was explicitly selected in your OS settings.\n" |  | ||||||
|                                      "Perhaps it is set with 'QT_STYLE_OVERRIDE' environment variable?")); |  | ||||||
|   } |  | ||||||
| 
 |  | ||||||
|   // Load tab settings.
 |   // Load tab settings.
 | ||||||
|   m_ui->m_checkCloseTabsMiddleClick->setChecked(settings()->value(GROUP(GUI), SETTING(GUI::TabCloseMiddleClick)).toBool()); |   m_ui->m_checkCloseTabsMiddleClick->setChecked(settings()->value(GROUP(GUI), SETTING(GUI::TabCloseMiddleClick)).toBool()); | ||||||
|   m_ui->m_checkCloseTabsDoubleClick->setChecked(settings()->value(GROUP(GUI), SETTING(GUI::TabCloseDoubleClick)).toBool()); |   m_ui->m_checkCloseTabsDoubleClick->setChecked(settings()->value(GROUP(GUI), SETTING(GUI::TabCloseDoubleClick)).toBool()); | ||||||
|  | @ -336,8 +348,6 @@ void SettingsGui::saveSettings() { | ||||||
|   settings()->setValue(GROUP(GUI), GUI::MainWindowStartsHidden, m_ui->m_checkHidden->isChecked()); |   settings()->setValue(GROUP(GUI), GUI::MainWindowStartsHidden, m_ui->m_checkHidden->isChecked()); | ||||||
|   settings()->setValue(GROUP(GUI), GUI::HideMainWindowWhenMinimized, m_ui->m_checkHideWhenMinimized->isChecked()); |   settings()->setValue(GROUP(GUI), GUI::HideMainWindowWhenMinimized, m_ui->m_checkHideWhenMinimized->isChecked()); | ||||||
| 
 | 
 | ||||||
|   settings()->setValue(GROUP(GUI), GUI::ForceDarkFusion, m_ui->m_checkForceDarkFusion->isChecked()); |  | ||||||
| 
 |  | ||||||
| #if (defined(Q_OS_UNIX) && !defined(Q_OS_MACOS)) || defined(Q_OS_WIN) | #if (defined(Q_OS_UNIX) && !defined(Q_OS_MACOS)) || defined(Q_OS_WIN) | ||||||
|   settings()->setValue(GROUP(GUI), GUI::UnreadNumbersOnTaskBar, m_ui->m_displayUnreadMessageCountOnTaskBar->isChecked()); |   settings()->setValue(GROUP(GUI), GUI::UnreadNumbersOnTaskBar, m_ui->m_displayUnreadMessageCountOnTaskBar->isChecked()); | ||||||
| #endif | #endif | ||||||
|  | @ -378,6 +388,10 @@ void SettingsGui::saveSettings() { | ||||||
|     qApp->settings()->setValue(GROUP(GUI), GUI::Style, new_style); |     qApp->settings()->setValue(GROUP(GUI), GUI::Style, new_style); | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|  |   if (m_ui->m_checkForceAlternativePalette->isEnabled()) { | ||||||
|  |     settings()->setValue(GROUP(GUI), GUI::ForceDarkFusion, m_ui->m_checkForceAlternativePalette->isChecked()); | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|   // Save tab settings.
 |   // Save tab settings.
 | ||||||
|   settings()->setValue(GROUP(GUI), GUI::TabCloseMiddleClick, m_ui->m_checkCloseTabsMiddleClick->isChecked()); |   settings()->setValue(GROUP(GUI), GUI::TabCloseMiddleClick, m_ui->m_checkCloseTabsMiddleClick->isChecked()); | ||||||
|   settings()->setValue(GROUP(GUI), GUI::TabCloseDoubleClick, m_ui->m_checkCloseTabsDoubleClick->isChecked()); |   settings()->setValue(GROUP(GUI), GUI::TabCloseDoubleClick, m_ui->m_checkCloseTabsDoubleClick->isChecked()); | ||||||
|  |  | ||||||
|  | @ -24,6 +24,7 @@ class SettingsGui : public SettingsPanel { | ||||||
|     bool eventFilter(QObject* obj, QEvent* e); |     bool eventFilter(QObject* obj, QEvent* e); | ||||||
| 
 | 
 | ||||||
|   private slots: |   private slots: | ||||||
|  |     void updateSkinOptions(); | ||||||
|     void resetCustomSkinColor(); |     void resetCustomSkinColor(); | ||||||
| 
 | 
 | ||||||
|   private: |   private: | ||||||
|  |  | ||||||
|  | @ -101,9 +101,9 @@ | ||||||
|         </spacer> |         </spacer> | ||||||
|        </item> |        </item> | ||||||
|        <item row="2" column="1"> |        <item row="2" column="1"> | ||||||
|         <widget class="QCheckBox" name="m_checkForceDarkFusion"> |         <widget class="QCheckBox" name="m_checkForceAlternativePalette"> | ||||||
|          <property name="text"> |          <property name="text"> | ||||||
|           <string>Force dark look (Fusion only)</string> |           <string>Force alternative color palette defined in skin</string> | ||||||
|          </property> |          </property> | ||||||
|         </widget> |         </widget> | ||||||
|        </item> |        </item> | ||||||
|  | @ -458,7 +458,7 @@ | ||||||
|   <tabstop>m_cmbSelectToolBar</tabstop> |   <tabstop>m_cmbSelectToolBar</tabstop> | ||||||
|   <tabstop>m_cmbIconTheme</tabstop> |   <tabstop>m_cmbIconTheme</tabstop> | ||||||
|   <tabstop>m_cmbStyles</tabstop> |   <tabstop>m_cmbStyles</tabstop> | ||||||
|   <tabstop>m_checkForceDarkFusion</tabstop> |   <tabstop>m_checkForceAlternativePalette</tabstop> | ||||||
|   <tabstop>m_treeSkins</tabstop> |   <tabstop>m_treeSkins</tabstop> | ||||||
|   <tabstop>m_gbCustomSkinColors</tabstop> |   <tabstop>m_gbCustomSkinColors</tabstop> | ||||||
|  </tabstops> |  </tabstops> | ||||||
|  |  | ||||||
|  | @ -42,7 +42,7 @@ void SkinFactory::loadCurrentSkin() { | ||||||
|   qCriticalNN << LOGSEC_GUI << "Failed to load selected or default skin. Quitting!"; |   qCriticalNN << LOGSEC_GUI << "Failed to load selected or default skin. Quitting!"; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| bool SkinFactory::isStyleGoodForDarkVariant(const QString& style_name) const { | bool SkinFactory::isStyleGoodForAlternativeStylePalette(const QString& style_name) const { | ||||||
|   static QRegularExpression re = QRegularExpression("^(fusion)|(qt[56]ct-style)$"); |   static QRegularExpression re = QRegularExpression("^(fusion)|(qt[56]ct-style)$"); | ||||||
| 
 | 
 | ||||||
|   return re.match(style_name.toLower()).hasMatch(); |   return re.match(style_name.toLower()).hasMatch(); | ||||||
|  | @ -55,13 +55,26 @@ void SkinFactory::loadSkinFromData(const Skin& skin) { | ||||||
|   const QString cli_forced_style = qApp->cmdParser()->value(QSL(CLI_STYLE_SHORT)); |   const QString cli_forced_style = qApp->cmdParser()->value(QSL(CLI_STYLE_SHORT)); | ||||||
| 
 | 
 | ||||||
|   if (env_forced_style.isEmpty() && cli_forced_style.isEmpty()) { |   if (env_forced_style.isEmpty() && cli_forced_style.isEmpty()) { | ||||||
|     qApp->setStyle(style_name); |  | ||||||
|     m_styleIsFrozen = false; |     m_styleIsFrozen = false; | ||||||
| 
 | 
 | ||||||
|     qDebugNN << LOGSEC_GUI << "Setting style:" << QUOTE_W_SPACE_DOT(style_name); |     if (!skin.m_forcedStyles.isEmpty()) { | ||||||
|  |       qDebugNN << LOGSEC_GUI << "Forcing one of skin's declared styles:" | ||||||
|  |                << QUOTE_W_SPACE_DOT(skin.m_forcedStyles); | ||||||
|  | 
 | ||||||
|  |       for (const QString& skin_forced_style : skin.m_forcedStyles) { | ||||||
|  |         if (qApp->setStyle(skin_forced_style) != nullptr) { | ||||||
|  |           break; | ||||||
|  |         } | ||||||
|  |       } | ||||||
|  |     } | ||||||
|  |     else { | ||||||
|  |       qDebugNN << LOGSEC_GUI << "Setting style:" << QUOTE_W_SPACE_DOT(style_name); | ||||||
|  |       qApp->setStyle(style_name); | ||||||
|  |     } | ||||||
|   } |   } | ||||||
|   else { |   else { | ||||||
|     m_styleIsFrozen = true; |     m_styleIsFrozen = true; | ||||||
|  | 
 | ||||||
|     qWarningNN << LOGSEC_GUI << "Respecting forced style(s):\n" |     qWarningNN << LOGSEC_GUI << "Respecting forced style(s):\n" | ||||||
|                << "  QT_STYLE_OVERRIDE: " QUOTE_NO_SPACE(env_forced_style) << "\n" |                << "  QT_STYLE_OVERRIDE: " QUOTE_NO_SPACE(env_forced_style) << "\n" | ||||||
|                << "  CLI (-style): " QUOTE_NO_SPACE(cli_forced_style); |                << "  CLI (-style): " QUOTE_NO_SPACE(cli_forced_style); | ||||||
|  | @ -71,86 +84,97 @@ void SkinFactory::loadSkinFromData(const Skin& skin) { | ||||||
|   // they specifically set object name to style name.
 |   // they specifically set object name to style name.
 | ||||||
|   m_currentStyle = qApp->style()->objectName(); |   m_currentStyle = qApp->style()->objectName(); | ||||||
| 
 | 
 | ||||||
|   if (isStyleGoodForDarkVariant(m_currentStyle) && |   if (isStyleGoodForAlternativeStylePalette(m_currentStyle) && | ||||||
|       qApp->settings()->value(GROUP(GUI), SETTING(GUI::ForceDarkFusion)).toBool()) { |  | ||||||
|     qDebugNN << LOGSEC_GUI << "Activating dark palette for Fusion style."; |  | ||||||
| 
 | 
 | ||||||
|     QPalette fusion_palette = qApp->palette(); |       /* Skin has alternative style palette and forces its usage. */ | ||||||
|     QColor clr_maibg(QSL("#2D2F32")); |       ((!skin.m_stylePalette.isEmpty() && skin.m_forcedStylePalette) || | ||||||
|     QColor clr_basbg(QSL("#373A3D")); |  | ||||||
|     QColor clr_altbg(QSL("#323437")); |  | ||||||
|     QColor clr_selbg(QSL("#8291AD")); |  | ||||||
|     QColor clr_selfg(QSL("#FFFFFF")); |  | ||||||
|     QColor clr_btnfg(QSL("#E7E7E7")); |  | ||||||
|     QColor clr_dibfg(QSL("#A7A7A7")); |  | ||||||
|     QColor clr_winfg(QSL("#D8D8D8")); |  | ||||||
|     QColor clr_diwfg(QSL("#999999")); |  | ||||||
|     QColor clr_brdbg(QSL("#202224")); // Use colour picker on dark brdr under list header for this one
 |  | ||||||
|     QColor clr_wlink(QSL("#a1acc1")); |  | ||||||
| 
 | 
 | ||||||
|     //
 |        /* User wants alternative style palette anyway. */ | ||||||
|     // Normal state.
 |        qApp->settings()->value(GROUP(GUI), SETTING(GUI::ForceDarkFusion)).toBool())) { | ||||||
|     //
 |     qDebugNN << LOGSEC_GUI << "Activating alternative palette."; | ||||||
| 
 | 
 | ||||||
|     // Backgrounds & bases.
 |     QPalette pal; | ||||||
|     fusion_palette.setColor(QPalette::ColorRole::Window, clr_maibg); |  | ||||||
|     fusion_palette.setColor(QPalette::ColorRole::Base, clr_basbg); |  | ||||||
|     fusion_palette.setColor(QPalette::ColorRole::Dark, clr_brdbg); |  | ||||||
|     fusion_palette.setColor(QPalette::ColorRole::AlternateBase, clr_altbg); |  | ||||||
|     fusion_palette.setColor(QPalette::ColorRole::Button, clr_altbg); |  | ||||||
|     fusion_palette.setColor(QPalette::ColorRole::Light, clr_altbg); |  | ||||||
|     fusion_palette.setColor(QPalette::ColorRole::Highlight, clr_selbg); |  | ||||||
| 
 | 
 | ||||||
|     // Texts.
 |     if (skin.m_stylePalette.isEmpty()) { | ||||||
|     fusion_palette.setColor(QPalette::ColorRole::ButtonText, clr_btnfg); |       QColor clr_maibg(QSL("#2D2F32")); | ||||||
|     fusion_palette.setColor(QPalette::ColorRole::WindowText, clr_winfg); |       QColor clr_basbg(QSL("#373A3D")); | ||||||
|     fusion_palette.setColor(QPalette::ColorRole::BrightText, clr_basbg); |       QColor clr_altbg(QSL("#323437")); | ||||||
|     fusion_palette.setColor(QPalette::ColorRole::Text, clr_winfg); |       QColor clr_selbg(QSL("#8291AD")); | ||||||
|     fusion_palette.setColor(QPalette::ColorRole::PlaceholderText, clr_dibfg); |       QColor clr_selfg(QSL("#FFFFFF")); | ||||||
|     fusion_palette.setColor(QPalette::ColorRole::Link, clr_wlink); |       QColor clr_btnfg(QSL("#E7E7E7")); | ||||||
|     fusion_palette.setColor(QPalette::ColorRole::LinkVisited, clr_wlink); |       QColor clr_dibfg(QSL("#A7A7A7")); | ||||||
|     fusion_palette.setColor(QPalette::ColorRole::HighlightedText, clr_selfg); |       QColor clr_winfg(QSL("#D8D8D8")); | ||||||
|  |       QColor clr_diwfg(QSL("#999999")); | ||||||
|  |       QColor clr_brdbg(QSL("#202224")); // Use color picker on dark brdr under list header for this one
 | ||||||
|  |       QColor clr_wlink(QSL("#a1acc1")); | ||||||
| 
 | 
 | ||||||
|     //
 |       //
 | ||||||
|     // Inactive state.
 |       // Normal state.
 | ||||||
|     //
 |       //
 | ||||||
| 
 | 
 | ||||||
|     // Backgrounds & bases.
 |       // Backgrounds & bases.
 | ||||||
|  |       pal.setColor(QPalette::ColorRole::Window, clr_maibg); | ||||||
|  |       pal.setColor(QPalette::ColorRole::Base, clr_basbg); | ||||||
|  |       pal.setColor(QPalette::ColorRole::Dark, clr_brdbg); | ||||||
|  |       pal.setColor(QPalette::ColorRole::AlternateBase, clr_altbg); | ||||||
|  |       pal.setColor(QPalette::ColorRole::Button, clr_altbg); | ||||||
|  |       pal.setColor(QPalette::ColorRole::Light, clr_altbg); | ||||||
|  |       pal.setColor(QPalette::ColorRole::Highlight, clr_selbg); | ||||||
| 
 | 
 | ||||||
|     // Texts.
 |       // Texts.
 | ||||||
|  |       pal.setColor(QPalette::ColorRole::ButtonText, clr_btnfg); | ||||||
|  |       pal.setColor(QPalette::ColorRole::WindowText, clr_winfg); | ||||||
|  |       pal.setColor(QPalette::ColorRole::BrightText, clr_basbg); | ||||||
|  |       pal.setColor(QPalette::ColorRole::Text, clr_winfg); | ||||||
|  |       pal.setColor(QPalette::ColorRole::PlaceholderText, clr_dibfg); | ||||||
|  |       pal.setColor(QPalette::ColorRole::Link, clr_wlink); | ||||||
|  |       pal.setColor(QPalette::ColorRole::LinkVisited, clr_wlink); | ||||||
|  |       pal.setColor(QPalette::ColorRole::HighlightedText, clr_selfg); | ||||||
| 
 | 
 | ||||||
|     //
 |       //
 | ||||||
|     // Disabled state.
 |       // Inactive state.
 | ||||||
|     //
 |       //
 | ||||||
| 
 | 
 | ||||||
|     // Backgrounds & bases.
 |       // Backgrounds & bases.
 | ||||||
|     fusion_palette.setColor(QPalette::ColorGroup::Disabled, QPalette::ColorRole::Window, clr_maibg); |  | ||||||
|     fusion_palette.setColor(QPalette::ColorGroup::Disabled, QPalette::ColorRole::Base, clr_basbg); |  | ||||||
|     fusion_palette.setColor(QPalette::ColorGroup::Disabled, QPalette::ColorRole::Dark, clr_brdbg); |  | ||||||
|     fusion_palette.setColor(QPalette::ColorGroup::Disabled, QPalette::ColorRole::AlternateBase, clr_altbg); |  | ||||||
|     fusion_palette.setColor(QPalette::ColorGroup::Disabled, QPalette::ColorRole::Button, clr_altbg); |  | ||||||
|     fusion_palette.setColor(QPalette::ColorGroup::Disabled, QPalette::ColorRole::Light, clr_altbg); |  | ||||||
|     fusion_palette.setColor(QPalette::ColorGroup::Disabled, QPalette::ColorRole::Highlight, clr_selbg); |  | ||||||
| 
 | 
 | ||||||
|     // Texts.
 |       // Texts.
 | ||||||
|     fusion_palette.setColor(QPalette::ColorGroup::Disabled, QPalette::ColorRole::ButtonText, clr_dibfg); |  | ||||||
|     fusion_palette.setColor(QPalette::ColorGroup::Disabled, QPalette::ColorRole::WindowText, clr_diwfg); |  | ||||||
|     fusion_palette.setColor(QPalette::ColorGroup::Disabled, QPalette::ColorRole::BrightText, clr_basbg); |  | ||||||
|     fusion_palette.setColor(QPalette::ColorGroup::Disabled, QPalette::ColorRole::Text, clr_diwfg); |  | ||||||
|     fusion_palette.setColor(QPalette::ColorGroup::Disabled, QPalette::ColorRole::PlaceholderText, clr_dibfg); |  | ||||||
|     fusion_palette.setColor(QPalette::ColorGroup::Disabled, QPalette::ColorRole::Link, clr_wlink); |  | ||||||
|     fusion_palette.setColor(QPalette::ColorGroup::Disabled, QPalette::ColorRole::LinkVisited, clr_wlink); |  | ||||||
|     fusion_palette.setColor(QPalette::ColorGroup::Disabled, QPalette::ColorRole::HighlightedText, clr_selfg); |  | ||||||
| 
 | 
 | ||||||
|     //
 |       //
 | ||||||
|     // Tooltips.
 |       // Disabled state.
 | ||||||
|     //
 |       //
 | ||||||
| 
 | 
 | ||||||
|     fusion_palette.setColor(QPalette::ColorGroup::All, QPalette::ColorRole::ToolTipBase, clr_maibg); |       // Backgrounds & bases.
 | ||||||
|     fusion_palette.setColor(QPalette::ColorGroup::All, QPalette::ColorRole::ToolTipText, clr_winfg); |       pal.setColor(QPalette::ColorGroup::Disabled, QPalette::ColorRole::Window, clr_maibg); | ||||||
|  |       pal.setColor(QPalette::ColorGroup::Disabled, QPalette::ColorRole::Base, clr_basbg); | ||||||
|  |       pal.setColor(QPalette::ColorGroup::Disabled, QPalette::ColorRole::Dark, clr_brdbg); | ||||||
|  |       pal.setColor(QPalette::ColorGroup::Disabled, QPalette::ColorRole::AlternateBase, clr_altbg); | ||||||
|  |       pal.setColor(QPalette::ColorGroup::Disabled, QPalette::ColorRole::Button, clr_altbg); | ||||||
|  |       pal.setColor(QPalette::ColorGroup::Disabled, QPalette::ColorRole::Light, clr_altbg); | ||||||
|  |       pal.setColor(QPalette::ColorGroup::Disabled, QPalette::ColorRole::Highlight, clr_selbg); | ||||||
| 
 | 
 | ||||||
|     QToolTip::setPalette(fusion_palette); |       // Texts.
 | ||||||
|     qApp->setPalette(fusion_palette); |       pal.setColor(QPalette::ColorGroup::Disabled, QPalette::ColorRole::ButtonText, clr_dibfg); | ||||||
|  |       pal.setColor(QPalette::ColorGroup::Disabled, QPalette::ColorRole::WindowText, clr_diwfg); | ||||||
|  |       pal.setColor(QPalette::ColorGroup::Disabled, QPalette::ColorRole::BrightText, clr_basbg); | ||||||
|  |       pal.setColor(QPalette::ColorGroup::Disabled, QPalette::ColorRole::Text, clr_diwfg); | ||||||
|  |       pal.setColor(QPalette::ColorGroup::Disabled, QPalette::ColorRole::PlaceholderText, clr_dibfg); | ||||||
|  |       pal.setColor(QPalette::ColorGroup::Disabled, QPalette::ColorRole::Link, clr_wlink); | ||||||
|  |       pal.setColor(QPalette::ColorGroup::Disabled, QPalette::ColorRole::LinkVisited, clr_wlink); | ||||||
|  |       pal.setColor(QPalette::ColorGroup::Disabled, QPalette::ColorRole::HighlightedText, clr_selfg); | ||||||
|  | 
 | ||||||
|  |       //
 | ||||||
|  |       // Tooltips.
 | ||||||
|  |       //
 | ||||||
|  | 
 | ||||||
|  |       pal.setColor(QPalette::ColorGroup::All, QPalette::ColorRole::ToolTipBase, clr_maibg); | ||||||
|  |       pal.setColor(QPalette::ColorGroup::All, QPalette::ColorRole::ToolTipText, clr_winfg); | ||||||
|  |     } | ||||||
|  |     else { | ||||||
|  |       pal = skin.extractPalette(); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     QToolTip::setPalette(pal); | ||||||
|  |     qApp->setPalette(pal); | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   if (!skin.m_rawData.isEmpty()) { |   if (!skin.m_rawData.isEmpty()) { | ||||||
|  | @ -271,6 +295,49 @@ Skin SkinFactory::skinInfo(const QString& skin_name, bool* ok) const { | ||||||
| 
 | 
 | ||||||
|       skin.m_colorPalette = palette; |       skin.m_colorPalette = palette; | ||||||
| 
 | 
 | ||||||
|  |       // Obtain alternative style palette.
 | ||||||
|  |       skin.m_forcedStyles = skin_node | ||||||
|  |                             .namedItem(QSL("forced-styles")) | ||||||
|  |                             .toElement().text().split(',', | ||||||
|  | #if QT_VERSION >= 0x050F00 // Qt >= 5.15.0
 | ||||||
|  |                                                       Qt::SplitBehaviorFlags::SkipEmptyParts); | ||||||
|  | #else | ||||||
|  |                                                       QString::SplitBehavior::SkipEmptyParts); | ||||||
|  | #endif | ||||||
|  | 
 | ||||||
|  |       skin.m_forcedStylePalette = skin_node.namedItem(QSL("forced-style-palette")).toElement().text() == | ||||||
|  |                                   QVariant(true).toString(); | ||||||
|  | 
 | ||||||
|  |       QDomElement style_palette_root = skin_node.namedItem(QSL("style-palette")).toElement(); | ||||||
|  | 
 | ||||||
|  |       if (!style_palette_root.isNull()) { | ||||||
|  |         const QMetaObject& mop = QPalette::staticMetaObject; | ||||||
|  |         QMetaEnum enumerp = mop.enumerator(mop.indexOfEnumerator(QSL("ColorGroup").toLocal8Bit().constData())); | ||||||
|  |         QMetaEnum enumerx = mop.enumerator(mop.indexOfEnumerator(QSL("ColorRole").toLocal8Bit().constData())); | ||||||
|  | 
 | ||||||
|  |         QMultiHash<QPalette::ColorGroup, QPair<QPalette::ColorRole, QColor>> groups; | ||||||
|  | 
 | ||||||
|  |         QDomNodeList groups_of_palette = style_palette_root.elementsByTagName(QSL("group")); | ||||||
|  | 
 | ||||||
|  |         for (int i = 0; i < groups_of_palette.size(); i++) { | ||||||
|  |           const QDomNode& group_root_nd = groups_of_palette.at(i); | ||||||
|  |           QPalette::ColorGroup group = QPalette::ColorGroup(enumerp.keyToValue(group_root_nd.toElement().attribute(QSL("id")).toLatin1())); | ||||||
|  | 
 | ||||||
|  |           QDomNodeList colors_of_group = group_root_nd.toElement().elementsByTagName(QSL("color")); | ||||||
|  | 
 | ||||||
|  |           for (int j = 0; j < colors_of_group.size(); j++) { | ||||||
|  |             const QDomNode& color_nd = colors_of_group.at(j); | ||||||
|  | 
 | ||||||
|  |             QColor color(color_nd.toElement().text()); | ||||||
|  |             QPalette::ColorRole role = QPalette::ColorRole(enumerx.keyToValue(color_nd.toElement().attribute(QSL("role")).toLatin1())); | ||||||
|  | 
 | ||||||
|  |             groups.insert(group, QPair<QPalette::ColorRole, QColor>(role, color)); | ||||||
|  |           } | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         skin.m_stylePalette = groups; | ||||||
|  |       } | ||||||
|  | 
 | ||||||
|       // Free resources.
 |       // Free resources.
 | ||||||
|       skin_file.close(); |       skin_file.close(); | ||||||
|       skin_file.deleteLater(); |       skin_file.deleteLater(); | ||||||
|  | @ -394,6 +461,27 @@ QVariant Skin::colorForModel(SkinEnums::PaletteColors type, bool ignore_custom_c | ||||||
|       : QVariant(); |       : QVariant(); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | QPalette Skin::extractPalette() const { | ||||||
|  |   QPalette pal; | ||||||
|  |   QList<QPalette::ColorGroup> groups = m_stylePalette.keys(); | ||||||
|  | 
 | ||||||
|  |   if (groups.contains(QPalette::ColorGroup::All)) { | ||||||
|  | 
 | ||||||
|  |     groups.removeAll(QPalette::ColorGroup::All); | ||||||
|  |     groups.insert(0, QPalette::ColorGroup::All); | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   for (QPalette::ColorGroup grp : groups) { | ||||||
|  |     auto roles = m_stylePalette.values(grp); | ||||||
|  | 
 | ||||||
|  |     for (const auto& rl : roles) { | ||||||
|  |       pal.setColor(grp, rl.first, rl.second); | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   return pal; | ||||||
|  | } | ||||||
|  | 
 | ||||||
| QString SkinEnums::palleteColorText(PaletteColors col) { | QString SkinEnums::palleteColorText(PaletteColors col) { | ||||||
|   switch (col) { |   switch (col) { | ||||||
|     case SkinEnums::PaletteColors::FgInteresting: |     case SkinEnums::PaletteColors::FgInteresting: | ||||||
|  |  | ||||||
|  | @ -8,6 +8,7 @@ | ||||||
| #include <QColor> | #include <QColor> | ||||||
| #include <QHash> | #include <QHash> | ||||||
| #include <QMetaType> | #include <QMetaType> | ||||||
|  | #include <QPalette> | ||||||
| #include <QStringList> | #include <QStringList> | ||||||
| #include <QVariant> | #include <QVariant> | ||||||
| 
 | 
 | ||||||
|  | @ -49,8 +50,12 @@ struct RSSGUARD_DLLSPEC Skin { | ||||||
|   QString m_layoutMarkup; |   QString m_layoutMarkup; | ||||||
|   QString m_enclosureMarkup; |   QString m_enclosureMarkup; | ||||||
|   QHash<SkinEnums::PaletteColors, QColor> m_colorPalette; |   QHash<SkinEnums::PaletteColors, QColor> m_colorPalette; | ||||||
|  |   QStringList m_forcedStyles; | ||||||
|  |   bool m_forcedStylePalette; | ||||||
|  |   QMultiHash<QPalette::ColorGroup, QPair<QPalette::ColorRole, QColor>> m_stylePalette; | ||||||
| 
 | 
 | ||||||
|   QVariant colorForModel(SkinEnums::PaletteColors type, bool ignore_custom_colors = false) const; |   QVariant colorForModel(SkinEnums::PaletteColors type, bool ignore_custom_colors = false) const; | ||||||
|  |   QPalette extractPalette() const; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| uint qHash(const SkinEnums::PaletteColors& key); | uint qHash(const SkinEnums::PaletteColors& key); | ||||||
|  | @ -68,7 +73,7 @@ class RSSGUARD_DLLSPEC SkinFactory : public QObject { | ||||||
|     void loadCurrentSkin(); |     void loadCurrentSkin(); | ||||||
|     Skin currentSkin() const; |     Skin currentSkin() const; | ||||||
| 
 | 
 | ||||||
|     bool isStyleGoodForDarkVariant(const QString& style_name) const; |     bool isStyleGoodForAlternativeStylePalette(const QString& style_name) const; | ||||||
| 
 | 
 | ||||||
|     // Returns the name of the skin, that should be activated
 |     // Returns the name of the skin, that should be activated
 | ||||||
|     // after application restart.
 |     // after application restart.
 | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		
		Reference in a new issue