VirtualBox

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

Last change on this file was 108985, checked in by vboxsync, 8 days ago

FE/Qt: bugref:10814: VBox Manager / Tool-pane: Handle tool labels visibility change through extra-data; That affects both toolbars instead of the one where the change issued.

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

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