VirtualBox

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

Last change on this file was 104358, checked in by vboxsync, 4 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
Line 
1/* $Id: UIIndicatorsPool.cpp 104358 2024-04-18 05:33:40Z vboxsync $ */
2/** @file
3 * VBox Qt GUI - UIIndicatorsPool 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 <QAccessibleWidget>
31#include <QHBoxLayout>
32#include <QPainter>
33#include <QStyle>
34#include <QTimer>
35
36/* GUI includes: */
37#include "QIStatusBarIndicator.h"
38#include "UIAnimationFramework.h"
39#include "UICommon.h"
40#include "UIConverter.h"
41#include "UIExtraDataManager.h"
42#include "UIHostComboEditor.h"
43#include "UIIconPool.h"
44#include "UIIndicatorsPool.h"
45#include "UIMachine.h"
46#include "UITranslationEventListener.h"
47
48
49/** QIStateStatusBarIndicator extension for Runtime UI. */
50class UISessionStateStatusBarIndicator : public QIStateStatusBarIndicator
51{
52 Q_OBJECT;
53
54public:
55
56 /** Constructor which remembers passed @a session object. */
57 UISessionStateStatusBarIndicator(IndicatorType enmType, UIMachine *pMachine);
58
59 /** Returns the indicator type. */
60 IndicatorType type() const { return m_enmType; }
61
62 /** Returns the indicator description. */
63 virtual QString description() const { return m_strDescription; }
64
65public slots:
66
67 /** Abstract update routine. */
68 virtual void updateAppearance() = 0;
69
70protected slots:
71
72 /** Handles translation event. */
73 void sltRetranslateUI();
74
75protected:
76
77 /** Holds the indicator type. */
78 const IndicatorType m_enmType;
79
80 /** Holds the machine UI reference. */
81 UIMachine *m_pMachine;
82
83 /** Holds the indicator description. */
84 QString m_strDescription;
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;
96};
97
98
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
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. */
133 virtual QString text(QAccessible::Text /* enmTextRole */) const RT_OVERRIDE
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
149UISessionStateStatusBarIndicator::UISessionStateStatusBarIndicator(IndicatorType enmType, UIMachine *pMachine)
150 : m_enmType(enmType)
151 , m_pMachine(pMachine)
152{
153 /* Install UISessionStateStatusBarIndicator accessibility interface factory: */
154 QAccessible::installFactory(QIAccessibilityInterfaceForUISessionStateStatusBarIndicator::pFactory);
155 connect(&translationEventListener(), &UITranslationEventListener::sigRetranslateUI,
156 this, &UISessionStateStatusBarIndicator::sltRetranslateUI);
157}
158
159void UISessionStateStatusBarIndicator::sltRetranslateUI()
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
170/** UISessionStateStatusBarIndicator extension for Runtime UI: Hard-drive indicator. */
171class UIIndicatorHardDrive : public UISessionStateStatusBarIndicator
172{
173 Q_OBJECT;
174
175public:
176
177 /** Constructs indicator passing @a pMachine to the base-class. */
178 UIIndicatorHardDrive(UIMachine *pMachine)
179 : UISessionStateStatusBarIndicator(IndicatorType_HardDisks, pMachine)
180 {
181 /* Assign state-icons: */
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"));
186 /* Configure connection: */
187 connect(m_pMachine, &UIMachine::sigMachineStateChange,
188 this, &UIIndicatorHardDrive::updateAppearance);
189 connect(m_pMachine, &UIMachine::sigStorageDeviceChange,
190 this, &UIIndicatorHardDrive::updateAppearance);
191 connect(m_pMachine, &UIMachine::sigMediumChange,
192 this, &UIIndicatorHardDrive::updateAppearance);
193 /* Translate finally: */
194 sltRetranslateUI();
195 }
196
197protected slots:
198
199 /** Update routine. */
200 virtual void updateAppearance() RT_OVERRIDE
201 {
202 /* Acquire data: */
203 QString strFullData;
204 bool fAttachmentsPresent = false;
205 m_pMachine->acquireHardDiskStatusInfo(strFullData, fAttachmentsPresent);
206
207 /* Show/hide indicator if there are no attachments
208 * and parent is visible already: */
209 if ( parentWidget()
210 && parentWidget()->isVisible())
211 setVisible(fAttachmentsPresent);
212
213 /* Update tool-tip: */
214 if (!strFullData.isEmpty())
215 setToolTip(s_strTable.arg(strFullData));
216 /* Update indicator state: */
217 setState(fAttachmentsPresent ? KDeviceActivity_Idle : KDeviceActivity_Null);
218 }
219};
220
221
222/** UISessionStateStatusBarIndicator extension for Runtime UI: Optical-drive indicator. */
223class UIIndicatorOpticalDisks : public UISessionStateStatusBarIndicator
224{
225 Q_OBJECT;
226
227public:
228
229 /** Constructs indicator passing @a pMachine to the base-class. */
230 UIIndicatorOpticalDisks(UIMachine *pMachine)
231 : UISessionStateStatusBarIndicator(IndicatorType_OpticalDisks, pMachine)
232 {
233 /* Assign state-icons: */
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"));
238 /* Configure connection: */
239 connect(m_pMachine, &UIMachine::sigMachineStateChange,
240 this, &UIIndicatorOpticalDisks::updateAppearance);
241 connect(m_pMachine, &UIMachine::sigStorageDeviceChange,
242 this, &UIIndicatorOpticalDisks::updateAppearance);
243 connect(m_pMachine, &UIMachine::sigMediumChange,
244 this, &UIIndicatorOpticalDisks::updateAppearance);
245 /* Translate finally: */
246 sltRetranslateUI();
247 }
248
249protected slots:
250
251 /** Update routine. */
252 virtual void updateAppearance() RT_OVERRIDE
253 {
254 QString strFullData;
255 bool fAttachmentsPresent = false;
256 bool fAttachmentsMounted = false;
257 m_pMachine->acquireOpticalDiskStatusInfo(strFullData, fAttachmentsPresent, fAttachmentsMounted);
258
259 /* Show/hide indicator if there are no attachments
260 * and parent is visible already: */
261 if ( parentWidget()
262 && parentWidget()->isVisible())
263 setVisible(fAttachmentsPresent);
264
265 /* Update tool-tip: */
266 if (!strFullData.isEmpty())
267 setToolTip(s_strTable.arg(strFullData));
268 /* Update indicator state: */
269 setState(fAttachmentsMounted ? KDeviceActivity_Idle : KDeviceActivity_Null);
270 }
271};
272
273
274/** UISessionStateStatusBarIndicator extension for Runtime UI: Floppy-drive indicator. */
275class UIIndicatorFloppyDisks : public UISessionStateStatusBarIndicator
276{
277 Q_OBJECT;
278
279public:
280
281 /** Constructs indicator passing @a pMachine to the base-class. */
282 UIIndicatorFloppyDisks(UIMachine *pMachine)
283 : UISessionStateStatusBarIndicator(IndicatorType_FloppyDisks, pMachine)
284 {
285 /* Assign state-icons: */
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"));
290 /* Configure connection: */
291 connect(m_pMachine, &UIMachine::sigMachineStateChange,
292 this, &UIIndicatorFloppyDisks::updateAppearance);
293 connect(m_pMachine, &UIMachine::sigStorageDeviceChange,
294 this, &UIIndicatorFloppyDisks::updateAppearance);
295 connect(m_pMachine, &UIMachine::sigMediumChange,
296 this, &UIIndicatorFloppyDisks::updateAppearance);
297 /* Translate finally: */
298 sltRetranslateUI();
299 }
300
301protected slots:
302
303 /** Update routine. */
304 virtual void updateAppearance() RT_OVERRIDE
305 {
306 QString strFullData;
307 bool fAttachmentsPresent = false;
308 bool fAttachmentsMounted = false;
309 m_pMachine->acquireFloppyDiskStatusInfo(strFullData, fAttachmentsPresent, fAttachmentsMounted);
310
311 /* Show/hide indicator if there are no attachments
312 * and parent is visible already: */
313 if ( parentWidget()
314 && parentWidget()->isVisible())
315 setVisible(fAttachmentsPresent);
316
317 /* Update tool-tip: */
318 if (!strFullData.isEmpty())
319 setToolTip(s_strTable.arg(strFullData));
320 /* Update indicator state: */
321 setState(fAttachmentsMounted ? KDeviceActivity_Idle : KDeviceActivity_Null);
322 }
323};
324
325
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
342 /** Constructs indicator passing @a pMachine to the base-class. */
343 UIIndicatorAudio(UIMachine *pMachine)
344 : UISessionStateStatusBarIndicator(IndicatorType_Audio, pMachine)
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"));
351 /* Configure connection: */
352 connect(m_pMachine, &UIMachine::sigMachineStateChange,
353 this, &UIIndicatorAudio::updateAppearance);
354 connect(m_pMachine, &UIMachine::sigInitialized,
355 this, &UIIndicatorAudio::updateAppearance);
356 connect(m_pMachine, &UIMachine::sigAudioAdapterChange,
357 this, &UIIndicatorAudio::updateAppearance);
358 /* Translate finally: */
359 sltRetranslateUI();
360 }
361
362protected slots:
363
364 /** Update routine. */
365 virtual void updateAppearance() RT_OVERRIDE
366 {
367 QString strFullData;
368 bool fAudioEnabled = false;
369 bool fEnabledOutput = false;
370 bool fEnabledInput = false;
371 m_pMachine->acquireAudioStatusInfo(strFullData, fAudioEnabled, fEnabledOutput, fEnabledInput);
372
373 /* Show/hide indicator if there are no attachments
374 * and parent is visible already: */
375 if ( parentWidget()
376 && parentWidget()->isVisible())
377 setVisible(fAudioEnabled);
378
379 /* Update tool-tip: */
380 if (!strFullData.isEmpty())
381 setToolTip(s_strTable.arg(strFullData));
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);
389 }
390};
391
392
393/** UISessionStateStatusBarIndicator extension for Runtime UI: Network indicator. */
394class UIIndicatorNetwork : public UISessionStateStatusBarIndicator
395{
396 Q_OBJECT;
397
398public:
399
400 /** Constructs indicator passing @a pMachine to the base-class. */
401 UIIndicatorNetwork(UIMachine *pMachine)
402 : UISessionStateStatusBarIndicator(IndicatorType_Network, pMachine)
403 {
404 /* Assign state-icons: */
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"));
409 /* Configure connection: */
410 connect(m_pMachine, &UIMachine::sigMachineStateChange,
411 this, &UIIndicatorNetwork::updateAppearance);
412 connect(m_pMachine, &UIMachine::sigNetworkAdapterChange,
413 this, &UIIndicatorNetwork::updateAppearance);
414 /* Translate finally: */
415 sltRetranslateUI();
416 }
417
418protected slots:
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 }
440};
441
442
443/** UISessionStateStatusBarIndicator extension for Runtime UI: USB indicator. */
444class UIIndicatorUSB : public UISessionStateStatusBarIndicator
445{
446 Q_OBJECT;
447
448public:
449
450 /** Constructs indicator passing @a pMachine to the base-class. */
451 UIIndicatorUSB(UIMachine *pMachine)
452 : UISessionStateStatusBarIndicator(IndicatorType_USB, pMachine)
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"));
459 /* Configure connection: */
460 connect(m_pMachine, &UIMachine::sigMachineStateChange,
461 this, &UIIndicatorUSB::updateAppearance);
462 connect(m_pMachine, &UIMachine::sigUSBControllerChange,
463 this, &UIIndicatorUSB::updateAppearance);
464 connect(m_pMachine, &UIMachine::sigUSBDeviceStateChange,
465 this, &UIIndicatorUSB::updateAppearance);
466 /* Translate finally: */
467 sltRetranslateUI();
468 }
469
470protected slots:
471
472 /** Update routine. */
473 virtual void updateAppearance() RT_OVERRIDE
474 {
475 QString strFullData;
476 bool fUsbEnabled = false;
477 m_pMachine->acquireUsbStatusInfo(strFullData, fUsbEnabled);
478
479 /* Show/hide indicator if there are no attachments
480 * and parent is visible already: */
481 if ( parentWidget()
482 && parentWidget()->isVisible())
483 setVisible(fUsbEnabled);
484
485 /* Update tool-tip: */
486 if (!strFullData.isEmpty())
487 setToolTip(s_strTable.arg(strFullData));
488 /* Update indicator state: */
489 setState(fUsbEnabled ? KDeviceActivity_Idle : KDeviceActivity_Null);
490 }
491};
492
493
494/** UISessionStateStatusBarIndicator extension for Runtime UI: Shared-folders indicator. */
495class UIIndicatorSharedFolders : public UISessionStateStatusBarIndicator
496{
497 Q_OBJECT;
498
499public:
500
501 /** Constructs indicator passing @a pMachine to the base-class. */
502 UIIndicatorSharedFolders(UIMachine *pMachine)
503 : UISessionStateStatusBarIndicator(IndicatorType_SharedFolders, pMachine)
504 {
505 /* Assign state-icons: */
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"));
510 /* Configure connection: */
511 connect(m_pMachine, &UIMachine::sigMachineStateChange,
512 this, &UIIndicatorSharedFolders::updateAppearance);
513 connect(m_pMachine, &UIMachine::sigSharedFolderChange,
514 this, &UIIndicatorSharedFolders::updateAppearance);
515 /* Translate finally: */
516 sltRetranslateUI();
517 }
518
519protected slots:
520
521 /** Update routine. */
522 virtual void updateAppearance() RT_OVERRIDE
523 {
524 QString strFullData;
525 bool fFoldersPresent = false;
526 m_pMachine->acquireSharedFoldersStatusInfo(strFullData, fFoldersPresent);
527
528 /* Update tool-tip: */
529 if (!strFullData.isEmpty())
530 setToolTip(s_strTable.arg(strFullData));
531 /* Update indicator state: */
532 setState(fFoldersPresent ? KDeviceActivity_Idle : KDeviceActivity_Null);
533 }
534};
535
536
537/** UISessionStateStatusBarIndicator extension for Runtime UI: Display indicator. */
538class UIIndicatorDisplay : public UISessionStateStatusBarIndicator
539{
540 Q_OBJECT;
541
542public:
543
544 /** Display states. */
545 enum DisplayState
546 {
547 DisplayState_Unavailable = 0,
548 DisplayState_Software = 1,
549 DisplayState_Hardware = 2
550 };
551
552 /** Constructs indicator passing @a pMachine to the base-class. */
553 UIIndicatorDisplay(UIMachine *pMachine)
554 : UISessionStateStatusBarIndicator(IndicatorType_Display, pMachine)
555 {
556 /* Assign state-icons: */
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: */
561 connect(m_pMachine, &UIMachine::sigMachineStateChange,
562 this, &UIIndicatorDisplay::updateAppearance);
563 /* Translate finally: */
564 sltRetranslateUI();
565 }
566
567protected slots:
568
569 /** Update routine. */
570 virtual void updateAppearance() RT_OVERRIDE
571 {
572 QString strFullData;
573 bool fAcceleration3D = false;
574 m_pMachine->acquireDisplayStatusInfo(strFullData, fAcceleration3D);
575
576 /* Update tool-tip: */
577 if (!strFullData.isEmpty())
578 setToolTip(s_strTable.arg(strFullData));
579 /* Update indicator state: */
580 DisplayState enmState = DisplayState_Unavailable;
581 if (m_pMachine->machineState() != KMachineState_Null)
582 {
583 if (!fAcceleration3D)
584 enmState = DisplayState_Software;
585 else
586 enmState = DisplayState_Hardware;
587 }
588 setState(enmState);
589 }
590};
591
592
593/** UISessionStateStatusBarIndicator extension for Runtime UI: Recording indicator. */
594class UIIndicatorRecording : public UISessionStateStatusBarIndicator
595{
596 Q_OBJECT;
597 Q_PROPERTY(double rotationAngleStart READ rotationAngleStart);
598 Q_PROPERTY(double rotationAngleFinal READ rotationAngleFinal);
599 Q_PROPERTY(double rotationAngle READ rotationAngle WRITE setRotationAngle);
600
601 /** Recording states. */
602 enum RecordingState
603 {
604 RecordingState_Unavailable = 0,
605 RecordingState_Disabled = 1,
606 RecordingState_Enabled = 2,
607 RecordingState_Paused = 3
608 };
609
610public:
611
612 /** Constructs indicator passing @a pMachine to the base-class. */
613 UIIndicatorRecording(UIMachine *pMachine)
614 : UISessionStateStatusBarIndicator(IndicatorType_Recording, pMachine)
615 , m_pAnimation(0)
616 , m_dRotationAngle(0)
617 {
618 /* Assign state-icons: */
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: */
624 connect(m_pMachine, &UIMachine::sigMachineStateChange,
625 this, &UIIndicatorRecording::updateAppearance);
626 connect(m_pMachine, &UIMachine::sigRecordingChange,
627 this, &UIIndicatorRecording::updateAppearance);
628 /* Create *enabled* state animation: */
629 m_pAnimation = UIAnimationLoop::installAnimationLoop(this, "rotationAngle",
630 "rotationAngleStart", "rotationAngleFinal",
631 1000);
632 /* Translate finally: */
633 sltRetranslateUI();
634 }
635
636protected:
637
638 /** Handles paint @a pEvent. */
639 virtual void paintEvent(QPaintEvent *pEvent) RT_OVERRIDE
640 {
641 /* Call to base-class: */
642 UISessionStateStatusBarIndicator::paintEvent(pEvent);
643
644 /* Create new painter: */
645 QPainter painter(this);
646 /* Configure painter for *enabled* state: */
647 if (state() == RecordingState_Enabled)
648 {
649 /* Configure painter for smooth animation: */
650 painter.setRenderHint(QPainter::Antialiasing);
651 painter.setRenderHint(QPainter::SmoothPixmapTransform);
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
663protected slots:
664
665 /** Update routine. */
666 virtual void updateAppearance() RT_OVERRIDE
667 {
668 QString strFullData;
669 bool fRecordingEnabled = false;
670 bool fMachinePaused = false;
671 m_pMachine->acquireRecordingStatusInfo(strFullData, fRecordingEnabled, fMachinePaused);
672
673 /* Update tool-tip: */
674 if (!strFullData.isEmpty())
675 setToolTip(s_strTable.arg(strFullData));
676 /* Set initial indicator state: */
677 RecordingState enmState = RecordingState_Unavailable;
678 if (m_pMachine->machineState() != KMachineState_Null)
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);
688 }
689
690private slots:
691
692 /** Handles state change. */
693 void setState(int iState) RT_OVERRIDE
694 {
695 /* Update animation state: */
696 switch (iState)
697 {
698 case RecordingState_Disabled:
699 m_pAnimation->stop();
700 m_dRotationAngle = 0;
701 break;
702 case RecordingState_Enabled:
703 m_pAnimation->start();
704 break;
705 case RecordingState_Paused:
706 m_pAnimation->stop();
707 break;
708 default:
709 break;
710 }
711 /* Call to base-class: */
712 QIStateStatusBarIndicator::setState(iState);
713 }
714
715private:
716
717 /** Returns rotation start angle. */
718 double rotationAngleStart() const { return 0; }
719 /** Returns rotation finish angle. */
720 double rotationAngleFinal() const { return 360; }
721 /** Returns current rotation angle. */
722 double rotationAngle() const { return m_dRotationAngle; }
723 /** Defines current rotation angle. */
724 void setRotationAngle(double dRotationAngle) { m_dRotationAngle = dRotationAngle; update(); }
725
726 /** Holds the rotation animation instance. */
727 UIAnimationLoop *m_pAnimation;
728 /** Holds current rotation angle. */
729 double m_dRotationAngle;
730};
731
732
733/** UISessionStateStatusBarIndicator extension for Runtime UI: Features indicator. */
734class UIIndicatorFeatures : public UISessionStateStatusBarIndicator
735{
736 Q_OBJECT;
737
738public:
739
740 /** Constructs indicator passing @a pMachine to the base-class. */
741 UIIndicatorFeatures(UIMachine *pMachine)
742 : UISessionStateStatusBarIndicator(IndicatorType_Features, pMachine)
743 , m_uEffectiveCPULoad(0)
744 {
745 /* Assign state-icons: */
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} */
749 setStateIcon(KVMExecutionEngine_NotSet, UIIconPool::iconSet(":/vtx_amdv_disabled_16px.png"));
750 setStateIcon(KVMExecutionEngine_Interpreter, UIIconPool::iconSet(":/vtx_amdv_disabled_16px.png"));
751 setStateIcon(KVMExecutionEngine_Recompiler, UIIconPool::iconSet(":/vtx_amdv_disabled_16px.png"));
752 setStateIcon(KVMExecutionEngine_HwVirt, UIIconPool::iconSet(":/vtx_amdv_16px.png"));
753 setStateIcon(KVMExecutionEngine_NativeApi, UIIconPool::iconSet(":/vm_execution_engine_native_api_16px.png"));
754 /* Configure connection: */
755 connect(m_pMachine, &UIMachine::sigMachineStateChange,
756 this, &UIIndicatorFeatures::sltHandleMachineStateChange);
757 connect(m_pMachine, &UIMachine::sigInitialized,
758 this, &UIIndicatorFeatures::updateAppearance);
759 connect(m_pMachine, &UIMachine::sigCPUExecutionCapChange,
760 this, &UIIndicatorFeatures::updateAppearance);
761 /* Configure CPU load update timer: */
762 m_pTimerAutoUpdate = new QTimer(this);
763 if (m_pTimerAutoUpdate)
764 {
765 connect(m_pTimerAutoUpdate, &QTimer::timeout,
766 this, &UIIndicatorFeatures::sltHandleTimeout);
767 /* Start the timer immediately if the machine is running: */
768 sltHandleMachineStateChange();
769 }
770 /* Translate finally: */
771 sltRetranslateUI();
772 }
773
774protected:
775
776 /** Handles paint @a pEvent. */
777 virtual void paintEvent(QPaintEvent *pEvent) RT_OVERRIDE
778 {
779 /* Call to base-class: */
780 UISessionStateStatusBarIndicator::paintEvent(pEvent);
781
782 /* Create new painter: */
783 QPainter painter(this);
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
795 painter.setPen(Qt::NoPen);
796 painter.setBrush(Qt::black);
797 painter.drawRect(outRect);
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);
816 }
817
818protected slots:
819
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
834private slots:
835
836 /** Updates auto-update timer depending on machine state. */
837 void sltHandleMachineStateChange()
838 {
839 /* Update appearance first of all: */
840 updateAppearance();
841
842 /* Start or stop CPU load update timer: */
843 if (m_pMachine->machineState() == KMachineState_Running)
844 m_pTimerAutoUpdate->start(1000);
845 else
846 m_pTimerAutoUpdate->stop();
847 }
848
849 /** Handles timer timeout with CPU load percentage update. */
850 void sltHandleTimeout()
851 {
852 m_pMachine->acquireEffectiveCPULoad(m_uEffectiveCPULoad);
853 update();
854 }
855
856private:
857
858 /** Holds the auto-update timer instance. */
859 QTimer *m_pTimerAutoUpdate;
860
861 /** Holds the effective CPU load. Expected to be in range [0, 100] */
862 ulong m_uEffectiveCPULoad;
863};
864
865
866/** UISessionStateStatusBarIndicator extension for Runtime UI: Mouse indicator. */
867class UIIndicatorMouse : public UISessionStateStatusBarIndicator
868{
869 Q_OBJECT;
870
871public:
872
873 /** Constructor, using @a pMachine for state-update routine. */
874 UIIndicatorMouse(UIMachine *pMachine)
875 : UISessionStateStatusBarIndicator(IndicatorType_Mouse, pMachine)
876 {
877 /* Assign state-icons: */
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"));
883 /* Configure connection: */
884 connect(m_pMachine, &UIMachine::sigMouseStateChange,
885 this, static_cast<void(UIIndicatorMouse::*)(int)>(&UIIndicatorMouse::setState)); // us to blame ..
886 /* Translate finally: */
887 sltRetranslateUI();
888 }
889
890protected slots:
891
892 /** Update routine. */
893 virtual void updateAppearance() RT_OVERRIDE
894 {
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));
921 }
922
923private slots:
924
925 /** Handles state change. */
926 void setState(int iState) RT_OVERRIDE
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 }
939};
940
941/** UISessionStateStatusBarIndicator extension for Runtime UI: Keyboard indicator. */
942class UIIndicatorKeyboard : public UISessionStateStatusBarIndicator
943{
944 Q_OBJECT;
945
946public:
947
948 /** Constructor, using @a pMachine for state-update routine. */
949 UIIndicatorKeyboard(UIMachine *pMachine)
950 : UISessionStateStatusBarIndicator(IndicatorType_Keyboard, pMachine)
951 {
952 /* Assign state-icons: */
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"));
962 /* Configure connection: */
963 connect(m_pMachine, &UIMachine::sigKeyboardStateChange,
964 this, static_cast<void(UIIndicatorKeyboard::*)(int)>(&UIIndicatorKeyboard::setState)); // us to blame ..
965 /* Translate finally: */
966 sltRetranslateUI();
967 }
968
969protected slots:
970
971 /** Update routine. */
972 virtual void updateAppearance() RT_OVERRIDE
973 {
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));
988 }
989};
990
991/** QITextStatusBarIndicator extension for Runtime UI: Keyboard-extension indicator. */
992class UIIndicatorKeyboardExtension : public QITextStatusBarIndicator
993{
994 Q_OBJECT;
995
996public:
997
998 /** Constructor. */
999 UIIndicatorKeyboardExtension()
1000 {
1001 /* Make sure host-combination label will be updated: */
1002 connect(gEDataManager, &UIExtraDataManager::sigRuntimeUIHostKeyCombinationChange,
1003 this, &UIIndicatorKeyboardExtension::sltUpdateAppearance);
1004 /* Translate finally: */
1005 sltRetranslateUI();
1006 connect(&translationEventListener(), &UITranslationEventListener::sigRetranslateUI,
1007 this, &UIIndicatorKeyboardExtension::sltRetranslateUI);
1008 }
1009
1010public slots:
1011
1012 /** Update routine. */
1013 void sltUpdateAppearance()
1014 {
1015 setText(UIHostCombo::toReadableString(gEDataManager->hostKeyCombination()));
1016 }
1017
1018private slots:
1019
1020 /** Retranslation routine. */
1021 void sltRetranslateUI()
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
1033UIIndicatorsPool::UIIndicatorsPool(UIMachine *pMachine, QWidget *pParent /* = 0 */)
1034 : QWidget(pParent)
1035 , m_pMachine(pMachine)
1036 , m_fEnabled(false)
1037 , m_pMainLayout(0)
1038 , m_pTimerAutoUpdate(0)
1039{
1040 prepare();
1041}
1042
1043UIIndicatorsPool::~UIIndicatorsPool()
1044{
1045 cleanup();
1046}
1047
1048void UIIndicatorsPool::updateAppearance(IndicatorType indicatorType)
1049{
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();
1064}
1065
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
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
1085void UIIndicatorsPool::sltHandleConfigurationChange(const QUuid &uMachineID)
1086{
1087 /* Skip unrelated machine IDs: */
1088 if (uiCommon().managedVMUuid() != uMachineID)
1089 return;
1090
1091 /* Update pool: */
1092 updatePool();
1093}
1094
1095void UIIndicatorsPool::sltAutoUpdateIndicatorStates()
1096{
1097 /* We should update states for following indicators: */
1098 QVector<KDeviceType> deviceTypes;
1099 if (m_pool.contains(IndicatorType_HardDisks))
1100 deviceTypes.append(KDeviceType_HardDisk);
1101 if (m_pool.contains(IndicatorType_OpticalDisks))
1102 deviceTypes.append(KDeviceType_DVD);
1103 if (m_pool.contains(IndicatorType_FloppyDisks))
1104 deviceTypes.append(KDeviceType_Floppy);
1105 if (m_pool.contains(IndicatorType_USB))
1106 deviceTypes.append(KDeviceType_USB);
1107 if (m_pool.contains(IndicatorType_Network))
1108 deviceTypes.append(KDeviceType_Network);
1109 if (m_pool.contains(IndicatorType_SharedFolders))
1110 deviceTypes.append(KDeviceType_SharedFolder);
1111 if (m_pool.contains(IndicatorType_Display))
1112 deviceTypes.append(KDeviceType_Graphics3D);
1113
1114 /* Acquire current device states from the machine: */
1115 QVector<KDeviceActivity> states;
1116 m_pMachine->acquireDeviceActivity(deviceTypes, states);
1117
1118 /* Update indicators with the acquired states: */
1119 for (int iIndicator = 0; iIndicator < states.size(); ++iIndicator)
1120 {
1121 QIStatusBarIndicator *pIndicator = 0;
1122 switch (deviceTypes[iIndicator])
1123 {
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;
1132 }
1133 if (pIndicator)
1134 updateIndicatorStateForDevice(pIndicator, states[iIndicator]);
1135 }
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: */
1145 emit sigContextMenuRequest(indicatorType, pEvent->pos());
1146 return;
1147 }
1148}
1149
1150void UIIndicatorsPool::prepare()
1151{
1152 /* Prepare connections: */
1153 prepareConnections();
1154 /* Prepare contents: */
1155 prepareContents();
1156 /* Prepare auto-update timer: */
1157 prepareUpdateTimer();
1158}
1159
1160void UIIndicatorsPool::prepareConnections()
1161{
1162 /* Listen for the status-bar configuration changes: */
1163 connect(gEDataManager, &UIExtraDataManager::sigStatusBarConfigurationChange,
1164 this, &UIIndicatorsPool::sltHandleConfigurationChange);
1165}
1166
1167void UIIndicatorsPool::prepareContents()
1168{
1169 /* Create main-layout: */
1170 m_pMainLayout = new QHBoxLayout(this);
1171 AssertPtrReturnVoid(m_pMainLayout);
1172 {
1173 /* Configure main-layout: */
1174 m_pMainLayout->setContentsMargins(0, 0, 0, 0);
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
1180 /* Update pool: */
1181 updatePool();
1182 }
1183}
1184
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: */
1192 connect(m_pTimerAutoUpdate, &QTimer::timeout,
1193 this, &UIIndicatorsPool::sltAutoUpdateIndicatorStates);
1194 setAutoUpdateIndicatorStates(true);
1195 }
1196}
1197
1198void UIIndicatorsPool::updatePool()
1199{
1200 /* Acquire status-bar availability: */
1201 m_fEnabled = gEDataManager->statusBarEnabled(uiCommon().managedVMUuid());
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: */
1217 m_restrictions = gEDataManager->restrictedStatusBarIndicators(uiCommon().managedVMUuid());
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
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: */
1234 m_order = gEDataManager->statusBarIndicatorOrder(uiCommon().managedVMUuid());
1235 /* Make sure the order is complete taking restrictions into account: */
1236 for (int iType = IndicatorType_Invalid; iType < IndicatorType_Max; ++iType)
1237 {
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 }
1251
1252 /* Add/Update allowed indicators: */
1253 foreach (const IndicatorType &indicatorType, m_order)
1254 {
1255 /* Indicator exists: */
1256 if (m_pool.contains(indicatorType))
1257 {
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 {
1273 /* Create indicator: */
1274 switch (indicatorType)
1275 {
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;
1289 default: break;
1290 }
1291 /* Configure indicator: */
1292 connect(m_pool.value(indicatorType), &QIStatusBarIndicator::sigContextMenuRequest,
1293 this, &UIIndicatorsPool::sltContextMenuRequest);
1294 /* Insert indicator into main-layout at proper position: */
1295 m_pMainLayout->insertWidget(indicatorPosition(indicatorType), m_pool.value(indicatorType));
1296 }
1297 }
1298}
1299
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
1322void UIIndicatorsPool::cleanup()
1323{
1324 /* Cleanup auto-update timer: */
1325 cleanupUpdateTimer();
1326 /* Cleanup indicators: */
1327 cleanupContents();
1328}
1329
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
1337int UIIndicatorsPool::indicatorPosition(IndicatorType indicatorType) const
1338{
1339 int iPosition = 0;
1340 foreach (const IndicatorType &iteratedIndicatorType, m_order)
1341 if (iteratedIndicatorType == indicatorType)
1342 return iPosition;
1343 else
1344 ++iPosition;
1345 return iPosition;
1346}
1347
1348void UIIndicatorsPool::updateIndicatorStateForDevice(QIStatusBarIndicator *pIndicator, KDeviceActivity enmState)
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: */
1359 if (m_pMachine->isPaused())
1360 {
1361 /* If current state differs from IDLE => set the IDLE one: */
1362 if (pStateIndicator->state() != KDeviceActivity_Idle)
1363 pStateIndicator->setState(KDeviceActivity_Idle);
1364 }
1365 else
1366 {
1367 /* If current state differs from actual => set the actual one: */
1368 if (pStateIndicator->state() != enmState)
1369 pStateIndicator->setState(enmState);
1370 }
1371}
1372
1373#include "UIIndicatorsPool.moc"
Note: See TracBrowser for help on using the repository browser.

© 2023 Oracle
ContactPrivacy policyTerms of Use