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