VirtualBox

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

Last change on this file since 103538 was 102836, checked in by vboxsync, 5 months ago

FE/Qt: Chooser pane: A bit of cleanup for cloud VM update processing; More careful manual control over the repeated update scheduling.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 47.0 KB
Line 
1/* $Id: UIChooserItemMachine.cpp 102836 2024-01-11 12:12:42Z vboxsync $ */
2/** @file
3 * VBox Qt GUI - UIChooserItemMachine 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 <QGraphicsSceneDragDropEvent>
30#include <QGraphicsView>
31#include <QPainter>
32#include <QStyleOptionGraphicsItem>
33#include <QWindow>
34
35/* GUI includes: */
36#include "UIChooserItemGroup.h"
37#include "UIChooserItemMachine.h"
38#include "UIChooserModel.h"
39#include "UIChooserNodeGroup.h"
40#include "UIChooserNodeMachine.h"
41#include "UIIconPool.h"
42#include "UIImageTools.h"
43#include "UIVirtualBoxManager.h"
44#include "UIVirtualMachineItemCloud.h"
45#include "UIVirtualMachineItemLocal.h"
46
47
48UIChooserItemMachine::UIChooserItemMachine(UIChooserItem *pParent, UIChooserNodeMachine *pNode)
49 : UIChooserItem(pParent, pNode)
50 , m_iDefaultLightnessStart(0)
51 , m_iDefaultLightnessFinal(0)
52 , m_iHoverLightnessStart(0)
53 , m_iHoverLightnessFinal(0)
54 , m_iHighlightLightnessStart(0)
55 , m_iHighlightLightnessFinal(0)
56 , m_iFirstRowMaximumWidth(0)
57 , m_iMinimumNameWidth(0)
58 , m_iMaximumNameWidth(0)
59 , m_iMinimumSnapshotNameWidth(0)
60 , m_iMaximumSnapshotNameWidth(0)
61{
62 prepare();
63}
64
65UIChooserItemMachine::~UIChooserItemMachine()
66{
67 cleanup();
68}
69
70UIChooserNodeMachine *UIChooserItemMachine::nodeToMachineType() const
71{
72 return node() ? node()->toMachineNode() : 0;
73}
74
75QUuid UIChooserItemMachine::id() const
76{
77 return nodeToMachineType() ? nodeToMachineType()->id() : QUuid();
78}
79
80bool UIChooserItemMachine::accessible() const
81{
82 return nodeToMachineType() ? nodeToMachineType()->accessible() : false;
83}
84
85UIVirtualMachineItem *UIChooserItemMachine::cache() const
86{
87 return nodeToMachineType() ? nodeToMachineType()->cache() : 0;
88}
89
90UIVirtualMachineItemType UIChooserItemMachine::cacheType() const
91{
92 return cache() ? cache()->itemType() : UIVirtualMachineItemType_Invalid;
93}
94
95void UIChooserItemMachine::recache()
96{
97 if (cache())
98 cache()->recache();
99}
100
101bool UIChooserItemMachine::isLockedMachine() const
102{
103 /* For local machines only, others always unlocked: */
104 if (cacheType() != UIVirtualMachineItemType_Local)
105 return false;
106
107 /* Acquire local machine state: */
108 AssertPtrReturn(cache()->toLocal(), true);
109 const KMachineState enmState = cache()->toLocal()->machineState();
110 return enmState != KMachineState_PoweredOff
111 && enmState != KMachineState_Saved
112 && enmState != KMachineState_Teleported
113 && enmState != KMachineState_Aborted
114 && enmState != KMachineState_AbortedSaved;
115}
116
117bool UIChooserItemMachine::isToolButtonArea(const QPoint &position, int iMarginMultiplier /* = 1 */) const
118{
119 const int iFullWidth = geometry().width();
120 const int iFullHeight = geometry().height();
121 const int iMarginHR = data(MachineItemData_MarginHR).toInt();
122 const int iButtonMargin = data(MachineItemData_ButtonMargin).toInt();
123 const int iToolPixmapX = iFullWidth - iMarginHR - 1 - m_toolPixmap.width() / m_toolPixmap.devicePixelRatio();
124 const int iToolPixmapY = (iFullHeight - m_toolPixmap.height() / m_toolPixmap.devicePixelRatio()) / 2;
125 QRect rect = QRect(iToolPixmapX,
126 iToolPixmapY,
127 m_toolPixmap.width() / m_toolPixmap.devicePixelRatio(),
128 m_toolPixmap.height() / m_toolPixmap.devicePixelRatio());
129 rect.adjust(-iMarginMultiplier * iButtonMargin, -iMarginMultiplier * iButtonMargin,
130 iMarginMultiplier * iButtonMargin, iMarginMultiplier * iButtonMargin);
131 return rect.contains(position);
132}
133
134/* static */
135QString UIChooserItemMachine::className()
136{
137 return "UIChooserItemMachine";
138}
139
140/* static */
141void UIChooserItemMachine::enumerateMachineItems(const QList<UIChooserItem*> &il,
142 QList<UIChooserItemMachine*> &ol,
143 int iEnumerationFlags /* = 0 */)
144{
145 /* Enumerate all the passed items: */
146 foreach (UIChooserItem *pItem, il)
147 {
148 /* If that is machine-item: */
149 AssertPtrReturnVoid(pItem);
150 if (pItem->type() == UIChooserNodeType_Machine)
151 {
152 /* Get the iterated machine-item: */
153 UIChooserItemMachine *pMachineItem = pItem->toMachineItem();
154 AssertPtrReturnVoid(pMachineItem);
155 /* Skip if exactly this item is already enumerated: */
156 if (ol.contains(pMachineItem))
157 continue;
158 /* Skip if item with same ID is already enumerated but we need unique: */
159 if ((iEnumerationFlags & UIChooserItemMachineEnumerationFlag_Unique) &&
160 checkIfContains(ol, pMachineItem))
161 continue;
162 /* Skip if this item is accessible and we no need it: */
163 if ((iEnumerationFlags & UIChooserItemMachineEnumerationFlag_Inaccessible) &&
164 pMachineItem->accessible())
165 continue;
166 /* Add it: */
167 ol << pMachineItem;
168 }
169 /* If that is group-item: */
170 else if (pItem->type() == UIChooserNodeType_Group)
171 {
172 /* Enumerate all the machine-items recursively: */
173 enumerateMachineItems(pItem->items(UIChooserNodeType_Machine), ol, iEnumerationFlags);
174 /* Enumerate all the group-items recursively: */
175 enumerateMachineItems(pItem->items(UIChooserNodeType_Group), ol, iEnumerationFlags);
176 }
177 }
178}
179
180void UIChooserItemMachine::retranslateUi()
181{
182}
183
184void UIChooserItemMachine::showEvent(QShowEvent *pEvent)
185{
186 /* Call to base-class: */
187 UIChooserItem::showEvent(pEvent);
188
189 /* Recache and update pixmaps: */
190 AssertPtrReturnVoid(cache());
191 cache()->recachePixmap();
192 updatePixmaps();
193}
194
195void UIChooserItemMachine::resizeEvent(QGraphicsSceneResizeEvent *pEvent)
196{
197 /* Call to base-class: */
198 UIChooserItem::resizeEvent(pEvent);
199
200 /* What is the new geometry? */
201 const QRectF newGeometry = geometry();
202
203 /* Should we update visible name? */
204 if (previousGeometry().width() != newGeometry.width())
205 updateFirstRowMaximumWidth();
206
207 /* Remember the new geometry: */
208 setPreviousGeometry(newGeometry);
209}
210
211void UIChooserItemMachine::mousePressEvent(QGraphicsSceneMouseEvent *pEvent)
212{
213 /* Call to base-class: */
214 UIChooserItem::mousePressEvent(pEvent);
215 /* No drag for inaccessible: */
216 if (!accessible())
217 pEvent->ignore();
218}
219
220void UIChooserItemMachine::paint(QPainter *pPainter, const QStyleOptionGraphicsItem *pOptions, QWidget* /* pWidget = 0 */)
221{
222 /* Acquire rectangle: */
223 const QRect rectangle = pOptions->rect;
224
225 /* Paint background: */
226 paintBackground(pPainter, rectangle);
227 /* Paint frame: */
228 paintFrame(pPainter, rectangle);
229 /* Paint machine info: */
230 paintMachineInfo(pPainter, rectangle);
231}
232
233void UIChooserItemMachine::setSelected(bool fSelected)
234{
235 /* Call to base-class: */
236 UIChooserItem::setSelected(fSelected);
237
238 /* Special treatment for real cloud items: */
239 if (cacheType() == UIVirtualMachineItemType_CloudReal)
240 {
241 UIVirtualMachineItemCloud *pCloudMachineItem = cache()->toCloud();
242 AssertPtrReturnVoid(pCloudMachineItem);
243 const bool fUpdateRequired = fSelected && pCloudMachineItem->accessible();
244 pCloudMachineItem->setUpdateRequiredByLocalReason(fUpdateRequired);
245 if (fUpdateRequired)
246 pCloudMachineItem->updateInfoAsync(false /* delayed? */);
247 }
248}
249
250void UIChooserItemMachine::startEditing()
251{
252 AssertMsgFailed(("Machine graphics item do NOT support editing yet!"));
253}
254
255void UIChooserItemMachine::updateItem()
256{
257 /* Update this machine-item: */
258 updatePixmaps();
259 updateMinimumNameWidth();
260 updateVisibleName();
261 updateMinimumSnapshotNameWidth();
262 updateVisibleSnapshotName();
263 updateStateTextSize();
264 updateToolTip();
265 update();
266
267 /* Update parent group-item: */
268 parentItem()->updateToolTip();
269 parentItem()->update();
270}
271
272void UIChooserItemMachine::updateToolTip()
273{
274 AssertPtrReturnVoid(cache());
275 setToolTip(cache()->toolTipText());
276}
277
278QList<UIChooserItem*> UIChooserItemMachine::items(UIChooserNodeType) const
279{
280 AssertMsgFailed(("Machine graphics item do NOT support children!"));
281 return QList<UIChooserItem*>();
282}
283
284void UIChooserItemMachine::addItem(UIChooserItem*, bool, int)
285{
286 AssertMsgFailed(("Machine graphics item do NOT support children!"));
287}
288
289void UIChooserItemMachine::removeItem(UIChooserItem*)
290{
291 AssertMsgFailed(("Machine graphics item do NOT support children!"));
292}
293
294UIChooserItem* UIChooserItemMachine::searchForItem(const QString &strSearchTag, int iSearchFlags)
295{
296 /* Ignore if we are not searching for the machine-item: */
297 if (!(iSearchFlags & UIChooserItemSearchFlag_Machine))
298 return 0;
299
300 /* Are we searching by the exact ID? */
301 if (iSearchFlags & UIChooserItemSearchFlag_ExactId)
302 {
303 /* Exact ID doesn't match? */
304 if (id() != QUuid(strSearchTag))
305 return 0;
306 }
307 /* Are we searching by the exact name? */
308 else if (iSearchFlags & UIChooserItemSearchFlag_ExactName)
309 {
310 /* Exact name doesn't match? */
311 if (name() != strSearchTag)
312 return 0;
313 }
314 /* Are we searching by the few first symbols? */
315 else
316 {
317 /* Name doesn't start with passed symbols? */
318 if (!name().startsWith(strSearchTag, Qt::CaseInsensitive))
319 return 0;
320 }
321
322 /* Returning this: */
323 return this;
324}
325
326UIChooserItem *UIChooserItemMachine::firstMachineItem()
327{
328 return this;
329}
330
331void UIChooserItemMachine::updateLayout()
332{
333 // Just do nothing ..
334}
335
336int UIChooserItemMachine::minimumWidthHint() const
337{
338 /* Prepare variables: */
339 const int iMarginHL = data(MachineItemData_MarginHL).toInt();
340 const int iMarginHR = data(MachineItemData_MarginHR).toInt();
341 const int iMajorSpacing = data(MachineItemData_MajorSpacing).toInt();
342 const int iMinorSpacing = data(MachineItemData_MinorSpacing).toInt();
343 const int iButtonMargin = data(MachineItemData_ButtonMargin).toInt();
344
345 /* Calculating proposed width: */
346 int iProposedWidth = 0;
347
348 /* Two margins: */
349 iProposedWidth += iMarginHL + iMarginHR;
350 /* And machine-item content to take into account: */
351 int iTopLineWidth = m_iMinimumNameWidth;
352 /* Only local items can have snapshots: */
353 if ( cacheType() == UIVirtualMachineItemType_Local
354 && !cache()->toLocal()->snapshotName().isEmpty())
355 iTopLineWidth += (iMinorSpacing +
356 m_iMinimumSnapshotNameWidth);
357 int iBottomLineWidth = m_statePixmapSize.width() +
358 iMinorSpacing +
359 m_stateTextSize.width();
360 int iMiddleColumnWidth = qMax(iTopLineWidth, iBottomLineWidth);
361 int iMachineItemWidth = m_pixmapSize.width() +
362 iMajorSpacing +
363 iMiddleColumnWidth +
364 iMajorSpacing +
365 m_toolPixmapSize.width() + 2 * iButtonMargin;
366 iProposedWidth += iMachineItemWidth;
367
368 /* Return result: */
369 return iProposedWidth;
370}
371
372int UIChooserItemMachine::minimumHeightHint() const
373{
374 /* Prepare variables: */
375 const int iMarginV = data(MachineItemData_MarginV).toInt();
376 const int iMachineItemTextSpacing = data(MachineItemData_TextSpacing).toInt();
377 const int iButtonMargin = data(MachineItemData_ButtonMargin).toInt();
378
379 /* Calculating proposed height: */
380 int iProposedHeight = 0;
381
382 /* Two margins: */
383 iProposedHeight += 2 * iMarginV;
384 /* And machine-item content to take into account: */
385 int iTopLineHeight = qMax(m_visibleNameSize.height(), m_visibleSnapshotNameSize.height());
386 int iBottomLineHeight = qMax(m_statePixmapSize.height(), m_stateTextSize.height());
387 int iMiddleColumnHeight = iTopLineHeight +
388 iMachineItemTextSpacing +
389 iBottomLineHeight;
390 QList<int> heights;
391 heights << m_pixmapSize.height() << iMiddleColumnHeight << m_toolPixmapSize.height() + 2 * iButtonMargin;
392 int iMaxHeight = 0;
393 foreach (int iHeight, heights)
394 iMaxHeight = qMax(iMaxHeight, iHeight);
395 iProposedHeight += iMaxHeight;
396
397 /* Return result: */
398 return iProposedHeight;
399}
400
401QSizeF UIChooserItemMachine::sizeHint(Qt::SizeHint enmWhich, const QSizeF &constraint /* = QSizeF() */) const
402{
403 /* If Qt::MinimumSize requested: */
404 if (enmWhich == Qt::MinimumSize)
405 return QSizeF(minimumWidthHint(), minimumHeightHint());
406 /* Else call to base-class: */
407 return UIChooserItem::sizeHint(enmWhich, constraint);
408}
409
410QPixmap UIChooserItemMachine::toPixmap()
411{
412 /* Ask item to paint itself into pixmap: */
413 qreal dDpr = gpManager->windowHandle()->devicePixelRatio();
414 QSize actualSize = size().toSize();
415 QPixmap pixmap(actualSize * dDpr);
416 pixmap.setDevicePixelRatio(dDpr);
417 QPainter painter(&pixmap);
418 QStyleOptionGraphicsItem options;
419 options.rect = QRect(QPoint(0, 0), actualSize);
420 paint(&painter, &options);
421 return pixmap;
422}
423
424bool UIChooserItemMachine::isDropAllowed(QGraphicsSceneDragDropEvent *pEvent, UIChooserItemDragToken where) const
425{
426 /* No drops while saving groups: */
427 if (model()->isGroupSavingInProgress())
428 return false;
429 /* If drag token is shown, its up to parent to decide: */
430 if (where != UIChooserItemDragToken_Off)
431 return parentItem()->isDropAllowed(pEvent);
432
433 /* No drops for immutable item: */
434 if (isLockedMachine())
435 return false;
436 /* No drops for inaccessible item: */
437 if (!accessible())
438 return false;
439
440 /* Else we should try to cast mime to known classes: */
441 const QMimeData *pMimeData = pEvent->mimeData();
442 if (pMimeData->hasFormat(UIChooserItemMachine::className()))
443 {
444 /* Get passed machine-item: */
445 const UIChooserItemMimeData *pCastedMimeData = qobject_cast<const UIChooserItemMimeData*>(pMimeData);
446 AssertPtrReturn(pCastedMimeData, false);
447 UIChooserItem *pItem = pCastedMimeData->item();
448 AssertPtrReturn(pItem, false);
449 UIChooserItemMachine *pMachineItem = pItem->toMachineItem();
450 AssertPtrReturn(pMachineItem, false);
451
452 /* No drops for cloud items: */
453 if ( cacheType() != UIVirtualMachineItemType_Local
454 || pMachineItem->cacheType() != UIVirtualMachineItemType_Local)
455 return false;
456 /* No drops for immutable item: */
457 if (pMachineItem->isLockedMachine())
458 return false;
459 /* No drops for the same item: */
460 if (pMachineItem->id() == id())
461 return false;
462
463 /* Allow finally: */
464 return true;
465 }
466 /* That was invalid mime: */
467 return false;
468}
469
470void UIChooserItemMachine::processDrop(QGraphicsSceneDragDropEvent *pEvent, UIChooserItem *pFromWho, UIChooserItemDragToken where)
471{
472 /* Get mime: */
473 const QMimeData *pMime = pEvent->mimeData();
474 /* Make sure this handler called by this item (not by children): */
475 AssertMsg(!pFromWho && where == UIChooserItemDragToken_Off, ("Machine graphics item do NOT support children!"));
476 Q_UNUSED(pFromWho);
477 Q_UNUSED(where);
478 if (pMime->hasFormat(UIChooserItemMachine::className()))
479 {
480 switch (pEvent->proposedAction())
481 {
482 case Qt::MoveAction:
483 case Qt::CopyAction:
484 {
485 /* Remember scene: */
486 UIChooserModel *pModel = model();
487
488 /* Get passed item: */
489 const UIChooserItemMimeData *pCastedMime = qobject_cast<const UIChooserItemMimeData*>(pMime);
490 AssertMsg(pCastedMime, ("Can't cast passed mime-data to UIChooserItemMimeData!"));
491 UIChooserNode *pNode = pCastedMime->item()->node();
492
493 /* Group passed item with current-item into the new group: */
494 UIChooserNodeGroup *pNewGroupNode = new UIChooserNodeGroup(parentItem()->node(),
495 parentItem()->node()->nodes().size(),
496 QUuid() /* id */,
497 UIChooserModel::uniqueGroupName(parentItem()->node()),
498 parentItem()->node()->toGroupNode()->groupType(),
499 true /* opened */);
500 UIChooserItemGroup *pNewGroupItem = new UIChooserItemGroup(parentItem(), pNewGroupNode);
501 UIChooserNodeMachine *pNewMachineNode1 = new UIChooserNodeMachine(pNewGroupNode,
502 pNewGroupNode->nodes().size(),
503 nodeToMachineType());
504 new UIChooserItemMachine(pNewGroupItem, pNewMachineNode1);
505 UIChooserNodeMachine *pNewMachineNode2 = new UIChooserNodeMachine(pNewGroupNode,
506 pNewGroupNode->nodes().size(),
507 pNode->toMachineNode());
508 new UIChooserItemMachine(pNewGroupItem, pNewMachineNode2);
509
510 /* If proposed action is 'move': */
511 if (pEvent->proposedAction() == Qt::MoveAction)
512 {
513 /* Delete passed node: */
514 delete pNode;
515 }
516 /* Delete this node: */
517 delete node();
518
519 /* Update model: */
520 pModel->wipeOutEmptyGroups();
521 pModel->updateNavigationItemList();
522 pModel->updateLayout();
523 pModel->setSelectedItem(pNewGroupItem);
524 pModel->saveGroups();
525 break;
526 }
527 default:
528 break;
529 }
530 }
531}
532
533void UIChooserItemMachine::resetDragToken()
534{
535 /* Reset drag token for this item: */
536 if (dragTokenPlace() != UIChooserItemDragToken_Off)
537 {
538 setDragTokenPlace(UIChooserItemDragToken_Off);
539 update();
540 }
541}
542
543QMimeData* UIChooserItemMachine::createMimeData()
544{
545 return new UIChooserItemMimeData(this);
546}
547
548void UIChooserItemMachine::sltHandleWindowRemapped()
549{
550 /* Recache and update pixmaps: */
551 AssertPtrReturnVoid(cache());
552 cache()->recachePixmap();
553 updatePixmaps();
554}
555
556void UIChooserItemMachine::prepare()
557{
558 /* Color tones: */
559#if defined(VBOX_WS_MAC)
560 m_iDefaultLightnessStart = 120;
561 m_iDefaultLightnessFinal = 110;
562 m_iHoverLightnessStart = 125;
563 m_iHoverLightnessFinal = 115;
564 m_iHighlightLightnessStart = 115;
565 m_iHighlightLightnessFinal = 105;
566#elif defined(VBOX_WS_WIN)
567 m_iDefaultLightnessStart = 120;
568 m_iDefaultLightnessFinal = 110;
569 m_iHoverLightnessStart = 220;
570 m_iHoverLightnessFinal = 210;
571 m_iHighlightLightnessStart = 190;
572 m_iHighlightLightnessFinal = 180;
573#else /* !VBOX_WS_MAC && !VBOX_WS_WIN */
574 m_iDefaultLightnessStart = 110;
575 m_iDefaultLightnessFinal = 100;
576 m_iHoverLightnessStart = 125;
577 m_iHoverLightnessFinal = 115;
578 m_iHighlightLightnessStart = 110;
579 m_iHighlightLightnessFinal = 100;
580#endif /* !VBOX_WS_MAC && !VBOX_WS_WIN */
581
582 /* Fonts: */
583 m_nameFont = font();
584 m_nameFont.setWeight(QFont::Bold);
585 m_snapshotNameFont = font();
586 m_stateTextFont = font();
587
588 /* Sizes: */
589 m_iFirstRowMaximumWidth = 0;
590 m_iMinimumNameWidth = 0;
591 m_iMaximumNameWidth = 0;
592 m_iMinimumSnapshotNameWidth = 0;
593 m_iMaximumSnapshotNameWidth = 0;
594
595 /* Add item to the parent: */
596 AssertPtrReturnVoid(parentItem());
597 parentItem()->addItem(this, isFavorite(), position());
598
599 /* Configure connections: */
600 connect(gpManager, &UIVirtualBoxManager::sigWindowRemapped,
601 this, &UIChooserItemMachine::sltHandleWindowRemapped);
602 connect(model(), &UIChooserModel::sigSelectionChanged,
603 this, &UIChooserItemMachine::sltUpdateFirstRowMaximumWidth);
604 connect(this, &UIChooserItemMachine::sigHoverEnter,
605 this, &UIChooserItemMachine::sltUpdateFirstRowMaximumWidth);
606 connect(this, &UIChooserItemMachine::sigHoverLeave,
607 this, &UIChooserItemMachine::sltUpdateFirstRowMaximumWidth);
608
609 /* Init: */
610 updateItem();
611
612 /* Apply language settings: */
613 retranslateUi();
614}
615
616void UIChooserItemMachine::cleanup()
617{
618 /* If that item is current: */
619 if (model()->currentItem() == this)
620 {
621 /* Unset current-item: */
622 model()->setCurrentItem(0);
623 }
624 /* If that item is in selection list: */
625 if (model()->selectedItems().contains(this))
626 {
627 /* Remove item from the selection list: */
628 model()->removeFromSelectedItems(this);
629 }
630 /* If that item is in navigation list: */
631 if (model()->navigationItems().contains(this))
632 {
633 /* Remove item from the navigation list: */
634 model()->removeFromNavigationItems(this);
635 }
636
637 /* Remove item from the parent: */
638 AssertPtrReturnVoid(parentItem());
639 parentItem()->removeItem(this);
640}
641
642QVariant UIChooserItemMachine::data(int iKey) const
643{
644 /* Provide other members with required data: */
645 switch (iKey)
646 {
647 /* Layout hints: */
648 case MachineItemData_MarginHL: return QApplication::style()->pixelMetric(QStyle::PM_SmallIconSize);
649 case MachineItemData_MarginHR: return QApplication::style()->pixelMetric(QStyle::PM_SmallIconSize) / 4 * 5;
650 case MachineItemData_MarginV: return QApplication::style()->pixelMetric(QStyle::PM_SmallIconSize) / 4 * 3;
651 case MachineItemData_MajorSpacing: return QApplication::style()->pixelMetric(QStyle::PM_SmallIconSize) / 2;
652 case MachineItemData_MinorSpacing: return QApplication::style()->pixelMetric(QStyle::PM_SmallIconSize) / 4;
653 case MachineItemData_TextSpacing: return 0;
654 case MachineItemData_ButtonMargin: return QApplication::style()->pixelMetric(QStyle::PM_SmallIconSize) / 4;
655
656 /* Default: */
657 default: break;
658 }
659 return QVariant();
660}
661
662void UIChooserItemMachine::updatePixmaps()
663{
664 /* Update pixmap: */
665 updatePixmap();
666 /* Update state-pixmap: */
667 updateStatePixmap();
668 /* Update tool-pixmap: */
669 updateToolPixmap();
670}
671
672void UIChooserItemMachine::updatePixmap()
673{
674 /* Get new pixmap and pixmap-size: */
675 AssertPtrReturnVoid(cache());
676 QSize pixmapSize;
677 QPixmap pixmap = cache()->osPixmap(&pixmapSize);
678 /* Update linked values: */
679 if (m_pixmapSize != pixmapSize)
680 {
681 m_pixmapSize = pixmapSize;
682 updateFirstRowMaximumWidth();
683 updateGeometry();
684 }
685 if (m_pixmap.toImage() != pixmap.toImage())
686 {
687 m_pixmap = pixmap;
688 update();
689 }
690}
691
692void UIChooserItemMachine::updateStatePixmap()
693{
694 /* Determine icon metric: */
695 const int iIconMetric = QApplication::style()->pixelMetric(QStyle::PM_SmallIconSize);
696 /* Get new state-pixmap and state-pixmap size: */
697 AssertPtrReturnVoid(cache());
698 const QIcon stateIcon = cache()->machineStateIcon();
699 AssertReturnVoid(!stateIcon.isNull());
700 const QSize statePixmapSize = QSize(iIconMetric, iIconMetric);
701 const qreal fDevicePixelRatio = gpManager->windowHandle() ? gpManager->windowHandle()->devicePixelRatio() : 1;
702 const QPixmap statePixmap = stateIcon.pixmap(statePixmapSize, fDevicePixelRatio);
703 /* Update linked values: */
704 if (m_statePixmapSize != statePixmapSize)
705 {
706 m_statePixmapSize = statePixmapSize;
707 updateGeometry();
708 }
709 if (m_statePixmap.toImage() != statePixmap.toImage())
710 {
711 m_statePixmap = statePixmap;
712 update();
713 }
714}
715
716void UIChooserItemMachine::updateToolPixmap()
717{
718 /* Determine icon metric: */
719 const int iIconMetric = QApplication::style()->pixelMetric(QStyle::PM_LargeIconSize) * .75;
720 /* Create new tool-pixmap and tool-pixmap size: */
721 const QIcon toolIcon = UIIconPool::iconSet(":/tools_menu_24px.png");
722 AssertReturnVoid(!toolIcon.isNull());
723 const QSize toolPixmapSize = QSize(iIconMetric, iIconMetric);
724 const qreal fDevicePixelRatio = gpManager->windowHandle() ? gpManager->windowHandle()->devicePixelRatio() : 1;
725 const QPixmap toolPixmap = toolIcon.pixmap(toolPixmapSize, fDevicePixelRatio);
726 /* Update linked values: */
727 if (m_toolPixmapSize != toolPixmapSize)
728 {
729 m_toolPixmapSize = toolPixmapSize;
730 updateGeometry();
731 }
732 if (m_toolPixmap.toImage() != toolPixmap.toImage())
733 {
734 m_toolPixmap = toolPixmap;
735 update();
736 }
737}
738
739void UIChooserItemMachine::updateFirstRowMaximumWidth()
740{
741 /* Prepare variables: */
742 const int iMarginHL = data(MachineItemData_MarginHL).toInt();
743 const int iMarginHR = data(MachineItemData_MarginHR).toInt();
744 const int iMajorSpacing = data(MachineItemData_MajorSpacing).toInt();
745 const int iButtonMargin = data(MachineItemData_ButtonMargin).toInt();
746
747 /* Calculate new maximum width for the first row: */
748 int iFirstRowMaximumWidth = (int)geometry().width();
749 iFirstRowMaximumWidth -= iMarginHL; /* left margin */
750 iFirstRowMaximumWidth -= m_pixmapSize.width(); /* left pixmap width */
751 iFirstRowMaximumWidth -= iMajorSpacing; /* spacing between left pixmap and name(s) */
752 if ( model()->firstSelectedItem() == this
753 || isHovered())
754 {
755 iFirstRowMaximumWidth -= iMajorSpacing; /* spacing between name(s) and right pixmap */
756 iFirstRowMaximumWidth -= m_toolPixmapSize.width() + 2 * iButtonMargin; /* right pixmap width */
757 }
758 iFirstRowMaximumWidth -= iMarginHR; /* right margin */
759
760 /* Is there something changed? */
761 if (m_iFirstRowMaximumWidth == iFirstRowMaximumWidth)
762 return;
763
764 /* Update linked values: */
765 m_iFirstRowMaximumWidth = iFirstRowMaximumWidth;
766 updateMaximumNameWidth();
767 updateMaximumSnapshotNameWidth();
768}
769
770void UIChooserItemMachine::updateMinimumNameWidth()
771{
772 /* Calculate new minimum name width: */
773 QPaintDevice *pPaintDevice = model()->paintDevice();
774 QFontMetrics fm(m_nameFont, pPaintDevice);
775#if QT_VERSION >= QT_VERSION_CHECK(5, 11, 0)
776 int iMinimumNameWidth = fm.horizontalAdvance(compressText(m_nameFont, pPaintDevice, name(),
777 textWidth(m_nameFont, pPaintDevice, 15)));
778#else
779 int iMinimumNameWidth = fm.width(compressText(m_nameFont, pPaintDevice, name(), textWidth(m_nameFont, pPaintDevice, 15)));
780#endif
781
782 /* Is there something changed? */
783 if (m_iMinimumNameWidth == iMinimumNameWidth)
784 return;
785
786 /* Update linked values: */
787 m_iMinimumNameWidth = iMinimumNameWidth;
788 updateGeometry();
789}
790
791void UIChooserItemMachine::updateMinimumSnapshotNameWidth()
792{
793 /* Calculate new minimum snapshot-name width: */
794 int iMinimumSnapshotNameWidth = 0;
795 /* Is there any snapshot exists? */
796 if ( cacheType() == UIVirtualMachineItemType_Local
797 && !cache()->toLocal()->snapshotName().isEmpty())
798 {
799 QFontMetrics fm(m_snapshotNameFont, model()->paintDevice());
800#if QT_VERSION >= QT_VERSION_CHECK(5, 11, 0)
801 int iBracketWidth = fm.horizontalAdvance("()"); /* bracket width */
802 int iActualTextWidth = fm.horizontalAdvance(cache()->toLocal()->snapshotName()); /* snapshot-name width */
803 int iMinimumTextWidth = fm.horizontalAdvance("..."); /* ellipsis width */
804#else
805 int iBracketWidth = fm.width("()"); /* bracket width */
806 int iActualTextWidth = fm.width(cache()->toLocal()->snapshotName()); /* snapshot-name width */
807 int iMinimumTextWidth = fm.width("..."); /* ellipsis width */
808#endif
809 iMinimumSnapshotNameWidth = iBracketWidth + qMin(iActualTextWidth, iMinimumTextWidth);
810 }
811
812 /* Is there something changed? */
813 if (m_iMinimumSnapshotNameWidth == iMinimumSnapshotNameWidth)
814 return;
815
816 /* Update linked values: */
817 m_iMinimumSnapshotNameWidth = iMinimumSnapshotNameWidth;
818 updateMaximumNameWidth();
819 updateGeometry();
820}
821
822void UIChooserItemMachine::updateMaximumNameWidth()
823{
824 /* Calculate new maximum name width: */
825 int iMaximumNameWidth = m_iFirstRowMaximumWidth;
826 /* Do we have a minimum snapshot-name width? */
827 if (m_iMinimumSnapshotNameWidth != 0)
828 {
829 /* Prepare variables: */
830 int iMinorSpacing = data(MachineItemData_MinorSpacing).toInt();
831 /* Take spacing and snapshot-name into account: */
832 iMaximumNameWidth -= (iMinorSpacing + m_iMinimumSnapshotNameWidth);
833 }
834
835 /* Is there something changed? */
836 if (m_iMaximumNameWidth == iMaximumNameWidth)
837 return;
838
839 /* Update linked values: */
840 m_iMaximumNameWidth = iMaximumNameWidth;
841 updateVisibleName();
842}
843
844void UIChooserItemMachine::updateMaximumSnapshotNameWidth()
845{
846 /* Prepare variables: */
847 int iMinorSpacing = data(MachineItemData_MinorSpacing).toInt();
848
849 /* Calculate new maximum snapshot-name width: */
850 int iMaximumSnapshotNameWidth = m_iFirstRowMaximumWidth;
851 iMaximumSnapshotNameWidth -= (iMinorSpacing + m_visibleNameSize.width());
852
853 /* Is there something changed? */
854 if (m_iMaximumSnapshotNameWidth == iMaximumSnapshotNameWidth)
855 return;
856
857 /* Update linked values: */
858 m_iMaximumSnapshotNameWidth = iMaximumSnapshotNameWidth;
859 updateVisibleSnapshotName();
860}
861
862void UIChooserItemMachine::updateVisibleName()
863{
864 /* Prepare variables: */
865 QPaintDevice *pPaintDevice = model()->paintDevice();
866
867 /* Calculate new visible name and name-size: */
868 QString strVisibleName = compressText(m_nameFont, pPaintDevice, name(), m_iMaximumNameWidth);
869 QSize visibleNameSize = textSize(m_nameFont, pPaintDevice, strVisibleName);
870
871 /* Update linked values: */
872 if (m_visibleNameSize != visibleNameSize)
873 {
874 m_visibleNameSize = visibleNameSize;
875 updateMaximumSnapshotNameWidth();
876 updateGeometry();
877 }
878 if (m_strVisibleName != strVisibleName)
879 {
880 m_strVisibleName = strVisibleName;
881 update();
882 }
883}
884
885void UIChooserItemMachine::updateVisibleSnapshotName()
886{
887 /* Make sure this is local machine item: */
888 if (cacheType() != UIVirtualMachineItemType_Local)
889 return;
890
891 /* Prepare variables: */
892 QPaintDevice *pPaintDevice = model()->paintDevice();
893
894 /* Calculate new visible snapshot-name: */
895#if QT_VERSION >= QT_VERSION_CHECK(5, 11, 0)
896 int iBracketWidth = QFontMetrics(m_snapshotNameFont, pPaintDevice).horizontalAdvance("()");
897#else
898 int iBracketWidth = QFontMetrics(m_snapshotNameFont, pPaintDevice).width("()");
899#endif
900 QString strVisibleSnapshotName = compressText(m_snapshotNameFont, pPaintDevice, cache()->toLocal()->snapshotName(),
901 m_iMaximumSnapshotNameWidth - iBracketWidth);
902 strVisibleSnapshotName = QString("(%1)").arg(strVisibleSnapshotName);
903 QSize visibleSnapshotNameSize = textSize(m_snapshotNameFont, pPaintDevice, strVisibleSnapshotName);
904
905 /* Update linked values: */
906 if (m_visibleSnapshotNameSize != visibleSnapshotNameSize)
907 {
908 m_visibleSnapshotNameSize = visibleSnapshotNameSize;
909 updateGeometry();
910 }
911 if (m_strVisibleSnapshotName != strVisibleSnapshotName)
912 {
913 m_strVisibleSnapshotName = strVisibleSnapshotName;
914 update();
915 }
916}
917
918void UIChooserItemMachine::updateStateTextSize()
919{
920 /* Get new state-text and state-text size: */
921 AssertPtrReturnVoid(cache());
922 const QSize stateTextSize = textSize(m_stateTextFont, model()->paintDevice(), cache()->machineStateName());
923
924 /* Update linked values: */
925 if (m_stateTextSize != stateTextSize)
926 {
927 m_stateTextSize = stateTextSize;
928 updateGeometry();
929 }
930}
931
932void UIChooserItemMachine::paintBackground(QPainter *pPainter, const QRect &rectangle)
933{
934 /* Save painter: */
935 pPainter->save();
936
937 /* Prepare color: */
938 const QPalette pal = QApplication::palette();
939
940 /* Selected-item background: */
941 if (model()->selectedItems().contains(this))
942 {
943 /* Prepare color: */
944 QColor backgroundColor = pal.color(QPalette::Active, QPalette::Highlight);
945 /* Draw gradient: */
946 QLinearGradient bgGrad(rectangle.topLeft(), rectangle.bottomLeft());
947 bgGrad.setColorAt(0, backgroundColor.lighter(m_iHighlightLightnessStart));
948 bgGrad.setColorAt(1, backgroundColor.lighter(m_iHighlightLightnessFinal));
949 pPainter->fillRect(rectangle, bgGrad);
950
951 if (isHovered())
952 {
953 /* Prepare color: */
954 QColor animationColor1 = QColor(Qt::white);
955 QColor animationColor2 = QColor(Qt::white);
956#ifdef VBOX_WS_MAC
957 animationColor1.setAlpha(90);
958#else
959 animationColor1.setAlpha(30);
960#endif
961 animationColor2.setAlpha(0);
962 /* Draw hovered-item animated gradient: */
963 QRect animatedRect = rectangle;
964 animatedRect.setWidth(animatedRect.height());
965 const int iLength = 2 * animatedRect.width() + rectangle.width();
966 const int iShift = - animatedRect.width() + iLength * animatedValue() / 100;
967 animatedRect.moveLeft(iShift);
968 QLinearGradient bgAnimatedGrad(animatedRect.topLeft(), animatedRect.bottomRight());
969 bgAnimatedGrad.setColorAt(0, animationColor2);
970 bgAnimatedGrad.setColorAt(0.1, animationColor2);
971 bgAnimatedGrad.setColorAt(0.5, animationColor1);
972 bgAnimatedGrad.setColorAt(0.9, animationColor2);
973 bgAnimatedGrad.setColorAt(1, animationColor2);
974 pPainter->fillRect(rectangle, bgAnimatedGrad);
975 }
976 }
977 /* Hovered-item background: */
978 else if (isHovered())
979 {
980 /* Prepare color: */
981 QColor backgroundColor = pal.color(QPalette::Active, QPalette::Highlight);
982 /* Draw gradient: */
983 QLinearGradient bgGrad(rectangle.topLeft(), rectangle.bottomLeft());
984 bgGrad.setColorAt(0, backgroundColor.lighter(m_iHoverLightnessStart));
985 bgGrad.setColorAt(1, backgroundColor.lighter(m_iHoverLightnessFinal));
986 pPainter->fillRect(rectangle, bgGrad);
987
988 /* Prepare color: */
989 QColor animationColor1 = QColor(Qt::white);
990 QColor animationColor2 = QColor(Qt::white);
991#ifdef VBOX_WS_MAC
992 animationColor1.setAlpha(120);
993#else
994 animationColor1.setAlpha(50);
995#endif
996 animationColor2.setAlpha(0);
997 /* Draw hovered-item animated gradient: */
998 QRect animatedRect = rectangle;
999 animatedRect.setWidth(animatedRect.height());
1000 const int iLength = 2 * animatedRect.width() + rectangle.width();
1001 const int iShift = - animatedRect.width() + iLength * animatedValue() / 100;
1002 animatedRect.moveLeft(iShift);
1003 QLinearGradient bgAnimatedGrad(animatedRect.topLeft(), animatedRect.bottomRight());
1004 bgAnimatedGrad.setColorAt(0, animationColor2);
1005 bgAnimatedGrad.setColorAt(0.1, animationColor2);
1006 bgAnimatedGrad.setColorAt(0.5, animationColor1);
1007 bgAnimatedGrad.setColorAt(0.9, animationColor2);
1008 bgAnimatedGrad.setColorAt(1, animationColor2);
1009 pPainter->fillRect(rectangle, bgAnimatedGrad);
1010 }
1011 /* Default background: */
1012 else
1013 {
1014 /* Prepare color: */
1015 QColor backgroundColor = pal.color(QPalette::Active, QPalette::Window);
1016 /* Draw gradient: */
1017 QLinearGradient bgGrad(rectangle.topLeft(), rectangle.bottomLeft());
1018 bgGrad.setColorAt(0, backgroundColor.lighter(m_iDefaultLightnessStart));
1019 bgGrad.setColorAt(1, backgroundColor.lighter(m_iDefaultLightnessFinal));
1020 pPainter->fillRect(rectangle, bgGrad);
1021 }
1022
1023 /* Paint drag token UP? */
1024 if (dragTokenPlace() != UIChooserItemDragToken_Off)
1025 {
1026 /* Window color: */
1027 QColor backgroundColor;
1028
1029 QLinearGradient dragTokenGradient;
1030 QRect dragTokenRect = rectangle;
1031 if (dragTokenPlace() == UIChooserItemDragToken_Up)
1032 {
1033 /* Selected-item background: */
1034 if (model()->selectedItems().contains(this))
1035 backgroundColor = pal.color(QPalette::Active, QPalette::Highlight);
1036 /* Default background: */
1037 else
1038 backgroundColor = pal.color(QPalette::Active, QPalette::Window);
1039
1040 dragTokenRect.setHeight(5);
1041 dragTokenGradient.setStart(dragTokenRect.bottomLeft());
1042 dragTokenGradient.setFinalStop(dragTokenRect.topLeft());
1043 }
1044 else if (dragTokenPlace() == UIChooserItemDragToken_Down)
1045 {
1046 /* Selected-item background: */
1047 if (model()->selectedItems().contains(this))
1048 backgroundColor = pal.color(QPalette::Active, QPalette::Highlight);
1049 /* Default background: */
1050 else
1051 backgroundColor = pal.color(QPalette::Active, QPalette::Window);
1052
1053 dragTokenRect.setTopLeft(dragTokenRect.bottomLeft() - QPoint(0, 4));
1054 dragTokenGradient.setStart(dragTokenRect.topLeft());
1055 dragTokenGradient.setFinalStop(dragTokenRect.bottomLeft());
1056 }
1057 QColor color1 = backgroundColor;
1058 QColor color2 = backgroundColor;
1059 color1.setAlpha(64);
1060 color2.setAlpha(255);
1061 dragTokenGradient.setColorAt(0, color1);
1062 dragTokenGradient.setColorAt(1, color2);
1063 pPainter->fillRect(dragTokenRect, dragTokenGradient);
1064 }
1065
1066 /* Restore painter: */
1067 pPainter->restore();
1068}
1069
1070void UIChooserItemMachine::paintFrame(QPainter *pPainter, const QRect &rectangle)
1071{
1072 /* Only selected and/or hovered item should have a frame: */
1073 if (!model()->selectedItems().contains(this) && !isHovered())
1074 return;
1075
1076 /* Save painter: */
1077 pPainter->save();
1078
1079 /* Prepare color: */
1080 const QPalette pal = QApplication::palette();
1081 QColor strokeColor;
1082
1083 /* Selected-item frame: */
1084 if (model()->selectedItems().contains(this))
1085 strokeColor = pal.color(QPalette::Active, QPalette::Highlight).lighter(m_iHighlightLightnessStart - 40);
1086 /* Hovered-item frame: */
1087 else if (isHovered())
1088 strokeColor = pal.color(QPalette::Active, QPalette::Highlight).lighter(m_iHoverLightnessStart - 40);
1089
1090 /* Create/assign pen: */
1091 QPen pen(strokeColor);
1092 pen.setWidth(0);
1093 pPainter->setPen(pen);
1094
1095 /* Draw borders: */
1096 if (dragTokenPlace() != UIChooserItemDragToken_Up)
1097 pPainter->drawLine(rectangle.topLeft(), rectangle.topRight() + QPoint(1, 0));
1098 if (dragTokenPlace() != UIChooserItemDragToken_Down)
1099 pPainter->drawLine(rectangle.bottomLeft(), rectangle.bottomRight() + QPoint(1, 0));
1100 pPainter->drawLine(rectangle.topLeft(), rectangle.bottomLeft());
1101
1102 /* Restore painter: */
1103 pPainter->restore();
1104}
1105
1106void UIChooserItemMachine::paintMachineInfo(QPainter *pPainter, const QRect &rectangle)
1107{
1108 /* Prepare variables: */
1109 const int iFullWidth = rectangle.width();
1110 const int iFullHeight = rectangle.height();
1111 const int iMarginHL = data(MachineItemData_MarginHL).toInt();
1112 const int iMarginHR = data(MachineItemData_MarginHR).toInt();
1113 const int iMajorSpacing = data(MachineItemData_MajorSpacing).toInt();
1114 const int iMinorSpacing = data(MachineItemData_MinorSpacing).toInt();
1115 const int iMachineItemTextSpacing = data(MachineItemData_TextSpacing).toInt();
1116 const int iButtonMargin = data(MachineItemData_ButtonMargin).toInt();
1117
1118 /* Selected or hovered item foreground: */
1119 if (model()->selectedItems().contains(this) || isHovered())
1120 {
1121 /* Prepare palette: */
1122 const QPalette pal = QApplication::palette();
1123
1124 /* Get background color: */
1125 const QColor highlight = pal.color(QPalette::Active, QPalette::Highlight);
1126 const QColor background = model()->selectedItems().contains(this)
1127 ? highlight.lighter(m_iHighlightLightnessStart)
1128 : highlight.lighter(m_iHoverLightnessStart);
1129
1130 /* Gather foreground color for background one: */
1131 const QColor foreground = suitableForegroundColor(pal, background);
1132 pPainter->setPen(foreground);
1133 }
1134
1135 /* Calculate indents: */
1136 int iLeftColumnIndent = iMarginHL;
1137
1138 /* Paint left column: */
1139 {
1140 /* Prepare variables: */
1141 int iMachinePixmapX = iLeftColumnIndent;
1142 int iMachinePixmapY = (iFullHeight - m_pixmap.height() / m_pixmap.devicePixelRatio()) / 2;
1143 /* Paint pixmap: */
1144 paintPixmap(/* Painter: */
1145 pPainter,
1146 /* Point to paint in: */
1147 QPoint(iMachinePixmapX, iMachinePixmapY),
1148 /* Pixmap to paint: */
1149 m_pixmap);
1150 }
1151
1152 /* Calculate indents: */
1153 int iMiddleColumnIndent = iLeftColumnIndent +
1154 m_pixmapSize.width() +
1155 iMajorSpacing;
1156
1157 /* Paint middle column: */
1158 {
1159 /* Calculate indents: */
1160 int iTopLineHeight = qMax(m_visibleNameSize.height(), m_visibleSnapshotNameSize.height());
1161 int iBottomLineHeight = qMax(m_statePixmapSize.height(), m_stateTextSize.height());
1162 int iRightColumnHeight = iTopLineHeight + iMachineItemTextSpacing + iBottomLineHeight;
1163 int iTopLineIndent = (iFullHeight - iRightColumnHeight) / 2 - 1;
1164
1165 /* Paint top line: */
1166 {
1167 /* Paint left element: */
1168 {
1169 /* Prepare variables: */
1170 int iNameX = iMiddleColumnIndent;
1171 int iNameY = iTopLineIndent;
1172 /* Paint name: */
1173 paintText(/* Painter: */
1174 pPainter,
1175 /* Point to paint in: */
1176 QPoint(iNameX, iNameY),
1177 /* Font to paint text: */
1178 m_nameFont,
1179 /* Paint device: */
1180 model()->paintDevice(),
1181 /* Text to paint: */
1182 m_strVisibleName);
1183 }
1184
1185 /* Calculate indents: */
1186 int iSnapshotNameIndent = iMiddleColumnIndent +
1187 m_visibleNameSize.width() +
1188 iMinorSpacing;
1189
1190 /* Paint middle element: */
1191 if ( cacheType() == UIVirtualMachineItemType_Local
1192 && !cache()->toLocal()->snapshotName().isEmpty())
1193 {
1194 /* Prepare variables: */
1195 int iSnapshotNameX = iSnapshotNameIndent;
1196 int iSnapshotNameY = iTopLineIndent;
1197 /* Paint snapshot-name: */
1198 paintText(/* Painter: */
1199 pPainter,
1200 /* Point to paint in: */
1201 QPoint(iSnapshotNameX, iSnapshotNameY),
1202 /* Font to paint text: */
1203 m_snapshotNameFont,
1204 /* Paint device: */
1205 model()->paintDevice(),
1206 /* Text to paint: */
1207 m_strVisibleSnapshotName);
1208 }
1209 }
1210
1211 /* Calculate indents: */
1212 int iBottomLineIndent = iTopLineIndent + iTopLineHeight + 1;
1213
1214 /* Paint bottom line: */
1215 {
1216 /* Paint left element: */
1217 {
1218 /* Prepare variables: */
1219 int iMachineStatePixmapX = iMiddleColumnIndent;
1220 int iMachineStatePixmapY = iBottomLineIndent;
1221 /* Paint state pixmap: */
1222 paintPixmap(/* Painter: */
1223 pPainter,
1224 /* Point to paint in: */
1225 QPoint(iMachineStatePixmapX, iMachineStatePixmapY),
1226 /* Pixmap to paint: */
1227 m_statePixmap);
1228 }
1229
1230 /* Calculate indents: */
1231 int iMachineStateTextIndent = iMiddleColumnIndent +
1232 m_statePixmapSize.width() +
1233 iMinorSpacing;
1234
1235 /* Paint right element: */
1236 {
1237 /* Prepare variables: */
1238 int iMachineStateTextX = iMachineStateTextIndent;
1239 int iMachineStateTextY = iBottomLineIndent + 1;
1240 /* Paint state text: */
1241 AssertPtrReturnVoid(cache());
1242 paintText(/* Painter: */
1243 pPainter,
1244 /* Point to paint in: */
1245 QPoint(iMachineStateTextX, iMachineStateTextY),
1246 /* Font to paint text: */
1247 m_stateTextFont,
1248 /* Paint device: */
1249 model()->paintDevice(),
1250 /* Text to paint: */
1251 cache()->machineStateName());
1252 }
1253 }
1254 }
1255
1256 /* Calculate indents: */
1257 QGraphicsView *pView = model()->scene()->views().first();
1258 const QPointF sceneCursorPosition = pView->mapToScene(pView->mapFromGlobal(QCursor::pos()));
1259 const QPoint itemCursorPosition = mapFromScene(sceneCursorPosition).toPoint();
1260 int iRightColumnIndent = iFullWidth - iMarginHR - 1 - m_toolPixmap.width() / m_toolPixmap.devicePixelRatio();
1261
1262 /* Paint right column: */
1263 if ( model()->firstSelectedItem() == this
1264 || isHovered())
1265 {
1266 /* Prepare variables: */
1267 const int iToolPixmapX = iRightColumnIndent;
1268 const int iToolPixmapY = (iFullHeight - m_toolPixmap.height() / m_toolPixmap.devicePixelRatio()) / 2;
1269 QRect toolButtonRectangle = QRect(iToolPixmapX,
1270 iToolPixmapY,
1271 m_toolPixmap.width() / m_toolPixmap.devicePixelRatio(),
1272 m_toolPixmap.height() / m_toolPixmap.devicePixelRatio());
1273 toolButtonRectangle.adjust(- iButtonMargin, -iButtonMargin, iButtonMargin, iButtonMargin);
1274
1275 /* Paint tool button: */
1276 if ( isHovered()
1277 && isToolButtonArea(itemCursorPosition, 4))
1278 paintFlatButton(/* Painter: */
1279 pPainter,
1280 /* Button rectangle: */
1281 toolButtonRectangle,
1282 /* Cursor position: */
1283 itemCursorPosition);
1284
1285 /* Paint pixmap: */
1286 paintPixmap(/* Painter: */
1287 pPainter,
1288 /* Point to paint in: */
1289 QPoint(iToolPixmapX, iToolPixmapY),
1290 /* Pixmap to paint: */
1291 m_toolPixmap);
1292 }
1293}
1294
1295/* static */
1296bool UIChooserItemMachine::checkIfContains(const QList<UIChooserItemMachine*> &list, UIChooserItemMachine *pItem)
1297{
1298 /* Check if passed list contains passed machine-item id: */
1299 foreach (UIChooserItemMachine *pIteratedItem, list)
1300 if (pIteratedItem->id() == pItem->id())
1301 return true;
1302 /* Found nothing? */
1303 return false;
1304}
Note: See TracBrowser for help on using the repository browser.

© 2023 Oracle
ContactPrivacy policyTerms of Use