Changeset 30868 in vbox
- Timestamp:
- Jul 16, 2010 9:42:12 AM (15 years ago)
- Location:
- trunk/src/VBox/Frontends/VirtualBox
- Files:
-
- 7 added
- 9 edited
- 3 copied
- 11 moved
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Frontends/VirtualBox/Makefile.kmk
r30753 r30868 148 148 endif 149 149 ifdef VBOX_BLEEDING_EDGE 150 VirtualBox_src/ VBoxSelectorWnd.cpp_DEFS += \150 VirtualBox_src/selector/VBoxSelectorWnd.cpp_DEFS += \ 151 151 VBOX_BLEEDING_EDGE=\"$(VBOX_BLEEDING_EDGE)\" 152 152 VirtualBox_src/runtime/UIMachineWindow.cpp_DEFS += \ … … 174 174 ./src/X11 \ 175 175 ./src/darwin \ 176 ./src/selector \ 176 177 ./src/runtime \ 177 178 ./src/runtime/normal \ … … 246 247 src/VBoxGlobalSettings.h \ 247 248 src/VBoxMediaManagerDlg.h \ 248 src/VBoxSelectorWnd.h \249 249 src/VBoxSnapshotDetailsDlg.h \ 250 src/VBoxSnapshotsWgt.h \251 250 src/VBoxTakeSnapshotDlg.h \ 252 251 src/VBoxUpdateDlg.h \ 253 252 src/VBoxVMInformationDlg.h \ 254 src/UIVMListView.h \255 src/UIVirtualBoxEventHandler.h \256 253 src/VBoxVMLogViewer.h \ 257 254 src/globals/VBoxGlobal.h \ … … 310 307 src/wizards/exportappliance/UIExportApplianceWzd.h \ 311 308 src/wizards/importappliance/UIImportApplianceWzd.h \ 309 src/widgets/UIBar.h \ 312 310 src/widgets/UIDownloader.h \ 313 311 src/widgets/UIDownloaderAdditions.h \ 314 312 src/widgets/UIDownloaderUserManual.h \ 313 src/widgets/UIPopupBox.h \ 315 314 src/widgets/UISpacerWidgets.h \ 316 315 src/widgets/UISpecialControls.h \ … … 327 326 src/widgets/VBoxProgressDialog.h \ 328 327 src/widgets/VBoxWarningPane.h \ 328 src/selector/UIVMDesktop.h \ 329 src/selector/UIVMListView.h \ 330 src/selector/UIVMPreviewWindow.h \ 331 src/selector/UIVirtualBoxEventHandler.h \ 332 src/selector/VBoxSelectorWnd.h \ 333 src/selector/VBoxSnapshotsWgt.h \ 329 334 src/runtime/UIMachine.h \ 330 335 src/runtime/UISession.h \ … … 361 366 # Sources containing local definitions of classes that use the Q_OBJECT macro. 362 367 VirtualBox_QT_MOCSRCS = \ 363 src/VBoxSelectorWnd.cpp \364 368 src/VBoxMediaManagerDlg.cpp \ 369 src/globals/UIExtraDataEventHandler.cpp \ 370 src/extensions/QISplitter.cpp \ 371 src/selector/UIVMDesktop.cpp \ 365 372 src/runtime/UIActionsPool.cpp \ 366 src/runtime/UIMachineMenuBar.cpp \367 373 src/runtime/UIIndicatorsPool.cpp \ 368 374 src/runtime/UIMachine.cpp \ 369 375 src/runtime/UIMachineLogic.cpp \ 370 src/extensions/QISplitter.cpp \ 371 src/globals/UIExtraDataEventHandler.cpp 376 src/runtime/UIMachineMenuBar.cpp 372 377 373 378 ifdef VBOX_WITH_XPCOM … … 393 398 src/VBoxMediaManagerDlg.cpp \ 394 399 src/VBoxMedium.cpp \ 395 src/VBoxSelectorWnd.cpp \396 400 src/VBoxSnapshotDetailsDlg.cpp \ 397 src/VBoxSnapshotsWgt.cpp \398 401 src/VBoxTakeSnapshotDlg.cpp \ 399 402 src/VBoxUpdateDlg.cpp \ 400 403 src/VBoxVMInformationDlg.cpp \ 401 src/UIVMItem.cpp \402 src/UIVMListView.cpp \403 src/UIVirtualBoxEventHandler.cpp \404 404 src/VBoxVMLogViewer.cpp \ 405 405 src/globals/COMDefs.cpp \ … … 459 459 src/wizards/exportappliance/UIExportApplianceWzd.cpp \ 460 460 src/wizards/importappliance/UIImportApplianceWzd.cpp \ 461 src/widgets/UIBar.cpp \ 461 462 src/widgets/UIDownloader.cpp \ 462 463 src/widgets/UIDownloaderAdditions.cpp \ 463 464 src/widgets/UIDownloaderUserManual.cpp \ 465 src/widgets/UIPopupBox.cpp \ 464 466 src/widgets/UISpecialControls.cpp \ 465 467 src/widgets/VBoxApplianceEditorWgt.cpp \ … … 476 478 src/widgets/VBoxProgressDialog.cpp \ 477 479 src/widgets/VBoxWarningPane.cpp \ 480 src/selector/UIVMDesktop.cpp \ 481 src/selector/UIVMItem.cpp \ 482 src/selector/UIVMListView.cpp \ 483 src/selector/UIVMPreviewWindow.cpp \ 484 src/selector/UIVirtualBoxEventHandler.cpp \ 485 src/selector/VBoxSelectorWnd.cpp \ 486 src/selector/VBoxSnapshotsWgt.cpp \ 478 487 src/runtime/UIMachine.cpp \ 479 488 src/runtime/UISession.cpp \ -
trunk/src/VBox/Frontends/VirtualBox/VBoxUI.pro
r28800 r30868 26 26 src/VBoxMediaManagerDlg.ui \ 27 27 src/VBoxSnapshotDetailsDlg.ui \ 28 src/VBoxSnapshotsWgt.ui \29 28 src/VBoxTakeSnapshotDlg.ui \ 30 29 src/VBoxUpdateDlg.ui \ … … 68 67 src/wizards/importappliance/UIImportApplianceWzdPage2.ui \ 69 68 src/wizards/registration/UIRegistrationWzdPage1.ui \ 70 src/widgets/VBoxApplianceEditorWgt.ui 69 src/widgets/VBoxApplianceEditorWgt.ui \ 70 src/selector/VBoxSnapshotsWgt.ui 71 71 72 72 TRANSLATIONS = \ -
trunk/src/VBox/Frontends/VirtualBox/src/extensions/QILabel.cpp
r28800 r30868 237 237 style()->drawPrimitive (QStyle::PE_FrameFocusRect, &option, &painter, this); 238 238 } 239 } 240 241 void QILabel::showEvent(QShowEvent *pEvent) 242 { 243 QLabel::showEvent(pEvent); 244 emit shown(); 239 245 } 240 246 -
trunk/src/VBox/Frontends/VirtualBox/src/extensions/QILabel.h
r28800 r30868 6 6 7 7 /* 8 * Copyright (C) 2006-20 09Oracle Corporation8 * Copyright (C) 2006-2010 Oracle Corporation 9 9 * 10 10 * This file is part of VirtualBox Open Source Edition (OSE), as … … 48 48 QString text() const; 49 49 50 signals: 51 void shown(); 52 50 53 public slots: 51 54 … … 64 67 void focusOutEvent (QFocusEvent *aEvent); 65 68 void paintEvent (QPaintEvent *aEvent); 69 void showEvent(QShowEvent *pEvent); 66 70 67 71 private: -
trunk/src/VBox/Frontends/VirtualBox/src/extensions/QISplitter.cpp
r30087 r30868 18 18 */ 19 19 20 /* Local includes */ 21 #include "QISplitter.h" 22 20 23 /* Global includes */ 21 24 #include <QApplication> … … 23 26 #include <QPainter> 24 27 #include <QPaintEvent> 25 26 /* Local includes */27 #include "QISplitter.h"28 28 29 29 /* A simple shaded line. */ … … 121 121 } 122 122 123 QISplitter::QISplitter(Qt::Orientation orientation /* = Qt::Horizontal */, QWidget *pParent /* = 0 */)123 QISplitter::QISplitter(Qt::Orientation orientation, QWidget *pParent /* = 0 */) 124 124 : QSplitter(orientation, pParent) 125 125 , m_fPolished(false) -
trunk/src/VBox/Frontends/VirtualBox/src/extensions/QISplitter.h
r30087 r30868 32 32 33 33 QISplitter(QWidget *pParent = 0); 34 QISplitter(Qt::Orientation orientation = Qt::Horizontal, QWidget *pParent = 0);34 QISplitter(Qt::Orientation orientation, QWidget *pParent = 0); 35 35 36 36 void setHandleType(Type type) { m_type = type; } -
trunk/src/VBox/Frontends/VirtualBox/src/globals/VBoxDefs.cpp
r30753 r30868 44 44 const char* VBoxDefs::GUI_PermanentSharedFoldersAtRuntime = "GUI/PermanentSharedFoldersAtRuntime"; 45 45 const char* VBoxDefs::GUI_LanguageId = "GUI/LanguageID"; 46 const char* VBoxDefs::GUI_PreviewUpdate = "GUI/PreviewUpdate"; 47 const char* VBoxDefs::GUI_DetailsPageBoxes = "GUI/DetailsPageBoxes"; 46 48 #ifdef Q_WS_X11 47 49 const char* VBoxDefs::GUI_LicenseKey = "GUI/LicenseAgreed"; -
trunk/src/VBox/Frontends/VirtualBox/src/globals/VBoxDefs.h
r30753 r30868 122 122 static const char* GUI_PermanentSharedFoldersAtRuntime; 123 123 static const char* GUI_LanguageId; 124 static const char* GUI_PreviewUpdate; 125 static const char* GUI_DetailsPageBoxes; 124 126 #ifdef Q_WS_X11 125 127 static const char* GUI_LicenseKey; -
trunk/src/VBox/Frontends/VirtualBox/src/selector/UIVMDesktop.cpp
r30798 r30868 1 /* $Id$ */ 1 2 /** @file 2 3 * 3 4 * VBox frontends: Qt GUI ("VirtualBox"): 4 * VBoxSelectorWndclass implementation5 * UIVMDesktop class implementation 5 6 */ 6 7 7 8 /* 8 * Copyright (C) 20 06-2010 Oracle Corporation9 * Copyright (C) 2010 Oracle Corporation 9 10 * 10 11 * This file is part of VirtualBox Open Source Edition (OSE), as … … 17 18 */ 18 19 19 #ifdef VBOX_WITH_PRECOMPILED_HEADERS 20 # include "precomp.h" 21 #else /* !VBOX_WITH_PRECOMPILED_HEADERS */ 22 #include "QISplitter.h" 23 #include "QITabWidget.h" 24 #include "UIExportApplianceWzd.h" 20 /* Local includes */ 21 #include "QILabel.h" 22 #include "UIBar.h" 25 23 #include "UIIconPool.h" 26 #include "UIIm portApplianceWzd.h"27 #include "UI NewVMWzd.h"24 #include "UIImageTools.h" 25 #include "UIPopupBox.h" 28 26 #include "UISpacerWidgets.h" 29 27 #include "UISpecialControls.h" 30 #include "UIVMListView.h" 31 #include "VBoxGlobal.h" 32 #include "VBoxMediaManagerDlg.h" 33 #include "VBoxProblemReporter.h" 34 #include "VBoxSelectorWnd.h" 35 #include "VBoxSettingsDialogSpecific.h" 28 #include "UIVMDesktop.h" 29 #include "UIVMItem.h" 30 #include "UIVMPreviewWindow.h" 31 #include "UIVirtualBoxEventHandler.h" 36 32 #include "VBoxSnapshotsWgt.h" 37 33 #include "VBoxToolBar.h" 34 38 35 #include "VBoxUtils.h" 39 #include "VBoxVMLogViewer.h" 40 #include "UIVirtualBoxEventHandler.h" 41 42 #include "UIDownloaderUserManual.h" 43 44 #ifdef Q_WS_X11 45 #include <iprt/env.h> 46 #endif 47 48 /* Qt includes */ 49 #include <QTextBrowser> 50 #include <QMenuBar> 51 #include <QMenu> 52 #include <QMenuItem> 36 37 /* Global includes */ 38 #include <QDir> 39 #include <QLabel> 40 #include <QScrollArea> 41 #include <QStackedLayout> 53 42 #include <QStackedWidget> 54 #include <QDesktopWidget>55 43 #include <QToolButton> 56 57 #include <iprt/buildconfig.h> 58 #include <VBox/version.h> 59 #endif /* !VBOX_WITH_PRECOMPILED_HEADERS */ 60 61 // VBoxVMDetailsView class 62 //////////////////////////////////////////////////////////////////////////////// 44 #include <QUrl> 45 46 #include <iprt/assert.h> 47 48 /* 49 * Todo: 50 * - dynamically change size of preview window! 51 */ 52 53 //#ifdef Q_WS_MAC 54 # define DARWIN_USE_TOOLBAR 55 //#endif /* Q_WS_MAC */ 56 57 static const QString sTableTpl = 58 "<table border=0 cellspacing=1 cellpadding=0>%1</table>"; 59 static const QString sSectionItemTpl1 = 60 "<tr><td width=40%><nobr><i>%1</i></nobr></td><td/><td/></tr>"; 61 static const QString sSectionItemTpl2 = 62 "<tr><td><nobr>%1:</nobr></td><td/><td>%2</td></tr>"; 63 // "<tr><td width=40%><nobr>%1:</nobr></td><td/><td>%2</td></tr>"; 64 static const QString sSectionItemTpl3 = 65 "<tr><td width=40%><nobr>%1</nobr></td><td/><td/></tr>"; 66 67 #ifdef Q_WS_MAC 68 static const int gsLeftMargin = 5; 69 static const int gsTopMargin = 5; 70 static const int gsRightMargin = 5; 71 static const int gsBottomMargin = 5; 72 #else /* Q_WS_MAC */ 73 static const int gsLeftMargin = 0; 74 static const int gsTopMargin = 5; 75 static const int gsRightMargin = 5; 76 static const int gsBottomMargin = 5; 77 #endif /* !Q_WS_MAC */ 63 78 64 79 /** 65 * Two-page widget stack to represent VM details: one page for normal details 66 * and another one for inaccessibility errors. 80 * UIDescriptionPagePrivate 67 81 */ 68 class VBoxVMDetailsView: public QIWithRetranslateUI<QStackedWidget>82 class UIDetailsPagePrivate : public QIWithRetranslateUI<QStackedWidget> 69 83 { 70 84 Q_OBJECT; 71 85 86 enum Section 87 { 88 GeneralSec, 89 SystemSec, 90 PreviewSec, 91 DisplaySec, 92 StorageSec, 93 AudioSec, 94 NetworkSec, 95 SerialPortsSec, 96 #ifdef VBOX_WITH_PARALLEL_PORTS 97 ParallelPortsSec, 98 #endif /* VBOX_WITH_PARALLEL_PORTS */ 99 USBSec, 100 SharedFoldersSec, 101 EndSec 102 }; 103 72 104 public: 73 105 74 VBoxVMDetailsView (QWidget *aParent, 75 QAction *aRefreshAction = NULL); 76 77 void setDetailsText (const QString &aText) 78 { 79 mDetailsText->setText (aText); 80 setCurrentIndex (0); 81 } 82 83 void setErrorText (const QString &aText) 84 { 106 UIDetailsPagePrivate(QWidget *aParent, QAction *aRefreshAction = 0); 107 ~UIDetailsPagePrivate(); 108 109 void setMachine(const CMachine& machine); 110 111 void setText(const QString &aText) 112 { 113 m_machine = CMachine(); 114 createTextPage(); 115 m_pText->setText(aText); 116 setCurrentIndex(indexOf(m_pText)); 117 } 118 119 void setErrorText(const QString &aText) 120 { 121 m_machine = CMachine(); 85 122 createErrPage(); 86 mErrText->setText (aText); 87 setCurrentIndex (1); 88 } 89 90 void setEmpty() 91 { 92 mDetailsText->setText (QString::null); 93 setCurrentIndex (0); 94 } 95 123 m_pErrText->setText(aText); 124 setCurrentIndex(indexOf(m_pErrBox)); 125 } 96 126 signals: 97 127 98 void linkClicked 128 void linkClicked(const QString &aURL); 99 129 100 130 protected: … … 104 134 private slots: 105 135 106 void gotLinkClicked (const QUrl &aURL) 107 { 108 emit linkClicked (aURL.toString()); 136 void sltUpdateGeneral(); 137 void sltUpdatePreview(); 138 void sltUpdateSystem(); 139 void sltUpdateDisplay(); 140 void sltUpdateStorage(); 141 void sltUpdateAudio(); 142 void sltUpdateNetwork(); 143 void sltUpdateSerialPorts(); 144 #ifdef VBOX_WITH_PARALLEL_PORTS 145 void sltUpdateParallelPorts(); 146 #endif /* VBOX_WITH_PARALLEL_PORTS */ 147 void sltUpdateUSB(); 148 void sltUpdateSharedFolders(); 149 150 void sltContextMenuRequested(const QPoint &pos); 151 152 void gotLinkClicked(const QUrl &aURL) 153 { 154 emit linkClicked(aURL.toString()); 109 155 } 110 156 111 157 private: 112 158 159 void createTextPage(); 113 160 void createErrPage(); 114 161 115 QRichTextBrowser *mDetailsText; 116 117 QWidget *mErrBox; 118 QLabel *mErrLabel; 119 QTextBrowser *mErrText; 162 /* Private member vars */ 163 CVirtualBox m_vbox; 164 CMachine m_machine; 165 166 /* Details view */ 167 QWidget *m_pDetails; 168 QHash<Section, QString> m_EDStrs; 169 QHash<Section, QAction*> m_actions; 170 QHash<Section, UIPopupBox*> m_secBoxes; 171 bool m_fChangeable; 172 bool m_fUSBAvailable; 173 174 /* Free text */ 175 QRichTextBrowser *m_pText; 176 177 /* Error text */ 178 QWidget *m_pErrBox; 179 QLabel *m_pErrLabel; 180 QTextBrowser *m_pErrText; 120 181 QToolButton *mRefreshButton; 121 182 QAction *mRefreshAction; 122 183 }; 123 184 124 VBoxVMDetailsView::VBoxVMDetailsView (QWidget *aParent, 125 QAction *aRefreshAction /* = NULL */) 126 : QIWithRetranslateUI<QStackedWidget> (aParent) 127 , mErrBox (NULL), mErrLabel (NULL), mErrText (NULL) 128 , mRefreshButton (NULL) 129 , mRefreshAction (aRefreshAction) 130 { 131 Assert (mRefreshAction); 132 133 /* create normal details page */ 134 135 mDetailsText = new QRichTextBrowser (mErrBox); 136 mDetailsText->setViewportMargins (10, 10, 10, 10); 137 mDetailsText->setFocusPolicy (Qt::StrongFocus); 138 mDetailsText->document()->setDefaultStyleSheet ("a { text-decoration: none; }"); 139 /* make "transparent" */ 140 mDetailsText->setFrameShape (QFrame::NoFrame); 141 mDetailsText->viewport()->setAutoFillBackground (false); 142 mDetailsText->setOpenLinks (false); 143 144 connect (mDetailsText, SIGNAL (anchorClicked (const QUrl &)), 145 this, SLOT (gotLinkClicked (const QUrl &))); 146 147 addWidget (mDetailsText); 148 } 149 150 void VBoxVMDetailsView::createErrPage() 151 { 152 /* create inaccessible details page */ 153 154 if (mErrBox) 185 UIDetailsPagePrivate::UIDetailsPagePrivate(QWidget *aParent, 186 QAction *aRefreshAction /* = 0 */) 187 : QIWithRetranslateUI<QStackedWidget>(aParent) 188 , m_vbox(vboxGlobal().virtualBox()) 189 , m_fChangeable(false) 190 , m_fUSBAvailable(true) 191 , m_pText(0) 192 , m_pErrBox(0), m_pErrLabel(0), m_pErrText(0) 193 , mRefreshButton(0) 194 , mRefreshAction(aRefreshAction) 195 { 196 Assert(mRefreshAction); 197 198 /* The names for the extra data list */ 199 m_EDStrs[GeneralSec] = "general"; 200 m_EDStrs[SystemSec] = "system"; 201 m_EDStrs[PreviewSec] = "preview"; 202 m_EDStrs[DisplaySec] = "display"; 203 m_EDStrs[StorageSec] = "storage"; 204 m_EDStrs[AudioSec] = "audio"; 205 m_EDStrs[NetworkSec] = "network"; 206 m_EDStrs[SerialPortsSec] = "serialPorts"; 207 #ifdef VBOX_WITH_PARALLEL_PORTS 208 m_EDStrs[ParallelPortsSec] = "parallelPorts"; 209 #endif /* VBOX_WITH_PARALLEL_PORTS */ 210 m_EDStrs[USBSec] = "usb"; 211 m_EDStrs[SharedFoldersSec] = "sharedFolders"; 212 213 QScrollArea *pSArea = new QScrollArea(this); 214 pSArea->setFrameStyle(QFrame::NoFrame); 215 m_pDetails = new QWidget(this); 216 QVBoxLayout *pMainLayout = new QVBoxLayout(m_pDetails); 217 pMainLayout->setContentsMargins(gsLeftMargin, gsTopMargin, gsRightMargin, gsBottomMargin); 218 219 /* Create the context menu, which allows showing/hiding of the boxes */ 220 m_pDetails->setContextMenuPolicy(Qt::CustomContextMenu); 221 connect(m_pDetails, SIGNAL(customContextMenuRequested(const QPoint&)), 222 this, SLOT(sltContextMenuRequested(const QPoint&))); 223 for(int i = 0; i < EndSec; ++i) 224 { 225 /* Create the context menu actions */ 226 QAction *pAction = new QAction(this); 227 pAction->setData(i); 228 pAction->setCheckable(true); 229 m_actions[static_cast<Section>(i)] = pAction; 230 231 /* Create the popup boxes */ 232 UIPopupBox *pPopup = new UIPopupBox(this); 233 connect(pPopup, SIGNAL(titleClicked(const QString)), 234 this, SIGNAL(linkClicked(const QString))); 235 pPopup->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed); 236 m_secBoxes[static_cast<Section>(i)] = pPopup; 237 } 238 239 /* General */ 240 { 241 QILabel *pLabel= new QILabel(m_secBoxes.value(GeneralSec)); 242 connect(pLabel, SIGNAL(shown()), 243 this, SLOT(sltUpdateGeneral())); 244 m_secBoxes.value(GeneralSec)->setTitleIcon(UIIconPool::iconSet(":/machine_16px.png")); 245 m_secBoxes.value(GeneralSec)->setTitleLink("#general"); 246 m_secBoxes.value(GeneralSec)->setContentWidget(pLabel); 247 m_secBoxes.value(GeneralSec)->hide(); 248 } 249 250 /* System */ 251 { 252 QILabel *pLabel= new QILabel(this); 253 connect(pLabel, SIGNAL(shown()), 254 this, SLOT(sltUpdateSystem())); 255 m_secBoxes.value(SystemSec)->setTitleIcon(UIIconPool::iconSet(":/chipset_16px.png")); 256 m_secBoxes.value(SystemSec)->setTitleLink("#system"); 257 m_secBoxes.value(SystemSec)->setContentWidget(pLabel); 258 m_secBoxes.value(SystemSec)->hide(); 259 } 260 261 /* Preview */ 262 { 263 UIVMPreviewWindow *pWidget = new UIVMPreviewWindow(this); 264 m_secBoxes.value(PreviewSec)->setTitleIcon(UIIconPool::iconSet(":/machine_16px.png")); 265 m_secBoxes.value(PreviewSec)->setContentWidget(pWidget); 266 m_secBoxes.value(PreviewSec)->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); 267 /* Make sure the width is always the same, regardless if the preview is 268 * shown or not. */ 269 m_secBoxes.value(PreviewSec)->setFixedWidth(m_secBoxes.value(PreviewSec)->sizeHint().width()); 270 m_secBoxes.value(PreviewSec)->hide(); 271 } 272 273 QHBoxLayout *tt1 = new QHBoxLayout(); 274 QVBoxLayout *tt2 = new QVBoxLayout(); 275 tt2->addWidget(m_secBoxes.value(GeneralSec)); 276 tt2->addWidget(m_secBoxes.value(SystemSec)); 277 tt2->addStretch(1); 278 tt1->addLayout(tt2); 279 QVBoxLayout *tt3 = new QVBoxLayout(); 280 tt3->addWidget(m_secBoxes.value(PreviewSec)); 281 tt3->addStretch(1); 282 tt1->addLayout(tt3); 283 pMainLayout->addLayout(tt1); 284 285 /* Display */ 286 { 287 QILabel *pLabel= new QILabel(this); 288 connect(pLabel, SIGNAL(shown()), 289 this, SLOT(sltUpdateDisplay())); 290 m_secBoxes.value(DisplaySec)->setTitleIcon(UIIconPool::iconSet(":/vrdp_16px.png")); 291 m_secBoxes.value(DisplaySec)->setTitleLink("#display"); 292 m_secBoxes.value(DisplaySec)->setContentWidget(pLabel); 293 m_secBoxes.value(DisplaySec)->hide(); 294 pMainLayout->addWidget(m_secBoxes.value(DisplaySec)); 295 } 296 297 /* Storage */ 298 { 299 QILabel *pLabel= new QILabel(this); 300 connect(pLabel, SIGNAL(shown()), 301 this, SLOT(sltUpdateStorage())); 302 m_secBoxes.value(StorageSec)->setTitleIcon(UIIconPool::iconSet(":/attachment_16px.png")); 303 m_secBoxes.value(StorageSec)->setTitleLink("#storage"); 304 m_secBoxes.value(StorageSec)->setContentWidget(pLabel); 305 m_secBoxes.value(StorageSec)->hide(); 306 pMainLayout->addWidget(m_secBoxes.value(StorageSec)); 307 } 308 309 /* Audio */ 310 { 311 QILabel *pLabel= new QILabel(this); 312 connect(pLabel, SIGNAL(shown()), 313 this, SLOT(sltUpdateAudio())); 314 m_secBoxes.value(AudioSec)->setTitleIcon(UIIconPool::iconSet(":/sound_16px.png")); 315 m_secBoxes.value(AudioSec)->setTitleLink("#audio"); 316 m_secBoxes.value(AudioSec)->setContentWidget(pLabel); 317 m_secBoxes.value(AudioSec)->hide(); 318 pMainLayout->addWidget(m_secBoxes.value(AudioSec)); 319 } 320 321 /* Network */ 322 { 323 QILabel *pLabel= new QILabel(this); 324 connect(pLabel, SIGNAL(shown()), 325 this, SLOT(sltUpdateNetwork())); 326 m_secBoxes.value(NetworkSec)->setTitleIcon(UIIconPool::iconSet(":/nw_16px.png")); 327 m_secBoxes.value(NetworkSec)->setTitleLink("#network"); 328 m_secBoxes.value(NetworkSec)->setContentWidget(pLabel); 329 m_secBoxes.value(NetworkSec)->hide(); 330 pMainLayout->addWidget(m_secBoxes.value(NetworkSec)); 331 } 332 333 /* Serial Ports */ 334 { 335 QILabel *pLabel= new QILabel(this); 336 connect(pLabel, SIGNAL(shown()), 337 this, SLOT(sltUpdateSerialPorts())); 338 m_secBoxes.value(SerialPortsSec)->setTitleIcon(UIIconPool::iconSet(":/serial_port_16px.png")); 339 m_secBoxes.value(SerialPortsSec)->setTitleLink("#serialPorts"); 340 m_secBoxes.value(SerialPortsSec)->setContentWidget(pLabel); 341 m_secBoxes.value(SerialPortsSec)->hide(); 342 pMainLayout->addWidget(m_secBoxes.value(SerialPortsSec)); 343 } 344 345 #ifdef VBOX_WITH_PARALLEL_PORTS 346 /* Parallel Ports */ 347 { 348 QILabel *pLabel= new QILabel(this); 349 connect(pLabel, SIGNAL(shown()), 350 this, SLOT(sltUpdateParallelPorts())); 351 m_secBoxes.value(ParallelPortsSec)->setTitleIcon(UIIconPool::iconSet(":/parallel_port_16px.png")); 352 m_secBoxes.value(ParallelPortsSec)->setTitleLink("#parallelPorts"); 353 m_secBoxes.value(ParallelPortsSec)->setContentWidget(pLabel); 354 m_secBoxes.value(ParallelPortsSec)->hide(); 355 pMainLayout->addWidget(m_secBoxes.value(ParallelPortsSec)); 356 } 357 #endif /* VBOX_WITH_PARALLEL_PORTS */ 358 359 /* USB */ 360 { 361 QILabel *pLabel= new QILabel(this); 362 connect(pLabel, SIGNAL(shown()), 363 this, SLOT(sltUpdateUSB())); 364 m_secBoxes.value(USBSec)->setTitleIcon(UIIconPool::iconSet(":/usb_16px.png")); 365 m_secBoxes.value(USBSec)->setTitleLink("#usb"); 366 m_secBoxes.value(USBSec)->setContentWidget(pLabel); 367 m_secBoxes.value(USBSec)->hide(); 368 pMainLayout->addWidget(m_secBoxes.value(USBSec)); 369 } 370 371 /* Shared Folders */ 372 { 373 QILabel *pLabel= new QILabel(this); 374 connect(pLabel, SIGNAL(shown()), 375 this, SLOT(sltUpdateSharedFolders())); 376 m_secBoxes.value(SharedFoldersSec)->setTitleIcon(UIIconPool::iconSet(":/shared_folder_16px.png")); 377 m_secBoxes.value(SharedFoldersSec)->setTitleLink("#sfolders"); 378 m_secBoxes.value(SharedFoldersSec)->setContentWidget(pLabel); 379 m_secBoxes.value(SharedFoldersSec)->hide(); 380 pMainLayout->addWidget(m_secBoxes.value(SharedFoldersSec)); 381 } 382 383 pMainLayout->addStretch(1); 384 385 pSArea->setWidget(m_pDetails); 386 pSArea->setWidgetResizable(true); 387 addWidget(pSArea); 388 389 /* Read the configuration from extra data. Defaults are provided in place. */ 390 QStringList boxes = vboxGlobal().virtualBox().GetExtraDataStringList(VBoxDefs::GUI_DetailsPageBoxes, 391 /* Defaults */ 392 QStringList() 393 << m_EDStrs.value(GeneralSec) 394 << m_EDStrs.value(SystemSec) 395 << m_EDStrs.value(PreviewSec) 396 << m_EDStrs.value(DisplaySec) 397 << m_EDStrs.value(StorageSec) 398 << m_EDStrs.value(AudioSec) 399 << m_EDStrs.value(NetworkSec) 400 << m_EDStrs.value(USBSec) 401 << m_EDStrs.value(SharedFoldersSec)); 402 for (int i = 0; i < boxes.size(); ++i) 403 { 404 QString strED = boxes.value(i); 405 bool fOpen = !strED.endsWith("Closed"); 406 Section sec = m_EDStrs.key(fOpen ? strED : strED.remove("Closed"), EndSec); 407 if (sec != EndSec) 408 { 409 m_actions[sec]->setChecked(true); 410 m_secBoxes.value(sec)->setOpen(fOpen); 411 m_secBoxes.value(sec)->show(); 412 } 413 } 414 415 retranslateUi(); 416 } 417 418 UIDetailsPagePrivate::~UIDetailsPagePrivate() 419 { 420 /* Save the configuration to extra data at destruction */ 421 QStringList boxes; 422 for (int i = 0; i < EndSec; ++i) 423 { 424 if (m_actions[static_cast<Section>(i)]->isChecked()) 425 { 426 QString strED = m_EDStrs.value(static_cast<Section>(i)); 427 if (!m_secBoxes.value(static_cast<Section>(i))->isOpen()) 428 strED += "Closed"; 429 boxes << strED; 430 } 431 } 432 vboxGlobal().virtualBox().SetExtraDataStringList(VBoxDefs::GUI_DetailsPageBoxes, 433 boxes); 434 } 435 436 void UIDetailsPagePrivate::sltUpdateGeneral() 437 { 438 m_secBoxes.value(GeneralSec)->setTitleLinkEnabled(m_fChangeable); 439 QILabel *pLabel = qobject_cast<QILabel*>(m_secBoxes.value(GeneralSec)->contentWidget()); 440 if (pLabel->isVisible()) 441 { 442 if (!m_machine.isNull()) 443 { 444 QString item = sSectionItemTpl2.arg(tr("Name", "details report"), 445 m_machine.GetName()) 446 + sSectionItemTpl2.arg(tr("OS Type", "details report"), 447 vboxGlobal().vmGuestOSTypeDescription(m_machine.GetOSTypeId())); 448 449 QString table = sTableTpl.arg(item); 450 pLabel->setText(table); 451 452 }else 453 pLabel->setText(""); 454 } 455 } 456 457 void UIDetailsPagePrivate::sltUpdateSystem() 458 { 459 m_secBoxes.value(SystemSec)->setTitleLinkEnabled(m_fChangeable); 460 QILabel *pLabel = qobject_cast<QILabel*>(m_secBoxes.value(SystemSec)->contentWidget()); 461 if (pLabel->isVisible()) 462 { 463 if (!m_machine.isNull()) 464 { 465 QString item = sSectionItemTpl2.arg(tr("Base Memory", "details report"), 466 tr("<nobr>%1 MB</nobr>", "details report")) 467 .arg(m_machine.GetMemorySize()); 468 469 int cCPU = m_machine.GetCPUCount(); 470 if (cCPU > 1) 471 item += sSectionItemTpl2.arg(tr("Processors", "details report"), 472 tr("<nobr>%1</nobr>", "details report")) 473 .arg(cCPU); 474 475 /* Boot order */ 476 QStringList bootOrder; 477 for (ulong i = 1; i <= m_vbox.GetSystemProperties().GetMaxBootPosition(); ++i) 478 { 479 KDeviceType device = m_machine.GetBootOrder(i); 480 if (device == KDeviceType_Null) 481 continue; 482 bootOrder << vboxGlobal().toString(device); 483 } 484 if (bootOrder.isEmpty()) 485 bootOrder << vboxGlobal().toString(KDeviceType_Null); 486 487 item += sSectionItemTpl2.arg(tr("Boot Order", "details report"), bootOrder.join(", ")); 488 489 #ifdef VBOX_WITH_FULL_DETAILS_REPORT 490 /* BIOS Settings holder */ 491 const CBIOSSettings &biosSettings = m_machine.GetBIOSSettings(); 492 QStringList bios; 493 /* ACPI */ 494 if (biosSettings.GetACPIEnabled()) 495 bios << tr("ACPI", "details report"); 496 497 /* IO APIC */ 498 if (biosSettings.GetIOAPICEnabled()) 499 bios << tr("IO APIC", "details report"); 500 501 if (!bios.isEmpty()) 502 item += sSectionItemTpl2.arg(tr("BIOS", "details report"), bios.join(", ")); 503 #endif /* VBOX_WITH_FULL_DETAILS_REPORT */ 504 505 QStringList accel; 506 if (m_vbox.GetHost().GetProcessorFeature(KProcessorFeature_HWVirtEx)) 507 { 508 509 /* VT-x/AMD-V */ 510 if (m_machine.GetHWVirtExProperty(KHWVirtExPropertyType_Enabled)) 511 accel << tr("VT-x/AMD-V", "details report"); 512 513 /* Nested Paging */ 514 if (m_machine.GetHWVirtExProperty(KHWVirtExPropertyType_NestedPaging)) 515 accel << tr("Nested Paging", "details report"); 516 517 } 518 /* PAE/NX */ 519 if (m_machine.GetCPUProperty(KCPUPropertyType_PAE)) 520 accel << tr("PAE/NX", "details report"); 521 522 if (!accel.isEmpty()) 523 item += sSectionItemTpl2.arg(tr("Acceleration", "details report"), accel.join(", ")); 524 525 QString table = sTableTpl.arg(item); 526 pLabel->setText(table); 527 } else 528 pLabel->setText(""); 529 } 530 } 531 532 void UIDetailsPagePrivate::sltUpdatePreview() 533 { 534 qobject_cast<UIVMPreviewWindow*>(m_secBoxes.value(PreviewSec)->contentWidget())->setMachine(m_machine); 535 } 536 537 void UIDetailsPagePrivate::sltUpdateDisplay() 538 { 539 m_secBoxes.value(DisplaySec)->setTitleLinkEnabled(m_fChangeable); 540 QILabel *pLabel = qobject_cast<QILabel*>(m_secBoxes.value(DisplaySec)->contentWidget()); 541 if (pLabel->isVisible()) 542 { 543 if (!m_machine.isNull()) 544 { 545 /* Video tab */ 546 QString item = QString(sSectionItemTpl2) 547 .arg(tr("Video Memory", "details report"), 548 tr("<nobr>%1 MB</nobr>", "details report")) 549 .arg(m_machine.GetVRAMSize()); 550 551 int cGuestScreens = m_machine.GetMonitorCount(); 552 if (cGuestScreens > 1) 553 { 554 item += QString(sSectionItemTpl2) 555 .arg(tr("Screens", "details report")) 556 .arg(cGuestScreens); 557 } 558 559 QStringList accel; 560 #ifdef VBOX_WITH_VIDEOHWACCEL 561 if (m_machine.GetAccelerate2DVideoEnabled()) 562 accel << tr("2D Video", "details report"); 563 #endif /* VBOX_WITH_VIDEOHWACCEL */ 564 if (m_machine.GetAccelerate3DEnabled()) 565 accel << tr("3D", "details report"); 566 567 if (!accel.isEmpty()) 568 item += sSectionItemTpl2.arg(tr("Acceleration", "details report"), accel.join(", ")); 569 570 /* VRDP tab */ 571 const CVRDPServer &srv = m_machine.GetVRDPServer(); 572 if (!srv.isNull()) 573 { 574 if (srv.GetEnabled()) 575 item += QString(sSectionItemTpl2) 576 .arg(tr("Remote Display Server Port", "details report (VRDP Server)")) 577 .arg(srv.GetPorts()); 578 else 579 item += QString(sSectionItemTpl2) 580 .arg(tr("Remote Display Server", "details report (VRDP Server)")) 581 .arg(tr("Disabled", "details report (VRDP Server)")); 582 } 583 584 QString table = sTableTpl.arg(item); 585 pLabel->setText(table); 586 } else 587 pLabel->setText(""); 588 } 589 } 590 591 void UIDetailsPagePrivate::sltUpdateStorage() 592 { 593 m_secBoxes.value(StorageSec)->setTitleLinkEnabled(m_fChangeable); 594 QILabel *pLabel = qobject_cast<QILabel*>(m_secBoxes.value(StorageSec)->contentWidget()); 595 if (pLabel->isVisible()) 596 { 597 if (!m_machine.isNull()) 598 { 599 QString item; 600 /* Iterate over the all machine controllers: */ 601 const CStorageControllerVector &controllers = m_machine.GetStorageControllers(); 602 for (int i = 0; i < controllers.size(); ++i) 603 { 604 /* Get current controller: */ 605 const CStorageController &controller = controllers[i]; 606 /* Add controller information: */ 607 item += QString(sSectionItemTpl3).arg(controller.GetName()); 608 609 /* Populate sorted map with attachments information: */ 610 QMap<StorageSlot,QString> attachmentsMap; 611 const CMediumAttachmentVector &attachments = m_machine.GetMediumAttachmentsOfController(controller.GetName()); 612 for (int j = 0; j < attachments.size(); ++j) 613 { 614 /* Get current attachment: */ 615 const CMediumAttachment &attachment = attachments[j]; 616 /* Prepare current storage slot: */ 617 StorageSlot attachmentSlot(controller.GetBus(), attachment.GetPort(), attachment.GetDevice()); 618 /* Append 'device slot name' with 'device type name' for CD/DVD devices only: */ 619 QString strDeviceType = attachment.GetType() == KDeviceType_DVD ? tr("(CD/DVD)") : QString(); 620 if (!strDeviceType.isNull()) 621 strDeviceType.prepend(' '); 622 /* Prepare current medium object: */ 623 const CMedium &medium = attachment.GetMedium(); 624 /* Prepare information about current medium & attachment: */ 625 QString strAttachmentInfo = !attachment.isOk() ? QString() : 626 QString(sSectionItemTpl2) 627 .arg(QString(" ") + 628 vboxGlobal().toString(StorageSlot(controller.GetBus(), 629 attachment.GetPort(), 630 attachment.GetDevice())) + strDeviceType) 631 .arg(vboxGlobal().details(medium, false)); 632 /* Insert that attachment into map: */ 633 if (!strAttachmentInfo.isNull()) 634 attachmentsMap.insert(attachmentSlot, strAttachmentInfo); 635 } 636 637 /* Iterate over the sorted map with attachments information: */ 638 QMapIterator<StorageSlot,QString> it(attachmentsMap); 639 while (it.hasNext()) 640 { 641 /* Add controller information: */ 642 it.next(); 643 item += it.value(); 644 } 645 } 646 647 if (item.isNull()) 648 { 649 item = QString(sSectionItemTpl1) 650 .arg(tr("Not Attached", "details report (Storage)")); 651 } 652 653 QString table = sTableTpl.arg(item); 654 pLabel->setText(table); 655 } else 656 pLabel->setText(""); 657 } 658 } 659 660 void UIDetailsPagePrivate::sltUpdateAudio() 661 { 662 m_secBoxes.value(AudioSec)->setTitleLinkEnabled(m_fChangeable); 663 QILabel *pLabel = qobject_cast<QILabel*>(m_secBoxes.value(AudioSec)->contentWidget()); 664 if (pLabel->isVisible()) 665 { 666 if (!m_machine.isNull()) 667 { 668 QString item; 669 670 const CAudioAdapter &audio = m_machine.GetAudioAdapter(); 671 if (audio.GetEnabled()) 672 item = QString(sSectionItemTpl2) 673 .arg(tr("Host Driver", "details report (audio)"), 674 vboxGlobal().toString(audio.GetAudioDriver())) + 675 QString(sSectionItemTpl2) 676 .arg(tr("Controller", "details report (audio)"), 677 vboxGlobal().toString(audio.GetAudioController())); 678 else 679 item = QString(sSectionItemTpl1) 680 .arg(tr("Disabled", "details report (audio)")); 681 682 QString table = sTableTpl.arg(item); 683 pLabel->setText(table); 684 } else 685 pLabel->setText(""); 686 } 687 } 688 689 void UIDetailsPagePrivate::sltUpdateNetwork() 690 { 691 m_secBoxes.value(NetworkSec)->setTitleLinkEnabled(m_fChangeable); 692 QILabel *pLabel = qobject_cast<QILabel*>(m_secBoxes.value(NetworkSec)->contentWidget()); 693 if (pLabel->isVisible()) 694 { 695 if (!m_machine.isNull()) 696 { 697 QString item; 698 699 ulong count = m_vbox.GetSystemProperties().GetNetworkAdapterCount(); 700 for (ulong slot = 0; slot < count; slot ++) 701 { 702 const CNetworkAdapter &adapter = m_machine.GetNetworkAdapter(slot); 703 if (adapter.GetEnabled()) 704 { 705 KNetworkAttachmentType type = adapter.GetAttachmentType(); 706 QString attType = vboxGlobal().toString(adapter.GetAdapterType()) 707 .replace(QRegExp("\\s\\(.+\\)"), " (%1)"); 708 /* don't use the adapter type string for types that have 709 * an additional symbolic network/interface name field, use 710 * this name instead */ 711 if (type == KNetworkAttachmentType_Bridged) 712 attType = attType.arg(tr("Bridged adapter, %1", 713 "details report (network)").arg(adapter.GetHostInterface())); 714 else if (type == KNetworkAttachmentType_Internal) 715 attType = attType.arg(tr("Internal network, '%1'", 716 "details report (network)").arg(adapter.GetInternalNetwork())); 717 else if (type == KNetworkAttachmentType_HostOnly) 718 attType = attType.arg(tr("Host-only adapter, '%1'", 719 "details report (network)").arg(adapter.GetHostInterface())); 720 #ifdef VBOX_WITH_VDE 721 else if (type == KNetworkAttachmentType_VDE) 722 attType = attType.arg(tr("VDE network, '%1'", 723 "details report (network)").arg(adapter.GetVDENetwork())); 724 #endif 725 else 726 attType = attType.arg(vboxGlobal().toString(type)); 727 728 item += QString(sSectionItemTpl2) 729 .arg(tr("Adapter %1", "details report (network)") 730 .arg(adapter.GetSlot() + 1)) 731 .arg(attType); 732 } 733 } 734 if (item.isNull()) 735 { 736 item = QString(sSectionItemTpl1) 737 .arg(tr("Disabled", "details report (network)")); 738 } 739 740 QString table = sTableTpl.arg(item); 741 pLabel->setText(table); 742 } else 743 pLabel->setText(""); 744 } 745 } 746 747 void UIDetailsPagePrivate::sltUpdateSerialPorts() 748 { 749 m_secBoxes.value(SerialPortsSec)->setTitleLinkEnabled(m_fChangeable); 750 QILabel *pLabel = qobject_cast<QILabel*>(m_secBoxes.value(SerialPortsSec)->contentWidget()); 751 if (pLabel->isVisible()) 752 { 753 if (!m_machine.isNull()) 754 { 755 QString item; 756 757 ulong count = m_vbox.GetSystemProperties().GetSerialPortCount(); 758 for (ulong slot = 0; slot < count; slot ++) 759 { 760 const CSerialPort &port = m_machine.GetSerialPort(slot); 761 if (port.GetEnabled()) 762 { 763 KPortMode mode = port.GetHostMode(); 764 QString data = 765 vboxGlobal().toCOMPortName(port.GetIRQ(), port.GetIOBase()) + ", "; 766 if (mode == KPortMode_HostPipe || 767 mode == KPortMode_HostDevice || 768 mode == KPortMode_RawFile) 769 data += QString("%1 (<nobr>%2</nobr>)") 770 .arg(vboxGlobal().toString(mode)) 771 .arg(QDir::toNativeSeparators(port.GetPath())); 772 else 773 data += vboxGlobal().toString(mode); 774 775 item += QString(sSectionItemTpl2) 776 .arg(tr("Port %1", "details report (serial ports)") 777 .arg(port.GetSlot() + 1)) 778 .arg(data); 779 } 780 } 781 if (item.isNull()) 782 { 783 item = QString(sSectionItemTpl1) 784 .arg(tr("Disabled", "details report (serial ports)")); 785 } 786 787 QString table = sTableTpl.arg(item); 788 pLabel->setText(table); 789 } else 790 pLabel->setText(""); 791 } 792 } 793 794 #ifdef VBOX_WITH_PARALLEL_PORTS 795 void UIDetailsPagePrivate::sltUpdateParallelPorts() 796 { 797 m_secBoxes.value(ParallelPortsSec)->setTitleLinkEnabled(m_fChangeable); 798 QILabel *pLabel = qobject_cast<QILabel*>(m_secBoxes.value(ParallelPortsSec)->contentWidget()); 799 if (pLabel->isVisible()) 800 { 801 if (!m_machine.isNull()) 802 { 803 QString item; 804 805 ulong count = m_vbox.GetSystemProperties().GetParallelPortCount(); 806 for (ulong slot = 0; slot < count; slot ++) 807 { 808 const CParallelPort &port = m_machine.GetParallelPort(slot); 809 if (port.GetEnabled()) 810 { 811 QString data = 812 vboxGlobal().toLPTPortName(port.GetIRQ(), port.GetIOBase()) + 813 QString(" (<nobr>%1</nobr>)") 814 .arg(QDir::toNativeSeparators(port.GetPath())); 815 816 item += QString(sSectionItemTpl2) 817 .arg(tr("Port %1", "details report (parallel ports)") 818 .arg(port.GetSlot() + 1)) 819 .arg(data); 820 } 821 } 822 if (item.isNull()) 823 { 824 item = QString(sSectionItemTpl1) 825 .arg(tr("Disabled", "details report (parallel ports)")); 826 } 827 828 /* Currently disabled */ 829 QString table = sTableTpl.arg(item); 830 pLabel->setText(table); 831 } else 832 pLabel->setText(""); 833 } 834 } 835 #endif /* VBOX_WITH_PARALLEL_PORTS */ 836 837 void UIDetailsPagePrivate::sltUpdateUSB() 838 { 839 m_secBoxes.value(USBSec)->setTitleLinkEnabled(m_fChangeable); 840 QILabel *pLabel = qobject_cast<QILabel*>(m_secBoxes.value(USBSec)->contentWidget()); 841 if (pLabel->isVisible()) 842 { 843 if (!m_machine.isNull()) 844 { 845 QString item; 846 847 const CUSBController &ctl = m_machine.GetUSBController(); 848 if ( !ctl.isNull() 849 && ctl.GetProxyAvailable()) 850 { 851 m_fUSBAvailable = true; 852 /* the USB controller may be unavailable (i.e. in VirtualBox OSE) */ 853 if (ctl.GetEnabled()) 854 { 855 const CUSBDeviceFilterVector &coll = ctl.GetDeviceFilters(); 856 uint active = 0; 857 for (int i = 0; i < coll.size(); ++i) 858 if (coll[i].GetActive()) 859 active ++; 860 861 item = QString(sSectionItemTpl2) 862 .arg(tr("Device Filters", "details report (USB)"), 863 tr("%1 (%2 active)", "details report (USB)") 864 .arg(coll.size()).arg(active)); 865 } 866 else 867 item = QString(sSectionItemTpl1) 868 .arg(tr("Disabled", "details report (USB)")); 869 870 QString table = sTableTpl.arg(item); 871 pLabel->setText(table); 872 } else 873 { 874 m_fUSBAvailable = false; 875 /* Fully hide when USB is not available */ 876 m_secBoxes.value(USBSec)->hide(); 877 } 878 } else 879 pLabel->setText(""); 880 } 881 } 882 883 void UIDetailsPagePrivate::sltUpdateSharedFolders() 884 { 885 m_secBoxes.value(SharedFoldersSec)->setTitleLinkEnabled(m_fChangeable); 886 QILabel *pLabel = qobject_cast<QILabel*>(m_secBoxes.value(SharedFoldersSec)->contentWidget()); 887 if (pLabel->isVisible()) 888 { 889 if (!m_machine.isNull()) 890 { 891 QString item; 892 893 ulong count = m_machine.GetSharedFolders().size(); 894 if (count > 0) 895 { 896 item = QString(sSectionItemTpl2) 897 .arg(tr("Shared Folders", "details report (shared folders)")) 898 .arg(count); 899 } 900 else 901 item = QString(sSectionItemTpl1) 902 .arg(tr("None", "details report (shared folders)")); 903 904 QString table = sTableTpl.arg(item); 905 pLabel->setText(table); 906 } else 907 pLabel->setText(""); 908 } 909 } 910 911 void UIDetailsPagePrivate::sltContextMenuRequested(const QPoint &pos) 912 { 913 QList<QAction*> actions = m_actions.values(); 914 if (!m_fUSBAvailable) 915 actions.removeOne(m_actions.value(USBSec)); 916 QAction *pReturn = QMenu::exec(actions, m_pDetails->mapToGlobal(pos), 0, this); 917 if (pReturn) 918 { 919 UIPopupBox *pBox = m_secBoxes.value(static_cast<Section>(pReturn->data().toInt())); 920 if (pReturn->isChecked()) 921 pBox->show(); 922 else 923 pBox->hide(); 924 } 925 } 926 927 void UIDetailsPagePrivate::setMachine(const CMachine& machine) 928 { 929 m_machine = machine; 930 if (m_machine.isNull()) 931 m_fChangeable = false; 932 else 933 { 934 KMachineState state = m_machine.GetState(); 935 bool running = m_machine.GetSessionState() != KSessionState_Closed; 936 m_fChangeable = !running && state != KMachineState_Saved; 937 } 938 939 sltUpdateGeneral(); 940 sltUpdateSystem(); 941 sltUpdatePreview(); 942 sltUpdateDisplay(); 943 sltUpdateStorage(); 944 sltUpdateAudio(); 945 sltUpdateNetwork(); 946 sltUpdateSerialPorts(); 947 #ifdef VBOX_WITH_PARALLEL_PORTS 948 sltUpdateParallelPorts(); 949 #endif /* VBOX_WITH_PARALLEL_PORTS */ 950 sltUpdateUSB(); 951 sltUpdateSharedFolders(); 952 953 setCurrentIndex(0); 954 } 955 956 void UIDetailsPagePrivate::createTextPage() 957 { 958 if (m_pText) 155 959 return; 156 960 157 mErrBox = new QWidget(); 158 159 QVBoxLayout *vLayout = new QVBoxLayout (mErrBox); 160 vLayout->setSpacing (10); 161 162 mErrLabel = new QLabel (mErrBox); 163 mErrLabel->setWordWrap (true); 164 mErrLabel->setSizePolicy (QSizePolicy::Expanding, QSizePolicy::Fixed); 165 vLayout->addWidget (mErrLabel); 166 167 mErrText = new QTextBrowser (mErrBox); 168 mErrText->setFocusPolicy (Qt::StrongFocus); 169 mErrText->document()->setDefaultStyleSheet ("a { text-decoration: none; }"); 170 vLayout->addWidget (mErrText); 961 /* Create normal text page */ 962 m_pText = new QRichTextBrowser(this); 963 m_pText->setFocusPolicy(Qt::StrongFocus); 964 m_pText->document()->setDefaultStyleSheet("a { text-decoration: none; }"); 965 /* Make "transparent" */ 966 m_pText->setFrameShape(QFrame::NoFrame); 967 m_pText->viewport()->setAutoFillBackground(false); 968 m_pText->setOpenLinks(false); 969 970 connect(m_pText, SIGNAL(anchorClicked(const QUrl &)), 971 this, SLOT(gotLinkClicked(const QUrl &))); 972 973 addWidget(m_pText); 974 } 975 976 void UIDetailsPagePrivate::createErrPage() 977 { 978 if (m_pErrBox) 979 return; 980 981 /* Create inaccessible details page */ 982 m_pErrBox = new QWidget(); 983 984 QVBoxLayout *vLayout = new QVBoxLayout(m_pErrBox); 985 vLayout->setSpacing(10); 986 vLayout->setContentsMargins(gsLeftMargin, gsTopMargin, gsRightMargin, gsBottomMargin); 987 988 m_pErrLabel = new QLabel(m_pErrBox); 989 m_pErrLabel->setWordWrap(true); 990 m_pErrLabel->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed); 991 vLayout->addWidget(m_pErrLabel); 992 993 m_pErrText = new QTextBrowser(m_pErrBox); 994 m_pErrText->setFocusPolicy(Qt::StrongFocus); 995 m_pErrText->document()->setDefaultStyleSheet("a { text-decoration: none; }"); 996 vLayout->addWidget(m_pErrText); 171 997 172 998 if (mRefreshAction) 173 999 { 174 mRefreshButton = new QToolButton (mErrBox);175 mRefreshButton->setFocusPolicy 176 177 QHBoxLayout *hLayout = new QHBoxLayout 178 vLayout->addLayout 179 hLayout->addItem (new QSpacerItem(0, 0, QSizePolicy::Expanding,1000 mRefreshButton = new QToolButton(m_pErrBox); 1001 mRefreshButton->setFocusPolicy(Qt::StrongFocus); 1002 1003 QHBoxLayout *hLayout = new QHBoxLayout(); 1004 vLayout->addLayout(hLayout); 1005 hLayout->addItem(new QSpacerItem(0, 0, QSizePolicy::Expanding, 180 1006 QSizePolicy::Minimum)); 181 hLayout->addWidget (mRefreshButton); 182 183 connect (mRefreshButton, SIGNAL (clicked()), 184 mRefreshAction, SIGNAL (triggered())); 185 } 186 187 vLayout->addItem (new QSpacerItem (0, 0, QSizePolicy::Minimum, 188 QSizePolicy::Expanding)); 189 190 addWidget (mErrBox); 1007 hLayout->addWidget(mRefreshButton); 1008 1009 connect(mRefreshButton, SIGNAL(clicked()), 1010 mRefreshAction, SIGNAL(triggered())); 1011 } 1012 1013 vLayout->addItem(new QSpacerItem(0, 0, 1014 QSizePolicy::Minimum, 1015 QSizePolicy::Expanding)); 1016 1017 addWidget(m_pErrBox); 191 1018 192 1019 retranslateUi(); 193 1020 } 194 1021 195 void VBoxVMDetailsView::retranslateUi()196 { 197 if (m ErrLabel)198 m ErrLabel->setText (tr(1022 void UIDetailsPagePrivate::retranslateUi() 1023 { 1024 if (m_pErrLabel) 1025 m_pErrLabel->setText(tr( 199 1026 "The selected virtual machine is <i>inaccessible</i>. Please " 200 1027 "inspect the error message shown below and press the " … … 204 1031 if (mRefreshAction && mRefreshButton) 205 1032 { 206 mRefreshButton->setText (mRefreshAction->text()); 207 mRefreshButton->setIcon (mRefreshAction->icon()); 208 mRefreshButton->setToolButtonStyle (Qt::ToolButtonTextBesideIcon); 209 } 210 } 211 212 // VBoxVMDescriptionPage class 213 //////////////////////////////////////////////////////////////////////////////// 1033 mRefreshButton->setText(mRefreshAction->text()); 1034 mRefreshButton->setIcon(mRefreshAction->icon()); 1035 mRefreshButton->setToolButtonStyle(Qt::ToolButtonTextBesideIcon); 1036 } 1037 1038 /* General */ 1039 { 1040 m_secBoxes.value(GeneralSec)->setTitle(tr("General", "details report")); 1041 m_actions.value(GeneralSec)->setText(m_secBoxes.value(GeneralSec)->title()); 1042 } 1043 1044 /* System */ 1045 { 1046 m_secBoxes.value(SystemSec)->setTitle(tr("System", "details report")); 1047 m_actions.value(SystemSec)->setText(m_secBoxes.value(SystemSec)->title()); 1048 } 1049 1050 /* Preview */ 1051 { 1052 m_secBoxes.value(PreviewSec)->setTitle(tr("Preview", "details report")); 1053 m_actions.value(PreviewSec)->setText(m_secBoxes.value(PreviewSec)->title()); 1054 } 1055 1056 /* Display */ 1057 { 1058 m_secBoxes.value(DisplaySec)->setTitle(tr("Display", "details report")); 1059 m_actions.value(DisplaySec)->setText(m_secBoxes.value(DisplaySec)->title()); 1060 } 1061 1062 /* Storage */ 1063 { 1064 m_secBoxes.value(StorageSec)->setTitle(tr("Storage", "details report")); 1065 m_actions.value(StorageSec)->setText(m_secBoxes.value(StorageSec)->title()); 1066 } 1067 1068 /* Audio */ 1069 { 1070 m_secBoxes.value(AudioSec)->setTitle(tr("Audio", "details report")); 1071 m_actions.value(AudioSec)->setText(m_secBoxes.value(AudioSec)->title()); 1072 } 1073 1074 /* Network */ 1075 { 1076 m_secBoxes.value(NetworkSec)->setTitle(tr("Network", "details report")); 1077 m_actions.value(NetworkSec)->setText(m_secBoxes.value(NetworkSec)->title()); 1078 } 1079 1080 /* Serial Ports */ 1081 { 1082 m_secBoxes.value(SerialPortsSec)->setTitle(tr("Serial Ports", "details report")); 1083 m_actions.value(SerialPortsSec)->setText(m_secBoxes.value(SerialPortsSec)->title()); 1084 } 1085 1086 #ifdef VBOX_WITH_PARALLEL_PORTS 1087 /* Parallel Ports */ 1088 { 1089 m_secBoxes.value(ParallelPortsSec)->setTitle(tr("Parallel Ports", "details report")); 1090 m_actions.value(ParallelPortsSec)->setText(m_secBoxes.value(ParallelPortsSec)->title()); 1091 } 1092 #endif /* VBOX_WITH_PARALLEL_PORTS */ 1093 1094 /* USB */ 1095 { 1096 m_secBoxes.value(USBSec)->setTitle(tr("USB", "details report")); 1097 m_actions.value(USBSec)->setText(m_secBoxes.value(USBSec)->title()); 1098 } 1099 1100 /* Shared Folders */ 1101 { 1102 m_secBoxes.value(SharedFoldersSec)->setTitle(tr("Shared Folders", "details report")); 1103 m_actions.value(SharedFoldersSec)->setText(m_secBoxes.value(SharedFoldersSec)->title()); 1104 } 1105 } 214 1106 215 1107 /** 216 * Comments page widget to represent VM comments.1108 * UIDescriptionPagePrivate 217 1109 */ 218 class VBoxVMDescriptionPage : public QIWithRetranslateUI<QWidget>1110 class UIDescriptionPagePrivate : public QIWithRetranslateUI<QWidget> 219 1111 { 220 1112 Q_OBJECT; … … 222 1114 public: 223 1115 224 VBoxVMDescriptionPage (VBoxSelectorWnd *);225 ~ VBoxVMDescriptionPage() {}226 227 void setMachineItem (UIVMItem *aItem);1116 UIDescriptionPagePrivate(QWidget *pParent = 0); 1117 ~UIDescriptionPagePrivate() {} 1118 1119 void setMachineItem(UIVMItem *pVMItem); 228 1120 229 1121 void updateState(); 230 1122 1123 signals: 1124 1125 void linkClicked(const QString &aURL); 1126 231 1127 protected: 232 1128 … … 239 1135 private: 240 1136 241 UIVMItem *mItem; 242 243 VBoxSelectorWnd *mParent; 244 QToolButton *mBtnEdit; 245 QTextBrowser *mBrowser; 246 QLabel *mLabel; 1137 UIVMItem *m_pVMItem; 1138 1139 QToolButton *m_pEditBtn; 1140 QTextBrowser *m_pBrowser; 1141 QLabel *m_pLabel; 247 1142 }; 248 1143 249 VBoxVMDescriptionPage::VBoxVMDescriptionPage (VBoxSelectorWnd *aParent) 250 : QIWithRetranslateUI<QWidget> (aParent) 251 , mItem (NULL), mParent (aParent) 252 , mBtnEdit (0), mBrowser (0), mLabel (0) 253 { 254 /* main layout */ 255 QVBoxLayout *vMainLayout = new QVBoxLayout (this); 256 vMainLayout->setSpacing (10); 257 VBoxGlobal::setLayoutMargin (vMainLayout, 0); 258 259 /* mBrowser */ 260 mBrowser = new QTextBrowser (this); 261 mBrowser->setSizePolicy (QSizePolicy::Expanding, QSizePolicy::Expanding); 262 mBrowser->setFocusPolicy (Qt::StrongFocus); 263 mBrowser->document()->setDefaultStyleSheet ("a { text-decoration: none; }"); 264 vMainLayout->addWidget (mBrowser); 1144 UIDescriptionPagePrivate::UIDescriptionPagePrivate(QWidget *pParent /* = 0 */) 1145 : QIWithRetranslateUI<QWidget>(pParent) 1146 , m_pVMItem(0) 1147 , m_pEditBtn(0) 1148 , m_pBrowser(0) 1149 , m_pLabel(0) 1150 { 1151 /* Main layout */ 1152 QVBoxLayout *pMainLayout = new QVBoxLayout(this); 1153 pMainLayout->setSpacing(10); 1154 VBoxGlobal::setLayoutMargin(pMainLayout, 0); 1155 1156 /* m_pBrowser */ 1157 m_pBrowser = new QTextBrowser(this); 1158 m_pBrowser->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); 1159 m_pBrowser->setFocusPolicy(Qt::StrongFocus); 1160 m_pBrowser->document()->setDefaultStyleSheet("a { text-decoration: none; }"); 1161 pMainLayout->addWidget(m_pBrowser); 265 1162 /* hidden by default */ 266 m Browser->setHidden(true);267 268 m Label = new QLabel(this);269 m Label->setFrameStyle (mBrowser->frameStyle());270 m Label->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);271 m Label->setAlignment(Qt::AlignCenter);272 m Label->setWordWrap(true);273 vMainLayout->addWidget (mLabel);1163 m_pBrowser->setHidden(true); 1164 1165 m_pLabel = new QLabel(this); 1166 m_pLabel->setFrameStyle(m_pBrowser->frameStyle()); 1167 m_pLabel->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); 1168 m_pLabel->setAlignment(Qt::AlignCenter); 1169 m_pLabel->setWordWrap(true); 1170 pMainLayout->addWidget(m_pLabel); 274 1171 /* always disabled */ 275 m Label->setEnabled(false);1172 m_pLabel->setEnabled(false); 276 1173 277 1174 /* button layout */ 278 QHBoxLayout *hBtnLayout = new QHBoxLayout 279 vMainLayout->addLayout(hBtnLayout);280 hBtnLayout->setSpacing 281 hBtnLayout->addItem (new QSpacerItem(0, 0,282 283 1175 QHBoxLayout *hBtnLayout = new QHBoxLayout(); 1176 pMainLayout->addLayout(hBtnLayout); 1177 hBtnLayout->setSpacing(10); 1178 hBtnLayout->addItem(new QSpacerItem(0, 0, 1179 QSizePolicy::Expanding, 1180 QSizePolicy::Minimum)); 284 1181 285 1182 /* button */ 286 m BtnEdit = new QToolButton(this);287 m BtnEdit->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed);288 m BtnEdit->setFocusPolicy(Qt::StrongFocus);289 m BtnEdit->setIcon(UIIconPool::iconSet(":/edit_description_16px.png",290 ":/edit_description_disabled_16px.png"));291 m BtnEdit->setToolButtonStyle(Qt::ToolButtonTextBesideIcon);292 connect (mBtnEdit, SIGNAL (clicked()), this, SLOT(goToSettings()));293 hBtnLayout->addWidget (mBtnEdit);294 295 vMainLayout->addItem (new QSpacerItem(0, 0,296 297 1183 m_pEditBtn = new QToolButton(this); 1184 m_pEditBtn->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed); 1185 m_pEditBtn->setFocusPolicy(Qt::StrongFocus); 1186 m_pEditBtn->setIcon(UIIconPool::iconSet(":/edit_description_16px.png", 1187 ":/edit_description_disabled_16px.png")); 1188 m_pEditBtn->setToolButtonStyle(Qt::ToolButtonTextBesideIcon); 1189 connect(m_pEditBtn, SIGNAL(clicked()), this, SLOT(goToSettings())); 1190 hBtnLayout->addWidget(m_pEditBtn); 1191 1192 pMainLayout->addItem(new QSpacerItem(0, 0, 1193 QSizePolicy::Expanding, 1194 QSizePolicy::Minimum)); 298 1195 299 1196 /* apply language settings */ … … 304 1201 305 1202 /** 306 * The machine list @a aItem is used to access cached machine data w/o making1203 * The machine list @a pVMItem is used to access cached machine data w/o making 307 1204 * unnecessary RPC calls. 308 1205 */ 309 void VBoxVMDescriptionPage::setMachineItem (UIVMItem *aItem)310 { 311 m Item = aItem;312 313 QString text = aItem ? aItem->machine().GetDescription() : QString::null;1206 void UIDescriptionPagePrivate::setMachineItem(UIVMItem *pVMItem) 1207 { 1208 m_pVMItem = pVMItem; 1209 1210 QString text = pVMItem ? pVMItem->machine().GetDescription() : QString::null; 314 1211 315 1212 if (!text.isEmpty()) 316 1213 { 317 m Label->setHidden(true);318 m Browser->setText(text);319 m Browser->setVisible(true);1214 m_pLabel->setHidden(true); 1215 m_pBrowser->setText(text); 1216 m_pBrowser->setVisible(true); 320 1217 } 321 1218 else 322 1219 { 323 m Browser->setHidden(true);324 m Browser->clear();325 m Label->setVisible(true);1220 m_pBrowser->setHidden(true); 1221 m_pBrowser->clear(); 1222 m_pLabel->setVisible(true); 326 1223 } 327 1224 … … 330 1227 } 331 1228 332 void VBoxVMDescriptionPage::retranslateUi()333 { 334 m Label->setText (tr("No description. Press the Edit button below to add it."));335 336 m BtnEdit->setText (tr("Edit"));337 m BtnEdit->setShortcut (QKeySequence("Ctrl+E"));338 m BtnEdit->setToolTip (tr("Edit (Ctrl+E)"));339 m BtnEdit->adjustSize();340 m BtnEdit->updateGeometry();1229 void UIDescriptionPagePrivate::retranslateUi() 1230 { 1231 m_pLabel->setText(tr("No description. Press the Edit button below to add it.")); 1232 1233 m_pEditBtn->setText(tr("Edit")); 1234 m_pEditBtn->setShortcut(QKeySequence("Ctrl+E")); 1235 m_pEditBtn->setToolTip(tr("Edit (Ctrl+E)")); 1236 m_pEditBtn->adjustSize(); 1237 m_pEditBtn->updateGeometry(); 341 1238 } 342 1239 … … 347 1244 * first. 348 1245 */ 349 void VBoxVMDescriptionPage::updateState()1246 void UIDescriptionPagePrivate::updateState() 350 1247 { 351 1248 /// @todo disabling the edit button for a saved VM will not be necessary … … 353 1250 /// that can be changed in the saved state, can be changed. 354 1251 355 if (m Item)356 { 357 bool saved = m Item->state() == KMachineState_Saved;358 bool busy = m Item->sessionState() != KSessionState_Closed;359 m BtnEdit->setEnabled(!saved && !busy);1252 if (m_pVMItem) 1253 { 1254 bool saved = m_pVMItem->state() == KMachineState_Saved; 1255 bool busy = m_pVMItem->sessionState() != KSessionState_Closed; 1256 m_pEditBtn->setEnabled(!saved && !busy); 360 1257 } 361 1258 else 362 mBtnEdit->setEnabled (false); 363 } 364 365 void VBoxVMDescriptionPage::goToSettings() 366 { 367 mParent->vmSettings ("#general", "mTeDescription"); 368 } 369 370 // VBoxSelectorWnd class 371 //////////////////////////////////////////////////////////////////////////////// 372 373 /** \class VBoxSelectorWnd 374 * 375 * The VBoxSelectorWnd class is a VM selector window, one of two main VBox 376 * GUI windows. 377 * 378 * This window appears when the user starts the VirtualBox executable. 379 * It allows to view the list of configured VMs, their settings 380 * and the current state, create, reconfigure, delete and start VMs. 1259 m_pEditBtn->setEnabled(false); 1260 } 1261 1262 void UIDescriptionPagePrivate::goToSettings() 1263 { 1264 emit linkClicked("#general%%mTeDescription"); 1265 } 1266 1267 /** 1268 * UIVMDesktop 381 1269 */ 382 383 /** 384 * Constructs the VM selector window. 385 * 386 * @param aSelf pointer to a variable where to store |this| right after 387 * this object's constructor is called (necessary to avoid 388 * recursion in VBoxGlobal::selectorWnd()) 389 */ 390 VBoxSelectorWnd:: 391 VBoxSelectorWnd (VBoxSelectorWnd **aSelf, QWidget* aParent, 392 Qt::WindowFlags aFlags /* = Qt::Window */) 393 : QIWithRetranslateUI2<QMainWindow> (aParent, aFlags) 394 , mDoneInaccessibleWarningOnce (false) 395 { 396 VBoxGlobalSettings settings = vboxGlobal().settings(); 397 398 if (aSelf) 399 *aSelf = this; 400 401 statusBar()->setContextMenuPolicy(Qt::CustomContextMenu); 402 connect(statusBar(), SIGNAL(customContextMenuRequested(const QPoint&)), 403 this, SLOT(showViewContextMenu(const QPoint&))); 404 405 #if defined (Q_WS_MAC) && (QT_VERSION < 0x040402) 406 qApp->installEventFilter (this); 407 #endif /* defined (Q_WS_MAC) && (QT_VERSION < 0x040402) */ 408 409 #if !(defined (Q_WS_WIN) || defined (Q_WS_MAC)) 410 /* The application icon. On Win32, it's built-in to the executable. On Mac 411 * OS X the icon referenced in info.plist is used. */ 412 setWindowIcon (QIcon (":/VirtualBox_48px.png")); 413 #endif 414 415 /* actions */ 416 417 mFileMediaMgrAction = new QAction (this); 418 mFileMediaMgrAction->setIcon(UIIconPool::iconSet(":/diskimage_16px.png")); 419 420 mFileApplianceImportAction = new QAction (this); 421 mFileApplianceImportAction->setIcon(UIIconPool::iconSet(":/import_16px.png")); 422 423 mFileApplianceExportAction = new QAction (this); 424 mFileApplianceExportAction->setIcon(UIIconPool::iconSet(":/export_16px.png")); 425 426 mFileSettingsAction = new QAction(this); 427 mFileSettingsAction->setMenuRole (QAction::PreferencesRole); 428 mFileSettingsAction->setIcon(UIIconPool::iconSet(":/global_settings_16px.png")); 429 mFileExitAction = new QAction (this); 430 mFileExitAction->setMenuRole (QAction::QuitRole); 431 mFileExitAction->setIcon(UIIconPool::iconSet(":/exit_16px.png")); 432 433 mVmNewAction = new QAction (this); 434 mVmNewAction->setIcon(UIIconPool::iconSetFull( 435 QSize (32, 32), QSize (16, 16), 436 ":/vm_new_32px.png", ":/new_16px.png")); 437 mVmConfigAction = new QAction (this); 438 mVmConfigAction->setIcon(UIIconPool::iconSetFull( 439 QSize (32, 32), QSize (16, 16), 440 ":/vm_settings_32px.png", ":/settings_16px.png", 441 ":/vm_settings_disabled_32px.png", ":/settings_dis_16px.png")); 442 mVmDeleteAction = new QAction (this); 443 mVmDeleteAction->setIcon(UIIconPool::iconSetFull( 444 QSize (32, 32), QSize (16, 16), 445 ":/vm_delete_32px.png", ":/delete_16px.png", 446 ":/vm_delete_disabled_32px.png", ":/delete_dis_16px.png")); 447 mVmStartAction = new QAction (this); 448 mVmStartAction->setIcon(UIIconPool::iconSetFull( 449 QSize (32, 32), QSize (16, 16), 450 ":/vm_start_32px.png", ":/start_16px.png", 451 ":/vm_start_disabled_32px.png", ":/start_dis_16px.png")); 452 mVmDiscardAction = new QAction (this); 453 mVmDiscardAction->setIcon(UIIconPool::iconSetFull( 454 QSize (32, 32), QSize (16, 16), 455 ":/vm_discard_32px.png", ":/discard_16px.png", 456 ":/vm_discard_disabled_32px.png", ":/discard_dis_16px.png")); 457 mVmPauseAction = new QAction (this); 458 mVmPauseAction->setCheckable (true); 459 mVmPauseAction->setIcon(UIIconPool::iconSetFull( 460 QSize (32, 32), QSize (16, 16), 461 ":/vm_pause_32px.png", ":/pause_16px.png", 462 ":/vm_pause_disabled_32px.png", ":/pause_disabled_16px.png")); 463 mVmRefreshAction = new QAction (this); 464 mVmRefreshAction->setIcon(UIIconPool::iconSetFull( 465 QSize (32, 32), QSize (16, 16), 466 ":/refresh_32px.png", ":/refresh_16px.png", 467 ":/refresh_disabled_32px.png", ":/refresh_disabled_16px.png")); 468 mVmShowLogsAction = new QAction (this); 469 mVmShowLogsAction->setIcon(UIIconPool::iconSetFull( 470 QSize (32, 32), QSize (16, 16), 471 ":/vm_show_logs_32px.png", ":/show_logs_16px.png", 472 ":/vm_show_logs_disabled_32px.png", ":/show_logs_disabled_16px.png")); 473 474 mHelpActions.setup (this); 475 476 QISplitter *pSplitter = new QISplitter(this); 477 pSplitter->setHandleType(QISplitter::Native); 478 /* Central widget @ horizontal layout */ 479 setCentralWidget(pSplitter); 480 481 /* VM list toolbar */ 482 mVMToolBar = new VBoxToolBar(this); 483 mVMToolBar->setContextMenuPolicy(Qt::CustomContextMenu); 1270 enum 1271 { 1272 Dtls = 0, 1273 Snap, 1274 Desc 1275 }; 1276 1277 UIVMDesktop::UIVMDesktop(VBoxToolBar *pToolBar, QAction *pRefreshAction, QWidget *pParent /* = 0 */) 1278 : QIWithRetranslateUI<QWidget>(pParent) 1279 { 1280 m_pHeaderBtn = new UITexturedSegmentedButton(3); 1281 m_pHeaderBtn->setIcon(Dtls, UIIconPool::iconSet(":/settings_16px.png")); 1282 m_pHeaderBtn->setIcon(Snap, UIIconPool::iconSet(":/take_snapshot_16px.png", 1283 ":/take_snapshot_dis_16px.png")); 1284 m_pHeaderBtn->setIcon(Desc, UIIconPool::iconSet(":/description_16px.png", 1285 ":/description_disabled_16px.png")); 1286 m_pHeaderBtn->animateClick(0); 1287 1288 QVBoxLayout *pMainLayout = new QVBoxLayout(this); 1289 pMainLayout->setContentsMargins(0, 0, 0, 0); 1290 1291 /* The header to select the different pages. Has different styles on the 1292 * different platforms. */ 1293 #ifdef DARWIN_USE_TOOLBAR 1294 if (pToolBar) 1295 { 1296 pToolBar->addWidget(new UIHorizontalSpacerWidget(this)); 1297 pToolBar->addWidget(m_pHeaderBtn); 1298 pToolBar->addWidget(new UIHorizontalSpacerWidget(this)); 1299 pToolBar->updateLayout(); 1300 } else 1301 #else /* DARWIN_USE_TOOLBAR */ 1302 NOREF(pToolBar); 1303 #endif /* !DARWIN_USE_TOOLBAR */ 1304 { 1305 UIBar *pBar = new UIBar(this); 484 1306 #ifndef Q_WS_MAC 485 connect(mVMToolBar, SIGNAL(customContextMenuRequested(const QPoint&)), 486 this, SLOT(showViewContextMenu(const QPoint&))); 487 #else /* !Q_WS_MAC */ 488 /* A simple connect doesn't work on the Mac, also we want receive right 489 * click notifications on the title bar. So register our own handler. */ 490 ::darwinRegisterForUnifiedToolbarContextMenuEvents(this); 491 #endif /* Q_WS_MAC */ 492 493 /* VM list view */ 494 mVMListView = new UIVMListView(); 495 mVMModel = new UIVMItemModel(mVMListView); 496 mVMListView->setModel(mVMModel); 497 mVMListView->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); 498 499 /* Make non-possible to activate list elements by single click, 500 * this hack should disable the current possibility to do it if present */ 501 if (mVMListView->style()->styleHint (QStyle::SH_ItemView_ActivateItemOnSingleClick, 0, mVMListView)) 502 mVMListView->setStyleSheet ("activate-on-singleclick : 0"); 503 504 #if MAC_LEOPARD_STYLE 505 /* Enable unified toolbars on Mac OS X. Available on Qt >= 4.3 */ 506 addToolBar (mVMToolBar); 507 mVMToolBar->setMacToolbar(); 508 pSplitter->addWidget (mVMListView); 509 #else /* MAC_LEOPARD_STYLE */ 510 QWidget *pLeftWidget = new QWidget(this); 511 QVBoxLayout *pLeftVLayout = new QVBoxLayout(pLeftWidget); 512 pLeftVLayout->setContentsMargins(5, 5, 0, 0); 513 pLeftVLayout->addWidget(mVMToolBar); 514 pLeftVLayout->addWidget(mVMListView); 515 pSplitter->addWidget(pLeftWidget); 516 #endif /* MAC_LEOPARD_STYLE */ 517 518 /* VM tab widget containing details and snapshots tabs */ 519 mVmTabWidget = new QITabWidget(); 520 pSplitter->addWidget (mVmTabWidget); 521 522 /* Set the initial distribution. The right site is bigger. */ 523 pSplitter->setStretchFactor(0, 2); 524 pSplitter->setStretchFactor(1, 3); 525 526 527 /* VM details view */ 528 mVmDetailsView = new VBoxVMDetailsView (NULL, mVmRefreshAction); 529 mVmTabWidget->addTab(mVmDetailsView, 530 UIIconPool::iconSet(":/settings_16px.png"), 531 QString::null); 532 533 /* VM snapshots list */ 534 mVmSnapshotsWgt = new VBoxSnapshotsWgt (NULL); 535 mVmTabWidget->addTab(mVmSnapshotsWgt, 536 UIIconPool::iconSet(":/take_snapshot_16px.png", 537 ":/take_snapshot_dis_16px.png"), 538 QString::null); 539 mVmSnapshotsWgt->setContentsMargins (10, 10, 10, 10); 540 541 /* VM comments page */ 542 mVmDescriptionPage = new VBoxVMDescriptionPage (this); 543 mVmTabWidget->addTab(mVmDescriptionPage, 544 UIIconPool::iconSet(":/description_16px.png", 545 ":/description_disabled_16px.png"), 546 QString::null); 547 mVmDescriptionPage->setContentsMargins (10, 10, 10, 10); 548 549 /* add actions to the toolbar */ 550 551 mVMToolBar->setIconSize (QSize (32, 32)); 552 mVMToolBar->setToolButtonStyle (Qt::ToolButtonTextUnderIcon); 553 mVMToolBar->setSizePolicy (QSizePolicy::Fixed, QSizePolicy::Preferred); 554 555 mVMToolBar->addAction (mVmNewAction); 556 mVMToolBar->addAction (mVmConfigAction); 557 #if 0 /* delete action is really rare */ 558 mVMToolBar->addAction (mVmDeleteAction); 559 #endif 560 mVMToolBar->addAction (mVmStartAction); 561 mVMToolBar->addAction (mVmDiscardAction); 562 563 /* Configure menubar */ 564 menuBar()->setContextMenuPolicy(Qt::CustomContextMenu); 565 connect(menuBar(), SIGNAL(customContextMenuRequested(const QPoint&)), 566 this, SLOT(showViewContextMenu(const QPoint&))); 567 568 /* add actions to menubar */ 569 mFileMenu = menuBar()->addMenu (QString::null); 570 mFileMenu->addAction (mFileMediaMgrAction); 571 mFileMenu->addAction (mFileApplianceImportAction); 572 mFileMenu->addAction (mFileApplianceExportAction); 573 #ifndef Q_WS_MAC 574 mFileMenu->addSeparator(); 575 #endif /* Q_WS_MAC */ 576 mFileMenu->addAction (mFileSettingsAction); 577 #ifndef Q_WS_MAC 578 mFileMenu->addSeparator(); 579 #endif /* Q_WS_MAC */ 580 mFileMenu->addAction (mFileExitAction); 581 582 mVMMenu = menuBar()->addMenu (QString::null); 583 mVMMenu->addAction (mVmNewAction); 584 mVMMenu->addAction (mVmConfigAction); 585 mVMMenu->addAction (mVmDeleteAction); 586 mVMMenu->addSeparator(); 587 mVMMenu->addAction (mVmStartAction); 588 mVMMenu->addAction (mVmDiscardAction); 589 mVMMenu->addAction (mVmPauseAction); 590 mVMMenu->addSeparator(); 591 mVMMenu->addAction (mVmRefreshAction); 592 mVMMenu->addAction (mVmShowLogsAction); 593 594 mVMCtxtMenu = new QMenu (this); 595 mVMCtxtMenu->addAction (mVmConfigAction); 596 mVMCtxtMenu->addAction (mVmDeleteAction); 597 mVMCtxtMenu->addSeparator(); 598 mVMCtxtMenu->addAction (mVmStartAction); 599 mVMCtxtMenu->addAction (mVmDiscardAction); 600 mVMCtxtMenu->addAction (mVmPauseAction); 601 mVMCtxtMenu->addSeparator(); 602 mVMCtxtMenu->addAction (mVmRefreshAction); 603 mVMCtxtMenu->addAction (mVmShowLogsAction); 604 605 /* Make sure every status bar hint from the context menu is cleared when 606 * the menu is closed. */ 607 connect (mVMCtxtMenu, SIGNAL(aboutToHide()), 608 statusBar(), SLOT(clearMessage())); 609 610 mHelpMenu = menuBar()->addMenu (QString::null); 611 mHelpActions.addTo (mHelpMenu); 612 613 #ifdef VBOX_GUI_WITH_SYSTRAY 614 mTrayIcon = new VBoxTrayIcon (this, mVMModel); 615 Assert (mTrayIcon); 616 connect (mTrayIcon, SIGNAL (activated (QSystemTrayIcon::ActivationReason)), 617 this, SLOT (trayIconActivated (QSystemTrayIcon::ActivationReason))); 618 #endif 1307 // pBar->setFixedHeight(65); 1308 #endif /* !Q_WS_MAC */ 1309 pBar->setContentWidget(m_pHeaderBtn); 1310 pMainLayout->addWidget(pBar); 1311 } 1312 1313 /* Add the pages */ 1314 QStackedLayout *pStack = new QStackedLayout(pMainLayout); 1315 1316 m_pDetails = new UIDetailsPagePrivate(this, pRefreshAction); 1317 connect(m_pDetails, SIGNAL(linkClicked(const QString&)), 1318 this, SIGNAL(linkClicked(const QString&))); 1319 pStack->addWidget(m_pDetails); 1320 m_pSnapshotsPage = new VBoxSnapshotsWgt(this); 1321 m_pSnapshotsPage->setContentsMargins(gsLeftMargin, gsTopMargin, gsRightMargin, gsBottomMargin); 1322 pStack->addWidget(m_pSnapshotsPage); 1323 m_pDescription = new UIDescriptionPagePrivate(this); 1324 connect(m_pDescription, SIGNAL(linkClicked(const QString&)), 1325 this, SIGNAL(linkClicked(const QString&))); 1326 m_pDescription->setContentsMargins(gsLeftMargin, gsTopMargin, gsRightMargin, gsBottomMargin); 1327 pStack->addWidget(m_pDescription); 1328 1329 /* Connect the header buttons with the stack layout. */ 1330 connect(m_pHeaderBtn, SIGNAL(clicked(int)), 1331 pStack, SLOT(setCurrentIndex(int))); 619 1332 620 1333 retranslateUi(); 621 622 CVirtualBox vbox = vboxGlobal().virtualBox(); 623 /* Restore the position of the window */ 624 { 625 QString winPos = vbox.GetExtraData (VBoxDefs::GUI_LastWindowPosition); 626 627 bool ok = false, max = false; 628 int x = 0, y = 0, w = 0, h = 0; 629 x = winPos.section (',', 0, 0).toInt (&ok); 630 if (ok) 631 y = winPos.section (',', 1, 1).toInt (&ok); 632 if (ok) 633 w = winPos.section (',', 2, 2).toInt (&ok); 634 if (ok) 635 h = winPos.section (',', 3, 3).toInt (&ok); 636 if (ok) 637 max = winPos.section (',', 4, 4) == VBoxDefs::GUI_LastWindowState_Max; 638 639 QRect ar = ok ? QApplication::desktop()->availableGeometry (QPoint (x, y)) : 640 QApplication::desktop()->availableGeometry (this); 641 642 if (ok /* previous parameters were read correctly */ 643 && (y > 0) && (y < ar.bottom()) /* check vertical bounds */ 644 && (x + w > ar.left()) && (x < ar.right()) /* & horizontal bounds */) 645 { 646 mNormalGeo.moveTo (x, y); 647 mNormalGeo.setSize (QSize (w, h).expandedTo (minimumSizeHint()) 648 .boundedTo (ar.size())); 649 setGeometry (mNormalGeo); 650 if (max) /* maximize if needed */ 651 showMaximized(); 652 } 653 else 654 { 655 mNormalGeo.setSize (QSize (770, 550).expandedTo (minimumSizeHint()) 656 .boundedTo (ar.size())); 657 mNormalGeo.moveCenter (ar.center()); 658 setGeometry (mNormalGeo); 659 } 660 } 661 662 /* Update the list */ 663 refreshVMList(); 664 665 /* Reset to the first item */ 666 mVMListView->selectItemByRow (0); 667 668 /* restore the position of vm selector */ 669 { 670 QString prevVMId = vbox.GetExtraData (VBoxDefs::GUI_LastVMSelected); 671 672 mVMListView->selectItemById (prevVMId); 673 } 674 675 /* Read the splitter handle position */ 676 { 677 QString sliderPos = vbox.GetExtraData(VBoxDefs::GUI_SplitterSizes); 678 QStringList strSizes = sliderPos.split(","); 679 if (strSizes.size() == 2) 680 { 681 QList<int> sizes; 682 for (int i=0; i < strSizes.size(); ++i) 683 sizes << strSizes.at(i).toInt(); 684 pSplitter->setSizes(sizes); 685 } 686 } 687 688 /* Restore toolbar and statusbar visibility */ 689 { 690 QString strToolbar = vbox.GetExtraData(VBoxDefs::GUI_Toolbar); 691 QString strStatusbar = vbox.GetExtraData(VBoxDefs::GUI_Statusbar); 692 693 mVMToolBar->setVisible(strToolbar.isEmpty() || strToolbar == "true"); 694 statusBar()->setVisible(strStatusbar.isEmpty() || strStatusbar == "true"); 695 } 696 697 /* refresh the details et all (necessary for the case when the stored 698 * selection is still the first list item) */ 699 vmListViewCurrentChanged(); 700 701 /* signals and slots connections */ 702 connect (mFileMediaMgrAction, SIGNAL (triggered()), this, SLOT (fileMediaMgr())); 703 connect (mFileApplianceImportAction, SIGNAL (triggered()), this, SLOT (fileImportAppliance())); 704 connect (mFileApplianceExportAction, SIGNAL (triggered()), this, SLOT (fileExportAppliance())); 705 connect (mFileSettingsAction, SIGNAL (triggered()), this, SLOT (fileSettings())); 706 connect (mFileExitAction, SIGNAL (triggered()), this, SLOT (fileExit())); 707 connect (mVmNewAction, SIGNAL (triggered()), this, SLOT (vmNew())); 708 709 connect (mVmConfigAction, SIGNAL (triggered()), this, SLOT (vmSettings())); 710 connect (mVmDeleteAction, SIGNAL (triggered()), this, SLOT (vmDelete())); 711 connect (mVmStartAction, SIGNAL (triggered()), this, SLOT (vmStart())); 712 connect (mVmDiscardAction, SIGNAL (triggered()), this, SLOT (vmDiscard())); 713 connect (mVmPauseAction, SIGNAL (toggled (bool)), this, SLOT (vmPause (bool))); 714 connect (mVmRefreshAction, SIGNAL (triggered()), this, SLOT (vmRefresh())); 715 connect (mVmShowLogsAction, SIGNAL (triggered()), this, SLOT (vmShowLogs())); 716 717 connect (mVMListView, SIGNAL (currentChanged()), 718 this, SLOT (vmListViewCurrentChanged())); 719 connect (mVMListView, SIGNAL (activated()), 720 this, SLOT (vmStart())); 721 connect (mVMListView, SIGNAL (customContextMenuRequested (const QPoint &)), 722 this, SLOT (showContextMenu (const QPoint &))); 723 724 connect (mVmDetailsView, SIGNAL (linkClicked (const QString &)), 725 this, SLOT(vmSettings(const QString &))); 726 727 /* listen to media enumeration signals */ 728 connect (&vboxGlobal(), SIGNAL (mediumEnumStarted()), 729 this, SLOT (mediumEnumStarted())); 730 connect (&vboxGlobal(), SIGNAL (mediumEnumFinished (const VBoxMediaList &)), 731 this, SLOT (mediumEnumFinished (const VBoxMediaList &))); 732 733 /* connect VirtualBox events */ 734 connect (gVBoxEvents, SIGNAL(sigMachineStateChange(QString, KMachineState)), 735 this, SLOT(machineStateChanged(QString, KMachineState))); 736 connect (gVBoxEvents, SIGNAL(sigMachineDataChange(QString)), 737 this, SLOT(machineDataChanged(QString))); 738 connect (gVBoxEvents, SIGNAL(sigMachineRegistered(QString, bool)), 739 this, SLOT(machineRegistered(QString, bool))); 740 connect (gVBoxEvents, SIGNAL(sigSessionStateChange(QString, KSessionState)), 741 this, SLOT(sessionStateChanged(QString, KSessionState))); 742 connect (gVBoxEvents, SIGNAL(sigSnapshotChange(QString, QString)), 743 this, SLOT(snapshotChanged(QString, QString))); 744 #ifdef VBOX_GUI_WITH_SYSTRAY 745 connect (gEDataEvents, SIGNAL(sigMainWindowCountChange(int)), 746 this, SLOT(mainWindowCountChanged(int))); 747 connect (gEDataEvents, SIGNAL(sigCanShowTrayIcon(bool)), 748 this, SLOT(trayIconCanShow(bool))); 749 connect (gEDataEvents, SIGNAL(sigTrayIconChange(bool)), 750 this, SLOT(trayIconChanged(bool))); 751 connect (&vboxGlobal(), SIGNAL(sigTrayIconShow(bool)), 752 this, SLOT(trayIconShow(bool))); 753 #endif 754 755 /* Listen to potential downloaders signals: */ 756 connect(&vboxProblem(), SIGNAL(sigDownloaderUserManualCreated()), this, SLOT(sltDownloaderUserManualEmbed())); 757 758 /* bring the VM list to the focus */ 759 mVMListView->setFocus(); 760 } 761 762 VBoxSelectorWnd::~VBoxSelectorWnd() 763 { 764 /* Destroy our event handlers */ 765 UIVirtualBoxEventHandler::destroy(); 766 767 CVirtualBox vbox = vboxGlobal().virtualBox(); 768 769 /* Save the position of the window */ 770 { 771 int y = mNormalGeo.y(); 772 QString winPos = QString ("%1,%2,%3,%4") 773 .arg (mNormalGeo.x()).arg (y) 774 .arg (mNormalGeo.width()).arg (mNormalGeo.height()); 775 #ifdef Q_WS_MAC 776 ::darwinUnregisterForUnifiedToolbarContextMenuEvents(this); 777 if (::darwinIsWindowMaximized(this)) 778 #else /* Q_WS_MAC */ 779 if (isMaximized()) 780 #endif /* !Q_WS_MAC */ 781 winPos += QString (",%1").arg (VBoxDefs::GUI_LastWindowState_Max); 782 783 vbox.SetExtraData (VBoxDefs::GUI_LastWindowPosition, winPos); 784 } 785 786 /* Save VM selector position */ 787 { 788 UIVMItem *item = mVMListView->selectedItem(); 789 QString curVMId = item ? 790 QString (item->id()) : 791 QString::null; 792 vbox.SetExtraData (VBoxDefs::GUI_LastVMSelected, curVMId); 793 } 794 795 /* Save the splitter handle position */ 796 { 797 QSplitter *pSplitter = static_cast<QSplitter*>(centralWidget()); 798 QList<int> sizes = pSplitter->sizes(); 799 QStringList strSizes; 800 for (int i=0; i < sizes.size(); ++i) 801 strSizes << QString::number(sizes.at(i)); 802 vbox.SetExtraData(VBoxDefs::GUI_SplitterSizes, strSizes.join(",")); 803 } 804 805 #ifdef VBOX_GUI_WITH_SYSTRAY 806 /* Delete systray menu object */ 807 delete mTrayIcon; 808 mTrayIcon = NULL; 809 #endif 810 811 /* Delete the items from our model */ 812 mVMModel->clear(); 813 } 814 815 // 816 // Public slots 817 ///////////////////////////////////////////////////////////////////////////// 818 819 void VBoxSelectorWnd::fileMediaMgr() 820 { 821 VBoxMediaManagerDlg::showModeless (this); 822 } 823 824 void VBoxSelectorWnd::fileImportAppliance() 825 { 826 UIImportApplianceWzd wzd (this); 827 828 wzd.exec(); 829 } 830 831 void VBoxSelectorWnd::fileExportAppliance() 832 { 833 QString name; 834 835 UIVMItem *item = mVMListView->selectedItem(); 836 if (item) 837 name = item->name(); 838 839 UIExportApplianceWzd wzd (this, name); 840 841 wzd.exec(); 842 } 843 844 void VBoxSelectorWnd::fileSettings() 845 { 846 VBoxGlobalSettings settings = vboxGlobal().settings(); 847 CSystemProperties props = vboxGlobal().virtualBox().GetSystemProperties(); 848 849 VBoxSettingsDialog *dlg = new VBoxGLSettingsDlg (this); 850 dlg->getFrom(); 851 852 if (dlg->exec() == QDialog::Accepted) 853 dlg->putBackTo(); 854 855 delete dlg; 856 } 857 858 void VBoxSelectorWnd::fileExit() 859 { 860 /* We have to check if there are any open windows beside this mainwindow 861 * (e.g. VDM) and if so close them. Note that the default behavior is 862 * different to Qt3 where a *mainWidget* exists & if this going to close 863 * all other windows are closed automatically. We do the same below. */ 864 foreach (QWidget *widget, QApplication::topLevelWidgets()) 865 { 866 if (widget->isVisible() && 867 widget != this) 868 widget->close(); 869 } 870 /* We close this widget last. */ 871 close(); 872 } 873 874 void VBoxSelectorWnd::vmNew() 875 { 876 UINewVMWzd wzd (this); 877 if (wzd.exec() == QDialog::Accepted) 878 { 879 CMachine m = wzd.machine(); 880 881 /* wait until the list is updated by OnMachineRegistered() */ 882 QModelIndex index; 883 while (!index.isValid()) 884 { 885 qApp->processEvents(); 886 index = mVMModel->indexById (m.GetId()); 887 } 888 mVMListView->setCurrentIndex (index); 889 } 890 } 891 892 /** 893 * Opens the VM settings dialog. 894 */ 895 void VBoxSelectorWnd::vmSettings (const QString &aCategory, const QString &aControl, 896 const QString &aUuid /* = QString::null */) 897 { 898 if (!aCategory.isEmpty() && aCategory [0] != '#') 899 { 900 /* Assume it's a href from the Details HTML */ 901 vboxGlobal().openURL (aCategory); 902 return; 903 } 904 905 UIVMItem *item = aUuid.isNull() ? mVMListView->selectedItem() : 906 mVMModel->itemById (aUuid); 907 908 AssertMsgReturnVoid (item, ("Item must be always selected here")); 909 910 // open a direct session to modify VM settings 911 QString id = item->id(); 912 CSession session = vboxGlobal().openSession (id); 913 if (session.isNull()) 914 return; 915 916 CMachine m = session.GetMachine(); 917 AssertMsgReturn (!m.isNull(), ("Machine must not be null"), (void) 0); 918 919 VBoxSettingsDialog *dlg = new VBoxVMSettingsDlg (this, m, aCategory, aControl); 920 dlg->getFrom(); 921 922 if (dlg->exec() == QDialog::Accepted) 923 { 924 QString oldName = m.GetName(); 925 dlg->putBackTo(); 926 927 m.SaveSettings(); 928 if (m.isOk()) 929 { 930 if (oldName.compare (m.GetName())) 931 mVMModel->sort(); 932 } 933 else 934 vboxProblem().cannotSaveMachineSettings (m); 935 936 /* To check use the result in future 937 * vboxProblem().cannotApplyMachineSettings (m, res); */ 938 } 939 940 delete dlg; 941 942 mVMListView->setFocus(); 943 944 session.Close(); 945 } 946 947 void VBoxSelectorWnd::vmDelete (const QString &aUuid /* = QString::null */) 948 { 949 UIVMItem *item = aUuid.isNull() ? mVMListView->selectedItem() : 950 mVMModel->itemById (aUuid); 951 952 AssertMsgReturnVoid (item, ("Item must be always selected here")); 953 954 if (vboxProblem().confirmMachineDeletion (item->machine())) 955 { 956 CVirtualBox vbox = vboxGlobal().virtualBox(); 957 QString id = item->id(); 958 bool ok = false; 959 if (item->accessible()) 960 { 961 /* Open a direct session to modify VM settings */ 962 CSession session = vboxGlobal().openSession (id); 963 if (session.isNull()) 964 return; 965 CMachine machine = session.GetMachine(); 966 /* Detach all attached Hard Disks */ 967 CMediumAttachmentVector vec = machine.GetMediumAttachments(); 968 for (int i = 0; i < vec.size(); ++ i) 969 { 970 CMediumAttachment hda = vec [i]; 971 const QString ctlName = hda.GetController(); 972 973 machine.DetachDevice(ctlName, hda.GetPort(), hda.GetDevice()); 974 if (!machine.isOk()) 975 { 976 CStorageController ctl = machine.GetStorageControllerByName(ctlName); 977 vboxProblem().cannotDetachDevice (this, machine, VBoxDefs::MediumType_HardDisk, 978 vboxGlobal().getMedium (CMedium (hda.GetMedium())).location(), 979 ctl.GetBus(), hda.GetPort(), hda.GetDevice()); 980 } 981 } 982 /* Commit changes */ 983 machine.SaveSettings(); 984 if (!machine.isOk()) 985 vboxProblem().cannotSaveMachineSettings (machine); 986 else 987 ok = true; 988 session.Close(); 989 } 990 else 991 ok = true; 992 993 if (ok) 994 { 995 CMachine machine = item->machine(); 996 vbox.UnregisterMachine (id); 997 if (vbox.isOk() && item->accessible()) 998 { 999 /* delete machine settings */ 1000 machine.DeleteSettings(); 1001 /* remove the item shortly: cmachine it refers to is no longer valid! */ 1002 int row = mVMModel->rowById (item->id()); 1003 mVMModel->removeItem (item); 1004 delete item; 1005 mVMListView->ensureSomeRowSelected (row); 1006 } 1007 if (!vbox.isOk() || !machine.isOk()) 1008 vboxProblem().cannotDeleteMachine (vbox, machine); 1009 } 1010 } 1011 } 1012 1013 void VBoxSelectorWnd::vmStart (const QString &aUuid /* = QString::null */) 1014 { 1015 QUuid uuid (aUuid); 1016 UIVMItem *item = uuid.isNull() ? mVMListView->selectedItem() : 1017 mVMModel->itemById (aUuid); 1018 1019 AssertMsgReturnVoid (item, ("Item must be always selected here")); 1020 1021 /* Are we called from the mVMListView's activated() signal? */ 1022 if (uuid.isNull()) 1023 { 1024 /* We always get here when mVMListView emits the activated() signal, 1025 * so we must explicitly check if the action is enabled or not. */ 1026 if (!mVmStartAction->isEnabled()) 1027 return; 1028 } 1029 1030 AssertMsg (!vboxGlobal().isVMConsoleProcess(), 1031 ("Must NOT be a VM console process")); 1032 1033 /* just switch to the VM window if it already exists */ 1034 if (item->canSwitchTo()) 1035 { 1036 item->switchTo(); 1037 return; 1038 } 1039 1040 AssertMsg ( item->state() == KMachineState_PoweredOff 1041 || item->state() == KMachineState_Saved 1042 || item->state() == KMachineState_Teleported 1043 || item->state() == KMachineState_Aborted 1044 , ("Machine must be PoweredOff/Saved/Aborted (%d)", item->state())); 1045 1046 QString id = item->id(); 1047 CVirtualBox vbox = vboxGlobal().virtualBox(); 1048 CSession session; 1049 1050 session.createInstance (CLSID_Session); 1051 if (session.isNull()) 1052 { 1053 vboxProblem().cannotOpenSession (session); 1054 return; 1055 } 1056 1057 #if defined (Q_OS_WIN32) 1058 /* allow the started VM process to make itself the foreground window */ 1059 AllowSetForegroundWindow (ASFW_ANY); 1060 #endif 1061 1062 QString env; 1063 #if defined (Q_WS_X11) 1064 /* make sure the VM process will start on the same display as the Selector */ 1065 const char *display = RTEnvGet ("DISPLAY"); 1066 if (display) 1067 env.append(QString("DISPLAY=%1\n").arg(display)); 1068 const char *xauth = RTEnvGet ("XAUTHORITY"); 1069 if (xauth) 1070 env.append(QString("XAUTHORITY=%1\n").arg(xauth)); 1071 #endif 1072 1073 CProgress progress = vbox.OpenRemoteSession (session, id, "GUI/Qt", env); 1074 if (!vbox.isOk()) 1075 { 1076 vboxProblem().cannotOpenSession (vbox, item->machine()); 1077 return; 1078 } 1079 1080 /* Hide the "VM spawning" progress dialog */ 1081 /* I hope 1 minute will be enough to spawn any running VM silently, isn't it? */ 1082 int iSpawningDuration = 60000; 1083 vboxProblem().showModalProgressDialog(progress, item->name(), this, iSpawningDuration); 1084 if (progress.GetResultCode() != 0) 1085 vboxProblem().cannotOpenSession(vbox, item->machine(), progress); 1086 1087 session.Close(); 1088 } 1089 1090 void VBoxSelectorWnd::vmDiscard (const QString &aUuid /* = QString::null */) 1091 { 1092 UIVMItem *item = aUuid.isNull() ? mVMListView->selectedItem() : 1093 mVMModel->itemById (aUuid); 1094 1095 AssertMsgReturnVoid (item, ("Item must be always selected here")); 1096 1097 if (!vboxProblem().confirmDiscardSavedState (item->machine())) 1098 return; 1099 1100 /* open a session to modify VM settings */ 1101 QString id = item->id(); 1102 CSession session; 1103 CVirtualBox vbox = vboxGlobal().virtualBox(); 1104 session.createInstance (CLSID_Session); 1105 if (session.isNull()) 1106 { 1107 vboxProblem().cannotOpenSession (session); 1108 return; 1109 } 1110 vbox.OpenSession (session, id); 1111 if (!vbox.isOk()) 1112 { 1113 vboxProblem().cannotOpenSession (vbox, item->machine()); 1114 return; 1115 } 1116 1117 CConsole console = session.GetConsole(); 1118 console.ForgetSavedState(true); 1119 if (!console.isOk()) 1120 vboxProblem().cannotDiscardSavedState (console); 1121 1122 session.Close(); 1123 } 1124 1125 void VBoxSelectorWnd::vmPause (bool aPause, const QString &aUuid /* = QString::null */) 1126 { 1127 UIVMItem *item = aUuid.isNull() ? mVMListView->selectedItem() : 1128 mVMModel->itemById (aUuid); 1129 1130 AssertMsgReturnVoid (item, ("Item must be always selected here")); 1131 1132 CSession session = vboxGlobal().openExistingSession (item->id()); 1133 if (session.isNull()) 1134 return; 1135 1136 CConsole console = session.GetConsole(); 1137 if (console.isNull()) 1138 return; 1139 1140 if (aPause) 1141 console.Pause(); 1142 else 1143 console.Resume(); 1144 1145 bool ok = console.isOk(); 1146 if (!ok) 1147 { 1148 if (aPause) 1149 vboxProblem().cannotPauseMachine (console); 1150 else 1151 vboxProblem().cannotResumeMachine (console); 1152 } 1153 1154 session.Close(); 1155 } 1156 1157 void VBoxSelectorWnd::vmRefresh (const QString &aUuid /* = QString::null */) 1158 { 1159 UIVMItem *item = aUuid.isNull() ? mVMListView->selectedItem() : 1160 mVMModel->itemById (aUuid); 1161 1162 AssertMsgReturnVoid (item, ("Item must be always selected here")); 1163 1164 refreshVMItem (item->id(), 1165 true /* aDetails */, 1166 true /* aSnapshot */, 1167 true /* aDescription */); 1168 } 1169 1170 void VBoxSelectorWnd::vmShowLogs (const QString &aUuid /* = QString::null */) 1171 { 1172 UIVMItem *item = aUuid.isNull() ? mVMListView->selectedItem() : 1173 mVMModel->itemById (aUuid); 1174 1175 AssertMsgReturnVoid (item, ("Item must be always selected here")); 1176 1177 CMachine machine = item->machine(); 1178 VBoxVMLogViewer::createLogViewer (this, machine); 1179 } 1180 1181 void VBoxSelectorWnd::refreshVMList() 1182 { 1183 CVirtualBox vbox = vboxGlobal().virtualBox(); 1184 CMachineVector vec = vbox.GetMachines(); 1185 for (CMachineVector::ConstIterator m = vec.begin(); 1186 m != vec.end(); ++ m) 1187 mVMModel->addItem (new UIVMItem (*m)); 1188 mVMModel->sort(); 1189 1190 vmListViewCurrentChanged(); 1191 1192 #ifdef VBOX_GUI_WITH_SYSTRAY 1193 if (vboxGlobal().isTrayMenu()) 1194 mTrayIcon->refresh(); 1195 #endif 1196 } 1197 1198 void VBoxSelectorWnd::refreshVMItem (const QString &aID, bool aDetails, 1199 bool aSnapshots, 1200 bool aDescription) 1201 { 1202 UIVMItem *item = mVMModel->itemById (aID); 1203 if (item) 1204 { 1205 mVMModel->refreshItem (item); 1206 if (item && item->id() == aID) 1207 vmListViewCurrentChanged (aDetails, aSnapshots, aDescription); 1208 } 1209 } 1210 1211 void VBoxSelectorWnd::showContextMenu (const QPoint &aPoint) 1212 { 1213 /* Send a context menu request */ 1214 const QModelIndex &index = mVMListView->indexAt (aPoint); 1215 if (index.isValid()) 1216 if (mVMListView->model()->data (index, 1217 UIVMItemModel::UIVMItemPtrRole).value <UIVMItem*>()) 1218 mVMCtxtMenu->exec (mVMListView->mapToGlobal (aPoint)); 1219 } 1220 1221 #ifdef VBOX_GUI_WITH_SYSTRAY 1222 1223 void VBoxSelectorWnd::trayIconActivated (QSystemTrayIcon::ActivationReason aReason) 1224 { 1225 switch (aReason) 1226 { 1227 case QSystemTrayIcon::Context: 1228 1229 mTrayIcon->refresh(); 1230 break; 1231 1232 case QSystemTrayIcon::Trigger: 1233 break; 1234 1235 case QSystemTrayIcon::DoubleClick: 1236 1237 vboxGlobal().trayIconShowSelector(); 1238 break; 1239 1240 case QSystemTrayIcon::MiddleClick: 1241 break; 1242 1243 default: 1244 break; 1245 } 1246 } 1247 1248 void VBoxSelectorWnd::showWindow() 1249 { 1250 showNormal(); 1251 raise(); 1252 activateWindow(); 1253 } 1254 1255 #endif // VBOX_GUI_WITH_SYSTRAY 1256 1257 // Protected members 1258 ///////////////////////////////////////////////////////////////////////////// 1259 1260 bool VBoxSelectorWnd::event (QEvent *e) 1261 { 1262 switch (e->type()) 1263 { 1264 /* By handling every Resize and Move we keep track of the normal 1265 * (non-minimized and non-maximized) window geometry. Shame on Qt 1266 * that it doesn't provide this geometry in its public APIs. */ 1267 1268 case QEvent::Resize: 1269 { 1270 QResizeEvent *re = (QResizeEvent *) e; 1271 if ((windowState() & (Qt::WindowMaximized | Qt::WindowMinimized | 1272 Qt::WindowFullScreen)) == 0) 1273 mNormalGeo.setSize (re->size()); 1274 break; 1275 } 1276 case QEvent::Move: 1277 { 1278 if ((windowState() & (Qt::WindowMaximized | Qt::WindowMinimized | 1279 Qt::WindowFullScreen)) == 0) 1280 mNormalGeo.moveTo (geometry().x(), geometry().y()); 1281 break; 1282 } 1283 case QEvent::WindowDeactivate: 1284 { 1285 /* Make sure every status bar hint is cleared when the window lost 1286 * focus. */ 1287 statusBar()->clearMessage(); 1288 break; 1289 } 1290 #ifdef Q_WS_MAC 1291 case QEvent::ContextMenu: 1292 { 1293 /* This is the unified context menu event. Lets show the context 1294 * menu. */ 1295 QContextMenuEvent *pCE = static_cast<QContextMenuEvent*>(e); 1296 showViewContextMenu(pCE->globalPos()); 1297 /* Accept it to interrupt the chain. */ 1298 pCE->accept(); 1299 return false; 1300 break; 1301 } 1302 case QEvent::ToolBarChange: 1303 { 1304 CVirtualBox vbox = vboxGlobal().virtualBox(); 1305 /* We have to invert the isVisible check one time, cause this event 1306 * is sent *before* the real toggle is done. Really intuitive 1307 * Trolls. */ 1308 vbox.SetExtraData(VBoxDefs::GUI_Toolbar, !::darwinIsToolbarVisible(mVMToolBar) ? "true" : "false"); 1309 break; 1310 } 1311 #endif /* Q_WS_MAC */ 1312 default: 1313 break; 1314 } 1315 1316 return QMainWindow::event (e); 1317 } 1318 1319 void VBoxSelectorWnd::closeEvent (QCloseEvent *aEvent) 1320 { 1321 #ifdef VBOX_GUI_WITH_SYSTRAY 1322 /* Needed for breaking out of the while() loop in main(). */ 1323 if (vboxGlobal().isTrayMenu()) 1324 vboxGlobal().setTrayMenu (false); 1325 #endif 1326 1327 emit closing(); 1328 QMainWindow::closeEvent (aEvent); 1329 } 1330 1331 #if defined (Q_WS_MAC) && (QT_VERSION < 0x040402) 1332 bool VBoxSelectorWnd::eventFilter (QObject *aObject, QEvent *aEvent) 1333 { 1334 if (!isActiveWindow()) 1335 return QIWithRetranslateUI2<QMainWindow>::eventFilter (aObject, aEvent); 1336 1337 if (qobject_cast<QWidget*> (aObject) && 1338 qobject_cast<QWidget*> (aObject)->window() != this) 1339 return QIWithRetranslateUI2<QMainWindow>::eventFilter (aObject, aEvent); 1340 1341 switch (aEvent->type()) 1342 { 1343 case QEvent::KeyPress: 1344 { 1345 /* Bug in Qt below 4.4.2. The key events are send to the current 1346 * window even if a menu is shown & has the focus. See 1347 * http://trolltech.com/developer/task-tracker/index_html?method=entry&id=214681. */ 1348 if (::darwinIsMenuOpen()) 1349 return true; 1350 } 1351 default: 1352 break; 1353 } 1354 return QIWithRetranslateUI2<QMainWindow>::eventFilter (aObject, aEvent); 1355 } 1356 #endif /* defined (Q_WS_MAC) && (QT_VERSION < 0x040402) */ 1357 1358 /** 1359 * Sets the strings of the subwidgets using the current 1360 * language. 1361 */ 1362 void VBoxSelectorWnd::retranslateUi() 1363 { 1364 #ifdef VBOX_OSE 1365 QString title (tr ("VirtualBox OSE")); 1366 #else 1367 QString title (VBOX_PRODUCT); 1368 #endif 1369 1370 #ifdef VBOX_BLEEDING_EDGE 1371 title += QString(" EXPERIMENTAL build ") 1372 + QString(RTBldCfgVersion()) 1373 + QString(" r") 1374 + QString(RTBldCfgRevisionStr()) 1375 + QString(" - "VBOX_BLEEDING_EDGE); 1376 #endif 1377 1378 setWindowTitle (title); 1379 1380 mVmTabWidget->setTabText (mVmTabWidget->indexOf (mVmDetailsView), tr ("&Details")); 1381 /* note: Snapshots and Details tabs are changed dynamically by 1382 * vmListViewCurrentChanged() */ 1383 1384 /* ensure the details and screenshot view are updated */ 1385 vmListViewCurrentChanged(); 1386 1387 mFileMediaMgrAction->setText (tr ("&Virtual Media Manager...")); 1388 mFileMediaMgrAction->setShortcut (QKeySequence ("Ctrl+D")); 1389 mFileMediaMgrAction->setStatusTip (tr ("Display the Virtual Media Manager dialog")); 1390 1391 mFileApplianceImportAction->setText (tr ("&Import Appliance...")); 1392 mFileApplianceImportAction->setShortcut (QKeySequence ("Ctrl+I")); 1393 mFileApplianceImportAction->setStatusTip (tr ("Import an appliance into VirtualBox")); 1394 1395 mFileApplianceExportAction->setText (tr ("&Export Appliance...")); 1396 mFileApplianceExportAction->setShortcut (QKeySequence ("Ctrl+E")); 1397 mFileApplianceExportAction->setStatusTip (tr ("Export one or more VirtualBox virtual machines as an appliance")); 1398 1399 #ifdef Q_WS_MAC 1400 /* 1401 * Macification: Getting the right menu as application preference menu item. 1402 * 1403 * QMenuBar::isCommand() in qmenubar_mac.cpp doesn't recognize "Setting"(s) 1404 * unless it's in the first position. So, we use the Mac term here to make 1405 * sure we get picked instead of the VM settings. 1406 * 1407 * Now, since both QMenuBar and we translate these strings, it's going to 1408 * be really interesting to see how this plays on non-english systems... 1409 */ 1410 mFileSettingsAction->setText (tr ("&Preferences...", "global settings")); 1411 #else 1412 /* 1413 * ...and on other platforms we use "Preferences" as well. The #ifdef is 1414 * left because of the possible localization problems on Mac we first need 1415 * to figure out. 1416 */ 1417 mFileSettingsAction->setText (tr ("&Preferences...", "global settings")); 1418 #endif 1419 mFileSettingsAction->setShortcut (QKeySequence ("Ctrl+G")); 1420 mFileSettingsAction->setStatusTip (tr ("Display the global settings dialog")); 1421 1422 mFileExitAction->setText (tr ("E&xit")); 1423 mFileExitAction->setShortcut (QKeySequence ("Ctrl+Q")); 1424 mFileExitAction->setStatusTip (tr ("Close application")); 1425 1426 mVmNewAction->setText (tr ("&New...")); 1427 mVmNewAction->setShortcut (QKeySequence ("Ctrl+N")); 1428 mVmNewAction->setStatusTip (tr ("Create a new virtual machine")); 1429 mVmNewAction->setToolTip (mVmNewAction->text().remove ('&').remove ('.') + 1430 QString (" (%1)").arg (mVmNewAction->shortcut().toString())); 1431 1432 mVmConfigAction->setText (tr ("&Settings...")); 1433 mVmConfigAction->setShortcut (QKeySequence ("Ctrl+S")); 1434 mVmConfigAction->setStatusTip (tr ("Configure the selected virtual machine")); 1435 mVmConfigAction->setToolTip (mVmConfigAction->text().remove ('&').remove ('.') + 1436 QString (" (%1)").arg (mVmConfigAction->shortcut().toString())); 1437 1438 mVmDeleteAction->setText (tr ("&Delete")); 1439 mVmDeleteAction->setShortcut (QKeySequence ("Ctrl+R")); 1440 mVmDeleteAction->setStatusTip (tr ("Delete the selected virtual machine")); 1441 1442 /* Note: mVmStartAction text is set up in vmListViewCurrentChanged() */ 1443 1444 mVmDiscardAction->setText (tr ("D&iscard")); 1445 mVmDiscardAction->setStatusTip ( 1446 tr ("Discard the saved state of the selected virtual machine")); 1447 1448 mVmPauseAction->setText (tr ("&Pause")); 1449 mVmPauseAction->setStatusTip ( 1450 tr ("Suspend the execution of the virtual machine")); 1451 1452 mVmRefreshAction->setText (tr ("Re&fresh")); 1453 mVmRefreshAction->setStatusTip ( 1454 tr ("Refresh the accessibility state of the selected virtual machine")); 1455 1456 mVmShowLogsAction->setText (tr ("Show &Log...")); 1457 mVmShowLogsAction->setIconText (tr ("Log", "icon text")); 1458 mVmShowLogsAction->setShortcut (QKeySequence ("Ctrl+L")); 1459 mVmShowLogsAction->setStatusTip ( 1460 tr ("Show the log files of the selected virtual machine")); 1461 1462 mHelpActions.retranslateUi(); 1463 1464 #ifdef Q_WS_MAC 1465 mFileMenu->setTitle (tr("&File", "Mac OS X version")); 1466 #else /* Q_WS_MAC */ 1467 mFileMenu->setTitle (tr("&File", "Non Mac OS X version")); 1468 #endif /* !Q_WS_MAC */ 1469 mVMMenu->setTitle (tr ("&Machine")); 1470 mHelpMenu->setTitle (tr ("&Help")); 1471 1472 #ifdef VBOX_GUI_WITH_SYSTRAY 1473 if (vboxGlobal().isTrayMenu()) 1474 { 1475 mTrayIcon->retranslateUi(); 1476 mTrayIcon->refresh(); 1477 } 1478 #endif 1479 1480 #ifdef QT_MAC_USE_COCOA 1481 /* There is a bug in Qt Cocoa which result in showing a "more arrow" when 1482 the necessary size of the toolbar is increased. Also for some languages 1483 the with doesn't match if the text increase. So manually adjust the size 1484 after changing the text. */ 1485 mVMToolBar->updateLayout(); 1486 #endif /* QT_MAC_USE_COCOA */ 1487 } 1488 1489 1490 // Private members 1491 ///////////////////////////////////////////////////////////////////////////// 1492 1493 // 1494 // Private slots 1495 ///////////////////////////////////////////////////////////////////////////// 1496 1497 void VBoxSelectorWnd::vmListViewCurrentChanged (bool aRefreshDetails, 1498 bool aRefreshSnapshots, 1499 bool aRefreshDescription) 1500 { 1501 UIVMItem *item = mVMListView->selectedItem(); 1502 1503 if (item && item->accessible()) 1504 { 1505 CMachine m = item->machine(); 1506 1507 KMachineState state = item->state(); 1508 bool running = item->sessionState() != KSessionState_Closed; 1509 bool modifyEnabled = !running && state != KMachineState_Saved; 1510 1511 if (aRefreshDetails) 1512 { 1513 mVmDetailsView->setDetailsText ( 1514 vboxGlobal().detailsReport (m, modifyEnabled /* withLinks */)); 1515 } 1516 if (aRefreshSnapshots) 1517 { 1518 /* update the snapshots tab name */ 1519 QString name = tr ("&Snapshots"); 1520 ULONG count = item->snapshotCount(); 1521 if (count) 1522 name += QString (" (%1)").arg (count); 1523 mVmTabWidget->setTabText (mVmTabWidget->indexOf (mVmSnapshotsWgt), name); 1524 /* refresh the snapshots widget */ 1525 mVmSnapshotsWgt->setMachine (m); 1526 /* ensure the tab is enabled */ 1527 mVmTabWidget->setTabEnabled (mVmTabWidget->indexOf (mVmSnapshotsWgt), true); 1528 } 1529 if (aRefreshDescription) 1530 { 1531 /* update the description tab name */ 1532 QString name = m.GetDescription().isEmpty() ? 1533 tr ("D&escription") : tr ("D&escription *"); 1534 mVmTabWidget->setTabText (mVmTabWidget->indexOf (mVmDescriptionPage), name); 1535 /* refresh the description widget */ 1536 mVmDescriptionPage->setMachineItem (item); 1537 /* ensure the tab is enabled */ 1538 mVmTabWidget->setTabEnabled (mVmTabWidget->indexOf (mVmDescriptionPage), true); 1539 } 1540 1541 /* enable/disable modify actions */ 1542 mVmConfigAction->setEnabled (modifyEnabled); 1543 mVmDeleteAction->setEnabled (modifyEnabled); 1544 mVmDiscardAction->setEnabled (state == KMachineState_Saved && !running); 1545 mVmPauseAction->setEnabled ( state == KMachineState_Running 1546 || state == KMachineState_Teleporting 1547 || state == KMachineState_LiveSnapshotting 1548 || state == KMachineState_Paused 1549 || state == KMachineState_TeleportingPausedVM /** @todo Live Migration: does this make sense? */ 1550 ); 1551 1552 /* change the Start button text accordingly */ 1553 if ( state == KMachineState_PoweredOff 1554 || state == KMachineState_Saved 1555 || state == KMachineState_Teleported 1556 || state == KMachineState_Aborted 1557 ) 1558 { 1559 mVmStartAction->setText (tr ("S&tart")); 1560 #ifdef QT_MAC_USE_COCOA 1561 /* There is a bug in Qt Cocoa which result in showing a "more arrow" when 1562 the necessary size of the toolbar is increased. Also for some languages 1563 the with doesn't match if the text increase. So manually adjust the size 1564 after changing the text. */ 1565 mVMToolBar->updateLayout(); 1566 #endif /* QT_MAC_USE_COCOA */ 1567 mVmStartAction->setStatusTip ( 1568 tr ("Start the selected virtual machine")); 1569 1570 mVmStartAction->setEnabled (!running); 1571 } 1572 else 1573 { 1574 mVmStartAction->setText (tr ("S&how")); 1575 #ifdef QT_MAC_USE_COCOA 1576 /* There is a bug in Qt Cocoa which result in showing a "more arrow" when 1577 the necessary size of the toolbar is increased. Also for some languages 1578 the with doesn't match if the text increase. So manually adjust the size 1579 after changing the text. */ 1580 mVMToolBar->updateLayout(); 1581 #endif /* QT_MAC_USE_COCOA */ 1582 mVmStartAction->setStatusTip ( 1583 tr ("Switch to the window of the selected virtual machine")); 1584 1585 mVmStartAction->setEnabled (item->canSwitchTo()); 1586 } 1587 1588 /* change the Pause/Resume button text accordingly */ 1589 if ( state == KMachineState_Paused 1590 || state == KMachineState_TeleportingPausedVM /*?*/ 1591 ) 1592 { 1593 mVmPauseAction->setText (tr ("R&esume")); 1594 mVmPauseAction->setShortcut (QKeySequence ("Ctrl+P")); 1595 mVmPauseAction->setStatusTip ( 1596 tr ("Resume the execution of the virtual machine")); 1597 mVmPauseAction->blockSignals (true); 1598 mVmPauseAction->setChecked (true); 1599 mVmPauseAction->blockSignals (false); 1600 } 1601 else 1602 { 1603 mVmPauseAction->setText (tr ("&Pause")); 1604 mVmPauseAction->setShortcut (QKeySequence ("Ctrl+P")); 1605 mVmPauseAction->setStatusTip ( 1606 tr ("Suspend the execution of the virtual machine")); 1607 mVmPauseAction->blockSignals (true); 1608 mVmPauseAction->setChecked (false); 1609 mVmPauseAction->blockSignals (false); 1610 } 1611 1612 /* disable Refresh for accessible machines */ 1613 mVmRefreshAction->setEnabled (false); 1614 1615 /* enable the show log item for the selected vm */ 1616 mVmShowLogsAction->setEnabled (true); 1617 } 1618 else 1619 { 1620 /* Note that the machine becomes inaccessible (or if the last VM gets 1621 * deleted), we have to update all fields, ignoring input 1622 * arguments. */ 1623 1624 if (item) 1625 { 1626 /* the VM is inaccessible */ 1627 mVmDetailsView->setErrorText ( 1628 VBoxProblemReporter::formatErrorInfo (item->accessError())); 1629 mVmRefreshAction->setEnabled (true); 1630 } 1631 else 1632 { 1633 /* default HTML support in Qt is terrible so just try to get 1634 * something really simple */ 1635 mVmDetailsView->setDetailsText 1636 (tr ("<h3>" 1637 "Welcome to VirtualBox!</h3>" 1638 "<p>The left part of this window is " 1639 "a list of all virtual machines on your computer. " 1640 "The list is empty now because you haven't created any virtual " 1641 "machines yet." 1642 "<img src=:/welcome.png align=right/></p>" 1643 "<p>In order to create a new virtual machine, press the " 1644 "<b>New</b> button in the main tool bar located " 1645 "at the top of the window.</p>" 1646 "<p>You can press the <b>%1</b> key to get instant help, " 1647 "or visit " 1648 "<a href=http://www.virtualbox.org>www.virtualbox.org</a> " 1649 "for the latest information and news.</p>").arg (QKeySequence (QKeySequence::HelpContents).toString (QKeySequence::NativeText))); 1650 mVmRefreshAction->setEnabled (false); 1651 } 1652 1653 /* empty and disable other tabs */ 1654 1655 mVmSnapshotsWgt->setMachine (CMachine()); 1656 mVmTabWidget->setTabText (mVmTabWidget->indexOf (mVmSnapshotsWgt), tr ("&Snapshots")); 1657 mVmTabWidget->setTabEnabled (mVmTabWidget->indexOf (mVmSnapshotsWgt), false); 1658 1659 mVmDescriptionPage->setMachineItem (NULL); 1660 mVmTabWidget->setTabText (mVmTabWidget->indexOf (mVmDescriptionPage), tr ("D&escription")); 1661 mVmTabWidget->setTabEnabled (mVmTabWidget->indexOf (mVmDescriptionPage), false); 1662 1663 /* disable modify actions */ 1664 mVmConfigAction->setEnabled (false); 1665 mVmDeleteAction->setEnabled (item != NULL); 1666 mVmDiscardAction->setEnabled (false); 1667 mVmPauseAction->setEnabled (false); 1668 1669 /* change the Start button text accordingly */ 1670 mVmStartAction->setText (tr ("S&tart")); 1671 mVmStartAction->setStatusTip ( 1672 tr ("Start the selected virtual machine")); 1673 mVmStartAction->setEnabled (false); 1674 1675 /* disable the show log item for the selected vm */ 1676 mVmShowLogsAction->setEnabled (false); 1677 } 1678 } 1679 1680 void VBoxSelectorWnd::mediumEnumStarted() 1681 { 1682 /* refresh the current details to pick up hard disk sizes */ 1683 vmListViewCurrentChanged (true /* aRefreshDetails */); 1684 } 1685 1686 void VBoxSelectorWnd::mediumEnumFinished (const VBoxMediaList &list) 1687 { 1688 /* refresh the current details to pick up hard disk sizes */ 1689 vmListViewCurrentChanged (true /* aRefreshDetails */); 1690 1691 /* we warn about inaccessible media only once (after media emumeration 1692 * started from main() at startup), to avoid annoying the user */ 1693 if ( mDoneInaccessibleWarningOnce 1694 #ifdef VBOX_GUI_WITH_SYSTRAY 1695 || vboxGlobal().isTrayMenu() 1696 #endif 1697 ) 1698 return; 1699 1700 mDoneInaccessibleWarningOnce = true; 1701 1702 do 1703 { 1704 /* ignore the signal if a modal widget is currently active (we won't be 1705 * able to properly show the modeless VDI manager window in this case) */ 1706 if (QApplication::activeModalWidget()) 1707 break; 1708 1709 /* ignore the signal if a VBoxMediaManagerDlg window is active */ 1710 if (qApp->activeWindow() && 1711 !strcmp (qApp->activeWindow()->metaObject()->className(), "VBoxMediaManagerDlg")) 1712 break; 1713 1714 /* look for at least one inaccessible media */ 1715 VBoxMediaList::const_iterator it; 1716 for (it = list.begin(); it != list.end(); ++ it) 1717 if ((*it).state() == KMediumState_Inaccessible) 1718 break; 1719 1720 if (it != list.end() && vboxProblem().remindAboutInaccessibleMedia()) 1721 { 1722 /* Show the VDM dialog but don't refresh once more after a 1723 * just-finished refresh */ 1724 VBoxMediaManagerDlg::showModeless (this, false /* aRefresh */); 1725 } 1726 } 1727 while (0); 1728 } 1729 1730 void VBoxSelectorWnd::machineStateChanged(QString strId, KMachineState /* state */) 1731 { 1732 #ifdef VBOX_GUI_WITH_SYSTRAY 1733 if (vboxGlobal().isTrayMenu()) 1734 { 1735 /* Check if there are some machines alive - else quit, since 1736 * we're not needed as a systray menu anymore. */ 1737 if (vboxGlobal().mainWindowCount() == 0) 1738 { 1739 fileExit(); 1740 return; 1741 } 1742 } 1743 #endif 1744 1745 refreshVMItem (strId, 1746 false /* aDetails */, 1747 false /* aSnapshots */, 1748 false /* aDescription */); 1749 1750 /* simulate a state change signal */ 1751 mVmDescriptionPage->updateState(); 1752 } 1753 1754 void VBoxSelectorWnd::machineDataChanged(QString strId) 1755 { 1756 refreshVMItem (strId, 1757 true /* aDetails */, 1758 false /* aSnapshots */, 1759 true /* aDescription */); 1760 } 1761 1762 void VBoxSelectorWnd::machineRegistered(QString strId, bool fRegistered) 1763 { 1764 if (fRegistered) 1765 { 1766 CVirtualBox vbox = vboxGlobal().virtualBox(); 1767 CMachine m = vbox.GetMachine (strId); 1768 if (!m.isNull()) 1769 { 1770 mVMModel->addItem (new UIVMItem (m)); 1771 mVMModel->sort(); 1772 /* Make sure the description, ... pages are properly updated. 1773 * Actualy we haven't call the next method, but unfortunately Qt 1774 * seems buggy if the new item is on the same position as the 1775 * previous one. So go on the safe side and call this by our self. */ 1776 vmListViewCurrentChanged(); 1777 } 1778 /* m.isNull() is ok (theoretically, the machine could have been 1779 * already deregistered by some other client at this point) */ 1780 } 1781 else 1782 { 1783 UIVMItem *item = mVMModel->itemById (strId); 1784 if (item) 1785 { 1786 int row = mVMModel->rowById (item->id()); 1787 mVMModel->removeItem (item); 1788 delete item; 1789 mVMListView->ensureSomeRowSelected (row); 1790 } 1791 1792 /* item = 0 is ok (if we originated this event then the item 1793 * has been already removed) */ 1794 } 1795 } 1796 1797 void VBoxSelectorWnd::sessionStateChanged(QString strId, KSessionState /* state */) 1798 { 1799 refreshVMItem (strId, 1800 true /* aDetails */, 1801 false /* aSnapshots */, 1802 false /* aDescription */); 1803 1804 /* simulate a state change signal */ 1805 mVmDescriptionPage->updateState(); 1806 } 1807 1808 void VBoxSelectorWnd::snapshotChanged(QString strId, QString /* strSnapshotId */) 1809 { 1810 refreshVMItem (strId, 1811 false /* aDetails */, 1812 true /* aSnapshot */, 1813 false /* aDescription */); 1814 } 1815 1816 #ifdef VBOX_GUI_WITH_SYSTRAY 1817 1818 void VBoxSelectorWnd::mainWindowCountChanged(int count) 1819 { 1820 if (vboxGlobal().isTrayMenu() && count <= 1) 1821 fileExit(); 1822 } 1823 1824 void VBoxSelectorWnd::trayIconCanShow(bool fEnabled) 1825 { 1826 emit trayIconChanged(VBoxChangeTrayIconEvent (vboxGlobal().settings().trayIconEnabled())); 1827 } 1828 1829 void VBoxSelectorWnd::trayIconShow(bool fEnabled) 1830 { 1831 if (vboxGlobal().isTrayMenu() && mTrayIcon) 1832 mTrayIcon->trayIconShow(fEnabled); 1833 } 1834 1835 void VBoxSelectorWnd::trayIconChanged(bool fEnabled) 1836 { 1837 /* Not used yet. */ 1838 } 1839 1840 VBoxTrayIcon::VBoxTrayIcon (VBoxSelectorWnd* aParent, UIVMItemModel* aVMModel) 1841 { 1842 mParent = aParent; 1843 mVMModel = aVMModel; 1844 1845 mShowSelectorAction = new QAction (this); 1846 Assert (mShowSelectorAction); 1847 mShowSelectorAction->setIcon(UIIconPool::iconSet(":/VirtualBox_16px.png")); 1848 1849 mHideSystrayMenuAction = new QAction (this); 1850 Assert (mHideSystrayMenuAction); 1851 mHideSystrayMenuAction->setIcon(UIIconPool::iconSet(":/exit_16px.png")); 1852 1853 /* reuse parent action data */ 1854 1855 mVmConfigAction = new QAction (this); 1856 Assert (mVmConfigAction); 1857 mVmConfigAction->setIcon (mParent->vmConfigAction()->icon()); 1858 1859 mVmDeleteAction = new QAction (this); 1860 Assert (mVmDeleteAction); 1861 mVmDeleteAction->setIcon (mParent->vmDeleteAction()->icon()); 1862 1863 mVmStartAction = new QAction (this); 1864 Assert (mVmStartAction); 1865 mVmStartAction->setIcon (mParent->vmStartAction()->icon()); 1866 1867 mVmDiscardAction = new QAction (this); 1868 Assert (mVmDiscardAction); 1869 mVmDiscardAction->setIcon (mParent->vmDiscardAction()->icon()); 1870 1871 mVmPauseAction = new QAction (this); 1872 Assert (mVmPauseAction); 1873 mVmPauseAction->setCheckable (true); 1874 mVmPauseAction->setIcon (mParent->vmPauseAction()->icon()); 1875 1876 mVmRefreshAction = new QAction (this); 1877 Assert (mVmRefreshAction); 1878 mVmRefreshAction->setIcon (mParent->vmRefreshAction()->icon()); 1879 1880 mVmShowLogsAction = new QAction (this); 1881 Assert (mVmConfigAction); 1882 mVmShowLogsAction->setIcon (mParent->vmShowLogsAction()->icon()); 1883 1884 mTrayIconMenu = new QMenu (aParent); 1885 Assert (mTrayIconMenu); 1886 1887 setIcon (QIcon (":/VirtualBox_16px.png")); 1888 setContextMenu (mTrayIconMenu); 1889 1890 connect (mShowSelectorAction, SIGNAL (triggered()), mParent, SLOT (showWindow())); 1891 connect (mHideSystrayMenuAction, SIGNAL (triggered()), this, SLOT (trayIconShow())); 1892 } 1893 1894 VBoxTrayIcon::~VBoxTrayIcon () 1895 { 1896 /* Erase dialog handle in config file. */ 1897 if (mActive) 1898 { 1899 vboxGlobal().virtualBox().SetExtraData (VBoxDefs::GUI_TrayIconWinID, 1900 QString::null); 1901 hide(); 1902 } 1903 } 1904 1905 void VBoxTrayIcon::retranslateUi () 1906 { 1907 if (!mActive) 1908 return; 1909 1910 mShowSelectorAction->setText (tr ("Show Selector Window")); 1911 mShowSelectorAction->setStatusTip (tr ( 1912 "Show the selector window assigned to this menu")); 1913 1914 mHideSystrayMenuAction->setText (tr ("Hide Tray Icon")); 1915 mHideSystrayMenuAction->setStatusTip (tr ( 1916 "Remove this icon from the system tray")); 1917 1918 /* reuse parent action data */ 1919 1920 mVmConfigAction->setText (mParent->vmConfigAction()->text()); 1921 mVmConfigAction->setStatusTip (mParent->vmConfigAction()->statusTip()); 1922 1923 mVmDeleteAction->setText (mParent->vmDeleteAction()->text()); 1924 mVmDeleteAction->setStatusTip (mParent->vmDeleteAction()->statusTip()); 1925 1926 mVmPauseAction->setText (mParent->vmPauseAction()->text()); 1927 mVmPauseAction->setStatusTip (mParent->vmPauseAction()->statusTip()); 1928 1929 mVmDiscardAction->setText (mParent->vmDiscardAction()->text()); 1930 mVmDiscardAction->setStatusTip (mParent->vmDiscardAction()->statusTip()); 1931 1932 mVmShowLogsAction->setText (mParent->vmShowLogsAction()->text()); 1933 mVmShowLogsAction->setStatusTip (mParent->vmShowLogsAction()->statusTip()); 1934 } 1935 1936 void VBoxTrayIcon::showSubMenu () 1937 { 1938 if (!mActive) 1939 return; 1940 1941 UIVMItem* pItem = NULL; 1942 QMenu *pMenu = NULL; 1943 QVariant vID; 1944 1945 if ((pMenu = qobject_cast<QMenu*>(sender()))) 1946 { 1947 vID = pMenu->menuAction()->data(); 1948 if (vID.canConvert<QString>() && mVMModel) 1949 pItem = mVMModel->itemById (qvariant_cast<QString>(vID)); 1950 } 1951 1952 mVmConfigAction->setData (vID); 1953 mVmDeleteAction->setData (vID); 1954 mVmDiscardAction->setData (vID); 1955 mVmStartAction->setData (vID); 1956 mVmPauseAction->setData (vID); 1957 mVmShowLogsAction->setData (vID); 1958 1959 if (pItem && pItem->accessible()) 1960 { 1961 /* look at vmListViewCurrentChanged() */ 1962 CMachine m = pItem->machine(); 1963 KMachineState s = pItem->state(); 1964 bool running = pItem->sessionState() != KSessionState_Closed; 1965 bool modifyEnabled = !running && s != KMachineState_Saved; 1966 1967 /* Settings */ 1968 mVmConfigAction->setEnabled (modifyEnabled); 1969 1970 /* Delete */ 1971 mVmDeleteAction->setEnabled (modifyEnabled); 1972 1973 /* Discard */ 1974 mVmDiscardAction->setEnabled (s == KMachineState_Saved && !running); 1975 1976 /* Change the Start button text accordingly */ 1977 if ( s == KMachineState_PoweredOff 1978 || s == KMachineState_Saved 1979 || s == KMachineState_Teleported 1980 || s == KMachineState_Aborted 1981 ) 1982 { 1983 mVmStartAction->setText (UIVMListView::tr ("S&tart")); 1984 mVmStartAction->setStatusTip ( 1985 UIVMListView::tr ("Start the selected virtual machine")); 1986 mVmStartAction->setEnabled (!running); 1987 } 1988 else 1989 { 1990 mVmStartAction->setText (UIVMListView::tr ("S&how")); 1991 mVmStartAction->setStatusTip ( 1992 UIVMListView::tr ("Switch to the window of the selected virtual machine")); 1993 mVmStartAction->setEnabled (pItem->canSwitchTo()); 1994 } 1995 1996 /* Change the Pause/Resume button text accordingly */ 1997 mVmPauseAction->setEnabled ( s == KMachineState_Running 1998 || s == KMachineState_Teleporting 1999 || s == KMachineState_LiveSnapshotting 2000 || s == KMachineState_Paused 2001 || s == KMachineState_TeleportingPausedVM 2002 ); 2003 2004 if ( s == KMachineState_Paused 2005 || s == KMachineState_TeleportingPausedVM /*?*/ 2006 ) 2007 { 2008 mVmPauseAction->setText (UIVMListView::tr ("R&esume")); 2009 mVmPauseAction->setStatusTip ( 2010 UIVMListView::tr ("Resume the execution of the virtual machine")); 2011 mVmPauseAction->blockSignals (true); 2012 mVmPauseAction->setChecked (true); 2013 mVmPauseAction->blockSignals (false); 2014 } 2015 else 2016 { 2017 mVmPauseAction->setText (UIVMListView::tr ("&Pause")); 2018 mVmPauseAction->setStatusTip ( 2019 UIVMListView::tr ("Suspend the execution of the virtual machine")); 2020 mVmPauseAction->blockSignals (true); 2021 mVmPauseAction->setChecked (false); 2022 mVmPauseAction->blockSignals (false); 2023 } 2024 2025 mVmShowLogsAction->setEnabled (true); 2026 2027 /* Disconnect old slot which maybe was connected from another selected sub menu. */ 2028 disconnect (mVmConfigAction, SIGNAL (triggered()), this, SLOT (vmSettings())); 2029 disconnect (mVmDeleteAction, SIGNAL (triggered()), this, SLOT (vmDelete())); 2030 disconnect (mVmDiscardAction, SIGNAL (triggered()), this, SLOT (vmDiscard())); 2031 disconnect (mVmStartAction, SIGNAL (triggered()), this, SLOT (vmStart())); 2032 disconnect (mVmPauseAction, SIGNAL (toggled (bool)), this, SLOT (vmPause (bool))); 2033 disconnect (mVmShowLogsAction, SIGNAL (triggered()), this, SLOT (vmShowLogs())); 2034 2035 /* Connect new sub menu with slots. */ 2036 connect (mVmConfigAction, SIGNAL (triggered()), this, SLOT (vmSettings())); 2037 connect (mVmDeleteAction, SIGNAL (triggered()), this, SLOT (vmDelete())); 2038 connect (mVmDiscardAction, SIGNAL (triggered()), this, SLOT (vmDiscard())); 2039 connect (mVmStartAction, SIGNAL (triggered()), this, SLOT (vmStart())); 2040 connect (mVmPauseAction, SIGNAL (toggled (bool)), this, SLOT (vmPause (bool))); 2041 connect (mVmShowLogsAction, SIGNAL (triggered()), this, SLOT (vmShowLogs())); 2042 } 2043 else /* Item is not accessible. */ 2044 { 2045 mVmConfigAction->setEnabled (false); 2046 mVmDeleteAction->setEnabled (pItem != NULL); 2047 mVmDiscardAction->setEnabled (false); 2048 mVmPauseAction->setEnabled (false); 2049 2050 /* Set the Start button text accordingly. */ 2051 mVmStartAction->setText (UIVMListView::tr ("S&tart")); 2052 mVmStartAction->setStatusTip ( 2053 UIVMListView::tr ("Start the selected virtual machine")); 2054 mVmStartAction->setEnabled (false); 2055 2056 /* Disable the show log item for the selected vm. */ 2057 mVmShowLogsAction->setEnabled (false); 2058 } 2059 2060 /* Build sub menu entries (add rest of sub menu entries later here). */ 2061 pMenu->addAction (mVmStartAction); 2062 pMenu->addAction (mVmPauseAction); 2063 } 2064 2065 void VBoxTrayIcon::hideSubMenu () 2066 { 2067 if (!mActive) 2068 return; 2069 2070 UIVMItem* pItem = NULL; 2071 QVariant vID; 2072 2073 if (QMenu *pMenu = qobject_cast<QMenu*>(sender())) 2074 { 2075 vID = pMenu->menuAction()->data(); 2076 if (vID.canConvert<QString>() && mVMModel) 2077 pItem = mVMModel->itemById (qvariant_cast<QString>(vID)); 2078 } 2079 2080 /* Nothing to do here yet. */ 2081 2082 Assert (pItem); 2083 } 2084 2085 void VBoxTrayIcon::refresh () 2086 { 2087 if (!mActive) 2088 return; 2089 2090 AssertReturnVoid (mVMModel); 2091 AssertReturnVoid (mTrayIconMenu); 2092 2093 mTrayIconMenu->clear(); 2094 2095 UIVMItem* pItem = NULL; 2096 QMenu* pCurMenu = mTrayIconMenu; 2097 QMenu* pSubMenu = NULL; 2098 2099 int iCurItemCount = 0; 2100 2101 mTrayIconMenu->addAction (mShowSelectorAction); 2102 mTrayIconMenu->setDefaultAction (mShowSelectorAction); 2103 2104 if (mVMModel->rowCount() > 0) 2105 mTrayIconMenu->addSeparator(); 2106 2107 for (int i = 0; i < mVMModel->rowCount(); i++, iCurItemCount++) 2108 { 2109 pItem = mVMModel->itemByRow(i); 2110 Assert(pItem); 2111 2112 if (iCurItemCount > 10) /* 10 machines per sub menu. */ 2113 { 2114 pSubMenu = new QMenu (tr ("&Other Machines...", "tray menu")); 2115 Assert (pSubMenu); 2116 pCurMenu->addMenu (pSubMenu); 2117 pCurMenu = pSubMenu; 2118 iCurItemCount = 0; 2119 } 2120 2121 pSubMenu = new QMenu (QString ("&%1. %2") 2122 .arg ((iCurItemCount + 1) % 100).arg (pItem->name())); 2123 Assert (pSubMenu); 2124 pSubMenu->setIcon (pItem->sessionStateIcon()); 2125 2126 QAction *pAction = NULL; 2127 QVariant vID; 2128 vID.setValue (pItem->id()); 2129 2130 pSubMenu->menuAction()->setData (vID); 2131 connect (pSubMenu, SIGNAL (aboutToShow()), this, SLOT (showSubMenu())); 2132 connect (pSubMenu, SIGNAL (aboutToHide()), this, SLOT (hideSubMenu())); 2133 pCurMenu->addMenu (pSubMenu); 2134 } 2135 2136 if (mVMModel->rowCount() > 0) 2137 mTrayIconMenu->addSeparator(); 2138 2139 mTrayIconMenu->addAction (mHideSystrayMenuAction); 2140 2141 /* We're done constructing the menu, show it */ 2142 setVisible (true); 2143 } 2144 2145 UIVMItem* VBoxTrayIcon::GetItem (QObject* aObject) 2146 { 2147 UIVMItem* pItem = NULL; 2148 if (QAction *pAction = qobject_cast<QAction*>(sender())) 2149 { 2150 QVariant v = pAction->data(); 2151 if (v.canConvert<QString>() && mVMModel) 2152 pItem = mVMModel->itemById (qvariant_cast<QString>(v)); 2153 } 2154 2155 Assert (pItem); 2156 return pItem; 2157 } 2158 2159 void VBoxTrayIcon::trayIconShow (bool aShow) 2160 { 2161 if (!vboxGlobal().isTrayMenu()) 2162 return; 2163 2164 mActive = aShow; 2165 if (mActive) 2166 { 2167 refresh(); 2168 retranslateUi(); 2169 } 2170 setVisible (mActive); 2171 2172 if (!mActive) 2173 mParent->fileExit(); 2174 } 2175 2176 void VBoxTrayIcon::vmSettings() 2177 { 2178 UIVMItem* pItem = GetItem (sender()); 2179 mParent->vmSettings (NULL, NULL, pItem->id()); 2180 } 2181 2182 void VBoxTrayIcon::vmDelete() 2183 { 2184 UIVMItem* pItem = GetItem (sender()); 2185 mParent->vmDelete (pItem->id()); 2186 } 2187 2188 void VBoxTrayIcon::vmStart() 2189 { 2190 UIVMItem* pItem = GetItem (sender()); 2191 mParent->vmStart (pItem->id()); 2192 } 2193 2194 void VBoxTrayIcon::vmDiscard() 2195 { 2196 UIVMItem* pItem = GetItem (sender()); 2197 mParent->vmDiscard (pItem->id()); 2198 } 2199 2200 void VBoxTrayIcon::vmPause(bool aPause) 2201 { 2202 UIVMItem* pItem = GetItem (sender()); 2203 mParent->vmPause (aPause, pItem->id()); 2204 } 2205 2206 void VBoxTrayIcon::vmRefresh() 2207 { 2208 UIVMItem* pItem = GetItem (sender()); 2209 mParent->vmRefresh (pItem->id()); 2210 } 2211 2212 void VBoxTrayIcon::vmShowLogs() 2213 { 2214 UIVMItem* pItem = GetItem (sender()); 2215 mParent->vmShowLogs (pItem->id()); 2216 } 2217 2218 #endif // VBOX_GUI_WITH_SYSTRAY 2219 2220 void VBoxSelectorWnd::sltDownloaderUserManualEmbed() 2221 { 2222 /* If there is User Manual downloader created => show the process bar: */ 2223 if (UIDownloaderUserManual *pDl = UIDownloaderUserManual::current()) 2224 statusBar()->addWidget(pDl->processWidget(this), 0); 2225 } 2226 2227 void VBoxSelectorWnd::showViewContextMenu(const QPoint &pos) 2228 { 2229 CVirtualBox vbox = vboxGlobal().virtualBox(); 2230 QString strToolbar = vbox.GetExtraData(VBoxDefs::GUI_Toolbar); 2231 QString strStatusbar = vbox.GetExtraData(VBoxDefs::GUI_Statusbar); 2232 bool fToolbar = strToolbar.isEmpty() || strToolbar == "true"; 2233 bool fStatusbar = strStatusbar.isEmpty() || strStatusbar == "true"; 2234 2235 QList<QAction*> actions; 2236 QAction *pShowToolBar = new QAction(tr("Show Toolbar"), 0); 2237 pShowToolBar->setCheckable(true); 2238 pShowToolBar->setChecked(fToolbar); 2239 actions << pShowToolBar; 2240 QAction *pShowStatusBar = new QAction(tr("Show Statusbar"), 0); 2241 pShowStatusBar->setCheckable(true); 2242 pShowStatusBar->setChecked(fStatusbar); 2243 actions << pShowStatusBar; 2244 2245 QPoint gpos = pos; 2246 QWidget *pSender = static_cast<QWidget*>(sender()); 2247 if (pSender) 2248 gpos = pSender->mapToGlobal(pos); 2249 QAction *pResult = QMenu::exec(actions, gpos); 2250 if (pResult == pShowToolBar) 2251 { 2252 if (pResult->isChecked()) 2253 { 2254 mVMToolBar->show(); 2255 vbox.SetExtraData(VBoxDefs::GUI_Toolbar, "true"); 2256 } 2257 else 2258 { 2259 mVMToolBar->hide(); 2260 vbox.SetExtraData(VBoxDefs::GUI_Toolbar, "false"); 2261 } 2262 }else if (pResult == pShowStatusBar) 2263 { 2264 if (pResult->isChecked()) 2265 { 2266 statusBar()->show(); 2267 vbox.SetExtraData(VBoxDefs::GUI_Statusbar, "true"); 2268 } 2269 else 2270 { 2271 statusBar()->hide(); 2272 vbox.SetExtraData(VBoxDefs::GUI_Statusbar, "false"); 2273 } 2274 } 2275 } 2276 2277 #include "VBoxSelectorWnd.moc" 1334 } 1335 1336 void UIVMDesktop::retranslateUi() 1337 { 1338 m_pHeaderBtn->setTitle(Dtls, tr("&Details")); 1339 } 1340 1341 void UIVMDesktop::updateDetails(UIVMItem * /* pVMItem */, const CMachine& machine) 1342 { 1343 // KMachineState state = pVMItem->state(); 1344 // bool fRunning = pVMItem->sessionState() != KSessionState_Closed; 1345 // bool fModifyEnabled = !fRunning && state != KMachineState_Saved; 1346 m_pDetails->setMachine(machine); 1347 } 1348 1349 void UIVMDesktop::updateDetailsText(const QString &strText) 1350 { 1351 m_pDetails->setText(strText); 1352 } 1353 1354 void UIVMDesktop::updateDetailsErrorText(const QString &strText) 1355 { 1356 m_pDetails->setErrorText(strText); 1357 } 1358 1359 void UIVMDesktop::updateSnapshots(UIVMItem *pVMItem, const CMachine& machine) 1360 { 1361 /* Update the snapshots header name */ 1362 QString name = tr("&Snapshots"); 1363 if (pVMItem) 1364 { 1365 ULONG count = pVMItem->snapshotCount(); 1366 if (count) 1367 name += QString(" (%1)").arg(count); 1368 } 1369 m_pHeaderBtn->setTitle(Snap, name); 1370 /* Refresh the snapshots widget */ 1371 if (!machine.isNull()) 1372 { 1373 m_pHeaderBtn->setEnabled(Snap, true); 1374 m_pSnapshotsPage->setMachine(machine); 1375 } else 1376 { 1377 m_pHeaderBtn->animateClick(Dtls); 1378 m_pHeaderBtn->setEnabled(Snap, false); 1379 } 1380 } 1381 1382 void UIVMDesktop::updateDescription(UIVMItem *pVMItem, const CMachine& machine) 1383 { 1384 /* Update the description header name */ 1385 QString name = tr("D&escription"); 1386 if (pVMItem) 1387 { 1388 if(!machine.GetDescription().isEmpty()) 1389 name += " *"; 1390 } 1391 m_pHeaderBtn->setTitle(Desc, name); 1392 /* refresh the description widget */ 1393 if (!machine.isNull()) 1394 { 1395 m_pHeaderBtn->setEnabled(Desc, true); 1396 m_pDescription->setMachineItem(pVMItem); 1397 } else 1398 { 1399 m_pHeaderBtn->animateClick(Dtls); 1400 m_pHeaderBtn->setEnabled(Desc, false); 1401 } 1402 } 1403 1404 void UIVMDesktop::updateDescriptionState() 1405 { 1406 m_pDescription->updateState(); 1407 } 1408 1409 #include "UIVMDesktop.moc" 1410 -
trunk/src/VBox/Frontends/VirtualBox/src/selector/UIVMDesktop.h
r30798 r30868 2 2 * 3 3 * VBox frontends: Qt GUI ("VirtualBox"): 4 * VBoxSelectorWnd class declaration4 * UIVMDesktop class declarations 5 5 */ 6 6 7 7 /* 8 * Copyright (C) 20 06-2008Oracle Corporation8 * Copyright (C) 2010 Oracle Corporation 9 9 * 10 10 * This file is part of VirtualBox Open Source Edition (OSE), as … … 17 17 */ 18 18 19 #ifndef __ VBoxSelectorWnd_h__20 #define __ VBoxSelectorWnd_h__19 #ifndef __UIVMDesktop_h__ 20 #define __UIVMDesktop_h__ 21 21 22 #include "COMDefs.h" 23 22 /* Local includes */ 24 23 #include "QIWithRetranslateUI.h" 25 24 26 #include "VBoxGlobal.h" 27 #include "VBoxProblemReporter.h" 28 #include "VBoxHelpActions.h" 29 30 /* Qt includes */ 31 #include <QMainWindow> 32 #ifdef VBOX_GUI_WITH_SYSTRAY 33 #include <QSystemTrayIcon> 34 #endif 25 /* Global includes */ 26 #include <QWidget> 35 27 36 28 /* Local forward declarations */ 37 class QITabWidget; 29 class CMachine; 30 class UIDescriptionPagePrivate; 31 class UIDetailsPagePrivate; 32 class UITexturedSegmentedButton; 38 33 class UIVMItem; 39 class UIVMItemModel;40 class UIVMListView;41 34 class VBoxSnapshotsWgt; 42 35 class VBoxToolBar; 43 class VBoxTrayIcon;44 class VBoxVMDescriptionPage;45 class VBoxVMDetailsView;46 class VBoxVMLogViewer;47 36 48 /* Global forward declarations */ 49 class QEvent; 50 class QListView; 51 52 class VBoxSelectorWnd : public QIWithRetranslateUI2 <QMainWindow> 37 class UIVMDesktop: public QIWithRetranslateUI<QWidget> 53 38 { 54 39 Q_OBJECT; … … 56 41 public: 57 42 58 VBoxSelectorWnd (VBoxSelectorWnd **aSelf, 59 QWidget* aParent = 0, 60 Qt::WindowFlags aFlags = Qt::Window); 61 virtual ~VBoxSelectorWnd(); 43 UIVMDesktop(VBoxToolBar *pToolBar, QAction *pRefreshAction, QWidget *pParent = 0); 44 45 void updateDetails(UIVMItem *pVMItem, const CMachine& machine); 46 void updateDetailsText(const QString &strText); 47 void updateDetailsErrorText(const QString &strText); 48 49 void updateSnapshots(UIVMItem *pVMItem, const CMachine& machine); 50 void updateDescription(UIVMItem *pVMItem, const CMachine& machine); 51 void updateDescriptionState(); 62 52 63 53 signals: 64 54 65 void closing(); 66 67 public slots: 68 69 void fileMediaMgr(); 70 void fileImportAppliance(); 71 void fileExportAppliance(); 72 void fileSettings(); 73 void fileExit(); 74 75 void vmNew(); 76 void vmSettings (const QString &aCategory = QString::null, 77 const QString &aControl = QString::null, 78 const QString & = QString::null); 79 void vmDelete (const QString & = QString::null); 80 void vmStart (const QString & = QString::null); 81 void vmDiscard (const QString & = QString::null); 82 void vmPause (bool, const QString & = QString::null); 83 void vmRefresh (const QString & = QString::null); 84 void vmShowLogs (const QString & = QString::null); 85 86 void refreshVMList(); 87 void refreshVMItem (const QString &aID, bool aDetails, 88 bool aSnapshots, 89 bool aDescription); 90 91 void showContextMenu (const QPoint &aPoint); 92 93 #ifdef VBOX_GUI_WITH_SYSTRAY 94 void trayIconActivated (QSystemTrayIcon::ActivationReason aReason); 95 void showWindow(); 96 #endif 97 98 const QAction *vmNewAction() const { return mVmNewAction; } 99 const QAction *vmConfigAction() const { return mVmConfigAction; } 100 const QAction *vmDeleteAction() const { return mVmDeleteAction; } 101 const QAction *vmStartAction() const { return mVmStartAction; } 102 const QAction *vmDiscardAction() const { return mVmDiscardAction; } 103 const QAction *vmPauseAction() const { return mVmPauseAction; } 104 const QAction *vmRefreshAction() const { return mVmRefreshAction; } 105 const QAction *vmShowLogsAction() const { return mVmShowLogsAction; } 55 void linkClicked(const QString &strURL); 106 56 107 57 protected: 108 58 109 /* Events */110 bool event (QEvent *aEvent);111 void closeEvent (QCloseEvent *aEvent);112 //#if defined (Q_WS_MAC) && (QT_VERSION < 0x040402)113 // bool eventFilter (QObject *aObject, QEvent *aEvent);114 //#endif /* defined (Q_WS_MAC) && (QT_VERSION < 0x040402) */115 116 59 void retranslateUi(); 117 118 private slots:119 120 void vmListViewCurrentChanged (bool aRefreshDetails = true,121 bool aRefreshSnapshots = true,122 bool aRefreshDescription = true);123 124 void mediumEnumStarted();125 void mediumEnumFinished (const VBoxMediaList &);126 127 /* VirtualBox callback events we're interested in */128 129 void machineStateChanged(QString strId, KMachineState state);130 void machineDataChanged(QString strId);131 void machineRegistered(QString strID, bool fRegistered);132 void sessionStateChanged(QString strId, KSessionState state);133 void snapshotChanged(QString strId, QString strSnapshotId);134 #ifdef VBOX_GUI_WITH_SYSTRAY135 void mainWindowCountChanged(int count);136 void trayIconCanShow(bool fEnabled);137 void trayIconShow(bool fEnabled);138 void trayIconChanged(bool fEnabled);139 #endif140 141 void sltDownloaderUserManualEmbed();142 143 void showViewContextMenu(const QPoint &pos);144 60 145 61 private: 146 62 147 /* Main menus */ 148 QMenu *mFileMenu; 149 QMenu *mVMMenu; 150 QMenu *mHelpMenu; 151 152 /* Main toolbar */ 153 VBoxToolBar *mVMToolBar; 154 155 /* VM list context menu */ 156 QMenu *mVMCtxtMenu; 157 // UIOSDMenu *mVMCtxtMenu; 158 159 /* Actions */ 160 QAction *mFileMediaMgrAction; 161 QAction *mFileApplianceImportAction; 162 QAction *mFileApplianceExportAction; 163 QAction *mFileSettingsAction; 164 QAction *mFileExitAction; 165 QAction *mVmNewAction; 166 QAction *mVmConfigAction; 167 QAction *mVmDeleteAction; 168 QAction *mVmStartAction; 169 QAction *mVmDiscardAction; 170 QAction *mVmPauseAction; 171 QAction *mVmRefreshAction; 172 QAction *mVmShowLogsAction; 173 174 VBoxHelpActions mHelpActions; 175 176 #ifdef VBOX_GUI_WITH_SYSTRAY 177 /* The systray icon */ 178 VBoxTrayIcon *mTrayIcon; 179 #endif 180 181 /* The vm list view/model */ 182 UIVMListView *mVMListView; 183 UIVMItemModel *mVMModel; 184 185 /* The right information widgets */ 186 QITabWidget *mVmTabWidget; 187 VBoxVMDetailsView *mVmDetailsView; 188 VBoxSnapshotsWgt *mVmSnapshotsWgt; 189 VBoxVMDescriptionPage *mVmDescriptionPage; 190 191 QRect mNormalGeo; 192 193 bool mDoneInaccessibleWarningOnce : 1; 63 /* Private member vars */ 64 UITexturedSegmentedButton *m_pHeaderBtn; 65 UIDetailsPagePrivate *m_pDetails; 66 VBoxSnapshotsWgt *m_pSnapshotsPage; 67 UIDescriptionPagePrivate *m_pDescription; 194 68 }; 195 69 196 # ifdef VBOX_GUI_WITH_SYSTRAY70 #endif /* !__UIVMDesktop_h__ */ 197 71 198 Q_DECLARE_METATYPE(QString);199 200 class VBoxTrayIcon : public QSystemTrayIcon201 {202 Q_OBJECT;203 204 public:205 206 VBoxTrayIcon (VBoxSelectorWnd* aParent, UIVMItemModel* aVMModel);207 virtual ~VBoxTrayIcon ();208 209 void refresh ();210 void retranslateUi ();211 212 protected:213 214 UIVMItem* GetItem (QObject* aObject);215 216 signals:217 218 public slots:219 220 void trayIconShow (bool aShow = false);221 222 private slots:223 224 void showSubMenu();225 void hideSubMenu ();226 227 void vmSettings();228 void vmDelete();229 void vmStart();230 void vmDiscard();231 void vmPause(bool aPause);232 void vmRefresh();233 void vmShowLogs();234 235 private:236 237 bool mActive; /* Is systray menu active/available? */238 239 /* The vm list model */240 UIVMItemModel *mVMModel;241 242 VBoxSelectorWnd* mParent;243 QMenu *mTrayIconMenu;244 245 QAction *mShowSelectorAction;246 QAction *mHideSystrayMenuAction;247 QAction *mVmConfigAction;248 QAction *mVmDeleteAction;249 QAction *mVmStartAction;250 QAction *mVmDiscardAction;251 QAction *mVmPauseAction;252 QAction *mVmRefreshAction;253 QAction *mVmShowLogsAction;254 };255 256 #endif // VBOX_GUI_WITH_SYSTRAY257 258 #endif // __VBoxSelectorWnd_h__259 -
trunk/src/VBox/Frontends/VirtualBox/src/selector/VBoxSelectorWnd.cpp
r30866 r30868 21 21 #else /* !VBOX_WITH_PRECOMPILED_HEADERS */ 22 22 #include "QISplitter.h" 23 #include "QITabWidget.h" 23 #include "UIBar.h" 24 #include "UIDownloaderUserManual.h" 24 25 #include "UIExportApplianceWzd.h" 25 26 #include "UIIconPool.h" 26 27 #include "UIImportApplianceWzd.h" 27 28 #include "UINewVMWzd.h" 28 #include "UISpacerWidgets.h" 29 #include "UISpecialControls.h" 29 #include "UIVMDesktop.h" 30 30 #include "UIVMListView.h" 31 #include "UIVirtualBoxEventHandler.h" 31 32 #include "VBoxGlobal.h" 32 33 #include "VBoxMediaManagerDlg.h" … … 34 35 #include "VBoxSelectorWnd.h" 35 36 #include "VBoxSettingsDialogSpecific.h" 36 #include "VBoxSnapshotsWgt.h"37 37 #include "VBoxToolBar.h" 38 #include "VBoxUtils.h"39 38 #include "VBoxVMLogViewer.h" 40 #include "UIVirtualBoxEventHandler.h" 41 42 #include "UIDownloaderUserManual.h" 43 44 #ifdef Q_WS_X11 45 #include <iprt/env.h> 46 #endif 47 48 /* Qt includes */ 49 #include <QTextBrowser> 39 40 /* Global includes */ 41 #include <QDesktopWidget> 50 42 #include <QMenuBar> 51 #include <QMenu> 52 #include <QMenuItem> 53 #include <QStackedWidget> 54 #include <QDesktopWidget> 55 #include <QToolButton> 43 #include <QResizeEvent> 56 44 57 45 #include <iprt/buildconfig.h> 58 46 #include <VBox/version.h> 47 #ifdef Q_WS_X11 48 # include <iprt/env.h> 49 #endif 59 50 #endif /* !VBOX_WITH_PRECOMPILED_HEADERS */ 60 61 // VBoxVMDetailsView class62 ////////////////////////////////////////////////////////////////////////////////63 64 /**65 * Two-page widget stack to represent VM details: one page for normal details66 * and another one for inaccessibility errors.67 */68 class VBoxVMDetailsView : public QIWithRetranslateUI<QStackedWidget>69 {70 Q_OBJECT;71 72 public:73 74 VBoxVMDetailsView (QWidget *aParent,75 QAction *aRefreshAction = NULL);76 77 void setDetailsText (const QString &aText)78 {79 mDetailsText->setText (aText);80 setCurrentIndex (0);81 }82 83 void setErrorText (const QString &aText)84 {85 createErrPage();86 mErrText->setText (aText);87 setCurrentIndex (1);88 }89 90 void setEmpty()91 {92 mDetailsText->setText (QString::null);93 setCurrentIndex (0);94 }95 96 signals:97 98 void linkClicked (const QString &aURL);99 100 protected:101 102 void retranslateUi();103 104 private slots:105 106 void gotLinkClicked (const QUrl &aURL)107 {108 emit linkClicked (aURL.toString());109 }110 111 private:112 113 void createErrPage();114 115 QRichTextBrowser *mDetailsText;116 117 QWidget *mErrBox;118 QLabel *mErrLabel;119 QTextBrowser *mErrText;120 QToolButton *mRefreshButton;121 QAction *mRefreshAction;122 };123 124 VBoxVMDetailsView::VBoxVMDetailsView (QWidget *aParent,125 QAction *aRefreshAction /* = NULL */)126 : QIWithRetranslateUI<QStackedWidget> (aParent)127 , mErrBox (NULL), mErrLabel (NULL), mErrText (NULL)128 , mRefreshButton (NULL)129 , mRefreshAction (aRefreshAction)130 {131 Assert (mRefreshAction);132 133 /* create normal details page */134 135 mDetailsText = new QRichTextBrowser (mErrBox);136 mDetailsText->setViewportMargins (10, 10, 10, 10);137 mDetailsText->setFocusPolicy (Qt::StrongFocus);138 mDetailsText->document()->setDefaultStyleSheet ("a { text-decoration: none; }");139 /* make "transparent" */140 mDetailsText->setFrameShape (QFrame::NoFrame);141 mDetailsText->viewport()->setAutoFillBackground (false);142 mDetailsText->setOpenLinks (false);143 144 connect (mDetailsText, SIGNAL (anchorClicked (const QUrl &)),145 this, SLOT (gotLinkClicked (const QUrl &)));146 147 addWidget (mDetailsText);148 }149 150 void VBoxVMDetailsView::createErrPage()151 {152 /* create inaccessible details page */153 154 if (mErrBox)155 return;156 157 mErrBox = new QWidget();158 159 QVBoxLayout *vLayout = new QVBoxLayout (mErrBox);160 vLayout->setSpacing (10);161 162 mErrLabel = new QLabel (mErrBox);163 mErrLabel->setWordWrap (true);164 mErrLabel->setSizePolicy (QSizePolicy::Expanding, QSizePolicy::Fixed);165 vLayout->addWidget (mErrLabel);166 167 mErrText = new QTextBrowser (mErrBox);168 mErrText->setFocusPolicy (Qt::StrongFocus);169 mErrText->document()->setDefaultStyleSheet ("a { text-decoration: none; }");170 vLayout->addWidget (mErrText);171 172 if (mRefreshAction)173 {174 mRefreshButton = new QToolButton (mErrBox);175 mRefreshButton->setFocusPolicy (Qt::StrongFocus);176 177 QHBoxLayout *hLayout = new QHBoxLayout ();178 vLayout->addLayout (hLayout);179 hLayout->addItem (new QSpacerItem (0, 0, QSizePolicy::Expanding,180 QSizePolicy::Minimum));181 hLayout->addWidget (mRefreshButton);182 183 connect (mRefreshButton, SIGNAL (clicked()),184 mRefreshAction, SIGNAL (triggered()));185 }186 187 vLayout->addItem (new QSpacerItem (0, 0, QSizePolicy::Minimum,188 QSizePolicy::Expanding));189 190 addWidget (mErrBox);191 192 retranslateUi();193 }194 195 void VBoxVMDetailsView::retranslateUi()196 {197 if (mErrLabel)198 mErrLabel->setText (tr (199 "The selected virtual machine is <i>inaccessible</i>. Please "200 "inspect the error message shown below and press the "201 "<b>Refresh</b> button if you want to repeat the accessibility "202 "check:"));203 204 if (mRefreshAction && mRefreshButton)205 {206 mRefreshButton->setText (mRefreshAction->text());207 mRefreshButton->setIcon (mRefreshAction->icon());208 mRefreshButton->setToolButtonStyle (Qt::ToolButtonTextBesideIcon);209 }210 }211 212 // VBoxVMDescriptionPage class213 ////////////////////////////////////////////////////////////////////////////////214 215 /**216 * Comments page widget to represent VM comments.217 */218 class VBoxVMDescriptionPage : public QIWithRetranslateUI<QWidget>219 {220 Q_OBJECT;221 222 public:223 224 VBoxVMDescriptionPage (VBoxSelectorWnd *);225 ~VBoxVMDescriptionPage() {}226 227 void setMachineItem (UIVMItem *aItem);228 229 void updateState();230 231 protected:232 233 void retranslateUi();234 235 private slots:236 237 void goToSettings();238 239 private:240 241 UIVMItem *mItem;242 243 VBoxSelectorWnd *mParent;244 QToolButton *mBtnEdit;245 QTextBrowser *mBrowser;246 QLabel *mLabel;247 };248 249 VBoxVMDescriptionPage::VBoxVMDescriptionPage (VBoxSelectorWnd *aParent)250 : QIWithRetranslateUI<QWidget> (aParent)251 , mItem (NULL), mParent (aParent)252 , mBtnEdit (0), mBrowser (0), mLabel (0)253 {254 /* main layout */255 QVBoxLayout *vMainLayout = new QVBoxLayout (this);256 vMainLayout->setSpacing (10);257 VBoxGlobal::setLayoutMargin (vMainLayout, 0);258 259 /* mBrowser */260 mBrowser = new QTextBrowser (this);261 mBrowser->setSizePolicy (QSizePolicy::Expanding, QSizePolicy::Expanding);262 mBrowser->setFocusPolicy (Qt::StrongFocus);263 mBrowser->document()->setDefaultStyleSheet ("a { text-decoration: none; }");264 vMainLayout->addWidget (mBrowser);265 /* hidden by default */266 mBrowser->setHidden (true);267 268 mLabel = new QLabel (this);269 mLabel->setFrameStyle (mBrowser->frameStyle());270 mLabel->setSizePolicy (QSizePolicy::Expanding, QSizePolicy::Expanding);271 mLabel->setAlignment (Qt::AlignCenter);272 mLabel->setWordWrap (true);273 vMainLayout->addWidget (mLabel);274 /* always disabled */275 mLabel->setEnabled (false);276 277 /* button layout */278 QHBoxLayout *hBtnLayout = new QHBoxLayout ();279 vMainLayout->addLayout (hBtnLayout);280 hBtnLayout->setSpacing (10);281 hBtnLayout->addItem (new QSpacerItem (0, 0,282 QSizePolicy::Expanding,283 QSizePolicy::Minimum));284 285 /* button */286 mBtnEdit = new QToolButton (this);287 mBtnEdit->setSizePolicy (QSizePolicy::Preferred, QSizePolicy::Fixed);288 mBtnEdit->setFocusPolicy (Qt::StrongFocus);289 mBtnEdit->setIcon(UIIconPool::iconSet(":/edit_description_16px.png",290 ":/edit_description_disabled_16px.png"));291 mBtnEdit->setToolButtonStyle (Qt::ToolButtonTextBesideIcon);292 connect (mBtnEdit, SIGNAL (clicked()), this, SLOT (goToSettings()));293 hBtnLayout->addWidget (mBtnEdit);294 295 vMainLayout->addItem (new QSpacerItem (0, 0,296 QSizePolicy::Expanding,297 QSizePolicy::Minimum));298 299 /* apply language settings */300 retranslateUi();301 302 updateState();303 }304 305 /**306 * The machine list @a aItem is used to access cached machine data w/o making307 * unnecessary RPC calls.308 */309 void VBoxVMDescriptionPage::setMachineItem (UIVMItem *aItem)310 {311 mItem = aItem;312 313 QString text = aItem ? aItem->machine().GetDescription() : QString::null;314 315 if (!text.isEmpty())316 {317 mLabel->setHidden (true);318 mBrowser->setText (text);319 mBrowser->setVisible (true);320 }321 else322 {323 mBrowser->setHidden (true);324 mBrowser->clear();325 mLabel->setVisible (true);326 }327 328 /* check initial machine and session states */329 updateState();330 }331 332 void VBoxVMDescriptionPage::retranslateUi()333 {334 mLabel->setText (tr ("No description. Press the Edit button below to add it."));335 336 mBtnEdit->setText (tr ("Edit"));337 mBtnEdit->setShortcut (QKeySequence ("Ctrl+E"));338 mBtnEdit->setToolTip (tr ("Edit (Ctrl+E)"));339 mBtnEdit->adjustSize();340 mBtnEdit->updateGeometry();341 }342 343 /**344 * Called by the parent from machineStateChanged() and sessionStateChanged()345 * signal handlers. We cannot connect to these signals ourselves because we346 * use the UIVMListBoxItem which needs to be properly updated by the parent347 * first.348 */349 void VBoxVMDescriptionPage::updateState()350 {351 /// @todo disabling the edit button for a saved VM will not be necessary352 /// when we implement the selective VM Settings dialog, where only fields353 /// that can be changed in the saved state, can be changed.354 355 if (mItem)356 {357 bool saved = mItem->state() == KMachineState_Saved;358 bool busy = mItem->sessionState() != KSessionState_Closed;359 mBtnEdit->setEnabled (!saved && !busy);360 }361 else362 mBtnEdit->setEnabled (false);363 }364 365 void VBoxVMDescriptionPage::goToSettings()366 {367 mParent->vmSettings ("#general", "mTeDescription");368 }369 51 370 52 // VBoxSelectorWnd class … … 474 156 mHelpActions.setup (this); 475 157 476 QISplitter *pSplitter = new QISplitter(this);477 pSplitter->setHandleType(QISplitter::Native);478 /* Central widget @ horizontal layout */479 setCentralWidget(pSplitter);480 481 158 /* VM list toolbar */ 482 159 mVMToolBar = new VBoxToolBar(this); … … 502 179 mVMListView->setStyleSheet ("activate-on-singleclick : 0"); 503 180 181 m_pSplitter = new QISplitter(this); 182 m_pSplitter->setHandleType(QISplitter::Native); 183 184 #define BIG_TOOLBAR 504 185 #if MAC_LEOPARD_STYLE 505 186 /* Enable unified toolbars on Mac OS X. Available on Qt >= 4.3 */ 506 187 addToolBar (mVMToolBar); 507 188 mVMToolBar->setMacToolbar(); 508 pSplitter->addWidget (mVMListView); 189 /* Central widget @ horizontal layout */ 190 setCentralWidget(m_pSplitter); 191 m_pSplitter->addWidget (mVMListView); 509 192 #else /* MAC_LEOPARD_STYLE */ 193 // mVMToolBar->setContentsMargins(5, 5, 0, 0); 194 // addToolBar (mVMToolBar); 195 // m_pSplitter->addWidget (mVMListView); 510 196 QWidget *pLeftWidget = new QWidget(this); 511 197 QVBoxLayout *pLeftVLayout = new QVBoxLayout(pLeftWidget); 512 pLeftVLayout->setContentsMargins(5, 5, 0, 0); 198 pLeftVLayout->setContentsMargins(0, 0, 0, 0); 199 pLeftVLayout->setSpacing(0); 200 # ifdef BIG_TOOLBAR 201 m_pBar = new UIBar(this); 202 m_pBar->setContentWidget(mVMToolBar); 203 pLeftVLayout->addWidget(m_pBar); 204 pLeftVLayout->addWidget(m_pSplitter); 205 setCentralWidget(pLeftWidget); 206 m_pSplitter->addWidget(mVMListView); 207 # else /* BIG_TOOLBAR */ 513 208 pLeftVLayout->addWidget(mVMToolBar); 514 209 pLeftVLayout->addWidget(mVMListView); 515 pSplitter->addWidget(pLeftWidget); 210 setCentralWidget(m_pSplitter); 211 m_pSplitter->addWidget(pLeftWidget); 212 # endif /* BIG_TOOLBAR */ 516 213 #endif /* MAC_LEOPARD_STYLE */ 517 518 /* VM tab widget containing details and snapshots tabs */519 mVmTabWidget = new QITabWidget();520 pSplitter->addWidget (mVmTabWidget);521 522 /* Set the initial distribution. The right site is bigger. */523 pSplitter->setStretchFactor(0, 2);524 pSplitter->setStretchFactor(1, 3);525 526 527 /* VM details view */528 mVmDetailsView = new VBoxVMDetailsView (NULL, mVmRefreshAction);529 mVmTabWidget->addTab(mVmDetailsView,530 UIIconPool::iconSet(":/settings_16px.png"),531 QString::null);532 533 /* VM snapshots list */534 mVmSnapshotsWgt = new VBoxSnapshotsWgt (NULL);535 mVmTabWidget->addTab(mVmSnapshotsWgt,536 UIIconPool::iconSet(":/take_snapshot_16px.png",537 ":/take_snapshot_dis_16px.png"),538 QString::null);539 mVmSnapshotsWgt->setContentsMargins (10, 10, 10, 10);540 541 /* VM comments page */542 mVmDescriptionPage = new VBoxVMDescriptionPage (this);543 mVmTabWidget->addTab(mVmDescriptionPage,544 UIIconPool::iconSet(":/description_16px.png",545 ":/description_disabled_16px.png"),546 QString::null);547 mVmDescriptionPage->setContentsMargins (10, 10, 10, 10);548 214 549 215 /* add actions to the toolbar */ … … 551 217 mVMToolBar->setIconSize (QSize (32, 32)); 552 218 mVMToolBar->setToolButtonStyle (Qt::ToolButtonTextUnderIcon); 553 mVMToolBar->setSizePolicy (QSizePolicy::Fixed, QSizePolicy::Preferred);219 // mVMToolBar->setSizePolicy (QSizePolicy::Fixed, QSizePolicy::Preferred); 554 220 555 221 mVMToolBar->addAction (mVmNewAction); … … 560 226 mVMToolBar->addAction (mVmStartAction); 561 227 mVMToolBar->addAction (mVmDiscardAction); 228 229 /* VM tab widget containing details and snapshots tabs */ 230 QWidget *w = new QWidget(); 231 QVBoxLayout *pVBox = new QVBoxLayout(w); 232 pVBox->setContentsMargins(0, 0, 0, 0); 233 234 m_pVMDesktop = new UIVMDesktop(mVMToolBar, mVmRefreshAction, this); 235 pVBox->addWidget(m_pVMDesktop); 236 237 m_pSplitter->addWidget (w); 238 239 /* Set the initial distribution. The right site is bigger. */ 240 m_pSplitter->setStretchFactor(0, 2); 241 m_pSplitter->setStretchFactor(1, 3); 562 242 563 243 /* Configure menubar */ … … 675 355 /* Read the splitter handle position */ 676 356 { 677 QString sliderPos = vbox.GetExtraData(VBoxDefs::GUI_SplitterSizes); 678 QStringList strSizes = sliderPos.split(","); 679 if (strSizes.size() == 2) 680 { 681 QList<int> sizes; 682 for (int i=0; i < strSizes.size(); ++i) 683 sizes << strSizes.at(i).toInt(); 684 pSplitter->setSizes(sizes); 685 } 357 QList<int> sizes = vbox.GetExtraDataIntList(VBoxDefs::GUI_SplitterSizes); 358 if (sizes.size() == 2) 359 m_pSplitter->setSizes(sizes); 686 360 } 687 361 … … 691 365 QString strStatusbar = vbox.GetExtraData(VBoxDefs::GUI_Statusbar); 692 366 367 #ifdef Q_WS_MAC 693 368 mVMToolBar->setVisible(strToolbar.isEmpty() || strToolbar == "true"); 369 #else /* Q_WS_MAC */ 370 m_pBar->setVisible(strToolbar.isEmpty() || strToolbar == "true"); 371 #endif /* !Q_WS_MAC */ 694 372 statusBar()->setVisible(strStatusbar.isEmpty() || strStatusbar == "true"); 695 373 } … … 722 400 this, SLOT (showContextMenu (const QPoint &))); 723 401 724 connect (m VmDetailsView, SIGNAL (linkClicked(const QString &)),402 connect (m_pVMDesktop, SIGNAL(linkClicked(const QString &)), 725 403 this, SLOT(vmSettings(const QString &))); 726 404 … … 762 440 VBoxSelectorWnd::~VBoxSelectorWnd() 763 441 { 442 CVirtualBox vbox = vboxGlobal().virtualBox(); 443 764 444 /* Destroy our event handlers */ 765 445 UIVirtualBoxEventHandler::destroy(); 766 767 CVirtualBox vbox = vboxGlobal().virtualBox();768 446 769 447 /* Save the position of the window */ … … 795 473 /* Save the splitter handle position */ 796 474 { 797 QSplitter *pSplitter = static_cast<QSplitter*>(centralWidget()); 798 QList<int> sizes = pSplitter->sizes(); 799 QStringList strSizes; 800 for (int i=0; i < sizes.size(); ++i) 801 strSizes << QString::number(sizes.at(i)); 802 vbox.SetExtraData(VBoxDefs::GUI_SplitterSizes, strSizes.join(",")); 475 vbox.SetExtraDataIntList(VBoxDefs::GUI_SplitterSizes, m_pSplitter->sizes()); 803 476 } 804 477 … … 893 566 * Opens the VM settings dialog. 894 567 */ 895 void VBoxSelectorWnd::vmSettings (const QString &aCategory, const QString &aControl, 568 void VBoxSelectorWnd::vmSettings (const QString &aCategory /* = QString::null */, 569 const QString &aControl /* = QString::null */, 896 570 const QString &aUuid /* = QString::null */) 897 571 { … … 901 575 vboxGlobal().openURL (aCategory); 902 576 return; 577 } 578 QString strCategory = aCategory; 579 QString strControl = aControl; 580 /* Maybe the control is coded into the URL by %% */ 581 if (aControl == QString::null) 582 { 583 QStringList parts = aCategory.split("%%"); 584 if (parts.size() == 2) 585 { 586 strCategory = parts.at(0); 587 strControl = parts.at(1); 588 } 903 589 } 904 590 … … 917 603 AssertMsgReturn (!m.isNull(), ("Machine must not be null"), (void) 0); 918 604 919 VBoxSettingsDialog *dlg = new VBoxVMSettingsDlg (this, m, aCategory, aControl);605 VBoxSettingsDialog *dlg = new VBoxVMSettingsDlg (this, m, strCategory, strControl); 920 606 dlg->getFrom(); 921 607 … … 1377 1063 1378 1064 setWindowTitle (title); 1379 1380 mVmTabWidget->setTabText (mVmTabWidget->indexOf (mVmDetailsView), tr ("&Details"));1381 /* note: Snapshots and Details tabs are changed dynamically by1382 * vmListViewCurrentChanged() */1383 1065 1384 1066 /* ensure the details and screenshot view are updated */ … … 1510 1192 1511 1193 if (aRefreshDetails) 1512 { 1513 mVmDetailsView->setDetailsText ( 1514 vboxGlobal().detailsReport (m, modifyEnabled /* withLinks */)); 1515 } 1194 m_pVMDesktop->updateDetails(item, m); 1516 1195 if (aRefreshSnapshots) 1517 { 1518 /* update the snapshots tab name */ 1519 QString name = tr ("&Snapshots"); 1520 ULONG count = item->snapshotCount(); 1521 if (count) 1522 name += QString (" (%1)").arg (count); 1523 mVmTabWidget->setTabText (mVmTabWidget->indexOf (mVmSnapshotsWgt), name); 1524 /* refresh the snapshots widget */ 1525 mVmSnapshotsWgt->setMachine (m); 1526 /* ensure the tab is enabled */ 1527 mVmTabWidget->setTabEnabled (mVmTabWidget->indexOf (mVmSnapshotsWgt), true); 1528 } 1196 m_pVMDesktop->updateSnapshots(item, m); 1529 1197 if (aRefreshDescription) 1530 { 1531 /* update the description tab name */ 1532 QString name = m.GetDescription().isEmpty() ? 1533 tr ("D&escription") : tr ("D&escription *"); 1534 mVmTabWidget->setTabText (mVmTabWidget->indexOf (mVmDescriptionPage), name); 1535 /* refresh the description widget */ 1536 mVmDescriptionPage->setMachineItem (item); 1537 /* ensure the tab is enabled */ 1538 mVmTabWidget->setTabEnabled (mVmTabWidget->indexOf (mVmDescriptionPage), true); 1539 } 1198 m_pVMDesktop->updateDescription(item, m); 1540 1199 1541 1200 /* enable/disable modify actions */ … … 1625 1284 { 1626 1285 /* the VM is inaccessible */ 1627 m VmDetailsView->setErrorText(1628 VBoxProblemReporter::formatErrorInfo 1629 mVmRefreshAction->setEnabled 1286 m_pVMDesktop->updateDetailsErrorText( 1287 VBoxProblemReporter::formatErrorInfo(item->accessError())); 1288 mVmRefreshAction->setEnabled(true); 1630 1289 } 1631 1290 else … … 1633 1292 /* default HTML support in Qt is terrible so just try to get 1634 1293 * something really simple */ 1635 m VmDetailsView->setDetailsText1636 (tr("<h3>"1637 1638 1639 1640 1641 1642 1643 1644 1645 1646 1647 1648 1649 1650 mVmRefreshAction->setEnabled 1294 m_pVMDesktop->updateDetailsText( 1295 tr("<h3>" 1296 "Welcome to VirtualBox!</h3>" 1297 "<p>The left part of this window is " 1298 "a list of all virtual machines on your computer. " 1299 "The list is empty now because you haven't created any virtual " 1300 "machines yet." 1301 "<img src=:/welcome.png align=right/></p>" 1302 "<p>In order to create a new virtual machine, press the " 1303 "<b>New</b> button in the main tool bar located " 1304 "at the top of the window.</p>" 1305 "<p>You can press the <b>%1</b> key to get instant help, " 1306 "or visit " 1307 "<a href=http://www.virtualbox.org>www.virtualbox.org</a> " 1308 "for the latest information and news.</p>").arg (QKeySequence (QKeySequence::HelpContents).toString (QKeySequence::NativeText))); 1309 mVmRefreshAction->setEnabled(false); 1651 1310 } 1652 1311 1653 1312 /* empty and disable other tabs */ 1654 1655 mVmSnapshotsWgt->setMachine (CMachine()); 1656 mVmTabWidget->setTabText (mVmTabWidget->indexOf (mVmSnapshotsWgt), tr ("&Snapshots")); 1657 mVmTabWidget->setTabEnabled (mVmTabWidget->indexOf (mVmSnapshotsWgt), false); 1658 1659 mVmDescriptionPage->setMachineItem (NULL); 1660 mVmTabWidget->setTabText (mVmTabWidget->indexOf (mVmDescriptionPage), tr ("D&escription")); 1661 mVmTabWidget->setTabEnabled (mVmTabWidget->indexOf (mVmDescriptionPage), false); 1313 m_pVMDesktop->updateSnapshots(0, CMachine()); 1314 m_pVMDesktop->updateDescription(0, CMachine()); 1662 1315 1663 1316 /* disable modify actions */ … … 1749 1402 1750 1403 /* simulate a state change signal */ 1751 m VmDescriptionPage->updateState();1404 m_pVMDesktop->updateDescriptionState(); 1752 1405 } 1753 1406 … … 1803 1456 1804 1457 /* simulate a state change signal */ 1805 m VmDescriptionPage->updateState();1458 m_pVMDesktop->updateDescriptionState(); 1806 1459 } 1807 1460 … … 2252 1905 if (pResult->isChecked()) 2253 1906 { 1907 #ifdef Q_WS_MAC 2254 1908 mVMToolBar->show(); 1909 #else /* Q_WS_MAC */ 1910 m_pBar->show(); 1911 #endif /* !Q_WS_MAC */ 2255 1912 vbox.SetExtraData(VBoxDefs::GUI_Toolbar, "true"); 2256 1913 } 2257 1914 else 2258 1915 { 1916 #ifdef Q_WS_MAC 2259 1917 mVMToolBar->hide(); 1918 #else /* Q_WS_MAC */ 1919 m_pBar->hide(); 1920 #endif /* !Q_WS_MAC */ 2260 1921 vbox.SetExtraData(VBoxDefs::GUI_Toolbar, "false"); 2261 1922 } … … 2275 1936 } 2276 1937 2277 #include "VBoxSelectorWnd.moc" -
trunk/src/VBox/Frontends/VirtualBox/src/selector/VBoxSelectorWnd.h
r30866 r30868 20 20 #define __VBoxSelectorWnd_h__ 21 21 22 /* Local includes */ 22 23 #include "COMDefs.h" 23 24 24 #include "QIWithRetranslateUI.h" 25 26 25 #include "VBoxGlobal.h" 26 #include "VBoxHelpActions.h" 27 27 #include "VBoxProblemReporter.h" 28 #include "VBoxHelpActions.h" 29 30 /* Qt includes */ 28 29 /* Global includes */ 31 30 #include <QMainWindow> 32 31 #ifdef VBOX_GUI_WITH_SYSTRAY 33 #include <QSystemTrayIcon>32 # include <QSystemTrayIcon> 34 33 #endif 35 34 36 35 /* Local forward declarations */ 37 class QITabWidget; 36 class QISplitter; 37 class UIBar; 38 class UIVMDesktop; 38 39 class UIVMItem; 39 40 class UIVMItemModel; 40 41 class UIVMListView; 41 class VBoxSnapshotsWgt;42 42 class VBoxToolBar; 43 43 class VBoxTrayIcon; 44 class VBoxVMDescriptionPage;45 class VBoxVMDetailsView;46 44 class VBoxVMLogViewer; 47 45 48 /* Global forward declarations */ 49 class QEvent; 50 class QListView; 51 52 class VBoxSelectorWnd : public QIWithRetranslateUI2 <QMainWindow> 46 class VBoxSelectorWnd : public QIWithRetranslateUI2<QMainWindow> 53 47 { 54 48 Q_OBJECT; … … 150 144 QMenu *mHelpMenu; 151 145 146 /* Central splitter window */ 147 QISplitter *m_pSplitter; 148 152 149 /* Main toolbar */ 150 #ifndef Q_WS_MAC 151 UIBar *m_pBar; 152 #endif /* !Q_WS_MAC */ 153 153 VBoxToolBar *mVMToolBar; 154 154 155 155 /* VM list context menu */ 156 156 QMenu *mVMCtxtMenu; 157 // UIOSDMenu *mVMCtxtMenu;158 157 159 158 /* Actions */ … … 184 183 185 184 /* The right information widgets */ 186 QITabWidget *mVmTabWidget; 187 VBoxVMDetailsView *mVmDetailsView; 188 VBoxSnapshotsWgt *mVmSnapshotsWgt; 189 VBoxVMDescriptionPage *mVmDescriptionPage; 185 UIVMDesktop *m_pVMDesktop; 190 186 191 187 QRect mNormalGeo; -
trunk/src/VBox/Frontends/VirtualBox/src/widgets/UISpacerWidgets.h
r30188 r30868 32 32 : QWidget(pParent) 33 33 { 34 setContentsMargins(0, 0, 0, 0); 34 35 setOrientation(Qt::Horizontal); 35 36 } … … 45 46 Qt::Orientation orientation() const { return m_orientation; } 46 47 47 QSize sizeHint() const { return QSize( 1, 1); }48 QSize sizeHint() const { return QSize(0, 0); } 48 49 49 50 private:
Note:
See TracChangeset
for help on using the changeset viewer.