1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <QtGraphics_Controls.hxx>
22 #include <QtGui/QPainter>
23 #include <QtWidgets/QApplication>
24 #include <QtWidgets/QFrame>
25 #include <QtWidgets/QLabel>
26 #include <QtWidgets/QLineEdit>
28 #include <QtInstance.hxx>
29 #include <QtTools.hxx>
30 #include <QtGraphicsBase.hxx>
31 #include <vcl/decoview.hxx>
34 Conversion function between VCL ControlState together with
35 ImplControlValue and Qt state flags.
36 @param nControlState State of the widget (default, focused, ...) in Native Widget Framework.
37 @param aValue Value held by the widget (on, off, ...)
39 static QStyle::State
vclStateValue2StateFlag(ControlState nControlState
,
40 const ImplControlValue
& aValue
)
43 = ((nControlState
& ControlState::ENABLED
) ? QStyle::State_Enabled
: QStyle::State_None
)
44 | ((nControlState
& ControlState::FOCUSED
)
45 ? QStyle::State_HasFocus
| QStyle::State_KeyboardFocusChange
47 | ((nControlState
& ControlState::PRESSED
) ? QStyle::State_Sunken
: QStyle::State_None
)
48 | ((nControlState
& ControlState::SELECTED
) ? QStyle::State_Selected
: QStyle::State_None
)
49 | ((nControlState
& ControlState::ROLLOVER
) ? QStyle::State_MouseOver
50 : QStyle::State_None
);
52 switch (aValue
.getTristateVal())
55 nState
|= QStyle::State_On
;
57 case ButtonValue::Off
:
58 nState
|= QStyle::State_Off
;
60 case ButtonValue::Mixed
:
61 nState
|= QStyle::State_NoChange
;
70 static void lcl_ApplyBackgroundColorToStyleOption(QStyleOption
& rOption
,
71 const Color
& rBackgroundColor
)
73 if (rBackgroundColor
!= COL_AUTO
)
75 QColor aColor
= toQColor(rBackgroundColor
);
76 for (QPalette::ColorRole role
: { QPalette::Window
, QPalette::Button
, QPalette::Base
})
77 rOption
.palette
.setColor(role
, aColor
);
81 QtGraphics_Controls::QtGraphics_Controls(const QtGraphicsBase
& rGraphics
)
82 : m_rGraphics(rGraphics
)
86 bool QtGraphics_Controls::isNativeControlSupported(ControlType type
, ControlPart part
)
90 case ControlType::Tooltip
:
91 case ControlType::Progress
:
92 case ControlType::ListNode
:
93 return (part
== ControlPart::Entire
);
95 case ControlType::Pushbutton
:
96 case ControlType::Radiobutton
:
97 case ControlType::Checkbox
:
98 return (part
== ControlPart::Entire
) || (part
== ControlPart::Focus
);
100 case ControlType::ListHeader
:
101 return (part
== ControlPart::Button
);
103 case ControlType::Menubar
:
104 case ControlType::MenuPopup
:
105 case ControlType::Editbox
:
106 case ControlType::MultilineEditbox
:
107 case ControlType::Combobox
:
108 case ControlType::Toolbar
:
109 case ControlType::Frame
:
110 case ControlType::Scrollbar
:
111 case ControlType::WindowBackground
:
112 case ControlType::Fixedline
:
115 case ControlType::Listbox
:
116 return (part
== ControlPart::Entire
|| part
== ControlPart::HasBackgroundTexture
);
118 case ControlType::Spinbox
:
119 return (part
== ControlPart::Entire
|| part
== ControlPart::HasBackgroundTexture
);
121 case ControlType::Slider
:
122 return (part
== ControlPart::TrackHorzArea
|| part
== ControlPart::TrackVertArea
);
124 case ControlType::TabItem
:
125 case ControlType::TabPane
:
126 return ((part
== ControlPart::Entire
) || part
== ControlPart::TabPaneWithHeader
);
135 inline int QtGraphics_Controls::pixelMetric(QStyle::PixelMetric metric
, const QStyleOption
* option
,
136 const QWidget
* pWidget
)
138 return QApplication::style()->pixelMetric(metric
, option
, pWidget
);
141 inline QSize
QtGraphics_Controls::sizeFromContents(QStyle::ContentsType type
,
142 const QStyleOption
* option
,
143 const QSize
& contentsSize
)
145 return QApplication::style()->sizeFromContents(type
, option
, contentsSize
);
148 inline QRect
QtGraphics_Controls::subControlRect(QStyle::ComplexControl control
,
149 const QStyleOptionComplex
* option
,
150 QStyle::SubControl subControl
)
152 return QApplication::style()->subControlRect(control
, option
, subControl
);
155 inline QRect
QtGraphics_Controls::subElementRect(QStyle::SubElement element
,
156 const QStyleOption
* option
)
158 return QApplication::style()->subElementRect(element
, option
);
161 void QtGraphics_Controls::draw(QStyle::ControlElement element
, QStyleOption
& rOption
, QImage
* image
,
162 const Color
& rBackgroundColor
, QStyle::State
const state
, QRect rect
)
164 const QRect targetRect
= !rect
.isNull() ? rect
: image
->rect();
166 rOption
.state
|= state
;
167 rOption
.rect
= downscale(targetRect
);
169 lcl_ApplyBackgroundColorToStyleOption(rOption
, rBackgroundColor
);
171 QPainter
painter(image
);
172 QApplication::style()->drawControl(element
, &rOption
, &painter
);
175 void QtGraphics_Controls::draw(QStyle::PrimitiveElement element
, QStyleOption
& rOption
,
176 QImage
* image
, const Color
& rBackgroundColor
,
177 QStyle::State
const state
, QRect rect
)
179 const QRect targetRect
= !rect
.isNull() ? rect
: image
->rect();
181 rOption
.state
|= state
;
182 rOption
.rect
= downscale(targetRect
);
184 lcl_ApplyBackgroundColorToStyleOption(rOption
, rBackgroundColor
);
186 QPainter
painter(image
);
187 QApplication::style()->drawPrimitive(element
, &rOption
, &painter
);
190 void QtGraphics_Controls::draw(QStyle::ComplexControl element
, QStyleOptionComplex
& rOption
,
191 QImage
* image
, const Color
& rBackgroundColor
,
192 QStyle::State
const state
)
194 const QRect targetRect
= image
->rect();
196 rOption
.state
|= state
;
197 rOption
.rect
= downscale(targetRect
);
199 lcl_ApplyBackgroundColorToStyleOption(rOption
, rBackgroundColor
);
201 QPainter
painter(image
);
202 QApplication::style()->drawComplexControl(element
, &rOption
, &painter
);
205 void QtGraphics_Controls::drawFrame(QStyle::PrimitiveElement element
, QImage
* image
,
206 const Color
& rBackgroundColor
, QStyle::State
const& state
,
207 bool bClip
, QStyle::PixelMetric eLineMetric
)
209 const int fw
= pixelMetric(eLineMetric
);
210 QStyleOptionFrame option
;
211 option
.frameShape
= QFrame::StyledPanel
;
212 option
.state
= QStyle::State_Sunken
| state
;
213 option
.lineWidth
= fw
;
215 QRect aRect
= downscale(image
->rect());
218 lcl_ApplyBackgroundColorToStyleOption(option
, rBackgroundColor
);
220 QPainter
painter(image
);
222 painter
.setClipRegion(QRegion(aRect
).subtracted(aRect
.adjusted(fw
, fw
, -fw
, -fw
)));
223 QApplication::style()->drawPrimitive(element
, &option
, &painter
);
226 static QTabBar::Shape
lcl_mapTabBarPosition(TabBarPosition eTabPos
)
230 case TabBarPosition::Bottom
:
231 return QTabBar::RoundedSouth
;
232 case TabBarPosition::Left
:
233 return QTabBar::RoundedWest
;
234 case TabBarPosition::Right
:
235 return QTabBar::RoundedEast
;
236 case TabBarPosition::Top
:
237 return QTabBar::RoundedNorth
;
239 assert(false && "Unhandled tab bar position");
240 return QTabBar::RoundedNorth
;
244 void QtGraphics_Controls::fillQStyleOptionTab(const ImplControlValue
& value
, QStyleOptionTab
& sot
)
246 const TabitemValue
& rValue
= static_cast<const TabitemValue
&>(value
);
247 if (rValue
.isFirst())
248 sot
.position
= rValue
.isLast() ? QStyleOptionTab::OnlyOneTab
: QStyleOptionTab::Beginning
;
249 else if (rValue
.isLast())
250 sot
.position
= rValue
.isFirst() ? QStyleOptionTab::OnlyOneTab
: QStyleOptionTab::End
;
252 sot
.position
= QStyleOptionTab::Middle
;
254 sot
.shape
= lcl_mapTabBarPosition(rValue
.meTabBarPosition
);
257 void QtGraphics_Controls::fullQStyleOptionTabWidgetFrame(QStyleOptionTabWidgetFrame
& option
,
260 option
.state
= QStyle::State_Enabled
;
261 option
.rightCornerWidgetSize
= QSize(0, 0);
262 option
.leftCornerWidgetSize
= QSize(0, 0);
263 int nLineWidth
= pixelMetric(QStyle::PM_DefaultFrameWidth
);
264 option
.lineWidth
= bDownscale
? std::max(1, downscale(nLineWidth
, Round::Ceil
)) : nLineWidth
;
265 option
.midLineWidth
= 0;
266 option
.shape
= QTabBar::RoundedNorth
;
269 bool QtGraphics_Controls::drawNativeControl(ControlType type
, ControlPart part
,
270 const tools::Rectangle
& rControlRegion
,
271 ControlState nControlState
,
272 const ImplControlValue
& value
, const OUString
&,
273 const Color
& rBackgroundColor
)
275 bool nativeSupport
= isNativeControlSupported(type
, part
);
278 assert(!nativeSupport
&& "drawNativeControl called without native support!");
282 if (m_lastPopupRect
.isValid()
283 && (type
!= ControlType::MenuPopup
|| part
!= ControlPart::MenuItem
))
284 m_lastPopupRect
= QRect();
286 bool returnVal
= true;
288 QRect widgetRect
= toQRect(rControlRegion
);
290 //if no image, or resized, make a new image
291 if (!m_image
|| m_image
->size() != widgetRect
.size())
293 m_image
.reset(new QImage(widgetRect
.width(), widgetRect
.height(),
294 QImage::Format_ARGB32_Premultiplied
));
295 m_image
->setDevicePixelRatio(m_rGraphics
.devicePixelRatioF());
298 // Default image color - just once
301 case ControlType::MenuPopup
:
302 if (part
== ControlPart::MenuItemCheckMark
|| part
== ControlPart::MenuItemRadioMark
)
304 // it is necessary to fill the background transparently first, as this
305 // is painted after menuitem highlight, otherwise there would be a grey area
306 m_image
->fill(Qt::transparent
);
309 [[fallthrough
]]; // QPalette::Window
310 case ControlType::Menubar
:
311 case ControlType::WindowBackground
:
312 m_image
->fill(QApplication::palette().color(QPalette::Window
).rgb());
314 case ControlType::Tooltip
:
315 m_image
->fill(QApplication::palette().color(QPalette::ToolTipBase
).rgb());
317 case ControlType::Scrollbar
:
318 if ((part
== ControlPart::DrawBackgroundVert
)
319 || (part
== ControlPart::DrawBackgroundHorz
))
321 m_image
->fill(QApplication::palette().color(QPalette::Window
).rgb());
324 [[fallthrough
]]; // Qt::transparent
326 m_image
->fill(Qt::transparent
);
330 if (type
== ControlType::Pushbutton
)
332 const PushButtonValue
& rPBValue
= static_cast<const PushButtonValue
&>(value
);
333 if (part
== ControlPart::Focus
)
334 // Nothing to do. Drawing focus separately is not needed because that's
335 // already handled by the ControlState::FOCUSED state being set when
336 // drawing the entire control
338 assert(part
== ControlPart::Entire
);
339 QStyleOptionButton option
;
340 if (nControlState
& ControlState::DEFAULT
)
341 option
.features
|= QStyleOptionButton::DefaultButton
;
342 if (rPBValue
.m_bFlatButton
)
343 option
.features
|= QStyleOptionButton::Flat
;
344 draw(QStyle::CE_PushButton
, option
, m_image
.get(), rBackgroundColor
,
345 vclStateValue2StateFlag(nControlState
, value
));
347 else if (type
== ControlType::Menubar
)
349 if (part
== ControlPart::MenuItem
)
351 QStyleOptionMenuItem option
;
352 option
.state
= vclStateValue2StateFlag(nControlState
, value
);
353 if ((nControlState
& ControlState::ROLLOVER
)
354 && QApplication::style()->styleHint(QStyle::SH_MenuBar_MouseTracking
))
355 option
.state
|= QStyle::State_Selected
;
358 & ControlState::SELECTED
) // Passing State_Sunken is currently not documented.
359 option
.state
|= QStyle::State_Sunken
; // But some kinds of QStyle interpret it.
361 draw(QStyle::CE_MenuBarItem
, option
, m_image
.get(), rBackgroundColor
);
363 else if (part
== ControlPart::Entire
)
365 QStyleOptionMenuItem option
;
366 draw(QStyle::CE_MenuBarEmptyArea
, option
, m_image
.get(), rBackgroundColor
,
367 vclStateValue2StateFlag(nControlState
, value
));
374 else if (type
== ControlType::MenuPopup
)
376 assert(part
== ControlPart::MenuItem
? m_lastPopupRect
.isValid()
377 : !m_lastPopupRect
.isValid());
378 if (part
== ControlPart::MenuItem
)
380 QStyleOptionMenuItem option
;
381 draw(QStyle::CE_MenuItem
, option
, m_image
.get(), rBackgroundColor
,
382 vclStateValue2StateFlag(nControlState
, value
));
383 // HACK: LO core first paints the entire popup and only then it paints menu items,
384 // but QMenu::paintEvent() paints popup frame after all items. That means highlighted
385 // items here would paint the highlight over the frame border. Since calls to ControlPart::MenuItem
386 // are always preceded by calls to ControlPart::Entire, just remember the size for the whole
387 // popup (otherwise not possible to get here) and draw the border afterwards.
388 QRect
framerect(m_lastPopupRect
.topLeft() - widgetRect
.topLeft(),
389 widgetRect
.size().expandedTo(m_lastPopupRect
.size()));
390 QStyleOptionFrame frame
;
391 draw(QStyle::PE_FrameMenu
, frame
, m_image
.get(), rBackgroundColor
,
392 vclStateValue2StateFlag(nControlState
, value
), framerect
);
394 else if (part
== ControlPart::Separator
)
396 QStyleOptionMenuItem option
;
397 option
.menuItemType
= QStyleOptionMenuItem::Separator
;
398 // Painting the whole menu item area results in different background
399 // with at least Plastique style, so clip only to the separator itself
400 // (QSize( 2, 2 ) is hardcoded in Qt)
401 option
.rect
= m_image
->rect();
402 QSize size
= sizeFromContents(QStyle::CT_MenuItem
, &option
, QSize(2, 2));
403 QRect rect
= m_image
->rect();
404 QPoint center
= rect
.center();
405 rect
.setHeight(size
.height());
406 rect
.moveCenter(center
);
407 option
.state
|= vclStateValue2StateFlag(nControlState
, value
);
410 QPainter
painter(m_image
.get());
411 // don't paint over popup frame border (like the hack above, but here it can be simpler)
412 const int fw
= pixelMetric(QStyle::PM_MenuPanelWidth
);
413 painter
.setClipRect(rect
.adjusted(fw
, 0, -fw
, 0));
414 QApplication::style()->drawControl(QStyle::CE_MenuItem
, &option
, &painter
);
416 else if (part
== ControlPart::MenuItemCheckMark
|| part
== ControlPart::MenuItemRadioMark
)
418 QStyleOptionMenuItem option
;
419 option
.checkType
= (part
== ControlPart::MenuItemCheckMark
)
420 ? QStyleOptionMenuItem::NonExclusive
421 : QStyleOptionMenuItem::Exclusive
;
422 option
.checked
= bool(nControlState
& ControlState::PRESSED
);
423 // widgetRect is now the rectangle for the checkbox/radiobutton itself, but Qt
424 // paints the whole menu item, so translate position (and it'll be clipped);
425 // it is also necessary to fill the background transparently first, as this
426 // is painted after menuitem highlight, otherwise there would be a grey area
427 assert(value
.getType() == ControlType::MenuPopup
);
428 const MenupopupValue
* menuVal
= static_cast<const MenupopupValue
*>(&value
);
429 QRect
menuItemRect(toQRect(menuVal
->maItemRect
));
430 QRect
rect(menuItemRect
.topLeft() - widgetRect
.topLeft(),
431 widgetRect
.size().expandedTo(menuItemRect
.size()));
432 // checkboxes are always displayed next to images in menus, so are never centered
433 const int focus_size
= pixelMetric(QStyle::PM_FocusFrameHMargin
);
434 rect
.moveTo(-focus_size
, rect
.y());
435 draw(QStyle::CE_MenuItem
, option
, m_image
.get(), rBackgroundColor
,
436 vclStateValue2StateFlag(nControlState
& ~ControlState::PRESSED
, value
), rect
);
438 else if (part
== ControlPart::Entire
)
440 QStyleOptionMenuItem option
;
441 option
.state
= vclStateValue2StateFlag(nControlState
, value
);
442 draw(QStyle::PE_PanelMenu
, option
, m_image
.get(), rBackgroundColor
);
443 // Try hard to get any frame!
444 QStyleOptionFrame frame
;
445 draw(QStyle::PE_FrameMenu
, frame
, m_image
.get(), rBackgroundColor
);
446 draw(QStyle::PE_FrameWindow
, frame
, m_image
.get(), rBackgroundColor
);
447 m_lastPopupRect
= widgetRect
;
452 else if ((type
== ControlType::Toolbar
) && (part
== ControlPart::Button
))
454 QStyleOptionToolButton option
;
456 option
.arrowType
= Qt::NoArrow
;
457 option
.subControls
= QStyle::SC_ToolButton
;
458 option
.state
= vclStateValue2StateFlag(nControlState
, value
);
459 option
.state
|= QStyle::State_Raised
| QStyle::State_Enabled
| QStyle::State_AutoRaise
;
461 draw(QStyle::CC_ToolButton
, option
, m_image
.get(), rBackgroundColor
);
463 else if ((type
== ControlType::Toolbar
) && (part
== ControlPart::Entire
))
465 QStyleOptionToolBar option
;
466 draw(QStyle::CE_ToolBar
, option
, m_image
.get(), rBackgroundColor
,
467 vclStateValue2StateFlag(nControlState
, value
));
469 else if ((type
== ControlType::Toolbar
)
470 && (part
== ControlPart::ThumbVert
|| part
== ControlPart::ThumbHorz
))
472 // reduce paint area only to the handle area
473 const int handleExtend
= pixelMetric(QStyle::PM_ToolBarHandleExtent
);
475 QRect aRect
= m_image
->rect();
476 if (part
== ControlPart::ThumbVert
)
478 aRect
.setWidth(handleExtend
);
479 option
.state
= QStyle::State_Horizontal
;
482 aRect
.setHeight(handleExtend
);
483 draw(QStyle::PE_IndicatorToolBarHandle
, option
, m_image
.get(), rBackgroundColor
,
484 vclStateValue2StateFlag(nControlState
, value
), aRect
);
486 else if (type
== ControlType::Editbox
|| type
== ControlType::MultilineEditbox
)
488 drawFrame(QStyle::PE_FrameLineEdit
, m_image
.get(), rBackgroundColor
,
489 vclStateValue2StateFlag(nControlState
, value
), false);
491 else if (type
== ControlType::Combobox
)
493 QStyleOptionComboBox option
;
494 option
.editable
= true;
495 draw(QStyle::CC_ComboBox
, option
, m_image
.get(), rBackgroundColor
,
496 vclStateValue2StateFlag(nControlState
, value
));
498 else if (type
== ControlType::Listbox
)
500 QStyleOptionComboBox option
;
501 option
.editable
= false;
504 case ControlPart::ListboxWindow
:
505 drawFrame(QStyle::PE_Frame
, m_image
.get(), rBackgroundColor
,
506 vclStateValue2StateFlag(nControlState
, value
), true,
507 QStyle::PM_ComboBoxFrameWidth
);
509 case ControlPart::SubEdit
:
510 draw(QStyle::CE_ComboBoxLabel
, option
, m_image
.get(), rBackgroundColor
,
511 vclStateValue2StateFlag(nControlState
, value
));
513 case ControlPart::Entire
:
514 draw(QStyle::CC_ComboBox
, option
, m_image
.get(), rBackgroundColor
,
515 vclStateValue2StateFlag(nControlState
, value
));
517 case ControlPart::ButtonDown
:
518 option
.subControls
= QStyle::SC_ComboBoxArrow
;
519 draw(QStyle::CC_ComboBox
, option
, m_image
.get(), rBackgroundColor
,
520 vclStateValue2StateFlag(nControlState
, value
));
527 else if (type
== ControlType::ListNode
)
530 option
.state
= vclStateValue2StateFlag(nControlState
, value
);
531 option
.state
|= QStyle::State_Item
| QStyle::State_Children
;
533 if (value
.getTristateVal() == ButtonValue::On
)
534 option
.state
|= QStyle::State_Open
;
536 draw(QStyle::PE_IndicatorBranch
, option
, m_image
.get(), rBackgroundColor
);
538 else if (type
== ControlType::ListHeader
)
540 QStyleOptionHeader option
;
541 draw(QStyle::CE_HeaderSection
, option
, m_image
.get(), rBackgroundColor
,
542 vclStateValue2StateFlag(nControlState
, value
));
544 else if (type
== ControlType::Checkbox
)
546 if (part
== ControlPart::Entire
)
548 QStyleOptionButton option
;
549 // clear FOCUSED bit, focus is drawn separately
550 nControlState
&= ~ControlState::FOCUSED
;
551 draw(QStyle::CE_CheckBox
, option
, m_image
.get(), rBackgroundColor
,
552 vclStateValue2StateFlag(nControlState
, value
));
554 else if (part
== ControlPart::Focus
)
556 QStyleOptionFocusRect option
;
557 draw(QStyle::PE_FrameFocusRect
, option
, m_image
.get(), rBackgroundColor
,
558 vclStateValue2StateFlag(nControlState
, value
));
561 else if (type
== ControlType::Scrollbar
)
563 if ((part
== ControlPart::DrawBackgroundVert
) || (part
== ControlPart::DrawBackgroundHorz
))
565 QStyleOptionSlider option
;
566 assert(value
.getType() == ControlType::Scrollbar
);
567 const ScrollbarValue
* sbVal
= static_cast<const ScrollbarValue
*>(&value
);
569 //if the scroll bar is active (aka not degenerate... allow for hover events)
570 if (sbVal
->mnVisibleSize
< sbVal
->mnMax
)
571 option
.state
= QStyle::State_MouseOver
;
573 bool horizontal
= (part
== ControlPart::DrawBackgroundHorz
); //horizontal or vertical
574 option
.orientation
= horizontal
? Qt::Horizontal
: Qt::Vertical
;
576 option
.state
|= QStyle::State_Horizontal
;
578 // If the scrollbar has a mnMin == 0 and mnMax == 0 then mnVisibleSize is set to -1?!
579 // I don't know if a negative mnVisibleSize makes any sense, so just handle this case
580 // without crashing LO with a SIGFPE in the Qt library.
581 const tools::Long nVisibleSize
582 = (sbVal
->mnMin
== sbVal
->mnMax
) ? 0 : sbVal
->mnVisibleSize
;
584 option
.minimum
= sbVal
->mnMin
;
585 option
.maximum
= sbVal
->mnMax
- nVisibleSize
;
586 option
.maximum
= qMax(option
.maximum
, option
.minimum
); // bnc#619772
587 option
.sliderValue
= sbVal
->mnCur
;
588 option
.sliderPosition
= sbVal
->mnCur
;
589 option
.pageStep
= nVisibleSize
;
590 if (part
== ControlPart::DrawBackgroundHorz
)
592 = (QGuiApplication::isRightToLeft()
593 && sbVal
->maButton1Rect
.Left() < sbVal
->maButton2Rect
.Left())
594 || (QGuiApplication::isLeftToRight()
595 && sbVal
->maButton1Rect
.Left() > sbVal
->maButton2Rect
.Left());
597 //setup the active control... always the slider
598 if (sbVal
->mnThumbState
& ControlState::ROLLOVER
)
599 option
.activeSubControls
= QStyle::SC_ScrollBarSlider
;
601 draw(QStyle::CC_ScrollBar
, option
, m_image
.get(), rBackgroundColor
,
602 vclStateValue2StateFlag(nControlState
, value
));
609 else if (type
== ControlType::Spinbox
)
611 QStyleOptionSpinBox option
;
614 // determine active control
615 if (value
.getType() == ControlType::SpinButtons
)
617 const SpinbuttonValue
* pSpinVal
= static_cast<const SpinbuttonValue
*>(&value
);
618 if (pSpinVal
->mnUpperState
& ControlState::PRESSED
)
619 option
.activeSubControls
|= QStyle::SC_SpinBoxUp
;
620 if (pSpinVal
->mnLowerState
& ControlState::PRESSED
)
621 option
.activeSubControls
|= QStyle::SC_SpinBoxDown
;
622 if (pSpinVal
->mnUpperState
& ControlState::ENABLED
)
623 option
.stepEnabled
|= QAbstractSpinBox::StepUpEnabled
;
624 if (pSpinVal
->mnLowerState
& ControlState::ENABLED
)
625 option
.stepEnabled
|= QAbstractSpinBox::StepDownEnabled
;
626 if (pSpinVal
->mnUpperState
& ControlState::ROLLOVER
)
627 option
.state
= QStyle::State_MouseOver
;
628 if (pSpinVal
->mnLowerState
& ControlState::ROLLOVER
)
629 option
.state
= QStyle::State_MouseOver
;
632 draw(QStyle::CC_SpinBox
, option
, m_image
.get(), rBackgroundColor
,
633 vclStateValue2StateFlag(nControlState
, value
));
635 else if (type
== ControlType::Radiobutton
)
637 if (part
== ControlPart::Entire
)
639 QStyleOptionButton option
;
640 // clear FOCUSED bit, focus is drawn separately
641 nControlState
&= ~ControlState::FOCUSED
;
642 draw(QStyle::CE_RadioButton
, option
, m_image
.get(), rBackgroundColor
,
643 vclStateValue2StateFlag(nControlState
, value
));
645 else if (part
== ControlPart::Focus
)
647 QStyleOptionFocusRect option
;
648 draw(QStyle::PE_FrameFocusRect
, option
, m_image
.get(), rBackgroundColor
,
649 vclStateValue2StateFlag(nControlState
, value
));
652 else if (type
== ControlType::Tooltip
)
655 draw(QStyle::PE_PanelTipLabel
, option
, m_image
.get(), rBackgroundColor
,
656 vclStateValue2StateFlag(nControlState
, value
));
658 else if (type
== ControlType::Frame
)
660 drawFrame(QStyle::PE_Frame
, m_image
.get(), rBackgroundColor
,
661 vclStateValue2StateFlag(nControlState
, value
));
663 else if (type
== ControlType::WindowBackground
)
665 // Nothing to do - see "Default image color" switch ^^
667 else if (type
== ControlType::Fixedline
)
669 QStyleOptionMenuItem option
;
670 option
.menuItemType
= QStyleOptionMenuItem::Separator
;
671 option
.state
= vclStateValue2StateFlag(nControlState
, value
);
672 option
.state
|= QStyle::State_Item
;
674 draw(QStyle::CE_MenuItem
, option
, m_image
.get(), rBackgroundColor
);
676 else if (type
== ControlType::Slider
677 && (part
== ControlPart::TrackHorzArea
|| part
== ControlPart::TrackVertArea
))
679 assert(value
.getType() == ControlType::Slider
);
680 const SliderValue
* slVal
= static_cast<const SliderValue
*>(&value
);
681 QStyleOptionSlider option
;
683 option
.state
= vclStateValue2StateFlag(nControlState
, value
);
684 option
.maximum
= slVal
->mnMax
;
685 option
.minimum
= slVal
->mnMin
;
686 option
.sliderPosition
= option
.sliderValue
= slVal
->mnCur
;
687 bool horizontal
= (part
== ControlPart::TrackHorzArea
); //horizontal or vertical
688 option
.orientation
= horizontal
? Qt::Horizontal
: Qt::Vertical
;
690 option
.state
|= QStyle::State_Horizontal
;
692 draw(QStyle::CC_Slider
, option
, m_image
.get(), rBackgroundColor
);
694 else if (type
== ControlType::Progress
&& part
== ControlPart::Entire
)
696 QStyleOptionProgressBar option
;
698 option
.maximum
= widgetRect
.width();
699 option
.progress
= value
.getNumericVal();
701 draw(QStyle::CE_ProgressBar
, option
, m_image
.get(), rBackgroundColor
,
702 vclStateValue2StateFlag(nControlState
, value
));
704 else if (type
== ControlType::TabItem
&& part
== ControlPart::Entire
)
707 fillQStyleOptionTab(value
, sot
);
708 draw(QStyle::CE_TabBarTabShape
, sot
, m_image
.get(), rBackgroundColor
,
709 vclStateValue2StateFlag(nControlState
, value
));
711 else if (type
== ControlType::TabPane
&& part
== ControlPart::Entire
)
713 const TabPaneValue
& rValue
= static_cast<const TabPaneValue
&>(value
);
715 // get the overlap size for the tabs, so they will overlap the frame
716 QStyleOptionTab tabOverlap
;
717 tabOverlap
.shape
= QTabBar::RoundedNorth
;
718 TabPaneValue::m_nOverlap
= pixelMetric(QStyle::PM_TabBarBaseOverlap
, &tabOverlap
);
720 QStyleOptionTabWidgetFrame option
;
721 fullQStyleOptionTabWidgetFrame(option
, false);
722 option
.tabBarRect
= toQRect(rValue
.m_aTabHeaderRect
);
723 option
.selectedTabRect
724 = rValue
.m_aSelectedTabRect
.IsEmpty() ? QRect() : toQRect(rValue
.m_aSelectedTabRect
);
725 option
.tabBarSize
= toQSize(rValue
.m_aTabHeaderRect
.GetSize());
726 option
.rect
= m_image
->rect();
727 QRect aRect
= subElementRect(QStyle::SE_TabWidgetTabPane
, &option
);
728 draw(QStyle::PE_FrameTabWidget
, option
, m_image
.get(), rBackgroundColor
,
729 vclStateValue2StateFlag(nControlState
, value
), aRect
);
739 bool QtGraphics_Controls::getNativeControlRegion(
740 ControlType type
, ControlPart part
, const tools::Rectangle
& controlRegion
,
741 ControlState controlState
, const ImplControlValue
& val
, const OUString
& rCaption
,
742 tools::Rectangle
& nativeBoundingRegion
, tools::Rectangle
& nativeContentRegion
)
744 QtInstance
& rQtInstance
= GetQtInstance();
745 if (!rQtInstance
.IsMainThread())
748 rQtInstance
.RunInMainThread([&]() {
749 bRet
= getNativeControlRegion(type
, part
, controlRegion
, controlState
, val
, rCaption
,
750 nativeBoundingRegion
, nativeContentRegion
);
757 QRect boundingRect
= toQRect(controlRegion
);
758 QRect contentRect
= boundingRect
;
759 QStyleOptionComplex styleOption
;
763 // Metrics of the push button
764 case ControlType::Pushbutton
:
765 if (part
== ControlPart::Entire
)
767 styleOption
.state
= vclStateValue2StateFlag(controlState
, val
);
769 if (controlState
& ControlState::DEFAULT
)
771 int size
= upscale(pixelMetric(QStyle::PM_ButtonDefaultIndicator
, &styleOption
),
773 boundingRect
.adjust(-size
, -size
, size
, size
);
777 else if (part
== ControlPart::Focus
)
780 case ControlType::Editbox
:
781 case ControlType::MultilineEditbox
:
783 // we have to get stable borders, otherwise layout loops.
784 // so we simply only scale the detected borders.
785 QStyleOptionFrame fo
;
786 fo
.frameShape
= QFrame::StyledPanel
;
787 fo
.state
= QStyle::State_Sunken
;
788 fo
.lineWidth
= pixelMetric(QStyle::PM_DefaultFrameWidth
);
789 fo
.rect
= downscale(contentRect
);
790 fo
.rect
.setSize(sizeFromContents(QStyle::CT_LineEdit
, &fo
, fo
.rect
.size()));
791 QRect aSubRect
= subElementRect(QStyle::SE_LineEditContents
, &fo
);
793 // VCL tests borders with small defaults before layout, where Qt returns no sub-rect,
794 // so this gets us at least some frame.
795 int nLine
= upscale(fo
.lineWidth
, Round::Ceil
);
796 int nLeft
= qMin(-nLine
, upscale(fo
.rect
.left() - aSubRect
.left(), Round::Floor
));
797 int nTop
= qMin(-nLine
, upscale(fo
.rect
.top() - aSubRect
.top(), Round::Floor
));
798 int nRight
= qMax(nLine
, upscale(fo
.rect
.right() - aSubRect
.right(), Round::Ceil
));
799 int nBottom
= qMax(nLine
, upscale(fo
.rect
.bottom() - aSubRect
.bottom(), Round::Ceil
));
800 boundingRect
.adjust(nLeft
, nTop
, nRight
, nBottom
);
802 // tdf#150451: ensure a minimum size that fits text content + frame at top and bottom.
803 // Themes may use the widget type for determining the actual frame width to use,
804 // so pass a dummy QLineEdit
806 // NOTE: This is currently only done here for the minimum size calculation and
807 // not above because the handling for edit boxes here and in the calling code
808 // currently does all kinds of "interesting" things like doing extra size adjustments
809 // or passing the content rect where the bounding rect would be expected,...
810 // Ideally this should be cleaned up in the callers and all platform integrations
811 // to adhere to what the doc in vcl/inc/WidgetDrawInterface.hxx says, but this
812 // here keeps it working with existing code for now.
813 // (s.a. discussion in https://gerrit.libreoffice.org/c/core/+/146516 for more details)
814 QLineEdit aDummyEdit
;
815 const int nFrameWidth
= pixelMetric(QStyle::PM_DefaultFrameWidth
, nullptr, &aDummyEdit
);
816 QFontMetrics
aFontMetrics(QApplication::font());
817 const int minHeight
= upscale(aFontMetrics
.height() + 2 * nFrameWidth
, Round::Floor
);
818 if (boundingRect
.height() < minHeight
)
820 const int nDiff
= minHeight
- boundingRect
.height();
821 boundingRect
.setHeight(boundingRect
.height() + nDiff
);
822 contentRect
.setHeight(contentRect
.height() + nDiff
);
828 case ControlType::Checkbox
:
829 if (part
== ControlPart::Entire
)
831 styleOption
.state
= vclStateValue2StateFlag(controlState
, val
);
833 int nWidth
= pixelMetric(QStyle::PM_IndicatorWidth
, &styleOption
);
834 int nHeight
= pixelMetric(QStyle::PM_IndicatorHeight
, &styleOption
);
835 contentRect
.setSize(upscale(QSize(nWidth
, nHeight
), Round::Ceil
));
837 int nHMargin
= pixelMetric(QStyle::PM_FocusFrameHMargin
, &styleOption
);
838 int nVMargin
= pixelMetric(QStyle::PM_FocusFrameVMargin
, &styleOption
);
839 contentRect
.adjust(0, 0, 2 * upscale(nHMargin
, Round::Ceil
),
840 2 * upscale(nVMargin
, Round::Ceil
));
842 boundingRect
= contentRect
;
846 case ControlType::Combobox
:
847 case ControlType::Listbox
:
849 QStyleOptionComboBox cbo
;
851 cbo
.rect
= downscale(QRect(0, 0, contentRect
.width(), contentRect
.height()));
852 cbo
.state
= vclStateValue2StateFlag(controlState
, val
);
856 case ControlPart::Entire
:
858 // find out the minimum size that should be used
859 // assume contents is a text line
860 QSize aContentSize
= downscale(contentRect
.size(), Round::Ceil
);
861 QFontMetrics
aFontMetrics(QApplication::font());
862 aContentSize
.setHeight(aFontMetrics
.height());
863 QSize aMinSize
= upscale(
864 sizeFromContents(QStyle::CT_ComboBox
, &cbo
, aContentSize
), Round::Ceil
);
865 if (aMinSize
.height() > contentRect
.height())
866 contentRect
.setHeight(aMinSize
.height());
867 boundingRect
= contentRect
;
871 case ControlPart::ButtonDown
:
873 contentRect
= upscale(
874 subControlRect(QStyle::CC_ComboBox
, &cbo
, QStyle::SC_ComboBoxArrow
));
875 contentRect
.translate(boundingRect
.left(), boundingRect
.top());
879 case ControlPart::SubEdit
:
881 contentRect
= upscale(
882 subControlRect(QStyle::CC_ComboBox
, &cbo
, QStyle::SC_ComboBoxEditField
));
883 contentRect
.translate(boundingRect
.left(), boundingRect
.top());
892 case ControlType::Spinbox
:
894 QStyleOptionSpinBox sbo
;
897 sbo
.rect
= downscale(QRect(0, 0, contentRect
.width(), contentRect
.height()));
898 sbo
.state
= vclStateValue2StateFlag(controlState
, val
);
902 case ControlPart::Entire
:
904 QSize aContentSize
= downscale(contentRect
.size(), Round::Ceil
);
905 QFontMetrics
aFontMetrics(QApplication::font());
906 aContentSize
.setHeight(aFontMetrics
.height());
907 QSize aMinSize
= upscale(
908 sizeFromContents(QStyle::CT_SpinBox
, &sbo
, aContentSize
), Round::Ceil
);
909 if (aMinSize
.height() > contentRect
.height())
910 contentRect
.setHeight(aMinSize
.height());
911 boundingRect
= contentRect
;
915 case ControlPart::ButtonUp
:
917 = upscale(subControlRect(QStyle::CC_SpinBox
, &sbo
, QStyle::SC_SpinBoxUp
));
918 contentRect
.translate(boundingRect
.left(), boundingRect
.top());
921 case ControlPart::ButtonDown
:
923 = upscale(subControlRect(QStyle::CC_SpinBox
, &sbo
, QStyle::SC_SpinBoxDown
));
924 contentRect
.translate(boundingRect
.left(), boundingRect
.top());
927 case ControlPart::SubEdit
:
928 contentRect
= upscale(
929 subControlRect(QStyle::CC_SpinBox
, &sbo
, QStyle::SC_SpinBoxEditField
));
930 contentRect
.translate(boundingRect
.left(), boundingRect
.top());
938 case ControlType::MenuPopup
:
943 case ControlPart::MenuItemCheckMark
:
944 h
= upscale(pixelMetric(QStyle::PM_IndicatorHeight
), Round::Floor
);
945 w
= upscale(pixelMetric(QStyle::PM_IndicatorWidth
), Round::Floor
);
948 case ControlPart::MenuItemRadioMark
:
949 h
= upscale(pixelMetric(QStyle::PM_ExclusiveIndicatorHeight
), Round::Floor
);
950 w
= upscale(pixelMetric(QStyle::PM_ExclusiveIndicatorWidth
), Round::Floor
);
958 contentRect
= QRect(0, 0, w
, h
);
959 boundingRect
= contentRect
;
963 case ControlType::Frame
:
965 if (part
== ControlPart::Border
)
967 int nFrameWidth
= upscale(pixelMetric(QStyle::PM_DefaultFrameWidth
), Round::Ceil
);
968 contentRect
.adjust(nFrameWidth
, nFrameWidth
, -nFrameWidth
, -nFrameWidth
);
973 case ControlType::Radiobutton
:
975 const int h
= upscale(pixelMetric(QStyle::PM_ExclusiveIndicatorHeight
), Round::Ceil
);
976 const int w
= upscale(pixelMetric(QStyle::PM_ExclusiveIndicatorWidth
), Round::Ceil
);
978 contentRect
= QRect(boundingRect
.left(), boundingRect
.top(), w
, h
);
979 int nHMargin
= pixelMetric(QStyle::PM_FocusFrameHMargin
, &styleOption
);
980 int nVMargin
= pixelMetric(QStyle::PM_FocusFrameVMargin
, &styleOption
);
981 contentRect
.adjust(0, 0, upscale(2 * nHMargin
, Round::Ceil
),
982 upscale(2 * nVMargin
, Round::Ceil
));
983 boundingRect
= contentRect
;
988 case ControlType::Slider
:
990 const int w
= upscale(pixelMetric(QStyle::PM_SliderLength
), Round::Ceil
);
991 if (part
== ControlPart::ThumbHorz
)
994 = QRect(boundingRect
.left(), boundingRect
.top(), w
, boundingRect
.height());
995 boundingRect
= contentRect
;
998 else if (part
== ControlPart::ThumbVert
)
1001 = QRect(boundingRect
.left(), boundingRect
.top(), boundingRect
.width(), w
);
1002 boundingRect
= contentRect
;
1007 case ControlType::Toolbar
:
1009 const int nWorH
= upscale(pixelMetric(QStyle::PM_ToolBarHandleExtent
), Round::Ceil
);
1010 if (part
== ControlPart::ThumbHorz
)
1013 = QRect(boundingRect
.left(), boundingRect
.top(), boundingRect
.width(), nWorH
);
1014 boundingRect
= contentRect
;
1017 else if (part
== ControlPart::ThumbVert
)
1020 = QRect(boundingRect
.left(), boundingRect
.top(), nWorH
, boundingRect
.height());
1021 boundingRect
= contentRect
;
1024 else if (part
== ControlPart::Button
)
1026 QStyleOptionToolButton option
;
1027 option
.arrowType
= Qt::NoArrow
;
1028 option
.features
= QStyleOptionToolButton::None
;
1029 option
.rect
= downscale(QRect({ 0, 0 }, contentRect
.size()));
1030 contentRect
= upscale(
1031 subControlRect(QStyle::CC_ToolButton
, &option
, QStyle::SC_ToolButton
));
1032 boundingRect
= contentRect
;
1037 case ControlType::Scrollbar
:
1039 // core can't handle 3-button scrollbars well, so we fix that in hitTestNativeControl(),
1040 // for the rest also provide the track area (i.e. area not taken by buttons)
1041 if (part
== ControlPart::TrackVertArea
|| part
== ControlPart::TrackHorzArea
)
1043 QStyleOptionSlider option
;
1044 bool horizontal
= (part
== ControlPart::TrackHorzArea
); //horizontal or vertical
1045 option
.orientation
= horizontal
? Qt::Horizontal
: Qt::Vertical
;
1047 option
.state
|= QStyle::State_Horizontal
;
1048 // getNativeControlRegion usually gets ImplControlValue as 'val' (i.e. not the proper
1049 // subclass), so use random sensible values (doesn't matter anyway, as the wanted
1050 // geometry here depends only on button sizes)
1051 option
.maximum
= 10;
1053 option
.sliderPosition
= option
.sliderValue
= 4;
1054 option
.pageStep
= 2;
1055 // Adjust coordinates to make the widget appear to be at (0,0), i.e. make
1056 // widget and screen coordinates the same. QStyle functions should use screen
1057 // coordinates but at least QPlastiqueStyle::subControlRect() is buggy
1058 // and sometimes uses widget coordinates.
1059 option
.rect
= downscale(QRect({ 0, 0 }, contentRect
.size()));
1060 contentRect
= upscale(
1061 subControlRect(QStyle::CC_ScrollBar
, &option
, QStyle::SC_ScrollBarGroove
));
1062 contentRect
.translate(boundingRect
.left()
1063 - (contentRect
.width() - boundingRect
.width()),
1064 boundingRect
.top());
1065 boundingRect
= contentRect
;
1070 case ControlType::TabItem
:
1072 QStyleOptionTab sot
;
1073 fillQStyleOptionTab(val
, sot
);
1074 QSize aMinSize
= upscale(sizeFromContents(QStyle::CT_TabBarTab
, &sot
,
1075 downscale(contentRect
.size(), Round::Ceil
)),
1077 contentRect
.setSize(aMinSize
);
1078 boundingRect
= contentRect
;
1082 case ControlType::TabPane
:
1084 const TabPaneValue
& rValue
= static_cast<const TabPaneValue
&>(val
);
1085 QStyleOptionTabWidgetFrame sotwf
;
1086 fullQStyleOptionTabWidgetFrame(sotwf
, true);
1088 std::max(rValue
.m_aTabHeaderRect
.GetWidth(), controlRegion
.GetWidth()),
1089 rValue
.m_aTabHeaderRect
.GetHeight() + controlRegion
.GetHeight());
1090 QSize aMinSize
= upscale(
1091 sizeFromContents(QStyle::CT_TabWidget
, &sotwf
, downscale(contentSize
, Round::Ceil
)),
1093 contentRect
.setSize(aMinSize
);
1094 boundingRect
= contentRect
;
1103 nativeBoundingRegion
= toRectangle(boundingRect
);
1104 nativeContentRegion
= toRectangle(contentRect
);
1110 /** Test whether the position is in the native widget.
1111 If the return value is true, bIsInside contains information whether
1112 aPos was or was not inside the native widget specified by the
1113 nType/nPart combination.
1115 bool QtGraphics_Controls::hitTestNativeControl(ControlType nType
, ControlPart nPart
,
1116 const tools::Rectangle
& rControlRegion
,
1117 const Point
& rPos
, bool& rIsInside
)
1119 if (nType
== ControlType::Scrollbar
)
1121 if (nPart
!= ControlPart::ButtonUp
&& nPart
!= ControlPart::ButtonDown
1122 && nPart
!= ControlPart::ButtonLeft
&& nPart
!= ControlPart::ButtonRight
)
1123 { // we adjust only for buttons (because some scrollbars have 3 buttons,
1124 // and LO core doesn't handle such scrollbars well)
1128 bool bHorizontal
= (nPart
== ControlPart::ButtonLeft
|| nPart
== ControlPart::ButtonRight
);
1129 QRect rect
= toQRect(rControlRegion
);
1130 QPoint
pos(rPos
.X(), rPos
.Y());
1131 // Adjust coordinates to make the widget appear to be at (0,0), i.e. make
1132 // widget and screen coordinates the same. QStyle functions should use screen
1133 // coordinates but at least QPlastiqueStyle::subControlRect() is buggy
1134 // and sometimes uses widget coordinates.
1135 pos
-= rect
.topLeft();
1137 QStyleOptionSlider options
;
1138 options
.orientation
= bHorizontal
? Qt::Horizontal
: Qt::Vertical
;
1140 options
.state
|= QStyle::State_Horizontal
;
1141 options
.rect
= rect
;
1142 // some random sensible values, since we call this code only for scrollbar buttons,
1143 // the slider position does not exactly matter
1144 options
.maximum
= 10;
1145 options
.minimum
= 0;
1146 options
.sliderPosition
= options
.sliderValue
= 4;
1147 options
.pageStep
= 2;
1148 QStyle::SubControl control
1149 = QApplication::style()->hitTestComplexControl(QStyle::CC_ScrollBar
, &options
, pos
);
1150 if (nPart
== ControlPart::ButtonUp
|| nPart
== ControlPart::ButtonLeft
)
1151 rIsInside
= (control
== QStyle::SC_ScrollBarSubLine
);
1153 rIsInside
= (control
== QStyle::SC_ScrollBarAddLine
);
1159 inline int QtGraphics_Controls::downscale(int size
, Round eRound
)
1161 return static_cast<int>(eRound
== Round::Ceil
? ceil(size
/ m_rGraphics
.devicePixelRatioF())
1162 : floor(size
/ m_rGraphics
.devicePixelRatioF()));
1165 inline int QtGraphics_Controls::upscale(int size
, Round eRound
)
1167 return static_cast<int>(eRound
== Round::Ceil
? ceil(size
* m_rGraphics
.devicePixelRatioF())
1168 : floor(size
* m_rGraphics
.devicePixelRatioF()));
1171 inline QRect
QtGraphics_Controls::downscale(const QRect
& rect
)
1173 return QRect(downscale(rect
.x(), Round::Floor
), downscale(rect
.y(), Round::Floor
),
1174 downscale(rect
.width(), Round::Ceil
), downscale(rect
.height(), Round::Ceil
));
1177 inline QRect
QtGraphics_Controls::upscale(const QRect
& rect
)
1179 return QRect(upscale(rect
.x(), Round::Floor
), upscale(rect
.y(), Round::Floor
),
1180 upscale(rect
.width(), Round::Ceil
), upscale(rect
.height(), Round::Ceil
));
1183 inline QSize
QtGraphics_Controls::downscale(const QSize
& size
, Round eRound
)
1185 return QSize(downscale(size
.width(), eRound
), downscale(size
.height(), eRound
));
1188 inline QSize
QtGraphics_Controls::upscale(const QSize
& size
, Round eRound
)
1190 return QSize(upscale(size
.width(), eRound
), upscale(size
.height(), eRound
));
1193 inline QPoint
QtGraphics_Controls::upscale(const QPoint
& point
, Round eRound
)
1195 return QPoint(upscale(point
.x(), eRound
), upscale(point
.y(), eRound
));
1198 /* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */