Changeset 86772 in vbox for trunk/src/VBox/Frontends
- Timestamp:
- Oct 30, 2020 4:02:16 PM (4 years ago)
- Location:
- trunk/src/VBox/Frontends/VirtualBox
- Files:
-
- 6 edited
- 2 copied
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Frontends/VirtualBox/Makefile.kmk
r86707 r86772 802 802 src/globals/UIPopupCenter.h \ 803 803 src/globals/UIProgressEventHandler.h \ 804 src/globals/UIProgressObject.h \ 804 805 src/globals/UIQObjectStuff.h \ 805 806 src/globals/UIShortcutPool.h \ … … 1320 1321 src/globals/UIPopupCenter.cpp \ 1321 1322 src/globals/UIProgressEventHandler.cpp \ 1323 src/globals/UIProgressObject.cpp \ 1322 1324 src/globals/UIQObjectStuff.cpp \ 1323 1325 src/globals/UIShortcutPool.cpp \ -
trunk/src/VBox/Frontends/VirtualBox/src/globals/UIProgressObject.cpp
r86768 r86772 1 1 /* $Id$ */ 2 2 /** @file 3 * VBox Qt GUI - UIProgress Dialogclass implementation.3 * VBox Qt GUI - UIProgressObject class implementation. 4 4 */ 5 5 … … 16 16 */ 17 17 18 /* Qt includes: */19 #include <QCloseEvent>20 #include <QEventLoop>21 #include <QProgressBar>22 #include <QTime>23 #include <QTimer>24 #include <QVBoxLayout>25 26 18 /* GUI includes: */ 27 #include "QIDialogButtonBox.h"28 #include "QILabel.h"29 19 #include "UIErrorString.h" 30 #include "UIExtraDataManager.h"31 #include "UIMainEventListener.h"32 #include "UIModalWindowManager.h"33 #include "UIProgressDialog.h"34 20 #include "UIProgressEventHandler.h" 35 #include "UISpecialControls.h" 36 #include "UICommon.h" 37 #ifdef VBOX_WS_MAC 38 # include "VBoxUtils-darwin.h" 39 #endif 21 #include "UIProgressObject.h" 40 22 41 23 /* COM includes: */ 42 #include "CEventListener.h"43 #include "CEventSource.h"44 24 #include "CProgress.h" 45 25 46 26 47 /********************************************************************************************************************************* 48 * Class UIProgressDialog implementation. * 49 *********************************************************************************************************************************/ 50 51 const char *UIProgressDialog::m_spcszOpDescTpl = "%1 ... (%2/%3)"; 52 53 UIProgressDialog::UIProgressDialog(CProgress &comProgress, 54 const QString &strTitle, 55 QPixmap *pImage /* = 0 */, 56 int cMinDuration /* = 2000 */, 57 QWidget *pParent /* = 0 */) 58 : QIWithRetranslateUI2<QIDialog>(pParent, Qt::MSWindowsFixedSizeDialogHint | Qt::WindowTitleHint) 59 , m_comProgress(comProgress) 60 , m_strTitle(strTitle) 61 , m_pImage(pImage) 62 , m_cMinDuration(cMinDuration) 63 , m_fLegacyHandling(gEDataManager->legacyProgressHandlingRequested()) 64 , m_pLabelImage(0) 65 , m_pLabelDescription(0) 66 , m_pProgressBar(0) 67 , m_pButtonCancel(0) 68 , m_pLabelEta(0) 69 , m_cOperations(m_comProgress.GetOperationCount()) 70 , m_uCurrentOperation(m_comProgress.GetOperation() + 1) 71 , m_uCurrentOperationWeight(m_comProgress.GetOperationWeight()) 72 , m_fCancelEnabled(false) 73 , m_fEnded(false) 74 , m_pEventHandler(0) 75 { 76 /* Prepare: */ 77 prepare(); 78 } 79 80 UIProgressDialog::~UIProgressDialog() 81 { 82 /* Cleanup: */ 83 cleanup(); 84 } 85 86 void UIProgressDialog::retranslateUi() 87 { 88 m_pButtonCancel->setText(tr("&Cancel")); 89 m_pButtonCancel->setToolTip(tr("Cancel the current operation")); 90 } 91 92 int UIProgressDialog::run(int cRefreshInterval) 93 { 94 /* Make sure progress hasn't finished already: */ 95 if (!m_comProgress.isOk() || m_comProgress.GetCompleted()) 96 { 97 /* Progress completed? */ 98 if (m_comProgress.isOk()) 99 return Accepted; 100 /* Or aborted? */ 101 else 102 return Rejected; 103 } 104 105 /* Start refresh timer (if necessary): */ 106 int id = 0; 107 if (m_fLegacyHandling) 108 id = startTimer(cRefreshInterval); 109 110 /* Set busy cursor. 111 * We don't do this on the Mac, cause regarding the design rules of 112 * Apple there is no busy window behavior. A window should always be 113 * responsive and it is in our case (We show the progress dialog bar). */ 114 #ifndef VBOX_WS_MAC 115 if (m_fCancelEnabled) 116 QApplication::setOverrideCursor(QCursor(Qt::BusyCursor)); 117 else 118 QApplication::setOverrideCursor(QCursor(Qt::WaitCursor)); 119 #endif /* VBOX_WS_MAC */ 120 121 /* Create a local event-loop: */ 122 { 123 /* Guard ourself for the case 124 * we destroyed ourself in our event-loop: */ 125 QPointer<UIProgressDialog> guard = this; 126 127 /* Holds the modal loop, but don't show the window immediately: */ 128 execute(false); 129 130 /* Are we still valid? */ 131 if (guard.isNull()) 132 return Rejected; 133 } 134 135 /* Kill refresh timer (if necessary): */ 136 if (m_fLegacyHandling) 137 killTimer(id); 138 139 #ifndef VBOX_WS_MAC 140 /* Reset the busy cursor */ 141 QApplication::restoreOverrideCursor(); 142 #endif /* VBOX_WS_MAC */ 143 144 return result(); 145 } 146 147 void UIProgressDialog::show() 148 { 149 /* We should not show progress-dialog 150 * if it was already finalized but not yet closed. 151 * This could happens in case of some other 152 * modal dialog prevents our event-loop from 153 * being exit overlapping 'this'. */ 154 if (!m_fEnded) 155 QIDialog::show(); 156 } 157 158 void UIProgressDialog::reject() 159 { 160 if (m_fCancelEnabled) 161 sltCancelOperation(); 162 } 163 164 void UIProgressDialog::timerEvent(QTimerEvent *) 165 { 166 /* Call the timer event handling delegate: */ 167 handleTimerEvent(); 168 } 169 170 void UIProgressDialog::closeEvent(QCloseEvent *pEvent) 171 { 172 if (m_fCancelEnabled) 173 sltCancelOperation(); 174 else 175 pEvent->ignore(); 176 } 177 178 void UIProgressDialog::sltHandleProgressPercentageChange(const QUuid &, const int iPercent) 179 { 180 /* New mode only: */ 181 AssertReturnVoid(!m_fLegacyHandling); 182 183 /* Update progress: */ 184 updateProgressState(); 185 updateProgressPercentage(iPercent); 186 } 187 188 void UIProgressDialog::sltHandleProgressTaskComplete(const QUuid &) 189 { 190 /* New mode only: */ 191 AssertReturnVoid(!m_fLegacyHandling); 192 193 /* If progress-dialog is not yet ended but progress is aborted or completed: */ 194 if (!m_fEnded && (!m_comProgress.isOk() || m_comProgress.GetCompleted())) 195 { 196 /* Set progress to 100%: */ 197 updateProgressPercentage(100); 198 199 /* Try to close the dialog: */ 200 closeProgressDialog(); 201 } 202 } 203 204 void UIProgressDialog::sltHandleWindowStackChange() 205 { 206 /* If progress-dialog is not yet ended but progress is aborted or completed: */ 207 if (!m_fEnded && (!m_comProgress.isOk() || m_comProgress.GetCompleted())) 208 { 209 /* Try to close the dialog: */ 210 closeProgressDialog(); 211 } 212 } 213 214 void UIProgressDialog::sltCancelOperation() 215 { 216 m_pButtonCancel->setEnabled(false); 217 m_comProgress.Cancel(); 218 } 219 220 void UIProgressDialog::prepare() 221 { 222 /* Setup dialog: */ 223 if (m_strTitle.isNull()) 224 setWindowTitle(m_comProgress.GetDescription()); 225 else 226 setWindowTitle(QString("%1: %2").arg(m_strTitle, m_comProgress.GetDescription())); 227 setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); 228 #ifdef VBOX_WS_MAC 229 ::darwinSetHidesAllTitleButtons(this); 230 #endif 231 232 /* Make sure dialog is handling window stack changes: */ 233 connect(&windowManager(), &UIModalWindowManager::sigStackChanged, 234 this, &UIProgressDialog::sltHandleWindowStackChange); 235 236 /* Prepare: */ 237 prepareEventHandler(); 238 prepareWidgets(); 239 } 240 241 void UIProgressDialog::prepareEventHandler() 242 { 243 if (!m_fLegacyHandling) 244 { 245 /* Create CProgress event handler: */ 246 m_pEventHandler = new UIProgressEventHandler(this, m_comProgress); 247 connect(m_pEventHandler, &UIProgressEventHandler::sigProgressPercentageChange, 248 this, &UIProgressDialog::sltHandleProgressPercentageChange); 249 connect(m_pEventHandler, &UIProgressEventHandler::sigProgressTaskComplete, 250 this, &UIProgressDialog::sltHandleProgressTaskComplete); 251 } 252 } 253 254 void UIProgressDialog::prepareWidgets() 255 { 256 /* Create main layout: */ 257 QHBoxLayout *pMainLayout = new QHBoxLayout(this); 258 AssertPtrReturnVoid(pMainLayout); 259 { 260 /* Configure layout: */ 261 #ifdef VBOX_WS_MAC 262 if (m_pImage) 263 pMainLayout->setContentsMargins(30, 15, 30, 15); 264 else 265 pMainLayout->setContentsMargins(6, 6, 6, 6); 266 #endif 267 268 /* If there is image: */ 269 if (m_pImage) 270 { 271 /* Create image label: */ 272 m_pLabelImage = new QLabel; 273 AssertPtrReturnVoid(m_pLabelImage); 274 { 275 /* Configure label: */ 276 m_pLabelImage->setPixmap(*m_pImage); 277 278 /* Add into layout: */ 279 pMainLayout->addWidget(m_pLabelImage); 280 } 281 } 282 283 /* Create description layout: */ 284 QVBoxLayout *pDescriptionLayout = new QVBoxLayout; 285 AssertPtrReturnVoid(pDescriptionLayout); 286 { 287 /* Configure layout: */ 288 pDescriptionLayout->setMargin(0); 289 290 /* Add stretch: */ 291 pDescriptionLayout->addStretch(1); 292 293 /* Create description label: */ 294 m_pLabelDescription = new QILabel; 295 AssertPtrReturnVoid(m_pLabelDescription); 296 { 297 /* Configure label: */ 298 if (m_cOperations > 1) 299 m_pLabelDescription->setText(QString(m_spcszOpDescTpl) 300 .arg(m_comProgress.GetOperationDescription()) 301 .arg(m_uCurrentOperation).arg(m_cOperations)); 302 else 303 m_pLabelDescription->setText(QString("%1 ...") 304 .arg(m_comProgress.GetOperationDescription())); 305 306 /* Add into layout: */ 307 pDescriptionLayout->addWidget(m_pLabelDescription, 0, Qt::AlignHCenter); 308 } 309 310 /* Create proggress layout: */ 311 QHBoxLayout *pProgressLayout = new QHBoxLayout; 312 AssertPtrReturnVoid(pProgressLayout); 313 { 314 /* Configure layout: */ 315 pProgressLayout->setMargin(0); 316 317 /* Create progress-bar: */ 318 m_pProgressBar = new QProgressBar; 319 AssertPtrReturnVoid(m_pProgressBar); 320 { 321 /* Configure progress-bar: */ 322 // WORKAROUND: 323 // Based on agreement implemented in r131088 and r131090, 324 // if progress has just one operation with weight equal to 1, 325 // we should make it "infinite" by setting maximum to minimum. 326 if (m_uCurrentOperation == 1 && m_uCurrentOperationWeight == 1) 327 m_pProgressBar->setMaximum(0); 328 else 329 m_pProgressBar->setMaximum(100); 330 m_pProgressBar->setValue(0); 331 332 /* Add into layout: */ 333 pProgressLayout->addWidget(m_pProgressBar, 0, Qt::AlignVCenter); 334 } 335 336 /* Create cancel button: */ 337 m_pButtonCancel = new UIMiniCancelButton; 338 AssertPtrReturnVoid(m_pButtonCancel); 339 { 340 /* Configure cancel button: */ 341 m_fCancelEnabled = m_comProgress.GetCancelable(); 342 m_pButtonCancel->setEnabled(m_fCancelEnabled); 343 m_pButtonCancel->setFocusPolicy(Qt::ClickFocus); 344 connect(m_pButtonCancel, &UIMiniCancelButton::clicked, this, &UIProgressDialog::sltCancelOperation); 345 346 /* Add into layout: */ 347 pProgressLayout->addWidget(m_pButtonCancel, 0, Qt::AlignVCenter); 348 } 349 350 /* Add into layout: */ 351 pDescriptionLayout->addLayout(pProgressLayout); 352 } 353 354 /* Create estimation label: */ 355 m_pLabelEta = new QILabel; 356 { 357 /* Add into layout: */ 358 pDescriptionLayout->addWidget(m_pLabelEta, 0, Qt::AlignLeft | Qt::AlignVCenter); 359 } 360 361 /* Add stretch: */ 362 pDescriptionLayout->addStretch(1); 363 364 /* Add into layout: */ 365 pMainLayout->addLayout(pDescriptionLayout); 366 } 367 } 368 369 /* Translate finally: */ 370 retranslateUi(); 371 372 /* The progress dialog will be shown automatically after 373 * the duration is over if progress is not finished yet. */ 374 QTimer::singleShot(m_cMinDuration, this, SLOT(show())); 375 } 376 377 void UIProgressDialog::cleanupWidgets() 378 { 379 /* Nothing for now. */ 380 } 381 382 void UIProgressDialog::cleanupEventHandler() 383 { 384 if (!m_fLegacyHandling) 385 { 386 /* Destroy CProgress event handler: */ 387 delete m_pEventHandler; 388 m_pEventHandler = 0; 389 } 390 } 391 392 void UIProgressDialog::cleanup() 393 { 394 /* Wait for CProgress to complete: */ 395 m_comProgress.WaitForCompletion(-1); 396 397 /* Call the timer event handling delegate: */ 398 if (m_fLegacyHandling) 399 handleTimerEvent(); 400 401 /* Cleanup: */ 402 cleanupEventHandler(); 403 cleanupWidgets(); 404 } 405 406 void UIProgressDialog::updateProgressState() 407 { 408 /* Mark progress canceled if so: */ 409 if (m_comProgress.GetCanceled()) 410 m_pLabelEta->setText(tr("Canceling...")); 411 /* Update the progress dialog otherwise: */ 412 else 413 { 414 /* Update ETA: */ 415 const long iNewTime = m_comProgress.GetTimeRemaining(); 416 long iSeconds; 417 long iMinutes; 418 long iHours; 419 long iDays; 420 421 iSeconds = iNewTime < 0 ? 0 : iNewTime; 422 iMinutes = iSeconds / 60; 423 iSeconds -= iMinutes * 60; 424 iHours = iMinutes / 60; 425 iMinutes -= iHours * 60; 426 iDays = iHours / 24; 427 iHours -= iDays * 24; 428 429 const QString strDays = UICommon::daysToString(iDays); 430 const QString strHours = UICommon::hoursToString(iHours); 431 const QString strMinutes = UICommon::minutesToString(iMinutes); 432 const QString strSeconds = UICommon::secondsToString(iSeconds); 433 434 const QString strTwoComp = tr("%1, %2 remaining", "You may wish to translate this more like \"Time remaining: %1, %2\""); 435 const QString strOneComp = tr("%1 remaining", "You may wish to translate this more like \"Time remaining: %1\""); 436 437 if (iDays > 1 && iHours > 0) 438 m_pLabelEta->setText(strTwoComp.arg(strDays).arg(strHours)); 439 else if (iDays > 1) 440 m_pLabelEta->setText(strOneComp.arg(strDays)); 441 else if (iDays > 0 && iHours > 0) 442 m_pLabelEta->setText(strTwoComp.arg(strDays).arg(strHours)); 443 else if (iDays > 0 && iMinutes > 5) 444 m_pLabelEta->setText(strTwoComp.arg(strDays).arg(strMinutes)); 445 else if (iDays > 0) 446 m_pLabelEta->setText(strOneComp.arg(strDays)); 447 else if (iHours > 2) 448 m_pLabelEta->setText(strOneComp.arg(strHours)); 449 else if (iHours > 0 && iMinutes > 0) 450 m_pLabelEta->setText(strTwoComp.arg(strHours).arg(strMinutes)); 451 else if (iHours > 0) 452 m_pLabelEta->setText(strOneComp.arg(strHours)); 453 else if (iMinutes > 2) 454 m_pLabelEta->setText(strOneComp.arg(strMinutes)); 455 else if (iMinutes > 0 && iSeconds > 5) 456 m_pLabelEta->setText(strTwoComp.arg(strMinutes).arg(strSeconds)); 457 else if (iMinutes > 0) 458 m_pLabelEta->setText(strOneComp.arg(strMinutes)); 459 else if (iSeconds > 5) 460 m_pLabelEta->setText(strOneComp.arg(strSeconds)); 461 else if (iSeconds > 0) 462 m_pLabelEta->setText(tr("A few seconds remaining")); 463 else 464 m_pLabelEta->clear(); 465 466 /* Then operation text (if changed): */ 467 ulong uNewOp = m_comProgress.GetOperation() + 1; 468 if (uNewOp != m_uCurrentOperation) 469 { 470 m_uCurrentOperation = uNewOp; 471 m_uCurrentOperationWeight = m_comProgress.GetOperationWeight(); 472 m_pLabelDescription->setText(QString(m_spcszOpDescTpl) 473 .arg(m_comProgress.GetOperationDescription()) 474 .arg(m_uCurrentOperation).arg(m_cOperations)); 475 } 476 477 /* Then cancel button: */ 478 m_fCancelEnabled = m_comProgress.GetCancelable(); 479 m_pButtonCancel->setEnabled(m_fCancelEnabled); 480 } 481 } 482 483 void UIProgressDialog::updateProgressPercentage(int iPercent /* = -1 */) 484 { 485 /* Update operation percentage: */ 486 if (iPercent == -1) 487 iPercent = m_comProgress.GetPercent(); 488 m_pProgressBar->setValue(iPercent); 489 490 /* Notify listeners about the operation progress update: */ 491 emit sigProgressChange(m_cOperations, m_comProgress.GetOperationDescription(), 492 m_comProgress.GetOperation() + 1, iPercent); 493 } 494 495 void UIProgressDialog::closeProgressDialog() 496 { 497 /* If window is on the top of the stack: */ 498 if (windowManager().isWindowOnTheTopOfTheModalWindowStack(this)) 499 { 500 /* Progress completed? */ 501 if (m_comProgress.isOk()) 502 done(Accepted); 503 /* Or aborted? */ 504 else 505 done(Rejected); 506 507 /* Mark progress-dialog finished: */ 508 m_fEnded = true; 509 } 510 } 511 512 void UIProgressDialog::handleTimerEvent() 513 { 514 /* Old mode only: */ 515 AssertReturnVoid(m_fLegacyHandling); 516 517 /* If progress-dialog is ended: */ 518 if (m_fEnded) 519 { 520 // WORKAROUND: 521 // We should hide progress-dialog if it was already ended but not yet closed. This could happen 522 // in case if some other modal dialog prevents our event-loop from being exit overlapping 'this'. 523 /* If window is on the top of the stack and still shown: */ 524 if (!isHidden() && windowManager().isWindowOnTheTopOfTheModalWindowStack(this)) 525 hide(); 526 527 return; 528 } 529 530 /* If progress-dialog is not yet ended but progress is aborted or completed: */ 531 if (!m_comProgress.isOk() || m_comProgress.GetCompleted()) 532 { 533 /* Set progress to 100%: */ 534 updateProgressPercentage(100); 535 536 /* Try to close the dialog: */ 537 return closeProgressDialog(); 538 } 539 540 /* Update progress: */ 541 updateProgressState(); 542 updateProgressPercentage(); 543 } 544 545 546 /********************************************************************************************************************************* 547 * Class UIProgress implementation. * 548 *********************************************************************************************************************************/ 549 550 UIProgress::UIProgress(CProgress &comProgress, QObject *pParent /* = 0 */) 27 UIProgressObject::UIProgressObject(CProgress &comProgress, QObject *pParent /* = 0 */) 551 28 : QObject(pParent) 552 29 , m_comProgress(comProgress) … … 556 33 } 557 34 558 UIProgress ::~UIProgress()35 UIProgressObject::~UIProgressObject() 559 36 { 560 37 cleanup(); 561 38 } 562 39 563 void UIProgress ::exec()40 void UIProgressObject::exec() 564 41 { 565 42 /* Make sure progress hasn't aborted/finished already: */ … … 574 51 /* Guard ourself for the case 575 52 * we self-destroyed in our event-loop: */ 576 QPointer<UIProgress > guard = this;53 QPointer<UIProgressObject> guard = this; 577 54 578 55 /* Start the blocking event-loop: */ … … 588 65 } 589 66 590 void UIProgress ::cancel()67 void UIProgressObject::cancel() 591 68 { 592 69 /* Make sure progress hasn't aborted/finished already: */ … … 604 81 /* Guard ourself for the case 605 82 * we self-destroyed in our event-loop: */ 606 QPointer<UIProgress > guard = this;83 QPointer<UIProgressObject> guard = this; 607 84 608 85 /* Start the blocking event-loop: */ … … 618 95 } 619 96 620 void UIProgress ::sltHandleProgressPercentageChange(const QUuid &, const int iPercent)97 void UIProgressObject::sltHandleProgressPercentageChange(const QUuid &, const int iPercent) 621 98 { 622 99 emit sigProgressChange(m_comProgress.GetOperationCount(), … … 626 103 } 627 104 628 void UIProgress ::sltHandleProgressTaskComplete(const QUuid &)105 void UIProgressObject::sltHandleProgressTaskComplete(const QUuid &) 629 106 { 630 107 /* Notify listeners about the operation progress error: */ … … 642 119 } 643 120 644 void UIProgress ::prepare()121 void UIProgressObject::prepare() 645 122 { 646 123 /* Create CProgress event handler: */ 647 124 m_pEventHandler = new UIProgressEventHandler(this, m_comProgress); 648 connect(m_pEventHandler, &UIProgressEventHandler::sigProgressPercentageChange, 649 this, &UIProgress::sltHandleProgressPercentageChange); 650 connect(m_pEventHandler, &UIProgressEventHandler::sigProgressTaskComplete, 651 this, &UIProgress::sltHandleProgressTaskComplete); 652 connect(m_pEventHandler, &UIProgressEventHandler::sigHandlingFinished, 653 this, &UIProgress::sigProgressEventHandlingFinished); 125 if (m_pEventHandler) 126 { 127 connect(m_pEventHandler, &UIProgressEventHandler::sigProgressPercentageChange, 128 this, &UIProgressObject::sltHandleProgressPercentageChange); 129 connect(m_pEventHandler, &UIProgressEventHandler::sigProgressTaskComplete, 130 this, &UIProgressObject::sltHandleProgressTaskComplete); 131 connect(m_pEventHandler, &UIProgressEventHandler::sigHandlingFinished, 132 this, &UIProgressObject::sigProgressEventHandlingFinished); 133 } 654 134 } 655 135 656 void UIProgress ::cleanup()136 void UIProgressObject::cleanup() 657 137 { 658 138 /* Destroy CProgress event handler: */ -
trunk/src/VBox/Frontends/VirtualBox/src/globals/UIProgressObject.h
r86768 r86772 1 1 /* $Id$ */ 2 2 /** @file 3 * VBox Qt GUI - UIProgress Dialogclass declaration.3 * VBox Qt GUI - UIProgressObject class declaration. 4 4 */ 5 5 … … 16 16 */ 17 17 18 #ifndef FEQT_INCLUDED_SRC_ widgets_UIProgressDialog_h19 #define FEQT_INCLUDED_SRC_ widgets_UIProgressDialog_h18 #ifndef FEQT_INCLUDED_SRC_globals_UIProgressObject_h 19 #define FEQT_INCLUDED_SRC_globals_UIProgressObject_h 20 20 #ifndef RT_WITHOUT_PRAGMA_ONCE 21 21 # pragma once 22 22 #endif 23 23 24 /* Qt includes: */ 25 #include <QEventLoop> 26 #include <QObject> 27 #include <QPointer> 28 24 29 /* GUI includes: */ 25 #include "QIDialog.h"26 #include "QIWithRetranslateUI.h"27 30 #include "UILibraryDefs.h" 28 31 29 32 /* Forward declarations: */ 30 class QLabel;31 class QProgressBar;32 class QILabel;33 class UIMiniCancelButton;34 33 class UIProgressEventHandler; 35 34 class CProgress; 36 37 38 /** QProgressDialog enhancement that allows to:39 * 1) prevent closing the dialog when it has no cancel button;40 * 2) effectively track the IProgress object completion (w/o using41 * IProgress::waitForCompletion() and w/o blocking the UI thread in any other way for too long).42 * @note The CProgress instance is passed as a non-const reference to the constructor (to memorize COM errors if they happen),43 * and therefore must not be destroyed before the created UIProgressDialog instance is destroyed. */44 class SHARED_LIBRARY_STUFF UIProgressDialog : public QIWithRetranslateUI2<QIDialog>45 {46 Q_OBJECT;47 48 signals:49 50 /** Notifies listeners about wrapped CProgress change.51 * @param iOperations Brings the number of operations CProgress have.52 * @param strOperation Brings the description of the current CProgress operation.53 * @param iOperation Brings the index of the current CProgress operation.54 * @param iPercent Brings the percentage of the current CProgress operation. */55 void sigProgressChange(ulong iOperations, QString strOperation,56 ulong iOperation, ulong iPercent);57 58 public:59 60 /** Constructs progress-dialog passing @a pParent to the base-class.61 * @param comProgress Brings the progress reference.62 * @param strTitle Brings the progress-dialog title.63 * @param pImage Brings the progress-dialog image.64 * @param cMinDuration Brings the minimum duration before the progress-dialog is shown. */65 UIProgressDialog(CProgress &comProgress, const QString &strTitle,66 QPixmap *pImage = 0, int cMinDuration = 2000, QWidget *pParent = 0);67 /** Destructs progress-dialog. */68 virtual ~UIProgressDialog() /* override */;69 70 /** Executes the progress-dialog within its loop with passed @a iRefreshInterval. */71 int run(int iRefreshInterval);72 73 public slots:74 75 /** Shows progress-dialog if it's not yet shown. */76 void show();77 78 protected:79 80 /** Handles translation event. */81 virtual void retranslateUi() /* override */;82 83 /** Rejects dialog. */84 virtual void reject() /* override */;85 86 /** Handles timer @a pEvent. */87 virtual void timerEvent(QTimerEvent *pEvent) /* override */;88 /** Handles close @a pEvent. */89 virtual void closeEvent(QCloseEvent *pEvent) /* override */;90 91 private slots:92 93 /** Handles percentage changed event for progress with @a uProgressId to @a iPercent. */94 void sltHandleProgressPercentageChange(const QUuid &uProgressId, const int iPercent);95 /** Handles task completed event for progress with @a uProgressId. */96 void sltHandleProgressTaskComplete(const QUuid &uProgressId);97 98 /** Handles window stack changed signal. */99 void sltHandleWindowStackChange();100 101 /** Handles request to cancel operation. */102 void sltCancelOperation();103 104 private:105 106 /** Prepares all. */107 void prepare();108 /** Prepares event handler. */109 void prepareEventHandler();110 /** Prepares widgets. */111 void prepareWidgets();112 /** Cleanups widgets. */113 void cleanupWidgets();114 /** Cleanups event handler. */115 void cleanupEventHandler();116 /** Cleanups all. */117 void cleanup();118 119 /** Updates progress-dialog state. */120 void updateProgressState();121 /** Updates progress-dialog percentage. */122 void updateProgressPercentage(int iPercent = -1);123 124 /** Closes progress dialog (if possible). */125 void closeProgressDialog();126 127 /** Performes timer event handling. */128 void handleTimerEvent();129 130 /** Holds the progress reference. */131 CProgress &m_comProgress;132 /** Holds the progress-dialog title. */133 QString m_strTitle;134 /** Holds the dialog image. */135 QPixmap *m_pImage;136 /** Holds the minimum duration before the progress-dialog is shown. */137 int m_cMinDuration;138 139 /** Holds whether legacy handling is requested for this progress. */140 bool m_fLegacyHandling;141 142 /** Holds the image label instance. */143 QLabel *m_pLabelImage;144 /** Holds the description label instance. */145 QILabel *m_pLabelDescription;146 /** Holds the progress-bar instance. */147 QProgressBar *m_pProgressBar;148 /** Holds the cancel button instance. */149 UIMiniCancelButton *m_pButtonCancel;150 /** Holds the ETA label instance. */151 QILabel *m_pLabelEta;152 153 /** Holds the amount of operations. */154 const ulong m_cOperations;155 /** Holds the number of current operation. */156 ulong m_uCurrentOperation;157 /** Holds the weight of current operation. */158 ulong m_uCurrentOperationWeight;159 /** Holds whether progress cancel is enabled. */160 bool m_fCancelEnabled;161 /** Holds whether the progress has ended. */162 bool m_fEnded;163 164 /** Holds the progress event handler instance. */165 UIProgressEventHandler *m_pEventHandler;166 167 /** Holds the operation description template. */168 static const char *m_spcszOpDescTpl;169 };170 171 35 172 36 /** QObject reimplementation allowing to effectively track the CProgress object completion … … 174 38 * @note The CProgress instance is passed as a non-const reference to the constructor 175 39 * (to memorize COM errors if they happen), and therefore must not be destroyed 176 * before the created UIProgress instance is destroyed. 177 * @todo To be moved to separate files. */ 178 class SHARED_LIBRARY_STUFF UIProgress : public QObject 40 * before the created UIProgressObject instance is destroyed. */ 41 class SHARED_LIBRARY_STUFF UIProgressObject : public QObject 179 42 { 180 43 Q_OBJECT; … … 202 65 public: 203 66 204 /** Constructs progress handlerpassing @a pParent to the base-class.67 /** Constructs progress-object passing @a pParent to the base-class. 205 68 * @param comProgress Brings the progress reference. */ 206 UIProgress (CProgress &comProgress, QObject *pParent = 0);69 UIProgressObject(CProgress &comProgress, QObject *pParent = 0); 207 70 /** Destructs progress handler. */ 208 virtual ~UIProgress () /* override */;71 virtual ~UIProgressObject() /* override */; 209 72 210 73 /** Executes the progress within local event-loop. */ … … 239 102 }; 240 103 241 242 #endif /* !FEQT_INCLUDED_SRC_widgets_UIProgressDialog_h */ 243 104 #endif /* !FEQT_INCLUDED_SRC_globals_UIProgressObject_h */ -
trunk/src/VBox/Frontends/VirtualBox/src/manager/UIVirtualMachineItemCloud.cpp
r86771 r86772 27 27 #include "UIIconPool.h" 28 28 #include "UIMessageCenter.h" 29 #include "UIProgress Dialog.h"29 #include "UIProgressObject.h" 30 30 #include "UIThreadPool.h" 31 31 #include "UIVirtualMachineItemCloud.h" … … 314 314 { 315 315 /* Prepare 'Refresh' progress handler: */ 316 m_pProgressHandler = new UIProgress (m_comProgress, this);316 m_pProgressHandler = new UIProgressObject(m_comProgress, this); 317 317 if (m_pProgressHandler) 318 318 { 319 connect(m_pProgressHandler.data(), &UIProgress ::sigProgressEventHandlingFinished,319 connect(m_pProgressHandler.data(), &UIProgressObject::sigProgressEventHandlingFinished, 320 320 this, &UIVirtualMachineItemCloud::sltHandleRefreshCloudMachineInfoDone); 321 321 emit sigRefreshStarted(); -
trunk/src/VBox/Frontends/VirtualBox/src/manager/UIVirtualMachineItemCloud.h
r86771 r86772 35 35 /* Forward declarations: */ 36 36 class QTimer; 37 class UIProgress ;37 class UIProgressObject; 38 38 39 39 /** UIVirtualMachineItem sub-class used as cloud Virtual Machine item interface. */ … … 161 161 162 162 /** Holds whether we should update info. */ 163 bool m_fRefreshScheduled;163 bool m_fRefreshScheduled; 164 164 /** Holds the machine refresh timer instance. */ 165 QTimer *m_pTimer;165 QTimer *m_pTimer; 166 166 /** Holds the machine refresh progress object instance. */ 167 CProgress m_comProgress;167 CProgress m_comProgress; 168 168 /** Holds the machine refresh progress handler instance. */ 169 QPointer<UIProgress > m_pProgressHandler;169 QPointer<UIProgressObject> m_pProgressHandler; 170 170 /** @} */ 171 171 }; -
trunk/src/VBox/Frontends/VirtualBox/src/settings/machine/UIMachineSettingsGeneral.cpp
r86205 r86772 35 35 #include "UIModalWindowManager.h" 36 36 #include "UINameAndSystemEditor.h" 37 #include "UIProgress Dialog.h"37 #include "UIProgressObject.h" 38 38 39 39 /* COM includes: */ … … 1154 1154 1155 1155 /* Create encryption update progress object: */ 1156 QPointer<UIProgress > pObject;1156 QPointer<UIProgressObject> pObject; 1157 1157 if (fSuccess) 1158 1158 { 1159 pObject = new UIProgress (comProgress);1159 pObject = new UIProgressObject(comProgress); 1160 1160 if (pObject) 1161 1161 { 1162 connect(pObject.data(), &UIProgress ::sigProgressChange,1162 connect(pObject.data(), &UIProgressObject::sigProgressChange, 1163 1163 this, &UIMachineSettingsGeneral::sigOperationProgressChange, 1164 1164 Qt::QueuedConnection); 1165 connect(pObject.data(), &UIProgress ::sigProgressError,1165 connect(pObject.data(), &UIProgressObject::sigProgressError, 1166 1166 this, &UIMachineSettingsGeneral::sigOperationProgressError, 1167 1167 Qt::BlockingQueuedConnection); -
trunk/src/VBox/Frontends/VirtualBox/src/widgets/UIProgressDialog.cpp
r86325 r86772 44 44 #include "CProgress.h" 45 45 46 47 /*********************************************************************************************************************************48 * Class UIProgressDialog implementation. *49 *********************************************************************************************************************************/50 46 51 47 const char *UIProgressDialog::m_spcszOpDescTpl = "%1 ... (%2/%3)"; … … 542 538 updateProgressPercentage(); 543 539 } 544 545 546 /*********************************************************************************************************************************547 * Class UIProgress implementation. *548 *********************************************************************************************************************************/549 550 UIProgress::UIProgress(CProgress &comProgress, QObject *pParent /* = 0 */)551 : QObject(pParent)552 , m_comProgress(comProgress)553 , m_pEventHandler(0)554 {555 prepare();556 }557 558 UIProgress::~UIProgress()559 {560 cleanup();561 }562 563 void UIProgress::exec()564 {565 /* Make sure progress hasn't aborted/finished already: */566 if (!m_comProgress.isOk() || m_comProgress.GetCompleted())567 return;568 569 /* We are creating a locally-scoped event-loop object,570 * but holding a pointer to it for a control needs: */571 QEventLoop eventLoop;572 m_pEventLoopExec = &eventLoop;573 574 /* Guard ourself for the case575 * we self-destroyed in our event-loop: */576 QPointer<UIProgress> guard = this;577 578 /* Start the blocking event-loop: */579 eventLoop.exec();580 581 /* Event-loop object unblocked,582 * Are we still valid? */583 if (guard.isNull())584 return;585 586 /* Cleanup the pointer finally: */587 m_pEventLoopExec = 0;588 }589 590 void UIProgress::cancel()591 {592 /* Make sure progress hasn't aborted/finished already: */593 if (!m_comProgress.isOk() || m_comProgress.GetCompleted())594 return;595 596 /* Cancel progress first of all: */597 m_comProgress.Cancel();598 599 /* We are creating a locally-scoped event-loop object,600 * but holding a pointer to it for a control needs: */601 QEventLoop eventLoop;602 m_pEventLoopCancel = &eventLoop;603 604 /* Guard ourself for the case605 * we self-destroyed in our event-loop: */606 QPointer<UIProgress> guard = this;607 608 /* Start the blocking event-loop: */609 eventLoop.exec();610 611 /* Event-loop object unblocked,612 * Are we still valid? */613 if (guard.isNull())614 return;615 616 /* Cleanup the pointer finally: */617 m_pEventLoopCancel = 0;618 }619 620 void UIProgress::sltHandleProgressPercentageChange(const QUuid &, const int iPercent)621 {622 emit sigProgressChange(m_comProgress.GetOperationCount(),623 m_comProgress.GetOperationDescription(),624 m_comProgress.GetOperation(),625 iPercent);626 }627 628 void UIProgress::sltHandleProgressTaskComplete(const QUuid &)629 {630 /* Notify listeners about the operation progress error: */631 if (!m_comProgress.isOk() || m_comProgress.GetResultCode() != 0)632 emit sigProgressError(UIErrorString::formatErrorInfo(m_comProgress));633 634 /* Exit from the exec event-loop if there is any: */635 if (m_pEventLoopExec)636 m_pEventLoopExec->exit();637 /* Exit from the cancel event-loop if there is any: */638 if (m_pEventLoopCancel)639 m_pEventLoopCancel->exit();640 641 emit sigProgressComplete();642 }643 644 void UIProgress::prepare()645 {646 /* Create CProgress event handler: */647 m_pEventHandler = new UIProgressEventHandler(this, m_comProgress);648 connect(m_pEventHandler, &UIProgressEventHandler::sigProgressPercentageChange,649 this, &UIProgress::sltHandleProgressPercentageChange);650 connect(m_pEventHandler, &UIProgressEventHandler::sigProgressTaskComplete,651 this, &UIProgress::sltHandleProgressTaskComplete);652 connect(m_pEventHandler, &UIProgressEventHandler::sigHandlingFinished,653 this, &UIProgress::sigProgressEventHandlingFinished);654 }655 656 void UIProgress::cleanup()657 {658 /* Destroy CProgress event handler: */659 delete m_pEventHandler;660 m_pEventHandler = 0;661 } -
trunk/src/VBox/Frontends/VirtualBox/src/widgets/UIProgressDialog.h
r86325 r86772 34 34 class UIProgressEventHandler; 35 35 class CProgress; 36 37 36 38 37 /** QProgressDialog enhancement that allows to: … … 169 168 }; 170 169 171 172 /** QObject reimplementation allowing to effectively track the CProgress object completion173 * (w/o using CProgress::waitForCompletion() and w/o blocking the calling thread in any other way for too long).174 * @note The CProgress instance is passed as a non-const reference to the constructor175 * (to memorize COM errors if they happen), and therefore must not be destroyed176 * before the created UIProgress instance is destroyed.177 * @todo To be moved to separate files. */178 class SHARED_LIBRARY_STUFF UIProgress : public QObject179 {180 Q_OBJECT;181 182 signals:183 184 /** Notifies listeners about wrapped CProgress change.185 * @param iOperations Brings the number of operations CProgress have.186 * @param strOperation Brings the description of the current CProgress operation.187 * @param iOperation Brings the index of the current CProgress operation.188 * @param iPercent Brings the percentage of the current CProgress operation. */189 void sigProgressChange(ulong iOperations, QString strOperation,190 ulong iOperation, ulong iPercent);191 192 /** Notifies listeners about particular COM error.193 * @param strErrorInfo holds the details of the error happened. */194 void sigProgressError(QString strErrorInfo);195 196 /** Notifies listeners about wrapped CProgress complete. */197 void sigProgressComplete();198 199 /** Notifies listeners about CProgress event handling finished. */200 void sigProgressEventHandlingFinished();201 202 public:203 204 /** Constructs progress handler passing @a pParent to the base-class.205 * @param comProgress Brings the progress reference. */206 UIProgress(CProgress &comProgress, QObject *pParent = 0);207 /** Destructs progress handler. */208 virtual ~UIProgress() /* override */;209 210 /** Executes the progress within local event-loop. */211 void exec();212 /** Cancels the progress within local event-loop. */213 void cancel();214 215 private slots:216 217 /** Handles percentage changed event for progress with @a uProgressId to @a iPercent. */218 void sltHandleProgressPercentageChange(const QUuid &uProgressId, const int iPercent);219 /** Handles task completed event for progress with @a uProgressId. */220 void sltHandleProgressTaskComplete(const QUuid &uProgressId);221 222 private:223 224 /** Prepares all. */225 void prepare();226 /** Cleanups all. */227 void cleanup();228 229 /** Holds the progress reference. */230 CProgress &m_comProgress;231 232 /** Holds the progress event handler instance. */233 UIProgressEventHandler *m_pEventHandler;234 235 /** Holds the exec event-loop instance. */236 QPointer<QEventLoop> m_pEventLoopExec;237 /** Holds the cancel event-loop instance. */238 QPointer<QEventLoop> m_pEventLoopCancel;239 };240 241 242 170 #endif /* !FEQT_INCLUDED_SRC_widgets_UIProgressDialog_h */ 243 171
Note:
See TracChangeset
for help on using the changeset viewer.