/xbmc/dialogs/GUIDialogBusy.cpp

http://github.com/xbmc/xbmc · C++ · 157 lines · 121 code · 26 blank · 10 comment · 15 complexity · d1453579d10a1b93c88db9383dad6fd4 MD5 · raw file

  1. /*
  2. * Copyright (C) 2005-2018 Team Kodi
  3. * This file is part of Kodi - https://kodi.tv
  4. *
  5. * SPDX-License-Identifier: GPL-2.0-or-later
  6. * See LICENSES/README.md for more information.
  7. */
  8. #include "GUIDialogBusy.h"
  9. #include "ServiceBroker.h"
  10. #include "guilib/GUIComponent.h"
  11. #include "guilib/GUIProgressControl.h"
  12. #include "guilib/GUIWindowManager.h"
  13. #include "threads/IRunnable.h"
  14. #include "threads/Thread.h"
  15. #define PROGRESS_CONTROL 10
  16. class CBusyWaiter : public CThread
  17. {
  18. std::shared_ptr<CEvent> m_done;
  19. IRunnable *m_runnable;
  20. public:
  21. explicit CBusyWaiter(IRunnable *runnable) :
  22. CThread(runnable, "waiting"), m_done(new CEvent()), m_runnable(runnable) { }
  23. ~CBusyWaiter() override { StopThread(); }
  24. bool Wait(unsigned int displaytime, bool allowCancel)
  25. {
  26. std::shared_ptr<CEvent> e_done(m_done);
  27. Create();
  28. unsigned int start = XbmcThreads::SystemClockMillis();
  29. if (!CGUIDialogBusy::WaitOnEvent(*e_done, displaytime, allowCancel))
  30. {
  31. m_runnable->Cancel();
  32. unsigned int elapsed = XbmcThreads::SystemClockMillis() - start;
  33. unsigned int remaining = (elapsed >= displaytime) ? 0 : displaytime - elapsed;
  34. CGUIDialogBusy::WaitOnEvent(*e_done, remaining, false);
  35. return false;
  36. }
  37. return true;
  38. }
  39. // 'this' is actually deleted from the thread where it's on the stack
  40. void Process() override
  41. {
  42. std::shared_ptr<CEvent> e_done(m_done);
  43. CThread::Process();
  44. (*e_done).Set();
  45. }
  46. };
  47. bool CGUIDialogBusy::Wait(IRunnable *runnable, unsigned int displaytime, bool allowCancel)
  48. {
  49. if (!runnable)
  50. return false;
  51. CBusyWaiter waiter(runnable);
  52. if (!waiter.Wait(displaytime, allowCancel))
  53. {
  54. return false;
  55. }
  56. return true;
  57. }
  58. bool CGUIDialogBusy::WaitOnEvent(CEvent &event, unsigned int displaytime /* = 100 */, bool allowCancel /* = true */)
  59. {
  60. bool cancelled = false;
  61. if (!event.WaitMSec(displaytime))
  62. {
  63. // throw up the progress
  64. CGUIDialogBusy* dialog = CServiceBroker::GetGUI()->GetWindowManager().GetWindow<CGUIDialogBusy>(WINDOW_DIALOG_BUSY);
  65. if (dialog)
  66. {
  67. if (dialog->IsDialogRunning())
  68. {
  69. throw std::logic_error("busy dialog already running");
  70. }
  71. dialog->Open();
  72. while(!event.WaitMSec(1))
  73. {
  74. dialog->ProcessRenderLoop(false);
  75. if (allowCancel && dialog->IsCanceled())
  76. {
  77. cancelled = true;
  78. break;
  79. }
  80. }
  81. dialog->Close(true);
  82. }
  83. }
  84. return !cancelled;
  85. }
  86. CGUIDialogBusy::CGUIDialogBusy(void)
  87. : CGUIDialog(WINDOW_DIALOG_BUSY, "DialogBusy.xml", DialogModalityType::MODAL)
  88. {
  89. m_loadType = LOAD_ON_GUI_INIT;
  90. m_bCanceled = false;
  91. m_progress = -1;
  92. }
  93. CGUIDialogBusy::~CGUIDialogBusy(void) = default;
  94. void CGUIDialogBusy::Open_Internal(const std::string &param /* = "" */)
  95. {
  96. m_bCanceled = false;
  97. m_bLastVisible = true;
  98. m_progress = -1;
  99. CGUIDialog::Open_Internal(false, param);
  100. }
  101. void CGUIDialogBusy::DoProcess(unsigned int currentTime, CDirtyRegionList &dirtyregions)
  102. {
  103. bool visible = CServiceBroker::GetGUI()->GetWindowManager().IsModalDialogTopmost(WINDOW_DIALOG_BUSY);
  104. if(!visible && m_bLastVisible)
  105. dirtyregions.push_back(CDirtyRegion(m_renderRegion));
  106. m_bLastVisible = visible;
  107. // update the progress control if available
  108. CGUIControl *control = GetControl(PROGRESS_CONTROL);
  109. if (control && control->GetControlType() == CGUIControl::GUICONTROL_PROGRESS)
  110. {
  111. CGUIProgressControl *progress = static_cast<CGUIProgressControl*>(control);
  112. progress->SetPercentage(m_progress);
  113. progress->SetVisible(m_progress > -1);
  114. }
  115. CGUIDialog::DoProcess(currentTime, dirtyregions);
  116. }
  117. void CGUIDialogBusy::Render()
  118. {
  119. if(!m_bLastVisible)
  120. return;
  121. CGUIDialog::Render();
  122. }
  123. bool CGUIDialogBusy::OnBack(int actionID)
  124. {
  125. m_bCanceled = true;
  126. return true;
  127. }
  128. void CGUIDialogBusy::SetProgress(float percent)
  129. {
  130. m_progress = percent;
  131. }