Skip to content

Commit b16b768

Browse files
sync: from linuxdeepin/qt5integration
Synchronize source files from linuxdeepin/qt5integration. Source-pull-request: linuxdeepin/qt5integration#231
1 parent b049bf8 commit b16b768

File tree

4 files changed

+150
-73
lines changed

4 files changed

+150
-73
lines changed

CMakeLists.txt

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -103,12 +103,23 @@ function(dtk_add_plugin)
103103
endfunction()
104104

105105
find_package(Dtk${VERSION_SUFFIX} REQUIRED COMPONENTS Widget)
106-
cmake_dependent_option(ENABLE_QT_XDG_ICON_LOADER "Enable QtXdgIconLoader" ON "QT_VERSION_MAJOR EQUAL 5" OFF)
106+
107+
option(ENABLE_QT_XDG_ICON_LOADER "Enable QtXdgIconLoader" ON)
108+
find_package(Qt${QT_VERSION_MAJOR}XdgIconLoader)
109+
find_package(Qt${QT_VERSION_MAJOR}Xdg REQUIRED)
110+
if (NOT Qt${QT_VERSION_MAJOR}XdgIconLoader_FOUND)
111+
message(WARNING " Qt${QT_VERSION_MAJOR}XdgIconLoader Not Found, DISABLE QtXdgIconLoader !")
112+
set (ENABLE_QT_XDG_ICON_LOADER OFF)
113+
endif()
114+
107115
if(ENABLE_QT_XDG_ICON_LOADER)
108-
find_package(Qt5XdgIconLoader REQUIRED)
109-
find_package(Qt5Xdg REQUIRED)
110-
set(QT_XDG_ICON_DEPS Qt5XdgIconLoader Qt5Xdg)
111-
set(XDG_ICON_VERSION_MAJOR ${Qt5XdgIconLoader_VERSION_MAJOR})
116+
set(QT_XDG_ICON_DEPS Qt${QT_VERSION_MAJOR}XdgIconLoader Qt${QT_VERSION_MAJOR}Xdg)
117+
118+
if("${QT_VERSION_MAJOR}" STREQUAL "5")
119+
set(XDG_ICON_VERSION_MAJOR ${Qt5XdgIconLoader_VERSION_MAJOR})
120+
elseif("${QT_VERSION_MAJOR}" STREQUAL "6")
121+
set(XDG_ICON_VERSION_MAJOR ${Qt6XdgIconLoader_VERSION_MAJOR})
122+
endif()
112123
endif()
113124

114125
set(PLUGIN_OUTPUT_BASE_DIR ${CMAKE_BINARY_DIR}/plugins CACHE STRING "Plugin output base path")

platformthemeplugin/CMakeLists.txt

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ find_package(Qt${QT_VERSION_MAJOR} REQUIRED COMPONENTS DBus Widgets)
66
set(QT_LIBS Qt${QT_VERSION_MAJOR}::DBus Qt${QT_VERSION_MAJOR}::Widgets)
77
if(QT_VERSION_MAJOR EQUAL 5)
88
find_package(Qt5X11Extras REQUIRED)
9-
list(APPEND QT_LIBS Qt5::X11Extras ${QT_XDG_ICON_DEPS})
9+
list(APPEND QT_LIBS Qt5::X11Extras)
1010
if(QT_VERSION_MINOR GREATER_EQUAL 8) # Qt5.8
1111
find_package(Qt5ThemeSupport REQUIRED)
1212
list(APPEND QT_LIBS Qt5::ThemeSupportPrivate)
@@ -26,10 +26,12 @@ if(QT_VERSION_MAJOR EQUAL 5)
2626
else()
2727
list(APPEND QT_LIBS Qt6::GuiPrivate)
2828
endif()
29+
2930
find_package(PkgConfig REQUIRED)
3031
pkg_check_modules(Deps REQUIRED IMPORTED_TARGET mtdev x11)
3132
if(ENABLE_QT_XDG_ICON_LOADER)
3233
set(DEFS -DXDG_ICON_VERSION_MAR=${XDG_ICON_VERSION_MAJOR})
34+
list(APPEND QT_LIBS ${QT_XDG_ICON_DEPS})
3335
endif()
3436
if(QT_VERSION_MAJOR EQUAL 5)
3537
qt5_add_dbus_interface(DBUS_INTERFACES ${CMAKE_CURRENT_LIST_DIR}/xmls/com.deepin.filemanager.filedialog.xml filedialog_interface)

styleplugins/chameleon/chameleonstyle.cpp

Lines changed: 102 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@
4040
#include <QBitmap>
4141
#include <QTableView>
4242
#include <QStyledItemDelegate>
43+
#include <QVariantAnimation>
4344
#include <DSpinBox>
4445
#include <DTreeView>
4546
#include <DIconButton>
@@ -122,6 +123,57 @@ inline static bool isTheClassObject(QObject *object)
122123
#endif
123124
}
124125

126+
ChameleonMovementAnimation::ChameleonMovementAnimation(QWidget *targetWidget)
127+
: QVariantAnimation(targetWidget)
128+
{
129+
setDuration(150);
130+
131+
connect(this, &QVariantAnimation::valueChanged, targetWidget, [this] (const QVariant &value) {
132+
if (!isRuning())
133+
return;
134+
135+
const auto rect = value.toRect();
136+
Q_ASSERT(!m_currentRect.isEmpty());
137+
this->targetWidget()->update(m_currentRect.united(rect));
138+
m_currentRect = rect;
139+
});
140+
connect(this, &QVariantAnimation::finished, targetWidget, [this] {
141+
Q_ASSERT(m_currentRect == m_targetRect);
142+
// 确保动画结束后有一帧的刷新,因为在菜单的动画过程中会修改菜单文字的 opacity
143+
// 对opacity的修改会根据是否处于动画状态进行判断,因此要确保动画结束后刷新它
144+
this->targetWidget()->update(m_currentRect);
145+
});
146+
}
147+
148+
QWidget *ChameleonMovementAnimation::targetWidget() const
149+
{
150+
return qobject_cast<QWidget*>(parent());
151+
}
152+
153+
void ChameleonMovementAnimation::setTargetRect(const QRect &rect)
154+
{
155+
if (m_targetRect == rect)
156+
return;
157+
158+
m_lastTargetRect = m_targetRect;
159+
m_targetRect = rect;
160+
161+
if (m_currentRect.isEmpty())
162+
m_currentRect = m_lastTargetRect;
163+
164+
// 当目标绘制区域改变时,说明当前正在进行的动画过期了,应该重新开始动画
165+
stop();
166+
setStartValue(m_currentRect);
167+
setEndValue(rect);
168+
169+
if (!m_currentRect.isEmpty()) {
170+
start();
171+
} else {
172+
// 这种情况说明不需要进行动画,往往发生在首次显示,这时候应该直接绘制到目标区域
173+
m_currentRect = rect;
174+
}
175+
}
176+
125177
ChameleonStyle::ChameleonStyle()
126178
: DStyle()
127179
{
@@ -2757,7 +2809,7 @@ bool ChameleonStyle::drawMenuBarItem(const QStyleOptionMenuItem *option, QRect &
27572809
return true;
27582810
}
27592811

2760-
void ChameleonStyle::drawMenuItemBackground(const QStyleOption *option, QPainter *painter, QStyleOptionMenuItem::MenuItemType type) const
2812+
ChameleonMovementAnimation *ChameleonStyle::drawMenuItemBackground(const QStyleOption *option, QPainter *painter, QStyleOptionMenuItem::MenuItemType type) const
27612813
{
27622814
QBrush color;
27632815
bool selected = (option->state & QStyle::State_Enabled) && option->state & QStyle::State_Selected;
@@ -2766,50 +2818,11 @@ void ChameleonStyle::drawMenuItemBackground(const QStyleOption *option, QPainter
27662818
painter->setPen(Qt::NoPen);
27672819
painter->setBrush(getColor(option, QPalette::Highlight));
27682820
painter->drawRect(option->rect);
2769-
return;
2821+
return nullptr;
27702822
}
27712823

2772-
// 清理旧的阴影
2773-
if (option->styleObject) {
2774-
const QRect shadow = option->styleObject->property("_d_menu_shadow_rect").toRect();
2775-
const QRect shadow_base = option->styleObject->property("_d_menu_shadow_base_rect").toRect();
2776-
2777-
// 如果当前菜单项时已选中的,并且shadow_base不等于当前区域,此时应当清理阴影区域
2778-
// 如果当前要绘制的item是触发阴影绘制的那一项,那么,此时应当清空阴影区域
2779-
if ((selected && shadow_base != option->rect)
2780-
|| (!selected && shadow_base == option->rect)
2781-
|| (!selected && shadow_base.width() != option->rect.width())) {
2782-
// 清空阴影区域
2783-
option->styleObject->setProperty("_d_menu_shadow_rect", QVariant());
2784-
option->styleObject->setProperty("_d_menu_shadow_base_rect", QVariant());
2785-
2786-
// 确保阴影区域能重绘
2787-
if (QWidget *w = qobject_cast<QWidget*>(option->styleObject)) {
2788-
w->update(shadow);
2789-
}
2790-
}
2791-
}
2792-
27932824
if (selected) {
2794-
color = option->palette.highlight();
2795-
2796-
// draw shadow
2797-
if (type == QStyleOptionMenuItem::Normal) {
2798-
if (option->styleObject) {
2799-
QRect shadow(0, 0, option->rect.width(), 7);
2800-
shadow.moveTop(option->rect.bottom() + 1);
2801-
option->styleObject->setProperty("_d_menu_shadow_rect", shadow);
2802-
option->styleObject->setProperty("_d_menu_shadow_base_rect", option->rect);
2803-
2804-
// 确保阴影区域能重绘
2805-
if (QWidget *w = qobject_cast<QWidget*>(option->styleObject)) {
2806-
w->update(shadow);
2807-
}
2808-
}
2809-
}
2810-
2811-
painter->fillRect(option->rect, color);
2812-
} else {
2825+
} else do {
28132826
color = option->palette.window().color();
28142827

28152828
if (color.color().isValid() && color.color().alpha() != 0) {
@@ -2846,35 +2859,51 @@ void ChameleonStyle::drawMenuItemBackground(const QStyleOption *option, QPainter
28462859
}
28472860

28482861
if (!option->styleObject)
2849-
return;
2862+
break;
28502863

2851-
// 为上一个item绘制阴影
2852-
const QRect shadow = option->styleObject->property("_d_menu_shadow_rect").toRect();
2864+
} while (false);
28532865

2854-
// 判断阴影rect是否在自己的区域
2855-
if (!option->rect.contains(shadow.center()))
2856-
return;
2866+
{ // 无论如何都尝试绘制,因为可能有动画存在
2867+
color = option->palette.highlight();
28572868

2858-
static QColor shadow_color;
2859-
static QPixmap shadow_pixmap;
2869+
QWidget *animationTargetWidget = qobject_cast<QWidget*>(option->styleObject);
2870+
if (!option->styleObject)
2871+
animationTargetWidget = dynamic_cast<QWidget*>(painter->device());
28602872

2861-
if (shadow_color != option->palette.color(QPalette::Active, QPalette::Highlight)) {
2862-
shadow_color = option->palette.color(QPalette::Active, QPalette::Highlight);
2863-
QImage image(":/chameleonstyle/menu_shadow.svg");
2864-
QPainter pa(&image);
2865-
pa.setCompositionMode(QPainter::CompositionMode_SourceIn);
2866-
pa.fillRect(image.rect(), shadow_color);
2867-
shadow_pixmap = QPixmap::fromImage(image);
2868-
}
2873+
ChameleonMovementAnimation *animation = nullptr;
28692874

2870-
if (!shadow_pixmap.isNull()) {
2871-
if (QMenu *menu = qobject_cast<QMenu *>(option->styleObject)) {
2872-
if (!menu->geometry().contains(QCursor::pos()))
2873-
return;
2875+
if (animationTargetWidget) {
2876+
animation = animationTargetWidget->findChild<ChameleonMovementAnimation*>("_d_menu_select_animation",
2877+
Qt::FindDirectChildrenOnly);
2878+
if (!animation) {
2879+
animation = new ChameleonMovementAnimation(animationTargetWidget);
2880+
animation->setObjectName("_d_menu_select_animation");
28742881
}
2875-
painter->drawPixmap(shadow, shadow_pixmap);
2882+
2883+
if (selected)
2884+
animation->setTargetRect(option->rect);
2885+
}
2886+
2887+
if (animation && animation->isRuning()) {
2888+
auto opacity = painter->opacity();
2889+
// 一些状态为 disable 的 menu item 在绘制时会修改不透明度,这里暂时改回1.0。
2890+
painter->setOpacity(1.0);
2891+
painter->setBrush(color);
2892+
painter->setPen(Qt::NoPen);
2893+
QRect rect = animation->currentRect().adjusted(6, 0, -6, 0);
2894+
painter->drawRoundedRect(rect, 6, 6);
2895+
painter->setOpacity(opacity);
2896+
2897+
return animation;
2898+
} else if (selected) {
2899+
painter->setBrush(color);
2900+
painter->setPen(Qt::NoPen);
2901+
QRect rect = option->rect.adjusted(6, 0, -6, 0);
2902+
painter->drawRoundedRect(rect, 6, 6);
28762903
}
28772904
}
2905+
2906+
return nullptr;
28782907
}
28792908

28802909
void ChameleonStyle::drawMenuItemRedPoint(const QStyleOptionMenuItem *option, QPainter *painter, const QWidget *widget) const
@@ -2955,7 +2984,7 @@ bool ChameleonStyle::drawMenuItem(const QStyleOptionMenuItem *option, QPainter *
29552984
bool sunken = menuItem->state & State_Sunken;
29562985

29572986
//绘制背景
2958-
drawMenuItemBackground(option, painter, menuItem->menuItemType);
2987+
auto animation = drawMenuItemBackground(option, painter, menuItem->menuItemType);
29592988

29602989
//绘制分段
29612990
if (menuItem->menuItemType == QStyleOptionMenuItem::Separator) {
@@ -2972,6 +3001,13 @@ bool ChameleonStyle::drawMenuItem(const QStyleOptionMenuItem *option, QPainter *
29723001
return true;
29733002
}
29743003

3004+
const bool useHighlightedText = selected && !animation;
3005+
if (!useHighlightedText && selected) {
3006+
// 在动画中时,selected item 的文字颜色不会使用 HighlightedText,当动画结束后会立即
3007+
// 变为 HighlightedText,会显得比较突然,因此使用不透明度对文本等内容进行过渡
3008+
painter->setOpacity(1.0 - animation->progress());
3009+
}
3010+
29753011
//绘制选择框
29763012
bool ignoreCheckMark = false;
29773013

@@ -2990,7 +3026,7 @@ bool ChameleonStyle::drawMenuItem(const QStyleOptionMenuItem *option, QPainter *
29903026
checkRect.moveCenter(QPoint(checkRect.left() + smallIconSize / 2, menuItem->rect.center().y()));
29913027
painter->setRenderHint(QPainter::Antialiasing);
29923028

2993-
if (selected)
3029+
if (useHighlightedText)
29943030
painter->setPen(getColor(option, QPalette::HighlightedText));
29953031
else
29963032
painter->setPen(getColor(option, QPalette::BrightText));
@@ -3010,7 +3046,7 @@ bool ChameleonStyle::drawMenuItem(const QStyleOptionMenuItem *option, QPainter *
30103046

30113047
}
30123048

3013-
if (selected) {
3049+
if (useHighlightedText) {
30143050
painter->setPen(getColor(option, QPalette::HighlightedText));
30153051
} else {
30163052
if ((option->state & QStyle::State_Enabled)) {

styleplugins/chameleon/chameleonstyle.h

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
#define CHAMELEONSTYLE_H
77

88
#include <DStyle>
9+
#include <QVariantAnimation>
910

1011
DWIDGET_USE_NAMESPACE
1112

@@ -18,6 +19,33 @@ class DStyleOptionButtonBoxButton;
1819
DWIDGET_END_NAMESPACE
1920

2021
namespace chameleon {
22+
class ChameleonMovementAnimation : public QVariantAnimation
23+
{
24+
Q_OBJECT
25+
26+
public:
27+
explicit ChameleonMovementAnimation(QWidget *targetWidget);
28+
29+
inline QRect currentRect() const {
30+
return m_currentRect;
31+
}
32+
33+
inline bool isRuning() const {
34+
return state() == QVariantAnimation::Running;
35+
}
36+
37+
inline float progress() const {
38+
return float(currentLoopTime()) / duration();
39+
}
40+
41+
QWidget *targetWidget() const;
42+
void setTargetRect(const QRect &rect);
43+
44+
private:
45+
QRect m_currentRect;
46+
QRect m_targetRect;
47+
QRect m_lastTargetRect;
48+
};
2149

2250
class ChameleonStyle : public DStyle
2351
{
@@ -67,7 +95,7 @@ class ChameleonStyle : public DStyle
6795
bool drawSpinBox(const QStyleOptionSpinBox *opt, QPainter *p, const QWidget *w) const;
6896
void updateSpinBoxButtonState(const QStyleOptionSpinBox *opt, QStyleOptionButton& button, bool isActive, bool isEnabled) const;
6997
bool drawMenuBarItem(const QStyleOptionMenuItem *option, QRect &rect, QPainter *painter, const QWidget *widget) const;
70-
void drawMenuItemBackground(const QStyleOption *option, QPainter *painter, QStyleOptionMenuItem::MenuItemType type) const;
98+
ChameleonMovementAnimation *drawMenuItemBackground(const QStyleOption *option, QPainter *painter, QStyleOptionMenuItem::MenuItemType type) const;
7199
bool drawMenuItem(const QStyleOptionMenuItem *option, QPainter *painter, const QWidget *widget) const;
72100
bool drawTabBar(QPainter *painter ,const QStyleOptionTab *tab, const QWidget *widget) const;
73101
bool drawTabBarLabel(QPainter *painter ,const QStyleOptionTab *tab, const QWidget *widget) const;

0 commit comments

Comments
 (0)