VirtualBox

source: vbox/trunk/src/VBox/Frontends/VirtualBox/src/manager/details/UIDetailsSet.cpp@ 103977

Last change on this file since 103977 was 98103, checked in by vboxsync, 2 years ago

Copyright year updates by scm.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
  • Property svn:mergeinfo set to (toggle deleted branches)
    /branches/VBox-3.0/src/VBox/Frontends/VirtualBox/src/selector/graphics/chooser/UIGChooserItemGroup.cpp58652,​70973
    /branches/VBox-3.2/src/VBox/Frontends/VirtualBox/src/selector/graphics/chooser/UIGChooserItemGroup.cpp66309,​66318
    /branches/VBox-4.0/src/VBox/Frontends/VirtualBox/src/selector/graphics/chooser/UIGChooserItemGroup.cpp70873
    /branches/VBox-4.1/src/VBox/Frontends/VirtualBox/src/selector/graphics/chooser/UIGChooserItemGroup.cpp74233
    /branches/VBox-4.2/src/VBox/Frontends/VirtualBox/src/selector/graphics/details/UIGDetailsSet.cpp91503-91504,​91506-91508,​91510,​91514-91515,​91521
    /branches/VBox-4.3/src/VBox/Frontends/VirtualBox/src/selector/graphics/details/UIGDetailsSet.cpp91223
    /branches/VBox-4.3/trunk/src/VBox/Frontends/VirtualBox/src/selector/graphics/details/UIGDetailsSet.cpp91223
    /branches/dsen/gui/src/VBox/Frontends/VirtualBox/src/selector/graphics/chooser/UIGChooserItemGroup.cpp79076-79078,​79089,​79109-79110,​79112-79113,​79127-79130,​79134,​79141,​79151,​79155,​79157-79159,​79193,​79197
    /branches/dsen/gui2/src/VBox/Frontends/VirtualBox/src/selector/graphics/details/UIGDetailsSet.cpp79562-79569,​79572-79573,​79578,​79581-79582,​79590-79591,​79598-79599,​79602-79603,​79605-79606,​79632,​79635,​79637,​79644
    /branches/dsen/gui3/src/VBox/Frontends/VirtualBox/src/selector/graphics/details/UIGDetailsSet.cpp79645-79692
    /trunk/src/VBox/Frontends/VirtualBox/src/selector/graphics/chooser/UIGChooserItemGroup.cpp79225,​79271
File size: 25.8 KB
Line 
1/* $Id: UIDetailsSet.cpp 98103 2023-01-17 14:15:46Z vboxsync $ */
2/** @file
3 * VBox Qt GUI - UIDetailsSet 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 <QPainter>
30#include <QStyle>
31#include <QStyleOptionGraphicsItem>
32
33/* GUI includes: */
34#include "UICommon.h"
35#include "UIDetailsElements.h"
36#include "UIDetailsModel.h"
37#include "UIDetailsSet.h"
38#include "UIMedium.h"
39#include "UIVirtualBoxEventHandler.h"
40#include "UIVirtualMachineItemCloud.h"
41#include "UIVirtualMachineItemLocal.h"
42
43/* COM includes: */
44#include "CUSBController.h"
45#include "CUSBDeviceFilters.h"
46
47
48UIDetailsSet::UIDetailsSet(UIDetailsItem *pParent)
49 : UIDetailsItem(pParent)
50 , m_pMachineItem(0)
51 , m_fFullSet(true)
52 , m_fIsLocal(true)
53 , m_fHasDetails(false)
54 , m_configurationAccessLevel(ConfigurationAccessLevel_Null)
55 , m_pBuildStep(0)
56 , m_iBackgroundDarknessStart(115)
57 , m_iBackgroundDarknessFinal(150)
58{
59 /* Add set to the parent group: */
60 parentItem()->addItem(this);
61
62 /* Prepare set: */
63 prepareSet();
64
65 /* Prepare connections: */
66 prepareConnections();
67}
68
69UIDetailsSet::~UIDetailsSet()
70{
71 /* Cleanup items: */
72 clearItems();
73
74 /* Remove set from the parent group: */
75 parentItem()->removeItem(this);
76}
77
78void UIDetailsSet::clearSet()
79{
80 /* Clear passed arguments: */
81 m_pMachineItem = 0;
82 m_comMachine = CMachine();
83 m_comCloudMachine = CCloudMachine();
84}
85
86void UIDetailsSet::buildSet(UIVirtualMachineItem *pMachineItem, bool fFullSet, const QMap<DetailsElementType, bool> &settings)
87{
88 /* Remember passed arguments: */
89 m_pMachineItem = pMachineItem;
90 m_fIsLocal = m_pMachineItem->itemType() == UIVirtualMachineItemType_Local;
91 m_fHasDetails = m_pMachineItem->hasDetails();
92 m_fFullSet = fFullSet;
93 m_settings = settings;
94
95 /* Prepare a list of types to build: */
96 QList<DetailsElementType> types;
97
98 /* Make sure we have details: */
99 if (m_fHasDetails)
100 {
101 /* Special handling wrt item type: */
102 switch (m_pMachineItem->itemType())
103 {
104 case UIVirtualMachineItemType_Local:
105 {
106 /* Get local machine: */
107 m_comMachine = m_pMachineItem->toLocal()->machine();
108
109 /* Compose a list of types to build: */
110 if (m_fFullSet)
111 types << DetailsElementType_General << DetailsElementType_System << DetailsElementType_Preview
112 << DetailsElementType_Display << DetailsElementType_Storage << DetailsElementType_Audio
113 << DetailsElementType_Network << DetailsElementType_Serial << DetailsElementType_USB
114 << DetailsElementType_SF << DetailsElementType_UI << DetailsElementType_Description;
115 else
116 types << DetailsElementType_General << DetailsElementType_System << DetailsElementType_Preview;
117
118 /* Take into account USB controller restrictions: */
119 const CUSBDeviceFilters &filters = m_comMachine.GetUSBDeviceFilters();
120 if (filters.isNull() || !m_comMachine.GetUSBProxyAvailable())
121 m_settings.remove(DetailsElementType_USB);
122
123 break;
124 }
125 case UIVirtualMachineItemType_CloudReal:
126 {
127 /* Get cloud machine: */
128 m_comCloudMachine = m_pMachineItem->toCloud()->machine();
129
130 /* Compose a list of types to build: */
131 types << DetailsElementType_General;
132
133 break;
134 }
135 default:
136 break;
137 }
138 }
139
140 /* Cleanup if new types differs from old: */
141 if (m_types != types)
142 {
143 clearItems();
144 m_elements.clear();
145 updateGeometry();
146 }
147
148 /* Remember new types: */
149 m_types = types;
150
151 /* Build or emit fake signal: */
152 if (m_fHasDetails)
153 rebuildSet();
154 else
155 emit sigBuildDone();
156}
157
158void UIDetailsSet::updateLayout()
159{
160 /* Prepare variables: */
161 const int iMargin = data(SetData_Margin).toInt();
162 const int iSpacing = data(SetData_Spacing).toInt();
163 const int iMaximumWidth = geometry().width();
164 UIDetailsElement *pPreviewElement = element(DetailsElementType_Preview);
165 const bool fPreviewVisible = pPreviewElement && pPreviewElement->isVisible();
166 const int iPreviewWidth = fPreviewVisible ? pPreviewElement->minimumWidthHint() : 0;
167 const int iPreviewHeight = fPreviewVisible ? pPreviewElement->minimumHeightHint() : 0;
168 int iVerticalIndent = iMargin;
169 int iPreviewGroupHeight = 0;
170 bool fPreviewGroupUnfinished = fPreviewVisible;
171 QList<UIDetailsElement*> listPreviewGroup;
172 m_listPreviewGroup.clear();
173 m_listOutsideGroup.clear();
174
175 /* Layout all the items but Preview: */
176 foreach (UIDetailsItem *pItem, items())
177 {
178 /* Make sure item exists: */
179 AssertPtrReturnVoid(pItem);
180 /* Skip item if hidden: */
181 if (!pItem->isVisible())
182 continue;
183
184 /* Acquire element type: */
185 UIDetailsElement *pElement = pItem->toElement();
186 AssertPtrReturnVoid(pElement);
187 const DetailsElementType enmElementType = pElement->elementType();
188 /* Skip Preview element: */
189 if (enmElementType == DetailsElementType_Preview)
190 continue;
191
192 /* Calculate element size: */
193 QSizeF elementSize;
194
195 /* If we haven't finished filling Preview group: */
196 if (fPreviewGroupUnfinished)
197 {
198 /* For Preview group we have limited element width: */
199 elementSize.setWidth(iMaximumWidth - (iSpacing + iPreviewWidth));
200 /* Resize element to width to get corresponding height: */
201 pElement->resize(elementSize.width(), pElement->geometry().height());
202 /* Now we can get element height based on width above: */
203 elementSize.setHeight(pElement->minimumHeightHint());
204 /* Resize element to height based on width above: */
205 pElement->resize(pElement->geometry().width(), elementSize.height());
206
207 /* Calculate remaining vertical space: */
208 const int iRemainingSpace = (iPreviewHeight + iSpacing) - iPreviewGroupHeight;
209
210 /* If last element height is at least two times taller than the remaining space: */
211 if (elementSize.height() / 2 > iRemainingSpace)
212 {
213 /* We should stop filling Preview group now: */
214 fPreviewGroupUnfinished = false;
215
216 /* Advance indent only if there is remaining space at all: */
217 if (iRemainingSpace > 0)
218 iVerticalIndent += iRemainingSpace;
219 }
220 /* Otherwise last element can still be inserted to Preview group: */
221 else
222 {
223 /* Advance Preview group height: */
224 iPreviewGroupHeight += (elementSize.height() + iSpacing);
225 /* Append last Preview group element: */
226 listPreviewGroup << pElement;
227 m_listPreviewGroup << enmElementType;
228 }
229 }
230
231 /* If we have finished filling Preview group: */
232 if (!fPreviewGroupUnfinished)
233 {
234 /* Calculate element width: */
235 elementSize.setWidth(iMaximumWidth);
236 /* Resize element to width to get corresponding height: */
237 pElement->resize(elementSize.width(), pElement->geometry().height());
238 /* Now we can get element height based on width above: */
239 elementSize.setHeight(pElement->minimumHeightHint());
240 /* Resize element to height based on width above: */
241 pElement->resize(pElement->geometry().width(), elementSize.height());
242 /* Append last Outside group element: */
243 m_listOutsideGroup << enmElementType;
244 }
245
246 /* Move element: */
247 pElement->setPos(0, iVerticalIndent);
248 /* Layout element content: */
249 pElement->updateLayout();
250
251 /* Advance indent: */
252 iVerticalIndent += (elementSize.height() + iSpacing);
253 }
254
255 /* Make sure last opened Preview group item, if exists, consumes rest of vertical space: */
256 if (!listPreviewGroup.isEmpty())
257 {
258 /* Calculate remaining vertical space: */
259 const int iRemainingSpace = (iPreviewHeight + iSpacing) - iPreviewGroupHeight;
260 if (iRemainingSpace > 0)
261 {
262 /* Look for last opened element: */
263 int iLastOpenedElement = -1;
264 foreach (UIDetailsElement *pElement, listPreviewGroup)
265 if (pElement->isOpened())
266 iLastOpenedElement = listPreviewGroup.indexOf(pElement);
267
268 /* If at least one is opened: */
269 if (iLastOpenedElement != -1)
270 {
271 /* Resize element to width to get corresponding height: */
272 UIDetailsElement *pFoundOne = listPreviewGroup.at(iLastOpenedElement);
273 pFoundOne->resize(pFoundOne->geometry().width(), pFoundOne->geometry().height() + iRemainingSpace);
274
275 /* Adjust subsequent element positions: */
276 for (int i = iLastOpenedElement + 1; i < listPreviewGroup.size(); ++i)
277 {
278 UIDetailsElement *pIteratedOne = listPreviewGroup.at(i);
279 pIteratedOne->setPos(pIteratedOne->geometry().x(), pIteratedOne->geometry().y() + iRemainingSpace);
280 }
281
282 /* Layout element content: */
283 pFoundOne->updateLayout();
284 }
285 }
286 }
287
288 /* If Preview exists: */
289 if (fPreviewVisible)
290 {
291 /* Align it to the right corner if there is at least one element in the Preview group.
292 * Otherwise we can put it to the left corner to be able to take whole the space. */
293 if (!listPreviewGroup.isEmpty())
294 pPreviewElement->setPos(iMaximumWidth - iPreviewWidth, iMargin);
295 else
296 pPreviewElement->setPos(0, iMargin);
297
298 /* Resize it to it's size if there is at least one element in the Preview group.
299 * Otherwise we can take whole the horizontal space we have. */
300 int iWidth = iPreviewWidth;
301 int iHeight = iPreviewHeight;
302 if (listPreviewGroup.isEmpty())
303 iWidth = iMaximumWidth;
304 if (!pPreviewElement->isAnimationRunning() && !pPreviewElement->isClosed())
305 iHeight += iPreviewGroupHeight - (iPreviewHeight + iSpacing);
306 pPreviewElement->resize(iWidth, iHeight);
307
308 /* Layout element content: */
309 pPreviewElement->updateLayout();
310 }
311
312 /* Set layout update procedure cause hints to be invalidated,
313 * so we have to update geometry to recalculate them: */
314 updateGeometry();
315}
316
317void UIDetailsSet::sltBuildStep(const QUuid &uStepId, int iStepNumber)
318{
319 /* Cleanup build-step: */
320 delete m_pBuildStep;
321 m_pBuildStep = 0;
322
323 /* Is step id valid? */
324 if (uStepId != m_uSetId)
325 return;
326
327 /* Step number feats the bounds: */
328 if (iStepNumber >= 0 && iStepNumber < m_types.size())
329 {
330 /* Load details settings: */
331 const DetailsElementType enmElementType = m_types.at(iStepNumber);
332 /* Should the element be visible? */
333 bool fVisible = m_settings.contains(enmElementType);
334 /* Should the element be opened? */
335 bool fOpen = fVisible && m_settings[enmElementType];
336
337 /* Check if element is present already: */
338 UIDetailsElement *pElement = element(enmElementType);
339 if (pElement && fOpen)
340 pElement->open(false);
341 /* Create element if necessary: */
342 bool fJustCreated = false;
343 if (!pElement)
344 {
345 fJustCreated = true;
346 pElement = createElement(enmElementType, fOpen);
347 }
348
349 /* Show element if necessary: */
350 if (fVisible && !pElement->isVisible())
351 {
352 /* Show the element: */
353 pElement->show();
354 /* Recursively update size-hint: */
355 pElement->updateGeometry();
356 /* Update layout: */
357 model()->updateLayout();
358 }
359 /* Hide element if necessary: */
360 else if (!fVisible && pElement->isVisible())
361 {
362 /* Hide the element: */
363 pElement->hide();
364 /* Recursively update size-hint: */
365 updateGeometry();
366 /* Update layout: */
367 model()->updateLayout();
368 }
369 /* Update model if necessary: */
370 else if (fJustCreated)
371 model()->updateLayout();
372
373 /* For visible element: */
374 if (pElement->isVisible())
375 {
376 /* Create next build-step: */
377 m_pBuildStep = new UIPrepareStep(this, pElement, uStepId, iStepNumber + 1);
378
379 /* Build element: */
380 pElement->updateAppearance();
381 }
382 /* For invisible element: */
383 else
384 {
385 /* Just build next step: */
386 sltBuildStep(uStepId, iStepNumber + 1);
387 }
388 }
389 /* Step number out of bounds: */
390 else
391 {
392 /* Update model: */
393 model()->updateLayout();
394 /* Repaint all the items: */
395 foreach (UIDetailsItem *pItem, items())
396 pItem->update();
397 /* Notify listener about build done: */
398 emit sigBuildDone();
399 }
400}
401
402void UIDetailsSet::paint(QPainter *pPainter, const QStyleOptionGraphicsItem *pOptions, QWidget *)
403{
404 /* Paint background: */
405 paintBackground(pPainter, pOptions);
406}
407
408QString UIDetailsSet::description() const
409{
410 return tr("Contains the details of virtual machine '%1'").arg(m_pMachineItem->name());
411}
412
413void UIDetailsSet::addItem(UIDetailsItem *pItem)
414{
415 switch (pItem->type())
416 {
417 case UIDetailsItemType_Element:
418 {
419 UIDetailsElement *pElement = pItem->toElement();
420 DetailsElementType type = pElement->elementType();
421 AssertMsg(!m_elements.contains(type), ("Element already added!"));
422 m_elements.insert(type, pItem);
423 break;
424 }
425 default:
426 {
427 AssertMsgFailed(("Invalid item type!"));
428 break;
429 }
430 }
431}
432
433void UIDetailsSet::removeItem(UIDetailsItem *pItem)
434{
435 switch (pItem->type())
436 {
437 case UIDetailsItemType_Element:
438 {
439 UIDetailsElement *pElement = pItem->toElement();
440 DetailsElementType type = pElement->elementType();
441 AssertMsg(m_elements.contains(type), ("Element do not present (type = %d)!", (int)type));
442 m_elements.remove(type);
443 break;
444 }
445 default:
446 {
447 AssertMsgFailed(("Invalid item type!"));
448 break;
449 }
450 }
451}
452
453QList<UIDetailsItem*> UIDetailsSet::items(UIDetailsItemType enmType /* = UIDetailsItemType_Element */) const
454{
455 switch (enmType)
456 {
457 case UIDetailsItemType_Element: return m_elements.values();
458 case UIDetailsItemType_Any: return items(UIDetailsItemType_Element);
459 default: AssertMsgFailed(("Invalid item type!")); break;
460 }
461 return QList<UIDetailsItem*>();
462}
463
464bool UIDetailsSet::hasItems(UIDetailsItemType enmType /* = UIDetailsItemType_Element */) const
465{
466 switch (enmType)
467 {
468 case UIDetailsItemType_Element: return !m_elements.isEmpty();
469 case UIDetailsItemType_Any: return hasItems(UIDetailsItemType_Element);
470 default: AssertMsgFailed(("Invalid item type!")); break;
471 }
472 return false;
473}
474
475void UIDetailsSet::clearItems(UIDetailsItemType enmType /* = UIDetailsItemType_Element */)
476{
477 switch (enmType)
478 {
479 case UIDetailsItemType_Element:
480 {
481 foreach (int iKey, m_elements.keys())
482 delete m_elements[iKey];
483 AssertMsg(m_elements.isEmpty(), ("Set items cleanup failed!"));
484 break;
485 }
486 case UIDetailsItemType_Any:
487 {
488 clearItems(UIDetailsItemType_Element);
489 break;
490 }
491 default:
492 {
493 AssertMsgFailed(("Invalid item type!"));
494 break;
495 }
496 }
497}
498
499UIDetailsElement *UIDetailsSet::element(DetailsElementType enmElementType) const
500{
501 UIDetailsItem *pItem = m_elements.value(enmElementType, 0);
502 if (pItem)
503 return pItem->toElement();
504 return 0;
505}
506
507int UIDetailsSet::minimumWidthHint() const
508{
509 /* Zero if has no details: */
510 if (!hasDetails())
511 return 0;
512
513 /* Prepare variables: */
514 const int iSpacing = data(SetData_Spacing).toInt();
515 int iMinimumWidthHintPreview = 0;
516 int iMinimumWidthHintInGroup = 0;
517 int iMinimumWidthHintOutGroup = 0;
518
519 /* Take into account all the elements: */
520 foreach (UIDetailsItem *pItem, items())
521 {
522 /* Make sure item exists: */
523 AssertPtrReturn(pItem, 0);
524 /* Skip item if hidden: */
525 if (!pItem->isVisible())
526 continue;
527
528 /* Acquire element type: */
529 UIDetailsElement *pElement = pItem->toElement();
530 AssertPtrReturn(pElement, 0);
531 DetailsElementType enmElementType = pElement->elementType();
532
533 /* Calculate corresponding hints: */
534 if (enmElementType == DetailsElementType_Preview)
535 iMinimumWidthHintPreview = pItem->minimumWidthHint();
536 else
537 {
538 if (m_listPreviewGroup.contains(enmElementType))
539 iMinimumWidthHintInGroup = qMax(iMinimumWidthHintInGroup, pItem->minimumWidthHint());
540 else if (m_listOutsideGroup.contains(enmElementType))
541 iMinimumWidthHintOutGroup = qMax(iMinimumWidthHintOutGroup, pItem->minimumWidthHint());
542 }
543 }
544
545 /* Append minimum width of Preview and Preview group: */
546 int iMinimumWidthHint = 0;
547 if (iMinimumWidthHintPreview)
548 iMinimumWidthHint += iMinimumWidthHintPreview;
549 if (iMinimumWidthHintInGroup)
550 iMinimumWidthHint += iMinimumWidthHintInGroup;
551 if (iMinimumWidthHintPreview && iMinimumWidthHintInGroup)
552 iMinimumWidthHint += iSpacing;
553 /* Compare with minimum width of Outside group: */
554 iMinimumWidthHint = qMax(iMinimumWidthHint, iMinimumWidthHintOutGroup);
555 /* Return result: */
556 return iMinimumWidthHint;
557}
558
559int UIDetailsSet::minimumHeightHint() const
560{
561 /* Zero if has no details: */
562 if (!hasDetails())
563 return 0;
564
565 /* Prepare variables: */
566 const int iMargin = data(SetData_Margin).toInt();
567 const int iSpacing = data(SetData_Spacing).toInt();
568 int iMinimumHeightHintPreview = 0;
569 int iMinimumHeightHintInGroup = 0;
570 int iMinimumHeightHintOutGroup = 0;
571
572 /* Take into account all the elements: */
573 foreach (UIDetailsItem *pItem, items())
574 {
575 /* Make sure item exists: */
576 AssertPtrReturn(pItem, 0);
577 /* Skip item if hidden: */
578 if (!pItem->isVisible())
579 continue;
580
581 /* Acquire element type: */
582 UIDetailsElement *pElement = pItem->toElement();
583 AssertPtrReturn(pElement, 0);
584 DetailsElementType enmElementType = pElement->elementType();
585
586 /* Calculate corresponding hints: */
587 if (enmElementType == DetailsElementType_Preview)
588 iMinimumHeightHintPreview += pItem->minimumHeightHint();
589 else
590 {
591 if (m_listPreviewGroup.contains(enmElementType))
592 iMinimumHeightHintInGroup += (pItem->minimumHeightHint() + iSpacing);
593 else if (m_listOutsideGroup.contains(enmElementType))
594 iMinimumHeightHintOutGroup += (pItem->minimumHeightHint() + iSpacing);
595 }
596 }
597 /* Minus last spacing: */
598 if (iMinimumHeightHintInGroup > 0)
599 iMinimumHeightHintInGroup -= iSpacing;
600 if (iMinimumHeightHintOutGroup > 0)
601 iMinimumHeightHintOutGroup -= iSpacing;
602
603 /* Append minimum height of Preview and Preview group: */
604 int iMinimumHeightHint = qMax(iMinimumHeightHintPreview, iMinimumHeightHintInGroup);
605 /* Add spacing if necessary: */
606 if (!m_listPreviewGroup.isEmpty() && !m_listOutsideGroup.isEmpty())
607 iMinimumHeightHint += iSpacing;
608 /* Add Outside group height if necessary: */
609 if (!m_listOutsideGroup.isEmpty())
610 iMinimumHeightHint += iMinimumHeightHintOutGroup;
611 /* And two margins finally: */
612 iMinimumHeightHint += 2 * iMargin;
613 /* Return result: */
614 return iMinimumHeightHint;
615}
616
617void UIDetailsSet::sltMachineStateChange(const QUuid &uId)
618{
619 /* For local VMs only: */
620 if (!m_fIsLocal)
621 return;
622
623 /* Make sure VM is set: */
624 if (m_comMachine.isNull())
625 return;
626
627 /* Is this our VM changed? */
628 if (m_comMachine.GetId() != uId)
629 return;
630
631 /* Update appearance: */
632 rebuildSet();
633}
634
635void UIDetailsSet::sltMachineAttributesChange(const QUuid &uId)
636{
637 /* For local VMs only: */
638 if (!m_fIsLocal)
639 return;
640
641 /* Make sure VM is set: */
642 if (m_comMachine.isNull())
643 return;
644
645 /* Is this our VM changed? */
646 if (m_comMachine.GetId() != uId)
647 return;
648
649 /* Update appearance: */
650 rebuildSet();
651}
652
653void UIDetailsSet::sltMediumEnumerated(const QUuid &uId)
654{
655 /* For local VMs only: */
656 if (!m_fIsLocal)
657 return;
658
659 /* Make sure VM is set: */
660 if (m_comMachine.isNull())
661 return;
662
663 /* Is this our medium changed? */
664 const UIMedium guiMedium = uiCommon().medium(uId);
665 if ( guiMedium.isNull()
666 || !guiMedium.machineIds().contains(m_comMachine.GetId()))
667 return;
668
669 /* Update appearance: */
670 rebuildSet();
671}
672
673void UIDetailsSet::prepareSet()
674{
675 /* Setup size-policy: */
676 setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Fixed);
677}
678
679void UIDetailsSet::prepareConnections()
680{
681 /* Global-events connections: */
682 connect(gVBoxEvents, &UIVirtualBoxEventHandler::sigMachineStateChange, this, &UIDetailsSet::sltMachineStateChange);
683 connect(gVBoxEvents, &UIVirtualBoxEventHandler::sigMachineDataChange, this, &UIDetailsSet::sltMachineAttributesChange);
684 connect(gVBoxEvents, &UIVirtualBoxEventHandler::sigSessionStateChange, this, &UIDetailsSet::sltMachineAttributesChange);
685 connect(gVBoxEvents, &UIVirtualBoxEventHandler::sigSnapshotTake, this, &UIDetailsSet::sltMachineAttributesChange);
686 connect(gVBoxEvents, &UIVirtualBoxEventHandler::sigSnapshotDelete, this, &UIDetailsSet::sltMachineAttributesChange);
687 connect(gVBoxEvents, &UIVirtualBoxEventHandler::sigSnapshotChange, this, &UIDetailsSet::sltMachineAttributesChange);
688 connect(gVBoxEvents, &UIVirtualBoxEventHandler::sigSnapshotRestore, this, &UIDetailsSet::sltMachineAttributesChange);
689
690 /* Meidum-enumeration connections: */
691 connect(&uiCommon(), &UICommon::sigMediumEnumerated, this, &UIDetailsSet::sltMediumEnumerated);
692}
693
694QVariant UIDetailsSet::data(int iKey) const
695{
696 /* Provide other members with required data: */
697 switch (iKey)
698 {
699 /* Layout hints: */
700 case SetData_Margin: return 1;
701 case SetData_Spacing: return 1;
702 /* Default: */
703 default: break;
704 }
705 return QVariant();
706}
707
708void UIDetailsSet::rebuildSet()
709{
710 /* Make sure we have details: */
711 if (!m_fHasDetails)
712 return;
713
714 /* Recache properties: */
715 m_configurationAccessLevel = m_pMachineItem->configurationAccessLevel();
716
717 /* Cleanup build-step: */
718 delete m_pBuildStep;
719 m_pBuildStep = 0;
720
721 /* Generate new set-id: */
722 m_uSetId = QUuid::createUuid();
723
724 /* Request to build first step: */
725 emit sigBuildStep(m_uSetId, 0);
726}
727
728UIDetailsElement *UIDetailsSet::createElement(DetailsElementType enmElementType, bool fOpen)
729{
730 /* Element factory: */
731 switch (enmElementType)
732 {
733 case DetailsElementType_General: return new UIDetailsElementGeneral(this, fOpen);
734 case DetailsElementType_System: return new UIDetailsElementSystem(this, fOpen);
735 case DetailsElementType_Preview: return new UIDetailsElementPreview(this, fOpen);
736 case DetailsElementType_Display: return new UIDetailsElementDisplay(this, fOpen);
737 case DetailsElementType_Storage: return new UIDetailsElementStorage(this, fOpen);
738 case DetailsElementType_Audio: return new UIDetailsElementAudio(this, fOpen);
739 case DetailsElementType_Network: return new UIDetailsElementNetwork(this, fOpen);
740 case DetailsElementType_Serial: return new UIDetailsElementSerial(this, fOpen);
741 case DetailsElementType_USB: return new UIDetailsElementUSB(this, fOpen);
742 case DetailsElementType_SF: return new UIDetailsElementSF(this, fOpen);
743 case DetailsElementType_UI: return new UIDetailsElementUI(this, fOpen);
744 case DetailsElementType_Description: return new UIDetailsElementDescription(this, fOpen);
745 default: AssertFailed(); break; /* Shut up, MSC! */
746 }
747 return 0;
748}
749
750void UIDetailsSet::paintBackground(QPainter *pPainter, const QStyleOptionGraphicsItem *pOptions) const
751{
752 /* Save painter: */
753 pPainter->save();
754
755 /* Prepare variables: */
756 const QRect optionRect = pOptions->rect;
757
758 /* Acquire background color: */
759 const QColor backgroundColor = QApplication::palette().color(QPalette::Active, QPalette::Window);
760
761 /* Paint default background: */
762 QColor bcTone1 = backgroundColor.darker(m_iBackgroundDarknessStart);
763 QColor bcTone2 = backgroundColor.darker(m_iBackgroundDarknessFinal);
764 QLinearGradient gradientDefault(optionRect.topLeft(), optionRect.bottomRight());
765 gradientDefault.setColorAt(0, bcTone1);
766 gradientDefault.setColorAt(1, bcTone2);
767 pPainter->fillRect(optionRect, gradientDefault);
768
769 /* Restore painter: */
770 pPainter->restore();
771}
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