VirtualBox

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

Last change on this file was 106061, checked in by vboxsync, 3 weeks ago

Copyright year updates by scm.

  • 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 106061 2024-09-16 14:03:52Z vboxsync $ */
2/** @file
3 * VBox Qt GUI - UIChooserItemGlobal class implementation.
4 */
5
6/*
7 * Copyright (C) 2012-2024 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 <QApplication>
30#include <QGraphicsSceneMouseEvent>
31#include <QGraphicsView>
32#include <QPainter>
33#include <QStyleOptionGraphicsItem>
34#include <QWindow>
35
36/* GUI includes: */
37#include "UIChooserItemGlobal.h"
38#include "UIChooserModel.h"
39#include "UIChooserNodeGlobal.h"
40#include "UIIconPool.h"
41#include "UIImageTools.h"
42#include "UITranslationEventListener.h"
43#include "UIVirtualBoxManager.h"
44
45
46UIChooserItemGlobal::UIChooserItemGlobal(UIChooserItem *pParent, UIChooserNodeGlobal *pNode)
47 : UIChooserItem(pParent, pNode)
48#ifdef VBOX_WS_MAC
49 , m_iDefaultColorDeviation(0)
50#endif
51 , m_iHoverLightnessStart(0)
52 , m_iHoverLightnessFinal(0)
53 , m_iHighlightLightnessStart(0)
54 , m_iHighlightLightnessFinal(0)
55 , m_iMinimumNameWidth(0)
56 , m_iMaximumNameWidth(0)
57 , m_iHeightHint(0)
58{
59 prepare();
60}
61
62UIChooserItemGlobal::~UIChooserItemGlobal()
63{
64 cleanup();
65}
66
67UIChooserNodeGlobal *UIChooserItemGlobal::nodeToGlobalType() const
68{
69 return node() ? node()->toGlobalNode() : 0;
70}
71
72bool UIChooserItemGlobal::isToolButtonArea(const QPoint &position, int iMarginMultiplier /* = 1 */) const
73{
74 const int iFullWidth = geometry().width();
75 const int iFullHeight = geometry().height();
76 const int iMarginHR = data(GlobalItemData_MarginHR).toInt();
77 const int iButtonMargin = data(GlobalItemData_ButtonMargin).toInt();
78 const int iToolPixmapX = iFullWidth - iMarginHR - 1
79 - m_toolPixmap.width() / m_toolPixmap.devicePixelRatio();
80 const int iToolPixmapY = (iFullHeight - m_toolPixmap.height() / m_toolPixmap.devicePixelRatio()) / 2;
81 QRect rect = QRect(iToolPixmapX,
82 iToolPixmapY,
83 m_toolPixmap.width() / m_toolPixmap.devicePixelRatio(),
84 m_toolPixmap.height() / m_toolPixmap.devicePixelRatio());
85 rect.adjust(-iMarginMultiplier * iButtonMargin, -iMarginMultiplier * iButtonMargin,
86 iMarginMultiplier * iButtonMargin, iMarginMultiplier * iButtonMargin);
87 return rect.contains(position);
88}
89
90bool UIChooserItemGlobal::isPinButtonArea(const QPoint &position, int iMarginMultiplier /* = 1 */) const
91{
92 const int iFullWidth = geometry().width();
93 const int iFullHeight = geometry().height();
94 const int iMarginHR = data(GlobalItemData_MarginHR).toInt();
95 const int iSpacing = data(GlobalItemData_Spacing).toInt();
96 const int iButtonMargin = data(GlobalItemData_ButtonMargin).toInt();
97 const int iPinPixmapX = iFullWidth - iMarginHR - 1
98 - m_toolPixmap.width() / m_toolPixmap.devicePixelRatio()
99 - iSpacing
100 - m_pinPixmap.width() / m_pinPixmap.devicePixelRatio();
101 const int iPinPixmapY = (iFullHeight - m_pinPixmap.height() / m_pinPixmap.devicePixelRatio()) / 2;
102 QRect rect = QRect(iPinPixmapX,
103 iPinPixmapY,
104 m_pinPixmap.width() / m_pinPixmap.devicePixelRatio(),
105 m_pinPixmap.height() / m_pinPixmap.devicePixelRatio());
106 rect.adjust(-iMarginMultiplier * iButtonMargin, -iMarginMultiplier * iButtonMargin,
107 iMarginMultiplier * iButtonMargin, iMarginMultiplier * iButtonMargin);
108 return rect.contains(position);
109}
110
111int UIChooserItemGlobal::heightHint() const
112{
113 return m_iHeightHint;
114}
115
116void UIChooserItemGlobal::setHeightHint(int iHint)
117{
118 /* Remember a new hint: */
119 m_iHeightHint = iHint;
120
121 /* Update geometry and the model layout: */
122 updateGeometry();
123 model()->updateLayout();
124}
125
126void UIChooserItemGlobal::sltRetranslateUI()
127{
128}
129
130void UIChooserItemGlobal::showEvent(QShowEvent *pEvent)
131{
132 /* Call to base-class: */
133 UIChooserItem::showEvent(pEvent);
134
135 /* Update pixmaps: */
136 updatePixmaps();
137}
138
139void UIChooserItemGlobal::resizeEvent(QGraphicsSceneResizeEvent *pEvent)
140{
141 /* Call to base-class: */
142 UIChooserItem::resizeEvent(pEvent);
143
144 /* What is the new geometry? */
145 const QRectF newGeometry = geometry();
146
147 /* Should we update visible name? */
148 if (previousGeometry().width() != newGeometry.width())
149 updateMaximumNameWidth();
150
151 /* Remember the new geometry: */
152 setPreviousGeometry(newGeometry);
153}
154
155void UIChooserItemGlobal::mousePressEvent(QGraphicsSceneMouseEvent *pEvent)
156{
157 /* Call to base-class: */
158 UIChooserItem::mousePressEvent(pEvent);
159 /* No drag at all: */
160 pEvent->ignore();
161}
162
163void UIChooserItemGlobal::paint(QPainter *pPainter, const QStyleOptionGraphicsItem *pOptions, QWidget * /* pWidget = 0 */)
164{
165 /* Acquire rectangle: */
166 const QRect rectangle = pOptions->rect;
167
168 /* Paint background: */
169 paintBackground(pPainter, rectangle);
170 /* Paint frame: */
171 paintFrame(pPainter, rectangle);
172 /* Paint global info: */
173 paintGlobalInfo(pPainter, rectangle);
174}
175
176void UIChooserItemGlobal::setFavorite(bool fFavorite)
177{
178 /* Call to base-class: */
179 UIChooserItem::setFavorite(fFavorite);
180
181 /* Update pin-pixmap: */
182 updatePinPixmap();
183}
184
185void UIChooserItemGlobal::startEditing()
186{
187 AssertMsgFailed(("Global graphics item do NOT support editing yet!"));
188}
189
190void UIChooserItemGlobal::updateItem()
191{
192 /* Update this global-item: */
193 updatePixmaps();
194 updateMinimumNameWidth();
195 updateVisibleName();
196 updateToolTip();
197 update();
198
199 /* Update parent group-item: */
200 parentItem()->updateToolTip();
201 parentItem()->update();
202}
203
204void UIChooserItemGlobal::updateToolTip()
205{
206 // Nothing for now..
207}
208
209QList<UIChooserItem*> UIChooserItemGlobal::items(UIChooserNodeType) const
210{
211 AssertMsgFailedReturn(("Global graphics item do NOT support children!"), QList<UIChooserItem*>());
212}
213
214void UIChooserItemGlobal::addItem(UIChooserItem *, bool, int)
215{
216 AssertMsgFailed(("Global graphics item do NOT support children!"));
217}
218
219void UIChooserItemGlobal::removeItem(UIChooserItem *)
220{
221 AssertMsgFailed(("Global graphics item do NOT support children!"));
222}
223
224UIChooserItem *UIChooserItemGlobal::searchForItem(const QString &, int iSearchFlags)
225{
226 /* Ignore if we are not searching for the global-item: */
227 if (!(iSearchFlags & UIChooserItemSearchFlag_Global))
228 return 0;
229
230 /* Returning this: */
231 return this;
232}
233
234UIChooserItem *UIChooserItemGlobal::firstMachineItem()
235{
236 return 0;
237}
238
239void UIChooserItemGlobal::updateLayout()
240{
241 // Just do nothing ..
242}
243
244int UIChooserItemGlobal::minimumWidthHint() const
245{
246 /* Prepare variables: */
247 const int iMarginHL = data(GlobalItemData_MarginHL).toInt();
248 const int iMarginHR = data(GlobalItemData_MarginHR).toInt();
249 const int iSpacing = data(GlobalItemData_Spacing).toInt();
250
251 /* Calculating proposed width: */
252 int iProposedWidth = 0;
253
254 /* Two margins: */
255 iProposedWidth += iMarginHL + iMarginHR;
256 /* And global-item content width: */
257 iProposedWidth += (m_pixmapSize.width() +
258 iSpacing +
259 m_iMinimumNameWidth +
260 iSpacing +
261 m_toolPixmapSize.width() +
262 iSpacing +
263 m_pinPixmapSize.width());
264
265 /* Return result: */
266 return iProposedWidth;
267}
268
269int UIChooserItemGlobal::minimumHeightHint() const
270{
271 /* Prepare variables: */
272 const int iMarginV = data(GlobalItemData_MarginV).toInt();
273
274 /* Calculating proposed height: */
275 int iProposedHeight = 0;
276
277 /* Global-item content height: */
278 int iContentHeight = qMax(m_pixmapSize.height(), m_visibleNameSize.height());
279 iContentHeight = qMax(iContentHeight, m_toolPixmapSize.height());
280 iContentHeight = qMax(iContentHeight, m_pinPixmapSize.height());
281
282 /* If we have height hint: */
283 if (m_iHeightHint)
284 {
285 /* Take the largest value between height hint and content height: */
286 iProposedHeight += qMax(m_iHeightHint, iContentHeight);
287 }
288 /* Otherwise: */
289 else
290 {
291 /* Two margins: */
292 iProposedHeight += 2 * iMarginV;
293 /* And content height: */
294 iProposedHeight += iContentHeight;
295 }
296
297 /* Return result: */
298 return iProposedHeight;
299}
300
301QSizeF UIChooserItemGlobal::sizeHint(Qt::SizeHint which, const QSizeF &constraint /* = QSizeF() */) const
302{
303 /* If Qt::MinimumSize requested: */
304 if (which == Qt::MinimumSize)
305 return QSizeF(minimumWidthHint(), minimumHeightHint());
306 /* Else call to base-class: */
307 return UIChooserItem::sizeHint(which, constraint);
308}
309
310QPixmap UIChooserItemGlobal::toPixmap()
311{
312 AssertFailedReturn(QPixmap());
313}
314
315bool UIChooserItemGlobal::isDropAllowed(QGraphicsSceneDragDropEvent *, UIChooserItemDragToken) const
316{
317 /* No drops at all: */
318 return false;
319}
320
321void UIChooserItemGlobal::processDrop(QGraphicsSceneDragDropEvent *, UIChooserItem *, UIChooserItemDragToken)
322{
323 /* Nothing to process: */
324}
325
326void UIChooserItemGlobal::resetDragToken()
327{
328 /* Nothing to process: */
329}
330
331QMimeData *UIChooserItemGlobal::createMimeData()
332{
333 /* Nothing to return: */
334 return 0;
335}
336
337void UIChooserItemGlobal::sltHandleWindowRemapped()
338{
339 updatePixmaps();
340}
341
342void UIChooserItemGlobal::prepare()
343{
344 /* Color tones: */
345#if defined(VBOX_WS_MAC)
346 m_iDefaultColorDeviation = 105;
347 m_iHoverLightnessStart = 125;
348 m_iHoverLightnessFinal = 115;
349 m_iHighlightLightnessStart = 115;
350 m_iHighlightLightnessFinal = 105;
351#elif defined(VBOX_WS_WIN)
352 m_iHoverLightnessStart = 220;
353 m_iHoverLightnessFinal = 210;
354 m_iHighlightLightnessStart = 190;
355 m_iHighlightLightnessFinal = 180;
356#else /* !VBOX_WS_MAC && !VBOX_WS_WIN */
357 m_iHoverLightnessStart = 125;
358 m_iHoverLightnessFinal = 115;
359 m_iHighlightLightnessStart = 110;
360 m_iHighlightLightnessFinal = 100;
361#endif /* !VBOX_WS_MAC && !VBOX_WS_WIN */
362
363 /* Fonts: */
364 m_nameFont = font();
365 m_nameFont.setWeight(QFont::Bold);
366
367 /* Sizes: */
368 m_iMinimumNameWidth = 0;
369 m_iMaximumNameWidth = 0;
370
371 /* Add item to the parent: */
372 AssertPtrReturnVoid(parentItem());
373 parentItem()->addItem(this, isFavorite(), position());
374
375 /* Configure connections: */
376 connect(gpManager, &UIVirtualBoxManager::sigWindowRemapped,
377 this, &UIChooserItemGlobal::sltHandleWindowRemapped);
378
379 /* Init: */
380 updatePixmaps();
381
382 /* Apply language settings: */
383 sltRetranslateUI();
384 connect(&translationEventListener(), &UITranslationEventListener::sigRetranslateUI,
385 this, &UIChooserItemGlobal::sltRetranslateUI);
386}
387
388void UIChooserItemGlobal::cleanup()
389{
390 /* If that item is current: */
391 if (model()->currentItem() == this)
392 {
393 /* Unset current-item: */
394 model()->setCurrentItem(0);
395 }
396 /* If that item is in selection list: */
397 if (model()->selectedItems().contains(this))
398 {
399 /* Remove item from the selection list: */
400 model()->removeFromSelectedItems(this);
401 }
402 /* If that item is in navigation list: */
403 if (model()->navigationItems().contains(this))
404 {
405 /* Remove item from the navigation list: */
406 model()->removeFromNavigationItems(this);
407 }
408
409 /* Remove item from the parent: */
410 AssertPtrReturnVoid(parentItem());
411 parentItem()->removeItem(this);
412}
413
414QVariant UIChooserItemGlobal::data(int iKey) const
415{
416 /* Provide other members with required data: */
417 switch (iKey)
418 {
419 /* Layout hints: */
420 case GlobalItemData_MarginHL: return QApplication::style()->pixelMetric(QStyle::PM_SmallIconSize);
421 case GlobalItemData_MarginHR: return QApplication::style()->pixelMetric(QStyle::PM_SmallIconSize) / 4 * 5;
422 case GlobalItemData_MarginV: return QApplication::style()->pixelMetric(QStyle::PM_SmallIconSize) / 4 * 3;
423 case GlobalItemData_Spacing: return QApplication::style()->pixelMetric(QStyle::PM_SmallIconSize) / 2;
424 case GlobalItemData_ButtonMargin: return QApplication::style()->pixelMetric(QStyle::PM_SmallIconSize) / 4;
425
426 /* Default: */
427 default: break;
428 }
429 return QVariant();
430}
431
432void UIChooserItemGlobal::updatePixmaps()
433{
434 /* Update pixmap: */
435 updatePixmap();
436 /* Update tool-pixmap: */
437 updateToolPixmap();
438 /* Update pin-pixmap: */
439 updatePinPixmap();
440}
441
442void UIChooserItemGlobal::updatePixmap()
443{
444 /* Acquire new metric, then compose pixmap-size: */
445 const int iMetric = QApplication::style()->pixelMetric(QStyle::PM_LargeIconSize);
446 const QSize pixmapSize = QSize(iMetric, iMetric);
447
448 /* Create new icon, then acquire pixmap: */
449 const QIcon icon = UIIconPool::iconSet(":/tools_global_32px.png");
450 const qreal fDevicePixelRatio = gpManager->windowHandle() ? gpManager->windowHandle()->devicePixelRatio() : 1;
451 const QPixmap pixmap = icon.pixmap(pixmapSize, fDevicePixelRatio);
452
453 /* Update linked values: */
454 if (m_pixmapSize != pixmapSize)
455 {
456 m_pixmapSize = pixmapSize;
457 updateMaximumNameWidth();
458 updateGeometry();
459 }
460 if (m_pixmap.toImage() != pixmap.toImage())
461 {
462 m_pixmap = pixmap;
463 update();
464 }
465}
466
467void UIChooserItemGlobal::updateToolPixmap()
468{
469 /* Determine icon metric: */
470 const int iIconMetric = QApplication::style()->pixelMetric(QStyle::PM_LargeIconSize) * .75;
471 /* Create new tool-pixmap and tool-pixmap size: */
472 const QIcon toolIcon = UIIconPool::iconSet(":/tools_menu_24px.png");
473 AssertReturnVoid(!toolIcon.isNull());
474 const QSize toolPixmapSize = QSize(iIconMetric, iIconMetric);
475 const qreal fDevicePixelRatio = gpManager->windowHandle() ? gpManager->windowHandle()->devicePixelRatio() : 1;
476 const QPixmap toolPixmap = toolIcon.pixmap(toolPixmapSize, fDevicePixelRatio);
477 /* Update linked values: */
478 if (m_toolPixmapSize != toolPixmapSize)
479 {
480 m_toolPixmapSize = toolPixmapSize;
481 updateGeometry();
482 }
483 if (m_toolPixmap.toImage() != toolPixmap.toImage())
484 {
485 m_toolPixmap = toolPixmap;
486 update();
487 }
488}
489
490void UIChooserItemGlobal::updatePinPixmap()
491{
492 /* Determine icon metric: */
493 const int iIconMetric = QApplication::style()->pixelMetric(QStyle::PM_LargeIconSize) * .75;
494 /* Create new tool-pixmap and tool-pixmap size: */
495 const QIcon pinIcon = UIIconPool::iconSet(isFavorite() ? ":/favorite_pressed_24px.png" : ":/favorite_24px.png");
496 AssertReturnVoid(!pinIcon.isNull());
497 const QSize pinPixmapSize = QSize(iIconMetric, iIconMetric);
498 const qreal fDevicePixelRatio = gpManager->windowHandle() ? gpManager->windowHandle()->devicePixelRatio() : 1;
499 const QPixmap pinPixmap = pinIcon.pixmap(pinPixmapSize, fDevicePixelRatio);
500 /* Update linked values: */
501 if (m_pinPixmapSize != pinPixmapSize)
502 {
503 m_pinPixmapSize = pinPixmapSize;
504 updateGeometry();
505 }
506 if (m_pinPixmap.toImage() != pinPixmap.toImage())
507 {
508 m_pinPixmap = pinPixmap;
509 update();
510 }
511}
512
513void UIChooserItemGlobal::updateMinimumNameWidth()
514{
515 /* Calculate new minimum name width: */
516 QPaintDevice *pPaintDevice = model()->paintDevice();
517 const QFontMetrics fm(m_nameFont, pPaintDevice);
518 const int iMinimumNameWidth = fm.horizontalAdvance(compressText(m_nameFont, pPaintDevice, name(),
519 textWidth(m_nameFont, pPaintDevice, 15)));
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.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette