Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
qohosstyle.cpp
Go to the documentation of this file.
1// Copyright (C) 2025 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
4#include "qohosstyle_p.h"
5#include <QtGui/qicon.h>
6#include <QtGui/qpainter.h>
7#include <QtGui/qpainterpath.h>
8#include <QtWidgets/qabstractscrollarea.h>
9#include <QtWidgets/qcheckbox.h>
10#include <QtWidgets/qcombobox.h>
11#include <QtWidgets/qlineedit.h>
12#include <QtWidgets/qlistview.h>
13#include <QtWidgets/qmdisubwindow.h>
14#include <QtWidgets/qpushbutton.h>
15#include <QtWidgets/qradiobutton.h>
16#include <QtWidgets/qscrollbar.h>
17#include <QtWidgets/qspinbox.h>
18#include <QtWidgets/qstyleditemdelegate.h>
19#include <QtWidgets/qstyleoption.h>
20#include <QtWidgets/qtoolbutton.h>
21#include <QtWidgets/qtreeview.h>
22#include "qpa/qplatformtheme.h"
23#include "private/qguiapplication_p.h"
24#include "private/qstylehelper_p.h"
25#include <algorithm>
26
27namespace {
28
29// Map a standard pixmap to the XDG icon-theme name that QAbstractFileIconProvider
30// uses for the same QFileIconProvider type, so the widgets path resolves through the
31// platform theme's icon engine exactly as the gui path does.
32QString ohosThemeIconName(QStyle::StandardPixmap standardPixmap)
33{
34 switch (standardPixmap) {
35 case QStyle::SP_ComputerIcon: return QStringLiteral("computer");
36 case QStyle::SP_DesktopIcon: return QStringLiteral("user-desktop");
37 case QStyle::SP_TrashIcon: return QStringLiteral("user-trash");
38 case QStyle::SP_DriveNetIcon: return QStringLiteral("network-workgroup");
39 case QStyle::SP_DriveHDIcon: return QStringLiteral("drive-harddisk");
40 case QStyle::SP_DirClosedIcon: return QStringLiteral("folder");
41 case QStyle::SP_DirIcon: return QStringLiteral("folder");
42 case QStyle::SP_FileIcon: return QStringLiteral("text-x-generic");
43 default: break;
44 }
45
46 return QString();
47}
48
49constexpr int checkBoxOrRadioButtonIndicatorSize = 24;
50constexpr int checkBoxOrRadioButtonIndicatorStrokeWidth = 1;
51constexpr int checkBoxOrRadioButtonIndicatorGap = 2;
52constexpr int checkBoxOrRadioButtonHoverSize =
53 checkBoxOrRadioButtonIndicatorSize + (2 * checkBoxOrRadioButtonIndicatorGap);
54constexpr int checkBoxOrRadioButtonFocusStrokeWidth = 2;
55constexpr int checkBoxOrRadioButtonSize =
56 checkBoxOrRadioButtonIndicatorSize + (2 * checkBoxOrRadioButtonIndicatorGap)
57 + (2 * checkBoxOrRadioButtonFocusStrokeWidth);
58constexpr int radioButtonIndicatorStrokeWidth = 6;
59
60constexpr int textCursorWidth = 1;
61
62constexpr int itemViewItemHorizontalMargin = 16;
63constexpr int itemViewItemVerticalMargin = 8;
64constexpr int itemViewItemWithDecorationVerticalMargin = 10;
65constexpr int itemViewItemSpacing = 8;
66constexpr int itemViewSeparatorHeight = 5;
67
68constexpr int focusFrameWidth = 2;
69constexpr int focusFrameCornerRadius = 16;
70
71constexpr int headerMargin = 16;
72constexpr int headerDefaultSectionSizeVertical = 48;
73
74constexpr double lineEditCornerRadius = 32.0;
75constexpr int lineEditHorizontalMargin = 16;
76constexpr int lineEditVerticalMargin = 9;
77
78constexpr int menuBarItemSpacing = 16;
79constexpr int menuBarVerticalMargin = 8;
80constexpr int menuBarHorizontalMargin = 8;
81
82constexpr int menuItemVerticalMargin = 8;
83constexpr int menuItemCornerRadius = 4;
84constexpr int menuItemHoverHorizontalMargin = 4;
85
86constexpr int pushButtonHorizontalMargin = 16;
87constexpr int pushButtonVerticalMargin = 8;
88constexpr int pushButtonCornerRadius = 8;
89constexpr int pushButtonFocusFrameGap = 2;
90constexpr int pushButtonFocusFrameWidth = 2;
91
92constexpr int progressBarMinHeight = 24;
93constexpr int progressBarGrooveHeight = 4;
94constexpr int progressBarCornerRadius = 2;
95
96constexpr int shadowXSRadius = 22;
97
98constexpr int sliderThickness = 40;
99constexpr int sliderGrooveHeight = 4;
100constexpr int sliderCornerRadius = 2;
101constexpr int sliderThumbSize = 16;
102constexpr int sliderHoverSize = 4;
103constexpr int sliderFocusStrokeWidth = 2;
104
105constexpr int smallIconSize = 12;
106
107constexpr int splitterHandleWidth = 6;
108constexpr int splitterWidth = 12;
109
110constexpr int titleBarHeight = 46;
111
112constexpr int toolButtonCornerRadius = 4;
113constexpr int toolButtonFocusFrameWidth = 2;
114
115constexpr int toolTipCornerRadius = 8;
116constexpr int toolTipFrameWidth = 8;
117constexpr int toolTipBackgroundAlpha = 204;
118
119constexpr int spinBoxFrameHeight = 32;
120constexpr int spinBoxButtonBoxWidth = 32;
121constexpr int spinBoxButtonBoxHeight = 16;
122constexpr int spinBoxEditHorizontalMargin = 4;
123constexpr double spinBoxFrameRadius = 12.0;
124constexpr int spinBoxFrameStroke = 2;
125
126constexpr int maxScrollBarSize = 9;
127constexpr int thinScrollBarSize = 3;
128constexpr int thickScrollBarSize = 6;
129
130constexpr int tabBarTabRadius = 8;
131constexpr int tabBarTabFrameWidth = 2;
132constexpr int tabBarTabUnderLineWidth = 2;
133
134constexpr int groupBoxBottomPadding = 8;
135constexpr int groupBoxFrameCornerRadius = 8;
136constexpr int groupBoxHorizontalPadding = 12;
137constexpr int groupBoxTitleToContentSpacing = 8;
138constexpr int groupBoxTopPadding = 24;
139
140constexpr int comboBoxVerticalMargin = 4;
141constexpr int comboBoxFrameRadius = 8;
142constexpr int comboBoxFrameLeftRightPadding = 16;
143constexpr int comboBoxFocusFrameWidth = 2;
144
145constexpr int tabWidgetFrameWidth = 1;
146
147constexpr double ohos_id_alpha_disabled = 0.4;
148constexpr double ohos_id_alpha_content_tertiary = 0.4;
149
150QColor makeInactiveOrDisabledFromColor(const QColor &color)
151{
152 auto disabledColor = color;
153 disabledColor.setAlphaF(qBound(0.0, color.alphaF() * ohos_id_alpha_disabled, 1.0));
154
155 return disabledColor;
156}
157
158template<typename T>
159bool qobjectIsInstanceOf(const QObject *obj)
160{
161 return qobject_cast<const T *>(obj) != nullptr;
162}
163
164template<typename T>
165bool qStyleOptionIs(const QStyleOption *option)
166{
167 return qstyleoption_cast<const T *>(option) != nullptr;
168}
169
170bool isItemViewSeparator(const QModelIndex &index)
171{
172 return index.data(Qt::AccessibleDescriptionRole).toString() == QLatin1String("separator");
173}
174
175bool isFirstItem(const QModelIndex &index)
176{
177 return index.isValid() && index.row() == 0 && index.column() == 0;
178}
179
180bool isLastItem(const QModelIndex &index)
181{
182 return index.isValid()
183 && index.row() == index.model()->rowCount(index.parent()) - 1
184 && index.column() == index.model()->columnCount(index.parent()) - 1;
185}
186
187bool isHoverable(const QWidget *widget)
188{
189 static bool (* const hoverTypeCheckFuncs[])(const QObject *obj) = {
190 &qobjectIsInstanceOf<QCheckBox>,
191 &qobjectIsInstanceOf<QPushButton>,
192 &qobjectIsInstanceOf<QRadioButton>,
193 &qobjectIsInstanceOf<QSlider>,
194 &qobjectIsInstanceOf<QToolButton>,
195 &qobjectIsInstanceOf<QComboBox>,
196 &qobjectIsInstanceOf<QScrollBar>,
197 };
198
199 return std::any_of(
200 std::begin(hoverTypeCheckFuncs), std::end(hoverTypeCheckFuncs),
201 [&](const auto &typeCheckFunc) {
202 return typeCheckFunc(widget);
203 });
204}
205
206QRect adjusted(const QRect &rect, int growth)
207{
208 return rect.adjusted(-growth, -growth, growth, growth);
209}
210
211QFont getGroupBoxTitleFont(const QWidget *widget)
212{
213 const bool widgetHasItsOwnFont = widget != nullptr && widget->testAttribute(Qt::WA_SetFont);
214 if (widgetHasItsOwnFont)
215 return widget->font();
216
217 const auto *themeFont =
218 QGuiApplicationPrivate::platformTheme()->font(QPlatformTheme::GroupBoxTitleFont);
219 return themeFont != nullptr ? *themeFont : QFont();
220}
221
222QColor getSunkenOrHoverColor(bool isSunken, const QPalette &palette)
223{
224 return isSunken
225 ? palette.color(QPalette::Active, QPalette::Dark)
226 : palette.color(QPalette::Active, QPalette::Light);
227}
228
229void paintOnStackTop(QPainter &painter, const std::function<void(QPainter &painter)> &paint)
230{
231 painter.save();
232 paint(painter);
233 painter.restore();
234}
235
236void drawLine(QPainter &painter, const QPen &pen, const QPoint &aPoint, const QPoint &bPoint)
237{
238 paintOnStackTop(painter, [&](QPainter &painter) {
239 painter.setRenderHints(QPainter::Antialiasing);
240 painter.setPen(pen);
241 painter.drawLine(aPoint, bPoint);
242 });
243}
244
245void drawEllipse(QPainter &painter, const QPen &pen, const QBrush &brush, const QRect &rect)
246{
247 painter.save();
248 painter.setRenderHints(QPainter::Antialiasing);
249 painter.setPen(pen);
250 painter.setBrush(brush);
251 painter.drawEllipse(rect);
252 painter.restore();
253}
254
255void drawRect(QPainter &painter, const QPen &pen, const QBrush &brush, const QRect &rect)
256{
257 paintOnStackTop(painter, [&](QPainter &painter) {
258 painter.setRenderHints(QPainter::Antialiasing);
259 painter.setPen(pen);
260 painter.setBrush(brush);
261 painter.drawRect(rect);
262 });
263}
264
265void drawRoundedRect(
266 QPainter &painter, const QPen &pen, const QBrush &brush, const QRectF &rect, qreal xRadius, qreal yRadius)
267{
268 paintOnStackTop(painter, [&](QPainter &painter) {
269 painter.setRenderHints(QPainter::Antialiasing);
270 painter.setPen(pen);
271 painter.setBrush(brush);
272 painter.drawRoundedRect(rect, xRadius, yRadius);
273 });
274}
275
276QPainterPath roundedPathInRect(
277 const QRectF &rect, qreal topLeftCornerRadius, qreal topRightCornerRadius, qreal bottomLeftCornerRadius,
278 qreal bottomRightCornerRadius)
279{
280 QPainterPath path;
281
282 const auto bottom = rect.y() + rect.height();
283 const auto right = rect.x() + rect.width();
284
285 const auto topLeftDiameter = 2 * topLeftCornerRadius;
286 path.moveTo(rect.x() + topLeftCornerRadius, rect.y());
287 path.arcTo(rect.x(), rect.y(), topLeftDiameter, topLeftDiameter, 90.0, 90.0);
288
289 const auto bottomLeftDiameter = 2 * bottomLeftCornerRadius;
290 path.lineTo(rect.x(), bottom - bottomLeftCornerRadius);
291 path.arcTo(rect.x(), bottom - bottomLeftDiameter, bottomLeftDiameter, bottomLeftDiameter, 180.0, 90.0);
292
293 const auto bottomRightDiameter = 2 * bottomRightCornerRadius;
294 path.lineTo(right - bottomRightCornerRadius, bottom);
295 path.arcTo(
296 right - bottomRightDiameter, bottom - bottomRightDiameter, bottomRightDiameter, bottomRightDiameter, 270.0,
297 90.0);
298
299 const auto topRightDiameter = 2 * topRightCornerRadius;
300 path.lineTo(right, rect.y() + topRightCornerRadius);
301 path.arcTo(right - topRightDiameter, rect.y(), topRightDiameter, topRightDiameter, 360.0, 90.0);
302
303 path.closeSubpath();
304
305 return path;
306}
307
308void drawPath(QPainter &painter, const QPen &pen, const QBrush &brush, const QPainterPath& path)
309{
310 paintOnStackTop(painter, [&](QPainter &painter) {
311 painter.setRenderHints(QPainter::Antialiasing);
312 painter.setPen(pen);
313 painter.setBrush(brush);
314 painter.drawPath(path);
315 });
316}
317
318void drawRoundedRect(
319 QPainter &painter, const QPen &pen, const QBrush brush, const QRectF &rect, qreal topLeftCornerRadius,
320 qreal topRightCornerRadius, qreal bottomLeftCornerRadius, qreal bottomRightCornerRadius)
321{
322 drawPath(
323 painter, pen, brush, roundedPathInRect(rect, topLeftCornerRadius, topRightCornerRadius, bottomLeftCornerRadius,
324 bottomRightCornerRadius));
325}
326
327void drawPolyline(
328 QPainter &painter, const QPen &pen, const QBrush &brush, const std::vector<QPointF> &polygonPoints)
329{
330 paintOnStackTop(painter, [&](auto &p) {
331 p.setRenderHint(QPainter::Antialiasing);
332 p.setPen(pen);
333 p.setBrush(brush);
334 p.drawPolyline(polygonPoints.data(), polygonPoints.size());
335 });
336}
337
338enum class ArrowDirection { Up, Down, Left, Right };
339
340void drawArrow(
341 QPainter &painter, const QRectF &boundingRect, qreal arrowSize, ArrowDirection direction,
342 const QColor &color)
343{
344 const auto arrowWidth = 2;
345 const auto arrowCenter = boundingRect.center();
346 auto arrowRect = QRectF(0, 0, arrowSize, arrowSize * 0.5);
347 arrowRect.moveCenter(arrowCenter);
348 arrowRect.adjust(arrowWidth * 0.5, arrowWidth * 0.5, -arrowWidth * 0.5, -arrowWidth * 0.5);
349
350 const std::vector<QPointF> polygonPoints = {
351 QPointF(arrowRect.x(), arrowRect.y()),
352 QPointF(arrowRect.x() + arrowRect.width() * 0.5, arrowRect.y() + arrowRect.height()),
353 QPointF(arrowRect.x() + arrowRect.width(), arrowRect.y())
354 };
355
356 paintOnStackTop(painter, [&](auto &p) {
357 p.translate(arrowCenter);
358 switch (direction) {
359 case ArrowDirection::Down:
360 break;
361 case ArrowDirection::Up:
362 p.rotate(180);
363 break;
364 case ArrowDirection::Left:
365 p.rotate(90);
366 break;
367 case ArrowDirection::Right:
368 p.rotate(-90);
369 break;
370 }
371 p.translate(-arrowCenter);
372
373 drawPolyline(
374 p, QPen(color, arrowWidth, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin), Qt::NoBrush,
375 polygonPoints);
376 });
377}
378
379void drawCheckBoxOrRadioButtonIndicator(QPainter &painter, const QStyleOption &option, bool isCheckBox)
380{
381 const auto isEnabled = option.state.testFlag(QStyle::State_Enabled);
382 const auto isOn = option.state.testFlag(QStyle::State_On);
383 const auto isMouseOver = option.state.testFlag(QStyle::State_MouseOver);
384 const auto isSunken = option.state.testFlag(QStyle::State_Sunken);
385
386 painter.save();
387 painter.setRenderHints(QPainter::Antialiasing);
388
389 painter.setOpacity(isEnabled ? 1.0 : ohos_id_alpha_disabled);
390
391 QRect hoverRect(0, 0, checkBoxOrRadioButtonHoverSize, checkBoxOrRadioButtonHoverSize);
392 hoverRect.moveCenter(option.rect.center());
393 if (isMouseOver || isSunken)
394 drawEllipse(painter, Qt::NoPen, getSunkenOrHoverColor(isSunken, option.palette), hoverRect);
395
396 QRect indicatorRect(0, 0, checkBoxOrRadioButtonIndicatorSize, checkBoxOrRadioButtonIndicatorSize);
397 indicatorRect.moveCenter(option.rect.center());
398
399 auto activeColor = option.palette.color(QPalette::Active, QPalette::Highlight);
400 if (isOn) {
401 if (isCheckBox) {
402 drawEllipse(painter, Qt::NoPen, activeColor, indicatorRect);
403
404 QPixmap svgPixmap(indicatorRect.size());
405 if (svgPixmap.load(QString::fromStdString(":/resources/ic_gallery_material_select_checkbo.svg"))) {
406 painter.drawPixmap(indicatorRect.topLeft(), svgPixmap);
407 }
408 } else {
409 drawEllipse(
410 painter, QPen(activeColor, radioButtonIndicatorStrokeWidth), Qt::NoBrush,
411 adjusted(indicatorRect, -radioButtonIndicatorStrokeWidth / 2));
412 }
413 } else {
414 const auto outlineColor = option.palette.color(QPalette::Inactive, QPalette::Button);
415 const auto backgroundBrush = option.palette.brush(QPalette::Inactive, QPalette::Base);
416 const auto discRect = adjusted(indicatorRect, -checkBoxOrRadioButtonIndicatorStrokeWidth);
417
418 drawEllipse(
419 painter, QPen(outlineColor, checkBoxOrRadioButtonIndicatorStrokeWidth), backgroundBrush,
420 discRect);
421
422 if (const auto *themePalette = QGuiApplicationPrivate::platformTheme()->palette(
423 isCheckBox
424 ? QPlatformTheme::Palette::CheckBoxPalette
425 : QPlatformTheme::Palette::RadioButtonPalette)) {
426 const auto overlayOutlineColor = themePalette->color(QPalette::Inactive, QPalette::Button);
427 const auto overlayBackgroundBrush = themePalette->brush(QPalette::Inactive, QPalette::Base);
428
429 const bool shouldPresentOverlayForOverriddenOutlineColor =
430 outlineColor != overlayOutlineColor;
431 const bool shouldPresentOverlayForOverriddenBackgroundBrush =
432 backgroundBrush != overlayBackgroundBrush;
433
434 if (shouldPresentOverlayForOverriddenOutlineColor
435 || shouldPresentOverlayForOverriddenBackgroundBrush) {
436 drawEllipse(
437 painter,
438 shouldPresentOverlayForOverriddenOutlineColor
439 ? QPen(overlayOutlineColor, checkBoxOrRadioButtonIndicatorStrokeWidth)
440 : QPen(Qt::NoPen),
441 shouldPresentOverlayForOverriddenBackgroundBrush
442 ? overlayBackgroundBrush
443 : QBrush(Qt::NoBrush),
444 discRect);
445 }
446 }
447 }
448
449 painter.restore();
450}
451
452void drawLineEditBackground(QPainter &painter, const QStyleOption &option)
453{
454 auto radius = std::min(
455 std::min(option.rect.size().width(), option.rect.size().height()) * 0.5, lineEditCornerRadius);
456
457 const auto colorGroup = option.palette.currentColorGroup();
458 const auto baseBrush = option.palette.brush(colorGroup, QPalette::Base);
459
460 drawRoundedRect(painter, Qt::NoPen, baseBrush, option.rect, radius, radius);
461
462 if (const auto *ohosThemePalette = QGuiApplicationPrivate::platformTheme()->palette(
463 QPlatformTheme::Palette::TextLineEditPalette)) {
464 const auto overlayBaseBrush = ohosThemePalette->brush(colorGroup, QPalette::Base);
465 const bool shouldPresentOverlayForOverriddenBaseBrush = baseBrush != overlayBaseBrush;
466 if (shouldPresentOverlayForOverriddenBaseBrush)
467 drawRoundedRect(painter, Qt::NoPen, overlayBaseBrush, option.rect, radius, radius);
468 }
469}
470
471QColor getPushButtonOverlayFill(bool isPressed, const QStyleOptionButton &option)
472{
473 const auto role = isPressed ? QPalette::Dark : QPalette::Light;
474 if (const auto *themePalette =
475 QGuiApplicationPrivate::platformTheme()->palette(QPlatformTheme::Palette::ButtonPalette))
476 return themePalette->color(QPalette::Active, role);
477 return option.palette.color(QPalette::Active, role);
478}
479
480QBrush getPushButtonBackgroundBrush(const QStyleOptionButton &option)
481{
482 const auto isDefaultButton = option.features.testFlag(QStyleOptionButton::DefaultButton);
483 const auto isAutoDefaultButton = option.features.testFlag(QStyleOptionButton::AutoDefaultButton);
484 const auto isEnabled = option.state.testFlag(QStyle::State_Enabled);
485 const auto isOn = option.state.testFlag(QStyle::State_On);
486
487 const auto defaultButtonBackgroundColor = isEnabled
488 ? option.palette.color(QPalette::Active, QPalette::AlternateBase)
489 : makeInactiveOrDisabledFromColor(option.palette.color(QPalette::Active, QPalette::AlternateBase));
490
491 if (isOn)
492 return isDefaultButton || isAutoDefaultButton
493 ? defaultButtonBackgroundColor
494 : getPushButtonOverlayFill(true, option);
495
496 if (isDefaultButton)
497 return defaultButtonBackgroundColor;
498
499 return option.palette.brush(
500 isEnabled ? QPalette::Active : QPalette::Inactive, QPalette::Button);
501}
502
503std::optional<QBrush> getPushButtonFillOverlayBrush(const QStyleOptionButton &option)
504{
505 const auto isDefaultButton = option.features.testFlag(QStyleOptionButton::DefaultButton);
506 const auto isOn = option.state.testFlag(QStyle::State_On);
507 if (isDefaultButton || isOn)
508 return std::nullopt;
509
510 const auto colorGroup = option.state.testFlag(QStyle::State_Enabled)
511 ? QPalette::Active
512 : QPalette::Inactive;
513 if (option.palette.isBrushSet(colorGroup, QPalette::Button))
514 return std::nullopt;
515
516 if (const auto *themePalette =
517 QGuiApplicationPrivate::platformTheme()->palette(QPlatformTheme::Palette::ButtonPalette)) {
518 const auto themeBrush = themePalette->brush(colorGroup, QPalette::Button);
519 if (option.palette.brush(colorGroup, QPalette::Button) != themeBrush)
520 return themeBrush;
521 }
522
523 return std::nullopt;
524}
525
526QColor getPushButtonTextColor(const QStyleOptionButton &option)
527{
528 const auto isEnabled = option.state.testFlag(QStyle::State_Enabled);
529 const auto isDefaultButton = option.features.testFlag(QStyleOptionButton::DefaultButton);
530 const auto isOn = option.state.testFlag(QStyle::State_On);
531
532 return isDefaultButton || isOn
533 ? option.palette.color(QPalette::Active, QPalette::BrightText)
534 : option.palette.color(
535 isEnabled
536 ? QPalette::Active
537 : QPalette::Disabled,
538 QPalette::ButtonText);
539}
540
541void drawPushButtonBackground(QPainter &painter, const QStyleOptionButton &option)
542{
543 paintOnStackTop(painter, [&](QPainter &painter) {
544 const auto isMouseOver = option.state.testFlag(QStyle::State_MouseOver);
545 const auto isSunken = option.state.testFlag(QStyle::State_Sunken);
546
547 painter.setRenderHints(QPainter::Antialiasing);
548 painter.setPen(Qt::NoPen);
549
550 auto adjustment = pushButtonFocusFrameGap + pushButtonFocusFrameWidth;
551 auto rect = option.rect.adjusted(adjustment, adjustment, -adjustment, -adjustment);
552
553 painter.setBrush(getPushButtonBackgroundBrush(option));
554 painter.drawRoundedRect(rect, pushButtonCornerRadius, pushButtonCornerRadius);
555
556 const auto fillOverlayBrush = getPushButtonFillOverlayBrush(option);
557 if (fillOverlayBrush) {
558 painter.setBrush(*fillOverlayBrush);
559 painter.drawRoundedRect(rect, pushButtonCornerRadius, pushButtonCornerRadius);
560 }
561
562 if (isMouseOver || isSunken) {
563 painter.setBrush(getPushButtonOverlayFill(isSunken, option));
564 painter.drawRoundedRect(rect, pushButtonCornerRadius, pushButtonCornerRadius);
565 }
566 });
567}
568
569void drawPushButtonFocus(QPainter &painter, const QStyleOption &option)
570{
571 paintOnStackTop(painter, [&](QPainter &painter) {
572 painter.setRenderHints(QPainter::Antialiasing);
573 painter.setBrush(Qt::NoBrush);
574 painter.setPen(QPen(option.palette.color(QPalette::Active, QPalette::Highlight), pushButtonFocusFrameWidth));
575 auto cornerRadius = pushButtonCornerRadius + pushButtonFocusFrameGap;
576 painter.drawRoundedRect(option.rect, cornerRadius, cornerRadius);
577 });
578}
579
580QRect getProgressBarGrooveRect(const QStyleOptionProgressBar &option)
581{
582 auto rect = option.rect;
583 const bool horizontal = option.state & QStyle::State_Horizontal;
584 if (horizontal) {
585 rect.setHeight(progressBarGrooveHeight);
586 rect.moveTop(option.rect.center().y());
587 } else {
588 rect.setWidth(progressBarGrooveHeight);
589 rect.moveRight(option.rect.center().x());
590 }
591
592 return rect;
593}
594
595void drawProgressBarContent(QPainter &painter, const QStyleOptionProgressBar &option)
596{
597 auto rect = getProgressBarGrooveRect(option);
598 const bool horizontal = option.state & QStyle::State_Horizontal;
599
600 const bool isIndeterminate = option.maximum == 0 && option.minimum == 0;
601 if (isIndeterminate) {
602 // TODO: proper busy indicator pending UI spec. Fill groove as a placeholder.
603 drawRoundedRect(painter, Qt::NoPen, option.palette.brush(QPalette::Highlight),
604 rect, progressBarCornerRadius, progressBarCornerRadius);
605 return;
606 }
607
608 const qint64 totalSteps = std::max(qint64(1), qint64(option.maximum) - option.minimum);
609 const double fraction = static_cast<double>(qint64(option.progress) - option.minimum)
610 / static_cast<double>(totalSteps);
611
612 if (horizontal) {
613 rect.setWidth(fraction * rect.width());
614 rect.moveLeft(option.invertedAppearance ? option.rect.width() - rect.width() : 0);
615 } else {
616 rect.setHeight(fraction * rect.height());
617 rect.moveTop(option.invertedAppearance ? 0 : option.rect.height() - rect.height());
618 }
619
620 drawRoundedRect(
621 painter, Qt::NoPen, option.palette.brush(QPalette::Highlight), rect, progressBarCornerRadius,
622 progressBarCornerRadius);
623}
624
625void drawSliderGroove(QPainter &painter, const QStyleOptionSlider &option)
626{
627 drawRoundedRect(
628 painter, Qt::NoPen, option.palette.color(QPalette::Active, QPalette::Mid),
629 option.rect, sliderCornerRadius, sliderCornerRadius);
630
631 QRect fillRect;
632 if (option.orientation == Qt::Horizontal) {
633 const auto sliderPosition = QStyle::sliderPositionFromValue(
634 option.minimum, option.maximum, option.sliderPosition, option.rect.width(), option.upsideDown);
635 fillRect = QRect(option.rect.topLeft(), QSize(sliderPosition, option.rect.height()));
636 } else {
637 const auto sliderPosition = QStyle::sliderPositionFromValue(
638 option.minimum, option.maximum, option.sliderPosition, option.rect.height(), option.upsideDown);
639 fillRect = QRect(
640 option.rect.x(), option.rect.y() + sliderPosition, option.rect.width(), option.rect.height() - sliderPosition);
641 }
642 drawRoundedRect(
643 painter, Qt::NoPen, option.palette.brush(QPalette::Highlight), fillRect, sliderCornerRadius,
644 sliderCornerRadius);
645}
646
647void drawSliderThumb(QPainter &painter, const QStyleOptionSlider &option)
648{
649 QRect shadowRect(0, 0, shadowXSRadius, shadowXSRadius);
650 shadowRect.moveCenter(option.rect.center());
651
652 QRadialGradient radialGrad(shadowRect.center(), shadowXSRadius * 1.0);
653 radialGrad.setColorAt(0.0, Qt::transparent);
654 radialGrad.setColorAt(1.0, option.palette.color(QPalette::Active, QPalette::Shadow));
655
656 drawEllipse(painter, Qt::NoPen, QBrush(radialGrad), shadowRect);
657
658 if (option.state.testFlag(QStyle::State_MouseOver))
659 drawEllipse(painter, Qt::NoPen, option.palette.color(QPalette::Active, QPalette::Light), option.rect);
660
661 auto adjustedRect = option.rect.adjusted(sliderHoverSize, sliderHoverSize, -sliderHoverSize, -sliderHoverSize);
662 drawEllipse(painter, Qt::NoPen, option.palette.color(QPalette::Active, QPalette::AlternateBase), adjustedRect);
663
664 if (option.state.testFlag(QStyle::State_Sunken))
665 drawEllipse(painter, Qt::NoPen, option.palette.color(QPalette::Active, QPalette::Dark), adjustedRect);
666
667 if (option.state.testFlag(QStyle::State_HasFocus)) {
668 drawEllipse(
669 painter, QPen(option.palette.color(QPalette::Active, QPalette::Highlight), sliderFocusStrokeWidth),
670 Qt::NoBrush, adjusted(option.rect, -1));
671 }
672}
673
674void drawToolButton(QPainter &painter, const QStyleOption &option)
675{
676 const auto isEnabled = option.state.testFlag(QStyle::State_Enabled);
677 const auto isMouseOver = option.state.testFlag(QStyle::State_MouseOver);
678 const auto isSunken = option.state.testFlag(QStyle::State_Sunken);
679
680 drawRoundedRect(
681 painter, Qt::NoPen, option.palette.brush(isEnabled ? QPalette::Active : QPalette::Disabled, QPalette::Button),
682 option.rect, toolButtonCornerRadius, toolButtonCornerRadius);
683
684 if (isMouseOver || isSunken) {
685 drawRoundedRect(
686 painter, Qt::NoPen, getSunkenOrHoverColor(isSunken, option.palette), option.rect, toolButtonCornerRadius,
687 toolButtonCornerRadius);
688 }
689}
690
691void drawToolBarbackground(QPainter &painter, const QStyleOption &option)
692{
693 paintOnStackTop(painter, [&](QPainter &painter) {
694 painter.setRenderHints(QPainter::Antialiasing);
695 painter.fillRect(option.rect, option.palette.brush(QPalette::Active, QPalette::Window));
696 });
697}
698
699void drawMenuBarBarbackground(QPainter &painter, const QStyleOption &option)
700{
701 paintOnStackTop(painter, [&](QPainter &painter) {
702 painter.setRenderHints(QPainter::Antialiasing);
703 painter.fillRect(option.rect, option.palette.brush(QPalette::Active, QPalette::Window));
704 });
705}
706
707void drawListItemSeparator(QPainter &painter, const QStyleOption &option)
708{
709 QPoint center = option.rect.center();
710 drawLine(
711 painter, option.palette.color(QPalette::Active, QPalette::Mid),
712 QPoint(option.rect.left(), center.y()), QPoint(option.rect.right(), center.y()));
713}
714
715void drawMenuItem(QPainter &painter, const QStyleOptionMenuItem &option, int checkMarkSize, int iconSize)
716{
717 const auto contentRect = option.rect.adjusted(itemViewItemHorizontalMargin, 0, -itemViewItemHorizontalMargin, 0);
718 if (option.menuItemType == QStyleOptionMenuItem::Separator) {
719 auto copyOption = option;
720 copyOption.rect = contentRect;
721 drawListItemSeparator(painter, copyOption);
722 } else {
723 const bool isSelected = option.state.testFlag(QStyle::State_Selected);
724 const bool isSunken = option.state.testFlag(QStyle::State_Sunken);
725
726 if (isSelected || isSunken) {
727 drawRoundedRect(
728 painter, Qt::NoPen, getSunkenOrHoverColor(isSunken, option.palette),
729 option.rect.adjusted(menuItemHoverHorizontalMargin, 0, -menuItemHoverHorizontalMargin, 0),
730 menuItemCornerRadius, menuItemCornerRadius);
731 }
732
733 const bool isCheckable = option.checkType != QStyleOptionMenuItem::NotCheckable;
734 QRect checkMarkRect;
735 if (isCheckable) {
736 checkMarkRect = contentRect;
737 checkMarkRect.setWidth(checkMarkSize);
738
739 auto copyOption = option;
740 copyOption.rect = checkMarkRect;
741 if (option.checked)
742 copyOption.state |= QStyle::State_On;
743
744 drawCheckBoxOrRadioButtonIndicator(painter, copyOption, true);
745 }
746
747 const bool hasIcon = !option.icon.isNull();
748 QRect iconRect;
749 if (hasIcon) {
750 iconRect = QRect(contentRect.x(), contentRect.center().y() - iconSize * 0.5, iconSize, iconSize);
751 iconRect.moveLeft(checkMarkRect.right() + itemViewItemHorizontalMargin);
752
753 option.icon.paint(
754 &painter, iconRect, Qt::AlignCenter,
755 option.state.testFlag(QStyle::State_Enabled) ? QIcon::Normal : QIcon::Disabled,
756 option.checked ? QIcon::On : QIcon::Off);
757 }
758
759 QRect textRect = contentRect;
760 if (isCheckable)
761 textRect.setLeft(checkMarkRect.right() + itemViewItemHorizontalMargin);
762 if (hasIcon)
763 textRect.setLeft(iconRect.right() + itemViewItemHorizontalMargin);
764 paintOnStackTop(painter, [&](QPainter &painter) {
765 painter.setPen(option.palette.color(QPalette::Text));
766 painter.drawText(
767 textRect, (Qt::AlignLeft | Qt::AlignVCenter | Qt::TextShowMnemonic), option.text);
768 });
769 }
770}
771
772void drawMenuTearOff(QPainter &painter, const QStyleOption &option)
773{
774 const auto pointY = option.rect.y() + option.rect.height() / 2;
775 drawLine(
776 painter, QPen(option.palette.color(QPalette::Text), 1, Qt::DashLine), QPoint(option.rect.x(), pointY),
777 QPoint(option.rect.x() + option.rect.width(), pointY)
778 );
779}
780
781void drawSplitter(QPainter &painter, const QStyleOption &option)
782{
783 constexpr int splitterAvailableSizeDivider = 12;
784 const bool isHorizontal = option.state.testFlag(QStyle::State_Horizontal);
785
786 if (option.rect.width() > 1 && option.rect.height() > 1) {
787 const auto handleSize = isHorizontal
788 ? QSize(splitterHandleWidth, option.rect.height() / splitterAvailableSizeDivider)
789 : QSize(option.rect.width() / splitterAvailableSizeDivider, splitterHandleWidth);
790 const auto handleRect = QRect(
791 QPoint(
792 (option.rect.width() - handleSize.width()) * 0.5,
793 (option.rect.height() - handleSize.height()) * 0.5),
794 handleSize);
795 const auto cornerRadius = std::min(handleSize.width(), handleSize.height()) * 0.5;
796 drawRoundedRect(
797 painter, Qt::NoPen, option.palette.color(QPalette::Active, QPalette::Mid),
798 handleRect, cornerRadius, cornerRadius);
799 } else {
800 auto endPoint = isHorizontal ? option.rect.bottomLeft() : option.rect.topRight();
801 drawLine(painter, option.palette.dark().color(), option.rect.topLeft(), endPoint);
802 }
803}
804
805void drawSpinBoxFrame(
806 QPainter &painter, const QStyleOptionSpinBox &option, const QRect &frameRect, int frameWidth)
807{
808 auto isEnabled = option.state.testFlag(QStyle::State_Enabled);
809
810 QPen pen =
811 option.frame && option.subControls.testFlag(QStyle::SC_SpinBoxFrame)
812 ? QPen(option.palette.color(QPalette::Active, QPalette::Mid), frameWidth)
813 : Qt::NoPen;
814
815 const qreal strokeInset = frameWidth / 2.0;
816 const QRectF strokeRect = QRectF(frameRect)
817 .adjusted(strokeInset, strokeInset, -strokeInset, -strokeInset);
818
819 paintOnStackTop(painter, [&](auto &p) {
820 p.setOpacity(isEnabled ? 1.0 : ohos_id_alpha_disabled);
821 drawRoundedRect(
822 p, pen, option.palette.window(), strokeRect, spinBoxFrameRadius, spinBoxFrameRadius);
823 });
824}
825
826void drawSpinBoxButton(QPainter &painter, const QStyleOptionSpinBox &option, int penWidth)
827{
828 const bool isDownButton = option.subControls == QStyle::SC_SpinBoxDown;
829 const bool mirrored = option.direction == Qt::RightToLeft;
830
831 const qreal strokeInset = penWidth / 2.0;
832 const qreal outerLeftInset = mirrored ? strokeInset : 0.0;
833 const qreal outerRightInset = mirrored ? 0.0 : -strokeInset;
834 const QRectF rect = isDownButton
835 ? QRectF(option.rect).adjusted(outerLeftInset, 0.0, outerRightInset, -strokeInset)
836 : QRectF(option.rect).adjusted(outerLeftInset, strokeInset, outerRightInset, 0.0);
837
838 auto isEnabled = option.state.testFlag(QStyle::State_Enabled);
839 auto isPressed = option.state.testFlag(QStyle::State_Sunken);
840
841 QPen pen(option.palette.color(QPalette::Active, QPalette::Mid), penWidth);
842 QBrush brush(option.palette.window());
843
844 if (isPressed)
845 brush = QBrush(option.palette.highlight());
846
847 const qreal topLeftRadius = (mirrored && !isDownButton) ? spinBoxFrameRadius : 0.0;
848 const qreal topRightRadius = (!mirrored && !isDownButton) ? spinBoxFrameRadius : 0.0;
849 const qreal bottomLeftRadius = (mirrored && isDownButton) ? spinBoxFrameRadius : 0.0;
850 const qreal bottomRightRadius = (!mirrored && isDownButton) ? spinBoxFrameRadius : 0.0;
851
852 paintOnStackTop(painter, [&](auto &p) {
853 p.setOpacity(isEnabled ? 1.0 : ohos_id_alpha_disabled);
854 drawRoundedRect(
855 p, pen, brush, rect, topLeftRadius, topRightRadius, bottomLeftRadius, bottomRightRadius);
856 });
857}
858
859void drawScrollBarSlider(QPainter &painter, const QStyleOptionSlider &option)
860{
861 int scrollBarRadius =
862 option.orientation == Qt::Vertical
863 ? option.rect.width() * 0.5
864 : option.rect.height() * 0.5;
865
866 paintOnStackTop(painter, [&](QPainter &painter) {
867 painter.setOpacity(ohos_id_alpha_content_tertiary);
868 drawRoundedRect(
869 painter, Qt::NoPen, option.palette.color(QPalette::Active, QPalette::Midlight),
870 option.rect, scrollBarRadius, scrollBarRadius);
871 });
872}
873
874Qt::Orientation tabBarShapeToOrientation(QTabBar::Shape shape)
875{
876 switch (shape) {
877 case QTabBar::RoundedNorth:
878 case QTabBar::RoundedSouth:
879 case QTabBar::TriangularNorth:
880 case QTabBar::TriangularSouth:
881 return Qt::Horizontal;
882 case QTabBar::RoundedWest:
883 case QTabBar::TriangularWest:
884 case QTabBar::RoundedEast:
885 case QTabBar::TriangularEast:
886 return Qt::Vertical;
887 }
888}
889
890void drawTabBarTabShape(QPainter &painter, const QStyleOptionTab &option)
891{
892 auto isSelected = option.state.testFlag(QStyle::State_Selected);
893 auto isFocused = option.state.testFlag(QStyle::State_HasFocus);
894 QRect rect(option.rect);
895 adjusted(rect, -tabBarTabFrameWidth - 1);
896
897 QPoint underLineStart, underLineEnd;
898 if (tabBarShapeToOrientation(option.shape) == Qt::Horizontal) {
899 int lineY = rect.y() + rect.height() - tabBarTabUnderLineWidth;
900 underLineStart = QPoint(rect.x() + tabBarTabRadius, lineY);
901 underLineEnd = QPoint(rect.x() + rect.width() - tabBarTabRadius, lineY);
902 } else {
903 int lineX = rect.x();
904
905 if (option.shape == QTabBar::RoundedWest || option.shape == QTabBar::TriangularWest)
906 lineX += rect.width() - tabBarTabUnderLineWidth;
907 else
908 lineX += tabBarTabUnderLineWidth;
909
910 underLineStart = QPoint(lineX, rect.y() + tabBarTabRadius);
911 underLineEnd = QPoint(lineX, rect.y() + rect.height() - tabBarTabRadius);
912 }
913
914 drawRoundedRect(painter, Qt::NoPen, option.palette.window(), rect, tabBarTabRadius, tabBarTabRadius);
915 if (!isFocused && isSelected)
916 drawLine(painter, QPen(option.palette.highlight(), tabBarTabUnderLineWidth), underLineStart, underLineEnd);
917}
918
919void drawComboBoxFrame(QPainter &painter, const QStyleOptionComboBox &option)
920{
921 const auto isMouseOver = option.state.testFlag(QStyle::State_MouseOver);
922 const auto isOpened = option.state.testFlag(QStyle::State_On);
923 const auto isFocused = option.state.testFlag(QStyle::State_HasFocus);
924
925 auto focusedPen = QPen(
926 option.palette.color(QPalette::Active, QPalette::AlternateBase),
927 comboBoxFocusFrameWidth);
928
929 const auto buttonBrush = option.palette.brush(QPalette::Button);
930 drawRoundedRect(
931 painter, isFocused ? focusedPen : Qt::NoPen, buttonBrush, option.rect,
932 comboBoxFrameRadius, comboBoxFrameRadius);
933
934 const auto *ohosThemePalette =
935 QGuiApplicationPrivate::platformTheme()->palette(QPlatformTheme::Palette::ComboBoxPalette);
936 const auto overlayButtonBrush = ohosThemePalette->brush(QPalette::Button);
937
938 bool shouldPresentOverlayForOverriddenButtonBrush = buttonBrush != overlayButtonBrush;
939 if (shouldPresentOverlayForOverriddenButtonBrush)
940 drawRoundedRect(
941 painter, Qt::NoPen, overlayButtonBrush, option.rect, comboBoxFrameRadius, comboBoxFrameRadius);
942
943 if (isMouseOver || isOpened) {
944 auto pen = isOpened ? focusedPen : Qt::NoPen;
945 auto brush = getSunkenOrHoverColor(isOpened, option.palette);
946 drawRoundedRect(painter, pen, brush, option.rect, comboBoxFrameRadius, comboBoxFrameRadius);
947 }
948}
949
950void drawComboBoxListViewItem(QPainter &painter, const QStyleOptionViewItem &option, const QBrush &brush)
951{
952 if (isFirstItem(option.index)) {
953 drawRoundedRect(
954 painter, Qt::NoPen, brush, option.rect, focusFrameCornerRadius, focusFrameCornerRadius, 0, 0);
955 } else if (isLastItem(option.index)) {
956 drawRoundedRect(
957 painter, Qt::NoPen, brush, option.rect, 0, 0, focusFrameCornerRadius, focusFrameCornerRadius);
958 } else {
959 drawRect(painter, Qt::NoPen, brush, option.rect);
960 }
961}
962
963void drawTreeViewHighlightItem(QPainter &painter, const QStyleOptionViewItem &option, const QBrush &brush)
964{
965 switch (option.viewItemPosition) {
966 case QStyleOptionViewItem::OnlyOne:
967 drawRoundedRect(
968 painter, Qt::NoPen, brush, option.rect, focusFrameCornerRadius, focusFrameCornerRadius);
969 break;
970 case QStyleOptionViewItem::Beginning:
971 drawRoundedRect(
972 painter, Qt::NoPen, brush, option.rect, focusFrameCornerRadius, 0, focusFrameCornerRadius, 0);
973 break;
974 case QStyleOptionViewItem::Invalid:
975 case QStyleOptionViewItem::Middle:
976 drawRect(painter, Qt::NoPen, brush, option.rect);
977 break;
978 case QStyleOptionViewItem::End:
979 drawRoundedRect(
980 painter, Qt::NoPen, brush, option.rect, 0, focusFrameCornerRadius, 0, focusFrameCornerRadius);
981 break;
982 }
983}
984
985void drawPanelItemViewItem(QPainter &painter, const QStyleOptionViewItem &option, bool isComboBoxListViewItem)
986{
987 if (isItemViewSeparator(option.index)) {
988 auto copyOption = option;
989 copyOption.rect = option.rect.adjusted(itemViewItemHorizontalMargin, 0, -itemViewItemHorizontalMargin, 0);
990 drawListItemSeparator(painter, copyOption);
991 } else {
992 auto isSelected = option.state.testFlag(QStyle::State_Selected);
993 auto isMouseOver = option.state.testFlag(QStyle::State_MouseOver);
994
995 auto colorGroup = option.state.testFlag(QStyle::State_Enabled) ? QPalette::Normal : QPalette::Disabled;
996 if (colorGroup == QPalette::Normal && !option.state.testFlag(QStyle::State_Active))
997 colorGroup = QPalette::Inactive;
998
999 const QBrush brush =
1000 isSelected
1001 ? option.palette.brush(colorGroup, QPalette::Highlight)
1002 : isMouseOver
1003 ? option.palette.color(QPalette::Active, QPalette::Light)
1004 : option.backgroundBrush.style() == Qt::NoBrush
1005 ? Qt::NoBrush
1006 : option.backgroundBrush;
1007
1008 if (isComboBoxListViewItem)
1009 drawComboBoxListViewItem(painter, option, brush);
1010 else
1011 drawTreeViewHighlightItem(painter, option, brush);
1012 }
1013}
1014
1015void drawHeaderSection(QPainter &painter, const QStyleOptionHeader &option)
1016{
1017 QRect rect =
1018 option.position == QStyleOptionHeader::OnlyOneSection
1019 ? option.rect
1020 : option.orientation == Qt::Horizontal
1021 ? option.rect.adjusted(-1, 0, 0, 0)
1022 : option.rect.adjusted(0, -1, 0, 0);
1023
1024 drawRect(painter, QPen(Qt::black), option.palette.brush(QPalette::Button), rect);
1025}
1026
1027void drawWindowBackgroundAndFrame(
1028 QPainter &painter, const QStyleOptionFrame &option, QFlags<Qt::WindowState> state, int titleBarHeight)
1029{
1030 const auto offset = option.lineWidth * 0.5;
1031 const auto windowFrameColor =
1032 state.testFlag(Qt::WindowActive)
1033 ? option.palette.color(QPalette::Active, QPalette::Base)
1034 : option.palette.color(QPalette::Inactive, QPalette::Base);
1035 if (state.testFlag(Qt::WindowMinimized)) {
1036 drawRoundedRect(
1037 painter, QPen(windowFrameColor, option.lineWidth), Qt::NoBrush,
1038 option.rect.adjusted(offset, offset, -offset, -offset), focusFrameCornerRadius, focusFrameCornerRadius, 0,
1039 0);
1040 drawRect(
1041 painter, Qt::NoPen, option.palette.brush(QPalette::Window),
1042 option.rect.adjusted(option.lineWidth, titleBarHeight, -option.lineWidth, 0));
1043 } else {
1044 drawRoundedRect(
1045 painter, Qt::NoPen, windowFrameColor, option.rect.adjusted(0, titleBarHeight, 0, 0), 0, 0,
1046 focusFrameCornerRadius, focusFrameCornerRadius);
1047 drawRoundedRect(
1048 painter, Qt::NoPen, option.palette.brush(QPalette::Window),
1049 option.rect.adjusted(option.lineWidth, titleBarHeight, -option.lineWidth, -option.lineWidth),
1050 focusFrameCornerRadius, focusFrameCornerRadius);
1051 drawRoundedRect(
1052 painter, QPen(windowFrameColor, option.lineWidth), Qt::NoBrush,
1053 option.rect.adjusted(offset, offset, -offset, -offset), focusFrameCornerRadius, focusFrameCornerRadius);
1054 }
1055}
1056
1057void drawToolTip(QPainter &painter, const QStyleOptionFrame &option)
1058{
1059 drawRoundedRect(
1060 painter, option.palette.color(QPalette::Active, QPalette::Base),
1061 option.palette.toolTipBase(), option.rect, toolTipCornerRadius,
1062 toolTipCornerRadius);
1063}
1064
1065QRect titleBarSubControlRect(const QStyleOptionTitleBar &option, QCommonStyle::SubControl subControl)
1066{
1067 const bool isMinimized = (option.titleBarState & Qt::WindowMinimized) != 0;
1068 const bool isMaximized = (option.titleBarState & Qt::WindowMaximized) != 0;
1069
1070 const bool hasTitle = option.titleBarFlags.testFlag(Qt::WindowTitleHint);
1071 const bool hasSystemMenuButton = option.titleBarFlags.testFlag(Qt::WindowSystemMenuHint);
1072 const bool hasShadeButton = option.titleBarFlags.testFlag(Qt::WindowShadeButtonHint);
1073 const bool hasContextHelpButton = option.titleBarFlags.testFlag(Qt::WindowContextHelpButtonHint);
1074 const bool hasMinimizeButton = option.titleBarFlags.testFlag(Qt::WindowMinimizeButtonHint);
1075 const bool hasMaximizeButton = option.titleBarFlags.testFlag(Qt::WindowMaximizeButtonHint);
1076
1077 const auto controlSize = QSize(30, 30);
1078 const int titleBarHorizontalMargin = 25;
1079 const int titleBarControlVerticalMargin = 15;
1080
1081 const auto titleBarContentRect = QRect(
1082 option.rect.x() + titleBarHorizontalMargin, (option.rect.height() - controlSize.height()) / 2,
1083 option.rect.width() - 2 * titleBarHorizontalMargin, controlSize.height());
1084 const auto titleBarContentRectRight = titleBarContentRect.x() + titleBarContentRect.width();
1085 const auto delta = controlSize.width() + titleBarControlVerticalMargin;
1086
1087 QRect result;
1088 switch (subControl) {
1089 case QCommonStyle::SC_TitleBarSysMenu:
1090 if (hasSystemMenuButton)
1091 result = QRect(titleBarContentRect.topLeft(), controlSize);
1092 break;
1093 case QCommonStyle::SC_TitleBarLabel:
1094 if (hasTitle) {
1095 result = titleBarContentRect;
1096 if (hasSystemMenuButton)
1097 result.adjust(delta, 0, -delta, 0);
1098 if (hasMinimizeButton)
1099 result.adjust(0, 0, -delta, 0);
1100 if (hasMaximizeButton)
1101 result.adjust(0, 0, -delta, 0);
1102 if (hasShadeButton)
1103 result.adjust(0, 0, -delta, 0);
1104 if (hasContextHelpButton)
1105 result.adjust(0, 0, -delta, 0);
1106 }
1107 break;
1108 case QCommonStyle::SC_TitleBarMaxButton:
1109 if (!isMaximized && hasMaximizeButton) {
1110 result = QRect(
1111 QPoint(titleBarContentRectRight - 3 * delta + titleBarControlVerticalMargin,
1112 titleBarContentRect.y()), controlSize);
1113 }
1114 break;
1115 case QCommonStyle::SC_TitleBarNormalButton:
1116 if (isMinimized && hasMinimizeButton) {
1117 result = QRect(
1118 QPoint(titleBarContentRectRight - 2 * delta + titleBarControlVerticalMargin,
1119 titleBarContentRect.y()), controlSize);
1120 } else if (isMaximized && hasMaximizeButton) {
1121 result = QRect(
1122 QPoint(titleBarContentRectRight - 3 * delta + titleBarControlVerticalMargin,
1123 titleBarContentRect.y()), controlSize);
1124 }
1125 break;
1126 case QCommonStyle::SC_TitleBarMinButton:
1127 if (!isMinimized && hasMinimizeButton) {
1128 result = QRect(
1129 QPoint(titleBarContentRectRight - 2 * delta + titleBarControlVerticalMargin,
1130 titleBarContentRect.y()), controlSize);
1131 }
1132 break;
1133 case QCommonStyle::SC_TitleBarCloseButton:
1134 result = QRect(
1135 QPoint(titleBarContentRectRight - controlSize.width(), titleBarContentRect.y()), controlSize);
1136 break;
1137 case QCommonStyle::SC_TitleBarShadeButton:
1138 case QCommonStyle::SC_TitleBarUnshadeButton:
1139 result = QRect(
1140 QPoint(titleBarContentRectRight - 4 * delta + titleBarControlVerticalMargin,
1141 titleBarContentRect.y()), controlSize);
1142 break;
1143 case QCommonStyle::SC_TitleBarContextHelpButton:
1144 result = QRect(
1145 QPoint(titleBarContentRectRight - (hasShadeButton ? 5 : 4) * delta + titleBarControlVerticalMargin,
1146 titleBarContentRect.y()), controlSize);
1147 break;
1148 default:
1149 break;
1150 }
1151
1152 return result;
1153}
1154
1155}
1156
1157QOhosStyle::QOhosStyle()
1158 : QCommonStyle()
1159{
1160}
1161
1162void QOhosStyle::drawPrimitive(
1163 PrimitiveElement element, const QStyleOption *option, QPainter *painter, const QWidget *widget) const
1164{
1165 switch (element) {
1166 case PE_Frame: {
1167 if (qobjectIsInstanceOf<QAbstractScrollArea>(widget)) {
1168 if (const auto *frameOption = qstyleoption_cast<const QStyleOptionFrame *>(option)) {
1169 const int frameWidth = frameOption->lineWidth;
1170 drawRect(
1171 *painter, QPen(option->palette.color(QPalette::Active, QPalette::Mid), frameWidth), Qt::NoBrush,
1172 adjusted(frameOption->rect, -frameWidth));
1173 } else {
1174 QCommonStyle::drawPrimitive(element, option, painter, widget);
1175 }
1176 } else if (widget && !qobjectIsInstanceOf<QComboBox>(widget->parent())) {
1177 QCommonStyle::drawPrimitive(element, option, painter, widget);
1178 }
1179 break;
1180 }
1181 case PE_FrameWindow:
1182 if (qStyleOptionIs<QStyleOptionFrame>(option)) {
1183 drawWindowBackgroundAndFrame(
1184 *painter, *qstyleoption_cast<const QStyleOptionFrame *>(option), widget->windowState(),
1185 pixelMetric(PM_TitleBarHeight, option, widget));
1186 }
1187 break;
1188 case PE_FrameFocusRect:
1189 if (qstyleoption_cast<const QStyleOptionFocusRect *>(option)) {
1190 if (qobjectIsInstanceOf<QPushButton>(widget)) {
1191 drawPushButtonFocus(*painter, *option);
1192 } else if (qobjectIsInstanceOf<QToolButton>(widget)) {
1193 const auto menuButtonIndicatorSize =
1194 qobject_cast<const QToolButton *>(widget)->popupMode() == QToolButton::MenuButtonPopup
1195 ? pixelMetric(PM_MenuButtonIndicator, option, widget)
1196 : 0;
1197 drawRoundedRect(
1198 *painter,
1199 QPen(option->palette.color(QPalette::Active, QPalette::Highlight), toolButtonFocusFrameWidth),
1200 Qt::NoBrush, option->rect.adjusted(-1, -1, 1 + menuButtonIndicatorSize, 1),
1201 toolButtonCornerRadius, toolButtonCornerRadius);
1202 } else if (qobjectIsInstanceOf<QCheckBox>(widget) || qobjectIsInstanceOf<QRadioButton>(widget)) {
1203 drawEllipse(
1204 *painter, QPen(option->palette.color(QPalette::Active, QPalette::Highlight),
1205 checkBoxOrRadioButtonFocusStrokeWidth), Qt::NoBrush, option->rect);
1206 } else if (qobjectIsInstanceOf<QTabBar>(widget)) {
1207 drawRoundedRect(
1208 *painter, QPen(option->palette.highlight(), tabBarTabFrameWidth), Qt::NoBrush,
1209 option->rect, tabBarTabRadius, tabBarTabRadius);
1210 } else {
1211 drawRoundedRect(
1212 *painter, QPen(option->palette.color(QPalette::Active, QPalette::Highlight), focusFrameWidth),
1213 Qt::NoBrush, option->rect, focusFrameCornerRadius, focusFrameCornerRadius);
1214 }
1215 }
1216 break;
1217 case PE_PanelButtonCommand:
1218 if (qStyleOptionIs<QStyleOptionButton>(option))
1219 drawPushButtonBackground(*painter, *qstyleoption_cast<const QStyleOptionButton *>(option));
1220 break;
1221 case PE_PanelButtonTool:
1222 if (qobjectIsInstanceOf<QMdiSubWindow>(widget)) {
1223 const QPalette *toolButtonThemePalette =
1224 QGuiApplicationPrivate::platformTheme()->palette(QPlatformTheme::Palette::ToolButtonPalette);
1225 const auto panelButtonColor =
1226 toolButtonThemePalette->color(QPalette::Active, QPalette::AlternateBase);
1227 drawEllipse(
1228 *painter, Qt::NoPen,
1229 widget->windowState().testFlag(Qt::WindowActive)
1230 ? panelButtonColor
1231 : makeInactiveOrDisabledFromColor(panelButtonColor),
1232 option->rect);
1233 } else {
1234 const QToolButton *toolButton = qobject_cast<const QToolButton *>(widget);
1235 const auto menuButtonIndicatorSize =
1236 toolButton != nullptr && toolButton->popupMode() == QToolButton::MenuButtonPopup
1237 ? pixelMetric(PM_MenuButtonIndicator, option, widget)
1238 : 0;
1239 auto optionCopy = *option;
1240 optionCopy.rect.setWidth(option->rect.width() + menuButtonIndicatorSize);
1241 drawToolButton(*painter, optionCopy);
1242 }
1243 break;
1244 case PE_PanelMenuBar:
1245 drawMenuBarBarbackground(*painter, *option);
1246 break;
1247 case PE_IndicatorCheckBox:
1248 drawCheckBoxOrRadioButtonIndicator(*painter, *option, true);
1249 break;
1250 case PE_IndicatorRadioButton:
1251 drawCheckBoxOrRadioButtonIndicator(*painter, *option, false);
1252 break;
1253 case PE_PanelLineEdit: {
1254 // HACK: Q(Abstrace)SpinBox contains a QLineEdit inside, which is painted separately from
1255 // the QSpinBox itself. We will be drawing the whole QSpinBox in the drawComplexControl.
1256 if (widget != nullptr && qobjectIsInstanceOf<QAbstractSpinBox>(widget->parentWidget()))
1257 break;
1258
1259 // HACK: QComboBox in editable mode presents line edit in the center. This line edit is drawn
1260 // above QComboBox. There are two issues here: QComboBox has different base color than line edit.
1261 // Second, line edit and QComboBox has the same size - so drawing a line edit overlays a frame border.
1262 // To fix above, do not draw line edit background.
1263 if (widget != nullptr && qobjectIsInstanceOf<QComboBox>(widget->parentWidget()))
1264 break;
1265
1266 // HACK: while editing Tree View/Widget item - line edit component is presented above it. If the line edit has
1267 // some opacity in background content below it (item content) is visible. This causes an effect that original
1268 // text is still visible while editing. To fix it, override background (base) color and use solid color value.
1269 auto optionCopy = *option;
1270 if (widget != nullptr && qstrcmp(widget->metaObject()->className(), "QExpandingLineEdit") == 0) {
1271 optionCopy.palette.setColor(
1272 QPalette::Base,
1273 option->palette.color(QPalette::Active, QPalette::AlternateBase));
1274 }
1275
1276 drawLineEditBackground(*painter, optionCopy);
1277 break;
1278 }
1279 case PE_PanelButtonBevel:
1280 if (qStyleOptionIs<QStyleOptionSpinBox>(option)) {
1281 drawSpinBoxButton(
1282 *painter, *qstyleoption_cast<const QStyleOptionSpinBox *>(option),
1283 pixelMetric(PM_SpinBoxFrameWidth, option, widget));
1284 }
1285 break;
1286 case PE_IndicatorSpinDown:
1287 case PE_IndicatorSpinUp: {
1288 // HACK: QCommonStyle adjusts the indicator left as follows: copy.rect.adjust(3, 0, -4, 0);
1289 // However, Ohos requires 4 pixels of horizontal margin and 2 pixels of vertical margin
1290 QRect indicatorRect = option->rect.adjusted(1, 2, 0, -2);
1291 constexpr int arrowWidth = 2;
1292 auto x = indicatorRect.x();
1293 auto y = indicatorRect.y();
1294 auto width = indicatorRect.width();
1295 auto height = indicatorRect.height();
1296 auto verticalSpacing = 4;
1297 auto horizontalSpacing = 7;
1298
1299 qreal x1 = x + horizontalSpacing;
1300 qreal x2 = x + width * 0.5;
1301 qreal x3 = x + width - horizontalSpacing;
1302
1303 qreal y1, y2;
1304 if (element == PE_IndicatorSpinDown) {
1305 y1 = y + verticalSpacing;
1306 y2 = y + height - verticalSpacing;
1307 } else {
1308 y1 = y + height - verticalSpacing;
1309 y2 = y + verticalSpacing;
1310 }
1311 auto y3 = y1;
1312
1313 QPen indicatorPen(option->palette.color(QPalette::Active, QPalette::Text), arrowWidth);
1314 indicatorPen.setCapStyle(Qt::RoundCap);
1315 indicatorPen.setJoinStyle(Qt::RoundJoin);
1316
1317 paintOnStackTop(*painter, [&](auto &p) {
1318 p.setOpacity(option->state.testFlag(State_Enabled) ? 1.0 : ohos_id_alpha_disabled);
1319 p.setRenderHint(QPainter::Antialiasing);
1320 p.setPen(indicatorPen);
1321 p.setBrush(Qt::NoBrush);
1322 p.drawLine(x1, y1, x2, y2);
1323 p.drawLine(x2, y2, x3, y3);
1324 });
1325 break;
1326 }
1327 case PE_FrameGroupBox: {
1328 const auto frame = qstyleoption_cast<const QStyleOptionFrame *>(option);
1329 if (frame != nullptr) {
1330 QPen pen;
1331 pen.setColor(option->palette.mid().color());
1332 pen.setStyle(
1333 frame->features.testFlag(QStyleOptionFrame::FrameFeature::Flat)
1334 ? Qt::NoPen : Qt::SolidLine);
1335
1336 painter->setClipRegion(frame->rect);
1337 drawRoundedRect(
1338 *painter, pen, option->palette.window(), frame->rect, groupBoxFrameCornerRadius,
1339 groupBoxFrameCornerRadius);
1340 }
1341 break;
1342 }
1343 case PE_IndicatorArrowUp:
1344 case PE_IndicatorArrowDown:
1345 case PE_IndicatorArrowLeft:
1346 case PE_IndicatorArrowRight: {
1347 QRect availableRect;
1348 int maxArrowSize = 0;
1349 if (qobjectIsInstanceOf<QComboBox>(widget)) {
1350 availableRect = option->rect;
1351 maxArrowSize = std::min(availableRect.width(), availableRect.height()) * 0.5;
1352 } else if (qobjectIsInstanceOf<QToolButton>(widget) || qobjectIsInstanceOf<QPushButton>(widget)) {
1353 const auto menuButtonIndicatorSize = pixelMetric(PM_MenuButtonIndicator, option, widget);
1354 availableRect = QRect(
1355 widget->size().width() - menuButtonIndicatorSize, 0, menuButtonIndicatorSize, widget->size().height());
1356 maxArrowSize = std::min(availableRect.width(), availableRect.height()) * 0.5;
1357 } else {
1358 availableRect = option->rect;
1359 maxArrowSize = std::min(availableRect.width(), availableRect.height());
1360 }
1361
1362 auto direction = ArrowDirection::Down;
1363 switch (element) {
1364 default:
1365 case PE_IndicatorArrowDown:
1366 break;
1367 case PE_IndicatorArrowUp:
1368 direction = ArrowDirection::Up;
1369 break;
1370 case PE_IndicatorArrowLeft:
1371 direction = ArrowDirection::Left;
1372 break;
1373 case PE_IndicatorArrowRight:
1374 direction = ArrowDirection::Right;
1375 break;
1376 }
1377
1378 const auto isEnabled = option->state.testFlag(QStyle::State_Enabled);
1379
1380 paintOnStackTop(*painter, [&](auto &p) {
1381 p.setOpacity(isEnabled ? 1.0 : ohos_id_alpha_disabled);
1382 drawArrow(
1383 p, availableRect, maxArrowSize, direction,
1384 option->palette.color(QPalette::Active, QPalette::WindowText));
1385 });
1386 break;
1387 }
1388 case PE_IndicatorButtonDropDown: {
1389 if (qobjectIsInstanceOf<QToolButton>(widget))
1390 break;
1391 QCommonStyle::drawPrimitive(element, option, painter, widget);
1392 break;
1393 }
1394 case PE_IndicatorHeaderArrow: {
1395 const auto headerOption = qstyleoption_cast<const QStyleOptionHeader *>(option);
1396 if (headerOption == nullptr || headerOption->sortIndicator == QStyleOptionHeader::None)
1397 break;
1398
1399 const auto direction = headerOption->sortIndicator == QStyleOptionHeader::SortDown
1400 ? ArrowDirection::Up
1401 : ArrowDirection::Down;
1402
1403 drawArrow(
1404 *painter, option->rect, option->rect.width(), direction,
1405 option->palette.color(QPalette::Active, QPalette::ButtonText));
1406 break;
1407 }
1408 case PE_PanelItemViewItem:
1409 if (qStyleOptionIs<QStyleOptionViewItem>(option)) {
1410 drawPanelItemViewItem(
1411 *painter, *qstyleoption_cast<const QStyleOptionViewItem *>(option),
1412 widget != nullptr && qstrcmp(widget->metaObject()->className(), "QComboBoxListView") == 0);
1413 }
1414 break;
1415 case PE_FrameTabWidget:
1416 if (qStyleOptionIs<QStyleOptionTabWidgetFrame>(option)) {
1417 QRect rect = option->rect;
1418
1419 switch (qstyleoption_cast<const QStyleOptionTabWidgetFrame *>(option)->shape) {
1420 case QTabBar::RoundedNorth:
1421 case QTabBar::TriangularNorth:
1422 rect.adjust(0, tabWidgetFrameWidth, 0, 0);
1423 break;
1424 case QTabBar::RoundedWest:
1425 case QTabBar::TriangularWest:
1426 rect.adjust(tabWidgetFrameWidth, 0, 0, 0);
1427 break;
1428 case QTabBar::RoundedSouth:
1429 case QTabBar::TriangularSouth:
1430 rect.adjust(0, 0, 0, -(tabWidgetFrameWidth * 2));
1431 break;
1432 case QTabBar::RoundedEast:
1433 case QTabBar::TriangularEast:
1434 rect.adjust(0, 0, -(tabWidgetFrameWidth * 2), 0);
1435 break;
1436 }
1437
1438 drawRect(
1439 *painter, QPen(option->palette.color(QPalette::Dark), tabWidgetFrameWidth),
1440 Qt::NoBrush, rect);
1441 }
1442 break;
1443 case PE_PanelTipLabel:
1444 if (qStyleOptionIs<QStyleOptionFrame>(option))
1445 drawToolTip(*painter, *qstyleoption_cast<const QStyleOptionFrame *>(option));
1446 break;
1447 default:
1448 QCommonStyle::drawPrimitive(element, option, painter, widget);
1449 break;
1450 }
1451}
1452
1453void QOhosStyle::drawControl(
1454 ControlElement element, const QStyleOption *option, QPainter *painter, const QWidget *widget) const
1455{
1456 switch (element) {
1457 case CE_HeaderSection:
1458 if (qStyleOptionIs<QStyleOptionHeader>(option))
1459 drawHeaderSection(*painter, *qstyleoption_cast<const QStyleOptionHeader *>(option));
1460 break;
1461 case CE_MenuBarEmptyArea:
1462 break;
1463 case CE_MenuItem:
1464 if (qStyleOptionIs<QStyleOptionMenuItem>(option)) {
1465 const auto *menuItemStyleOption = qstyleoption_cast<const QStyleOptionMenuItem *>(option);
1466 drawMenuItem(
1467 *painter, *menuItemStyleOption, pixelMetric(PM_IndicatorWidth, option, widget),
1468 pixelMetric(PM_SmallIconSize, option, widget));
1469 if (menuItemStyleOption->menuItemType == QStyleOptionMenuItem::SubMenu) {
1470 const auto iconSize = pixelMetric(PM_SmallIconSize, option, widget);
1471 const auto menuItemRect = menuItemStyleOption->rect;
1472
1473 QStyleOptionMenuItem menuArrowStyleOption = *menuItemStyleOption;
1474 menuArrowStyleOption.rect = QRect(
1475 menuItemRect.right() - itemViewItemHorizontalMargin - iconSize,
1476 menuItemRect.top() + (menuItemRect.height() - iconSize) / 2, iconSize, iconSize);
1477 QColor arrowColor = menuItemStyleOption->palette.color(QPalette::Active, QPalette::Text);
1478 menuArrowStyleOption.palette.setColor(
1479 QPalette::Active, QPalette::WindowText, arrowColor);
1480 drawPrimitive(
1481 menuArrowStyleOption.direction == Qt::RightToLeft ? PE_IndicatorArrowLeft : PE_IndicatorArrowRight,
1482 &menuArrowStyleOption, painter, widget);
1483 }
1484 }
1485 break;
1486 case CE_MenuTearoff:
1487 drawMenuTearOff(*painter, *option);
1488 break;
1489 case CE_ProgressBarGroove:
1490 if (qstyleoption_cast<const QStyleOptionProgressBar *>(option)) {
1491 drawRoundedRect(
1492 *painter, Qt::NoPen, option->palette.color(QPalette::Active, QPalette::Mid),
1493 getProgressBarGrooveRect(*qstyleoption_cast<const QStyleOptionProgressBar *>(option)),
1494 progressBarCornerRadius, progressBarCornerRadius);
1495 }
1496 break;
1497 case CE_ProgressBarContents:
1498 if (qstyleoption_cast<const QStyleOptionProgressBar *>(option))
1499 drawProgressBarContent(*painter, *qstyleoption_cast<const QStyleOptionProgressBar *>(option));
1500 break;
1501 case CE_ProgressBarLabel:
1502 break;
1503 case CE_Splitter:
1504 drawSplitter(*painter, *option);
1505 break;
1506 case CE_ToolBar:
1507 drawToolBarbackground(*painter, *option);
1508 break;
1509 case CE_ScrollBarSlider:
1510 if (qStyleOptionIs<QStyleOptionSlider>(option))
1511 drawScrollBarSlider(*painter, *qstyleoption_cast<const QStyleOptionSlider *>(option));
1512 break;
1513 case CE_TabBarTabShape: {
1514 auto tabOption = qstyleoption_cast<const QStyleOptionTab *>(option);
1515 if (tabOption != nullptr)
1516 drawTabBarTabShape(*painter, *tabOption);
1517 break;
1518 }
1519 case CE_TabBarTabLabel: {
1520 auto tabOption = qstyleoption_cast<const QStyleOptionTab *>(option);
1521 if (tabOption != nullptr) {
1522 auto copy = *tabOption;
1523 if (!option->state.testFlag(State_Selected))
1524 copy.palette.setCurrentColorGroup(QPalette::Inactive);
1525 QCommonStyle::drawControl(element, &copy, painter, widget);
1526 }
1527 break;
1528 }
1529 case CE_PushButtonLabel: {
1530 if (qStyleOptionIs<QStyleOptionButton>(option)) {
1531 auto buttonOption = qstyleoption_cast<const QStyleOptionButton *>(option);
1532
1533 auto buttonOptionCopy = *buttonOption;
1534 buttonOptionCopy.palette.setColor(QPalette::ButtonText, getPushButtonTextColor(*buttonOption));
1535
1536 QCommonStyle::drawControl(element, &buttonOptionCopy, painter, widget);
1537 }
1538 break;
1539 }
1540 case CE_DockWidgetTitle: {
1541 const auto *dockWidgetOption = qstyleoption_cast<const QStyleOptionDockWidget *>(option);
1542 if (dockWidgetOption == nullptr)
1543 break;
1544 auto dockWidgetOptionCopy = *dockWidgetOption;
1545 if (!dockWidgetOptionCopy.title.isEmpty()) {
1546 QRect titleRect = subElementRect(SE_DockWidgetTitleBarText, option, widget);
1547 if (dockWidgetOptionCopy.verticalTitleBar) {
1548 QRect rect = dockWidgetOptionCopy.rect;
1549 QRect verticalRect = rect.transposed();
1550 titleRect = QRect(
1551 verticalRect.left() + rect.bottom() - titleRect.bottom(),
1552 verticalRect.top() + titleRect.left() - rect.left(),
1553 titleRect.height(),
1554 titleRect.width());
1555 }
1556 dockWidgetOptionCopy.title = painter->fontMetrics().elidedText(
1557 dockWidgetOptionCopy.title, Qt::ElideRight, titleRect.width());
1558 }
1559 QCommonStyle::drawControl(element, &dockWidgetOptionCopy, painter, widget);
1560 break;
1561 }
1562 default:
1563 QCommonStyle::drawControl(element, option, painter, widget);
1564 }
1565}
1566
1567void QOhosStyle::drawComplexControl(
1568 ComplexControl control, const QStyleOptionComplex *option, QPainter *painter, const QWidget *widget) const
1569{
1570 switch (control) {
1571 case CC_Slider: {
1572 const auto sliderStyleOption = qstyleoption_cast<const QStyleOptionSlider *>(option);
1573 if (sliderStyleOption != nullptr) {
1574 if (option->subControls.testFlag(SC_SliderGroove)) {
1575 auto sliderStyleOptionCopy = *sliderStyleOption;
1576 sliderStyleOptionCopy.rect = subControlRect(control, option, SC_SliderGroove, widget);
1577 drawSliderGroove(*painter, sliderStyleOptionCopy);
1578 }
1579 if (option->subControls.testFlag(SC_SliderHandle)) {
1580 auto sliderStyleOptionCopy = *sliderStyleOption;
1581 sliderStyleOptionCopy.rect = subControlRect(control, option, SC_SliderHandle, widget);
1582 drawSliderThumb(*painter, sliderStyleOptionCopy);
1583 }
1584 }
1585 break;
1586 }
1587 case CC_SpinBox:
1588 if (qStyleOptionIs<QStyleOptionSpinBox>(option)) {
1589 auto spinBox = qstyleoption_cast<const QStyleOptionSpinBox *>(option);
1590 auto frameRect = subControlRect(control, spinBox, SC_SpinBoxFrame, widget);
1591 auto frameWidth = pixelMetric(PM_SpinBoxFrameWidth, spinBox, widget);
1592 drawSpinBoxFrame(*painter, *spinBox, frameRect, frameWidth);
1593
1594 auto copy = *spinBox;
1595 copy.frame = false;
1596
1597 QCommonStyle::drawComplexControl(control, &copy, painter, widget);
1598 }
1599 break;
1600 case CC_ScrollBar: {
1601 const auto scrollBarStyleOption = qstyleoption_cast<const QStyleOptionSlider *>(option);
1602 if (scrollBarStyleOption != nullptr) {
1603 if (option->subControls.testFlag(SC_ScrollBarSlider)) {
1604 auto scrollBarStyleOptionCopy = *scrollBarStyleOption;
1605 scrollBarStyleOptionCopy.rect = subControlRect(control, option, SC_ScrollBarSlider, widget);
1606 drawControl(CE_ScrollBarSlider, &scrollBarStyleOptionCopy, painter, widget);
1607 }
1608 }
1609 break;
1610 }
1611 case CC_GroupBox: {
1612 if (qStyleOptionIs<QStyleOptionGroupBox>(option)) {
1613 auto groupBox = *qstyleoption_cast<const QStyleOptionGroupBox *>(option);
1614 groupBox.textAlignment |= Qt::AlignVCenter;
1615
1616 const auto colorGroup = option->state.testFlag(QStyle::State_Enabled)
1617 ? QPalette::Active
1618 : QPalette::Disabled;
1619 if (!groupBox.palette.isBrushSet(colorGroup, QPalette::WindowText))
1620 groupBox.textColor = groupBox.palette.color(QPalette::Text);
1621
1622 const auto titleFont = getGroupBoxTitleFont(widget);
1623 painter->setFont(titleFont);
1624
1625 QCommonStyle::drawComplexControl(control, &groupBox, painter, widget);
1626 }
1627 break;
1628 }
1629 case CC_ComboBox: {
1630 if (qStyleOptionIs<QStyleOptionComboBox>(option)) {
1631 const auto comboBoxStyleOption = qstyleoption_cast<const QStyleOptionComboBox *>(option);
1632 if (option->subControls.testFlag(SC_ComboBoxFrame)) {
1633 auto comboBoxStyleOptionCopy = *comboBoxStyleOption;
1634 comboBoxStyleOptionCopy.rect = subControlRect(control, option, SC_ComboBoxFrame, widget);
1635 drawComboBoxFrame(*painter, comboBoxStyleOptionCopy);
1636 }
1637
1638 if (option->subControls.testFlag(SC_ComboBoxArrow)) {
1639 auto optionCopy = *option;
1640 auto comboBoxOptions = static_cast<QStyleOption *>(&optionCopy);
1641 comboBoxOptions->rect = subControlRect(control, option, SC_ComboBoxArrow, widget);
1642 drawPrimitive(PE_IndicatorArrowDown, comboBoxOptions, painter, widget);
1643 }
1644 } else {
1645 QCommonStyle::drawComplexControl(control, option, painter, widget);
1646 }
1647 break;
1648 }
1649 default:
1650 QCommonStyle::drawComplexControl(control, option, painter, widget);
1651 }
1652}
1653
1654QRect QOhosStyle::subControlRect(
1655 ComplexControl control, const QStyleOptionComplex *option, SubControl subControl, const QWidget *widget) const
1656{
1657 switch (control) {
1658 case CC_Slider:
1659 if (qStyleOptionIs<QStyleOptionSlider>(option)) {
1660 const auto sliderStyleOption = qstyleoption_cast<const QStyleOptionSlider *>(option);
1661 switch (subControl) {
1662 case SC_SliderGroove: {
1663 const auto sliderLengthOffset = pixelMetric(PM_SliderLength, option, widget) * 0.5;
1664 auto grooveRect = QCommonStyle::subControlRect(control, option, subControl, widget);
1665
1666 if (sliderStyleOption->orientation == Qt::Horizontal) {
1667 grooveRect.adjust(sliderLengthOffset, 0, -sliderLengthOffset, 0);
1668 grooveRect.setHeight(sliderGrooveHeight);
1669 grooveRect.moveTop(option->rect.center().y() - sliderGrooveHeight * 0.5);
1670 } else {
1671 grooveRect.adjust(0, sliderLengthOffset, 0, -sliderLengthOffset);
1672 grooveRect.setWidth(sliderGrooveHeight);
1673 grooveRect.moveLeft(option->rect.center().x() - sliderGrooveHeight * 0.5);
1674 }
1675
1676 return grooveRect;
1677 }
1678 case SC_SliderHandle: {
1679 auto handleRect = QCommonStyle::subControlRect(control, option, subControl, widget);
1680 if (sliderStyleOption->orientation == Qt::Horizontal)
1681 handleRect.moveTop(option->rect.center().y() - handleRect.height() * 0.5);
1682 else
1683 handleRect.moveLeft(option->rect.center().x() - handleRect.width() * 0.5);
1684 return handleRect;
1685 }
1686 default:
1687 return QCommonStyle::subControlRect(control, option, subControl, widget);
1688 }
1689 } else {
1690 return QCommonStyle::subControlRect(control, option, subControl, widget);
1691 }
1692 case CC_SpinBox:
1693 if (qStyleOptionIs<QStyleOptionSpinBox>(option)) {
1694 const auto spinBox = qstyleoption_cast<const QStyleOptionSpinBox *>(option);
1695 auto frameWidth = spinBox->frame ? pixelMetric(PM_SpinBoxFrameWidth, option, widget) : 0;
1696
1697 switch (subControl) {
1698 case SC_SpinBoxFrame: {
1699 auto frameRect = spinBox->rect;
1700 frameRect.setHeight(spinBoxFrameHeight);
1701 frameRect.moveCenter(spinBox->rect.center());
1702 return visualRect(spinBox->direction, spinBox->rect, frameRect);
1703 }
1704 case SC_SpinBoxDown:
1705 case SC_SpinBoxUp: {
1706 auto frameRect = subControlRect(CC_SpinBox, option, SC_SpinBoxFrame, widget);
1707 if (spinBox->buttonSymbols == QAbstractSpinBox::NoButtons)
1708 return QRect();
1709 auto buttonRect = QRect(
1710 frameRect.left() + frameRect.width() - spinBoxButtonBoxWidth,
1711 frameRect.top() + (frameRect.height() - spinBoxFrameHeight) * 0.5,
1712 spinBoxButtonBoxWidth, spinBoxButtonBoxHeight);
1713 if (subControl == SC_SpinBoxDown)
1714 buttonRect.translate(0, spinBoxButtonBoxHeight);
1715 return visualRect(spinBox->direction, frameRect, buttonRect);
1716 }
1717 case SC_SpinBoxEditField: {
1718 auto editRect = adjusted(spinBox->rect, -frameWidth);
1719 if (spinBox->buttonSymbols != QAbstractSpinBox::NoButtons) {
1720 editRect.setWidth(spinBox->rect.width() - frameWidth - spinBoxButtonBoxWidth);
1721 editRect = visualRect(spinBox->direction, spinBox->rect, editRect);
1722 }
1723 return editRect;
1724 }
1725 default:
1726 return QCommonStyle::subControlRect(control, option, subControl, widget);
1727 }
1728 } else {
1729 return QCommonStyle::subControlRect(control, option, subControl, widget);
1730 }
1731 case CC_ScrollBar:
1732 if (qStyleOptionIs<QStyleOptionSlider>(option)) {
1733 auto scrollBoxStyleOption = qstyleoption_cast<const QStyleOptionSlider *>(option);
1734 auto defaultUpButtonRect = QCommonStyle::subControlRect(control, option, SC_ScrollBarSubLine, widget);
1735 auto defaultDownButtonRect = QCommonStyle::subControlRect(control, option, SC_ScrollBarAddLine, widget);
1736 switch (subControl) {
1737 case SC_ScrollBarAddLine:
1738 case SC_ScrollBarSubLine:
1739 return QRect();
1740 case SC_ScrollBarSubPage: {
1741 auto subPageRect = QCommonStyle::subControlRect(control, option, subControl, widget);
1742 if (scrollBoxStyleOption->orientation == Qt::Vertical)
1743 subPageRect.moveTop(subPageRect.top() - defaultDownButtonRect.height());
1744 else
1745 subPageRect.moveLeft(subPageRect.left() - defaultDownButtonRect.width());
1746 return subPageRect;
1747 }
1748 case SC_ScrollBarAddPage: {
1749 auto addPageRect = QCommonStyle::subControlRect(control, option, subControl, widget);
1750 if (scrollBoxStyleOption->orientation == Qt::Vertical)
1751 addPageRect.moveTop(addPageRect.top() + defaultUpButtonRect.height());
1752 else
1753 addPageRect.moveLeft(addPageRect.left() + defaultUpButtonRect.width());
1754 return addPageRect;
1755 }
1756 case SC_ScrollBarSlider: {
1757 const bool activeScrollBar =
1758 option->state.testFlag(QCommonStyle::State_Enabled)
1759 && option->state.testFlag(QCommonStyle::State_MouseOver);
1760 auto scrollBarExtent = activeScrollBar ? thickScrollBarSize : thinScrollBarSize;
1761
1762 auto sliderRect = QCommonStyle::subControlRect(control, option, subControl, widget);
1763 if (scrollBoxStyleOption->orientation == Qt::Vertical) {
1764 sliderRect.setWidth(scrollBarExtent);
1765 sliderRect.setHeight(sliderRect.height() + defaultUpButtonRect.height() + defaultDownButtonRect.height());
1766 sliderRect.moveTop(sliderRect.top() - defaultUpButtonRect.height());
1767 sliderRect.moveLeft((option->rect.width() - sliderRect.width()) * 0.5);
1768 } else {
1769 sliderRect.setHeight(scrollBarExtent);
1770 sliderRect.setWidth(sliderRect.width() + defaultUpButtonRect.width() + defaultDownButtonRect.width());
1771 sliderRect.moveTop((option->rect.height() - sliderRect.height()) * 0.5);
1772 sliderRect.moveLeft(sliderRect.left() - defaultUpButtonRect.width());
1773 }
1774 return sliderRect;
1775 }
1776 default:
1777 return QCommonStyle::subControlRect(control, option, subControl, widget);
1778 }
1779 } else {
1780 return QCommonStyle::subControlRect(control, option, subControl, widget);
1781 }
1782 case CC_GroupBox:
1783 if (qStyleOptionIs<QStyleOptionGroupBox>(option)) {
1784 auto groupBox = *qstyleoption_cast<const QStyleOptionGroupBox *>(option);
1785 groupBox.fontMetrics = QFontMetrics(getGroupBoxTitleFont(widget));
1786
1787 auto labelRect =
1788 QCommonStyle::subControlRect(control, &groupBox, SC_GroupBoxLabel, widget);
1789 if (groupBox.text.isEmpty()) {
1790 labelRect.moveTop(groupBox.rect.top() + groupBoxTopPadding);
1791 labelRect.moveBottom(labelRect.top());
1792 } else {
1793 labelRect.moveTop(
1794 groupBox.rect.top() + groupBoxTopPadding + groupBox.fontMetrics.height() / 2);
1795 }
1796
1797 switch (subControl) {
1798 case SC_GroupBoxFrame:
1799 return QCommonStyle::subControlRect(control, &groupBox, subControl, widget);
1800 case SC_GroupBoxLabel: {
1801 return labelRect;
1802 }
1803 case SC_GroupBoxCheckBox: {
1804 auto checkBoxRect =
1805 QCommonStyle::subControlRect(control, &groupBox, subControl, widget);
1806 checkBoxRect.moveTop(labelRect.center().y() - checkBoxRect.height() / 2);
1807 return checkBoxRect;
1808 }
1809 case SC_GroupBoxContents: {
1810 auto contentsRect =
1811 QCommonStyle::subControlRect(control, &groupBox, SC_GroupBoxContents, widget);
1812 contentsRect.setTop(labelRect.bottom() + (groupBox.text.isEmpty() ? 0 : groupBoxTitleToContentSpacing));
1813 contentsRect.setBottom(groupBox.rect.bottom() - groupBoxBottomPadding);
1814 contentsRect.adjust(groupBoxHorizontalPadding, 0, -groupBoxHorizontalPadding, 0);
1815 return contentsRect;
1816 }
1817 default:
1818 return QCommonStyle::subControlRect(control, option, subControl, widget);
1819 }
1820 } else {
1821 return QCommonStyle::subControlRect(control, option, subControl, widget);
1822 }
1823 case CC_ComboBox:
1824 if (qStyleOptionIs<QStyleOptionComboBox>(option)) {
1825 auto comboBoxStyleOption = qstyleoption_cast<const QStyleOptionComboBox *>(option);
1826 const auto arrowSize = pixelMetric(PM_MenuButtonIndicator, option, widget);
1827 switch (subControl) {
1828 case SC_ComboBoxFrame: {
1829 return adjusted(comboBoxStyleOption->rect, -comboBoxFocusFrameWidth);;
1830 }
1831 case SC_ComboBoxEditField: {
1832 const auto editFieldRect = comboBoxStyleOption->rect.adjusted(
1833 comboBoxFrameLeftRightPadding, comboBoxVerticalMargin,
1834 -arrowSize - comboBoxFrameLeftRightPadding, -comboBoxVerticalMargin);
1835 return visualRect(comboBoxStyleOption->direction, comboBoxStyleOption->rect, editFieldRect);
1836 }
1837 case SC_ComboBoxArrow: {
1838 auto arrowIconRect = comboBoxStyleOption->rect;
1839 arrowIconRect.setWidth(arrowSize);
1840 arrowIconRect.moveRight(comboBoxStyleOption->rect.right() - comboBoxFrameLeftRightPadding);
1841 return visualRect(comboBoxStyleOption->direction, comboBoxStyleOption->rect, arrowIconRect);
1842 }
1843 default:
1844 return QCommonStyle::subControlRect(control, option, subControl, widget);
1845 }
1846 } else {
1847 return QCommonStyle::subControlRect(control, option, subControl, widget);
1848 }
1849 case CC_TitleBar:
1850 if (qStyleOptionIs<QStyleOptionTitleBar>(option)) {
1851 auto titleBarOption = qstyleoption_cast<const QStyleOptionTitleBar *>(option);
1852 return visualRect(
1853 titleBarOption->direction, titleBarOption->rect, titleBarSubControlRect(*titleBarOption, subControl));
1854 } else {
1855 return QCommonStyle::subControlRect(control, option, subControl, widget);
1856 }
1857 default:
1858 return QCommonStyle::subControlRect(control, option, subControl, widget);
1859 }
1860}
1861
1862QRect QOhosStyle::subElementRect(SubElement element, const QStyleOption *option, const QWidget *widget) const
1863{
1864 switch (element) {
1865 case SE_PushButtonContents:
1866 return option->rect.adjusted(pushButtonHorizontalMargin, 0, -pushButtonHorizontalMargin, 0);
1867 case SE_ItemViewItemFocusRect:
1868 return option->rect.adjusted(focusFrameWidth, focusFrameWidth, -focusFrameWidth, -focusFrameWidth);
1869 case SE_ProgressBarGroove:
1870 case SE_ProgressBarContents:
1871 return option->rect;
1872 case SE_ProgressBarLabel:
1873 return QRect();
1874 case SE_LineEditContents: {
1875 int horizontalMargin =
1876 widget != nullptr && qobjectIsInstanceOf<QAbstractSpinBox>(widget->parent())
1877 ? spinBoxEditHorizontalMargin
1878 : lineEditHorizontalMargin;
1879 return option->rect.adjusted(horizontalMargin, 0, -horizontalMargin, 0);
1880 }
1881 case SE_CheckBoxFocusRect:
1882 case SE_RadioButtonFocusRect:
1883 return QRect(
1884 checkBoxOrRadioButtonFocusStrokeWidth, (option->rect.height() - checkBoxOrRadioButtonHoverSize) * 0.5,
1885 checkBoxOrRadioButtonHoverSize, checkBoxOrRadioButtonHoverSize);
1886 case SE_CheckBoxClickRect:
1887 return subElementRect(SE_CheckBoxIndicator, option, widget)
1888 | subElementRect(SE_CheckBoxContents, option, widget);
1889 case SE_RadioButtonClickRect:
1890 return subElementRect(SE_RadioButtonIndicator, option, widget)
1891 | subElementRect(SE_RadioButtonContents, option, widget);
1892 default:
1893 return QCommonStyle::subElementRect(element, option, widget);;
1894 }
1895}
1896
1897QSize QOhosStyle::sizeFromContents(
1898 ContentsType contents, const QStyleOption *option, const QSize &contentsSize, const QWidget *widget) const
1899{
1900 switch (contents) {
1901 case CT_ItemViewItem: {
1902 const auto viewItemStyleOption = qstyleoption_cast<const QStyleOptionViewItem *>(option);
1903 if (viewItemStyleOption != nullptr) {
1904 if (isItemViewSeparator(viewItemStyleOption->index)) {
1905 return QSize(option->rect.width(), itemViewSeparatorHeight);
1906 } else {
1907 auto verticalMargin = viewItemStyleOption->features.testFlag(QStyleOptionViewItem::HasDecoration)
1908 ? itemViewItemWithDecorationVerticalMargin
1909 : itemViewItemVerticalMargin;
1910 return QCommonStyle::sizeFromContents(contents, option, contentsSize, widget)
1911 + QSize(0, 2 * verticalMargin);
1912 }
1913 } else {
1914 return QCommonStyle::sizeFromContents(contents, option, contentsSize, widget);
1915 }
1916 }
1917 case CT_PushButton: {
1918 auto sizeAlignment = (2 * pushButtonFocusFrameGap) + (2 * pushButtonFocusFrameWidth);
1919 return contentsSize + QSize(
1920 (pushButtonHorizontalMargin * 2) + sizeAlignment, (pushButtonVerticalMargin * 2) + sizeAlignment);
1921 }
1922 case CT_ComboBox: {
1923 const auto arrowSize = pixelMetric(PM_MenuButtonIndicator, option, widget);
1924 auto comboBoxSize = qStyleOptionIs<QStyleOptionComboBox>(option)
1925 && qstyleoption_cast<const QStyleOptionComboBox *>(option)->editable
1926 ? contentsSize + QSize(2 * lineEditHorizontalMargin, 0)
1927 : contentsSize;
1928 const auto frameWidthCompensation = 2 * comboBoxFocusFrameWidth;
1929 comboBoxSize.rwidth() += (arrowSize + frameWidthCompensation + 2 * comboBoxFrameLeftRightPadding);
1930 comboBoxSize.rheight() += (frameWidthCompensation + 2 * comboBoxVerticalMargin + 2 * lineEditVerticalMargin);
1931 return comboBoxSize;
1932 }
1933 case CT_ProgressBar: {
1934 const auto progressBarStyleOption = qstyleoption_cast<const QStyleOptionProgressBar *>(option);
1935 if (progressBarStyleOption != nullptr) {
1936 const bool horizontal = progressBarStyleOption->state & QStyle::State_Horizontal;
1937 if (horizontal)
1938 return QSize(contentsSize.width(), std::max(contentsSize.height(), progressBarMinHeight));
1939 else
1940 return QSize(std::max(contentsSize.height(), progressBarMinHeight), contentsSize.height());
1941 } else {
1942 return QCommonStyle::sizeFromContents(contents, option, contentsSize, widget);
1943 }
1944 }
1945 case CT_MenuItem: {
1946 const auto defaultSize = QCommonStyle::sizeFromContents(contents, option, contentsSize, widget);
1947 const auto *menuItemStyleOption = qstyleoption_cast<const QStyleOptionMenuItem *>(option);
1948 if (menuItemStyleOption != nullptr) {
1949 if (menuItemStyleOption->menuItemType == QStyleOptionMenuItem::Separator) {
1950 return QSize(defaultSize.width(), itemViewSeparatorHeight);
1951 } else {
1952 const auto menuVMargin = pixelMetric(PM_MenuVMargin, option, widget);
1953 const auto arrowWidth = menuItemStyleOption->menuItemType == QStyleOptionMenuItem::SubMenu
1954 ? menuVMargin + pixelMetric(PM_SmallIconSize, option, widget)
1955 : 0;
1956 const auto checkboxWidth = menuItemStyleOption->checkType != QStyleOptionMenuItem::NotCheckable
1957 ? menuVMargin + pixelMetric(PM_IndicatorWidth, option, widget)
1958 : 0;
1959
1960 return defaultSize
1961 + QSize(2 * itemViewItemHorizontalMargin, 2 * menuVMargin)
1962 + QSize(arrowWidth, 0)
1963 + QSize(checkboxWidth, 0);
1964 }
1965 } else {
1966 return defaultSize;
1967 }
1968 }
1969 case CT_GroupBox: {
1970 const auto groupBox = qstyleoption_cast<const QStyleOptionGroupBox *>(option);
1971 if (groupBox == nullptr)
1972 return QCommonStyle::sizeFromContents(contents, option, contentsSize, widget);
1973
1974 const QFontMetrics titleMetrics(getGroupBoxTitleFont(widget));
1975 QSize titleSize(
1976 titleMetrics.horizontalAdvance(groupBox->text) + titleMetrics.horizontalAdvance(u' '),
1977 titleMetrics.height());
1978 if (groupBox->subControls.testFlag(SC_GroupBoxCheckBox)) {
1979 titleSize.rwidth() += pixelMetric(PM_IndicatorWidth, option, widget)
1980 + pixelMetric(PM_CheckBoxLabelSpacing, option, widget);
1981 titleSize.rheight() =
1982 std::max(titleSize.height(), pixelMetric(PM_IndicatorHeight, option, widget));
1983 }
1984
1985 return QCommonStyle::sizeFromContents(contents, option, titleSize, widget);
1986 }
1987 case CT_LineEdit: {
1988 int horizontalMargin;
1989 if (widget != nullptr && qobjectIsInstanceOf<QAbstractSpinBox>(widget->parent()))
1990 horizontalMargin = spinBoxEditHorizontalMargin;
1991 else
1992 horizontalMargin = lineEditHorizontalMargin;
1993 return contentsSize + QSize(horizontalMargin * 2, lineEditVerticalMargin * 2);
1994 }
1995 case CT_SpinBox: {
1996 const auto spinBox = qstyleoption_cast<const QStyleOptionSpinBox *>(option);
1997 if (spinBox != nullptr) {
1998 int buttonWidth;
1999 if (spinBox->subControls.testFlag(QStyle::SC_SpinBoxUp)
2000 && spinBox->subControls.testFlag(QStyle::SC_SpinBoxDown)) {
2001 buttonWidth = subControlRect(CC_SpinBox, spinBox, SC_SpinBoxDown, widget).width();
2002 } else {
2003 buttonWidth = 0;
2004 }
2005 const int frameWidth
2006 = spinBox->frame ? pixelMetric(PM_SpinBoxFrameWidth, option, widget) : 0;
2007
2008 return QSize(contentsSize.width() + buttonWidth + 2 * frameWidth + spinBoxEditHorizontalMargin * 2,
2009 std::max(contentsSize.height() + 2 * frameWidth, spinBoxFrameHeight));
2010 }
2011
2012 return contentsSize;
2013 }
2014 default:
2015 return QCommonStyle::sizeFromContents(contents, option, contentsSize, widget);
2016 }
2017}
2018
2019int QOhosStyle::pixelMetric(PixelMetric metric, const QStyleOption *option, const QWidget *widget) const
2020{
2021 switch (metric) {
2022 case PM_ButtonMargin:
2023 case PM_ButtonDefaultIndicator:
2024 case PM_ButtonShiftHorizontal:
2025 case PM_ButtonShiftVertical:
2026 return 0;
2027 case PM_IndicatorWidth:
2028 case PM_ExclusiveIndicatorWidth:
2029 return checkBoxOrRadioButtonSize;
2030 case PM_IndicatorHeight:
2031 case PM_ExclusiveIndicatorHeight:
2032 return checkBoxOrRadioButtonSize;
2033 case PM_FocusFrameHMargin:
2034 return qStyleOptionIs<QStyleOptionViewItem>(option)
2035 ? itemViewItemSpacing
2036 : QCommonStyle::pixelMetric(metric, option, widget);
2037 case PM_TextCursorWidth:
2038 return textCursorWidth;
2039 case PM_DefaultFrameWidth:
2040 if (qobjectIsInstanceOf<QLineEdit>(widget) || qobjectIsInstanceOf<QPushButton>(widget))
2041 return 0;
2042 else
2043 return QCommonStyle::pixelMetric(metric, option, widget);
2044 case PM_MenuBarPanelWidth:
2045 return 0;
2046 case PM_MenuBarItemSpacing:
2047 return menuBarItemSpacing;
2048 case PM_MenuBarVMargin:
2049 return menuBarVerticalMargin;
2050 case PM_MenuBarHMargin:
2051 return menuBarHorizontalMargin;
2052 case PM_MenuPanelWidth:
2053 return 0;
2054 case PM_MenuHMargin:
2055 return 0;
2056 case PM_MenuVMargin:
2057 return menuItemVerticalMargin;
2058 case PM_ProgressBarChunkWidth:
2059 return 0;
2060 case PM_SliderThickness:
2061 return sliderThickness;
2062 case PM_SliderLength:
2063 case PM_SliderControlThickness:
2064 return sliderThumbSize + 2 * sliderHoverSize;
2065 case PM_SmallIconSize:
2066 return qStyleOptionIs<QStyleOptionMenuItem>(option) || qStyleOptionIs<QStyleOptionComboBox>(option)
2067 ? smallIconSize
2068 : QCommonStyle::pixelMetric(metric, option, widget);
2069 case PM_SplitterWidth:
2070 return splitterWidth;
2071 case PM_SpinBoxFrameWidth:
2072 return spinBoxFrameStroke;
2073 case PM_ScrollBarExtent:
2074 return maxScrollBarSize;
2075 case PM_TabBarTabShiftVertical:
2076 case PM_TabBarBaseOverlap:
2077 return 0;
2078 case PM_TabBarTabHSpace:
2079 return 2 * tabBarTabRadius + 2 * tabBarTabFrameWidth;
2080 case PM_TitleBarHeight:
2081 return titleBarHeight;
2082 case PM_HeaderMargin:
2083 return headerMargin;
2084 case PM_HeaderDefaultSectionSizeVertical:
2085 return headerDefaultSectionSizeVertical;
2086 case PM_ToolTipLabelFrameWidth:
2087 return toolTipFrameWidth;
2088 case PM_MenuButtonIndicator:
2089 return 2 * QCommonStyle::pixelMetric(metric, option, widget);
2090 default:
2091 return QCommonStyle::pixelMetric(metric, option, widget);
2092 }
2093}
2094
2095int QOhosStyle::styleHint(
2096 StyleHint hint, const QStyleOption *option, const QWidget *widget, QStyleHintReturn *hintReturn) const
2097{
2098 switch (hint) {
2099 case SH_Slider_AbsoluteSetButtons:
2100 return Qt::LeftButton | Qt::MiddleButton;
2101 case SH_Slider_PageSetButtons:
2102 return 0;
2103 case SH_ItemView_ShowDecorationSelected:
2104 return qobjectIsInstanceOf<QTreeView>(widget) ? 0 : 1;
2105 case SH_ToolTipLabel_Opacity:
2106 return toolTipBackgroundAlpha;
2107 case SH_Menu_MouseTracking:
2108 case SH_MenuBar_MouseTracking:
2109 return 1;
2110 default:
2111 return QCommonStyle::styleHint(hint, option, widget, hintReturn);
2112 }
2113}
2114
2115void QOhosStyle::polish(QWidget *widget)
2116{
2117 QCommonStyle::polish(widget);
2118
2119 if (isHoverable(widget))
2120 widget->setAttribute(Qt::WA_Hover);
2121
2122 if (qobjectIsInstanceOf<QPushButton>(widget)) {
2123 if (qobject_cast<QPushButton *>(widget)->isDefault()) {
2124 QPalette palette = widget->palette();
2125 auto textDisabledColor = palette.color(QPalette::Active, QPalette::Base);
2126 textDisabledColor.setAlphaF(ohos_id_alpha_disabled);
2127 palette.setColor(QPalette::All, QPalette::ButtonText, palette.color(QPalette::Active, QPalette::Base));
2128 palette.setColor(QPalette::Disabled, QPalette::ButtonText, textDisabledColor);
2129 widget->setPalette(palette);
2130 }
2131 } else if (qobjectIsInstanceOf<QScrollBar>(widget)) {
2132 widget->setAttribute(Qt::WA_NoSystemBackground);
2133 widget->setAttribute(Qt::WA_OpaquePaintEvent, false);
2134 } else if (qobjectIsInstanceOf<QListView>(widget)) {
2135 qobject_cast<QListView *>(widget)->viewport()->setAttribute(Qt::WA_Hover);
2136 } else if (qobjectIsInstanceOf<QComboBox>(widget)) {
2137 auto comboBox = qobject_cast<QComboBox *>(widget);
2138 const char *delegateClassName = comboBox->itemDelegate()->metaObject()->className();
2139 bool isDefaultComboBoxDelegate =
2140 qstrcmp(delegateClassName, "QComboBoxDelegate") == 0
2141 || qstrcmp(delegateClassName, "QComboMenuDelegate") == 0;
2142 if (isDefaultComboBoxDelegate)
2143 comboBox->setItemDelegate(new QStyledItemDelegate(comboBox->view()));
2144 } else if (qobjectIsInstanceOf<QMdiSubWindow>(widget)) {
2145 widget->setAttribute(Qt::WA_TranslucentBackground);
2146 widget->setAutoFillBackground(false);
2147
2148 auto palette = widget->palette();
2149 palette.setColor(QPalette::Highlight, palette.color(QPalette::Active, QPalette::Base));
2150 palette.setColor(QPalette::Inactive, QPalette::Dark, palette.color(QPalette::Inactive, QPalette::Base));
2151 palette.setColor(
2152 QPalette::Inactive, QPalette::Window,
2153 makeInactiveOrDisabledFromColor(palette.color(QPalette::Active, QPalette::AlternateBase)));
2154 palette.setColor(QPalette::HighlightedText, Qt::black);
2155 widget->setPalette(palette);
2156 }
2157}
2158
2159void QOhosStyle::unpolish(QWidget *widget)
2160{
2161 if (isHoverable(widget)) {
2162 widget->setAttribute(Qt::WA_Hover, false);
2163 } else if (qobjectIsInstanceOf<QScrollBar>(widget)) {
2164 widget->setAttribute(Qt::WA_NoSystemBackground, false);
2165 widget->setAttribute(Qt::WA_OpaquePaintEvent);
2166 } else if (qobjectIsInstanceOf<QListView>(widget)) {
2167 qobject_cast<QListView *>(widget)->viewport()->setAttribute(Qt::WA_Hover, false);
2168 }
2169 QCommonStyle::unpolish(widget);
2170}
2171
2172QPalette QOhosStyle::standardPalette() const
2173{
2174 return *QGuiApplicationPrivate::platformTheme()->palette();
2175}
2176
2177QIcon QOhosStyle::standardIcon(
2178 StandardPixmap standardPixmap, const QStyleOption *option, const QWidget *widget) const
2179{
2180 const QString iconName = ohosThemeIconName(standardPixmap);
2181 if (!iconName.isEmpty()) {
2182 const QIcon icon = QIcon::fromTheme(iconName);
2183 if (!icon.isNull())
2184 return icon;
2185 }
2186
2187 return QCommonStyle::standardIcon(standardPixmap, option, widget);
2188}