Changeset 54733 in vbox for trunk/src/VBox/Frontends/VirtualBox
- Timestamp:
- Mar 12, 2015 5:49:10 PM (10 years ago)
- Location:
- trunk/src/VBox/Frontends/VirtualBox
- Files:
-
- 2 edited
- 2 copied
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Frontends/VirtualBox/Makefile.kmk
r54731 r54733 299 299 src/medium/UIMediumManager.h \ 300 300 src/runtime/UIActionPoolRuntime.h \ 301 src/runtime/UIAddDiskEncryptionPasswordDialog.h \ 301 302 src/runtime/UIConsoleEventHandler.h \ 302 303 src/runtime/UIFrameBuffer.h \ … … 491 492 src/medium/UIMediumManager.cpp \ 492 493 src/runtime/UIActionPoolRuntime.cpp \ 494 src/runtime/UIAddDiskEncryptionPasswordDialog.cpp \ 493 495 src/runtime/UIFrameBuffer.cpp \ 494 496 src/runtime/UIIndicatorsPool.cpp \ 495 497 src/runtime/UIStatusBarEditorWindow.cpp \ 496 src/runtime/UISession.cpp \497 498 src/selector/UIActionPoolSelector.cpp \ 498 499 src/selector/UIVMDesktop.cpp \ … … 579 580 src/medium/UIMediumManager.cpp \ 580 581 src/runtime/UIActionPoolRuntime.cpp \ 582 src/runtime/UIAddDiskEncryptionPasswordDialog.cpp \ 581 583 src/runtime/UIConsoleEventHandler.cpp \ 582 584 src/runtime/UIFrameBuffer.cpp \ -
trunk/src/VBox/Frontends/VirtualBox/src/runtime/UIAddDiskEncryptionPasswordDialog.cpp
r54732 r54733 1 1 /* $Id$ */ 2 2 /** @file 3 * VBox Qt GUI - UI Sessionclass implementation.3 * VBox Qt GUI - UIAddDiskEncryptionPasswordDialog class implementation. 4 4 */ 5 5 6 6 /* 7 * Copyright (C) 2006-201 3Oracle Corporation7 * Copyright (C) 2006-2015 Oracle Corporation 8 8 * 9 9 * This file is part of VirtualBox Open Source Edition (OSE), as … … 21 21 22 22 /* Qt includes: */ 23 # include <QApplication> 24 # include <QDesktopWidget> 25 # include <QWidget> 26 # ifdef Q_WS_MAC 27 # include <QTimer> 28 # endif /* Q_WS_MAC */ 23 # include <QVBoxLayout> 24 # include <QLineEdit> 25 # include <QTableView> 26 # include <QHeaderView> 27 # include <QItemEditorFactory> 28 # include <QAbstractTableModel> 29 # include <QStandardItemEditorCreator> 29 30 30 31 /* GUI includes: */ 31 # include "VBoxGlobal.h" 32 # include "UIExtraDataManager.h" 33 # include "UISession.h" 34 # include "UIMachine.h" 35 # include "UIMedium.h" 36 # include "UIActionPoolRuntime.h" 37 # include "UIMachineLogic.h" 38 # include "UIMachineView.h" 39 # include "UIMachineWindow.h" 40 # include "UIMessageCenter.h" 41 # include "UIPopupCenter.h" 42 # include "UIWizardFirstRun.h" 43 # include "UIConsoleEventHandler.h" 44 # include "UIFrameBuffer.h" 45 # include "UISettingsDialogSpecific.h" 46 # ifdef VBOX_WITH_VIDEOHWACCEL 47 # include "VBoxFBOverlay.h" 48 # endif /* VBOX_WITH_VIDEOHWACCEL */ 49 # ifdef Q_WS_MAC 50 # include "UIMenuBar.h" 51 # include "VBoxUtils-darwin.h" 52 # endif /* Q_WS_MAC */ 53 54 # ifdef VBOX_GUI_WITH_KEYS_RESET_HANDLER 55 # include "UIKeyboardHandler.h" 56 # include <signal.h> 57 # endif /* VBOX_GUI_WITH_KEYS_RESET_HANDLER */ 58 59 /* COM includes: */ 60 # include "CSystemProperties.h" 61 # include "CStorageController.h" 62 # include "CMediumAttachment.h" 63 # include "CNetworkAdapter.h" 64 # include "CHostNetworkInterface.h" 65 # include "CVRDEServer.h" 66 # include "CUSBController.h" 67 # include "CUSBDeviceFilters.h" 68 # include "CHostVideoInputDevice.h" 69 # include "CSnapshot.h" 70 # include "CMedium.h" 32 # include "QILabel.h" 33 # include "QIDialogButtonBox.h" 34 # include "QIWithRetranslateUI.h" 35 # include "QIStyledItemDelegate.h" 36 # include "UIAddDiskEncryptionPasswordDialog.h" 37 38 /* Other VBox includes: */ 39 # include <iprt/assert.h> 71 40 72 41 #endif /* !VBOX_WITH_PRECOMPILED_HEADERS */ 73 42 74 #ifdef Q_WS_X11 75 # include <QX11Info> 76 # include <X11/Xlib.h> 77 # include <X11/Xutil.h> 78 # ifndef VBOX_WITHOUT_XCURSOR 79 # include <X11/Xcursor/Xcursor.h> 80 # endif /* VBOX_WITHOUT_XCURSOR */ 81 #endif /* Q_WS_X11 */ 82 83 84 /* Qt includes: */ 85 #include <QDialog> 86 #include <QVBoxLayout> 87 #include <QLineEdit> 88 #include <QTableView> 89 #include <QHeaderView> 90 #include <QItemEditorFactory> 91 #include <QAbstractTableModel> 92 #include <QStandardItemEditorCreator> 93 /* GUI includes: */ 94 #include "QILabel.h" 95 #include "QIDialogButtonBox.h" 96 #include "QIWithRetranslateUI.h" 97 #include "QIStyledItemDelegate.h" 98 99 /* Type definitions: */ 100 typedef QMap<QString, QString> EncryptionPasswordsMap; 101 typedef QMultiMap<QString, QString> EncryptedMediumsMap; 102 103 /** Encryption-data table field indexes. 104 * @todo To be moved into separate file.. */ 105 enum UIEncryptionTableSection 106 { 107 UIEncryptionTableSection_Id, 108 UIEncryptionTableSection_Password, 109 UIEncryptionTableSection_Max 43 /** UIEncryptionDataTable field indexes. */ 44 enum UIEncryptionDataTableSection 45 { 46 UIEncryptionDataTableSection_Id, 47 UIEncryptionDataTableSection_Password, 48 UIEncryptionDataTableSection_Max 110 49 }; 111 50 112 /** QLineEdit implementation allowing to enter 113 * disk encryption password for particular password id. 114 * @todo To be moved into separate file.. */ 115 class UILineEdit : public QLineEdit 51 /** QLineEdit reimplementation used as 52 * the embedded password editor for the UIEncryptionDataTable. */ 53 class UIPasswordEditor : public QLineEdit 116 54 { 117 55 Q_OBJECT; 56 57 /** Holds the current password of the editor. */ 118 58 Q_PROPERTY(QString password READ password WRITE setPassword USER true); 119 59 120 60 signals: 121 61 122 /** Notifies listener about data should be committed. */62 /** Notifies listeners about data should be committed. */ 123 63 void sigCommitData(QWidget *pThis); 124 64 … … 127 67 /** Constructor. 128 68 * @param pParent being passed to the base-class. */ 129 UILineEdit(QWidget *pParent) 130 : QLineEdit(pParent) 131 { 132 /* Prepare: */ 133 prepare(); 134 } 135 136 public slots: 137 138 /** Handles @s strText changes. */ 139 void sltTextChanged(const QString &strText) 140 { 141 Q_UNUSED(strText); 142 /* Commit data to the listener: */ 143 emit sigCommitData(this); 144 } 69 UIPasswordEditor(QWidget *pParent); 70 71 private slots: 72 73 /** Handles @s strPassword changes. */ 74 void sltPasswordChanged(const QString &strPassword); 145 75 146 76 private: 147 77 148 78 /** Prepare routine. */ 149 void prepare() 150 { 151 /* Set alignment: */ 152 setAlignment(Qt::AlignCenter); 153 /* Set echo mode: */ 154 setEchoMode(QLineEdit::Password); 155 /* Listen for the text changes: */ 156 connect(this, SIGNAL(textChanged(const QString&)), 157 this, SLOT(sltTextChanged(const QString&))); 158 } 159 160 /** Returns the password from the editor. */ 79 void prepare(); 80 81 /** Property: Returns the current password of the editor. */ 161 82 QString password() const { return QLineEdit::text(); } 162 /** Defines the @a strPassword tothe editor. */83 /** Property: Defines the current @a strPassword of the editor. */ 163 84 void setPassword(const QString &strPassword) { QLineEdit::setText(strPassword); } 164 85 }; 165 86 166 /** QAbstractTableModel implementation reflecting 167 * disk encryption passwords for particular password ids. 168 * @todo To be moved into separate file.. */ 87 /** QAbstractTableModel reimplementation used as 88 * the data representation model for the UIEncryptionDataTable. */ 169 89 class UIEncryptionDataModel : public QAbstractTableModel 170 90 { … … 176 96 * @param pParent being passed to the base-class, 177 97 * @param encryptedMediums contains the lists of medium ids (values) encrypted with passwords with ids (keys). */ 178 UIEncryptionDataModel(QObject *pParent, const EncryptedMediumsMap &encryptedMediums) 179 : QAbstractTableModel(pParent) 180 , m_encryptedMediums(encryptedMediums) 181 { 182 /* Prepare: */ 183 prepare(); 184 } 185 186 /** Returns encryption passwords. */ 98 UIEncryptionDataModel(QObject *pParent, const EncryptedMediumsMap &encryptedMediums); 99 100 /** Returns the shallow copy of the encryption password map instance. */ 187 101 EncryptionPasswordsMap encryptionPasswords() const { return m_encryptionPasswords; } 188 102 103 /** Returns the row count, taking optional @a parent instead of root if necessary. */ 104 virtual int rowCount(const QModelIndex &parent = QModelIndex()) const; 105 /** Returns the column count, taking optional @a parent instead of root if necessary. */ 106 virtual int columnCount(const QModelIndex &parent = QModelIndex()) const; 107 189 108 /** Returns the @a index flags. */ 190 virtual Qt::ItemFlags flags(const QModelIndex &index) const 191 { 192 /* Check index validness: */ 193 if (!index.isValid()) 194 return Qt::NoItemFlags; 195 /* Depending on column index: */ 196 switch (index.column()) 197 { 198 case UIEncryptionTableSection_Id: return Qt::ItemIsEnabled | Qt::ItemIsSelectable; 199 case UIEncryptionTableSection_Password: return Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsEditable; 200 default: break; 201 } 202 /* No flags by default: */ 203 return Qt::NoItemFlags; 204 } 205 206 /** Returns the row count. Provide optional @a parent instead of root if necessary. */ 207 virtual int rowCount(const QModelIndex &parent = QModelIndex()) const 208 { 209 Q_UNUSED(parent); 210 return m_encryptionPasswords.size(); 211 } 212 213 /** Returns the column count. Provide optional @a parent instead of root if necessary. */ 214 virtual int columnCount(const QModelIndex &parent = QModelIndex()) const 215 { 216 Q_UNUSED(parent); 217 return UIEncryptionTableSection_Max; 218 } 219 220 /** Returns header data for @a iSection, @a orientation and @a iRole. */ 221 virtual QVariant headerData(int iSection, Qt::Orientation orientation, int iRole) const 222 { 223 /* Check argument validness: */ 224 if (iRole != Qt::DisplayRole || orientation != Qt::Horizontal) 225 return QVariant(); 226 /* Depending on column index: */ 227 switch (iSection) 228 { 229 case UIEncryptionTableSection_Id: return tr("Password ID"); 230 case UIEncryptionTableSection_Password: return tr("Password"); 231 default: break; 232 } 233 /* Null value by default: */ 234 return QVariant(); 235 } 236 237 /** Returns @a index data for @a iRole. */ 238 virtual QVariant data(const QModelIndex &index, int iRole /* = Qt::DisplayRole */) const 239 { 240 /* Check index validness: */ 241 if (!index.isValid()) 242 return QVariant(); 243 /* Depending on role: */ 244 switch (iRole) 245 { 246 case Qt::DisplayRole: 247 { 248 /* Depending on column index: */ 249 switch (index.column()) 250 { 251 case UIEncryptionTableSection_Id: 252 return m_encryptionPasswords.keys().at(index.row()); 253 case UIEncryptionTableSection_Password: 254 return QString().fill('*', m_encryptionPasswords.value(m_encryptionPasswords.keys().at(index.row())).size()); 255 default: 256 return QVariant(); 257 } 258 break; 259 } 260 case Qt::EditRole: 261 { 262 /* Depending on column index: */ 263 switch (index.column()) 264 { 265 case UIEncryptionTableSection_Password: 266 return m_encryptionPasswords.value(m_encryptionPasswords.keys().at(index.row())); 267 default: 268 return QVariant(); 269 } 270 break; 271 } 272 case Qt::TextAlignmentRole: 273 { 274 /* Depending on column index: */ 275 switch (index.column()) 276 { 277 case UIEncryptionTableSection_Password: 278 return Qt::AlignCenter; 279 default: return QVariant(); 280 } 281 break; 282 } 283 default: 284 break; 285 } 286 /* Null value by default: */ 287 return QVariant(); 288 } 289 290 /** Defines @a index data for @a iRole as @a value. */ 291 virtual bool setData(const QModelIndex &index, const QVariant &value, int iRole /* = Qt::EditRole */) 292 { 293 /* Check index validness: */ 294 if (!index.isValid()) 295 return false; 296 /* Check argument validness: */ 297 if (iRole != Qt::EditRole) 298 return false; 299 /* Depending on column index: */ 300 switch (index.column()) 301 { 302 case UIEncryptionTableSection_Password: m_encryptionPasswords[m_encryptionPasswords.keys().at(index.row())] = value.toString(); break; 303 default: break; 304 } 305 /* Nothing to set by default: */ 306 return false; 307 } 109 virtual Qt::ItemFlags flags(const QModelIndex &index) const; 110 111 /** Returns the header data for the @a iSection, @a orientation and @a iRole. */ 112 virtual QVariant headerData(int iSection, Qt::Orientation orientation, int iRole) const; 113 114 /** Returns the @a index data for the @a iRole. */ 115 virtual QVariant data(const QModelIndex &index, int iRole = Qt::DisplayRole) const; 116 /** Defines the @a index data for the @a iRole as @a value. */ 117 virtual bool setData(const QModelIndex &index, const QVariant &value, int iRole = Qt::EditRole); 308 118 309 119 private: 310 120 311 121 /** Prepare routine. */ 312 void prepare() 313 { 314 /* Populate the map of passwords. */ 315 foreach (const QString &strPasswordId, m_encryptedMediums.keys()) 316 m_encryptionPasswords.insert(strPasswordId, QString()); 317 } 122 void prepare(); 318 123 319 124 /** Holds the encrypted medium map reference. */ 320 125 const EncryptedMediumsMap &m_encryptedMediums; 321 126 322 /** Holds the encrypt ed password id map. */127 /** Holds the encryption password map instance. */ 323 128 EncryptionPasswordsMap m_encryptionPasswords; 324 129 }; 325 130 326 /** QTableView implementation allowing to enter327 * disk encryption passwords for particular password ids.328 * @todo To be moved into separate file.. */131 /** QTableView reimplementation used to 132 * allow the UIAddDiskEncryptionPasswordDialog to enter 133 * disk encryption passwords for particular password ids. */ 329 134 class UIEncryptionDataTable : public QTableView 330 135 { … … 335 140 /** Constructor. 336 141 * @param pParent being passed to the base-class. */ 337 UIEncryptionDataTable(const EncryptedMediumsMap &encryptedMediums) 338 : m_encryptedMediums(encryptedMediums) 339 , m_pModelEncryptionData(0) 340 { 341 /* Prepare: */ 342 prepare(); 343 } 344 345 /** Returns encryption passwords. */ 346 EncryptionPasswordsMap encryptionPasswords() const 347 { 348 AssertPtrReturn(m_pModelEncryptionData, EncryptionPasswordsMap()); 349 return m_pModelEncryptionData->encryptionPasswords(); 350 } 142 UIEncryptionDataTable(const EncryptedMediumsMap &encryptedMediums); 143 144 /** Returns the shallow copy of the encryption password map 145 * acquired from the UIEncryptionDataModel instance. */ 146 EncryptionPasswordsMap encryptionPasswords() const; 351 147 352 148 private: 353 149 354 150 /** Prepare routine. */ 355 void prepare() 356 { 357 /* Create encryption-data model: */ 358 m_pModelEncryptionData = new UIEncryptionDataModel(this, m_encryptedMediums); 359 AssertPtrReturnVoid(m_pModelEncryptionData); 360 { 361 /* Assign configured model to table: */ 362 setModel(m_pModelEncryptionData); 363 } 364 365 /* Create item delegate: */ 366 QIStyledItemDelegate *pStyledItemDelegate = new QIStyledItemDelegate(this); 367 AssertPtrReturnVoid(pStyledItemDelegate); 368 { 369 /* Create item editor factory: */ 370 QItemEditorFactory *pNewItemEditorFactory = new QItemEditorFactory; 371 AssertPtrReturnVoid(pNewItemEditorFactory); 372 { 373 /* Create item editor creator: */ 374 QStandardItemEditorCreator<UILineEdit> *pQStringItemEditorCreator = new QStandardItemEditorCreator<UILineEdit>(); 375 AssertPtrReturnVoid(pQStringItemEditorCreator); 376 { 377 /* Register UILineEdit as the QString editor: */ 378 pNewItemEditorFactory->registerEditor(QVariant::String, pQStringItemEditorCreator); 379 } 380 /* Assign configured item editor factory to table delegate: */ 381 pStyledItemDelegate->setItemEditorFactory(pNewItemEditorFactory); 382 } 383 /* Assign configured item delegate to table: */ 384 delete itemDelegate(); 385 setItemDelegate(pStyledItemDelegate); 386 } 387 388 /* Configure table: */ 389 setTabKeyNavigation(false); 390 setContextMenuPolicy(Qt::CustomContextMenu); 391 setSelectionBehavior(QAbstractItemView::SelectRows); 392 setSelectionMode(QAbstractItemView::SingleSelection); 393 setEditTriggers(QAbstractItemView::CurrentChanged | QAbstractItemView::SelectedClicked); 394 395 /* Configure headers: */ 396 verticalHeader()->hide(); 397 verticalHeader()->setDefaultSectionSize((int)(verticalHeader()->minimumSectionSize() * 1.33)); 398 horizontalHeader()->setStretchLastSection(false); 399 horizontalHeader()->setResizeMode(UIEncryptionTableSection_Id, QHeaderView::Interactive); 400 horizontalHeader()->setResizeMode(UIEncryptionTableSection_Password, QHeaderView::Stretch); 401 } 151 void prepare(); 402 152 403 153 /** Holds the encrypted medium map reference. */ 404 154 const EncryptedMediumsMap &m_encryptedMediums; 405 155 406 /** Holds the encryption-data model . */156 /** Holds the encryption-data model instance. */ 407 157 UIEncryptionDataModel *m_pModelEncryptionData; 408 158 }; 409 159 410 /** QDialog implementation allowing to enter 411 * disk encryption passwords for particular password ids. 412 * @todo To be moved into separate files.. */ 413 class UIAddDiskEncryptionPasswordDialog : public QIWithRetranslateUI<QDialog> 414 { 415 Q_OBJECT; 416 417 public: 418 419 /** Constructor. 420 * @param pParent being passed to the base-class, 421 * @param encryptedMediums contains the lists of medium ids (values) encrypted with passwords with ids (keys). */ 422 UIAddDiskEncryptionPasswordDialog(QWidget *pParent, const EncryptedMediumsMap &encryptedMediums) 423 : QIWithRetranslateUI<QDialog>(pParent) 424 , m_encryptedMediums(encryptedMediums) 425 , m_pLabelDescription(0) 426 , m_pTableEncryptionData(0) 427 { 428 /* Prepare: */ 429 prepare(); 430 /* Retranslate: */ 431 retranslateUi(); 432 } 433 434 /** Returns encryption passwords. */ 435 EncryptionPasswordsMap encryptionPasswords() const 436 { 437 AssertPtrReturn(m_pTableEncryptionData, EncryptionPasswordsMap()); 438 return m_pTableEncryptionData->encryptionPasswords(); 439 } 440 441 private: 442 443 /** Prepare routine. */ 444 void prepare() 445 { 446 /* Create main-layout: */ 447 QVBoxLayout *pMainLayout = new QVBoxLayout(this); 448 AssertPtrReturnVoid(pMainLayout); 449 { 450 /* Create input-layout: */ 451 QVBoxLayout *pInputLayout = new QVBoxLayout; 452 AssertPtrReturnVoid(pInputLayout); 453 { 454 /* Create description label: */ 455 m_pLabelDescription = new QILabel; 456 m_pLabelDescription->useSizeHintForWidth(450); 457 m_pLabelDescription->updateGeometry(); 458 AssertPtrReturnVoid(m_pLabelDescription); 459 { 460 /* Configure description label: */ 461 m_pLabelDescription->setWordWrap(true); 462 /* Add label into layout: */ 463 pInputLayout->addWidget(m_pLabelDescription); 464 } 465 /* Create encryption-data table: */ 466 m_pTableEncryptionData = new UIEncryptionDataTable(m_encryptedMediums); 467 AssertPtrReturnVoid(m_pTableEncryptionData); 468 { 469 /* Add label into layout: */ 470 pInputLayout->addWidget(m_pTableEncryptionData); 471 } 472 /* Add layout into parent: */ 473 pMainLayout->addLayout(pInputLayout); 474 } 475 /* Create button-box: */ 476 QIDialogButtonBox *pButtonBox = new QIDialogButtonBox; 477 AssertPtrReturnVoid(pButtonBox); 478 { 479 /* Configure button-box: */ 480 pButtonBox->setStandardButtons(QDialogButtonBox::Ok | QDialogButtonBox::Cancel); 481 connect(pButtonBox, SIGNAL(accepted()), this, SLOT(accept())); 482 connect(pButtonBox, SIGNAL(rejected()), this, SLOT(reject())); 483 /* Add button-box into layout: */ 484 pMainLayout->addWidget(pButtonBox); 485 } 486 } 487 } 488 489 /** Translation routine. */ 490 void retranslateUi() 491 { 492 AssertPtrReturnVoid(m_pLabelDescription); 493 m_pLabelDescription->setText(tr("This virtual machine is password protected. " 494 "Please enter the %n encryption password(s) below.", 495 "This text is never used with n == 0. " 496 "Feel free to drop the %n where possible, " 497 "we only included it because of problems with Qt Linguist " 498 "(but the user can see how many passwords are in the list " 499 "and doesn't need to be told).", 500 m_encryptedMediums.size())); 501 } 502 503 /** Holds the encrypted medium map reference. */ 504 const EncryptedMediumsMap &m_encryptedMediums; 505 506 /** Holds the description label. */ 507 QILabel *m_pLabelDescription; 508 /** Holds the encryption-data table. */ 509 UIEncryptionDataTable *m_pTableEncryptionData; 510 }; 511 512 513 #ifdef VBOX_GUI_WITH_KEYS_RESET_HANDLER 514 static void signalHandlerSIGUSR1(int sig, siginfo_t *, void *); 515 #endif 516 517 #ifdef Q_WS_MAC 518 /** 519 * MacOS X: Application Services: Core Graphics: Display reconfiguration callback. 520 * 521 * Notifies UISession about @a display configuration change. 522 * Corresponding change described by Core Graphics @a flags. 523 * Uses UISession @a pHandler to process this change. 524 * 525 * @note Last argument (@a pHandler) must always be valid pointer to UISession object. 526 * @note Calls for UISession::sltHandleHostDisplayAboutToChange() slot if display configuration changed. 527 */ 528 void cgDisplayReconfigurationCallback(CGDirectDisplayID display, CGDisplayChangeSummaryFlags flags, void *pHandler) 529 { 530 /* Which flags we are handling? */ 531 int iHandledFlags = kCGDisplayAddFlag /* display added */ 532 | kCGDisplayRemoveFlag /* display removed */ 533 | kCGDisplaySetModeFlag /* display mode changed */; 534 535 /* Handle 'display-add' case: */ 536 if (flags & kCGDisplayAddFlag) 537 LogRelFlow(("UISession::cgDisplayReconfigurationCallback: Display added.\n")); 538 /* Handle 'display-remove' case: */ 539 else if (flags & kCGDisplayRemoveFlag) 540 LogRelFlow(("UISession::cgDisplayReconfigurationCallback: Display removed.\n")); 541 /* Handle 'mode-set' case: */ 542 else if (flags & kCGDisplaySetModeFlag) 543 LogRelFlow(("UISession::cgDisplayReconfigurationCallback: Display mode changed.\n")); 544 545 /* Ask handler to process our callback: */ 546 if (flags & iHandledFlags) 547 QTimer::singleShot(0, static_cast<UISession*>(pHandler), 548 SLOT(sltHandleHostDisplayAboutToChange())); 549 550 Q_UNUSED(display); 551 } 552 #endif /* Q_WS_MAC */ 553 554 /* static */ 555 bool UISession::create(UISession *&pSession, UIMachine *pMachine) 556 { 557 /* Make sure null pointer passed: */ 558 AssertReturn(pSession == 0, false); 559 560 /* Create session UI: */ 561 pSession = new UISession(pMachine); 562 /* Make sure it's prepared: */ 563 if (!pSession->prepare()) 564 { 565 /* Destroy session UI otherwise: */ 566 destroy(pSession); 567 /* False in that case: */ 160 UIPasswordEditor::UIPasswordEditor(QWidget *pParent) 161 : QLineEdit(pParent) 162 { 163 /* Prepare: */ 164 prepare(); 165 } 166 167 void UIPasswordEditor::sltPasswordChanged(const QString &strPassword) 168 { 169 Q_UNUSED(strPassword); 170 /* Commit data to the listener: */ 171 emit sigCommitData(this); 172 } 173 174 void UIPasswordEditor::prepare() 175 { 176 /* Set alignment: */ 177 setAlignment(Qt::AlignCenter); 178 /* Set echo mode: */ 179 setEchoMode(QLineEdit::Password); 180 /* Listen for the text changes: */ 181 connect(this, SIGNAL(textChanged(const QString&)), 182 this, SLOT(sltPasswordChanged(const QString&))); 183 } 184 185 UIEncryptionDataModel::UIEncryptionDataModel(QObject *pParent, const EncryptedMediumsMap &encryptedMediums) 186 : QAbstractTableModel(pParent) 187 , m_encryptedMediums(encryptedMediums) 188 { 189 /* Prepare: */ 190 prepare(); 191 } 192 193 int UIEncryptionDataModel::rowCount(const QModelIndex &parent /* = QModelIndex() */) const 194 { 195 Q_UNUSED(parent); 196 return m_encryptionPasswords.size(); 197 } 198 199 int UIEncryptionDataModel::columnCount(const QModelIndex &parent /* = QModelIndex() */) const 200 { 201 Q_UNUSED(parent); 202 return UIEncryptionDataTableSection_Max; 203 } 204 205 Qt::ItemFlags UIEncryptionDataModel::flags(const QModelIndex &index) const 206 { 207 /* Check index validness: */ 208 if (!index.isValid()) 209 return Qt::NoItemFlags; 210 /* Depending on column index: */ 211 switch (index.column()) 212 { 213 case UIEncryptionDataTableSection_Id: return Qt::ItemIsEnabled | Qt::ItemIsSelectable; 214 case UIEncryptionDataTableSection_Password: return Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsEditable; 215 default: break; 216 } 217 /* No flags by default: */ 218 return Qt::NoItemFlags; 219 } 220 221 QVariant UIEncryptionDataModel::headerData(int iSection, Qt::Orientation orientation, int iRole) const 222 { 223 /* Check argument validness: */ 224 if (iRole != Qt::DisplayRole || orientation != Qt::Horizontal) 225 return QVariant(); 226 /* Depending on column index: */ 227 switch (iSection) 228 { 229 case UIEncryptionDataTableSection_Id: return tr("Password ID"); 230 case UIEncryptionDataTableSection_Password: return tr("Password"); 231 default: break; 232 } 233 /* Null value by default: */ 234 return QVariant(); 235 } 236 237 QVariant UIEncryptionDataModel::data(const QModelIndex &index, int iRole /* = Qt::DisplayRole */) const 238 { 239 /* Check index validness: */ 240 if (!index.isValid()) 241 return QVariant(); 242 /* Depending on role: */ 243 switch (iRole) 244 { 245 case Qt::DisplayRole: 246 { 247 /* Depending on column index: */ 248 switch (index.column()) 249 { 250 case UIEncryptionDataTableSection_Id: 251 return m_encryptionPasswords.keys().at(index.row()); 252 case UIEncryptionDataTableSection_Password: 253 return QString().fill('*', m_encryptionPasswords.value(m_encryptionPasswords.keys().at(index.row())).size()); 254 default: 255 return QVariant(); 256 } 257 break; 258 } 259 case Qt::EditRole: 260 { 261 /* Depending on column index: */ 262 switch (index.column()) 263 { 264 case UIEncryptionDataTableSection_Password: 265 return m_encryptionPasswords.value(m_encryptionPasswords.keys().at(index.row())); 266 default: 267 return QVariant(); 268 } 269 break; 270 } 271 case Qt::TextAlignmentRole: 272 { 273 /* Depending on column index: */ 274 switch (index.column()) 275 { 276 case UIEncryptionDataTableSection_Password: 277 return Qt::AlignCenter; 278 default: return QVariant(); 279 } 280 break; 281 } 282 default: 283 break; 284 } 285 /* Null value by default: */ 286 return QVariant(); 287 } 288 289 bool UIEncryptionDataModel::setData(const QModelIndex &index, const QVariant &value, int iRole /* = Qt::EditRole */) 290 { 291 /* Check index validness: */ 292 if (!index.isValid()) 568 293 return false; 569 } 570 /* True by default: */ 571 return true; 572 } 573 574 /* static */ 575 void UISession::destroy(UISession *&pSession) 576 { 577 /* Make sure valid pointer passed: */ 578 AssertReturnVoid(pSession != 0); 579 580 /* Cleanup session UI: */ 581 pSession->cleanup(); 582 /* Destroy session: */ 583 delete pSession; 584 pSession = 0; 585 } 586 587 bool UISession::initialize() 588 { 589 /* Preprocess initialization: */ 590 if (!preprocessInitialization()) 294 /* Check argument validness: */ 295 if (iRole != Qt::EditRole) 591 296 return false; 592 593 /* Notify user about mouse&keyboard auto-capturing: */ 594 if (vboxGlobal().settings().autoCapture()) 595 popupCenter().remindAboutAutoCapture(machineLogic()->activeMachineWindow()); 596 597 /* Check if we are in teleportation waiting mode. 598 * In that case no first run wizard is necessary. */ 599 m_machineState = machine().GetState(); 600 if ( isFirstTimeStarted() 601 && !(( m_machineState == KMachineState_PoweredOff 602 || m_machineState == KMachineState_Aborted 603 || m_machineState == KMachineState_Teleported) 604 && machine().GetTeleporterEnabled())) 605 { 606 UISafePointerWizard pWizard = new UIWizardFirstRun(mainMachineWindow(), machine()); 607 pWizard->prepare(); 608 pWizard->exec(); 609 if (pWizard) 610 delete pWizard; 611 } 612 613 /* Apply debug settings from the command line. */ 614 if (!debugger().isNull() && debugger().isOk()) 615 { 616 if (vboxGlobal().isPatmDisabled()) 617 debugger().SetPATMEnabled(false); 618 if (vboxGlobal().isCsamDisabled()) 619 debugger().SetCSAMEnabled(false); 620 if (vboxGlobal().isSupervisorCodeExecedRecompiled()) 621 debugger().SetRecompileSupervisor(true); 622 if (vboxGlobal().isUserCodeExecedRecompiled()) 623 debugger().SetRecompileUser(true); 624 if (vboxGlobal().areWeToExecuteAllInIem()) 625 debugger().SetExecuteAllInIEM(true); 626 if (!vboxGlobal().isDefaultWarpPct()) 627 debugger().SetVirtualTimeRate(vboxGlobal().getWarpPct()); 628 } 629 630 /* Power UP if this is NOT separate process: */ 631 if (!vboxGlobal().isSeparateProcess()) 632 if (!powerUp()) 633 return false; 634 635 /* Check if we missed a really quick termination after successful startup: */ 636 if (isTurnedOff()) 637 return false; 638 639 /* Postprocess initialization: */ 640 if (!postprocessInitialization()) 641 return false; 642 643 /* Fetch corresponding states: */ 644 if (vboxGlobal().isSeparateProcess()) 645 { 646 m_fIsMouseSupportsAbsolute = mouse().GetAbsoluteSupported(); 647 m_fIsMouseSupportsRelative = mouse().GetRelativeSupported(); 648 m_fIsMouseSupportsMultiTouch = mouse().GetMultiTouchSupported(); 649 m_fIsMouseHostCursorNeeded = mouse().GetNeedsHostCursor(); 650 sltAdditionsChange(); 651 } 652 machineLogic()->initializePostPowerUp(); 653 654 #ifdef VBOX_WITH_VIDEOHWACCEL 655 /* Log whether 2D video acceleration is enabled: */ 656 LogRel(("2D video acceleration is %s.\n", 657 machine().GetAccelerate2DVideoEnabled() && VBoxGlobal::isAcceleration2DVideoAvailable() 658 ? "enabled" : "disabled")); 659 #endif /* VBOX_WITH_VIDEOHWACCEL */ 660 661 /* Log whether HID LEDs sync is enabled: */ 662 #if defined(Q_WS_MAC) || defined(Q_WS_WIN) 663 LogRel(("HID LEDs sync is %s.\n", 664 uimachine()->machineLogic()->isHidLedsSyncEnabled() 665 ? "enabled" : "disabled")); 666 #else /* !Q_WS_MAC && !Q_WS_WIN */ 667 LogRel(("HID LEDs sync is not supported on this platform.\n")); 668 #endif /* !Q_WS_MAC && !Q_WS_WIN */ 669 670 #ifdef VBOX_GUI_WITH_PIDFILE 671 vboxGlobal().createPidfile(); 672 #endif /* VBOX_GUI_WITH_PIDFILE */ 673 674 /* Warn listeners about we are initialized: */ 675 emit sigInitialized(); 676 677 /* True by default: */ 678 return true; 679 } 680 681 bool UISession::powerUp() 682 { 683 /* Prepare map of the encrypted ids: */ 684 EncryptedMediumsMap encryptedPasswordIds; 685 foreach (const CMediumAttachment &attachment, machine().GetMediumAttachments()) 686 { 687 /* Acquire hard-drives only: */ 688 if (attachment.GetType() == KDeviceType_HardDisk) 689 { 690 /* Get attachment medium: */ 691 const CMedium medium = attachment.GetMedium(); 692 /* Append our map if this medium has encryption: */ 693 const QString strKeyId = medium.GetProperty("CRYPT/KeyId"); 694 if (!strKeyId.isNull()) 695 encryptedPasswordIds.insert(strKeyId, medium.GetId()); 696 } 697 } 698 /* Ask for disk encryption passwords if necessary: */ 699 EncryptionPasswordsMap encryptionPasswords; 700 if (!encryptedPasswordIds.isEmpty()) 701 { 702 QPointer<UIAddDiskEncryptionPasswordDialog> pDlg = 703 new UIAddDiskEncryptionPasswordDialog(machineLogic()->activeMachineWindow(), 704 encryptedPasswordIds); 705 if (pDlg->exec() == QDialog::Accepted) 706 encryptionPasswords = pDlg->encryptionPasswords(); 707 if (pDlg) 708 delete pDlg; 709 } 710 711 /* Power UP machine: */ 712 #ifdef VBOX_WITH_DEBUGGER_GUI 713 CProgress progress = vboxGlobal().isStartPausedEnabled() || vboxGlobal().isDebuggerAutoShowEnabled() ? 714 console().PowerUpPaused() : console().PowerUp(); 715 #else /* !VBOX_WITH_DEBUGGER_GUI */ 716 CProgress progress = console().PowerUp(); 717 #endif /* !VBOX_WITH_DEBUGGER_GUI */ 718 719 /* Check for immediate failure: */ 720 if (!console().isOk() || progress.isNull()) 721 { 722 if (vboxGlobal().showStartVMErrors()) 723 msgCenter().cannotStartMachine(console(), machineName()); 724 return false; 725 } 726 727 /* Guard progressbar warnings from auto-closing: */ 728 if (uimachine()->machineLogic()) 729 uimachine()->machineLogic()->setPreventAutoClose(true); 730 731 /* Show "Starting/Restoring" progress dialog: */ 732 if (isSaved()) 733 { 734 msgCenter().showModalProgressDialog(progress, machineName(), ":/progress_state_restore_90px.png", 0, 0); 735 /* After restoring from 'saved' state, machine-window(s) geometry should be adjusted: */ 736 machineLogic()->adjustMachineWindowsGeometry(); 737 } 738 else 739 msgCenter().showModalProgressDialog(progress, machineName(), ":/progress_start_90px.png"); 740 741 /* Check for progress failure: */ 742 if (!progress.isOk() || progress.GetResultCode() != 0) 743 { 744 if (vboxGlobal().showStartVMErrors()) 745 msgCenter().cannotStartMachine(progress, machineName()); 746 return false; 747 } 748 749 /* Add the disk encryption passwords: */ 750 if (!encryptionPasswords.isEmpty()) 751 { 752 foreach (const QString &strKey, encryptionPasswords.keys()) 753 { 754 console().AddDiskEncryptionPassword(strKey, encryptionPasswords.value(strKey), true); 755 if (!console().isOk()) 756 msgCenter().cannotAddDiskEncryptionPassword(console()); 757 } 758 } 759 760 /* Allow further auto-closing: */ 761 if (uimachine()->machineLogic()) 762 uimachine()->machineLogic()->setPreventAutoClose(false); 763 764 /* True by default: */ 765 return true; 766 } 767 768 bool UISession::saveState() 769 { 770 /* Prepare the saving progress: */ 771 CProgress progress = console().SaveState(); 772 if (console().isOk()) 773 { 774 /* Show the saving progress: */ 775 msgCenter().showModalProgressDialog(progress, machineName(), ":/progress_state_save_90px.png"); 776 if (!progress.isOk() || progress.GetResultCode() != 0) 777 { 778 /* Failed in progress: */ 779 msgCenter().cannotSaveMachineState(progress, machineName()); 780 return false; 781 } 782 } 783 else 784 { 785 /* Failed in console: */ 786 msgCenter().cannotSaveMachineState(console()); 787 return false; 788 } 789 /* Passed: */ 790 return true; 791 } 792 793 bool UISession::shutdown() 794 { 795 /* Send ACPI shutdown signal if possible: */ 796 console().PowerButton(); 797 if (!console().isOk()) 798 { 799 /* Failed in console: */ 800 msgCenter().cannotACPIShutdownMachine(console()); 801 return false; 802 } 803 /* Passed: */ 804 return true; 805 } 806 807 bool UISession::powerOff(bool fIncludingDiscard, bool &fServerCrashed) 808 { 809 /* Prepare the power-off progress: */ 810 CProgress progress = console().PowerDown(); 811 if (console().isOk()) 812 { 813 /* Show the power-off progress: */ 814 msgCenter().showModalProgressDialog(progress, machineName(), ":/progress_poweroff_90px.png"); 815 if (progress.isOk() && progress.GetResultCode() == 0) 816 { 817 /* Discard the current state if requested: */ 818 if (fIncludingDiscard) 819 return restoreCurrentSnapshot(); 820 } 821 else 822 { 823 /* Failed in progress: */ 824 msgCenter().cannotPowerDownMachine(progress, machineName()); 825 return false; 826 } 827 } 828 else 829 { 830 /* Check the machine state, it might be already gone: */ 831 if (!console().isNull()) 832 { 833 /* Failed in console: */ 834 COMResult res(console()); 835 /* This can happen if VBoxSVC is not running: */ 836 if (FAILED_DEAD_INTERFACE(res.rc())) 837 fServerCrashed = true; 838 else 839 msgCenter().cannotPowerDownMachine(console()); 840 return false; 841 } 842 } 843 /* Passed: */ 844 return true; 845 } 846 847 bool UISession::restoreCurrentSnapshot() 848 { 849 /* Prepare result: */ 850 bool fResult = false; 851 852 /* Simulate try-catch block: */ 853 do 854 { 855 /* Search for corresponding VM: */ 856 CVirtualBox vbox = vboxGlobal().virtualBox(); 857 const QString strMachineID = vboxGlobal().managedVMUuid(); 858 const CMachine mach = vbox.FindMachine(strMachineID); 859 if (!vbox.isOk() || mach.isNull()) 860 { 861 /* Unable to find VM: */ 862 msgCenter().cannotFindMachineById(vbox, strMachineID); 863 break; 864 } 865 866 /* Open a direct session to modify that VM: */ 867 CSession sess = vboxGlobal().openSession(vboxGlobal().managedVMUuid(), 868 vboxGlobal().isSeparateProcess() 869 ? KLockType_Write : KLockType_Shared); 870 if (sess.isNull()) 871 { 872 /* Unable to open session: */ 873 break; 874 } 875 876 /* Simulate try-catch block: */ 877 do 878 { 879 /* Acquire console for this session: */ 880 CConsole cons = sess.GetConsole(); 881 if (cons.isNull()) 882 { 883 /* Unable to acquire console: */ 884 break; 885 } 886 887 /* Prepare the snapshot-discard progress: */ 888 const CSnapshot snap = mach.GetCurrentSnapshot(); 889 CProgress prog = cons.RestoreSnapshot(snap); 890 if (!cons.isOk() || prog.isNull()) 891 { 892 /* Unable to restore snapshot: */ 893 msgCenter().cannotRestoreSnapshot(cons, snap.GetName(), machineName()); 894 break; 895 } 896 897 /* Show the snapshot-discard progress: */ 898 msgCenter().showModalProgressDialog(prog, mach.GetName(), ":/progress_snapshot_discard_90px.png"); 899 if (prog.GetResultCode() != 0) 900 { 901 /* Unable to restore snapshot: */ 902 msgCenter().cannotRestoreSnapshot(prog, snap.GetName(), mach.GetName()); 903 break; 904 } 905 906 /* Success: */ 907 fResult = true; 908 } 909 while (0); 910 911 /* Unlock machine finally: */ 912 sess.UnlockMachine(); 913 } 914 while (0); 915 916 /* Return result: */ 917 return fResult; 918 } 919 920 void UISession::closeRuntimeUI() 921 { 922 /* Start corresponding slot asynchronously: */ 923 emit sigCloseRuntimeUI(); 924 } 925 926 UIMachineLogic* UISession::machineLogic() const 927 { 928 return uimachine() ? uimachine()->machineLogic() : 0; 929 } 930 931 QWidget* UISession::mainMachineWindow() const 932 { 933 return machineLogic() ? machineLogic()->mainMachineWindow() : 0; 934 } 935 936 bool UISession::isVisualStateAllowed(UIVisualStateType state) const 937 { 938 return m_pMachine->isVisualStateAllowed(state); 939 } 940 941 void UISession::changeVisualState(UIVisualStateType visualStateType) 942 { 943 m_pMachine->asyncChangeVisualState(visualStateType); 944 } 945 946 bool UISession::setPause(bool fOn) 947 { 948 if (fOn) 949 console().Pause(); 950 else 951 console().Resume(); 952 953 bool ok = console().isOk(); 954 if (!ok) 955 { 956 if (fOn) 957 msgCenter().cannotPauseMachine(console()); 958 else 959 msgCenter().cannotResumeMachine(console()); 960 } 961 962 return ok; 963 } 964 965 void UISession::sltInstallGuestAdditionsFrom(const QString &strSource) 966 { 967 /* This flag indicates whether we want to do the usual .ISO mounting or not. 968 * First try updating the Guest Additions directly without mounting the .ISO. */ 969 bool fDoMount = false; 970 971 /* Auto-update in GUI currently is disabled. */ 972 #ifndef VBOX_WITH_ADDITIONS_AUTOUPDATE_UI 973 fDoMount = true; 974 #else /* VBOX_WITH_ADDITIONS_AUTOUPDATE_UI */ 975 QVector<KAdditionsUpdateFlag> aFlagsUpdate; 976 QVector<QString> aArgs; 977 CProgress progressInstall = guest().UpdateGuestAdditions(strSource, 978 aArgs, aFlagsUpdate); 979 bool fResult = guest().isOk(); 980 if (fResult) 981 { 982 msgCenter().showModalProgressDialog(progressInstall, tr("Updating Guest Additions"), 983 ":/progress_install_guest_additions_90px.png", 984 0, 500 /* 500ms delay. */); 985 if (progressInstall.GetCanceled()) 986 return; 987 988 HRESULT rc = progressInstall.GetResultCode(); 989 if (!progressInstall.isOk() || rc != S_OK) 990 { 991 /* If we got back a VBOX_E_NOT_SUPPORTED we don't complain (guest OS 992 * simply isn't supported yet), so silently fall back to "old" .ISO 993 * mounting method. */ 994 if ( !SUCCEEDED_WARNING(rc) 995 && rc != VBOX_E_NOT_SUPPORTED) 996 { 997 msgCenter().cannotUpdateGuestAdditions(progressInstall); 998 999 /* Log the error message in the release log. */ 1000 QString strErr = progressInstall.GetErrorInfo().GetText(); 1001 if (!strErr.isEmpty()) 1002 LogRel(("%s\n", strErr.toLatin1().constData())); 1003 } 1004 fDoMount = true; /* Since automatic updating failed, fall back to .ISO mounting. */ 1005 } 1006 } 1007 #endif /* VBOX_WITH_ADDITIONS_AUTOUPDATE_UI */ 1008 1009 /* Do we still want mounting? */ 1010 if (!fDoMount) 1011 return; 1012 1013 /* Open corresponding medium: */ 1014 QString strMediumID; 1015 CVirtualBox vbox = vboxGlobal().virtualBox(); 1016 CMedium image = vbox.OpenMedium(strSource, KDeviceType_DVD, KAccessMode_ReadWrite, false /* fForceNewUuid */); 1017 if (vbox.isOk() && !image.isNull()) 1018 strMediumID = image.GetId(); 1019 else 1020 { 1021 msgCenter().cannotOpenMedium(vbox, UIMediumType_DVD, strSource, mainMachineWindow()); 1022 return; 1023 } 1024 1025 /* Make sure GA medium ID is valid: */ 1026 AssertReturnVoid(!strMediumID.isNull()); 1027 1028 /* Searching for the first suitable controller/slot: */ 1029 QString strControllerName; 1030 LONG iCntPort = -1, iCntDevice = -1; 1031 foreach (const CStorageController &controller, machine().GetStorageControllers()) 1032 { 1033 foreach (const CMediumAttachment &attachment, machine().GetMediumAttachmentsOfController(controller.GetName())) 1034 { 1035 if (attachment.GetType() == KDeviceType_DVD) 1036 { 1037 strControllerName = controller.GetName(); 1038 iCntPort = attachment.GetPort(); 1039 iCntDevice = attachment.GetDevice(); 1040 break; 1041 } 1042 } 1043 if (!strControllerName.isNull()) 1044 break; 1045 } 1046 1047 /* Make sure suitable controller/slot were found: */ 1048 if (strControllerName.isNull()) 1049 { 1050 msgCenter().cannotMountGuestAdditions(machineName()); 1051 return; 1052 } 1053 1054 /* Try to find UIMedium among cached: */ 1055 UIMedium medium = vboxGlobal().medium(strMediumID); 1056 if (medium.isNull()) 1057 { 1058 /* Create new one if necessary: */ 1059 medium = UIMedium(image, UIMediumType_DVD, KMediumState_Created); 1060 vboxGlobal().createMedium(medium); 1061 } 1062 1063 /* Mount medium to corresponding controller/slot: */ 1064 machine().MountMedium(strControllerName, iCntPort, iCntDevice, medium.medium(), false /* force */); 1065 if (!machine().isOk()) 1066 { 1067 /* Ask for force mounting: */ 1068 if (msgCenter().cannotRemountMedium(machine(), medium, true /* mount? */, 1069 true /* retry? */, mainMachineWindow())) 1070 { 1071 /* Force mount medium to the predefined port/device: */ 1072 machine().MountMedium(strControllerName, iCntPort, iCntDevice, medium.medium(), true /* force */); 1073 if (!machine().isOk()) 1074 msgCenter().cannotRemountMedium(machine(), medium, true /* mount? */, 1075 false /* retry? */, mainMachineWindow()); 1076 } 1077 } 1078 } 1079 1080 void UISession::sltCloseRuntimeUI() 1081 { 1082 /* First, we have to hide any opened modal/popup widgets. 1083 * They then should unlock their event-loops synchronously. 1084 * If all such loops are unlocked, we can close Runtime UI: */ 1085 if (QWidget *pWidget = QApplication::activeModalWidget() ? 1086 QApplication::activeModalWidget() : 1087 QApplication::activePopupWidget() ? 1088 QApplication::activePopupWidget() : 0) 1089 { 1090 /* First we should try to close this widget: */ 1091 pWidget->close(); 1092 /* If widget rejected the 'close-event' we can 1093 * still hide it and hope it will behave correctly 1094 * and unlock his event-loop if any: */ 1095 if (!pWidget->isHidden()) 1096 pWidget->hide(); 1097 /* Restart this slot: */ 1098 emit sigCloseRuntimeUI(); 1099 return; 1100 } 1101 1102 /* Finally close the Runtime UI: */ 1103 UIMachine::destroy(); 1104 } 1105 1106 #ifdef RT_OS_DARWIN 1107 void UISession::sltHandleMenuBarConfigurationChange(const QString &strMachineID) 1108 { 1109 /* Skip unrelated machine IDs: */ 1110 if (vboxGlobal().managedVMUuid() != strMachineID) 1111 return; 1112 1113 /* Update Mac OS X menu-bar: */ 1114 updateMenu(); 1115 } 1116 #endif /* RT_OS_DARWIN */ 1117 1118 void UISession::sltMousePointerShapeChange(bool fVisible, bool fAlpha, QPoint hotCorner, QSize size, QVector<uint8_t> shape) 1119 { 1120 /* In case of shape data is present: */ 1121 if (shape.size() > 0) 1122 { 1123 /* We are ignoring visibility flag: */ 1124 m_fIsHidingHostPointer = false; 1125 1126 /* And updating current cursor shape: */ 1127 setPointerShape(shape.data(), fAlpha, 1128 hotCorner.x(), hotCorner.y(), 1129 size.width(), size.height()); 1130 } 1131 /* In case of shape data is NOT present: */ 1132 else 1133 { 1134 /* Remember if we should hide the cursor: */ 1135 m_fIsHidingHostPointer = !fVisible; 1136 } 1137 1138 /* Notify listeners about mouse capability changed: */ 1139 emit sigMousePointerShapeChange(); 1140 1141 } 1142 1143 void UISession::sltMouseCapabilityChange(bool fSupportsAbsolute, bool fSupportsRelative, bool fSupportsMultiTouch, bool fNeedsHostCursor) 1144 { 1145 LogRelFlow(("UISession::sltMouseCapabilityChange: " 1146 "Supports absolute: %s, Supports relative: %s, " 1147 "Supports multi-touch: %s, Needs host cursor: %s\n", 1148 fSupportsAbsolute ? "TRUE" : "FALSE", fSupportsRelative ? "TRUE" : "FALSE", 1149 fSupportsMultiTouch ? "TRUE" : "FALSE", fNeedsHostCursor ? "TRUE" : "FALSE")); 1150 1151 /* Check if something had changed: */ 1152 if ( m_fIsMouseSupportsAbsolute != fSupportsAbsolute 1153 || m_fIsMouseSupportsRelative != fSupportsRelative 1154 || m_fIsMouseSupportsMultiTouch != fSupportsMultiTouch 1155 || m_fIsMouseHostCursorNeeded != fNeedsHostCursor) 1156 { 1157 /* Store new data: */ 1158 m_fIsMouseSupportsAbsolute = fSupportsAbsolute; 1159 m_fIsMouseSupportsRelative = fSupportsRelative; 1160 m_fIsMouseSupportsMultiTouch = fSupportsMultiTouch; 1161 m_fIsMouseHostCursorNeeded = fNeedsHostCursor; 1162 1163 /* Notify listeners about mouse capability changed: */ 1164 emit sigMouseCapabilityChange(); 1165 } 1166 } 1167 1168 void UISession::sltKeyboardLedsChangeEvent(bool fNumLock, bool fCapsLock, bool fScrollLock) 1169 { 1170 /* Check if something had changed: */ 1171 if ( m_fNumLock != fNumLock 1172 || m_fCapsLock != fCapsLock 1173 || m_fScrollLock != fScrollLock) 1174 { 1175 /* Store new num lock data: */ 1176 if (m_fNumLock != fNumLock) 1177 { 1178 m_fNumLock = fNumLock; 1179 m_uNumLockAdaptionCnt = 2; 1180 } 1181 1182 /* Store new caps lock data: */ 1183 if (m_fCapsLock != fCapsLock) 1184 { 1185 m_fCapsLock = fCapsLock; 1186 m_uCapsLockAdaptionCnt = 2; 1187 } 1188 1189 /* Store new scroll lock data: */ 1190 if (m_fScrollLock != fScrollLock) 1191 { 1192 m_fScrollLock = fScrollLock; 1193 } 1194 1195 /* Notify listeners about mouse capability changed: */ 1196 emit sigKeyboardLedsChange(); 1197 } 1198 } 1199 1200 void UISession::sltStateChange(KMachineState state) 1201 { 1202 /* Check if something had changed: */ 1203 if (m_machineState != state) 1204 { 1205 /* Store new data: */ 1206 m_machineStatePrevious = m_machineState; 1207 m_machineState = state; 1208 1209 /* Notify listeners about machine state changed: */ 1210 emit sigMachineStateChange(); 1211 } 1212 } 1213 1214 void UISession::sltVRDEChange() 1215 { 1216 /* Make sure VRDE server is present: */ 1217 const CVRDEServer server = machine().GetVRDEServer(); 1218 AssertMsgReturnVoid(machine().isOk() && !server.isNull(), 1219 ("VRDE server should NOT be null!\n")); 1220 1221 /* Check/Uncheck VRDE Server action depending on feature status: */ 1222 actionPool()->action(UIActionIndexRT_M_View_T_VRDEServer)->blockSignals(true); 1223 actionPool()->action(UIActionIndexRT_M_View_T_VRDEServer)->setChecked(server.GetEnabled()); 1224 actionPool()->action(UIActionIndexRT_M_View_T_VRDEServer)->blockSignals(false); 1225 1226 /* Notify listeners about VRDE change: */ 1227 emit sigVRDEChange(); 1228 } 1229 1230 void UISession::sltVideoCaptureChange() 1231 { 1232 /* Check/Uncheck Video Capture action depending on feature status: */ 1233 actionPool()->action(UIActionIndexRT_M_View_M_VideoCapture_T_Start)->blockSignals(true); 1234 actionPool()->action(UIActionIndexRT_M_View_M_VideoCapture_T_Start)->setChecked(machine().GetVideoCaptureEnabled()); 1235 actionPool()->action(UIActionIndexRT_M_View_M_VideoCapture_T_Start)->blockSignals(false); 1236 1237 /* Notify listeners about Video Capture change: */ 1238 emit sigVideoCaptureChange(); 1239 } 1240 1241 void UISession::sltGuestMonitorChange(KGuestMonitorChangedEventType changeType, ulong uScreenId, QRect screenGeo) 1242 { 1243 /* Ignore KGuestMonitorChangedEventType_NewOrigin change event: */ 1244 if (changeType == KGuestMonitorChangedEventType_NewOrigin) 1245 return; 1246 /* Ignore KGuestMonitorChangedEventType_Disabled event for primary screen: */ 1247 AssertMsg(countOfVisibleWindows() > 0, ("All machine windows are hidden!")); 1248 if (changeType == KGuestMonitorChangedEventType_Disabled && uScreenId == 0) 1249 return; 1250 1251 /* Process KGuestMonitorChangedEventType_Enabled change event: */ 1252 if ( !isScreenVisible(uScreenId) 1253 && changeType == KGuestMonitorChangedEventType_Enabled) 1254 setScreenVisible(uScreenId, true); 1255 /* Process KGuestMonitorChangedEventType_Disabled change event: */ 1256 else if ( isScreenVisible(uScreenId) 1257 && changeType == KGuestMonitorChangedEventType_Disabled) 1258 setScreenVisible(uScreenId, false); 1259 1260 /* Notify listeners about the change: */ 1261 emit sigGuestMonitorChange(changeType, uScreenId, screenGeo); 1262 } 1263 1264 #ifdef RT_OS_DARWIN 1265 /** 1266 * MacOS X: Restarts display-reconfiguration watchdog timer from the beginning. 1267 * @note Watchdog is trying to determine display reconfiguration in 1268 * UISession::sltCheckIfHostDisplayChanged() slot every 500ms for 40 tries. 1269 */ 1270 void UISession::sltHandleHostDisplayAboutToChange() 1271 { 1272 LogRelFlow(("UISession::sltHandleHostDisplayAboutToChange()\n")); 1273 1274 if (m_pWatchdogDisplayChange->isActive()) 1275 m_pWatchdogDisplayChange->stop(); 1276 m_pWatchdogDisplayChange->setProperty("tryNumber", 1); 1277 m_pWatchdogDisplayChange->start(); 1278 } 1279 1280 /** 1281 * MacOS X: Determines display reconfiguration. 1282 * @note Calls for UISession::sltHandleHostScreenCountChange() if screen count changed. 1283 * @note Calls for UISession::sltHandleHostScreenGeometryChange() if screen geometry changed. 1284 */ 1285 void UISession::sltCheckIfHostDisplayChanged() 1286 { 1287 LogRelFlow(("UISession::sltCheckIfHostDisplayChanged()\n")); 1288 1289 /* Acquire desktop wrapper: */ 1290 QDesktopWidget *pDesktop = QApplication::desktop(); 1291 1292 /* Check if display count changed: */ 1293 if (pDesktop->screenCount() != m_hostScreens.size()) 1294 { 1295 /* Reset watchdog: */ 1296 m_pWatchdogDisplayChange->setProperty("tryNumber", 0); 1297 /* Notify listeners about screen-count changed: */ 1298 return sltHandleHostScreenCountChange(); 1299 } 1300 else 1301 { 1302 /* Check if at least one display geometry changed: */ 1303 for (int iScreenIndex = 0; iScreenIndex < pDesktop->screenCount(); ++iScreenIndex) 1304 { 1305 if (pDesktop->screenGeometry(iScreenIndex) != m_hostScreens.at(iScreenIndex)) 1306 { 1307 /* Reset watchdog: */ 1308 m_pWatchdogDisplayChange->setProperty("tryNumber", 0); 1309 /* Notify listeners about screen-geometry changed: */ 1310 return sltHandleHostScreenGeometryChange(); 1311 } 1312 } 1313 } 1314 1315 /* Check if watchdog expired, restart if not: */ 1316 int cTryNumber = m_pWatchdogDisplayChange->property("tryNumber").toInt(); 1317 if (cTryNumber > 0 && cTryNumber < 40) 1318 { 1319 /* Restart watchdog again: */ 1320 m_pWatchdogDisplayChange->setProperty("tryNumber", ++cTryNumber); 1321 m_pWatchdogDisplayChange->start(); 1322 } 1323 else 1324 { 1325 /* Reset watchdog: */ 1326 m_pWatchdogDisplayChange->setProperty("tryNumber", 0); 1327 } 1328 } 1329 #endif /* RT_OS_DARWIN */ 1330 1331 void UISession::sltHandleHostScreenCountChange() 1332 { 1333 LogRelFlow(("UISession: Host-screen count changed.\n")); 1334 1335 /* Recache display data: */ 1336 updateHostScreenData(); 1337 1338 /* Notify current machine-logic: */ 1339 emit sigHostScreenCountChange(); 1340 } 1341 1342 void UISession::sltHandleHostScreenGeometryChange() 1343 { 1344 LogRelFlow(("UISession: Host-screen geometry changed.\n")); 1345 1346 /* Recache display data: */ 1347 updateHostScreenData(); 1348 1349 /* Notify current machine-logic: */ 1350 emit sigHostScreenGeometryChange(); 1351 } 1352 1353 void UISession::sltHandleHostScreenAvailableAreaChange() 1354 { 1355 LogRelFlow(("UISession: Host-screen available-area changed.\n")); 1356 1357 /* Notify current machine-logic: */ 1358 emit sigHostScreenAvailableAreaChange(); 1359 } 1360 1361 void UISession::sltAdditionsChange() 1362 { 1363 /* Variable flags: */ 1364 ULONG ulGuestAdditionsRunLevel = guest().GetAdditionsRunLevel(); 1365 LONG64 lLastUpdatedIgnored; 1366 bool fIsGuestSupportsGraphics = guest().GetFacilityStatus(KAdditionsFacilityType_Graphics, lLastUpdatedIgnored) 1367 == KAdditionsFacilityStatus_Active; 1368 bool fIsGuestSupportsSeamless = guest().GetFacilityStatus(KAdditionsFacilityType_Seamless, lLastUpdatedIgnored) 1369 == KAdditionsFacilityStatus_Active; 1370 /* Check if something had changed: */ 1371 if (m_ulGuestAdditionsRunLevel != ulGuestAdditionsRunLevel || 1372 m_fIsGuestSupportsGraphics != fIsGuestSupportsGraphics || 1373 m_fIsGuestSupportsSeamless != fIsGuestSupportsSeamless) 1374 { 1375 /* Store new data: */ 1376 m_ulGuestAdditionsRunLevel = ulGuestAdditionsRunLevel; 1377 m_fIsGuestSupportsGraphics = fIsGuestSupportsGraphics; 1378 m_fIsGuestSupportsSeamless = fIsGuestSupportsSeamless; 1379 1380 /* Notify listeners about guest additions state really changed: */ 1381 emit sigAdditionsStateActualChange(); 1382 } 1383 1384 /* Notify listeners about guest additions state event came: */ 1385 emit sigAdditionsStateChange(); 1386 } 1387 1388 UISession::UISession(UIMachine *pMachine) 1389 : QObject(pMachine) 1390 /* Base variables: */ 1391 , m_pMachine(pMachine) 1392 , m_pActionPool(0) 1393 #ifdef Q_WS_MAC 1394 , m_pMenuBar(0) 1395 #endif /* Q_WS_MAC */ 1396 /* Common variables: */ 1397 , m_machineStatePrevious(KMachineState_Null) 1398 , m_machineState(KMachineState_Null) 1399 #ifndef Q_WS_MAC 1400 , m_pMachineWindowIcon(0) 1401 #endif /* !Q_WS_MAC */ 1402 , m_mouseCapturePolicy(MouseCapturePolicy_Default) 1403 , m_guruMeditationHandlerType(GuruMeditationHandlerType_Default) 1404 , m_hiDPIOptimizationType(HiDPIOptimizationType_None) 1405 , m_requestedVisualStateType(UIVisualStateType_Invalid) 1406 #ifdef Q_WS_WIN 1407 , m_alphaCursor(0) 1408 #endif /* Q_WS_WIN */ 1409 #ifdef Q_WS_MAC 1410 , m_pWatchdogDisplayChange(0) 1411 #endif /* Q_WS_MAC */ 1412 , m_defaultCloseAction(MachineCloseAction_Invalid) 1413 , m_restrictedCloseActions(MachineCloseAction_Invalid) 1414 , m_fAllCloseActionsRestricted(false) 1415 /* Common flags: */ 1416 , m_fInitialized(false) 1417 , m_fIsFirstTimeStarted(false) 1418 , m_fIsGuestResizeIgnored(false) 1419 , m_fIsAutoCaptureDisabled(false) 1420 /* Guest additions flags: */ 1421 , m_ulGuestAdditionsRunLevel(0) 1422 , m_fIsGuestSupportsGraphics(false) 1423 , m_fIsGuestSupportsSeamless(false) 1424 /* Mouse flags: */ 1425 , m_fNumLock(false) 1426 , m_fCapsLock(false) 1427 , m_fScrollLock(false) 1428 , m_uNumLockAdaptionCnt(2) 1429 , m_uCapsLockAdaptionCnt(2) 1430 /* Mouse flags: */ 1431 , m_fIsMouseSupportsAbsolute(false) 1432 , m_fIsMouseSupportsRelative(false) 1433 , m_fIsMouseSupportsMultiTouch(false) 1434 , m_fIsMouseHostCursorNeeded(false) 1435 , m_fIsMouseCaptured(false) 1436 , m_fIsMouseIntegrated(true) 1437 , m_fIsValidPointerShapePresent(false) 1438 , m_fIsHidingHostPointer(true) 1439 { 1440 } 1441 1442 UISession::~UISession() 1443 { 1444 } 1445 1446 bool UISession::prepare() 1447 { 1448 /* Prepare session: */ 1449 if (!prepareSession()) 1450 return false; 1451 1452 /* Prepare actions: */ 1453 prepareActions(); 1454 1455 /* Prepare connections: */ 1456 prepareConnections(); 1457 1458 /* Prepare console event-handlers: */ 1459 prepareConsoleEventHandlers(); 1460 1461 /* Prepare screens: */ 1462 prepareScreens(); 1463 1464 /* Prepare framebuffers: */ 1465 prepareFramebuffers(); 1466 1467 /* Load settings: */ 1468 loadSessionSettings(); 1469 1470 #ifdef VBOX_GUI_WITH_KEYS_RESET_HANDLER 1471 struct sigaction sa; 1472 sa.sa_sigaction = &signalHandlerSIGUSR1; 1473 sigemptyset(&sa.sa_mask); 1474 sa.sa_flags = SA_RESTART | SA_SIGINFO; 1475 sigaction(SIGUSR1, &sa, NULL); 1476 #endif /* VBOX_GUI_WITH_KEYS_RESET_HANDLER */ 1477 1478 /* True by default: */ 1479 return true; 1480 } 1481 1482 bool UISession::prepareSession() 1483 { 1484 /* Open session: */ 1485 m_session = vboxGlobal().openSession(vboxGlobal().managedVMUuid(), 1486 vboxGlobal().isSeparateProcess() 1487 ? KLockType_Shared : KLockType_VM); 1488 if (m_session.isNull()) 1489 return false; 1490 1491 /* Get machine: */ 1492 m_machine = m_session.GetMachine(); 1493 if (m_machine.isNull()) 1494 return false; 1495 1496 /* Get console: */ 1497 m_console = m_session.GetConsole(); 1498 if (m_console.isNull()) 1499 return false; 1500 1501 /* Get display: */ 1502 m_display = m_console.GetDisplay(); 1503 if (m_display.isNull()) 1504 return false; 1505 1506 /* Get guest: */ 1507 m_guest = m_console.GetGuest(); 1508 if (m_guest.isNull()) 1509 return false; 1510 1511 /* Get mouse: */ 1512 m_mouse = m_console.GetMouse(); 1513 if (m_mouse.isNull()) 1514 return false; 1515 1516 /* Get keyboard: */ 1517 m_keyboard = m_console.GetKeyboard(); 1518 if (m_keyboard.isNull()) 1519 return false; 1520 1521 /* Get debugger: */ 1522 m_debugger = m_console.GetDebugger(); 1523 if (m_debugger.isNull()) 1524 return false; 1525 1526 /* Update machine-name: */ 1527 m_strMachineName = machine().GetName(); 1528 1529 /* Update machine-state: */ 1530 m_machineState = machine().GetState(); 1531 1532 /* True by default: */ 1533 return true; 1534 } 1535 1536 void UISession::prepareActions() 1537 { 1538 /* Create action-pool: */ 1539 m_pActionPool = UIActionPool::create(UIActionPoolType_Runtime); 1540 AssertPtrReturnVoid(actionPool()); 1541 { 1542 /* Configure action-pool: */ 1543 actionPool()->toRuntime()->setSession(this); 1544 1545 /* Get host: */ 1546 const CHost host = vboxGlobal().host(); 1547 UIExtraDataMetaDefs::RuntimeMenuViewActionType restrictionForView = UIExtraDataMetaDefs::RuntimeMenuViewActionType_Invalid; 1548 UIExtraDataMetaDefs::RuntimeMenuDevicesActionType restrictionForDevices = UIExtraDataMetaDefs::RuntimeMenuDevicesActionType_Invalid; 1549 1550 /* VRDE server stuff: */ 1551 { 1552 /* Initialize 'View' menu: */ 1553 const CVRDEServer server = machine().GetVRDEServer(); 1554 if (server.isNull()) 1555 restrictionForView = (UIExtraDataMetaDefs::RuntimeMenuViewActionType)(restrictionForView | UIExtraDataMetaDefs::RuntimeMenuViewActionType_VRDEServer); 1556 } 1557 1558 /* Storage stuff: */ 1559 { 1560 /* Initialize CD/FD menus: */ 1561 int iDevicesCountCD = 0; 1562 int iDevicesCountFD = 0; 1563 foreach (const CMediumAttachment &attachment, machine().GetMediumAttachments()) 1564 { 1565 if (attachment.GetType() == KDeviceType_DVD) 1566 ++iDevicesCountCD; 1567 if (attachment.GetType() == KDeviceType_Floppy) 1568 ++iDevicesCountFD; 1569 } 1570 QAction *pOpticalDevicesMenu = actionPool()->action(UIActionIndexRT_M_Devices_M_OpticalDevices); 1571 QAction *pFloppyDevicesMenu = actionPool()->action(UIActionIndexRT_M_Devices_M_FloppyDevices); 1572 pOpticalDevicesMenu->setData(iDevicesCountCD); 1573 pFloppyDevicesMenu->setData(iDevicesCountFD); 1574 if (!iDevicesCountCD) 1575 restrictionForDevices = (UIExtraDataMetaDefs::RuntimeMenuDevicesActionType)(restrictionForDevices | UIExtraDataMetaDefs::RuntimeMenuDevicesActionType_OpticalDevices); 1576 if (!iDevicesCountFD) 1577 restrictionForDevices = (UIExtraDataMetaDefs::RuntimeMenuDevicesActionType)(restrictionForDevices | UIExtraDataMetaDefs::RuntimeMenuDevicesActionType_FloppyDevices); 1578 } 1579 1580 /* Network stuff: */ 1581 { 1582 /* Initialize Network menu: */ 1583 bool fAtLeastOneAdapterActive = false; 1584 const KChipsetType chipsetType = machine().GetChipsetType(); 1585 ULONG uSlots = vboxGlobal().virtualBox().GetSystemProperties().GetMaxNetworkAdapters(chipsetType); 1586 for (ULONG uSlot = 0; uSlot < uSlots; ++uSlot) 1587 { 1588 const CNetworkAdapter &adapter = machine().GetNetworkAdapter(uSlot); 1589 if (adapter.GetEnabled()) 1590 { 1591 fAtLeastOneAdapterActive = true; 1592 break; 1593 } 1594 } 1595 if (!fAtLeastOneAdapterActive) 1596 restrictionForDevices = (UIExtraDataMetaDefs::RuntimeMenuDevicesActionType)(restrictionForDevices | UIExtraDataMetaDefs::RuntimeMenuDevicesActionType_Network); 1597 } 1598 1599 /* USB stuff: */ 1600 { 1601 /* Check whether there is at least one USB controller with an available proxy. */ 1602 const bool fUSBEnabled = !machine().GetUSBDeviceFilters().isNull() 1603 && !machine().GetUSBControllers().isEmpty() 1604 && machine().GetUSBProxyAvailable(); 1605 if (!fUSBEnabled) 1606 restrictionForDevices = (UIExtraDataMetaDefs::RuntimeMenuDevicesActionType)(restrictionForDevices | UIExtraDataMetaDefs::RuntimeMenuDevicesActionType_USBDevices); 1607 } 1608 1609 /* WebCams stuff: */ 1610 { 1611 /* Check whether there is an accessible video input devices pool: */ 1612 host.GetVideoInputDevices(); 1613 const bool fWebCamsEnabled = host.isOk() && !machine().GetUSBControllers().isEmpty(); 1614 if (!fWebCamsEnabled) 1615 restrictionForDevices = (UIExtraDataMetaDefs::RuntimeMenuDevicesActionType)(restrictionForDevices | UIExtraDataMetaDefs::RuntimeMenuDevicesActionType_WebCams); 1616 } 1617 1618 /* Apply cumulative restriction for 'View' menu: */ 1619 actionPool()->toRuntime()->setRestrictionForMenuView(UIActionRestrictionLevel_Session, restrictionForView); 1620 /* Apply cumulative restriction for 'Devices' menu: */ 1621 actionPool()->toRuntime()->setRestrictionForMenuDevices(UIActionRestrictionLevel_Session, restrictionForDevices); 1622 1623 #ifdef Q_WS_MAC 1624 /* Create Mac OS X menu-bar: */ 1625 m_pMenuBar = new UIMenuBar; 1626 AssertPtrReturnVoid(m_pMenuBar); 1627 { 1628 /* Configure Mac OS X menu-bar: */ 1629 connect(gEDataManager, SIGNAL(sigMenuBarConfigurationChange(const QString&)), 1630 this, SLOT(sltHandleMenuBarConfigurationChange(const QString&))); 1631 /* Update Mac OS X menu-bar: */ 1632 updateMenu(); 1633 } 1634 #endif /* Q_WS_MAC */ 1635 } 1636 } 1637 1638 void UISession::prepareConnections() 1639 { 1640 connect(this, SIGNAL(sigInitialized()), this, SLOT(sltMarkInitialized())); 1641 connect(this, SIGNAL(sigCloseRuntimeUI()), this, SLOT(sltCloseRuntimeUI())); 1642 1643 #ifdef Q_WS_MAC 1644 /* Install native display reconfiguration callback: */ 1645 CGDisplayRegisterReconfigurationCallback(cgDisplayReconfigurationCallback, this); 1646 #else /* !Q_WS_MAC */ 1647 /* Install Qt display reconfiguration callbacks: */ 1648 connect(QApplication::desktop(), SIGNAL(screenCountChanged(int)), 1649 this, SLOT(sltHandleHostScreenCountChange())); 1650 connect(QApplication::desktop(), SIGNAL(resized(int)), 1651 this, SLOT(sltHandleHostScreenGeometryChange())); 1652 connect(QApplication::desktop(), SIGNAL(workAreaResized(int)), 1653 this, SLOT(sltHandleHostScreenAvailableAreaChange())); 1654 #endif /* !Q_WS_MAC */ 1655 } 1656 1657 void UISession::prepareConsoleEventHandlers() 1658 { 1659 /* Create console event-handler: */ 1660 UIConsoleEventHandler::create(this); 1661 1662 /* Add console event connections: */ 1663 connect(gConsoleEvents, SIGNAL(sigMousePointerShapeChange(bool, bool, QPoint, QSize, QVector<uint8_t>)), 1664 this, SLOT(sltMousePointerShapeChange(bool, bool, QPoint, QSize, QVector<uint8_t>))); 1665 1666 connect(gConsoleEvents, SIGNAL(sigMouseCapabilityChange(bool, bool, bool, bool)), 1667 this, SLOT(sltMouseCapabilityChange(bool, bool, bool, bool))); 1668 1669 connect(gConsoleEvents, SIGNAL(sigKeyboardLedsChangeEvent(bool, bool, bool)), 1670 this, SLOT(sltKeyboardLedsChangeEvent(bool, bool, bool))); 1671 1672 connect(gConsoleEvents, SIGNAL(sigStateChange(KMachineState)), 1673 this, SLOT(sltStateChange(KMachineState))); 1674 1675 connect(gConsoleEvents, SIGNAL(sigAdditionsChange()), 1676 this, SLOT(sltAdditionsChange())); 1677 1678 connect(gConsoleEvents, SIGNAL(sigVRDEChange()), 1679 this, SLOT(sltVRDEChange())); 1680 1681 connect(gConsoleEvents, SIGNAL(sigVideoCaptureChange()), 1682 this, SLOT(sltVideoCaptureChange())); 1683 1684 connect(gConsoleEvents, SIGNAL(sigNetworkAdapterChange(CNetworkAdapter)), 1685 this, SIGNAL(sigNetworkAdapterChange(CNetworkAdapter))); 1686 1687 connect(gConsoleEvents, SIGNAL(sigMediumChange(CMediumAttachment)), 1688 this, SIGNAL(sigMediumChange(CMediumAttachment))); 1689 1690 connect(gConsoleEvents, SIGNAL(sigUSBControllerChange()), 1691 this, SIGNAL(sigUSBControllerChange())); 1692 1693 connect(gConsoleEvents, SIGNAL(sigUSBDeviceStateChange(CUSBDevice, bool, CVirtualBoxErrorInfo)), 1694 this, SIGNAL(sigUSBDeviceStateChange(CUSBDevice, bool, CVirtualBoxErrorInfo))); 1695 1696 connect(gConsoleEvents, SIGNAL(sigSharedFolderChange()), 1697 this, SIGNAL(sigSharedFolderChange())); 1698 1699 connect(gConsoleEvents, SIGNAL(sigRuntimeError(bool, QString, QString)), 1700 this, SIGNAL(sigRuntimeError(bool, QString, QString))); 1701 1702 #ifdef Q_WS_MAC 1703 connect(gConsoleEvents, SIGNAL(sigShowWindow()), 1704 this, SIGNAL(sigShowWindows()), Qt::QueuedConnection); 1705 #endif /* Q_WS_MAC */ 1706 1707 connect(gConsoleEvents, SIGNAL(sigCPUExecutionCapChange()), 1708 this, SIGNAL(sigCPUExecutionCapChange())); 1709 1710 connect(gConsoleEvents, SIGNAL(sigGuestMonitorChange(KGuestMonitorChangedEventType, ulong, QRect)), 1711 this, SLOT(sltGuestMonitorChange(KGuestMonitorChangedEventType, ulong, QRect))); 1712 } 1713 1714 void UISession::prepareScreens() 1715 { 1716 /* Recache display data: */ 1717 updateHostScreenData(); 1718 1719 #ifdef Q_WS_MAC 1720 /* Prepare display-change watchdog: */ 1721 m_pWatchdogDisplayChange = new QTimer(this); 1722 { 1723 m_pWatchdogDisplayChange->setInterval(500); 1724 m_pWatchdogDisplayChange->setSingleShot(true); 1725 connect(m_pWatchdogDisplayChange, SIGNAL(timeout()), 1726 this, SLOT(sltCheckIfHostDisplayChanged())); 1727 } 1728 #endif /* Q_WS_MAC */ 1729 1730 /* Prepare initial screen visibility status: */ 1731 m_monitorVisibilityVector.resize(machine().GetMonitorCount()); 1732 m_monitorVisibilityVector.fill(false); 1733 m_monitorVisibilityVector[0] = true; 1734 1735 /* If machine is in 'saved' state: */ 1736 if (isSaved()) 1737 { 1738 /* Update screen visibility status from saved-state: */ 1739 for (int iScreenIndex = 0; iScreenIndex < m_monitorVisibilityVector.size(); ++iScreenIndex) 1740 { 1741 BOOL fEnabled = true; 1742 ULONG uGuestOriginX = 0, uGuestOriginY = 0, uGuestWidth = 0, uGuestHeight = 0; 1743 machine().QuerySavedGuestScreenInfo(iScreenIndex, 1744 uGuestOriginX, uGuestOriginY, 1745 uGuestWidth, uGuestHeight, fEnabled); 1746 m_monitorVisibilityVector[iScreenIndex] = fEnabled; 1747 } 1748 /* And make sure at least one of them is visible (primary if others are hidden): */ 1749 if (countOfVisibleWindows() < 1) 1750 m_monitorVisibilityVector[0] = true; 1751 } 1752 else if (vboxGlobal().isSeparateProcess()) 1753 { 1754 /* Update screen visibility status from display directly: */ 1755 for (int iScreenIndex = 0; iScreenIndex < m_monitorVisibilityVector.size(); ++iScreenIndex) 1756 { 1757 KGuestMonitorStatus enmStatus = KGuestMonitorStatus_Disabled; 1758 ULONG uGuestWidth = 0, uGuestHeight = 0, uBpp = 0; 1759 LONG iGuestOriginX = 0, iGuestOriginY = 0; 1760 display().GetScreenResolution(iScreenIndex, 1761 uGuestWidth, uGuestHeight, uBpp, 1762 iGuestOriginX, iGuestOriginY, enmStatus); 1763 m_monitorVisibilityVector[iScreenIndex] = (enmStatus == KGuestMonitorStatus_Enabled); 1764 } 1765 /* And make sure at least one of them is visible (primary if others are hidden): */ 1766 if (countOfVisibleWindows() < 1) 1767 m_monitorVisibilityVector[0] = true; 1768 } 1769 } 1770 1771 void UISession::prepareFramebuffers() 1772 { 1773 /* Each framebuffer will be really prepared on first UIMachineView creation: */ 1774 m_frameBufferVector.resize(machine().GetMonitorCount()); 1775 } 1776 1777 void UISession::loadSessionSettings() 1778 { 1779 /* Load extra-data settings: */ 1780 { 1781 /* Get machine ID: */ 1782 const QString strMachineID = vboxGlobal().managedVMUuid(); 1783 1784 #ifndef Q_WS_MAC 1785 /* Load/prepare user's machine-window icon: */ 1786 QIcon icon; 1787 foreach (const QString &strIconName, gEDataManager->machineWindowIconNames(strMachineID)) 1788 if (!strIconName.isEmpty()) 1789 icon.addFile(strIconName); 1790 if (!icon.isNull()) 1791 m_pMachineWindowIcon = new QIcon(icon); 1792 1793 /* Load user's machine-window name postfix: */ 1794 m_strMachineWindowNamePostfix = gEDataManager->machineWindowNamePostfix(strMachineID); 1795 #endif /* !Q_WS_MAC */ 1796 1797 /* Determine mouse-capture policy: */ 1798 m_mouseCapturePolicy = gEDataManager->mouseCapturePolicy(strMachineID); 1799 1800 /* Determine Guru Meditation handler type: */ 1801 m_guruMeditationHandlerType = gEDataManager->guruMeditationHandlerType(strMachineID); 1802 1803 /* Determine HiDPI optimization type: */ 1804 m_hiDPIOptimizationType = gEDataManager->hiDPIOptimizationType(strMachineID); 1805 1806 /* Is there should be First RUN Wizard? */ 1807 m_fIsFirstTimeStarted = gEDataManager->machineFirstTimeStarted(strMachineID); 1808 1809 /* Should guest autoresize? */ 1810 QAction *pGuestAutoresizeSwitch = actionPool()->action(UIActionIndexRT_M_View_T_GuestAutoresize); 1811 pGuestAutoresizeSwitch->setChecked(gEDataManager->guestScreenAutoResizeEnabled(strMachineID)); 1812 1813 #ifndef Q_WS_MAC 1814 /* Menu-bar options: */ 1815 { 1816 const bool fEnabledGlobally = !vboxGlobal().settings().isFeatureActive("noMenuBar"); 1817 const bool fEnabledForMachine = gEDataManager->menuBarEnabled(strMachineID); 1818 const bool fEnabled = fEnabledGlobally && fEnabledForMachine; 1819 QAction *pActionMenuBarSettings = actionPool()->action(UIActionIndexRT_M_View_M_MenuBar_S_Settings); 1820 pActionMenuBarSettings->setEnabled(fEnabled); 1821 QAction *pActionMenuBarSwitch = actionPool()->action(UIActionIndexRT_M_View_M_MenuBar_T_Visibility); 1822 pActionMenuBarSwitch->blockSignals(true); 1823 pActionMenuBarSwitch->setChecked(fEnabled); 1824 pActionMenuBarSwitch->blockSignals(false); 1825 } 1826 #endif /* !Q_WS_MAC */ 1827 1828 /* Status-bar options: */ 1829 { 1830 const bool fEnabledGlobally = !vboxGlobal().settings().isFeatureActive("noStatusBar"); 1831 const bool fEnabledForMachine = gEDataManager->statusBarEnabled(strMachineID); 1832 const bool fEnabled = fEnabledGlobally && fEnabledForMachine; 1833 QAction *pActionStatusBarSettings = actionPool()->action(UIActionIndexRT_M_View_M_StatusBar_S_Settings); 1834 pActionStatusBarSettings->setEnabled(fEnabled); 1835 QAction *pActionStatusBarSwitch = actionPool()->action(UIActionIndexRT_M_View_M_StatusBar_T_Visibility); 1836 pActionStatusBarSwitch->blockSignals(true); 1837 pActionStatusBarSwitch->setChecked(fEnabled); 1838 pActionStatusBarSwitch->blockSignals(false); 1839 } 1840 1841 /* Input options: */ 1842 actionPool()->action(UIActionIndexRT_M_Input_M_Mouse_T_Integration)->setChecked(isMouseIntegrated()); 1843 1844 /* What is the default close action and the restricted are? */ 1845 m_defaultCloseAction = gEDataManager->defaultMachineCloseAction(strMachineID); 1846 m_restrictedCloseActions = gEDataManager->restrictedMachineCloseActions(strMachineID); 1847 m_fAllCloseActionsRestricted = (!vboxGlobal().isSeparateProcess() || (m_restrictedCloseActions & MachineCloseAction_Detach)) 1848 && (m_restrictedCloseActions & MachineCloseAction_SaveState) 1849 && (m_restrictedCloseActions & MachineCloseAction_Shutdown) 1850 && (m_restrictedCloseActions & MachineCloseAction_PowerOff); 1851 // Close VM Dialog hides PowerOff_RestoringSnapshot implicitly if PowerOff is hidden.. 1852 // && (m_restrictedCloseActions & MachineCloseAction_PowerOff_RestoringSnapshot); 1853 } 1854 } 1855 1856 void UISession::saveSessionSettings() 1857 { 1858 /* Save extra-data settings: */ 1859 { 1860 /* Disable First RUN Wizard: */ 1861 gEDataManager->setMachineFirstTimeStarted(false, vboxGlobal().managedVMUuid()); 1862 1863 /* Remember if guest should autoresize: */ 1864 if (actionPool()) 1865 { 1866 const QAction *pGuestAutoresizeSwitch = actionPool()->action(UIActionIndexRT_M_View_T_GuestAutoresize); 1867 gEDataManager->setGuestScreenAutoResizeEnabled(pGuestAutoresizeSwitch->isChecked(), vboxGlobal().managedVMUuid()); 1868 } 1869 1870 #ifndef Q_WS_MAC 1871 /* Cleanup user's machine-window icon: */ 1872 delete m_pMachineWindowIcon; 1873 m_pMachineWindowIcon = 0; 1874 #endif /* !Q_WS_MAC */ 1875 } 1876 } 1877 1878 void UISession::cleanupFramebuffers() 1879 { 1880 /* Cleanup framebuffers finally: */ 1881 for (int i = m_frameBufferVector.size() - 1; i >= 0; --i) 1882 { 1883 UIFrameBuffer *pFrameBuffer = m_frameBufferVector[i]; 1884 if (pFrameBuffer) 1885 { 1886 /* Mark framebuffer as unused: */ 1887 pFrameBuffer->setMarkAsUnused(true); 1888 /* Detach framebuffer from Display: */ 1889 pFrameBuffer->detach(); 1890 /* Delete framebuffer reference: */ 1891 delete pFrameBuffer; 1892 } 1893 } 1894 m_frameBufferVector.clear(); 1895 } 1896 1897 void UISession::cleanupConsoleEventHandlers() 1898 { 1899 /* Destroy console event-handler if necessary: */ 1900 if (gConsoleEvents) 1901 UIConsoleEventHandler::destroy(); 1902 } 1903 1904 void UISession::cleanupConnections() 1905 { 1906 #ifdef Q_WS_MAC 1907 /* Remove display reconfiguration callback: */ 1908 CGDisplayRemoveReconfigurationCallback(cgDisplayReconfigurationCallback, this); 1909 #endif /* Q_WS_MAC */ 1910 } 1911 1912 void UISession::cleanupActions() 1913 { 1914 #ifdef Q_WS_MAC 1915 /* Destroy Mac OS X menu-bar: */ 1916 delete m_pMenuBar; 1917 m_pMenuBar = 0; 1918 #endif /* Q_WS_MAC */ 1919 1920 /* Destroy action-pool if necessary: */ 1921 if (actionPool()) 1922 UIActionPool::destroy(actionPool()); 1923 } 1924 1925 void UISession::cleanupSession() 1926 { 1927 /* Detach debugger: */ 1928 if (!m_debugger.isNull()) 1929 m_debugger.detach(); 1930 1931 /* Detach keyboard: */ 1932 if (!m_keyboard.isNull()) 1933 m_keyboard.detach(); 1934 1935 /* Detach mouse: */ 1936 if (!m_mouse.isNull()) 1937 m_mouse.detach(); 1938 1939 /* Detach guest: */ 1940 if (!m_guest.isNull()) 1941 m_guest.detach(); 1942 1943 /* Detach display: */ 1944 if (!m_display.isNull()) 1945 m_display.detach(); 1946 1947 /* Detach console: */ 1948 if (!m_console.isNull()) 1949 m_console.detach(); 1950 1951 /* Detach machine: */ 1952 if (!m_machine.isNull()) 1953 m_machine.detach(); 1954 1955 /* Close session: */ 1956 if (!m_session.isNull() && vboxGlobal().isVBoxSVCAvailable()) 1957 { 1958 m_session.UnlockMachine(); 1959 m_session.detach(); 1960 } 1961 } 1962 1963 void UISession::cleanup() 1964 { 1965 #ifdef Q_WS_WIN 1966 /* Destroy alpha cursor: */ 1967 if (m_alphaCursor) 1968 DestroyIcon(m_alphaCursor); 1969 #endif /* Q_WS_WIN */ 1970 1971 /* Save settings: */ 1972 saveSessionSettings(); 1973 1974 /* Cleanup framebuffers: */ 1975 cleanupFramebuffers(); 1976 1977 /* Cleanup console event-handlers: */ 1978 cleanupConsoleEventHandlers(); 1979 1980 /* Cleanup connections: */ 1981 cleanupConnections(); 1982 1983 /* Cleanup actions: */ 1984 cleanupActions(); 1985 1986 /* Cleanup session: */ 1987 cleanupSession(); 1988 } 1989 1990 #ifdef Q_WS_MAC 1991 void UISession::updateMenu() 1992 { 1993 /* Rebuild Mac OS X menu-bar: */ 1994 m_pMenuBar->clear(); 1995 foreach (QMenu *pMenu, actionPool()->menus()) 1996 { 1997 UIMenu *pMenuUI = qobject_cast<UIMenu*>(pMenu); 1998 if (!pMenuUI->isConsumable() || !pMenuUI->isConsumed()) 1999 m_pMenuBar->addMenu(pMenuUI); 2000 if (pMenuUI->isConsumable() && !pMenuUI->isConsumed()) 2001 pMenuUI->setConsumed(true); 2002 } 2003 } 2004 #endif /* Q_WS_MAC */ 2005 2006 WId UISession::winId() const 2007 { 2008 return mainMachineWindow()->winId(); 2009 } 2010 2011 void UISession::setPointerShape(const uchar *pShapeData, bool fHasAlpha, 2012 uint uXHot, uint uYHot, uint uWidth, uint uHeight) 2013 { 2014 AssertMsg(pShapeData, ("Shape data must not be NULL!\n")); 2015 2016 m_fIsValidPointerShapePresent = false; 2017 const uchar *srcAndMaskPtr = pShapeData; 2018 uint andMaskSize = (uWidth + 7) / 8 * uHeight; 2019 const uchar *srcShapePtr = pShapeData + ((andMaskSize + 3) & ~3); 2020 uint srcShapePtrScan = uWidth * 4; 2021 2022 #if defined (Q_WS_WIN) 2023 2024 BITMAPV5HEADER bi; 2025 HBITMAP hBitmap; 2026 void *lpBits; 2027 2028 ::ZeroMemory(&bi, sizeof (BITMAPV5HEADER)); 2029 bi.bV5Size = sizeof(BITMAPV5HEADER); 2030 bi.bV5Width = uWidth; 2031 bi.bV5Height = - (LONG)uHeight; 2032 bi.bV5Planes = 1; 2033 bi.bV5BitCount = 32; 2034 bi.bV5Compression = BI_BITFIELDS; 2035 bi.bV5RedMask = 0x00FF0000; 2036 bi.bV5GreenMask = 0x0000FF00; 2037 bi.bV5BlueMask = 0x000000FF; 2038 if (fHasAlpha) 2039 bi.bV5AlphaMask = 0xFF000000; 2040 else 2041 bi.bV5AlphaMask = 0; 2042 2043 HDC hdc = GetDC(NULL); 2044 2045 /* Create the DIB section with an alpha channel: */ 2046 hBitmap = CreateDIBSection(hdc, (BITMAPINFO *)&bi, DIB_RGB_COLORS, (void **)&lpBits, NULL, (DWORD) 0); 2047 2048 ReleaseDC(NULL, hdc); 2049 2050 HBITMAP hMonoBitmap = NULL; 2051 if (fHasAlpha) 2052 { 2053 /* Create an empty mask bitmap: */ 2054 hMonoBitmap = CreateBitmap(uWidth, uHeight, 1, 1, NULL); 2055 } 2056 else 2057 { 2058 /* Word aligned AND mask. Will be allocated and created if necessary. */ 2059 uint8_t *pu8AndMaskWordAligned = NULL; 2060 2061 /* Width in bytes of the original AND mask scan line. */ 2062 uint32_t cbAndMaskScan = (uWidth + 7) / 8; 2063 2064 if (cbAndMaskScan & 1) 2065 { 2066 /* Original AND mask is not word aligned. */ 2067 2068 /* Allocate memory for aligned AND mask. */ 2069 pu8AndMaskWordAligned = (uint8_t *)RTMemTmpAllocZ((cbAndMaskScan + 1) * uHeight); 2070 2071 Assert(pu8AndMaskWordAligned); 2072 2073 if (pu8AndMaskWordAligned) 2074 { 2075 /* According to MSDN the padding bits must be 0. 2076 * Compute the bit mask to set padding bits to 0 in the last byte of original AND mask. */ 2077 uint32_t u32PaddingBits = cbAndMaskScan * 8 - uWidth; 2078 Assert(u32PaddingBits < 8); 2079 uint8_t u8LastBytesPaddingMask = (uint8_t)(0xFF << u32PaddingBits); 2080 2081 Log(("u8LastBytesPaddingMask = %02X, aligned w = %d, width = %d, cbAndMaskScan = %d\n", 2082 u8LastBytesPaddingMask, (cbAndMaskScan + 1) * 8, uWidth, cbAndMaskScan)); 2083 2084 uint8_t *src = (uint8_t *)srcAndMaskPtr; 2085 uint8_t *dst = pu8AndMaskWordAligned; 2086 2087 unsigned i; 2088 for (i = 0; i < uHeight; i++) 2089 { 2090 memcpy(dst, src, cbAndMaskScan); 2091 2092 dst[cbAndMaskScan - 1] &= u8LastBytesPaddingMask; 2093 2094 src += cbAndMaskScan; 2095 dst += cbAndMaskScan + 1; 2096 } 2097 } 2098 } 2099 2100 /* Create the AND mask bitmap: */ 2101 hMonoBitmap = ::CreateBitmap(uWidth, uHeight, 1, 1, 2102 pu8AndMaskWordAligned? pu8AndMaskWordAligned: srcAndMaskPtr); 2103 2104 if (pu8AndMaskWordAligned) 2105 { 2106 RTMemTmpFree(pu8AndMaskWordAligned); 2107 } 2108 } 2109 2110 Assert(hBitmap); 2111 Assert(hMonoBitmap); 2112 if (hBitmap && hMonoBitmap) 2113 { 2114 DWORD *dstShapePtr = (DWORD *) lpBits; 2115 2116 for (uint y = 0; y < uHeight; y ++) 2117 { 2118 memcpy(dstShapePtr, srcShapePtr, srcShapePtrScan); 2119 srcShapePtr += srcShapePtrScan; 2120 dstShapePtr += uWidth; 2121 } 2122 2123 ICONINFO ii; 2124 ii.fIcon = FALSE; 2125 ii.xHotspot = uXHot; 2126 ii.yHotspot = uYHot; 2127 ii.hbmMask = hMonoBitmap; 2128 ii.hbmColor = hBitmap; 2129 2130 HCURSOR hAlphaCursor = CreateIconIndirect(&ii); 2131 Assert(hAlphaCursor); 2132 if (hAlphaCursor) 2133 { 2134 /* Set the new cursor: */ 2135 m_cursor = QCursor(hAlphaCursor); 2136 if (m_alphaCursor) 2137 DestroyIcon(m_alphaCursor); 2138 m_alphaCursor = hAlphaCursor; 2139 m_fIsValidPointerShapePresent = true; 2140 } 2141 } 2142 2143 if (hMonoBitmap) 2144 DeleteObject(hMonoBitmap); 2145 if (hBitmap) 2146 DeleteObject(hBitmap); 2147 2148 #elif defined (Q_WS_X11) && !defined (VBOX_WITHOUT_XCURSOR) 2149 2150 XcursorImage *img = XcursorImageCreate(uWidth, uHeight); 2151 Assert(img); 2152 if (img) 2153 { 2154 img->xhot = uXHot; 2155 img->yhot = uYHot; 2156 2157 XcursorPixel *dstShapePtr = img->pixels; 2158 2159 for (uint y = 0; y < uHeight; y ++) 2160 { 2161 memcpy (dstShapePtr, srcShapePtr, srcShapePtrScan); 2162 2163 if (!fHasAlpha) 2164 { 2165 /* Convert AND mask to the alpha channel: */ 2166 uchar byte = 0; 2167 for (uint x = 0; x < uWidth; x ++) 2168 { 2169 if (!(x % 8)) 2170 byte = *(srcAndMaskPtr ++); 2171 else 2172 byte <<= 1; 2173 2174 if (byte & 0x80) 2175 { 2176 /* Linux doesn't support inverted pixels (XOR ops, 2177 * to be exact) in cursor shapes, so we detect such 2178 * pixels and always replace them with black ones to 2179 * make them visible at least over light colors */ 2180 if (dstShapePtr [x] & 0x00FFFFFF) 2181 dstShapePtr [x] = 0xFF000000; 2182 else 2183 dstShapePtr [x] = 0x00000000; 2184 } 2185 else 2186 dstShapePtr [x] |= 0xFF000000; 2187 } 2188 } 2189 2190 srcShapePtr += srcShapePtrScan; 2191 dstShapePtr += uWidth; 2192 } 2193 2194 /* Set the new cursor: */ 2195 m_cursor = QCursor(XcursorImageLoadCursor(QX11Info::display(), img)); 2196 m_fIsValidPointerShapePresent = true; 2197 2198 XcursorImageDestroy(img); 2199 } 2200 2201 #elif defined(Q_WS_MAC) 2202 2203 /* Create a ARGB image out of the shape data. */ 2204 QImage image (uWidth, uHeight, QImage::Format_ARGB32); 2205 const uint8_t* pbSrcMask = static_cast<const uint8_t*> (srcAndMaskPtr); 2206 unsigned cbSrcMaskLine = RT_ALIGN (uWidth, 8) / 8; 2207 for (unsigned int y = 0; y < uHeight; ++y) 2208 { 2209 for (unsigned int x = 0; x < uWidth; ++x) 2210 { 2211 unsigned int color = ((unsigned int*)srcShapePtr)[y*uWidth+x]; 2212 /* If the alpha channel isn't in the shape data, we have to 2213 * create them from the and-mask. This is a bit field where 1 2214 * represent transparency & 0 opaque respectively. */ 2215 if (!fHasAlpha) 2216 { 2217 if (!(pbSrcMask[x / 8] & (1 << (7 - (x % 8))))) 2218 color |= 0xff000000; 2219 else 2220 { 2221 /* This isn't quite right, but it's the best we can do I think... */ 2222 if (color & 0x00ffffff) 2223 color = 0xff000000; 2224 else 2225 color = 0x00000000; 2226 } 2227 } 2228 image.setPixel (x, y, color); 2229 } 2230 /* Move one scanline forward. */ 2231 pbSrcMask += cbSrcMaskLine; 2232 } 2233 2234 /* Set the new cursor: */ 2235 m_cursor = QCursor(QPixmap::fromImage(image), uXHot, uYHot); 2236 m_fIsValidPointerShapePresent = true; 2237 NOREF(srcShapePtrScan); 2238 2239 #else 2240 2241 # warning "port me" 2242 2243 #endif 2244 } 2245 2246 bool UISession::preprocessInitialization() 2247 { 2248 #ifdef VBOX_WITH_NETFLT 2249 /* Skip further checks if VM in saved state */ 2250 if (isSaved()) 2251 return true; 2252 2253 /* Make sure all the attached and enabled network 2254 * adapters are present on the host. This check makes sense 2255 * in two cases only - when attachement type is Bridged Network 2256 * or Host-only Interface. NOTE: Only currently enabled 2257 * attachement type is checked (incorrect parameters check for 2258 * currently disabled attachement types is skipped). */ 2259 QStringList failedInterfaceNames; 2260 QStringList availableInterfaceNames; 2261 2262 /* Create host network interface names list */ 2263 foreach (const CHostNetworkInterface &iface, vboxGlobal().host().GetNetworkInterfaces()) 2264 { 2265 availableInterfaceNames << iface.GetName(); 2266 availableInterfaceNames << iface.GetShortName(); 2267 } 2268 2269 ulong cCount = vboxGlobal().virtualBox().GetSystemProperties().GetMaxNetworkAdapters(machine().GetChipsetType()); 2270 for (ulong uAdapterIndex = 0; uAdapterIndex < cCount; ++uAdapterIndex) 2271 { 2272 CNetworkAdapter na = machine().GetNetworkAdapter(uAdapterIndex); 2273 2274 if (na.GetEnabled()) 2275 { 2276 QString strIfName = QString(); 2277 2278 /* Get physical network interface name for currently 2279 * enabled network attachement type */ 2280 switch (na.GetAttachmentType()) 2281 { 2282 case KNetworkAttachmentType_Bridged: 2283 strIfName = na.GetBridgedInterface(); 2284 break; 2285 case KNetworkAttachmentType_HostOnly: 2286 strIfName = na.GetHostOnlyInterface(); 2287 break; 2288 } 2289 2290 if (!strIfName.isEmpty() && 2291 !availableInterfaceNames.contains(strIfName)) 2292 { 2293 LogFlow(("Found invalid network interface: %s\n", strIfName.toStdString().c_str())); 2294 failedInterfaceNames << QString("%1 (adapter %2)").arg(strIfName).arg(uAdapterIndex + 1); 2295 } 2296 } 2297 } 2298 2299 /* Check if non-existent interfaces found */ 2300 if (!failedInterfaceNames.isEmpty()) 2301 { 2302 if (msgCenter().cannotStartWithoutNetworkIf(machineName(), failedInterfaceNames.join(", "))) 2303 machineLogic()->openNetworkSettingsDialog(); 2304 else 2305 return false; 2306 } 2307 #endif /* VBOX_WITH_NETFLT */ 2308 2309 /* True by default: */ 2310 return true; 2311 } 2312 2313 bool UISession::postprocessInitialization() 2314 { 2315 /* Check if the required virtualization features are active. We get this info only when the session is active. */ 2316 const bool fIs64BitsGuest = vboxGlobal().virtualBox().GetGuestOSType(guest().GetOSTypeId()).GetIs64Bit(); 2317 const bool fRecommendVirtEx = vboxGlobal().virtualBox().GetGuestOSType(guest().GetOSTypeId()).GetRecommendedVirtEx(); 2318 AssertMsg(!fIs64BitsGuest || fRecommendVirtEx, ("Virtualization support missed for 64bit guest!\n")); 2319 const bool fIsVirtActive = debugger().GetHWVirtExEnabled(); 2320 if (fRecommendVirtEx && !fIsVirtActive) 2321 { 2322 /* Check whether vt-x / amd-v supported: */ 2323 bool fVTxAMDVSupported = vboxGlobal().host().GetProcessorFeature(KProcessorFeature_HWVirtEx); 2324 2325 /* Pause VM: */ 2326 setPause(true); 2327 2328 /* Ask the user about further actions: */ 2329 bool fShouldWeClose; 2330 if (fIs64BitsGuest) 2331 fShouldWeClose = msgCenter().warnAboutVirtExInactiveFor64BitsGuest(fVTxAMDVSupported); 2332 else 2333 fShouldWeClose = msgCenter().warnAboutVirtExInactiveForRecommendedGuest(fVTxAMDVSupported); 2334 2335 /* If user asked to close VM: */ 2336 if (fShouldWeClose) 2337 { 2338 /* Prevent auto-closure during power off sequence: */ 2339 machineLogic()->setPreventAutoClose(true); 2340 /* Power off VM: */ 2341 bool fServerCrashed = false; 2342 powerOff(false, fServerCrashed); 2343 return false; 2344 } 2345 2346 /* Resume VM: */ 2347 setPause(false); 2348 } 2349 2350 /* True by default: */ 2351 return true; 2352 } 2353 2354 bool UISession::isScreenVisible(ulong uScreenId) const 2355 { 2356 Assert(uScreenId < (ulong)m_monitorVisibilityVector.size()); 2357 return m_monitorVisibilityVector.value((int)uScreenId, false); 2358 } 2359 2360 void UISession::setScreenVisible(ulong uScreenId, bool fIsMonitorVisible) 2361 { 2362 Assert(uScreenId < (ulong)m_monitorVisibilityVector.size()); 2363 if (uScreenId < (ulong)m_monitorVisibilityVector.size()) 2364 m_monitorVisibilityVector[(int)uScreenId] = fIsMonitorVisible; 2365 } 2366 2367 int UISession::countOfVisibleWindows() 2368 { 2369 int cCountOfVisibleWindows = 0; 2370 for (int i = 0; i < m_monitorVisibilityVector.size(); ++i) 2371 if (m_monitorVisibilityVector[i]) 2372 ++cCountOfVisibleWindows; 2373 return cCountOfVisibleWindows; 2374 } 2375 2376 UIFrameBuffer* UISession::frameBuffer(ulong uScreenId) const 2377 { 2378 Assert(uScreenId < (ulong)m_frameBufferVector.size()); 2379 return m_frameBufferVector.value((int)uScreenId, 0); 2380 } 2381 2382 void UISession::setFrameBuffer(ulong uScreenId, UIFrameBuffer* pFrameBuffer) 2383 { 2384 Assert(uScreenId < (ulong)m_frameBufferVector.size()); 2385 if (uScreenId < (ulong)m_frameBufferVector.size()) 2386 m_frameBufferVector[(int)uScreenId] = pFrameBuffer; 2387 } 2388 2389 void UISession::updateHostScreenData() 2390 { 2391 m_hostScreens.clear(); 2392 QDesktopWidget *pDesktop = QApplication::desktop(); 2393 for (int iScreenIndex = 0; iScreenIndex < pDesktop->screenCount(); ++iScreenIndex) 2394 m_hostScreens << pDesktop->screenGeometry(iScreenIndex); 2395 } 2396 2397 #ifdef VBOX_GUI_WITH_KEYS_RESET_HANDLER 2398 /** 2399 * Custom signal handler. When switching VTs, we might not get release events 2400 * for Ctrl-Alt and in case a savestate is performed on the new VT, the VM will 2401 * be saved with modifier keys stuck. This is annoying enough for introducing 2402 * this hack. 2403 */ 2404 /* static */ 2405 static void signalHandlerSIGUSR1(int sig, siginfo_t * /* pInfo */, void * /*pSecret */) 2406 { 2407 /* only SIGUSR1 is interesting */ 2408 if (sig == SIGUSR1) 2409 if (UIMachine *pMachine = vboxGlobal().virtualMachine()) 2410 pMachine->uisession()->machineLogic()->keyboardHandler()->releaseAllPressedKeys(); 2411 } 2412 #endif /* VBOX_GUI_WITH_KEYS_RESET_HANDLER */ 2413 2414 #include "UISession.moc" 2415 297 /* Depending on column index: */ 298 switch (index.column()) 299 { 300 case UIEncryptionDataTableSection_Password: m_encryptionPasswords[m_encryptionPasswords.keys().at(index.row())] = value.toString(); break; 301 default: break; 302 } 303 /* Nothing to set by default: */ 304 return false; 305 } 306 307 void UIEncryptionDataModel::prepare() 308 { 309 /* Populate the map of passwords. */ 310 foreach (const QString &strPasswordId, m_encryptedMediums.keys()) 311 m_encryptionPasswords.insert(strPasswordId, QString()); 312 } 313 314 UIEncryptionDataTable::UIEncryptionDataTable(const EncryptedMediumsMap &encryptedMediums) 315 : m_encryptedMediums(encryptedMediums) 316 , m_pModelEncryptionData(0) 317 { 318 /* Prepare: */ 319 prepare(); 320 } 321 322 EncryptionPasswordsMap UIEncryptionDataTable::encryptionPasswords() const 323 { 324 AssertPtrReturn(m_pModelEncryptionData, EncryptionPasswordsMap()); 325 return m_pModelEncryptionData->encryptionPasswords(); 326 } 327 328 void UIEncryptionDataTable::prepare() 329 { 330 /* Create encryption-data model: */ 331 m_pModelEncryptionData = new UIEncryptionDataModel(this, m_encryptedMediums); 332 AssertPtrReturnVoid(m_pModelEncryptionData); 333 { 334 /* Assign configured model to table: */ 335 setModel(m_pModelEncryptionData); 336 } 337 338 /* Create item delegate: */ 339 QIStyledItemDelegate *pStyledItemDelegate = new QIStyledItemDelegate(this); 340 AssertPtrReturnVoid(pStyledItemDelegate); 341 { 342 /* Create item editor factory: */ 343 QItemEditorFactory *pNewItemEditorFactory = new QItemEditorFactory; 344 AssertPtrReturnVoid(pNewItemEditorFactory); 345 { 346 /* Create item editor creator: */ 347 QStandardItemEditorCreator<UIPasswordEditor> *pQStringItemEditorCreator = new QStandardItemEditorCreator<UIPasswordEditor>(); 348 AssertPtrReturnVoid(pQStringItemEditorCreator); 349 { 350 /* Register UIPasswordEditor as the QString editor: */ 351 pNewItemEditorFactory->registerEditor(QVariant::String, pQStringItemEditorCreator); 352 } 353 /* Assign configured item editor factory to table delegate: */ 354 pStyledItemDelegate->setItemEditorFactory(pNewItemEditorFactory); 355 } 356 /* Assign configured item delegate to table: */ 357 delete itemDelegate(); 358 setItemDelegate(pStyledItemDelegate); 359 } 360 361 /* Configure table: */ 362 setTabKeyNavigation(false); 363 setContextMenuPolicy(Qt::CustomContextMenu); 364 setSelectionBehavior(QAbstractItemView::SelectRows); 365 setSelectionMode(QAbstractItemView::SingleSelection); 366 setEditTriggers(QAbstractItemView::CurrentChanged | QAbstractItemView::SelectedClicked); 367 368 /* Configure headers: */ 369 verticalHeader()->hide(); 370 verticalHeader()->setDefaultSectionSize((int)(verticalHeader()->minimumSectionSize() * 1.33)); 371 horizontalHeader()->setStretchLastSection(false); 372 horizontalHeader()->setResizeMode(UIEncryptionDataTableSection_Id, QHeaderView::Interactive); 373 horizontalHeader()->setResizeMode(UIEncryptionDataTableSection_Password, QHeaderView::Stretch); 374 } 375 376 UIAddDiskEncryptionPasswordDialog::UIAddDiskEncryptionPasswordDialog(QWidget *pParent, const EncryptedMediumsMap &encryptedMediums) 377 : QIWithRetranslateUI<QDialog>(pParent) 378 , m_encryptedMediums(encryptedMediums) 379 , m_pLabelDescription(0) 380 , m_pTableEncryptionData(0) 381 { 382 /* Prepare: */ 383 prepare(); 384 /* Retranslate: */ 385 retranslateUi(); 386 } 387 388 EncryptionPasswordsMap UIAddDiskEncryptionPasswordDialog::encryptionPasswords() const 389 { 390 AssertPtrReturn(m_pTableEncryptionData, EncryptionPasswordsMap()); 391 return m_pTableEncryptionData->encryptionPasswords(); 392 } 393 394 void UIAddDiskEncryptionPasswordDialog::prepare() 395 { 396 /* Create main-layout: */ 397 QVBoxLayout *pMainLayout = new QVBoxLayout(this); 398 AssertPtrReturnVoid(pMainLayout); 399 { 400 /* Create input-layout: */ 401 QVBoxLayout *pInputLayout = new QVBoxLayout; 402 AssertPtrReturnVoid(pInputLayout); 403 { 404 /* Create description label: */ 405 m_pLabelDescription = new QILabel; 406 m_pLabelDescription->useSizeHintForWidth(450); 407 m_pLabelDescription->updateGeometry(); 408 AssertPtrReturnVoid(m_pLabelDescription); 409 { 410 /* Configure description label: */ 411 m_pLabelDescription->setWordWrap(true); 412 /* Add label into layout: */ 413 pInputLayout->addWidget(m_pLabelDescription); 414 } 415 /* Create encryption-data table: */ 416 m_pTableEncryptionData = new UIEncryptionDataTable(m_encryptedMediums); 417 AssertPtrReturnVoid(m_pTableEncryptionData); 418 { 419 /* Add label into layout: */ 420 pInputLayout->addWidget(m_pTableEncryptionData); 421 } 422 /* Add layout into parent: */ 423 pMainLayout->addLayout(pInputLayout); 424 } 425 /* Create button-box: */ 426 QIDialogButtonBox *pButtonBox = new QIDialogButtonBox; 427 AssertPtrReturnVoid(pButtonBox); 428 { 429 /* Configure button-box: */ 430 pButtonBox->setStandardButtons(QDialogButtonBox::Ok | QDialogButtonBox::Cancel); 431 connect(pButtonBox, SIGNAL(accepted()), this, SLOT(accept())); 432 connect(pButtonBox, SIGNAL(rejected()), this, SLOT(reject())); 433 /* Add button-box into layout: */ 434 pMainLayout->addWidget(pButtonBox); 435 } 436 } 437 } 438 439 void UIAddDiskEncryptionPasswordDialog::retranslateUi() 440 { 441 AssertPtrReturnVoid(m_pLabelDescription); 442 m_pLabelDescription->setText(tr("This virtual machine is password protected. " 443 "Please enter the %n encryption password(s) below.", 444 "This text is never used with n == 0. " 445 "Feel free to drop the %n where possible, " 446 "we only included it because of problems with Qt Linguist " 447 "(but the user can see how many passwords are in the list " 448 "and doesn't need to be told).", 449 m_encryptedMediums.size())); 450 } 451 452 #include "UIAddDiskEncryptionPasswordDialog.moc" 453 -
trunk/src/VBox/Frontends/VirtualBox/src/runtime/UIAddDiskEncryptionPasswordDialog.h
r54732 r54733 1 /* $Id$ */2 1 /** @file 3 * VBox Qt GUI - UI Session class implementation.2 * VBox Qt GUI - UIAddDiskEncryptionPasswordDialog class declaration. 4 3 */ 5 4 6 5 /* 7 * Copyright (C) 2006-201 3Oracle Corporation6 * Copyright (C) 2006-2015 Oracle Corporation 8 7 * 9 8 * This file is part of VirtualBox Open Source Edition (OSE), as … … 16 15 */ 17 16 18 #ifdef VBOX_WITH_PRECOMPILED_HEADERS 19 # include <precomp.h> 20 #else /* !VBOX_WITH_PRECOMPILED_HEADERS */ 21 22 /* Qt includes: */ 23 # include <QApplication> 24 # include <QDesktopWidget> 25 # include <QWidget> 26 # ifdef Q_WS_MAC 27 # include <QTimer> 28 # endif /* Q_WS_MAC */ 29 30 /* GUI includes: */ 31 # include "VBoxGlobal.h" 32 # include "UIExtraDataManager.h" 33 # include "UISession.h" 34 # include "UIMachine.h" 35 # include "UIMedium.h" 36 # include "UIActionPoolRuntime.h" 37 # include "UIMachineLogic.h" 38 # include "UIMachineView.h" 39 # include "UIMachineWindow.h" 40 # include "UIMessageCenter.h" 41 # include "UIPopupCenter.h" 42 # include "UIWizardFirstRun.h" 43 # include "UIConsoleEventHandler.h" 44 # include "UIFrameBuffer.h" 45 # include "UISettingsDialogSpecific.h" 46 # ifdef VBOX_WITH_VIDEOHWACCEL 47 # include "VBoxFBOverlay.h" 48 # endif /* VBOX_WITH_VIDEOHWACCEL */ 49 # ifdef Q_WS_MAC 50 # include "UIMenuBar.h" 51 # include "VBoxUtils-darwin.h" 52 # endif /* Q_WS_MAC */ 53 54 # ifdef VBOX_GUI_WITH_KEYS_RESET_HANDLER 55 # include "UIKeyboardHandler.h" 56 # include <signal.h> 57 # endif /* VBOX_GUI_WITH_KEYS_RESET_HANDLER */ 58 59 /* COM includes: */ 60 # include "CSystemProperties.h" 61 # include "CStorageController.h" 62 # include "CMediumAttachment.h" 63 # include "CNetworkAdapter.h" 64 # include "CHostNetworkInterface.h" 65 # include "CVRDEServer.h" 66 # include "CUSBController.h" 67 # include "CUSBDeviceFilters.h" 68 # include "CHostVideoInputDevice.h" 69 # include "CSnapshot.h" 70 # include "CMedium.h" 71 72 #endif /* !VBOX_WITH_PRECOMPILED_HEADERS */ 73 74 #ifdef Q_WS_X11 75 # include <QX11Info> 76 # include <X11/Xlib.h> 77 # include <X11/Xutil.h> 78 # ifndef VBOX_WITHOUT_XCURSOR 79 # include <X11/Xcursor/Xcursor.h> 80 # endif /* VBOX_WITHOUT_XCURSOR */ 81 #endif /* Q_WS_X11 */ 82 17 #ifndef ___UIAddDiskEncryptionPasswordDialog_h___ 18 #define ___UIAddDiskEncryptionPasswordDialog_h___ 83 19 84 20 /* Qt includes: */ 85 21 #include <QDialog> 86 #include <QVBoxLayout> 87 #include <QLineEdit> 88 #include <QTableView> 89 #include <QHeaderView> 90 #include <QItemEditorFactory> 91 #include <QAbstractTableModel> 92 #include <QStandardItemEditorCreator> 22 #include <QMultiMap> 23 #include <QMap> 24 93 25 /* GUI includes: */ 94 #include "QILabel.h"95 #include "QIDialogButtonBox.h"96 26 #include "QIWithRetranslateUI.h" 97 #include "QIStyledItemDelegate.h" 27 28 /* Forward declarations: */ 29 class UIEncryptionDataTable; 30 class QILabel; 98 31 99 32 /* Type definitions: */ 33 typedef QMultiMap<QString, QString> EncryptedMediumsMap; 100 34 typedef QMap<QString, QString> EncryptionPasswordsMap; 101 typedef QMultiMap<QString, QString> EncryptedMediumsMap;102 35 103 /** Encryption-data table field indexes. 104 * @todo To be moved into separate file.. */ 105 enum UIEncryptionTableSection 106 { 107 UIEncryptionTableSection_Id, 108 UIEncryptionTableSection_Password, 109 UIEncryptionTableSection_Max 110 }; 111 112 /** QLineEdit implementation allowing to enter 113 * disk encryption password for particular password id. 114 * @todo To be moved into separate file.. */ 115 class UILineEdit : public QLineEdit 116 { 117 Q_OBJECT; 118 Q_PROPERTY(QString password READ password WRITE setPassword USER true); 119 120 signals: 121 122 /** Notifies listener about data should be committed. */ 123 void sigCommitData(QWidget *pThis); 124 125 public: 126 127 /** Constructor. 128 * @param pParent being passed to the base-class. */ 129 UILineEdit(QWidget *pParent) 130 : QLineEdit(pParent) 131 { 132 /* Prepare: */ 133 prepare(); 134 } 135 136 public slots: 137 138 /** Handles @s strText changes. */ 139 void sltTextChanged(const QString &strText) 140 { 141 Q_UNUSED(strText); 142 /* Commit data to the listener: */ 143 emit sigCommitData(this); 144 } 145 146 private: 147 148 /** Prepare routine. */ 149 void prepare() 150 { 151 /* Set alignment: */ 152 setAlignment(Qt::AlignCenter); 153 /* Set echo mode: */ 154 setEchoMode(QLineEdit::Password); 155 /* Listen for the text changes: */ 156 connect(this, SIGNAL(textChanged(const QString&)), 157 this, SLOT(sltTextChanged(const QString&))); 158 } 159 160 /** Returns the password from the editor. */ 161 QString password() const { return QLineEdit::text(); } 162 /** Defines the @a strPassword to the editor. */ 163 void setPassword(const QString &strPassword) { QLineEdit::setText(strPassword); } 164 }; 165 166 /** QAbstractTableModel implementation reflecting 167 * disk encryption passwords for particular password ids. 168 * @todo To be moved into separate file.. */ 169 class UIEncryptionDataModel : public QAbstractTableModel 170 { 171 Q_OBJECT; 172 173 public: 174 175 /** Constructor. 176 * @param pParent being passed to the base-class, 177 * @param encryptedMediums contains the lists of medium ids (values) encrypted with passwords with ids (keys). */ 178 UIEncryptionDataModel(QObject *pParent, const EncryptedMediumsMap &encryptedMediums) 179 : QAbstractTableModel(pParent) 180 , m_encryptedMediums(encryptedMediums) 181 { 182 /* Prepare: */ 183 prepare(); 184 } 185 186 /** Returns encryption passwords. */ 187 EncryptionPasswordsMap encryptionPasswords() const { return m_encryptionPasswords; } 188 189 /** Returns the @a index flags. */ 190 virtual Qt::ItemFlags flags(const QModelIndex &index) const 191 { 192 /* Check index validness: */ 193 if (!index.isValid()) 194 return Qt::NoItemFlags; 195 /* Depending on column index: */ 196 switch (index.column()) 197 { 198 case UIEncryptionTableSection_Id: return Qt::ItemIsEnabled | Qt::ItemIsSelectable; 199 case UIEncryptionTableSection_Password: return Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsEditable; 200 default: break; 201 } 202 /* No flags by default: */ 203 return Qt::NoItemFlags; 204 } 205 206 /** Returns the row count. Provide optional @a parent instead of root if necessary. */ 207 virtual int rowCount(const QModelIndex &parent = QModelIndex()) const 208 { 209 Q_UNUSED(parent); 210 return m_encryptionPasswords.size(); 211 } 212 213 /** Returns the column count. Provide optional @a parent instead of root if necessary. */ 214 virtual int columnCount(const QModelIndex &parent = QModelIndex()) const 215 { 216 Q_UNUSED(parent); 217 return UIEncryptionTableSection_Max; 218 } 219 220 /** Returns header data for @a iSection, @a orientation and @a iRole. */ 221 virtual QVariant headerData(int iSection, Qt::Orientation orientation, int iRole) const 222 { 223 /* Check argument validness: */ 224 if (iRole != Qt::DisplayRole || orientation != Qt::Horizontal) 225 return QVariant(); 226 /* Depending on column index: */ 227 switch (iSection) 228 { 229 case UIEncryptionTableSection_Id: return tr("Password ID"); 230 case UIEncryptionTableSection_Password: return tr("Password"); 231 default: break; 232 } 233 /* Null value by default: */ 234 return QVariant(); 235 } 236 237 /** Returns @a index data for @a iRole. */ 238 virtual QVariant data(const QModelIndex &index, int iRole /* = Qt::DisplayRole */) const 239 { 240 /* Check index validness: */ 241 if (!index.isValid()) 242 return QVariant(); 243 /* Depending on role: */ 244 switch (iRole) 245 { 246 case Qt::DisplayRole: 247 { 248 /* Depending on column index: */ 249 switch (index.column()) 250 { 251 case UIEncryptionTableSection_Id: 252 return m_encryptionPasswords.keys().at(index.row()); 253 case UIEncryptionTableSection_Password: 254 return QString().fill('*', m_encryptionPasswords.value(m_encryptionPasswords.keys().at(index.row())).size()); 255 default: 256 return QVariant(); 257 } 258 break; 259 } 260 case Qt::EditRole: 261 { 262 /* Depending on column index: */ 263 switch (index.column()) 264 { 265 case UIEncryptionTableSection_Password: 266 return m_encryptionPasswords.value(m_encryptionPasswords.keys().at(index.row())); 267 default: 268 return QVariant(); 269 } 270 break; 271 } 272 case Qt::TextAlignmentRole: 273 { 274 /* Depending on column index: */ 275 switch (index.column()) 276 { 277 case UIEncryptionTableSection_Password: 278 return Qt::AlignCenter; 279 default: return QVariant(); 280 } 281 break; 282 } 283 default: 284 break; 285 } 286 /* Null value by default: */ 287 return QVariant(); 288 } 289 290 /** Defines @a index data for @a iRole as @a value. */ 291 virtual bool setData(const QModelIndex &index, const QVariant &value, int iRole /* = Qt::EditRole */) 292 { 293 /* Check index validness: */ 294 if (!index.isValid()) 295 return false; 296 /* Check argument validness: */ 297 if (iRole != Qt::EditRole) 298 return false; 299 /* Depending on column index: */ 300 switch (index.column()) 301 { 302 case UIEncryptionTableSection_Password: m_encryptionPasswords[m_encryptionPasswords.keys().at(index.row())] = value.toString(); break; 303 default: break; 304 } 305 /* Nothing to set by default: */ 306 return false; 307 } 308 309 private: 310 311 /** Prepare routine. */ 312 void prepare() 313 { 314 /* Populate the map of passwords. */ 315 foreach (const QString &strPasswordId, m_encryptedMediums.keys()) 316 m_encryptionPasswords.insert(strPasswordId, QString()); 317 } 318 319 /** Holds the encrypted medium map reference. */ 320 const EncryptedMediumsMap &m_encryptedMediums; 321 322 /** Holds the encrypted password id map. */ 323 EncryptionPasswordsMap m_encryptionPasswords; 324 }; 325 326 /** QTableView implementation allowing to enter 327 * disk encryption passwords for particular password ids. 328 * @todo To be moved into separate file.. */ 329 class UIEncryptionDataTable : public QTableView 330 { 331 Q_OBJECT; 332 333 public: 334 335 /** Constructor. 336 * @param pParent being passed to the base-class. */ 337 UIEncryptionDataTable(const EncryptedMediumsMap &encryptedMediums) 338 : m_encryptedMediums(encryptedMediums) 339 , m_pModelEncryptionData(0) 340 { 341 /* Prepare: */ 342 prepare(); 343 } 344 345 /** Returns encryption passwords. */ 346 EncryptionPasswordsMap encryptionPasswords() const 347 { 348 AssertPtrReturn(m_pModelEncryptionData, EncryptionPasswordsMap()); 349 return m_pModelEncryptionData->encryptionPasswords(); 350 } 351 352 private: 353 354 /** Prepare routine. */ 355 void prepare() 356 { 357 /* Create encryption-data model: */ 358 m_pModelEncryptionData = new UIEncryptionDataModel(this, m_encryptedMediums); 359 AssertPtrReturnVoid(m_pModelEncryptionData); 360 { 361 /* Assign configured model to table: */ 362 setModel(m_pModelEncryptionData); 363 } 364 365 /* Create item delegate: */ 366 QIStyledItemDelegate *pStyledItemDelegate = new QIStyledItemDelegate(this); 367 AssertPtrReturnVoid(pStyledItemDelegate); 368 { 369 /* Create item editor factory: */ 370 QItemEditorFactory *pNewItemEditorFactory = new QItemEditorFactory; 371 AssertPtrReturnVoid(pNewItemEditorFactory); 372 { 373 /* Create item editor creator: */ 374 QStandardItemEditorCreator<UILineEdit> *pQStringItemEditorCreator = new QStandardItemEditorCreator<UILineEdit>(); 375 AssertPtrReturnVoid(pQStringItemEditorCreator); 376 { 377 /* Register UILineEdit as the QString editor: */ 378 pNewItemEditorFactory->registerEditor(QVariant::String, pQStringItemEditorCreator); 379 } 380 /* Assign configured item editor factory to table delegate: */ 381 pStyledItemDelegate->setItemEditorFactory(pNewItemEditorFactory); 382 } 383 /* Assign configured item delegate to table: */ 384 delete itemDelegate(); 385 setItemDelegate(pStyledItemDelegate); 386 } 387 388 /* Configure table: */ 389 setTabKeyNavigation(false); 390 setContextMenuPolicy(Qt::CustomContextMenu); 391 setSelectionBehavior(QAbstractItemView::SelectRows); 392 setSelectionMode(QAbstractItemView::SingleSelection); 393 setEditTriggers(QAbstractItemView::CurrentChanged | QAbstractItemView::SelectedClicked); 394 395 /* Configure headers: */ 396 verticalHeader()->hide(); 397 verticalHeader()->setDefaultSectionSize((int)(verticalHeader()->minimumSectionSize() * 1.33)); 398 horizontalHeader()->setStretchLastSection(false); 399 horizontalHeader()->setResizeMode(UIEncryptionTableSection_Id, QHeaderView::Interactive); 400 horizontalHeader()->setResizeMode(UIEncryptionTableSection_Password, QHeaderView::Stretch); 401 } 402 403 /** Holds the encrypted medium map reference. */ 404 const EncryptedMediumsMap &m_encryptedMediums; 405 406 /** Holds the encryption-data model. */ 407 UIEncryptionDataModel *m_pModelEncryptionData; 408 }; 409 410 /** QDialog implementation allowing to enter 411 * disk encryption passwords for particular password ids. 412 * @todo To be moved into separate files.. */ 36 /** QDialog reimplementation used to 37 * allow the user to enter disk encryption passwords for particular password ids. */ 413 38 class UIAddDiskEncryptionPasswordDialog : public QIWithRetranslateUI<QDialog> 414 39 { … … 420 45 * @param pParent being passed to the base-class, 421 46 * @param encryptedMediums contains the lists of medium ids (values) encrypted with passwords with ids (keys). */ 422 UIAddDiskEncryptionPasswordDialog(QWidget *pParent, const EncryptedMediumsMap &encryptedMediums) 423 : QIWithRetranslateUI<QDialog>(pParent) 424 , m_encryptedMediums(encryptedMediums) 425 , m_pLabelDescription(0) 426 , m_pTableEncryptionData(0) 427 { 428 /* Prepare: */ 429 prepare(); 430 /* Retranslate: */ 431 retranslateUi(); 432 } 47 UIAddDiskEncryptionPasswordDialog(QWidget *pParent, const EncryptedMediumsMap &encryptedMediums); 433 48 434 /** Returns encryption passwords. */ 435 EncryptionPasswordsMap encryptionPasswords() const 436 { 437 AssertPtrReturn(m_pTableEncryptionData, EncryptionPasswordsMap()); 438 return m_pTableEncryptionData->encryptionPasswords(); 439 } 49 /** Returns the shallow copy of the encryption password map 50 * acquired from the UIEncryptionDataTable instance. */ 51 EncryptionPasswordsMap encryptionPasswords() const; 440 52 441 53 private: 442 54 443 55 /** Prepare routine. */ 444 void prepare() 445 { 446 /* Create main-layout: */ 447 QVBoxLayout *pMainLayout = new QVBoxLayout(this); 448 AssertPtrReturnVoid(pMainLayout); 449 { 450 /* Create input-layout: */ 451 QVBoxLayout *pInputLayout = new QVBoxLayout; 452 AssertPtrReturnVoid(pInputLayout); 453 { 454 /* Create description label: */ 455 m_pLabelDescription = new QILabel; 456 m_pLabelDescription->useSizeHintForWidth(450); 457 m_pLabelDescription->updateGeometry(); 458 AssertPtrReturnVoid(m_pLabelDescription); 459 { 460 /* Configure description label: */ 461 m_pLabelDescription->setWordWrap(true); 462 /* Add label into layout: */ 463 pInputLayout->addWidget(m_pLabelDescription); 464 } 465 /* Create encryption-data table: */ 466 m_pTableEncryptionData = new UIEncryptionDataTable(m_encryptedMediums); 467 AssertPtrReturnVoid(m_pTableEncryptionData); 468 { 469 /* Add label into layout: */ 470 pInputLayout->addWidget(m_pTableEncryptionData); 471 } 472 /* Add layout into parent: */ 473 pMainLayout->addLayout(pInputLayout); 474 } 475 /* Create button-box: */ 476 QIDialogButtonBox *pButtonBox = new QIDialogButtonBox; 477 AssertPtrReturnVoid(pButtonBox); 478 { 479 /* Configure button-box: */ 480 pButtonBox->setStandardButtons(QDialogButtonBox::Ok | QDialogButtonBox::Cancel); 481 connect(pButtonBox, SIGNAL(accepted()), this, SLOT(accept())); 482 connect(pButtonBox, SIGNAL(rejected()), this, SLOT(reject())); 483 /* Add button-box into layout: */ 484 pMainLayout->addWidget(pButtonBox); 485 } 486 } 487 } 56 void prepare(); 488 57 489 58 /** Translation routine. */ 490 void retranslateUi() 491 { 492 AssertPtrReturnVoid(m_pLabelDescription); 493 m_pLabelDescription->setText(tr("This virtual machine is password protected. " 494 "Please enter the %n encryption password(s) below.", 495 "This text is never used with n == 0. " 496 "Feel free to drop the %n where possible, " 497 "we only included it because of problems with Qt Linguist " 498 "(but the user can see how many passwords are in the list " 499 "and doesn't need to be told).", 500 m_encryptedMediums.size())); 501 } 59 void retranslateUi(); 502 60 503 61 /** Holds the encrypted medium map reference. */ 504 62 const EncryptedMediumsMap &m_encryptedMediums; 505 63 506 /** Holds the description label . */64 /** Holds the description label instance. */ 507 65 QILabel *m_pLabelDescription; 508 /** Holds the encryption-data table . */66 /** Holds the encryption-data table instance. */ 509 67 UIEncryptionDataTable *m_pTableEncryptionData; 510 68 }; 511 69 512 513 #ifdef VBOX_GUI_WITH_KEYS_RESET_HANDLER 514 static void signalHandlerSIGUSR1(int sig, siginfo_t *, void *); 515 #endif 516 517 #ifdef Q_WS_MAC 518 /** 519 * MacOS X: Application Services: Core Graphics: Display reconfiguration callback. 520 * 521 * Notifies UISession about @a display configuration change. 522 * Corresponding change described by Core Graphics @a flags. 523 * Uses UISession @a pHandler to process this change. 524 * 525 * @note Last argument (@a pHandler) must always be valid pointer to UISession object. 526 * @note Calls for UISession::sltHandleHostDisplayAboutToChange() slot if display configuration changed. 527 */ 528 void cgDisplayReconfigurationCallback(CGDirectDisplayID display, CGDisplayChangeSummaryFlags flags, void *pHandler) 529 { 530 /* Which flags we are handling? */ 531 int iHandledFlags = kCGDisplayAddFlag /* display added */ 532 | kCGDisplayRemoveFlag /* display removed */ 533 | kCGDisplaySetModeFlag /* display mode changed */; 534 535 /* Handle 'display-add' case: */ 536 if (flags & kCGDisplayAddFlag) 537 LogRelFlow(("UISession::cgDisplayReconfigurationCallback: Display added.\n")); 538 /* Handle 'display-remove' case: */ 539 else if (flags & kCGDisplayRemoveFlag) 540 LogRelFlow(("UISession::cgDisplayReconfigurationCallback: Display removed.\n")); 541 /* Handle 'mode-set' case: */ 542 else if (flags & kCGDisplaySetModeFlag) 543 LogRelFlow(("UISession::cgDisplayReconfigurationCallback: Display mode changed.\n")); 544 545 /* Ask handler to process our callback: */ 546 if (flags & iHandledFlags) 547 QTimer::singleShot(0, static_cast<UISession*>(pHandler), 548 SLOT(sltHandleHostDisplayAboutToChange())); 549 550 Q_UNUSED(display); 551 } 552 #endif /* Q_WS_MAC */ 553 554 /* static */ 555 bool UISession::create(UISession *&pSession, UIMachine *pMachine) 556 { 557 /* Make sure null pointer passed: */ 558 AssertReturn(pSession == 0, false); 559 560 /* Create session UI: */ 561 pSession = new UISession(pMachine); 562 /* Make sure it's prepared: */ 563 if (!pSession->prepare()) 564 { 565 /* Destroy session UI otherwise: */ 566 destroy(pSession); 567 /* False in that case: */ 568 return false; 569 } 570 /* True by default: */ 571 return true; 572 } 573 574 /* static */ 575 void UISession::destroy(UISession *&pSession) 576 { 577 /* Make sure valid pointer passed: */ 578 AssertReturnVoid(pSession != 0); 579 580 /* Cleanup session UI: */ 581 pSession->cleanup(); 582 /* Destroy session: */ 583 delete pSession; 584 pSession = 0; 585 } 586 587 bool UISession::initialize() 588 { 589 /* Preprocess initialization: */ 590 if (!preprocessInitialization()) 591 return false; 592 593 /* Notify user about mouse&keyboard auto-capturing: */ 594 if (vboxGlobal().settings().autoCapture()) 595 popupCenter().remindAboutAutoCapture(machineLogic()->activeMachineWindow()); 596 597 /* Check if we are in teleportation waiting mode. 598 * In that case no first run wizard is necessary. */ 599 m_machineState = machine().GetState(); 600 if ( isFirstTimeStarted() 601 && !(( m_machineState == KMachineState_PoweredOff 602 || m_machineState == KMachineState_Aborted 603 || m_machineState == KMachineState_Teleported) 604 && machine().GetTeleporterEnabled())) 605 { 606 UISafePointerWizard pWizard = new UIWizardFirstRun(mainMachineWindow(), machine()); 607 pWizard->prepare(); 608 pWizard->exec(); 609 if (pWizard) 610 delete pWizard; 611 } 612 613 /* Apply debug settings from the command line. */ 614 if (!debugger().isNull() && debugger().isOk()) 615 { 616 if (vboxGlobal().isPatmDisabled()) 617 debugger().SetPATMEnabled(false); 618 if (vboxGlobal().isCsamDisabled()) 619 debugger().SetCSAMEnabled(false); 620 if (vboxGlobal().isSupervisorCodeExecedRecompiled()) 621 debugger().SetRecompileSupervisor(true); 622 if (vboxGlobal().isUserCodeExecedRecompiled()) 623 debugger().SetRecompileUser(true); 624 if (vboxGlobal().areWeToExecuteAllInIem()) 625 debugger().SetExecuteAllInIEM(true); 626 if (!vboxGlobal().isDefaultWarpPct()) 627 debugger().SetVirtualTimeRate(vboxGlobal().getWarpPct()); 628 } 629 630 /* Power UP if this is NOT separate process: */ 631 if (!vboxGlobal().isSeparateProcess()) 632 if (!powerUp()) 633 return false; 634 635 /* Check if we missed a really quick termination after successful startup: */ 636 if (isTurnedOff()) 637 return false; 638 639 /* Postprocess initialization: */ 640 if (!postprocessInitialization()) 641 return false; 642 643 /* Fetch corresponding states: */ 644 if (vboxGlobal().isSeparateProcess()) 645 { 646 m_fIsMouseSupportsAbsolute = mouse().GetAbsoluteSupported(); 647 m_fIsMouseSupportsRelative = mouse().GetRelativeSupported(); 648 m_fIsMouseSupportsMultiTouch = mouse().GetMultiTouchSupported(); 649 m_fIsMouseHostCursorNeeded = mouse().GetNeedsHostCursor(); 650 sltAdditionsChange(); 651 } 652 machineLogic()->initializePostPowerUp(); 653 654 #ifdef VBOX_WITH_VIDEOHWACCEL 655 /* Log whether 2D video acceleration is enabled: */ 656 LogRel(("2D video acceleration is %s.\n", 657 machine().GetAccelerate2DVideoEnabled() && VBoxGlobal::isAcceleration2DVideoAvailable() 658 ? "enabled" : "disabled")); 659 #endif /* VBOX_WITH_VIDEOHWACCEL */ 660 661 /* Log whether HID LEDs sync is enabled: */ 662 #if defined(Q_WS_MAC) || defined(Q_WS_WIN) 663 LogRel(("HID LEDs sync is %s.\n", 664 uimachine()->machineLogic()->isHidLedsSyncEnabled() 665 ? "enabled" : "disabled")); 666 #else /* !Q_WS_MAC && !Q_WS_WIN */ 667 LogRel(("HID LEDs sync is not supported on this platform.\n")); 668 #endif /* !Q_WS_MAC && !Q_WS_WIN */ 669 670 #ifdef VBOX_GUI_WITH_PIDFILE 671 vboxGlobal().createPidfile(); 672 #endif /* VBOX_GUI_WITH_PIDFILE */ 673 674 /* Warn listeners about we are initialized: */ 675 emit sigInitialized(); 676 677 /* True by default: */ 678 return true; 679 } 680 681 bool UISession::powerUp() 682 { 683 /* Prepare map of the encrypted ids: */ 684 EncryptedMediumsMap encryptedPasswordIds; 685 foreach (const CMediumAttachment &attachment, machine().GetMediumAttachments()) 686 { 687 /* Acquire hard-drives only: */ 688 if (attachment.GetType() == KDeviceType_HardDisk) 689 { 690 /* Get attachment medium: */ 691 const CMedium medium = attachment.GetMedium(); 692 /* Append our map if this medium has encryption: */ 693 const QString strKeyId = medium.GetProperty("CRYPT/KeyId"); 694 if (!strKeyId.isNull()) 695 encryptedPasswordIds.insert(strKeyId, medium.GetId()); 696 } 697 } 698 /* Ask for disk encryption passwords if necessary: */ 699 EncryptionPasswordsMap encryptionPasswords; 700 if (!encryptedPasswordIds.isEmpty()) 701 { 702 QPointer<UIAddDiskEncryptionPasswordDialog> pDlg = 703 new UIAddDiskEncryptionPasswordDialog(machineLogic()->activeMachineWindow(), 704 encryptedPasswordIds); 705 if (pDlg->exec() == QDialog::Accepted) 706 encryptionPasswords = pDlg->encryptionPasswords(); 707 if (pDlg) 708 delete pDlg; 709 } 710 711 /* Power UP machine: */ 712 #ifdef VBOX_WITH_DEBUGGER_GUI 713 CProgress progress = vboxGlobal().isStartPausedEnabled() || vboxGlobal().isDebuggerAutoShowEnabled() ? 714 console().PowerUpPaused() : console().PowerUp(); 715 #else /* !VBOX_WITH_DEBUGGER_GUI */ 716 CProgress progress = console().PowerUp(); 717 #endif /* !VBOX_WITH_DEBUGGER_GUI */ 718 719 /* Check for immediate failure: */ 720 if (!console().isOk() || progress.isNull()) 721 { 722 if (vboxGlobal().showStartVMErrors()) 723 msgCenter().cannotStartMachine(console(), machineName()); 724 return false; 725 } 726 727 /* Guard progressbar warnings from auto-closing: */ 728 if (uimachine()->machineLogic()) 729 uimachine()->machineLogic()->setPreventAutoClose(true); 730 731 /* Show "Starting/Restoring" progress dialog: */ 732 if (isSaved()) 733 { 734 msgCenter().showModalProgressDialog(progress, machineName(), ":/progress_state_restore_90px.png", 0, 0); 735 /* After restoring from 'saved' state, machine-window(s) geometry should be adjusted: */ 736 machineLogic()->adjustMachineWindowsGeometry(); 737 } 738 else 739 msgCenter().showModalProgressDialog(progress, machineName(), ":/progress_start_90px.png"); 740 741 /* Check for progress failure: */ 742 if (!progress.isOk() || progress.GetResultCode() != 0) 743 { 744 if (vboxGlobal().showStartVMErrors()) 745 msgCenter().cannotStartMachine(progress, machineName()); 746 return false; 747 } 748 749 /* Add the disk encryption passwords: */ 750 if (!encryptionPasswords.isEmpty()) 751 { 752 foreach (const QString &strKey, encryptionPasswords.keys()) 753 { 754 console().AddDiskEncryptionPassword(strKey, encryptionPasswords.value(strKey), true); 755 if (!console().isOk()) 756 msgCenter().cannotAddDiskEncryptionPassword(console()); 757 } 758 } 759 760 /* Allow further auto-closing: */ 761 if (uimachine()->machineLogic()) 762 uimachine()->machineLogic()->setPreventAutoClose(false); 763 764 /* True by default: */ 765 return true; 766 } 767 768 bool UISession::saveState() 769 { 770 /* Prepare the saving progress: */ 771 CProgress progress = console().SaveState(); 772 if (console().isOk()) 773 { 774 /* Show the saving progress: */ 775 msgCenter().showModalProgressDialog(progress, machineName(), ":/progress_state_save_90px.png"); 776 if (!progress.isOk() || progress.GetResultCode() != 0) 777 { 778 /* Failed in progress: */ 779 msgCenter().cannotSaveMachineState(progress, machineName()); 780 return false; 781 } 782 } 783 else 784 { 785 /* Failed in console: */ 786 msgCenter().cannotSaveMachineState(console()); 787 return false; 788 } 789 /* Passed: */ 790 return true; 791 } 792 793 bool UISession::shutdown() 794 { 795 /* Send ACPI shutdown signal if possible: */ 796 console().PowerButton(); 797 if (!console().isOk()) 798 { 799 /* Failed in console: */ 800 msgCenter().cannotACPIShutdownMachine(console()); 801 return false; 802 } 803 /* Passed: */ 804 return true; 805 } 806 807 bool UISession::powerOff(bool fIncludingDiscard, bool &fServerCrashed) 808 { 809 /* Prepare the power-off progress: */ 810 CProgress progress = console().PowerDown(); 811 if (console().isOk()) 812 { 813 /* Show the power-off progress: */ 814 msgCenter().showModalProgressDialog(progress, machineName(), ":/progress_poweroff_90px.png"); 815 if (progress.isOk() && progress.GetResultCode() == 0) 816 { 817 /* Discard the current state if requested: */ 818 if (fIncludingDiscard) 819 return restoreCurrentSnapshot(); 820 } 821 else 822 { 823 /* Failed in progress: */ 824 msgCenter().cannotPowerDownMachine(progress, machineName()); 825 return false; 826 } 827 } 828 else 829 { 830 /* Check the machine state, it might be already gone: */ 831 if (!console().isNull()) 832 { 833 /* Failed in console: */ 834 COMResult res(console()); 835 /* This can happen if VBoxSVC is not running: */ 836 if (FAILED_DEAD_INTERFACE(res.rc())) 837 fServerCrashed = true; 838 else 839 msgCenter().cannotPowerDownMachine(console()); 840 return false; 841 } 842 } 843 /* Passed: */ 844 return true; 845 } 846 847 bool UISession::restoreCurrentSnapshot() 848 { 849 /* Prepare result: */ 850 bool fResult = false; 851 852 /* Simulate try-catch block: */ 853 do 854 { 855 /* Search for corresponding VM: */ 856 CVirtualBox vbox = vboxGlobal().virtualBox(); 857 const QString strMachineID = vboxGlobal().managedVMUuid(); 858 const CMachine mach = vbox.FindMachine(strMachineID); 859 if (!vbox.isOk() || mach.isNull()) 860 { 861 /* Unable to find VM: */ 862 msgCenter().cannotFindMachineById(vbox, strMachineID); 863 break; 864 } 865 866 /* Open a direct session to modify that VM: */ 867 CSession sess = vboxGlobal().openSession(vboxGlobal().managedVMUuid(), 868 vboxGlobal().isSeparateProcess() 869 ? KLockType_Write : KLockType_Shared); 870 if (sess.isNull()) 871 { 872 /* Unable to open session: */ 873 break; 874 } 875 876 /* Simulate try-catch block: */ 877 do 878 { 879 /* Acquire console for this session: */ 880 CConsole cons = sess.GetConsole(); 881 if (cons.isNull()) 882 { 883 /* Unable to acquire console: */ 884 break; 885 } 886 887 /* Prepare the snapshot-discard progress: */ 888 const CSnapshot snap = mach.GetCurrentSnapshot(); 889 CProgress prog = cons.RestoreSnapshot(snap); 890 if (!cons.isOk() || prog.isNull()) 891 { 892 /* Unable to restore snapshot: */ 893 msgCenter().cannotRestoreSnapshot(cons, snap.GetName(), machineName()); 894 break; 895 } 896 897 /* Show the snapshot-discard progress: */ 898 msgCenter().showModalProgressDialog(prog, mach.GetName(), ":/progress_snapshot_discard_90px.png"); 899 if (prog.GetResultCode() != 0) 900 { 901 /* Unable to restore snapshot: */ 902 msgCenter().cannotRestoreSnapshot(prog, snap.GetName(), mach.GetName()); 903 break; 904 } 905 906 /* Success: */ 907 fResult = true; 908 } 909 while (0); 910 911 /* Unlock machine finally: */ 912 sess.UnlockMachine(); 913 } 914 while (0); 915 916 /* Return result: */ 917 return fResult; 918 } 919 920 void UISession::closeRuntimeUI() 921 { 922 /* Start corresponding slot asynchronously: */ 923 emit sigCloseRuntimeUI(); 924 } 925 926 UIMachineLogic* UISession::machineLogic() const 927 { 928 return uimachine() ? uimachine()->machineLogic() : 0; 929 } 930 931 QWidget* UISession::mainMachineWindow() const 932 { 933 return machineLogic() ? machineLogic()->mainMachineWindow() : 0; 934 } 935 936 bool UISession::isVisualStateAllowed(UIVisualStateType state) const 937 { 938 return m_pMachine->isVisualStateAllowed(state); 939 } 940 941 void UISession::changeVisualState(UIVisualStateType visualStateType) 942 { 943 m_pMachine->asyncChangeVisualState(visualStateType); 944 } 945 946 bool UISession::setPause(bool fOn) 947 { 948 if (fOn) 949 console().Pause(); 950 else 951 console().Resume(); 952 953 bool ok = console().isOk(); 954 if (!ok) 955 { 956 if (fOn) 957 msgCenter().cannotPauseMachine(console()); 958 else 959 msgCenter().cannotResumeMachine(console()); 960 } 961 962 return ok; 963 } 964 965 void UISession::sltInstallGuestAdditionsFrom(const QString &strSource) 966 { 967 /* This flag indicates whether we want to do the usual .ISO mounting or not. 968 * First try updating the Guest Additions directly without mounting the .ISO. */ 969 bool fDoMount = false; 970 971 /* Auto-update in GUI currently is disabled. */ 972 #ifndef VBOX_WITH_ADDITIONS_AUTOUPDATE_UI 973 fDoMount = true; 974 #else /* VBOX_WITH_ADDITIONS_AUTOUPDATE_UI */ 975 QVector<KAdditionsUpdateFlag> aFlagsUpdate; 976 QVector<QString> aArgs; 977 CProgress progressInstall = guest().UpdateGuestAdditions(strSource, 978 aArgs, aFlagsUpdate); 979 bool fResult = guest().isOk(); 980 if (fResult) 981 { 982 msgCenter().showModalProgressDialog(progressInstall, tr("Updating Guest Additions"), 983 ":/progress_install_guest_additions_90px.png", 984 0, 500 /* 500ms delay. */); 985 if (progressInstall.GetCanceled()) 986 return; 987 988 HRESULT rc = progressInstall.GetResultCode(); 989 if (!progressInstall.isOk() || rc != S_OK) 990 { 991 /* If we got back a VBOX_E_NOT_SUPPORTED we don't complain (guest OS 992 * simply isn't supported yet), so silently fall back to "old" .ISO 993 * mounting method. */ 994 if ( !SUCCEEDED_WARNING(rc) 995 && rc != VBOX_E_NOT_SUPPORTED) 996 { 997 msgCenter().cannotUpdateGuestAdditions(progressInstall); 998 999 /* Log the error message in the release log. */ 1000 QString strErr = progressInstall.GetErrorInfo().GetText(); 1001 if (!strErr.isEmpty()) 1002 LogRel(("%s\n", strErr.toLatin1().constData())); 1003 } 1004 fDoMount = true; /* Since automatic updating failed, fall back to .ISO mounting. */ 1005 } 1006 } 1007 #endif /* VBOX_WITH_ADDITIONS_AUTOUPDATE_UI */ 1008 1009 /* Do we still want mounting? */ 1010 if (!fDoMount) 1011 return; 1012 1013 /* Open corresponding medium: */ 1014 QString strMediumID; 1015 CVirtualBox vbox = vboxGlobal().virtualBox(); 1016 CMedium image = vbox.OpenMedium(strSource, KDeviceType_DVD, KAccessMode_ReadWrite, false /* fForceNewUuid */); 1017 if (vbox.isOk() && !image.isNull()) 1018 strMediumID = image.GetId(); 1019 else 1020 { 1021 msgCenter().cannotOpenMedium(vbox, UIMediumType_DVD, strSource, mainMachineWindow()); 1022 return; 1023 } 1024 1025 /* Make sure GA medium ID is valid: */ 1026 AssertReturnVoid(!strMediumID.isNull()); 1027 1028 /* Searching for the first suitable controller/slot: */ 1029 QString strControllerName; 1030 LONG iCntPort = -1, iCntDevice = -1; 1031 foreach (const CStorageController &controller, machine().GetStorageControllers()) 1032 { 1033 foreach (const CMediumAttachment &attachment, machine().GetMediumAttachmentsOfController(controller.GetName())) 1034 { 1035 if (attachment.GetType() == KDeviceType_DVD) 1036 { 1037 strControllerName = controller.GetName(); 1038 iCntPort = attachment.GetPort(); 1039 iCntDevice = attachment.GetDevice(); 1040 break; 1041 } 1042 } 1043 if (!strControllerName.isNull()) 1044 break; 1045 } 1046 1047 /* Make sure suitable controller/slot were found: */ 1048 if (strControllerName.isNull()) 1049 { 1050 msgCenter().cannotMountGuestAdditions(machineName()); 1051 return; 1052 } 1053 1054 /* Try to find UIMedium among cached: */ 1055 UIMedium medium = vboxGlobal().medium(strMediumID); 1056 if (medium.isNull()) 1057 { 1058 /* Create new one if necessary: */ 1059 medium = UIMedium(image, UIMediumType_DVD, KMediumState_Created); 1060 vboxGlobal().createMedium(medium); 1061 } 1062 1063 /* Mount medium to corresponding controller/slot: */ 1064 machine().MountMedium(strControllerName, iCntPort, iCntDevice, medium.medium(), false /* force */); 1065 if (!machine().isOk()) 1066 { 1067 /* Ask for force mounting: */ 1068 if (msgCenter().cannotRemountMedium(machine(), medium, true /* mount? */, 1069 true /* retry? */, mainMachineWindow())) 1070 { 1071 /* Force mount medium to the predefined port/device: */ 1072 machine().MountMedium(strControllerName, iCntPort, iCntDevice, medium.medium(), true /* force */); 1073 if (!machine().isOk()) 1074 msgCenter().cannotRemountMedium(machine(), medium, true /* mount? */, 1075 false /* retry? */, mainMachineWindow()); 1076 } 1077 } 1078 } 1079 1080 void UISession::sltCloseRuntimeUI() 1081 { 1082 /* First, we have to hide any opened modal/popup widgets. 1083 * They then should unlock their event-loops synchronously. 1084 * If all such loops are unlocked, we can close Runtime UI: */ 1085 if (QWidget *pWidget = QApplication::activeModalWidget() ? 1086 QApplication::activeModalWidget() : 1087 QApplication::activePopupWidget() ? 1088 QApplication::activePopupWidget() : 0) 1089 { 1090 /* First we should try to close this widget: */ 1091 pWidget->close(); 1092 /* If widget rejected the 'close-event' we can 1093 * still hide it and hope it will behave correctly 1094 * and unlock his event-loop if any: */ 1095 if (!pWidget->isHidden()) 1096 pWidget->hide(); 1097 /* Restart this slot: */ 1098 emit sigCloseRuntimeUI(); 1099 return; 1100 } 1101 1102 /* Finally close the Runtime UI: */ 1103 UIMachine::destroy(); 1104 } 1105 1106 #ifdef RT_OS_DARWIN 1107 void UISession::sltHandleMenuBarConfigurationChange(const QString &strMachineID) 1108 { 1109 /* Skip unrelated machine IDs: */ 1110 if (vboxGlobal().managedVMUuid() != strMachineID) 1111 return; 1112 1113 /* Update Mac OS X menu-bar: */ 1114 updateMenu(); 1115 } 1116 #endif /* RT_OS_DARWIN */ 1117 1118 void UISession::sltMousePointerShapeChange(bool fVisible, bool fAlpha, QPoint hotCorner, QSize size, QVector<uint8_t> shape) 1119 { 1120 /* In case of shape data is present: */ 1121 if (shape.size() > 0) 1122 { 1123 /* We are ignoring visibility flag: */ 1124 m_fIsHidingHostPointer = false; 1125 1126 /* And updating current cursor shape: */ 1127 setPointerShape(shape.data(), fAlpha, 1128 hotCorner.x(), hotCorner.y(), 1129 size.width(), size.height()); 1130 } 1131 /* In case of shape data is NOT present: */ 1132 else 1133 { 1134 /* Remember if we should hide the cursor: */ 1135 m_fIsHidingHostPointer = !fVisible; 1136 } 1137 1138 /* Notify listeners about mouse capability changed: */ 1139 emit sigMousePointerShapeChange(); 1140 1141 } 1142 1143 void UISession::sltMouseCapabilityChange(bool fSupportsAbsolute, bool fSupportsRelative, bool fSupportsMultiTouch, bool fNeedsHostCursor) 1144 { 1145 LogRelFlow(("UISession::sltMouseCapabilityChange: " 1146 "Supports absolute: %s, Supports relative: %s, " 1147 "Supports multi-touch: %s, Needs host cursor: %s\n", 1148 fSupportsAbsolute ? "TRUE" : "FALSE", fSupportsRelative ? "TRUE" : "FALSE", 1149 fSupportsMultiTouch ? "TRUE" : "FALSE", fNeedsHostCursor ? "TRUE" : "FALSE")); 1150 1151 /* Check if something had changed: */ 1152 if ( m_fIsMouseSupportsAbsolute != fSupportsAbsolute 1153 || m_fIsMouseSupportsRelative != fSupportsRelative 1154 || m_fIsMouseSupportsMultiTouch != fSupportsMultiTouch 1155 || m_fIsMouseHostCursorNeeded != fNeedsHostCursor) 1156 { 1157 /* Store new data: */ 1158 m_fIsMouseSupportsAbsolute = fSupportsAbsolute; 1159 m_fIsMouseSupportsRelative = fSupportsRelative; 1160 m_fIsMouseSupportsMultiTouch = fSupportsMultiTouch; 1161 m_fIsMouseHostCursorNeeded = fNeedsHostCursor; 1162 1163 /* Notify listeners about mouse capability changed: */ 1164 emit sigMouseCapabilityChange(); 1165 } 1166 } 1167 1168 void UISession::sltKeyboardLedsChangeEvent(bool fNumLock, bool fCapsLock, bool fScrollLock) 1169 { 1170 /* Check if something had changed: */ 1171 if ( m_fNumLock != fNumLock 1172 || m_fCapsLock != fCapsLock 1173 || m_fScrollLock != fScrollLock) 1174 { 1175 /* Store new num lock data: */ 1176 if (m_fNumLock != fNumLock) 1177 { 1178 m_fNumLock = fNumLock; 1179 m_uNumLockAdaptionCnt = 2; 1180 } 1181 1182 /* Store new caps lock data: */ 1183 if (m_fCapsLock != fCapsLock) 1184 { 1185 m_fCapsLock = fCapsLock; 1186 m_uCapsLockAdaptionCnt = 2; 1187 } 1188 1189 /* Store new scroll lock data: */ 1190 if (m_fScrollLock != fScrollLock) 1191 { 1192 m_fScrollLock = fScrollLock; 1193 } 1194 1195 /* Notify listeners about mouse capability changed: */ 1196 emit sigKeyboardLedsChange(); 1197 } 1198 } 1199 1200 void UISession::sltStateChange(KMachineState state) 1201 { 1202 /* Check if something had changed: */ 1203 if (m_machineState != state) 1204 { 1205 /* Store new data: */ 1206 m_machineStatePrevious = m_machineState; 1207 m_machineState = state; 1208 1209 /* Notify listeners about machine state changed: */ 1210 emit sigMachineStateChange(); 1211 } 1212 } 1213 1214 void UISession::sltVRDEChange() 1215 { 1216 /* Make sure VRDE server is present: */ 1217 const CVRDEServer server = machine().GetVRDEServer(); 1218 AssertMsgReturnVoid(machine().isOk() && !server.isNull(), 1219 ("VRDE server should NOT be null!\n")); 1220 1221 /* Check/Uncheck VRDE Server action depending on feature status: */ 1222 actionPool()->action(UIActionIndexRT_M_View_T_VRDEServer)->blockSignals(true); 1223 actionPool()->action(UIActionIndexRT_M_View_T_VRDEServer)->setChecked(server.GetEnabled()); 1224 actionPool()->action(UIActionIndexRT_M_View_T_VRDEServer)->blockSignals(false); 1225 1226 /* Notify listeners about VRDE change: */ 1227 emit sigVRDEChange(); 1228 } 1229 1230 void UISession::sltVideoCaptureChange() 1231 { 1232 /* Check/Uncheck Video Capture action depending on feature status: */ 1233 actionPool()->action(UIActionIndexRT_M_View_M_VideoCapture_T_Start)->blockSignals(true); 1234 actionPool()->action(UIActionIndexRT_M_View_M_VideoCapture_T_Start)->setChecked(machine().GetVideoCaptureEnabled()); 1235 actionPool()->action(UIActionIndexRT_M_View_M_VideoCapture_T_Start)->blockSignals(false); 1236 1237 /* Notify listeners about Video Capture change: */ 1238 emit sigVideoCaptureChange(); 1239 } 1240 1241 void UISession::sltGuestMonitorChange(KGuestMonitorChangedEventType changeType, ulong uScreenId, QRect screenGeo) 1242 { 1243 /* Ignore KGuestMonitorChangedEventType_NewOrigin change event: */ 1244 if (changeType == KGuestMonitorChangedEventType_NewOrigin) 1245 return; 1246 /* Ignore KGuestMonitorChangedEventType_Disabled event for primary screen: */ 1247 AssertMsg(countOfVisibleWindows() > 0, ("All machine windows are hidden!")); 1248 if (changeType == KGuestMonitorChangedEventType_Disabled && uScreenId == 0) 1249 return; 1250 1251 /* Process KGuestMonitorChangedEventType_Enabled change event: */ 1252 if ( !isScreenVisible(uScreenId) 1253 && changeType == KGuestMonitorChangedEventType_Enabled) 1254 setScreenVisible(uScreenId, true); 1255 /* Process KGuestMonitorChangedEventType_Disabled change event: */ 1256 else if ( isScreenVisible(uScreenId) 1257 && changeType == KGuestMonitorChangedEventType_Disabled) 1258 setScreenVisible(uScreenId, false); 1259 1260 /* Notify listeners about the change: */ 1261 emit sigGuestMonitorChange(changeType, uScreenId, screenGeo); 1262 } 1263 1264 #ifdef RT_OS_DARWIN 1265 /** 1266 * MacOS X: Restarts display-reconfiguration watchdog timer from the beginning. 1267 * @note Watchdog is trying to determine display reconfiguration in 1268 * UISession::sltCheckIfHostDisplayChanged() slot every 500ms for 40 tries. 1269 */ 1270 void UISession::sltHandleHostDisplayAboutToChange() 1271 { 1272 LogRelFlow(("UISession::sltHandleHostDisplayAboutToChange()\n")); 1273 1274 if (m_pWatchdogDisplayChange->isActive()) 1275 m_pWatchdogDisplayChange->stop(); 1276 m_pWatchdogDisplayChange->setProperty("tryNumber", 1); 1277 m_pWatchdogDisplayChange->start(); 1278 } 1279 1280 /** 1281 * MacOS X: Determines display reconfiguration. 1282 * @note Calls for UISession::sltHandleHostScreenCountChange() if screen count changed. 1283 * @note Calls for UISession::sltHandleHostScreenGeometryChange() if screen geometry changed. 1284 */ 1285 void UISession::sltCheckIfHostDisplayChanged() 1286 { 1287 LogRelFlow(("UISession::sltCheckIfHostDisplayChanged()\n")); 1288 1289 /* Acquire desktop wrapper: */ 1290 QDesktopWidget *pDesktop = QApplication::desktop(); 1291 1292 /* Check if display count changed: */ 1293 if (pDesktop->screenCount() != m_hostScreens.size()) 1294 { 1295 /* Reset watchdog: */ 1296 m_pWatchdogDisplayChange->setProperty("tryNumber", 0); 1297 /* Notify listeners about screen-count changed: */ 1298 return sltHandleHostScreenCountChange(); 1299 } 1300 else 1301 { 1302 /* Check if at least one display geometry changed: */ 1303 for (int iScreenIndex = 0; iScreenIndex < pDesktop->screenCount(); ++iScreenIndex) 1304 { 1305 if (pDesktop->screenGeometry(iScreenIndex) != m_hostScreens.at(iScreenIndex)) 1306 { 1307 /* Reset watchdog: */ 1308 m_pWatchdogDisplayChange->setProperty("tryNumber", 0); 1309 /* Notify listeners about screen-geometry changed: */ 1310 return sltHandleHostScreenGeometryChange(); 1311 } 1312 } 1313 } 1314 1315 /* Check if watchdog expired, restart if not: */ 1316 int cTryNumber = m_pWatchdogDisplayChange->property("tryNumber").toInt(); 1317 if (cTryNumber > 0 && cTryNumber < 40) 1318 { 1319 /* Restart watchdog again: */ 1320 m_pWatchdogDisplayChange->setProperty("tryNumber", ++cTryNumber); 1321 m_pWatchdogDisplayChange->start(); 1322 } 1323 else 1324 { 1325 /* Reset watchdog: */ 1326 m_pWatchdogDisplayChange->setProperty("tryNumber", 0); 1327 } 1328 } 1329 #endif /* RT_OS_DARWIN */ 1330 1331 void UISession::sltHandleHostScreenCountChange() 1332 { 1333 LogRelFlow(("UISession: Host-screen count changed.\n")); 1334 1335 /* Recache display data: */ 1336 updateHostScreenData(); 1337 1338 /* Notify current machine-logic: */ 1339 emit sigHostScreenCountChange(); 1340 } 1341 1342 void UISession::sltHandleHostScreenGeometryChange() 1343 { 1344 LogRelFlow(("UISession: Host-screen geometry changed.\n")); 1345 1346 /* Recache display data: */ 1347 updateHostScreenData(); 1348 1349 /* Notify current machine-logic: */ 1350 emit sigHostScreenGeometryChange(); 1351 } 1352 1353 void UISession::sltHandleHostScreenAvailableAreaChange() 1354 { 1355 LogRelFlow(("UISession: Host-screen available-area changed.\n")); 1356 1357 /* Notify current machine-logic: */ 1358 emit sigHostScreenAvailableAreaChange(); 1359 } 1360 1361 void UISession::sltAdditionsChange() 1362 { 1363 /* Variable flags: */ 1364 ULONG ulGuestAdditionsRunLevel = guest().GetAdditionsRunLevel(); 1365 LONG64 lLastUpdatedIgnored; 1366 bool fIsGuestSupportsGraphics = guest().GetFacilityStatus(KAdditionsFacilityType_Graphics, lLastUpdatedIgnored) 1367 == KAdditionsFacilityStatus_Active; 1368 bool fIsGuestSupportsSeamless = guest().GetFacilityStatus(KAdditionsFacilityType_Seamless, lLastUpdatedIgnored) 1369 == KAdditionsFacilityStatus_Active; 1370 /* Check if something had changed: */ 1371 if (m_ulGuestAdditionsRunLevel != ulGuestAdditionsRunLevel || 1372 m_fIsGuestSupportsGraphics != fIsGuestSupportsGraphics || 1373 m_fIsGuestSupportsSeamless != fIsGuestSupportsSeamless) 1374 { 1375 /* Store new data: */ 1376 m_ulGuestAdditionsRunLevel = ulGuestAdditionsRunLevel; 1377 m_fIsGuestSupportsGraphics = fIsGuestSupportsGraphics; 1378 m_fIsGuestSupportsSeamless = fIsGuestSupportsSeamless; 1379 1380 /* Notify listeners about guest additions state really changed: */ 1381 emit sigAdditionsStateActualChange(); 1382 } 1383 1384 /* Notify listeners about guest additions state event came: */ 1385 emit sigAdditionsStateChange(); 1386 } 1387 1388 UISession::UISession(UIMachine *pMachine) 1389 : QObject(pMachine) 1390 /* Base variables: */ 1391 , m_pMachine(pMachine) 1392 , m_pActionPool(0) 1393 #ifdef Q_WS_MAC 1394 , m_pMenuBar(0) 1395 #endif /* Q_WS_MAC */ 1396 /* Common variables: */ 1397 , m_machineStatePrevious(KMachineState_Null) 1398 , m_machineState(KMachineState_Null) 1399 #ifndef Q_WS_MAC 1400 , m_pMachineWindowIcon(0) 1401 #endif /* !Q_WS_MAC */ 1402 , m_mouseCapturePolicy(MouseCapturePolicy_Default) 1403 , m_guruMeditationHandlerType(GuruMeditationHandlerType_Default) 1404 , m_hiDPIOptimizationType(HiDPIOptimizationType_None) 1405 , m_requestedVisualStateType(UIVisualStateType_Invalid) 1406 #ifdef Q_WS_WIN 1407 , m_alphaCursor(0) 1408 #endif /* Q_WS_WIN */ 1409 #ifdef Q_WS_MAC 1410 , m_pWatchdogDisplayChange(0) 1411 #endif /* Q_WS_MAC */ 1412 , m_defaultCloseAction(MachineCloseAction_Invalid) 1413 , m_restrictedCloseActions(MachineCloseAction_Invalid) 1414 , m_fAllCloseActionsRestricted(false) 1415 /* Common flags: */ 1416 , m_fInitialized(false) 1417 , m_fIsFirstTimeStarted(false) 1418 , m_fIsGuestResizeIgnored(false) 1419 , m_fIsAutoCaptureDisabled(false) 1420 /* Guest additions flags: */ 1421 , m_ulGuestAdditionsRunLevel(0) 1422 , m_fIsGuestSupportsGraphics(false) 1423 , m_fIsGuestSupportsSeamless(false) 1424 /* Mouse flags: */ 1425 , m_fNumLock(false) 1426 , m_fCapsLock(false) 1427 , m_fScrollLock(false) 1428 , m_uNumLockAdaptionCnt(2) 1429 , m_uCapsLockAdaptionCnt(2) 1430 /* Mouse flags: */ 1431 , m_fIsMouseSupportsAbsolute(false) 1432 , m_fIsMouseSupportsRelative(false) 1433 , m_fIsMouseSupportsMultiTouch(false) 1434 , m_fIsMouseHostCursorNeeded(false) 1435 , m_fIsMouseCaptured(false) 1436 , m_fIsMouseIntegrated(true) 1437 , m_fIsValidPointerShapePresent(false) 1438 , m_fIsHidingHostPointer(true) 1439 { 1440 } 1441 1442 UISession::~UISession() 1443 { 1444 } 1445 1446 bool UISession::prepare() 1447 { 1448 /* Prepare session: */ 1449 if (!prepareSession()) 1450 return false; 1451 1452 /* Prepare actions: */ 1453 prepareActions(); 1454 1455 /* Prepare connections: */ 1456 prepareConnections(); 1457 1458 /* Prepare console event-handlers: */ 1459 prepareConsoleEventHandlers(); 1460 1461 /* Prepare screens: */ 1462 prepareScreens(); 1463 1464 /* Prepare framebuffers: */ 1465 prepareFramebuffers(); 1466 1467 /* Load settings: */ 1468 loadSessionSettings(); 1469 1470 #ifdef VBOX_GUI_WITH_KEYS_RESET_HANDLER 1471 struct sigaction sa; 1472 sa.sa_sigaction = &signalHandlerSIGUSR1; 1473 sigemptyset(&sa.sa_mask); 1474 sa.sa_flags = SA_RESTART | SA_SIGINFO; 1475 sigaction(SIGUSR1, &sa, NULL); 1476 #endif /* VBOX_GUI_WITH_KEYS_RESET_HANDLER */ 1477 1478 /* True by default: */ 1479 return true; 1480 } 1481 1482 bool UISession::prepareSession() 1483 { 1484 /* Open session: */ 1485 m_session = vboxGlobal().openSession(vboxGlobal().managedVMUuid(), 1486 vboxGlobal().isSeparateProcess() 1487 ? KLockType_Shared : KLockType_VM); 1488 if (m_session.isNull()) 1489 return false; 1490 1491 /* Get machine: */ 1492 m_machine = m_session.GetMachine(); 1493 if (m_machine.isNull()) 1494 return false; 1495 1496 /* Get console: */ 1497 m_console = m_session.GetConsole(); 1498 if (m_console.isNull()) 1499 return false; 1500 1501 /* Get display: */ 1502 m_display = m_console.GetDisplay(); 1503 if (m_display.isNull()) 1504 return false; 1505 1506 /* Get guest: */ 1507 m_guest = m_console.GetGuest(); 1508 if (m_guest.isNull()) 1509 return false; 1510 1511 /* Get mouse: */ 1512 m_mouse = m_console.GetMouse(); 1513 if (m_mouse.isNull()) 1514 return false; 1515 1516 /* Get keyboard: */ 1517 m_keyboard = m_console.GetKeyboard(); 1518 if (m_keyboard.isNull()) 1519 return false; 1520 1521 /* Get debugger: */ 1522 m_debugger = m_console.GetDebugger(); 1523 if (m_debugger.isNull()) 1524 return false; 1525 1526 /* Update machine-name: */ 1527 m_strMachineName = machine().GetName(); 1528 1529 /* Update machine-state: */ 1530 m_machineState = machine().GetState(); 1531 1532 /* True by default: */ 1533 return true; 1534 } 1535 1536 void UISession::prepareActions() 1537 { 1538 /* Create action-pool: */ 1539 m_pActionPool = UIActionPool::create(UIActionPoolType_Runtime); 1540 AssertPtrReturnVoid(actionPool()); 1541 { 1542 /* Configure action-pool: */ 1543 actionPool()->toRuntime()->setSession(this); 1544 1545 /* Get host: */ 1546 const CHost host = vboxGlobal().host(); 1547 UIExtraDataMetaDefs::RuntimeMenuViewActionType restrictionForView = UIExtraDataMetaDefs::RuntimeMenuViewActionType_Invalid; 1548 UIExtraDataMetaDefs::RuntimeMenuDevicesActionType restrictionForDevices = UIExtraDataMetaDefs::RuntimeMenuDevicesActionType_Invalid; 1549 1550 /* VRDE server stuff: */ 1551 { 1552 /* Initialize 'View' menu: */ 1553 const CVRDEServer server = machine().GetVRDEServer(); 1554 if (server.isNull()) 1555 restrictionForView = (UIExtraDataMetaDefs::RuntimeMenuViewActionType)(restrictionForView | UIExtraDataMetaDefs::RuntimeMenuViewActionType_VRDEServer); 1556 } 1557 1558 /* Storage stuff: */ 1559 { 1560 /* Initialize CD/FD menus: */ 1561 int iDevicesCountCD = 0; 1562 int iDevicesCountFD = 0; 1563 foreach (const CMediumAttachment &attachment, machine().GetMediumAttachments()) 1564 { 1565 if (attachment.GetType() == KDeviceType_DVD) 1566 ++iDevicesCountCD; 1567 if (attachment.GetType() == KDeviceType_Floppy) 1568 ++iDevicesCountFD; 1569 } 1570 QAction *pOpticalDevicesMenu = actionPool()->action(UIActionIndexRT_M_Devices_M_OpticalDevices); 1571 QAction *pFloppyDevicesMenu = actionPool()->action(UIActionIndexRT_M_Devices_M_FloppyDevices); 1572 pOpticalDevicesMenu->setData(iDevicesCountCD); 1573 pFloppyDevicesMenu->setData(iDevicesCountFD); 1574 if (!iDevicesCountCD) 1575 restrictionForDevices = (UIExtraDataMetaDefs::RuntimeMenuDevicesActionType)(restrictionForDevices | UIExtraDataMetaDefs::RuntimeMenuDevicesActionType_OpticalDevices); 1576 if (!iDevicesCountFD) 1577 restrictionForDevices = (UIExtraDataMetaDefs::RuntimeMenuDevicesActionType)(restrictionForDevices | UIExtraDataMetaDefs::RuntimeMenuDevicesActionType_FloppyDevices); 1578 } 1579 1580 /* Network stuff: */ 1581 { 1582 /* Initialize Network menu: */ 1583 bool fAtLeastOneAdapterActive = false; 1584 const KChipsetType chipsetType = machine().GetChipsetType(); 1585 ULONG uSlots = vboxGlobal().virtualBox().GetSystemProperties().GetMaxNetworkAdapters(chipsetType); 1586 for (ULONG uSlot = 0; uSlot < uSlots; ++uSlot) 1587 { 1588 const CNetworkAdapter &adapter = machine().GetNetworkAdapter(uSlot); 1589 if (adapter.GetEnabled()) 1590 { 1591 fAtLeastOneAdapterActive = true; 1592 break; 1593 } 1594 } 1595 if (!fAtLeastOneAdapterActive) 1596 restrictionForDevices = (UIExtraDataMetaDefs::RuntimeMenuDevicesActionType)(restrictionForDevices | UIExtraDataMetaDefs::RuntimeMenuDevicesActionType_Network); 1597 } 1598 1599 /* USB stuff: */ 1600 { 1601 /* Check whether there is at least one USB controller with an available proxy. */ 1602 const bool fUSBEnabled = !machine().GetUSBDeviceFilters().isNull() 1603 && !machine().GetUSBControllers().isEmpty() 1604 && machine().GetUSBProxyAvailable(); 1605 if (!fUSBEnabled) 1606 restrictionForDevices = (UIExtraDataMetaDefs::RuntimeMenuDevicesActionType)(restrictionForDevices | UIExtraDataMetaDefs::RuntimeMenuDevicesActionType_USBDevices); 1607 } 1608 1609 /* WebCams stuff: */ 1610 { 1611 /* Check whether there is an accessible video input devices pool: */ 1612 host.GetVideoInputDevices(); 1613 const bool fWebCamsEnabled = host.isOk() && !machine().GetUSBControllers().isEmpty(); 1614 if (!fWebCamsEnabled) 1615 restrictionForDevices = (UIExtraDataMetaDefs::RuntimeMenuDevicesActionType)(restrictionForDevices | UIExtraDataMetaDefs::RuntimeMenuDevicesActionType_WebCams); 1616 } 1617 1618 /* Apply cumulative restriction for 'View' menu: */ 1619 actionPool()->toRuntime()->setRestrictionForMenuView(UIActionRestrictionLevel_Session, restrictionForView); 1620 /* Apply cumulative restriction for 'Devices' menu: */ 1621 actionPool()->toRuntime()->setRestrictionForMenuDevices(UIActionRestrictionLevel_Session, restrictionForDevices); 1622 1623 #ifdef Q_WS_MAC 1624 /* Create Mac OS X menu-bar: */ 1625 m_pMenuBar = new UIMenuBar; 1626 AssertPtrReturnVoid(m_pMenuBar); 1627 { 1628 /* Configure Mac OS X menu-bar: */ 1629 connect(gEDataManager, SIGNAL(sigMenuBarConfigurationChange(const QString&)), 1630 this, SLOT(sltHandleMenuBarConfigurationChange(const QString&))); 1631 /* Update Mac OS X menu-bar: */ 1632 updateMenu(); 1633 } 1634 #endif /* Q_WS_MAC */ 1635 } 1636 } 1637 1638 void UISession::prepareConnections() 1639 { 1640 connect(this, SIGNAL(sigInitialized()), this, SLOT(sltMarkInitialized())); 1641 connect(this, SIGNAL(sigCloseRuntimeUI()), this, SLOT(sltCloseRuntimeUI())); 1642 1643 #ifdef Q_WS_MAC 1644 /* Install native display reconfiguration callback: */ 1645 CGDisplayRegisterReconfigurationCallback(cgDisplayReconfigurationCallback, this); 1646 #else /* !Q_WS_MAC */ 1647 /* Install Qt display reconfiguration callbacks: */ 1648 connect(QApplication::desktop(), SIGNAL(screenCountChanged(int)), 1649 this, SLOT(sltHandleHostScreenCountChange())); 1650 connect(QApplication::desktop(), SIGNAL(resized(int)), 1651 this, SLOT(sltHandleHostScreenGeometryChange())); 1652 connect(QApplication::desktop(), SIGNAL(workAreaResized(int)), 1653 this, SLOT(sltHandleHostScreenAvailableAreaChange())); 1654 #endif /* !Q_WS_MAC */ 1655 } 1656 1657 void UISession::prepareConsoleEventHandlers() 1658 { 1659 /* Create console event-handler: */ 1660 UIConsoleEventHandler::create(this); 1661 1662 /* Add console event connections: */ 1663 connect(gConsoleEvents, SIGNAL(sigMousePointerShapeChange(bool, bool, QPoint, QSize, QVector<uint8_t>)), 1664 this, SLOT(sltMousePointerShapeChange(bool, bool, QPoint, QSize, QVector<uint8_t>))); 1665 1666 connect(gConsoleEvents, SIGNAL(sigMouseCapabilityChange(bool, bool, bool, bool)), 1667 this, SLOT(sltMouseCapabilityChange(bool, bool, bool, bool))); 1668 1669 connect(gConsoleEvents, SIGNAL(sigKeyboardLedsChangeEvent(bool, bool, bool)), 1670 this, SLOT(sltKeyboardLedsChangeEvent(bool, bool, bool))); 1671 1672 connect(gConsoleEvents, SIGNAL(sigStateChange(KMachineState)), 1673 this, SLOT(sltStateChange(KMachineState))); 1674 1675 connect(gConsoleEvents, SIGNAL(sigAdditionsChange()), 1676 this, SLOT(sltAdditionsChange())); 1677 1678 connect(gConsoleEvents, SIGNAL(sigVRDEChange()), 1679 this, SLOT(sltVRDEChange())); 1680 1681 connect(gConsoleEvents, SIGNAL(sigVideoCaptureChange()), 1682 this, SLOT(sltVideoCaptureChange())); 1683 1684 connect(gConsoleEvents, SIGNAL(sigNetworkAdapterChange(CNetworkAdapter)), 1685 this, SIGNAL(sigNetworkAdapterChange(CNetworkAdapter))); 1686 1687 connect(gConsoleEvents, SIGNAL(sigMediumChange(CMediumAttachment)), 1688 this, SIGNAL(sigMediumChange(CMediumAttachment))); 1689 1690 connect(gConsoleEvents, SIGNAL(sigUSBControllerChange()), 1691 this, SIGNAL(sigUSBControllerChange())); 1692 1693 connect(gConsoleEvents, SIGNAL(sigUSBDeviceStateChange(CUSBDevice, bool, CVirtualBoxErrorInfo)), 1694 this, SIGNAL(sigUSBDeviceStateChange(CUSBDevice, bool, CVirtualBoxErrorInfo))); 1695 1696 connect(gConsoleEvents, SIGNAL(sigSharedFolderChange()), 1697 this, SIGNAL(sigSharedFolderChange())); 1698 1699 connect(gConsoleEvents, SIGNAL(sigRuntimeError(bool, QString, QString)), 1700 this, SIGNAL(sigRuntimeError(bool, QString, QString))); 1701 1702 #ifdef Q_WS_MAC 1703 connect(gConsoleEvents, SIGNAL(sigShowWindow()), 1704 this, SIGNAL(sigShowWindows()), Qt::QueuedConnection); 1705 #endif /* Q_WS_MAC */ 1706 1707 connect(gConsoleEvents, SIGNAL(sigCPUExecutionCapChange()), 1708 this, SIGNAL(sigCPUExecutionCapChange())); 1709 1710 connect(gConsoleEvents, SIGNAL(sigGuestMonitorChange(KGuestMonitorChangedEventType, ulong, QRect)), 1711 this, SLOT(sltGuestMonitorChange(KGuestMonitorChangedEventType, ulong, QRect))); 1712 } 1713 1714 void UISession::prepareScreens() 1715 { 1716 /* Recache display data: */ 1717 updateHostScreenData(); 1718 1719 #ifdef Q_WS_MAC 1720 /* Prepare display-change watchdog: */ 1721 m_pWatchdogDisplayChange = new QTimer(this); 1722 { 1723 m_pWatchdogDisplayChange->setInterval(500); 1724 m_pWatchdogDisplayChange->setSingleShot(true); 1725 connect(m_pWatchdogDisplayChange, SIGNAL(timeout()), 1726 this, SLOT(sltCheckIfHostDisplayChanged())); 1727 } 1728 #endif /* Q_WS_MAC */ 1729 1730 /* Prepare initial screen visibility status: */ 1731 m_monitorVisibilityVector.resize(machine().GetMonitorCount()); 1732 m_monitorVisibilityVector.fill(false); 1733 m_monitorVisibilityVector[0] = true; 1734 1735 /* If machine is in 'saved' state: */ 1736 if (isSaved()) 1737 { 1738 /* Update screen visibility status from saved-state: */ 1739 for (int iScreenIndex = 0; iScreenIndex < m_monitorVisibilityVector.size(); ++iScreenIndex) 1740 { 1741 BOOL fEnabled = true; 1742 ULONG uGuestOriginX = 0, uGuestOriginY = 0, uGuestWidth = 0, uGuestHeight = 0; 1743 machine().QuerySavedGuestScreenInfo(iScreenIndex, 1744 uGuestOriginX, uGuestOriginY, 1745 uGuestWidth, uGuestHeight, fEnabled); 1746 m_monitorVisibilityVector[iScreenIndex] = fEnabled; 1747 } 1748 /* And make sure at least one of them is visible (primary if others are hidden): */ 1749 if (countOfVisibleWindows() < 1) 1750 m_monitorVisibilityVector[0] = true; 1751 } 1752 else if (vboxGlobal().isSeparateProcess()) 1753 { 1754 /* Update screen visibility status from display directly: */ 1755 for (int iScreenIndex = 0; iScreenIndex < m_monitorVisibilityVector.size(); ++iScreenIndex) 1756 { 1757 KGuestMonitorStatus enmStatus = KGuestMonitorStatus_Disabled; 1758 ULONG uGuestWidth = 0, uGuestHeight = 0, uBpp = 0; 1759 LONG iGuestOriginX = 0, iGuestOriginY = 0; 1760 display().GetScreenResolution(iScreenIndex, 1761 uGuestWidth, uGuestHeight, uBpp, 1762 iGuestOriginX, iGuestOriginY, enmStatus); 1763 m_monitorVisibilityVector[iScreenIndex] = (enmStatus == KGuestMonitorStatus_Enabled); 1764 } 1765 /* And make sure at least one of them is visible (primary if others are hidden): */ 1766 if (countOfVisibleWindows() < 1) 1767 m_monitorVisibilityVector[0] = true; 1768 } 1769 } 1770 1771 void UISession::prepareFramebuffers() 1772 { 1773 /* Each framebuffer will be really prepared on first UIMachineView creation: */ 1774 m_frameBufferVector.resize(machine().GetMonitorCount()); 1775 } 1776 1777 void UISession::loadSessionSettings() 1778 { 1779 /* Load extra-data settings: */ 1780 { 1781 /* Get machine ID: */ 1782 const QString strMachineID = vboxGlobal().managedVMUuid(); 1783 1784 #ifndef Q_WS_MAC 1785 /* Load/prepare user's machine-window icon: */ 1786 QIcon icon; 1787 foreach (const QString &strIconName, gEDataManager->machineWindowIconNames(strMachineID)) 1788 if (!strIconName.isEmpty()) 1789 icon.addFile(strIconName); 1790 if (!icon.isNull()) 1791 m_pMachineWindowIcon = new QIcon(icon); 1792 1793 /* Load user's machine-window name postfix: */ 1794 m_strMachineWindowNamePostfix = gEDataManager->machineWindowNamePostfix(strMachineID); 1795 #endif /* !Q_WS_MAC */ 1796 1797 /* Determine mouse-capture policy: */ 1798 m_mouseCapturePolicy = gEDataManager->mouseCapturePolicy(strMachineID); 1799 1800 /* Determine Guru Meditation handler type: */ 1801 m_guruMeditationHandlerType = gEDataManager->guruMeditationHandlerType(strMachineID); 1802 1803 /* Determine HiDPI optimization type: */ 1804 m_hiDPIOptimizationType = gEDataManager->hiDPIOptimizationType(strMachineID); 1805 1806 /* Is there should be First RUN Wizard? */ 1807 m_fIsFirstTimeStarted = gEDataManager->machineFirstTimeStarted(strMachineID); 1808 1809 /* Should guest autoresize? */ 1810 QAction *pGuestAutoresizeSwitch = actionPool()->action(UIActionIndexRT_M_View_T_GuestAutoresize); 1811 pGuestAutoresizeSwitch->setChecked(gEDataManager->guestScreenAutoResizeEnabled(strMachineID)); 1812 1813 #ifndef Q_WS_MAC 1814 /* Menu-bar options: */ 1815 { 1816 const bool fEnabledGlobally = !vboxGlobal().settings().isFeatureActive("noMenuBar"); 1817 const bool fEnabledForMachine = gEDataManager->menuBarEnabled(strMachineID); 1818 const bool fEnabled = fEnabledGlobally && fEnabledForMachine; 1819 QAction *pActionMenuBarSettings = actionPool()->action(UIActionIndexRT_M_View_M_MenuBar_S_Settings); 1820 pActionMenuBarSettings->setEnabled(fEnabled); 1821 QAction *pActionMenuBarSwitch = actionPool()->action(UIActionIndexRT_M_View_M_MenuBar_T_Visibility); 1822 pActionMenuBarSwitch->blockSignals(true); 1823 pActionMenuBarSwitch->setChecked(fEnabled); 1824 pActionMenuBarSwitch->blockSignals(false); 1825 } 1826 #endif /* !Q_WS_MAC */ 1827 1828 /* Status-bar options: */ 1829 { 1830 const bool fEnabledGlobally = !vboxGlobal().settings().isFeatureActive("noStatusBar"); 1831 const bool fEnabledForMachine = gEDataManager->statusBarEnabled(strMachineID); 1832 const bool fEnabled = fEnabledGlobally && fEnabledForMachine; 1833 QAction *pActionStatusBarSettings = actionPool()->action(UIActionIndexRT_M_View_M_StatusBar_S_Settings); 1834 pActionStatusBarSettings->setEnabled(fEnabled); 1835 QAction *pActionStatusBarSwitch = actionPool()->action(UIActionIndexRT_M_View_M_StatusBar_T_Visibility); 1836 pActionStatusBarSwitch->blockSignals(true); 1837 pActionStatusBarSwitch->setChecked(fEnabled); 1838 pActionStatusBarSwitch->blockSignals(false); 1839 } 1840 1841 /* Input options: */ 1842 actionPool()->action(UIActionIndexRT_M_Input_M_Mouse_T_Integration)->setChecked(isMouseIntegrated()); 1843 1844 /* What is the default close action and the restricted are? */ 1845 m_defaultCloseAction = gEDataManager->defaultMachineCloseAction(strMachineID); 1846 m_restrictedCloseActions = gEDataManager->restrictedMachineCloseActions(strMachineID); 1847 m_fAllCloseActionsRestricted = (!vboxGlobal().isSeparateProcess() || (m_restrictedCloseActions & MachineCloseAction_Detach)) 1848 && (m_restrictedCloseActions & MachineCloseAction_SaveState) 1849 && (m_restrictedCloseActions & MachineCloseAction_Shutdown) 1850 && (m_restrictedCloseActions & MachineCloseAction_PowerOff); 1851 // Close VM Dialog hides PowerOff_RestoringSnapshot implicitly if PowerOff is hidden.. 1852 // && (m_restrictedCloseActions & MachineCloseAction_PowerOff_RestoringSnapshot); 1853 } 1854 } 1855 1856 void UISession::saveSessionSettings() 1857 { 1858 /* Save extra-data settings: */ 1859 { 1860 /* Disable First RUN Wizard: */ 1861 gEDataManager->setMachineFirstTimeStarted(false, vboxGlobal().managedVMUuid()); 1862 1863 /* Remember if guest should autoresize: */ 1864 if (actionPool()) 1865 { 1866 const QAction *pGuestAutoresizeSwitch = actionPool()->action(UIActionIndexRT_M_View_T_GuestAutoresize); 1867 gEDataManager->setGuestScreenAutoResizeEnabled(pGuestAutoresizeSwitch->isChecked(), vboxGlobal().managedVMUuid()); 1868 } 1869 1870 #ifndef Q_WS_MAC 1871 /* Cleanup user's machine-window icon: */ 1872 delete m_pMachineWindowIcon; 1873 m_pMachineWindowIcon = 0; 1874 #endif /* !Q_WS_MAC */ 1875 } 1876 } 1877 1878 void UISession::cleanupFramebuffers() 1879 { 1880 /* Cleanup framebuffers finally: */ 1881 for (int i = m_frameBufferVector.size() - 1; i >= 0; --i) 1882 { 1883 UIFrameBuffer *pFrameBuffer = m_frameBufferVector[i]; 1884 if (pFrameBuffer) 1885 { 1886 /* Mark framebuffer as unused: */ 1887 pFrameBuffer->setMarkAsUnused(true); 1888 /* Detach framebuffer from Display: */ 1889 pFrameBuffer->detach(); 1890 /* Delete framebuffer reference: */ 1891 delete pFrameBuffer; 1892 } 1893 } 1894 m_frameBufferVector.clear(); 1895 } 1896 1897 void UISession::cleanupConsoleEventHandlers() 1898 { 1899 /* Destroy console event-handler if necessary: */ 1900 if (gConsoleEvents) 1901 UIConsoleEventHandler::destroy(); 1902 } 1903 1904 void UISession::cleanupConnections() 1905 { 1906 #ifdef Q_WS_MAC 1907 /* Remove display reconfiguration callback: */ 1908 CGDisplayRemoveReconfigurationCallback(cgDisplayReconfigurationCallback, this); 1909 #endif /* Q_WS_MAC */ 1910 } 1911 1912 void UISession::cleanupActions() 1913 { 1914 #ifdef Q_WS_MAC 1915 /* Destroy Mac OS X menu-bar: */ 1916 delete m_pMenuBar; 1917 m_pMenuBar = 0; 1918 #endif /* Q_WS_MAC */ 1919 1920 /* Destroy action-pool if necessary: */ 1921 if (actionPool()) 1922 UIActionPool::destroy(actionPool()); 1923 } 1924 1925 void UISession::cleanupSession() 1926 { 1927 /* Detach debugger: */ 1928 if (!m_debugger.isNull()) 1929 m_debugger.detach(); 1930 1931 /* Detach keyboard: */ 1932 if (!m_keyboard.isNull()) 1933 m_keyboard.detach(); 1934 1935 /* Detach mouse: */ 1936 if (!m_mouse.isNull()) 1937 m_mouse.detach(); 1938 1939 /* Detach guest: */ 1940 if (!m_guest.isNull()) 1941 m_guest.detach(); 1942 1943 /* Detach display: */ 1944 if (!m_display.isNull()) 1945 m_display.detach(); 1946 1947 /* Detach console: */ 1948 if (!m_console.isNull()) 1949 m_console.detach(); 1950 1951 /* Detach machine: */ 1952 if (!m_machine.isNull()) 1953 m_machine.detach(); 1954 1955 /* Close session: */ 1956 if (!m_session.isNull() && vboxGlobal().isVBoxSVCAvailable()) 1957 { 1958 m_session.UnlockMachine(); 1959 m_session.detach(); 1960 } 1961 } 1962 1963 void UISession::cleanup() 1964 { 1965 #ifdef Q_WS_WIN 1966 /* Destroy alpha cursor: */ 1967 if (m_alphaCursor) 1968 DestroyIcon(m_alphaCursor); 1969 #endif /* Q_WS_WIN */ 1970 1971 /* Save settings: */ 1972 saveSessionSettings(); 1973 1974 /* Cleanup framebuffers: */ 1975 cleanupFramebuffers(); 1976 1977 /* Cleanup console event-handlers: */ 1978 cleanupConsoleEventHandlers(); 1979 1980 /* Cleanup connections: */ 1981 cleanupConnections(); 1982 1983 /* Cleanup actions: */ 1984 cleanupActions(); 1985 1986 /* Cleanup session: */ 1987 cleanupSession(); 1988 } 1989 1990 #ifdef Q_WS_MAC 1991 void UISession::updateMenu() 1992 { 1993 /* Rebuild Mac OS X menu-bar: */ 1994 m_pMenuBar->clear(); 1995 foreach (QMenu *pMenu, actionPool()->menus()) 1996 { 1997 UIMenu *pMenuUI = qobject_cast<UIMenu*>(pMenu); 1998 if (!pMenuUI->isConsumable() || !pMenuUI->isConsumed()) 1999 m_pMenuBar->addMenu(pMenuUI); 2000 if (pMenuUI->isConsumable() && !pMenuUI->isConsumed()) 2001 pMenuUI->setConsumed(true); 2002 } 2003 } 2004 #endif /* Q_WS_MAC */ 2005 2006 WId UISession::winId() const 2007 { 2008 return mainMachineWindow()->winId(); 2009 } 2010 2011 void UISession::setPointerShape(const uchar *pShapeData, bool fHasAlpha, 2012 uint uXHot, uint uYHot, uint uWidth, uint uHeight) 2013 { 2014 AssertMsg(pShapeData, ("Shape data must not be NULL!\n")); 2015 2016 m_fIsValidPointerShapePresent = false; 2017 const uchar *srcAndMaskPtr = pShapeData; 2018 uint andMaskSize = (uWidth + 7) / 8 * uHeight; 2019 const uchar *srcShapePtr = pShapeData + ((andMaskSize + 3) & ~3); 2020 uint srcShapePtrScan = uWidth * 4; 2021 2022 #if defined (Q_WS_WIN) 2023 2024 BITMAPV5HEADER bi; 2025 HBITMAP hBitmap; 2026 void *lpBits; 2027 2028 ::ZeroMemory(&bi, sizeof (BITMAPV5HEADER)); 2029 bi.bV5Size = sizeof(BITMAPV5HEADER); 2030 bi.bV5Width = uWidth; 2031 bi.bV5Height = - (LONG)uHeight; 2032 bi.bV5Planes = 1; 2033 bi.bV5BitCount = 32; 2034 bi.bV5Compression = BI_BITFIELDS; 2035 bi.bV5RedMask = 0x00FF0000; 2036 bi.bV5GreenMask = 0x0000FF00; 2037 bi.bV5BlueMask = 0x000000FF; 2038 if (fHasAlpha) 2039 bi.bV5AlphaMask = 0xFF000000; 2040 else 2041 bi.bV5AlphaMask = 0; 2042 2043 HDC hdc = GetDC(NULL); 2044 2045 /* Create the DIB section with an alpha channel: */ 2046 hBitmap = CreateDIBSection(hdc, (BITMAPINFO *)&bi, DIB_RGB_COLORS, (void **)&lpBits, NULL, (DWORD) 0); 2047 2048 ReleaseDC(NULL, hdc); 2049 2050 HBITMAP hMonoBitmap = NULL; 2051 if (fHasAlpha) 2052 { 2053 /* Create an empty mask bitmap: */ 2054 hMonoBitmap = CreateBitmap(uWidth, uHeight, 1, 1, NULL); 2055 } 2056 else 2057 { 2058 /* Word aligned AND mask. Will be allocated and created if necessary. */ 2059 uint8_t *pu8AndMaskWordAligned = NULL; 2060 2061 /* Width in bytes of the original AND mask scan line. */ 2062 uint32_t cbAndMaskScan = (uWidth + 7) / 8; 2063 2064 if (cbAndMaskScan & 1) 2065 { 2066 /* Original AND mask is not word aligned. */ 2067 2068 /* Allocate memory for aligned AND mask. */ 2069 pu8AndMaskWordAligned = (uint8_t *)RTMemTmpAllocZ((cbAndMaskScan + 1) * uHeight); 2070 2071 Assert(pu8AndMaskWordAligned); 2072 2073 if (pu8AndMaskWordAligned) 2074 { 2075 /* According to MSDN the padding bits must be 0. 2076 * Compute the bit mask to set padding bits to 0 in the last byte of original AND mask. */ 2077 uint32_t u32PaddingBits = cbAndMaskScan * 8 - uWidth; 2078 Assert(u32PaddingBits < 8); 2079 uint8_t u8LastBytesPaddingMask = (uint8_t)(0xFF << u32PaddingBits); 2080 2081 Log(("u8LastBytesPaddingMask = %02X, aligned w = %d, width = %d, cbAndMaskScan = %d\n", 2082 u8LastBytesPaddingMask, (cbAndMaskScan + 1) * 8, uWidth, cbAndMaskScan)); 2083 2084 uint8_t *src = (uint8_t *)srcAndMaskPtr; 2085 uint8_t *dst = pu8AndMaskWordAligned; 2086 2087 unsigned i; 2088 for (i = 0; i < uHeight; i++) 2089 { 2090 memcpy(dst, src, cbAndMaskScan); 2091 2092 dst[cbAndMaskScan - 1] &= u8LastBytesPaddingMask; 2093 2094 src += cbAndMaskScan; 2095 dst += cbAndMaskScan + 1; 2096 } 2097 } 2098 } 2099 2100 /* Create the AND mask bitmap: */ 2101 hMonoBitmap = ::CreateBitmap(uWidth, uHeight, 1, 1, 2102 pu8AndMaskWordAligned? pu8AndMaskWordAligned: srcAndMaskPtr); 2103 2104 if (pu8AndMaskWordAligned) 2105 { 2106 RTMemTmpFree(pu8AndMaskWordAligned); 2107 } 2108 } 2109 2110 Assert(hBitmap); 2111 Assert(hMonoBitmap); 2112 if (hBitmap && hMonoBitmap) 2113 { 2114 DWORD *dstShapePtr = (DWORD *) lpBits; 2115 2116 for (uint y = 0; y < uHeight; y ++) 2117 { 2118 memcpy(dstShapePtr, srcShapePtr, srcShapePtrScan); 2119 srcShapePtr += srcShapePtrScan; 2120 dstShapePtr += uWidth; 2121 } 2122 2123 ICONINFO ii; 2124 ii.fIcon = FALSE; 2125 ii.xHotspot = uXHot; 2126 ii.yHotspot = uYHot; 2127 ii.hbmMask = hMonoBitmap; 2128 ii.hbmColor = hBitmap; 2129 2130 HCURSOR hAlphaCursor = CreateIconIndirect(&ii); 2131 Assert(hAlphaCursor); 2132 if (hAlphaCursor) 2133 { 2134 /* Set the new cursor: */ 2135 m_cursor = QCursor(hAlphaCursor); 2136 if (m_alphaCursor) 2137 DestroyIcon(m_alphaCursor); 2138 m_alphaCursor = hAlphaCursor; 2139 m_fIsValidPointerShapePresent = true; 2140 } 2141 } 2142 2143 if (hMonoBitmap) 2144 DeleteObject(hMonoBitmap); 2145 if (hBitmap) 2146 DeleteObject(hBitmap); 2147 2148 #elif defined (Q_WS_X11) && !defined (VBOX_WITHOUT_XCURSOR) 2149 2150 XcursorImage *img = XcursorImageCreate(uWidth, uHeight); 2151 Assert(img); 2152 if (img) 2153 { 2154 img->xhot = uXHot; 2155 img->yhot = uYHot; 2156 2157 XcursorPixel *dstShapePtr = img->pixels; 2158 2159 for (uint y = 0; y < uHeight; y ++) 2160 { 2161 memcpy (dstShapePtr, srcShapePtr, srcShapePtrScan); 2162 2163 if (!fHasAlpha) 2164 { 2165 /* Convert AND mask to the alpha channel: */ 2166 uchar byte = 0; 2167 for (uint x = 0; x < uWidth; x ++) 2168 { 2169 if (!(x % 8)) 2170 byte = *(srcAndMaskPtr ++); 2171 else 2172 byte <<= 1; 2173 2174 if (byte & 0x80) 2175 { 2176 /* Linux doesn't support inverted pixels (XOR ops, 2177 * to be exact) in cursor shapes, so we detect such 2178 * pixels and always replace them with black ones to 2179 * make them visible at least over light colors */ 2180 if (dstShapePtr [x] & 0x00FFFFFF) 2181 dstShapePtr [x] = 0xFF000000; 2182 else 2183 dstShapePtr [x] = 0x00000000; 2184 } 2185 else 2186 dstShapePtr [x] |= 0xFF000000; 2187 } 2188 } 2189 2190 srcShapePtr += srcShapePtrScan; 2191 dstShapePtr += uWidth; 2192 } 2193 2194 /* Set the new cursor: */ 2195 m_cursor = QCursor(XcursorImageLoadCursor(QX11Info::display(), img)); 2196 m_fIsValidPointerShapePresent = true; 2197 2198 XcursorImageDestroy(img); 2199 } 2200 2201 #elif defined(Q_WS_MAC) 2202 2203 /* Create a ARGB image out of the shape data. */ 2204 QImage image (uWidth, uHeight, QImage::Format_ARGB32); 2205 const uint8_t* pbSrcMask = static_cast<const uint8_t*> (srcAndMaskPtr); 2206 unsigned cbSrcMaskLine = RT_ALIGN (uWidth, 8) / 8; 2207 for (unsigned int y = 0; y < uHeight; ++y) 2208 { 2209 for (unsigned int x = 0; x < uWidth; ++x) 2210 { 2211 unsigned int color = ((unsigned int*)srcShapePtr)[y*uWidth+x]; 2212 /* If the alpha channel isn't in the shape data, we have to 2213 * create them from the and-mask. This is a bit field where 1 2214 * represent transparency & 0 opaque respectively. */ 2215 if (!fHasAlpha) 2216 { 2217 if (!(pbSrcMask[x / 8] & (1 << (7 - (x % 8))))) 2218 color |= 0xff000000; 2219 else 2220 { 2221 /* This isn't quite right, but it's the best we can do I think... */ 2222 if (color & 0x00ffffff) 2223 color = 0xff000000; 2224 else 2225 color = 0x00000000; 2226 } 2227 } 2228 image.setPixel (x, y, color); 2229 } 2230 /* Move one scanline forward. */ 2231 pbSrcMask += cbSrcMaskLine; 2232 } 2233 2234 /* Set the new cursor: */ 2235 m_cursor = QCursor(QPixmap::fromImage(image), uXHot, uYHot); 2236 m_fIsValidPointerShapePresent = true; 2237 NOREF(srcShapePtrScan); 2238 2239 #else 2240 2241 # warning "port me" 2242 2243 #endif 2244 } 2245 2246 bool UISession::preprocessInitialization() 2247 { 2248 #ifdef VBOX_WITH_NETFLT 2249 /* Skip further checks if VM in saved state */ 2250 if (isSaved()) 2251 return true; 2252 2253 /* Make sure all the attached and enabled network 2254 * adapters are present on the host. This check makes sense 2255 * in two cases only - when attachement type is Bridged Network 2256 * or Host-only Interface. NOTE: Only currently enabled 2257 * attachement type is checked (incorrect parameters check for 2258 * currently disabled attachement types is skipped). */ 2259 QStringList failedInterfaceNames; 2260 QStringList availableInterfaceNames; 2261 2262 /* Create host network interface names list */ 2263 foreach (const CHostNetworkInterface &iface, vboxGlobal().host().GetNetworkInterfaces()) 2264 { 2265 availableInterfaceNames << iface.GetName(); 2266 availableInterfaceNames << iface.GetShortName(); 2267 } 2268 2269 ulong cCount = vboxGlobal().virtualBox().GetSystemProperties().GetMaxNetworkAdapters(machine().GetChipsetType()); 2270 for (ulong uAdapterIndex = 0; uAdapterIndex < cCount; ++uAdapterIndex) 2271 { 2272 CNetworkAdapter na = machine().GetNetworkAdapter(uAdapterIndex); 2273 2274 if (na.GetEnabled()) 2275 { 2276 QString strIfName = QString(); 2277 2278 /* Get physical network interface name for currently 2279 * enabled network attachement type */ 2280 switch (na.GetAttachmentType()) 2281 { 2282 case KNetworkAttachmentType_Bridged: 2283 strIfName = na.GetBridgedInterface(); 2284 break; 2285 case KNetworkAttachmentType_HostOnly: 2286 strIfName = na.GetHostOnlyInterface(); 2287 break; 2288 } 2289 2290 if (!strIfName.isEmpty() && 2291 !availableInterfaceNames.contains(strIfName)) 2292 { 2293 LogFlow(("Found invalid network interface: %s\n", strIfName.toStdString().c_str())); 2294 failedInterfaceNames << QString("%1 (adapter %2)").arg(strIfName).arg(uAdapterIndex + 1); 2295 } 2296 } 2297 } 2298 2299 /* Check if non-existent interfaces found */ 2300 if (!failedInterfaceNames.isEmpty()) 2301 { 2302 if (msgCenter().cannotStartWithoutNetworkIf(machineName(), failedInterfaceNames.join(", "))) 2303 machineLogic()->openNetworkSettingsDialog(); 2304 else 2305 return false; 2306 } 2307 #endif /* VBOX_WITH_NETFLT */ 2308 2309 /* True by default: */ 2310 return true; 2311 } 2312 2313 bool UISession::postprocessInitialization() 2314 { 2315 /* Check if the required virtualization features are active. We get this info only when the session is active. */ 2316 const bool fIs64BitsGuest = vboxGlobal().virtualBox().GetGuestOSType(guest().GetOSTypeId()).GetIs64Bit(); 2317 const bool fRecommendVirtEx = vboxGlobal().virtualBox().GetGuestOSType(guest().GetOSTypeId()).GetRecommendedVirtEx(); 2318 AssertMsg(!fIs64BitsGuest || fRecommendVirtEx, ("Virtualization support missed for 64bit guest!\n")); 2319 const bool fIsVirtActive = debugger().GetHWVirtExEnabled(); 2320 if (fRecommendVirtEx && !fIsVirtActive) 2321 { 2322 /* Check whether vt-x / amd-v supported: */ 2323 bool fVTxAMDVSupported = vboxGlobal().host().GetProcessorFeature(KProcessorFeature_HWVirtEx); 2324 2325 /* Pause VM: */ 2326 setPause(true); 2327 2328 /* Ask the user about further actions: */ 2329 bool fShouldWeClose; 2330 if (fIs64BitsGuest) 2331 fShouldWeClose = msgCenter().warnAboutVirtExInactiveFor64BitsGuest(fVTxAMDVSupported); 2332 else 2333 fShouldWeClose = msgCenter().warnAboutVirtExInactiveForRecommendedGuest(fVTxAMDVSupported); 2334 2335 /* If user asked to close VM: */ 2336 if (fShouldWeClose) 2337 { 2338 /* Prevent auto-closure during power off sequence: */ 2339 machineLogic()->setPreventAutoClose(true); 2340 /* Power off VM: */ 2341 bool fServerCrashed = false; 2342 powerOff(false, fServerCrashed); 2343 return false; 2344 } 2345 2346 /* Resume VM: */ 2347 setPause(false); 2348 } 2349 2350 /* True by default: */ 2351 return true; 2352 } 2353 2354 bool UISession::isScreenVisible(ulong uScreenId) const 2355 { 2356 Assert(uScreenId < (ulong)m_monitorVisibilityVector.size()); 2357 return m_monitorVisibilityVector.value((int)uScreenId, false); 2358 } 2359 2360 void UISession::setScreenVisible(ulong uScreenId, bool fIsMonitorVisible) 2361 { 2362 Assert(uScreenId < (ulong)m_monitorVisibilityVector.size()); 2363 if (uScreenId < (ulong)m_monitorVisibilityVector.size()) 2364 m_monitorVisibilityVector[(int)uScreenId] = fIsMonitorVisible; 2365 } 2366 2367 int UISession::countOfVisibleWindows() 2368 { 2369 int cCountOfVisibleWindows = 0; 2370 for (int i = 0; i < m_monitorVisibilityVector.size(); ++i) 2371 if (m_monitorVisibilityVector[i]) 2372 ++cCountOfVisibleWindows; 2373 return cCountOfVisibleWindows; 2374 } 2375 2376 UIFrameBuffer* UISession::frameBuffer(ulong uScreenId) const 2377 { 2378 Assert(uScreenId < (ulong)m_frameBufferVector.size()); 2379 return m_frameBufferVector.value((int)uScreenId, 0); 2380 } 2381 2382 void UISession::setFrameBuffer(ulong uScreenId, UIFrameBuffer* pFrameBuffer) 2383 { 2384 Assert(uScreenId < (ulong)m_frameBufferVector.size()); 2385 if (uScreenId < (ulong)m_frameBufferVector.size()) 2386 m_frameBufferVector[(int)uScreenId] = pFrameBuffer; 2387 } 2388 2389 void UISession::updateHostScreenData() 2390 { 2391 m_hostScreens.clear(); 2392 QDesktopWidget *pDesktop = QApplication::desktop(); 2393 for (int iScreenIndex = 0; iScreenIndex < pDesktop->screenCount(); ++iScreenIndex) 2394 m_hostScreens << pDesktop->screenGeometry(iScreenIndex); 2395 } 2396 2397 #ifdef VBOX_GUI_WITH_KEYS_RESET_HANDLER 2398 /** 2399 * Custom signal handler. When switching VTs, we might not get release events 2400 * for Ctrl-Alt and in case a savestate is performed on the new VT, the VM will 2401 * be saved with modifier keys stuck. This is annoying enough for introducing 2402 * this hack. 2403 */ 2404 /* static */ 2405 static void signalHandlerSIGUSR1(int sig, siginfo_t * /* pInfo */, void * /*pSecret */) 2406 { 2407 /* only SIGUSR1 is interesting */ 2408 if (sig == SIGUSR1) 2409 if (UIMachine *pMachine = vboxGlobal().virtualMachine()) 2410 pMachine->uisession()->machineLogic()->keyboardHandler()->releaseAllPressedKeys(); 2411 } 2412 #endif /* VBOX_GUI_WITH_KEYS_RESET_HANDLER */ 2413 2414 #include "UISession.moc" 2415 70 #endif /* !___UIAddDiskEncryptionPasswordDialog_h___ */ -
trunk/src/VBox/Frontends/VirtualBox/src/runtime/UISession.cpp
r54732 r54733 44 44 # include "UIFrameBuffer.h" 45 45 # include "UISettingsDialogSpecific.h" 46 # include "UIAddDiskEncryptionPasswordDialog.h" 46 47 # ifdef VBOX_WITH_VIDEOHWACCEL 47 48 # include "VBoxFBOverlay.h" … … 80 81 # endif /* VBOX_WITHOUT_XCURSOR */ 81 82 #endif /* Q_WS_X11 */ 82 83 84 /* Qt includes: */85 #include <QDialog>86 #include <QVBoxLayout>87 #include <QLineEdit>88 #include <QTableView>89 #include <QHeaderView>90 #include <QItemEditorFactory>91 #include <QAbstractTableModel>92 #include <QStandardItemEditorCreator>93 /* GUI includes: */94 #include "QILabel.h"95 #include "QIDialogButtonBox.h"96 #include "QIWithRetranslateUI.h"97 #include "QIStyledItemDelegate.h"98 99 /* Type definitions: */100 typedef QMap<QString, QString> EncryptionPasswordsMap;101 typedef QMultiMap<QString, QString> EncryptedMediumsMap;102 103 /** Encryption-data table field indexes.104 * @todo To be moved into separate file.. */105 enum UIEncryptionTableSection106 {107 UIEncryptionTableSection_Id,108 UIEncryptionTableSection_Password,109 UIEncryptionTableSection_Max110 };111 112 /** QLineEdit implementation allowing to enter113 * disk encryption password for particular password id.114 * @todo To be moved into separate file.. */115 class UILineEdit : public QLineEdit116 {117 Q_OBJECT;118 Q_PROPERTY(QString password READ password WRITE setPassword USER true);119 120 signals:121 122 /** Notifies listener about data should be committed. */123 void sigCommitData(QWidget *pThis);124 125 public:126 127 /** Constructor.128 * @param pParent being passed to the base-class. */129 UILineEdit(QWidget *pParent)130 : QLineEdit(pParent)131 {132 /* Prepare: */133 prepare();134 }135 136 public slots:137 138 /** Handles @s strText changes. */139 void sltTextChanged(const QString &strText)140 {141 Q_UNUSED(strText);142 /* Commit data to the listener: */143 emit sigCommitData(this);144 }145 146 private:147 148 /** Prepare routine. */149 void prepare()150 {151 /* Set alignment: */152 setAlignment(Qt::AlignCenter);153 /* Set echo mode: */154 setEchoMode(QLineEdit::Password);155 /* Listen for the text changes: */156 connect(this, SIGNAL(textChanged(const QString&)),157 this, SLOT(sltTextChanged(const QString&)));158 }159 160 /** Returns the password from the editor. */161 QString password() const { return QLineEdit::text(); }162 /** Defines the @a strPassword to the editor. */163 void setPassword(const QString &strPassword) { QLineEdit::setText(strPassword); }164 };165 166 /** QAbstractTableModel implementation reflecting167 * disk encryption passwords for particular password ids.168 * @todo To be moved into separate file.. */169 class UIEncryptionDataModel : public QAbstractTableModel170 {171 Q_OBJECT;172 173 public:174 175 /** Constructor.176 * @param pParent being passed to the base-class,177 * @param encryptedMediums contains the lists of medium ids (values) encrypted with passwords with ids (keys). */178 UIEncryptionDataModel(QObject *pParent, const EncryptedMediumsMap &encryptedMediums)179 : QAbstractTableModel(pParent)180 , m_encryptedMediums(encryptedMediums)181 {182 /* Prepare: */183 prepare();184 }185 186 /** Returns encryption passwords. */187 EncryptionPasswordsMap encryptionPasswords() const { return m_encryptionPasswords; }188 189 /** Returns the @a index flags. */190 virtual Qt::ItemFlags flags(const QModelIndex &index) const191 {192 /* Check index validness: */193 if (!index.isValid())194 return Qt::NoItemFlags;195 /* Depending on column index: */196 switch (index.column())197 {198 case UIEncryptionTableSection_Id: return Qt::ItemIsEnabled | Qt::ItemIsSelectable;199 case UIEncryptionTableSection_Password: return Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsEditable;200 default: break;201 }202 /* No flags by default: */203 return Qt::NoItemFlags;204 }205 206 /** Returns the row count. Provide optional @a parent instead of root if necessary. */207 virtual int rowCount(const QModelIndex &parent = QModelIndex()) const208 {209 Q_UNUSED(parent);210 return m_encryptionPasswords.size();211 }212 213 /** Returns the column count. Provide optional @a parent instead of root if necessary. */214 virtual int columnCount(const QModelIndex &parent = QModelIndex()) const215 {216 Q_UNUSED(parent);217 return UIEncryptionTableSection_Max;218 }219 220 /** Returns header data for @a iSection, @a orientation and @a iRole. */221 virtual QVariant headerData(int iSection, Qt::Orientation orientation, int iRole) const222 {223 /* Check argument validness: */224 if (iRole != Qt::DisplayRole || orientation != Qt::Horizontal)225 return QVariant();226 /* Depending on column index: */227 switch (iSection)228 {229 case UIEncryptionTableSection_Id: return tr("Password ID");230 case UIEncryptionTableSection_Password: return tr("Password");231 default: break;232 }233 /* Null value by default: */234 return QVariant();235 }236 237 /** Returns @a index data for @a iRole. */238 virtual QVariant data(const QModelIndex &index, int iRole /* = Qt::DisplayRole */) const239 {240 /* Check index validness: */241 if (!index.isValid())242 return QVariant();243 /* Depending on role: */244 switch (iRole)245 {246 case Qt::DisplayRole:247 {248 /* Depending on column index: */249 switch (index.column())250 {251 case UIEncryptionTableSection_Id:252 return m_encryptionPasswords.keys().at(index.row());253 case UIEncryptionTableSection_Password:254 return QString().fill('*', m_encryptionPasswords.value(m_encryptionPasswords.keys().at(index.row())).size());255 default:256 return QVariant();257 }258 break;259 }260 case Qt::EditRole:261 {262 /* Depending on column index: */263 switch (index.column())264 {265 case UIEncryptionTableSection_Password:266 return m_encryptionPasswords.value(m_encryptionPasswords.keys().at(index.row()));267 default:268 return QVariant();269 }270 break;271 }272 case Qt::TextAlignmentRole:273 {274 /* Depending on column index: */275 switch (index.column())276 {277 case UIEncryptionTableSection_Password:278 return Qt::AlignCenter;279 default: return QVariant();280 }281 break;282 }283 default:284 break;285 }286 /* Null value by default: */287 return QVariant();288 }289 290 /** Defines @a index data for @a iRole as @a value. */291 virtual bool setData(const QModelIndex &index, const QVariant &value, int iRole /* = Qt::EditRole */)292 {293 /* Check index validness: */294 if (!index.isValid())295 return false;296 /* Check argument validness: */297 if (iRole != Qt::EditRole)298 return false;299 /* Depending on column index: */300 switch (index.column())301 {302 case UIEncryptionTableSection_Password: m_encryptionPasswords[m_encryptionPasswords.keys().at(index.row())] = value.toString(); break;303 default: break;304 }305 /* Nothing to set by default: */306 return false;307 }308 309 private:310 311 /** Prepare routine. */312 void prepare()313 {314 /* Populate the map of passwords. */315 foreach (const QString &strPasswordId, m_encryptedMediums.keys())316 m_encryptionPasswords.insert(strPasswordId, QString());317 }318 319 /** Holds the encrypted medium map reference. */320 const EncryptedMediumsMap &m_encryptedMediums;321 322 /** Holds the encrypted password id map. */323 EncryptionPasswordsMap m_encryptionPasswords;324 };325 326 /** QTableView implementation allowing to enter327 * disk encryption passwords for particular password ids.328 * @todo To be moved into separate file.. */329 class UIEncryptionDataTable : public QTableView330 {331 Q_OBJECT;332 333 public:334 335 /** Constructor.336 * @param pParent being passed to the base-class. */337 UIEncryptionDataTable(const EncryptedMediumsMap &encryptedMediums)338 : m_encryptedMediums(encryptedMediums)339 , m_pModelEncryptionData(0)340 {341 /* Prepare: */342 prepare();343 }344 345 /** Returns encryption passwords. */346 EncryptionPasswordsMap encryptionPasswords() const347 {348 AssertPtrReturn(m_pModelEncryptionData, EncryptionPasswordsMap());349 return m_pModelEncryptionData->encryptionPasswords();350 }351 352 private:353 354 /** Prepare routine. */355 void prepare()356 {357 /* Create encryption-data model: */358 m_pModelEncryptionData = new UIEncryptionDataModel(this, m_encryptedMediums);359 AssertPtrReturnVoid(m_pModelEncryptionData);360 {361 /* Assign configured model to table: */362 setModel(m_pModelEncryptionData);363 }364 365 /* Create item delegate: */366 QIStyledItemDelegate *pStyledItemDelegate = new QIStyledItemDelegate(this);367 AssertPtrReturnVoid(pStyledItemDelegate);368 {369 /* Create item editor factory: */370 QItemEditorFactory *pNewItemEditorFactory = new QItemEditorFactory;371 AssertPtrReturnVoid(pNewItemEditorFactory);372 {373 /* Create item editor creator: */374 QStandardItemEditorCreator<UILineEdit> *pQStringItemEditorCreator = new QStandardItemEditorCreator<UILineEdit>();375 AssertPtrReturnVoid(pQStringItemEditorCreator);376 {377 /* Register UILineEdit as the QString editor: */378 pNewItemEditorFactory->registerEditor(QVariant::String, pQStringItemEditorCreator);379 }380 /* Assign configured item editor factory to table delegate: */381 pStyledItemDelegate->setItemEditorFactory(pNewItemEditorFactory);382 }383 /* Assign configured item delegate to table: */384 delete itemDelegate();385 setItemDelegate(pStyledItemDelegate);386 }387 388 /* Configure table: */389 setTabKeyNavigation(false);390 setContextMenuPolicy(Qt::CustomContextMenu);391 setSelectionBehavior(QAbstractItemView::SelectRows);392 setSelectionMode(QAbstractItemView::SingleSelection);393 setEditTriggers(QAbstractItemView::CurrentChanged | QAbstractItemView::SelectedClicked);394 395 /* Configure headers: */396 verticalHeader()->hide();397 verticalHeader()->setDefaultSectionSize((int)(verticalHeader()->minimumSectionSize() * 1.33));398 horizontalHeader()->setStretchLastSection(false);399 horizontalHeader()->setResizeMode(UIEncryptionTableSection_Id, QHeaderView::Interactive);400 horizontalHeader()->setResizeMode(UIEncryptionTableSection_Password, QHeaderView::Stretch);401 }402 403 /** Holds the encrypted medium map reference. */404 const EncryptedMediumsMap &m_encryptedMediums;405 406 /** Holds the encryption-data model. */407 UIEncryptionDataModel *m_pModelEncryptionData;408 };409 410 /** QDialog implementation allowing to enter411 * disk encryption passwords for particular password ids.412 * @todo To be moved into separate files.. */413 class UIAddDiskEncryptionPasswordDialog : public QIWithRetranslateUI<QDialog>414 {415 Q_OBJECT;416 417 public:418 419 /** Constructor.420 * @param pParent being passed to the base-class,421 * @param encryptedMediums contains the lists of medium ids (values) encrypted with passwords with ids (keys). */422 UIAddDiskEncryptionPasswordDialog(QWidget *pParent, const EncryptedMediumsMap &encryptedMediums)423 : QIWithRetranslateUI<QDialog>(pParent)424 , m_encryptedMediums(encryptedMediums)425 , m_pLabelDescription(0)426 , m_pTableEncryptionData(0)427 {428 /* Prepare: */429 prepare();430 /* Retranslate: */431 retranslateUi();432 }433 434 /** Returns encryption passwords. */435 EncryptionPasswordsMap encryptionPasswords() const436 {437 AssertPtrReturn(m_pTableEncryptionData, EncryptionPasswordsMap());438 return m_pTableEncryptionData->encryptionPasswords();439 }440 441 private:442 443 /** Prepare routine. */444 void prepare()445 {446 /* Create main-layout: */447 QVBoxLayout *pMainLayout = new QVBoxLayout(this);448 AssertPtrReturnVoid(pMainLayout);449 {450 /* Create input-layout: */451 QVBoxLayout *pInputLayout = new QVBoxLayout;452 AssertPtrReturnVoid(pInputLayout);453 {454 /* Create description label: */455 m_pLabelDescription = new QILabel;456 m_pLabelDescription->useSizeHintForWidth(450);457 m_pLabelDescription->updateGeometry();458 AssertPtrReturnVoid(m_pLabelDescription);459 {460 /* Configure description label: */461 m_pLabelDescription->setWordWrap(true);462 /* Add label into layout: */463 pInputLayout->addWidget(m_pLabelDescription);464 }465 /* Create encryption-data table: */466 m_pTableEncryptionData = new UIEncryptionDataTable(m_encryptedMediums);467 AssertPtrReturnVoid(m_pTableEncryptionData);468 {469 /* Add label into layout: */470 pInputLayout->addWidget(m_pTableEncryptionData);471 }472 /* Add layout into parent: */473 pMainLayout->addLayout(pInputLayout);474 }475 /* Create button-box: */476 QIDialogButtonBox *pButtonBox = new QIDialogButtonBox;477 AssertPtrReturnVoid(pButtonBox);478 {479 /* Configure button-box: */480 pButtonBox->setStandardButtons(QDialogButtonBox::Ok | QDialogButtonBox::Cancel);481 connect(pButtonBox, SIGNAL(accepted()), this, SLOT(accept()));482 connect(pButtonBox, SIGNAL(rejected()), this, SLOT(reject()));483 /* Add button-box into layout: */484 pMainLayout->addWidget(pButtonBox);485 }486 }487 }488 489 /** Translation routine. */490 void retranslateUi()491 {492 AssertPtrReturnVoid(m_pLabelDescription);493 m_pLabelDescription->setText(tr("This virtual machine is password protected. "494 "Please enter the %n encryption password(s) below.",495 "This text is never used with n == 0. "496 "Feel free to drop the %n where possible, "497 "we only included it because of problems with Qt Linguist "498 "(but the user can see how many passwords are in the list "499 "and doesn't need to be told).",500 m_encryptedMediums.size()));501 }502 503 /** Holds the encrypted medium map reference. */504 const EncryptedMediumsMap &m_encryptedMediums;505 506 /** Holds the description label. */507 QILabel *m_pLabelDescription;508 /** Holds the encryption-data table. */509 UIEncryptionDataTable *m_pTableEncryptionData;510 };511 512 83 513 84 #ifdef VBOX_GUI_WITH_KEYS_RESET_HANDLER … … 2412 1983 #endif /* VBOX_GUI_WITH_KEYS_RESET_HANDLER */ 2413 1984 2414 #include "UISession.moc"2415
Note:
See TracChangeset
for help on using the changeset viewer.