VirtualBox

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

Last change on this file since 100347 was 100064, checked in by vboxsync, 20 months ago

FE/Qt: bugref:10421. Replacing VBOX_WS_X11 with VBOX_WS_NIX.

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