VirtualBox

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

Last change on this file since 104158 was 104055, checked in by vboxsync, 10 months ago

FE/Qt: Typo in UIExtraDataManager / Beta stuff.

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