VirtualBox

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

Last change on this file was 108356, checked in by vboxsync, 4 weeks ago

FE/Qt: bugref:10814: VBox Manager / Tools pane: Introducing invisible for now Management tool class which can be used to accumulate various manager tools; Pass it through all the handling places.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 192.4 KB
Line 
1/* $Id: UIExtraDataManager.cpp 108356 2025-02-24 16:21:30Z 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_HideFromManager << GUI_HideDetails
1947 << GUI_PreventReconfiguration << GUI_PreventSnapshotOperations
1948#ifndef VBOX_WS_MAC
1949 << GUI_MachineWindowIcons << GUI_MachineWindowNamePostfix
1950#endif
1951 << GUI_LastNormalWindowPosition << GUI_LastScaleWindowPosition
1952#ifndef VBOX_WS_MAC
1953 << GUI_MenuBar_Enabled
1954#endif
1955 << GUI_MenuBar_ContextMenu_Enabled
1956 << GUI_RestrictedRuntimeMenus
1957 << GUI_RestrictedRuntimeApplicationMenuActions
1958 << GUI_RestrictedRuntimeMachineMenuActions
1959 << GUI_RestrictedRuntimeViewMenuActions
1960 << GUI_RestrictedRuntimeInputMenuActions
1961 << GUI_RestrictedRuntimeDevicesMenuActions
1962#ifdef VBOX_WITH_DEBUGGER_GUI
1963 << GUI_RestrictedRuntimeDebuggerMenuActions
1964#endif
1965#ifdef VBOX_WS_MAC
1966 << GUI_RestrictedRuntimeWindowMenuActions
1967#endif
1968 << GUI_RestrictedRuntimeHelpMenuActions
1969 << GUI_RestrictedVisualStates
1970 << GUI_Fullscreen << GUI_Seamless << GUI_Scale
1971#ifdef VBOX_WS_NIX
1972 << GUI_Fullscreen_LegacyMode
1973 << GUI_DistinguishMachineWindowGroups
1974#endif
1975 << GUI_AutoresizeGuest << GUI_LastVisibilityStatusForGuestScreen << GUI_LastGuestSizeHint
1976 << GUI_VirtualScreenToHostScreen << GUI_AutomountGuestScreens
1977#ifndef VBOX_WS_MAC
1978 << GUI_ShowMiniToolBar << GUI_MiniToolBarAutoHide << GUI_MiniToolBarAlignment
1979#endif
1980 << GUI_StatusBar_Enabled << GUI_StatusBar_ContextMenu_Enabled << GUI_RestrictedStatusBarIndicators << GUI_StatusBar_IndicatorOrder
1981#ifdef VBOX_WS_MAC
1982 << GUI_RealtimeDockIconUpdateEnabled << GUI_RealtimeDockIconUpdateMonitor << GUI_DockIconDisableOverlay
1983#endif
1984 << GUI_PassCAD
1985 << GUI_MouseCapturePolicy
1986 << GUI_GuruMeditationHandler
1987 << GUI_HidLedsSync
1988 << GUI_ScaleFactor << GUI_Scaling_Optimization
1989 << GUI_SessionInformationDialogGeometry
1990 << GUI_GuestControl_ProcessControlSplitterHints
1991 << GUI_GuestControl_FileManagerDialogGeometry
1992 << GUI_GuestControl_FileManagerOptions
1993 << GUI_GuestControl_ProcessControlDialogGeometry
1994 << GUI_DefaultCloseAction << GUI_RestrictedCloseActions
1995 << GUI_LastCloseAction << GUI_CloseActionHook << GUI_DiscardStateOnPowerOff
1996#ifdef VBOX_WITH_DEBUGGER_GUI
1997 << GUI_Dbg_Enabled << GUI_Dbg_AutoShow
1998#endif
1999 << GUI_ExtraDataManager_Geometry << GUI_ExtraDataManager_SplitterHints
2000 << GUI_LogWindowGeometry
2001 << GUI_HelpBrowser_LastURLList
2002 << GUI_HelpBrowser_DialogGeometry
2003 << GUI_HelpBrowser_Bookmarks
2004 << GUI_HelpBrowser_ZoomPercentage;
2005}
2006
2007#endif /* VBOX_GUI_WITH_EXTRADATA_MANAGER_UI */
2008
2009
2010/*********************************************************************************************************************************
2011* Class UIExtraDataManager implementation. *
2012*********************************************************************************************************************************/
2013
2014/* static */
2015UIExtraDataManager *UIExtraDataManager::s_pInstance = 0;
2016const QUuid UIExtraDataManager::GlobalID;
2017
2018/* static */
2019void UIExtraDataManager::create()
2020{
2021 AssertReturnVoid(!s_pInstance);
2022 new UIExtraDataManager;
2023 s_pInstance->prepare();
2024}
2025
2026/* static */
2027void UIExtraDataManager::destroy()
2028{
2029 AssertPtrReturnVoid(s_pInstance);
2030 s_pInstance->cleanup();
2031 delete s_pInstance;
2032}
2033
2034/* static */
2035UIExtraDataManager *UIExtraDataManager::instance()
2036{
2037 /* This is the fallback behavior, we need the lazy-init here
2038 * only to make sure gEDataManager is never NULL. */
2039 AssertPtr(s_pInstance);
2040 if (!s_pInstance)
2041 create();
2042 return s_pInstance;
2043}
2044
2045#ifdef VBOX_GUI_WITH_EXTRADATA_MANAGER_UI
2046/* static */
2047void UIExtraDataManager::openWindow(QWidget *pCenterWidget)
2048{
2049 /* Pass to instance: */
2050 instance()->open(pCenterWidget);
2051}
2052#endif /* VBOX_GUI_WITH_EXTRADATA_MANAGER_UI */
2053
2054void UIExtraDataManager::hotloadMachineExtraDataMap(const QUuid &uID)
2055{
2056 /* Make sure it is valid ID: */
2057 AssertMsgReturnVoid(!uID.isNull() && uID != GlobalID,
2058 ("Invalid VM ID = {%s}\n", uID.toString().toUtf8().constData()));
2059 /* Which is not loaded yet: */
2060 AssertReturnVoid(!m_data.contains(uID));
2061
2062 /* Search for corresponding machine: */
2063 CVirtualBox vbox = gpGlobalSession->virtualBox();
2064 CMachine machine = vbox.FindMachine(uID.toString());
2065 if (machine.isNull())
2066 return;
2067
2068 /* Make sure at least empty map is created: */
2069 m_data[uID] = ExtraDataMap();
2070
2071 /* Do not handle inaccessible machine: */
2072 if (!machine.GetAccessible())
2073 return;
2074
2075 /* Load machine extra-data map: */
2076 foreach (const QString &strKey, machine.GetExtraDataKeys())
2077 m_data[uID][strKey] = machine.GetExtraData(strKey);
2078
2079 /* Notifies about extra-data map acknowledged: */
2080 emit sigExtraDataMapAcknowledging(uID);
2081}
2082
2083QString UIExtraDataManager::extraDataString(const QString &strKey, const QUuid &uID /* = GlobalID */)
2084{
2085 /* Get the actual value: */
2086 QString strValue = extraDataStringUnion(strKey, uID);
2087 /* If actual value is null we might be able to find old one: */
2088 if (strValue.isNull())
2089 {
2090 foreach (const QString &strOldKey, g_mapOfObsoleteKeys.values(strKey))
2091 {
2092 strValue = extraDataStringUnion(strOldKey, uID);
2093 if (!strValue.isNull())
2094 break;
2095 }
2096 }
2097 /* Return null string if result is empty: */
2098 if (strValue.isEmpty())
2099 return QString();
2100
2101 /* Returns corresponding value: */
2102 return strValue;
2103}
2104
2105void UIExtraDataManager::setExtraDataString(const QString &strKey, const QString &strValue, const QUuid &uID /* = GlobalID */)
2106{
2107 /* Make sure VBoxSVC is available: */
2108 if (!gpGlobalSession->isVBoxSVCAvailable())
2109 return;
2110
2111 /* Hot-load machine extra-data map if necessary: */
2112 if (uID != GlobalID && !m_data.contains(uID))
2113 hotloadMachineExtraDataMap(uID);
2114
2115 /* Access corresponding map: */
2116 ExtraDataMap &data = m_data[uID];
2117
2118 /* [Re]cache passed value: */
2119 data[strKey] = strValue;
2120
2121 /* Global extra-data: */
2122 if (uID == GlobalID)
2123 {
2124 /* Get global object: */
2125 CVirtualBox comVBox = gpGlobalSession->virtualBox();
2126 /* Update global extra-data: */
2127 comVBox.SetExtraData(strKey, strValue);
2128 if (!comVBox.isOk())
2129 msgCenter().cannotSetExtraData(comVBox, strKey, strValue);
2130 /* Wipe out old keys: */
2131 foreach (const QString &strOldKey, g_mapOfObsoleteKeys.values(strKey))
2132 {
2133 comVBox.SetExtraData(strOldKey, QString());
2134 if (!comVBox.isOk())
2135 {
2136 msgCenter().cannotSetExtraData(comVBox, strOldKey, strValue);
2137 break;
2138 }
2139 }
2140 }
2141 /* Machine extra-data: */
2142 else
2143 {
2144 /* Search for corresponding machine: */
2145 CVirtualBox comVBox = gpGlobalSession->virtualBox();
2146 const CMachine comMachine = comVBox.FindMachine(uID.toString());
2147 AssertReturnVoid(comVBox.isOk() && !comMachine.isNull());
2148 /* Check the configuration access-level: */
2149 const KMachineState enmMachineState = comMachine.GetState();
2150 const KSessionState enmSessionState = comMachine.GetSessionState();
2151 const ConfigurationAccessLevel enmLevel = configurationAccessLevel(enmSessionState, enmMachineState);
2152 /* Prepare machine session: */
2153 CSession comSession;
2154 if (enmLevel == ConfigurationAccessLevel_Full)
2155 comSession = openSession(uID);
2156 else
2157 comSession = openExistingSession(uID);
2158 AssertReturnVoid(!comSession.isNull());
2159 /* Get machine from that session: */
2160 CMachine comSessionMachine = comSession.GetMachine();
2161 /* Update machine extra-data: */
2162 comSessionMachine.SetExtraData(strKey, strValue);
2163 if (!comSessionMachine.isOk())
2164 msgCenter().cannotSetExtraData(comSessionMachine, strKey, strValue);
2165 /* Wipe out old keys: */
2166 foreach (const QString &strOldKey, g_mapOfObsoleteKeys.values(strKey))
2167 {
2168 comSessionMachine.SetExtraData(strOldKey, QString());
2169 if (!comSessionMachine.isOk())
2170 {
2171 msgCenter().cannotSetExtraData(comSessionMachine, strOldKey, strValue);
2172 break;
2173 }
2174 }
2175 comSession.UnlockMachine();
2176 }
2177}
2178
2179QStringList UIExtraDataManager::extraDataStringList(const QString &strKey, const QUuid &uID /* = GlobalID */)
2180{
2181 /* Get the actual value: */
2182 QString strValue = extraDataStringUnion(strKey, uID);
2183 /* If actual value is null we might be able to find old one: */
2184 if (strValue.isNull())
2185 {
2186 foreach (const QString &strOldKey, g_mapOfObsoleteKeys.values(strKey))
2187 {
2188 strValue = extraDataStringUnion(strOldKey, uID);
2189 if (!strValue.isNull())
2190 break;
2191 }
2192 }
2193 /* Return empty string list if result is empty: */
2194 if (strValue.isEmpty())
2195 return QStringList();
2196
2197 /* Few old extra-data string-lists were separated with 'semicolon' symbol.
2198 * All new separated by 'comma'. We have to take that into account. */
2199 return strValue.split(QRegularExpression("[;,]"), Qt::SkipEmptyParts);
2200}
2201
2202void UIExtraDataManager::setExtraDataStringList(const QString &strKey, const QStringList &value, const QUuid &uID /* = GlobalID */)
2203{
2204 /* Make sure VBoxSVC is available: */
2205 if (!gpGlobalSession->isVBoxSVCAvailable())
2206 return;
2207
2208 /* Hot-load machine extra-data map if necessary: */
2209 if (uID != GlobalID && !m_data.contains(uID))
2210 hotloadMachineExtraDataMap(uID);
2211
2212 /* Access corresponding map: */
2213 ExtraDataMap &data = m_data[uID];
2214
2215 /* [Re]cache passed value: */
2216 data[strKey] = value.join(",");
2217
2218 /* Global extra-data: */
2219 if (uID == GlobalID)
2220 {
2221 /* Get global object: */
2222 CVirtualBox comVBox = gpGlobalSession->virtualBox();
2223 /* Update global extra-data: */
2224 comVBox.SetExtraDataStringList(strKey, value);
2225 if (!comVBox.isOk())
2226 msgCenter().cannotSetExtraData(comVBox, strKey, value.join(","));
2227 /* Wipe out old keys: */
2228 foreach (const QString &strOldKey, g_mapOfObsoleteKeys.values(strKey))
2229 {
2230 comVBox.SetExtraData(strOldKey, QString());
2231 if (!comVBox.isOk())
2232 {
2233 msgCenter().cannotSetExtraData(comVBox, strOldKey, value.join(","));
2234 break;
2235 }
2236 }
2237 }
2238 /* Machine extra-data: */
2239 else
2240 {
2241 /* Search for corresponding machine: */
2242 CVirtualBox comVBox = gpGlobalSession->virtualBox();
2243 const CMachine comMachine = comVBox.FindMachine(uID.toString());
2244 AssertReturnVoid(comVBox.isOk() && !comMachine.isNull());
2245 /* Check the configuration access-level: */
2246 const KMachineState enmMachineState = comMachine.GetState();
2247 const KSessionState enmSessionState = comMachine.GetSessionState();
2248 const ConfigurationAccessLevel enmLevel = configurationAccessLevel(enmSessionState, enmMachineState);
2249 /* Prepare machine session: */
2250 CSession comSession;
2251 if (enmLevel == ConfigurationAccessLevel_Full)
2252 comSession = openSession(uID);
2253 else
2254 comSession = openExistingSession(uID);
2255 AssertReturnVoid(!comSession.isNull());
2256 /* Get machine from that session: */
2257 CMachine comSessionMachine = comSession.GetMachine();
2258 /* Update machine extra-data: */
2259 comSessionMachine.SetExtraDataStringList(strKey, value);
2260 if (!comSessionMachine.isOk())
2261 msgCenter().cannotSetExtraData(comSessionMachine, strKey, value.join(","));
2262 /* Wipe out old keys: */
2263 foreach (const QString &strOldKey, g_mapOfObsoleteKeys.values(strKey))
2264 {
2265 comSessionMachine.SetExtraData(strOldKey, QString());
2266 if (!comSessionMachine.isOk())
2267 {
2268 msgCenter().cannotSetExtraData(comSessionMachine, strOldKey, value.join(","));
2269 break;
2270 }
2271 }
2272 comSession.UnlockMachine();
2273 }
2274}
2275
2276UIExtraDataManager::UIExtraDataManager()
2277 : m_pHandler(0)
2278{
2279 /* Connect to static instance: */
2280 s_pInstance = this;
2281}
2282
2283UIExtraDataManager::~UIExtraDataManager()
2284{
2285 /* Disconnect from static instance: */
2286 s_pInstance = 0;
2287}
2288
2289UIExtraDataMetaDefs::DialogType UIExtraDataManager::restrictedDialogTypes(const QUuid &uID)
2290{
2291 /* Prepare result: */
2292 UIExtraDataMetaDefs::DialogType result = UIExtraDataMetaDefs::DialogType_Invalid;
2293 /* Get restricted runtime-menu-types: */
2294 foreach (const QString &strValue, extraDataStringList(GUI_RestrictedDialogs, uID))
2295 {
2296 UIExtraDataMetaDefs::DialogType value = gpConverter->fromInternalString<UIExtraDataMetaDefs::DialogType>(strValue);
2297 if (value != UIExtraDataMetaDefs::DialogType_Invalid)
2298 result = static_cast<UIExtraDataMetaDefs::DialogType>(result | value);
2299 }
2300 /* Return result: */
2301 return result;
2302}
2303
2304void UIExtraDataManager::setRestrictedDialogTypes(UIExtraDataMetaDefs::DialogType dialogs, const QUuid &uID)
2305{
2306 /* We have MenuType enum registered, so we can enumerate it: */
2307 const QMetaObject &smo = UIExtraDataMetaDefs::staticMetaObject;
2308 const int iEnumIndex = smo.indexOfEnumerator("DialogType");
2309 QMetaEnum metaEnum = smo.enumerator(iEnumIndex);
2310
2311 /* Prepare result: */
2312 QStringList result;
2313 /* Handle DialogType_All enum-value: */
2314 if (dialogs == UIExtraDataMetaDefs::DialogType_All)
2315 result << gpConverter->toInternalString(dialogs);
2316 else
2317 {
2318 /* Handle other enum-values: */
2319 for (int iKeyIndex = 0; iKeyIndex < metaEnum.keyCount(); ++iKeyIndex)
2320 {
2321 /* Get iterated enum-value: */
2322 const UIExtraDataMetaDefs::DialogType enumValue =
2323 static_cast<UIExtraDataMetaDefs::DialogType>(metaEnum.keyToValue(metaEnum.key(iKeyIndex)));
2324 /* Skip DialogType_Invalid & DialogType_All enum-values: */
2325 if (enumValue == UIExtraDataMetaDefs::DialogType_Invalid ||
2326 enumValue == UIExtraDataMetaDefs::DialogType_All)
2327 continue;
2328 if (dialogs & enumValue)
2329 result << gpConverter->toInternalString(enumValue);
2330 }
2331 }
2332 /* Save result: */
2333 setExtraDataStringList(GUI_RestrictedDialogs, result, uID);
2334}
2335
2336QStringList UIExtraDataManager::suppressedMessages(const QUuid &uID /* = GlobalID */)
2337{
2338 return extraDataStringList(GUI_SuppressMessages, uID);
2339}
2340
2341void UIExtraDataManager::setSuppressedMessages(const QStringList &list)
2342{
2343 setExtraDataStringList(GUI_SuppressMessages, list);
2344}
2345
2346QStringList UIExtraDataManager::messagesWithInvertedOption()
2347{
2348 return extraDataStringList(GUI_InvertMessageOption);
2349}
2350
2351#ifdef VBOX_NOTIFICATION_CENTER_WITH_KEEP_BUTTON
2352bool UIExtraDataManager::keepSuccessfullNotificationProgresses()
2353{
2354 /* 'False' unless feature allowed: */
2355 return isFeatureAllowed(GUI_NotificationCenter_KeepSuccessfullProgresses);
2356}
2357
2358void UIExtraDataManager::setKeepSuccessfullNotificationProgresses(bool fKeep)
2359{
2360 /* 'True' if feature allowed, null-string otherwise: */
2361 setExtraDataString(GUI_NotificationCenter_KeepSuccessfullProgresses, toFeatureAllowed(fKeep));
2362}
2363#endif /* VBOX_NOTIFICATION_CENTER_WITH_KEEP_BUTTON */
2364
2365Qt::Alignment UIExtraDataManager::notificationCenterAlignment()
2366{
2367 const QString strValue = extraDataString(GUI_NotificationCenter_Alignment);
2368 return strValue.isEmpty() ? Qt::AlignTop : gpConverter->fromInternalString<Qt::Alignment>(strValue);
2369}
2370
2371void UIExtraDataManager::setNotificationCenterAlignment(Qt::Alignment enmOrder)
2372{
2373 const QString strValue = enmOrder == Qt::AlignTop ? QString() : gpConverter->toInternalString(enmOrder);
2374 setExtraDataString(GUI_NotificationCenter_Alignment, strValue);
2375}
2376
2377Qt::SortOrder UIExtraDataManager::notificationCenterOrder()
2378{
2379 const QString strValue = extraDataString(GUI_NotificationCenter_Order);
2380 return strValue.isEmpty() ? Qt::DescendingOrder : gpConverter->fromInternalString<Qt::SortOrder>(strValue);
2381}
2382
2383void UIExtraDataManager::setNotificationCenterOrder(Qt::SortOrder enmOrder)
2384{
2385 const QString strValue = enmOrder == Qt::DescendingOrder ? QString() : gpConverter->toInternalString(enmOrder);
2386 setExtraDataString(GUI_NotificationCenter_Order, strValue);
2387}
2388
2389bool UIExtraDataManager::preventBetaBuildLabel()
2390{
2391 return isFeatureAllowed(GUI_PreventBetaLabel);
2392}
2393
2394#if !defined(VBOX_BLEEDING_EDGE) && !defined(DEBUG)
2395QString UIExtraDataManager::preventBetaBuildWarningForVersion()
2396{
2397 return extraDataString(GUI_PreventBetaWarning);
2398}
2399#endif /* !defined(VBOX_BLEEDING_EDGE) && !defined(DEBUG) */
2400
2401#ifdef VBOX_GUI_WITH_NETWORK_MANAGER
2402bool UIExtraDataManager::applicationUpdateEnabled()
2403{
2404 /* 'True' unless 'restriction' feature allowed: */
2405 return !isFeatureAllowed(GUI_PreventApplicationUpdate);
2406}
2407
2408QString UIExtraDataManager::applicationUpdateData()
2409{
2410 return extraDataString(GUI_UpdateDate);
2411}
2412
2413void UIExtraDataManager::setApplicationUpdateData(const QString &strValue)
2414{
2415 setExtraDataString(GUI_UpdateDate, strValue);
2416}
2417
2418qulonglong UIExtraDataManager::applicationUpdateCheckCounter()
2419{
2420 /* Read subsequent update check counter value: */
2421 qulonglong uResult = 1;
2422 const QString strCheckCount = extraDataString(GUI_UpdateCheckCount);
2423 if (!strCheckCount.isEmpty())
2424 {
2425 bool ok = false;
2426 qulonglong uCheckCount = strCheckCount.toULongLong(&ok);
2427 if (ok) uResult = uCheckCount;
2428 }
2429 /* Return update check counter value: */
2430 return uResult;
2431}
2432
2433void UIExtraDataManager::incrementApplicationUpdateCheckCounter()
2434{
2435 /* Increment update check counter value: */
2436 setExtraDataString(GUI_UpdateCheckCount, QString::number(applicationUpdateCheckCounter() + 1));
2437}
2438#endif /* VBOX_GUI_WITH_NETWORK_MANAGER */
2439
2440bool UIExtraDataManager::legacyProgressHandlingRequested()
2441{
2442 /* 'False' unless feature allowed: */
2443 return isFeatureAllowed(GUI_Progress_LegacyMode);
2444}
2445
2446bool UIExtraDataManager::guiFeatureEnabled(GUIFeatureType enmFeature)
2447{
2448 /* Acquire GUI feature list: */
2449 GUIFeatureType enmFeatures = GUIFeatureType_None;
2450 foreach (const QString &strValue, extraDataStringList(GUI_Customizations))
2451 enmFeatures = static_cast<GUIFeatureType>(enmFeatures | gpConverter->fromInternalString<GUIFeatureType>(strValue));
2452 /* Return whether the requested feature is enabled: */
2453 return enmFeatures & enmFeature;
2454}
2455
2456QList<GlobalSettingsPageType> UIExtraDataManager::restrictedGlobalSettingsPages()
2457{
2458 /* Prepare result: */
2459 QList<GlobalSettingsPageType> result;
2460 /* Get restricted global-settings-pages: */
2461 foreach (const QString &strValue, extraDataStringList(GUI_RestrictedGlobalSettingsPages))
2462 {
2463 GlobalSettingsPageType value = gpConverter->fromInternalString<GlobalSettingsPageType>(strValue);
2464 if (value != GlobalSettingsPageType_Invalid)
2465 result << value;
2466 }
2467 /* Return result: */
2468 return result;
2469}
2470
2471QList<MachineSettingsPageType> UIExtraDataManager::restrictedMachineSettingsPages(const QUuid &uID)
2472{
2473 /* Prepare result: */
2474 QList<MachineSettingsPageType> result;
2475 /* Get restricted machine-settings-pages: */
2476 foreach (const QString &strValue, extraDataStringList(GUI_RestrictedMachineSettingsPages, uID))
2477 {
2478 MachineSettingsPageType value = gpConverter->fromInternalString<MachineSettingsPageType>(strValue);
2479 if (value != MachineSettingsPageType_Invalid)
2480 result << value;
2481 }
2482 /* Return result: */
2483 return result;
2484}
2485
2486bool UIExtraDataManager::isSettingsInExpertMode()
2487{
2488#ifdef DEBUG
2489 /* For debug build return true by default: */
2490 if (extraDataString(GUI_Settings_ExpertMode).isEmpty())
2491 return true;
2492#endif
2493
2494 /* 'False' unless feature allowed: */
2495 return isFeatureAllowed(GUI_Settings_ExpertMode);
2496}
2497
2498void UIExtraDataManager::setSettingsInExpertMode(bool fExpertMode)
2499{
2500 /* Store actual feature state, whether it is "true" or "false",
2501 * because absent state means default, depending on defines: */
2502 setExtraDataString(GUI_Settings_ExpertMode, toFeatureState(fExpertMode));
2503}
2504
2505QString UIExtraDataManager::languageId()
2506{
2507 /* Load language ID: */
2508 return extraDataString(GUI_LanguageID);
2509}
2510
2511void UIExtraDataManager::setLanguageId(const QString &strLanguageId)
2512{
2513 /* Save language ID: */
2514 setExtraDataString(GUI_LanguageID, strLanguageId);
2515}
2516
2517MaximumGuestScreenSizePolicy UIExtraDataManager::maxGuestResolutionPolicy()
2518{
2519 /* Return maximum guest-screen resolution policy: */
2520 return gpConverter->fromInternalString<MaximumGuestScreenSizePolicy>(extraDataString(GUI_MaxGuestResolution));
2521}
2522
2523void UIExtraDataManager::setMaxGuestScreenResolution(MaximumGuestScreenSizePolicy enmPolicy, const QSize resolution /* = QSize() */)
2524{
2525 /* If policy is 'Fixed' => call the wrapper: */
2526 if (enmPolicy == MaximumGuestScreenSizePolicy_Fixed)
2527 setMaxGuestResolutionForPolicyFixed(resolution);
2528 /* Otherwise => just store the value: */
2529 else
2530 setExtraDataString(GUI_MaxGuestResolution, gpConverter->toInternalString(enmPolicy));
2531}
2532
2533QSize UIExtraDataManager::maxGuestResolutionForPolicyFixed()
2534{
2535 /* Acquire maximum guest-screen resolution policy: */
2536 const QString strPolicy = extraDataString(GUI_MaxGuestResolution);
2537 const MaximumGuestScreenSizePolicy enmPolicy = gpConverter->fromInternalString<MaximumGuestScreenSizePolicy>(strPolicy);
2538
2539 /* Make sure maximum guest-screen resolution policy is really Fixed: */
2540 if (enmPolicy != MaximumGuestScreenSizePolicy_Fixed)
2541 return QSize();
2542
2543 /* Parse maximum guest-screen resolution: */
2544 const QStringList values = strPolicy.split(',');
2545 int iWidth = values.at(0).toInt();
2546 int iHeight = values.at(1).toInt();
2547 if (iWidth <= 0)
2548 iWidth = 640;
2549 if (iHeight <= 0)
2550 iHeight = 480;
2551
2552 /* Return maximum guest-screen resolution: */
2553 return QSize(iWidth, iHeight);
2554}
2555
2556void UIExtraDataManager::setMaxGuestResolutionForPolicyFixed(const QSize &resolution)
2557{
2558 /* If resolution is 'empty' => call the wrapper: */
2559 if (resolution.isEmpty())
2560 setMaxGuestScreenResolution(MaximumGuestScreenSizePolicy_Automatic);
2561 /* Otherwise => just store the value: */
2562 else
2563 setExtraDataString(GUI_MaxGuestResolution, QString("%1,%2").arg(resolution.width()).arg(resolution.height()));
2564}
2565
2566bool UIExtraDataManager::activateHoveredMachineWindow()
2567{
2568 /* 'False' unless feature allowed: */
2569 return isFeatureAllowed(GUI_ActivateHoveredMachineWindow);
2570}
2571
2572void UIExtraDataManager::setActivateHoveredMachineWindow(bool fActivate)
2573{
2574 /* 'True' if feature allowed, null-string otherwise: */
2575 setExtraDataString(GUI_ActivateHoveredMachineWindow, toFeatureAllowed(fActivate));
2576}
2577
2578bool UIExtraDataManager::disableHostScreenSaver()
2579{
2580 /* 'False' unless feature allowed: */
2581 return isFeatureAllowed(GUI_DisableHostScreenSaver);
2582}
2583
2584void UIExtraDataManager::setDisableHostScreenSaver(bool fActivate)
2585{
2586 /* 'True' if feature allowed, null-string otherwise: */
2587 setExtraDataString(GUI_DisableHostScreenSaver, toFeatureAllowed(fActivate));
2588}
2589
2590QString UIExtraDataManager::hostKeyCombination()
2591{
2592 /* Acquire host-key combination: */
2593 QString strHostCombo = extraDataString(GUI_Input_HostKeyCombination);
2594 /* Invent some sane default if it's absolutely wrong or invalid: */
2595 QRegularExpression reTemplate("0|[1-9]\\d*(,[1-9]\\d*)?(,[1-9]\\d*)?");
2596 if (!reTemplate.match(strHostCombo).hasMatch() || !UIHostCombo::isValidKeyCombo(strHostCombo))
2597 {
2598#if defined (VBOX_WS_MAC)
2599 strHostCombo = "55"; // QZ_LMETA
2600#elif defined (VBOX_WS_WIN)
2601 strHostCombo = "163"; // VK_RCONTROL
2602#elif defined (VBOX_WS_NIX)
2603 strHostCombo = "65508"; // XK_Control_R
2604#else
2605# warning "port me!"
2606#endif
2607 }
2608 /* Return host-key combination: */
2609 return strHostCombo;
2610}
2611
2612void UIExtraDataManager::setFontScaleFactor(int iFontScaleFactor)
2613{
2614 if (iFontScaleFactor < UIExtraDataDefs::iFontScaleMin || iFontScaleFactor > UIExtraDataDefs::iFontScaleMax)
2615 return;
2616 setExtraDataString(GUI_FontScaleFactor, QString::number(iFontScaleFactor));
2617}
2618
2619int UIExtraDataManager::fontScaleFactor()
2620{
2621 QString strFontScaleFactor = extraDataString(GUI_FontScaleFactor);
2622 bool fConversion = false;
2623 int iScaleFactor = strFontScaleFactor.toInt(&fConversion);
2624 if (!fConversion || iScaleFactor < UIExtraDataDefs::iFontScaleMin || iScaleFactor > UIExtraDataDefs::iFontScaleMax)
2625 return 100;
2626 return iScaleFactor;
2627}
2628
2629void UIExtraDataManager::setHostKeyCombination(const QString &strHostCombo)
2630{
2631 /* Do not save anything if it's absolutely wrong or invalid: */
2632 QRegularExpression reTemplate("0|[1-9]\\d*(,[1-9]\\d*)?(,[1-9]\\d*)?");
2633 if (!reTemplate.match(strHostCombo).hasMatch() || !UIHostCombo::isValidKeyCombo(strHostCombo))
2634 return;
2635 /* Define host-combo: */
2636 setExtraDataString(GUI_Input_HostKeyCombination, strHostCombo);
2637}
2638
2639QStringList UIExtraDataManager::shortcutOverrides(const QString &strPoolExtraDataID)
2640{
2641 if (strPoolExtraDataID == GUI_Input_SelectorShortcuts)
2642 return extraDataStringList(GUI_Input_SelectorShortcuts);
2643 if (strPoolExtraDataID == GUI_Input_MachineShortcuts)
2644 return extraDataStringList(GUI_Input_MachineShortcuts);
2645 return QStringList();
2646}
2647
2648bool UIExtraDataManager::autoCaptureEnabled()
2649{
2650 /* Prepare auto-capture flag: */
2651 bool fAutoCapture = true /* indifferently */;
2652 /* Acquire whether the auto-capture is restricted: */
2653 QString strAutoCapture = extraDataString(GUI_Input_AutoCapture);
2654 /* Invent some sane default if it's empty: */
2655 if (strAutoCapture.isEmpty())
2656 {
2657#if defined(VBOX_WS_NIX) && defined(DEBUG)
2658 fAutoCapture = false;
2659#else
2660 fAutoCapture = true;
2661#endif
2662 }
2663 /* 'True' unless feature restricted: */
2664 else
2665 fAutoCapture = !isFeatureRestricted(GUI_Input_AutoCapture);
2666 /* Return auto-capture flag: */
2667 return fAutoCapture;
2668}
2669
2670void UIExtraDataManager::setAutoCaptureEnabled(bool fEnabled)
2671{
2672 /* Store actual feature state, whether it is "true" or "false",
2673 * because absent state means default, different on various hosts: */
2674 setExtraDataString(GUI_Input_AutoCapture, toFeatureState(fEnabled));
2675}
2676
2677QString UIExtraDataManager::remappedScanCodes()
2678{
2679 /* Acquire remapped scan codes: */
2680 QString strRemappedScanCodes = extraDataString(GUI_RemapScancodes);
2681 /* Clear the record if it's absolutely wrong: */
2682 QRegularExpression reTemplate("(\\d+=\\d+,)*\\d+=\\d+");
2683 if (!reTemplate.match(strRemappedScanCodes).hasMatch())
2684 strRemappedScanCodes.clear();
2685 /* Return remapped scan codes: */
2686 return strRemappedScanCodes;
2687}
2688
2689QString UIExtraDataManager::proxySettings()
2690{
2691 return extraDataString(GUI_ProxySettings);
2692}
2693
2694void UIExtraDataManager::setProxySettings(const QString &strSettings)
2695{
2696 setExtraDataString(GUI_ProxySettings, strSettings);
2697}
2698
2699QString UIExtraDataManager::recentFolderForHardDrives()
2700{
2701 return extraDataString(GUI_RecentFolderHD);
2702}
2703
2704QString UIExtraDataManager::recentFolderForOpticalDisks()
2705{
2706 return extraDataString(GUI_RecentFolderCD);
2707}
2708
2709QString UIExtraDataManager::recentFolderForFloppyDisks()
2710{
2711 return extraDataString(GUI_RecentFolderFD);
2712}
2713
2714void UIExtraDataManager::setRecentFolderForHardDrives(const QString &strValue)
2715{
2716 setExtraDataString(GUI_RecentFolderHD, strValue);
2717}
2718
2719void UIExtraDataManager::setRecentFolderForOpticalDisks(const QString &strValue)
2720{
2721 setExtraDataString(GUI_RecentFolderCD, strValue);
2722}
2723
2724void UIExtraDataManager::setRecentFolderForFloppyDisks(const QString &strValue)
2725{
2726 setExtraDataString(GUI_RecentFolderFD, strValue);
2727}
2728
2729QStringList UIExtraDataManager::recentListOfHardDrives()
2730{
2731 return extraDataStringList(GUI_RecentListHD);
2732}
2733
2734QStringList UIExtraDataManager::recentListOfOpticalDisks()
2735{
2736 return extraDataStringList(GUI_RecentListCD);
2737}
2738
2739QStringList UIExtraDataManager::recentListOfFloppyDisks()
2740{
2741 return extraDataStringList(GUI_RecentListFD);
2742}
2743
2744void UIExtraDataManager::setRecentListOfHardDrives(const QStringList &value)
2745{
2746 setExtraDataStringList(GUI_RecentListHD, value);
2747}
2748
2749void UIExtraDataManager::setRecentListOfOpticalDisks(const QStringList &value)
2750{
2751 setExtraDataStringList(GUI_RecentListCD, value);
2752}
2753
2754void UIExtraDataManager::setRecentListOfFloppyDisks(const QStringList &value)
2755{
2756 setExtraDataStringList(GUI_RecentListFD, value);
2757}
2758
2759UIExtraDataMetaDefs::DetailsElementOptionTypeNetwork UIExtraDataManager::restrictedNetworkAttachmentTypes()
2760{
2761 /* Prepare result: */
2762 UIExtraDataMetaDefs::DetailsElementOptionTypeNetwork enmResult =
2763 UIExtraDataMetaDefs::DetailsElementOptionTypeNetwork_Invalid;
2764 /* Get restricted network attachment types: */
2765 foreach (const QString &strValue, extraDataStringList(GUI_RestrictedNetworkAttachmentTypes))
2766 {
2767 const UIExtraDataMetaDefs::DetailsElementOptionTypeNetwork enmValue =
2768 gpConverter->fromInternalString<UIExtraDataMetaDefs::DetailsElementOptionTypeNetwork>(strValue);
2769 if (enmValue != UIExtraDataMetaDefs::DetailsElementOptionTypeNetwork_Invalid && !(enmResult & enmValue))
2770 enmResult = static_cast<UIExtraDataMetaDefs::DetailsElementOptionTypeNetwork>(enmResult | enmValue);
2771 }
2772 /* Return result: */
2773 return enmResult;
2774}
2775
2776QString UIExtraDataManager::visoCreatorRecentFolder()
2777{
2778 return extraDataString(GUI_VISOCreator_RecentFolder);
2779}
2780
2781void UIExtraDataManager::setVISOCreatorRecentFolder(const QString &strValue)
2782{
2783 setExtraDataString(GUI_VISOCreator_RecentFolder, strValue);
2784}
2785
2786QRect UIExtraDataManager::visoCreatorDialogGeometry(QWidget *pWidget, QWidget *pParentWidget, const QRect &defaultGeometry)
2787{
2788 return dialogGeometry(GUI_VISOCreator_DialogGeometry, pWidget, pParentWidget, defaultGeometry);
2789}
2790
2791void UIExtraDataManager::setVisoCreatorDialogGeometry(const QRect &geometry, bool fMaximized)
2792{
2793 setDialogGeometry(GUI_VISOCreator_DialogGeometry, geometry, fMaximized);
2794}
2795
2796bool UIExtraDataManager::visoCreatorDialogShouldBeMaximized()
2797{
2798 return dialogShouldBeMaximized(GUI_VISOCreator_DialogGeometry);
2799}
2800
2801QRect UIExtraDataManager::selectorWindowGeometry(QWidget *pWidget)
2802{
2803 return dialogGeometry(GUI_LastSelectorWindowPosition, pWidget);
2804}
2805
2806bool UIExtraDataManager::selectorWindowShouldBeMaximized()
2807{
2808 return dialogShouldBeMaximized(GUI_LastSelectorWindowPosition);
2809}
2810
2811void UIExtraDataManager::setSelectorWindowGeometry(const QRect &geometry, bool fMaximized)
2812{
2813 /* Serialize passed values: */
2814 QStringList data;
2815 data << QString::number(geometry.x());
2816 data << QString::number(geometry.y());
2817 data << QString::number(geometry.width());
2818 data << QString::number(geometry.height());
2819 if (fMaximized)
2820 data << GUI_Geometry_State_Max;
2821
2822 /* Re-cache corresponding extra-data: */
2823 setExtraDataStringList(GUI_LastSelectorWindowPosition, data);
2824}
2825
2826QList<int> UIExtraDataManager::selectorWindowSplitterHints()
2827{
2828 /* Get corresponding extra-data: */
2829 const QStringList data = extraDataStringList(GUI_SplitterSizes);
2830
2831 /* Parse loaded data: */
2832 QList<int> hints;
2833 hints << (data.size() > 0 ? data[0].toInt() : 0);
2834 hints << (data.size() > 1 ? data[1].toInt() : 0);
2835
2836 /* Return hints: */
2837 return hints;
2838}
2839
2840void UIExtraDataManager::setSelectorWindowSplitterHints(const QList<int> &hints)
2841{
2842 /* Parse passed hints: */
2843 QStringList data;
2844 data << (hints.size() > 0 ? QString::number(hints[0]) : QString());
2845 data << (hints.size() > 1 ? QString::number(hints[1]) : QString());
2846
2847 /* Re-cache corresponding extra-data: */
2848 setExtraDataStringList(GUI_SplitterSizes, data);
2849}
2850
2851bool UIExtraDataManager::selectorWindowToolBarVisible()
2852{
2853 /* 'True' unless feature restricted: */
2854 return !isFeatureRestricted(GUI_Toolbar);
2855}
2856
2857void UIExtraDataManager::setSelectorWindowToolBarVisible(bool fVisible)
2858{
2859 /* 'False' if feature restricted, null-string otherwise: */
2860 setExtraDataString(GUI_Toolbar, toFeatureRestricted(!fVisible));
2861}
2862
2863bool UIExtraDataManager::selectorWindowToolBarTextVisible()
2864{
2865 /* 'True' unless feature restricted: */
2866 return !isFeatureRestricted(GUI_Toolbar_Text);
2867}
2868
2869void UIExtraDataManager::setSelectorWindowToolBarTextVisible(bool fVisible)
2870{
2871 /* 'False' if feature restricted, null-string otherwise: */
2872 setExtraDataString(GUI_Toolbar_Text, toFeatureRestricted(!fVisible));
2873}
2874
2875void UIExtraDataManager::toolsPaneLastItemsChosen(UIToolType &enmTypeGlobal,
2876 UIToolType &enmTypeMachine,
2877 UIToolType &enmTypeManagement)
2878{
2879 /* Parse loaded data: */
2880 QList<UIToolType> result;
2881 foreach (const QString &strValue, extraDataStringList(GUI_Tools_LastItemsSelected))
2882 {
2883 const UIToolType enmType = gpConverter->fromInternalString<UIToolType>(strValue);
2884 if (enmType != UIToolType_Invalid)
2885 result << enmType;
2886 }
2887
2888 /* Assign values: */
2889 enmTypeGlobal = result.value(0);
2890 if (!UIToolStuff::isTypeOfClass(enmTypeGlobal, UIToolClass_Global))
2891 enmTypeGlobal = UIToolType_Home;
2892 enmTypeMachine = result.value(1);
2893 if (!UIToolStuff::isTypeOfClass(enmTypeMachine, UIToolClass_Machine))
2894 enmTypeMachine = UIToolType_Details;
2895 enmTypeManagement = result.value(2);
2896 if (!UIToolStuff::isTypeOfClass(enmTypeManagement, UIToolClass_Management))
2897 enmTypeManagement = UIToolType_Extensions;
2898}
2899
2900void UIExtraDataManager::setToolsPaneLastItemsChosen(UIToolType enmTypeGlobal,
2901 UIToolType enmTypeMachine,
2902 UIToolType enmTypeManagement)
2903{
2904 /* Serialize passed values: */
2905 const QList<UIToolType> currentTypes = QList<UIToolType>()
2906 << enmTypeGlobal
2907 << enmTypeMachine
2908 << enmTypeManagement;
2909 QStringList data;
2910 foreach (const UIToolType &enmType, currentTypes)
2911 data << gpConverter->toInternalString(enmType);
2912
2913 /* Re-cache corresponding extra-data: */
2914 setExtraDataStringList(GUI_Tools_LastItemsSelected, data);
2915}
2916
2917QList<UIToolType> UIExtraDataManager::detachedTools()
2918{
2919 /* Parse loaded data: */
2920 QList<UIToolType> result;
2921 foreach (const QString &strValue, extraDataStringList(GUI_Tools_Detached))
2922 {
2923 const UIToolType enmType = gpConverter->fromInternalString<UIToolType>(strValue);
2924 if (enmType != UIToolType_Invalid)
2925 result << enmType;
2926 }
2927
2928 /* Return result: */
2929 return result;
2930}
2931
2932void UIExtraDataManager::setDetachedTools(const QList<UIToolType> &tools)
2933{
2934 /* Serialize passed values: */
2935 QStringList data;
2936 foreach (const UIToolType &enmType, tools)
2937 data << gpConverter->toInternalString(enmType);
2938
2939 /* Re-cache corresponding extra-data: */
2940 setExtraDataStringList(GUI_Tools_Detached, data);
2941}
2942
2943bool UIExtraDataManager::isToolTextVisible()
2944{
2945 /* 'False' unless feature allowed: */
2946 return isFeatureAllowed(GUI_Tools_Text);
2947}
2948
2949void UIExtraDataManager::setToolTextVisible(bool fVisible)
2950{
2951 /* 'True' if feature allowed, null-string otherwise: */
2952 return setExtraDataString(GUI_Tools_Text, toFeatureAllowed(fVisible));
2953}
2954
2955bool UIExtraDataManager::selectorWindowStatusBarVisible()
2956{
2957 /* 'True' unless feature restricted: */
2958 return !isFeatureRestricted(GUI_Statusbar);
2959}
2960
2961void UIExtraDataManager::setSelectorWindowStatusBarVisible(bool fVisible)
2962{
2963 /* 'False' if feature restricted, null-string otherwise: */
2964 setExtraDataString(GUI_Statusbar, toFeatureRestricted(!fVisible));
2965}
2966
2967QStringList UIExtraDataManager::knownMachineGroupDefinitionKeys()
2968{
2969 /* Acquire a list of known group definition keys: */
2970 QStringList result;
2971 foreach (const QString &strKey, m_data.value(GlobalID).keys())
2972 if (strKey.startsWith(GUI_GroupDefinitions))
2973 {
2974 QString strGroupID = strKey;
2975 strGroupID.remove(GUI_GroupDefinitions);
2976 result << strGroupID;
2977 }
2978
2979 /* Return result: */
2980 return result;
2981}
2982
2983QStringList UIExtraDataManager::machineGroupDefinitions(const QString &strGroupID)
2984{
2985 return extraDataStringList(GUI_GroupDefinitions + strGroupID);
2986}
2987
2988void UIExtraDataManager::setMachineGroupDefinitions(const QString &strGroupID, const QStringList &definitions)
2989{
2990 setExtraDataStringList(GUI_GroupDefinitions + strGroupID, definitions);
2991}
2992
2993QString UIExtraDataManager::selectorWindowLastItemChosen()
2994{
2995 return extraDataString(GUI_LastItemSelected);
2996}
2997
2998void UIExtraDataManager::setSelectorWindowLastItemChosen(const QString &strItemID)
2999{
3000 setExtraDataString(GUI_LastItemSelected, strItemID);
3001}
3002
3003QMap<DetailsElementType, bool> UIExtraDataManager::selectorWindowDetailsElements()
3004{
3005 /* Get corresponding extra-data: */
3006 const QStringList data = extraDataStringList(GUI_Details_Elements);
3007
3008 /* Desearialize passed elements: */
3009 QMap<DetailsElementType, bool> elements;
3010 foreach (QString strItem, data)
3011 {
3012 bool fOpened = true;
3013 if (strItem.endsWith("Closed", Qt::CaseInsensitive))
3014 {
3015 fOpened = false;
3016 strItem.remove("Closed", Qt::CaseInsensitive);
3017 }
3018 const DetailsElementType enmType = gpConverter->fromInternalString<DetailsElementType>(strItem);
3019 if (enmType != DetailsElementType_Invalid)
3020 elements[enmType] = fOpened;
3021 }
3022
3023 /* If settings are empty: */
3024 if (elements.isEmpty())
3025 {
3026 /* Propose the defaults: */
3027 elements[DetailsElementType_General] = true;
3028 elements[DetailsElementType_Preview] = true;
3029 elements[DetailsElementType_System] = true;
3030 elements[DetailsElementType_Display] = true;
3031 elements[DetailsElementType_Storage] = true;
3032 elements[DetailsElementType_Audio] = true;
3033 elements[DetailsElementType_Network] = true;
3034 elements[DetailsElementType_USB] = true;
3035 elements[DetailsElementType_SF] = true;
3036 elements[DetailsElementType_Description] = true;
3037 }
3038
3039 /* Return elements: */
3040 return elements;
3041}
3042
3043void UIExtraDataManager::setSelectorWindowDetailsElements(const QMap<DetailsElementType, bool> &elements)
3044{
3045 /* Prepare corresponding extra-data: */
3046 QStringList data;
3047
3048 /* Searialize passed elements: */
3049 foreach (DetailsElementType enmType, elements.keys())
3050 {
3051 QString strValue = gpConverter->toInternalString(enmType);
3052 if (!elements[enmType])
3053 strValue += "Closed";
3054 data << strValue;
3055 }
3056
3057 /* Re-cache corresponding extra-data: */
3058 setExtraDataStringList(GUI_Details_Elements, data);
3059}
3060
3061PreviewUpdateIntervalType UIExtraDataManager::selectorWindowPreviewUpdateInterval()
3062{
3063 return gpConverter->fromInternalString<PreviewUpdateIntervalType>(extraDataString(GUI_Details_Elements_Preview_UpdateInterval));
3064}
3065
3066void UIExtraDataManager::setSelectorWindowPreviewUpdateInterval(PreviewUpdateIntervalType interval)
3067{
3068 setExtraDataString(GUI_Details_Elements_Preview_UpdateInterval, gpConverter->toInternalString(interval));
3069}
3070
3071QStringList UIExtraDataManager::vboxManagerDetailsPaneElementOptions(DetailsElementType enmElementType)
3072{
3073 /* Compose full key from GUI_Details_Elements and enmElementType: */
3074 QString strElementType = gpConverter->toInternalString(enmElementType);
3075 AssertReturn(!strElementType.isEmpty(), QStringList());
3076 strElementType[0] = strElementType.at(0).toUpper();
3077 const QString strFullKey = QString("%1/%2").arg(GUI_Details_Elements).arg(strElementType);
3078
3079 /* Return option list: */
3080 return extraDataStringList(strFullKey);
3081}
3082
3083void UIExtraDataManager::setVBoxManagerDetailsPaneElementOptions(DetailsElementType enmElementType, const QStringList &options)
3084{
3085 /* Compose full key from GUI_Details_Elements and enmElementType: */
3086 QString strElementType = gpConverter->toInternalString(enmElementType);
3087 AssertReturnVoid(!strElementType.isEmpty());
3088 strElementType[0] = strElementType.at(0).toUpper();
3089 const QString strFullKey = QString("%1/%2").arg(GUI_Details_Elements).arg(strElementType);
3090
3091 /* Store option list: */
3092 setExtraDataStringList(strFullKey, options);
3093}
3094
3095bool UIExtraDataManager::snapshotManagerDetailsExpanded()
3096{
3097 /* 'False' unless feature allowed: */
3098 return isFeatureAllowed(GUI_SnapshotManager_Details_Expanded);
3099}
3100
3101void UIExtraDataManager::setSnapshotManagerDetailsExpanded(bool fExpanded)
3102{
3103 /* 'True' if feature allowed, null-string otherwise: */
3104 return setExtraDataString(GUI_SnapshotManager_Details_Expanded, toFeatureAllowed(fExpanded));
3105}
3106
3107bool UIExtraDataManager::virtualMediaManagerDetailsExpanded()
3108{
3109 /* 'False' unless feature allowed: */
3110 return isFeatureAllowed(GUI_VirtualMediaManager_Details_Expanded);
3111}
3112
3113void UIExtraDataManager::setVirtualMediaManagerDetailsExpanded(bool fExpanded)
3114{
3115 /* 'True' if feature allowed, null-string otherwise: */
3116 return setExtraDataString(GUI_VirtualMediaManager_Details_Expanded, toFeatureAllowed(fExpanded));
3117}
3118
3119bool UIExtraDataManager::virtualMediaManagerSearchWidgetExpanded()
3120{
3121 /* 'False' unless feature allowed: */
3122 return isFeatureAllowed(GUI_VirtualMediaManager_Search_Widget_Expanded);
3123}
3124
3125void UIExtraDataManager::setVirtualMediaManagerSearchWidgetExpanded(bool fExpanded)
3126{
3127 /* 'True' if feature allowed, null-string otherwise: */
3128 return setExtraDataString(GUI_VirtualMediaManager_Search_Widget_Expanded, toFeatureAllowed(fExpanded));
3129}
3130
3131bool UIExtraDataManager::hostNetworkManagerDetailsExpanded()
3132{
3133 /* 'False' unless feature allowed: */
3134 return isFeatureAllowed(GUI_HostNetworkManager_Details_Expanded);
3135}
3136
3137void UIExtraDataManager::setHostNetworkManagerDetailsExpanded(bool fExpanded)
3138{
3139 /* 'True' if feature allowed, null-string otherwise: */
3140 return setExtraDataString(GUI_HostNetworkManager_Details_Expanded, toFeatureAllowed(fExpanded));
3141}
3142
3143QStringList UIExtraDataManager::cloudProfileManagerRestrictions()
3144{
3145 return extraDataStringList(GUI_CloudProfileManager_Restrictions);
3146}
3147
3148void UIExtraDataManager::setCloudProfileManagerRestrictions(const QStringList &restrictions)
3149{
3150 return setExtraDataStringList(GUI_CloudProfileManager_Restrictions, restrictions);
3151}
3152
3153bool UIExtraDataManager::cloudProfileManagerDetailsExpanded()
3154{
3155 /* 'False' unless feature allowed: */
3156 return isFeatureAllowed(GUI_CloudProfileManager_Details_Expanded);
3157}
3158
3159void UIExtraDataManager::setCloudProfileManagerDetailsExpanded(bool fExpanded)
3160{
3161 /* 'True' if feature allowed, null-string otherwise: */
3162 return setExtraDataString(GUI_CloudProfileManager_Details_Expanded, toFeatureAllowed(fExpanded));
3163}
3164
3165QStringList UIExtraDataManager::cloudConsoleManagerApplications()
3166{
3167 /* Gather a list of keys matching required expression: */
3168 QStringList result;
3169 const QRegularExpression re(QString("^%1/([^/]+)$").arg(GUI_CloudConsoleManager_Application));
3170 foreach (const QString &strKey, m_data.value(GlobalID).keys())
3171 {
3172 const QRegularExpressionMatch mt = re.match(strKey);
3173 if (mt.hasMatch())
3174 result << mt.captured(1);
3175 }
3176 return result;
3177}
3178
3179QStringList UIExtraDataManager::cloudConsoleManagerProfiles(const QString &strId)
3180{
3181 /* Gather a list of keys matching required expression: */
3182 QStringList result;
3183 const QRegularExpression re(QString("^%1/%2/([^/]+)$").arg(GUI_CloudConsoleManager_Application, strId));
3184 foreach (const QString &strKey, m_data.value(GlobalID).keys())
3185 {
3186 const QRegularExpressionMatch mt = re.match(strKey);
3187 if (mt.hasMatch())
3188 result << mt.captured(1);
3189 }
3190 return result;
3191}
3192
3193QString UIExtraDataManager::cloudConsoleManagerApplication(const QString &strId)
3194{
3195 return extraDataString(QString("%1/%2").arg(GUI_CloudConsoleManager_Application, strId));
3196}
3197
3198void UIExtraDataManager::setCloudConsoleManagerApplication(const QString &strId, const QString &strDefinition)
3199{
3200 setExtraDataString(QString("%1/%2").arg(GUI_CloudConsoleManager_Application, strId), strDefinition);
3201}
3202
3203QString UIExtraDataManager::cloudConsoleManagerProfile(const QString &strApplicationId, const QString &strProfileId)
3204{
3205 return extraDataString(QString("%1/%2/%3").arg(GUI_CloudConsoleManager_Application, strApplicationId, strProfileId));
3206}
3207
3208void UIExtraDataManager::setCloudConsoleManagerProfile(const QString &strApplicationId, const QString &strProfileId, const QString &strDefinition)
3209{
3210 setExtraDataString(QString("%1/%2/%3").arg(GUI_CloudConsoleManager_Application, strApplicationId, strProfileId), strDefinition);
3211}
3212
3213QStringList UIExtraDataManager::cloudConsoleManagerRestrictions()
3214{
3215 return extraDataStringList(GUI_CloudConsoleManager_Restrictions);
3216}
3217
3218void UIExtraDataManager::setCloudConsoleManagerRestrictions(const QStringList &restrictions)
3219{
3220 return setExtraDataStringList(GUI_CloudConsoleManager_Restrictions, restrictions);
3221}
3222
3223bool UIExtraDataManager::cloudConsoleManagerDetailsExpanded()
3224{
3225 /* 'False' unless feature allowed: */
3226 return isFeatureAllowed(GUI_CloudConsoleManager_Details_Expanded);
3227}
3228
3229void UIExtraDataManager::setCloudConsoleManagerDetailsExpanded(bool fExpanded)
3230{
3231 /* 'True' if feature allowed, null-string otherwise: */
3232 return setExtraDataString(GUI_CloudConsoleManager_Details_Expanded, toFeatureAllowed(fExpanded));
3233}
3234
3235QString UIExtraDataManager::cloudConsolePublicKeyPath()
3236{
3237 return extraDataString(GUI_CloudConsole_PublicKey_Path);
3238}
3239
3240void UIExtraDataManager::setCloudConsolePublicKeyPath(const QString &strPath)
3241{
3242 setExtraDataString(GUI_CloudConsole_PublicKey_Path, strPath);
3243}
3244
3245bool UIExtraDataManager::showMachineInVirtualBoxManagerChooser(const QUuid &uID)
3246{
3247 /* 'True' unless 'restriction' feature allowed: */
3248 return !isFeatureAllowed(GUI_HideFromManager, uID);
3249}
3250
3251bool UIExtraDataManager::showMachineInVirtualBoxManagerDetails(const QUuid &uID)
3252{
3253 /* 'True' unless 'restriction' feature allowed: */
3254 return !isFeatureAllowed(GUI_HideDetails, uID);
3255}
3256
3257bool UIExtraDataManager::machineReconfigurationEnabled(const QUuid &uID)
3258{
3259 /* 'True' unless 'restriction' feature allowed: */
3260 return !isFeatureAllowed(GUI_PreventReconfiguration, uID);
3261}
3262
3263bool UIExtraDataManager::machineSnapshotOperationsEnabled(const QUuid &uID)
3264{
3265 /* 'True' unless 'restriction' feature allowed: */
3266 return !isFeatureAllowed(GUI_PreventSnapshotOperations, uID);
3267}
3268
3269QStringList UIExtraDataManager::machineWindowIconNames(const QUuid &uID)
3270{
3271 return extraDataStringList(GUI_MachineWindowIcons, uID);
3272}
3273
3274#ifndef VBOX_WS_MAC
3275QString UIExtraDataManager::machineWindowNamePostfix(const QUuid &uID)
3276{
3277 return extraDataString(GUI_MachineWindowNamePostfix, uID);
3278}
3279#endif /* !VBOX_WS_MAC */
3280
3281QRect UIExtraDataManager::machineWindowGeometry(UIVisualStateType visualStateType, ulong uScreenIndex, const QUuid &uID)
3282{
3283 /* Choose corresponding key: */
3284 QString strKey;
3285 switch (visualStateType)
3286 {
3287 case UIVisualStateType_Normal: strKey = extraDataKeyPerScreen(GUI_LastNormalWindowPosition, uScreenIndex); break;
3288 case UIVisualStateType_Scale: strKey = extraDataKeyPerScreen(GUI_LastScaleWindowPosition, uScreenIndex); break;
3289 default: AssertFailedReturn(QRect());
3290 }
3291
3292 /* Get corresponding extra-data: */
3293 const QStringList data = extraDataStringList(strKey, uID);
3294
3295 /* Parse loaded data: */
3296 int iX = 0, iY = 0, iW = 0, iH = 0;
3297 bool fOk = data.size() >= 4;
3298 do
3299 {
3300 if (!fOk) break;
3301 iX = data[0].toInt(&fOk);
3302 if (!fOk) break;
3303 iY = data[1].toInt(&fOk);
3304 if (!fOk) break;
3305 iW = data[2].toInt(&fOk);
3306 if (!fOk) break;
3307 iH = data[3].toInt(&fOk);
3308 }
3309 while (0);
3310
3311 /* Return geometry (loaded or null): */
3312 return fOk ? QRect(iX, iY, iW, iH) : QRect();
3313}
3314
3315bool UIExtraDataManager::machineWindowShouldBeMaximized(UIVisualStateType visualStateType, ulong uScreenIndex, const QUuid &uID)
3316{
3317 /* Choose corresponding key: */
3318 QString strKey;
3319 switch (visualStateType)
3320 {
3321 case UIVisualStateType_Normal: strKey = extraDataKeyPerScreen(GUI_LastNormalWindowPosition, uScreenIndex); break;
3322 case UIVisualStateType_Scale: strKey = extraDataKeyPerScreen(GUI_LastScaleWindowPosition, uScreenIndex); break;
3323 default: AssertFailedReturn(false);
3324 }
3325
3326 /* Get corresponding extra-data: */
3327 const QStringList data = extraDataStringList(strKey, uID);
3328
3329 /* Make sure 5th item has required value: */
3330 return data.size() == 5 && data[4] == GUI_Geometry_State_Max;
3331}
3332
3333void UIExtraDataManager::setMachineWindowGeometry(UIVisualStateType visualStateType, ulong uScreenIndex, const QRect &geometry, bool fMaximized, const QUuid &uID)
3334{
3335 /* Choose corresponding key: */
3336 QString strKey;
3337 switch (visualStateType)
3338 {
3339 case UIVisualStateType_Normal: strKey = extraDataKeyPerScreen(GUI_LastNormalWindowPosition, uScreenIndex); break;
3340 case UIVisualStateType_Scale: strKey = extraDataKeyPerScreen(GUI_LastScaleWindowPosition, uScreenIndex); break;
3341 default: AssertFailedReturnVoid();
3342 }
3343
3344 /* Serialize passed values: */
3345 QStringList data;
3346 data << QString::number(geometry.x());
3347 data << QString::number(geometry.y());
3348 data << QString::number(geometry.width());
3349 data << QString::number(geometry.height());
3350 if (fMaximized)
3351 data << GUI_Geometry_State_Max;
3352
3353 /* Re-cache corresponding extra-data: */
3354 setExtraDataStringList(strKey, data, uID);
3355}
3356
3357#ifndef VBOX_WS_MAC
3358bool UIExtraDataManager::menuBarEnabled(const QUuid &uID)
3359{
3360 /* 'True' unless feature restricted: */
3361 return !isFeatureRestricted(GUI_MenuBar_Enabled, uID);
3362}
3363
3364void UIExtraDataManager::setMenuBarEnabled(bool fEnabled, const QUuid &uID)
3365{
3366 /* 'False' if feature restricted, null-string otherwise: */
3367 setExtraDataString(GUI_MenuBar_Enabled, toFeatureRestricted(!fEnabled), uID);
3368}
3369#endif /* !VBOX_WS_MAC */
3370
3371bool UIExtraDataManager::menuBarContextMenuEnabled(const QUuid &uID)
3372{
3373 /* 'True' unless feature restricted: */
3374 return !isFeatureRestricted(GUI_MenuBar_ContextMenu_Enabled, uID);
3375}
3376
3377void UIExtraDataManager::setMenuBarContextMenuEnabled(bool fEnabled, const QUuid &uID)
3378{
3379 /* 'False' if feature restricted, null-string otherwise: */
3380 setExtraDataString(GUI_MenuBar_ContextMenu_Enabled, toFeatureRestricted(!fEnabled), uID);
3381}
3382
3383UIExtraDataMetaDefs::MenuType UIExtraDataManager::restrictedRuntimeMenuTypes(const QUuid &uID)
3384{
3385 /* Prepare result: */
3386 UIExtraDataMetaDefs::MenuType result = UIExtraDataMetaDefs::MenuType_Invalid;
3387 /* Get restricted runtime-menu-types: */
3388 foreach (const QString &strValue, extraDataStringList(GUI_RestrictedRuntimeMenus, uID))
3389 {
3390 UIExtraDataMetaDefs::MenuType value = gpConverter->fromInternalString<UIExtraDataMetaDefs::MenuType>(strValue);
3391 if (value != UIExtraDataMetaDefs::MenuType_Invalid)
3392 result = static_cast<UIExtraDataMetaDefs::MenuType>(result | value);
3393 }
3394 /* Return result: */
3395 return result;
3396}
3397
3398void UIExtraDataManager::setRestrictedRuntimeMenuTypes(UIExtraDataMetaDefs::MenuType types, const QUuid &uID)
3399{
3400 /* We have MenuType enum registered, so we can enumerate it: */
3401 const QMetaObject &smo = UIExtraDataMetaDefs::staticMetaObject;
3402 const int iEnumIndex = smo.indexOfEnumerator("MenuType");
3403 QMetaEnum metaEnum = smo.enumerator(iEnumIndex);
3404
3405 /* Prepare result: */
3406 QStringList result;
3407 /* Handle MenuType_All enum-value: */
3408 if (types == UIExtraDataMetaDefs::MenuType_All)
3409 result << gpConverter->toInternalString(types);
3410 else
3411 {
3412 /* Handle other enum-values: */
3413 for (int iKeyIndex = 0; iKeyIndex < metaEnum.keyCount(); ++iKeyIndex)
3414 {
3415 /* Get iterated enum-value: */
3416 const UIExtraDataMetaDefs::MenuType enumValue =
3417 static_cast<UIExtraDataMetaDefs::MenuType>(metaEnum.keyToValue(metaEnum.key(iKeyIndex)));
3418 /* Skip MenuType_Invalid & MenuType_All enum-values: */
3419 if (enumValue == UIExtraDataMetaDefs::MenuType_Invalid ||
3420 enumValue == UIExtraDataMetaDefs::MenuType_All)
3421 continue;
3422 if (types & enumValue)
3423 result << gpConverter->toInternalString(enumValue);
3424 }
3425 }
3426 /* Save result: */
3427 setExtraDataStringList(GUI_RestrictedRuntimeMenus, result, uID);
3428}
3429
3430UIExtraDataMetaDefs::MenuApplicationActionType UIExtraDataManager::restrictedRuntimeMenuApplicationActionTypes(const QUuid &uID)
3431{
3432 /* Prepare result: */
3433 UIExtraDataMetaDefs::MenuApplicationActionType result = UIExtraDataMetaDefs::MenuApplicationActionType_Invalid;
3434 /* Get restricted runtime-application-menu action-types: */
3435 foreach (const QString &strValue, extraDataStringList(GUI_RestrictedRuntimeApplicationMenuActions, uID))
3436 {
3437 UIExtraDataMetaDefs::MenuApplicationActionType value = gpConverter->fromInternalString<UIExtraDataMetaDefs::MenuApplicationActionType>(strValue);
3438 if (value != UIExtraDataMetaDefs::MenuApplicationActionType_Invalid)
3439 result = static_cast<UIExtraDataMetaDefs::MenuApplicationActionType>(result | value);
3440 }
3441 /* Return result: */
3442 return result;
3443}
3444
3445void UIExtraDataManager::setRestrictedRuntimeMenuApplicationActionTypes(UIExtraDataMetaDefs::MenuApplicationActionType types, const QUuid &uID)
3446{
3447 /* We have MenuApplicationActionType enum registered, so we can enumerate it: */
3448 const QMetaObject &smo = UIExtraDataMetaDefs::staticMetaObject;
3449 const int iEnumIndex = smo.indexOfEnumerator("MenuApplicationActionType");
3450 QMetaEnum metaEnum = smo.enumerator(iEnumIndex);
3451
3452 /* Prepare result: */
3453 QStringList result;
3454 /* Handle MenuApplicationActionType_All enum-value: */
3455 if (types == UIExtraDataMetaDefs::MenuApplicationActionType_All)
3456 result << gpConverter->toInternalString(types);
3457 else
3458 {
3459 /* Handle other enum-values: */
3460 for (int iKeyIndex = 0; iKeyIndex < metaEnum.keyCount(); ++iKeyIndex)
3461 {
3462 /* Get iterated enum-value: */
3463 const UIExtraDataMetaDefs::MenuApplicationActionType enumValue =
3464 static_cast<UIExtraDataMetaDefs::MenuApplicationActionType>(metaEnum.keyToValue(metaEnum.key(iKeyIndex)));
3465 /* Skip MenuApplicationActionType_Invalid & MenuApplicationActionType_All enum-values: */
3466 if (enumValue == UIExtraDataMetaDefs::MenuApplicationActionType_Invalid ||
3467 enumValue == UIExtraDataMetaDefs::MenuApplicationActionType_All)
3468 continue;
3469 if (types & enumValue)
3470 result << gpConverter->toInternalString(enumValue);
3471 }
3472 }
3473 /* Save result: */
3474 setExtraDataStringList(GUI_RestrictedRuntimeApplicationMenuActions, result, uID);
3475}
3476
3477UIExtraDataMetaDefs::RuntimeMenuMachineActionType UIExtraDataManager::restrictedRuntimeMenuMachineActionTypes(const QUuid &uID)
3478{
3479 /* Prepare result: */
3480 UIExtraDataMetaDefs::RuntimeMenuMachineActionType result = UIExtraDataMetaDefs::RuntimeMenuMachineActionType_Invalid;
3481 /* Get restricted runtime-machine-menu action-types: */
3482 foreach (const QString &strValue, extraDataStringList(GUI_RestrictedRuntimeMachineMenuActions, uID))
3483 {
3484 UIExtraDataMetaDefs::RuntimeMenuMachineActionType value = gpConverter->fromInternalString<UIExtraDataMetaDefs::RuntimeMenuMachineActionType>(strValue);
3485 /* Since empty value has default restriction, we are supporting special 'Nothing' value: */
3486 if (value == UIExtraDataMetaDefs::RuntimeMenuMachineActionType_Nothing)
3487 {
3488 result = UIExtraDataMetaDefs::RuntimeMenuMachineActionType_Nothing;
3489 break;
3490 }
3491 if (value != UIExtraDataMetaDefs::RuntimeMenuMachineActionType_Invalid)
3492 result = static_cast<UIExtraDataMetaDefs::RuntimeMenuMachineActionType>(result | value);
3493 }
3494 /* Defaults: */
3495 if (result == UIExtraDataMetaDefs::RuntimeMenuMachineActionType_Invalid)
3496 {
3497 result = static_cast<UIExtraDataMetaDefs::RuntimeMenuMachineActionType>(result | UIExtraDataMetaDefs::RuntimeMenuMachineActionType_SaveState);
3498 result = static_cast<UIExtraDataMetaDefs::RuntimeMenuMachineActionType>(result | UIExtraDataMetaDefs::RuntimeMenuMachineActionType_PowerOff);
3499 }
3500 /* Return result: */
3501 return result;
3502}
3503
3504void UIExtraDataManager::setRestrictedRuntimeMenuMachineActionTypes(UIExtraDataMetaDefs::RuntimeMenuMachineActionType types, const QUuid &uID)
3505{
3506 /* We have RuntimeMenuMachineActionType enum registered, so we can enumerate it: */
3507 const QMetaObject &smo = UIExtraDataMetaDefs::staticMetaObject;
3508 const int iEnumIndex = smo.indexOfEnumerator("RuntimeMenuMachineActionType");
3509 QMetaEnum metaEnum = smo.enumerator(iEnumIndex);
3510
3511 /* Prepare result: */
3512 QStringList result;
3513 /* Handle RuntimeMenuMachineActionType_All enum-value: */
3514 if (types == UIExtraDataMetaDefs::RuntimeMenuMachineActionType_All)
3515 result << gpConverter->toInternalString(types);
3516 else
3517 {
3518 /* Handle other enum-values: */
3519 for (int iKeyIndex = 0; iKeyIndex < metaEnum.keyCount(); ++iKeyIndex)
3520 {
3521 /* Get iterated enum-value: */
3522 const UIExtraDataMetaDefs::RuntimeMenuMachineActionType enumValue =
3523 static_cast<UIExtraDataMetaDefs::RuntimeMenuMachineActionType>(metaEnum.keyToValue(metaEnum.key(iKeyIndex)));
3524 /* Skip RuntimeMenuMachineActionType_Invalid, RuntimeMenuMachineActionType_Nothing & RuntimeMenuMachineActionType_All enum-values: */
3525 if (enumValue == UIExtraDataMetaDefs::RuntimeMenuMachineActionType_Invalid ||
3526 enumValue == UIExtraDataMetaDefs::RuntimeMenuMachineActionType_Nothing ||
3527 enumValue == UIExtraDataMetaDefs::RuntimeMenuMachineActionType_All)
3528 continue;
3529 if (types & enumValue)
3530 result << gpConverter->toInternalString(enumValue);
3531 }
3532 }
3533 /* Since empty value has default restriction, we are supporting special 'Nothing' value: */
3534 if (result.isEmpty())
3535 result << gpConverter->toInternalString(UIExtraDataMetaDefs::RuntimeMenuMachineActionType_Nothing);
3536 /* Save result: */
3537 setExtraDataStringList(GUI_RestrictedRuntimeMachineMenuActions, result, uID);
3538}
3539
3540UIExtraDataMetaDefs::RuntimeMenuViewActionType UIExtraDataManager::restrictedRuntimeMenuViewActionTypes(const QUuid &uID)
3541{
3542 /* Prepare result: */
3543 UIExtraDataMetaDefs::RuntimeMenuViewActionType result = UIExtraDataMetaDefs::RuntimeMenuViewActionType_Invalid;
3544 /* Get restricted runtime-view-menu action-types: */
3545 foreach (const QString &strValue, extraDataStringList(GUI_RestrictedRuntimeViewMenuActions, uID))
3546 {
3547 UIExtraDataMetaDefs::RuntimeMenuViewActionType value = gpConverter->fromInternalString<UIExtraDataMetaDefs::RuntimeMenuViewActionType>(strValue);
3548 if (value != UIExtraDataMetaDefs::RuntimeMenuViewActionType_Invalid)
3549 result = static_cast<UIExtraDataMetaDefs::RuntimeMenuViewActionType>(result | value);
3550 }
3551 /* Return result: */
3552 return result;
3553}
3554
3555void UIExtraDataManager::setRestrictedRuntimeMenuViewActionTypes(UIExtraDataMetaDefs::RuntimeMenuViewActionType types, const QUuid &uID)
3556{
3557 /* We have RuntimeMenuViewActionType enum registered, so we can enumerate it: */
3558 const QMetaObject &smo = UIExtraDataMetaDefs::staticMetaObject;
3559 const int iEnumIndex = smo.indexOfEnumerator("RuntimeMenuViewActionType");
3560 QMetaEnum metaEnum = smo.enumerator(iEnumIndex);
3561
3562 /* Prepare result: */
3563 QStringList result;
3564 /* Handle RuntimeMenuViewActionType_All enum-value: */
3565 if (types == UIExtraDataMetaDefs::RuntimeMenuViewActionType_All)
3566 result << gpConverter->toInternalString(types);
3567 else
3568 {
3569 /* Handle other enum-values: */
3570 for (int iKeyIndex = 0; iKeyIndex < metaEnum.keyCount(); ++iKeyIndex)
3571 {
3572 /* Get iterated enum-value: */
3573 const UIExtraDataMetaDefs::RuntimeMenuViewActionType enumValue =
3574 static_cast<UIExtraDataMetaDefs::RuntimeMenuViewActionType>(metaEnum.keyToValue(metaEnum.key(iKeyIndex)));
3575 /* Skip RuntimeMenuViewActionType_Invalid & RuntimeMenuViewActionType_All enum-values: */
3576 if (enumValue == UIExtraDataMetaDefs::RuntimeMenuViewActionType_Invalid ||
3577 enumValue == UIExtraDataMetaDefs::RuntimeMenuViewActionType_All)
3578 continue;
3579 if (types & enumValue)
3580 result << gpConverter->toInternalString(enumValue);
3581 }
3582 }
3583 /* Save result: */
3584 setExtraDataStringList(GUI_RestrictedRuntimeViewMenuActions, result, uID);
3585}
3586
3587UIExtraDataMetaDefs::RuntimeMenuInputActionType UIExtraDataManager::restrictedRuntimeMenuInputActionTypes(const QUuid &uID)
3588{
3589 /* Prepare result: */
3590 UIExtraDataMetaDefs::RuntimeMenuInputActionType result = UIExtraDataMetaDefs::RuntimeMenuInputActionType_Invalid;
3591 /* Get restricted runtime-machine-menu action-types: */
3592 foreach (const QString &strValue, extraDataStringList(GUI_RestrictedRuntimeInputMenuActions, uID))
3593 {
3594 UIExtraDataMetaDefs::RuntimeMenuInputActionType value = gpConverter->fromInternalString<UIExtraDataMetaDefs::RuntimeMenuInputActionType>(strValue);
3595 if (value != UIExtraDataMetaDefs::RuntimeMenuInputActionType_Invalid)
3596 result = static_cast<UIExtraDataMetaDefs::RuntimeMenuInputActionType>(result | value);
3597 }
3598 /* Return result: */
3599 return result;
3600}
3601
3602void UIExtraDataManager::setRestrictedRuntimeMenuInputActionTypes(UIExtraDataMetaDefs::RuntimeMenuInputActionType types, const QUuid &uID)
3603{
3604 /* We have RuntimeMenuInputActionType enum registered, so we can enumerate it: */
3605 const QMetaObject &smo = UIExtraDataMetaDefs::staticMetaObject;
3606 const int iEnumIndex = smo.indexOfEnumerator("RuntimeMenuInputActionType");
3607 QMetaEnum metaEnum = smo.enumerator(iEnumIndex);
3608
3609 /* Prepare result: */
3610 QStringList result;
3611 /* Handle RuntimeMenuInputActionType_All enum-value: */
3612 if (types == UIExtraDataMetaDefs::RuntimeMenuInputActionType_All)
3613 result << gpConverter->toInternalString(types);
3614 else
3615 {
3616 /* Handle other enum-values: */
3617 for (int iKeyIndex = 0; iKeyIndex < metaEnum.keyCount(); ++iKeyIndex)
3618 {
3619 /* Get iterated enum-value: */
3620 const UIExtraDataMetaDefs::RuntimeMenuInputActionType enumValue =
3621 static_cast<UIExtraDataMetaDefs::RuntimeMenuInputActionType>(metaEnum.keyToValue(metaEnum.key(iKeyIndex)));
3622 /* Skip RuntimeMenuInputActionType_Invalid & RuntimeMenuInputActionType_All enum-values: */
3623 if (enumValue == UIExtraDataMetaDefs::RuntimeMenuInputActionType_Invalid ||
3624 enumValue == UIExtraDataMetaDefs::RuntimeMenuInputActionType_All)
3625 continue;
3626 if (types & enumValue)
3627 result << gpConverter->toInternalString(enumValue);
3628 }
3629 }
3630 /* Save result: */
3631 setExtraDataStringList(GUI_RestrictedRuntimeInputMenuActions, result, uID);
3632}
3633
3634UIExtraDataMetaDefs::RuntimeMenuDevicesActionType UIExtraDataManager::restrictedRuntimeMenuDevicesActionTypes(const QUuid &uID)
3635{
3636 /* Prepare result: */
3637 UIExtraDataMetaDefs::RuntimeMenuDevicesActionType result = UIExtraDataMetaDefs::RuntimeMenuDevicesActionType_Invalid;
3638 /* Get restricted runtime-devices-menu action-types: */
3639 foreach (const QString &strValue, extraDataStringList(GUI_RestrictedRuntimeDevicesMenuActions, uID))
3640 {
3641 UIExtraDataMetaDefs::RuntimeMenuDevicesActionType value = gpConverter->fromInternalString<UIExtraDataMetaDefs::RuntimeMenuDevicesActionType>(strValue);
3642 /* Since empty value has default restriction, we are supporting special 'Nothing' value: */
3643 if (value == UIExtraDataMetaDefs::RuntimeMenuDevicesActionType_Nothing)
3644 {
3645 result = UIExtraDataMetaDefs::RuntimeMenuDevicesActionType_Nothing;
3646 break;
3647 }
3648 if (value != UIExtraDataMetaDefs::RuntimeMenuDevicesActionType_Invalid)
3649 result = static_cast<UIExtraDataMetaDefs::RuntimeMenuDevicesActionType>(result | value);
3650 }
3651 /* Defaults: */
3652 if (result == UIExtraDataMetaDefs::RuntimeMenuDevicesActionType_Invalid)
3653 {
3654 result = static_cast<UIExtraDataMetaDefs::RuntimeMenuDevicesActionType>(result | UIExtraDataMetaDefs::RuntimeMenuDevicesActionType_HardDrives);
3655 }
3656 /* Return result: */
3657 return result;
3658}
3659
3660void UIExtraDataManager::setRestrictedRuntimeMenuDevicesActionTypes(UIExtraDataMetaDefs::RuntimeMenuDevicesActionType types, const QUuid &uID)
3661{
3662 /* We have RuntimeMenuDevicesActionType enum registered, so we can enumerate it: */
3663 const QMetaObject &smo = UIExtraDataMetaDefs::staticMetaObject;
3664 const int iEnumIndex = smo.indexOfEnumerator("RuntimeMenuDevicesActionType");
3665 QMetaEnum metaEnum = smo.enumerator(iEnumIndex);
3666
3667 /* Prepare result: */
3668 QStringList result;
3669 /* Handle RuntimeMenuDevicesActionType_All enum-value: */
3670 if (types == UIExtraDataMetaDefs::RuntimeMenuDevicesActionType_All)
3671 result << gpConverter->toInternalString(types);
3672 else
3673 {
3674 /* Handle other enum-values: */
3675 for (int iKeyIndex = 0; iKeyIndex < metaEnum.keyCount(); ++iKeyIndex)
3676 {
3677 /* Get iterated enum-value: */
3678 const UIExtraDataMetaDefs::RuntimeMenuDevicesActionType enumValue =
3679 static_cast<UIExtraDataMetaDefs::RuntimeMenuDevicesActionType>(metaEnum.keyToValue(metaEnum.key(iKeyIndex)));
3680 /* Skip RuntimeMenuDevicesActionType_Invalid, RuntimeMenuDevicesActionType_Nothing & RuntimeMenuDevicesActionType_All enum-values: */
3681 if (enumValue == UIExtraDataMetaDefs::RuntimeMenuDevicesActionType_Invalid ||
3682 enumValue == UIExtraDataMetaDefs::RuntimeMenuDevicesActionType_Nothing ||
3683 enumValue == UIExtraDataMetaDefs::RuntimeMenuDevicesActionType_All)
3684 continue;
3685 if (types & enumValue)
3686 result << gpConverter->toInternalString(enumValue);
3687 }
3688 }
3689 /* Since empty value has default restriction, we are supporting special 'Nothing' value: */
3690 if (result.isEmpty())
3691 result << gpConverter->toInternalString(UIExtraDataMetaDefs::RuntimeMenuDevicesActionType_Nothing);
3692 /* Save result: */
3693 setExtraDataStringList(GUI_RestrictedRuntimeDevicesMenuActions, result, uID);
3694}
3695
3696#ifdef VBOX_WITH_DEBUGGER_GUI
3697UIExtraDataMetaDefs::RuntimeMenuDebuggerActionType UIExtraDataManager::restrictedRuntimeMenuDebuggerActionTypes(const QUuid &uID)
3698{
3699 /* Prepare result: */
3700 UIExtraDataMetaDefs::RuntimeMenuDebuggerActionType result = UIExtraDataMetaDefs::RuntimeMenuDebuggerActionType_Invalid;
3701 /* Get restricted runtime-debugger-menu action-types: */
3702 foreach (const QString &strValue, extraDataStringList(GUI_RestrictedRuntimeDebuggerMenuActions, uID))
3703 {
3704 UIExtraDataMetaDefs::RuntimeMenuDebuggerActionType value = gpConverter->fromInternalString<UIExtraDataMetaDefs::RuntimeMenuDebuggerActionType>(strValue);
3705 if (value != UIExtraDataMetaDefs::RuntimeMenuDebuggerActionType_Invalid)
3706 result = static_cast<UIExtraDataMetaDefs::RuntimeMenuDebuggerActionType>(result | value);
3707 }
3708 /* Return result: */
3709 return result;
3710}
3711
3712void UIExtraDataManager::setRestrictedRuntimeMenuDebuggerActionTypes(UIExtraDataMetaDefs::RuntimeMenuDebuggerActionType types, const QUuid &uID)
3713{
3714 /* We have RuntimeMenuDebuggerActionType enum registered, so we can enumerate it: */
3715 const QMetaObject &smo = UIExtraDataMetaDefs::staticMetaObject;
3716 const int iEnumIndex = smo.indexOfEnumerator("RuntimeMenuDebuggerActionType");
3717 QMetaEnum metaEnum = smo.enumerator(iEnumIndex);
3718
3719 /* Prepare result: */
3720 QStringList result;
3721 /* Handle RuntimeMenuDebuggerActionType_All enum-value: */
3722 if (types == UIExtraDataMetaDefs::RuntimeMenuDebuggerActionType_All)
3723 result << gpConverter->toInternalString(types);
3724 else
3725 {
3726 /* Handle other enum-values: */
3727 for (int iKeyIndex = 0; iKeyIndex < metaEnum.keyCount(); ++iKeyIndex)
3728 {
3729 /* Get iterated enum-value: */
3730 const UIExtraDataMetaDefs::RuntimeMenuDebuggerActionType enumValue =
3731 static_cast<UIExtraDataMetaDefs::RuntimeMenuDebuggerActionType>(metaEnum.keyToValue(metaEnum.key(iKeyIndex)));
3732 /* Skip RuntimeMenuDebuggerActionType_Invalid & RuntimeMenuDebuggerActionType_All enum-values: */
3733 if (enumValue == UIExtraDataMetaDefs::RuntimeMenuDebuggerActionType_Invalid ||
3734 enumValue == UIExtraDataMetaDefs::RuntimeMenuDebuggerActionType_All)
3735 continue;
3736 if (types & enumValue)
3737 result << gpConverter->toInternalString(enumValue);
3738 }
3739 }
3740 /* Save result: */
3741 setExtraDataStringList(GUI_RestrictedRuntimeDebuggerMenuActions, result, uID);
3742}
3743#endif /* VBOX_WITH_DEBUGGER_GUI */
3744
3745#ifdef VBOX_WS_MAC
3746UIExtraDataMetaDefs::MenuWindowActionType UIExtraDataManager::restrictedRuntimeMenuWindowActionTypes(const QUuid &uID)
3747{
3748 /* Prepare result: */
3749 UIExtraDataMetaDefs::MenuWindowActionType result = UIExtraDataMetaDefs::MenuWindowActionType_Invalid;
3750 /* Get restricted runtime-window-menu action-types: */
3751 foreach (const QString &strValue, extraDataStringList(GUI_RestrictedRuntimeWindowMenuActions, uID))
3752 {
3753 UIExtraDataMetaDefs::MenuWindowActionType value = gpConverter->fromInternalString<UIExtraDataMetaDefs::MenuWindowActionType>(strValue);
3754 if (value != UIExtraDataMetaDefs::MenuWindowActionType_Invalid)
3755 result = static_cast<UIExtraDataMetaDefs::MenuWindowActionType>(result | value);
3756 }
3757 /* Return result: */
3758 return result;
3759}
3760
3761void UIExtraDataManager::setRestrictedRuntimeMenuWindowActionTypes(UIExtraDataMetaDefs::MenuWindowActionType types, const QUuid &uID)
3762{
3763 /* We have MenuWindowActionType enum registered, so we can enumerate it: */
3764 const QMetaObject &smo = UIExtraDataMetaDefs::staticMetaObject;
3765 const int iEnumIndex = smo.indexOfEnumerator("MenuWindowActionType");
3766 QMetaEnum metaEnum = smo.enumerator(iEnumIndex);
3767
3768 /* Prepare result: */
3769 QStringList result;
3770 /* Handle MenuWindowActionType_All enum-value: */
3771 if (types == UIExtraDataMetaDefs::MenuWindowActionType_All)
3772 result << gpConverter->toInternalString(types);
3773 else
3774 {
3775 /* Handle other enum-values: */
3776 for (int iKeyIndex = 0; iKeyIndex < metaEnum.keyCount(); ++iKeyIndex)
3777 {
3778 /* Get iterated enum-value: */
3779 const UIExtraDataMetaDefs::MenuWindowActionType enumValue =
3780 static_cast<const UIExtraDataMetaDefs::MenuWindowActionType>(metaEnum.keyToValue(metaEnum.key(iKeyIndex)));
3781 /* Skip MenuWindowActionType_Invalid & MenuWindowActionType_All enum-values: */
3782 if (enumValue == UIExtraDataMetaDefs::MenuWindowActionType_Invalid ||
3783 enumValue == UIExtraDataMetaDefs::MenuWindowActionType_All)
3784 continue;
3785 if (types & enumValue)
3786 result << gpConverter->toInternalString(enumValue);
3787 }
3788 }
3789 /* Save result: */
3790 setExtraDataStringList(GUI_RestrictedRuntimeWindowMenuActions, result, uID);
3791}
3792#endif /* VBOX_WS_MAC */
3793
3794UIExtraDataMetaDefs::MenuHelpActionType UIExtraDataManager::restrictedRuntimeMenuHelpActionTypes(const QUuid &uID)
3795{
3796 /* Prepare result: */
3797 UIExtraDataMetaDefs::MenuHelpActionType result = UIExtraDataMetaDefs::MenuHelpActionType_Invalid;
3798 /* Get restricted runtime-help-menu action-types: */
3799 foreach (const QString &strValue, extraDataStringList(GUI_RestrictedRuntimeHelpMenuActions, uID))
3800 {
3801 UIExtraDataMetaDefs::MenuHelpActionType value = gpConverter->fromInternalString<UIExtraDataMetaDefs::MenuHelpActionType>(strValue);
3802 if (value != UIExtraDataMetaDefs::MenuHelpActionType_Invalid)
3803 result = static_cast<UIExtraDataMetaDefs::MenuHelpActionType>(result | value);
3804 }
3805 /* Return result: */
3806 return result;
3807}
3808
3809void UIExtraDataManager::setRestrictedRuntimeMenuHelpActionTypes(UIExtraDataMetaDefs::MenuHelpActionType types, const QUuid &uID)
3810{
3811 /* We have MenuHelpActionType enum registered, so we can enumerate it: */
3812 const QMetaObject &smo = UIExtraDataMetaDefs::staticMetaObject;
3813 const int iEnumIndex = smo.indexOfEnumerator("MenuHelpActionType");
3814 QMetaEnum metaEnum = smo.enumerator(iEnumIndex);
3815
3816 /* Prepare result: */
3817 QStringList result;
3818 /* Handle MenuHelpActionType_All enum-value: */
3819 if (types == UIExtraDataMetaDefs::MenuHelpActionType_All)
3820 result << gpConverter->toInternalString(types);
3821 else
3822 {
3823 /* Handle other enum-values: */
3824 for (int iKeyIndex = 0; iKeyIndex < metaEnum.keyCount(); ++iKeyIndex)
3825 {
3826 /* Get iterated enum-value: */
3827 const UIExtraDataMetaDefs::MenuHelpActionType enumValue =
3828 static_cast<UIExtraDataMetaDefs::MenuHelpActionType>(metaEnum.keyToValue(metaEnum.key(iKeyIndex)));
3829 /* Skip MenuHelpActionType_Invalid && MenuHelpActionType_All enum-values: */
3830 if (enumValue == UIExtraDataMetaDefs::MenuHelpActionType_Invalid ||
3831 enumValue == UIExtraDataMetaDefs::MenuHelpActionType_All)
3832 continue;
3833 if (types & enumValue)
3834 result << gpConverter->toInternalString(enumValue);
3835 }
3836 }
3837 /* Save result: */
3838 setExtraDataStringList(GUI_RestrictedRuntimeHelpMenuActions, result, uID);
3839}
3840
3841UIVisualStateType UIExtraDataManager::restrictedVisualStates(const QUuid &uID)
3842{
3843 /* Prepare result: */
3844 UIVisualStateType result = UIVisualStateType_Invalid;
3845 /* Get restricted visual-state-types: */
3846 foreach (const QString &strValue, extraDataStringList(GUI_RestrictedVisualStates, uID))
3847 {
3848 UIVisualStateType value = gpConverter->fromInternalString<UIVisualStateType>(strValue);
3849 if (value != UIVisualStateType_Invalid)
3850 result = static_cast<UIVisualStateType>(result | value);
3851 }
3852 /* Return result: */
3853 return result;
3854}
3855
3856UIVisualStateType UIExtraDataManager::requestedVisualState(const QUuid &uID)
3857{
3858 if (isFeatureAllowed(GUI_Fullscreen, uID)) return UIVisualStateType_Fullscreen;
3859 if (isFeatureAllowed(GUI_Seamless, uID)) return UIVisualStateType_Seamless;
3860 if (isFeatureAllowed(GUI_Scale, uID)) return UIVisualStateType_Scale;
3861 return UIVisualStateType_Normal;
3862}
3863
3864void UIExtraDataManager::setRequestedVisualState(UIVisualStateType visualState, const QUuid &uID)
3865{
3866 setExtraDataString(GUI_Fullscreen, toFeatureAllowed(visualState == UIVisualStateType_Fullscreen), uID);
3867 setExtraDataString(GUI_Seamless, toFeatureAllowed(visualState == UIVisualStateType_Seamless), uID);
3868 setExtraDataString(GUI_Scale, toFeatureAllowed(visualState == UIVisualStateType_Scale), uID);
3869}
3870
3871#ifdef VBOX_WS_NIX
3872bool UIExtraDataManager::legacyFullscreenModeRequested()
3873{
3874 /* 'False' unless feature allowed: */
3875 return isFeatureAllowed(GUI_Fullscreen_LegacyMode);
3876}
3877
3878bool UIExtraDataManager::distinguishMachineWindowGroups(const QUuid &uID)
3879{
3880 /* 'False' unless feature allowed: */
3881 return isFeatureAllowed(GUI_DistinguishMachineWindowGroups, uID);
3882}
3883
3884void UIExtraDataManager::setDistinguishMachineWindowGroups(const QUuid &uID, bool fEnabled)
3885{
3886 /* 'True' if feature allowed, null-string otherwise: */
3887 setExtraDataString(GUI_DistinguishMachineWindowGroups, toFeatureAllowed(fEnabled), uID);
3888}
3889#endif /* VBOX_WS_NIX */
3890
3891bool UIExtraDataManager::guestScreenAutoResizeEnabled(const QUuid &uID)
3892{
3893 /* 'True' unless feature restricted: */
3894 return !isFeatureRestricted(GUI_AutoresizeGuest, uID);
3895}
3896
3897void UIExtraDataManager::setGuestScreenAutoResizeEnabled(bool fEnabled, const QUuid &uID)
3898{
3899 /* 'False' if feature restricted, null-string otherwise: */
3900 setExtraDataString(GUI_AutoresizeGuest, toFeatureRestricted(!fEnabled), uID);
3901}
3902
3903bool UIExtraDataManager::lastGuestScreenVisibilityStatus(ulong uScreenIndex, const QUuid &uID)
3904{
3905 /* Not for primary screen: */
3906 if (uScreenIndex == 0)
3907 return true;
3908
3909 /* Compose corresponding key: */
3910 const QString strKey = extraDataKeyPerScreen(GUI_LastVisibilityStatusForGuestScreen, uScreenIndex);
3911
3912 /* 'False' unless feature allowed: */
3913 return isFeatureAllowed(strKey, uID);
3914}
3915
3916void UIExtraDataManager::setLastGuestScreenVisibilityStatus(ulong uScreenIndex, bool fEnabled, const QUuid &uID)
3917{
3918 /* Not for primary screen: */
3919 if (uScreenIndex == 0)
3920 return;
3921
3922 /* Compose corresponding key: */
3923 const QString strKey = extraDataKeyPerScreen(GUI_LastVisibilityStatusForGuestScreen, uScreenIndex);
3924
3925 /* 'True' if feature allowed, null-string otherwise: */
3926 return setExtraDataString(strKey, toFeatureAllowed(fEnabled), uID);
3927}
3928
3929QSize UIExtraDataManager::lastGuestScreenSizeHint(ulong uScreenIndex, const QUuid &uID)
3930{
3931 /* Choose corresponding key: */
3932 const QString strKey = extraDataKeyPerScreen(GUI_LastGuestSizeHint, uScreenIndex);
3933
3934 /* Get corresponding extra-data: */
3935 const QStringList data = extraDataStringList(strKey, uID);
3936
3937 /* Parse loaded data: */
3938 int iW = 0, iH = 0;
3939 bool fOk = data.size() == 2;
3940 do
3941 {
3942 if (!fOk) break;
3943 iW = data[0].toInt(&fOk);
3944 if (!fOk) break;
3945 iH = data[1].toInt(&fOk);
3946 }
3947 while (0);
3948
3949 /* Return size (loaded or invalid): */
3950 return fOk ? QSize(iW, iH) : QSize();
3951}
3952
3953void UIExtraDataManager::setLastGuestScreenSizeHint(ulong uScreenIndex, const QSize &sizeHint, const QUuid &uID)
3954{
3955 /* Choose corresponding key: */
3956 const QString strKey = extraDataKeyPerScreen(GUI_LastGuestSizeHint, uScreenIndex);
3957
3958 /* Serialize passed values: */
3959 QStringList data;
3960 data << QString::number(sizeHint.width());
3961 data << QString::number(sizeHint.height());
3962
3963 /* Re-cache corresponding extra-data: */
3964 setExtraDataStringList(strKey, data, uID);
3965}
3966
3967int UIExtraDataManager::hostScreenForPassedGuestScreen(int iGuestScreenIndex, const QUuid &uID)
3968{
3969 /* Choose corresponding key: */
3970 const QString strKey = extraDataKeyPerScreen(GUI_VirtualScreenToHostScreen, iGuestScreenIndex, true);
3971
3972 /* Get value and convert it to index: */
3973 const QString strValue = extraDataString(strKey, uID);
3974 bool fOk = false;
3975 const int iHostScreenIndex = strValue.toULong(&fOk);
3976
3977 /* Return corresponding index: */
3978 return fOk ? iHostScreenIndex : -1;
3979}
3980
3981void UIExtraDataManager::setHostScreenForPassedGuestScreen(int iGuestScreenIndex, int iHostScreenIndex, const QUuid &uID)
3982{
3983 /* Choose corresponding key: */
3984 const QString strKey = extraDataKeyPerScreen(GUI_VirtualScreenToHostScreen, iGuestScreenIndex, true);
3985
3986 /* Save passed index under corresponding value: */
3987 setExtraDataString(strKey, iHostScreenIndex != -1 ? QString::number(iHostScreenIndex) : QString(), uID);
3988}
3989
3990bool UIExtraDataManager::autoMountGuestScreensEnabled(const QUuid &uID)
3991{
3992 /* Show only if 'allowed' flag is set: */
3993 return isFeatureAllowed(GUI_AutomountGuestScreens, uID);
3994}
3995
3996#ifndef VBOX_WS_MAC
3997bool UIExtraDataManager::miniToolbarEnabled(const QUuid &uID)
3998{
3999 /* 'True' unless feature restricted: */
4000 return !isFeatureRestricted(GUI_ShowMiniToolBar, uID);
4001}
4002
4003void UIExtraDataManager::setMiniToolbarEnabled(bool fEnabled, const QUuid &uID)
4004{
4005 /* 'False' if feature restricted, null-string otherwise: */
4006 setExtraDataString(GUI_ShowMiniToolBar, toFeatureRestricted(!fEnabled), uID);
4007}
4008
4009bool UIExtraDataManager::autoHideMiniToolbar(const QUuid &uID)
4010{
4011 /* 'True' unless feature restricted: */
4012 return !isFeatureRestricted(GUI_MiniToolBarAutoHide, uID);
4013}
4014
4015void UIExtraDataManager::setAutoHideMiniToolbar(bool fAutoHide, const QUuid &uID)
4016{
4017 /* 'False' if feature restricted, null-string otherwise: */
4018 setExtraDataString(GUI_MiniToolBarAutoHide, toFeatureRestricted(!fAutoHide), uID);
4019}
4020
4021Qt::AlignmentFlag UIExtraDataManager::miniToolbarAlignment(const QUuid &uID)
4022{
4023 /* Return Qt::AlignBottom unless MiniToolbarAlignment_Top specified separately: */
4024 switch (gpConverter->fromInternalString<MiniToolbarAlignment>(extraDataString(GUI_MiniToolBarAlignment, uID)))
4025 {
4026 case MiniToolbarAlignment_Top: return Qt::AlignTop;
4027 default: break;
4028 }
4029 return Qt::AlignBottom;
4030}
4031
4032void UIExtraDataManager::setMiniToolbarAlignment(Qt::AlignmentFlag alignment, const QUuid &uID)
4033{
4034 /* Remove record unless Qt::AlignTop specified separately: */
4035 switch (alignment)
4036 {
4037 case Qt::AlignTop: setExtraDataString(GUI_MiniToolBarAlignment, gpConverter->toInternalString(MiniToolbarAlignment_Top), uID); return;
4038 default: break;
4039 }
4040 setExtraDataString(GUI_MiniToolBarAlignment, QString(), uID);
4041}
4042#endif /* VBOX_WS_MAC */
4043
4044bool UIExtraDataManager::statusBarEnabled(const QUuid &uID)
4045{
4046 /* 'True' unless feature restricted: */
4047 return !isFeatureRestricted(GUI_StatusBar_Enabled, uID);
4048}
4049
4050void UIExtraDataManager::setStatusBarEnabled(bool fEnabled, const QUuid &uID)
4051{
4052 /* 'False' if feature restricted, null-string otherwise: */
4053 setExtraDataString(GUI_StatusBar_Enabled, toFeatureRestricted(!fEnabled), uID);
4054}
4055
4056bool UIExtraDataManager::statusBarContextMenuEnabled(const QUuid &uID)
4057{
4058 /* 'True' unless feature restricted: */
4059 return !isFeatureRestricted(GUI_StatusBar_ContextMenu_Enabled, uID);
4060}
4061
4062void UIExtraDataManager::setStatusBarContextMenuEnabled(bool fEnabled, const QUuid &uID)
4063{
4064 /* 'False' if feature restricted, null-string otherwise: */
4065 setExtraDataString(GUI_StatusBar_ContextMenu_Enabled, toFeatureRestricted(!fEnabled), uID);
4066}
4067
4068QList<IndicatorType> UIExtraDataManager::restrictedStatusBarIndicators(const QUuid &uID)
4069{
4070 /* Prepare result: */
4071 QList<IndicatorType> result;
4072 /* Get restricted status-bar indicators: */
4073 foreach (const QString &strValue, extraDataStringList(GUI_RestrictedStatusBarIndicators, uID))
4074 {
4075 const IndicatorType value = gpConverter->fromInternalString<IndicatorType>(strValue);
4076 if (value != IndicatorType_Invalid && !result.contains(value))
4077 result << value;
4078 }
4079 /* Return result: */
4080 return result;
4081}
4082
4083void UIExtraDataManager::setRestrictedStatusBarIndicators(const QList<IndicatorType> &list, const QUuid &uID)
4084{
4085 /* Parse passed list: */
4086 QStringList data;
4087 foreach (const IndicatorType &indicatorType, list)
4088 data << gpConverter->toInternalString(indicatorType);
4089
4090 /* Re-cache corresponding extra-data: */
4091 setExtraDataStringList(GUI_RestrictedStatusBarIndicators, data, uID);
4092}
4093
4094QList<IndicatorType> UIExtraDataManager::statusBarIndicatorOrder(const QUuid &uID)
4095{
4096 /* Prepare result: */
4097 QList<IndicatorType> result;
4098 /* Get status-bar indicator order: */
4099 foreach (const QString &strValue, extraDataStringList(GUI_StatusBar_IndicatorOrder, uID))
4100 {
4101 const IndicatorType value = gpConverter->fromInternalString<IndicatorType>(strValue);
4102 if (value != IndicatorType_Invalid && !result.contains(value))
4103 result << value;
4104 }
4105
4106 /* We should update the list with missing indicators: */
4107 for (int i = (int)IndicatorType_Invalid; i < (int)IndicatorType_Max; ++i)
4108 {
4109 /* Skip the IndicatorType_Invalid (we used it as start of this loop): */
4110 if (i == (int)IndicatorType_Invalid)
4111 continue;
4112 /* Skip the IndicatorType_KeyboardExtension (special handling): */
4113 if (i == (int)IndicatorType_KeyboardExtension)
4114 continue;
4115
4116 /* Get the current one: */
4117 const IndicatorType enmCurrent = (IndicatorType)i;
4118
4119 /* Skip the current one if it's present: */
4120 if (result.contains(enmCurrent))
4121 continue;
4122
4123 /* Let's find the first of those which stays before it and is not missing: */
4124 IndicatorType enmPrevious = (IndicatorType)(enmCurrent - 1);
4125 while (enmPrevious != IndicatorType_Invalid && !result.contains(enmPrevious))
4126 enmPrevious = (IndicatorType)(enmPrevious - 1);
4127
4128 /* Calculate position to insert missing one: */
4129 const int iInsertPosition = enmPrevious != IndicatorType_Invalid
4130 ? result.indexOf(enmPrevious) + 1
4131 : 0;
4132
4133 /* Finally insert missing indicator at required position: */
4134 result.insert(iInsertPosition, enmCurrent);
4135 }
4136
4137 /* Return result: */
4138 return result;
4139}
4140
4141void UIExtraDataManager::setStatusBarIndicatorOrder(const QList<IndicatorType> &list, const QUuid &uID)
4142{
4143 /* Parse passed list: */
4144 QStringList data;
4145 foreach (const IndicatorType &indicatorType, list)
4146 data << gpConverter->toInternalString(indicatorType);
4147
4148 /* Re-cache corresponding extra-data: */
4149 setExtraDataStringList(GUI_StatusBar_IndicatorOrder, data, uID);
4150}
4151
4152#ifdef VBOX_WS_MAC
4153bool UIExtraDataManager::realtimeDockIconUpdateEnabled(const QUuid &uID)
4154{
4155 /* 'True' unless feature restricted: */
4156 return !isFeatureRestricted(GUI_RealtimeDockIconUpdateEnabled, uID);
4157}
4158
4159void UIExtraDataManager::setRealtimeDockIconUpdateEnabled(bool fEnabled, const QUuid &uID)
4160{
4161 /* 'False' if feature restricted, null-string otherwise: */
4162 setExtraDataString(GUI_RealtimeDockIconUpdateEnabled, toFeatureRestricted(!fEnabled), uID);
4163}
4164
4165int UIExtraDataManager::realtimeDockIconUpdateMonitor(const QUuid &uID)
4166{
4167 return extraDataString(GUI_RealtimeDockIconUpdateMonitor, uID).toInt();
4168}
4169
4170void UIExtraDataManager::setRealtimeDockIconUpdateMonitor(int iIndex, const QUuid &uID)
4171{
4172 setExtraDataString(GUI_RealtimeDockIconUpdateMonitor, iIndex ? QString::number(iIndex) : QString(), uID);
4173}
4174
4175bool UIExtraDataManager::dockIconDisableOverlay(const QUuid &uID)
4176{
4177 /* 'False' unless feature allowed: */
4178 return isFeatureAllowed(GUI_DockIconDisableOverlay, uID);
4179}
4180
4181void UIExtraDataManager::setDockIconDisableOverlay(bool fDisabled, const QUuid &uID)
4182{
4183 /* 'True' if feature allowed, null-string otherwise: */
4184 setExtraDataString(GUI_DockIconDisableOverlay, toFeatureAllowed(fDisabled), uID);
4185}
4186#endif /* VBOX_WS_MAC */
4187
4188bool UIExtraDataManager::passCADtoGuest(const QUuid &uID)
4189{
4190 /* 'False' unless feature allowed: */
4191 return isFeatureAllowed(GUI_PassCAD, uID);
4192}
4193
4194MouseCapturePolicy UIExtraDataManager::mouseCapturePolicy(const QUuid &uID)
4195{
4196 return gpConverter->fromInternalString<MouseCapturePolicy>(extraDataString(GUI_MouseCapturePolicy, uID));
4197}
4198
4199GuruMeditationHandlerType UIExtraDataManager::guruMeditationHandlerType(const QUuid &uID)
4200{
4201 return gpConverter->fromInternalString<GuruMeditationHandlerType>(extraDataString(GUI_GuruMeditationHandler, uID));
4202}
4203
4204bool UIExtraDataManager::hidLedsSyncState(const QUuid &uID)
4205{
4206 /* 'True' unless feature restricted: */
4207 return !isFeatureRestricted(GUI_HidLedsSync, uID);
4208}
4209
4210double UIExtraDataManager::scaleFactor(const QUuid &uID, int iScreenIndex)
4211{
4212 /* Get corresponding extra-data for this machine: */
4213 QStringList data = extraDataStringList(GUI_ScaleFactor, uID);
4214
4215 /* 1.0 is default scale factor: */
4216 if (data.size() == 0)
4217 return 1.0;
4218
4219 int iIndex = iScreenIndex;
4220 /* use the 0th. scale factor in case we dont have a scale factor for @p iScreenIndex: */
4221 if (data.size() <= iScreenIndex)
4222 iIndex = 0;
4223
4224 bool fOk = false;
4225 const double dScaleFactor = data.at(iIndex).toDouble(&fOk);
4226 if (!fOk)
4227 return 1.0;
4228 return dScaleFactor;
4229}
4230
4231QList<double> UIExtraDataManager::scaleFactors(const QUuid &uID)
4232{
4233 /* Look for the scale factor for this machine first: */
4234 QStringList data = extraDataStringList(GUI_ScaleFactor, uID);
4235
4236 QList<double> scaleFactorList;
4237 /* 1.0 is default scale factor: */
4238 if (data.size() == 0)
4239 {
4240 scaleFactorList.append(1.0);
4241 return scaleFactorList;
4242 }
4243
4244 bool fOk = false;
4245 double scaleFactor;
4246 for (int i = 0; i < data.size(); ++i)
4247 {
4248 scaleFactor = data[i].toDouble(&fOk);
4249 if (!fOk)
4250 scaleFactor = 1.0;
4251 scaleFactorList.append(scaleFactor);
4252 }
4253 return scaleFactorList;
4254}
4255
4256void UIExtraDataManager::setScaleFactor(double dScaleFactor, const QUuid &uID, int iScreenIndex)
4257{
4258 QStringList data = extraDataStringList(GUI_ScaleFactor, uID);
4259
4260 /* Just make sure that we have corresponding data item: */
4261 if (data.size() <= iScreenIndex)
4262 {
4263 for (int i = data.size(); i <= iScreenIndex; ++i)
4264 data.append(QString::number(1.0));
4265 }
4266
4267 data[iScreenIndex] = QString::number(dScaleFactor);
4268 setExtraDataStringList(GUI_ScaleFactor, data, uID);
4269}
4270
4271void UIExtraDataManager::setScaleFactors(const QList<double> &scaleFactors, const QUuid &uID)
4272{
4273 QStringList data;
4274 for (int i = 0; i < scaleFactors.size(); ++i)
4275 data.append(QString::number(scaleFactors[i]));
4276 setExtraDataStringList(GUI_ScaleFactor, data, uID);
4277}
4278
4279ScalingOptimizationType UIExtraDataManager::scalingOptimizationType(const QUuid &uID)
4280{
4281 return gpConverter->fromInternalString<ScalingOptimizationType>(extraDataString(GUI_Scaling_Optimization, uID));
4282}
4283
4284QRect UIExtraDataManager::sessionInformationDialogGeometry(QWidget *pWidget, QWidget *pParentWidget)
4285{
4286 return dialogGeometry(GUI_SessionInformationDialogGeometry, pWidget, pParentWidget);
4287}
4288
4289bool UIExtraDataManager::sessionInformationDialogShouldBeMaximized()
4290{
4291 return dialogShouldBeMaximized(GUI_SessionInformationDialogGeometry);
4292}
4293
4294void UIExtraDataManager::setSessionInformationDialogGeometry(const QRect &geometry, bool fMaximized)
4295{
4296 /* Serialize passed values: */
4297 QStringList data;
4298 data << QString::number(geometry.x());
4299 data << QString::number(geometry.y());
4300 data << QString::number(geometry.width());
4301 data << QString::number(geometry.height());
4302 if (fMaximized)
4303 data << GUI_Geometry_State_Max;
4304
4305 /* Re-cache corresponding extra-data: */
4306 setExtraDataStringList(GUI_SessionInformationDialogGeometry, data);
4307}
4308
4309
4310void UIExtraDataManager::setGuestControlProcessControlSplitterHints(const QList<int> &hints)
4311{
4312 QStringList data;
4313 data << (hints.size() > 0 ? QString::number(hints[0]) : QString());
4314 data << (hints.size() > 1 ? QString::number(hints[1]) : QString());
4315
4316 /* Re-cache corresponding extra-data: */
4317 setExtraDataStringList(GUI_GuestControl_ProcessControlSplitterHints, data);
4318}
4319
4320QList<int> UIExtraDataManager::guestControlProcessControlSplitterHints()
4321{
4322 /* Get corresponding extra-data: */
4323 const QStringList data = extraDataStringList(GUI_GuestControl_ProcessControlSplitterHints);
4324
4325 /* Parse loaded data: */
4326 QList<int> hints;
4327 hints << (data.size() > 0 ? data[0].toInt() : 0);
4328 hints << (data.size() > 1 ? data[1].toInt() : 0);
4329
4330 /* Return hints: */
4331 return hints;
4332}
4333
4334QRect UIExtraDataManager::fileManagerDialogGeometry(QWidget *pWidget, QWidget *pParentWidget)
4335{
4336 return dialogGeometry(GUI_GuestControl_FileManagerDialogGeometry, pWidget, pParentWidget);
4337}
4338
4339bool UIExtraDataManager::fileManagerDialogShouldBeMaximized()
4340{
4341 return dialogShouldBeMaximized(GUI_GuestControl_FileManagerDialogGeometry);
4342}
4343
4344void UIExtraDataManager::setFileManagerDialogGeometry(const QRect &geometry, bool fMaximized)
4345{
4346 setDialogGeometry(GUI_GuestControl_FileManagerDialogGeometry, geometry, fMaximized);
4347}
4348
4349void UIExtraDataManager::setFileManagerVisiblePanels(const QStringList &panelNameList)
4350{
4351 setExtraDataStringList(GUI_GuestControl_FileManagerVisiblePanels, panelNameList);
4352}
4353
4354QStringList UIExtraDataManager::fileManagerVisiblePanels()
4355{
4356 return extraDataStringList(GUI_GuestControl_FileManagerVisiblePanels);
4357}
4358
4359QRect UIExtraDataManager::softKeyboardDialogGeometry(QWidget *pWidget, QWidget *pParentWidget, const QRect &defaultGeometry)
4360{
4361 return dialogGeometry(GUI_SoftKeyboard_DialogGeometry, pWidget, pParentWidget, defaultGeometry);
4362}
4363
4364void UIExtraDataManager::setSoftKeyboardDialogGeometry(const QRect &geometry, bool fMaximized)
4365{
4366 setDialogGeometry(GUI_SoftKeyboard_DialogGeometry, geometry, fMaximized);
4367}
4368
4369bool UIExtraDataManager::softKeyboardDialogShouldBeMaximized()
4370{
4371 return dialogShouldBeMaximized(GUI_SoftKeyboard_DialogGeometry);
4372}
4373
4374void UIExtraDataManager::setSoftKeyboardOptions(bool fHideNumPad, bool fHideOSMenuKeys, bool fMultimediaKeys)
4375{
4376 QStringList data;
4377
4378 if (fHideNumPad)
4379 data << GUI_SoftKeyboard_HideNumPad;
4380 if (fHideOSMenuKeys)
4381 data << GUI_SoftKeyboard_HideOSMenuKeys;
4382 if (fMultimediaKeys)
4383 data << GUI_SoftKeyboard_HideMultimediaKeys;
4384
4385 setExtraDataStringList(GUI_SoftKeyboard_Options, data);
4386}
4387
4388void UIExtraDataManager::softKeyboardOptions(bool &fOutHideNumPad, bool &fOutHideOSMenuKeys, bool &fOutHideMultimediaKeys)
4389{
4390 fOutHideNumPad = false;
4391 fOutHideOSMenuKeys = false;
4392 const QStringList data = extraDataStringList(GUI_SoftKeyboard_Options);
4393 for (int i = 0; i < data.size(); ++i)
4394 {
4395 if (data[i] == GUI_SoftKeyboard_HideNumPad)
4396 fOutHideNumPad = true;
4397 if (data[i] == GUI_SoftKeyboard_HideOSMenuKeys)
4398 fOutHideOSMenuKeys = true;
4399 if (data[i] == GUI_SoftKeyboard_HideMultimediaKeys)
4400 fOutHideMultimediaKeys = true;
4401 }
4402}
4403
4404void UIExtraDataManager::setSoftKeyboardColorTheme(const QStringList &colorStringList)
4405{
4406 setExtraDataStringList(GUI_SoftKeyboard_ColorTheme, colorStringList);
4407}
4408
4409QStringList UIExtraDataManager::softKeyboardColorTheme()
4410{
4411 return extraDataStringList(GUI_SoftKeyboard_ColorTheme);
4412}
4413
4414void UIExtraDataManager::setSoftKeyboardSelectedColorTheme(const QString &strColorThemeName)
4415{
4416 setExtraDataString(GUI_SoftKeyboard_SelectedColorTheme, strColorThemeName);
4417}
4418
4419QString UIExtraDataManager::softKeyboardSelectedColorTheme()
4420{
4421 return extraDataString(GUI_SoftKeyboard_SelectedColorTheme);
4422}
4423
4424void UIExtraDataManager::setSoftKeyboardSelectedLayout(const QUuid &uLayoutUid)
4425{
4426 setExtraDataString(GUI_SoftKeyboard_SelectedLayout, uLayoutUid.toString());
4427}
4428
4429QUuid UIExtraDataManager::softKeyboardSelectedLayout()
4430{
4431 return QUuid(extraDataString(GUI_SoftKeyboard_SelectedLayout));
4432}
4433
4434void UIExtraDataManager::setFileManagerOptions(bool fListDirectoriesFirst,
4435 bool fShowDeleteConfirmation,
4436 bool fShowHumanReadableSizes,
4437 bool fShowHiddenObjects)
4438{
4439 /* Serialize passed values: */
4440 QStringList data;
4441
4442 if (fListDirectoriesFirst)
4443 data << GUI_GuestControl_FileManagerListDirectoriesFirst;
4444 if (fShowDeleteConfirmation)
4445 data << GUI_GuestControl_FileManagerShowDeleteConfirmation;
4446 if (fShowHumanReadableSizes)
4447 data << GUI_GuestControl_FileManagerShowHumanReadableSizes;
4448 if (fShowHiddenObjects)
4449 data << GUI_GuestControl_FileManagerShowHiddenObjects;
4450
4451 /* Re-cache corresponding extra-data: */
4452 setExtraDataStringList(GUI_GuestControl_FileManagerOptions, data);
4453}
4454
4455bool UIExtraDataManager::fileManagerListDirectoriesFirst()
4456{
4457 const QStringList data = extraDataStringList(GUI_GuestControl_FileManagerOptions);
4458 for (int i = 0; i < data.size(); ++i)
4459 {
4460 if (data[i] == GUI_GuestControl_FileManagerListDirectoriesFirst)
4461 return true;
4462 }
4463 return false;
4464}
4465
4466bool UIExtraDataManager::fileManagerShowDeleteConfirmation()
4467{
4468 const QStringList data = extraDataStringList(GUI_GuestControl_FileManagerOptions);
4469 for (int i = 0; i < data.size(); ++i)
4470 {
4471 if (data[i] == GUI_GuestControl_FileManagerShowDeleteConfirmation)
4472 return true;
4473 }
4474 return false;
4475}
4476
4477bool UIExtraDataManager::fileManagerShowHumanReadableSizes()
4478{
4479 const QStringList data = extraDataStringList(GUI_GuestControl_FileManagerOptions);
4480 for (int i = 0; i < data.size(); ++i)
4481 {
4482 if (data[i] == GUI_GuestControl_FileManagerShowHumanReadableSizes)
4483 return true;
4484 }
4485 return false;
4486}
4487
4488bool UIExtraDataManager::fileManagerShowHiddenObjects()
4489{
4490 const QStringList data = extraDataStringList(GUI_GuestControl_FileManagerOptions);
4491 for (int i = 0; i < data.size(); ++i)
4492 {
4493 if (data[i] == GUI_GuestControl_FileManagerShowHiddenObjects)
4494 return true;
4495 }
4496 return false;
4497}
4498
4499QRect UIExtraDataManager::guestProcessControlDialogGeometry(QWidget *pWidget, QWidget *pParentWidget, const QRect &defaultGeometry)
4500{
4501 return dialogGeometry(GUI_GuestControl_ProcessControlDialogGeometry, pWidget, pParentWidget, defaultGeometry);
4502}
4503
4504bool UIExtraDataManager::guestProcessControlDialogShouldBeMaximized()
4505{
4506 return dialogShouldBeMaximized(GUI_GuestControl_ProcessControlDialogGeometry);
4507}
4508
4509void UIExtraDataManager::setGuestProcessControlDialogGeometry(const QRect &geometry, bool fMaximized)
4510{
4511 setDialogGeometry(GUI_GuestControl_ProcessControlDialogGeometry, geometry, fMaximized);
4512}
4513
4514MachineCloseAction UIExtraDataManager::defaultMachineCloseAction(const QUuid &uID)
4515{
4516 return gpConverter->fromInternalString<MachineCloseAction>(extraDataString(GUI_DefaultCloseAction, uID));
4517}
4518
4519MachineCloseAction UIExtraDataManager::restrictedMachineCloseActions(const QUuid &uID)
4520{
4521 /* Prepare result: */
4522 MachineCloseAction result = MachineCloseAction_Invalid;
4523 /* Get restricted machine-close-actions: */
4524 foreach (const QString &strValue, extraDataStringList(GUI_RestrictedCloseActions, uID))
4525 {
4526 MachineCloseAction value = gpConverter->fromInternalString<MachineCloseAction>(strValue);
4527 if (value != MachineCloseAction_Invalid)
4528 result = static_cast<MachineCloseAction>(result | value);
4529 }
4530 /* Return result: */
4531 return result;
4532}
4533
4534MachineCloseAction UIExtraDataManager::lastMachineCloseAction(const QUuid &uID)
4535{
4536 return gpConverter->fromInternalString<MachineCloseAction>(extraDataString(GUI_LastCloseAction, uID));
4537}
4538
4539void UIExtraDataManager::setLastMachineCloseAction(MachineCloseAction machineCloseAction, const QUuid &uID)
4540{
4541 setExtraDataString(GUI_LastCloseAction, gpConverter->toInternalString(machineCloseAction), uID);
4542}
4543
4544QString UIExtraDataManager::machineCloseHookScript(const QUuid &uID)
4545{
4546 return extraDataString(GUI_CloseActionHook, uID);
4547}
4548
4549bool UIExtraDataManager::discardStateOnPowerOff(const QUuid &uID)
4550{
4551 /* 'False' unless feature allowed: */
4552 return isFeatureAllowed(GUI_DiscardStateOnPowerOff, uID);
4553}
4554
4555#ifdef VBOX_WITH_DEBUGGER_GUI
4556QString UIExtraDataManager::debugFlagValue(const QString &strDebugFlagKey)
4557{
4558 return extraDataString(strDebugFlagKey).toLower().trimmed();
4559}
4560#endif /* VBOX_WITH_DEBUGGER_GUI */
4561
4562#ifdef VBOX_GUI_WITH_EXTRADATA_MANAGER_UI
4563QRect UIExtraDataManager::extraDataManagerGeometry(QWidget *pWidget, QWidget *pParentWidget)
4564{
4565 return dialogGeometry(GUI_ExtraDataManager_Geometry, pWidget, pParentWidget);
4566}
4567
4568bool UIExtraDataManager::extraDataManagerShouldBeMaximized()
4569{
4570 return dialogShouldBeMaximized(GUI_ExtraDataManager_Geometry);
4571}
4572
4573void UIExtraDataManager::setExtraDataManagerGeometry(const QRect &geometry, bool fMaximized)
4574{
4575 /* Serialize passed values: */
4576 QStringList data;
4577 data << QString::number(geometry.x());
4578 data << QString::number(geometry.y());
4579 data << QString::number(geometry.width());
4580 data << QString::number(geometry.height());
4581 if (fMaximized)
4582 data << GUI_Geometry_State_Max;
4583
4584 /* Re-cache corresponding extra-data: */
4585 setExtraDataStringList(GUI_ExtraDataManager_Geometry, data);
4586}
4587
4588QList<int> UIExtraDataManager::extraDataManagerSplitterHints(QWidget *pWidget)
4589{
4590 /* Get corresponding extra-data: */
4591 const QStringList data = extraDataStringList(GUI_ExtraDataManager_SplitterHints);
4592
4593 /* Parse loaded data: */
4594 int iLeft = 0, iRight = 0;
4595 bool fOk = data.size() == 2;
4596 do
4597 {
4598 if (!fOk) break;
4599 iLeft = data[0].toInt(&fOk);
4600 if (!fOk) break;
4601 iRight = data[1].toInt(&fOk);
4602 }
4603 while (0);
4604
4605 /* Prepare hints (loaded or adviced): */
4606 QList<int> hints;
4607 if (fOk)
4608 {
4609 hints << iLeft;
4610 hints << iRight;
4611 }
4612 else
4613 {
4614 hints << (int)(pWidget->width() * .9 * (1.0 / 3));
4615 hints << (int)(pWidget->width() * .9 * (2.0 / 3));
4616 }
4617
4618 /* Return hints: */
4619 return hints;
4620}
4621
4622void UIExtraDataManager::setExtraDataManagerSplitterHints(const QList<int> &hints)
4623{
4624 /* Parse passed hints: */
4625 QStringList data;
4626 data << (hints.size() > 0 ? QString::number(hints[0]) : QString());
4627 data << (hints.size() > 1 ? QString::number(hints[1]) : QString());
4628
4629 /* Re-cache corresponding extra-data: */
4630 setExtraDataStringList(GUI_ExtraDataManager_SplitterHints, data);
4631}
4632#endif /* VBOX_GUI_WITH_EXTRADATA_MANAGER_UI */
4633
4634QRect UIExtraDataManager::logWindowGeometry(QWidget *pWidget, QWidget *pParentWidget, const QRect &defaultGeometry)
4635{
4636 return dialogGeometry(GUI_LogWindowGeometry, pWidget, pParentWidget, defaultGeometry);
4637}
4638
4639bool UIExtraDataManager::logWindowShouldBeMaximized()
4640{
4641 return dialogShouldBeMaximized(GUI_LogWindowGeometry);
4642}
4643
4644void UIExtraDataManager::setLogWindowGeometry(const QRect &geometry, bool fMaximized)
4645{
4646 /* Serialize passed values: */
4647 QStringList data;
4648 data << QString::number(geometry.x());
4649 data << QString::number(geometry.y());
4650 data << QString::number(geometry.width());
4651 data << QString::number(geometry.height());
4652 if (fMaximized)
4653 data << GUI_Geometry_State_Max;
4654
4655 /* Re-cache corresponding extra-data: */
4656 setExtraDataStringList(GUI_LogWindowGeometry, data);
4657}
4658
4659void UIExtraDataManager::setLogViweverOptions(const QFont &font, bool wrapLines, bool showLineNumbers)
4660{
4661 /* Serialize passed values: */
4662 QStringList data;
4663 data << font.family();
4664 /* Make sure that we have some non-empty string as font style name: */
4665 QString strStyleName = font.styleName();
4666 if (strStyleName.isEmpty())
4667 data << GUI_LogViewerNoFontStyleName;
4668 else
4669 data << font.styleName();
4670 data << QString::number(font.pointSize());
4671
4672 if (wrapLines)
4673 data << GUI_LogViewerWrapLinesEnabled;
4674 if (!showLineNumbers)
4675 data << GUI_LogViewerShowLineNumbersDisabled;
4676
4677 /* Re-cache corresponding extra-data: */
4678 setExtraDataStringList(GUI_LogViewerOptions, data);
4679}
4680
4681bool UIExtraDataManager::logViewerWrapLines()
4682{
4683 const QStringList data = extraDataStringList(GUI_LogViewerOptions);
4684 for (int i = 0; i < data.size(); ++i)
4685 {
4686 if (data[i] == GUI_LogViewerWrapLinesEnabled)
4687 return true;
4688 }
4689 return false;
4690}
4691
4692bool UIExtraDataManager::logViewerShowLineNumbers()
4693{
4694 const QStringList data = extraDataStringList(GUI_LogViewerOptions);
4695 for (int i = 0; i < data.size(); ++i)
4696 {
4697 if (data[i] == GUI_LogViewerShowLineNumbersDisabled)
4698 return false;
4699 }
4700 return true;
4701}
4702
4703QFont UIExtraDataManager::logViewerFont()
4704{
4705 const QStringList data = extraDataStringList(GUI_LogViewerOptions);
4706 if (data.size() < 3)
4707 return QFont();
4708 QString strFamily = data[0];
4709 QString strStyleName = data[1];
4710 if (strStyleName == GUI_LogViewerNoFontStyleName)
4711 strStyleName.clear();
4712 bool fOk = false;
4713 int iFontSize = data[2].toInt(&fOk);
4714 if (!fOk)
4715 iFontSize = 9;
4716 return QFontDatabase::font(strFamily, strStyleName, iFontSize);
4717}
4718
4719void UIExtraDataManager::setHelpBrowserLastUrlList(const QStringList &urlList)
4720{
4721 setExtraDataStringList(GUI_HelpBrowser_LastURLList, urlList);
4722}
4723
4724QStringList UIExtraDataManager::helpBrowserLastUrlList()
4725{
4726 return extraDataStringList(GUI_HelpBrowser_LastURLList);
4727}
4728
4729void UIExtraDataManager::setHelpBrowserZoomPercentage(int iZoomPercentage)
4730{
4731 setExtraDataString(GUI_HelpBrowser_ZoomPercentage, QString::number(iZoomPercentage));
4732}
4733
4734int UIExtraDataManager::helpBrowserZoomPercentage()
4735{
4736 return extraDataString(GUI_HelpBrowser_ZoomPercentage).toInt();
4737}
4738
4739QRect UIExtraDataManager::helpBrowserDialogGeometry(QWidget *pWidget, QWidget *pParentWidget, const QRect &defaultGeometry)
4740{
4741 return dialogGeometry(GUI_HelpBrowser_DialogGeometry, pWidget, pParentWidget, defaultGeometry);
4742}
4743
4744void UIExtraDataManager::setHelpBrowserDialogGeometry(const QRect &geometry, bool fMaximized)
4745{
4746 /* Serialize passed values: */
4747 QStringList data;
4748 data << QString::number(geometry.x());
4749 data << QString::number(geometry.y());
4750 data << QString::number(geometry.width());
4751 data << QString::number(geometry.height());
4752 if (fMaximized)
4753 data << GUI_Geometry_State_Max;
4754
4755 /* Re-cache corresponding extra-data: */
4756 setExtraDataStringList(GUI_HelpBrowser_DialogGeometry, data);
4757}
4758
4759bool UIExtraDataManager::helpBrowserDialogShouldBeMaximized()
4760{
4761 return dialogShouldBeMaximized(GUI_HelpBrowser_DialogGeometry);
4762}
4763
4764void UIExtraDataManager::setHelpBrowserBookmarks(const QStringList &bookmarks)
4765{
4766 setExtraDataStringList(GUI_HelpBrowser_Bookmarks, bookmarks);
4767}
4768
4769QStringList UIExtraDataManager::helpBrowserBookmarks()
4770{
4771 return extraDataStringList(GUI_HelpBrowser_Bookmarks);
4772}
4773
4774void UIExtraDataManager::setVMActivityOverviewHiddenColumnList(const QStringList &hiddenColumnList)
4775{
4776 setExtraDataStringList(GUI_VMActivityOverview_HiddenColumns, hiddenColumnList);
4777}
4778
4779QStringList UIExtraDataManager::VMActivityOverviewHiddenColumnList()
4780{
4781 return extraDataStringList(GUI_VMActivityOverview_HiddenColumns);
4782}
4783
4784bool UIExtraDataManager::VMActivityOverviewShowAllMachines()
4785{
4786 return isFeatureAllowed(GUI_VMActivityOverview_ShowAllMachines);
4787}
4788
4789void UIExtraDataManager::setVMActivityOverviewShowAllMachines(bool fShow)
4790{
4791 setExtraDataString(GUI_VMActivityOverview_ShowAllMachines, toFeatureAllowed(fShow));
4792}
4793
4794void UIExtraDataManager::setVMActivityMonitorDataSeriesColors(const QStringList &colorList)
4795{
4796 setExtraDataStringList(GUI_VMActivityMonitor_DataSeriesColors, colorList);
4797}
4798
4799QStringList UIExtraDataManager::VMActivityMonitorDataSeriesColors()
4800{
4801 return extraDataStringList(GUI_VMActivityMonitor_DataSeriesColors);
4802}
4803
4804bool UIExtraDataManager::VMActivityMonitorShowVMExits()
4805{
4806 return isFeatureAllowed(GUI_VMActivityMonitor_ShowVMExits);
4807}
4808
4809void UIExtraDataManager::setVMActivityMonitorShowVMExits(bool fShow)
4810{
4811 setExtraDataString(GUI_VMActivityMonitor_ShowVMExits, toFeatureAllowed(fShow));
4812}
4813
4814QRect UIExtraDataManager::mediumSelectorDialogGeometry(QWidget *pWidget, QWidget *pParentWidget, const QRect &defaultGeometry)
4815{
4816 return dialogGeometry(GUI_MediumSelector_DialogGeometry, pWidget, pParentWidget, defaultGeometry);
4817}
4818
4819void UIExtraDataManager::setMediumSelectorDialogGeometry(const QRect &geometry, bool fMaximized)
4820{
4821 setDialogGeometry(GUI_MediumSelector_DialogGeometry, geometry, fMaximized);
4822}
4823
4824bool UIExtraDataManager::mediumSelectorDialogShouldBeMaximized()
4825{
4826 return dialogShouldBeMaximized(GUI_MediumSelector_DialogGeometry);
4827}
4828
4829void UIExtraDataManager::sltExtraDataChange(const QUuid &uMachineID, const QString &strKey, const QString &strValue)
4830{
4831 /* Re-cache value only if uMachineID known already: */
4832 if (m_data.contains(uMachineID))
4833 {
4834 if (!strValue.isEmpty())
4835 m_data[uMachineID][strKey] = strValue;
4836 else
4837 m_data[uMachineID].remove(strKey);
4838 }
4839
4840 /* Global extra-data 'change' event: */
4841 if (uMachineID == GlobalID)
4842 {
4843 if (strKey.startsWith("GUI/"))
4844 {
4845 /* Notification-center alignment? */
4846 if (strKey == GUI_NotificationCenter_Alignment)
4847 emit sigNotificationCenterAlignmentChange();
4848 /* Notification-center order? */
4849 if (strKey == GUI_NotificationCenter_Order)
4850 emit sigNotificationCenterOrderChange();
4851 /* Settings expert mode? */
4852 if (strKey == GUI_Settings_ExpertMode)
4853 emit sigSettingsExpertModeChange();
4854 /* Language changed? */
4855 if (strKey == GUI_LanguageID)
4856 emit sigLanguageChange(extraDataString(strKey));
4857 /* Selector UI shortcut changed? */
4858 else if (strKey == GUI_Input_SelectorShortcuts)
4859 emit sigSelectorUIShortcutChange();
4860 /* Runtime UI shortcut changed? */
4861 else if (strKey == GUI_Input_MachineShortcuts)
4862 emit sigRuntimeUIShortcutChange();
4863 /* Runtime UI host-key combintation changed? */
4864 else if (strKey == GUI_Input_HostKeyCombination)
4865 emit sigRuntimeUIHostKeyCombinationChange();
4866 /* Cloud Profile Manager restrictions changed: */
4867 else if (strKey == GUI_CloudProfileManager_Restrictions)
4868 emit sigCloudProfileManagerRestrictionChange();
4869 /* Cloud Console Manager data changed: */
4870 else if (strKey.startsWith(QString(GUI_CloudConsoleManager_Application) + '/'))
4871 emit sigCloudConsoleManagerDataChange();
4872 /* Cloud Console Manager restrictions changed: */
4873 else if (strKey == GUI_CloudConsoleManager_Restrictions)
4874 emit sigCloudConsoleManagerRestrictionChange();
4875#if defined(VBOX_WS_NIX) || defined(VBOX_WS_WIN)
4876 else if (strKey == GUI_DisableHostScreenSaver)
4877 emit sigDisableHostScreenSaverStateChange(isFeatureAllowed(GUI_DisableHostScreenSaver));
4878#endif
4879 /* Details categories: */
4880 else if (strKey == GUI_Details_Elements)
4881 emit sigDetailsCategoriesChange();
4882 /* Details options: */
4883 else if (strKey.startsWith(QString(GUI_Details_Elements) + '/'))
4884 {
4885 QString strLeftover = strKey;
4886 strLeftover.remove(QString(GUI_Details_Elements) + '/');
4887 const DetailsElementType enmType = gpConverter->fromInternalString<DetailsElementType>(strLeftover);
4888 if (enmType != DetailsElementType_Invalid)
4889 emit sigDetailsOptionsChange(enmType);
4890 }
4891 /* Font scaling factor has changed: */
4892 else if (strKey == GUI_FontScaleFactor)
4893 emit sigFontScaleFactorChanged(fontScaleFactor());
4894 }
4895 }
4896 /* Machine extra-data 'change' event: */
4897 else
4898 {
4899 /* Current VM only: */
4900 if ( uiCommon().uiType() == UIType_RuntimeUI
4901 && uMachineID == uiCommon().managedVMUuid())
4902 {
4903 /* HID LEDs sync state changed (allowed if not restricted)? */
4904 if (strKey == GUI_HidLedsSync)
4905 emit sigHidLedsSyncStateChange(!isFeatureRestricted(strKey, uMachineID));
4906#ifdef VBOX_WS_MAC
4907 /* 'Dock icon' appearance changed (allowed if not restricted)? */
4908 else if (strKey == GUI_RealtimeDockIconUpdateEnabled ||
4909 strKey == GUI_RealtimeDockIconUpdateMonitor)
4910 emit sigDockIconAppearanceChange(!isFeatureRestricted(strKey, uMachineID));
4911 /* 'Dock icon overlay' appearance changed (restricted if not allowed)? */
4912 else if (strKey == GUI_DockIconDisableOverlay)
4913 emit sigDockIconOverlayAppearanceChange(isFeatureAllowed(strKey, uMachineID));
4914#endif /* VBOX_WS_MAC */
4915 }
4916
4917 /* Menu-bar configuration change: */
4918 if (
4919#ifndef VBOX_WS_MAC
4920 strKey == GUI_MenuBar_Enabled ||
4921#endif /* !VBOX_WS_MAC */
4922 strKey == GUI_RestrictedRuntimeMenus ||
4923 strKey == GUI_RestrictedRuntimeApplicationMenuActions ||
4924 strKey == GUI_RestrictedRuntimeMachineMenuActions ||
4925 strKey == GUI_RestrictedRuntimeViewMenuActions ||
4926 strKey == GUI_RestrictedRuntimeInputMenuActions ||
4927 strKey == GUI_RestrictedRuntimeDevicesMenuActions ||
4928#ifdef VBOX_WITH_DEBUGGER_GUI
4929 strKey == GUI_RestrictedRuntimeDebuggerMenuActions ||
4930#endif /* VBOX_WITH_DEBUGGER_GUI */
4931#ifdef VBOX_WS_MAC
4932 strKey == GUI_RestrictedRuntimeWindowMenuActions ||
4933#endif /* VBOX_WS_MAC */
4934 strKey == GUI_RestrictedRuntimeHelpMenuActions)
4935 emit sigMenuBarConfigurationChange(uMachineID);
4936 /* Status-bar configuration change: */
4937 else if (strKey == GUI_StatusBar_Enabled ||
4938 strKey == GUI_RestrictedStatusBarIndicators ||
4939 strKey == GUI_StatusBar_IndicatorOrder)
4940 emit sigStatusBarConfigurationChange(uMachineID);
4941 /* Visual state change: */
4942 else if (strKey == GUI_Fullscreen ||
4943 strKey == GUI_Seamless ||
4944 strKey == GUI_Scale)
4945 emit sigVisualStateChange(uMachineID);
4946 /* Scale-factor change: */
4947 else if (strKey == GUI_ScaleFactor)
4948 emit sigScaleFactorChange(uMachineID);
4949 /* Scaling optimization type change: */
4950 else if (strKey == GUI_Scaling_Optimization)
4951 emit sigScalingOptimizationTypeChange(uMachineID);
4952 }
4953
4954 /* Notify listeners: */
4955 emit sigExtraDataChange(uMachineID, strKey, strValue);
4956}
4957
4958void UIExtraDataManager::prepare()
4959{
4960 /* Prepare global extra-data map: */
4961 prepareGlobalExtraDataMap();
4962 /* Prepare extra-data event-handler: */
4963 prepareExtraDataEventHandler();
4964 /* Prepare extra-data settings: */
4965 prepareExtraDataSettings();
4966}
4967
4968void UIExtraDataManager::prepareGlobalExtraDataMap()
4969{
4970 /* Get CVirtualBox: */
4971 CVirtualBox vbox = gpGlobalSession->virtualBox();
4972
4973 /* Make sure at least empty map is created: */
4974 m_data[GlobalID] = ExtraDataMap();
4975
4976 /* Load global extra-data map: */
4977 foreach (const QString &strKey, vbox.GetExtraDataKeys())
4978 m_data[GlobalID][strKey] = vbox.GetExtraData(strKey);
4979}
4980
4981void UIExtraDataManager::prepareExtraDataEventHandler()
4982{
4983 /* Create extra-data event-handler: */
4984 m_pHandler = new UIExtraDataEventHandler(this);
4985 /* Configure extra-data event-handler: */
4986 AssertPtrReturnVoid(m_pHandler);
4987 {
4988 /* Create queued (async) connections for signals of event proxy object: */
4989 connect(m_pHandler, &UIExtraDataEventHandler::sigExtraDataChange,
4990 this, &UIExtraDataManager::sltExtraDataChange,
4991 Qt::QueuedConnection);
4992 }
4993}
4994
4995void UIExtraDataManager::prepareExtraDataSettings()
4996{
4997 /* For the case when Expert mode is undecided yet: */
4998 if (extraDataString(UIExtraDataDefs::GUI_Settings_ExpertMode).isNull())
4999 {
5000 /* If there are VMs already, mark the mode as Expert one, we've decided
5001 * that forcing all users to Basic mode by default is overkill a bit. */
5002 if (!gpGlobalSession->virtualBox().GetMachines().isEmpty())
5003 setSettingsInExpertMode(true);
5004 }
5005}
5006
5007#ifdef VBOX_GUI_WITH_EXTRADATA_MANAGER_UI
5008void UIExtraDataManager::cleanupWindow()
5009{
5010 delete m_pWindow;
5011}
5012#endif /* VBOX_GUI_WITH_EXTRADATA_MANAGER_UI */
5013
5014void UIExtraDataManager::cleanupExtraDataEventHandler()
5015{
5016 /* Destroy extra-data event-handler: */
5017 delete m_pHandler;
5018 m_pHandler = 0;
5019}
5020
5021void UIExtraDataManager::cleanup()
5022{
5023 /* Cleanup extra-data event-handler: */
5024 cleanupExtraDataEventHandler();
5025#ifdef VBOX_GUI_WITH_EXTRADATA_MANAGER_UI
5026 /* Cleanup window: */
5027 cleanupWindow();
5028#endif /* VBOX_GUI_WITH_EXTRADATA_MANAGER_UI */
5029}
5030
5031#ifdef VBOX_GUI_WITH_EXTRADATA_MANAGER_UI
5032void UIExtraDataManager::open(QWidget *pCenterWidget)
5033{
5034 /* If necessary: */
5035 if (!m_pWindow)
5036 {
5037 /* Create window: */
5038 m_pWindow = new UIExtraDataManagerWindow(pCenterWidget);
5039 /* Configure window connections: */
5040 connect(this, &UIExtraDataManager::sigExtraDataMapAcknowledging,
5041 m_pWindow.data(), &UIExtraDataManagerWindow::sltExtraDataMapAcknowledging);
5042 connect(this, &UIExtraDataManager::sigExtraDataChange,
5043 m_pWindow.data(), &UIExtraDataManagerWindow::sltExtraDataChange);
5044 }
5045 /* Show and raise window: */
5046 m_pWindow->showAndRaise(pCenterWidget);
5047}
5048#endif /* VBOX_GUI_WITH_EXTRADATA_MANAGER_UI */
5049
5050QString UIExtraDataManager::extraDataStringUnion(const QString &strKey, const QUuid &uID)
5051{
5052 /* If passed uID differs from the GlobalID: */
5053 if (uID != GlobalID)
5054 {
5055 /* Search through the machine extra-data first: */
5056 MapOfExtraDataMaps::const_iterator itMap = m_data.constFind(uID);
5057 /* Hot-load machine extra-data map if necessary: */
5058 if (itMap == m_data.constEnd())
5059 {
5060 hotloadMachineExtraDataMap(uID);
5061 itMap = m_data.constFind(uID);
5062 }
5063 if (itMap != m_data.constEnd())
5064 {
5065 /* Return string if present in the map: */
5066 ExtraDataMap::const_iterator itValue = itMap->constFind(strKey);
5067 if (itValue != itMap->constEnd())
5068 return *itValue;
5069 }
5070 }
5071
5072 /* Search through the global extra-data finally: */
5073 MapOfExtraDataMaps::const_iterator itMap = m_data.constFind(GlobalID);
5074 if (itMap != m_data.constEnd())
5075 {
5076 /* Return string if present in the map: */
5077 ExtraDataMap::const_iterator itValue = itMap->constFind(strKey);
5078 if (itValue != itMap->constEnd())
5079 return *itValue;
5080 }
5081
5082 /* Not found, return null string: */
5083 return QString();
5084}
5085
5086bool UIExtraDataManager::isFeatureAllowed(const QString &strKey, const QUuid &uID /* = GlobalID */)
5087{
5088 /* Get the value. Return 'false' if not found: */
5089 const QString strValue = extraDataStringUnion(strKey, uID);
5090 if (strValue.isNull())
5091 return false;
5092
5093 /* Check corresponding value: */
5094 return strValue.compare("true", Qt::CaseInsensitive) == 0
5095 || strValue.compare("yes", Qt::CaseInsensitive) == 0
5096 || strValue.compare("on", Qt::CaseInsensitive) == 0
5097 || strValue == "1";
5098}
5099
5100bool UIExtraDataManager::isFeatureRestricted(const QString &strKey, const QUuid &uID /* = GlobalID */)
5101{
5102 /* Get the value. Return 'false' if not found: */
5103 const QString strValue = extraDataStringUnion(strKey, uID);
5104 if (strValue.isNull())
5105 return false;
5106
5107 /* Check corresponding value: */
5108 return strValue.compare("false", Qt::CaseInsensitive) == 0
5109 || strValue.compare("no", Qt::CaseInsensitive) == 0
5110 || strValue.compare("off", Qt::CaseInsensitive) == 0
5111 || strValue == "0";
5112}
5113
5114QString UIExtraDataManager::toFeatureState(bool fState)
5115{
5116 return fState ? QString("true") : QString("false");
5117}
5118
5119QString UIExtraDataManager::toFeatureAllowed(bool fAllowed)
5120{
5121 return fAllowed ? QString("true") : QString();
5122}
5123
5124QString UIExtraDataManager::toFeatureRestricted(bool fRestricted)
5125{
5126 return fRestricted ? QString("false") : QString();
5127}
5128
5129void UIExtraDataManager::setDialogGeometry(const QString &strKey, const QRect &geometry, bool fMaximized)
5130{
5131 /* Serialize passed values: */
5132 QStringList data;
5133 data << QString::number(geometry.x());
5134 data << QString::number(geometry.y());
5135 data << QString::number(geometry.width());
5136 data << QString::number(geometry.height());
5137 if (fMaximized)
5138 data << GUI_Geometry_State_Max;
5139
5140 /* Save corresponding extra-data: */
5141 setExtraDataStringList(strKey, data);
5142}
5143
5144QRect UIExtraDataManager::dialogGeometry(const QString &strKey,
5145 QWidget *pWidget,
5146 QWidget *pParentWidget /* = 0 */,
5147 const QRect &defaultGeometry /* = QRect() */)
5148{
5149 /* Get corresponding extra-data: */
5150 const QStringList data = extraDataStringList(strKey);
5151
5152 /* Parse loaded data: */
5153 int iX = 0, iY = 0, iW = 0, iH = 0;
5154 bool fOk = data.size() >= 4;
5155 do
5156 {
5157 if (!fOk) break;
5158 iX = data[0].toInt(&fOk);
5159 if (!fOk) break;
5160 iY = data[1].toInt(&fOk);
5161 if (!fOk) break;
5162 iW = data[2].toInt(&fOk);
5163 if (!fOk) break;
5164 iH = data[3].toInt(&fOk);
5165 }
5166 while (0);
5167
5168 /* Get available-geometry [of screen with point (iX, iY) if possible]: */
5169 const QRect availableGeometry = fOk ? gpDesktop->availableGeometry(QPoint(iX, iY)) :
5170 gpDesktop->availableGeometry();
5171
5172 /* Use geometry (loaded or default): */
5173 QRect geometry = fOk
5174 ? QRect(iX, iY, iW, iH)
5175 : !defaultGeometry.isNull()
5176 ? defaultGeometry
5177 : QRect(QPoint(0, 0), availableGeometry.size() * .50 /* % */);
5178
5179 /* Take hint-widget into account: */
5180 if (pWidget)
5181 geometry.setSize(geometry.size().expandedTo(pWidget->minimumSizeHint()));
5182
5183 /* As a fallback, move default-geometry to pParentWidget' geometry center: */
5184 if (!fOk && pParentWidget)
5185 geometry.moveCenter(pParentWidget->geometry().center());
5186 /* As final fallback, move default-geometry to available-geometry' center: */
5187 else if (!fOk)
5188 geometry.moveCenter(availableGeometry.center());
5189
5190 /* In Windows Qt fails to reposition out of screen window properly, so doing it ourselves: */
5191#ifdef VBOX_WS_WIN
5192 /* Make sure resulting geometry is within current bounds: */
5193 if (!availableGeometry.contains(geometry))
5194 geometry = UIDesktopWidgetWatchdog::getNormalized(geometry, QRegion(availableGeometry));
5195#endif /* VBOX_WS_WIN */
5196
5197 /* Return result: */
5198 return geometry;
5199}
5200
5201bool UIExtraDataManager::dialogShouldBeMaximized(const QString &strKey)
5202{
5203 /* Get corresponding extra-data: */
5204 const QStringList data = extraDataStringList(strKey);
5205
5206 /* Make sure 5th item has required value: */
5207 return data.size() == 5 && data[4] == GUI_Geometry_State_Max;
5208}
5209
5210/* static */
5211QString UIExtraDataManager::extraDataKeyPerScreen(const QString &strBase, ulong uScreenIndex, bool fSameRuleForPrimary /* = false */)
5212{
5213 return fSameRuleForPrimary || uScreenIndex ? strBase + QString::number(uScreenIndex) : strBase;
5214}
5215
5216#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