VirtualBox

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

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

FE/Qt: UIVirtualBoxManager: Store whether log-viewer opened detached or embedded way to extra-data.

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

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