VirtualBox

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

Last change on this file since 105266 was 105081, checked in by vboxsync, 9 months ago

FE/Qt: Moving local machine related stuff from UICommon to new UILocalMachineStuff namespace; Reworking GUI to use it accordingly; Dependencies and includes cleanup.

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

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