VirtualBox

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