VirtualBox

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

Last change on this file since 101447 was 101447, checked in by vboxsync, 12 months ago

FE/Qt: bugref:10513: UIAdvancedSettingsDialog: Connecting experience mode check-box state to extra-data read/write.

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