VirtualBox

source: vbox/trunk/src/VBox/Frontends/VirtualBox/src/manager/chooser/UIChooserItemGlobal.cpp@ 103538

Last change on this file since 103538 was 102423, checked in by vboxsync, 6 months ago

FE/Qt: macOS: Adjust cocoa native colors for QIToolBar and Chooser pane global item.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 28.4 KB
Line 
1/* $Id: UIChooserItemGlobal.cpp 102423 2023-12-01 14:23:43Z vboxsync $ */
2/** @file
3 * VBox Qt GUI - UIChooserItemGlobal class implementation.
4 */
5
6/*
7 * Copyright (C) 2012-2023 Oracle and/or its affiliates.
8 *
9 * This file is part of VirtualBox base platform packages, as
10 * available from https://www.virtualbox.org.
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation, in version 3 of the
15 * License.
16 *
17 * This program is distributed in the hope that it will be useful, but
18 * WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 * General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, see <https://www.gnu.org/licenses>.
24 *
25 * SPDX-License-Identifier: GPL-3.0-only
26 */
27
28/* Qt includes: */
29#include <QGraphicsSceneMouseEvent>
30#include <QGraphicsView>
31#include <QPainter>
32#include <QStyleOptionGraphicsItem>
33#include <QWindow>
34
35/* GUI includes: */
36#include "UIChooserItemGlobal.h"
37#include "UIChooserModel.h"
38#include "UIChooserNodeGlobal.h"
39#include "UIIconPool.h"
40#include "UIImageTools.h"
41#include "UIVirtualBoxManager.h"
42
43
44UIChooserItemGlobal::UIChooserItemGlobal(UIChooserItem *pParent, UIChooserNodeGlobal *pNode)
45 : UIChooserItem(pParent, pNode)
46#ifdef VBOX_WS_MAC
47 , m_iDefaultColorDeviation(0)
48#endif
49 , m_iHoverLightnessStart(0)
50 , m_iHoverLightnessFinal(0)
51 , m_iHighlightLightnessStart(0)
52 , m_iHighlightLightnessFinal(0)
53 , m_iMinimumNameWidth(0)
54 , m_iMaximumNameWidth(0)
55 , m_iHeightHint(0)
56{
57 prepare();
58}
59
60UIChooserItemGlobal::~UIChooserItemGlobal()
61{
62 cleanup();
63}
64
65UIChooserNodeGlobal *UIChooserItemGlobal::nodeToGlobalType() const
66{
67 return node() ? node()->toGlobalNode() : 0;
68}
69
70bool UIChooserItemGlobal::isToolButtonArea(const QPoint &position, int iMarginMultiplier /* = 1 */) const
71{
72 const int iFullWidth = geometry().width();
73 const int iFullHeight = geometry().height();
74 const int iMarginHR = data(GlobalItemData_MarginHR).toInt();
75 const int iButtonMargin = data(GlobalItemData_ButtonMargin).toInt();
76 const int iToolPixmapX = iFullWidth - iMarginHR - 1
77 - m_toolPixmap.width() / m_toolPixmap.devicePixelRatio();
78 const int iToolPixmapY = (iFullHeight - m_toolPixmap.height() / m_toolPixmap.devicePixelRatio()) / 2;
79 QRect rect = QRect(iToolPixmapX,
80 iToolPixmapY,
81 m_toolPixmap.width() / m_toolPixmap.devicePixelRatio(),
82 m_toolPixmap.height() / m_toolPixmap.devicePixelRatio());
83 rect.adjust(-iMarginMultiplier * iButtonMargin, -iMarginMultiplier * iButtonMargin,
84 iMarginMultiplier * iButtonMargin, iMarginMultiplier * iButtonMargin);
85 return rect.contains(position);
86}
87
88bool UIChooserItemGlobal::isPinButtonArea(const QPoint &position, int iMarginMultiplier /* = 1 */) const
89{
90 const int iFullWidth = geometry().width();
91 const int iFullHeight = geometry().height();
92 const int iMarginHR = data(GlobalItemData_MarginHR).toInt();
93 const int iSpacing = data(GlobalItemData_Spacing).toInt();
94 const int iButtonMargin = data(GlobalItemData_ButtonMargin).toInt();
95 const int iPinPixmapX = iFullWidth - iMarginHR - 1
96 - m_toolPixmap.width() / m_toolPixmap.devicePixelRatio()
97 - iSpacing
98 - m_pinPixmap.width() / m_pinPixmap.devicePixelRatio();
99 const int iPinPixmapY = (iFullHeight - m_pinPixmap.height() / m_pinPixmap.devicePixelRatio()) / 2;
100 QRect rect = QRect(iPinPixmapX,
101 iPinPixmapY,
102 m_pinPixmap.width() / m_pinPixmap.devicePixelRatio(),
103 m_pinPixmap.height() / m_pinPixmap.devicePixelRatio());
104 rect.adjust(-iMarginMultiplier * iButtonMargin, -iMarginMultiplier * iButtonMargin,
105 iMarginMultiplier * iButtonMargin, iMarginMultiplier * iButtonMargin);
106 return rect.contains(position);
107}
108
109int UIChooserItemGlobal::heightHint() const
110{
111 return m_iHeightHint;
112}
113
114void UIChooserItemGlobal::setHeightHint(int iHint)
115{
116 /* Remember a new hint: */
117 m_iHeightHint = iHint;
118
119 /* Update geometry and the model layout: */
120 updateGeometry();
121 model()->updateLayout();
122}
123
124void UIChooserItemGlobal::retranslateUi()
125{
126}
127
128void UIChooserItemGlobal::showEvent(QShowEvent *pEvent)
129{
130 /* Call to base-class: */
131 UIChooserItem::showEvent(pEvent);
132
133 /* Update pixmaps: */
134 updatePixmaps();
135}
136
137void UIChooserItemGlobal::resizeEvent(QGraphicsSceneResizeEvent *pEvent)
138{
139 /* Call to base-class: */
140 UIChooserItem::resizeEvent(pEvent);
141
142 /* What is the new geometry? */
143 const QRectF newGeometry = geometry();
144
145 /* Should we update visible name? */
146 if (previousGeometry().width() != newGeometry.width())
147 updateMaximumNameWidth();
148
149 /* Remember the new geometry: */
150 setPreviousGeometry(newGeometry);
151}
152
153void UIChooserItemGlobal::mousePressEvent(QGraphicsSceneMouseEvent *pEvent)
154{
155 /* Call to base-class: */
156 UIChooserItem::mousePressEvent(pEvent);
157 /* No drag at all: */
158 pEvent->ignore();
159}
160
161void UIChooserItemGlobal::paint(QPainter *pPainter, const QStyleOptionGraphicsItem *pOptions, QWidget * /* pWidget = 0 */)
162{
163 /* Acquire rectangle: */
164 const QRect rectangle = pOptions->rect;
165
166 /* Paint background: */
167 paintBackground(pPainter, rectangle);
168 /* Paint frame: */
169 paintFrame(pPainter, rectangle);
170 /* Paint global info: */
171 paintGlobalInfo(pPainter, rectangle);
172}
173
174void UIChooserItemGlobal::setFavorite(bool fFavorite)
175{
176 /* Call to base-class: */
177 UIChooserItem::setFavorite(fFavorite);
178
179 /* Update pin-pixmap: */
180 updatePinPixmap();
181}
182
183void UIChooserItemGlobal::startEditing()
184{
185 AssertMsgFailed(("Global graphics item do NOT support editing yet!"));
186}
187
188void UIChooserItemGlobal::updateItem()
189{
190 /* Update this global-item: */
191 updatePixmaps();
192 updateMinimumNameWidth();
193 updateVisibleName();
194 updateToolTip();
195 update();
196
197 /* Update parent group-item: */
198 parentItem()->updateToolTip();
199 parentItem()->update();
200}
201
202void UIChooserItemGlobal::updateToolTip()
203{
204 // Nothing for now..
205}
206
207QList<UIChooserItem*> UIChooserItemGlobal::items(UIChooserNodeType) const
208{
209 AssertMsgFailedReturn(("Global graphics item do NOT support children!"), QList<UIChooserItem*>());
210}
211
212void UIChooserItemGlobal::addItem(UIChooserItem *, bool, int)
213{
214 AssertMsgFailed(("Global graphics item do NOT support children!"));
215}
216
217void UIChooserItemGlobal::removeItem(UIChooserItem *)
218{
219 AssertMsgFailed(("Global graphics item do NOT support children!"));
220}
221
222UIChooserItem *UIChooserItemGlobal::searchForItem(const QString &, int iSearchFlags)
223{
224 /* Ignore if we are not searching for the global-item: */
225 if (!(iSearchFlags & UIChooserItemSearchFlag_Global))
226 return 0;
227
228 /* Returning this: */
229 return this;
230}
231
232UIChooserItem *UIChooserItemGlobal::firstMachineItem()
233{
234 return 0;
235}
236
237void UIChooserItemGlobal::updateLayout()
238{
239 // Just do nothing ..
240}
241
242int UIChooserItemGlobal::minimumWidthHint() const
243{
244 /* Prepare variables: */
245 const int iMarginHL = data(GlobalItemData_MarginHL).toInt();
246 const int iMarginHR = data(GlobalItemData_MarginHR).toInt();
247 const int iSpacing = data(GlobalItemData_Spacing).toInt();
248
249 /* Calculating proposed width: */
250 int iProposedWidth = 0;
251
252 /* Two margins: */
253 iProposedWidth += iMarginHL + iMarginHR;
254 /* And global-item content width: */
255 iProposedWidth += (m_pixmapSize.width() +
256 iSpacing +
257 m_iMinimumNameWidth +
258 iSpacing +
259 m_toolPixmapSize.width() +
260 iSpacing +
261 m_pinPixmapSize.width());
262
263 /* Return result: */
264 return iProposedWidth;
265}
266
267int UIChooserItemGlobal::minimumHeightHint() const
268{
269 /* Prepare variables: */
270 const int iMarginV = data(GlobalItemData_MarginV).toInt();
271
272 /* Calculating proposed height: */
273 int iProposedHeight = 0;
274
275 /* Global-item content height: */
276 int iContentHeight = qMax(m_pixmapSize.height(), m_visibleNameSize.height());
277 iContentHeight = qMax(iContentHeight, m_toolPixmapSize.height());
278 iContentHeight = qMax(iContentHeight, m_pinPixmapSize.height());
279
280 /* If we have height hint: */
281 if (m_iHeightHint)
282 {
283 /* Take the largest value between height hint and content height: */
284 iProposedHeight += qMax(m_iHeightHint, iContentHeight);
285 }
286 /* Otherwise: */
287 else
288 {
289 /* Two margins: */
290 iProposedHeight += 2 * iMarginV;
291 /* And content height: */
292 iProposedHeight += iContentHeight;
293 }
294
295 /* Return result: */
296 return iProposedHeight;
297}
298
299QSizeF UIChooserItemGlobal::sizeHint(Qt::SizeHint which, const QSizeF &constraint /* = QSizeF() */) const
300{
301 /* If Qt::MinimumSize requested: */
302 if (which == Qt::MinimumSize)
303 return QSizeF(minimumWidthHint(), minimumHeightHint());
304 /* Else call to base-class: */
305 return UIChooserItem::sizeHint(which, constraint);
306}
307
308QPixmap UIChooserItemGlobal::toPixmap()
309{
310 AssertFailedReturn(QPixmap());
311}
312
313bool UIChooserItemGlobal::isDropAllowed(QGraphicsSceneDragDropEvent *, UIChooserItemDragToken) const
314{
315 /* No drops at all: */
316 return false;
317}
318
319void UIChooserItemGlobal::processDrop(QGraphicsSceneDragDropEvent *, UIChooserItem *, UIChooserItemDragToken)
320{
321 /* Nothing to process: */
322}
323
324void UIChooserItemGlobal::resetDragToken()
325{
326 /* Nothing to process: */
327}
328
329QMimeData *UIChooserItemGlobal::createMimeData()
330{
331 /* Nothing to return: */
332 return 0;
333}
334
335void UIChooserItemGlobal::sltHandleWindowRemapped()
336{
337 updatePixmaps();
338}
339
340void UIChooserItemGlobal::prepare()
341{
342 /* Color tones: */
343#if defined(VBOX_WS_MAC)
344 m_iDefaultColorDeviation = 105;
345 m_iHoverLightnessStart = 125;
346 m_iHoverLightnessFinal = 115;
347 m_iHighlightLightnessStart = 115;
348 m_iHighlightLightnessFinal = 105;
349#elif defined(VBOX_WS_WIN)
350 m_iHoverLightnessStart = 220;
351 m_iHoverLightnessFinal = 210;
352 m_iHighlightLightnessStart = 190;
353 m_iHighlightLightnessFinal = 180;
354#else /* !VBOX_WS_MAC && !VBOX_WS_WIN */
355 m_iHoverLightnessStart = 125;
356 m_iHoverLightnessFinal = 115;
357 m_iHighlightLightnessStart = 110;
358 m_iHighlightLightnessFinal = 100;
359#endif /* !VBOX_WS_MAC && !VBOX_WS_WIN */
360
361 /* Fonts: */
362 m_nameFont = font();
363 m_nameFont.setWeight(QFont::Bold);
364
365 /* Sizes: */
366 m_iMinimumNameWidth = 0;
367 m_iMaximumNameWidth = 0;
368
369 /* Add item to the parent: */
370 AssertPtrReturnVoid(parentItem());
371 parentItem()->addItem(this, isFavorite(), position());
372
373 /* Configure connections: */
374 connect(gpManager, &UIVirtualBoxManager::sigWindowRemapped,
375 this, &UIChooserItemGlobal::sltHandleWindowRemapped);
376
377 /* Init: */
378 updatePixmaps();
379
380 /* Apply language settings: */
381 retranslateUi();
382}
383
384void UIChooserItemGlobal::cleanup()
385{
386 /* If that item is current: */
387 if (model()->currentItem() == this)
388 {
389 /* Unset current-item: */
390 model()->setCurrentItem(0);
391 }
392 /* If that item is in selection list: */
393 if (model()->selectedItems().contains(this))
394 {
395 /* Remove item from the selection list: */
396 model()->removeFromSelectedItems(this);
397 }
398 /* If that item is in navigation list: */
399 if (model()->navigationItems().contains(this))
400 {
401 /* Remove item from the navigation list: */
402 model()->removeFromNavigationItems(this);
403 }
404
405 /* Remove item from the parent: */
406 AssertPtrReturnVoid(parentItem());
407 parentItem()->removeItem(this);
408}
409
410QVariant UIChooserItemGlobal::data(int iKey) const
411{
412 /* Provide other members with required data: */
413 switch (iKey)
414 {
415 /* Layout hints: */
416 case GlobalItemData_MarginHL: return QApplication::style()->pixelMetric(QStyle::PM_SmallIconSize);
417 case GlobalItemData_MarginHR: return QApplication::style()->pixelMetric(QStyle::PM_SmallIconSize) / 4 * 5;
418 case GlobalItemData_MarginV: return QApplication::style()->pixelMetric(QStyle::PM_SmallIconSize) / 4 * 3;
419 case GlobalItemData_Spacing: return QApplication::style()->pixelMetric(QStyle::PM_SmallIconSize) / 2;
420 case GlobalItemData_ButtonMargin: return QApplication::style()->pixelMetric(QStyle::PM_SmallIconSize) / 4;
421
422 /* Default: */
423 default: break;
424 }
425 return QVariant();
426}
427
428void UIChooserItemGlobal::updatePixmaps()
429{
430 /* Update pixmap: */
431 updatePixmap();
432 /* Update tool-pixmap: */
433 updateToolPixmap();
434 /* Update pin-pixmap: */
435 updatePinPixmap();
436}
437
438void UIChooserItemGlobal::updatePixmap()
439{
440 /* Acquire new metric, then compose pixmap-size: */
441 const int iMetric = QApplication::style()->pixelMetric(QStyle::PM_LargeIconSize);
442 const QSize pixmapSize = QSize(iMetric, iMetric);
443
444 /* Create new icon, then acquire pixmap: */
445 const QIcon icon = UIIconPool::iconSet(":/tools_global_32px.png");
446 const qreal fDevicePixelRatio = gpManager->windowHandle() ? gpManager->windowHandle()->devicePixelRatio() : 1;
447 const QPixmap pixmap = icon.pixmap(pixmapSize, fDevicePixelRatio);
448
449 /* Update linked values: */
450 if (m_pixmapSize != pixmapSize)
451 {
452 m_pixmapSize = pixmapSize;
453 updateMaximumNameWidth();
454 updateGeometry();
455 }
456 if (m_pixmap.toImage() != pixmap.toImage())
457 {
458 m_pixmap = pixmap;
459 update();
460 }
461}
462
463void UIChooserItemGlobal::updateToolPixmap()
464{
465 /* Determine icon metric: */
466 const int iIconMetric = QApplication::style()->pixelMetric(QStyle::PM_LargeIconSize) * .75;
467 /* Create new tool-pixmap and tool-pixmap size: */
468 const QIcon toolIcon = UIIconPool::iconSet(":/tools_menu_24px.png");
469 AssertReturnVoid(!toolIcon.isNull());
470 const QSize toolPixmapSize = QSize(iIconMetric, iIconMetric);
471 const qreal fDevicePixelRatio = gpManager->windowHandle() ? gpManager->windowHandle()->devicePixelRatio() : 1;
472 const QPixmap toolPixmap = toolIcon.pixmap(toolPixmapSize, fDevicePixelRatio);
473 /* Update linked values: */
474 if (m_toolPixmapSize != toolPixmapSize)
475 {
476 m_toolPixmapSize = toolPixmapSize;
477 updateGeometry();
478 }
479 if (m_toolPixmap.toImage() != toolPixmap.toImage())
480 {
481 m_toolPixmap = toolPixmap;
482 update();
483 }
484}
485
486void UIChooserItemGlobal::updatePinPixmap()
487{
488 /* Determine icon metric: */
489 const int iIconMetric = QApplication::style()->pixelMetric(QStyle::PM_LargeIconSize) * .75;
490 /* Create new tool-pixmap and tool-pixmap size: */
491 const QIcon pinIcon = UIIconPool::iconSet(isFavorite() ? ":/favorite_pressed_24px.png" : ":/favorite_24px.png");
492 AssertReturnVoid(!pinIcon.isNull());
493 const QSize pinPixmapSize = QSize(iIconMetric, iIconMetric);
494 const qreal fDevicePixelRatio = gpManager->windowHandle() ? gpManager->windowHandle()->devicePixelRatio() : 1;
495 const QPixmap pinPixmap = pinIcon.pixmap(pinPixmapSize, fDevicePixelRatio);
496 /* Update linked values: */
497 if (m_pinPixmapSize != pinPixmapSize)
498 {
499 m_pinPixmapSize = pinPixmapSize;
500 updateGeometry();
501 }
502 if (m_pinPixmap.toImage() != pinPixmap.toImage())
503 {
504 m_pinPixmap = pinPixmap;
505 update();
506 }
507}
508
509void UIChooserItemGlobal::updateMinimumNameWidth()
510{
511 /* Calculate new minimum name width: */
512 QPaintDevice *pPaintDevice = model()->paintDevice();
513 const QFontMetrics fm(m_nameFont, pPaintDevice);
514#if QT_VERSION >= QT_VERSION_CHECK(5, 11, 0)
515 const int iMinimumNameWidth = fm.horizontalAdvance(compressText(m_nameFont, pPaintDevice, name(),
516 textWidth(m_nameFont, pPaintDevice, 15)));
517#else
518 const int iMinimumNameWidth = fm.width(compressText(m_nameFont, pPaintDevice, name(), textWidth(m_nameFont, pPaintDevice, 15)));
519#endif
520
521 /* Is there something changed? */
522 if (m_iMinimumNameWidth == iMinimumNameWidth)
523 return;
524
525 /* Update linked values: */
526 m_iMinimumNameWidth = iMinimumNameWidth;
527 updateGeometry();
528}
529
530void UIChooserItemGlobal::updateMaximumNameWidth()
531{
532 /* Prepare variables: */
533 const int iMarginHL = data(GlobalItemData_MarginHL).toInt();
534 const int iMarginHR = data(GlobalItemData_MarginHR).toInt();
535 const int iSpacing = data(GlobalItemData_Spacing).toInt();
536
537 /* Calculate new maximum name width: */
538 int iMaximumNameWidth = (int)geometry().width();
539 iMaximumNameWidth -= iMarginHL; /* left margin */
540 iMaximumNameWidth -= m_pixmapSize.width(); /* pixmap width */
541 iMaximumNameWidth -= iSpacing; /* spacing between pixmap and name */
542 iMaximumNameWidth -= iMarginHR; /* right margin */
543
544 /* Is there something changed? */
545 if (m_iMaximumNameWidth == iMaximumNameWidth)
546 return;
547
548 /* Update linked values: */
549 m_iMaximumNameWidth = iMaximumNameWidth;
550 updateVisibleName();
551}
552
553void UIChooserItemGlobal::updateVisibleName()
554{
555 /* Prepare variables: */
556 QPaintDevice *pPaintDevice = model()->paintDevice();
557
558 /* Calculate new visible name and name-size: */
559 const QString strVisibleName = compressText(m_nameFont, pPaintDevice, name(), m_iMaximumNameWidth);
560 const QSize visibleNameSize = textSize(m_nameFont, pPaintDevice, strVisibleName);
561
562 /* Update linked values: */
563 if (m_visibleNameSize != visibleNameSize)
564 {
565 m_visibleNameSize = visibleNameSize;
566 updateGeometry();
567 }
568 if (m_strVisibleName != strVisibleName)
569 {
570 m_strVisibleName = strVisibleName;
571 update();
572 }
573}
574
575void UIChooserItemGlobal::paintBackground(QPainter *pPainter, const QRect &rectangle)
576{
577 /* Save painter: */
578 pPainter->save();
579
580 /* Prepare color: */
581 const QPalette pal = QApplication::palette();
582
583 /* Selected-item background: */
584 if (model()->selectedItems().contains(this))
585 {
586 /* Prepare color: */
587 const QColor backgroundColor = pal.color(QPalette::Active, QPalette::Highlight);
588 /* Draw gradient: */
589 QLinearGradient bgGrad(rectangle.topLeft(), rectangle.bottomLeft());
590 bgGrad.setColorAt(0, backgroundColor.lighter(m_iHighlightLightnessStart));
591 bgGrad.setColorAt(1, backgroundColor.lighter(m_iHighlightLightnessFinal));
592 pPainter->fillRect(rectangle, bgGrad);
593
594 if (isHovered())
595 {
596 /* Prepare color: */
597 QColor animationColor1 = QColor(Qt::white);
598 QColor animationColor2 = QColor(Qt::white);
599#ifdef VBOX_WS_MAC
600 animationColor1.setAlpha(90);
601#else
602 animationColor1.setAlpha(30);
603#endif
604 animationColor2.setAlpha(0);
605 /* Draw hovered-item animated gradient: */
606 QRect animatedRect = rectangle;
607 animatedRect.setWidth(animatedRect.height());
608 const int iLength = 2 * animatedRect.width() + rectangle.width();
609 const int iShift = - animatedRect.width() + iLength * animatedValue() / 100;
610 animatedRect.moveLeft(iShift);
611 QLinearGradient bgAnimatedGrad(animatedRect.topLeft(), animatedRect.bottomRight());
612 bgAnimatedGrad.setColorAt(0, animationColor2);
613 bgAnimatedGrad.setColorAt(0.1, animationColor2);
614 bgAnimatedGrad.setColorAt(0.5, animationColor1);
615 bgAnimatedGrad.setColorAt(0.9, animationColor2);
616 bgAnimatedGrad.setColorAt(1, animationColor2);
617 pPainter->fillRect(rectangle, bgAnimatedGrad);
618 }
619 }
620 /* Hovered-item background: */
621 else if (isHovered())
622 {
623 /* Prepare color: */
624 const QColor backgroundColor = pal.color(QPalette::Active, QPalette::Highlight);
625 /* Draw gradient: */
626 QLinearGradient bgGrad(rectangle.topLeft(), rectangle.bottomLeft());
627 bgGrad.setColorAt(0, backgroundColor.lighter(m_iHoverLightnessStart));
628 bgGrad.setColorAt(1, backgroundColor.lighter(m_iHoverLightnessFinal));
629 pPainter->fillRect(rectangle, bgGrad);
630
631 /* Prepare color: */
632 QColor animationColor1 = QColor(Qt::white);
633 QColor animationColor2 = QColor(Qt::white);
634#ifdef VBOX_WS_MAC
635 animationColor1.setAlpha(120);
636#else
637 animationColor1.setAlpha(50);
638#endif
639 animationColor2.setAlpha(0);
640 /* Draw hovered-item animated gradient: */
641 QRect animatedRect = rectangle;
642 animatedRect.setWidth(animatedRect.height());
643 const int iLength = 2 * animatedRect.width() + rectangle.width();
644 const int iShift = - animatedRect.width() + iLength * animatedValue() / 100;
645 animatedRect.moveLeft(iShift);
646 QLinearGradient bgAnimatedGrad(animatedRect.topLeft(), animatedRect.bottomRight());
647 bgAnimatedGrad.setColorAt(0, animationColor2);
648 bgAnimatedGrad.setColorAt(0.1, animationColor2);
649 bgAnimatedGrad.setColorAt(0.5, animationColor1);
650 bgAnimatedGrad.setColorAt(0.9, animationColor2);
651 bgAnimatedGrad.setColorAt(1, animationColor2);
652 pPainter->fillRect(rectangle, bgAnimatedGrad);
653 }
654 /* Default background: */
655 else
656 {
657#ifdef VBOX_WS_MAC
658 /* Prepare color: */
659 const QColor backgroundColor = pal.color(QPalette::Active, QPalette::Window);
660 /* Draw gradient: */
661 QLinearGradient bgGrad(rectangle.topLeft(), rectangle.bottomLeft());
662 bgGrad.setColorAt(0, backgroundColor.lighter(m_iDefaultColorDeviation));
663 bgGrad.setColorAt(1, backgroundColor.darker(m_iDefaultColorDeviation));
664 pPainter->fillRect(rectangle, bgGrad);
665#else
666 /* Draw simple background: */
667 pPainter->fillRect(rectangle, pal.color(QPalette::Active, QPalette::Window));
668#endif
669 }
670
671 /* Restore painter: */
672 pPainter->restore();
673}
674
675void UIChooserItemGlobal::paintFrame(QPainter *pPainter, const QRect &rectangle)
676{
677 /* Only selected and/or hovered item should have a frame: */
678 if (!model()->selectedItems().contains(this) && !isHovered())
679 return;
680
681 /* Save painter: */
682 pPainter->save();
683
684 /* Prepare color: */
685 const QPalette pal = QApplication::palette();
686 QColor strokeColor;
687
688 /* Selected-item frame: */
689 if (model()->selectedItems().contains(this))
690 strokeColor = pal.color(QPalette::Active, QPalette::Highlight).lighter(m_iHighlightLightnessStart - 40);
691 /* Hovered-item frame: */
692 else if (isHovered())
693 strokeColor = pal.color(QPalette::Active, QPalette::Highlight).lighter(m_iHoverLightnessStart - 40);
694
695 /* Create/assign pen: */
696 QPen pen(strokeColor);
697 pen.setWidth(0);
698 pPainter->setPen(pen);
699
700 /* Draw borders: */
701 pPainter->drawLine(rectangle.topLeft(), rectangle.topRight() + QPoint(1, 0));
702 pPainter->drawLine(rectangle.bottomLeft(), rectangle.bottomRight() + QPoint(1, 0));
703 pPainter->drawLine(rectangle.topLeft(), rectangle.bottomLeft());
704
705 /* Restore painter: */
706 pPainter->restore();
707}
708
709void UIChooserItemGlobal::paintGlobalInfo(QPainter *pPainter, const QRect &rectangle)
710{
711 /* Prepare variables: */
712 const int iFullWidth = rectangle.width();
713 const int iFullHeight = rectangle.height();
714 const int iMarginHL = data(GlobalItemData_MarginHL).toInt();
715 const int iMarginHR = data(GlobalItemData_MarginHR).toInt();
716 const int iSpacing = data(GlobalItemData_Spacing).toInt();
717 const int iButtonMargin = data(GlobalItemData_ButtonMargin).toInt();
718
719 /* Selected or hovered item foreground: */
720 if (model()->selectedItems().contains(this) || isHovered())
721 {
722 /* Prepare palette: */
723 const QPalette pal = QApplication::palette();
724
725 /* Get background color: */
726 const QColor highlight = pal.color(QPalette::Active, QPalette::Highlight);
727 const QColor background = model()->selectedItems().contains(this)
728 ? highlight.lighter(m_iHighlightLightnessStart)
729 : highlight.lighter(m_iHoverLightnessStart);
730
731 /* Gather foreground color for background one: */
732 const QColor foreground = suitableForegroundColor(pal, background);
733 pPainter->setPen(foreground);
734 }
735
736 /* Calculate indents: */
737 int iLeftColumnIndent = iMarginHL;
738
739 /* Paint left column: */
740 {
741 /* Prepare variables: */
742 const int iGlobalPixmapX = iLeftColumnIndent;
743 const int iGlobalPixmapY = (iFullHeight - m_pixmap.height() / m_pixmap.devicePixelRatio()) / 2;
744
745 /* Paint pixmap: */
746 paintPixmap(/* Painter: */
747 pPainter,
748 /* Point to paint in: */
749 QPoint(iGlobalPixmapX, iGlobalPixmapY),
750 /* Pixmap to paint: */
751 m_pixmap);
752 }
753
754 /* Calculate indents: */
755 const int iMiddleColumnIndent = iLeftColumnIndent +
756 m_pixmapSize.width() +
757 iSpacing;
758
759 /* Paint middle column: */
760 {
761 /* Prepare variables: */
762 const int iNameX = iMiddleColumnIndent;
763 const int iNameY = (iFullHeight - m_visibleNameSize.height()) / 2;
764
765 /* Paint name: */
766 paintText(/* Painter: */
767 pPainter,
768 /* Point to paint in: */
769 QPoint(iNameX, iNameY),
770 /* Font to paint text: */
771 m_nameFont,
772 /* Paint device: */
773 model()->paintDevice(),
774 /* Text to paint: */
775 m_strVisibleName);
776 }
777
778 /* Calculate indents: */
779 QGraphicsView *pView = model()->scene()->views().first();
780 const QPointF sceneCursorPosition = pView->mapToScene(pView->mapFromGlobal(QCursor::pos()));
781 const QPoint itemCursorPosition = mapFromScene(sceneCursorPosition).toPoint();
782 int iRightColumnIndent = iFullWidth - iMarginHR - 1 - m_toolPixmap.width() / m_toolPixmap.devicePixelRatio();
783
784 /* Paint right column: */
785 if ( model()->firstSelectedItem() == this
786 || isHovered())
787 {
788 /* Prepare variables: */
789 const int iToolPixmapX = iRightColumnIndent;
790 const int iToolPixmapY = (iFullHeight - m_toolPixmap.height() / m_toolPixmap.devicePixelRatio()) / 2;
791 QRect toolButtonRectangle = QRect(iToolPixmapX,
792 iToolPixmapY,
793 m_toolPixmap.width() / m_toolPixmap.devicePixelRatio(),
794 m_toolPixmap.height() / m_toolPixmap.devicePixelRatio());
795 toolButtonRectangle.adjust(- iButtonMargin, -iButtonMargin, iButtonMargin, iButtonMargin);
796
797 /* Paint tool button: */
798 if ( isHovered()
799 && isToolButtonArea(itemCursorPosition, 4))
800 paintFlatButton(/* Painter: */
801 pPainter,
802 /* Button rectangle: */
803 toolButtonRectangle,
804 /* Cursor position: */
805 itemCursorPosition);
806
807 /* Paint pixmap: */
808 paintPixmap(/* Painter: */
809 pPainter,
810 /* Point to paint in: */
811 QPoint(iToolPixmapX, iToolPixmapY),
812 /* Pixmap to paint: */
813 m_toolPixmap);
814 }
815
816 /* Calculate indents: */
817 iRightColumnIndent = iRightColumnIndent - m_toolPixmap.width() / m_toolPixmap.devicePixelRatio() - iSpacing;
818
819 /* Paint right column: */
820 if ( model()->firstSelectedItem() == this
821 || isHovered())
822 {
823 /* Prepare variables: */
824 const int iPinPixmapX = iRightColumnIndent;
825 const int iPinPixmapY = (iFullHeight - m_pinPixmap.height() / m_pinPixmap.devicePixelRatio()) / 2;
826 QRect pinButtonRectangle = QRect(iPinPixmapX,
827 iPinPixmapY,
828 m_pinPixmap.width() / m_pinPixmap.devicePixelRatio(),
829 m_pinPixmap.height() / m_pinPixmap.devicePixelRatio());
830 pinButtonRectangle.adjust(- iButtonMargin, -iButtonMargin, iButtonMargin, iButtonMargin);
831
832 /* Paint pin button: */
833 if ( isHovered()
834 && isPinButtonArea(itemCursorPosition, 4))
835 paintFlatButton(/* Painter: */
836 pPainter,
837 /* Button rectangle: */
838 pinButtonRectangle,
839 /* Cursor position: */
840 itemCursorPosition);
841
842 /* Paint pixmap: */
843 paintPixmap(/* Painter: */
844 pPainter,
845 /* Point to paint in: */
846 QPoint(iPinPixmapX, iPinPixmapY),
847 /* Pixmap to paint: */
848 m_pinPixmap);
849 }
850}
Note: See TracBrowser for help on using the repository browser.

© 2023 Oracle
ContactPrivacy policyTerms of Use