VirtualBox

source: vbox/trunk/src/VBox/Frontends/VirtualBox/src/extradata/UIExtraDataManager.cpp@ 82781

Last change on this file since 82781 was 81612, checked in by vboxsync, 5 years ago

FE/Qt: Extra-data Manager stuff: A group of fixes for r134303.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 181.4 KB
Line 
1/* $Id: UIExtraDataManager.cpp 81612 2019-10-31 18:20:11Z vboxsync $ */
2/** @file
3 * VBox Qt GUI - UIExtraDataManager class implementation.
4 */
5
6/*
7 * Copyright (C) 2010-2019 Oracle Corporation
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.virtualbox.org. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License (GPL) as published by the Free Software
13 * Foundation, in version 2 as it comes in the "COPYING" file of the
14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16 */
17
18/* Qt includes: */
19#include <QFontDatabase>
20#include <QMetaEnum>
21#include <QMutex>
22#include <QRegularExpression>
23#ifdef VBOX_GUI_WITH_EXTRADATA_MANAGER_UI
24# include <QComboBox>
25# include <QHeaderView>
26# include <QLabel>
27# include <QLineEdit>
28# include <QListView>
29# include <QMainWindow>
30# include <QMenuBar>
31# include <QPainter>
32# include <QPushButton>
33# include <QSortFilterProxyModel>
34# include <QStyledItemDelegate>
35# include <QTableView>
36# include <QVBoxLayout>
37# include <QStandardItemModel>
38# include <QXmlStreamWriter>
39# include <QXmlStreamReader>
40#endif /* VBOX_GUI_WITH_EXTRADATA_MANAGER_UI */
41
42/* GUI includes: */
43#include "UICommon.h"
44#include "UIActionPool.h"
45#include "UIConverter.h"
46#include "UIDesktopWidgetWatchdog.h"
47#include "UIExtraDataManager.h"
48#include "UIHostComboEditor.h"
49#include "UIMainEventListener.h"
50#include "UIMessageCenter.h"
51#include "UISettingsDefs.h"
52#ifdef VBOX_GUI_WITH_EXTRADATA_MANAGER_UI
53# include "QIDialog.h"
54# include "QIDialogButtonBox.h"
55# include "QIFileDialog.h"
56# include "QISplitter.h"
57# include "QIWidgetValidator.h"
58# include "QIWithRestorableGeometry.h"
59# include "VBoxUtils.h"
60# include "UIIconPool.h"
61# include "UIToolBar.h"
62# include "UIVirtualBoxEventHandler.h"
63#endif /* VBOX_GUI_WITH_EXTRADATA_MANAGER_UI */
64
65/* COM includes: */
66#include "COMEnums.h"
67#include "CEventListener.h"
68#include "CEventSource.h"
69#include "CMachine.h"
70#include "CVirtualBox.h"
71
72
73/* Namespaces: */
74using namespace UIExtraDataDefs;
75using namespace UISettingsDefs;
76
77
78/** Private QObject extension
79 * providing UIExtraDataManager with the CVirtualBox event-source. */
80class UIExtraDataEventHandler : public QObject
81{
82 Q_OBJECT;
83
84signals:
85
86 /** Notifies about 'extra-data change' event: */
87 void sigExtraDataChange(const QUuid &uMachineID, const QString &strKey, const QString &strValue);
88
89public:
90
91 /** Constructs event proxy object on the basis of passed @a pParent. */
92 UIExtraDataEventHandler(QObject *pParent);
93 /** Destructs event proxy object. */
94 ~UIExtraDataEventHandler();
95
96protected slots:
97
98 /** Preprocess 'extra-data can change' event: */
99 void sltPreprocessExtraDataCanChange(const QUuid &uMachineID, const QString &strKey, const QString &strValue, bool &fVeto, QString &strVetoReason);
100 /** Preprocess 'extra-data change' event: */
101 void sltPreprocessExtraDataChange(const QUuid &uMachineID, const QString &strKey, const QString &strValue);
102
103protected:
104
105 /** @name Prepare/Cleanup cascade.
106 * @{ */
107 /** Prepares all. */
108 void prepare();
109 /** Prepares listener. */
110 void prepareListener();
111 /** Prepares connections. */
112 void prepareConnections();
113
114 /** Cleanups connections. */
115 void cleanupConnections();
116 /** Cleanups listener. */
117 void cleanupListener();
118 /** Cleanups all. */
119 void cleanup();
120 /** @} */
121
122private:
123
124 /** Holds the Qt event listener instance. */
125 ComObjPtr<UIMainEventListenerImpl> m_pQtListener;
126 /** Holds the COM event listener instance. */
127 CEventListener m_comEventListener;
128
129 /** Protects sltPreprocessExtraDataChange. */
130 QMutex m_mutex;
131};
132
133
134/*********************************************************************************************************************************
135* Class UIExtraDataEventHandler implementation. *
136*********************************************************************************************************************************/
137
138UIExtraDataEventHandler::UIExtraDataEventHandler(QObject *pParent)
139 : QObject(pParent)
140{
141 /* Prepare: */
142 prepare();
143}
144
145UIExtraDataEventHandler::~UIExtraDataEventHandler()
146{
147 /* Cleanup: */
148 cleanup();
149}
150
151void UIExtraDataEventHandler::prepare()
152{
153 /* Prepare: */
154 prepareListener();
155 prepareConnections();
156}
157
158void UIExtraDataEventHandler::prepareListener()
159{
160 /* Create event listener instance: */
161 m_pQtListener.createObject();
162 m_pQtListener->init(new UIMainEventListener, this);
163 m_comEventListener = CEventListener(m_pQtListener);
164
165 /* Get VirtualBox: */
166 const CVirtualBox comVBox = uiCommon().virtualBox();
167 AssertWrapperOk(comVBox);
168 /* Get VirtualBox event source: */
169 CEventSource comEventSourceVBox = comVBox.GetEventSource();
170 AssertWrapperOk(comEventSourceVBox);
171
172 /* Enumerate all the required event-types: */
173 QVector<KVBoxEventType> eventTypes;
174 eventTypes
175 << KVBoxEventType_OnExtraDataCanChange
176 << KVBoxEventType_OnExtraDataChanged;
177
178 /* Register event listener for VirtualBox event source: */
179 comEventSourceVBox.RegisterListener(m_comEventListener, eventTypes,
180 gEDataManager->eventHandlingType() == EventHandlingType_Active ? TRUE : FALSE);
181 AssertWrapperOk(comEventSourceVBox);
182
183 /* If event listener registered as passive one: */
184 if (gEDataManager->eventHandlingType() == EventHandlingType_Passive)
185 {
186 /* Register event sources in their listeners as well: */
187 m_pQtListener->getWrapped()->registerSource(comEventSourceVBox, m_comEventListener);
188 }
189}
190
191void UIExtraDataEventHandler::prepareConnections()
192{
193 /* Create direct (sync) connections for signals of main listener: */
194 connect(m_pQtListener->getWrapped(), &UIMainEventListener::sigExtraDataCanChange,
195 this, &UIExtraDataEventHandler::sltPreprocessExtraDataCanChange,
196 Qt::DirectConnection);
197 connect(m_pQtListener->getWrapped(), &UIMainEventListener::sigExtraDataChange,
198 this, &UIExtraDataEventHandler::sltPreprocessExtraDataChange,
199 Qt::DirectConnection);
200}
201
202void UIExtraDataEventHandler::cleanupConnections()
203{
204 /* Nothing for now. */
205}
206
207void UIExtraDataEventHandler::cleanupListener()
208{
209 /* If event listener registered as passive one: */
210 if (gEDataManager->eventHandlingType() == EventHandlingType_Passive)
211 {
212 /* Unregister everything: */
213 m_pQtListener->getWrapped()->unregisterSources();
214 }
215
216 /* Make sure VBoxSVC is available: */
217 if (!uiCommon().isVBoxSVCAvailable())
218 return;
219
220 /* Get VirtualBox: */
221 const CVirtualBox comVBox = uiCommon().virtualBox();
222 AssertWrapperOk(comVBox);
223 /* Get VirtualBox event source: */
224 CEventSource comEventSourceVBox = comVBox.GetEventSource();
225 AssertWrapperOk(comEventSourceVBox);
226
227 /* Unregister event listener for VirtualBox event source: */
228 comEventSourceVBox.UnregisterListener(m_comEventListener);
229}
230
231void UIExtraDataEventHandler::cleanup()
232{
233 /* Cleanup: */
234 cleanupConnections();
235 cleanupListener();
236}
237
238void UIExtraDataEventHandler::sltPreprocessExtraDataCanChange(const QUuid &uMachineID, const QString &strKey, const QString &/* strValue */, bool & /* fVeto */, QString & /* strVetoReason */)
239{
240 /* Preprocess global 'extra-data can change' event: */
241 if (uMachineID.isNull())
242 {
243 if (strKey.startsWith("GUI/"))
244 {
245 /* Check whether global extra-data property can be applied: */
246 /// @todo Here can be various extra-data flags handling.
247 // Generally we should check whether one or another flag feats some rule (like reg-exp).
248 // For each required strValue we should set fVeto = true; and fill strVetoReason = "with some text".
249 }
250 }
251}
252
253void UIExtraDataEventHandler::sltPreprocessExtraDataChange(const QUuid &uMachineID, const QString &strKey, const QString &strValue)
254{
255 /* Preprocess global 'extra-data change' event: */
256 if (uMachineID.isNull())
257 {
258 if (strKey.startsWith("GUI/"))
259 {
260 /* Apply global extra-data property: */
261 /// @todo Here can be various extra-data flags handling.
262 // Generally we should push one or another flag to various instances which want to handle
263 // those flags independently from UIExtraDataManager. Remember to process each required strValue
264 // from under the m_mutex lock (since we are in another thread) and unlock that m_mutex afterwards.
265 }
266 }
267
268 /* Motify listener about 'extra-data change' event: */
269 emit sigExtraDataChange(uMachineID, strKey, strValue);
270}
271
272
273#ifdef VBOX_GUI_WITH_EXTRADATA_MANAGER_UI
274
275/** Data fields. */
276enum Field
277{
278 Field_ID = Qt::UserRole + 1,
279 Field_Name,
280 Field_OsTypeID,
281 Field_Known
282};
283
284
285/** QStyledItemDelegate extension
286 * reflecting items of Extra Data Manager window: Chooser pane. */
287class UIChooserPaneDelegate : public QStyledItemDelegate
288{
289 Q_OBJECT;
290
291public:
292
293 /** Constructor. */
294 UIChooserPaneDelegate(QObject *pParent);
295
296private:
297
298 /** Size-hint calculation routine. */
299 QSize sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const;
300
301 /** Paint routine. */
302 void paint(QPainter *pPainter, const QStyleOptionViewItem &option, const QModelIndex &index) const;
303
304 /** Fetch pixmap info for passed QModelIndex. */
305 static void fetchPixmapInfo(const QModelIndex &index, QPixmap &pixmap, QSize &pixmapSize);
306
307 /** Margin. */
308 int m_iMargin;
309 /** Spacing. */
310 int m_iSpacing;
311};
312
313
314/*********************************************************************************************************************************
315* Class UIChooserPaneDelegate implementation. *
316*********************************************************************************************************************************/
317
318UIChooserPaneDelegate::UIChooserPaneDelegate(QObject *pParent)
319 : QStyledItemDelegate(pParent)
320 , m_iMargin(3)
321 , m_iSpacing(3)
322{
323}
324
325QSize UIChooserPaneDelegate::sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const
326{
327 /* Font metrics: */
328 const QFontMetrics &fm = option.fontMetrics;
329 /* Pixmap: */
330 QPixmap pixmap;
331 QSize pixmapSize;
332 fetchPixmapInfo(index, pixmap, pixmapSize);
333
334 /* Calculate width: */
335 const int iWidth = m_iMargin +
336 pixmapSize.width() +
337 2 * m_iSpacing +
338 qMax(fm.width(index.data(Field_Name).toString()),
339 fm.width(index.data(Field_ID).toString())) +
340 m_iMargin;
341 /* Calculate height: */
342 const int iHeight = m_iMargin +
343 qMax(pixmapSize.height(),
344 fm.height() + m_iSpacing + fm.height()) +
345 m_iMargin;
346
347 /* Return result: */
348 return QSize(iWidth, iHeight);
349}
350
351void UIChooserPaneDelegate::paint(QPainter *pPainter, const QStyleOptionViewItem &option, const QModelIndex &index) const
352{
353 /* Item rect: */
354 const QRect &optionRect = option.rect;
355 /* Palette: */
356 const QPalette &palette = option.palette;
357 /* Font metrics: */
358 const QFontMetrics &fm = option.fontMetrics;
359 /* Pixmap: */
360 QPixmap pixmap;
361 QSize pixmapSize;
362 fetchPixmapInfo(index, pixmap, pixmapSize);
363
364 /* If item selected: */
365 if (option.state & QStyle::State_Selected)
366 {
367 /* Fill background with selection color: */
368 QColor highlight = palette.color(option.state & QStyle::State_Active ?
369 QPalette::Active : QPalette::Inactive,
370 QPalette::Highlight);
371 QLinearGradient bgGrad(optionRect.topLeft(), optionRect.bottomLeft());
372 bgGrad.setColorAt(0, highlight.lighter(120));
373 bgGrad.setColorAt(1, highlight);
374 pPainter->fillRect(optionRect, bgGrad);
375 /* Draw focus frame: */
376 QStyleOptionFocusRect focusOption;
377 focusOption.rect = optionRect;
378 QApplication::style()->drawPrimitive(QStyle::PE_FrameFocusRect, &focusOption, pPainter);
379 }
380
381 /* Draw pixmap: */
382 const QPoint pixmapOrigin = optionRect.topLeft() +
383 QPoint(m_iMargin, m_iMargin);
384 pPainter->drawPixmap(pixmapOrigin, pixmap);
385
386 /* Is that known item? */
387 bool fKnown = index.data(Field_Known).toBool();
388 if (fKnown)
389 {
390 pPainter->save();
391 QFont font = pPainter->font();
392 font.setBold(true);
393 pPainter->setFont(font);
394 }
395
396 /* Draw item name: */
397 const QPoint nameOrigin = pixmapOrigin +
398 QPoint(pixmapSize.width(), 0) +
399 QPoint(2 * m_iSpacing, 0) +
400 QPoint(0, fm.ascent());
401 pPainter->drawText(nameOrigin, index.data(Field_Name).toString());
402
403 /* Was that known item? */
404 if (fKnown)
405 pPainter->restore();
406
407 /* Draw item ID: */
408 const QPoint idOrigin = nameOrigin +
409 QPoint(0, m_iSpacing) +
410 QPoint(0, fm.height());
411 pPainter->drawText(idOrigin, index.data(Field_ID).toString());
412}
413
414/* static */
415void UIChooserPaneDelegate::fetchPixmapInfo(const QModelIndex &index, QPixmap &pixmap, QSize &pixmapSize)
416{
417 /* If proper machine ID passed => return corresponding pixmap/size: */
418 if (index.data(Field_ID).toUuid() != UIExtraDataManager::GlobalID)
419 pixmap = uiCommon().vmGuestOSTypePixmapDefault(index.data(Field_OsTypeID).toString(), &pixmapSize);
420 else
421 {
422 /* For global ID we return static pixmap/size: */
423 const QIcon icon = UIIconPool::iconSet(":/edata_global_32px.png");
424 pixmapSize = icon.availableSizes().value(0, QSize(32, 32));
425 pixmap = icon.pixmap(pixmapSize);
426 }
427}
428
429
430/** QSortFilterProxyModel extension
431 * used by the chooser-pane of the UIExtraDataManagerWindow. */
432class UIChooserPaneSortingModel : public QSortFilterProxyModel
433{
434 Q_OBJECT;
435
436public:
437
438 /** Constructor, passes @a pParent to the QIRichToolButton constructor. */
439 UIChooserPaneSortingModel(QObject *pParent) : QSortFilterProxyModel(pParent) {}
440
441protected:
442
443 /** Returns true if the value of the item referred to by the given index left
444 * is less than the value of the item referred to by the given index right,
445 * otherwise returns false. */
446 bool lessThan(const QModelIndex &leftIdx, const QModelIndex &rightIdx) const
447 {
448 /* Compare by ID first: */
449 const QUuid strID1 = leftIdx.data(Field_ID).toUuid();
450 const QUuid strID2 = rightIdx.data(Field_ID).toUuid();
451 if (strID1 == UIExtraDataManager::GlobalID)
452 return true;
453 else if (strID2 == UIExtraDataManager::GlobalID)
454 return false;
455 /* Compare role finally: */
456 return QSortFilterProxyModel::lessThan(leftIdx, rightIdx);
457 }
458};
459
460
461/** QMainWindow extension
462 * providing Extra Data Manager with UI features. */
463class UIExtraDataManagerWindow : public QIWithRestorableGeometry<QMainWindow>
464{
465 Q_OBJECT;
466
467public:
468
469 /** @name Constructor/Destructor
470 * @{ */
471 /** Extra-data Manager Window constructor. */
472 UIExtraDataManagerWindow(QWidget *pCenterWidget);
473 /** Extra-data Manager Window destructor. */
474 ~UIExtraDataManagerWindow();
475 /** @} */
476
477 /** @name Management
478 * @{ */
479 /** Show and raise. */
480 void showAndRaise(QWidget *pCenterWidget);
481 /** @} */
482
483public slots:
484
485 /** @name General
486 * @{ */
487 /** Handles extra-data map acknowledging. */
488 void sltExtraDataMapAcknowledging(const QUuid &uID);
489 /** Handles extra-data change. */
490 void sltExtraDataChange(const QUuid &uID, const QString &strKey, const QString &strValue);
491 /** @} */
492
493private slots:
494
495 /** @name General
496 * @{ */
497 /** Handles machine (un)registration. */
498 void sltMachineRegistered(const QUuid &uID, bool fAdded);
499 /** @} */
500
501 /** @name Chooser-pane
502 * @{ */
503 /** Handles filter-apply signal for the chooser-pane. */
504 void sltChooserApplyFilter(const QString &strFilter);
505 /** Handles current-changed signal for the chooser-pane: */
506 void sltChooserHandleCurrentChanged(const QModelIndex &index);
507 /** Handles item-selection-changed signal for the chooser-pane: */
508 void sltChooserHandleSelectionChanged(const QItemSelection &selected,
509 const QItemSelection &deselected);
510 /** @} */
511
512 /** @name Data-pane
513 * @{ */
514 /** Handles filter-apply signal for the data-pane. */
515 void sltDataApplyFilter(const QString &strFilter);
516 /** Handles item-selection-changed signal for the data-pane: */
517 void sltDataHandleSelectionChanged(const QItemSelection &selected,
518 const QItemSelection &deselected);
519 /** Handles item-changed signal for the data-pane: */
520 void sltDataHandleItemChanged(QStandardItem *pItem);
521 /** Handles context-menu-requested signal for the data-pane: */
522 void sltDataHandleCustomContextMenuRequested(const QPoint &pos);
523 /** @} */
524
525 /** @name Actions
526 * @{ */
527 /** Add handler. */
528 void sltAdd();
529 /** Remove handler. */
530 void sltDel();
531 /** Save handler. */
532 void sltSave();
533 /** Load handler. */
534 void sltLoad();
535 /** @} */
536
537private:
538
539 /** @name General
540 * @{ */
541 /** Returns whether the window should be maximized when geometry being restored. */
542 virtual bool shouldBeMaximized() const /* override */;
543 /** @} */
544
545 /** @name Prepare/Cleanup
546 * @{ */
547 /** Prepare instance. */
548 void prepare();
549 /** Prepare this. */
550 void prepareThis();
551 /** Prepare connections. */
552 void prepareConnections();
553 /** Prepare menu. */
554 void prepareMenu();
555 /** Prepare central widget. */
556 void prepareCentralWidget();
557 /** Prepare tool-bar. */
558 void prepareToolBar();
559 /** Prepare splitter. */
560 void prepareSplitter();
561 /** Prepare panes: */
562 void preparePanes();
563 /** Prepare chooser pane. */
564 void preparePaneChooser();
565 /** Prepare data pane. */
566 void preparePaneData();
567 /** Prepare button-box. */
568 void prepareButtonBox();
569 /** Load window settings. */
570 void loadSettings();
571
572 /** Save window settings. */
573 void saveSettings();
574 /** Cleanup instance. */
575 void cleanup();
576 /** @} */
577
578 /** @name Actions
579 * @{ */
580 /** */
581 void updateActionsAvailability();
582 /** @} */
583
584 /** @name Chooser-pane
585 * @{ */
586 /** Returns chooser index for @a iRow. */
587 QModelIndex chooserIndex(int iRow) const;
588 /** Returns current chooser index. */
589 QModelIndex currentChooserIndex() const;
590
591 /** Returns chooser ID for @a iRow. */
592 QUuid chooserID(int iRow) const;
593 /** Returns current chooser ID. */
594 QUuid currentChooserID() const;
595
596 /** Returns chooser Name for @a iRow. */
597 QString chooserName(int iRow) const;
598 /** Returns current Name. */
599 QString currentChooserName() const;
600
601 /** Adds chooser item. */
602 void addChooserItem(const QUuid &uID,
603 const QString &strName,
604 const QString &strOsTypeID,
605 const int iPosition = -1);
606 /** Adds chooser item by machine. */
607 void addChooserItemByMachine(const CMachine &machine,
608 const int iPosition = -1);
609 /** Adds chooser item by ID. */
610 void addChooserItemByID(const QUuid &uID,
611 const int iPosition = -1);
612
613 /** Make sure chooser have current-index if possible. */
614 void makeSureChooserHaveCurrentIndexIfPossible();
615 /** @} */
616
617 /** @name Data-pane
618 * @{ */
619 /** Returns data index for @a iRow and @a iColumn. */
620 QModelIndex dataIndex(int iRow, int iColumn) const;
621
622 /** Returns data-key index for @a iRow. */
623 QModelIndex dataKeyIndex(int iRow) const;
624
625 /** Returns data-value index for @a iRow. */
626 QModelIndex dataValueIndex(int iRow) const;
627
628 /** Returns current data-key. */
629 QString dataKey(int iRow) const;
630
631 /** Returns current data-value. */
632 QString dataValue(int iRow) const;
633
634 /** Adds data item. */
635 void addDataItem(const QString &strKey,
636 const QString &strValue,
637 const int iPosition = -1);
638
639 /** Sorts data items. */
640 void sortData();
641
642 /** Returns the list of known extra-data keys. */
643 static QStringList knownExtraDataKeys();
644 /** @} */
645
646
647 /** @name Arguments
648 * @{ */
649 /** Holds the center widget reference. */
650 QWidget *m_pCenterWidget;
651 /** @} */
652
653 /** @name General
654 * @{ */
655 QVBoxLayout *m_pMainLayout;
656 /** Data pane: Tool-bar. */
657 UIToolBar *m_pToolBar;
658 /** Splitter. */
659 QISplitter *m_pSplitter;
660 /** @} */
661
662 /** @name Chooser-pane
663 * @{ */
664 /** Chooser pane. */
665 QWidget *m_pPaneOfChooser;
666 /** Chooser filter. */
667 QLineEdit *m_pFilterOfChooser;
668 /** Chooser pane: List-view. */
669 QListView *m_pViewOfChooser;
670 /** Chooser pane: Source-model. */
671 QStandardItemModel *m_pModelSourceOfChooser;
672 /** Chooser pane: Proxy-model. */
673 UIChooserPaneSortingModel *m_pModelProxyOfChooser;
674 /** @} */
675
676 /** @name Data-pane
677 * @{ */
678 /** Data pane. */
679 QWidget *m_pPaneOfData;
680 /** Data filter. */
681 QLineEdit *m_pFilterOfData;
682 /** Data pane: Table-view. */
683 QTableView *m_pViewOfData;
684 /** Data pane: Item-model. */
685 QStandardItemModel *m_pModelSourceOfData;
686 /** Data pane: Proxy-model. */
687 QSortFilterProxyModel *m_pModelProxyOfData;
688 /** @} */
689
690 /** @name Button Box
691 * @{ */
692 /** Dialog button-box. */
693 QIDialogButtonBox *m_pButtonBox;
694 /** @} */
695
696 /** @name Actions
697 * @{ */
698 /** Add action. */
699 QAction *m_pActionAdd;
700 /** Del action. */
701 QAction *m_pActionDel;
702 /** Load action. */
703 QAction *m_pActionLoad;
704 /** Save action. */
705 QAction *m_pActionSave;
706 /** @} */
707};
708
709
710/*********************************************************************************************************************************
711* Class UIExtraDataManagerWindow implementation. *
712*********************************************************************************************************************************/
713
714UIExtraDataManagerWindow::UIExtraDataManagerWindow(QWidget *pCenterWidget)
715 : m_pCenterWidget(pCenterWidget)
716 , m_pMainLayout(0), m_pToolBar(0), m_pSplitter(0)
717 , m_pPaneOfChooser(0), m_pFilterOfChooser(0), m_pViewOfChooser(0)
718 , m_pModelSourceOfChooser(0), m_pModelProxyOfChooser(0)
719 , m_pPaneOfData(0), m_pFilterOfData(0), m_pViewOfData(0),
720 m_pModelSourceOfData(0), m_pModelProxyOfData(0)
721 , m_pButtonBox(0)
722 , m_pActionAdd(0), m_pActionDel(0)
723 , m_pActionLoad(0), m_pActionSave(0)
724{
725 /* Prepare: */
726 prepare();
727}
728
729UIExtraDataManagerWindow::~UIExtraDataManagerWindow()
730{
731 /* Cleanup: */
732 cleanup();
733}
734
735void UIExtraDataManagerWindow::showAndRaise(QWidget*)
736{
737 /* Show: */
738 show();
739 /* Restore from minimized state: */
740 setWindowState(windowState() & ~Qt::WindowMinimized);
741 /* Raise: */
742 activateWindow();
743// /* Center according passed widget: */
744// UICommon::centerWidget(this, pCenterWidget, false);
745}
746
747void UIExtraDataManagerWindow::sltMachineRegistered(const QUuid &uID, bool fRegistered)
748{
749 /* Machine registered: */
750 if (fRegistered)
751 {
752 /* Gather list of 'known IDs': */
753 QList<QUuid> knownIDs;
754 for (int iRow = 0; iRow < m_pModelSourceOfChooser->rowCount(); ++iRow)
755 knownIDs.append(chooserID(iRow));
756
757 /* Get machine items: */
758 const CMachineVector machines = uiCommon().virtualBox().GetMachines();
759 /* Look for the proper place to insert new machine item: */
760 QUuid uPositionID = UIExtraDataManager::GlobalID;
761 foreach (const CMachine &machine, machines)
762 {
763 /* Get iterated machine ID: */
764 const QUuid uIteratedID = machine.GetId();
765 /* If 'iterated ID' equal to 'added ID' => break now: */
766 if (uIteratedID == uID)
767 break;
768 /* If 'iterated ID' is 'known ID' => remember it: */
769 if (knownIDs.contains(uIteratedID))
770 uPositionID = uIteratedID;
771 }
772
773 /* Add new chooser item into source-model: */
774 addChooserItemByID(uID, knownIDs.indexOf(uPositionID) + 1);
775 /* And sort proxy-model: */
776 m_pModelProxyOfChooser->sort(0, Qt::AscendingOrder);
777 /* Make sure chooser have current-index if possible: */
778 makeSureChooserHaveCurrentIndexIfPossible();
779 }
780 /* Machine unregistered: */
781 else
782 {
783 /* Remove chooser item with 'removed ID' if it is among 'known IDs': */
784 for (int iRow = 0; iRow < m_pModelSourceOfChooser->rowCount(); ++iRow)
785 if (chooserID(iRow) == uID)
786 m_pModelSourceOfChooser->removeRow(iRow);
787 }
788}
789
790void UIExtraDataManagerWindow::sltExtraDataMapAcknowledging(const QUuid &uID)
791{
792 /* Update item with 'changed ID' if it is among 'known IDs': */
793 for (int iRow = 0; iRow < m_pModelSourceOfChooser->rowCount(); ++iRow)
794 if (chooserID(iRow) == uID)
795 m_pModelSourceOfChooser->itemFromIndex(chooserIndex(iRow))->setData(true, Field_Known);
796}
797
798void UIExtraDataManagerWindow::sltExtraDataChange(const QUuid &uID, const QString &strKey, const QString &strValue)
799{
800 /* Skip unrelated IDs: */
801 if (currentChooserID() != uID)
802 return;
803
804 /* List of 'known keys': */
805 QStringList knownKeys;
806 for (int iRow = 0; iRow < m_pModelSourceOfData->rowCount(); ++iRow)
807 knownKeys << dataKey(iRow);
808
809 /* Check if 'changed key' is 'known key': */
810 int iPosition = knownKeys.indexOf(strKey);
811 /* If that is 'known key': */
812 if (iPosition != -1)
813 {
814 /* If 'changed value' is empty => REMOVE item: */
815 if (strValue.isEmpty())
816 m_pModelSourceOfData->removeRow(iPosition);
817 /* If 'changed value' is NOT empty => UPDATE item: */
818 else
819 {
820 m_pModelSourceOfData->itemFromIndex(dataKeyIndex(iPosition))->setData(strKey, Qt::UserRole);
821 m_pModelSourceOfData->itemFromIndex(dataValueIndex(iPosition))->setText(strValue);
822 }
823 }
824 /* Else if 'changed value' is NOT empty: */
825 else if (!strValue.isEmpty())
826 {
827 /* Look for the proper place for 'changed key': */
828 QString strPositionKey;
829 foreach (const QString &strIteratedKey, gEDataManager->map(uID).keys())
830 {
831 /* If 'iterated key' equal to 'changed key' => break now: */
832 if (strIteratedKey == strKey)
833 break;
834 /* If 'iterated key' is 'known key' => remember it: */
835 if (knownKeys.contains(strIteratedKey))
836 strPositionKey = strIteratedKey;
837 }
838 /* Calculate resulting position: */
839 iPosition = knownKeys.indexOf(strPositionKey) + 1;
840 /* INSERT item to the required position: */
841 addDataItem(strKey, strValue, iPosition);
842 /* And sort proxy-model: */
843 sortData();
844 }
845}
846
847void UIExtraDataManagerWindow::sltChooserApplyFilter(const QString &strFilter)
848{
849 /* Apply filtering rule: */
850 m_pModelProxyOfChooser->setFilterWildcard(strFilter);
851 /* Make sure chooser have current-index if possible: */
852 makeSureChooserHaveCurrentIndexIfPossible();
853}
854
855void UIExtraDataManagerWindow::sltChooserHandleCurrentChanged(const QModelIndex &index)
856{
857 /* Remove all the old items first: */
858 while (m_pModelSourceOfData->rowCount())
859 m_pModelSourceOfData->removeRow(0);
860
861 /* Ignore invalid indexes: */
862 if (!index.isValid())
863 return;
864
865 /* Add all the new items finally: */
866 const QUuid uID = index.data(Field_ID).toUuid();
867 if (!gEDataManager->contains(uID))
868 gEDataManager->hotloadMachineExtraDataMap(uID);
869 const ExtraDataMap data = gEDataManager->map(uID);
870 foreach (const QString &strKey, data.keys())
871 addDataItem(strKey, data.value(strKey));
872 /* And sort proxy-model: */
873 sortData();
874}
875
876void UIExtraDataManagerWindow::sltChooserHandleSelectionChanged(const QItemSelection&,
877 const QItemSelection&)
878{
879 /* Update actions availability: */
880 updateActionsAvailability();
881}
882
883void UIExtraDataManagerWindow::sltDataApplyFilter(const QString &strFilter)
884{
885 /* Apply filtering rule: */
886 m_pModelProxyOfData->setFilterWildcard(strFilter);
887}
888
889void UIExtraDataManagerWindow::sltDataHandleSelectionChanged(const QItemSelection&,
890 const QItemSelection&)
891{
892 /* Update actions availability: */
893 updateActionsAvailability();
894}
895
896void UIExtraDataManagerWindow::sltDataHandleItemChanged(QStandardItem *pItem)
897{
898 /* Make sure passed item is valid: */
899 AssertPtrReturnVoid(pItem);
900
901 /* Item-data index: */
902 const QModelIndex itemIndex = m_pModelSourceOfData->indexFromItem(pItem);
903 const int iRow = itemIndex.row();
904 const int iColumn = itemIndex.column();
905
906 /* Key-data is changed: */
907 if (iColumn == 0)
908 {
909 /* Should we replace changed key? */
910 bool fReplace = true;
911
912 /* List of 'known keys': */
913 QStringList knownKeys;
914 for (int iKeyRow = 0; iKeyRow < m_pModelSourceOfData->rowCount(); ++iKeyRow)
915 {
916 /* Do not consider the row we are changing as Qt's model is not yet updated: */
917 if (iKeyRow != iRow)
918 knownKeys << dataKey(iKeyRow);
919 }
920
921 /* If changed key exists: */
922 if (knownKeys.contains(itemIndex.data().toString()))
923 {
924 /* Show warning and ask for overwriting approval: */
925 if (!msgCenter().questionBinary(this, MessageType_Question,
926 QString("Overwriting already existing key, Continue?"),
927 0 /* auto-confirm id */,
928 QString("Overwrite") /* ok button text */,
929 QString() /* cancel button text */,
930 false /* ok button by default? */))
931 {
932 /* Cancel the operation, restore the original extra-data key: */
933 pItem->setData(itemIndex.data(Qt::UserRole).toString(), Qt::DisplayRole);
934 fReplace = false;
935 }
936 else
937 {
938 /* Delete previous extra-data key: */
939 gEDataManager->setExtraDataString(itemIndex.data().toString(),
940 QString(),
941 currentChooserID());
942 }
943 }
944
945 /* Replace changed extra-data key if necessary: */
946 if (fReplace)
947 {
948 gEDataManager->setExtraDataString(itemIndex.data(Qt::UserRole).toString(),
949 QString(),
950 currentChooserID());
951 gEDataManager->setExtraDataString(itemIndex.data().toString(),
952 dataValue(iRow),
953 currentChooserID());
954 }
955 }
956 /* Value-data is changed: */
957 else
958 {
959 /* Key-data index: */
960 const QModelIndex keyIndex = dataKeyIndex(iRow);
961 /* Update extra-data: */
962 gEDataManager->setExtraDataString(keyIndex.data().toString(),
963 itemIndex.data().toString(),
964 currentChooserID());
965 }
966}
967
968void UIExtraDataManagerWindow::sltDataHandleCustomContextMenuRequested(const QPoint &pos)
969{
970 /* Prepare menu: */
971 QMenu menu;
972 menu.addAction(m_pActionAdd);
973 menu.addAction(m_pActionDel);
974 menu.addSeparator();
975 menu.addAction(m_pActionSave);
976 /* Execute menu: */
977 m_pActionSave->setProperty("CalledFromContextMenu", true);
978 menu.exec(m_pViewOfData->viewport()->mapToGlobal(pos));
979 m_pActionSave->setProperty("CalledFromContextMenu", QVariant());
980}
981
982void UIExtraDataManagerWindow::sltAdd()
983{
984 /* Make sure this slot called by corresponding action only: */
985 QAction *pSenderAction = qobject_cast<QAction*>(sender());
986 AssertReturnVoid(pSenderAction && m_pActionAdd);
987
988 /* Create input-dialog: */
989 QPointer<QIDialog> pInputDialog = new QIDialog(this);
990 AssertPtrReturnVoid(pInputDialog.data());
991 {
992 /* Configure input-dialog: */
993 pInputDialog->setWindowTitle("Add extra-data record..");
994 pInputDialog->setMinimumWidth(400);
995 /* Create main-layout: */
996 QVBoxLayout *pMainLayout = new QVBoxLayout(pInputDialog);
997 AssertPtrReturnVoid(pMainLayout);
998 {
999 /* Create dialog validator group: */
1000 QObjectValidatorGroup *pValidatorGroup = new QObjectValidatorGroup(pInputDialog);
1001 AssertReturnVoid(pValidatorGroup);
1002 /* Create input-layout: */
1003 QGridLayout *pInputLayout = new QGridLayout;
1004 AssertPtrReturnVoid(pInputLayout);
1005 {
1006 /* Create key-label: */
1007 QLabel *pLabelKey = new QLabel("&Name:");
1008 {
1009 /* Configure key-label: */
1010 pLabelKey->setAlignment(Qt::AlignRight);
1011 /* Add key-label into input-layout: */
1012 pInputLayout->addWidget(pLabelKey, 0, 0);
1013 }
1014 /* Create key-editor: */
1015 QComboBox *pEditorKey = new QComboBox;
1016 {
1017 /* Configure key-editor: */
1018 pEditorKey->setEditable(true);
1019 pEditorKey->addItems(knownExtraDataKeys());
1020 pLabelKey->setBuddy(pEditorKey);
1021 /* Create key-editor property setter: */
1022 QObjectPropertySetter *pKeyPropertySetter = new QObjectPropertySetter(pInputDialog, "Key");
1023 AssertPtrReturnVoid(pKeyPropertySetter);
1024 {
1025 /* Configure key-editor property setter: */
1026 connect(pEditorKey, &QComboBox::editTextChanged,
1027 pKeyPropertySetter, &QObjectPropertySetter::sltAssignProperty);
1028 }
1029 /* Create key-editor validator: */
1030 QObjectValidator *pKeyValidator = new QObjectValidator(new QRegExpValidator(QRegExp("[\\s\\S]+"), this));
1031 AssertPtrReturnVoid(pKeyValidator);
1032 {
1033 /* Configure key-editor validator: */
1034 connect(pEditorKey, &QComboBox::editTextChanged,
1035 pKeyValidator, &QObjectValidator::sltValidate);
1036 /* Add key-editor validator into dialog validator group: */
1037 pValidatorGroup->addObjectValidator(pKeyValidator);
1038 }
1039 /* Add key-editor into input-layout: */
1040 pInputLayout->addWidget(pEditorKey, 0, 1);
1041 }
1042 /* Create value-label: */
1043 QLabel *pLabelValue = new QLabel("&Value:");
1044 {
1045 /* Configure value-label: */
1046 pLabelValue->setAlignment(Qt::AlignRight);
1047 /* Add value-label into input-layout: */
1048 pInputLayout->addWidget(pLabelValue, 1, 0);
1049 }
1050 /* Create value-editor: */
1051 QLineEdit *pEditorValue = new QLineEdit;
1052 {
1053 /* Configure value-editor: */
1054 pLabelValue->setBuddy(pEditorValue);
1055 /* Create value-editor property setter: */
1056 QObjectPropertySetter *pValuePropertySetter = new QObjectPropertySetter(pInputDialog, "Value");
1057 AssertPtrReturnVoid(pValuePropertySetter);
1058 {
1059 /* Configure value-editor property setter: */
1060 connect(pEditorValue, &QLineEdit::textEdited,
1061 pValuePropertySetter, &QObjectPropertySetter::sltAssignProperty);
1062 }
1063 /* Create value-editor validator: */
1064 QObjectValidator *pValueValidator = new QObjectValidator(new QRegExpValidator(QRegExp("[\\s\\S]+"), this));
1065 AssertPtrReturnVoid(pValueValidator);
1066 {
1067 /* Configure value-editor validator: */
1068 connect(pEditorValue, &QLineEdit::textEdited,
1069 pValueValidator, &QObjectValidator::sltValidate);
1070 /* Add value-editor validator into dialog validator group: */
1071 pValidatorGroup->addObjectValidator(pValueValidator);
1072 }
1073 /* Add value-editor into input-layout: */
1074 pInputLayout->addWidget(pEditorValue, 1, 1);
1075 }
1076 /* Add input-layout into main-layout: */
1077 pMainLayout->addLayout(pInputLayout);
1078 }
1079 /* Create stretch: */
1080 pMainLayout->addStretch();
1081 /* Create dialog button-box: */
1082 QIDialogButtonBox *pButtonBox = new QIDialogButtonBox;
1083 AssertPtrReturnVoid(pButtonBox);
1084 {
1085 /* Configure button-box: */
1086 pButtonBox->setStandardButtons(QDialogButtonBox::Ok | QDialogButtonBox::Cancel);
1087 pButtonBox->button(QDialogButtonBox::Ok)->setAutoDefault(true);
1088 pButtonBox->button(QDialogButtonBox::Ok)->setEnabled(pValidatorGroup->result());
1089 pButtonBox->button(QDialogButtonBox::Cancel)->setShortcut(Qt::Key_Escape);
1090 connect(pValidatorGroup, &QObjectValidatorGroup::sigValidityChange,
1091 pButtonBox->button(QDialogButtonBox::Ok), &QPushButton::setEnabled);
1092 connect(pButtonBox, &QIDialogButtonBox::accepted, pInputDialog.data(), &QIDialog::accept);
1093 connect(pButtonBox, &QIDialogButtonBox::rejected, pInputDialog.data(), &QIDialog::reject);
1094 /* Add button-box into main-layout: */
1095 pMainLayout->addWidget(pButtonBox);
1096 }
1097 }
1098 }
1099
1100 /* Execute input-dialog: */
1101 if (pInputDialog->exec() == QDialog::Accepted)
1102 {
1103 /* Should we add new key? */
1104 bool fAdd = true;
1105
1106 /* List of 'known keys': */
1107 QStringList knownKeys;
1108 for (int iKeyRow = 0; iKeyRow < m_pModelSourceOfData->rowCount(); ++iKeyRow)
1109 knownKeys << dataKey(iKeyRow);
1110
1111 /* If new key exists: */
1112 if (knownKeys.contains(pInputDialog->property("Key").toString()))
1113 {
1114 /* Show warning and ask for overwriting approval: */
1115 if (!msgCenter().questionBinary(this, MessageType_Question,
1116 QString("Overwriting already existing key, Continue?"),
1117 0 /* auto-confirm id */,
1118 QString("Overwrite") /* ok button text */,
1119 QString() /* cancel button text */,
1120 false /* ok button by default? */))
1121 {
1122 /* Cancel the operation: */
1123 fAdd = false;
1124 }
1125 }
1126
1127 /* Add new extra-data key if necessary: */
1128 if (fAdd)
1129 gEDataManager->setExtraDataString(pInputDialog->property("Key").toString(),
1130 pInputDialog->property("Value").toString(),
1131 currentChooserID());
1132 }
1133
1134 /* Destroy input-dialog: */
1135 if (pInputDialog)
1136 delete pInputDialog;
1137}
1138
1139void UIExtraDataManagerWindow::sltDel()
1140{
1141 /* Make sure this slot called by corresponding action only: */
1142 QAction *pSenderAction = qobject_cast<QAction*>(sender());
1143 AssertReturnVoid(pSenderAction && m_pActionDel);
1144
1145 /* Gather the map of chosen items: */
1146 QMap<QString, QString> items;
1147 foreach (const QModelIndex &keyIndex, m_pViewOfData->selectionModel()->selectedRows(0))
1148 items.insert(keyIndex.data().toString(), dataValueIndex(keyIndex.row()).data().toString());
1149
1150 /* Prepare details: */
1151 const QString strTableTemplate("<!--EOM--><table border=0 cellspacing=10 cellpadding=0 width=500>%1</table>");
1152 const QString strRowTemplate("<tr><td><tt>%1</tt></td><td align=right><tt>%2</tt></td></tr>");
1153 QString strDetails;
1154 foreach (const QString &strKey, items.keys())
1155 strDetails += strRowTemplate.arg(strKey, items.value(strKey));
1156 strDetails = strTableTemplate.arg(strDetails);
1157
1158 /* Ask for user' confirmation: */
1159 if (!msgCenter().errorWithQuestion(this, MessageType_Question,
1160 QString("<p>Do you really wish to "
1161 "remove chosen records?</p>"),
1162 strDetails))
1163 return;
1164
1165 /* Erase all the chosen extra-data records: */
1166 foreach (const QString &strKey, items.keys())
1167 gEDataManager->setExtraDataString(strKey, QString(), currentChooserID());
1168}
1169
1170void UIExtraDataManagerWindow::sltSave()
1171{
1172 /* Make sure this slot called by corresponding action only: */
1173 QAction *pSenderAction = qobject_cast<QAction*>(sender());
1174 AssertReturnVoid(pSenderAction && m_pActionSave);
1175
1176 /* Compose initial file-name: */
1177 const QString strInitialFileName = QDir(uiCommon().homeFolder()).absoluteFilePath(QString("%1_ExtraData.xml").arg(currentChooserName()));
1178 /* Open file-save dialog to choose file to save extra-data into: */
1179 const QString strFileName = QIFileDialog::getSaveFileName(strInitialFileName, "XML files (*.xml)", this,
1180 "Choose file to save extra-data into..", 0, true, true);
1181 /* Make sure file-name was chosen: */
1182 if (strFileName.isEmpty())
1183 return;
1184
1185 /* Create file: */
1186 QFile output(strFileName);
1187 /* Open file for writing: */
1188 bool fOpened = output.open(QIODevice::WriteOnly);
1189 AssertReturnVoid(fOpened);
1190 {
1191 /* Create XML stream writer: */
1192 QXmlStreamWriter stream(&output);
1193 /* Configure XML stream writer: */
1194 stream.setAutoFormatting(true);
1195 stream.setAutoFormattingIndent(2);
1196 /* Write document: */
1197 stream.writeStartDocument();
1198 {
1199 stream.writeStartElement("VirtualBox");
1200 {
1201 const QUuid uID = currentChooserID();
1202 bool fIsMachine = uID != UIExtraDataManager::GlobalID;
1203 const QString strType = fIsMachine ? "Machine" : "Global";
1204 stream.writeStartElement(strType);
1205 {
1206 if (fIsMachine)
1207 stream.writeAttribute("uuid", QString("{%1}").arg(uID.toString()));
1208 stream.writeStartElement("ExtraData");
1209 {
1210 /* Called from context-menu: */
1211 if (pSenderAction->property("CalledFromContextMenu").toBool() &&
1212 !m_pViewOfData->selectionModel()->selection().isEmpty())
1213 {
1214 foreach (const QModelIndex &keyIndex, m_pViewOfData->selectionModel()->selectedRows())
1215 {
1216 /* Get data-value index: */
1217 const QModelIndex valueIndex = dataValueIndex(keyIndex.row());
1218 /* Write corresponding extra-data item into stream: */
1219 stream.writeStartElement("ExtraDataItem");
1220 {
1221 stream.writeAttribute("name", keyIndex.data().toString());
1222 stream.writeAttribute("value", valueIndex.data().toString());
1223 }
1224 stream.writeEndElement(); /* ExtraDataItem */
1225 }
1226 }
1227 /* Called from menu-bar/tool-bar: */
1228 else
1229 {
1230 for (int iRow = 0; iRow < m_pModelProxyOfData->rowCount(); ++iRow)
1231 {
1232 /* Get indexes: */
1233 const QModelIndex keyIndex = m_pModelProxyOfData->index(iRow, 0);
1234 const QModelIndex valueIndex = m_pModelProxyOfData->index(iRow, 1);
1235 /* Write corresponding extra-data item into stream: */
1236 stream.writeStartElement("ExtraDataItem");
1237 {
1238 stream.writeAttribute("name", keyIndex.data().toString());
1239 stream.writeAttribute("value", valueIndex.data().toString());
1240 }
1241 stream.writeEndElement(); /* ExtraDataItem */
1242 }
1243 }
1244 }
1245 stream.writeEndElement(); /* ExtraData */
1246 }
1247 stream.writeEndElement(); /* strType */
1248 }
1249 stream.writeEndElement(); /* VirtualBox */
1250 }
1251 stream.writeEndDocument();
1252 /* Close file: */
1253 output.close();
1254 }
1255}
1256
1257void UIExtraDataManagerWindow::sltLoad()
1258{
1259 /* Make sure this slot called by corresponding action only: */
1260 QAction *pSenderAction = qobject_cast<QAction*>(sender());
1261 AssertReturnVoid(pSenderAction && m_pActionLoad);
1262
1263 /* Compose initial file-name: */
1264 const QString strInitialFileName = QDir(uiCommon().homeFolder()).absoluteFilePath(QString("%1_ExtraData.xml").arg(currentChooserName()));
1265 /* Open file-open dialog to choose file to open extra-data into: */
1266 const QString strFileName = QIFileDialog::getOpenFileName(strInitialFileName, "XML files (*.xml)", this,
1267 "Choose file to load extra-data from..");
1268 /* Make sure file-name was chosen: */
1269 if (strFileName.isEmpty())
1270 return;
1271
1272 /* Create file: */
1273 QFile input(strFileName);
1274 /* Open file for writing: */
1275 bool fOpened = input.open(QIODevice::ReadOnly);
1276 AssertReturnVoid(fOpened);
1277 {
1278 /* Create XML stream reader: */
1279 QXmlStreamReader stream(&input);
1280 /* Read XML stream: */
1281 while (!stream.atEnd())
1282 {
1283 /* Read subsequent token: */
1284 const QXmlStreamReader::TokenType tokenType = stream.readNext();
1285 /* Skip non-interesting tokens: */
1286 if (tokenType != QXmlStreamReader::StartElement)
1287 continue;
1288
1289 /* Get the name of the current element: */
1290 const QStringRef strElementName = stream.name();
1291
1292 /* Search for the scope ID: */
1293 QUuid uLoadingID;
1294 if (strElementName == "Global")
1295 uLoadingID = UIExtraDataManager::GlobalID;
1296 else if (strElementName == "Machine")
1297 {
1298 const QXmlStreamAttributes attributes = stream.attributes();
1299 if (attributes.hasAttribute("uuid"))
1300 {
1301 const QString strUuid = attributes.value("uuid").toString();
1302 const QUuid uLoadingID = strUuid;
1303 if (uLoadingID.isNull())
1304 msgCenter().alert(this, MessageType_Warning,
1305 QString("<p>Invalid extra-data ID:</p>"
1306 "<p>%1</p>").arg(strUuid));
1307 }
1308 }
1309 /* Look particular extra-data entries: */
1310 else if (strElementName == "ExtraDataItem")
1311 {
1312 const QXmlStreamAttributes attributes = stream.attributes();
1313 if (attributes.hasAttribute("name") && attributes.hasAttribute("value"))
1314 {
1315 const QString strName = attributes.value("name").toString();
1316 const QString strValue = attributes.value("value").toString();
1317 gEDataManager->setExtraDataString(strName, strValue, currentChooserID());
1318 }
1319 }
1320
1321 /* Check extra-data ID: */
1322 if (!uLoadingID.isNull() && uLoadingID != currentChooserID() &&
1323 !msgCenter().questionBinary(this, MessageType_Question,
1324 QString("<p>Inconsistent extra-data ID:</p>"
1325 "<p>Current: {%1}</p>"
1326 "<p>Loading: {%2}</p>"
1327 "<p>Continue with loading?</p>")
1328 .arg(currentChooserID().toString(), uLoadingID.toString())))
1329 break;
1330 }
1331 /* Handle XML stream error: */
1332 if (stream.hasError())
1333 msgCenter().alert(this, MessageType_Warning,
1334 QString("<p>Error reading XML file:</p>"
1335 "<p>%1</p>").arg(stream.error()));
1336 /* Close file: */
1337 input.close();
1338 }
1339}
1340
1341bool UIExtraDataManagerWindow::shouldBeMaximized() const
1342{
1343 return gEDataManager->extraDataManagerShouldBeMaximized();
1344}
1345
1346void UIExtraDataManagerWindow::prepare()
1347{
1348 /* Prepare this: */
1349 prepareThis();
1350 /* Prepare connections: */
1351 prepareConnections();
1352 /* Prepare menu: */
1353 prepareMenu();
1354 /* Prepare central-widget: */
1355 prepareCentralWidget();
1356 /* Load settings: */
1357 loadSettings();
1358}
1359
1360void UIExtraDataManagerWindow::prepareThis()
1361{
1362#ifndef VBOX_WS_MAC
1363 /* Apply window icons: */
1364 setWindowIcon(UIIconPool::iconSetFull(":/edata_manager_32px.png",
1365 ":/edata_manager_16px.png"));
1366#endif /* !VBOX_WS_MAC */
1367
1368 /* Apply window title: */
1369 setWindowTitle("Extra-data Manager");
1370
1371 /* Do not count that window as important for application,
1372 * it will NOT be taken into account when other top-level windows will be closed: */
1373 setAttribute(Qt::WA_QuitOnClose, false);
1374
1375 /* Delete window when closed: */
1376 setAttribute(Qt::WA_DeleteOnClose);
1377}
1378
1379void UIExtraDataManagerWindow::prepareConnections()
1380{
1381 /* Prepare connections: */
1382 connect(gVBoxEvents, &UIVirtualBoxEventHandler::sigMachineRegistered,
1383 this, &UIExtraDataManagerWindow::sltMachineRegistered);
1384}
1385
1386void UIExtraDataManagerWindow::prepareMenu()
1387{
1388 /* Create 'Actions' menu: */
1389 QMenu *pActionsMenu = menuBar()->addMenu("Actions");
1390 AssertReturnVoid(pActionsMenu);
1391 {
1392 /* Create 'Add' action: */
1393 m_pActionAdd = pActionsMenu->addAction("Add");
1394 AssertReturnVoid(m_pActionAdd);
1395 {
1396 /* Configure 'Add' action: */
1397 m_pActionAdd->setIcon(UIIconPool::iconSetFull(":/edata_add_22px.png", ":/edata_add_16px.png",
1398 ":/edata_add_disabled_22px.png", ":/edata_add_disabled_16px.png"));
1399 m_pActionAdd->setShortcut(QKeySequence("Ctrl+T"));
1400 connect(m_pActionAdd, &QAction::triggered, this, &UIExtraDataManagerWindow::sltAdd);
1401 }
1402 /* Create 'Del' action: */
1403 m_pActionDel = pActionsMenu->addAction("Remove");
1404 AssertReturnVoid(m_pActionDel);
1405 {
1406 /* Configure 'Del' action: */
1407 m_pActionDel->setIcon(UIIconPool::iconSetFull(":/edata_remove_22px.png", ":/edata_remove_16px.png",
1408 ":/edata_remove_disabled_22px.png", ":/edata_remove_disabled_16px.png"));
1409 m_pActionDel->setShortcut(QKeySequence("Ctrl+R"));
1410 connect(m_pActionDel, &QAction::triggered, this, &UIExtraDataManagerWindow::sltDel);
1411 }
1412
1413 /* Add separator: */
1414 pActionsMenu->addSeparator();
1415
1416 /* Create 'Load' action: */
1417 m_pActionLoad = pActionsMenu->addAction("Load");
1418 AssertReturnVoid(m_pActionLoad);
1419 {
1420 /* Configure 'Load' action: */
1421 m_pActionLoad->setIcon(UIIconPool::iconSetFull(":/edata_load_22px.png", ":/edata_load_16px.png",
1422 ":/edata_load_disabled_22px.png", ":/edata_load_disabled_16px.png"));
1423 m_pActionLoad->setShortcut(QKeySequence("Ctrl+L"));
1424 connect(m_pActionLoad, &QAction::triggered, this, &UIExtraDataManagerWindow::sltLoad);
1425 }
1426 /* Create 'Save' action: */
1427 m_pActionSave = pActionsMenu->addAction("Save As...");
1428 AssertReturnVoid(m_pActionSave);
1429 {
1430 /* Configure 'Save' action: */
1431 m_pActionSave->setIcon(UIIconPool::iconSetFull(":/edata_save_22px.png", ":/edata_save_16px.png",
1432 ":/edata_save_disabled_22px.png", ":/edata_save_disabled_16px.png"));
1433 m_pActionSave->setShortcut(QKeySequence("Ctrl+S"));
1434 connect(m_pActionSave, &QAction::triggered, this, &UIExtraDataManagerWindow::sltSave);
1435 }
1436 }
1437}
1438
1439void UIExtraDataManagerWindow::prepareCentralWidget()
1440{
1441 /* Prepare central-widget: */
1442 setCentralWidget(new QWidget);
1443 AssertPtrReturnVoid(centralWidget());
1444 {
1445 /* Prepare layout: */
1446 m_pMainLayout = new QVBoxLayout(centralWidget());
1447 AssertReturnVoid(m_pMainLayout && centralWidget()->layout() &&
1448 m_pMainLayout == centralWidget()->layout());
1449 {
1450#ifdef VBOX_WS_MAC
1451 /* No spacing/margins on the Mac: */
1452 m_pMainLayout->setContentsMargins(0, 0, 0, 0);
1453 m_pMainLayout->insertSpacing(0, 10);
1454#else /* !VBOX_WS_MAC */
1455 /* Set spacing/margin like in the selector window: */
1456 const int iL = qApp->style()->pixelMetric(QStyle::PM_LayoutLeftMargin) / 2;
1457 const int iT = qApp->style()->pixelMetric(QStyle::PM_LayoutTopMargin) / 2;
1458 const int iR = qApp->style()->pixelMetric(QStyle::PM_LayoutRightMargin) / 2;
1459 const int iB = qApp->style()->pixelMetric(QStyle::PM_LayoutBottomMargin) / 2;
1460 m_pMainLayout->setContentsMargins(iL, iT, iR, iB);
1461#endif /* !VBOX_WS_MAC */
1462 /* Prepare tool-bar: */
1463 prepareToolBar();
1464 /* Prepare splitter: */
1465 prepareSplitter();
1466 /* Prepare button-box: */
1467 prepareButtonBox();
1468 }
1469 /* Initial focus: */
1470 if (m_pViewOfChooser)
1471 m_pViewOfChooser->setFocus();
1472 }
1473}
1474
1475void UIExtraDataManagerWindow::prepareToolBar()
1476{
1477 /* Create tool-bar: */
1478 m_pToolBar = new UIToolBar(this);
1479 AssertPtrReturnVoid(m_pToolBar);
1480 {
1481 /* Configure tool-bar: */
1482 m_pToolBar->setIconSize(QSize(22, 22));
1483 m_pToolBar->setToolButtonStyle(Qt::ToolButtonTextUnderIcon);
1484 /* Add actions: */
1485 m_pToolBar->addAction(m_pActionAdd);
1486 m_pToolBar->addAction(m_pActionDel);
1487 m_pToolBar->addSeparator();
1488 m_pToolBar->addAction(m_pActionLoad);
1489 m_pToolBar->addAction(m_pActionSave);
1490 /* Integrate tool-bar into dialog: */
1491#ifdef VBOX_WS_MAC
1492 /* Enable unified tool-bars on Mac OS X. Available on Qt >= 4.3: */
1493 addToolBar(m_pToolBar);
1494 m_pToolBar->enableMacToolbar();
1495#else /* !VBOX_WS_MAC */
1496 /* Add tool-bar into main-layout: */
1497 m_pMainLayout->addWidget(m_pToolBar);
1498#endif /* !VBOX_WS_MAC */
1499 }
1500}
1501
1502void UIExtraDataManagerWindow::prepareSplitter()
1503{
1504 /* Create splitter: */
1505 m_pSplitter = new QISplitter;
1506 AssertPtrReturnVoid(m_pSplitter);
1507 {
1508 /* Prepare panes: */
1509 preparePanes();
1510 /* Configure splitter: */
1511 m_pSplitter->setChildrenCollapsible(false);
1512 m_pSplitter->setStretchFactor(0, 0);
1513 m_pSplitter->setStretchFactor(1, 1);
1514 /* Add splitter into main layout: */
1515 m_pMainLayout->addWidget(m_pSplitter);
1516 }
1517}
1518
1519void UIExtraDataManagerWindow::preparePanes()
1520{
1521 /* Prepare chooser-pane: */
1522 preparePaneChooser();
1523 /* Prepare data-pane: */
1524 preparePaneData();
1525 /* Link chooser and data panes: */
1526 connect(m_pViewOfChooser->selectionModel(), &QItemSelectionModel::currentChanged,
1527 this, &UIExtraDataManagerWindow::sltChooserHandleCurrentChanged);
1528 connect(m_pViewOfChooser->selectionModel(), &QItemSelectionModel::selectionChanged,
1529 this, &UIExtraDataManagerWindow::sltChooserHandleSelectionChanged);
1530 connect(m_pViewOfData->selectionModel(), &QItemSelectionModel::selectionChanged,
1531 this, &UIExtraDataManagerWindow::sltDataHandleSelectionChanged);
1532 connect(m_pModelSourceOfData, &QStandardItemModel::itemChanged,
1533 this, &UIExtraDataManagerWindow::sltDataHandleItemChanged);
1534 /* Make sure chooser have current-index if possible: */
1535 makeSureChooserHaveCurrentIndexIfPossible();
1536}
1537
1538void UIExtraDataManagerWindow::preparePaneChooser()
1539{
1540 /* Create chooser-pane: */
1541 m_pPaneOfChooser = new QWidget;
1542 AssertPtrReturnVoid(m_pPaneOfChooser);
1543 {
1544 /* Create layout: */
1545 QVBoxLayout *pLayout = new QVBoxLayout(m_pPaneOfChooser);
1546 AssertReturnVoid(pLayout && m_pPaneOfChooser->layout() &&
1547 pLayout == m_pPaneOfChooser->layout());
1548 {
1549 /* Configure layout: */
1550 const int iR = qApp->style()->pixelMetric(QStyle::PM_LayoutRightMargin) / 3;
1551 pLayout->setContentsMargins(0, 0, iR, 0);
1552 /* Create chooser-filter: */
1553 m_pFilterOfChooser = new QLineEdit;
1554 {
1555 /* Configure chooser-filter: */
1556 m_pFilterOfChooser->setPlaceholderText("Search..");
1557 connect(m_pFilterOfChooser, &QLineEdit::textChanged,
1558 this, &UIExtraDataManagerWindow::sltChooserApplyFilter);
1559 /* Add chooser-filter into layout: */
1560 pLayout->addWidget(m_pFilterOfChooser);
1561 }
1562 /* Create chooser-view: */
1563 m_pViewOfChooser = new QListView;
1564 AssertPtrReturnVoid(m_pViewOfChooser);
1565 {
1566 /* Configure chooser-view: */
1567 delete m_pViewOfChooser->itemDelegate();
1568 m_pViewOfChooser->setItemDelegate(new UIChooserPaneDelegate(m_pViewOfChooser));
1569 m_pViewOfChooser->setSelectionMode(QAbstractItemView::SingleSelection);
1570 /* Create source-model: */
1571 m_pModelSourceOfChooser = new QStandardItemModel(m_pViewOfChooser);
1572 AssertPtrReturnVoid(m_pModelSourceOfChooser);
1573 {
1574 /* Create proxy-model: */
1575 m_pModelProxyOfChooser = new UIChooserPaneSortingModel(m_pViewOfChooser);
1576 AssertPtrReturnVoid(m_pModelProxyOfChooser);
1577 {
1578 /* Configure proxy-model: */
1579 m_pModelProxyOfChooser->setSortRole(Field_Name);
1580 m_pModelProxyOfChooser->setFilterRole(Field_Name);
1581 m_pModelProxyOfChooser->setSortCaseSensitivity(Qt::CaseInsensitive);
1582 m_pModelProxyOfChooser->setFilterCaseSensitivity(Qt::CaseInsensitive);
1583 m_pModelProxyOfChooser->setSourceModel(m_pModelSourceOfChooser);
1584 m_pViewOfChooser->setModel(m_pModelProxyOfChooser);
1585 }
1586 /* Add global chooser item into source-model: */
1587 addChooserItemByID(UIExtraDataManager::GlobalID);
1588 /* Add machine chooser items into source-model: */
1589 CMachineVector machines = uiCommon().virtualBox().GetMachines();
1590 foreach (const CMachine &machine, machines)
1591 addChooserItemByMachine(machine);
1592 /* And sort proxy-model: */
1593 m_pModelProxyOfChooser->sort(0, Qt::AscendingOrder);
1594 }
1595 /* Add chooser-view into layout: */
1596 pLayout->addWidget(m_pViewOfChooser);
1597 }
1598 }
1599 /* Add chooser-pane into splitter: */
1600 m_pSplitter->addWidget(m_pPaneOfChooser);
1601 }
1602}
1603
1604void UIExtraDataManagerWindow::preparePaneData()
1605{
1606 /* Create data-pane: */
1607 m_pPaneOfData = new QWidget;
1608 AssertPtrReturnVoid(m_pPaneOfData);
1609 {
1610 /* Create layout: */
1611 QVBoxLayout *pLayout = new QVBoxLayout(m_pPaneOfData);
1612 AssertReturnVoid(pLayout && m_pPaneOfData->layout() &&
1613 pLayout == m_pPaneOfData->layout());
1614 {
1615 /* Configure layout: */
1616 const int iL = qApp->style()->pixelMetric(QStyle::PM_LayoutLeftMargin) / 3;
1617 pLayout->setContentsMargins(iL, 0, 0, 0);
1618 /* Create data-filter: */
1619 m_pFilterOfData = new QLineEdit;
1620 {
1621 /* Configure data-filter: */
1622 m_pFilterOfData->setPlaceholderText("Search..");
1623 connect(m_pFilterOfData, &QLineEdit::textChanged,
1624 this, &UIExtraDataManagerWindow::sltDataApplyFilter);
1625 /* Add data-filter into layout: */
1626 pLayout->addWidget(m_pFilterOfData);
1627 }
1628 /* Create data-view: */
1629 m_pViewOfData = new QTableView;
1630 AssertPtrReturnVoid(m_pViewOfData);
1631 {
1632 /* Create item-model: */
1633 m_pModelSourceOfData = new QStandardItemModel(0, 2, m_pViewOfData);
1634 AssertPtrReturnVoid(m_pModelSourceOfData);
1635 {
1636 /* Create proxy-model: */
1637 m_pModelProxyOfData = new QSortFilterProxyModel(m_pViewOfChooser);
1638 AssertPtrReturnVoid(m_pModelProxyOfData);
1639 {
1640 /* Configure proxy-model: */
1641 m_pModelProxyOfData->setSortCaseSensitivity(Qt::CaseInsensitive);
1642 m_pModelProxyOfData->setFilterCaseSensitivity(Qt::CaseInsensitive);
1643 m_pModelProxyOfData->setSourceModel(m_pModelSourceOfData);
1644 m_pViewOfData->setModel(m_pModelProxyOfData);
1645 }
1646 /* Configure item-model: */
1647 m_pModelSourceOfData->setHorizontalHeaderLabels(QStringList() << "Key" << "Value");
1648 }
1649 /* Configure data-view: */
1650 m_pViewOfData->setSortingEnabled(true);
1651 m_pViewOfData->setAlternatingRowColors(true);
1652 m_pViewOfData->setContextMenuPolicy(Qt::CustomContextMenu);
1653 m_pViewOfData->setSelectionMode(QAbstractItemView::ExtendedSelection);
1654 m_pViewOfData->setSelectionBehavior(QAbstractItemView::SelectRows);
1655 connect(m_pViewOfData, &QTableView::customContextMenuRequested,
1656 this, &UIExtraDataManagerWindow::sltDataHandleCustomContextMenuRequested);
1657 QHeaderView *pVHeader = m_pViewOfData->verticalHeader();
1658 QHeaderView *pHHeader = m_pViewOfData->horizontalHeader();
1659 pVHeader->hide();
1660 pHHeader->setSortIndicator(0, Qt::AscendingOrder);
1661 pHHeader->resizeSection(0, qMin(300, pHHeader->width() / 3));
1662 pHHeader->setStretchLastSection(true);
1663 /* Add data-view into layout: */
1664 pLayout->addWidget(m_pViewOfData);
1665 }
1666 }
1667 /* Add data-pane into splitter: */
1668 m_pSplitter->addWidget(m_pPaneOfData);
1669 }
1670}
1671
1672void UIExtraDataManagerWindow::prepareButtonBox()
1673{
1674 /* Create button-box: */
1675 m_pButtonBox = new QIDialogButtonBox;
1676 AssertPtrReturnVoid(m_pButtonBox);
1677 {
1678 /* Configure button-box: */
1679 m_pButtonBox->setStandardButtons(QDialogButtonBox::Help | QDialogButtonBox::Close);
1680 m_pButtonBox->button(QDialogButtonBox::Close)->setShortcut(Qt::Key_Escape);
1681 connect(m_pButtonBox, &QIDialogButtonBox::helpRequested, &msgCenter(), &UIMessageCenter::sltShowHelpHelpDialog);
1682 connect(m_pButtonBox, &QIDialogButtonBox::rejected, this, &UIExtraDataManagerWindow::close);
1683 /* Add button-box into main layout: */
1684 m_pMainLayout->addWidget(m_pButtonBox);
1685 }
1686}
1687
1688void UIExtraDataManagerWindow::loadSettings()
1689{
1690 /* Load window geometry: */
1691 {
1692 const QRect geo = gEDataManager->extraDataManagerGeometry(this, m_pCenterWidget);
1693 LogRel2(("GUI: UIExtraDataManagerWindow: Restoring geometry to: Origin=%dx%d, Size=%dx%d\n",
1694 geo.x(), geo.y(), geo.width(), geo.height()));
1695 restoreGeometry(geo);
1696 }
1697
1698 /* Load splitter hints: */
1699 {
1700 m_pSplitter->setSizes(gEDataManager->extraDataManagerSplitterHints(this));
1701 }
1702}
1703
1704void UIExtraDataManagerWindow::saveSettings()
1705{
1706 /* Save splitter hints: */
1707 {
1708 gEDataManager->setExtraDataManagerSplitterHints(m_pSplitter->sizes());
1709 }
1710
1711 /* Save window geometry: */
1712 {
1713 const QRect geo = currentGeometry();
1714 LogRel2(("GUI: UIExtraDataManagerWindow: Saving geometry as: Origin=%dx%d, Size=%dx%d\n",
1715 geo.x(), geo.y(), geo.width(), geo.height()));
1716 gEDataManager->setExtraDataManagerGeometry(geo, isCurrentlyMaximized());
1717 }
1718}
1719
1720void UIExtraDataManagerWindow::cleanup()
1721{
1722 /* Save settings: */
1723 saveSettings();
1724}
1725
1726void UIExtraDataManagerWindow::updateActionsAvailability()
1727{
1728 /* Is there something selected in chooser-view? */
1729 bool fChooserHasSelection = !m_pViewOfChooser->selectionModel()->selection().isEmpty();
1730 /* Is there something selected in data-view? */
1731 bool fDataHasSelection = !m_pViewOfData->selectionModel()->selection().isEmpty();
1732
1733 /* Enable/disable corresponding actions: */
1734 m_pActionAdd->setEnabled(fChooserHasSelection);
1735 m_pActionDel->setEnabled(fChooserHasSelection && fDataHasSelection);
1736 m_pActionLoad->setEnabled(fChooserHasSelection);
1737 m_pActionSave->setEnabled(fChooserHasSelection);
1738}
1739
1740QModelIndex UIExtraDataManagerWindow::chooserIndex(int iRow) const
1741{
1742 return m_pModelSourceOfChooser->index(iRow, 0);
1743}
1744
1745QModelIndex UIExtraDataManagerWindow::currentChooserIndex() const
1746{
1747 return m_pViewOfChooser->currentIndex();
1748}
1749
1750QUuid UIExtraDataManagerWindow::chooserID(int iRow) const
1751{
1752 return chooserIndex(iRow).data(Field_ID).toUuid();
1753}
1754
1755QUuid UIExtraDataManagerWindow::currentChooserID() const
1756{
1757 return currentChooserIndex().data(Field_ID).toUuid();
1758}
1759
1760QString UIExtraDataManagerWindow::chooserName(int iRow) const
1761{
1762 return chooserIndex(iRow).data(Field_Name).toString();
1763}
1764
1765QString UIExtraDataManagerWindow::currentChooserName() const
1766{
1767 return currentChooserIndex().data(Field_Name).toString();
1768}
1769
1770void UIExtraDataManagerWindow::addChooserItem(const QUuid &uID,
1771 const QString &strName,
1772 const QString &strOsTypeID,
1773 const int iPosition /* = -1 */)
1774{
1775 /* Create item: */
1776 QStandardItem *pItem = new QStandardItem;
1777 AssertPtrReturnVoid(pItem);
1778 {
1779 /* Which is NOT editable: */
1780 pItem->setEditable(false);
1781 /* Contains passed ID: */
1782 pItem->setData(uID, Field_ID);
1783 /* Contains passed name: */
1784 pItem->setData(strName, Field_Name);
1785 /* Contains passed OS Type ID: */
1786 pItem->setData(strOsTypeID, Field_OsTypeID);
1787 /* And designated as known/unknown depending on extra-data manager status: */
1788 pItem->setData(gEDataManager->contains(uID), Field_Known);
1789 /* If insert position defined: */
1790 if (iPosition != -1)
1791 {
1792 /* Insert this item at specified position: */
1793 m_pModelSourceOfChooser->insertRow(iPosition, pItem);
1794 }
1795 /* If insert position undefined: */
1796 else
1797 {
1798 /* Add this item as the last one: */
1799 m_pModelSourceOfChooser->appendRow(pItem);
1800 }
1801 }
1802}
1803
1804void UIExtraDataManagerWindow::addChooserItemByMachine(const CMachine &machine,
1805 const int iPosition /* = -1 */)
1806{
1807 /* Make sure VM is accessible: */
1808 if (!machine.isNull() && machine.GetAccessible())
1809 return addChooserItem(machine.GetId(), machine.GetName(), machine.GetOSTypeId(), iPosition);
1810}
1811
1812void UIExtraDataManagerWindow::addChooserItemByID(const QUuid &uID,
1813 const int iPosition /* = -1 */)
1814{
1815 /* Global ID? */
1816 if (uID == UIExtraDataManager::GlobalID)
1817 return addChooserItem(uID, QString("Global"), QString(), iPosition);
1818
1819 /* Search for the corresponding machine by ID: */
1820 CVirtualBox vbox = uiCommon().virtualBox();
1821 const CMachine machine = vbox.FindMachine(uID.toString());
1822 /* Make sure VM is accessible: */
1823 if (vbox.isOk() && !machine.isNull() && machine.GetAccessible())
1824 return addChooserItem(uID, machine.GetName(), machine.GetOSTypeId(), iPosition);
1825}
1826
1827void UIExtraDataManagerWindow::makeSureChooserHaveCurrentIndexIfPossible()
1828{
1829 /* Make sure chooser have current-index if possible: */
1830 if (!m_pViewOfChooser->currentIndex().isValid())
1831 {
1832 /* Do we still have anything to select? */
1833 const QModelIndex firstIndex = m_pModelProxyOfChooser->index(0, 0);
1834 if (firstIndex.isValid())
1835 m_pViewOfChooser->setCurrentIndex(firstIndex);
1836 }
1837}
1838
1839QModelIndex UIExtraDataManagerWindow::dataIndex(int iRow, int iColumn) const
1840{
1841 return m_pModelSourceOfData->index(iRow, iColumn);
1842}
1843
1844QModelIndex UIExtraDataManagerWindow::dataKeyIndex(int iRow) const
1845{
1846 return dataIndex(iRow, 0);
1847}
1848
1849QModelIndex UIExtraDataManagerWindow::dataValueIndex(int iRow) const
1850{
1851 return dataIndex(iRow, 1);
1852}
1853
1854QString UIExtraDataManagerWindow::dataKey(int iRow) const
1855{
1856 return dataKeyIndex(iRow).data().toString();
1857}
1858
1859QString UIExtraDataManagerWindow::dataValue(int iRow) const
1860{
1861 return dataValueIndex(iRow).data().toString();
1862}
1863
1864void UIExtraDataManagerWindow::addDataItem(const QString &strKey,
1865 const QString &strValue,
1866 const int iPosition /* = -1 */)
1867{
1868 /* Prepare items: */
1869 QList<QStandardItem*> items;
1870 /* Create key item: */
1871 items << new QStandardItem(strKey);
1872 items.last()->setData(strKey, Qt::UserRole);
1873 AssertPtrReturnVoid(items.last());
1874 /* Create value item: */
1875 items << new QStandardItem(strValue);
1876 AssertPtrReturnVoid(items.last());
1877 /* If insert position defined: */
1878 if (iPosition != -1)
1879 {
1880 /* Insert these items as the row at the required position: */
1881 m_pModelSourceOfData->insertRow(iPosition, items);
1882 }
1883 /* If insert position undefined: */
1884 else
1885 {
1886 /* Add these items as the last one row: */
1887 m_pModelSourceOfData->appendRow(items);
1888 }
1889}
1890
1891void UIExtraDataManagerWindow::sortData()
1892{
1893 /* Sort using current rules: */
1894 const QHeaderView *pHHeader = m_pViewOfData->horizontalHeader();
1895 const int iSortSection = pHHeader->sortIndicatorSection();
1896 const Qt::SortOrder sortOrder = pHHeader->sortIndicatorOrder();
1897 m_pModelProxyOfData->sort(iSortSection, sortOrder);
1898}
1899
1900/* static */
1901QStringList UIExtraDataManagerWindow::knownExtraDataKeys()
1902{
1903 return QStringList()
1904 << QString()
1905 << GUI_EventHandlingType
1906 << GUI_RestrictedDialogs
1907 << GUI_SuppressMessages << GUI_InvertMessageOption
1908#ifdef VBOX_GUI_WITH_NETWORK_MANAGER
1909 << GUI_PreventApplicationUpdate << GUI_UpdateDate << GUI_UpdateCheckCount
1910#endif /* VBOX_GUI_WITH_NETWORK_MANAGER */
1911 << GUI_Progress_LegacyMode
1912 << GUI_RestrictedGlobalSettingsPages << GUI_RestrictedMachineSettingsPages
1913 << GUI_LanguageID
1914 << GUI_ActivateHoveredMachineWindow
1915 << GUI_Input_SelectorShortcuts << GUI_Input_MachineShortcuts
1916 << GUI_RecentFolderHD << GUI_RecentFolderCD << GUI_RecentFolderFD
1917 << GUI_VISOCreator_RecentFolder
1918 << GUI_RecentListHD << GUI_RecentListCD << GUI_RecentListFD
1919 << GUI_RestrictedNetworkAttachmentTypes
1920 << GUI_LastSelectorWindowPosition << GUI_SplitterSizes
1921 << GUI_Toolbar << GUI_Toolbar_Text
1922 << GUI_Toolbar_MachineTools_Order << GUI_Toolbar_GlobalTools_Order
1923 << GUI_Tools_LastItemsSelected
1924 << GUI_Statusbar
1925 << GUI_GroupDefinitions << GUI_LastItemSelected
1926 << GUI_Details_Elements
1927 << GUI_Details_Elements_Preview_UpdateInterval
1928 << GUI_SnapshotManager_Details_Expanded
1929 << GUI_VirtualMediaManager_Details_Expanded
1930 << GUI_HostNetworkManager_Details_Expanded
1931 << GUI_CloudProfileManager_Details_Expanded
1932 << GUI_HideDescriptionForWizards
1933 << GUI_HideFromManager << GUI_HideDetails
1934 << GUI_PreventReconfiguration << GUI_PreventSnapshotOperations
1935 << GUI_FirstRun
1936#ifndef VBOX_WS_MAC
1937 << GUI_MachineWindowIcons << GUI_MachineWindowNamePostfix
1938#endif /* !VBOX_WS_MAC */
1939 << GUI_LastNormalWindowPosition << GUI_LastScaleWindowPosition
1940#ifndef VBOX_WS_MAC
1941 << GUI_MenuBar_Enabled
1942#endif
1943 << GUI_MenuBar_ContextMenu_Enabled
1944 << GUI_RestrictedRuntimeMenus
1945 << GUI_RestrictedRuntimeApplicationMenuActions
1946 << GUI_RestrictedRuntimeMachineMenuActions
1947 << GUI_RestrictedRuntimeViewMenuActions
1948 << GUI_RestrictedRuntimeInputMenuActions
1949 << GUI_RestrictedRuntimeDevicesMenuActions
1950#ifdef VBOX_WITH_DEBUGGER_GUI
1951 << GUI_RestrictedRuntimeDebuggerMenuActions
1952#endif /* VBOX_WITH_DEBUGGER_GUI */
1953#ifdef VBOX_WS_MAC
1954 << GUI_RestrictedRuntimeWindowMenuActions
1955#endif /* VBOX_WS_MAC */
1956 << GUI_RestrictedRuntimeHelpMenuActions
1957 << GUI_RestrictedVisualStates
1958 << GUI_Fullscreen << GUI_Seamless << GUI_Scale
1959#ifdef VBOX_WS_X11
1960 << GUI_Fullscreen_LegacyMode
1961 << GUI_DistinguishMachineWindowGroups
1962#endif /* VBOX_WS_X11 */
1963 << GUI_AutoresizeGuest << GUI_LastVisibilityStatusForGuestScreen << GUI_LastGuestSizeHint
1964 << GUI_VirtualScreenToHostScreen << GUI_AutomountGuestScreens
1965#ifdef VBOX_WITH_VIDEOHWACCEL
1966 << GUI_Accelerate2D_StretchLinear
1967 << GUI_Accelerate2D_PixformatYV12 << GUI_Accelerate2D_PixformatUYVY
1968 << GUI_Accelerate2D_PixformatYUY2 << GUI_Accelerate2D_PixformatAYUV
1969#endif /* VBOX_WITH_VIDEOHWACCEL */
1970#ifndef VBOX_WS_MAC
1971 << GUI_ShowMiniToolBar << GUI_MiniToolBarAutoHide << GUI_MiniToolBarAlignment
1972#endif /* !VBOX_WS_MAC */
1973 << GUI_StatusBar_Enabled << GUI_StatusBar_ContextMenu_Enabled << GUI_RestrictedStatusBarIndicators << GUI_StatusBar_IndicatorOrder
1974#ifdef VBOX_WS_MAC
1975 << GUI_RealtimeDockIconUpdateEnabled << GUI_RealtimeDockIconUpdateMonitor << GUI_DockIconDisableOverlay
1976#endif /* VBOX_WS_MAC */
1977 << GUI_PassCAD
1978 << GUI_MouseCapturePolicy
1979 << GUI_GuruMeditationHandler
1980 << GUI_HidLedsSync
1981 << GUI_ScaleFactor << GUI_Scaling_Optimization
1982 << GUI_SessionInformationDialogGeometry
1983 << GUI_GuestControl_ProcessControlSplitterHints
1984 << GUI_GuestControl_FileManagerDialogGeometry
1985 << GUI_GuestControl_FileManagerOptions
1986 << GUI_GuestControl_ProcessControlDialogGeometry
1987 << GUI_DefaultCloseAction << GUI_RestrictedCloseActions
1988 << GUI_LastCloseAction << GUI_CloseActionHook
1989#ifdef VBOX_WITH_DEBUGGER_GUI
1990 << GUI_Dbg_Enabled << GUI_Dbg_AutoShow
1991#endif /* VBOX_WITH_DEBUGGER_GUI */
1992 << GUI_ExtraDataManager_Geometry << GUI_ExtraDataManager_SplitterHints
1993 << GUI_LogWindowGeometry;
1994}
1995
1996#endif /* VBOX_GUI_WITH_EXTRADATA_MANAGER_UI */
1997
1998
1999/*********************************************************************************************************************************
2000* Class UIExtraDataManager implementation. *
2001*********************************************************************************************************************************/
2002
2003/* static */
2004UIExtraDataManager *UIExtraDataManager::s_pInstance = 0;
2005const QUuid UIExtraDataManager::GlobalID;
2006
2007/* static */
2008UIExtraDataManager* UIExtraDataManager::instance()
2009{
2010 /* Create/prepare instance if not yet exists: */
2011 if (!s_pInstance)
2012 {
2013 new UIExtraDataManager;
2014 s_pInstance->prepare();
2015 }
2016 /* Return instance: */
2017 return s_pInstance;
2018}
2019
2020/* static */
2021void UIExtraDataManager::destroy()
2022{
2023 /* Destroy/cleanup instance if still exists: */
2024 if (s_pInstance)
2025 {
2026 s_pInstance->cleanup();
2027 delete s_pInstance;
2028 }
2029}
2030
2031#ifdef VBOX_GUI_WITH_EXTRADATA_MANAGER_UI
2032/* static */
2033void UIExtraDataManager::openWindow(QWidget *pCenterWidget)
2034{
2035 /* Pass to instance: */
2036 instance()->open(pCenterWidget);
2037}
2038#endif /* VBOX_GUI_WITH_EXTRADATA_MANAGER_UI */
2039
2040void UIExtraDataManager::hotloadMachineExtraDataMap(const QUuid &uID)
2041{
2042 /* Make sure it is valid ID: */
2043 AssertMsgReturnVoid(!uID.isNull() && uID != GlobalID,
2044 ("Invalid VM ID = {%s}\n", uID.toString().toUtf8().constData()));
2045 /* Which is not loaded yet: */
2046 AssertReturnVoid(!m_data.contains(uID));
2047
2048 /* Search for corresponding machine: */
2049 CVirtualBox vbox = uiCommon().virtualBox();
2050 CMachine machine = vbox.FindMachine(uID.toString());
2051 AssertReturnVoid(vbox.isOk() && !machine.isNull());
2052
2053 /* Make sure at least empty map is created: */
2054 m_data[uID] = ExtraDataMap();
2055
2056 /* Do not handle inaccessible machine: */
2057 if (!machine.GetAccessible())
2058 return;
2059
2060 /* Load machine extra-data map: */
2061 foreach (const QString &strKey, machine.GetExtraDataKeys())
2062 m_data[uID][strKey] = machine.GetExtraData(strKey);
2063
2064 /* Notifies about extra-data map acknowledged: */
2065 emit sigExtraDataMapAcknowledging(uID);
2066}
2067
2068QString UIExtraDataManager::extraDataString(const QString &strKey, const QUuid &uID /* = GlobalID */)
2069{
2070 /* Get the actual value: */
2071 QString strValue = extraDataStringUnion(strKey, uID);
2072 /* If actual value is null we might be able to find old one: */
2073 if (strValue.isNull())
2074 {
2075 foreach (const QString &strOldKey, g_mapOfObsoleteKeys.values(strKey))
2076 {
2077 strValue = extraDataStringUnion(strOldKey, uID);
2078 if (!strValue.isNull())
2079 break;
2080 }
2081 }
2082 /* Return null string if result is empty: */
2083 if (strValue.isEmpty())
2084 return QString();
2085
2086 /* Returns corresponding value: */
2087 return strValue;
2088}
2089
2090void UIExtraDataManager::setExtraDataString(const QString &strKey, const QString &strValue, const QUuid &uID /* = GlobalID */)
2091{
2092 /* Make sure VBoxSVC is available: */
2093 if (!uiCommon().isVBoxSVCAvailable())
2094 return;
2095
2096 /* Hot-load machine extra-data map if necessary: */
2097 if (uID != GlobalID && !m_data.contains(uID))
2098 hotloadMachineExtraDataMap(uID);
2099
2100 /* Access corresponding map: */
2101 ExtraDataMap &data = m_data[uID];
2102
2103 /* [Re]cache passed value: */
2104 data[strKey] = strValue;
2105
2106 /* Global extra-data: */
2107 if (uID == GlobalID)
2108 {
2109 /* Get global object: */
2110 CVirtualBox comVBox = uiCommon().virtualBox();
2111 /* Update global extra-data: */
2112 comVBox.SetExtraData(strKey, strValue);
2113 if (!comVBox.isOk())
2114 msgCenter().cannotSetExtraData(comVBox, strKey, strValue);
2115 /* Wipe out old keys: */
2116 foreach (const QString &strOldKey, g_mapOfObsoleteKeys.values(strKey))
2117 {
2118 comVBox.SetExtraData(strOldKey, QString());
2119 if (!comVBox.isOk())
2120 {
2121 msgCenter().cannotSetExtraData(comVBox, strOldKey, strValue);
2122 break;
2123 }
2124 }
2125 }
2126 /* Machine extra-data: */
2127 else
2128 {
2129 /* Search for corresponding machine: */
2130 CVirtualBox comVBox = uiCommon().virtualBox();
2131 const CMachine comMachine = comVBox.FindMachine(uID.toString());
2132 AssertReturnVoid(comVBox.isOk() && !comMachine.isNull());
2133 /* Check the configuration access-level: */
2134 const KMachineState enmMachineState = comMachine.GetState();
2135 const KSessionState enmSessionState = comMachine.GetSessionState();
2136 const ConfigurationAccessLevel enmLevel = configurationAccessLevel(enmSessionState, enmMachineState);
2137 /* Prepare machine session: */
2138 CSession comSession;
2139 if (enmLevel == ConfigurationAccessLevel_Full)
2140 comSession = uiCommon().openSession(uID);
2141 else
2142 comSession = uiCommon().openExistingSession(uID);
2143 AssertReturnVoid(!comSession.isNull());
2144 /* Get machine from that session: */
2145 CMachine comSessionMachine = comSession.GetMachine();
2146 /* Update machine extra-data: */
2147 comSessionMachine.SetExtraData(strKey, strValue);
2148 if (!comSessionMachine.isOk())
2149 msgCenter().cannotSetExtraData(comSessionMachine, strKey, strValue);
2150 /* Wipe out old keys: */
2151 foreach (const QString &strOldKey, g_mapOfObsoleteKeys.values(strKey))
2152 {
2153 comSessionMachine.SetExtraData(strOldKey, QString());
2154 if (!comSessionMachine.isOk())
2155 {
2156 msgCenter().cannotSetExtraData(comSessionMachine, strOldKey, strValue);
2157 break;
2158 }
2159 }
2160 comSession.UnlockMachine();
2161 }
2162}
2163
2164QStringList UIExtraDataManager::extraDataStringList(const QString &strKey, const QUuid &uID /* = GlobalID */)
2165{
2166 /* Get the actual value: */
2167 QString strValue = extraDataStringUnion(strKey, uID);
2168 /* If actual value is null we might be able to find old one: */
2169 if (strValue.isNull())
2170 {
2171 foreach (const QString &strOldKey, g_mapOfObsoleteKeys.values(strKey))
2172 {
2173 strValue = extraDataStringUnion(strOldKey, uID);
2174 if (!strValue.isNull())
2175 break;
2176 }
2177 }
2178 /* Return empty string list if result is empty: */
2179 if (strValue.isEmpty())
2180 return QStringList();
2181
2182 /* Few old extra-data string-lists were separated with 'semicolon' symbol.
2183 * All new separated by 'comma'. We have to take that into account. */
2184 return strValue.split(QRegExp("[;,]"), QString::SkipEmptyParts);
2185}
2186
2187void UIExtraDataManager::setExtraDataStringList(const QString &strKey, const QStringList &value, const QUuid &uID /* = GlobalID */)
2188{
2189 /* Make sure VBoxSVC is available: */
2190 if (!uiCommon().isVBoxSVCAvailable())
2191 return;
2192
2193 /* Hot-load machine extra-data map if necessary: */
2194 if (uID != GlobalID && !m_data.contains(uID))
2195 hotloadMachineExtraDataMap(uID);
2196
2197 /* Access corresponding map: */
2198 ExtraDataMap &data = m_data[uID];
2199
2200 /* [Re]cache passed value: */
2201 data[strKey] = value.join(",");
2202
2203 /* Global extra-data: */
2204 if (uID == GlobalID)
2205 {
2206 /* Get global object: */
2207 CVirtualBox comVBox = uiCommon().virtualBox();
2208 /* Update global extra-data: */
2209 comVBox.SetExtraDataStringList(strKey, value);
2210 if (!comVBox.isOk())
2211 msgCenter().cannotSetExtraData(comVBox, strKey, value.join(","));
2212 /* Wipe out old keys: */
2213 foreach (const QString &strOldKey, g_mapOfObsoleteKeys.values(strKey))
2214 {
2215 comVBox.SetExtraData(strOldKey, QString());
2216 if (!comVBox.isOk())
2217 {
2218 msgCenter().cannotSetExtraData(comVBox, strOldKey, value.join(","));
2219 break;
2220 }
2221 }
2222 }
2223 /* Machine extra-data: */
2224 else
2225 {
2226 /* Search for corresponding machine: */
2227 CVirtualBox comVBox = uiCommon().virtualBox();
2228 const CMachine comMachine = comVBox.FindMachine(uID.toString());
2229 AssertReturnVoid(comVBox.isOk() && !comMachine.isNull());
2230 /* Check the configuration access-level: */
2231 const KMachineState enmMachineState = comMachine.GetState();
2232 const KSessionState enmSessionState = comMachine.GetSessionState();
2233 const ConfigurationAccessLevel enmLevel = configurationAccessLevel(enmSessionState, enmMachineState);
2234 /* Prepare machine session: */
2235 CSession comSession;
2236 if (enmLevel == ConfigurationAccessLevel_Full)
2237 comSession = uiCommon().openSession(uID);
2238 else
2239 comSession = uiCommon().openExistingSession(uID);
2240 AssertReturnVoid(!comSession.isNull());
2241 /* Get machine from that session: */
2242 CMachine comSessionMachine = comSession.GetMachine();
2243 /* Update machine extra-data: */
2244 comSessionMachine.SetExtraDataStringList(strKey, value);
2245 if (!comSessionMachine.isOk())
2246 msgCenter().cannotSetExtraData(comSessionMachine, strKey, value.join(","));
2247 /* Wipe out old keys: */
2248 foreach (const QString &strOldKey, g_mapOfObsoleteKeys.values(strKey))
2249 {
2250 comSessionMachine.SetExtraData(strOldKey, QString());
2251 if (!comSessionMachine.isOk())
2252 {
2253 msgCenter().cannotSetExtraData(comSessionMachine, strOldKey, value.join(","));
2254 break;
2255 }
2256 }
2257 comSession.UnlockMachine();
2258 }
2259}
2260
2261UIExtraDataManager::UIExtraDataManager()
2262 : m_pHandler(0)
2263{
2264 /* Connect to static instance: */
2265 s_pInstance = this;
2266}
2267
2268UIExtraDataManager::~UIExtraDataManager()
2269{
2270 /* Disconnect from static instance: */
2271 s_pInstance = 0;
2272}
2273
2274EventHandlingType UIExtraDataManager::eventHandlingType()
2275{
2276 return gpConverter->fromInternalString<EventHandlingType>(extraDataString(GUI_EventHandlingType));
2277}
2278
2279UIExtraDataMetaDefs::DialogType UIExtraDataManager::restrictedDialogTypes(const QUuid &uID)
2280{
2281 /* Prepare result: */
2282 UIExtraDataMetaDefs::DialogType result = UIExtraDataMetaDefs::DialogType_Invalid;
2283 /* Get restricted runtime-menu-types: */
2284 foreach (const QString &strValue, extraDataStringList(GUI_RestrictedDialogs, uID))
2285 {
2286 UIExtraDataMetaDefs::DialogType value = gpConverter->fromInternalString<UIExtraDataMetaDefs::DialogType>(strValue);
2287 if (value != UIExtraDataMetaDefs::DialogType_Invalid)
2288 result = static_cast<UIExtraDataMetaDefs::DialogType>(result | value);
2289 }
2290 /* Return result: */
2291 return result;
2292}
2293
2294void UIExtraDataManager::setRestrictedDialogTypes(UIExtraDataMetaDefs::DialogType dialogs, const QUuid &uID)
2295{
2296 /* We have MenuType enum registered, so we can enumerate it: */
2297 const QMetaObject &smo = UIExtraDataMetaDefs::staticMetaObject;
2298 const int iEnumIndex = smo.indexOfEnumerator("DialogType");
2299 QMetaEnum metaEnum = smo.enumerator(iEnumIndex);
2300
2301 /* Prepare result: */
2302 QStringList result;
2303 /* Handle DialogType_All enum-value: */
2304 if (dialogs == UIExtraDataMetaDefs::DialogType_All)
2305 result << gpConverter->toInternalString(dialogs);
2306 else
2307 {
2308 /* Handle other enum-values: */
2309 for (int iKeyIndex = 0; iKeyIndex < metaEnum.keyCount(); ++iKeyIndex)
2310 {
2311 /* Get iterated enum-value: */
2312 const UIExtraDataMetaDefs::DialogType enumValue =
2313 static_cast<UIExtraDataMetaDefs::DialogType>(metaEnum.keyToValue(metaEnum.key(iKeyIndex)));
2314 /* Skip DialogType_Invalid & DialogType_All enum-values: */
2315 if (enumValue == UIExtraDataMetaDefs::DialogType_Invalid ||
2316 enumValue == UIExtraDataMetaDefs::DialogType_All)
2317 continue;
2318 if (dialogs & enumValue)
2319 result << gpConverter->toInternalString(enumValue);
2320 }
2321 }
2322 /* Save result: */
2323 setExtraDataStringList(GUI_RestrictedDialogs, result, uID);
2324}
2325
2326QStringList UIExtraDataManager::suppressedMessages(const QUuid &uID /* = GlobalID */)
2327{
2328 return extraDataStringList(GUI_SuppressMessages, uID);
2329}
2330
2331void UIExtraDataManager::setSuppressedMessages(const QStringList &list)
2332{
2333 setExtraDataStringList(GUI_SuppressMessages, list);
2334}
2335
2336QStringList UIExtraDataManager::messagesWithInvertedOption()
2337{
2338 return extraDataStringList(GUI_InvertMessageOption);
2339}
2340
2341#if !defined(VBOX_BLEEDING_EDGE) && !defined(DEBUG)
2342QString UIExtraDataManager::preventBetaBuildWarningForVersion()
2343{
2344 return extraDataString(GUI_PreventBetaWarning);
2345}
2346#endif /* !defined(VBOX_BLEEDING_EDGE) && !defined(DEBUG) */
2347
2348#ifdef VBOX_GUI_WITH_NETWORK_MANAGER
2349bool UIExtraDataManager::applicationUpdateEnabled()
2350{
2351 /* 'True' unless 'restriction' feature allowed: */
2352 return !isFeatureAllowed(GUI_PreventApplicationUpdate);
2353}
2354
2355QString UIExtraDataManager::applicationUpdateData()
2356{
2357 return extraDataString(GUI_UpdateDate);
2358}
2359
2360void UIExtraDataManager::setApplicationUpdateData(const QString &strValue)
2361{
2362 setExtraDataString(GUI_UpdateDate, strValue);
2363}
2364
2365qulonglong UIExtraDataManager::applicationUpdateCheckCounter()
2366{
2367 /* Read subsequent update check counter value: */
2368 qulonglong uResult = 1;
2369 const QString strCheckCount = extraDataString(GUI_UpdateCheckCount);
2370 if (!strCheckCount.isEmpty())
2371 {
2372 bool ok = false;
2373 qulonglong uCheckCount = strCheckCount.toULongLong(&ok);
2374 if (ok) uResult = uCheckCount;
2375 }
2376 /* Return update check counter value: */
2377 return uResult;
2378}
2379
2380void UIExtraDataManager::incrementApplicationUpdateCheckCounter()
2381{
2382 /* Increment update check counter value: */
2383 setExtraDataString(GUI_UpdateCheckCount, QString::number(applicationUpdateCheckCounter() + 1));
2384}
2385#endif /* VBOX_GUI_WITH_NETWORK_MANAGER */
2386
2387bool UIExtraDataManager::legacyProgressHandlingRequested()
2388{
2389 /* 'False' unless feature allowed: */
2390 return isFeatureAllowed(GUI_Progress_LegacyMode);
2391}
2392
2393bool UIExtraDataManager::guiFeatureEnabled(GUIFeatureType enmFeature)
2394{
2395 /* Acquire GUI feature list: */
2396 GUIFeatureType enmFeatures = GUIFeatureType_None;
2397 foreach (const QString &strValue, extraDataStringList(GUI_Customizations))
2398 enmFeatures = static_cast<GUIFeatureType>(enmFeatures | gpConverter->fromInternalString<GUIFeatureType>(strValue));
2399 /* Return whether the requested feature is enabled: */
2400 return enmFeatures & enmFeature;
2401}
2402
2403QList<GlobalSettingsPageType> UIExtraDataManager::restrictedGlobalSettingsPages()
2404{
2405 /* Prepare result: */
2406 QList<GlobalSettingsPageType> result;
2407 /* Get restricted global-settings-pages: */
2408 foreach (const QString &strValue, extraDataStringList(GUI_RestrictedGlobalSettingsPages))
2409 {
2410 GlobalSettingsPageType value = gpConverter->fromInternalString<GlobalSettingsPageType>(strValue);
2411 if (value != GlobalSettingsPageType_Invalid)
2412 result << value;
2413 }
2414 /* Return result: */
2415 return result;
2416}
2417
2418QList<MachineSettingsPageType> UIExtraDataManager::restrictedMachineSettingsPages(const QUuid &uID)
2419{
2420 /* Prepare result: */
2421 QList<MachineSettingsPageType> result;
2422 /* Get restricted machine-settings-pages: */
2423 foreach (const QString &strValue, extraDataStringList(GUI_RestrictedMachineSettingsPages, uID))
2424 {
2425 MachineSettingsPageType value = gpConverter->fromInternalString<MachineSettingsPageType>(strValue);
2426 if (value != MachineSettingsPageType_Invalid)
2427 result << value;
2428 }
2429 /* Return result: */
2430 return result;
2431}
2432
2433bool UIExtraDataManager::hostScreenSaverDisabled()
2434{
2435 /* 'False' unless feature allowed: */
2436 return isFeatureAllowed(GUI_HostScreenSaverDisabled);
2437}
2438
2439void UIExtraDataManager::setHostScreenSaverDisabled(bool fDisabled)
2440{
2441 /* 'True' if feature allowed, null-string otherwise: */
2442 setExtraDataString(GUI_HostScreenSaverDisabled, toFeatureAllowed(fDisabled));
2443}
2444
2445QString UIExtraDataManager::languageId()
2446{
2447 /* Load language ID: */
2448 return extraDataString(GUI_LanguageID);
2449}
2450
2451void UIExtraDataManager::setLanguageId(const QString &strLanguageId)
2452{
2453 /* Save language ID: */
2454 setExtraDataString(GUI_LanguageID, strLanguageId);
2455}
2456
2457MaxGuestResolutionPolicy UIExtraDataManager::maxGuestResolutionPolicy()
2458{
2459 /* Return maximum guest-screen resolution policy: */
2460 return gpConverter->fromInternalString<MaxGuestResolutionPolicy>(extraDataString(GUI_MaxGuestResolution));
2461}
2462
2463void UIExtraDataManager::setMaxGuestScreenResolution(MaxGuestResolutionPolicy enmPolicy, const QSize resolution /* = QSize() */)
2464{
2465 /* If policy is 'Fixed' => call the wrapper: */
2466 if (enmPolicy == MaxGuestResolutionPolicy_Fixed)
2467 setMaxGuestResolutionForPolicyFixed(resolution);
2468 /* Otherwise => just store the value: */
2469 else
2470 setExtraDataString(GUI_MaxGuestResolution, gpConverter->toInternalString(enmPolicy));
2471}
2472
2473QSize UIExtraDataManager::maxGuestResolutionForPolicyFixed()
2474{
2475 /* Acquire maximum guest-screen resolution policy: */
2476 const QString strPolicy = extraDataString(GUI_MaxGuestResolution);
2477 const MaxGuestResolutionPolicy enmPolicy = gpConverter->fromInternalString<MaxGuestResolutionPolicy>(strPolicy);
2478
2479 /* Make sure maximum guest-screen resolution policy is really Fixed: */
2480 if (enmPolicy != MaxGuestResolutionPolicy_Fixed)
2481 return QSize();
2482
2483 /* Parse maximum guest-screen resolution: */
2484 const QStringList values = strPolicy.split(',');
2485 int iWidth = values.at(0).toInt();
2486 int iHeight = values.at(1).toInt();
2487 if (iWidth <= 0)
2488 iWidth = 640;
2489 if (iHeight <= 0)
2490 iHeight = 480;
2491
2492 /* Return maximum guest-screen resolution: */
2493 return QSize(iWidth, iHeight);
2494}
2495
2496void UIExtraDataManager::setMaxGuestResolutionForPolicyFixed(const QSize &resolution)
2497{
2498 /* If resolution is 'empty' => call the wrapper: */
2499 if (resolution.isEmpty())
2500 setMaxGuestScreenResolution(MaxGuestResolutionPolicy_Automatic);
2501 /* Otherwise => just store the value: */
2502 else
2503 setExtraDataString(GUI_MaxGuestResolution, QString("%1,%2").arg(resolution.width()).arg(resolution.height()));
2504}
2505
2506bool UIExtraDataManager::activateHoveredMachineWindow()
2507{
2508 /* 'False' unless feature allowed: */
2509 return isFeatureAllowed(GUI_ActivateHoveredMachineWindow);
2510}
2511
2512void UIExtraDataManager::setActivateHoveredMachineWindow(bool fActivate)
2513{
2514 /* 'True' if feature allowed, null-string otherwise: */
2515 setExtraDataString(GUI_ActivateHoveredMachineWindow, toFeatureAllowed(fActivate));
2516}
2517
2518QString UIExtraDataManager::hostKeyCombination()
2519{
2520 /* Acquire host-key combination: */
2521 QString strHostCombo = extraDataString(GUI_Input_HostKeyCombination);
2522 /* Invent some sane default if it's absolutely wrong or invalid: */
2523 QRegularExpression reTemplate("0|[1-9]\\d*(,[1-9]\\d*)?(,[1-9]\\d*)?");
2524 if (!reTemplate.match(strHostCombo).hasMatch() || !UIHostCombo::isValidKeyCombo(strHostCombo))
2525 {
2526#if defined (VBOX_WS_MAC)
2527 strHostCombo = "55"; // QZ_LMETA
2528#elif defined (VBOX_WS_WIN)
2529 strHostCombo = "163"; // VK_RCONTROL
2530#elif defined (VBOX_WS_X11)
2531 strHostCombo = "65508"; // XK_Control_R
2532#else
2533# warning "port me!"
2534#endif
2535 }
2536 /* Return host-key combination: */
2537 return strHostCombo;
2538}
2539
2540void UIExtraDataManager::setHostKeyCombination(const QString &strHostCombo)
2541{
2542 /* Do not save anything if it's absolutely wrong or invalid: */
2543 QRegularExpression reTemplate("0|[1-9]\\d*(,[1-9]\\d*)?(,[1-9]\\d*)?");
2544 if (!reTemplate.match(strHostCombo).hasMatch() || !UIHostCombo::isValidKeyCombo(strHostCombo))
2545 return;
2546 /* Define host-combo: */
2547 setExtraDataString(GUI_Input_HostKeyCombination, strHostCombo);
2548}
2549
2550QStringList UIExtraDataManager::shortcutOverrides(const QString &strPoolExtraDataID)
2551{
2552 if (strPoolExtraDataID == GUI_Input_SelectorShortcuts)
2553 return extraDataStringList(GUI_Input_SelectorShortcuts);
2554 if (strPoolExtraDataID == GUI_Input_MachineShortcuts)
2555 return extraDataStringList(GUI_Input_MachineShortcuts);
2556 return QStringList();
2557}
2558
2559bool UIExtraDataManager::autoCaptureEnabled()
2560{
2561 /* Prepare auto-capture flag: */
2562 bool fAutoCapture = true /* indifferently */;
2563 /* Acquire whether the auto-capture is restricted: */
2564 QString strAutoCapture = extraDataString(GUI_Input_AutoCapture);
2565 /* Invent some sane default if it's empty: */
2566 if (strAutoCapture.isEmpty())
2567 {
2568#if defined(VBOX_WS_X11) && defined(DEBUG)
2569 fAutoCapture = false;
2570#else
2571 fAutoCapture = true;
2572#endif
2573 }
2574 /* 'True' unless feature restricted: */
2575 else
2576 fAutoCapture = !isFeatureRestricted(GUI_Input_AutoCapture);
2577 /* Return auto-capture flag: */
2578 return fAutoCapture;
2579}
2580
2581void UIExtraDataManager::setAutoCaptureEnabled(bool fEnabled)
2582{
2583 /* Store actual feature state, whether it is "true" or "false",
2584 * because absent state means default, different on various hosts: */
2585 setExtraDataString(GUI_Input_AutoCapture, toFeatureState(fEnabled));
2586}
2587
2588QString UIExtraDataManager::remappedScanCodes()
2589{
2590 /* Acquire remapped scan codes: */
2591 QString strRemappedScanCodes = extraDataString(GUI_RemapScancodes);
2592 /* Clear the record if it's absolutely wrong: */
2593 QRegularExpression reTemplate("(\\d+=\\d+,)*\\d+=\\d+");
2594 if (!reTemplate.match(strRemappedScanCodes).hasMatch())
2595 strRemappedScanCodes.clear();
2596 /* Return remapped scan codes: */
2597 return strRemappedScanCodes;
2598}
2599
2600QString UIExtraDataManager::proxySettings()
2601{
2602 return extraDataString(GUI_ProxySettings);
2603}
2604
2605void UIExtraDataManager::setProxySettings(const QString &strSettings)
2606{
2607 setExtraDataString(GUI_ProxySettings, strSettings);
2608}
2609
2610QString UIExtraDataManager::recentFolderForHardDrives()
2611{
2612 return extraDataString(GUI_RecentFolderHD);
2613}
2614
2615QString UIExtraDataManager::recentFolderForOpticalDisks()
2616{
2617 return extraDataString(GUI_RecentFolderCD);
2618}
2619
2620QString UIExtraDataManager::recentFolderForFloppyDisks()
2621{
2622 return extraDataString(GUI_RecentFolderFD);
2623}
2624
2625void UIExtraDataManager::setRecentFolderForHardDrives(const QString &strValue)
2626{
2627 setExtraDataString(GUI_RecentFolderHD, strValue);
2628}
2629
2630void UIExtraDataManager::setRecentFolderForOpticalDisks(const QString &strValue)
2631{
2632 setExtraDataString(GUI_RecentFolderCD, strValue);
2633}
2634
2635void UIExtraDataManager::setRecentFolderForFloppyDisks(const QString &strValue)
2636{
2637 setExtraDataString(GUI_RecentFolderFD, strValue);
2638}
2639
2640QStringList UIExtraDataManager::recentListOfHardDrives()
2641{
2642 return extraDataStringList(GUI_RecentListHD);
2643}
2644
2645QStringList UIExtraDataManager::recentListOfOpticalDisks()
2646{
2647 return extraDataStringList(GUI_RecentListCD);
2648}
2649
2650QStringList UIExtraDataManager::recentListOfFloppyDisks()
2651{
2652 return extraDataStringList(GUI_RecentListFD);
2653}
2654
2655void UIExtraDataManager::setRecentListOfHardDrives(const QStringList &value)
2656{
2657 setExtraDataStringList(GUI_RecentListHD, value);
2658}
2659
2660void UIExtraDataManager::setRecentListOfOpticalDisks(const QStringList &value)
2661{
2662 setExtraDataStringList(GUI_RecentListCD, value);
2663}
2664
2665void UIExtraDataManager::setRecentListOfFloppyDisks(const QStringList &value)
2666{
2667 setExtraDataStringList(GUI_RecentListFD, value);
2668}
2669
2670UIExtraDataMetaDefs::DetailsElementOptionTypeNetwork UIExtraDataManager::restrictedNetworkAttachmentTypes()
2671{
2672 /* Prepare result: */
2673 UIExtraDataMetaDefs::DetailsElementOptionTypeNetwork enmResult =
2674 UIExtraDataMetaDefs::DetailsElementOptionTypeNetwork_Invalid;
2675 /* Get restricted network attachment types: */
2676 foreach (const QString &strValue, extraDataStringList(GUI_RestrictedNetworkAttachmentTypes))
2677 {
2678 const UIExtraDataMetaDefs::DetailsElementOptionTypeNetwork enmValue =
2679 gpConverter->fromInternalString<UIExtraDataMetaDefs::DetailsElementOptionTypeNetwork>(strValue);
2680 if (enmValue != UIExtraDataMetaDefs::DetailsElementOptionTypeNetwork_Invalid && !(enmResult & enmValue))
2681 enmResult = static_cast<UIExtraDataMetaDefs::DetailsElementOptionTypeNetwork>(enmResult | enmValue);
2682 }
2683 /* Return result: */
2684 return enmResult;
2685}
2686
2687QString UIExtraDataManager::visoCreatorRecentFolder()
2688{
2689 return extraDataString(GUI_VISOCreator_RecentFolder);
2690}
2691
2692void UIExtraDataManager::setVISOCreatorRecentFolder(const QString &strValue)
2693{
2694 setExtraDataString(GUI_VISOCreator_RecentFolder, strValue);
2695}
2696
2697QRect UIExtraDataManager::selectorWindowGeometry(QWidget *pWidget)
2698{
2699 return dialogGeometry(GUI_LastSelectorWindowPosition, pWidget);
2700}
2701
2702bool UIExtraDataManager::selectorWindowShouldBeMaximized()
2703{
2704 /* Get corresponding extra-data: */
2705 const QStringList data = extraDataStringList(GUI_LastSelectorWindowPosition);
2706
2707 /* Make sure 5th item has required value: */
2708 return data.size() == 5 && data[4] == GUI_Geometry_State_Max;
2709}
2710
2711void UIExtraDataManager::setSelectorWindowGeometry(const QRect &geometry, bool fMaximized)
2712{
2713 /* Serialize passed values: */
2714 QStringList data;
2715 data << QString::number(geometry.x());
2716 data << QString::number(geometry.y());
2717 data << QString::number(geometry.width());
2718 data << QString::number(geometry.height());
2719 if (fMaximized)
2720 data << GUI_Geometry_State_Max;
2721
2722 /* Re-cache corresponding extra-data: */
2723 setExtraDataStringList(GUI_LastSelectorWindowPosition, data);
2724}
2725
2726QList<int> UIExtraDataManager::selectorWindowSplitterHints()
2727{
2728 /* Get corresponding extra-data: */
2729 const QStringList data = extraDataStringList(GUI_SplitterSizes);
2730
2731 /* Parse loaded data: */
2732 QList<int> hints;
2733 hints << (data.size() > 0 ? data[0].toInt() : 0);
2734 hints << (data.size() > 1 ? data[1].toInt() : 0);
2735
2736 /* Return hints: */
2737 return hints;
2738}
2739
2740void UIExtraDataManager::setSelectorWindowSplitterHints(const QList<int> &hints)
2741{
2742 /* Parse passed hints: */
2743 QStringList data;
2744 data << (hints.size() > 0 ? QString::number(hints[0]) : QString());
2745 data << (hints.size() > 1 ? QString::number(hints[1]) : QString());
2746
2747 /* Re-cache corresponding extra-data: */
2748 setExtraDataStringList(GUI_SplitterSizes, data);
2749}
2750
2751bool UIExtraDataManager::selectorWindowToolBarVisible()
2752{
2753 /* 'True' unless feature restricted: */
2754 return !isFeatureRestricted(GUI_Toolbar);
2755}
2756
2757void UIExtraDataManager::setSelectorWindowToolBarVisible(bool fVisible)
2758{
2759 /* 'False' if feature restricted, null-string otherwise: */
2760 setExtraDataString(GUI_Toolbar, toFeatureRestricted(!fVisible));
2761}
2762
2763bool UIExtraDataManager::selectorWindowToolBarTextVisible()
2764{
2765 /* 'True' unless feature restricted: */
2766 return !isFeatureRestricted(GUI_Toolbar_Text);
2767}
2768
2769void UIExtraDataManager::setSelectorWindowToolBarTextVisible(bool fVisible)
2770{
2771 /* 'False' if feature restricted, null-string otherwise: */
2772 setExtraDataString(GUI_Toolbar_Text, toFeatureRestricted(!fVisible));
2773}
2774
2775QList<UIToolType> UIExtraDataManager::toolsPaneLastItemsChosen()
2776{
2777 /* Parse loaded data: */
2778 QList<UIToolType> result;
2779 foreach (const QString &strValue, extraDataStringList(GUI_Tools_LastItemsSelected))
2780 {
2781 const UIToolType enmType = gpConverter->fromInternalString<UIToolType>(strValue);
2782 if (enmType != UIToolType_Invalid)
2783 result << enmType;
2784 }
2785
2786 /* Return result: */
2787 return result;
2788}
2789
2790void UIExtraDataManager::setToolsPaneLastItemsChosen(const QList<UIToolType> &set)
2791{
2792 /* Serialize passed values: */
2793 QStringList data;
2794 foreach (const UIToolType &enmType, set)
2795 data << gpConverter->toInternalString(enmType);
2796
2797 /* Re-cache corresponding extra-data: */
2798 setExtraDataStringList(GUI_Tools_LastItemsSelected, data);
2799}
2800
2801bool UIExtraDataManager::selectorWindowStatusBarVisible()
2802{
2803 /* 'True' unless feature restricted: */
2804 return !isFeatureRestricted(GUI_Statusbar);
2805}
2806
2807void UIExtraDataManager::setSelectorWindowStatusBarVisible(bool fVisible)
2808{
2809 /* 'False' if feature restricted, null-string otherwise: */
2810 setExtraDataString(GUI_Statusbar, toFeatureRestricted(!fVisible));
2811}
2812
2813void UIExtraDataManager::clearSelectorWindowGroupsDefinitions()
2814{
2815 /* Wipe-out each the group definition record: */
2816 foreach (const QString &strKey, m_data.value(GlobalID).keys())
2817 if (strKey.startsWith(GUI_GroupDefinitions))
2818 setExtraDataString(strKey, QString());
2819}
2820
2821QStringList UIExtraDataManager::selectorWindowGroupsDefinitions(const QString &strGroupID)
2822{
2823 return extraDataStringList(GUI_GroupDefinitions + strGroupID);
2824}
2825
2826void UIExtraDataManager::setSelectorWindowGroupsDefinitions(const QString &strGroupID, const QStringList &definitions)
2827{
2828 setExtraDataStringList(GUI_GroupDefinitions + strGroupID, definitions);
2829}
2830
2831QString UIExtraDataManager::selectorWindowLastItemChosen()
2832{
2833 return extraDataString(GUI_LastItemSelected);
2834}
2835
2836void UIExtraDataManager::setSelectorWindowLastItemChosen(const QString &strItemID)
2837{
2838 setExtraDataString(GUI_LastItemSelected, strItemID);
2839}
2840
2841QMap<DetailsElementType, bool> UIExtraDataManager::selectorWindowDetailsElements()
2842{
2843 /* Get corresponding extra-data: */
2844 const QStringList data = extraDataStringList(GUI_Details_Elements);
2845
2846 /* Desearialize passed elements: */
2847 QMap<DetailsElementType, bool> elements;
2848 foreach (QString strItem, data)
2849 {
2850 bool fOpened = true;
2851 if (strItem.endsWith("Closed", Qt::CaseInsensitive))
2852 {
2853 fOpened = false;
2854 strItem.remove("Closed", Qt::CaseInsensitive);
2855 }
2856 const DetailsElementType enmType = gpConverter->fromInternalString<DetailsElementType>(strItem);
2857 if (enmType != DetailsElementType_Invalid)
2858 elements[enmType] = fOpened;
2859 }
2860
2861 /* If settings are empty: */
2862 if (elements.isEmpty())
2863 {
2864 /* Propose the defaults: */
2865 elements[DetailsElementType_General] = true;
2866 elements[DetailsElementType_Preview] = true;
2867 elements[DetailsElementType_System] = true;
2868 elements[DetailsElementType_Display] = true;
2869 elements[DetailsElementType_Storage] = true;
2870 elements[DetailsElementType_Audio] = true;
2871 elements[DetailsElementType_Network] = true;
2872 elements[DetailsElementType_USB] = true;
2873 elements[DetailsElementType_SF] = true;
2874 elements[DetailsElementType_Description] = true;
2875 }
2876
2877 /* Return elements: */
2878 return elements;
2879}
2880
2881void UIExtraDataManager::setSelectorWindowDetailsElements(const QMap<DetailsElementType, bool> &elements)
2882{
2883 /* Prepare corresponding extra-data: */
2884 QStringList data;
2885
2886 /* Searialize passed elements: */
2887 foreach (DetailsElementType enmType, elements.keys())
2888 {
2889 QString strValue = gpConverter->toInternalString(enmType);
2890 if (!elements[enmType])
2891 strValue += "Closed";
2892 data << strValue;
2893 }
2894
2895 /* Re-cache corresponding extra-data: */
2896 setExtraDataStringList(GUI_Details_Elements, data);
2897}
2898
2899PreviewUpdateIntervalType UIExtraDataManager::selectorWindowPreviewUpdateInterval()
2900{
2901 return gpConverter->fromInternalString<PreviewUpdateIntervalType>(extraDataString(GUI_Details_Elements_Preview_UpdateInterval));
2902}
2903
2904void UIExtraDataManager::setSelectorWindowPreviewUpdateInterval(PreviewUpdateIntervalType interval)
2905{
2906 setExtraDataString(GUI_Details_Elements_Preview_UpdateInterval, gpConverter->toInternalString(interval));
2907}
2908
2909QStringList UIExtraDataManager::vboxManagerDetailsPaneElementOptions(DetailsElementType enmElementType)
2910{
2911 /* Compose full key from GUI_Details_Elements and enmElementType: */
2912 QString strElementType = gpConverter->toInternalString(enmElementType);
2913 AssertReturn(!strElementType.isEmpty(), QStringList());
2914 strElementType[0] = strElementType.at(0).toUpper();
2915 const QString strFullKey = QString("%1/%2").arg(GUI_Details_Elements).arg(strElementType);
2916
2917 /* Return option list: */
2918 return extraDataStringList(strFullKey);
2919}
2920
2921void UIExtraDataManager::setVBoxManagerDetailsPaneElementOptions(DetailsElementType enmElementType, const QStringList &options)
2922{
2923 /* Compose full key from GUI_Details_Elements and enmElementType: */
2924 QString strElementType = gpConverter->toInternalString(enmElementType);
2925 AssertReturnVoid(!strElementType.isEmpty());
2926 strElementType[0] = strElementType.at(0).toUpper();
2927 const QString strFullKey = QString("%1/%2").arg(GUI_Details_Elements).arg(strElementType);
2928
2929 /* Store option list: */
2930 setExtraDataStringList(strFullKey, options);
2931}
2932
2933bool UIExtraDataManager::snapshotManagerDetailsExpanded()
2934{
2935 /* 'False' unless feature allowed: */
2936 return isFeatureAllowed(GUI_SnapshotManager_Details_Expanded);
2937}
2938
2939void UIExtraDataManager::setSnapshotManagerDetailsExpanded(bool fExpanded)
2940{
2941 /* 'True' if feature allowed, null-string otherwise: */
2942 return setExtraDataString(GUI_SnapshotManager_Details_Expanded, toFeatureAllowed(fExpanded));
2943}
2944
2945bool UIExtraDataManager::virtualMediaManagerDetailsExpanded()
2946{
2947 /* 'False' unless feature allowed: */
2948 return isFeatureAllowed(GUI_VirtualMediaManager_Details_Expanded);
2949}
2950
2951void UIExtraDataManager::setVirtualMediaManagerDetailsExpanded(bool fExpanded)
2952{
2953 /* 'True' if feature allowed, null-string otherwise: */
2954 return setExtraDataString(GUI_VirtualMediaManager_Details_Expanded, toFeatureAllowed(fExpanded));
2955}
2956
2957bool UIExtraDataManager::virtualMediaManagerSearchWidgetExpanded()
2958{
2959 /* 'False' unless feature allowed: */
2960 return isFeatureAllowed(GUI_VirtualMediaManager_Search_Widget_Expanded);
2961}
2962
2963void UIExtraDataManager::setVirtualMediaManagerSearchWidgetExpanded(bool fExpanded)
2964{
2965 /* 'True' if feature allowed, null-string otherwise: */
2966 return setExtraDataString(GUI_VirtualMediaManager_Search_Widget_Expanded, toFeatureAllowed(fExpanded));
2967}
2968
2969bool UIExtraDataManager::hostNetworkManagerDetailsExpanded()
2970{
2971 /* 'False' unless feature allowed: */
2972 return isFeatureAllowed(GUI_HostNetworkManager_Details_Expanded);
2973}
2974
2975void UIExtraDataManager::setHostNetworkManagerDetailsExpanded(bool fExpanded)
2976{
2977 /* 'True' if feature allowed, null-string otherwise: */
2978 return setExtraDataString(GUI_HostNetworkManager_Details_Expanded, toFeatureAllowed(fExpanded));
2979}
2980
2981bool UIExtraDataManager::cloudProfileManagerDetailsExpanded()
2982{
2983 /* 'False' unless feature allowed: */
2984 return isFeatureAllowed(GUI_CloudProfileManager_Details_Expanded);
2985}
2986
2987void UIExtraDataManager::setCloudProfileManagerDetailsExpanded(bool fExpanded)
2988{
2989 /* 'True' if feature allowed, null-string otherwise: */
2990 return setExtraDataString(GUI_CloudProfileManager_Details_Expanded, toFeatureAllowed(fExpanded));
2991}
2992
2993WizardMode UIExtraDataManager::modeForWizardType(WizardType type)
2994{
2995 /* Some wizard use only 'basic' mode: */
2996 if (type == WizardType_FirstRun)
2997 return WizardMode_Basic;
2998 /* Otherwise get mode from cached extra-data: */
2999 return extraDataStringList(GUI_HideDescriptionForWizards).contains(gpConverter->toInternalString(type))
3000 ? WizardMode_Expert : WizardMode_Basic;
3001}
3002
3003void UIExtraDataManager::setModeForWizardType(WizardType type, WizardMode mode)
3004{
3005 /* Get wizard name: */
3006 const QString strWizardName = gpConverter->toInternalString(type);
3007 /* Get current value: */
3008 const QStringList oldValue = extraDataStringList(GUI_HideDescriptionForWizards);
3009 QStringList newValue = oldValue;
3010 /* Include wizard-name into expert-mode wizard list if necessary: */
3011 if (mode == WizardMode_Expert && !newValue.contains(strWizardName))
3012 newValue << strWizardName;
3013 /* Exclude wizard-name from expert-mode wizard list if necessary: */
3014 else if (mode == WizardMode_Basic && newValue.contains(strWizardName))
3015 newValue.removeAll(strWizardName);
3016 /* Update extra-data if necessary: */
3017 if (newValue != oldValue)
3018 setExtraDataStringList(GUI_HideDescriptionForWizards, newValue);
3019}
3020
3021bool UIExtraDataManager::showMachineInVirtualBoxManagerChooser(const QUuid &uID)
3022{
3023 /* 'True' unless 'restriction' feature allowed: */
3024 return !isFeatureAllowed(GUI_HideFromManager, uID);
3025}
3026
3027bool UIExtraDataManager::showMachineInVirtualBoxManagerDetails(const QUuid &uID)
3028{
3029 /* 'True' unless 'restriction' feature allowed: */
3030 return !isFeatureAllowed(GUI_HideDetails, uID);
3031}
3032
3033bool UIExtraDataManager::machineReconfigurationEnabled(const QUuid &uID)
3034{
3035 /* 'True' unless 'restriction' feature allowed: */
3036 return !isFeatureAllowed(GUI_PreventReconfiguration, uID);
3037}
3038
3039bool UIExtraDataManager::machineSnapshotOperationsEnabled(const QUuid &uID)
3040{
3041 /* 'True' unless 'restriction' feature allowed: */
3042 return !isFeatureAllowed(GUI_PreventSnapshotOperations, uID);
3043}
3044
3045bool UIExtraDataManager::machineFirstTimeStarted(const QUuid &uID)
3046{
3047 /* 'True' only if feature is allowed: */
3048 return isFeatureAllowed(GUI_FirstRun, uID);
3049}
3050
3051void UIExtraDataManager::setMachineFirstTimeStarted(bool fFirstTimeStarted, const QUuid &uID)
3052{
3053 /* 'True' if feature allowed, null-string otherwise: */
3054 setExtraDataString(GUI_FirstRun, toFeatureAllowed(fFirstTimeStarted), uID);
3055}
3056
3057QStringList UIExtraDataManager::machineWindowIconNames(const QUuid &uID)
3058{
3059 return extraDataStringList(GUI_MachineWindowIcons, uID);
3060}
3061
3062#ifndef VBOX_WS_MAC
3063QString UIExtraDataManager::machineWindowNamePostfix(const QUuid &uID)
3064{
3065 return extraDataString(GUI_MachineWindowNamePostfix, uID);
3066}
3067#endif /* !VBOX_WS_MAC */
3068
3069QRect UIExtraDataManager::machineWindowGeometry(UIVisualStateType visualStateType, ulong uScreenIndex, const QUuid &uID)
3070{
3071 /* Choose corresponding key: */
3072 QString strKey;
3073 switch (visualStateType)
3074 {
3075 case UIVisualStateType_Normal: strKey = extraDataKeyPerScreen(GUI_LastNormalWindowPosition, uScreenIndex); break;
3076 case UIVisualStateType_Scale: strKey = extraDataKeyPerScreen(GUI_LastScaleWindowPosition, uScreenIndex); break;
3077 default: AssertFailedReturn(QRect());
3078 }
3079
3080 /* Get corresponding extra-data: */
3081 const QStringList data = extraDataStringList(strKey, uID);
3082
3083 /* Parse loaded data: */
3084 int iX = 0, iY = 0, iW = 0, iH = 0;
3085 bool fOk = data.size() >= 4;
3086 do
3087 {
3088 if (!fOk) break;
3089 iX = data[0].toInt(&fOk);
3090 if (!fOk) break;
3091 iY = data[1].toInt(&fOk);
3092 if (!fOk) break;
3093 iW = data[2].toInt(&fOk);
3094 if (!fOk) break;
3095 iH = data[3].toInt(&fOk);
3096 }
3097 while (0);
3098
3099 /* Return geometry (loaded or null): */
3100 return fOk ? QRect(iX, iY, iW, iH) : QRect();
3101}
3102
3103bool UIExtraDataManager::machineWindowShouldBeMaximized(UIVisualStateType visualStateType, ulong uScreenIndex, const QUuid &uID)
3104{
3105 /* Choose corresponding key: */
3106 QString strKey;
3107 switch (visualStateType)
3108 {
3109 case UIVisualStateType_Normal: strKey = extraDataKeyPerScreen(GUI_LastNormalWindowPosition, uScreenIndex); break;
3110 case UIVisualStateType_Scale: strKey = extraDataKeyPerScreen(GUI_LastScaleWindowPosition, uScreenIndex); break;
3111 default: AssertFailedReturn(false);
3112 }
3113
3114 /* Get corresponding extra-data: */
3115 const QStringList data = extraDataStringList(strKey, uID);
3116
3117 /* Make sure 5th item has required value: */
3118 return data.size() == 5 && data[4] == GUI_Geometry_State_Max;
3119}
3120
3121void UIExtraDataManager::setMachineWindowGeometry(UIVisualStateType visualStateType, ulong uScreenIndex, const QRect &geometry, bool fMaximized, const QUuid &uID)
3122{
3123 /* Choose corresponding key: */
3124 QString strKey;
3125 switch (visualStateType)
3126 {
3127 case UIVisualStateType_Normal: strKey = extraDataKeyPerScreen(GUI_LastNormalWindowPosition, uScreenIndex); break;
3128 case UIVisualStateType_Scale: strKey = extraDataKeyPerScreen(GUI_LastScaleWindowPosition, uScreenIndex); break;
3129 default: AssertFailedReturnVoid();
3130 }
3131
3132 /* Serialize passed values: */
3133 QStringList data;
3134 data << QString::number(geometry.x());
3135 data << QString::number(geometry.y());
3136 data << QString::number(geometry.width());
3137 data << QString::number(geometry.height());
3138 if (fMaximized)
3139 data << GUI_Geometry_State_Max;
3140
3141 /* Re-cache corresponding extra-data: */
3142 setExtraDataStringList(strKey, data, uID);
3143}
3144
3145#ifndef VBOX_WS_MAC
3146bool UIExtraDataManager::menuBarEnabled(const QUuid &uID)
3147{
3148 /* 'True' unless feature restricted: */
3149 return !isFeatureRestricted(GUI_MenuBar_Enabled, uID);
3150}
3151
3152void UIExtraDataManager::setMenuBarEnabled(bool fEnabled, const QUuid &uID)
3153{
3154 /* 'False' if feature restricted, null-string otherwise: */
3155 setExtraDataString(GUI_MenuBar_Enabled, toFeatureRestricted(!fEnabled), uID);
3156}
3157#endif /* !VBOX_WS_MAC */
3158
3159bool UIExtraDataManager::menuBarContextMenuEnabled(const QUuid &uID)
3160{
3161 /* 'True' unless feature restricted: */
3162 return !isFeatureRestricted(GUI_MenuBar_ContextMenu_Enabled, uID);
3163}
3164
3165void UIExtraDataManager::setMenuBarContextMenuEnabled(bool fEnabled, const QUuid &uID)
3166{
3167 /* 'False' if feature restricted, null-string otherwise: */
3168 setExtraDataString(GUI_MenuBar_ContextMenu_Enabled, toFeatureRestricted(!fEnabled), uID);
3169}
3170
3171UIExtraDataMetaDefs::MenuType UIExtraDataManager::restrictedRuntimeMenuTypes(const QUuid &uID)
3172{
3173 /* Prepare result: */
3174 UIExtraDataMetaDefs::MenuType result = UIExtraDataMetaDefs::MenuType_Invalid;
3175 /* Get restricted runtime-menu-types: */
3176 foreach (const QString &strValue, extraDataStringList(GUI_RestrictedRuntimeMenus, uID))
3177 {
3178 UIExtraDataMetaDefs::MenuType value = gpConverter->fromInternalString<UIExtraDataMetaDefs::MenuType>(strValue);
3179 if (value != UIExtraDataMetaDefs::MenuType_Invalid)
3180 result = static_cast<UIExtraDataMetaDefs::MenuType>(result | value);
3181 }
3182 /* Return result: */
3183 return result;
3184}
3185
3186void UIExtraDataManager::setRestrictedRuntimeMenuTypes(UIExtraDataMetaDefs::MenuType types, const QUuid &uID)
3187{
3188 /* We have MenuType enum registered, so we can enumerate it: */
3189 const QMetaObject &smo = UIExtraDataMetaDefs::staticMetaObject;
3190 const int iEnumIndex = smo.indexOfEnumerator("MenuType");
3191 QMetaEnum metaEnum = smo.enumerator(iEnumIndex);
3192
3193 /* Prepare result: */
3194 QStringList result;
3195 /* Handle MenuType_All enum-value: */
3196 if (types == UIExtraDataMetaDefs::MenuType_All)
3197 result << gpConverter->toInternalString(types);
3198 else
3199 {
3200 /* Handle other enum-values: */
3201 for (int iKeyIndex = 0; iKeyIndex < metaEnum.keyCount(); ++iKeyIndex)
3202 {
3203 /* Get iterated enum-value: */
3204 const UIExtraDataMetaDefs::MenuType enumValue =
3205 static_cast<UIExtraDataMetaDefs::MenuType>(metaEnum.keyToValue(metaEnum.key(iKeyIndex)));
3206 /* Skip MenuType_Invalid & MenuType_All enum-values: */
3207 if (enumValue == UIExtraDataMetaDefs::MenuType_Invalid ||
3208 enumValue == UIExtraDataMetaDefs::MenuType_All)
3209 continue;
3210 if (types & enumValue)
3211 result << gpConverter->toInternalString(enumValue);
3212 }
3213 }
3214 /* Save result: */
3215 setExtraDataStringList(GUI_RestrictedRuntimeMenus, result, uID);
3216}
3217
3218UIExtraDataMetaDefs::MenuApplicationActionType UIExtraDataManager::restrictedRuntimeMenuApplicationActionTypes(const QUuid &uID)
3219{
3220 /* Prepare result: */
3221 UIExtraDataMetaDefs::MenuApplicationActionType result = UIExtraDataMetaDefs::MenuApplicationActionType_Invalid;
3222 /* Get restricted runtime-application-menu action-types: */
3223 foreach (const QString &strValue, extraDataStringList(GUI_RestrictedRuntimeApplicationMenuActions, uID))
3224 {
3225 UIExtraDataMetaDefs::MenuApplicationActionType value = gpConverter->fromInternalString<UIExtraDataMetaDefs::MenuApplicationActionType>(strValue);
3226 if (value != UIExtraDataMetaDefs::MenuApplicationActionType_Invalid)
3227 result = static_cast<UIExtraDataMetaDefs::MenuApplicationActionType>(result | value);
3228 }
3229 /* Return result: */
3230 return result;
3231}
3232
3233void UIExtraDataManager::setRestrictedRuntimeMenuApplicationActionTypes(UIExtraDataMetaDefs::MenuApplicationActionType types, const QUuid &uID)
3234{
3235 /* We have MenuApplicationActionType enum registered, so we can enumerate it: */
3236 const QMetaObject &smo = UIExtraDataMetaDefs::staticMetaObject;
3237 const int iEnumIndex = smo.indexOfEnumerator("MenuApplicationActionType");
3238 QMetaEnum metaEnum = smo.enumerator(iEnumIndex);
3239
3240 /* Prepare result: */
3241 QStringList result;
3242 /* Handle MenuApplicationActionType_All enum-value: */
3243 if (types == UIExtraDataMetaDefs::MenuApplicationActionType_All)
3244 result << gpConverter->toInternalString(types);
3245 else
3246 {
3247 /* Handle other enum-values: */
3248 for (int iKeyIndex = 0; iKeyIndex < metaEnum.keyCount(); ++iKeyIndex)
3249 {
3250 /* Get iterated enum-value: */
3251 const UIExtraDataMetaDefs::MenuApplicationActionType enumValue =
3252 static_cast<UIExtraDataMetaDefs::MenuApplicationActionType>(metaEnum.keyToValue(metaEnum.key(iKeyIndex)));
3253 /* Skip MenuApplicationActionType_Invalid & MenuApplicationActionType_All enum-values: */
3254 if (enumValue == UIExtraDataMetaDefs::MenuApplicationActionType_Invalid ||
3255 enumValue == UIExtraDataMetaDefs::MenuApplicationActionType_All)
3256 continue;
3257 if (types & enumValue)
3258 result << gpConverter->toInternalString(enumValue);
3259 }
3260 }
3261 /* Save result: */
3262 setExtraDataStringList(GUI_RestrictedRuntimeApplicationMenuActions, result, uID);
3263}
3264
3265UIExtraDataMetaDefs::RuntimeMenuMachineActionType UIExtraDataManager::restrictedRuntimeMenuMachineActionTypes(const QUuid &uID)
3266{
3267 /* Prepare result: */
3268 UIExtraDataMetaDefs::RuntimeMenuMachineActionType result = UIExtraDataMetaDefs::RuntimeMenuMachineActionType_Invalid;
3269 /* Get restricted runtime-machine-menu action-types: */
3270 foreach (const QString &strValue, extraDataStringList(GUI_RestrictedRuntimeMachineMenuActions, uID))
3271 {
3272 UIExtraDataMetaDefs::RuntimeMenuMachineActionType value = gpConverter->fromInternalString<UIExtraDataMetaDefs::RuntimeMenuMachineActionType>(strValue);
3273 /* Since empty value has default restriction, we are supporting special 'Nothing' value: */
3274 if (value == UIExtraDataMetaDefs::RuntimeMenuMachineActionType_Nothing)
3275 {
3276 result = UIExtraDataMetaDefs::RuntimeMenuMachineActionType_Nothing;
3277 break;
3278 }
3279 if (value != UIExtraDataMetaDefs::RuntimeMenuMachineActionType_Invalid)
3280 result = static_cast<UIExtraDataMetaDefs::RuntimeMenuMachineActionType>(result | value);
3281 }
3282 /* Defaults: */
3283 if (result == UIExtraDataMetaDefs::RuntimeMenuMachineActionType_Invalid)
3284 {
3285 result = static_cast<UIExtraDataMetaDefs::RuntimeMenuMachineActionType>(result | UIExtraDataMetaDefs::RuntimeMenuMachineActionType_SaveState);
3286 result = static_cast<UIExtraDataMetaDefs::RuntimeMenuMachineActionType>(result | UIExtraDataMetaDefs::RuntimeMenuMachineActionType_PowerOff);
3287 }
3288 /* Return result: */
3289 return result;
3290}
3291
3292void UIExtraDataManager::setRestrictedRuntimeMenuMachineActionTypes(UIExtraDataMetaDefs::RuntimeMenuMachineActionType types, const QUuid &uID)
3293{
3294 /* We have RuntimeMenuMachineActionType enum registered, so we can enumerate it: */
3295 const QMetaObject &smo = UIExtraDataMetaDefs::staticMetaObject;
3296 const int iEnumIndex = smo.indexOfEnumerator("RuntimeMenuMachineActionType");
3297 QMetaEnum metaEnum = smo.enumerator(iEnumIndex);
3298
3299 /* Prepare result: */
3300 QStringList result;
3301 /* Handle RuntimeMenuMachineActionType_All enum-value: */
3302 if (types == UIExtraDataMetaDefs::RuntimeMenuMachineActionType_All)
3303 result << gpConverter->toInternalString(types);
3304 else
3305 {
3306 /* Handle other enum-values: */
3307 for (int iKeyIndex = 0; iKeyIndex < metaEnum.keyCount(); ++iKeyIndex)
3308 {
3309 /* Get iterated enum-value: */
3310 const UIExtraDataMetaDefs::RuntimeMenuMachineActionType enumValue =
3311 static_cast<UIExtraDataMetaDefs::RuntimeMenuMachineActionType>(metaEnum.keyToValue(metaEnum.key(iKeyIndex)));
3312 /* Skip RuntimeMenuMachineActionType_Invalid, RuntimeMenuMachineActionType_Nothing & RuntimeMenuMachineActionType_All enum-values: */
3313 if (enumValue == UIExtraDataMetaDefs::RuntimeMenuMachineActionType_Invalid ||
3314 enumValue == UIExtraDataMetaDefs::RuntimeMenuMachineActionType_Nothing ||
3315 enumValue == UIExtraDataMetaDefs::RuntimeMenuMachineActionType_All)
3316 continue;
3317 if (types & enumValue)
3318 result << gpConverter->toInternalString(enumValue);
3319 }
3320 }
3321 /* Since empty value has default restriction, we are supporting special 'Nothing' value: */
3322 if (result.isEmpty())
3323 result << gpConverter->toInternalString(UIExtraDataMetaDefs::RuntimeMenuMachineActionType_Nothing);
3324 /* Save result: */
3325 setExtraDataStringList(GUI_RestrictedRuntimeMachineMenuActions, result, uID);
3326}
3327
3328UIExtraDataMetaDefs::RuntimeMenuViewActionType UIExtraDataManager::restrictedRuntimeMenuViewActionTypes(const QUuid &uID)
3329{
3330 /* Prepare result: */
3331 UIExtraDataMetaDefs::RuntimeMenuViewActionType result = UIExtraDataMetaDefs::RuntimeMenuViewActionType_Invalid;
3332 /* Get restricted runtime-view-menu action-types: */
3333 foreach (const QString &strValue, extraDataStringList(GUI_RestrictedRuntimeViewMenuActions, uID))
3334 {
3335 UIExtraDataMetaDefs::RuntimeMenuViewActionType value = gpConverter->fromInternalString<UIExtraDataMetaDefs::RuntimeMenuViewActionType>(strValue);
3336 if (value != UIExtraDataMetaDefs::RuntimeMenuViewActionType_Invalid)
3337 result = static_cast<UIExtraDataMetaDefs::RuntimeMenuViewActionType>(result | value);
3338 }
3339 /* Return result: */
3340 return result;
3341}
3342
3343void UIExtraDataManager::setRestrictedRuntimeMenuViewActionTypes(UIExtraDataMetaDefs::RuntimeMenuViewActionType types, const QUuid &uID)
3344{
3345 /* We have RuntimeMenuViewActionType enum registered, so we can enumerate it: */
3346 const QMetaObject &smo = UIExtraDataMetaDefs::staticMetaObject;
3347 const int iEnumIndex = smo.indexOfEnumerator("RuntimeMenuViewActionType");
3348 QMetaEnum metaEnum = smo.enumerator(iEnumIndex);
3349
3350 /* Prepare result: */
3351 QStringList result;
3352 /* Handle RuntimeMenuViewActionType_All enum-value: */
3353 if (types == UIExtraDataMetaDefs::RuntimeMenuViewActionType_All)
3354 result << gpConverter->toInternalString(types);
3355 else
3356 {
3357 /* Handle other enum-values: */
3358 for (int iKeyIndex = 0; iKeyIndex < metaEnum.keyCount(); ++iKeyIndex)
3359 {
3360 /* Get iterated enum-value: */
3361 const UIExtraDataMetaDefs::RuntimeMenuViewActionType enumValue =
3362 static_cast<UIExtraDataMetaDefs::RuntimeMenuViewActionType>(metaEnum.keyToValue(metaEnum.key(iKeyIndex)));
3363 /* Skip RuntimeMenuViewActionType_Invalid & RuntimeMenuViewActionType_All enum-values: */
3364 if (enumValue == UIExtraDataMetaDefs::RuntimeMenuViewActionType_Invalid ||
3365 enumValue == UIExtraDataMetaDefs::RuntimeMenuViewActionType_All)
3366 continue;
3367 if (types & enumValue)
3368 result << gpConverter->toInternalString(enumValue);
3369 }
3370 }
3371 /* Save result: */
3372 setExtraDataStringList(GUI_RestrictedRuntimeViewMenuActions, result, uID);
3373}
3374
3375UIExtraDataMetaDefs::RuntimeMenuInputActionType UIExtraDataManager::restrictedRuntimeMenuInputActionTypes(const QUuid &uID)
3376{
3377 /* Prepare result: */
3378 UIExtraDataMetaDefs::RuntimeMenuInputActionType result = UIExtraDataMetaDefs::RuntimeMenuInputActionType_Invalid;
3379 /* Get restricted runtime-machine-menu action-types: */
3380 foreach (const QString &strValue, extraDataStringList(GUI_RestrictedRuntimeInputMenuActions, uID))
3381 {
3382 UIExtraDataMetaDefs::RuntimeMenuInputActionType value = gpConverter->fromInternalString<UIExtraDataMetaDefs::RuntimeMenuInputActionType>(strValue);
3383 if (value != UIExtraDataMetaDefs::RuntimeMenuInputActionType_Invalid)
3384 result = static_cast<UIExtraDataMetaDefs::RuntimeMenuInputActionType>(result | value);
3385 }
3386 /* Return result: */
3387 return result;
3388}
3389
3390void UIExtraDataManager::setRestrictedRuntimeMenuInputActionTypes(UIExtraDataMetaDefs::RuntimeMenuInputActionType types, const QUuid &uID)
3391{
3392 /* We have RuntimeMenuInputActionType enum registered, so we can enumerate it: */
3393 const QMetaObject &smo = UIExtraDataMetaDefs::staticMetaObject;
3394 const int iEnumIndex = smo.indexOfEnumerator("RuntimeMenuInputActionType");
3395 QMetaEnum metaEnum = smo.enumerator(iEnumIndex);
3396
3397 /* Prepare result: */
3398 QStringList result;
3399 /* Handle RuntimeMenuInputActionType_All enum-value: */
3400 if (types == UIExtraDataMetaDefs::RuntimeMenuInputActionType_All)
3401 result << gpConverter->toInternalString(types);
3402 else
3403 {
3404 /* Handle other enum-values: */
3405 for (int iKeyIndex = 0; iKeyIndex < metaEnum.keyCount(); ++iKeyIndex)
3406 {
3407 /* Get iterated enum-value: */
3408 const UIExtraDataMetaDefs::RuntimeMenuInputActionType enumValue =
3409 static_cast<UIExtraDataMetaDefs::RuntimeMenuInputActionType>(metaEnum.keyToValue(metaEnum.key(iKeyIndex)));
3410 /* Skip RuntimeMenuInputActionType_Invalid & RuntimeMenuInputActionType_All enum-values: */
3411 if (enumValue == UIExtraDataMetaDefs::RuntimeMenuInputActionType_Invalid ||
3412 enumValue == UIExtraDataMetaDefs::RuntimeMenuInputActionType_All)
3413 continue;
3414 if (types & enumValue)
3415 result << gpConverter->toInternalString(enumValue);
3416 }
3417 }
3418 /* Save result: */
3419 setExtraDataStringList(GUI_RestrictedRuntimeInputMenuActions, result, uID);
3420}
3421
3422UIExtraDataMetaDefs::RuntimeMenuDevicesActionType UIExtraDataManager::restrictedRuntimeMenuDevicesActionTypes(const QUuid &uID)
3423{
3424 /* Prepare result: */
3425 UIExtraDataMetaDefs::RuntimeMenuDevicesActionType result = UIExtraDataMetaDefs::RuntimeMenuDevicesActionType_Invalid;
3426 /* Get restricted runtime-devices-menu action-types: */
3427 foreach (const QString &strValue, extraDataStringList(GUI_RestrictedRuntimeDevicesMenuActions, uID))
3428 {
3429 UIExtraDataMetaDefs::RuntimeMenuDevicesActionType value = gpConverter->fromInternalString<UIExtraDataMetaDefs::RuntimeMenuDevicesActionType>(strValue);
3430 /* Since empty value has default restriction, we are supporting special 'Nothing' value: */
3431 if (value == UIExtraDataMetaDefs::RuntimeMenuDevicesActionType_Nothing)
3432 {
3433 result = UIExtraDataMetaDefs::RuntimeMenuDevicesActionType_Nothing;
3434 break;
3435 }
3436 if (value != UIExtraDataMetaDefs::RuntimeMenuDevicesActionType_Invalid)
3437 result = static_cast<UIExtraDataMetaDefs::RuntimeMenuDevicesActionType>(result | value);
3438 }
3439 /* Defaults: */
3440 if (result == UIExtraDataMetaDefs::RuntimeMenuDevicesActionType_Invalid)
3441 {
3442 result = static_cast<UIExtraDataMetaDefs::RuntimeMenuDevicesActionType>(result | UIExtraDataMetaDefs::RuntimeMenuDevicesActionType_HardDrives);
3443 }
3444 /* Return result: */
3445 return result;
3446}
3447
3448void UIExtraDataManager::setRestrictedRuntimeMenuDevicesActionTypes(UIExtraDataMetaDefs::RuntimeMenuDevicesActionType types, const QUuid &uID)
3449{
3450 /* We have RuntimeMenuDevicesActionType enum registered, so we can enumerate it: */
3451 const QMetaObject &smo = UIExtraDataMetaDefs::staticMetaObject;
3452 const int iEnumIndex = smo.indexOfEnumerator("RuntimeMenuDevicesActionType");
3453 QMetaEnum metaEnum = smo.enumerator(iEnumIndex);
3454
3455 /* Prepare result: */
3456 QStringList result;
3457 /* Handle RuntimeMenuDevicesActionType_All enum-value: */
3458 if (types == UIExtraDataMetaDefs::RuntimeMenuDevicesActionType_All)
3459 result << gpConverter->toInternalString(types);
3460 else
3461 {
3462 /* Handle other enum-values: */
3463 for (int iKeyIndex = 0; iKeyIndex < metaEnum.keyCount(); ++iKeyIndex)
3464 {
3465 /* Get iterated enum-value: */
3466 const UIExtraDataMetaDefs::RuntimeMenuDevicesActionType enumValue =
3467 static_cast<UIExtraDataMetaDefs::RuntimeMenuDevicesActionType>(metaEnum.keyToValue(metaEnum.key(iKeyIndex)));
3468 /* Skip RuntimeMenuDevicesActionType_Invalid, RuntimeMenuDevicesActionType_Nothing & RuntimeMenuDevicesActionType_All enum-values: */
3469 if (enumValue == UIExtraDataMetaDefs::RuntimeMenuDevicesActionType_Invalid ||
3470 enumValue == UIExtraDataMetaDefs::RuntimeMenuDevicesActionType_Nothing ||
3471 enumValue == UIExtraDataMetaDefs::RuntimeMenuDevicesActionType_All)
3472 continue;
3473 if (types & enumValue)
3474 result << gpConverter->toInternalString(enumValue);
3475 }
3476 }
3477 /* Since empty value has default restriction, we are supporting special 'Nothing' value: */
3478 if (result.isEmpty())
3479 result << gpConverter->toInternalString(UIExtraDataMetaDefs::RuntimeMenuDevicesActionType_Nothing);
3480 /* Save result: */
3481 setExtraDataStringList(GUI_RestrictedRuntimeDevicesMenuActions, result, uID);
3482}
3483
3484#ifdef VBOX_WITH_DEBUGGER_GUI
3485UIExtraDataMetaDefs::RuntimeMenuDebuggerActionType UIExtraDataManager::restrictedRuntimeMenuDebuggerActionTypes(const QUuid &uID)
3486{
3487 /* Prepare result: */
3488 UIExtraDataMetaDefs::RuntimeMenuDebuggerActionType result = UIExtraDataMetaDefs::RuntimeMenuDebuggerActionType_Invalid;
3489 /* Get restricted runtime-debugger-menu action-types: */
3490 foreach (const QString &strValue, extraDataStringList(GUI_RestrictedRuntimeDebuggerMenuActions, uID))
3491 {
3492 UIExtraDataMetaDefs::RuntimeMenuDebuggerActionType value = gpConverter->fromInternalString<UIExtraDataMetaDefs::RuntimeMenuDebuggerActionType>(strValue);
3493 if (value != UIExtraDataMetaDefs::RuntimeMenuDebuggerActionType_Invalid)
3494 result = static_cast<UIExtraDataMetaDefs::RuntimeMenuDebuggerActionType>(result | value);
3495 }
3496 /* Return result: */
3497 return result;
3498}
3499
3500void UIExtraDataManager::setRestrictedRuntimeMenuDebuggerActionTypes(UIExtraDataMetaDefs::RuntimeMenuDebuggerActionType types, const QUuid &uID)
3501{
3502 /* We have RuntimeMenuDebuggerActionType enum registered, so we can enumerate it: */
3503 const QMetaObject &smo = UIExtraDataMetaDefs::staticMetaObject;
3504 const int iEnumIndex = smo.indexOfEnumerator("RuntimeMenuDebuggerActionType");
3505 QMetaEnum metaEnum = smo.enumerator(iEnumIndex);
3506
3507 /* Prepare result: */
3508 QStringList result;
3509 /* Handle RuntimeMenuDebuggerActionType_All enum-value: */
3510 if (types == UIExtraDataMetaDefs::RuntimeMenuDebuggerActionType_All)
3511 result << gpConverter->toInternalString(types);
3512 else
3513 {
3514 /* Handle other enum-values: */
3515 for (int iKeyIndex = 0; iKeyIndex < metaEnum.keyCount(); ++iKeyIndex)
3516 {
3517 /* Get iterated enum-value: */
3518 const UIExtraDataMetaDefs::RuntimeMenuDebuggerActionType enumValue =
3519 static_cast<UIExtraDataMetaDefs::RuntimeMenuDebuggerActionType>(metaEnum.keyToValue(metaEnum.key(iKeyIndex)));
3520 /* Skip RuntimeMenuDebuggerActionType_Invalid & RuntimeMenuDebuggerActionType_All enum-values: */
3521 if (enumValue == UIExtraDataMetaDefs::RuntimeMenuDebuggerActionType_Invalid ||
3522 enumValue == UIExtraDataMetaDefs::RuntimeMenuDebuggerActionType_All)
3523 continue;
3524 if (types & enumValue)
3525 result << gpConverter->toInternalString(enumValue);
3526 }
3527 }
3528 /* Save result: */
3529 setExtraDataStringList(GUI_RestrictedRuntimeDebuggerMenuActions, result, uID);
3530}
3531#endif /* VBOX_WITH_DEBUGGER_GUI */
3532
3533#ifdef VBOX_WS_MAC
3534UIExtraDataMetaDefs::MenuWindowActionType UIExtraDataManager::restrictedRuntimeMenuWindowActionTypes(const QUuid &uID)
3535{
3536 /* Prepare result: */
3537 UIExtraDataMetaDefs::MenuWindowActionType result = UIExtraDataMetaDefs::MenuWindowActionType_Invalid;
3538 /* Get restricted runtime-window-menu action-types: */
3539 foreach (const QString &strValue, extraDataStringList(GUI_RestrictedRuntimeWindowMenuActions, uID))
3540 {
3541 UIExtraDataMetaDefs::MenuWindowActionType value = gpConverter->fromInternalString<UIExtraDataMetaDefs::MenuWindowActionType>(strValue);
3542 if (value != UIExtraDataMetaDefs::MenuWindowActionType_Invalid)
3543 result = static_cast<UIExtraDataMetaDefs::MenuWindowActionType>(result | value);
3544 }
3545 /* Return result: */
3546 return result;
3547}
3548
3549void UIExtraDataManager::setRestrictedRuntimeMenuWindowActionTypes(UIExtraDataMetaDefs::MenuWindowActionType types, const QUuid &uID)
3550{
3551 /* We have MenuWindowActionType enum registered, so we can enumerate it: */
3552 const QMetaObject &smo = UIExtraDataMetaDefs::staticMetaObject;
3553 const int iEnumIndex = smo.indexOfEnumerator("MenuWindowActionType");
3554 QMetaEnum metaEnum = smo.enumerator(iEnumIndex);
3555
3556 /* Prepare result: */
3557 QStringList result;
3558 /* Handle MenuWindowActionType_All enum-value: */
3559 if (types == UIExtraDataMetaDefs::MenuWindowActionType_All)
3560 result << gpConverter->toInternalString(types);
3561 else
3562 {
3563 /* Handle other enum-values: */
3564 for (int iKeyIndex = 0; iKeyIndex < metaEnum.keyCount(); ++iKeyIndex)
3565 {
3566 /* Get iterated enum-value: */
3567 const UIExtraDataMetaDefs::MenuWindowActionType enumValue =
3568 static_cast<const UIExtraDataMetaDefs::MenuWindowActionType>(metaEnum.keyToValue(metaEnum.key(iKeyIndex)));
3569 /* Skip MenuWindowActionType_Invalid & MenuWindowActionType_All enum-values: */
3570 if (enumValue == UIExtraDataMetaDefs::MenuWindowActionType_Invalid ||
3571 enumValue == UIExtraDataMetaDefs::MenuWindowActionType_All)
3572 continue;
3573 if (types & enumValue)
3574 result << gpConverter->toInternalString(enumValue);
3575 }
3576 }
3577 /* Save result: */
3578 setExtraDataStringList(GUI_RestrictedRuntimeWindowMenuActions, result, uID);
3579}
3580#endif /* VBOX_WS_MAC */
3581
3582UIExtraDataMetaDefs::MenuHelpActionType UIExtraDataManager::restrictedRuntimeMenuHelpActionTypes(const QUuid &uID)
3583{
3584 /* Prepare result: */
3585 UIExtraDataMetaDefs::MenuHelpActionType result = UIExtraDataMetaDefs::MenuHelpActionType_Invalid;
3586 /* Get restricted runtime-help-menu action-types: */
3587 foreach (const QString &strValue, extraDataStringList(GUI_RestrictedRuntimeHelpMenuActions, uID))
3588 {
3589 UIExtraDataMetaDefs::MenuHelpActionType value = gpConverter->fromInternalString<UIExtraDataMetaDefs::MenuHelpActionType>(strValue);
3590 if (value != UIExtraDataMetaDefs::MenuHelpActionType_Invalid)
3591 result = static_cast<UIExtraDataMetaDefs::MenuHelpActionType>(result | value);
3592 }
3593 /* Return result: */
3594 return result;
3595}
3596
3597void UIExtraDataManager::setRestrictedRuntimeMenuHelpActionTypes(UIExtraDataMetaDefs::MenuHelpActionType types, const QUuid &uID)
3598{
3599 /* We have MenuHelpActionType enum registered, so we can enumerate it: */
3600 const QMetaObject &smo = UIExtraDataMetaDefs::staticMetaObject;
3601 const int iEnumIndex = smo.indexOfEnumerator("MenuHelpActionType");
3602 QMetaEnum metaEnum = smo.enumerator(iEnumIndex);
3603
3604 /* Prepare result: */
3605 QStringList result;
3606 /* Handle MenuHelpActionType_All enum-value: */
3607 if (types == UIExtraDataMetaDefs::MenuHelpActionType_All)
3608 result << gpConverter->toInternalString(types);
3609 else
3610 {
3611 /* Handle other enum-values: */
3612 for (int iKeyIndex = 0; iKeyIndex < metaEnum.keyCount(); ++iKeyIndex)
3613 {
3614 /* Get iterated enum-value: */
3615 const UIExtraDataMetaDefs::MenuHelpActionType enumValue =
3616 static_cast<UIExtraDataMetaDefs::MenuHelpActionType>(metaEnum.keyToValue(metaEnum.key(iKeyIndex)));
3617 /* Skip MenuHelpActionType_Invalid && MenuHelpActionType_All enum-values: */
3618 if (enumValue == UIExtraDataMetaDefs::MenuHelpActionType_Invalid ||
3619 enumValue == UIExtraDataMetaDefs::MenuHelpActionType_All)
3620 continue;
3621 if (types & enumValue)
3622 result << gpConverter->toInternalString(enumValue);
3623 }
3624 }
3625 /* Save result: */
3626 setExtraDataStringList(GUI_RestrictedRuntimeHelpMenuActions, result, uID);
3627}
3628
3629UIVisualStateType UIExtraDataManager::restrictedVisualStates(const QUuid &uID)
3630{
3631 /* Prepare result: */
3632 UIVisualStateType result = UIVisualStateType_Invalid;
3633 /* Get restricted visual-state-types: */
3634 foreach (const QString &strValue, extraDataStringList(GUI_RestrictedVisualStates, uID))
3635 {
3636 UIVisualStateType value = gpConverter->fromInternalString<UIVisualStateType>(strValue);
3637 if (value != UIVisualStateType_Invalid)
3638 result = static_cast<UIVisualStateType>(result | value);
3639 }
3640 /* Return result: */
3641 return result;
3642}
3643
3644UIVisualStateType UIExtraDataManager::requestedVisualState(const QUuid &uID)
3645{
3646 if (isFeatureAllowed(GUI_Fullscreen, uID)) return UIVisualStateType_Fullscreen;
3647 if (isFeatureAllowed(GUI_Seamless, uID)) return UIVisualStateType_Seamless;
3648 if (isFeatureAllowed(GUI_Scale, uID)) return UIVisualStateType_Scale;
3649 return UIVisualStateType_Normal;
3650}
3651
3652void UIExtraDataManager::setRequestedVisualState(UIVisualStateType visualState, const QUuid &uID)
3653{
3654 setExtraDataString(GUI_Fullscreen, toFeatureAllowed(visualState == UIVisualStateType_Fullscreen), uID);
3655 setExtraDataString(GUI_Seamless, toFeatureAllowed(visualState == UIVisualStateType_Seamless), uID);
3656 setExtraDataString(GUI_Scale, toFeatureAllowed(visualState == UIVisualStateType_Scale), uID);
3657}
3658
3659#ifdef VBOX_WS_X11
3660bool UIExtraDataManager::legacyFullscreenModeRequested()
3661{
3662 /* 'False' unless feature allowed: */
3663 return isFeatureAllowed(GUI_Fullscreen_LegacyMode);
3664}
3665
3666bool UIExtraDataManager::distinguishMachineWindowGroups(const QUuid &uID)
3667{
3668 /* 'False' unless feature allowed: */
3669 return isFeatureAllowed(GUI_DistinguishMachineWindowGroups, uID);
3670}
3671
3672void UIExtraDataManager::setDistinguishMachineWindowGroups(const QUuid &uID, bool fEnabled)
3673{
3674 /* 'True' if feature allowed, null-string otherwise: */
3675 setExtraDataString(GUI_DistinguishMachineWindowGroups, toFeatureAllowed(fEnabled), uID);
3676}
3677#endif /* VBOX_WS_X11 */
3678
3679bool UIExtraDataManager::guestScreenAutoResizeEnabled(const QUuid &uID)
3680{
3681 /* 'True' unless feature restricted: */
3682 return !isFeatureRestricted(GUI_AutoresizeGuest, uID);
3683}
3684
3685void UIExtraDataManager::setGuestScreenAutoResizeEnabled(bool fEnabled, const QUuid &uID)
3686{
3687 /* 'False' if feature restricted, null-string otherwise: */
3688 setExtraDataString(GUI_AutoresizeGuest, toFeatureRestricted(!fEnabled), uID);
3689}
3690
3691bool UIExtraDataManager::lastGuestScreenVisibilityStatus(ulong uScreenIndex, const QUuid &uID)
3692{
3693 /* Not for primary screen: */
3694 if (uScreenIndex == 0)
3695 return true;
3696
3697 /* Compose corresponding key: */
3698 const QString strKey = extraDataKeyPerScreen(GUI_LastVisibilityStatusForGuestScreen, uScreenIndex);
3699
3700 /* 'False' unless feature allowed: */
3701 return isFeatureAllowed(strKey, uID);
3702}
3703
3704void UIExtraDataManager::setLastGuestScreenVisibilityStatus(ulong uScreenIndex, bool fEnabled, const QUuid &uID)
3705{
3706 /* Not for primary screen: */
3707 if (uScreenIndex == 0)
3708 return;
3709
3710 /* Compose corresponding key: */
3711 const QString strKey = extraDataKeyPerScreen(GUI_LastVisibilityStatusForGuestScreen, uScreenIndex);
3712
3713 /* 'True' if feature allowed, null-string otherwise: */
3714 return setExtraDataString(strKey, toFeatureAllowed(fEnabled), uID);
3715}
3716
3717QSize UIExtraDataManager::lastGuestScreenSizeHint(ulong uScreenIndex, const QUuid &uID)
3718{
3719 /* Choose corresponding key: */
3720 const QString strKey = extraDataKeyPerScreen(GUI_LastGuestSizeHint, uScreenIndex);
3721
3722 /* Get corresponding extra-data: */
3723 const QStringList data = extraDataStringList(strKey, uID);
3724
3725 /* Parse loaded data: */
3726 int iW = 0, iH = 0;
3727 bool fOk = data.size() == 2;
3728 do
3729 {
3730 if (!fOk) break;
3731 iW = data[0].toInt(&fOk);
3732 if (!fOk) break;
3733 iH = data[1].toInt(&fOk);
3734 }
3735 while (0);
3736
3737 /* Return size (loaded or invalid): */
3738 return fOk ? QSize(iW, iH) : QSize();
3739}
3740
3741void UIExtraDataManager::setLastGuestScreenSizeHint(ulong uScreenIndex, const QSize &sizeHint, const QUuid &uID)
3742{
3743 /* Choose corresponding key: */
3744 const QString strKey = extraDataKeyPerScreen(GUI_LastGuestSizeHint, uScreenIndex);
3745
3746 /* Serialize passed values: */
3747 QStringList data;
3748 data << QString::number(sizeHint.width());
3749 data << QString::number(sizeHint.height());
3750
3751 /* Re-cache corresponding extra-data: */
3752 setExtraDataStringList(strKey, data, uID);
3753}
3754
3755int UIExtraDataManager::hostScreenForPassedGuestScreen(int iGuestScreenIndex, const QUuid &uID)
3756{
3757 /* Choose corresponding key: */
3758 const QString strKey = extraDataKeyPerScreen(GUI_VirtualScreenToHostScreen, iGuestScreenIndex, true);
3759
3760 /* Get value and convert it to index: */
3761 const QString strValue = extraDataString(strKey, uID);
3762 bool fOk = false;
3763 const int iHostScreenIndex = strValue.toULong(&fOk);
3764
3765 /* Return corresponding index: */
3766 return fOk ? iHostScreenIndex : -1;
3767}
3768
3769void UIExtraDataManager::setHostScreenForPassedGuestScreen(int iGuestScreenIndex, int iHostScreenIndex, const QUuid &uID)
3770{
3771 /* Choose corresponding key: */
3772 const QString strKey = extraDataKeyPerScreen(GUI_VirtualScreenToHostScreen, iGuestScreenIndex, true);
3773
3774 /* Save passed index under corresponding value: */
3775 setExtraDataString(strKey, iHostScreenIndex != -1 ? QString::number(iHostScreenIndex) : QString(), uID);
3776}
3777
3778bool UIExtraDataManager::autoMountGuestScreensEnabled(const QUuid &uID)
3779{
3780 /* Show only if 'allowed' flag is set: */
3781 return isFeatureAllowed(GUI_AutomountGuestScreens, uID);
3782}
3783
3784#ifdef VBOX_WITH_VIDEOHWACCEL
3785bool UIExtraDataManager::useLinearStretch(const QUuid &uID)
3786{
3787 /* 'True' unless feature restricted: */
3788 return !isFeatureRestricted(GUI_Accelerate2D_StretchLinear, uID);
3789}
3790
3791bool UIExtraDataManager::usePixelFormatYV12(const QUuid &uID)
3792{
3793 /* 'True' unless feature restricted: */
3794 return !isFeatureRestricted(GUI_Accelerate2D_PixformatYV12, uID);
3795}
3796
3797bool UIExtraDataManager::usePixelFormatUYVY(const QUuid &uID)
3798{
3799 /* 'True' unless feature restricted: */
3800 return !isFeatureRestricted(GUI_Accelerate2D_PixformatUYVY, uID);
3801}
3802
3803bool UIExtraDataManager::usePixelFormatYUY2(const QUuid &uID)
3804{
3805 /* 'True' unless feature restricted: */
3806 return !isFeatureRestricted(GUI_Accelerate2D_PixformatYUY2, uID);
3807}
3808
3809bool UIExtraDataManager::usePixelFormatAYUV(const QUuid &uID)
3810{
3811 /* 'True' unless feature restricted: */
3812 return !isFeatureRestricted(GUI_Accelerate2D_PixformatAYUV, uID);
3813}
3814#endif /* VBOX_WITH_VIDEOHWACCEL */
3815
3816#ifndef VBOX_WS_MAC
3817bool UIExtraDataManager::miniToolbarEnabled(const QUuid &uID)
3818{
3819 /* 'True' unless feature restricted: */
3820 return !isFeatureRestricted(GUI_ShowMiniToolBar, uID);
3821}
3822
3823void UIExtraDataManager::setMiniToolbarEnabled(bool fEnabled, const QUuid &uID)
3824{
3825 /* 'False' if feature restricted, null-string otherwise: */
3826 setExtraDataString(GUI_ShowMiniToolBar, toFeatureRestricted(!fEnabled), uID);
3827}
3828
3829bool UIExtraDataManager::autoHideMiniToolbar(const QUuid &uID)
3830{
3831 /* 'True' unless feature restricted: */
3832 return !isFeatureRestricted(GUI_MiniToolBarAutoHide, uID);
3833}
3834
3835void UIExtraDataManager::setAutoHideMiniToolbar(bool fAutoHide, const QUuid &uID)
3836{
3837 /* 'False' if feature restricted, null-string otherwise: */
3838 setExtraDataString(GUI_MiniToolBarAutoHide, toFeatureRestricted(!fAutoHide), uID);
3839}
3840
3841Qt::AlignmentFlag UIExtraDataManager::miniToolbarAlignment(const QUuid &uID)
3842{
3843 /* Return Qt::AlignBottom unless MiniToolbarAlignment_Top specified separately: */
3844 switch (gpConverter->fromInternalString<MiniToolbarAlignment>(extraDataString(GUI_MiniToolBarAlignment, uID)))
3845 {
3846 case MiniToolbarAlignment_Top: return Qt::AlignTop;
3847 default: break;
3848 }
3849 return Qt::AlignBottom;
3850}
3851
3852void UIExtraDataManager::setMiniToolbarAlignment(Qt::AlignmentFlag alignment, const QUuid &uID)
3853{
3854 /* Remove record unless Qt::AlignTop specified separately: */
3855 switch (alignment)
3856 {
3857 case Qt::AlignTop: setExtraDataString(GUI_MiniToolBarAlignment, gpConverter->toInternalString(MiniToolbarAlignment_Top), uID); return;
3858 default: break;
3859 }
3860 setExtraDataString(GUI_MiniToolBarAlignment, QString(), uID);
3861}
3862#endif /* VBOX_WS_MAC */
3863
3864bool UIExtraDataManager::statusBarEnabled(const QUuid &uID)
3865{
3866 /* 'True' unless feature restricted: */
3867 return !isFeatureRestricted(GUI_StatusBar_Enabled, uID);
3868}
3869
3870void UIExtraDataManager::setStatusBarEnabled(bool fEnabled, const QUuid &uID)
3871{
3872 /* 'False' if feature restricted, null-string otherwise: */
3873 setExtraDataString(GUI_StatusBar_Enabled, toFeatureRestricted(!fEnabled), uID);
3874}
3875
3876bool UIExtraDataManager::statusBarContextMenuEnabled(const QUuid &uID)
3877{
3878 /* 'True' unless feature restricted: */
3879 return !isFeatureRestricted(GUI_StatusBar_ContextMenu_Enabled, uID);
3880}
3881
3882void UIExtraDataManager::setStatusBarContextMenuEnabled(bool fEnabled, const QUuid &uID)
3883{
3884 /* 'False' if feature restricted, null-string otherwise: */
3885 setExtraDataString(GUI_StatusBar_ContextMenu_Enabled, toFeatureRestricted(!fEnabled), uID);
3886}
3887
3888QList<IndicatorType> UIExtraDataManager::restrictedStatusBarIndicators(const QUuid &uID)
3889{
3890 /* Prepare result: */
3891 QList<IndicatorType> result;
3892 /* Get restricted status-bar indicators: */
3893 foreach (const QString &strValue, extraDataStringList(GUI_RestrictedStatusBarIndicators, uID))
3894 {
3895 const IndicatorType value = gpConverter->fromInternalString<IndicatorType>(strValue);
3896 if (value != IndicatorType_Invalid && !result.contains(value))
3897 result << value;
3898 }
3899 /* Return result: */
3900 return result;
3901}
3902
3903void UIExtraDataManager::setRestrictedStatusBarIndicators(const QList<IndicatorType> &list, const QUuid &uID)
3904{
3905 /* Parse passed list: */
3906 QStringList data;
3907 foreach (const IndicatorType &indicatorType, list)
3908 data << gpConverter->toInternalString(indicatorType);
3909
3910 /* Re-cache corresponding extra-data: */
3911 setExtraDataStringList(GUI_RestrictedStatusBarIndicators, data, uID);
3912}
3913
3914QList<IndicatorType> UIExtraDataManager::statusBarIndicatorOrder(const QUuid &uID)
3915{
3916 /* Prepare result: */
3917 QList<IndicatorType> result;
3918 /* Get status-bar indicator order: */
3919 foreach (const QString &strValue, extraDataStringList(GUI_StatusBar_IndicatorOrder, uID))
3920 {
3921 const IndicatorType value = gpConverter->fromInternalString<IndicatorType>(strValue);
3922 if (value != IndicatorType_Invalid && !result.contains(value))
3923 result << value;
3924 }
3925
3926 /* We should update the list with missing indicators: */
3927 for (int i = (int)IndicatorType_Invalid; i < (int)IndicatorType_Max; ++i)
3928 {
3929 /* Skip the IndicatorType_Invalid (we used it as start of this loop): */
3930 if (i == (int)IndicatorType_Invalid)
3931 continue;
3932 /* Skip the IndicatorType_KeyboardExtension (special handling): */
3933 if (i == (int)IndicatorType_KeyboardExtension)
3934 continue;
3935
3936 /* Get the current one: */
3937 const IndicatorType enmCurrent = (IndicatorType)i;
3938
3939 /* Skip the current one if it's present: */
3940 if (result.contains(enmCurrent))
3941 continue;
3942
3943 /* Let's find the first of those which stays before it and is not missing: */
3944 IndicatorType enmPrevious = (IndicatorType)(enmCurrent - 1);
3945 while (enmPrevious != IndicatorType_Invalid && !result.contains(enmPrevious))
3946 enmPrevious = (IndicatorType)(enmPrevious - 1);
3947
3948 /* Calculate position to insert missing one: */
3949 const int iInsertPosition = enmPrevious != IndicatorType_Invalid
3950 ? result.indexOf(enmPrevious) + 1
3951 : 0;
3952
3953 /* Finally insert missing indicator at required position: */
3954 result.insert(iInsertPosition, enmCurrent);
3955 }
3956
3957 /* Return result: */
3958 return result;
3959}
3960
3961void UIExtraDataManager::setStatusBarIndicatorOrder(const QList<IndicatorType> &list, const QUuid &uID)
3962{
3963 /* Parse passed list: */
3964 QStringList data;
3965 foreach (const IndicatorType &indicatorType, list)
3966 data << gpConverter->toInternalString(indicatorType);
3967
3968 /* Re-cache corresponding extra-data: */
3969 setExtraDataStringList(GUI_StatusBar_IndicatorOrder, data, uID);
3970}
3971
3972#ifdef VBOX_WS_MAC
3973bool UIExtraDataManager::realtimeDockIconUpdateEnabled(const QUuid &uID)
3974{
3975 /* 'True' unless feature restricted: */
3976 return !isFeatureRestricted(GUI_RealtimeDockIconUpdateEnabled, uID);
3977}
3978
3979void UIExtraDataManager::setRealtimeDockIconUpdateEnabled(bool fEnabled, const QUuid &uID)
3980{
3981 /* 'False' if feature restricted, null-string otherwise: */
3982 setExtraDataString(GUI_RealtimeDockIconUpdateEnabled, toFeatureRestricted(!fEnabled), uID);
3983}
3984
3985int UIExtraDataManager::realtimeDockIconUpdateMonitor(const QUuid &uID)
3986{
3987 return extraDataString(GUI_RealtimeDockIconUpdateMonitor, uID).toInt();
3988}
3989
3990void UIExtraDataManager::setRealtimeDockIconUpdateMonitor(int iIndex, const QUuid &uID)
3991{
3992 setExtraDataString(GUI_RealtimeDockIconUpdateMonitor, iIndex ? QString::number(iIndex) : QString(), uID);
3993}
3994
3995bool UIExtraDataManager::dockIconDisableOverlay(const QUuid &uID)
3996{
3997 /* 'False' unless feature allowed: */
3998 return isFeatureAllowed(GUI_DockIconDisableOverlay, uID);
3999}
4000
4001void UIExtraDataManager::setDockIconDisableOverlay(bool fDisabled, const QUuid &uID)
4002{
4003 /* 'True' if feature allowed, null-string otherwise: */
4004 setExtraDataString(GUI_DockIconDisableOverlay, toFeatureAllowed(fDisabled), uID);
4005}
4006#endif /* VBOX_WS_MAC */
4007
4008bool UIExtraDataManager::passCADtoGuest(const QUuid &uID)
4009{
4010 /* 'False' unless feature allowed: */
4011 return isFeatureAllowed(GUI_PassCAD, uID);
4012}
4013
4014MouseCapturePolicy UIExtraDataManager::mouseCapturePolicy(const QUuid &uID)
4015{
4016 return gpConverter->fromInternalString<MouseCapturePolicy>(extraDataString(GUI_MouseCapturePolicy, uID));
4017}
4018
4019GuruMeditationHandlerType UIExtraDataManager::guruMeditationHandlerType(const QUuid &uID)
4020{
4021 return gpConverter->fromInternalString<GuruMeditationHandlerType>(extraDataString(GUI_GuruMeditationHandler, uID));
4022}
4023
4024bool UIExtraDataManager::hidLedsSyncState(const QUuid &uID)
4025{
4026 /* 'True' unless feature restricted: */
4027 return !isFeatureRestricted(GUI_HidLedsSync, uID);
4028}
4029
4030double UIExtraDataManager::scaleFactor(const QUuid &uID, const int uScreenIndex)
4031{
4032 /* Get corresponding extra-data for this machine: */
4033 QStringList data = extraDataStringList(GUI_ScaleFactor, uID);
4034
4035 /* 1.0 is default scale factor: */
4036 if (data.size() == 0)
4037 return 1.0;
4038
4039 int index = uScreenIndex;
4040 /* use the 0th. scale factor in case we dont have a scale factor for @p uScreenIndex: */
4041 if (data.size() <= uScreenIndex)
4042 index = 0;
4043
4044 bool fOk = false;
4045 double scaleFactor = data[index].toDouble(&fOk);
4046 if (!fOk)
4047 return 1.0;
4048 return scaleFactor;
4049}
4050
4051QList<double> UIExtraDataManager::scaleFactors(const QUuid &uID)
4052{
4053 /* Look for the scale factor for this machine first: */
4054 QStringList data = extraDataStringList(GUI_ScaleFactor, uID);
4055
4056 QList<double> scaleFactorList;
4057 /* 1.0 is default scale factor: */
4058 if (data.size() == 0)
4059 {
4060 scaleFactorList.append(1.0);
4061 return scaleFactorList;
4062 }
4063
4064 bool fOk = false;
4065 double scaleFactor;
4066 for (int i = 0; i < data.size(); ++i)
4067 {
4068 scaleFactor = data[i].toDouble(&fOk);
4069 if (!fOk)
4070 scaleFactor = 1.0;
4071 scaleFactorList.append(scaleFactor);
4072 }
4073 return scaleFactorList;
4074}
4075
4076void UIExtraDataManager::setScaleFactor(double dScaleFactor, const QUuid &uID, const int uScreenIndex)
4077{
4078 QStringList data = extraDataStringList(GUI_ScaleFactor, uID);
4079
4080 /* Just make sure that we have corresponding data item: */
4081 if (data.size() <= uScreenIndex)
4082 {
4083 int listSize = data.size();
4084 for (int i = listSize; i <= uScreenIndex; ++i)
4085 data.append(QString::number(1.0));
4086 }
4087
4088 data[uScreenIndex] = QString::number(dScaleFactor);
4089 setExtraDataStringList(GUI_ScaleFactor, data, uID);
4090}
4091
4092void UIExtraDataManager::setScaleFactors(const QList<double> &scaleFactors, const QUuid &uID)
4093{
4094 QStringList data;
4095 for (int i = 0; i < scaleFactors.size(); ++i)
4096 data.append(QString::number(scaleFactors[i]));
4097 setExtraDataStringList(GUI_ScaleFactor, data, uID);
4098}
4099
4100ScalingOptimizationType UIExtraDataManager::scalingOptimizationType(const QUuid &uID)
4101{
4102 return gpConverter->fromInternalString<ScalingOptimizationType>(extraDataString(GUI_Scaling_Optimization, uID));
4103}
4104
4105QRect UIExtraDataManager::sessionInformationDialogGeometry(QWidget *pWidget, QWidget *pParentWidget)
4106{
4107 return dialogGeometry(GUI_SessionInformationDialogGeometry, pWidget, pParentWidget);
4108}
4109
4110bool UIExtraDataManager::sessionInformationDialogShouldBeMaximized()
4111{
4112 /* Get corresponding extra-data: */
4113 const QStringList data = extraDataStringList(GUI_SessionInformationDialogGeometry);
4114
4115 /* Make sure 5th item has required value: */
4116 return data.size() == 5 && data[4] == GUI_Geometry_State_Max;
4117}
4118
4119void UIExtraDataManager::setSessionInformationDialogGeometry(const QRect &geometry, bool fMaximized)
4120{
4121 /* Serialize passed values: */
4122 QStringList data;
4123 data << QString::number(geometry.x());
4124 data << QString::number(geometry.y());
4125 data << QString::number(geometry.width());
4126 data << QString::number(geometry.height());
4127 if (fMaximized)
4128 data << GUI_Geometry_State_Max;
4129
4130 /* Re-cache corresponding extra-data: */
4131 setExtraDataStringList(GUI_SessionInformationDialogGeometry, data);
4132}
4133
4134
4135void UIExtraDataManager::setGuestControlProcessControlSplitterHints(const QList<int> &hints)
4136{
4137 QStringList data;
4138 data << (hints.size() > 0 ? QString::number(hints[0]) : QString());
4139 data << (hints.size() > 1 ? QString::number(hints[1]) : QString());
4140
4141 /* Re-cache corresponding extra-data: */
4142 setExtraDataStringList(GUI_GuestControl_ProcessControlSplitterHints, data);
4143}
4144
4145QList<int> UIExtraDataManager::guestControlProcessControlSplitterHints()
4146{
4147 /* Get corresponding extra-data: */
4148 const QStringList data = extraDataStringList(GUI_GuestControl_ProcessControlSplitterHints);
4149
4150 /* Parse loaded data: */
4151 QList<int> hints;
4152 hints << (data.size() > 0 ? data[0].toInt() : 0);
4153 hints << (data.size() > 1 ? data[1].toInt() : 0);
4154
4155 /* Return hints: */
4156 return hints;
4157}
4158
4159QRect UIExtraDataManager::fileManagerDialogGeometry(QWidget *pWidget, QWidget *pParentWidget)
4160{
4161 return dialogGeometry(GUI_GuestControl_FileManagerDialogGeometry, pWidget, pParentWidget);
4162}
4163
4164bool UIExtraDataManager::fileManagerDialogShouldBeMaximized()
4165{
4166 /* Get corresponding extra-data: */
4167 const QStringList data = extraDataStringList(GUI_GuestControl_FileManagerDialogGeometry);
4168
4169 /* Make sure 5th item has required value: */
4170 return data.size() == 5 && data[4] == GUI_Geometry_State_Max;
4171}
4172
4173void UIExtraDataManager::setFileManagerDialogGeometry(const QRect &geometry, bool fMaximized)
4174{
4175 setDialogGeometry(GUI_GuestControl_FileManagerDialogGeometry, geometry, fMaximized);
4176}
4177
4178void UIExtraDataManager::setFileManagerVisiblePanels(const QStringList &panelNameList)
4179{
4180 setExtraDataStringList(GUI_GuestControl_FileManagerVisiblePanels, panelNameList);
4181}
4182
4183QStringList UIExtraDataManager::fileManagerVisiblePanels()
4184{
4185 return extraDataStringList(GUI_GuestControl_FileManagerVisiblePanels);
4186}
4187
4188QRect UIExtraDataManager::softKeyboardDialogGeometry(QWidget *pWidget, QWidget *pParentWidget, const QRect &defaultGeometry)
4189{
4190 return dialogGeometry(GUI_SoftKeyboard_DialogGeometry, pWidget, pParentWidget, defaultGeometry);
4191}
4192
4193void UIExtraDataManager::setSoftKeyboardDialogGeometry(const QRect &geometry, bool fMaximized)
4194{
4195 setDialogGeometry(GUI_SoftKeyboard_DialogGeometry, geometry, fMaximized);
4196}
4197
4198bool UIExtraDataManager::softKeyboardDialogShouldBeMaximized()
4199{
4200 /* Get corresponding extra-data: */
4201 const QStringList data = extraDataStringList(GUI_SoftKeyboard_DialogGeometry);
4202
4203 /* Make sure 5th item has required value: */
4204 return data.size() == 5 && data[4] == GUI_Geometry_State_Max;
4205}
4206
4207void UIExtraDataManager::setSoftKeyboardOptions(bool fHideNumPad, bool fHideOSMenuKeys, bool fMultimediaKeys)
4208{
4209 QStringList data;
4210
4211 if (fHideNumPad)
4212 data << GUI_SoftKeyboard_HideNumPad;
4213 if (fHideOSMenuKeys)
4214 data << GUI_SoftKeyboard_HideOSMenuKeys;
4215 if (fMultimediaKeys)
4216 data << GUI_SoftKeyboard_HideMultimediaKeys;
4217
4218 setExtraDataStringList(GUI_SoftKeyboard_Options, data);
4219}
4220
4221void UIExtraDataManager::softKeyboardOptions(bool &fOutHideNumPad, bool &fOutHideOSMenuKeys, bool &fOutHideMultimediaKeys)
4222{
4223 fOutHideNumPad = false;
4224 fOutHideOSMenuKeys = false;
4225 const QStringList data = extraDataStringList(GUI_SoftKeyboard_Options);
4226 for (int i = 0; i < data.size(); ++i)
4227 {
4228 if (data[i] == GUI_SoftKeyboard_HideNumPad)
4229 fOutHideNumPad = true;
4230 if (data[i] == GUI_SoftKeyboard_HideOSMenuKeys)
4231 fOutHideOSMenuKeys = true;
4232 if (data[i] == GUI_SoftKeyboard_HideMultimediaKeys)
4233 fOutHideMultimediaKeys = true;
4234 }
4235}
4236
4237void UIExtraDataManager::setSoftKeyboardColorTheme(const QStringList &colorStringList)
4238{
4239 setExtraDataStringList(GUI_SoftKeyboard_ColorTheme, colorStringList);
4240}
4241
4242QStringList UIExtraDataManager::softKeyboardColorTheme()
4243{
4244 return extraDataStringList(GUI_SoftKeyboard_ColorTheme);
4245}
4246
4247void UIExtraDataManager::setSoftKeyboardSelectedColorTheme(const QString &strColorThemeName)
4248{
4249 setExtraDataString(GUI_SoftKeyboard_SelectedColorTheme, strColorThemeName);
4250}
4251
4252QString UIExtraDataManager::softKeyboardSelectedColorTheme()
4253{
4254 return extraDataString(GUI_SoftKeyboard_SelectedColorTheme);
4255}
4256
4257void UIExtraDataManager::setSoftKeyboardSelectedLayout(const QUuid &uLayoutUid)
4258{
4259 setExtraDataString(GUI_SoftKeyboard_SelectedLayout, uLayoutUid.toString());
4260}
4261
4262QUuid UIExtraDataManager::softKeyboardSelectedLayout()
4263{
4264 return QUuid(extraDataString(GUI_SoftKeyboard_SelectedLayout));
4265}
4266
4267void UIExtraDataManager::setFileManagerOptions(bool fListDirectoriesFirst,
4268 bool fShowDeleteConfirmation,
4269 bool fShowHumanReadableSizes,
4270 bool fShowHiddenObjects)
4271{
4272 /* Serialize passed values: */
4273 QStringList data;
4274
4275 if (fListDirectoriesFirst)
4276 data << GUI_GuestControl_FileManagerListDirectoriesFirst;
4277 if (fShowDeleteConfirmation)
4278 data << GUI_GuestControl_FileManagerShowDeleteConfirmation;
4279 if (fShowHumanReadableSizes)
4280 data << GUI_GuestControl_FileManagerShowHumanReadableSizes;
4281 if (fShowHiddenObjects)
4282 data << GUI_GuestControl_FileManagerShowHiddenObjects;
4283
4284 /* Re-cache corresponding extra-data: */
4285 setExtraDataStringList(GUI_GuestControl_FileManagerOptions, data);
4286}
4287
4288bool UIExtraDataManager::fileManagerListDirectoriesFirst()
4289{
4290 const QStringList data = extraDataStringList(GUI_GuestControl_FileManagerOptions);
4291 for (int i = 0; i < data.size(); ++i)
4292 {
4293 if (data[i] == GUI_GuestControl_FileManagerListDirectoriesFirst)
4294 return true;
4295 }
4296 return false;
4297}
4298
4299bool UIExtraDataManager::fileManagerShowDeleteConfirmation()
4300{
4301 const QStringList data = extraDataStringList(GUI_GuestControl_FileManagerOptions);
4302 for (int i = 0; i < data.size(); ++i)
4303 {
4304 if (data[i] == GUI_GuestControl_FileManagerShowDeleteConfirmation)
4305 return true;
4306 }
4307 return false;
4308}
4309
4310bool UIExtraDataManager::fileManagerShowHumanReadableSizes()
4311{
4312 const QStringList data = extraDataStringList(GUI_GuestControl_FileManagerOptions);
4313 for (int i = 0; i < data.size(); ++i)
4314 {
4315 if (data[i] == GUI_GuestControl_FileManagerShowHumanReadableSizes)
4316 return true;
4317 }
4318 return false;
4319}
4320
4321bool UIExtraDataManager::fileManagerShowHiddenObjects()
4322{
4323 const QStringList data = extraDataStringList(GUI_GuestControl_FileManagerOptions);
4324 for (int i = 0; i < data.size(); ++i)
4325 {
4326 if (data[i] == GUI_GuestControl_FileManagerShowHiddenObjects)
4327 return true;
4328 }
4329 return false;
4330}
4331
4332QRect UIExtraDataManager::guestProcessControlDialogGeometry(QWidget *pWidget, QWidget *pParentWidget, const QRect &defaultGeometry)
4333{
4334 return dialogGeometry(GUI_GuestControl_ProcessControlDialogGeometry, pWidget, pParentWidget, defaultGeometry);
4335}
4336
4337bool UIExtraDataManager::guestProcessControlDialogShouldBeMaximized()
4338{
4339 /* Get corresponding extra-data: */
4340 const QStringList data = extraDataStringList(GUI_GuestControl_ProcessControlDialogGeometry);
4341
4342 /* Make sure 5th item has required value: */
4343 return data.size() == 5 && data[4] == GUI_Geometry_State_Max;
4344}
4345
4346void UIExtraDataManager::setGuestProcessControlDialogGeometry(const QRect &geometry, bool fMaximized)
4347{
4348 setDialogGeometry(GUI_GuestControl_ProcessControlDialogGeometry, geometry, fMaximized);
4349}
4350
4351MachineCloseAction UIExtraDataManager::defaultMachineCloseAction(const QUuid &uID)
4352{
4353 return gpConverter->fromInternalString<MachineCloseAction>(extraDataString(GUI_DefaultCloseAction, uID));
4354}
4355
4356MachineCloseAction UIExtraDataManager::restrictedMachineCloseActions(const QUuid &uID)
4357{
4358 /* Prepare result: */
4359 MachineCloseAction result = MachineCloseAction_Invalid;
4360 /* Get restricted machine-close-actions: */
4361 foreach (const QString &strValue, extraDataStringList(GUI_RestrictedCloseActions, uID))
4362 {
4363 MachineCloseAction value = gpConverter->fromInternalString<MachineCloseAction>(strValue);
4364 if (value != MachineCloseAction_Invalid)
4365 result = static_cast<MachineCloseAction>(result | value);
4366 }
4367 /* Return result: */
4368 return result;
4369}
4370
4371MachineCloseAction UIExtraDataManager::lastMachineCloseAction(const QUuid &uID)
4372{
4373 return gpConverter->fromInternalString<MachineCloseAction>(extraDataString(GUI_LastCloseAction, uID));
4374}
4375
4376void UIExtraDataManager::setLastMachineCloseAction(MachineCloseAction machineCloseAction, const QUuid &uID)
4377{
4378 setExtraDataString(GUI_LastCloseAction, gpConverter->toInternalString(machineCloseAction), uID);
4379}
4380
4381QString UIExtraDataManager::machineCloseHookScript(const QUuid &uID)
4382{
4383 return extraDataString(GUI_CloseActionHook, uID);
4384}
4385
4386#ifdef VBOX_WITH_DEBUGGER_GUI
4387QString UIExtraDataManager::debugFlagValue(const QString &strDebugFlagKey)
4388{
4389 return extraDataString(strDebugFlagKey).toLower().trimmed();
4390}
4391#endif /* VBOX_WITH_DEBUGGER_GUI */
4392
4393#ifdef VBOX_GUI_WITH_EXTRADATA_MANAGER_UI
4394QRect UIExtraDataManager::extraDataManagerGeometry(QWidget *pWidget, QWidget *pParentWidget)
4395{
4396 return dialogGeometry(GUI_ExtraDataManager_Geometry, pWidget, pParentWidget);
4397}
4398
4399bool UIExtraDataManager::extraDataManagerShouldBeMaximized()
4400{
4401 /* Get corresponding extra-data: */
4402 const QStringList data = extraDataStringList(GUI_ExtraDataManager_Geometry);
4403
4404 /* Make sure 5th item has required value: */
4405 return data.size() == 5 && data[4] == GUI_Geometry_State_Max;
4406}
4407
4408void UIExtraDataManager::setExtraDataManagerGeometry(const QRect &geometry, bool fMaximized)
4409{
4410 /* Serialize passed values: */
4411 QStringList data;
4412 data << QString::number(geometry.x());
4413 data << QString::number(geometry.y());
4414 data << QString::number(geometry.width());
4415 data << QString::number(geometry.height());
4416 if (fMaximized)
4417 data << GUI_Geometry_State_Max;
4418
4419 /* Re-cache corresponding extra-data: */
4420 setExtraDataStringList(GUI_ExtraDataManager_Geometry, data);
4421}
4422
4423QList<int> UIExtraDataManager::extraDataManagerSplitterHints(QWidget *pWidget)
4424{
4425 /* Get corresponding extra-data: */
4426 const QStringList data = extraDataStringList(GUI_ExtraDataManager_SplitterHints);
4427
4428 /* Parse loaded data: */
4429 int iLeft = 0, iRight = 0;
4430 bool fOk = data.size() == 2;
4431 do
4432 {
4433 if (!fOk) break;
4434 iLeft = data[0].toInt(&fOk);
4435 if (!fOk) break;
4436 iRight = data[1].toInt(&fOk);
4437 }
4438 while (0);
4439
4440 /* Prepare hints (loaded or adviced): */
4441 QList<int> hints;
4442 if (fOk)
4443 {
4444 hints << iLeft;
4445 hints << iRight;
4446 }
4447 else
4448 {
4449 hints << (int)(pWidget->width() * .9 * (1.0 / 3));
4450 hints << (int)(pWidget->width() * .9 * (2.0 / 3));
4451 }
4452
4453 /* Return hints: */
4454 return hints;
4455}
4456
4457void UIExtraDataManager::setExtraDataManagerSplitterHints(const QList<int> &hints)
4458{
4459 /* Parse passed hints: */
4460 QStringList data;
4461 data << (hints.size() > 0 ? QString::number(hints[0]) : QString());
4462 data << (hints.size() > 1 ? QString::number(hints[1]) : QString());
4463
4464 /* Re-cache corresponding extra-data: */
4465 setExtraDataStringList(GUI_ExtraDataManager_SplitterHints, data);
4466}
4467#endif /* VBOX_GUI_WITH_EXTRADATA_MANAGER_UI */
4468
4469QRect UIExtraDataManager::logWindowGeometry(QWidget *pWidget, QWidget *pParentWidget, const QRect &defaultGeometry)
4470{
4471 return dialogGeometry(GUI_LogWindowGeometry, pWidget, pParentWidget, defaultGeometry);
4472}
4473
4474bool UIExtraDataManager::logWindowShouldBeMaximized()
4475{
4476 /* Get corresponding extra-data: */
4477 const QStringList data = extraDataStringList(GUI_LogWindowGeometry);
4478
4479 /* Make sure 5th item has required value: */
4480 return data.size() == 5 && data[4] == GUI_Geometry_State_Max;
4481}
4482
4483void UIExtraDataManager::setLogWindowGeometry(const QRect &geometry, bool fMaximized)
4484{
4485 /* Serialize passed values: */
4486 QStringList data;
4487 data << QString::number(geometry.x());
4488 data << QString::number(geometry.y());
4489 data << QString::number(geometry.width());
4490 data << QString::number(geometry.height());
4491 if (fMaximized)
4492 data << GUI_Geometry_State_Max;
4493
4494 /* Re-cache corresponding extra-data: */
4495 setExtraDataStringList(GUI_LogWindowGeometry, data);
4496}
4497
4498void UIExtraDataManager::setLogViweverOptions(const QFont &font, bool wrapLines, bool showLineNumbers)
4499{
4500 /* Serialize passed values: */
4501 QStringList data;
4502 data << font.family();
4503 /* Make sure that we have some non-empty string as font style name: */
4504 QString strStyleName = font.styleName();
4505 if (strStyleName.isEmpty())
4506 data << GUI_LogViewerNoFontStyleName;
4507 else
4508 data << font.styleName();
4509 data << QString::number(font.pointSize());
4510
4511 if (wrapLines)
4512 data << GUI_LogViewerWrapLinesEnabled;
4513 if (!showLineNumbers)
4514 data << GUI_LogViewerShowLineNumbersDisabled;
4515
4516 /* Re-cache corresponding extra-data: */
4517 setExtraDataStringList(GUI_LogViewerOptions, data);
4518}
4519
4520bool UIExtraDataManager::logViewerWrapLines()
4521{
4522 const QStringList data = extraDataStringList(GUI_LogViewerOptions);
4523 for (int i = 0; i < data.size(); ++i)
4524 {
4525 if (data[i] == GUI_LogViewerWrapLinesEnabled)
4526 return true;
4527 }
4528 return false;
4529}
4530
4531bool UIExtraDataManager::logViewerShowLineNumbers()
4532{
4533 const QStringList data = extraDataStringList(GUI_LogViewerOptions);
4534 for (int i = 0; i < data.size(); ++i)
4535 {
4536 if (data[i] == GUI_LogViewerShowLineNumbersDisabled)
4537 return false;
4538 }
4539 return true;
4540}
4541
4542QFont UIExtraDataManager::logViewerFont()
4543{
4544 const QStringList data = extraDataStringList(GUI_LogViewerOptions);
4545 if (data.size() < 3)
4546 return QFont();
4547 QString strFamily = data[0];
4548 QString strStyleName = data[1];
4549 if (strStyleName == GUI_LogViewerNoFontStyleName)
4550 strStyleName.clear();
4551 bool fOk = false;
4552 int iFontSize = data[2].toInt(&fOk);
4553 if (!fOk)
4554 iFontSize = 9;
4555 QFontDatabase dataBase;
4556 return dataBase.font(strFamily, strStyleName, iFontSize);
4557}
4558
4559void UIExtraDataManager::setLogViewerVisiblePanels(const QStringList &panelNameList)
4560{
4561 setExtraDataStringList(GUI_GuestControl_LogViewerVisiblePanels, panelNameList);
4562}
4563
4564QStringList UIExtraDataManager::logViewerVisiblePanels()
4565{
4566 return extraDataStringList(GUI_GuestControl_LogViewerVisiblePanels);
4567}
4568
4569void UIExtraDataManager::sltExtraDataChange(const QUuid &uMachineID, const QString &strKey, const QString &strValue)
4570{
4571 /* Re-cache value only if uMachineID known already: */
4572 if (m_data.contains(uMachineID))
4573 {
4574 if (!strValue.isEmpty())
4575 m_data[uMachineID][strKey] = strValue;
4576 else
4577 m_data[uMachineID].remove(strKey);
4578 }
4579
4580 /* Global extra-data 'change' event: */
4581 if (uMachineID == GlobalID)
4582 {
4583 if (strKey.startsWith("GUI/"))
4584 {
4585 /* Language changed? */
4586 if (strKey == GUI_LanguageID)
4587 emit sigLanguageChange(extraDataString(strKey));
4588 /* Selector UI shortcut changed? */
4589 else if (strKey == GUI_Input_SelectorShortcuts)
4590 emit sigSelectorUIShortcutChange();
4591 /* Runtime UI shortcut changed? */
4592 else if (strKey == GUI_Input_MachineShortcuts)
4593 emit sigRuntimeUIShortcutChange();
4594 /* Runtime UI host-key combintation changed? */
4595 else if (strKey == GUI_Input_HostKeyCombination)
4596 emit sigRuntimeUIHostKeyCombinationChange();
4597 /* Details categories: */
4598 else if (strKey == GUI_Details_Elements)
4599 emit sigDetailsCategoriesChange();
4600 /* Details options: */
4601 else if (strKey.startsWith(QString(GUI_Details_Elements) + '/'))
4602 {
4603 QString strLeftover = strKey;
4604 strLeftover.remove(QString(GUI_Details_Elements) + '/');
4605 const DetailsElementType enmType = gpConverter->fromInternalString<DetailsElementType>(strLeftover);
4606 if (enmType != DetailsElementType_Invalid)
4607 emit sigDetailsOptionsChange(enmType);
4608 }
4609 }
4610 }
4611 /* Machine extra-data 'change' event: */
4612 else
4613 {
4614 /* Current VM only: */
4615 if ( uiCommon().uiType() == UICommon::UIType_RuntimeUI
4616 && uMachineID == uiCommon().managedVMUuid())
4617 {
4618 /* HID LEDs sync state changed (allowed if not restricted)? */
4619 if (strKey == GUI_HidLedsSync)
4620 emit sigHidLedsSyncStateChange(!isFeatureRestricted(strKey, uMachineID));
4621#ifdef VBOX_WS_MAC
4622 /* 'Dock icon' appearance changed (allowed if not restricted)? */
4623 else if (strKey == GUI_RealtimeDockIconUpdateEnabled ||
4624 strKey == GUI_RealtimeDockIconUpdateMonitor)
4625 emit sigDockIconAppearanceChange(!isFeatureRestricted(strKey, uMachineID));
4626 /* 'Dock icon overlay' appearance changed (restricted if not allowed)? */
4627 else if (strKey == GUI_DockIconDisableOverlay)
4628 emit sigDockIconOverlayAppearanceChange(isFeatureAllowed(strKey, uMachineID));
4629#endif /* VBOX_WS_MAC */
4630 }
4631
4632 /* Menu-bar configuration change: */
4633 if (
4634#ifndef VBOX_WS_MAC
4635 strKey == GUI_MenuBar_Enabled ||
4636#endif /* !VBOX_WS_MAC */
4637 strKey == GUI_RestrictedRuntimeMenus ||
4638 strKey == GUI_RestrictedRuntimeApplicationMenuActions ||
4639 strKey == GUI_RestrictedRuntimeMachineMenuActions ||
4640 strKey == GUI_RestrictedRuntimeViewMenuActions ||
4641 strKey == GUI_RestrictedRuntimeInputMenuActions ||
4642 strKey == GUI_RestrictedRuntimeDevicesMenuActions ||
4643#ifdef VBOX_WITH_DEBUGGER_GUI
4644 strKey == GUI_RestrictedRuntimeDebuggerMenuActions ||
4645#endif /* VBOX_WITH_DEBUGGER_GUI */
4646#ifdef VBOX_WS_MAC
4647 strKey == GUI_RestrictedRuntimeWindowMenuActions ||
4648#endif /* VBOX_WS_MAC */
4649 strKey == GUI_RestrictedRuntimeHelpMenuActions)
4650 emit sigMenuBarConfigurationChange(uMachineID);
4651 /* Status-bar configuration change: */
4652 else if (strKey == GUI_StatusBar_Enabled ||
4653 strKey == GUI_RestrictedStatusBarIndicators ||
4654 strKey == GUI_StatusBar_IndicatorOrder)
4655 emit sigStatusBarConfigurationChange(uMachineID);
4656 /* Scale-factor change: */
4657 else if (strKey == GUI_ScaleFactor)
4658 emit sigScaleFactorChange(uMachineID);
4659 /* Scaling optimization type change: */
4660 else if (strKey == GUI_Scaling_Optimization)
4661 emit sigScalingOptimizationTypeChange(uMachineID);
4662 }
4663
4664 /* Notify listeners: */
4665 emit sigExtraDataChange(uMachineID, strKey, strValue);
4666}
4667
4668void UIExtraDataManager::prepare()
4669{
4670 /* Prepare global extra-data map: */
4671 prepareGlobalExtraDataMap();
4672 /* Prepare extra-data event-handler: */
4673 prepareExtraDataEventHandler();
4674}
4675
4676void UIExtraDataManager::prepareGlobalExtraDataMap()
4677{
4678 /* Get CVirtualBox: */
4679 CVirtualBox vbox = uiCommon().virtualBox();
4680
4681 /* Make sure at least empty map is created: */
4682 m_data[GlobalID] = ExtraDataMap();
4683
4684 /* Load global extra-data map: */
4685 foreach (const QString &strKey, vbox.GetExtraDataKeys())
4686 m_data[GlobalID][strKey] = vbox.GetExtraData(strKey);
4687}
4688
4689void UIExtraDataManager::prepareExtraDataEventHandler()
4690{
4691 /* Create extra-data event-handler: */
4692 m_pHandler = new UIExtraDataEventHandler(this);
4693 /* Configure extra-data event-handler: */
4694 AssertPtrReturnVoid(m_pHandler);
4695 {
4696 /* Create queued (async) connections for signals of event proxy object: */
4697 connect(m_pHandler, &UIExtraDataEventHandler::sigExtraDataChange,
4698 this, &UIExtraDataManager::sltExtraDataChange,
4699 Qt::QueuedConnection);
4700 }
4701}
4702
4703#ifdef VBOX_GUI_WITH_EXTRADATA_MANAGER_UI
4704void UIExtraDataManager::cleanupWindow()
4705{
4706 delete m_pWindow;
4707}
4708#endif /* VBOX_GUI_WITH_EXTRADATA_MANAGER_UI */
4709
4710void UIExtraDataManager::cleanupExtraDataEventHandler()
4711{
4712 /* Destroy extra-data event-handler: */
4713 delete m_pHandler;
4714 m_pHandler = 0;
4715}
4716
4717void UIExtraDataManager::cleanup()
4718{
4719 /* Cleanup extra-data event-handler: */
4720 cleanupExtraDataEventHandler();
4721#ifdef VBOX_GUI_WITH_EXTRADATA_MANAGER_UI
4722 /* Cleanup window: */
4723 cleanupWindow();
4724#endif /* VBOX_GUI_WITH_EXTRADATA_MANAGER_UI */
4725}
4726
4727#ifdef VBOX_GUI_WITH_EXTRADATA_MANAGER_UI
4728void UIExtraDataManager::open(QWidget *pCenterWidget)
4729{
4730 /* If necessary: */
4731 if (!m_pWindow)
4732 {
4733 /* Create window: */
4734 m_pWindow = new UIExtraDataManagerWindow(pCenterWidget);
4735 /* Configure window connections: */
4736 connect(this, &UIExtraDataManager::sigExtraDataMapAcknowledging,
4737 m_pWindow.data(), &UIExtraDataManagerWindow::sltExtraDataMapAcknowledging);
4738 connect(this, &UIExtraDataManager::sigExtraDataChange,
4739 m_pWindow.data(), &UIExtraDataManagerWindow::sltExtraDataChange);
4740 }
4741 /* Show and raise window: */
4742 m_pWindow->showAndRaise(pCenterWidget);
4743}
4744#endif /* VBOX_GUI_WITH_EXTRADATA_MANAGER_UI */
4745
4746QString UIExtraDataManager::extraDataStringUnion(const QString &strKey, const QUuid &uID)
4747{
4748 /* If passed uID differs from the GlobalID: */
4749 if (uID != GlobalID)
4750 {
4751 /* Search through the machine extra-data first: */
4752 MapOfExtraDataMaps::const_iterator itMap = m_data.constFind(uID);
4753 /* Hot-load machine extra-data map if necessary: */
4754 if (itMap == m_data.constEnd())
4755 {
4756 hotloadMachineExtraDataMap(uID);
4757 itMap = m_data.constFind(uID);
4758 }
4759 if (itMap != m_data.constEnd())
4760 {
4761 /* Return string if present in the map: */
4762 ExtraDataMap::const_iterator itValue = itMap->constFind(strKey);
4763 if (itValue != itMap->constEnd())
4764 return *itValue;
4765 }
4766 }
4767
4768 /* Search through the global extra-data finally: */
4769 MapOfExtraDataMaps::const_iterator itMap = m_data.constFind(GlobalID);
4770 if (itMap != m_data.constEnd())
4771 {
4772 /* Return string if present in the map: */
4773 ExtraDataMap::const_iterator itValue = itMap->constFind(strKey);
4774 if (itValue != itMap->constEnd())
4775 return *itValue;
4776 }
4777
4778 /* Not found, return null string: */
4779 return QString();
4780}
4781
4782bool UIExtraDataManager::isFeatureAllowed(const QString &strKey, const QUuid &uID /* = GlobalID */)
4783{
4784 /* Get the value. Return 'false' if not found: */
4785 const QString strValue = extraDataStringUnion(strKey, uID);
4786 if (strValue.isNull())
4787 return false;
4788
4789 /* Check corresponding value: */
4790 return strValue.compare("true", Qt::CaseInsensitive) == 0
4791 || strValue.compare("yes", Qt::CaseInsensitive) == 0
4792 || strValue.compare("on", Qt::CaseInsensitive) == 0
4793 || strValue == "1";
4794}
4795
4796bool UIExtraDataManager::isFeatureRestricted(const QString &strKey, const QUuid &uID /* = GlobalID */)
4797{
4798 /* Get the value. Return 'false' if not found: */
4799 const QString strValue = extraDataStringUnion(strKey, uID);
4800 if (strValue.isNull())
4801 return false;
4802
4803 /* Check corresponding value: */
4804 return strValue.compare("false", Qt::CaseInsensitive) == 0
4805 || strValue.compare("no", Qt::CaseInsensitive) == 0
4806 || strValue.compare("off", Qt::CaseInsensitive) == 0
4807 || strValue == "0";
4808}
4809
4810QString UIExtraDataManager::toFeatureState(bool fState)
4811{
4812 return fState ? QString("true") : QString("false");
4813}
4814
4815QString UIExtraDataManager::toFeatureAllowed(bool fAllowed)
4816{
4817 return fAllowed ? QString("true") : QString();
4818}
4819
4820QString UIExtraDataManager::toFeatureRestricted(bool fRestricted)
4821{
4822 return fRestricted ? QString("false") : QString();
4823}
4824
4825void UIExtraDataManager::setDialogGeometry(const QString &strKey, const QRect &geometry, bool fMaximized)
4826{
4827 /* Serialize passed values: */
4828 QStringList data;
4829 data << QString::number(geometry.x());
4830 data << QString::number(geometry.y());
4831 data << QString::number(geometry.width());
4832 data << QString::number(geometry.height());
4833 if (fMaximized)
4834 data << GUI_Geometry_State_Max;
4835
4836 /* Save corresponding extra-data: */
4837 setExtraDataStringList(strKey, data);
4838}
4839
4840QRect UIExtraDataManager::dialogGeometry(const QString &strKey,
4841 QWidget *pWidget,
4842 QWidget *pParentWidget /* = 0 */,
4843 const QRect &defaultGeometry /* = QRect() */)
4844{
4845 /* Get corresponding extra-data: */
4846 const QStringList data = extraDataStringList(strKey);
4847
4848 /* Parse loaded data: */
4849 int iX = 0, iY = 0, iW = 0, iH = 0;
4850 bool fOk = data.size() >= 4;
4851 do
4852 {
4853 if (!fOk) break;
4854 iX = data[0].toInt(&fOk);
4855 if (!fOk) break;
4856 iY = data[1].toInt(&fOk);
4857 if (!fOk) break;
4858 iW = data[2].toInt(&fOk);
4859 if (!fOk) break;
4860 iH = data[3].toInt(&fOk);
4861 }
4862 while (0);
4863
4864 /* Get available-geometry [of screen with point (iX, iY) if possible]: */
4865 const QRect availableGeometry = fOk ? gpDesktop->availableGeometry(QPoint(iX, iY)) :
4866 gpDesktop->availableGeometry();
4867
4868 /* Use geometry (loaded or default): */
4869 QRect geometry = fOk
4870 ? QRect(iX, iY, iW, iH)
4871 : !defaultGeometry.isNull()
4872 ? defaultGeometry
4873 : QRect(QPoint(0, 0), availableGeometry.size() * .50 /* % */);
4874
4875 /* Take hint-widget into account: */
4876 if (pWidget)
4877 geometry.setSize(geometry.size().expandedTo(pWidget->minimumSizeHint()));
4878
4879 /* As a fallback, move default-geometry to pParentWidget' geometry center: */
4880 if (!fOk && pParentWidget)
4881 geometry.moveCenter(pParentWidget->geometry().center());
4882 /* As final fallback, move default-geometry to available-geometry' center: */
4883 else if (!fOk)
4884 geometry.moveCenter(availableGeometry.center());
4885
4886 /* In Windows Qt fails to reposition out of screen window properly, so doing it ourselves: */
4887#ifdef VBOX_WS_WIN
4888 /* Make sure resulting geometry is within current bounds: */
4889 if (!availableGeometry.contains(geometry))
4890 geometry = UICommon::getNormalized(geometry, QRegion(availableGeometry));
4891#endif /* VBOX_WS_WIN */
4892
4893 /* Return result: */
4894 return geometry;
4895}
4896
4897/* static */
4898QString UIExtraDataManager::extraDataKeyPerScreen(const QString &strBase, ulong uScreenIndex, bool fSameRuleForPrimary /* = false */)
4899{
4900 return fSameRuleForPrimary || uScreenIndex ? strBase + QString::number(uScreenIndex) : strBase;
4901}
4902
4903#include "UIExtraDataManager.moc"
Note: See TracBrowser for help on using the repository browser.

© 2023 Oracle
ContactPrivacy policyTerms of Use