Skip to content

fix: Optimised the Quick Panel UI#447

Open
JWWTSL wants to merge 2 commits intolinuxdeepin:masterfrom
JWWTSL:master
Open

fix: Optimised the Quick Panel UI#447
JWWTSL wants to merge 2 commits intolinuxdeepin:masterfrom
JWWTSL:master

Conversation

@JWWTSL
Copy link
Copy Markdown

@JWWTSL JWWTSL commented Apr 10, 2026

log: In light mode, icon and text colours are 000000 with 70% opacity; in dark mode, icon and text colours are ffffff with 70% opacity; on hover, icon and text colours are 100% opacity. Furthermore, the text colour of the titles in the secondary panel does not need to be adjusted; only the colours of the icons and text in the list need to be adjusted.

pms: bug-314503

Summary by Sourcery

Align quick panel list icon and text colors with design requirements across dock plugins, including hover behavior and light/dark theme opacity.

Bug Fixes:

  • Correct quick panel list item colors in light and dark themes to use 70% opacity by default and 100% on hover.

Enhancements:

  • Unify hover handling for quick panel items and their icons via shared parent hover state.
  • Adjust common icon button defaults and plugin delegates to use semi-transparent theme colors for inactive states.

log: In light mode, icon and text colours are 000000 with 70% opacity; in dark mode, icon and text colours are ffffff with 70% opacity; on hover, icon and text colours are 100% opacity. Furthermore, the text colour of the titles in the secondary panel does not need to be adjusted; only the colours of the icons and text in the list need to be adjusted.

pms: bug-314503
@deepin-ci-robot
Copy link
Copy Markdown

[APPROVALNOTIFIER] This PR is NOT APPROVED

This pull-request has been approved by: JWWTSL

The full list of commands accepted by this bot can be found here.

Details Needs approval from an approver in each of these files:

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

@sourcery-ai
Copy link
Copy Markdown

sourcery-ai bot commented Apr 10, 2026

Reviewer's Guide

Unifies quick panel icon and text hover behavior across multiple dock plugins by introducing parent-hover propagation, theme-aware text color updates with 70% default opacity and 100% on hover, and updating shared CommonIconButton colors and palettes to respect the new design in both light and dark modes.

Class diagram for unified quick panel hover behavior

classDiagram
    class DFloatingButton
    class QWidget
    class DLabel
    class DIconButton
    class DGuiApplicationHelper
    class QEnterEvent
    class QEvent
    class QIcon

    class QuickButton {
        +QuickButton(parent)
        +void setParentHover(bool hover)
        #void initStyleOption(DStyleOptionButton option)
        -bool m_parentHover
    }

    class CommonIconButton {
        +CommonIconButton(parent)
        +void setIcon(QIcon icon, QColor lightColor, QColor darkColor)
        +void setHoverEnable(bool enable)
        +void setIconSize(QSize size)
        +void setAllEnabled(bool enable)
        +void setParentHover(bool hover)
        -bool event(QEvent e)
        -void updatePalette()
        -QTimer m_refreshTimer
        -bool m_clickable
        -bool m_hover
        -bool m_parentHover
        -State m_state
        -QColor m_lightThemeColor
        -QColor m_darkThemeColor
        -bool m_activeState
        -bool m_hoverEnable
        -QSize m_iconSize
    }

    class QuickPanelWidget_bluetooth {
        +QuickPanelWidget_bluetooth(parent)
        +void mousePressEvent(QMouseEvent event)
        +void mouseReleaseEvent(QMouseEvent event)
        +void enterEvent(QEnterEvent event)
        +void leaveEvent(QEvent event)
        -void initUi()
        -void initConnection()
        -void updateTextColor(bool hover)
        -QuickButton m_iconWidget
        -DLabel m_nameLabel
        -DLabel m_stateLabel
        -DIconButton m_expandLabel
        -QPoint m_clickPoint
        -bool m_hover
    }

    class QuickPanelWidget_wirelesscasting {
        +QuickPanelWidget_wirelesscasting(parent)
        +void mousePressEvent(QMouseEvent event)
        +void mouseReleaseEvent(QMouseEvent event)
        +void enterEvent(QEnterEvent event)
        +void leaveEvent(QEvent event)
        -void initUi()
        -void initConnection()
        -void updateTextColor(bool hover)
        -QuickButton m_iconWidget
        -DLabel m_nameLabel
        -DLabel m_stateLabel
        -DIconButton m_expandLabel
        -QPoint m_clickPoint
        -bool m_hover
    }

    class QuickPanelWidget_eyecomfort {
        +QuickPanelWidget_eyecomfort(parent)
        +void mousePressEvent(QMouseEvent event)
        +void mouseReleaseEvent(QMouseEvent event)
        +void enterEvent(QEnterEvent event)
        +void leaveEvent(QEvent event)
        -void initUi()
        -void initConnection()
        -void updateTextColor(bool hover)
        -QuickButton m_iconWidget
        -DLabel m_nameLabel
        -DLabel m_stateLabel
        -DIconButton m_expandLabel
        -QPoint m_clickPoint
        -bool m_eyeComfortModeEnabled
        -bool m_hover
    }

    class QuickPanelWidget_media {
        +QuickPanelWidget_media(MediaController controller, QWidget parent)
        +void mouseReleaseEvent(QMouseEvent event)
        +void enterEvent(QEnterEvent event)
        +void leaveEvent(QEvent event)
        -void init()
        -void updateUI()
        -void updateTextColor(bool hover)
        -MediaController m_controller
        -DLabel m_titleLab
        -DLabel m_artistLab
        -CommonIconButton m_playButton
        -CommonIconButton m_nextButton
        -bool m_hover
    }

    class SignalQuickPanel {
        +SignalQuickPanel(parent)
        +void setIcon(QIcon icon)
        +void setDescription(QString description)
        +void mouseReleaseEvent(QMouseEvent event)
        +void enterEvent(QEnterEvent event)
        +void leaveEvent(QEvent event)
        -void initUI()
        -void refreshBg()
        -void updateTextColor()
        -CommonIconButton m_icon
        -DLabel m_description
        -bool m_active
        -bool m_hover
    }

    class JumpSettingButton {
        +JumpSettingButton(QWidget parent)
        +void setIcon(QIcon icon)
        +void setDescription(QString description)
        +bool event(QEvent e)
        +void paintEvent(QPaintEvent e)
        -CommonIconButton m_iconButton
        -bool m_hover
    }

    QuickButton --|> DFloatingButton
    QuickPanelWidget_bluetooth --|> QWidget
    QuickPanelWidget_wirelesscasting --|> QWidget
    QuickPanelWidget_eyecomfort --|> QWidget
    QuickPanelWidget_media --|> QWidget
    SignalQuickPanel --|> QWidget
    JumpSettingButton --|> QWidget

    QuickPanelWidget_bluetooth --> QuickButton
    QuickPanelWidget_wirelesscasting --> QuickButton
    QuickPanelWidget_eyecomfort --> QuickButton
    QuickPanelWidget_media --> CommonIconButton
    SignalQuickPanel --> CommonIconButton
    JumpSettingButton --> CommonIconButton

    CommonIconButton --> DGuiApplicationHelper
Loading

Flow diagram for hover-based text and icon color handling

flowchart TD
    A_mouseEnterQuickPanel[mouseEnter QuickPanelWidget] --> B_setHoverTrue[set m_hover true]
    B_setHoverTrue --> C_propagateParentHover[call setParentHover true on child buttons]
    C_propagateParentHover --> D_updateTextColorHover[call updateTextColor true]

    A2_mouseLeaveQuickPanel[mouseLeave QuickPanelWidget] --> B2_setHoverFalse[set m_hover false]
    B2_setHoverFalse --> C2_clearParentHover[call setParentHover false on child buttons]
    C2_clearParentHover --> D2_updateTextColorNormal[call updateTextColor false]

    subgraph updateTextColor
        D_updateTextColorHover --> E_getTheme[DGuiApplicationHelper.instance themeType]
        D2_updateTextColorNormal --> E_getTheme
        E_getTheme --> F_chooseBaseColor{themeType is LightType}
        F_chooseBaseColor -- yes --> G_lightColor[QColor 0,0,0]
        F_chooseBaseColor -- no --> H_darkColor[QColor 255,255,255]
        G_lightColor --> I_setAlpha[set alpha to 1.0 when hover or 0.7 otherwise]
        H_darkColor --> I_setAlpha
        I_setAlpha --> J_applyPalette[update QPalette WindowText,BrightText and set on labels]
    end

    subgraph CommonIconButton_hover
        K_enterEvent[event type Enter] --> L_setHoverTrue[set m_hover true]
        K_leaveEvent[event type Leave] --> M_setHoverFalse[set m_hover false]
        L_setHoverTrue --> N_updatePalette
        M_setHoverFalse --> N_updatePalette
        O_setParentHover[setParentHover from parent] --> P_updateParentHover[m_parentHover updated]
        P_updateParentHover --> N_updatePalette
        N_updatePalette --> Q_computeIconColor[theme-based color, alpha 178 normally, 255 if m_hover or m_parentHover]
        Q_computeIconColor --> R_applyIconPalette[update QPalette WindowText]
    end
Loading

File-Level Changes

Change Details Files
Propagate hover state from quick panel containers to their embedded buttons so icons and button backgrounds react when the row is hovered, not only when the button itself is hovered.
  • Add m_parentHover flag and setParentHover() API to QuickButton in bluetooth and eye-comfort-mode quickpanel widgets to let the container control hover visuals.
  • Adjust QuickButton::initStyleOption to base text alpha on m_parentHover and to treat m_parentHover as hover for background alpha decisions.
  • Update CommonIconButton to track a new m_parentHover flag, expose setParentHover(), and factor m_parentHover into hover palette updates instead of only using internal hover events.
plugins/dde-dock/bluetooth/quickpanelwidget.cpp
plugins/dde-dock/eye-comfort-mode/quickpanelwidget.cpp
plugins/dde-dock/eye-comfort-mode/quickpanelwidget.h
plugins/dde-dock/common/commoniconbutton.cpp
plugins/dde-dock/common/commoniconbutton.h
Implement consistent theme-aware text color behavior in quick panels: 70% opacity in idle state and 100% opacity on hover, with proper light/dark color selection.
  • Add DGuiApplicationHelper and QEnterEvent includes where needed to query theme and handle enter/leave events.
  • Introduce m_hover flags in QuickPanelWidget-like classes and SignalQuickPanel to track row hover state.
  • Add updateTextColor helpers in quickpanel widgets and SignalQuickPanel that choose black or white based on theme, set alpha to 0.7 or 1.0 depending on hover/active, and apply via QPalette to relevant labels.
  • Wire enterEvent/leaveEvent overrides in quickpanel widgets and SignalQuickPanel to toggle m_hover, call setParentHover on child icon buttons, and invoke updateTextColor accordingly.
plugins/dde-dock/bluetooth/quickpanelwidget.cpp
plugins/dde-dock/bluetooth/quickpanelwidget.h
plugins/dde-network-display-ui/plugins/dock-wirelesscasting-plugin/src/quickpanelwidget.cpp
plugins/dde-network-display-ui/plugins/dock-wirelesscasting-plugin/src/quickpanelwidget.h
plugins/dde-dock/media/quickpanelwidget.cpp
plugins/dde-dock/media/quickpanelwidget.h
plugins/dde-dock/eye-comfort-mode/quickpanelwidget.cpp
plugins/dde-dock/eye-comfort-mode/quickpanelwidget.h
plugins/dde-dock/common/singlequickpanel.cpp
plugins/dde-dock/common/singlequickpanel.h
Align shared icon and text default colors with the new spec (70% opacity black/white) across common components and delegates.
  • Change CommonIconButton default light/dark theme colors from fully opaque Qt::black/Qt::white to QColor(0,0,0,178) and QColor(255,255,255,178) respectively, and use these when setting playback and navigation icons in the media quick panel, JumpSettingButton, and SignalQuickPanel.
  • In PluginItemDelegate::paint and JumpSettingButton::paintEvent, set non-selected text colors to 70% opacity by adjusting the alpha of brightText-derived colors.
  • Ensure quick panel list item text in shared components uses the adjusted alpha while preserving full opacity for selected/active states.
plugins/dde-dock/common/commoniconbutton.cpp
plugins/dde-dock/media/quickpanelwidget.cpp
plugins/dde-dock/common/jumpsettingbutton.cpp
plugins/dde-dock/common/pluginitemdelegate.cpp
plugins/dde-dock/common/singlequickpanel.cpp

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

Copy link
Copy Markdown

@sourcery-ai sourcery-ai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey - I've found 1 issue, and left some high level feedback:

  • The hover/text-color handling (including theme detection, alpha 0.7 vs 1.0 and nearly identical updateTextColor implementations) is duplicated across several QuickPanelWidget variants; consider extracting a small shared helper/utility or base class to avoid repeating this logic in each plugin.
  • Several classes maintain a m_hover member while also passing a hover bool into updateTextColor (e.g., QuickPanelWidget in bluetooth/eye-comfort/wirelesscasting/media); since m_hover is never read inside updateTextColor, you can either drop the member or have updateTextColor read m_hover directly for clearer and less error-prone state management.
Prompt for AI Agents
Please address the comments from this code review:

## Overall Comments
- The hover/text-color handling (including theme detection, alpha 0.7 vs 1.0 and nearly identical updateTextColor implementations) is duplicated across several QuickPanelWidget variants; consider extracting a small shared helper/utility or base class to avoid repeating this logic in each plugin.
- Several classes maintain a m_hover member while also passing a hover bool into updateTextColor (e.g., QuickPanelWidget in bluetooth/eye-comfort/wirelesscasting/media); since m_hover is never read inside updateTextColor, you can either drop the member or have updateTextColor read m_hover directly for clearer and less error-prone state management.

## Individual Comments

### Comment 1
<location path="plugins/dde-dock/eye-comfort-mode/quickpanelwidget.cpp" line_range="41" />
<code_context>
             }
         } else {
-            textColor.setAlphaF(1);
+            textColor.setAlphaF(m_parentHover ? 1.0 : 0.7);
             if (!option->state.testFlag(QStyle::State_Raised)) { // press
                 bgColor.setAlphaF(0.2);
</code_context>
<issue_to_address>
**issue (complexity):** Consider simplifying the hover handling by deriving hover state from `underMouse()` instead of maintaining separate `m_hover`/`m_parentHover` flags and setter wiring between parent and child widgets.

You can keep the visual behavior while simplifying the hover logic and removing redundant state.

### 1) Remove `m_parentHover` and let the button inspect its parent

Instead of wiring a separate `m_parentHover` flag through `setParentHover`, you can read the parent’s hover state directly in `QuickButton::initStyleOption`:

```cpp
void QuickButton::initStyleOption(DStyleOptionButton *option) const
{
    DIconButton::initStyleOption(option);

    QColor bgColor = option->palette.color(backgroundRole());
    QColor textColor = option->palette.color(foregroundRole());

    const bool parentHover = parentWidget() && parentWidget()->underMouse();

    if (backgroundRole() == QPalette::Highlight) {
        textColor = Qt::white;
        if (!option->state.testFlag(QStyle::State_Raised)) {
            bgColor.setHslF(bgColor.hslHueF(), bgColor.hslSaturationF(), bgColor.lightnessF() * 0.9);
            textColor.setAlphaF(0.8);
        } else if (option->state.testFlag(QStyle::State_MouseOver)) {
            bgColor.setHslF(bgColor.hslHueF(), bgColor.hslSaturationF(), bgColor.lightnessF() * 1.1);
        }
    } else {
        textColor.setAlphaF(parentHover ? 1.0 : 0.7);
        if (!option->state.testFlag(QStyle::State_Raised)) {
            bgColor.setAlphaF(0.2);
        } else if (option->state.testFlag(QStyle::State_MouseOver) || parentHover) {
            bgColor.setAlphaF(0.15);
        } else {
            bgColor.setAlphaF(0.1);
        }
    }

    if (m_mode == ButtonMode::DisplayButton) {
        bgColor.setAlphaF(0);
    }

    option->palette.setColor(backgroundRole(), bgColor);
    option->palette.setColor(foregroundRole(), textColor);
    option->state.setFlag(QStyle::State_Raised, true);
}
```

Then you can drop `QuickButton::setParentHover`, the `m_parentHover` member, and all calls to `setParentHover` in `QuickPanelWidget`.

### 2) Use a single source of truth for hover in `QuickPanelWidget`

`m_hover` and the `hover` parameter on `updateTextColor` represent the same state. You can remove both and read the hover state from `underMouse()`:

```cpp
void QuickPanelWidget::enterEvent(QEnterEvent *event)
{
    updateTextColor();
    QWidget::enterEvent(event);
}

void QuickPanelWidget::leaveEvent(QEvent *event)
{
    updateTextColor();
    QWidget::leaveEvent(event);
}

void QuickPanelWidget::updateTextColor()
{
    const bool hover = underMouse();
    const bool isLight = DGuiApplicationHelper::instance()->themeType()
                         == DGuiApplicationHelper::LightType;

    QColor color = isLight ? QColor(0, 0, 0) : QColor(255, 255, 255);
    color.setAlphaF(hover ? 1.0 : 0.7);

    QPalette pa = m_nameLabel->palette();
    pa.setColor(QPalette::BrightText, color);
    pa.setColor(QPalette::WindowText, color);
    m_nameLabel->setPalette(pa);
    m_stateLabel->setPalette(pa);
}
```

With that, you can remove:

- The `m_hover` member.
- The `bool hover` parameter from `updateTextColor` and all call sites passing `true`/`false`.
- The `setParentHover(true/false)` calls (since `QuickButton` now reads `parentWidget()->underMouse()`).

This keeps all visual behavior but:

- Eliminates redundant state (`m_hover`, `m_parentHover`).
- Removes flag juggling between parent and child.
- Makes the hover behavior more self-contained and easier to reason about.
</issue_to_address>

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

}
} else {
textColor.setAlphaF(1);
textColor.setAlphaF(m_parentHover ? 1.0 : 0.7);
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

issue (complexity): Consider simplifying the hover handling by deriving hover state from underMouse() instead of maintaining separate m_hover/m_parentHover flags and setter wiring between parent and child widgets.

You can keep the visual behavior while simplifying the hover logic and removing redundant state.

1) Remove m_parentHover and let the button inspect its parent

Instead of wiring a separate m_parentHover flag through setParentHover, you can read the parent’s hover state directly in QuickButton::initStyleOption:

void QuickButton::initStyleOption(DStyleOptionButton *option) const
{
    DIconButton::initStyleOption(option);

    QColor bgColor = option->palette.color(backgroundRole());
    QColor textColor = option->palette.color(foregroundRole());

    const bool parentHover = parentWidget() && parentWidget()->underMouse();

    if (backgroundRole() == QPalette::Highlight) {
        textColor = Qt::white;
        if (!option->state.testFlag(QStyle::State_Raised)) {
            bgColor.setHslF(bgColor.hslHueF(), bgColor.hslSaturationF(), bgColor.lightnessF() * 0.9);
            textColor.setAlphaF(0.8);
        } else if (option->state.testFlag(QStyle::State_MouseOver)) {
            bgColor.setHslF(bgColor.hslHueF(), bgColor.hslSaturationF(), bgColor.lightnessF() * 1.1);
        }
    } else {
        textColor.setAlphaF(parentHover ? 1.0 : 0.7);
        if (!option->state.testFlag(QStyle::State_Raised)) {
            bgColor.setAlphaF(0.2);
        } else if (option->state.testFlag(QStyle::State_MouseOver) || parentHover) {
            bgColor.setAlphaF(0.15);
        } else {
            bgColor.setAlphaF(0.1);
        }
    }

    if (m_mode == ButtonMode::DisplayButton) {
        bgColor.setAlphaF(0);
    }

    option->palette.setColor(backgroundRole(), bgColor);
    option->palette.setColor(foregroundRole(), textColor);
    option->state.setFlag(QStyle::State_Raised, true);
}

Then you can drop QuickButton::setParentHover, the m_parentHover member, and all calls to setParentHover in QuickPanelWidget.

2) Use a single source of truth for hover in QuickPanelWidget

m_hover and the hover parameter on updateTextColor represent the same state. You can remove both and read the hover state from underMouse():

void QuickPanelWidget::enterEvent(QEnterEvent *event)
{
    updateTextColor();
    QWidget::enterEvent(event);
}

void QuickPanelWidget::leaveEvent(QEvent *event)
{
    updateTextColor();
    QWidget::leaveEvent(event);
}

void QuickPanelWidget::updateTextColor()
{
    const bool hover = underMouse();
    const bool isLight = DGuiApplicationHelper::instance()->themeType()
                         == DGuiApplicationHelper::LightType;

    QColor color = isLight ? QColor(0, 0, 0) : QColor(255, 255, 255);
    color.setAlphaF(hover ? 1.0 : 0.7);

    QPalette pa = m_nameLabel->palette();
    pa.setColor(QPalette::BrightText, color);
    pa.setColor(QPalette::WindowText, color);
    m_nameLabel->setPalette(pa);
    m_stateLabel->setPalette(pa);
}

With that, you can remove:

  • The m_hover member.
  • The bool hover parameter from updateTextColor and all call sites passing true/false.
  • The setParentHover(true/false) calls (since QuickButton now reads parentWidget()->underMouse()).

This keeps all visual behavior but:

  • Eliminates redundant state (m_hover, m_parentHover).
  • Removes flag juggling between parent and child.
  • Makes the hover behavior more self-contained and easier to reason about.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants