VirtualBox

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

Last change on this file was 104393, checked in by vboxsync, 4 weeks ago

FE/Qt. bugref:10622. Using new UITranslationEventListener in the UIActionPool class.

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

© 2023 Oracle
ContactPrivacy policyTerms of Use