diff --git a/NEWS.md b/NEWS.md index 0f01c6e0..f90c9420 100644 --- a/NEWS.md +++ b/NEWS.md @@ -1,6 +1,8 @@ Version 0.6.8 - enhancement: add link to cppreference in the help menu - fix: add mutex lock to prevent editor crash in rare conditions + - fix: In the create project dialog, the browser button doesn't work + - change: use QStyle to implement the dark style Version 0.6.7 - fix: messages send to the gdb process's standard error are not received diff --git a/RedPandaIDE/RedPandaIDE.pro b/RedPandaIDE/RedPandaIDE.pro index 51edaba3..0a0b54fe 100644 --- a/RedPandaIDE/RedPandaIDE.pro +++ b/RedPandaIDE/RedPandaIDE.pro @@ -112,6 +112,7 @@ SOURCES += \ widgets/coloredit.cpp \ widgets/consolewidget.cpp \ widgets/custommakefileinfodialog.cpp \ + widgets/darkfusionstyle.cpp \ widgets/filepropertiesdialog.cpp \ widgets/functiontooltipwidget.cpp \ widgets/headercompletionpopup.cpp \ @@ -225,6 +226,7 @@ HEADERS += \ widgets/coloredit.h \ widgets/consolewidget.h \ widgets/custommakefileinfodialog.h \ + widgets/darkfusionstyle.h \ widgets/filepropertiesdialog.h \ widgets/functiontooltipwidget.h \ widgets/headercompletionpopup.h \ @@ -291,9 +293,7 @@ RESOURCES += \ codes.qrc \ colorschemes.qrc \ defaultconfigs.qrc \ - themes/dark/dark.qrc \ - themes/light/light.qrc \ - themes/dracula/dracula.qrc \ + themes.qrc \ icons.qrc \ translations.qrc diff --git a/RedPandaIDE/mainwindow.cpp b/RedPandaIDE/mainwindow.cpp index 1bbb75be..15d7961b 100644 --- a/RedPandaIDE/mainwindow.cpp +++ b/RedPandaIDE/mainwindow.cpp @@ -16,6 +16,8 @@ #include "widgets/aboutdialog.h" #include "shortcutmanager.h" #include "colorscheme.h" +#include "thememanager.h" +#include "widgets/darkfusionstyle.h" #include #include @@ -413,12 +415,19 @@ void MainWindow::updateEditorColorSchemes() void MainWindow::applySettings() { - changeTheme(pSettings->environment().theme()); + //changeTheme(pSettings->environment().theme()); + ThemeManager themeManager; + PAppTheme appTheme = themeManager.theme(pSettings->environment().theme()); + if (appTheme->isDark()) + QApplication::setStyle(new DarkFusionStyle()); + else + QApplication::setStyle("fusion"); + qApp->setPalette(appTheme->palette()); + QFont font(pSettings->environment().interfaceFont(), pSettings->environment().interfaceFontSize()); font.setStyleStrategy(QFont::PreferAntialias); - QApplication * app = dynamic_cast(QApplication::instance()); - app->setFont(font); + qApp->setFont(font); this->setFont(font); updateDebuggerSettings(); } diff --git a/RedPandaIDE/mainwindow.ui b/RedPandaIDE/mainwindow.ui index 3eb3509b..145ceccf 100644 --- a/RedPandaIDE/mainwindow.ui +++ b/RedPandaIDE/mainwindow.ui @@ -324,6 +324,9 @@ false + + true + QAbstractItemView::SingleSelection @@ -470,7 +473,7 @@ QTabWidget::North - 0 + 1 @@ -520,6 +523,9 @@ + + true + QAbstractItemView::SingleSelection @@ -555,6 +561,9 @@ + + true + QAbstractItemView::SingleSelection diff --git a/RedPandaIDE/qsynedit/TextBuffer.h b/RedPandaIDE/qsynedit/TextBuffer.h index c607a916..65d52067 100644 --- a/RedPandaIDE/qsynedit/TextBuffer.h +++ b/RedPandaIDE/qsynedit/TextBuffer.h @@ -215,7 +215,8 @@ public: signals: void addedUndo(); - +protected: + void EnsureMaxEntries(); protected: int mBlockChangeNumber; int mBlockCount; @@ -226,7 +227,6 @@ protected: int mNextChangeNumber; int mInitialChangeNumber; bool mInsideRedo; - void EnsureMaxEntries(); }; using PSynEditUndoList = std::shared_ptr; diff --git a/RedPandaIDE/settingsdialog/compilerautolinkwidget.ui b/RedPandaIDE/settingsdialog/compilerautolinkwidget.ui index 91c655fa..c91a6c4a 100644 --- a/RedPandaIDE/settingsdialog/compilerautolinkwidget.ui +++ b/RedPandaIDE/settingsdialog/compilerautolinkwidget.ui @@ -78,6 +78,9 @@ + + true + Qt::ElideNone diff --git a/RedPandaIDE/settingsdialog/compilersetdirectorieswidget.ui b/RedPandaIDE/settingsdialog/compilersetdirectorieswidget.ui index a6d77fbb..03eb77e2 100644 --- a/RedPandaIDE/settingsdialog/compilersetdirectorieswidget.ui +++ b/RedPandaIDE/settingsdialog/compilersetdirectorieswidget.ui @@ -122,6 +122,9 @@ Qt::MoveAction + + true + diff --git a/RedPandaIDE/settingsdialog/editorsnippetwidget.ui b/RedPandaIDE/settingsdialog/editorsnippetwidget.ui index 1ae37c1f..476a72d9 100644 --- a/RedPandaIDE/settingsdialog/editorsnippetwidget.ui +++ b/RedPandaIDE/settingsdialog/editorsnippetwidget.ui @@ -35,6 +35,9 @@ + + true + QAbstractItemView::SingleSelection diff --git a/RedPandaIDE/settingsdialog/environmentappearencewidget.cpp b/RedPandaIDE/settingsdialog/environmentappearencewidget.cpp index d784274a..f0ac37e6 100644 --- a/RedPandaIDE/settingsdialog/environmentappearencewidget.cpp +++ b/RedPandaIDE/settingsdialog/environmentappearencewidget.cpp @@ -13,12 +13,12 @@ EnvironmentAppearenceWidget::EnvironmentAppearenceWidget(const QString& name, co ui->setupUi(this); ui->cbTheme->addItem("default"); ui->cbTheme->addItem("dark"); - ui->cbTheme->addItem("dracula"); - ui->cbTheme->addItem("light"); - QStyleFactory factory; - for (QString name:factory.keys()) { - ui->cbTheme->addItem(name); - } +// ui->cbTheme->addItem("dracula"); +// ui->cbTheme->addItem("light"); +// QStyleFactory factory; +// for (QString name:factory.keys()) { +// ui->cbTheme->addItem(name); +// } ui->cbLanguage->addItem("English","en"); ui->cbLanguage->addItem(tr("Simplified Chinese"),"zh_CN"); } diff --git a/RedPandaIDE/settingsdialog/environmentappearencewidget.ui b/RedPandaIDE/settingsdialog/environmentappearencewidget.ui index ae620a06..c6272357 100644 --- a/RedPandaIDE/settingsdialog/environmentappearencewidget.ui +++ b/RedPandaIDE/settingsdialog/environmentappearencewidget.ui @@ -98,7 +98,11 @@ 0 - + + + false + + diff --git a/RedPandaIDE/settingsdialog/environmentfileassociationwidget.ui b/RedPandaIDE/settingsdialog/environmentfileassociationwidget.ui index 24122b3b..f5254dd1 100644 --- a/RedPandaIDE/settingsdialog/environmentfileassociationwidget.ui +++ b/RedPandaIDE/settingsdialog/environmentfileassociationwidget.ui @@ -21,7 +21,11 @@ - + + + true + + diff --git a/RedPandaIDE/settingsdialog/environmentshortcutwidget.ui b/RedPandaIDE/settingsdialog/environmentshortcutwidget.ui index f74abf2f..5b1854b9 100644 --- a/RedPandaIDE/settingsdialog/environmentshortcutwidget.ui +++ b/RedPandaIDE/settingsdialog/environmentshortcutwidget.ui @@ -16,6 +16,9 @@ + + true + true diff --git a/RedPandaIDE/settingsdialog/projectcompileparamaterswidget.ui b/RedPandaIDE/settingsdialog/projectcompileparamaterswidget.ui index 4fc8cd54..505a1617 100644 --- a/RedPandaIDE/settingsdialog/projectcompileparamaterswidget.ui +++ b/RedPandaIDE/settingsdialog/projectcompileparamaterswidget.ui @@ -38,7 +38,7 @@ - 2 + 0 diff --git a/RedPandaIDE/settingsdialog/projectgeneralwidget.ui b/RedPandaIDE/settingsdialog/projectgeneralwidget.ui index 2f8968a2..2369ca5f 100644 --- a/RedPandaIDE/settingsdialog/projectgeneralwidget.ui +++ b/RedPandaIDE/settingsdialog/projectgeneralwidget.ui @@ -6,7 +6,7 @@ 0 0 - 674 + 685 639 @@ -207,6 +207,9 @@ QAbstractItemView::NoEditTriggers + + true + QListView::Fixed diff --git a/RedPandaIDE/settingsdialog/toolsgeneralwidget.ui b/RedPandaIDE/settingsdialog/toolsgeneralwidget.ui index 8a1d9eb9..ac73ee8f 100644 --- a/RedPandaIDE/settingsdialog/toolsgeneralwidget.ui +++ b/RedPandaIDE/settingsdialog/toolsgeneralwidget.ui @@ -83,7 +83,11 @@ 0 - + + + true + + diff --git a/RedPandaIDE/thememanager.cpp b/RedPandaIDE/thememanager.cpp index 9247b215..70c4361d 100644 --- a/RedPandaIDE/thememanager.cpp +++ b/RedPandaIDE/thememanager.cpp @@ -1,6 +1,162 @@ #include "thememanager.h" +#include +#include +#include +#include +#include +#include +#include +#include "utils.h" ThemeManager::ThemeManager(QObject *parent) : QObject(parent) { } + +PAppTheme ThemeManager::theme(const QString &themeName) +{ + PAppTheme appTheme = std::make_shared(); + appTheme->load(QString(":/themes/%1.json").arg(themeName)); + return appTheme; +} + +AppTheme::AppTheme(QObject *parent):QObject(parent) +{ + +} + +QColor AppTheme::color(ColorRole role) const +{ + return mColors.value(role,QColor()); +} + +QPalette AppTheme::palette() const +{ + QPalette pal = initialPalette(); + + const static struct { + ColorRole themeColor; + QPalette::ColorRole paletteColorRole; + QPalette::ColorGroup paletteColorGroup; + bool setColorRoleAsBrush; + } mapping[] = { + {ColorRole::PaletteWindow, QPalette::Window, QPalette::All, false}, + {ColorRole::PaletteWindowDisabled, QPalette::Window, QPalette::Disabled, false}, + {ColorRole::PaletteWindowText, QPalette::WindowText, QPalette::All, true}, + {ColorRole::PaletteWindowTextDisabled, QPalette::WindowText, QPalette::Disabled, true}, + {ColorRole::PaletteBase, QPalette::Base, QPalette::All, false}, + {ColorRole::PaletteBaseDisabled, QPalette::Base, QPalette::Disabled, false}, + {ColorRole::PaletteAlternateBase, QPalette::AlternateBase, QPalette::All, false}, + {ColorRole::PaletteAlternateBaseDisabled, QPalette::AlternateBase, QPalette::Disabled, false}, + {ColorRole::PaletteToolTipBase, QPalette::ToolTipBase, QPalette::All, true}, + {ColorRole::PaletteToolTipBaseDisabled, QPalette::ToolTipBase, QPalette::Disabled, true}, + {ColorRole::PaletteToolTipText, QPalette::ToolTipText, QPalette::All, false}, + {ColorRole::PaletteToolTipTextDisabled, QPalette::ToolTipText, QPalette::Disabled, false}, + {ColorRole::PaletteText, QPalette::Text, QPalette::All, true}, + {ColorRole::PaletteTextDisabled, QPalette::Text, QPalette::Disabled, true}, + {ColorRole::PaletteButton, QPalette::Button, QPalette::All, false}, + {ColorRole::PaletteButtonDisabled, QPalette::Button, QPalette::Disabled, false}, + {ColorRole::PaletteButtonText, QPalette::ButtonText, QPalette::All, true}, + {ColorRole::PaletteButtonTextDisabled, QPalette::ButtonText, QPalette::Disabled, true}, + {ColorRole::PaletteBrightText, QPalette::BrightText, QPalette::All, false}, + {ColorRole::PaletteBrightTextDisabled, QPalette::BrightText, QPalette::Disabled, false}, + {ColorRole::PaletteHighlight, QPalette::Highlight, QPalette::All, true}, + {ColorRole::PaletteHighlightDisabled, QPalette::Highlight, QPalette::Disabled, true}, + {ColorRole::PaletteHighlightedText, QPalette::HighlightedText, QPalette::All, true}, + {ColorRole::PaletteHighlightedTextDisabled, QPalette::HighlightedText, QPalette::Disabled, true}, + {ColorRole::PaletteLink, QPalette::Link, QPalette::All, false}, + {ColorRole::PaletteLinkDisabled, QPalette::Link, QPalette::Disabled, false}, + {ColorRole::PaletteLinkVisited, QPalette::LinkVisited, QPalette::All, false}, + {ColorRole::PaletteLinkVisitedDisabled, QPalette::LinkVisited, QPalette::Disabled, false}, + {ColorRole::PaletteLight, QPalette::Light, QPalette::All, false}, + {ColorRole::PaletteLightDisabled, QPalette::Light, QPalette::Disabled, false}, + {ColorRole::PaletteMidlight, QPalette::Midlight, QPalette::All, false}, + {ColorRole::PaletteMidlightDisabled, QPalette::Midlight, QPalette::Disabled, false}, + {ColorRole::PaletteDark, QPalette::Dark, QPalette::All, false}, + {ColorRole::PaletteDarkDisabled, QPalette::Dark, QPalette::Disabled, false}, + {ColorRole::PaletteMid, QPalette::Mid, QPalette::All, false}, + {ColorRole::PaletteMidDisabled, QPalette::Mid, QPalette::Disabled, false}, + {ColorRole::PaletteShadow, QPalette::Shadow, QPalette::All, false}, + {ColorRole::PaletteShadowDisabled, QPalette::Shadow, QPalette::Disabled, false} + }; + + for (auto entry: mapping) { + const QColor themeColor = color(entry.themeColor); + // Use original color if color is not defined in theme. + if (themeColor.isValid()) { +// if (entry.setColorRoleAsBrush) +// // TODO: Find out why sometimes setBrush is used +// pal.setBrush(entry.paletteColorGroup, entry.paletteColorRole, themeColor); +// else +// pal.setColor(entry.paletteColorGroup, entry.paletteColorRole, themeColor); + pal.setBrush(entry.paletteColorGroup, entry.paletteColorRole, themeColor); + pal.setColor(entry.paletteColorGroup, entry.paletteColorRole, themeColor); + } + } + + return pal; +} + +void AppTheme::load(const QString &filename) +{ + QFile file(filename); + if (!file.exists()) + return; + if (file.open(QFile::ReadOnly)) { + QByteArray content = file.readAll(); + QJsonParseError error; + QJsonDocument doc(QJsonDocument::fromJson(content,&error)); + if (error.error != QJsonParseError::NoError) { + throw FileError(tr("Error in json file '%1':%2 : %3") + .arg(filename) + .arg(error.offset) + .arg(error.errorString())); + } + QJsonObject obj=doc.object(); + mName = obj["name"].toString(); + mIsDark = obj["isDark"].toBool(false); + QJsonObject colors = obj["palette"].toObject(); + const QMetaObject &m = *metaObject(); + QMetaEnum e = m.enumerator(m.indexOfEnumerator("ColorRole")); + for (int i = 0, total = e.keyCount(); i < total; ++i) { + const QString key = QLatin1String(e.key(i)); + if (colors.contains(key)) { + QString val=colors[key].toString(); + mColors.insert(i, QColor(val)); + } + } + + } else { + throw FileError(tr("Can't open file '%1' for read.") + .arg(filename)); + } +} + +// If you copy QPalette, default values stay at default, even if that default is different +// within the context of different widgets. Create deep copy. +static QPalette copyPalette(const QPalette &p) +{ + QPalette res; + for (int group = 0; group < QPalette::NColorGroups; ++group) { + for (int role = 0; role < QPalette::NColorRoles; ++role) { + res.setBrush(QPalette::ColorGroup(group), + QPalette::ColorRole(role), + p.brush(QPalette::ColorGroup(group), QPalette::ColorRole(role))); + res.setColor(QPalette::ColorGroup(group), + QPalette::ColorRole(role), + p.color(QPalette::ColorGroup(group), QPalette::ColorRole(role))); + } + } + return res; +} + +QPalette AppTheme::initialPalette() +{ + static QPalette palette = copyPalette(QApplication::palette()); + return palette; +} + +bool AppTheme::isDark() const +{ + return mIsDark; +} diff --git a/RedPandaIDE/thememanager.h b/RedPandaIDE/thememanager.h index f2d65772..cf61d0e5 100644 --- a/RedPandaIDE/thememanager.h +++ b/RedPandaIDE/thememanager.h @@ -1,16 +1,88 @@ #ifndef THEMEMANAGER_H #define THEMEMANAGER_H - #include +#include +#include +#include + + +class AppTheme:public QObject { + Q_OBJECT +public: + explicit AppTheme(QObject* parent = nullptr); + + enum ColorRole { + /* Color for QPalette */ + + PaletteWindow, + PaletteWindowText, + PaletteBase, + PaletteAlternateBase, + PaletteToolTipBase, + PaletteToolTipText, + PaletteText, + PaletteButton, + PaletteButtonText, + PaletteBrightText, + PaletteHighlight, + PaletteHighlightedText, + PaletteLink, + PaletteLinkVisited, + + PaletteLight, + PaletteMidlight, + PaletteDark, + PaletteMid, + PaletteShadow, + + PaletteWindowDisabled, + PaletteWindowTextDisabled, + PaletteBaseDisabled, + PaletteAlternateBaseDisabled, + PaletteToolTipBaseDisabled, + PaletteToolTipTextDisabled, + PaletteTextDisabled, + PaletteButtonDisabled, + PaletteButtonTextDisabled, + PaletteBrightTextDisabled, + PaletteHighlightDisabled, + PaletteHighlightedTextDisabled, + PaletteLinkDisabled, + PaletteLinkVisitedDisabled, + + PaletteLightDisabled, + PaletteMidlightDisabled, + PaletteDarkDisabled, + PaletteMidDisabled, + PaletteShadowDisabled + }; + + Q_ENUM(ColorRole) + + QColor color(ColorRole role) const; + QPalette palette() const; + + void load(const QString& filename); + + bool isDark() const; + +private: + static QPalette initialPalette(); +private: + QHash mColors; + QString mName; + bool mIsDark; +}; + +using PAppTheme = std::shared_ptr; class ThemeManager : public QObject { Q_OBJECT public: explicit ThemeManager(QObject *parent = nullptr); - + PAppTheme theme(const QString& themeName); signals: - }; #endif // THEMEMANAGER_H diff --git a/RedPandaIDE/themes.qrc b/RedPandaIDE/themes.qrc new file mode 100644 index 00000000..d40fe313 --- /dev/null +++ b/RedPandaIDE/themes.qrc @@ -0,0 +1,7 @@ + + + themes/dark.json + themes/default.json + themes/dark_close.png + + diff --git a/RedPandaIDE/themes/dark.json b/RedPandaIDE/themes/dark.json new file mode 100644 index 00000000..a85fa5fc --- /dev/null +++ b/RedPandaIDE/themes/dark.json @@ -0,0 +1,32 @@ +{ + "name":"dark", + "isDark": true, + "palette": { + "PaletteWindow":"#19232D", + "PaletteWindowText":"#E0E1E3", + "PaletteBase":"#1E1E1E", + "PaletteAlternateBase":"#303030", + "PaletteButton": "#19232D", + "PaletteButtonDisabled": "#000000", + "PaletteBrightText": "#ff0000", + "PaletteText":"#e7e7e7", + "PaletteButtonText":"#d3d3d3", + "PaletteButtonTextDisabled":"#9DA9B5", + "PaletteHighlight":"#aa1f75cc", + "PaletteDark":"#ff232323", + "PaletteHighlightedText":"#ffe7e7e7", + "PaletteToolTipBase":"#66000000", + "PaletteToolTipText":"#ffe7e7e7", + "PaletteLink":"#ff007af4", + "PaletteLinkVisited":"#ffa57aff", + "PaletteWindowDisabled":"#333333", + "PaletteWindowTextDisabled":"#9DA9B5", + "PaletteHighlightDisabled":"#26486B", + "PaletteHighlightedTextDisabled":"#9DA9B5", + "PaletteBaseDisabled":"#19232D", + "PaletteTextDisabled":"#9DA9B5", + "PaletteMid": "#707070", + "PaletteLight": "#505050", + "PaletteMidLight": "#00ff00" + } +} diff --git a/RedPandaIDE/themes/dark/style.qss b/RedPandaIDE/themes/dark/style.qss index 5a503169..2c2a5f83 100644 --- a/RedPandaIDE/themes/dark/style.qss +++ b/RedPandaIDE/themes/dark/style.qss @@ -388,7 +388,7 @@ https://doc.qt.io/qt-5/stylesheet-examples.html#customizing-qmenu QMenu { border: 0px solid #455364; color: #E0E1E3; - margin: 0px; + margin: 2px; background-color: #37414F; selection-background-color: #1A72BB; } @@ -401,7 +401,7 @@ QMenu::separator { QMenu::item { background-color: #37414F; - padding: 4px 8px 4px 8px; + padding: 4px 15px 4px 20px; /* Reserve space for selection border */ border: 1px transparent #455364; } diff --git a/RedPandaIDE/themes/dark_close.png b/RedPandaIDE/themes/dark_close.png new file mode 100644 index 00000000..41dcd816 Binary files /dev/null and b/RedPandaIDE/themes/dark_close.png differ diff --git a/RedPandaIDE/themes/default.json b/RedPandaIDE/themes/default.json new file mode 100644 index 00000000..5293f64f --- /dev/null +++ b/RedPandaIDE/themes/default.json @@ -0,0 +1,6 @@ +{ + "name":"default", + "isDark":false, + "palette": { + } +} diff --git a/RedPandaIDE/utils.cpp b/RedPandaIDE/utils.cpp index bfd002cf..279a8c1f 100644 --- a/RedPandaIDE/utils.cpp +++ b/RedPandaIDE/utils.cpp @@ -434,32 +434,32 @@ QString TrimLeft(const QString &s) } } -void changeTheme(const QString &themeName) -{ - if (themeName.isEmpty() || themeName == "default") { - QApplication::setStyle("Fusion"); - QApplication* app = dynamic_cast(QApplication::instance()); - app->setStyleSheet(""); - return ; - } - QStyleFactory styleFactory; - if (styleFactory.keys().contains(themeName)) { - QApplication::setStyle(themeName); - QApplication* app = dynamic_cast(QApplication::instance()); - app->setStyleSheet(""); - return; - } - QFile f(QString(":/themes/%1/style.qss").arg(themeName)); +//void changeTheme(const QString &themeName) +//{ +// if (themeName.isEmpty() || themeName == "default") { +// QApplication::setStyle("Fusion"); +// QApplication* app = dynamic_cast(QApplication::instance()); +// //app->setStyleSheet(""); +// return ; +// } +// QStyleFactory styleFactory; +// if (styleFactory.keys().contains(themeName)) { +// QApplication::setStyle(themeName); +// QApplication* app = dynamic_cast(QApplication::instance()); +// app->setStyleSheet(""); +// return; +// } +// QFile f(QString(":/themes/%1/style.qss").arg(themeName)); - if (!f.exists()) { - qDebug()<<"Unable to set stylesheet, file not found\n"; - } else { - QApplication::setStyle("Windowsvista"); - f.open(QFile::ReadOnly | QFile::Text); - QTextStream ts(&f); - dynamic_cast(QApplication::instance())->setStyleSheet(ts.readAll()); - } -} +// if (!f.exists()) { +// qDebug()<<"Unable to set stylesheet, file not found\n"; +// } else { +// QApplication::setStyle("Fusion"); +// f.open(QFile::ReadOnly | QFile::Text); +// QTextStream ts(&f); +// dynamic_cast(QApplication::instance())->setStyleSheet(ts.readAll()); +// } +//} int compareFileModifiedTime(const QString &filename1, const QString &filename2) { diff --git a/RedPandaIDE/utils.h b/RedPandaIDE/utils.h index bd34a4bb..0a57c975 100644 --- a/RedPandaIDE/utils.h +++ b/RedPandaIDE/utils.h @@ -165,7 +165,7 @@ QString TrimLeft(const QString& s); bool StringIsBlank(const QString& s); int compareFileModifiedTime(const QString& filename1, const QString& filename2); -void changeTheme(const QString& themeName); +//void changeTheme(const QString& themeName); bool findComplement(const QString& s, const QChar& fromToken, diff --git a/RedPandaIDE/widgets/cpudialog.ui b/RedPandaIDE/widgets/cpudialog.ui index 4b87ae6c..21651ee7 100644 --- a/RedPandaIDE/widgets/cpudialog.ui +++ b/RedPandaIDE/widgets/cpudialog.ui @@ -159,6 +159,9 @@ QAbstractItemView::NoEditTriggers + + true + Qt::ElideNone diff --git a/RedPandaIDE/widgets/darkfusionstyle.cpp b/RedPandaIDE/widgets/darkfusionstyle.cpp new file mode 100644 index 00000000..962c1070 --- /dev/null +++ b/RedPandaIDE/widgets/darkfusionstyle.cpp @@ -0,0 +1,795 @@ +#include "darkfusionstyle.h" + +#include +#include +#include +#include +#include +#include +#include +#include + +#define BEGIN_STYLE_PIXMAPCACHE(a) \ + QRect rect = option->rect; \ + QPixmap internalPixmapCache; \ + QImage imageCache; \ + QPainter *p = painter; \ + QString unique = QStyleHelper::uniqueName((a), option, option->rect.size()); \ + int txType = painter->deviceTransform().type() | painter->worldTransform().type(); \ + bool doPixmapCache = (!option->rect.isEmpty()) \ + && ((txType <= QTransform::TxTranslate) || (painter->deviceTransform().type() == QTransform::TxScale)); \ + if (doPixmapCache && QPixmapCache::find(unique, &internalPixmapCache)) { \ + painter->drawPixmap(option->rect.topLeft(), internalPixmapCache); \ + } else { \ + if (doPixmapCache) { \ + rect.setRect(0, 0, option->rect.width(), option->rect.height()); \ + imageCache = styleCacheImage(option->rect.size()); \ + imageCache.fill(0); \ + p = new QPainter(&imageCache); \ + } + + + +#define END_STYLE_PIXMAPCACHE \ + if (doPixmapCache) { \ + p->end(); \ + delete p; \ + internalPixmapCache = QPixmap::fromImage(imageCache); \ + painter->drawPixmap(option->rect.topLeft(), internalPixmapCache); \ + QPixmapCache::insert(unique, internalPixmapCache); \ + } \ + } + + +namespace QStyleHelper { + + +static QString uniqueName(const QString &key, const QStyleOption *option, const QSize &size) +{ + const QStyleOptionComplex *complexOption = qstyleoption_cast(option); + QString tmp = QString("%1%2%3%4%5%6%7") + .arg(key) + .arg(option->state) + .arg(option->direction) + .arg(complexOption ? uint(complexOption->activeSubControls) : 0u) + .arg(option->palette.cacheKey()) + .arg(size.width()) + .arg(size.height()); + +#if QT_CONFIG(spinbox) + if (const QStyleOptionSpinBox *spinBox = qstyleoption_cast(option)) { + tmp = tmp + QString("%1%2%3") + .arg(spinBox->buttonSymbols) + .arg(spinBox->stepEnabled) + .arg(QLatin1Char(spinBox->frame ? '1' : '0')); + } +#endif // QT_CONFIG(spinbox) + + return tmp; +} + +Q_WIDGETS_EXPORT qreal dpi(const QStyleOption *option); + +Q_WIDGETS_EXPORT qreal dpiScaled(qreal value, qreal dpi); + +Q_WIDGETS_EXPORT qreal dpiScaled(qreal value, const QPaintDevice *device); + +Q_WIDGETS_EXPORT qreal dpiScaled(qreal value, const QStyleOption *option); +} + + +enum Direction { + TopDown, + FromLeft, + BottomUp, + FromRight +}; + +// from windows style +static const int windowsItemFrame = 2; // menu item frame width +static const int windowsItemHMargin = 3; // menu item hor text margin +static const int windowsItemVMargin = 8; // menu item ver text margin +static const int windowsRightBorder = 15; // right border on windows + +static const int groupBoxBottomMargin = 0; // space below the groupbox +static const int groupBoxTopMargin = 3; + +DarkFusionStyle::DarkFusionStyle():QProxyStyle("fusion") +{ + +} +// On mac we want a standard blue color used when the system palette is used +static bool isMacSystemPalette(const QPalette &pal){ + Q_UNUSED(pal); +#if defined(Q_OS_MACX) + const QPalette *themePalette = QGuiApplicationPrivate::platformTheme()->palette(); + if (themePalette && themePalette->color(QPalette::Normal, QPalette::Highlight) == + pal.color(QPalette::Normal, QPalette::Highlight) && + themePalette->color(QPalette::Normal, QPalette::HighlightedText) == + pal.color(QPalette::Normal, QPalette::HighlightedText)) + return true; +#endif + return false; +} + +// Used for grip handles +static QColor calcDarkShade() { + return QColor(255, 255, 255, 90); +} +static QColor calcLightShade() { + return QColor(0, 0, 0, 60); +} + +// The default button and handle gradient +static QLinearGradient qt_fusion_gradient(const QRect &rect, const QBrush &baseColor, Direction direction = TopDown) +{ + int x = rect.center().x(); + int y = rect.center().y(); + QLinearGradient gradient; + switch (direction) { + case FromLeft: + gradient = QLinearGradient(rect.left(), y, rect.right(), y); + break; + case FromRight: + gradient = QLinearGradient(rect.right(), y, rect.left(), y); + break; + case BottomUp: + gradient = QLinearGradient(x, rect.bottom(), x, rect.top()); + break; + case TopDown: + default: + gradient = QLinearGradient(x, rect.top(), x, rect.bottom()); + break; + } + if (baseColor.gradient()) + gradient.setStops(baseColor.gradient()->stops()); + else { + QColor gradientStartColor = baseColor.color().lighter(124); + QColor gradientStopColor = baseColor.color().lighter(102); + gradient.setColorAt(0, gradientStartColor); + gradient.setColorAt(1, gradientStopColor); + // Uncomment for adding shiny shading + // QColor midColor1 = mergedColors(gradientStartColor, gradientStopColor, 55); + // QColor midColor2 = mergedColors(gradientStartColor, gradientStopColor, 45); + // gradient.setColorAt(0.5, midColor1); + // gradient.setColorAt(0.501, midColor2); + } + return gradient; +} + + +static QColor calcHighlight(const QPalette &pal) { + if (isMacSystemPalette(pal)) + return QColor(60, 140, 230); + return pal.color(QPalette::Highlight); +} + +static QColor calcOutline(const QPalette &pal) { + if (pal.window().style() == Qt::TexturePattern) + return QColor(255, 255, 255, 160); + return pal.window().color().lighter(180); +} + +static QColor calcHighlightedOutline(const QPalette &pal) { + QColor highlightedOutline = calcHighlight(pal).lighter(125); + if (highlightedOutline.value() > 160) + highlightedOutline.setHsl(highlightedOutline.hue(), highlightedOutline.saturation(), 160); + return highlightedOutline; +} + +static QColor calcButtonColor(const QPalette &pal) { + QColor buttonColor = pal.button().color(); + int val = qGray(buttonColor.rgb()); + buttonColor = buttonColor.darker(100 + qMax(1, (180 - val)/6)); + buttonColor.setHsv(buttonColor.hue(), buttonColor.saturation() * 0.75, buttonColor.value()); + return buttonColor; +} + +static QColor calcTabFrameColor(const QPalette &pal) { + if (pal.window().style() == Qt::TexturePattern) + return QColor(255, 255, 255, 8); + return calcButtonColor(pal).lighter(104); +} + +static QColor calcTopShadow() { + return QColor(255, 255, 255, 18); +} + +static QColor calcInnerContrastLine() { + return QColor(0, 0, 0, 30); +} + +static QColor mergedColors(const QColor &colorA, const QColor &colorB, int factor = 50) +{ + const int maxFactor = 100; + QColor tmp = colorA; + tmp.setRed((tmp.red() * factor) / maxFactor + (colorB.red() * (maxFactor - factor)) / maxFactor); + tmp.setGreen((tmp.green() * factor) / maxFactor + (colorB.green() * (maxFactor - factor)) / maxFactor); + tmp.setBlue((tmp.blue() * factor) / maxFactor + (colorB.blue() * (maxFactor - factor)) / maxFactor); + return tmp; +} + +static QImage styleCacheImage(const QSize &size) +{ + const qreal pixelRatio = qApp->devicePixelRatio(); + QImage cacheImage = QImage(size * pixelRatio, QImage::Format_ARGB32_Premultiplied); + cacheImage.setDevicePixelRatio(pixelRatio); + return cacheImage; +} + + + +void DarkFusionStyle::drawPrimitive(PrimitiveElement elem, const QStyleOption *option, QPainter *painter, const QWidget *widget) const +{ + Q_ASSERT(option); + + QRect rect = option->rect; + int state = option->state; + + QColor outline = calcOutline(option->palette); + QColor highlightedOutline = calcHighlightedOutline(option->palette); + + QColor tabFrameColor = calcTabFrameColor(option->palette); + + switch (elem) { + +//#if QT_CONFIG(groupbox) +// // No frame drawn +// case PE_FrameGroupBox: +// { +// QPixmap pixmap(QLatin1String(":/qt-project.org/styles/commonstyle/images/fusion_groupbox.png")); +// int topMargin = 0; +// auto control = qobject_cast(widget); +// if (control && !control->isCheckable() && control->title().isEmpty()) { +// // Shrinking the topMargin if Not checkable AND title is empty +// topMargin = groupBoxTopMargin; +// } else { +// topMargin = qMax(pixelMetric(PM_ExclusiveIndicatorHeight), option->fontMetrics.height()) + groupBoxTopMargin; +// } +// QRect frame = option->rect.adjusted(0, topMargin, 0, 0); +// qDrawBorderPixmap(painter, frame, QMargins(6, 6, 6, 6), pixmap); +// break; +// } +//#endif // QT_CONFIG(groupbox) +// case PE_IndicatorBranch: { +// if (!(option->state & State_Children)) +// break; +// if (option->state & State_Open) +// drawPrimitive(PE_IndicatorArrowDown, option, painter, widget); +// else { +// const bool reverse = (option->direction == Qt::RightToLeft); +// drawPrimitive(reverse ? PE_IndicatorArrowLeft : PE_IndicatorArrowRight, option, painter, widget); +// } +// break; +// } +#if QT_CONFIG(tabbar) + case PE_FrameTabBarBase: + if (const QStyleOptionTabBarBase *tbb + = qstyleoption_cast(option)) { + painter->save(); + painter->setPen(QPen(outline.darker(110))); + switch (tbb->shape) { + case QTabBar::RoundedNorth: { + QRegion region(tbb->rect); + region -= tbb->selectedTabRect; + painter->drawLine(tbb->rect.topLeft(), tbb->rect.topRight()); + painter->setClipRegion(region); + painter->setPen(option->palette.light().color()); + painter->drawLine(tbb->rect.topLeft() + QPoint(0, 1), tbb->rect.topRight() + QPoint(0, 1)); + } + break; + case QTabBar::RoundedWest: + painter->drawLine(tbb->rect.left(), tbb->rect.top(), tbb->rect.left(), tbb->rect.bottom()); + break; + case QTabBar::RoundedSouth: + painter->drawLine(tbb->rect.left(), tbb->rect.bottom(), + tbb->rect.right(), tbb->rect.bottom()); + break; + case QTabBar::RoundedEast: + painter->drawLine(tbb->rect.topRight(), tbb->rect.bottomRight()); + break; + case QTabBar::TriangularNorth: + case QTabBar::TriangularEast: + case QTabBar::TriangularWest: + case QTabBar::TriangularSouth: + painter->restore(); + QCommonStyle::drawPrimitive(elem, option, painter, widget); + return; + } + painter->restore(); + } + return; +#endif // QT_CONFIG(tabbar) + case PE_PanelScrollAreaCorner: { + painter->save(); + QColor alphaOutline = outline; + alphaOutline.setAlpha(180); + painter->setPen(alphaOutline); + painter->setBrush(option->palette.brush(QPalette::Window)); + painter->drawRect(option->rect); + painter->restore(); + } break; +// case PE_IndicatorArrowUp: +// case PE_IndicatorArrowDown: +// case PE_IndicatorArrowRight: +// case PE_IndicatorArrowLeft: +// { +// if (option->rect.width() <= 1 || option->rect.height() <= 1) +// break; +// QColor arrowColor = option->palette.windowText().color(); +// arrowColor.setAlpha(160); +// Qt::ArrowType arrow = Qt::UpArrow; +// switch (elem) { +// case PE_IndicatorArrowDown: +// arrow = Qt::DownArrow; +// break; +// case PE_IndicatorArrowRight: +// arrow = Qt::RightArrow; +// break; +// case PE_IndicatorArrowLeft: +// arrow = Qt::LeftArrow; +// break; +// default: +// break; +// } +// qt_fusion_draw_arrow(arrow, painter, option, option->rect, arrowColor); +// } +// break; +// case PE_IndicatorItemViewItemCheck: +// { +// QStyleOptionButton button; +// button.QStyleOption::operator=(*option); +// button.state &= ~State_MouseOver; +// proxy()->drawPrimitive(PE_IndicatorCheckBox, &button, painter, widget); +// } +// return; +// case PE_IndicatorHeaderArrow: +// if (const QStyleOptionHeader *header = qstyleoption_cast(option)) { +// QRect r = header->rect; +// QColor arrowColor = header->palette.windowText().color(); +// arrowColor.setAlpha(180); +// QPoint offset = QPoint(0, -2); + +//#if defined(Q_OS_LINUX) +// if (header->sortIndicator & QStyleOptionHeader::SortUp) { +// qt_fusion_draw_arrow(Qt::UpArrow, painter, option, r.translated(offset), arrowColor); +// } else if (header->sortIndicator & QStyleOptionHeader::SortDown) { +// qt_fusion_draw_arrow(Qt::DownArrow, painter, option, r.translated(offset), arrowColor); +// } +//#else +// if (header->sortIndicator & QStyleOptionHeader::SortUp) { +// qt_fusion_draw_arrow(Qt::DownArrow, painter, option, r.translated(offset), arrowColor); +// } else if (header->sortIndicator & QStyleOptionHeader::SortDown) { +// qt_fusion_draw_arrow(Qt::UpArrow, painter, option, r.translated(offset), arrowColor); +// } +//#endif +// } +// break; +// case PE_IndicatorButtonDropDown: +// proxy()->drawPrimitive(PE_PanelButtonCommand, option, painter, widget); +// break; + + case PE_IndicatorToolBarSeparator: + { + QRect rect = option->rect; + const int margin = 6; + if (option->state & State_Horizontal) { + const int offset = rect.width()/2; + painter->setPen(QPen(option->palette.window().color().lighter(110))); + painter->drawLine(rect.bottomLeft().x() + offset, + rect.bottomLeft().y() - margin, + rect.topLeft().x() + offset, + rect.topLeft().y() + margin); + painter->setPen(QPen(option->palette.window().color().darker(110))); + painter->drawLine(rect.bottomLeft().x() + offset + 1, + rect.bottomLeft().y() - margin, + rect.topLeft().x() + offset + 1, + rect.topLeft().y() + margin); + } else { //Draw vertical separator + const int offset = rect.height()/2; + painter->setPen(QPen(option->palette.window().color().lighter(110))); + painter->drawLine(rect.topLeft().x() + margin , + rect.topLeft().y() + offset, + rect.topRight().x() - margin, + rect.topRight().y() + offset); + painter->setPen(QPen(option->palette.window().color().darker(110))); + painter->drawLine(rect.topLeft().x() + margin , + rect.topLeft().y() + offset + 1, + rect.topRight().x() - margin, + rect.topRight().y() + offset + 1); + } + } + break; + case PE_Frame: { + if (widget && widget->inherits("QComboBoxPrivateContainer")){ + QStyleOption copy = *option; + copy.state |= State_Raised; + proxy()->drawPrimitive(PE_PanelMenu, ©, painter, widget); + break; + } + painter->save(); + QPen thePen(outline.darker(108)); + thePen.setCosmetic(false); + painter->setPen(thePen); + painter->drawRect(option->rect.adjusted(0, 0, -1, -1)); + painter->restore(); } + break; + case PE_FrameMenu: + painter->save(); + { + painter->setPen(QPen(outline)); + painter->drawRect(option->rect.adjusted(0, 0, -1, -1)); + QColor frameLight = option->palette.window().color().darker(160); + QColor frameShadow = option->palette.window().color().lighter(110); + + //paint beveleffect + QRect frame = option->rect.adjusted(1, 1, -1, -1); + painter->setPen(frameLight); + painter->drawLine(frame.topLeft(), frame.bottomLeft()); + painter->drawLine(frame.topLeft(), frame.topRight()); + + painter->setPen(frameShadow); + painter->drawLine(frame.topRight(), frame.bottomRight()); + painter->drawLine(frame.bottomLeft(), frame.bottomRight()); + } + painter->restore(); + break; + case PE_FrameDockWidget: + + painter->save(); + { + QColor softshadow = option->palette.window().color().lighter(120); + + QRect rect= option->rect; + painter->setPen(softshadow); + painter->drawRect(option->rect.adjusted(0, 0, -1, -1)); + painter->setPen(QPen(option->palette.light(), 1)); + painter->drawLine(QPoint(rect.left() + 1, rect.top() + 1), QPoint(rect.left() + 1, rect.bottom() - 1)); + painter->setPen(QPen(option->palette.window().color().lighter(120))); + painter->drawLine(QPoint(rect.left() + 1, rect.bottom() - 1), QPoint(rect.right() - 2, rect.bottom() - 1)); + painter->drawLine(QPoint(rect.right() - 1, rect.top() + 1), QPoint(rect.right() - 1, rect.bottom() - 1)); + + } + painter->restore(); + break; +// case PE_PanelButtonTool: +// painter->save(); +// if ((option->state & State_Enabled || option->state & State_On) || !(option->state & State_AutoRaise)) { +// if (widget && widget->inherits("QDockWidgetTitleButton")) { +// if (option->state & State_MouseOver) +// proxy()->drawPrimitive(PE_PanelButtonCommand, option, painter, widget); +// } else { +// proxy()->drawPrimitive(PE_PanelButtonCommand, option, painter, widget); +// } +// } +// painter->restore(); +// break; +// case PE_IndicatorDockWidgetResizeHandle: +// { +// QStyleOption dockWidgetHandle = *option; +// bool horizontal = option->state & State_Horizontal; +// dockWidgetHandle.state.setFlag(State_Horizontal, !horizontal); +// proxy()->drawControl(CE_Splitter, &dockWidgetHandle, painter, widget); +// } +// break; + case PE_FrameWindow: + painter->save(); + { + QRect rect= option->rect; + painter->setPen(QPen(outline.lighter(150))); + painter->drawRect(option->rect.adjusted(0, 0, -1, -1)); + painter->setPen(QPen(option->palette.light(), 1)); + painter->drawLine(QPoint(rect.left() + 1, rect.top() + 1), + QPoint(rect.left() + 1, rect.bottom() - 1)); + painter->setPen(QPen(option->palette.window().color().darker(120))); + painter->drawLine(QPoint(rect.left() + 1, rect.bottom() - 1), + QPoint(rect.right() - 2, rect.bottom() - 1)); + painter->drawLine(QPoint(rect.right() - 1, rect.top() + 1), + QPoint(rect.right() - 1, rect.bottom() - 1)); + } + painter->restore(); + break; + case PE_FrameLineEdit: + { + QRect r = rect; + bool hasFocus = option->state & State_HasFocus; + + painter->save(); + + painter->setRenderHint(QPainter::Antialiasing, true); + // ### highdpi painter bug. + painter->translate(0.5, 0.5); + + // Draw Outline + painter->setPen( QPen(hasFocus ? highlightedOutline : outline)); + painter->drawRoundedRect(r.adjusted(0, 0, -1, -1), 2, 2); + + if (hasFocus) { + QColor softHighlight = highlightedOutline; + softHighlight.setAlpha(40); + painter->setPen(softHighlight); + painter->drawRoundedRect(r.adjusted(1, 1, -2, -2), 1.7, 1.7); + } + // Draw inner shadow + painter->setPen(calcTopShadow()); + painter->drawLine(QPoint(r.left() + 2, r.top() + 1), QPoint(r.right() - 2, r.top() + 1)); + + painter->restore(); + + } + break; + case PE_IndicatorCheckBox: + painter->save(); + if (const QStyleOptionButton *checkbox = qstyleoption_cast(option)) { + painter->setRenderHint(QPainter::Antialiasing, true); + painter->translate(0.5, 0.5); + rect = rect.adjusted(0, 0, -1, -1); + + QColor pressedColor = mergedColors(option->palette.base().color(), option->palette.windowText().color(), 85); + painter->setBrush(Qt::NoBrush); + + // Gradient fill + QLinearGradient gradient(rect.topLeft(), rect.bottomLeft()); + gradient.setColorAt(0, (state & State_Sunken) ? pressedColor : option->palette.base().color().lighter(115)); + gradient.setColorAt(0.15, (state & State_Sunken) ? pressedColor : option->palette.base().color()); + gradient.setColorAt(1, (state & State_Sunken) ? pressedColor : option->palette.base().color()); + + painter->setBrush((state & State_Sunken) ? QBrush(pressedColor) : gradient); + painter->setPen(QPen(outline.lighter(110))); + + if (option->state & State_HasFocus && option->state & State_KeyboardFocusChange) + painter->setPen(QPen(highlightedOutline)); + painter->drawRect(rect); + + QColor checkMarkColor = option->palette.text().color().lighter(120); + const qreal checkMarkPadding = 1 + rect.width() * 0.13; // at least one pixel padding + + if (checkbox->state & State_NoChange) { + gradient = QLinearGradient(rect.topLeft(), rect.bottomLeft()); + checkMarkColor.setAlpha(80); + gradient.setColorAt(0, checkMarkColor); + checkMarkColor.setAlpha(140); + gradient.setColorAt(1, checkMarkColor); + checkMarkColor.setAlpha(180); + painter->setPen(QPen(checkMarkColor, 1)); + painter->setBrush(gradient); + painter->drawRect(rect.adjusted(checkMarkPadding, checkMarkPadding, -checkMarkPadding, -checkMarkPadding)); + + } else if (checkbox->state & State_On) { + const qreal dpi = QStyleHelper::dpi(option); + qreal penWidth = QStyleHelper::dpiScaled(1.5, dpi); + penWidth = qMax(penWidth, 0.13 * rect.height()); + penWidth = qMin(penWidth, 0.20 * rect.height()); + QPen checkPen = QPen(checkMarkColor, penWidth); + checkMarkColor.setAlpha(210); + painter->translate(QStyleHelper::dpiScaled(-0.8, dpi), QStyleHelper::dpiScaled(0.5, dpi)); + painter->setPen(checkPen); + painter->setBrush(Qt::NoBrush); + + // Draw checkmark + QPainterPath path; + const qreal rectHeight = rect.height(); // assuming height equals width + path.moveTo(checkMarkPadding + rectHeight * 0.11, rectHeight * 0.47); + path.lineTo(rectHeight * 0.5, rectHeight - checkMarkPadding); + path.lineTo(rectHeight - checkMarkPadding, checkMarkPadding); + painter->drawPath(path.translated(rect.topLeft())); + } + } + painter->restore(); + break; + case PE_IndicatorRadioButton: + painter->save(); + { + QColor pressedColor = mergedColors(option->palette.base().color(), option->palette.windowText().color(), 85); + painter->setBrush((state & State_Sunken) ? pressedColor : option->palette.base().color()); + painter->setRenderHint(QPainter::Antialiasing, true); + QPainterPath circle; + const QPointF circleCenter = rect.center() + QPoint(1, 1); + const qreal outlineRadius = (rect.width() + (rect.width() + 1) % 2) / 2.0 - 1; + circle.addEllipse(circleCenter, outlineRadius, outlineRadius); + painter->setPen(QPen(option->palette.window().color().lighter(150))); + if (option->state & State_HasFocus && option->state & State_KeyboardFocusChange) + painter->setPen(QPen(highlightedOutline)); + painter->drawPath(circle); + + if (state & (State_On )) { + circle = QPainterPath(); + const qreal checkmarkRadius = outlineRadius / 2.32; + circle.addEllipse(circleCenter, checkmarkRadius, checkmarkRadius); + QColor checkMarkColor = option->palette.text().color().lighter(120); + checkMarkColor.setAlpha(200); + painter->setPen(checkMarkColor); + checkMarkColor.setAlpha(180); + painter->setBrush(checkMarkColor); + painter->drawPath(circle); + } + } + painter->restore(); + break; + case PE_IndicatorToolBarHandle: + { + //draw grips + if (option->state & State_Horizontal) { + for (int i = -3 ; i < 2 ; i += 3) { + for (int j = -8 ; j < 10 ; j += 3) { + painter->fillRect(rect.center().x() + i, rect.center().y() + j, 2, 2, calcLightShade()); + painter->fillRect(rect.center().x() + i, rect.center().y() + j, 1, 1, calcDarkShade()); + } + } + } else { //vertical toolbar + for (int i = -6 ; i < 12 ; i += 3) { + for (int j = -3 ; j < 2 ; j += 3) { + painter->fillRect(rect.center().x() + i, rect.center().y() + j, 2, 2, calcLightShade()); + painter->fillRect(rect.center().x() + i, rect.center().y() + j, 1, 1, calcDarkShade()); + } + } + } + break; + } + case PE_FrameDefaultButton: + break; + case PE_FrameFocusRect: + if (const QStyleOptionFocusRect *fropt = qstyleoption_cast(option)) { + //### check for d->alt_down + if (!(fropt->state & State_KeyboardFocusChange)) + return; + QRect rect = option->rect; + + painter->save(); + painter->setRenderHint(QPainter::Antialiasing, true); + painter->translate(0.5, 0.5); + QColor fillcolor = highlightedOutline; + fillcolor.setAlpha(80); + painter->setPen(fillcolor.lighter(120)); + fillcolor.setAlpha(30); + QLinearGradient gradient(rect.topLeft(), rect.bottomLeft()); + gradient.setColorAt(0, fillcolor.darker(160)); + gradient.setColorAt(1, fillcolor); + painter->setBrush(gradient); + painter->drawRoundedRect(option->rect.adjusted(0, 0, -1, -1), 1, 1); + painter->restore(); + } + break; + case PE_PanelButtonCommand: + { + bool isDefault = false; + bool isFlat = false; + bool isDown = (option->state & State_Sunken) || (option->state & State_On); + QRect r; + + if (const QStyleOptionButton *button = qstyleoption_cast(option)) { + isDefault = (button->features & QStyleOptionButton::DefaultButton) && (button->state & State_Enabled); + isFlat = (button->features & QStyleOptionButton::Flat); + } + + if (isFlat && !isDown) { + if (isDefault) { + r = option->rect.adjusted(0, 1, 0, -1); + painter->setPen(QPen(QColorConstants::Svg::lightgray)); + const QLine lines[4] = { + QLine(QPoint(r.left() + 2, r.top()), + QPoint(r.right() - 2, r.top())), + QLine(QPoint(r.left(), r.top() + 2), + QPoint(r.left(), r.bottom() - 2)), + QLine(QPoint(r.right(), r.top() + 2), + QPoint(r.right(), r.bottom() - 2)), + QLine(QPoint(r.left() + 2, r.bottom()), + QPoint(r.right() - 2, r.bottom())) + }; + painter->drawLines(lines, 4); + const QPoint points[4] = { + QPoint(r.right() - 1, r.bottom() - 1), + QPoint(r.right() - 1, r.top() + 1), + QPoint(r.left() + 1, r.bottom() - 1), + QPoint(r.left() + 1, r.top() + 1) + }; + painter->drawPoints(points, 4); + } + return; + } + + + bool isEnabled = option->state & State_Enabled; + bool hasFocus = (option->state & State_HasFocus && option->state & State_KeyboardFocusChange); + QColor buttonColor = calcButtonColor(option->palette); + + QColor darkOutline = outline; + if (hasFocus | isDefault) { + darkOutline = highlightedOutline; + } + + if (isDefault) + buttonColor = mergedColors(buttonColor, highlightedOutline.lighter(130), 90); + + BEGIN_STYLE_PIXMAPCACHE(QStringLiteral("pushbutton-") + buttonColor.name(QColor::HexArgb)) + r = rect.adjusted(0, 1, -1, 0); + + p->setRenderHint(QPainter::Antialiasing, true); + p->translate(0.5, -0.5); + + QLinearGradient gradient = qt_fusion_gradient(rect, (isEnabled && option->state & State_MouseOver ) ? buttonColor : buttonColor.darker(104)); + p->setPen(Qt::transparent); + p->setBrush(isDown ? QBrush(buttonColor.darker(110)) : gradient); + p->drawRoundedRect(r, 2.0, 2.0); + p->setBrush(Qt::NoBrush); + + // Outline + p->setPen(!isEnabled ? QPen(darkOutline.lighter(115)) : QPen(darkOutline)); + p->drawRoundedRect(r, 2.0, 2.0); + + p->setPen(calcInnerContrastLine()); + p->drawRoundedRect(r.adjusted(1, 1, -1, -1), 2.0, 2.0); + + END_STYLE_PIXMAPCACHE + } + break; + case PE_FrameTabWidget: + painter->save(); + painter->fillRect(option->rect.adjusted(0, 0, -1, -1), tabFrameColor); +#if QT_CONFIG(tabwidget) + if (const QStyleOptionTabWidgetFrame *twf = qstyleoption_cast(option)) { + QColor borderColor = outline.lighter(110); + QRect rect = option->rect.adjusted(0, 0, -1, -1); + + // Shadow outline + if (twf->shape != QTabBar::RoundedSouth) { + rect.adjust(0, 0, 0, -1); + QColor alphaShadow(Qt::black); + alphaShadow.setAlpha(15); + painter->setPen(alphaShadow); + painter->drawLine(option->rect.bottomLeft(), option->rect.bottomRight()); painter->setPen(borderColor); + } + + // outline + painter->setPen(outline); + painter->drawRect(rect); + + // Inner frame highlight + painter->setPen(calcInnerContrastLine()); + painter->drawRect(rect.adjusted(1, 1, -1, -1)); + + } +#endif // QT_CONFIG(tabwidget) + painter->restore(); + break ; + + case PE_FrameStatusBarItem: + break; +// case PE_IndicatorTabClose: +// { +// Q_D(const QFusionStyle); +// if (d->tabBarcloseButtonIcon.isNull()) +// d->tabBarcloseButtonIcon = proxy()->standardIcon(SP_DialogCloseButton, option, widget); +// if ((option->state & State_Enabled) && (option->state & State_MouseOver)) +// proxy()->drawPrimitive(PE_PanelButtonCommand, option, painter, widget); +// QPixmap pixmap = d->tabBarcloseButtonIcon.pixmap(qt_getWindow(widget), QSize(16, 16), QIcon::Normal, QIcon::On); +// proxy()->drawItemPixmap(painter, option->rect, Qt::AlignCenter, pixmap); +// } +// break; + case PE_PanelMenu: { + painter->save(); + const QBrush menuBackground = option->palette.base().color().darker(108); + QColor borderColor = option->palette.window().color().lighter(160); + qDrawPlainRect(painter, option->rect, borderColor, 1, &menuBackground); + painter->restore(); + } + break; + default: + QProxyStyle::drawPrimitive(elem, option, painter, widget); + break; + } +} + +QIcon DarkFusionStyle::standardIcon(StandardPixmap standardIcon, const QStyleOption *option, const QWidget *widget) const +{ + switch (standardIcon) { + case SP_TitleBarCloseButton: + case SP_DockWidgetCloseButton: + case SP_DialogCloseButton: + return QIcon(":/themes/dark_close.png"); + default: + break; + } + + return QProxyStyle::standardIcon(standardIcon, option, widget); +} diff --git a/RedPandaIDE/widgets/darkfusionstyle.h b/RedPandaIDE/widgets/darkfusionstyle.h new file mode 100644 index 00000000..acace490 --- /dev/null +++ b/RedPandaIDE/widgets/darkfusionstyle.h @@ -0,0 +1,19 @@ +#ifndef DARKFUSIONSTYLE_H +#define DARKFUSIONSTYLE_H + +#include + +class DarkFusionStyle : public QProxyStyle +{ + Q_OBJECT +public: + DarkFusionStyle(); + + // QStyle interface +public: + void drawPrimitive(PrimitiveElement pe, const QStyleOption *opt, QPainter *p, const QWidget *w) const override; + QIcon standardIcon(StandardPixmap standardIcon, const QStyleOption *option = nullptr, + const QWidget *widget = nullptr) const override; +}; + +#endif // DARKFUSIONSTYLE_H diff --git a/RedPandaIDE/widgets/newprojectdialog.cpp b/RedPandaIDE/widgets/newprojectdialog.cpp index b6efb7bf..fc212347 100644 --- a/RedPandaIDE/widgets/newprojectdialog.cpp +++ b/RedPandaIDE/widgets/newprojectdialog.cpp @@ -202,7 +202,7 @@ void NewProjectDialog::on_lstTemplates_currentItemChanged(QListWidgetItem *curre } -void NewProjectDialog::on_btnBrowse_triggered(QAction *) +void NewProjectDialog::on_btnBrowse_clicked() { QString dirPath = ui->txtLocation->text(); if (!QDir(dirPath).exists()) { diff --git a/RedPandaIDE/widgets/newprojectdialog.h b/RedPandaIDE/widgets/newprojectdialog.h index 0d59da5a..1c8b20b0 100644 --- a/RedPandaIDE/widgets/newprojectdialog.h +++ b/RedPandaIDE/widgets/newprojectdialog.h @@ -29,7 +29,7 @@ private slots: void on_lstTemplates_itemDoubleClicked(QListWidgetItem *item); void on_lstTemplates_currentItemChanged(QListWidgetItem *current, QListWidgetItem *previous); - void on_btnBrowse_triggered(QAction *arg1); + void on_btnBrowse_clicked(); private: void addTemplate(const QString& filename);