Changeset 75369 in vbox
- Timestamp:
- Nov 9, 2018 4:20:25 PM (7 years ago)
- svn:sync-xref-src-repo-rev:
- 126504
- Location:
- trunk/src/VBox/Frontends/VirtualBox
- Files:
-
- 2 edited
- 2 copied
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Frontends/VirtualBox/Makefile.kmk
r75295 r75369 799 799 src/globals/UIModalWindowManager.h \ 800 800 src/globals/UIPopupCenter.h \ 801 src/globals/UIProgressEventHandler.h \ 801 802 src/globals/UIShortcutPool.h \ 802 803 src/globals/UIThreadPool.h \ … … 1089 1090 src/globals/UIModalWindowManager.h \ 1090 1091 src/globals/UIPopupCenter.h \ 1092 src/globals/UIProgressEventHandler.h \ 1091 1093 src/globals/UIShortcutPool.h \ 1092 1094 src/globals/UIThreadPool.h \ … … 1243 1245 src/widgets/UIMiniToolBar.cpp \ 1244 1246 src/widgets/UIPortForwardingTable.cpp \ 1245 src/widgets/UIProgressDialog.cpp \1246 1247 src/widgets/UIStatusBarEditorWindow.cpp 1247 1248 … … 1318 1319 src/widgets/UIHotKeyEditor.cpp \ 1319 1320 src/widgets/UIPortForwardingTable.cpp \ 1320 src/widgets/UIProgressDialog.cpp \1321 1321 src/widgets/UIStatusBarEditorWindow.cpp 1322 1322 … … 1512 1512 src/globals/UIModalWindowManager.cpp \ 1513 1513 src/globals/UIPopupCenter.cpp \ 1514 src/globals/UIProgressEventHandler.cpp \ 1514 1515 src/globals/UIShortcutPool.cpp \ 1515 1516 src/globals/UIThreadPool.cpp \ … … 1854 1855 src/globals/UIModalWindowManager.cpp \ 1855 1856 src/globals/UIPopupCenter.cpp \ 1857 src/globals/UIProgressEventHandler.cpp \ 1856 1858 src/globals/UIShortcutPool.cpp \ 1857 1859 src/globals/UIThreadPool.cpp \ -
trunk/src/VBox/Frontends/VirtualBox/src/globals/UIProgressEventHandler.cpp
r75361 r75369 1 1 /* $Id$ */ 2 2 /** @file 3 * VBox Qt GUI - UIProgress Dialogclass implementation.3 * VBox Qt GUI - UIProgressEventHandler class implementation. 4 4 */ 5 5 … … 20 20 #else /* !VBOX_WITH_PRECOMPILED_HEADERS */ 21 21 22 /* Qt includes: */23 # include <QCloseEvent>24 # include <QEventLoop>25 # include <QProgressBar>26 # include <QTime>27 # include <QTimer>28 # include <QVBoxLayout>29 30 22 /* GUI includes: */ 31 # include "QIDialogButtonBox.h"32 # include "QILabel.h"33 # include "UIErrorString.h"34 23 # include "UIExtraDataManager.h" 35 24 # include "UIMainEventListener.h" 36 # include "UIModalWindowManager.h" 37 # include "UIProgressDialog.h" 38 # include "UISpecialControls.h" 25 # include "UIProgressEventHandler.h" 39 26 # include "VBoxGlobal.h" 40 27 # ifdef VBOX_WS_MAC … … 42 29 # endif /* VBOX_WS_MAC */ 43 30 44 /* COM includes: */45 # include "CEventListener.h"46 # include "CEventSource.h"47 # include "CProgress.h"48 49 31 #endif /* !VBOX_WITH_PRECOMPILED_HEADERS */ 50 51 52 /** Private QObject extension53 * providing UIExtraDataManager with the CVirtualBox event-source. */54 class UIProgressEventHandler : public QObject55 {56 Q_OBJECT;57 58 signals:59 60 /** Notifies about @a iPercent change for progress with @a uProgressId. */61 void sigProgressPercentageChange(const QUuid &uProgressId, const int iPercent);62 /** Notifies about task complete for progress with @a uProgressId. */63 void sigProgressTaskComplete(const QUuid &uProgressId);64 65 public:66 67 /** Constructs event proxy object on the basis of passed @a pParent. */68 UIProgressEventHandler(QObject *pParent, const CProgress &comProgress);69 /** Destructs event proxy object. */70 virtual ~UIProgressEventHandler() /* override */;71 72 protected:73 74 /** @name Prepare/Cleanup cascade.75 * @{ */76 /** Prepares all. */77 void prepare();78 /** Prepares listener. */79 void prepareListener();80 /** Prepares connections. */81 void prepareConnections();82 83 /** Cleanups connections. */84 void cleanupConnections();85 /** Cleanups listener. */86 void cleanupListener();87 /** Cleanups all. */88 void cleanup();89 /** @} */90 91 private:92 93 /** Holds the progress wrapper. */94 CProgress m_comProgress;95 96 /** Holds the Qt event listener instance. */97 ComObjPtr<UIMainEventListenerImpl> m_pQtListener;98 /** Holds the COM event listener instance. */99 CEventListener m_comEventListener;100 };101 102 103 /*********************************************************************************************************************************104 * Class UIProgressEventHandler implementation. *105 *********************************************************************************************************************************/106 32 107 33 UIProgressEventHandler::UIProgressEventHandler(QObject *pParent, const CProgress &comProgress) … … 199 125 cleanupListener(); 200 126 } 201 202 203 /*********************************************************************************************************************************204 * Class UIProgressDialog implementation. *205 *********************************************************************************************************************************/206 207 const char *UIProgressDialog::m_spcszOpDescTpl = "%1 ... (%2/%3)";208 209 UIProgressDialog::UIProgressDialog(CProgress &comProgress,210 const QString &strTitle,211 QPixmap *pImage /* = 0 */,212 int cMinDuration /* = 2000 */,213 QWidget *pParent /* = 0 */)214 : QIWithRetranslateUI2<QIDialog>(pParent, Qt::MSWindowsFixedSizeDialogHint | Qt::WindowTitleHint)215 , m_comProgress(comProgress)216 , m_strTitle(strTitle)217 , m_pImage(pImage)218 , m_cMinDuration(cMinDuration)219 , m_fLegacyHandling(gEDataManager->legacyProgressHandlingRequested())220 , m_pLabelImage(0)221 , m_pLabelDescription(0)222 , m_pProgressBar(0)223 , m_pButtonCancel(0)224 , m_pLabelEta(0)225 , m_cOperations(m_comProgress.GetOperationCount())226 , m_uCurrentOperation(m_comProgress.GetOperation() + 1)227 , m_fCancelEnabled(false)228 , m_fEnded(false)229 , m_pEventHandler(0)230 {231 /* Prepare: */232 prepare();233 }234 235 UIProgressDialog::~UIProgressDialog()236 {237 /* Cleanup: */238 cleanup();239 }240 241 void UIProgressDialog::retranslateUi()242 {243 m_pButtonCancel->setText(tr("&Cancel"));244 m_pButtonCancel->setToolTip(tr("Cancel the current operation"));245 }246 247 int UIProgressDialog::run(int cRefreshInterval)248 {249 /* Make sure progress hasn't finished already: */250 if (!m_comProgress.isOk() || m_comProgress.GetCompleted())251 {252 /* Progress completed? */253 if (m_comProgress.isOk())254 return Accepted;255 /* Or aborted? */256 else257 return Rejected;258 }259 260 /* Start refresh timer (if necessary): */261 int id = 0;262 if (m_fLegacyHandling)263 id = startTimer(cRefreshInterval);264 265 /* Set busy cursor.266 * We don't do this on the Mac, cause regarding the design rules of267 * Apple there is no busy window behavior. A window should always be268 * responsive and it is in our case (We show the progress dialog bar). */269 #ifndef VBOX_WS_MAC270 if (m_fCancelEnabled)271 QApplication::setOverrideCursor(QCursor(Qt::BusyCursor));272 else273 QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));274 #endif /* VBOX_WS_MAC */275 276 /* Create a local event-loop: */277 {278 /* Guard ourself for the case279 * we destroyed ourself in our event-loop: */280 QPointer<UIProgressDialog> guard = this;281 282 /* Holds the modal loop, but don't show the window immediately: */283 execute(false);284 285 /* Are we still valid? */286 if (guard.isNull())287 return Rejected;288 }289 290 /* Kill refresh timer (if necessary): */291 if (m_fLegacyHandling)292 killTimer(id);293 294 #ifndef VBOX_WS_MAC295 /* Reset the busy cursor */296 QApplication::restoreOverrideCursor();297 #endif /* VBOX_WS_MAC */298 299 return result();300 }301 302 void UIProgressDialog::show()303 {304 /* We should not show progress-dialog305 * if it was already finalized but not yet closed.306 * This could happens in case of some other307 * modal dialog prevents our event-loop from308 * being exit overlapping 'this'. */309 if (!m_fEnded)310 QIDialog::show();311 }312 313 void UIProgressDialog::reject()314 {315 if (m_fCancelEnabled)316 sltCancelOperation();317 }318 319 void UIProgressDialog::timerEvent(QTimerEvent *)320 {321 /* Call the timer event handling delegate: */322 handleTimerEvent();323 }324 325 void UIProgressDialog::closeEvent(QCloseEvent *pEvent)326 {327 if (m_fCancelEnabled)328 sltCancelOperation();329 else330 pEvent->ignore();331 }332 333 void UIProgressDialog::sltHandleProgressPercentageChange(const QUuid &, const int iPercent)334 {335 /* New mode only: */336 AssertReturnVoid(!m_fLegacyHandling);337 338 /* Update progress: */339 updateProgressState();340 updateProgressPercentage(iPercent);341 }342 343 void UIProgressDialog::sltHandleProgressTaskComplete(const QUuid &)344 {345 /* New mode only: */346 AssertReturnVoid(!m_fLegacyHandling);347 348 /* If progress-dialog is not yet ended but progress is aborted or completed: */349 if (!m_fEnded && (!m_comProgress.isOk() || m_comProgress.GetCompleted()))350 {351 /* Set progress to 100%: */352 updateProgressPercentage(100);353 354 /* Try to close the dialog: */355 closeProgressDialog();356 }357 }358 359 void UIProgressDialog::sltHandleWindowStackChange()360 {361 /* If progress-dialog is not yet ended but progress is aborted or completed: */362 if (!m_fEnded && (!m_comProgress.isOk() || m_comProgress.GetCompleted()))363 {364 /* Try to close the dialog: */365 closeProgressDialog();366 }367 }368 369 void UIProgressDialog::sltCancelOperation()370 {371 m_pButtonCancel->setEnabled(false);372 m_comProgress.Cancel();373 }374 375 void UIProgressDialog::prepare()376 {377 /* Setup dialog: */378 setWindowTitle(QString("%1: %2").arg(m_strTitle, m_comProgress.GetDescription()));379 setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);380 #ifdef VBOX_WS_MAC381 ::darwinSetHidesAllTitleButtons(this);382 #endif383 384 /* Make sure dialog is handling window stack changes: */385 connect(&windowManager(), &UIModalWindowManager::sigStackChanged,386 this, &UIProgressDialog::sltHandleWindowStackChange);387 388 /* Prepare: */389 prepareEventHandler();390 prepareWidgets();391 }392 393 void UIProgressDialog::prepareEventHandler()394 {395 if (!m_fLegacyHandling)396 {397 /* Create CProgress event handler: */398 m_pEventHandler = new UIProgressEventHandler(this, m_comProgress);399 connect(m_pEventHandler, &UIProgressEventHandler::sigProgressPercentageChange,400 this, &UIProgressDialog::sltHandleProgressPercentageChange);401 connect(m_pEventHandler, &UIProgressEventHandler::sigProgressTaskComplete,402 this, &UIProgressDialog::sltHandleProgressTaskComplete);403 }404 }405 406 void UIProgressDialog::prepareWidgets()407 {408 /* Create main layout: */409 QHBoxLayout *pMainLayout = new QHBoxLayout(this);410 AssertPtrReturnVoid(pMainLayout);411 {412 /* Configure layout: */413 #ifdef VBOX_WS_MAC414 if (m_pImage)415 pMainLayout->setContentsMargins(30, 15, 30, 15);416 else417 pMainLayout->setContentsMargins(6, 6, 6, 6);418 #endif419 420 /* If there is image: */421 if (m_pImage)422 {423 /* Create image label: */424 m_pLabelImage = new QLabel;425 AssertPtrReturnVoid(m_pLabelImage);426 {427 /* Configure label: */428 m_pLabelImage->setPixmap(*m_pImage);429 430 /* Add into layout: */431 pMainLayout->addWidget(m_pLabelImage);432 }433 }434 435 /* Create description layout: */436 QVBoxLayout *pDescriptionLayout = new QVBoxLayout;437 AssertPtrReturnVoid(pDescriptionLayout);438 {439 /* Configure layout: */440 pDescriptionLayout->setMargin(0);441 442 /* Add stretch: */443 pDescriptionLayout->addStretch(1);444 445 /* Create description label: */446 m_pLabelDescription = new QILabel;447 AssertPtrReturnVoid(m_pLabelDescription);448 {449 /* Configure label: */450 if (m_cOperations > 1)451 m_pLabelDescription->setText(QString(m_spcszOpDescTpl)452 .arg(m_comProgress.GetOperationDescription())453 .arg(m_uCurrentOperation).arg(m_cOperations));454 else455 m_pLabelDescription->setText(QString("%1 ...")456 .arg(m_comProgress.GetOperationDescription()));457 458 /* Add into layout: */459 pDescriptionLayout->addWidget(m_pLabelDescription, 0, Qt::AlignHCenter);460 }461 462 /* Create proggress layout: */463 QHBoxLayout *pProgressLayout = new QHBoxLayout;464 AssertPtrReturnVoid(pProgressLayout);465 {466 /* Configure layout: */467 pProgressLayout->setMargin(0);468 469 /* Create progress-bar: */470 m_pProgressBar = new QProgressBar;471 AssertPtrReturnVoid(m_pProgressBar);472 {473 /* Configure progress-bar: */474 m_pProgressBar->setMaximum(100);475 m_pProgressBar->setValue(0);476 477 /* Add into layout: */478 pProgressLayout->addWidget(m_pProgressBar, 0, Qt::AlignVCenter);479 }480 481 /* Create cancel button: */482 m_pButtonCancel = new UIMiniCancelButton;483 AssertPtrReturnVoid(m_pButtonCancel);484 {485 /* Configure cancel button: */486 m_fCancelEnabled = m_comProgress.GetCancelable();487 m_pButtonCancel->setEnabled(m_fCancelEnabled);488 m_pButtonCancel->setFocusPolicy(Qt::ClickFocus);489 connect(m_pButtonCancel, SIGNAL(clicked()), this, SLOT(sltCancelOperation()));490 491 /* Add into layout: */492 pProgressLayout->addWidget(m_pButtonCancel, 0, Qt::AlignVCenter);493 }494 495 /* Add into layout: */496 pDescriptionLayout->addLayout(pProgressLayout);497 }498 499 /* Create estimation label: */500 m_pLabelEta = new QILabel;501 {502 /* Add into layout: */503 pDescriptionLayout->addWidget(m_pLabelEta, 0, Qt::AlignLeft | Qt::AlignVCenter);504 }505 506 /* Add stretch: */507 pDescriptionLayout->addStretch(1);508 509 /* Add into layout: */510 pMainLayout->addLayout(pDescriptionLayout);511 }512 }513 514 /* Translate finally: */515 retranslateUi();516 517 /* The progress dialog will be shown automatically after518 * the duration is over if progress is not finished yet. */519 QTimer::singleShot(m_cMinDuration, this, SLOT(show()));520 }521 522 void UIProgressDialog::cleanupWidgets()523 {524 /* Nothing for now. */525 }526 527 void UIProgressDialog::cleanupEventHandler()528 {529 if (!m_fLegacyHandling)530 {531 /* Destroy CProgress event handler: */532 delete m_pEventHandler;533 m_pEventHandler = 0;534 }535 }536 537 void UIProgressDialog::cleanup()538 {539 /* Wait for CProgress to complete: */540 m_comProgress.WaitForCompletion(-1);541 542 /* Call the timer event handling delegate: */543 if (m_fLegacyHandling)544 handleTimerEvent();545 546 /* Cleanup: */547 cleanupEventHandler();548 cleanupWidgets();549 }550 551 void UIProgressDialog::updateProgressState()552 {553 /* Mark progress canceled if so: */554 if (m_comProgress.GetCanceled())555 m_pLabelEta->setText(tr("Canceling..."));556 /* Update the progress dialog otherwise: */557 else558 {559 /* Update ETA: */560 const long iNewTime = m_comProgress.GetTimeRemaining();561 long iSeconds;562 long iMinutes;563 long iHours;564 long iDays;565 566 iSeconds = iNewTime < 0 ? 0 : iNewTime;567 iMinutes = iSeconds / 60;568 iSeconds -= iMinutes * 60;569 iHours = iMinutes / 60;570 iMinutes -= iHours * 60;571 iDays = iHours / 24;572 iHours -= iDays * 24;573 574 const QString strDays = VBoxGlobal::daysToString(iDays);575 const QString strHours = VBoxGlobal::hoursToString(iHours);576 const QString strMinutes = VBoxGlobal::minutesToString(iMinutes);577 const QString strSeconds = VBoxGlobal::secondsToString(iSeconds);578 579 const QString strTwoComp = tr("%1, %2 remaining", "You may wish to translate this more like \"Time remaining: %1, %2\"");580 const QString strOneComp = tr("%1 remaining", "You may wish to translate this more like \"Time remaining: %1\"");581 582 if (iDays > 1 && iHours > 0)583 m_pLabelEta->setText(strTwoComp.arg(strDays).arg(strHours));584 else if (iDays > 1)585 m_pLabelEta->setText(strOneComp.arg(strDays));586 else if (iDays > 0 && iHours > 0)587 m_pLabelEta->setText(strTwoComp.arg(strDays).arg(strHours));588 else if (iDays > 0 && iMinutes > 5)589 m_pLabelEta->setText(strTwoComp.arg(strDays).arg(strMinutes));590 else if (iDays > 0)591 m_pLabelEta->setText(strOneComp.arg(strDays));592 else if (iHours > 2)593 m_pLabelEta->setText(strOneComp.arg(strHours));594 else if (iHours > 0 && iMinutes > 0)595 m_pLabelEta->setText(strTwoComp.arg(strHours).arg(strMinutes));596 else if (iHours > 0)597 m_pLabelEta->setText(strOneComp.arg(strHours));598 else if (iMinutes > 2)599 m_pLabelEta->setText(strOneComp.arg(strMinutes));600 else if (iMinutes > 0 && iSeconds > 5)601 m_pLabelEta->setText(strTwoComp.arg(strMinutes).arg(strSeconds));602 else if (iMinutes > 0)603 m_pLabelEta->setText(strOneComp.arg(strMinutes));604 else if (iSeconds > 5)605 m_pLabelEta->setText(strOneComp.arg(strSeconds));606 else if (iSeconds > 0)607 m_pLabelEta->setText(tr("A few seconds remaining"));608 else609 m_pLabelEta->clear();610 611 /* Then operation text (if changed): */612 ulong uNewOp = m_comProgress.GetOperation() + 1;613 if (uNewOp != m_uCurrentOperation)614 {615 m_uCurrentOperation = uNewOp;616 m_pLabelDescription->setText(QString(m_spcszOpDescTpl)617 .arg(m_comProgress.GetOperationDescription())618 .arg(m_uCurrentOperation).arg(m_cOperations));619 }620 621 /* Then cancel button: */622 m_fCancelEnabled = m_comProgress.GetCancelable();623 m_pButtonCancel->setEnabled(m_fCancelEnabled);624 }625 }626 627 void UIProgressDialog::updateProgressPercentage(int iPercent /* = -1 */)628 {629 /* Update operation percentage: */630 if (iPercent == -1)631 iPercent = m_comProgress.GetPercent();632 m_pProgressBar->setValue(iPercent);633 634 /* Notify listeners about the operation progress update: */635 emit sigProgressChange(m_cOperations, m_comProgress.GetOperationDescription(),636 m_comProgress.GetOperation() + 1, iPercent);637 }638 639 void UIProgressDialog::closeProgressDialog()640 {641 /* If window is on the top of the stack: */642 if (windowManager().isWindowOnTheTopOfTheModalWindowStack(this))643 {644 /* Progress completed? */645 if (m_comProgress.isOk())646 done(Accepted);647 /* Or aborted? */648 else649 done(Rejected);650 651 /* Mark progress-dialog finished: */652 m_fEnded = true;653 }654 }655 656 void UIProgressDialog::handleTimerEvent()657 {658 /* Old mode only: */659 AssertReturnVoid(m_fLegacyHandling);660 661 /* If progress-dialog is ended: */662 if (m_fEnded)663 {664 // WORKAROUND:665 // We should hide progress-dialog if it was already ended but not yet closed. This could happen666 // in case if some other modal dialog prevents our event-loop from being exit overlapping 'this'.667 /* If window is on the top of the stack and still shown: */668 if (!isHidden() && windowManager().isWindowOnTheTopOfTheModalWindowStack(this))669 hide();670 671 return;672 }673 674 /* If progress-dialog is not yet ended but progress is aborted or completed: */675 if (!m_comProgress.isOk() || m_comProgress.GetCompleted())676 {677 /* Set progress to 100%: */678 updateProgressPercentage(100);679 680 /* Try to close the dialog: */681 return closeProgressDialog();682 }683 684 /* Update progress: */685 updateProgressState();686 updateProgressPercentage();687 }688 689 690 /*********************************************************************************************************************************691 * Class UIProgress implementation. *692 *********************************************************************************************************************************/693 694 UIProgress::UIProgress(CProgress &comProgress, QObject *pParent /* = 0 */)695 : QObject(pParent)696 , m_comProgress(comProgress)697 , m_cOperations(m_comProgress.GetOperationCount())698 , m_fEnded(false)699 {700 }701 702 void UIProgress::run(int iRefreshInterval)703 {704 /* Make sure the CProgress still valid: */705 if (!m_comProgress.isOk())706 return;707 708 /* Start the refresh timer: */709 int id = startTimer(iRefreshInterval);710 711 /* Create a local event-loop: */712 {713 QEventLoop eventLoop;714 m_pEventLoop = &eventLoop;715 716 /* Guard ourself for the case717 * we destroyed ourself in our event-loop: */718 QPointer<UIProgress> guard = this;719 720 /* Start the blocking event-loop: */721 eventLoop.exec();722 723 /* Are we still valid? */724 if (guard.isNull())725 return;726 727 m_pEventLoop = 0;728 }729 730 /* Kill the refresh timer: */731 killTimer(id);732 }733 734 void UIProgress::timerEvent(QTimerEvent *)735 {736 /* Make sure the UIProgress still 'running': */737 if (m_fEnded)738 return;739 740 /* If progress had failed or finished: */741 if (!m_comProgress.isOk() || m_comProgress.GetCompleted())742 {743 /* Notify listeners about the operation progress error: */744 if (!m_comProgress.isOk() || m_comProgress.GetResultCode() != 0)745 emit sigProgressError(UIErrorString::formatErrorInfo(m_comProgress));746 747 /* Exit from the event-loop if there is any: */748 if (m_pEventLoop)749 m_pEventLoop->exit();750 751 /* Mark UIProgress as 'ended': */752 m_fEnded = true;753 754 /* Return early: */755 return;756 }757 758 /* If CProgress was not yet canceled: */759 if (!m_comProgress.GetCanceled())760 {761 /* Notify listeners about the operation progress update: */762 emit sigProgressChange(m_cOperations, m_comProgress.GetOperationDescription(),763 m_comProgress.GetOperation() + 1, m_comProgress.GetPercent());764 }765 }766 767 768 #include "UIProgressDialog.moc"769 -
trunk/src/VBox/Frontends/VirtualBox/src/globals/UIProgressEventHandler.h
r75361 r75369 1 1 /* $Id$ */ 2 2 /** @file 3 * VBox Qt GUI - UIProgress Dialogclass declaration.3 * VBox Qt GUI - UIProgressEventHandler class declaration. 4 4 */ 5 5 … … 16 16 */ 17 17 18 #ifndef ___UIProgress Dialog_h___19 #define ___UIProgress Dialog_h___18 #ifndef ___UIProgressEventHandler_h___ 19 #define ___UIProgressEventHandler_h___ 20 20 21 21 /* GUI includes: */ 22 #include "QIDialog.h" 23 #include "QIWithRetranslateUI.h" 24 #include "UILibraryDefs.h" 22 #include "UIMainEventListener.h" 25 23 26 /* Forward declarations: */ 27 class QLabel; 28 class QProgressBar; 29 class QILabel; 30 class UIMiniCancelButton; 31 class UIProgressEventHandler; 32 class CProgress; 24 /* COM includes: */ 25 # include "CEventListener.h" 26 # include "CEventSource.h" 27 # include "CProgress.h" 33 28 34 29 35 /** QProgressDialog enhancement that allows to: 36 * 1) prevent closing the dialog when it has no cancel button; 37 * 2) effectively track the IProgress object completion (w/o using 38 * IProgress::waitForCompletion() and w/o blocking the UI thread in any other way for too long). 39 * @note The CProgress instance is passed as a non-const reference to the constructor (to memorize COM errors if they happen), 40 * and therefore must not be destroyed before the created UIProgressDialog instance is destroyed. */ 41 class SHARED_LIBRARY_STUFF UIProgressDialog : public QIWithRetranslateUI2<QIDialog> 30 /** Private QObject extension 31 * providing UIExtraDataManager with the CVirtualBox event-source. */ 32 class SHARED_LIBRARY_STUFF UIProgressEventHandler : public QObject 42 33 { 43 34 Q_OBJECT; … … 45 36 signals: 46 37 47 /** Notifies listeners about wrapped CProgress change. 48 * @param iOperations Brings the number of operations CProgress have. 49 * @param strOperation Brings the description of the current CProgress operation. 50 * @param iOperation Brings the index of the current CProgress operation. 51 * @param iPercent Brings the percentage of the current CProgress operation. */ 52 void sigProgressChange(ulong iOperations, QString strOperation, 53 ulong iOperation, ulong iPercent); 38 /** Notifies about @a iPercent change for progress with @a uProgressId. */ 39 void sigProgressPercentageChange(const QUuid &uProgressId, const int iPercent); 40 /** Notifies about task complete for progress with @a uProgressId. */ 41 void sigProgressTaskComplete(const QUuid &uProgressId); 54 42 55 43 public: 56 44 57 /** Constructs progress-dialog passing @a pParent to the base-class. 58 * @param comProgress Brings the progress reference. 59 * @param strTitle Brings the progress-dialog title. 60 * @param pImage Brings the progress-dialog image. 61 * @param cMinDuration Brings the minimum duration before the progress-dialog is shown. */ 62 UIProgressDialog(CProgress &comProgress, const QString &strTitle, 63 QPixmap *pImage = 0, int cMinDuration = 2000, QWidget *pParent = 0); 64 /** Destructs progress-dialog. */ 65 virtual ~UIProgressDialog() /* override */; 66 67 /** Executes the progress-dialog within its loop with passed @a iRefreshInterval. */ 68 int run(int iRefreshInterval); 69 70 public slots: 71 72 /** Shows progress-dialog if it's not yet shown. */ 73 void show(); 45 /** Constructs event proxy object on the basis of passed @a pParent. */ 46 UIProgressEventHandler(QObject *pParent, const CProgress &comProgress); 47 /** Destructs event proxy object. */ 48 virtual ~UIProgressEventHandler() /* override */; 74 49 75 50 protected: 76 51 77 /** Handles translation event. */ 78 virtual void retranslateUi() /* override */; 52 /** @name Prepare/Cleanup cascade. 53 * @{ */ 54 /** Prepares all. */ 55 void prepare(); 56 /** Prepares listener. */ 57 void prepareListener(); 58 /** Prepares connections. */ 59 void prepareConnections(); 79 60 80 /** Rejects dialog. */ 81 virtual void reject() /* override */; 82 83 /** Handles timer @a pEvent. */ 84 virtual void timerEvent(QTimerEvent *pEvent) /* override */; 85 /** Handles close @a pEvent. */ 86 virtual void closeEvent(QCloseEvent *pEvent) /* override */; 87 88 private slots: 89 90 /** Handles percentage changed event for progress with @a uProgressId to @a iPercent. */ 91 void sltHandleProgressPercentageChange(const QUuid &uProgressId, const int iPercent); 92 /** Handles task completed event for progress with @a uProgressId. */ 93 void sltHandleProgressTaskComplete(const QUuid &uProgressId); 94 95 /** Handles window stack changed signal. */ 96 void sltHandleWindowStackChange(); 97 98 /** Handles request to cancel operation. */ 99 void sltCancelOperation(); 61 /** Cleanups connections. */ 62 void cleanupConnections(); 63 /** Cleanups listener. */ 64 void cleanupListener(); 65 /** Cleanups all. */ 66 void cleanup(); 67 /** @} */ 100 68 101 69 private: 102 70 103 /** Prepares all. */ 104 void prepare(); 105 /** Prepares event handler. */ 106 void prepareEventHandler(); 107 /** Prepares widgets. */ 108 void prepareWidgets(); 109 /** Cleanups widgets. */ 110 void cleanupWidgets(); 111 /** Cleanups event handler. */ 112 void cleanupEventHandler(); 113 /** Cleanups all. */ 114 void cleanup(); 71 /** Holds the progress wrapper. */ 72 CProgress m_comProgress; 115 73 116 /** Updates progress-dialog state. */ 117 void updateProgressState(); 118 /** Updates progress-dialog percentage. */ 119 void updateProgressPercentage(int iPercent = -1); 120 121 /** Closes progress dialog (if possible). */ 122 void closeProgressDialog(); 123 124 /** Performes timer event handling. */ 125 void handleTimerEvent(); 126 127 /** Holds the progress reference. */ 128 CProgress &m_comProgress; 129 /** Holds the progress-dialog title. */ 130 QString m_strTitle; 131 /** Holds the dialog image. */ 132 QPixmap *m_pImage; 133 /** Holds the minimum duration before the progress-dialog is shown. */ 134 int m_cMinDuration; 135 136 /** Holds whether legacy handling is requested for this progress. */ 137 bool m_fLegacyHandling; 138 139 /** Holds the image label instance. */ 140 QLabel *m_pLabelImage; 141 /** Holds the description label instance. */ 142 QILabel *m_pLabelDescription; 143 /** Holds the progress-bar instance. */ 144 QProgressBar *m_pProgressBar; 145 /** Holds the cancel button instance. */ 146 UIMiniCancelButton *m_pButtonCancel; 147 /** Holds the ETA label instance. */ 148 QILabel *m_pLabelEta; 149 150 /** Holds the amount of operations. */ 151 const ulong m_cOperations; 152 /** Holds the number of current operation. */ 153 ulong m_uCurrentOperation; 154 /** Holds whether progress cancel is enabled. */ 155 bool m_fCancelEnabled; 156 /** Holds whether the progress has ended. */ 157 bool m_fEnded; 158 159 /** Holds the progress event handler instance. */ 160 UIProgressEventHandler *m_pEventHandler; 161 162 /** Holds the operation description template. */ 163 static const char *m_spcszOpDescTpl; 74 /** Holds the Qt event listener instance. */ 75 ComObjPtr<UIMainEventListenerImpl> m_pQtListener; 76 /** Holds the COM event listener instance. */ 77 CEventListener m_comEventListener; 164 78 }; 165 79 166 80 167 /** QObject reimplementation allowing to effectively track the CProgress object completion 168 * (w/o using CProgress::waitForCompletion() and w/o blocking the calling thread in any other way for too long). 169 * @note The CProgress instance is passed as a non-const reference to the constructor 170 * (to memorize COM errors if they happen), and therefore must not be destroyed 171 * before the created UIProgress instance is destroyed. 172 * @todo To be moved to separate files. */ 173 class SHARED_LIBRARY_STUFF UIProgress : public QObject 174 { 175 Q_OBJECT; 176 177 signals: 178 179 /** Notifies listeners about wrapped CProgress change. 180 * @param iOperations Brings the number of operations CProgress have. 181 * @param strOperation Brings the description of the current CProgress operation. 182 * @param iOperation Brings the index of the current CProgress operation. 183 * @param iPercent Brings the percentage of the current CProgress operation. */ 184 void sigProgressChange(ulong iOperations, QString strOperation, 185 ulong iOperation, ulong iPercent); 186 187 /** Notifies listeners about particular COM error. 188 * @param strErrorInfo holds the details of the error happened. */ 189 void sigProgressError(QString strErrorInfo); 190 191 public: 192 193 /** Constructs progress handler passing @a pParent to the base-class. 194 * @param comProgress Brings the progress reference. */ 195 UIProgress(CProgress &comProgress, QObject *pParent = 0); 196 197 /** Executes the progress-handler within its loop with passed @a iRefreshInterval. */ 198 void run(int iRefreshInterval); 199 200 private: 201 202 /** Handles timer @a pEvent. */ 203 virtual void timerEvent(QTimerEvent *pEvent) /* override */; 204 205 /** Holds the progress reference. */ 206 CProgress &m_comProgress; 207 208 /** Holds the amount of operations. */ 209 const ulong m_cOperations; 210 /** Holds whether the progress has ended. */ 211 bool m_fEnded; 212 213 /** Holds the personal event-loop instance. */ 214 QPointer<QEventLoop> m_pEventLoop; 215 }; 216 217 218 #endif /* !___UIProgressDialog_h___ */ 219 81 #endif /* !___UIProgressEventHandler_h___ */ -
trunk/src/VBox/Frontends/VirtualBox/src/widgets/UIProgressDialog.cpp
r74942 r75369 36 36 # include "UIModalWindowManager.h" 37 37 # include "UIProgressDialog.h" 38 # include "UIProgressEventHandler.h" 38 39 # include "UISpecialControls.h" 39 40 # include "VBoxGlobal.h" … … 48 49 49 50 #endif /* !VBOX_WITH_PRECOMPILED_HEADERS */ 50 51 52 /** Private QObject extension53 * providing UIExtraDataManager with the CVirtualBox event-source. */54 class UIProgressEventHandler : public QObject55 {56 Q_OBJECT;57 58 signals:59 60 /** Notifies about @a iPercent change for progress with @a uProgressId. */61 void sigProgressPercentageChange(const QUuid &uProgressId, const int iPercent);62 /** Notifies about task complete for progress with @a uProgressId. */63 void sigProgressTaskComplete(const QUuid &uProgressId);64 65 public:66 67 /** Constructs event proxy object on the basis of passed @a pParent. */68 UIProgressEventHandler(QObject *pParent, const CProgress &comProgress);69 /** Destructs event proxy object. */70 virtual ~UIProgressEventHandler() /* override */;71 72 protected:73 74 /** @name Prepare/Cleanup cascade.75 * @{ */76 /** Prepares all. */77 void prepare();78 /** Prepares listener. */79 void prepareListener();80 /** Prepares connections. */81 void prepareConnections();82 83 /** Cleanups connections. */84 void cleanupConnections();85 /** Cleanups listener. */86 void cleanupListener();87 /** Cleanups all. */88 void cleanup();89 /** @} */90 91 private:92 93 /** Holds the progress wrapper. */94 CProgress m_comProgress;95 96 /** Holds the Qt event listener instance. */97 ComObjPtr<UIMainEventListenerImpl> m_pQtListener;98 /** Holds the COM event listener instance. */99 CEventListener m_comEventListener;100 };101 102 103 /*********************************************************************************************************************************104 * Class UIProgressEventHandler implementation. *105 *********************************************************************************************************************************/106 107 UIProgressEventHandler::UIProgressEventHandler(QObject *pParent, const CProgress &comProgress)108 : QObject(pParent)109 , m_comProgress(comProgress)110 {111 /* Prepare: */112 prepare();113 }114 115 UIProgressEventHandler::~UIProgressEventHandler()116 {117 /* Cleanup: */118 cleanup();119 }120 121 void UIProgressEventHandler::prepare()122 {123 /* Prepare: */124 prepareListener();125 prepareConnections();126 }127 128 void UIProgressEventHandler::prepareListener()129 {130 /* Create event listener instance: */131 m_pQtListener.createObject();132 m_pQtListener->init(new UIMainEventListener, this);133 m_comEventListener = CEventListener(m_pQtListener);134 135 /* Get CProgress event source: */136 CEventSource comEventSourceProgress = m_comProgress.GetEventSource();137 AssertWrapperOk(comEventSourceProgress);138 139 /* Enumerate all the required event-types: */140 QVector<KVBoxEventType> eventTypes;141 eventTypes142 << KVBoxEventType_OnProgressPercentageChanged143 << KVBoxEventType_OnProgressTaskCompleted;144 145 /* Register event listener for CProgress event source: */146 comEventSourceProgress.RegisterListener(m_comEventListener, eventTypes,147 gEDataManager->eventHandlingType() == EventHandlingType_Active ? TRUE : FALSE);148 AssertWrapperOk(comEventSourceProgress);149 150 /* If event listener registered as passive one: */151 if (gEDataManager->eventHandlingType() == EventHandlingType_Passive)152 {153 /* Register event sources in their listeners as well: */154 m_pQtListener->getWrapped()->registerSource(comEventSourceProgress, m_comEventListener);155 }156 }157 158 void UIProgressEventHandler::prepareConnections()159 {160 /* Create direct (sync) connections for signals of main listener: */161 connect(m_pQtListener->getWrapped(), &UIMainEventListener::sigProgressPercentageChange,162 this, &UIProgressEventHandler::sigProgressPercentageChange,163 Qt::DirectConnection);164 connect(m_pQtListener->getWrapped(), &UIMainEventListener::sigProgressTaskComplete,165 this, &UIProgressEventHandler::sigProgressTaskComplete,166 Qt::DirectConnection);167 }168 169 void UIProgressEventHandler::cleanupConnections()170 {171 /* Nothing for now. */172 }173 174 void UIProgressEventHandler::cleanupListener()175 {176 /* If event listener registered as passive one: */177 if (gEDataManager->eventHandlingType() == EventHandlingType_Passive)178 {179 /* Unregister everything: */180 m_pQtListener->getWrapped()->unregisterSources();181 }182 183 /* Make sure VBoxSVC is available: */184 if (!vboxGlobal().isVBoxSVCAvailable())185 return;186 187 /* Get CProgress event source: */188 CEventSource comEventSourceProgress = m_comProgress.GetEventSource();189 AssertWrapperOk(comEventSourceProgress);190 191 /* Unregister event listener for CProgress event source: */192 comEventSourceProgress.UnregisterListener(m_comEventListener);193 }194 195 void UIProgressEventHandler::cleanup()196 {197 /* Cleanup: */198 cleanupConnections();199 cleanupListener();200 }201 51 202 52 … … 764 614 } 765 615 } 766 767 768 #include "UIProgressDialog.moc"769
Note:
See TracChangeset
for help on using the changeset viewer.