38
46
#include "VBoxTakeSnapshotDlg.h"
39
47
#include "VBoxVMInformationDlg.h"
40
48
#include "UISettingsDialogSpecific.h"
49
#include "UIVMLogViewer.h"
50
#include "UIConverter.h"
42
52
# include "DockIconPreview.h"
43
53
# include "UIExtraDataEventHandler.h"
44
54
#endif /* Q_WS_MAC */
57
#include "CVirtualBoxErrorInfo.h"
58
#include "CMachineDebugger.h"
59
#include "CSnapshot.h"
61
#include "CStorageController.h"
62
#include "CMediumAttachment.h"
63
#include "CHostUSBDevice.h"
64
#include "CUSBDevice.h"
65
#include "CVRDEServer.h"
66
#include "CSystemProperties.h"
71
/* Other VBox includes: */
47
72
#include <iprt/path.h>
49
73
#ifdef VBOX_WITH_DEBUGGER_GUI
50
74
# include <iprt/ldr.h>
51
75
#endif /* VBOX_WITH_DEBUGGER_GUI */
77
/* External includes: */
54
79
# include <XKeyboard.h>
55
80
# include <QX11Info>
56
81
#endif /* Q_WS_X11 */
60
#include <QDesktopWidget>
63
83
struct MediumTarget
65
MediumTarget() : name(QString("")), port(0), device(0), id(QString()), type(VBoxDefs::MediumType_Invalid) {}
85
MediumTarget() : name(QString("")), port(0), device(0), id(QString()), type(UIMediumType_Invalid) {}
66
86
MediumTarget(const QString &strName, LONG iPort, LONG iDevice)
67
: name(strName), port(iPort), device(iDevice), id(QString()), type(VBoxDefs::MediumType_Invalid) {}
87
: name(strName), port(iPort), device(iDevice), id(QString()), type(UIMediumType_Invalid) {}
68
88
MediumTarget(const QString &strName, LONG iPort, LONG iDevice, const QString &strId)
69
: name(strName), port(iPort), device(iDevice), id(strId), type(VBoxDefs::MediumType_Invalid) {}
70
MediumTarget(const QString &strName, LONG iPort, LONG iDevice, VBoxDefs::MediumType eType)
89
: name(strName), port(iPort), device(iDevice), id(strId), type(UIMediumType_Invalid) {}
90
MediumTarget(const QString &strName, LONG iPort, LONG iDevice, UIMediumType eType)
71
91
: name(strName), port(iPort), device(iDevice), id(QString()), type(eType) {}
76
VBoxDefs::MediumType type;
78
98
Q_DECLARE_METATYPE(MediumTarget);
80
100
struct RecentMediumTarget
82
RecentMediumTarget() : name(QString("")), port(0), device(0), location(QString()), type(VBoxDefs::MediumType_Invalid) {}
83
RecentMediumTarget(const QString &strName, LONG iPort, LONG iDevice, const QString &strLocation, VBoxDefs::MediumType eType)
102
RecentMediumTarget() : name(QString("")), port(0), device(0), location(QString()), type(UIMediumType_Invalid) {}
103
RecentMediumTarget(const QString &strName, LONG iPort, LONG iDevice, const QString &strLocation, UIMediumType eType)
84
104
: name(strName), port(iPort), device(iDevice), location(strLocation), type(eType) {}
89
VBoxDefs::MediumType type;
91
111
Q_DECLARE_METATYPE(RecentMediumTarget);
101
121
Q_DECLARE_METATYPE(USBTarget);
103
124
UIMachineLogic* UIMachineLogic::create(QObject *pParent,
104
125
UISession *pSession,
105
126
UIVisualStateType visualStateType)
107
UIMachineLogic *logic = 0;
128
UIMachineLogic *pLogic = 0;
108
129
switch (visualStateType)
110
131
case UIVisualStateType_Normal:
111
logic = new UIMachineLogicNormal(pParent, pSession);
132
pLogic = new UIMachineLogicNormal(pParent, pSession);
113
134
case UIVisualStateType_Fullscreen:
114
logic = new UIMachineLogicFullscreen(pParent, pSession);
135
pLogic = new UIMachineLogicFullscreen(pParent, pSession);
116
137
case UIVisualStateType_Seamless:
117
logic = new UIMachineLogicSeamless(pParent, pSession);
138
pLogic = new UIMachineLogicSeamless(pParent, pSession);
119
140
case UIVisualStateType_Scale:
120
logic = new UIMachineLogicScale(pParent, pSession);
141
pLogic = new UIMachineLogicScale(pParent, pSession);
126
bool UIMachineLogic::checkAvailability()
148
void UIMachineLogic::destroy(UIMachineLogic *pWhichLogic)
153
void UIMachineLogic::prepare()
155
/* Prepare required features: */
156
prepareRequiredFeatures();
158
/* Prepare session connections: */
159
prepareSessionConnections();
161
/* Prepare action groups:
162
* Note: This has to be done before prepareActionConnections
163
* cause here actions/menus are recreated. */
164
prepareActionGroups();
165
/* Prepare action connections: */
166
prepareActionConnections();
168
/* Prepare handlers: */
171
/* Prepare machine window(s): */
172
prepareMachineWindows();
177
#endif /* Q_WS_MAC */
179
/* Power up machine: */
180
uisession()->powerUp();
182
/* Initialization: */
183
sltMachineStateChanged();
184
sltAdditionsStateChanged();
185
sltMouseCapabilityChanged();
187
#ifdef VBOX_WITH_DEBUGGER_GUI
188
/* Prepare debugger: */
190
#endif /* VBOX_WITH_DEBUGGER_GUI */
192
/* Retranslate logic part: */
196
void UIMachineLogic::cleanup()
198
#ifdef VBOX_WITH_DEBUGGER_GUI
199
/* Cleanup debugger: */
201
#endif /* VBOX_WITH_DEBUGGER_GUI */
206
#endif /* Q_WS_MAC */
208
/* Cleanup machine window(s): */
209
cleanupMachineWindows();
211
/* Cleanup handlers: */
214
/* Cleanup action groups: */
215
cleanupActionGroups();
218
CSession& UIMachineLogic::session() const
220
return uisession()->session();
131
223
UIMachineWindow* UIMachineLogic::mainMachineWindow() const
134
226
if (!isMachineWindowsCreated())
229
/* Otherwise return first of windows: */
137
230
return machineWindows()[0];
140
UIMachineWindow* UIMachineLogic::defaultMachineWindow() const
233
UIMachineWindow* UIMachineLogic::activeMachineWindow() const
142
235
/* Return null if windows are not created yet: */
143
236
if (!isMachineWindowsCreated())
146
/* Select main machine window by default: */
147
UIMachineWindow *pWindowToPropose = mainMachineWindow();
149
/* Check if there is active window present: */
150
foreach (UIMachineWindow *pWindowToCheck, machineWindows())
239
/* Check if there is an active window present: */
240
for (int i = 0; i < machineWindows().size(); ++i)
152
if (pWindowToCheck->machineWindow()->isActiveWindow())
154
pWindowToPropose = pWindowToCheck;
242
UIMachineWindow *pIteratedWindow = machineWindows()[i];
243
if (pIteratedWindow->isActiveWindow())
244
return pIteratedWindow;
159
/* Return default machine window: */
160
return pWindowToPropose;
247
/* Return main machine window: */
248
return mainMachineWindow();
197
285
#endif /* Q_WS_MAC */
199
UIMachineLogic::UIMachineLogic(QObject *pParent,
201
UIVisualStateType visualStateType)
287
void UIMachineLogic::sltMachineStateChanged()
289
/* Get machine state: */
290
KMachineState state = uisession()->machineState();
292
/* Update action groups: */
293
m_pRunningActions->setEnabled(uisession()->isRunning());
294
m_pRunningOrPausedActions->setEnabled(uisession()->isRunning() || uisession()->isPaused());
298
case KMachineState_Stuck: // TODO: Test it!
300
/* Prevent machine view from resizing: */
301
uisession()->setGuestResizeIgnored(true);
303
/* Get console and log folder. */
304
CConsole console = session().GetConsole();
305
const QString &strLogFolder = console.GetMachine().GetLogFolder();
307
/* Take the screenshot for debugging purposes and save it. */
308
takeScreenshot(strLogFolder + "/VBox.png", "png");
310
/* Warn the user about GURU: */
311
if (msgCenter().remindAboutGuruMeditation(console, QDir::toNativeSeparators(strLogFolder)))
315
msgCenter().cannotStopMachine(console);
319
case KMachineState_Paused:
320
case KMachineState_TeleportingPausedVM:
322
QAction *pPauseAction = gActionPool->action(UIActionIndexRuntime_Toggle_Pause);
323
if (!pPauseAction->isChecked())
325
/* Was paused from CSession side: */
326
pPauseAction->blockSignals(true);
327
pPauseAction->setChecked(true);
328
pPauseAction->blockSignals(false);
332
case KMachineState_Running:
333
case KMachineState_Teleporting:
334
case KMachineState_LiveSnapshotting:
336
QAction *pPauseAction = gActionPool->action(UIActionIndexRuntime_Toggle_Pause);
337
if (pPauseAction->isChecked())
339
/* Was resumed from CSession side: */
340
pPauseAction->blockSignals(true);
341
pPauseAction->setChecked(false);
342
pPauseAction->blockSignals(false);
346
case KMachineState_PoweredOff:
347
case KMachineState_Saved:
348
case KMachineState_Teleported:
349
case KMachineState_Aborted:
351
/* Close VM if it was turned off and closure allowed: */
352
if (!isPreventAutoClose())
354
/* VM has been powered off, saved or aborted, no matter
355
* internally or externally. We must *safely* close VM window(s): */
356
QTimer::singleShot(0, uisession(), SLOT(sltCloseVirtualSession()));
361
case KMachineState_Starting:
362
case KMachineState_Restoring:
363
case KMachineState_TeleportingIn:
365
/* The keyboard handler may wish to do some release logging on startup.
366
* Tell it that the logger is now active. */
367
doXKeyboardLogging(QX11Info::display());
376
/* Update Dock Overlay: */
378
#endif /* Q_WS_MAC */
381
void UIMachineLogic::sltAdditionsStateChanged()
383
/* Update action states: */
384
gActionPool->action(UIActionIndexRuntime_Toggle_GuestAutoresize)->setEnabled(uisession()->isGuestSupportsGraphics());
385
gActionPool->action(UIActionIndexRuntime_Toggle_Seamless)->setEnabled(uisession()->isGuestSupportsSeamless());
388
void UIMachineLogic::sltMouseCapabilityChanged()
390
/* Variable falgs: */
391
bool fIsMouseSupportsAbsolute = uisession()->isMouseSupportsAbsolute();
392
bool fIsMouseSupportsRelative = uisession()->isMouseSupportsRelative();
393
bool fIsMouseHostCursorNeeded = uisession()->isMouseHostCursorNeeded();
395
/* Update action state: */
396
QAction *pAction = gActionPool->action(UIActionIndexRuntime_Toggle_MouseIntegration);
397
pAction->setEnabled(fIsMouseSupportsAbsolute && fIsMouseSupportsRelative && !fIsMouseHostCursorNeeded);
398
if (fIsMouseHostCursorNeeded)
399
pAction->setChecked(false);
402
void UIMachineLogic::sltUSBDeviceStateChange(const CUSBDevice &device, bool fIsAttached, const CVirtualBoxErrorInfo &error)
404
/* Check if USB device have anything to tell us: */
408
msgCenter().cannotAttachUSBDevice(session().GetConsole(), vboxGlobal().details(device), error);
410
msgCenter().cannotDetachUSBDevice(session().GetConsole(), vboxGlobal().details(device), error);
414
void UIMachineLogic::sltRuntimeError(bool fIsFatal, const QString &strErrorId, const QString &strMessage)
416
msgCenter().showRuntimeError(session().GetConsole(), fIsFatal, strErrorId, strMessage);
420
void UIMachineLogic::sltShowWindows()
422
for (int i=0; i < machineWindows().size(); ++i)
424
UIMachineWindow *pMachineWindow = machineWindows().at(i);
425
/* Dunno what Qt thinks a window that has minimized to the dock
426
* should be - it is not hidden, neither is it minimized. OTOH it is
427
* marked shown and visible, but not activated. This latter isn't of
428
* much help though, since at this point nothing is marked activated.
429
* I might have overlooked something, but I'm buggered what if I know
430
* what. So, I'll just always show & activate the stupid window to
431
* make it get out of the dock when the user wishes to show a VM. */
432
pMachineWindow->raise();
433
pMachineWindow->activateWindow();
436
#endif /* Q_WS_MAC */
438
UIMachineLogic::UIMachineLogic(QObject *pParent, UISession *pSession, UIVisualStateType visualStateType)
202
439
: QIWithRetranslateUI3<QObject>(pParent)
203
440
, m_pSession(pSession)
204
441
, m_visualStateType(visualStateType)
314
562
/* Show windows: */
315
connect(uisession(), SIGNAL(sigShowWindows()),
316
this, SLOT(sltShowWindows()));
317
#endif /* Q_WS_MAC */
563
connect(uisession(), SIGNAL(sigShowWindows()), this, SLOT(sltShowWindows()));
564
#endif /* Q_WS_MAC */
567
void UIMachineLogic::prepareActionGroups()
570
/* On Mac OS X, all QMenu's are consumed by Qt after they are added to
571
* another QMenu or a QMenuBar. This means we have to recreate all QMenus
572
* when creating a new QMenuBar. */
573
gActionPool->recreateMenus();
574
#endif /* Q_WS_MAC */
576
/* Create group for all actions that are enabled only when the VM is running.
577
* Note that only actions whose enabled state depends exclusively on the
578
* execution state of the VM are added to this group. */
579
m_pRunningActions = new QActionGroup(this);
580
m_pRunningActions->setExclusive(false);
582
/* Create group for all actions that are enabled when the VM is running or paused.
583
* Note that only actions whose enabled state depends exclusively on the
584
* execution state of the VM are added to this group. */
585
m_pRunningOrPausedActions = new QActionGroup(this);
586
m_pRunningOrPausedActions->setExclusive(false);
588
/* Move actions into running actions group: */
589
m_pRunningActions->addAction(gActionPool->action(UIActionIndexRuntime_Simple_TypeCAD));
591
m_pRunningActions->addAction(gActionPool->action(UIActionIndexRuntime_Simple_TypeCABS));
593
m_pRunningActions->addAction(gActionPool->action(UIActionIndexRuntime_Simple_Reset));
594
m_pRunningActions->addAction(gActionPool->action(UIActionIndexRuntime_Simple_Shutdown));
595
m_pRunningActions->addAction(gActionPool->action(UIActionIndexRuntime_Toggle_Fullscreen));
596
m_pRunningActions->addAction(gActionPool->action(UIActionIndexRuntime_Toggle_Seamless));
597
m_pRunningActions->addAction(gActionPool->action(UIActionIndexRuntime_Toggle_Scale));
598
m_pRunningActions->addAction(gActionPool->action(UIActionIndexRuntime_Toggle_GuestAutoresize));
599
m_pRunningActions->addAction(gActionPool->action(UIActionIndexRuntime_Simple_AdjustWindow));
601
/* Move actions into running-n-paused actions group: */
602
m_pRunningOrPausedActions->addAction(gActionPool->action(UIActionIndexRuntime_Simple_SettingsDialog));
603
m_pRunningOrPausedActions->addAction(gActionPool->action(UIActionIndexRuntime_Simple_TakeSnapshot));
604
m_pRunningOrPausedActions->addAction(gActionPool->action(UIActionIndexRuntime_Simple_TakeScreenshot));
605
m_pRunningOrPausedActions->addAction(gActionPool->action(UIActionIndexRuntime_Simple_InformationDialog));
606
m_pRunningOrPausedActions->addAction(gActionPool->action(UIActionIndexRuntime_Menu_MouseIntegration));
607
m_pRunningOrPausedActions->addAction(gActionPool->action(UIActionIndexRuntime_Toggle_MouseIntegration));
608
m_pRunningOrPausedActions->addAction(gActionPool->action(UIActionIndexRuntime_Toggle_Pause));
609
m_pRunningOrPausedActions->addAction(gActionPool->action(UIActionIndexRuntime_Menu_OpticalDevices));
610
m_pRunningOrPausedActions->addAction(gActionPool->action(UIActionIndexRuntime_Menu_FloppyDevices));
611
m_pRunningOrPausedActions->addAction(gActionPool->action(UIActionIndexRuntime_Menu_USBDevices));
612
m_pRunningOrPausedActions->addAction(gActionPool->action(UIActionIndexRuntime_Menu_SharedClipboard));
613
m_pRunningOrPausedActions->addAction(gActionPool->action(UIActionIndexRuntime_Menu_DragAndDrop));
614
m_pRunningOrPausedActions->addAction(gActionPool->action(UIActionIndexRuntime_Menu_NetworkAdapters));
615
m_pRunningOrPausedActions->addAction(gActionPool->action(UIActionIndexRuntime_Simple_NetworkAdaptersDialog));
616
m_pRunningOrPausedActions->addAction(gActionPool->action(UIActionIndexRuntime_Menu_SharedFolders));
617
m_pRunningOrPausedActions->addAction(gActionPool->action(UIActionIndexRuntime_Simple_SharedFoldersDialog));
618
m_pRunningOrPausedActions->addAction(gActionPool->action(UIActionIndexRuntime_Toggle_VRDEServer));
619
m_pRunningOrPausedActions->addAction(gActionPool->action(UIActionIndexRuntime_Simple_InstallGuestTools));
320
622
void UIMachineLogic::prepareActionConnections()
375
683
this, SLOT(sltShowDebugCommandLine()));
376
684
connect(gActionPool->action(UIActionIndexRuntime_Toggle_Logging), SIGNAL(toggled(bool)),
377
685
this, SLOT(sltLoggingToggled(bool)));
381
void UIMachineLogic::prepareActionGroups()
384
/* On Mac OS X, all QMenu's are consumed by Qt after they are added to
385
* another QMenu or a QMenuBar. This means we have to recreate all QMenus
386
* when creating a new QMenuBar. */
387
gActionPool->recreateMenus();
388
#endif /* Q_WS_MAC */
390
/* Create group for all actions that are enabled only when the VM is running.
391
* Note that only actions whose enabled state depends exclusively on the
392
* execution state of the VM are added to this group. */
393
m_pRunningActions = new QActionGroup(this);
394
m_pRunningActions->setExclusive(false);
396
/* Create group for all actions that are enabled when the VM is running or paused.
397
* Note that only actions whose enabled state depends exclusively on the
398
* execution state of the VM are added to this group. */
399
m_pRunningOrPausedActions = new QActionGroup(this);
400
m_pRunningOrPausedActions->setExclusive(false);
402
/* Move actions into running actions group: */
403
m_pRunningActions->addAction(gActionPool->action(UIActionIndexRuntime_Simple_TypeCAD));
405
m_pRunningActions->addAction(gActionPool->action(UIActionIndexRuntime_Simple_TypeCABS));
407
m_pRunningActions->addAction(gActionPool->action(UIActionIndexRuntime_Simple_Reset));
408
m_pRunningActions->addAction(gActionPool->action(UIActionIndexRuntime_Simple_Shutdown));
409
m_pRunningActions->addAction(gActionPool->action(UIActionIndexRuntime_Toggle_Fullscreen));
410
m_pRunningActions->addAction(gActionPool->action(UIActionIndexRuntime_Toggle_Seamless));
411
m_pRunningActions->addAction(gActionPool->action(UIActionIndexRuntime_Toggle_Scale));
412
m_pRunningActions->addAction(gActionPool->action(UIActionIndexRuntime_Toggle_GuestAutoresize));
413
m_pRunningActions->addAction(gActionPool->action(UIActionIndexRuntime_Simple_AdjustWindow));
415
/* Move actions into running-n-paused actions group: */
416
m_pRunningOrPausedActions->addAction(gActionPool->action(UIActionIndexRuntime_Simple_SettingsDialog));
417
m_pRunningOrPausedActions->addAction(gActionPool->action(UIActionIndexRuntime_Simple_TakeSnapshot));
418
m_pRunningOrPausedActions->addAction(gActionPool->action(UIActionIndexRuntime_Simple_InformationDialog));
419
m_pRunningOrPausedActions->addAction(gActionPool->action(UIActionIndexRuntime_Menu_MouseIntegration));
420
m_pRunningOrPausedActions->addAction(gActionPool->action(UIActionIndexRuntime_Toggle_MouseIntegration));
421
m_pRunningOrPausedActions->addAction(gActionPool->action(UIActionIndexRuntime_Toggle_Pause));
422
m_pRunningOrPausedActions->addAction(gActionPool->action(UIActionIndexRuntime_Menu_OpticalDevices));
423
m_pRunningOrPausedActions->addAction(gActionPool->action(UIActionIndexRuntime_Menu_FloppyDevices));
424
m_pRunningOrPausedActions->addAction(gActionPool->action(UIActionIndexRuntime_Menu_USBDevices));
425
m_pRunningOrPausedActions->addAction(gActionPool->action(UIActionIndexRuntime_Menu_NetworkAdapters));
426
m_pRunningOrPausedActions->addAction(gActionPool->action(UIActionIndexRuntime_Simple_NetworkAdaptersDialog));
427
m_pRunningOrPausedActions->addAction(gActionPool->action(UIActionIndexRuntime_Menu_SharedFolders));
428
m_pRunningOrPausedActions->addAction(gActionPool->action(UIActionIndexRuntime_Simple_SharedFoldersDialog));
429
m_pRunningOrPausedActions->addAction(gActionPool->action(UIActionIndexRuntime_Toggle_VRDEServer));
430
m_pRunningOrPausedActions->addAction(gActionPool->action(UIActionIndexRuntime_Simple_InstallGuestTools));
686
connect(gActionPool->action(UIActionIndex_Simple_LogDialog), SIGNAL(triggered()),
687
this, SLOT(sltShowLogDialog()));
433
691
void UIMachineLogic::prepareHandlers()
566
822
UIKeyboardHandler::destroy(keyboardHandler());
569
void UIMachineLogic::sltMachineStateChanged()
571
/* Get machine state: */
572
KMachineState state = uisession()->machineState();
574
/* Update action groups: */
575
m_pRunningActions->setEnabled(uisession()->isRunning());
576
m_pRunningOrPausedActions->setEnabled(uisession()->isRunning() || uisession()->isPaused());
580
case KMachineState_Stuck: // TODO: Test it!
582
/* Prevent machine view from resizing: */
583
uisession()->setGuestResizeIgnored(true);
586
CConsole console = session().GetConsole();
588
/* Take the screenshot for debugging purposes and save it. */
589
QString strLogFolder = console.GetMachine().GetLogFolder();
590
CDisplay display = console.GetDisplay();
591
int cGuestScreens = uisession()->session().GetMachine().GetMonitorCount();
592
for (int i=0; i < cGuestScreens; ++i)
596
strFileName = strLogFolder + "/VBox.png";
598
strFileName = QString("%1/VBox.%2.png").arg(strLogFolder).arg(i);
602
display.GetScreenResolution(i, width, height, bpp);
603
QImage shot = QImage(width, height, QImage::Format_RGB32);
604
display.TakeScreenShot(i, shot.bits(), shot.width(), shot.height());
605
shot.save(QFile::encodeName(strFileName), "PNG");
608
/* Warn the user about GURU: */
609
if (msgCenter().remindAboutGuruMeditation(console, QDir::toNativeSeparators(strLogFolder)))
613
msgCenter().cannotStopMachine(console);
617
case KMachineState_Paused:
618
case KMachineState_TeleportingPausedVM:
620
QAction *pPauseAction = gActionPool->action(UIActionIndexRuntime_Toggle_Pause);
621
if (!pPauseAction->isChecked())
623
/* Was paused from CSession side: */
624
pPauseAction->blockSignals(true);
625
pPauseAction->setChecked(true);
626
pPauseAction->blockSignals(false);
630
case KMachineState_Running:
631
case KMachineState_Teleporting:
632
case KMachineState_LiveSnapshotting:
634
QAction *pPauseAction = gActionPool->action(UIActionIndexRuntime_Toggle_Pause);
635
if (pPauseAction->isChecked())
637
/* Was resumed from CSession side: */
638
pPauseAction->blockSignals(true);
639
pPauseAction->setChecked(false);
640
pPauseAction->blockSignals(false);
644
case KMachineState_PoweredOff:
645
case KMachineState_Saved:
646
case KMachineState_Teleported:
647
case KMachineState_Aborted:
649
/* Close VM if it was turned off and closure allowed: */
650
if (!isPreventAutoClose())
652
/* VM has been powered off, saved or aborted, no matter
653
* internally or externally. We must *safely* close VM window(s): */
654
QTimer::singleShot(0, uisession(), SLOT(sltCloseVirtualSession()));
659
case KMachineState_Starting:
660
case KMachineState_Restoring:
661
case KMachineState_TeleportingIn:
663
/* The keyboard handler may wish to do some release logging on startup.
664
* Tell it that the logger is now active. */
665
doXKeyboardLogging(QX11Info::display());
674
/* Update Dock Overlay: */
676
#endif /* Q_WS_MAC */
679
void UIMachineLogic::sltAdditionsStateChanged()
681
/* Variable flags: */
682
bool fIsSupportsGraphics = uisession()->isGuestSupportsGraphics();
683
bool fIsSupportsSeamless = uisession()->isGuestSupportsSeamless();
685
/* Update action states: */
686
gActionPool->action(UIActionIndexRuntime_Toggle_GuestAutoresize)->setEnabled(fIsSupportsGraphics);
687
gActionPool->action(UIActionIndexRuntime_Toggle_Seamless)->setEnabled(fIsSupportsSeamless);
689
/* Check if we should enter some extended mode: */
690
sltCheckRequestedModes();
693
void UIMachineLogic::sltMouseCapabilityChanged()
695
/* Variable falgs: */
696
bool fIsMouseSupportsAbsolute = uisession()->isMouseSupportsAbsolute();
697
bool fIsMouseSupportsRelative = uisession()->isMouseSupportsRelative();
698
bool fIsMouseHostCursorNeeded = uisession()->isMouseHostCursorNeeded();
700
/* Update action state: */
701
QAction *pAction = gActionPool->action(UIActionIndexRuntime_Toggle_MouseIntegration);
702
pAction->setEnabled(fIsMouseSupportsAbsolute && fIsMouseSupportsRelative && !fIsMouseHostCursorNeeded);
703
if (fIsMouseHostCursorNeeded)
704
pAction->setChecked(false);
707
void UIMachineLogic::sltUSBDeviceStateChange(const CUSBDevice &device, bool fIsAttached, const CVirtualBoxErrorInfo &error)
709
bool fSuccess = error.isNull();
714
msgCenter().cannotAttachUSBDevice(session().GetConsole(), vboxGlobal().details(device), error);
716
msgCenter().cannotDetachUSBDevice(session().GetConsole(), vboxGlobal().details(device), error);
720
void UIMachineLogic::sltRuntimeError(bool fIsFatal, const QString &strErrorId, const QString &strMessage)
722
msgCenter().showRuntimeError(session().GetConsole(), fIsFatal, strErrorId, strMessage);
726
void UIMachineLogic::sltShowWindows()
728
for (int i=0; i < m_machineWindowsList.size(); ++i)
730
UIMachineWindow *pMachineWindow = m_machineWindowsList.at(i);
731
/* Dunno what Qt thinks a window that has minimized to the dock
732
* should be - it is not hidden, neither is it minimized. OTOH it is
733
* marked shown and visible, but not activated. This latter isn't of
734
* much help though, since at this point nothing is marked activated.
735
* I might have overlooked something, but I'm buggered what if I know
736
* what. So, I'll just always show & activate the stupid window to
737
* make it get out of the dock when the user wishes to show a VM. */
738
pMachineWindow->machineWindow()->raise();
739
pMachineWindow->machineWindow()->activateWindow();
742
#endif /* Q_WS_MAC */
825
void UIMachineLogic::cleanupActionGroups()
744
829
void UIMachineLogic::sltCheckRequestedModes()
937
/* Get current machine: */
852
938
CMachine machine = session().GetMachine();
854
VBoxTakeSnapshotDlg dlg(defaultMachineWindow()->machineWindow(), machine);
940
/* Create take-snapshot dialog: */
941
QPointer<VBoxTakeSnapshotDlg> pDlg = new VBoxTakeSnapshotDlg(activeMachineWindow(), machine);
943
/* Assign corresponding icon: */
856
944
QString strTypeId = machine.GetOSTypeId();
857
dlg.mLbIcon->setPixmap(vboxGlobal().vmGuestOSTypeIcon(strTypeId));
945
pDlg->mLbIcon->setPixmap(vboxGlobal().vmGuestOSTypeIcon(strTypeId));
859
/* Search for the max available filter index. */
947
/* Search for the max available filter index: */
860
948
QString strNameTemplate = QApplication::translate("UIMachineLogic", "Snapshot %1");
861
949
int iMaxSnapshotIndex = searchMaxSnapshotIndex(machine, machine.FindSnapshot(QString()), strNameTemplate);
862
dlg.mLeName->setText(strNameTemplate.arg(++ iMaxSnapshotIndex));
864
if (dlg.exec() == QDialog::Accepted)
950
pDlg->mLeName->setText(strNameTemplate.arg(++ iMaxSnapshotIndex));
952
/* Exec the dialog: */
953
bool fDialogAccepted = pDlg->exec() == QDialog::Accepted;
955
/* Is the dialog still valid? */
866
CConsole console = session().GetConsole();
868
CProgress progress = console.TakeSnapshot(dlg.mLeName->text().trimmed(), dlg.mTeDescription->toPlainText());
958
/* Acquire variables: */
959
QString strSnapshotName = pDlg->mLeName->text().trimmed();
960
QString strSnapshotDescription = pDlg->mTeDescription->toPlainText();
962
/* Destroy dialog early: */
965
/* Was the dialog accepted? */
872
/* Show the "Taking Snapshot" progress dialog */
873
msgCenter().showModalProgressDialog(progress, machine.GetName(), ":/progress_snapshot_create_90px.png", 0, true);
875
if (progress.GetResultCode() != 0)
876
msgCenter().cannotTakeSnapshot(progress);
968
/* Prepare the take-snapshot progress: */
969
CConsole console = session().GetConsole();
970
CProgress progress = console.TakeSnapshot(strSnapshotName, strSnapshotDescription);
973
/* Show the take-snapshot progress: */
974
msgCenter().showModalProgressDialog(progress, machine.GetName(), ":/progress_snapshot_create_90px.png", 0, true);
975
if (progress.GetResultCode() != 0)
976
msgCenter().cannotTakeSnapshot(progress);
979
msgCenter().cannotTakeSnapshot(console);
879
msgCenter().cannotTakeSnapshot(console);
882
/* Restore the running state if needed. */
983
/* Restore the running state if needed: */
885
986
/* Make sure machine-state-change callback is processed: */
993
void UIMachineLogic::sltTakeScreenshot()
995
/* Do not process if window(s) missed! */
996
if (!isMachineWindowsCreated())
999
/* Which image formats for writing does this Qt version know of? */
1000
QList<QByteArray> formats = QImageWriter::supportedImageFormats();
1001
QStringList filters;
1002
/* Build a filters list out of it. */
1003
for (int i = 0; i < formats.size(); ++i)
1005
const QString &s = formats.at(i) + " (*." + formats.at(i).toLower() + ")";
1006
/* Check there isn't an entry already (even if it just uses another capitalization) */
1007
if (filters.indexOf(QRegExp(QRegExp::escape(s), Qt::CaseInsensitive)) == -1)
1010
/* Try to select some common defaults. */
1012
int i = filters.indexOf(QRegExp(".*png.*", Qt::CaseInsensitive));
1015
i = filters.indexOf(QRegExp(".*jpe+g.*", Qt::CaseInsensitive));
1017
i = filters.indexOf(QRegExp(".*bmp.*", Qt::CaseInsensitive));
1021
filters.prepend(filters.takeAt(i));
1022
strFilter = filters.first();
1026
/* Due to Qt bug, modal QFileDialog appeared above the active machine-window
1027
* does not retreive the focus from the currently focused machine-view,
1028
* as the result guest keyboard remains captured, so we should
1029
* clear the focus from this machine-view initially: */
1030
if (activeMachineWindow())
1031
activeMachineWindow()->machineView()->clearFocus();
1032
#endif /* Q_WS_WIN */
1034
/* Request the filename from the user. */
1035
const CMachine &machine = session().GetMachine();
1036
QFileInfo fi(machine.GetSettingsFilePath());
1037
QString strAbsolutePath(fi.absolutePath());
1038
QString strCompleteBaseName(fi.completeBaseName());
1039
QString strStart = QDir(strAbsolutePath).absoluteFilePath(strCompleteBaseName);
1040
QString strFilename = QIFileDialog::getSaveFileName(strStart,
1042
activeMachineWindow(),
1043
tr("Select a filename for the screenshot ..."),
1045
true /* resolve symlinks */,
1046
true /* confirm overwrite */);
1049
/* Due to Qt bug, modal QFileDialog appeared above the active machine-window
1050
* does not retreive the focus from the currently focused machine-view,
1051
* as the result guest keyboard remains captured, so we already
1052
* cleared the focus from this machine-view and should return
1053
* that focus finally: */
1054
if (activeMachineWindow())
1055
activeMachineWindow()->machineView()->setFocus();
1056
#endif /* Q_WS_WIN */
1058
/* Do the screenshot. */
1059
if (!strFilename.isEmpty())
1060
takeScreenshot(strFilename, strFilter.split(" ").value(0, "png"));
892
1063
void UIMachineLogic::sltShowInformationDialog()
894
1065
/* Do not process if window(s) missed! */
937
1108
if (!isMachineWindowsCreated())
940
/* Propose to close default machine window: */
941
defaultMachineWindow()->sltTryClose();
1111
/* Do not try to close machine-window if restricted: */
1112
if (isPreventAutoClose())
1115
/* First, we have to close/hide any opened modal & popup application widgets.
1116
* We have to make sure such window is hidden even if close-event was rejected.
1117
* We are re-throwing this slot if any widget present to test again.
1118
* If all opened widgets are closed/hidden, we can try to close machine-window: */
1119
QWidget *pWidget = QApplication::activeModalWidget() ? QApplication::activeModalWidget() :
1120
QApplication::activePopupWidget() ? QApplication::activePopupWidget() : 0;
1123
/* Closing/hiding all we found: */
1125
if (!pWidget->isHidden())
1127
QTimer::singleShot(0, this, SLOT(sltClose()));
1131
/* Try to close active machine-window: */
1132
activeMachineWindow()->close();
944
1135
void UIMachineLogic::sltOpenVMSettingsDialog(const QString &strCategory /* = QString() */)
1628
void UIMachineLogic::sltPrepareSharedClipboardMenu()
1630
/* Get and check the sender menu object: */
1631
QMenu *pMenu = qobject_cast<QMenu*>(sender());
1632
QMenu *pSharedClipboardMenu = gActionPool->action(UIActionIndexRuntime_Menu_SharedClipboard)->menu();
1633
AssertMsg(pMenu == pSharedClipboardMenu, ("This slot should only be called on hovering Shared Clipboard menu!\n"));
1634
Q_UNUSED(pSharedClipboardMenu);
1637
if (!m_pSharedClipboardActions)
1639
m_pSharedClipboardActions = new QActionGroup(this);
1640
for (int i = KClipboardMode_Disabled; i < KClipboardMode_Max; ++i)
1642
KClipboardMode mode = (KClipboardMode)i;
1643
QAction *pAction = new QAction(gpConverter->toString(mode), m_pSharedClipboardActions);
1644
pMenu->addAction(pAction);
1645
pAction->setData(QVariant::fromValue(mode));
1646
pAction->setCheckable(true);
1647
pAction->setChecked(session().GetMachine().GetClipboardMode() == mode);
1649
connect(m_pSharedClipboardActions, SIGNAL(triggered(QAction*)),
1650
this, SLOT(sltChangeSharedClipboardType(QAction*)));
1652
/* Subsequent runs: */
1654
foreach (QAction *pAction, m_pSharedClipboardActions->actions())
1655
if (pAction->data().value<KClipboardMode>() == session().GetMachine().GetClipboardMode())
1656
pAction->setChecked(true);
1659
void UIMachineLogic::sltChangeSharedClipboardType(QAction *pAction)
1661
/* Assign new mode (without save): */
1662
KClipboardMode mode = pAction->data().value<KClipboardMode>();
1663
session().GetMachine().SetClipboardMode(mode);
1666
void UIMachineLogic::sltPrepareDragAndDropMenu()
1668
/* Get and check the sender menu object: */
1669
QMenu *pMenu = qobject_cast<QMenu*>(sender());
1670
QMenu *pDragAndDropMenu = gActionPool->action(UIActionIndexRuntime_Menu_DragAndDrop)->menu();
1671
AssertMsg(pMenu == pDragAndDropMenu, ("This slot should only be called on hovering Drag'n'drop menu!\n"));
1672
Q_UNUSED(pDragAndDropMenu);
1675
if (!m_pDragAndDropActions)
1677
m_pDragAndDropActions = new QActionGroup(this);
1678
for (int i = KDragAndDropMode_Disabled; i < KDragAndDropMode_Max; ++i)
1680
KDragAndDropMode mode = (KDragAndDropMode)i;
1681
QAction *pAction = new QAction(gpConverter->toString(mode), m_pDragAndDropActions);
1682
pMenu->addAction(pAction);
1683
pAction->setData(QVariant::fromValue(mode));
1684
pAction->setCheckable(true);
1685
pAction->setChecked(session().GetMachine().GetDragAndDropMode() == mode);
1687
connect(m_pDragAndDropActions, SIGNAL(triggered(QAction*)),
1688
this, SLOT(sltChangeDragAndDropType(QAction*)));
1690
/* Subsequent runs: */
1692
foreach (QAction *pAction, m_pDragAndDropActions->actions())
1693
if (pAction->data().value<KDragAndDropMode>() == session().GetMachine().GetDragAndDropMode())
1694
pAction->setChecked(true);
1697
void UIMachineLogic::sltChangeDragAndDropType(QAction *pAction)
1699
/* Assign new mode (without save): */
1700
KDragAndDropMode mode = pAction->data().value<KDragAndDropMode>();
1701
session().GetMachine().SetDragAndDropMode(mode);
1427
1704
void UIMachineLogic::sltSwitchVrde(bool fOn)
1429
1706
/* Enable VRDE server if possible: */
1465
1734
return uisession()->sltInstallGuestAdditionsFrom(path);
1468
/* Download the required image */
1469
int result = msgCenter().cannotFindGuestAdditions(QDir::toNativeSeparators(strSrc1), QDir::toNativeSeparators(strSrc2));
1470
if (result == QIMessageBox::Yes)
1472
const QString &source = QString("http://download.virtualbox.org/virtualbox/%1/").arg(vboxGlobal().vboxVersionStringNormalized()) + name;
1473
const QString &target = QDir(vboxGlobal().virtualBox().GetHomeFolder()).absoluteFilePath(name);
1737
/* If downloader is running already: */
1738
if (UIDownloaderAdditions::current())
1740
/* Just show network access manager: */
1741
gNetworkManager->show();
1743
/* Else propose to download additions: */
1744
else if (msgCenter().cannotFindGuestAdditions())
1746
/* Create Additions downloader: */
1475
1747
UIDownloaderAdditions *pDl = UIDownloaderAdditions::create();
1476
/* Configure the additions downloader. */
1477
pDl->setSource(source);
1478
pDl->setTarget(target);
1479
pDl->setAction(gActionPool->action(UIActionIndexRuntime_Simple_InstallGuestTools));
1480
pDl->setParentWidget(mainMachineWindow()->machineWindow());
1481
/* After the download is finished the user may like to install the
1483
connect(pDl, SIGNAL(sigDownloadFinished(const QString&)),
1484
uisession(), SLOT(sltInstallGuestAdditionsFrom(const QString&)));
1485
/* Some of the modes may show additional info of the download progress: */
1486
emit sigDownloaderAdditionsCreated();
1487
/* Start the download: */
1748
/* After downloading finished => propose to install the Additions: */
1749
connect(pDl, SIGNAL(sigDownloadFinished(const QString&)), uisession(), SLOT(sltInstallGuestAdditionsFrom(const QString&)));
1750
/* Start downloading: */
1492
1755
#ifdef VBOX_WITH_DEBUGGER_GUI
1493
1757
void UIMachineLogic::sltPrepareDebugMenu()
1495
1759
/* The "Logging" item. */
1534
1804
cdebugger.SetLogEnabled(fState);
1808
void UIMachineLogic::sltShowLogDialog()
1810
/* Show VM Log Viewer: */
1811
UIVMLogViewer::showLogViewerFor(activeMachineWindow(), session().GetMachine());
1814
#endif /* VBOX_WITH_DEBUGGER_GUI */
1539
1816
#ifdef Q_WS_MAC
1540
1817
void UIMachineLogic::sltDockPreviewModeChanged(QAction *pAction)
1542
CMachine machine = m_pSession->session().GetMachine();
1819
CMachine machine = session().GetMachine();
1543
1820
if (!machine.isNull())
1545
1822
bool fEnabled = true;
1546
1823
if (pAction == gActionPool->action(UIActionIndexRuntime_Toggle_DockDisableMonitor))
1547
1824
fEnabled = false;
1549
machine.SetExtraData(VBoxDefs::GUI_RealtimeDockIconUpdateEnabled, fEnabled ? "true" : "false");
1826
machine.SetExtraData(GUI_RealtimeDockIconUpdateEnabled, fEnabled ? "true" : "false");
1550
1827
updateDockOverlay();
1554
1831
void UIMachineLogic::sltDockPreviewMonitorChanged(QAction *pAction)
1556
CMachine machine = m_pSession->session().GetMachine();
1833
CMachine machine = session().GetMachine();
1557
1834
if (!machine.isNull())
1559
1836
int monitor = pAction->data().toInt();
1560
machine.SetExtraData(VBoxDefs::GUI_RealtimeDockIconUpdateMonitor, QString::number(monitor));
1837
machine.SetExtraData(GUI_RealtimeDockIconUpdateMonitor, QString::number(monitor));
1561
1838
updateDockOverlay();
1604
1881
return iMaxIndex;
1884
void UIMachineLogic::takeScreenshot(const QString &strFile, const QString &strFormat /* = "png" */) const
1887
const CConsole &console = session().GetConsole();
1888
CDisplay display = console.GetDisplay();
1889
const int cGuestScreens = uisession()->session().GetMachine().GetMonitorCount();
1890
QList<QImage> images;
1891
ULONG uMaxWidth = 0;
1892
ULONG uMaxHeight = 0;
1893
/* First create screenshots of all guest screens and save them in a list.
1894
* Also sum the width of all images and search for the biggest image height. */
1895
for (int i = 0; i < cGuestScreens; ++i)
1900
display.GetScreenResolution(i, width, height, bpp);
1902
uMaxHeight = RT_MAX(uMaxHeight, height);
1903
QImage shot = QImage(width, height, QImage::Format_RGB32);
1904
display.TakeScreenShot(i, shot.bits(), shot.width(), shot.height());
1907
/* Create a image which will hold all sub images vertically. */
1908
QImage bigImg = QImage(uMaxWidth, uMaxHeight, QImage::Format_RGB32);
1909
QPainter p(&bigImg);
1912
for (int i = 0; i < images.size(); ++i)
1914
p.drawImage(w, 0, images.at(i));
1915
w += images.at(i).width();
1919
/* Save the big image in the requested format: */
1920
const QFileInfo fi(strFile);
1921
const QString &strPathWithoutSuffix = QDir(fi.absolutePath()).absoluteFilePath(fi.baseName());
1922
const QString &strSuffix = fi.suffix().isEmpty() ? strFormat : fi.suffix();
1923
bigImg.save(QDir::toNativeSeparators(QFile::encodeName(QString("%1.%2").arg(strPathWithoutSuffix, strSuffix))),
1924
strFormat.toAscii().constData());
1607
1927
#ifdef VBOX_WITH_DEBUGGER_GUI
1608
1928
bool UIMachineLogic::dbgCreated()