VirtualBox

source: vbox/trunk/src/VBox/Frontends/VirtualBox/src/runtime/UIMachine.cpp@ 38348

Last change on this file since 38348 was 38348, checked in by vboxsync, 13 years ago

FE/Qt: 5823: Generalize GUI action pool: Initial version: Action pool moved to the global part including global actions (related to both - 'VM manager' and 'VM itself' GUI parts). Global actions not reused in 'VM manager' yet.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 18.7 KB
Line 
1/* $Id: UIMachine.cpp 38348 2011-08-08 12:09:18Z vboxsync $ */
2/** @file
3 *
4 * VBox frontends: Qt GUI ("VirtualBox"):
5 * UIMachine class implementation
6 */
7
8/*
9 * Copyright (C) 2010 Oracle Corporation
10 *
11 * This file is part of VirtualBox Open Source Edition (OSE), as
12 * available from http://www.virtualbox.org. This file is free software;
13 * you can redistribute it and/or modify it under the terms of the GNU
14 * General Public License (GPL) as published by the Free Software
15 * Foundation, in version 2 as it comes in the "COPYING" file of the
16 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
17 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
18 */
19
20/* Global includes */
21#include <QTimer>
22
23/* Local includes */
24#include "VBoxGlobal.h"
25#include "UIMachine.h"
26#include "UISession.h"
27#include "UIActionPoolRuntime.h"
28#include "UIMachineLogic.h"
29#include "UIMachineWindow.h"
30
31#ifdef Q_WS_MAC
32# include <ApplicationServices/ApplicationServices.h>
33#endif /* Q_WS_MAC */
34
35class UIVisualState : public QObject
36{
37 Q_OBJECT;
38
39public:
40
41 /* Visual state holder constructor: */
42 UIVisualState(QObject *pParent, UISession *pSession)
43 : QObject(pParent)
44 , m_pSession(pSession)
45 , m_pMachineLogic(0)
46#ifdef Q_WS_MAC
47 , m_fadeToken(kCGDisplayFadeReservationInvalidToken)
48#endif /* Q_WS_MAC */
49 {
50 /* Connect state-change handler: */
51 connect(this, SIGNAL(sigChangeVisualState(UIVisualStateType)), parent(), SLOT(sltChangeVisualState(UIVisualStateType)));
52 }
53
54 /* Public getters: */
55 UIMachineLogic* machineLogic() const { return m_pMachineLogic; }
56 virtual UIVisualStateType visualStateType() const = 0;
57
58 virtual bool prepareChange(UIVisualStateType previousVisualStateType)
59 {
60 m_pMachineLogic = UIMachineLogic::create(this, m_pSession, visualStateType());
61 bool fResult = m_pMachineLogic->checkAvailability();
62#ifdef Q_WS_MAC
63 /* If the new is or the old type was fullscreen we add the blending
64 * transition between the mode switches.
65 * TODO: make this more general. */
66 if ( fResult
67 && ( visualStateType() == UIVisualStateType_Fullscreen
68 || previousVisualStateType == UIVisualStateType_Fullscreen))
69 {
70 /* Fade to black */
71 CGAcquireDisplayFadeReservation(kCGMaxDisplayReservationInterval, &m_fadeToken);
72 CGDisplayFade(m_fadeToken, 0.3, kCGDisplayBlendNormal, kCGDisplayBlendSolidColor, 0.0, 0.0, 0.0, true);
73 }
74#else /* Q_WS_MAC */
75 Q_UNUSED(previousVisualStateType);
76#endif /* !Q_WS_MAC */
77 return fResult;
78 }
79
80 virtual void change() = 0;
81
82 virtual void finishChange()
83 {
84#ifdef Q_WS_MAC
85 /* If there is a valid fade token, fade back to normal color in any
86 * case. */
87 if (m_fadeToken != kCGDisplayFadeReservationInvalidToken)
88 {
89 /* Fade back to the normal gamma */
90 CGDisplayFade(m_fadeToken, 0.5, kCGDisplayBlendSolidColor, kCGDisplayBlendNormal, 0.0, 0.0, 0.0, false);
91 CGReleaseDisplayFadeReservation(m_fadeToken);
92 m_fadeToken = kCGDisplayFadeReservationInvalidToken;
93 }
94#endif /* Q_WS_MAC */
95 }
96
97
98signals:
99
100 /* Signal to change-state: */
101 void sigChangeVisualState(UIVisualStateType visualStateType);
102
103protected:
104
105 /* Protected members: */
106 UISession *m_pSession;
107 UIMachineLogic *m_pMachineLogic;
108#ifdef Q_WS_MAC
109 CGDisplayFadeReservationToken m_fadeToken;
110#endif /* Q_WS_MAC */
111};
112
113class UIVisualStateNormal : public UIVisualState
114{
115 Q_OBJECT;
116
117public:
118
119 /* Normal visual state holder constructor: */
120 UIVisualStateNormal(QObject *pParent, UISession *pSession)
121 : UIVisualState(pParent, pSession) {}
122
123 UIVisualStateType visualStateType() const { return UIVisualStateType_Normal; }
124
125 void change()
126 {
127 /* Connect action handlers: */
128 connect(gActionPool->action(UIActionIndexRuntime_Toggle_Fullscreen), SIGNAL(triggered(bool)),
129 this, SLOT(sltGoToFullscreenMode()), Qt::QueuedConnection);
130 connect(gActionPool->action(UIActionIndexRuntime_Toggle_Seamless), SIGNAL(triggered(bool)),
131 this, SLOT(sltGoToSeamlessMode()), Qt::QueuedConnection);
132 connect(gActionPool->action(UIActionIndexRuntime_Toggle_Scale), SIGNAL(triggered(bool)),
133 this, SLOT(sltGoToScaleMode()), Qt::QueuedConnection);
134
135 /* Initialize the logic object: */
136 m_pMachineLogic->initialize();
137 }
138
139private slots:
140
141 void sltGoToFullscreenMode()
142 {
143 /* Change visual state to fullscreen: */
144 emit sigChangeVisualState(UIVisualStateType_Fullscreen);
145 }
146
147 void sltGoToSeamlessMode()
148 {
149 /* Change visual state to seamless: */
150 emit sigChangeVisualState(UIVisualStateType_Seamless);
151 }
152
153 void sltGoToScaleMode()
154 {
155 /* Change visual state to scale: */
156 emit sigChangeVisualState(UIVisualStateType_Scale);
157 }
158};
159
160class UIVisualStateFullscreen : public UIVisualState
161{
162 Q_OBJECT;
163
164public:
165
166 /* Fullscreen visual state holder constructor: */
167 UIVisualStateFullscreen(QObject *pParent, UISession *pSession)
168 : UIVisualState(pParent, pSession)
169 {
170 /* This visual state should take care of own action: */
171 QAction *pActionFullscreen = gActionPool->action(UIActionIndexRuntime_Toggle_Fullscreen);
172 if (!pActionFullscreen->isChecked())
173 {
174 pActionFullscreen->blockSignals(true);
175 pActionFullscreen->setChecked(true);
176 QTimer::singleShot(0, pActionFullscreen, SLOT(sltUpdateAppearance()));
177 pActionFullscreen->blockSignals(false);
178 }
179 }
180
181 /* Fullscreen visual state holder destructor: */
182 virtual ~UIVisualStateFullscreen()
183 {
184 /* This visual state should take care of own action: */
185 QAction *pActionFullscreen = gActionPool->action(UIActionIndexRuntime_Toggle_Fullscreen);
186 if (pActionFullscreen->isChecked())
187 {
188 pActionFullscreen->blockSignals(true);
189 pActionFullscreen->setChecked(false);
190 QTimer::singleShot(0, pActionFullscreen, SLOT(sltUpdateAppearance()));
191 pActionFullscreen->blockSignals(false);
192 }
193 }
194
195 UIVisualStateType visualStateType() const { return UIVisualStateType_Fullscreen; }
196
197 void change()
198 {
199 /* Connect action handlers: */
200 connect(gActionPool->action(UIActionIndexRuntime_Toggle_Fullscreen), SIGNAL(triggered(bool)),
201 this, SLOT(sltGoToNormalMode()), Qt::QueuedConnection);
202 connect(gActionPool->action(UIActionIndexRuntime_Toggle_Seamless), SIGNAL(triggered(bool)),
203 this, SLOT(sltGoToSeamlessMode()), Qt::QueuedConnection);
204 connect(gActionPool->action(UIActionIndexRuntime_Toggle_Scale), SIGNAL(triggered(bool)),
205 this, SLOT(sltGoToScaleMode()), Qt::QueuedConnection);
206
207 /* Initialize the logic object: */
208 m_pMachineLogic->initialize();
209 }
210
211private slots:
212
213 void sltGoToNormalMode()
214 {
215 /* Change visual state to normal: */
216 emit sigChangeVisualState(UIVisualStateType_Normal);
217 }
218
219 void sltGoToSeamlessMode()
220 {
221 /* Change visual state to seamless: */
222 emit sigChangeVisualState(UIVisualStateType_Seamless);
223 }
224
225 void sltGoToScaleMode()
226 {
227 /* Change visual state to scale: */
228 emit sigChangeVisualState(UIVisualStateType_Scale);
229 }
230};
231
232class UIVisualStateSeamless : public UIVisualState
233{
234 Q_OBJECT;
235
236public:
237
238 /* Seamless visual state holder constructor: */
239 UIVisualStateSeamless(QObject *pParent, UISession *pSession)
240 : UIVisualState(pParent, pSession)
241 {
242 /* This visual state should take care of own action: */
243 QAction *pActionSeamless = gActionPool->action(UIActionIndexRuntime_Toggle_Seamless);
244 if (!pActionSeamless->isChecked())
245 {
246 pActionSeamless->blockSignals(true);
247 pActionSeamless->setChecked(true);
248 QTimer::singleShot(0, pActionSeamless, SLOT(sltUpdateAppearance()));
249 pActionSeamless->blockSignals(false);
250 }
251 }
252
253 /* Seamless visual state holder destructor: */
254 virtual ~UIVisualStateSeamless()
255 {
256 /* This visual state should take care of own action: */
257 QAction *pActionSeamless = gActionPool->action(UIActionIndexRuntime_Toggle_Seamless);
258 if (pActionSeamless->isChecked())
259 {
260 pActionSeamless->blockSignals(true);
261 pActionSeamless->setChecked(false);
262 QTimer::singleShot(0, pActionSeamless, SLOT(sltUpdateAppearance()));
263 pActionSeamless->blockSignals(false);
264 }
265 }
266
267 UIVisualStateType visualStateType() const { return UIVisualStateType_Seamless; }
268
269 void change()
270 {
271 /* Connect action handlers: */
272 connect(gActionPool->action(UIActionIndexRuntime_Toggle_Seamless), SIGNAL(triggered(bool)),
273 this, SLOT(sltGoToNormalMode()), Qt::QueuedConnection);
274 connect(gActionPool->action(UIActionIndexRuntime_Toggle_Fullscreen), SIGNAL(triggered(bool)),
275 this, SLOT(sltGoToFullscreenMode()), Qt::QueuedConnection);
276 connect(gActionPool->action(UIActionIndexRuntime_Toggle_Scale), SIGNAL(triggered(bool)),
277 this, SLOT(sltGoToScaleMode()), Qt::QueuedConnection);
278
279 /* Initialize the logic object: */
280 m_pMachineLogic->initialize();
281 }
282
283private slots:
284
285 void sltGoToNormalMode()
286 {
287 /* Change visual state to normal: */
288 emit sigChangeVisualState(UIVisualStateType_Normal);
289 }
290
291 void sltGoToFullscreenMode()
292 {
293 /* Change visual state to fullscreen: */
294 emit sigChangeVisualState(UIVisualStateType_Fullscreen);
295 }
296
297 void sltGoToScaleMode()
298 {
299 /* Change visual state to scale: */
300 emit sigChangeVisualState(UIVisualStateType_Scale);
301 }
302};
303
304class UIVisualStateScale : public UIVisualState
305{
306 Q_OBJECT;
307
308public:
309
310 /* Scale visual state holder constructor: */
311 UIVisualStateScale(QObject *pParent, UISession *pSession)
312 : UIVisualState(pParent, pSession)
313 {
314 /* This visual state should take care of own action: */
315 QAction *pActionScale = gActionPool->action(UIActionIndexRuntime_Toggle_Scale);
316 if (!pActionScale->isChecked())
317 {
318 pActionScale->blockSignals(true);
319 pActionScale->setChecked(true);
320 QTimer::singleShot(0, pActionScale, SLOT(sltUpdateAppearance()));
321 pActionScale->blockSignals(false);
322 }
323 }
324
325 /* Seamless visual state holder destructor: */
326 virtual ~UIVisualStateScale()
327 {
328 /* This visual state should take care of own action: */
329 QAction *pActionScale = gActionPool->action(UIActionIndexRuntime_Toggle_Scale);
330 if (pActionScale->isChecked())
331 {
332 pActionScale->blockSignals(true);
333 pActionScale->setChecked(false);
334 QTimer::singleShot(0, pActionScale, SLOT(sltUpdateAppearance()));
335 pActionScale->blockSignals(false);
336 }
337 }
338
339 UIVisualStateType visualStateType() const { return UIVisualStateType_Scale; }
340
341 void change()
342 {
343 /* Connect action handlers: */
344 connect(gActionPool->action(UIActionIndexRuntime_Toggle_Scale), SIGNAL(triggered(bool)),
345 this, SLOT(sltGoToNormalMode()), Qt::QueuedConnection);
346 connect(gActionPool->action(UIActionIndexRuntime_Toggle_Fullscreen), SIGNAL(triggered(bool)),
347 this, SLOT(sltGoToFullscreenMode()), Qt::QueuedConnection);
348 connect(gActionPool->action(UIActionIndexRuntime_Toggle_Seamless), SIGNAL(triggered(bool)),
349 this, SLOT(sltGoToSeamlessMode()), Qt::QueuedConnection);
350
351 /* Initialize the logic object: */
352 m_pMachineLogic->initialize();
353 }
354
355private slots:
356
357 void sltGoToNormalMode()
358 {
359 /* Change visual state to normal: */
360 emit sigChangeVisualState(UIVisualStateType_Normal);
361 }
362
363 void sltGoToFullscreenMode()
364 {
365 /* Change visual state to fullscreen: */
366 emit sigChangeVisualState(UIVisualStateType_Fullscreen);
367 }
368
369 void sltGoToSeamlessMode()
370 {
371 /* Change visual state to seamless: */
372 emit sigChangeVisualState(UIVisualStateType_Seamless);
373 }
374};
375
376UIMachine::UIMachine(UIMachine **ppSelf, const CSession &session)
377 : QObject(0)
378 , m_ppThis(ppSelf)
379 , initialStateType(UIVisualStateType_Normal)
380 , m_session(session)
381 , m_pSession(0)
382 , m_pVisualState(0)
383{
384 /* Storing self: */
385 if (m_ppThis)
386 *m_ppThis = this;
387
388 /* Create action pool: */
389 UIActionPoolRuntime::create();
390
391 /* Create UISession object: */
392 m_pSession = new UISession(this, m_session);
393
394 /* Preventing application from closing in case of window(s) closed: */
395 qApp->setQuitOnLastWindowClosed(false);
396
397 /* Cache IMedium data: */
398 vboxGlobal().startEnumeratingMedia();
399
400 /* Load machine settings: */
401 loadMachineSettings();
402
403 /* Enter default (normal) state */
404 enterInitialVisualState();
405}
406
407UIMachine::~UIMachine()
408{
409 /* Save machine settings: */
410 saveMachineSettings();
411 /* Erase itself pointer: */
412 *m_ppThis = 0;
413 /* Delete uisession children in backward direction: */
414 delete m_pVisualState;
415 m_pVisualState = 0;
416 delete m_pSession;
417 m_pSession = 0;
418 m_session.UnlockMachine();
419 m_session.detach();
420 /* Destroy action pool: */
421 UIActionPoolRuntime::destroy();
422 /* Quit application: */
423 QApplication::quit();
424}
425
426QWidget* UIMachine::mainWindow() const
427{
428 if (machineLogic() &&
429 machineLogic()->mainMachineWindow() &&
430 machineLogic()->mainMachineWindow()->machineWindow())
431 return machineLogic()->mainMachineWindow()->machineWindow();
432 else
433 return 0;
434}
435
436void UIMachine::sltChangeVisualState(UIVisualStateType visualStateType)
437{
438 /* Create new state: */
439 UIVisualState *pNewVisualState = 0;
440 switch (visualStateType)
441 {
442 case UIVisualStateType_Normal:
443 {
444 /* Create normal visual state: */
445 pNewVisualState = new UIVisualStateNormal(this, m_pSession);
446 break;
447 }
448 case UIVisualStateType_Fullscreen:
449 {
450 /* Create fullscreen visual state: */
451 pNewVisualState = new UIVisualStateFullscreen(this, m_pSession);
452 break;
453 }
454 case UIVisualStateType_Seamless:
455 {
456 /* Create seamless visual state: */
457 pNewVisualState = new UIVisualStateSeamless(this, m_pSession);
458 break;
459 }
460 case UIVisualStateType_Scale:
461 {
462 /* Create scale visual state: */
463 pNewVisualState = new UIVisualStateScale(this, m_pSession);
464 break;
465 }
466 default:
467 break;
468 }
469
470 UIVisualStateType previousVisualStateType = UIVisualStateType_Normal;
471 if (m_pVisualState)
472 previousVisualStateType = m_pVisualState->visualStateType();
473
474 /* First we have to check if the selected mode is available at all.
475 * Only then we delete the old mode and switch to the new mode. */
476 if (pNewVisualState->prepareChange(previousVisualStateType))
477 {
478 /* Delete previous state: */
479 delete m_pVisualState;
480
481 /* Set the new mode as current mode: */
482 m_pVisualState = pNewVisualState;
483 m_pVisualState->change();
484
485 /* Finish any setup: */
486 m_pVisualState->finishChange();
487 }
488 else
489 {
490 /* Discard the temporary created new state: */
491 delete pNewVisualState;
492
493 /* If there is no state currently created => we have to exit: */
494 if (!m_pVisualState)
495 deleteLater();
496 }
497}
498
499void UIMachine::sltCloseVirtualMachine()
500{
501 delete this;
502}
503
504void UIMachine::enterInitialVisualState()
505{
506 sltChangeVisualState(initialStateType);
507}
508
509UIMachineLogic* UIMachine::machineLogic() const
510{
511 if (m_pVisualState && m_pVisualState->machineLogic())
512 return m_pVisualState->machineLogic();
513 else
514 return 0;
515}
516
517void UIMachine::loadMachineSettings()
518{
519 /* Load machine settings: */
520 CMachine machine = uisession()->session().GetMachine();
521
522 /* Load extra-data settings: */
523 {
524 /* Machine while saving own settings will save "yes" only for current
525 * visual representation mode if its differs from normal mode of course.
526 * But user can alter extra data manually in machine xml file and set there
527 * more than one visual representation mode flags. Shame on such user!
528 * There is no reason to enter in more than one visual representation mode
529 * at machine start, so we are choosing first of requested modes: */
530 bool fIsSomeExtendedModeChosen = false;
531
532 if (!fIsSomeExtendedModeChosen)
533 {
534 /* Test 'scale' flag: */
535 QString strScaleSettings = machine.GetExtraData(VBoxDefs::GUI_Scale);
536 if (strScaleSettings == "on")
537 {
538 fIsSomeExtendedModeChosen = true;
539 /* We can enter scale mode initially: */
540 initialStateType = UIVisualStateType_Scale;
541 }
542 }
543
544 if (!fIsSomeExtendedModeChosen)
545 {
546 /* Test 'seamless' flag: */
547 QString strSeamlessSettings = machine.GetExtraData(VBoxDefs::GUI_Seamless);
548 if (strSeamlessSettings == "on")
549 {
550 fIsSomeExtendedModeChosen = true;
551 /* We can't enter seamless mode initially,
552 * so we should ask ui-session for that: */
553 uisession()->setSeamlessModeRequested(true);
554 }
555 }
556
557 if (!fIsSomeExtendedModeChosen)
558 {
559 /* Test 'fullscreen' flag: */
560 QString strFullscreenSettings = machine.GetExtraData(VBoxDefs::GUI_Fullscreen);
561 if (strFullscreenSettings == "on")
562 {
563 fIsSomeExtendedModeChosen = true;
564 /* We can enter fullscreen mode initially: */
565 initialStateType = UIVisualStateType_Fullscreen;
566 }
567 }
568 }
569}
570
571void UIMachine::saveMachineSettings()
572{
573 /* Save machine settings: */
574 CMachine machine = uisession()->session().GetMachine();
575
576 /* Save extra-data settings: */
577 {
578 /* Set 'scale' flag: */
579 machine.SetExtraData(VBoxDefs::GUI_Scale, m_pVisualState &&
580 m_pVisualState->visualStateType() == UIVisualStateType_Scale ? "on" : QString());
581
582 /* Set 'seamless' flag: */
583 machine.SetExtraData(VBoxDefs::GUI_Seamless, m_pVisualState &&
584 m_pVisualState->visualStateType() == UIVisualStateType_Seamless ? "on" : QString());
585
586 /* Set 'fullscreen' flag: */
587 machine.SetExtraData(VBoxDefs::GUI_Fullscreen, m_pVisualState &&
588 m_pVisualState->visualStateType() == UIVisualStateType_Fullscreen ? "on" : QString());
589 }
590}
591
592#include "UIMachine.moc"
593
Note: See TracBrowser for help on using the repository browser.

© 2023 Oracle
ContactPrivacy policyTerms of Use