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