working custom colůors

This commit is contained in:
Martin Rotter 2021-11-25 15:09:30 +01:00
parent fb840a5440
commit 8ae02930f6
15 changed files with 173 additions and 16 deletions

View File

@ -26,7 +26,7 @@
<url type="donation">https://github.com/sponsors/martinrotter</url> <url type="donation">https://github.com/sponsors/martinrotter</url>
<content_rating type="oars-1.1" /> <content_rating type="oars-1.1" />
<releases> <releases>
<release version="4.0.4" date="2021-11-23"/> <release version="4.0.4" date="2021-11-25"/>
</releases> </releases>
<content_rating type="oars-1.0"> <content_rating type="oars-1.0">
<content_attribute id="violence-cartoon">none</content_attribute> <content_attribute id="violence-cartoon">none</content_attribute>

View File

@ -39,11 +39,11 @@ QVariant MessagesForFiltersModel::data(const QModelIndex& index, int role) const
if (m_filteringDecisions.contains(index.row())) { if (m_filteringDecisions.contains(index.row())) {
switch (m_filteringDecisions.value(index.row())) { switch (m_filteringDecisions.value(index.row())) {
case MessageObject::FilteringAction::Accept: case MessageObject::FilteringAction::Accept:
return qApp->skins()->currentSkin().m_colorPalette[SkinEnums::PaletteColors::Allright]; return qApp->skins()->currentSkin().colorForModel(SkinEnums::PaletteColors::Allright);
case MessageObject::FilteringAction::Ignore: case MessageObject::FilteringAction::Ignore:
case MessageObject::FilteringAction::Purge: case MessageObject::FilteringAction::Purge:
return qApp->skins()->currentSkin().m_colorPalette[SkinEnums::PaletteColors::FgError]; return qApp->skins()->currentSkin().colorForModel(SkinEnums::PaletteColors::FgError);
default: default:
break; break;

View File

@ -396,9 +396,9 @@ QVariant MessagesModel::data(const QModelIndex& idx, int role) const {
QVariant dta = m_cache->containsData(idx_important.row()) ? m_cache->data(idx_important) : QSqlQueryModel::data(idx_important); QVariant dta = m_cache->containsData(idx_important.row()) ? m_cache->data(idx_important) : QSqlQueryModel::data(idx_important);
return dta.toInt() == 1 return dta.toInt() == 1
? qApp->skins()->currentSkin().m_colorPalette[role == Qt::ItemDataRole::ForegroundRole ? qApp->skins()->currentSkin().colorForModel(role == Qt::ItemDataRole::ForegroundRole
? SkinEnums::PaletteColors::FgInteresting ? SkinEnums::PaletteColors::FgInteresting
: SkinEnums::PaletteColors::FgSelectedInteresting] : SkinEnums::PaletteColors::FgSelectedInteresting)
: QVariant(); : QVariant();
} }
@ -407,9 +407,9 @@ QVariant MessagesModel::data(const QModelIndex& idx, int role) const {
QVariant dta = m_cache->containsData(idx_read.row()) ? m_cache->data(idx_read) : QSqlQueryModel::data(idx_read); QVariant dta = m_cache->containsData(idx_read.row()) ? m_cache->data(idx_read) : QSqlQueryModel::data(idx_read);
return dta.toInt() == 0 return dta.toInt() == 0
? qApp->skins()->currentSkin().m_colorPalette[role == Qt::ItemDataRole::ForegroundRole ? qApp->skins()->currentSkin().colorForModel(role == Qt::ItemDataRole::ForegroundRole
? SkinEnums::PaletteColors::FgInteresting ? SkinEnums::PaletteColors::FgInteresting
: SkinEnums::PaletteColors::FgSelectedInteresting] : SkinEnums::PaletteColors::FgSelectedInteresting)
: QVariant(); : QVariant();
} }

View File

@ -163,13 +163,17 @@ QString MessageBrowser::prepareHtmlForMessage(const Message& message) {
.replace(QL1C('\r'), QL1C('\n')) .replace(QL1C('\r'), QL1C('\n'))
.remove(QL1C('\n'));*/ .remove(QL1C('\n'));*/
// TODO: If FgInteresting not defined by the skin
// use current pallette/Highlight color perhaps.E
return QSL("<html>" return QSL("<html>"
"<head><style>" "<head><style>"
"a { color: %2; }" "a { color: %2; }"
"</style></head>" "</style></head>"
"<body>%1</body>" "<body>%1</body>"
"</html>").arg(html, "</html>").arg(html,
qApp->skins()->currentSkin().m_colorPalette[SkinEnums::PaletteColors::FgInteresting].name()); qApp->skins()->currentSkin()
.colorForModel(SkinEnums::PaletteColors::FgInteresting)
.value<QColor>().name());
} }
bool MessageBrowser::eventFilter(QObject* watched, QEvent* event) { bool MessageBrowser::eventFilter(QObject* watched, QEvent* event) {

View File

@ -29,8 +29,14 @@ QColor ColorToolButton::color() const {
} }
void ColorToolButton::setColor(const QColor& color) { void ColorToolButton::setColor(const QColor& color) {
bool changed = m_color != color;
m_color = color; m_color = color;
if (changed) {
emit colorChanged(m_color);
}
repaint(); repaint();
} }

View File

@ -271,7 +271,6 @@ Authors of this application are NOT responsible for lost data.</string>
<zorder>m_stackedDatabaseDriver</zorder> <zorder>m_stackedDatabaseDriver</zorder>
<zorder>m_checkUseTransactions</zorder> <zorder>m_checkUseTransactions</zorder>
<zorder>m_lblDataStorageWarning</zorder> <zorder>m_lblDataStorageWarning</zorder>
<zorder>verticalSpacer</zorder>
</widget> </widget>
<customwidgets> <customwidgets>
<customwidget> <customwidget>

View File

@ -5,6 +5,8 @@
#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"
#include "gui/reusable/colortoolbutton.h"
#include "gui/reusable/plaintoolbutton.h"
#include "gui/systemtrayicon.h" #include "gui/systemtrayicon.h"
#include "gui/tabwidget.h" #include "gui/tabwidget.h"
#include "gui/toolbars/feedstoolbar.h" #include "gui/toolbars/feedstoolbar.h"
@ -15,6 +17,8 @@
#include "miscellaneous/settings.h" #include "miscellaneous/settings.h"
#include <QDropEvent> #include <QDropEvent>
#include <QMetaEnum>
#include <QMetaObject>
#include <QStyleFactory> #include <QStyleFactory>
SettingsGui::SettingsGui(Settings* settings, QWidget* parent) : SettingsPanel(settings, parent), m_ui(new Ui::SettingsGui) { SettingsGui::SettingsGui(Settings* settings, QWidget* parent) : SettingsPanel(settings, parent), m_ui(new Ui::SettingsGui) {
@ -30,8 +34,12 @@ SettingsGui::SettingsGui(Settings* settings, QWidget* parent) : SettingsPanel(se
<< /*: Version column of skin list. */ tr("Version") << /*: Version column of skin list. */ tr("Version")
<< tr("Author")); << tr("Author"));
m_ui->m_helpCustomSkinColors->setHelpText(tr("You can override some colors defined by your skin here. "
"Some colors are used dynamically throughout the application."), false);
// Setup skins. // Setup skins.
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);
@ -64,6 +72,8 @@ SettingsGui::SettingsGui(Settings* settings, QWidget* parent) : SettingsPanel(se
connect(m_ui->m_cmbStyles, static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged), this, &SettingsGui::dirtifySettings); connect(m_ui->m_cmbStyles, static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged), this, &SettingsGui::dirtifySettings);
connect(m_ui->m_cmbSelectToolBar, static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged), m_ui->m_stackedToolbars, connect(m_ui->m_cmbSelectToolBar, static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged), m_ui->m_stackedToolbars,
&QStackedWidget::setCurrentIndex); &QStackedWidget::setCurrentIndex);
connect(m_ui->m_gbCustomSkinColors, &QGroupBox::toggled, this, &SettingsGui::dirtifySettings);
connect(m_ui->m_gbCustomSkinColors, &QGroupBox::toggled, this, &SettingsGui::requireRestart);
} }
SettingsGui::~SettingsGui() { SettingsGui::~SettingsGui() {
@ -198,12 +208,74 @@ void SettingsGui::loadSettings() {
m_ui->m_editorFeedsToolbar->loadFromToolBar(qApp->mainForm()->tabWidget()->feedMessageViewer()->feedsToolBar()); m_ui->m_editorFeedsToolbar->loadFromToolBar(qApp->mainForm()->tabWidget()->feedMessageViewer()->feedsToolBar());
m_ui->m_editorMessagesToolbar->loadFromToolBar(qApp->mainForm()->tabWidget()->feedMessageViewer()->messagesToolBar()); m_ui->m_editorMessagesToolbar->loadFromToolBar(qApp->mainForm()->tabWidget()->feedMessageViewer()->messagesToolBar());
m_ui->m_editorStatusbar->loadFromToolBar(qApp->mainForm()->statusBar()); m_ui->m_editorStatusbar->loadFromToolBar(qApp->mainForm()->statusBar());
// Load custom colors.
m_ui->m_gbCustomSkinColors->setChecked(settings()->value(GROUP(CustomSkinColors),
SETTING(CustomSkinColors::Enabled)).toBool());
const QMetaObject& mo = SkinEnums::staticMetaObject;
QMetaEnum enumer = mo.enumerator(mo.indexOfEnumerator(QSL("PaletteColors").toLocal8Bit().constData()));
for (int i = 0, row = 0; i < enumer.keyCount(); i++, row++) {
SkinEnums::PaletteColors pal = SkinEnums::PaletteColors(enumer.value(i));
auto* clr_btn = new ColorToolButton(this);
auto* rst_btn = new PlainToolButton(this);
rst_btn->setToolTip(tr("Fetch color from activated skin"));
rst_btn->setIcon(qApp->icons()->fromTheme(QSL("edit-reset")));
QColor clr = settings()->value(GROUP(CustomSkinColors), enumer.key(i)).toString();
if (!clr.isValid()) {
clr = qApp->skins()->currentSkin().colorForModel(pal).value<QColor>();
}
rst_btn->setObjectName(QString::number(enumer.value(i)));
connect(rst_btn, &PlainToolButton::clicked, this, &SettingsGui::resetCustomSkinColor);
connect(clr_btn, &ColorToolButton::colorChanged, this, &SettingsGui::dirtifySettings);
connect(clr_btn, &ColorToolButton::colorChanged, this, &SettingsGui::requireRestart);
clr_btn->setObjectName(QString::number(enumer.value(i)));
clr_btn->setColor(clr);
auto* lay = new QHBoxLayout(this);
lay->addWidget(clr_btn);
lay->addWidget(rst_btn);
m_ui->m_layoutCustomColors->setWidget(row, QFormLayout::ItemRole::LabelRole, new QLabel(enumer.key(i), this));
m_ui->m_layoutCustomColors->setLayout(row, QFormLayout::ItemRole::FieldRole, lay);
}
onEndLoadSettings(); onEndLoadSettings();
} }
void SettingsGui::resetCustomSkinColor() {
auto* clr_btn = m_ui->m_gbCustomSkinColors->findChild<ColorToolButton*>(sender()->objectName());
SkinEnums::PaletteColors pal = SkinEnums::PaletteColors(sender()->objectName().toInt());
clr_btn->setColor(qApp->skins()->currentSkin().colorForModel(pal, true).value<QColor>());
}
void SettingsGui::saveSettings() { void SettingsGui::saveSettings() {
onBeginSaveSettings(); onBeginSaveSettings();
// Save custom skin colors.
settings()->setValue(GROUP(CustomSkinColors), CustomSkinColors::Enabled, m_ui->m_gbCustomSkinColors->isChecked());
const QMetaObject& mo = SkinEnums::staticMetaObject;
QMetaEnum enumer = mo.enumerator(mo.indexOfEnumerator(QSL("PaletteColors").toLocal8Bit().constData()));
auto children = m_ui->m_gbCustomSkinColors->findChildren<ColorToolButton*>();
for (const ColorToolButton* clr : children) {
settings()->setValue(GROUP(CustomSkinColors),
enumer.valueToKey(clr->objectName().toInt()),
clr->color().name());
}
// Save toolbar. // Save toolbar.
settings()->setValue(GROUP(GUI), GUI::ToolbarStyle, settings()->setValue(GROUP(GUI), GUI::ToolbarStyle,
m_ui->m_cmbToolbarButtonStyle->itemData(m_ui->m_cmbToolbarButtonStyle->currentIndex())); m_ui->m_cmbToolbarButtonStyle->itemData(m_ui->m_cmbToolbarButtonStyle->currentIndex()));

View File

@ -23,6 +23,9 @@ class SettingsGui : public SettingsPanel {
// Does check of controls before dialog can be submitted. // Does check of controls before dialog can be submitted.
bool eventFilter(QObject* obj, QEvent* e); bool eventFilter(QObject* obj, QEvent* e);
private slots:
void resetCustomSkinColor();
private: private:
Ui::SettingsGui* m_ui; Ui::SettingsGui* m_ui;
}; };

View File

@ -20,7 +20,7 @@
<item> <item>
<widget class="QTabWidget" name="m_tabUi"> <widget class="QTabWidget" name="m_tabUi">
<property name="currentIndex"> <property name="currentIndex">
<number>0</number> <number>1</number>
</property> </property>
<widget class="QWidget" name="m_tabIconSkin"> <widget class="QWidget" name="m_tabIconSkin">
<attribute name="title"> <attribute name="title">
@ -109,6 +109,27 @@
</item> </item>
</layout> </layout>
</widget> </widget>
<widget class="QWidget" name="m_tabCustomSkinColors">
<attribute name="title">
<string>Custom skin colors</string>
</attribute>
<layout class="QFormLayout">
<item row="1" column="0" colspan="2">
<widget class="HelpSpoiler" name="m_helpCustomSkinColors" native="true"/>
</item>
<item row="2" column="0">
<widget class="QGroupBox" name="m_gbCustomSkinColors">
<property name="title">
<string>Force custom skin colors</string>
</property>
<property name="checkable">
<bool>true</bool>
</property>
<layout class="QFormLayout" name="m_layoutCustomColors"/>
</widget>
</item>
</layout>
</widget>
<widget class="QWidget" name="m_tabNotifications"> <widget class="QWidget" name="m_tabNotifications">
<attribute name="title"> <attribute name="title">
<string>Tray area</string> <string>Tray area</string>
@ -374,6 +395,12 @@
<header>toolbareditor.h</header> <header>toolbareditor.h</header>
<container>1</container> <container>1</container>
</customwidget> </customwidget>
<customwidget>
<class>HelpSpoiler</class>
<extends>QWidget</extends>
<header>helpspoiler.h</header>
<container>1</container>
</customwidget>
</customwidgets> </customwidgets>
<tabstops> <tabstops>
<tabstop>m_tabUi</tabstop> <tabstop>m_tabUi</tabstop>

View File

@ -323,7 +323,8 @@ void WebViewer::onLinkHovered(const QString& url) {
{ url, url, QSystemTrayIcon::MessageIcon::NoIcon }, { url, url, QSystemTrayIcon::MessageIcon::NoIcon },
{ false, false, true }); { false, false, true });
QToolTip::showText(QCursor::pos(), url, {}, {}, 6000); // NOTE: Disable for now, not needed.
//QToolTip::showText(QCursor::pos(), url, {}, {}, 6000);
} }
void WebViewer::openUrlWithExternalTool(ExternalTool tool, const QString& target_url) { void WebViewer::openUrlWithExternalTool(ExternalTool tool, const QString& target_url) {

View File

@ -134,6 +134,12 @@ NON_CONST_DVALUE(QString) Messages::PreviewerFontStandardDef = QFont(QFont().fam
DKEY Messages::ListFont = "list_font"; DKEY Messages::ListFont = "list_font";
// Custom skin colors.
DKEY CustomSkinColors::ID = "custom_skin_colors";
DKEY CustomSkinColors::Enabled = "enabled";
DVALUE(bool) CustomSkinColors::EnabledDef = false;
// GUI. // GUI.
DKEY GUI::ID = "gui"; DKEY GUI::ID = "gui";

View File

@ -152,6 +152,16 @@ namespace Messages {
KEY ListFont; KEY ListFont;
} }
// Custom skin colors.
namespace CustomSkinColors {
KEY ID;
KEY Enabled;
VALUE(bool) EnabledDef;
KEY CustomSkinColors;
}
// GUI. // GUI.
namespace GUI { namespace GUI {
KEY ID; KEY ID;

View File

@ -10,6 +10,7 @@
#include <QDomElement> #include <QDomElement>
#include <QMetaEnum> #include <QMetaEnum>
#include <QMetaObject> #include <QMetaObject>
#include <QProcessEnvironment>
#include <QStyleFactory> #include <QStyleFactory>
#include <QToolTip> #include <QToolTip>
@ -50,8 +51,17 @@ bool SkinFactory::isStyleGoodForDarkVariant(const QString& style_name) const {
void SkinFactory::loadSkinFromData(const Skin& skin) { void SkinFactory::loadSkinFromData(const Skin& skin) {
QString style_name = qApp->settings()->value(GROUP(GUI), SETTING(GUI::Style)).toString(); QString style_name = qApp->settings()->value(GROUP(GUI), SETTING(GUI::Style)).toString();
auto env = QProcessEnvironment::systemEnvironment();
QString over_style = env.value(QSL("QT_STYLE_OVERRIDE"));
qApp->setStyle(style_name); if (over_style.isEmpty()) {
qApp->setStyle(style_name);
qDebugNN << LOGSEC_GUI << "Setting style:" << QUOTE_W_SPACE_DOT(style_name);
}
else {
qDebugNN << LOGSEC_GUI << "Respecting forced style:" << QUOTE_W_SPACE_DOT(over_style);
}
if (isStyleGoodForDarkVariant(style_name) && if (isStyleGoodForDarkVariant(style_name) &&
qApp->settings()->value(GROUP(GUI), SETTING(GUI::ForceDarkFusion)).toBool()) { qApp->settings()->value(GROUP(GUI), SETTING(GUI::ForceDarkFusion)).toBool()) {
@ -317,3 +327,19 @@ QList<Skin> SkinFactory::installedSkins() const {
uint qHash(const SkinEnums::PaletteColors& key) { uint qHash(const SkinEnums::PaletteColors& key) {
return uint(key); return uint(key);
} }
QVariant Skin::colorForModel(SkinEnums::PaletteColors type, bool ignore_custom_colors) const {
if (!ignore_custom_colors) {
const QMetaObject& mo = SkinEnums::staticMetaObject;
QMetaEnum enumer = mo.enumerator(mo.indexOfEnumerator(QSL("PaletteColors").toLocal8Bit().constData()));
QColor custom_clr = qApp->settings()->value(GROUP(CustomSkinColors), enumer.valueToKey(int(type))).toString();
if (custom_clr.isValid()) {
return custom_clr;
}
}
return m_colorPalette.contains(type)
? m_colorPalette[type]
: QVariant();
}

View File

@ -9,6 +9,7 @@
#include <QHash> #include <QHash>
#include <QMetaType> #include <QMetaType>
#include <QStringList> #include <QStringList>
#include <QVariant>
class SkinEnums : public QObject { class SkinEnums : public QObject {
Q_OBJECT Q_OBJECT
@ -46,6 +47,8 @@ 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;
QVariant colorForModel(SkinEnums::PaletteColors type, bool ignore_custom_colors = false) const;
}; };
uint qHash(const SkinEnums::PaletteColors& key); uint qHash(const SkinEnums::PaletteColors& key);

View File

@ -56,13 +56,13 @@ QVariant Feed::data(int column, int role) const {
case HIGHLIGHTED_FOREGROUND_TITLE_ROLE: case HIGHLIGHTED_FOREGROUND_TITLE_ROLE:
switch (status()) { switch (status()) {
case Status::NewMessages: case Status::NewMessages:
return qApp->skins()->currentSkin().m_colorPalette[SkinEnums::PaletteColors::FgSelectedInteresting]; return qApp->skins()->currentSkin().colorForModel(SkinEnums::PaletteColors::FgSelectedInteresting);
case Status::NetworkError: case Status::NetworkError:
case Status::ParsingError: case Status::ParsingError:
case Status::AuthError: case Status::AuthError:
case Status::OtherError: case Status::OtherError:
return qApp->skins()->currentSkin().m_colorPalette[SkinEnums::PaletteColors::FgSelectedError]; return qApp->skins()->currentSkin().colorForModel(SkinEnums::PaletteColors::FgSelectedError);
default: default:
return QVariant(); return QVariant();
@ -71,13 +71,13 @@ QVariant Feed::data(int column, int role) const {
case Qt::ItemDataRole::ForegroundRole: case Qt::ItemDataRole::ForegroundRole:
switch (status()) { switch (status()) {
case Status::NewMessages: case Status::NewMessages:
return qApp->skins()->currentSkin().m_colorPalette[SkinEnums::PaletteColors::FgInteresting]; return qApp->skins()->currentSkin().colorForModel(SkinEnums::PaletteColors::FgInteresting);
case Status::NetworkError: case Status::NetworkError:
case Status::ParsingError: case Status::ParsingError:
case Status::AuthError: case Status::AuthError:
case Status::OtherError: case Status::OtherError:
return qApp->skins()->currentSkin().m_colorPalette[SkinEnums::PaletteColors::FgError]; return qApp->skins()->currentSkin().colorForModel(SkinEnums::PaletteColors::FgError);
default: default:
return QVariant(); return QVariant();