VBoxSelectorWnd.cpp revision 4097e9a552510336106b0f86c0ae712dfc97f53c
/** @file
*
* VBox frontends: Qt GUI ("VirtualBox"):
* VBoxSelectorWnd class implementation
*/
/*
* Copyright (C) 2006-2007 innotek GmbH
*
* This file is part of VirtualBox Open Source Edition (OSE), as
* available from http://www.virtualbox.org. This file is free software;
* General Public License as published by the Free Software Foundation,
* in version 2 as it comes in the "COPYING" file of the VirtualBox OSE
* distribution. VirtualBox OSE is distributed in the hope that it will
* be useful, but WITHOUT ANY WARRANTY of any kind.
*/
#include "VBoxProblemReporter.h"
#include "VBoxSelectorWnd.h"
#include "VBoxVMListBox.h"
#include "VBoxConsoleWnd.h"
#include "VBoxToolBar.h"
#include "VBoxSnapshotsWgt.h"
#include "VBoxNewVMWzd.h"
#include "VBoxDiskImageManagerDlg.h"
#include "VBoxVMSettingsDlg.h"
#include "VBoxGlobalSettingsDlg.h"
#include "VBoxVMLogViewer.h"
#include <qlabel.h>
#include <qtextbrowser.h>
#include <qmenubar.h>
#include <qpopupmenu.h>
#include <qmessagebox.h>
#include <qwidgetlist.h>
#include <qtabwidget.h>
#include <qwidgetstack.h>
#include <qbutton.h>
#include <qprocess.h>
#include <qlayout.h>
#include <qvbox.h>
#ifdef Q_WS_X11
#endif
// VBoxVMDetailsView class
////////////////////////////////////////////////////////////////////////////////
/**
* Two-page widget stack to represent VM details: one page for normal details
* and another one for inaccessibility errors.
*/
class VBoxVMDetailsView : public QWidgetStack
{
public:
void languageChange();
{
raiseWidget (0);
}
{
raiseWidget (1);
}
void setEmpty()
{
raiseWidget (0);
}
private slots:
{
/* QTextBrowser will try to get the URL from the mime source factory
* and show an empty "page" after a failure. Reset the text to avoid
* this. */
}
private:
void createErrPage();
};
, mRefreshButton (NULL)
{
/* create normal details page */
mDetailsText->setLinkUnderline (false);
/* make "transparent" */
addWidget (mDetailsText, 0);
}
void VBoxVMDetailsView::createErrPage()
{
/* create inaccessible details page */
if (mErrBox)
return;
mErrText->setLinkUnderline (false);
if (mRefreshAction)
{
QSizePolicy::Minimum));
}
QSizePolicy::Expanding));
}
void VBoxVMDetailsView::languageChange()
{
if (mErrLabel)
"The selected virtual machine is <i>inaccessible</i>. Please "
"inspect the error message shown below and press the "
"<b>Refresh</b> button if you want to repeat the accessibility "
"check:"));
if (mRefreshAction && mRefreshButton)
{
/* If we set the combination of the text label and icon
* below, we lose the Alt+R shortcut functionality... */
mRefreshButton->setUsesTextLabel (true);
}
}
// VBoxVMDescriptionPage class
////////////////////////////////////////////////////////////////////////////////
/**
* Comments page widget to represent VM comments.
*/
class VBoxVMDescriptionPage : public QWidget
{
public:
VBoxVMDescriptionPage (VBoxSelectorWnd *, const char *);
~VBoxVMDescriptionPage() {}
void languageChange();
void updateState();
private slots:
void goToSettings();
private:
};
const char *aName)
{
/* main layout */
/* mBrowser */
mBrowser->setLinkUnderline (false);
/* hidden by default */
/* always disabled */
mLabel->setEnabled (false);
/* button layout */
QSizePolicy::Minimum));
/* button */
"edit_description_disabled_16px.png"));
mBtnEdit->setUsesTextLabel (true);
QSizePolicy::Minimum));
/* apply language settings */
updateState();
}
/**
* The machine list @a aItem is used to access cached machine data w/o making
* unnecessary RPC calls.
*/
{
{
}
else
{
}
/* check initial machine and session states */
updateState();
}
void VBoxVMDescriptionPage::languageChange()
{
mBtnEdit->adjustSize();
}
/**
* Called by the parent from machineStateChanged() and sessionStateChanged()
* signal handlers. We cannot connect to these signals ourselves because we
* use the VBoxVMListBoxItem which needs to be properly updated by the parent
* first.
*/
void VBoxVMDescriptionPage::updateState()
{
/// @todo disabling the edit button for a saved VM will not be necessary
/// when we implement the selective VM Settings dialog, where only fields
/// that can be changed in the saved state, can be changed.
if (mItem)
{
}
else
mBtnEdit->setEnabled (false);
}
void VBoxVMDescriptionPage::goToSettings()
{
}
// VBoxSelectorWnd class
////////////////////////////////////////////////////////////////////////////////
/** \class VBoxSelectorWnd
*
* The VBoxSelectorWnd class is a VM selector window, one of two main VBox
* GUI windows.
*
* This window appears when the user starts the VirtualBox executable.
* It allows to view the list of configured VMs, their settings
* and the current state, create, reconfigure, delete and start VMs.
*/
/**
* Constructs the VM selector window.
*
* @param aSelf pointer to a variable where to store |this| right after
* this object's constructor is called (necessary to avoid
* recursion in VBoxGlobal::selectorWnd())
*/
, doneInaccessibleWarningOnce (false)
{
if (aSelf)
*aSelf = this;
statusBar();
/* application icon */
/* actions */
"vm_settings.png", "settings_16px.png",
"vm_settings_dis.png", "settings_dis_16px.png"));
"vm_delete.png", "delete_16px.png",
"vm_delete_dis.png", "delete_dis_16px.png"));
"vm_start.png", "start_16px.png",
"vm_start_dis.png", "start_dis_16px.png"));
"vm_discard.png", "discard_16px.png",
"vm_discard_dis.png", "discard_dis_16px.png"));
"refresh_16px.png", "refresh_disabled_16px.png"));
"show_logs_16px.png", "show_logs_disabled_16px.png"));
/* subwidgets */
/* central widget & horizontal layout */
/* left vertical box */
/* right vertical box */
/* VM list toolbar */
/* VM list box */
/* VM tab widget containing details and snapshots tabs */
/* VM details view */
/* VM snapshots list */
"take_snapshot_dis_16px.png"),
/* VM comments page */
"description_disabled_16px.png"),
/* add actions to the toolbar */
setUsesTextLabel (true);
setUsesBigPixmaps (true);
vmTools->addSeparator();
#ifdef Q_WS_MAC
vmTools->setMacStyle();
#endif
/* add actions to menubar */
/* restore the position of the window */
{
int x = 0, y = 0, w = 0, h = 0;
if (ok)
if (ok)
if (ok)
if (ok)
if (ok)
{
move (x, y);
if (max)
/* maximize if needed */
}
else
{
}
}
/* signals and slots connections */
this, SLOT (vmListBoxCurrentChanged()));
/* listen to media enumeration signals */
this, SLOT (mediaEnumStarted()));
/* connect VirtualBox callback events */
/* bring the VM list to the focus */
}
{
/* save the position of the window */
{
if (isMaximized())
}
}
//
// Public slots
/////////////////////////////////////////////////////////////////////////////
void VBoxSelectorWnd::fileDiskMgr()
{
}
void VBoxSelectorWnd::fileSettings()
{
{
else
{
// see whether the user has changed something or not
if (!(settings == s))
vboxGlobal().setSettings (s);
}
}
}
void VBoxSelectorWnd::fileExit()
{
close();
}
void VBoxSelectorWnd::vmNew()
{
{
/* wait until the list is updated by OnMachineRegistered() */
VBoxVMListBoxItem *item = 0;
while (!item)
{
qApp->processEvents();
}
/*
* we must use setSelected() instead of setCurrentItem() below because
* setCurrentItem() does nothing after the first item has been added
* to the list (since it is already the current one), but we still
* need currentChanged() to be emitted to sync things (QListBox doesn't
* emit currentChanged() when the current item index changes from -1
* to 0, i.e. when the first item is being added -- seems to be a Qt
* bug).
*/
}
}
/**
* Opens the VM settings dialog.
*
* @param aCategory Category to select in the settings dialog. See
* VBoxVMSettingsDlg::setup().
* @param aControl Widget name to select in the settings dialog. See
* VBoxVMSettingsDlg::setup().
*/
{
{
/* Assume it's a href from the Details HTML */
return;
}
// open a direct session to modify VM settings
return;
dlg.getFromMachine (m);
{
{
m.SaveSettings();
if (m.isOk())
{
}
else
{
}
}
else
{
}
}
}
void VBoxSelectorWnd::vmDelete()
{
{
bool ok = false;
if (item->accessible())
{
/* open a direct session to modify VM settings */
return;
/* detach all hard disks before unregistering */
{
{
}
}
/* commit changes */
else
ok = true;
}
else
ok = true;
if (ok)
{
{
/* delete machine settings */
/* remove the item shortly: cmachine it refers to is no longer valid! */
}
}
}
}
void VBoxSelectorWnd::vmStart()
{
/* we always get here when vmListBox emits the selected() signal,
* so we must explicitly check if the action is enabled or not. */
if (!vmStartAction->isEnabled())
return;
#if defined (VBOX_GUI_SEPARATE_VM_PROCESS)
("Must NOT be a VM console process"));
/* just switch to the VM window if it already exists */
if (item->canSwitchTo())
{
return;
}
("Machine must be PoweredOff/Saved/Aborted"));
{
return;
}
#if defined (Q_OS_WIN32)
/* allow the started VM process to make itself the foreground window */
#endif
#if defined (Q_WS_X11)
/* make sure the VM process will start on the same display as the Selector */
{
if (display)
}
#endif
{
return;
}
/* show the "VM spawning" progress dialog */
if (progress.GetResultCode() != 0)
#else // !VBOX_GUI_SEPARATE_VM_PROCESS
return;
hide();
#endif
}
void VBoxSelectorWnd::vmDiscard()
{
return;
/* open a session to modify VM settings */
{
return;
}
{
return;
}
}
void VBoxSelectorWnd::vmRefresh()
{
true /* aDetails */,
true /* aSnapshot */,
true /* aDescription */);
}
void VBoxSelectorWnd::vmShowLogs()
{
}
void VBoxSelectorWnd::refreshVMList()
{
}
bool aSnapshots,
bool aDescription)
{
}
void VBoxSelectorWnd::showHelpContents()
{
}
// Protected members
/////////////////////////////////////////////////////////////////////////////
{
switch (e->type())
{
/* By handling every Resize and Move we keep track of the normal
* (non-minimized and non-maximized) window geometry. Shame on Qt
* that it doesn't provide this geometry in its public APIs. */
{
WindowFullScreen)) == 0)
break;
}
{
WindowFullScreen)) == 0)
normal_pos = pos();
break;
}
case QEvent::LanguageChange:
{
break;
}
default:
break;
}
return QMainWindow::event (e);
}
// Private members
/////////////////////////////////////////////////////////////////////////////
/**
* Sets the strings of the subwidgets using the current
* language.
*/
void VBoxSelectorWnd::languageChange()
{
#ifdef VBOX_OSE
#else
#endif
/* note: Snapshots and Details tabs are changed dynamically by
* vmListBoxCurrentChanged() */
/* ensure the details and screenshot view are updated */
#ifdef Q_WS_MAC
/*
* Macification: Getting the right menu as application preference menu item.
*
* QMenuBar::isCommand() in qmenubar_mac.cpp doesn't recognize "Setting"(s)
* unless it's in the first position. So, we use the Mac term here to make
* sure we get picked instead of the VM settings.
*
* Now, since both QMenuBar and we translate these strings, it's going to
* be really interesting to see how this plays on non-english systems...
*/
#else
/*
* ...and on other platforms we use "Preferences" as well. The #ifdef is
* left because of the possible localization problems on Mac we first need
* to figure out.
*/
#endif
/* Note: vmStartAction text is set up in vmListBoxCurrentChanged() */
tr ("Discard the saved state of the selected virtual machine"));
tr ("Refresh the accessibility state of the selected virtual machine"));
tr ("Show the log files of the selected virtual machine"));
tr ("Open the browser and go to the VirtualBox product web site"));
tr ("Open VirtualBox registration form"));
tr ("Cause all suppressed warnings and messages to be shown again"));
}
//
// Private slots
/////////////////////////////////////////////////////////////////////////////
bool aRefreshSnapshots,
bool aRefreshDescription)
{
{
/* selected always follows current */
}
{
if (aRefreshDetails)
{
modifyEnabled /* withLinks */));
}
if (aRefreshSnapshots)
{
/* update the snapshots tab name */
if (count)
/* refresh the snapshots widget */
vmSnapshotsWgt->setMachine (m);
/* ensure the tab is enabled */
}
if (aRefreshDescription)
{
/* update the description tab name */
/* refresh the description widget */
/* ensure the tab is enabled */
}
/* change the Start button text accordingly */
{
tr ("Switch to the window of the selected virtual machine"));
}
else
{
tr ("Start the selected virtual machine"));
}
/* disable Refresh for accessible machines */
vmRefreshAction->setEnabled (false);
/* enable the show log item for the selected vm */
vmShowLogsAction->setEnabled (true);
}
else
{
/* Note that the machine becomes inaccessible (or if the last VM gets
* deleted), we have to update all fields, ignoring input
* arguments. */
if (item)
{
/* the VM is inaccessible */
vmRefreshAction->setEnabled (true);
}
else
{
/* default HTML support in Qt is terrible so just try to get
* something really simple */
(tr ("<h3>"
"Welcome to VirtualBox!</h3>"
"<p>The left part of this window is intended to display "
"a list of all virtual machines on your computer. "
"The list is empty now because you haven't created any virtual "
"machines yet."
"<img src=welcome.png align=right/></p>"
"<p>In order to create a new virtual machine, press the "
"<b>New</b> button in the main tool bar located "
"at the top of the window.</p>"
"<p>You can press the <b>F1</b> key to get instant help, "
"or visit "
"<a href=http://www.virtualbox.org>www.virtualbox.org</a> "
"for the latest information and news.</p>"));
vmRefreshAction->setEnabled (false);
}
/* empty and disable other tabs */
/* disable modify actions */
vmConfigAction->setEnabled (false);
vmDiscardAction->setEnabled (false);
/* change the Start button text accordingly */
tr ("Start the selected virtual machine"));
vmStartAction->setEnabled (false);
/* disable the show log item for the selected vm */
vmShowLogsAction->setEnabled (false);
}
}
void VBoxSelectorWnd::mediaEnumStarted()
{
/* refresh the current details to pick up hard disk sizes */
vmListBoxCurrentChanged (true /* aRefreshDetails */);
}
{
/* refresh the current details to pick up hard disk sizes */
vmListBoxCurrentChanged (true /* aRefreshDetails */);
/* we warn about inaccessible media only once (after media emumeration
* started from main() at startup), to avoid annoying the user */
return;
doneInaccessibleWarningOnce = true;
do
{
/* ignore the signal if a modal widget is currently active (we won't be
* able to properly show the modeless VDI manager window in this case) */
if (QApplication::activeModalWidget())
break;
/* ignore the signal if a VBoxDiskImageManagerDlg window is active */
if (qApp->activeWindow() &&
break;
/* look for at least one inaccessible media */
break;
{
/* Show the VDM dialog but don't refresh once more after a
* just-finished refresh */
}
}
while (0);
}
{
refreshVMItem (e.id,
false /* aDetails */,
false /* aSnapshots */,
false /* aDescription */);
/* simulate a state change signal */
}
{
refreshVMItem (e.id,
true /* aDetails */,
false /* aSnapshots */,
true /* aDescription */);
}
{
if (e.registered)
{
if (!m.isNull())
{
new VBoxVMListBoxItem (vmListBox, m);
}
/* m.isNull() is ok (theoretically, the machine could have been
* already deregistered by some other client at this point) */
}
else
{
if (item)
/* item = 0 is ok (if we originated this event then the item
* has been already removed) */
}
}
{
refreshVMItem (e.id,
true /* aDetails */,
false /* aSnapshots */,
false /* aDescription */);
/* simulate a state change signal */
}
{
false /* aDetails */,
true /* aSnapshot */,
false /* aDescription */);
}
#include "VBoxSelectorWnd.moc"