Gui: fix light/dark switch when on classic (#21049)

* Gui: fix: taskpanel light/dark switch when on classic

* Gui: fix: taskpanel double icon

* Apply suggestions from code review

---------

Co-authored-by: Kacper Donat <kadet1090@gmail.com>
This commit is contained in:
Alfredo Monclus
2025-05-21 08:00:54 -06:00
committed by GitHub
parent e6cb6d57b4
commit 548af02619
16 changed files with 136 additions and 105 deletions

View File

@@ -1273,7 +1273,6 @@ void OverlayTabWidget::setOverlayMode(QWidget *widget, OverlayOption option)
&& !qobject_cast<Dialog::Clipping*>(widget))
|| qobject_cast<TaskView::TaskBox*>(widget))
return;
if(widget != tabBar()) {
if(OverlayParams::getDockOverlayAutoMouseThrough()
&& option == OverlayOption::ShowTab) {

View File

@@ -8,6 +8,7 @@
#include "actionbox.h"
#include <QVariant>
#include <QStyleOptionFrame>
namespace QSint
{
@@ -34,6 +35,7 @@ ActionBox::ActionBox(const QPixmap & icon, const QString & headerText, QWidget *
void ActionBox::init(const QString &headerText)
{
setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Maximum);
setFrameStyle(QFrame::NoFrame);
auto *mainLayout = new QHBoxLayout(this);

View File

@@ -43,6 +43,8 @@ void ActionGroup::init(bool hasHeader)
{
m_foldStep = 0;
myScheme = ActionPanelScheme::defaultScheme();
setBackgroundRole(QPalette::Button);
setAutoFillBackground(true);
auto *layout = new QVBoxLayout(this);
layout->setContentsMargins(0, 0, 0, 0);
@@ -50,6 +52,13 @@ void ActionGroup::init(bool hasHeader)
layout->addWidget(myHeader);
auto *separator = new QFrame(this);
separator->setFrameShape(QFrame::HLine);
separator->setFrameShadow(QFrame::Raised);
separator->setFixedHeight(separatorHeight);
separator->setContentsMargins(8, 0, 8, 0);
layout->addWidget(separator);
myGroup = new TaskGroup(this, hasHeader);
layout->addWidget(myGroup);
@@ -60,6 +69,14 @@ void ActionGroup::init(bool hasHeader)
connect(myHeader, &TaskHeader::activated, this, &ActionGroup::showHide);
}
void ActionGroup::setScheme(ActionPanelScheme *scheme)
{
myScheme = scheme;
myHeader->setScheme(scheme);
myGroup->setScheme(scheme);
update();
}
QBoxLayout* ActionGroup::groupLayout()
{
return myGroup->groupLayout();
@@ -122,14 +139,14 @@ void ActionGroup::processHide()
{
myDummy->hide();
myHeader->setFold(false);
setFixedHeight(myHeader->height());
setFixedHeight(myHeader->height() + separatorHeight);
setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred);
return;
}
m_tempHeight -= m_foldDelta;
myDummy->setFixedHeight(m_tempHeight);
setFixedHeight(myDummy->height() + myHeader->height());
setFixedHeight(myDummy->height() + myHeader->height() + separatorHeight);
QTimer::singleShot(myScheme->groupFoldDelay, this, &ActionGroup::processHide);
}
@@ -142,7 +159,7 @@ void ActionGroup::processShow()
m_foldPixmap = QPixmap();
myGroup->show();
myHeader->setFold(true);
setFixedHeight(m_fullHeight + myHeader->height());
setFixedHeight(m_fullHeight + myHeader->height() + separatorHeight);
setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred);
setMaximumHeight(QWIDGETSIZE_MAX);
return;
@@ -150,7 +167,7 @@ void ActionGroup::processShow()
m_tempHeight += m_foldDelta;
myDummy->setFixedHeight(m_tempHeight);
setFixedHeight(myDummy->height() + myHeader->height());
setFixedHeight(myDummy->height() + myHeader->height() + separatorHeight);
QTimer::singleShot(myScheme->groupFoldDelay, this, &ActionGroup::processShow);
}

View File

@@ -102,6 +102,11 @@ public:
*/
QBoxLayout* groupLayout();
/**
* @brief Set the style of the widgets
*/
void setScheme(ActionPanelScheme *scheme);
/**
* @brief Checks if the group is expandable.
* @return `true` if the group is expandable, `false` otherwise.
@@ -192,6 +197,9 @@ protected:
TaskGroup *myGroup = nullptr; ///< The container for actions/widgets.
QWidget *myDummy = nullptr; ///< Dummy widget for animation.
ActionPanelScheme *myScheme = nullptr; ///< The color scheme.
private:
const int separatorHeight = 1;
};
} // namespace QSint

View File

@@ -10,6 +10,8 @@
#include <QApplication>
#include <QStyleOptionToolButton>
#include <QAction>
#include <QPainter>
#include <cmath>
namespace QSint
{
@@ -68,4 +70,38 @@ QSize ActionLabel::minimumSizeHint() const
return sizeHint();
}
void ActionLabel::paintEvent(QPaintEvent *event)
{
Q_UNUSED(event);
QPainter painter(this);
constexpr int elementSpacing = 5;
int iconSize = fontMetrics().height();
QIcon icon = this->icon();
QString text = this->text();
QRect contentRect = rect().adjusted(elementSpacing, elementSpacing, -elementSpacing, -elementSpacing); // Apply margins
int currentX = contentRect.left();
if (!icon.isNull()) {
QPixmap pixmap = icon.pixmap(iconSize, iconSize);
QRect iconRect(currentX, contentRect.center().y() - iconSize / 2, iconSize, iconSize);
painter.setRenderHint(QPainter::SmoothPixmapTransform);
painter.drawPixmap(iconRect, pixmap);
currentX += iconSize + elementSpacing;
}
if (!text.isEmpty()) {
QRect textRect(currentX, contentRect.top(), contentRect.right() - currentX, contentRect.height());
QFont font = this->font();
font.setUnderline(underMouse());
painter.setFont(font);
painter.setRenderHint(QPainter::TextAntialiasing);
painter.drawText(textRect, Qt::AlignVCenter | Qt::AlignLeft, text);
}
}
} // namespace QSint

View File

@@ -56,6 +56,9 @@ public:
*/
QSize minimumSizeHint() const override;
private:
void paintEvent(QPaintEvent *event) override;
protected:
/**
* @brief Initializes the ActionLabel.

View File

@@ -29,11 +29,18 @@ ActionPanel::ActionPanel(QWidget *parent) :
void ActionPanel::setScheme(ActionPanelScheme *scheme)
{
if (!scheme) return;
if (!scheme) {
return;
}
myScheme = scheme;
setStyleSheet(myScheme->actionStyle);
// set scheme for children
QObjectList list(children());
Q_FOREACH(QObject *obj, list) {
if (dynamic_cast<ActionGroup*>(obj)) {
((ActionGroup*)obj)->setScheme(scheme);
continue;
}
}
update();
}

View File

@@ -11,60 +11,6 @@
namespace QSint
{
const QString ActionPanelScheme::minimumStyle = QStringLiteral(
"QSint--ActionGroup QFrame[class='header'] {"
"border: none;"
"}"
"QSint--ActionGroup QToolButton[class='header'] {"
"border: none;"
"font-weight: bold;"
"text-align: center;"
"background: none;"
"}"
"QSint--ActionGroup QToolButton[class='action'] {"
"border: none;"
"background: none;"
"}"
"QSint--ActionGroup QToolButton[class='action']:hover {"
"text-decoration: underline;"
"}"
"QSint--ActionGroup QFrame[class='content'][header='true'] {"
"border: none;"
"}"
);
QString ActionPanelScheme::systemStyle(const QPalette& p)
{
const QColor& highlightColor = p.color(QPalette::Highlight);
QColor headerBackground = highlightColor.darker(150);
const QColor& groupBackground = p.color(QPalette::Button);
QHash<QString, QString> replacements;
replacements["headerBackground"] = headerBackground.name();
replacements["groupBackground"] = groupBackground.name();;
QString style = QStringLiteral(
"QSint--ActionGroup QFrame[class='header'] {"
"background-color: {headerBackground};"
"}"
"QSint--ActionGroup QFrame[class='content'] {"
"background-color: {groupBackground};"
"}"
);
for (auto it = replacements.begin(); it != replacements.end(); ++it) {
style.replace("{" + it.key() + "}", it.value());
}
return style;
}
QPixmap ActionPanelScheme::drawFoldIcon(const QPalette& palette, bool fold, bool hover) const
{
QSize bSize = headerButtonSize;
@@ -82,13 +28,6 @@ QPixmap ActionPanelScheme::drawFoldIcon(const QPalette& palette, bool fold, bool
qreal bot_Y = 0.40 * bSize.height();
qreal top_Y = 0.64 * bSize.height();
if (hover) {
penWidth *= 1.8;
}
painter.setBrush(Qt::NoBrush);
painter.setPen(QPen(palette.color(QPalette::HighlightedText), penWidth));
QPolygon chevron;
if (fold) {
// Upward
@@ -102,7 +41,20 @@ QPixmap ActionPanelScheme::drawFoldIcon(const QPalette& palette, bool fold, bool
<< QPoint(rig_X, bot_Y);
}
painter.setBrush(Qt::NoBrush);
// Outline
QColor outlineColor = palette.color(QPalette::Button);
painter.setPen(QPen(outlineColor, penWidth * 3, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin));
painter.drawPolyline(chevron);
// Chevron
if (hover) {
penWidth *= 1.8;
}
QColor mainColor = palette.color(QPalette::Text);
painter.setPen(QPen(mainColor, penWidth, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin));
painter.drawPolyline(chevron);
painter.end();
return QPixmap::fromImage(img);
}
@@ -115,24 +67,29 @@ ActionPanelScheme::ActionPanelScheme()
QPalette p = QApplication::palette();
headerButtonSize = QSize(16, 16);
headerButtonFold = drawFoldIcon(p, true, false);
headerButtonFoldOver = drawFoldIcon(p, true, true);
headerButtonUnfold = drawFoldIcon(p, false, false);
headerButtonUnfoldOver = drawFoldIcon(p, false, true);
int iconSize = fm.height();
headerButtonSize = QSize(iconSize, iconSize);
builtinFold = drawFoldIcon(p, true, false);
builtinFoldOver = drawFoldIcon(p, true, true);
builtinUnfold = drawFoldIcon(p, false, false);
builtinUnfoldOver = drawFoldIcon(p, false, true);
builtinFold = headerButtonFold;
builtinFoldOver = headerButtonFoldOver;
builtinUnfold = headerButtonUnfold;
builtinUnfoldOver = headerButtonUnfoldOver;
if (qApp->styleSheet().isEmpty()) {
headerButtonFold = builtinFold;
headerButtonFoldOver = builtinFoldOver;
headerButtonUnfold = builtinUnfold;
headerButtonUnfoldOver = builtinUnfoldOver;
} else {
headerButtonFold = QPixmap();
headerButtonFoldOver = QPixmap();
headerButtonUnfold = QPixmap();
headerButtonUnfoldOver = QPixmap();
}
groupFoldSteps = 20;
groupFoldDelay = 15;
groupFoldEffect = NoFolding;
groupFoldThaw = true;
actionStyle = minimumStyle + systemStyle(p);
builtinScheme = actionStyle;
}
ActionPanelScheme* ActionPanelScheme::defaultScheme()
@@ -147,8 +104,6 @@ void ActionPanelScheme::clearActionStyle()
headerButtonFoldOver = QPixmap();
headerButtonUnfold = QPixmap();
headerButtonUnfoldOver = QPixmap();
actionStyle = minimumStyle;
}
void ActionPanelScheme::restoreActionStyle()
@@ -157,8 +112,6 @@ void ActionPanelScheme::restoreActionStyle()
headerButtonFoldOver = builtinFoldOver;
headerButtonUnfold = builtinUnfold;
headerButtonUnfoldOver = builtinUnfoldOver;
actionStyle = builtinScheme;
}
} // namespace QSint

View File

@@ -15,7 +15,6 @@
#include <QPainter>
#include <QPalette>
#include <QPixmap>
#include <QHash>
#include <QSize>
#include <QString>
#include <QStyle>
@@ -121,18 +120,6 @@ public:
*/
void restoreActionStyle();
/**
* @brief Minimal CSS style.
*/
static const QString minimumStyle;
/**
* @brief Generates a custom system style based on the palette.
* @param p The palette to use for generating the style.
* @return The generated style.
*/
QString systemStyle(const QPalette& p);
protected:
/**
* @brief Draws a fold/unfold icon.
@@ -151,7 +138,6 @@ private:
QPixmap builtinFoldOver;
QPixmap builtinUnfold;
QPixmap builtinUnfoldOver;
QString builtinScheme;
};
} // namespace QSint

View File

@@ -22,6 +22,8 @@ TaskGroup::TaskGroup(QWidget *parent, bool hasHeader)
setProperty("class", "content");
setProperty("header", hasHeader ? "true" : "false");
setScheme(ActionPanelScheme::defaultScheme());
QVBoxLayout *vbl = new QVBoxLayout();
vbl->setContentsMargins(4, 4, 4, 4);
vbl->setSpacing(0);
@@ -30,6 +32,14 @@ TaskGroup::TaskGroup(QWidget *parent, bool hasHeader)
setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Maximum);
}
void TaskGroup::setScheme(ActionPanelScheme *scheme)
{
if (scheme) {
myScheme = scheme;
update();
}
}
bool TaskGroup::addActionLabel(ActionLabel *label, bool addToLayout, bool addStretch)
{
if (!label) {

View File

@@ -25,6 +25,7 @@ class TaskGroup : public QFrame
public:
TaskGroup(QWidget *parent, bool hasHeader = false);
void setScheme(ActionPanelScheme *scheme);
inline QBoxLayout* groupLayout()
{

View File

@@ -35,6 +35,9 @@ TaskHeader::TaskHeader(const QIcon &icon, const QString &title, bool expandable,
myTitle->setText(title);
myTitle->setIcon(icon);
myTitle->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Preferred);
QFont font = myTitle->font();
font.setBold(true);
myTitle->setFont(font);
connect(myTitle, &ActionLabel::clicked, this, &TaskHeader::fold);

View File

@@ -1,6 +1,8 @@
QFrame {
Gui--DockWnd--ReportOutput,
Gui--TaskView--TaskView {
border: none;
}
}
QTabWidget::pane{
background-color: transparent;
border: transparent;

View File

@@ -1,6 +1,8 @@
QFrame {
Gui--DockWnd--ReportOutput,
Gui--TaskView--TaskView {
border: none;
}
QTabWidget::pane{
background-color: transparent;
border: transparent;

View File

@@ -1,4 +1,5 @@
QFrame {
Gui--DockWnd--ReportOutput,
Gui--TaskView--TaskView {
border: none;
}

View File

@@ -1,4 +1,5 @@
QFrame {
Gui--DockWnd--ReportOutput,
Gui--TaskView--TaskView {
border: none;
}