VirtualBox

source: vbox/trunk/src/VBox/Frontends/VirtualBox/src/runtime/UIIndicatorsPool.cpp

Last change on this file was 104358, checked in by vboxsync, 6 weeks ago

FE/Qt. bugref:10622. More refactoring around the retranslation functionality.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 50.7 KB
RevLine 
[26709]1/* $Id: UIIndicatorsPool.cpp 104358 2024-04-18 05:33:40Z vboxsync $ */
[26637]2/** @file
[51992]3 * VBox Qt GUI - UIIndicatorsPool class implementation.
[26637]4 */
5
6/*
[98103]7 * Copyright (C) 2010-2023 Oracle and/or its affiliates.
[26637]8 *
[96407]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
[26637]26 */
27
[41587]28/* Qt includes: */
[104358]29#include <QApplication>
[76606]30#include <QAccessibleWidget>
31#include <QHBoxLayout>
32#include <QPainter>
[98489]33#include <QStyle>
[76606]34#include <QTimer>
[28572]35
[41587]36/* GUI includes: */
[98375]37#include "QIStatusBarIndicator.h"
38#include "UIAnimationFramework.h"
39#include "UICommon.h"
40#include "UIConverter.h"
[98482]41#include "UIExtraDataManager.h"
[98375]42#include "UIHostComboEditor.h"
43#include "UIIconPool.h"
[76606]44#include "UIIndicatorsPool.h"
[98375]45#include "UIMachine.h"
[104290]46#include "UITranslationEventListener.h"
[26637]47
[41587]48
[51992]49/** QIStateStatusBarIndicator extension for Runtime UI. */
[104290]50class UISessionStateStatusBarIndicator : public QIStateStatusBarIndicator
[26637]51{
52 Q_OBJECT;
53
54public:
55
[51992]56 /** Constructor which remembers passed @a session object. */
[98491]57 UISessionStateStatusBarIndicator(IndicatorType enmType, UIMachine *pMachine);
[51992]58
[65254]59 /** Returns the indicator type. */
60 IndicatorType type() const { return m_enmType; }
61
[65255]62 /** Returns the indicator description. */
63 virtual QString description() const { return m_strDescription; }
64
[98974]65public slots:
66
[51992]67 /** Abstract update routine. */
68 virtual void updateAppearance() = 0;
69
[104290]70protected slots:
[51992]71
[65255]72 /** Handles translation event. */
[104290]73 void sltRetranslateUI();
[65255]74
[104290]75protected:
76
[65254]77 /** Holds the indicator type. */
78 const IndicatorType m_enmType;
79
[98375]80 /** Holds the machine UI reference. */
81 UIMachine *m_pMachine;
[65255]82
83 /** Holds the indicator description. */
84 QString m_strDescription;
[66946]85
86 /** Holds the table format. */
87 static const QString s_strTable;
88 /** Holds the table row format 1. */
89 static const QString s_strTableRow1;
90 /** Holds the table row format 2. */
91 static const QString s_strTableRow2;
92 /** Holds the table row format 3. */
93 static const QString s_strTableRow3;
94 /** Holds the table row format 4. */
95 static const QString s_strTableRow4;
[51992]96};
97
[65255]98
[66946]99/* static */
100const QString UISessionStateStatusBarIndicator::s_strTable = QString("<table cellspacing=5 style='white-space:pre'>%1</table>");
101/* static */
102const QString UISessionStateStatusBarIndicator::s_strTableRow1 = QString("<tr><td colspan='2'><nobr><b>%1</b></nobr></td></tr>");
103/* static */
104const QString UISessionStateStatusBarIndicator::s_strTableRow2 = QString("<tr><td><nobr>%1:</nobr></td><td><nobr>%2</nobr></td></tr>");
105/* static */
106const QString UISessionStateStatusBarIndicator::s_strTableRow3 = QString("<tr><td><nobr>%1</nobr></td><td><nobr>%2</nobr></td></tr>");
107/* static */
108const QString UISessionStateStatusBarIndicator::s_strTableRow4 = QString("<tr><td><nobr>&nbsp;%1:</nobr></td><td><nobr>%2</nobr></td></tr>");
109
110
[65257]111/** QAccessibleWidget extension used as an accessibility interface for UISessionStateStatusBarIndicator. */
112class QIAccessibilityInterfaceForUISessionStateStatusBarIndicator : public QAccessibleWidget
113{
114public:
115
116 /** Returns an accessibility interface for passed @a strClassname and @a pObject. */
117 static QAccessibleInterface *pFactory(const QString &strClassname, QObject *pObject)
118 {
119 /* Creating UISessionStateStatusBarIndicator accessibility interface: */
120 if (pObject && strClassname == QLatin1String("UISessionStateStatusBarIndicator"))
121 return new QIAccessibilityInterfaceForUISessionStateStatusBarIndicator(qobject_cast<QWidget*>(pObject));
122
123 /* Null by default: */
124 return 0;
125 }
126
127 /** Constructs an accessibility interface passing @a pWidget to the base-class. */
128 QIAccessibilityInterfaceForUISessionStateStatusBarIndicator(QWidget *pWidget)
129 : QAccessibleWidget(pWidget, QAccessible::Button)
130 {}
131
132 /** Returns a text for the passed @a enmTextRole. */
[93990]133 virtual QString text(QAccessible::Text /* enmTextRole */) const RT_OVERRIDE
[65257]134 {
135 /* Sanity check: */
136 AssertPtrReturn(indicator(), 0);
137
138 /* Return the indicator description: */
139 return indicator()->description();
140 }
141
142private:
143
144 /** Returns corresponding UISessionStateStatusBarIndicator. */
145 UISessionStateStatusBarIndicator *indicator() const { return qobject_cast<UISessionStateStatusBarIndicator*>(widget()); }
146};
147
148
[98491]149UISessionStateStatusBarIndicator::UISessionStateStatusBarIndicator(IndicatorType enmType, UIMachine *pMachine)
[65255]150 : m_enmType(enmType)
[98375]151 , m_pMachine(pMachine)
[65255]152{
[65257]153 /* Install UISessionStateStatusBarIndicator accessibility interface factory: */
154 QAccessible::installFactory(QIAccessibilityInterfaceForUISessionStateStatusBarIndicator::pFactory);
[104290]155 connect(&translationEventListener(), &UITranslationEventListener::sigRetranslateUI,
156 this, &UISessionStateStatusBarIndicator::sltRetranslateUI);
[65255]157}
158
[104290]159void UISessionStateStatusBarIndicator::sltRetranslateUI()
[65255]160{
161 /* Translate description: */
162 m_strDescription = tr("%1 status-bar indicator", "like 'hard-disk status-bar indicator'")
163 .arg(gpConverter->toString(type()));
164
165 /* Update appearance finally: */
166 updateAppearance();
167}
168
169
[51992]170/** UISessionStateStatusBarIndicator extension for Runtime UI: Hard-drive indicator. */
171class UIIndicatorHardDrive : public UISessionStateStatusBarIndicator
172{
173 Q_OBJECT;
174
175public:
176
[98485]177 /** Constructs indicator passing @a pMachine to the base-class. */
[98491]178 UIIndicatorHardDrive(UIMachine *pMachine)
179 : UISessionStateStatusBarIndicator(IndicatorType_HardDisks, pMachine)
[26637]180 {
[51994]181 /* Assign state-icons: */
[51293]182 setStateIcon(KDeviceActivity_Idle, UIIconPool::iconSet(":/hd_16px.png"));
183 setStateIcon(KDeviceActivity_Reading, UIIconPool::iconSet(":/hd_read_16px.png"));
184 setStateIcon(KDeviceActivity_Writing, UIIconPool::iconSet(":/hd_write_16px.png"));
185 setStateIcon(KDeviceActivity_Null, UIIconPool::iconSet(":/hd_disabled_16px.png"));
[98124]186 /* Configure connection: */
[99107]187 connect(m_pMachine, &UIMachine::sigMachineStateChange,
[99082]188 this, &UIIndicatorHardDrive::updateAppearance);
[99107]189 connect(m_pMachine, &UIMachine::sigStorageDeviceChange,
[98974]190 this, &UIIndicatorHardDrive::updateAppearance);
[99107]191 connect(m_pMachine, &UIMachine::sigMediumChange,
[99092]192 this, &UIIndicatorHardDrive::updateAppearance);
[51994]193 /* Translate finally: */
[104290]194 sltRetranslateUI();
[26637]195 }
[26758]196
[98974]197protected slots:
[98124]198
[51992]199 /** Update routine. */
[98973]200 virtual void updateAppearance() RT_OVERRIDE
[26758]201 {
[98485]202 /* Acquire data: */
[51994]203 QString strFullData;
[29015]204 bool fAttachmentsPresent = false;
[98485]205 m_pMachine->acquireHardDiskStatusInfo(strFullData, fAttachmentsPresent);
[26758]206
[98525]207 /* Show/hide indicator if there are no attachments
208 * and parent is visible already: */
209 if ( parentWidget()
210 && parentWidget()->isVisible())
211 setVisible(fAttachmentsPresent);
[26758]212
[51994]213 /* Update tool-tip: */
[98966]214 if (!strFullData.isEmpty())
215 setToolTip(s_strTable.arg(strFullData));
[51994]216 /* Update indicator state: */
[29015]217 setState(fAttachmentsPresent ? KDeviceActivity_Idle : KDeviceActivity_Null);
[26758]218 }
[26637]219};
220
[66946]221
[51992]222/** UISessionStateStatusBarIndicator extension for Runtime UI: Optical-drive indicator. */
223class UIIndicatorOpticalDisks : public UISessionStateStatusBarIndicator
[26637]224{
225 Q_OBJECT;
226
227public:
228
[98485]229 /** Constructs indicator passing @a pMachine to the base-class. */
[98491]230 UIIndicatorOpticalDisks(UIMachine *pMachine)
231 : UISessionStateStatusBarIndicator(IndicatorType_OpticalDisks, pMachine)
[26637]232 {
[51994]233 /* Assign state-icons: */
[51293]234 setStateIcon(KDeviceActivity_Idle, UIIconPool::iconSet(":/cd_16px.png"));
235 setStateIcon(KDeviceActivity_Reading, UIIconPool::iconSet(":/cd_read_16px.png"));
236 setStateIcon(KDeviceActivity_Writing, UIIconPool::iconSet(":/cd_write_16px.png"));
237 setStateIcon(KDeviceActivity_Null, UIIconPool::iconSet(":/cd_disabled_16px.png"));
[99082]238 /* Configure connection: */
[99107]239 connect(m_pMachine, &UIMachine::sigMachineStateChange,
[99082]240 this, &UIIndicatorOpticalDisks::updateAppearance);
[99107]241 connect(m_pMachine, &UIMachine::sigStorageDeviceChange,
[99092]242 this, &UIIndicatorOpticalDisks::updateAppearance);
[99107]243 connect(m_pMachine, &UIMachine::sigMediumChange,
[99092]244 this, &UIIndicatorOpticalDisks::updateAppearance);
[51994]245 /* Translate finally: */
[104290]246 sltRetranslateUI();
[26637]247 }
[26758]248
[98974]249protected slots:
[51992]250
251 /** Update routine. */
[98973]252 virtual void updateAppearance() RT_OVERRIDE
[26758]253 {
[51994]254 QString strFullData;
[29015]255 bool fAttachmentsPresent = false;
256 bool fAttachmentsMounted = false;
[98485]257 m_pMachine->acquireOpticalDiskStatusInfo(strFullData, fAttachmentsPresent, fAttachmentsMounted);
[26758]258
[98525]259 /* Show/hide indicator if there are no attachments
260 * and parent is visible already: */
261 if ( parentWidget()
262 && parentWidget()->isVisible())
263 setVisible(fAttachmentsPresent);
[26758]264
[51994]265 /* Update tool-tip: */
[98966]266 if (!strFullData.isEmpty())
267 setToolTip(s_strTable.arg(strFullData));
[51994]268 /* Update indicator state: */
[29015]269 setState(fAttachmentsMounted ? KDeviceActivity_Idle : KDeviceActivity_Null);
[26758]270 }
[26637]271};
272
[66946]273
[51992]274/** UISessionStateStatusBarIndicator extension for Runtime UI: Floppy-drive indicator. */
275class UIIndicatorFloppyDisks : public UISessionStateStatusBarIndicator
[26637]276{
277 Q_OBJECT;
278
279public:
280
[98485]281 /** Constructs indicator passing @a pMachine to the base-class. */
[98491]282 UIIndicatorFloppyDisks(UIMachine *pMachine)
283 : UISessionStateStatusBarIndicator(IndicatorType_FloppyDisks, pMachine)
[26637]284 {
[51994]285 /* Assign state-icons: */
[51293]286 setStateIcon(KDeviceActivity_Idle, UIIconPool::iconSet(":/fd_16px.png"));
287 setStateIcon(KDeviceActivity_Reading, UIIconPool::iconSet(":/fd_read_16px.png"));
288 setStateIcon(KDeviceActivity_Writing, UIIconPool::iconSet(":/fd_write_16px.png"));
289 setStateIcon(KDeviceActivity_Null, UIIconPool::iconSet(":/fd_disabled_16px.png"));
[99082]290 /* Configure connection: */
[99107]291 connect(m_pMachine, &UIMachine::sigMachineStateChange,
[99082]292 this, &UIIndicatorFloppyDisks::updateAppearance);
[99107]293 connect(m_pMachine, &UIMachine::sigStorageDeviceChange,
[99092]294 this, &UIIndicatorFloppyDisks::updateAppearance);
[99107]295 connect(m_pMachine, &UIMachine::sigMediumChange,
[99092]296 this, &UIIndicatorFloppyDisks::updateAppearance);
[51994]297 /* Translate finally: */
[104290]298 sltRetranslateUI();
[26637]299 }
[26758]300
[98974]301protected slots:
[51992]302
303 /** Update routine. */
[98973]304 virtual void updateAppearance() RT_OVERRIDE
[26758]305 {
[51994]306 QString strFullData;
[29015]307 bool fAttachmentsPresent = false;
308 bool fAttachmentsMounted = false;
[98485]309 m_pMachine->acquireFloppyDiskStatusInfo(strFullData, fAttachmentsPresent, fAttachmentsMounted);
[26758]310
[98525]311 /* Show/hide indicator if there are no attachments
312 * and parent is visible already: */
313 if ( parentWidget()
314 && parentWidget()->isVisible())
315 setVisible(fAttachmentsPresent);
[26758]316
[51994]317 /* Update tool-tip: */
[98966]318 if (!strFullData.isEmpty())
319 setToolTip(s_strTable.arg(strFullData));
[51994]320 /* Update indicator state: */
[29015]321 setState(fAttachmentsMounted ? KDeviceActivity_Idle : KDeviceActivity_Null);
[26758]322 }
[26637]323};
324
[66946]325
[68508]326/** UISessionStateStatusBarIndicator extension for Runtime UI: Audio indicator. */
327class UIIndicatorAudio : public UISessionStateStatusBarIndicator
328{
329 Q_OBJECT;
330
331public:
332
333 /** Audio states. */
334 enum AudioState
335 {
336 AudioState_AllOff = 0,
337 AudioState_OutputOn = RT_BIT(0),
338 AudioState_InputOn = RT_BIT(1),
339 AudioState_AllOn = AudioState_InputOn | AudioState_OutputOn
340 };
341
[98486]342 /** Constructs indicator passing @a pMachine to the base-class. */
[98491]343 UIIndicatorAudio(UIMachine *pMachine)
344 : UISessionStateStatusBarIndicator(IndicatorType_Audio, pMachine)
[68508]345 {
346 /* Assign state-icons: */
347 setStateIcon(AudioState_AllOff, UIIconPool::iconSet(":/audio_all_off_16px.png"));
348 setStateIcon(AudioState_OutputOn, UIIconPool::iconSet(":/audio_input_off_16px.png"));
349 setStateIcon(AudioState_InputOn, UIIconPool::iconSet(":/audio_output_off_16px.png"));
350 setStateIcon(AudioState_AllOn, UIIconPool::iconSet(":/audio_16px.png"));
[99082]351 /* Configure connection: */
[99107]352 connect(m_pMachine, &UIMachine::sigMachineStateChange,
[99082]353 this, &UIIndicatorAudio::updateAppearance);
[99107]354 connect(m_pMachine, &UIMachine::sigInitialized,
[99093]355 this, &UIIndicatorAudio::updateAppearance);
[99107]356 connect(m_pMachine, &UIMachine::sigAudioAdapterChange,
357 this, &UIIndicatorAudio::updateAppearance);
[68508]358 /* Translate finally: */
[104290]359 sltRetranslateUI();
[68508]360 }
361
[98974]362protected slots:
[68508]363
364 /** Update routine. */
[98973]365 virtual void updateAppearance() RT_OVERRIDE
[68508]366 {
367 QString strFullData;
[98486]368 bool fAudioEnabled = false;
369 bool fEnabledOutput = false;
370 bool fEnabledInput = false;
371 m_pMachine->acquireAudioStatusInfo(strFullData, fAudioEnabled, fEnabledOutput, fEnabledInput);
[68508]372
[98569]373 /* Show/hide indicator if there are no attachments
374 * and parent is visible already: */
375 if ( parentWidget()
376 && parentWidget()->isVisible())
377 setVisible(fAudioEnabled);
[68508]378
379 /* Update tool-tip: */
[98966]380 if (!strFullData.isEmpty())
381 setToolTip(s_strTable.arg(strFullData));
[98486]382 /* Update indicator state: */
383 AudioState enmState = AudioState_AllOff;
384 if (fEnabledOutput)
385 enmState = (AudioState)(enmState | AudioState_OutputOn);
386 if (fEnabledInput)
387 enmState = (AudioState)(enmState | AudioState_InputOn);
388 setState(enmState);
[68508]389 }
390};
391
392
[51992]393/** UISessionStateStatusBarIndicator extension for Runtime UI: Network indicator. */
394class UIIndicatorNetwork : public UISessionStateStatusBarIndicator
[26637]395{
396 Q_OBJECT;
397
398public:
399
[98487]400 /** Constructs indicator passing @a pMachine to the base-class. */
[98491]401 UIIndicatorNetwork(UIMachine *pMachine)
402 : UISessionStateStatusBarIndicator(IndicatorType_Network, pMachine)
[26637]403 {
[51994]404 /* Assign state-icons: */
[51293]405 setStateIcon(KDeviceActivity_Idle, UIIconPool::iconSet(":/nw_16px.png"));
406 setStateIcon(KDeviceActivity_Reading, UIIconPool::iconSet(":/nw_read_16px.png"));
407 setStateIcon(KDeviceActivity_Writing, UIIconPool::iconSet(":/nw_write_16px.png"));
408 setStateIcon(KDeviceActivity_Null, UIIconPool::iconSet(":/nw_disabled_16px.png"));
[99083]409 /* Configure connection: */
[98385]410 connect(m_pMachine, &UIMachine::sigMachineStateChange,
[99083]411 this, &UIIndicatorNetwork::updateAppearance);
412 connect(m_pMachine, &UIMachine::sigNetworkAdapterChange,
413 this, &UIIndicatorNetwork::updateAppearance);
[51994]414 /* Translate finally: */
[104290]415 sltRetranslateUI();
[26637]416 }
[26758]417
[98974]418protected slots:
[98973]419
420 /** Update routine. */
421 virtual void updateAppearance() RT_OVERRIDE
422 {
423 QString strFullData;
424 bool fAdaptersPresent = false;
425 bool fCablesDisconnected = true;
426 m_pMachine->acquireNetworkStatusInfo(strFullData, fAdaptersPresent, fCablesDisconnected);
427
428 /* Show/hide indicator if there are no attachments
429 * and parent is visible already: */
430 if ( parentWidget()
431 && parentWidget()->isVisible())
432 setVisible(fAdaptersPresent);
433
434 /* Update tool-tip: */
435 if (!strFullData.isEmpty())
436 setToolTip(s_strTable.arg(strFullData));
437 /* Update indicator state: */
438 setState(fAdaptersPresent && !fCablesDisconnected ? KDeviceActivity_Idle : KDeviceActivity_Null);
439 }
[26637]440};
441
[66946]442
[52220]443/** UISessionStateStatusBarIndicator extension for Runtime UI: USB indicator. */
444class UIIndicatorUSB : public UISessionStateStatusBarIndicator
445{
446 Q_OBJECT;
447
448public:
449
[98488]450 /** Constructs indicator passing @a pMachine to the base-class. */
[98491]451 UIIndicatorUSB(UIMachine *pMachine)
452 : UISessionStateStatusBarIndicator(IndicatorType_USB, pMachine)
[52220]453 {
454 /* Assign state-icons: */
455 setStateIcon(KDeviceActivity_Idle, UIIconPool::iconSet(":/usb_16px.png"));
456 setStateIcon(KDeviceActivity_Reading, UIIconPool::iconSet(":/usb_read_16px.png"));
457 setStateIcon(KDeviceActivity_Writing, UIIconPool::iconSet(":/usb_write_16px.png"));
458 setStateIcon(KDeviceActivity_Null, UIIconPool::iconSet(":/usb_disabled_16px.png"));
[99082]459 /* Configure connection: */
[99107]460 connect(m_pMachine, &UIMachine::sigMachineStateChange,
[99082]461 this, &UIIndicatorUSB::updateAppearance);
[99107]462 connect(m_pMachine, &UIMachine::sigUSBControllerChange,
[99094]463 this, &UIIndicatorUSB::updateAppearance);
[99107]464 connect(m_pMachine, &UIMachine::sigUSBDeviceStateChange,
[99094]465 this, &UIIndicatorUSB::updateAppearance);
[52220]466 /* Translate finally: */
[104290]467 sltRetranslateUI();
[52220]468 }
469
[98974]470protected slots:
[52220]471
472 /** Update routine. */
[98973]473 virtual void updateAppearance() RT_OVERRIDE
[52220]474 {
475 QString strFullData;
[98488]476 bool fUsbEnabled = false;
477 m_pMachine->acquireUsbStatusInfo(strFullData, fUsbEnabled);
[52220]478
[98569]479 /* Show/hide indicator if there are no attachments
480 * and parent is visible already: */
481 if ( parentWidget()
482 && parentWidget()->isVisible())
483 setVisible(fUsbEnabled);
[52220]484
485 /* Update tool-tip: */
[98966]486 if (!strFullData.isEmpty())
487 setToolTip(s_strTable.arg(strFullData));
[52220]488 /* Update indicator state: */
[98488]489 setState(fUsbEnabled ? KDeviceActivity_Idle : KDeviceActivity_Null);
[52220]490 }
491};
492
[66946]493
[51992]494/** UISessionStateStatusBarIndicator extension for Runtime UI: Shared-folders indicator. */
495class UIIndicatorSharedFolders : public UISessionStateStatusBarIndicator
[26637]496{
497 Q_OBJECT;
498
499public:
500
[98488]501 /** Constructs indicator passing @a pMachine to the base-class. */
[98491]502 UIIndicatorSharedFolders(UIMachine *pMachine)
503 : UISessionStateStatusBarIndicator(IndicatorType_SharedFolders, pMachine)
[26637]504 {
[51994]505 /* Assign state-icons: */
[51293]506 setStateIcon(KDeviceActivity_Idle, UIIconPool::iconSet(":/sf_16px.png"));
507 setStateIcon(KDeviceActivity_Reading, UIIconPool::iconSet(":/sf_read_16px.png"));
508 setStateIcon(KDeviceActivity_Writing, UIIconPool::iconSet(":/sf_write_16px.png"));
509 setStateIcon(KDeviceActivity_Null, UIIconPool::iconSet(":/sf_disabled_16px.png"));
[99082]510 /* Configure connection: */
[99107]511 connect(m_pMachine, &UIMachine::sigMachineStateChange,
[99082]512 this, &UIIndicatorSharedFolders::updateAppearance);
[99107]513 connect(m_pMachine, &UIMachine::sigSharedFolderChange,
[99094]514 this, &UIIndicatorSharedFolders::updateAppearance);
[51994]515 /* Translate finally: */
[104290]516 sltRetranslateUI();
[26637]517 }
[26758]518
[98974]519protected slots:
[51992]520
521 /** Update routine. */
[98973]522 virtual void updateAppearance() RT_OVERRIDE
[26758]523 {
[51994]524 QString strFullData;
[98488]525 bool fFoldersPresent = false;
526 m_pMachine->acquireSharedFoldersStatusInfo(strFullData, fFoldersPresent);
[26758]527
[51994]528 /* Update tool-tip: */
[98966]529 if (!strFullData.isEmpty())
530 setToolTip(s_strTable.arg(strFullData));
[51994]531 /* Update indicator state: */
[98488]532 setState(fFoldersPresent ? KDeviceActivity_Idle : KDeviceActivity_Null);
[26758]533 }
[26637]534};
535
[66946]536
[52112]537/** UISessionStateStatusBarIndicator extension for Runtime UI: Display indicator. */
538class UIIndicatorDisplay : public UISessionStateStatusBarIndicator
539{
540 Q_OBJECT;
541
542public:
543
[98977]544 /** Display states. */
545 enum DisplayState
546 {
547 DisplayState_Unavailable = 0,
548 DisplayState_Software = 1,
549 DisplayState_Hardware = 2
550 };
551
[98486]552 /** Constructs indicator passing @a pMachine to the base-class. */
[98491]553 UIIndicatorDisplay(UIMachine *pMachine)
554 : UISessionStateStatusBarIndicator(IndicatorType_Display, pMachine)
[52112]555 {
556 /* Assign state-icons: */
[98977]557 setStateIcon(DisplayState_Unavailable, UIIconPool::iconSet(":/display_software_disabled_16px.png"));
558 setStateIcon(DisplayState_Software, UIIconPool::iconSet(":/display_software_16px.png"));
559 setStateIcon(DisplayState_Hardware, UIIconPool::iconSet(":/display_hardware_16px.png"));
560 /* Configure connection: */
[99107]561 connect(m_pMachine, &UIMachine::sigMachineStateChange,
[98977]562 this, &UIIndicatorDisplay::updateAppearance);
[52112]563 /* Translate finally: */
[104290]564 sltRetranslateUI();
[52112]565 }
566
[98974]567protected slots:
[52112]568
569 /** Update routine. */
[98973]570 virtual void updateAppearance() RT_OVERRIDE
[52112]571 {
572 QString strFullData;
[98486]573 bool fAcceleration3D = false;
574 m_pMachine->acquireDisplayStatusInfo(strFullData, fAcceleration3D);
[52112]575
576 /* Update tool-tip: */
[98966]577 if (!strFullData.isEmpty())
578 setToolTip(s_strTable.arg(strFullData));
[98977]579 /* Update indicator state: */
580 DisplayState enmState = DisplayState_Unavailable;
[99082]581 if (m_pMachine->machineState() != KMachineState_Null)
[98977]582 {
583 if (!fAcceleration3D)
584 enmState = DisplayState_Software;
585 else
586 enmState = DisplayState_Hardware;
587 }
588 setState(enmState);
[52112]589 }
590};
591
[66946]592
[75291]593/** UISessionStateStatusBarIndicator extension for Runtime UI: Recording indicator. */
594class UIIndicatorRecording : public UISessionStateStatusBarIndicator
[26637]595{
596 Q_OBJECT;
[46810]597 Q_PROPERTY(double rotationAngleStart READ rotationAngleStart);
598 Q_PROPERTY(double rotationAngleFinal READ rotationAngleFinal);
599 Q_PROPERTY(double rotationAngle READ rotationAngle WRITE setRotationAngle);
[26637]600
[75291]601 /** Recording states. */
[98978]602 enum RecordingState
[26637]603 {
[98978]604 RecordingState_Unavailable = 0,
605 RecordingState_Disabled = 1,
606 RecordingState_Enabled = 2,
607 RecordingState_Paused = 3
[46582]608 };
[26758]609
[51992]610public:
611
[98489]612 /** Constructs indicator passing @a pMachine to the base-class. */
[98491]613 UIIndicatorRecording(UIMachine *pMachine)
614 : UISessionStateStatusBarIndicator(IndicatorType_Recording, pMachine)
[46810]615 , m_pAnimation(0)
616 , m_dRotationAngle(0)
[46582]617 {
[51994]618 /* Assign state-icons: */
[98978]619 setStateIcon(RecordingState_Unavailable, UIIconPool::iconSet(":/video_capture_disabled_16px.png"));
620 setStateIcon(RecordingState_Disabled, UIIconPool::iconSet(":/video_capture_16px.png"));
621 setStateIcon(RecordingState_Enabled, UIIconPool::iconSet(":/movie_reel_16px.png"));
622 setStateIcon(RecordingState_Paused, UIIconPool::iconSet(":/movie_reel_16px.png"));
623 /* Configure connection: */
[99107]624 connect(m_pMachine, &UIMachine::sigMachineStateChange,
[98978]625 this, &UIIndicatorRecording::updateAppearance);
[99107]626 connect(m_pMachine, &UIMachine::sigRecordingChange,
[99096]627 this, &UIIndicatorRecording::updateAppearance);
[51994]628 /* Create *enabled* state animation: */
[46810]629 m_pAnimation = UIAnimationLoop::installAnimationLoop(this, "rotationAngle",
[98978]630 "rotationAngleStart", "rotationAngleFinal",
631 1000);
[46582]632 /* Translate finally: */
[104290]633 sltRetranslateUI();
[26758]634 }
635
[98973]636protected:
[46582]637
[98973]638 /** Handles paint @a pEvent. */
639 virtual void paintEvent(QPaintEvent *pEvent) RT_OVERRIDE
[26758]640 {
[46810]641 /* Call to base-class: */
[98973]642 UISessionStateStatusBarIndicator::paintEvent(pEvent);
[26758]643
[46810]644 /* Create new painter: */
645 QPainter painter(this);
646 /* Configure painter for *enabled* state: */
[98978]647 if (state() == RecordingState_Enabled)
[46810]648 {
[46811]649 /* Configure painter for smooth animation: */
650 painter.setRenderHint(QPainter::Antialiasing);
651 painter.setRenderHint(QPainter::SmoothPixmapTransform);
[46810]652 /* Shift rotation origin according pixmap center: */
653 painter.translate(height() / 2, height() / 2);
654 /* Rotate painter: */
655 painter.rotate(rotationAngle());
656 /* Unshift rotation origin according pixmap center: */
657 painter.translate(- height() / 2, - height() / 2);
658 }
659 /* Draw contents: */
660 drawContents(&painter);
661 }
662
[98974]663protected slots:
664
[51992]665 /** Update routine. */
[98973]666 virtual void updateAppearance() RT_OVERRIDE
[51992]667 {
[98489]668 QString strFullData;
669 bool fRecordingEnabled = false;
670 bool fMachinePaused = false;
671 m_pMachine->acquireRecordingStatusInfo(strFullData, fRecordingEnabled, fMachinePaused);
[51992]672
[98489]673 /* Update tool-tip: */
[98966]674 if (!strFullData.isEmpty())
675 setToolTip(s_strTable.arg(strFullData));
[98489]676 /* Set initial indicator state: */
[98978]677 RecordingState enmState = RecordingState_Unavailable;
[99082]678 if (m_pMachine->machineState() != KMachineState_Null)
[98978]679 {
680 if (!fRecordingEnabled)
681 enmState = RecordingState_Disabled;
682 else if (!fMachinePaused)
683 enmState = RecordingState_Enabled;
684 else
685 enmState = RecordingState_Paused;
686 }
687 setState(enmState);
[51992]688 }
689
[98973]690private slots:
691
692 /** Handles state change. */
[103977]693 void setState(int iState) RT_OVERRIDE
[98973]694 {
695 /* Update animation state: */
696 switch (iState)
697 {
[98978]698 case RecordingState_Disabled:
[98973]699 m_pAnimation->stop();
700 m_dRotationAngle = 0;
701 break;
[98978]702 case RecordingState_Enabled:
[98973]703 m_pAnimation->start();
704 break;
[98978]705 case RecordingState_Paused:
[98973]706 m_pAnimation->stop();
707 break;
708 default:
709 break;
710 }
711 /* Call to base-class: */
712 QIStateStatusBarIndicator::setState(iState);
713 }
714
715private:
716
[51992]717 /** Returns rotation start angle. */
[46810]718 double rotationAngleStart() const { return 0; }
[51992]719 /** Returns rotation finish angle. */
[46810]720 double rotationAngleFinal() const { return 360; }
[51992]721 /** Returns current rotation angle. */
[46810]722 double rotationAngle() const { return m_dRotationAngle; }
[51992]723 /** Defines current rotation angle. */
[46810]724 void setRotationAngle(double dRotationAngle) { m_dRotationAngle = dRotationAngle; update(); }
725
[51992]726 /** Holds the rotation animation instance. */
[46810]727 UIAnimationLoop *m_pAnimation;
[51992]728 /** Holds current rotation angle. */
[98489]729 double m_dRotationAngle;
[26758]730};
731
[66946]732
[51992]733/** UISessionStateStatusBarIndicator extension for Runtime UI: Features indicator. */
734class UIIndicatorFeatures : public UISessionStateStatusBarIndicator
[26758]735{
736 Q_OBJECT;
737
738public:
739
[98490]740 /** Constructs indicator passing @a pMachine to the base-class. */
[98491]741 UIIndicatorFeatures(UIMachine *pMachine)
742 : UISessionStateStatusBarIndicator(IndicatorType_Features, pMachine)
[98602]743 , m_uEffectiveCPULoad(0)
[26758]744 {
[51994]745 /* Assign state-icons: */
[98490]746 /** @todo The vtx_amdv_disabled_16px.png icon isn't really approprate anymore (no raw-mode),
747 * might want to get something different for KVMExecutionEngine_Emulated or reuse the
748 * vm_execution_engine_native_api_16px.png one... @bugref{9898} */
[72329]749 setStateIcon(KVMExecutionEngine_NotSet, UIIconPool::iconSet(":/vtx_amdv_disabled_16px.png"));
[103085]750 setStateIcon(KVMExecutionEngine_Interpreter, UIIconPool::iconSet(":/vtx_amdv_disabled_16px.png"));
751 setStateIcon(KVMExecutionEngine_Recompiler, UIIconPool::iconSet(":/vtx_amdv_disabled_16px.png"));
[72329]752 setStateIcon(KVMExecutionEngine_HwVirt, UIIconPool::iconSet(":/vtx_amdv_16px.png"));
[72342]753 setStateIcon(KVMExecutionEngine_NativeApi, UIIconPool::iconSet(":/vm_execution_engine_native_api_16px.png"));
[99097]754 /* Configure connection: */
[98385]755 connect(m_pMachine, &UIMachine::sigMachineStateChange,
[80652]756 this, &UIIndicatorFeatures::sltHandleMachineStateChange);
[99107]757 connect(m_pMachine, &UIMachine::sigInitialized,
758 this, &UIIndicatorFeatures::updateAppearance);
[99097]759 connect(m_pMachine, &UIMachine::sigCPUExecutionCapChange,
760 this, &UIIndicatorFeatures::updateAppearance);
761 /* Configure CPU load update timer: */
[80206]762 m_pTimerAutoUpdate = new QTimer(this);
763 if (m_pTimerAutoUpdate)
764 {
[98973]765 connect(m_pTimerAutoUpdate, &QTimer::timeout,
766 this, &UIIndicatorFeatures::sltHandleTimeout);
[80206]767 /* Start the timer immediately if the machine is running: */
768 sltHandleMachineStateChange();
769 }
[51994]770 /* Translate finally: */
[104290]771 sltRetranslateUI();
[26637]772 }
[26758]773
[80206]774protected:
775
[98490]776 /** Handles paint @a pEvent. */
[93990]777 virtual void paintEvent(QPaintEvent *pEvent) RT_OVERRIDE
[80206]778 {
[98973]779 /* Call to base-class: */
[80206]780 UISessionStateStatusBarIndicator::paintEvent(pEvent);
[98973]781
782 /* Create new painter: */
[80206]783 QPainter painter(this);
[101385]784
785 /* Be a paranoid: */
786 ulong uCPU = qMin(m_uEffectiveCPULoad, static_cast<ulong>(100));
787
788 int iBorderThickness = 1;
789 /** Draw a black rectangle as background to the right hand side of 'this'.
790 * A smaller and colored rectangle will be drawn on top of this: **/
791 QPoint topLeftOut(0.76 * width() ,0);
792 QPoint bottomRightOut(width() - 1, height() - 1);
793 QRect outRect(topLeftOut, bottomRightOut);
794
[80206]795 painter.setPen(Qt::NoPen);
[101385]796 painter.setBrush(Qt::black);
[80209]797 painter.drawRect(outRect);
[101385]798
799 /* Draw a colored rectangle. Its color and height is dynamically computed from CPU usage: */
800 int inFullHeight = outRect.height() - 2 * iBorderThickness;
801 int inWidth = outRect.width() - 2 * iBorderThickness;
802 int inHeight = inFullHeight * uCPU / 100.;
803 QPoint topLeftIn(topLeftOut.x() + iBorderThickness,
804 topLeftOut.y() + iBorderThickness + (inFullHeight - inHeight));
805
806 QRect inRect(topLeftIn, QSize(inWidth, inHeight));
807 painter.setPen(Qt::NoPen);
808
809 /* Compute color as HSV: */
810 int iH = 120 * (1 - uCPU / 100.);
811 QColor fillColor;
812 fillColor.setHsv(iH, 255 /*saturation */, 255 /* value */);
813
814 painter.setBrush(fillColor);
815 painter.drawRect(inRect);
[80206]816 }
817
[98974]818protected slots:
819
[98973]820 /** Update routine. */
821 virtual void updateAppearance() RT_OVERRIDE
822 {
823 QString strFullData;
824 KVMExecutionEngine enmEngine = KVMExecutionEngine_NotSet;
825 m_pMachine->acquireFeaturesStatusInfo(strFullData, enmEngine);
826
827 /* Update tool-tip: */
828 if (!strFullData.isEmpty())
829 setToolTip(s_strTable.arg(strFullData));
830 /* Update indicator state: */
831 setState(enmEngine);
832 }
833
[80206]834private slots:
835
836 /** Updates auto-update timer depending on machine state. */
837 void sltHandleMachineStateChange()
838 {
[99097]839 /* Update appearance first of all: */
840 updateAppearance();
841
842 /* Start or stop CPU load update timer: */
[98432]843 if (m_pMachine->machineState() == KMachineState_Running)
[80206]844 m_pTimerAutoUpdate->start(1000);
[99097]845 else
846 m_pTimerAutoUpdate->stop();
[80206]847 }
848
[98490]849 /** Handles timer timeout with CPU load percentage update. */
850 void sltHandleTimeout()
[80206]851 {
[98602]852 m_pMachine->acquireEffectiveCPULoad(m_uEffectiveCPULoad);
[80206]853 update();
854 }
855
[51992]856private:
857
[98490]858 /** Holds the auto-update timer instance. */
[80206]859 QTimer *m_pTimerAutoUpdate;
[98490]860
[101385]861 /** Holds the effective CPU load. Expected to be in range [0, 100] */
[98602]862 ulong m_uEffectiveCPULoad;
[26637]863};
864
[66946]865
[51992]866/** UISessionStateStatusBarIndicator extension for Runtime UI: Mouse indicator. */
867class UIIndicatorMouse : public UISessionStateStatusBarIndicator
[26637]868{
869 Q_OBJECT;
870
871public:
872
[98490]873 /** Constructor, using @a pMachine for state-update routine. */
[98491]874 UIIndicatorMouse(UIMachine *pMachine)
875 : UISessionStateStatusBarIndicator(IndicatorType_Mouse, pMachine)
[26637]876 {
[51994]877 /* Assign state-icons: */
[51293]878 setStateIcon(0, UIIconPool::iconSet(":/mouse_disabled_16px.png"));
879 setStateIcon(1, UIIconPool::iconSet(":/mouse_16px.png"));
880 setStateIcon(2, UIIconPool::iconSet(":/mouse_seamless_16px.png"));
881 setStateIcon(3, UIIconPool::iconSet(":/mouse_can_seamless_16px.png"));
882 setStateIcon(4, UIIconPool::iconSet(":/mouse_can_seamless_uncaptured_16px.png"));
[52014]883 /* Configure connection: */
[98379]884 connect(m_pMachine, &UIMachine::sigMouseStateChange,
[101563]885 this, static_cast<void(UIIndicatorMouse::*)(int)>(&UIIndicatorMouse::setState)); // us to blame ..
[51994]886 /* Translate finally: */
[104290]887 sltRetranslateUI();
[26637]888 }
[26758]889
[98974]890protected slots:
[26758]891
[65255]892 /** Update routine. */
[98973]893 virtual void updateAppearance() RT_OVERRIDE
[51992]894 {
[66946]895 const QString strToolTip = QApplication::translate("UIIndicatorsPool",
896 "Indicates whether the host mouse pointer is "
897 "captured by the guest OS:%1", "Mouse tooltip");
898 QString strFullData;
899 strFullData += s_strTableRow3
900 .arg(QString("<img src=:/mouse_disabled_16px.png/>"))
901 .arg(QApplication::translate("UIIndicatorsPool", "pointer is not captured", "Mouse tooltip"));
902 strFullData += s_strTableRow3
903 .arg(QString("<img src=:/mouse_16px.png/>"))
904 .arg(QApplication::translate("UIIndicatorsPool", "pointer is captured", "Mouse tooltip"));
905 strFullData += s_strTableRow3
906 .arg(QString("<img src=:/mouse_seamless_16px.png/>"))
907 .arg(QApplication::translate("UIIndicatorsPool", "mouse integration (MI) is On", "Mouse tooltip"));
908 strFullData += s_strTableRow3
909 .arg(QString("<img src=:/mouse_can_seamless_16px.png/>"))
910 .arg(QApplication::translate("UIIndicatorsPool", "MI is Off, pointer is captured", "Mouse tooltip"));
911 strFullData += s_strTableRow3
912 .arg(QString("<img src=:/mouse_can_seamless_uncaptured_16px.png/>"))
913 .arg(QApplication::translate("UIIndicatorsPool", "MI is Off, pointer is not captured", "Mouse tooltip"));
914 strFullData = s_strTable.arg(strFullData);
915 strFullData += QApplication::translate("UIIndicatorsPool",
916 "Note that the mouse integration feature requires Guest "
917 "Additions to be installed in the guest OS.", "Mouse tooltip");
918
919 /* Update tool-tip: */
920 setToolTip(strToolTip.arg(strFullData));
[51992]921 }
[98973]922
923private slots:
924
925 /** Handles state change. */
[103977]926 void setState(int iState) RT_OVERRIDE
[98973]927 {
928 if ((iState & UIMouseStateType_MouseAbsoluteDisabled) &&
929 (iState & UIMouseStateType_MouseAbsolute) &&
930 !(iState & UIMouseStateType_MouseCaptured))
931 {
932 QIStateStatusBarIndicator::setState(4);
933 }
934 else
935 {
936 QIStateStatusBarIndicator::setState(iState & (UIMouseStateType_MouseAbsolute | UIMouseStateType_MouseCaptured));
937 }
938 }
[26637]939};
940
[51992]941/** UISessionStateStatusBarIndicator extension for Runtime UI: Keyboard indicator. */
942class UIIndicatorKeyboard : public UISessionStateStatusBarIndicator
[26637]943{
944 Q_OBJECT;
945
946public:
947
[98490]948 /** Constructor, using @a pMachine for state-update routine. */
[98491]949 UIIndicatorKeyboard(UIMachine *pMachine)
950 : UISessionStateStatusBarIndicator(IndicatorType_Keyboard, pMachine)
[26637]951 {
[51994]952 /* Assign state-icons: */
[98984]953 setStateIcon(0, UIIconPool::iconSet(":/hostkey_disabled_16px.png"));
954 setStateIcon(1, UIIconPool::iconSet(":/hostkey_16px.png"));
955 setStateIcon(3, UIIconPool::iconSet(":/hostkey_captured_16px.png"));
956 setStateIcon(5, UIIconPool::iconSet(":/hostkey_pressed_16px.png"));
957 setStateIcon(7, UIIconPool::iconSet(":/hostkey_captured_pressed_16px.png"));
958 setStateIcon(9, UIIconPool::iconSet(":/hostkey_checked_16px.png"));
959 setStateIcon(11, UIIconPool::iconSet(":/hostkey_captured_checked_16px.png"));
960 setStateIcon(13, UIIconPool::iconSet(":/hostkey_pressed_checked_16px.png"));
961 setStateIcon(15, UIIconPool::iconSet(":/hostkey_captured_pressed_checked_16px.png"));
[52014]962 /* Configure connection: */
[99107]963 connect(m_pMachine, &UIMachine::sigKeyboardStateChange,
[101563]964 this, static_cast<void(UIIndicatorKeyboard::*)(int)>(&UIIndicatorKeyboard::setState)); // us to blame ..
[51994]965 /* Translate finally: */
[104290]966 sltRetranslateUI();
[26637]967 }
[26758]968
[98974]969protected slots:
[51992]970
[65255]971 /** Update routine. */
[98973]972 virtual void updateAppearance() RT_OVERRIDE
[26758]973 {
[66946]974 const QString strToolTip = QApplication::translate("UIIndicatorsPool",
975 "Indicates whether the host keyboard is "
976 "captured by the guest OS:%1", "Keyboard tooltip");
977 QString strFullData;
978 strFullData += s_strTableRow3
979 .arg(QString("<img src=:/hostkey_16px.png/>"))
980 .arg(QApplication::translate("UIIndicatorsPool", "keyboard is not captured", "Keyboard tooltip"));
981 strFullData += s_strTableRow3
982 .arg(QString("<img src=:/hostkey_captured_16px.png/>"))
983 .arg(QApplication::translate("UIIndicatorsPool", "keyboard is captured", "Keyboard tooltip"));
984 strFullData = s_strTable.arg(strFullData);
985
986 /* Update tool-tip: */
987 setToolTip(strToolTip.arg(strFullData));
[26758]988 }
[26637]989};
990
[51992]991/** QITextStatusBarIndicator extension for Runtime UI: Keyboard-extension indicator. */
[104290]992class UIIndicatorKeyboardExtension : public QITextStatusBarIndicator
[26637]993{
[51992]994 Q_OBJECT;
995
996public:
997
998 /** Constructor. */
999 UIIndicatorKeyboardExtension()
1000 {
1001 /* Make sure host-combination label will be updated: */
[80652]1002 connect(gEDataManager, &UIExtraDataManager::sigRuntimeUIHostKeyCombinationChange,
1003 this, &UIIndicatorKeyboardExtension::sltUpdateAppearance);
[51992]1004 /* Translate finally: */
[104290]1005 sltRetranslateUI();
1006 connect(&translationEventListener(), &UITranslationEventListener::sigRetranslateUI,
1007 this, &UIIndicatorKeyboardExtension::sltRetranslateUI);
[51992]1008 }
1009
1010public slots:
1011
1012 /** Update routine. */
1013 void sltUpdateAppearance()
1014 {
[66569]1015 setText(UIHostCombo::toReadableString(gEDataManager->hostKeyCombination()));
[51992]1016 }
1017
[104290]1018private slots:
[51992]1019
1020 /** Retranslation routine. */
[104290]1021 void sltRetranslateUI()
[51992]1022 {
1023 sltUpdateAppearance();
1024 setToolTip(QApplication::translate("UIMachineWindowNormal",
1025 "Shows the currently assigned Host key.<br>"
1026 "This key, when pressed alone, toggles the keyboard and mouse "
1027 "capture state. It can also be used in combination with other keys "
1028 "to quickly perform actions from the main menu."));
1029 }
1030};
1031
1032
[98491]1033UIIndicatorsPool::UIIndicatorsPool(UIMachine *pMachine, QWidget *pParent /* = 0 */)
[51992]1034 : QWidget(pParent)
[98375]1035 , m_pMachine(pMachine)
[52100]1036 , m_fEnabled(false)
[98491]1037 , m_pMainLayout(0)
[51992]1038 , m_pTimerAutoUpdate(0)
1039{
[46677]1040 prepare();
[26637]1041}
1042
1043UIIndicatorsPool::~UIIndicatorsPool()
1044{
[46677]1045 cleanup();
[26637]1046}
1047
[51992]1048void UIIndicatorsPool::updateAppearance(IndicatorType indicatorType)
[26637]1049{
[51992]1050 /* Skip missed indicators: */
1051 if (!m_pool.contains(indicatorType))
1052 return;
1053
1054 /* Get indicator: */
1055 QIStatusBarIndicator *pIndicator = m_pool.value(indicatorType);
1056
1057 /* Assert indicators with NO appearance: */
1058 UISessionStateStatusBarIndicator *pSessionStateIndicator =
1059 qobject_cast<UISessionStateStatusBarIndicator*>(pIndicator);
1060 AssertPtrReturnVoid(pSessionStateIndicator);
1061
1062 /* Update indicator appearance: */
1063 pSessionStateIndicator->updateAppearance();
[46677]1064}
1065
[51992]1066void UIIndicatorsPool::setAutoUpdateIndicatorStates(bool fEnabled)
1067{
1068 /* Make sure auto-update timer exists: */
1069 AssertPtrReturnVoid(m_pTimerAutoUpdate);
1070
1071 /* Start/stop timer: */
1072 if (fEnabled)
1073 m_pTimerAutoUpdate->start(100);
1074 else
1075 m_pTimerAutoUpdate->stop();
1076}
1077
[75645]1078QPoint UIIndicatorsPool::mapIndicatorPositionToGlobal(IndicatorType enmIndicatorType, const QPoint &indicatorPosition)
1079{
1080 if (m_pool.contains(enmIndicatorType))
1081 return m_pool.value(enmIndicatorType)->mapToGlobal(indicatorPosition);
1082 return QPoint(0, 0);
1083}
1084
[74942]1085void UIIndicatorsPool::sltHandleConfigurationChange(const QUuid &uMachineID)
[51995]1086{
[53320]1087 /* Skip unrelated machine IDs: */
[79365]1088 if (uiCommon().managedVMUuid() != uMachineID)
[53320]1089 return;
1090
[51995]1091 /* Update pool: */
1092 updatePool();
1093}
1094
[51992]1095void UIIndicatorsPool::sltAutoUpdateIndicatorStates()
1096{
[52385]1097 /* We should update states for following indicators: */
1098 QVector<KDeviceType> deviceTypes;
[51992]1099 if (m_pool.contains(IndicatorType_HardDisks))
[52319]1100 deviceTypes.append(KDeviceType_HardDisk);
[51992]1101 if (m_pool.contains(IndicatorType_OpticalDisks))
[52319]1102 deviceTypes.append(KDeviceType_DVD);
[51992]1103 if (m_pool.contains(IndicatorType_FloppyDisks))
[52319]1104 deviceTypes.append(KDeviceType_Floppy);
[51992]1105 if (m_pool.contains(IndicatorType_USB))
[52319]1106 deviceTypes.append(KDeviceType_USB);
[51992]1107 if (m_pool.contains(IndicatorType_Network))
[52319]1108 deviceTypes.append(KDeviceType_Network);
[51992]1109 if (m_pool.contains(IndicatorType_SharedFolders))
[52319]1110 deviceTypes.append(KDeviceType_SharedFolder);
[52112]1111 if (m_pool.contains(IndicatorType_Display))
[52319]1112 deviceTypes.append(KDeviceType_Graphics3D);
1113
[98482]1114 /* Acquire current device states from the machine: */
1115 QVector<KDeviceActivity> states;
1116 m_pMachine->acquireDeviceActivity(deviceTypes, states);
[52319]1117
[52385]1118 /* Update indicators with the acquired states: */
1119 for (int iIndicator = 0; iIndicator < states.size(); ++iIndicator)
[52319]1120 {
[52385]1121 QIStatusBarIndicator *pIndicator = 0;
1122 switch (deviceTypes[iIndicator])
[52319]1123 {
[52385]1124 case KDeviceType_HardDisk: pIndicator = m_pool.value(IndicatorType_HardDisks); break;
1125 case KDeviceType_DVD: pIndicator = m_pool.value(IndicatorType_OpticalDisks); break;
1126 case KDeviceType_Floppy: pIndicator = m_pool.value(IndicatorType_FloppyDisks); break;
1127 case KDeviceType_USB: pIndicator = m_pool.value(IndicatorType_USB); break;
1128 case KDeviceType_Network: pIndicator = m_pool.value(IndicatorType_Network); break;
1129 case KDeviceType_SharedFolder: pIndicator = m_pool.value(IndicatorType_SharedFolders); break;
1130 case KDeviceType_Graphics3D: pIndicator = m_pool.value(IndicatorType_Display); break;
1131 default: AssertFailed(); break;
[52319]1132 }
1133 if (pIndicator)
[52385]1134 updateIndicatorStateForDevice(pIndicator, states[iIndicator]);
[52319]1135 }
[51992]1136}
1137
1138void UIIndicatorsPool::sltContextMenuRequest(QIStatusBarIndicator *pIndicator, QContextMenuEvent *pEvent)
1139{
1140 /* If that is one of pool indicators: */
1141 foreach (IndicatorType indicatorType, m_pool.keys())
1142 if (m_pool[indicatorType] == pIndicator)
1143 {
1144 /* Notify listener: */
[75645]1145 emit sigContextMenuRequest(indicatorType, pEvent->pos());
[51992]1146 return;
1147 }
1148}
1149
[46677]1150void UIIndicatorsPool::prepare()
1151{
[51992]1152 /* Prepare connections: */
1153 prepareConnections();
1154 /* Prepare contents: */
1155 prepareContents();
1156 /* Prepare auto-update timer: */
1157 prepareUpdateTimer();
1158}
[46686]1159
[51992]1160void UIIndicatorsPool::prepareConnections()
1161{
1162 /* Listen for the status-bar configuration changes: */
[80652]1163 connect(gEDataManager, &UIExtraDataManager::sigStatusBarConfigurationChange,
1164 this, &UIIndicatorsPool::sltHandleConfigurationChange);
[51992]1165}
1166
1167void UIIndicatorsPool::prepareContents()
1168{
1169 /* Create main-layout: */
1170 m_pMainLayout = new QHBoxLayout(this);
1171 AssertPtrReturnVoid(m_pMainLayout);
[26637]1172 {
[51992]1173 /* Configure main-layout: */
1174 m_pMainLayout->setContentsMargins(0, 0, 0, 0);
[70523]1175#ifdef VBOX_WS_MAC
1176 m_pMainLayout->setSpacing(5);
1177#else
1178 m_pMainLayout->setSpacing(qApp->style()->pixelMetric(QStyle::PM_LayoutHorizontalSpacing) / 2);
1179#endif
[51992]1180 /* Update pool: */
1181 updatePool();
1182 }
1183}
[46686]1184
[51992]1185void UIIndicatorsPool::prepareUpdateTimer()
1186{
1187 /* Create auto-update timer: */
1188 m_pTimerAutoUpdate = new QTimer(this);
1189 AssertPtrReturnVoid(m_pTimerAutoUpdate);
1190 {
1191 /* Configure auto-update timer: */
[80652]1192 connect(m_pTimerAutoUpdate, &QTimer::timeout,
1193 this, &UIIndicatorsPool::sltAutoUpdateIndicatorStates);
[51992]1194 setAutoUpdateIndicatorStates(true);
1195 }
1196}
1197
1198void UIIndicatorsPool::updatePool()
1199{
[52100]1200 /* Acquire status-bar availability: */
[79365]1201 m_fEnabled = gEDataManager->statusBarEnabled(uiCommon().managedVMUuid());
[52100]1202 /* If status-bar is not enabled: */
1203 if (!m_fEnabled)
1204 {
1205 /* Remove all indicators: */
1206 while (!m_pool.isEmpty())
1207 {
1208 const IndicatorType firstType = m_pool.keys().first();
1209 delete m_pool.value(firstType);
1210 m_pool.remove(firstType);
1211 }
1212 /* And return: */
1213 return;
1214 }
1215
1216 /* Acquire status-bar restrictions: */
[79365]1217 m_restrictions = gEDataManager->restrictedStatusBarIndicators(uiCommon().managedVMUuid());
[95808]1218 /* Make sure 'Recording' is restricted as well if no features supported: */
1219 if ( !m_restrictions.contains(IndicatorType_Recording)
1220 && !uiCommon().supportedRecordingFeatures())
1221 m_restrictions << IndicatorType_Recording;
1222
[52100]1223 /* Remove restricted indicators: */
1224 foreach (const IndicatorType &indicatorType, m_restrictions)
1225 {
1226 if (m_pool.contains(indicatorType))
1227 {
1228 delete m_pool.value(indicatorType);
1229 m_pool.remove(indicatorType);
1230 }
1231 }
1232
1233 /* Acquire status-bar order: */
[79365]1234 m_order = gEDataManager->statusBarIndicatorOrder(uiCommon().managedVMUuid());
[52035]1235 /* Make sure the order is complete taking restrictions into account: */
[51992]1236 for (int iType = IndicatorType_Invalid; iType < IndicatorType_Max; ++iType)
1237 {
[52035]1238 /* Get iterated type: */
1239 IndicatorType type = (IndicatorType)iType;
1240 /* Skip invalid type: */
1241 if (type == IndicatorType_Invalid)
1242 continue;
1243 /* Take restriction/presence into account: */
1244 bool fRestricted = m_restrictions.contains(type);
1245 bool fPresent = m_order.contains(type);
1246 if (fRestricted && fPresent)
1247 m_order.removeAll(type);
1248 else if (!fRestricted && !fPresent)
1249 m_order << type;
1250 }
[51992]1251
[52035]1252 /* Add/Update allowed indicators: */
1253 foreach (const IndicatorType &indicatorType, m_order)
1254 {
1255 /* Indicator exists: */
1256 if (m_pool.contains(indicatorType))
[51992]1257 {
[52035]1258 /* Get indicator: */
1259 QIStatusBarIndicator *pIndicator = m_pool.value(indicatorType);
1260 /* Make sure it have valid position: */
1261 const int iWantedIndex = indicatorPosition(indicatorType);
1262 const int iActualIndex = m_pMainLayout->indexOf(pIndicator);
1263 if (iActualIndex != iWantedIndex)
1264 {
1265 /* Re-inject indicator into main-layout at proper position: */
1266 m_pMainLayout->removeWidget(pIndicator);
1267 m_pMainLayout->insertWidget(iWantedIndex, pIndicator);
1268 }
1269 }
1270 /* Indicator missed: */
1271 else
1272 {
[51992]1273 /* Create indicator: */
1274 switch (indicatorType)
1275 {
[98491]1276 case IndicatorType_HardDisks: m_pool[indicatorType] = new UIIndicatorHardDrive(m_pMachine); break;
1277 case IndicatorType_OpticalDisks: m_pool[indicatorType] = new UIIndicatorOpticalDisks(m_pMachine); break;
1278 case IndicatorType_FloppyDisks: m_pool[indicatorType] = new UIIndicatorFloppyDisks(m_pMachine); break;
1279 case IndicatorType_Audio: m_pool[indicatorType] = new UIIndicatorAudio(m_pMachine); break;
1280 case IndicatorType_Network: m_pool[indicatorType] = new UIIndicatorNetwork(m_pMachine); break;
1281 case IndicatorType_USB: m_pool[indicatorType] = new UIIndicatorUSB(m_pMachine); break;
1282 case IndicatorType_SharedFolders: m_pool[indicatorType] = new UIIndicatorSharedFolders(m_pMachine); break;
1283 case IndicatorType_Display: m_pool[indicatorType] = new UIIndicatorDisplay(m_pMachine); break;
1284 case IndicatorType_Recording: m_pool[indicatorType] = new UIIndicatorRecording(m_pMachine); break;
1285 case IndicatorType_Features: m_pool[indicatorType] = new UIIndicatorFeatures(m_pMachine); break;
1286 case IndicatorType_Mouse: m_pool[indicatorType] = new UIIndicatorMouse(m_pMachine); break;
1287 case IndicatorType_Keyboard: m_pool[indicatorType] = new UIIndicatorKeyboard(m_pMachine); break;
1288 case IndicatorType_KeyboardExtension: m_pool[indicatorType] = new UIIndicatorKeyboardExtension; break;
[51992]1289 default: break;
1290 }
1291 /* Configure indicator: */
[80652]1292 connect(m_pool.value(indicatorType), &QIStatusBarIndicator::sigContextMenuRequest,
1293 this, &UIIndicatorsPool::sltContextMenuRequest);
[52035]1294 /* Insert indicator into main-layout at proper position: */
[51992]1295 m_pMainLayout->insertWidget(indicatorPosition(indicatorType), m_pool.value(indicatorType));
1296 }
[26637]1297 }
1298}
1299
[51992]1300void UIIndicatorsPool::cleanupUpdateTimer()
1301{
1302 /* Destroy auto-update timer: */
1303 AssertPtrReturnVoid(m_pTimerAutoUpdate);
1304 {
1305 m_pTimerAutoUpdate->stop();
1306 delete m_pTimerAutoUpdate;
1307 m_pTimerAutoUpdate = 0;
1308 }
1309}
1310
1311void UIIndicatorsPool::cleanupContents()
1312{
1313 /* Cleanup indicators: */
1314 while (!m_pool.isEmpty())
1315 {
1316 const IndicatorType firstType = m_pool.keys().first();
1317 delete m_pool.value(firstType);
1318 m_pool.remove(firstType);
1319 }
1320}
1321
[46677]1322void UIIndicatorsPool::cleanup()
1323{
[51992]1324 /* Cleanup auto-update timer: */
1325 cleanupUpdateTimer();
1326 /* Cleanup indicators: */
1327 cleanupContents();
1328}
1329
[52658]1330void UIIndicatorsPool::contextMenuEvent(QContextMenuEvent *pEvent)
1331{
1332 /* Do not pass-through context menu events,
1333 * otherwise they will raise the underlying status-bar context-menu. */
1334 pEvent->accept();
1335}
1336
[51992]1337int UIIndicatorsPool::indicatorPosition(IndicatorType indicatorType) const
1338{
1339 int iPosition = 0;
[52035]1340 foreach (const IndicatorType &iteratedIndicatorType, m_order)
[51992]1341 if (iteratedIndicatorType == indicatorType)
1342 return iPosition;
1343 else
1344 ++iPosition;
1345 return iPosition;
1346}
1347
[98482]1348void UIIndicatorsPool::updateIndicatorStateForDevice(QIStatusBarIndicator *pIndicator, KDeviceActivity enmState)
[51992]1349{
1350 /* Assert indicators with NO state: */
1351 QIStateStatusBarIndicator *pStateIndicator = qobject_cast<QIStateStatusBarIndicator*>(pIndicator);
1352 AssertPtrReturnVoid(pStateIndicator);
1353
1354 /* Skip indicators with NULL state: */
1355 if (pStateIndicator->state() == KDeviceActivity_Null)
1356 return;
1357
1358 /* Paused VM have all indicator states set to IDLE: */
[98482]1359 if (m_pMachine->isPaused())
[46677]1360 {
[51992]1361 /* If current state differs from IDLE => set the IDLE one: */
1362 if (pStateIndicator->state() != KDeviceActivity_Idle)
1363 pStateIndicator->setState(KDeviceActivity_Idle);
[46677]1364 }
[51992]1365 else
1366 {
[52319]1367 /* If current state differs from actual => set the actual one: */
[98482]1368 if (pStateIndicator->state() != enmState)
1369 pStateIndicator->setState(enmState);
[51992]1370 }
[46677]1371}
1372
[26637]1373#include "UIIndicatorsPool.moc"
Note: See TracBrowser for help on using the repository browser.

© 2023 Oracle
ContactPrivacy policyTerms of Use