VirtualBox

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

Last change on this file since 35740 was 33540, checked in by vboxsync, 14 years ago

*: spelling fixes, thanks Timeless!

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

© 2023 Oracle
ContactPrivacy policyTerms of Use