Uniform look for Red Panda C++ under KDE/DDE (#119)

* KDE theme: fix visual problems with KDE dark mode; add system theme

* Make "Light" theme truly light under Breeze Dark theme.
  * With this fix also expose dark mode support on Windows.
* Add "Auto" (system) theme that follows system style and color.
* Add "Adaptive" color scheme for system theme (using transparent background).
* Add support for transparent background in color schemes.

* move `alphaBlend` to utils

* hide Auto (system) theme on Windows
This commit is contained in:
Cyano Hao 2023-07-03 14:06:26 +08:00 committed by GitHub
parent c7a95d9eab
commit e89f4400eb
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
19 changed files with 258 additions and 36 deletions

View File

@ -530,6 +530,10 @@ iconsets_files.files += $$files(resources/iconsets/*.json, true)
theme_files.files += $$files(themes/*.json, false)
theme_files.files += $$files(themes/*.png, false)
windows: {
theme_files.files -= themes/system.json
}
colorscheme_files.files += $$files(colorschemes/*.scheme, false)
colorscheme_files.prefix = /colorschemes

View File

@ -0,0 +1,110 @@
{
"Character" : {
"foreground" : "#ce543b"
},
"Class" : {
"foreground" : "#267f99"
},
"Comment" : {
"foreground" : "#3b9827"
},
"Escape sequences" : {
"foreground" : "#e28346"
},
"Float" : {
"foreground" : "#4bc854"
},
"Function" : {
"foreground" : "#c4b65f"
},
"Global variable" : {
"foreground" : "#2381fe"
},
"Hexadecimal" : {
"foreground" : "#4bc854"
},
"Identifier" : {
"foreground" : "#ce543b"
},
"Illegal Char" : {
"foreground" : "#e63b3b"
},
"Local Variable" : {
"foreground" : "#2381fe"
},
"Number" : {
"foreground" : "#4bc854"
},
"Octal" : {
"foreground" : "#4bc854"
},
"Preprocessor" : {
"foreground" : "#cf46d5"
},
"Reserve Word for Types": {
"foreground": "#336be5"
},
"Reserved Word" : {
"foreground" : "#cf46d5"
},
"Space" : {
"foreground" : "#40808080"
},
"String" : {
"foreground" : "#ce543b"
},
"Symbol" : {
"foreground" : "#e0808080"
},
"Variable" : {
"foreground" : "#2381fe"
},
"Editor Text": {
"foreground" : "#808080",
"background" : "#00000000"
},
"Current Highlighted Word": {
"background": "#20808080"
},
"Selected text" : {
"background" : "#3c55aaff"
},
"Gutter" : {
"foreground" : "#c0808080",
"background" : "#20808080"
},
"Gutter Active Line" : {
"foreground" : "#808080"
},
"Error" : {
"foreground" : "#f52a22"
},
"Active Breakpoint" : {
"foreground" : "#FFFFCE",
"background" : "#00376F"
},
"Fold Line" : {
"foreground" : "#808080"
},
"Active Line" : {
"background" : "#10808080"
},
"Warning" : {
"foreground" : "#c69901"
},
"Indent Guide Line" : {
"foreground" : "#80808080"
},
"brace/parenthesis/bracket level 1" : {
"foreground" : "#569CD6"
},
"brace/parenthesis/bracket level 2" : {
"foreground" : "#E080C0"
},
"brace/parenthesis/bracket level 3" : {
"foreground" : "#D69D85"
},
"brace/parenthesis/bracket level 4" : {
"foreground" : "#4EC9B0"
}
}

View File

@ -5307,7 +5307,7 @@ void Editor::applyColorScheme(const QString& schemeName)
item = pColorManager->getItem(schemeName,COLOR_SCHEME_GUTTER);
if (item) {
gutter().setTextColor(item->foreground());
gutter().setColor(item->background());
gutter().setColor(alphaBlend(palette().color(QPalette::Base), item->background()));
}
item = pColorManager->getItem(schemeName,COLOR_SCHEME_GUTTER_ACTIVE_LINE);
if (item) {
@ -5350,7 +5350,7 @@ void Editor::applyColorScheme(const QString& schemeName)
item = pColorManager->getItem(schemeName,COLOR_SCHEME_TEXT);
if (item) {
this->setForegroundColor(item->foreground());
this->setBackgroundColor(item->background());
this->setBackgroundColor(alphaBlend(palette().color(QPalette::Base), item->background()));
} else {
this->setForegroundColor(palette().color(QPalette::Text));
this->setBackgroundColor(palette().color(QPalette::Base));

View File

@ -243,6 +243,11 @@ void setTheme(const QString& theme) {
int main(int argc, char *argv[])
{
#ifdef Q_OS_WINDOWS
// Make title bar and palette follow system-wide dark mode setting on recent Windows releases.
qputenv("QT_QPA_PLATFORM", "windows:darkmode=2");
#endif
QApplication app(argc, argv);
app.setAttribute(Qt::AA_UseHighDpiPixmaps);
@ -337,11 +342,21 @@ int main(int argc, char *argv[])
if (firstRun) {
//set theme
ChooseThemeDialog themeDialog;
#ifdef Q_OS_WINDOWS
// Qt's default style on Windows is not good.
themeDialog.hideAutoFollowSystemTheme();
#endif
themeDialog.exec();
switch (themeDialog.theme()) {
case ChooseThemeDialog::Theme::AutoFollowSystem:
setTheme("system");
break;
case ChooseThemeDialog::Theme::Dark:
setTheme("dark");
break;
case ChooseThemeDialog::Theme::Light:
setTheme("default");
break;
default:
setTheme("default");
}

View File

@ -67,6 +67,7 @@
#include <QMessageBox>
#include <QMimeData>
#include <QScreen>
#include <QStyleFactory>
#include <QTcpSocket>
#include <QTemporaryFile>
#include <QTextBlock>
@ -867,10 +868,15 @@ void MainWindow::applySettings()
themeManager.setUseCustomTheme(pSettings->environment().useCustomTheme());
try {
PAppTheme appTheme = themeManager.theme(pSettings->environment().theme());
if (appTheme->isDark())
QApplication::setStyle(new DarkFusionStyle());//app takes the onwership
else
QApplication::setStyle(new LightFusionStyle());//app takes the onwership
if (appTheme->useQtFusionStyle()) {
if (appTheme->isDark())
QApplication::setStyle(new DarkFusionStyle());//app takes the onwership
else
QApplication::setStyle(new LightFusionStyle());//app takes the onwership
} else {
QString systemStyle = QStyleFactory::keys()[0]; // Breeze for KDE, etc.
QApplication::setStyle(systemStyle);
}
qApp->setPalette(appTheme->palette());
//fix for qstatusbar bug
mFileEncodingStatus->setPalette(appTheme->palette());
@ -1715,6 +1721,7 @@ void MainWindow::updateActionIcons()
ui->toolbarCode->setIconSize(iconSize);
ui->toolbarCompile->setIconSize(iconSize);
ui->toolbarDebug->setIconSize(iconSize);
ui->toolbarCompilerSet->setIconSize(iconSize);
for (QToolButton* btn: mClassBrowserToolbar->findChildren<QToolButton *>()) {
btn->setIconSize(iconSize);
}

View File

@ -194,6 +194,7 @@ void AppTheme::load(const QString &filename)
QString localeName = obj["name_"+pSettings->environment().language()].toString();
if (!localeName.isEmpty())
mDisplayName = localeName;
mUseQtFusionStyle = obj["useQtFusionStyle"].toBool(true);
mIsDark = obj["isDark"].toBool(false);
mDefaultColorScheme = obj["default scheme"].toString();
mDefaultIconSet = obj["default iconset"].toString();
@ -268,6 +269,11 @@ void AppTheme::setDefaultColorScheme(const QString &newDefaultColorScheme)
mDefaultColorScheme = newDefaultColorScheme;
}
bool AppTheme::useQtFusionStyle() const
{
return mUseQtFusionStyle;
}
bool AppTheme::isDark() const
{
return mIsDark;

View File

@ -80,6 +80,7 @@ public:
void load(const QString& filename);
bool useQtFusionStyle() const;
bool isDark() const;
const QString &defaultColorScheme() const;
@ -98,6 +99,7 @@ private:
QHash<int,QColor> mColors;
QString mName;
QString mDisplayName;
bool mUseQtFusionStyle;
bool mIsDark;
QString mDefaultColorScheme;
QString mDefaultIconSet;

View File

@ -1,6 +1,7 @@
{
"name":"contrast",
"name":"Contract",
"name_zh_CN": "高对比度主题",
"useQtFusionStyle": true,
"isDark": true,
"default scheme": "Twilight",
"default iconset": "contrast",

View File

@ -1,6 +1,7 @@
{
"name":"dark",
"name":"Dark",
"name_zh_CN": "深色主题",
"useQtFusionStyle": true,
"isDark": true,
"default scheme": "VS Code",
"default iconset": "contrast",

View File

@ -1,11 +1,36 @@
{
"name":"light",
"name_zh_CN":"浅色主题",
"isDark":false,
"default scheme": "Intellij Classic",
"default iconset": "newlook",
"palette": {
"PaletteHighlight":"#ffdddddd",
"PaletteHighlightedText":"#ff000000"
}
"name":"Light",
"name_zh_CN": "浅色主题",
"useQtFusionStyle": true,
"isDark": false,
"default scheme": "Intellij Classic",
"default iconset": "newlook",
"palette": {
"PaletteWindow":"#efefef",
"PaletteWindowText":"#000000",
"PaletteBase":"#ffffff",
"PaletteAlternateBase":"#f7f7f7",
"PaletteToolTipBase":"#ffffdc",
"PaletteToolTipText":"#000000",
"PaletteText":"#000000",
"PaletteButton": "#efefef",
"PaletteButtonText":"#000000",
"PaletteBrightText": "#ffffff",
"PaletteHighlight":"#308cc6",
"PaletteHighlightedText":"#ffffff",
"PaletteLink":"#0000ff",
"PaletteLinkVisited":"#ff00ff",
"PaletteLight": "#ffffff",
"PaletteMidLight": "#cacaca",
"PaletteDark":"#9f9f9f",
"PaletteMid": "#b8b8b8",
"PaletteWindowDisabled":"#efefef",
"PaletteWindowTextDisabled":"#bebebe",
"PaletteBaseDisabled":"#efefef",
"PaletteTextDisabled":"#bebebe",
"PaletteButtonDisabled": "#efefef",
"PaletteButtonTextDisabled":"#bebebe",
"PaletteHighlightDisabled":"#919191",
"PaletteHighlightedTextDisabled":"#ffffff"
}
}

View File

@ -0,0 +1,9 @@
{
"name":"Auto (follow system style and color)",
"name_zh_CN":"自动(跟随系统样式和颜色)",
"useQtFusionStyle": false,
"isDark": false,
"default scheme": "Adaptive",
"default iconset": "newlook",
"palette": {}
}

View File

@ -307,6 +307,10 @@
<source>C++</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Auto (follow system style and color)</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>CodeSnippetsManager</name>

View File

@ -409,6 +409,11 @@ p, li { white-space: pre-wrap; }
<source>Light Theme</source>
<translation></translation>
</message>
<message>
<location filename="../widgets/choosethemedialog.ui" line="72"/>
<source>Auto (follow system style and color)</source>
<translation></translation>
</message>
<message>
<location filename="../widgets/choosethemedialog.ui" line="78"/>
<source>Default Language:</source>

View File

@ -216,6 +216,10 @@
<source>C++</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Auto (follow system style and color)</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>CodeSnippetsManager</name>

View File

@ -579,3 +579,13 @@ void openFileFolderInExplorer(const QString &path)
}
}
QColor alphaBlend(const QColor &lower, const QColor &upper) {
qreal wu = upper.alphaF(); // weight of upper color
qreal wl = 1 - wu; // weight of lower color
return QColor(
int(lower.red() * wl + upper.red() * wu),
int(lower.green() * wl + upper.green() * wu),
int(lower.blue() * wl + upper.blue() * wu)
);
}

View File

@ -156,5 +156,6 @@ QString getSizeString(int size);
class QComboBox;
void saveComboHistory(QComboBox* cb,const QString& text);
QColor alphaBlend(const QColor &lower, const QColor &upper);
#endif // UTILS_H

View File

@ -33,9 +33,13 @@ ChooseThemeDialog::~ChooseThemeDialog()
ChooseThemeDialog::Theme ChooseThemeDialog::theme()
{
if (ui->rbAuto->isChecked())
return Theme::AutoFollowSystem;
if (ui->rbDark->isChecked())
return Theme::Dark;
return Theme::Light;
if (ui->rbLight->isChecked())
return Theme::Light;
return Theme::Unknown;
}
ChooseThemeDialog::Language ChooseThemeDialog::language()
@ -48,3 +52,7 @@ void ChooseThemeDialog::on_btnOk_clicked()
accept();
}
void ChooseThemeDialog::hideAutoFollowSystemTheme()
{
ui->rbAuto->hide();
}

View File

@ -29,8 +29,10 @@ class ChooseThemeDialog : public QDialog
public:
enum class Theme {
Unknown = -1,
AutoFollowSystem = 0,
Dark,
Light
Light,
};
enum class Language {
C,
@ -41,6 +43,7 @@ public:
~ChooseThemeDialog();
Theme theme();
Language language();
void hideAutoFollowSystemTheme();
private slots:
void on_btnOk_clicked();

View File

@ -20,14 +20,23 @@
<string>Choose Theme</string>
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="0" column="0">
<widget class="QRadioButton" name="rbDark">
<item row="2" column="1">
<widget class="QLabel" name="label_2">
<property name="frameShape">
<enum>QFrame::Box</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Sunken</enum>
</property>
<property name="text">
<string>Dark Theme</string>
<string/>
</property>
<property name="pixmap">
<pixmap resource="../icons.qrc">:/demos/light.png</pixmap>
</property>
</widget>
</item>
<item row="1" column="0">
<item row="2" column="0">
<widget class="QLabel" name="label">
<property name="frameShape">
<enum>QFrame::Box</enum>
@ -43,26 +52,24 @@
</property>
</widget>
</item>
<item row="0" column="1">
<item row="1" column="0">
<widget class="QRadioButton" name="rbDark">
<property name="text">
<string>Dark Theme</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QRadioButton" name="rbLight">
<property name="text">
<string>Light Theme</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QLabel" name="label_2">
<property name="frameShape">
<enum>QFrame::Box</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Sunken</enum>
</property>
<item row="0" column="0">
<widget class="QRadioButton" name="rbAuto">
<property name="text">
<string/>
</property>
<property name="pixmap">
<pixmap resource="../icons.qrc">:/demos/light.png</pixmap>
<string>Auto (follow system style and color)</string>
</property>
</widget>
</item>