/src/VBox/Frontends/VirtualBox/src/widgets/VBoxProgressDialog.cpp

https://gitlab.com/ufo/virtualbox-ose-3-1-8 · C++ · 277 lines · 195 code · 37 blank · 45 comment · 46 complexity · 63784f78d759b185c1199b93ebdf311b MD5 · raw file

  1. /** @file
  2. *
  3. * VBox frontends: Qt GUI ("VirtualBox"):
  4. * VBoxProgressDialog class implementation
  5. */
  6. /*
  7. * Copyright (C) 2006-2009 Sun Microsystems, Inc.
  8. *
  9. * This file is part of VirtualBox Open Source Edition (OSE), as
  10. * available from http://www.virtualbox.org. This file is free software;
  11. * you can redistribute it and/or modify it under the terms of the GNU
  12. * General Public License (GPL) as published by the Free Software
  13. * Foundation, in version 2 as it comes in the "COPYING" file of the
  14. * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
  15. * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
  16. *
  17. * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
  18. * Clara, CA 95054 USA or visit http://www.sun.com if you need
  19. * additional information or have any questions.
  20. */
  21. /* VBox includes */
  22. #include "COMDefs.h"
  23. #include "QIDialogButtonBox.h"
  24. #include "QILabel.h"
  25. #include "VBoxGlobal.h"
  26. #include "VBoxProgressDialog.h"
  27. #include "VBoxSpecialControls.h"
  28. #ifdef Q_WS_MAC
  29. # include "VBoxUtils-darwin.h"
  30. #endif
  31. /* Qt includes */
  32. #include <QCloseEvent>
  33. #include <QEventLoop>
  34. #include <QProgressBar>
  35. #include <QTime>
  36. #include <QTimer>
  37. #include <QVBoxLayout>
  38. #define VBOX_SECOND 1
  39. #define VBOX_MINUTE VBOX_SECOND * 60
  40. #define VBOX_HOUR VBOX_MINUTE * 60
  41. #define VBOX_DAY VBOX_HOUR * 24
  42. const char *VBoxProgressDialog::sOpDescTpl = "%1... (%2/%3)";
  43. VBoxProgressDialog::VBoxProgressDialog (CProgress &aProgress,
  44. const QString &aTitle,
  45. int aMinDuration /* = 2000 */,
  46. QWidget *aParent /* = 0 */)
  47. // : QIDialog (aParent, Qt::Sheet | Qt::MSWindowsFixedSizeDialogHint | Qt::WindowTitleHint)
  48. : QIDialog (aParent, Qt::MSWindowsFixedSizeDialogHint | Qt::WindowTitleHint)
  49. , mProgress (aProgress)
  50. , mCancelBtn (0)
  51. , mCancelEnabled (false)
  52. , mOpCount (mProgress.GetOperationCount())
  53. , mCurOp (mProgress.GetOperation() + 1)
  54. , mEnded (false)
  55. {
  56. setModal (true);
  57. QVBoxLayout *pLayout1 = new QVBoxLayout (this);
  58. #ifdef Q_WS_MAC
  59. ::darwinSetHidesAllTitleButtons (this);
  60. ::darwinSetShowsResizeIndicator (this, false);
  61. VBoxGlobal::setLayoutMargin (pLayout1, 6);
  62. #endif /* Q_WS_MAC */
  63. mLabel = new QILabel (this);
  64. pLayout1->addWidget (mLabel, 0, Qt::AlignHCenter);
  65. QHBoxLayout *pLayout2 = new QHBoxLayout();
  66. pLayout2->setMargin (0);
  67. pLayout1->addLayout (pLayout2);
  68. mProgressBar = new QProgressBar (this);
  69. pLayout2->addWidget (mProgressBar, 0, Qt::AlignVCenter);
  70. if (mOpCount > 1)
  71. mLabel->setText (QString (sOpDescTpl)
  72. .arg (mProgress.GetOperationDescription())
  73. .arg (mCurOp).arg (mOpCount));
  74. else
  75. mLabel->setText (QString ("%1...")
  76. .arg (mProgress.GetOperationDescription()));
  77. mProgressBar->setMaximum (100);
  78. setWindowTitle (QString ("%1: %2").arg (aTitle, mProgress.GetDescription()));
  79. mProgressBar->setValue (0);
  80. mCancelEnabled = aProgress.GetCancelable();
  81. if (mCancelEnabled)
  82. {
  83. mCancelBtn = new VBoxMiniCancelButton (this);
  84. mCancelBtn->setFocusPolicy (Qt::ClickFocus);
  85. pLayout2->addWidget (mCancelBtn, 0, Qt::AlignVCenter);
  86. connect (mCancelBtn, SIGNAL (clicked()), this, SLOT (cancelOperation()));
  87. }
  88. mETA = new QILabel (this);
  89. pLayout1->addWidget (mETA, 0, Qt::AlignLeft | Qt::AlignVCenter);
  90. setSizePolicy (QSizePolicy::Fixed, QSizePolicy::Fixed);
  91. retranslateUi();
  92. /* The progress dialog will be shown automatically after
  93. * the duration is over if progress is not finished yet. */
  94. QTimer::singleShot (aMinDuration, this, SLOT (showDialog()));
  95. }
  96. void VBoxProgressDialog::retranslateUi()
  97. {
  98. mCancelText = tr ("Canceling...");
  99. if (mCancelBtn)
  100. {
  101. mCancelBtn->setText (tr ("&Cancel"));
  102. mCancelBtn->setToolTip (tr ("Cancel the current operation"));
  103. }
  104. }
  105. int VBoxProgressDialog::run (int aRefreshInterval)
  106. {
  107. if (mProgress.isOk())
  108. {
  109. /* Start refresh timer */
  110. int id = startTimer (aRefreshInterval);
  111. /* Set busy cursor */
  112. QApplication::setOverrideCursor (QCursor (Qt::WaitCursor));
  113. /* Enter the modal loop, but don't show the window immediately */
  114. exec (false);
  115. /* Kill refresh timer */
  116. killTimer (id);
  117. QApplication::restoreOverrideCursor();
  118. return result();
  119. }
  120. return Rejected;
  121. }
  122. void VBoxProgressDialog::showDialog()
  123. {
  124. /* We should not show progress-dialog
  125. * if it was already finalized but not yet closed.
  126. * This could happens in case of some other
  127. * modal dialog prevents our event-loop from
  128. * being exit overlapping 'this'. */
  129. if (!mEnded)
  130. show();
  131. }
  132. void VBoxProgressDialog::cancelOperation()
  133. {
  134. if (mCancelBtn)
  135. mCancelBtn->setEnabled (false);
  136. mProgress.Cancel();
  137. }
  138. void VBoxProgressDialog::timerEvent (QTimerEvent * /* aEvent */)
  139. {
  140. /* We should hide progress-dialog
  141. * if it was already finalized but not yet closed.
  142. * This could happens in case of some other
  143. * modal dialog prevents our event-loop from
  144. * being exit overlapping 'this'. */
  145. if (mEnded && !isHidden())
  146. {
  147. hide();
  148. return;
  149. }
  150. else if (mEnded)
  151. return;
  152. if (!mEnded && (!mProgress.isOk() || mProgress.GetCompleted()))
  153. {
  154. /* Progress finished */
  155. if (mProgress.isOk())
  156. {
  157. mProgressBar->setValue (100);
  158. done (Accepted);
  159. }
  160. /* Progress is not valid */
  161. else
  162. done (Rejected);
  163. /* Request to exit loop */
  164. mEnded = true;
  165. return;
  166. }
  167. if (!mProgress.GetCanceled())
  168. {
  169. /* Update the progress dialog */
  170. /* First ETA */
  171. long newTime = mProgress.GetTimeRemaining();
  172. QDateTime time;
  173. time.setTime_t (newTime);
  174. QDateTime refTime;
  175. refTime.setTime_t (0);
  176. int days = refTime.daysTo (time);
  177. int hours = time.addDays (-days).time().hour();
  178. int minutes = time.addDays (-days).time().minute();
  179. int seconds = time.addDays (-days).time().second();
  180. QString strDays = VBoxGlobal::daysToString(days);
  181. QString strHours = VBoxGlobal::hoursToString(hours);
  182. QString strMinutes = VBoxGlobal::minutesToString(minutes);
  183. QString strSeconds = VBoxGlobal::secondsToString(seconds);
  184. QString strTwoComp = tr ("%1, %2 remaining", "You may wish to translate this more like \"Time remaining: %1, %2\"");
  185. QString strOneComp = tr ("%1 remaining", "You may wish to translate this more like \"Time remaining: %1\"");
  186. if (newTime > VBOX_DAY * 2 + VBOX_HOUR)
  187. mETA->setText (strTwoComp.arg (strDays).arg (strHours));
  188. else if (newTime > VBOX_DAY * 2 + VBOX_MINUTE * 5)
  189. mETA->setText (strTwoComp.arg (strDays).arg (strMinutes));
  190. else if (newTime > VBOX_DAY * 2)
  191. mETA->setText (strOneComp.arg (strDays));
  192. else if (newTime > VBOX_DAY + VBOX_HOUR)
  193. mETA->setText (strTwoComp.arg (strDays).arg (strHours));
  194. else if (newTime > VBOX_DAY + VBOX_MINUTE * 5)
  195. mETA->setText (strTwoComp.arg (strDays).arg (strMinutes));
  196. else if (newTime > VBOX_HOUR * 23 + VBOX_MINUTE * 55)
  197. mETA->setText (strOneComp.arg (strDays));
  198. else if (newTime >= VBOX_HOUR * 2)
  199. mETA->setText (strTwoComp.arg (strHours).arg (strMinutes));
  200. else if (newTime > VBOX_HOUR + VBOX_MINUTE * 5)
  201. mETA->setText (strTwoComp.arg (strHours).arg (strMinutes));
  202. else if (newTime > VBOX_MINUTE * 55)
  203. mETA->setText (strOneComp.arg (strHours));
  204. else if (newTime > VBOX_MINUTE * 2)
  205. mETA->setText (strOneComp.arg (strMinutes));
  206. else if (newTime > VBOX_MINUTE + VBOX_SECOND * 5)
  207. mETA->setText (strTwoComp.arg (strMinutes).arg (strSeconds));
  208. else if (newTime > VBOX_SECOND * 55)
  209. mETA->setText (strOneComp.arg (strMinutes));
  210. else if (newTime > VBOX_SECOND * 5)
  211. mETA->setText (strOneComp.arg (strSeconds));
  212. else if (newTime >= 0)
  213. mETA->setText (tr ("A few seconds remaining"));
  214. else
  215. mETA->clear();
  216. /* Then operation text if changed */
  217. ulong newOp = mProgress.GetOperation() + 1;
  218. if (newOp != mCurOp)
  219. {
  220. mCurOp = newOp;
  221. mLabel->setText (QString (sOpDescTpl)
  222. .arg (mProgress.GetOperationDescription())
  223. .arg (mCurOp).arg (mOpCount));
  224. }
  225. mProgressBar->setValue (mProgress.GetPercent());
  226. }else
  227. mETA->setText (mCancelText);
  228. }
  229. void VBoxProgressDialog::reject()
  230. {
  231. if (mCancelEnabled)
  232. cancelOperation();
  233. }
  234. void VBoxProgressDialog::closeEvent (QCloseEvent *aEvent)
  235. {
  236. if (mCancelEnabled)
  237. cancelOperation();
  238. else
  239. aEvent->ignore();
  240. }