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