1 /*
2  *  Copyright (C) 2015-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 
9 #include "ProgressJob.h"
10 
11 #include "ServiceBroker.h"
12 #include "dialogs/GUIDialogExtendedProgressBar.h"
13 #include "dialogs/GUIDialogProgress.h"
14 #include "guilib/GUIComponent.h"
15 #include "guilib/GUIWindowManager.h"
16 #include "utils/Variant.h"
17 
18 #include <math.h>
19 
CProgressJob()20 CProgressJob::CProgressJob()
21   : m_progress(NULL),
22     m_progressDialog(NULL)
23 { }
24 
CProgressJob(CGUIDialogProgressBarHandle * progressBar)25 CProgressJob::CProgressJob(CGUIDialogProgressBarHandle* progressBar)
26   : m_progress(progressBar),
27     m_progressDialog(NULL)
28 { }
29 
~CProgressJob()30 CProgressJob::~CProgressJob()
31 {
32   MarkFinished();
33 
34   m_progress = NULL;
35   m_progressDialog = NULL;
36 }
37 
ShouldCancel(unsigned int progress,unsigned int total) const38 bool CProgressJob::ShouldCancel(unsigned int progress, unsigned int total) const
39 {
40   if (IsCancelled())
41     return true;
42 
43   SetProgress(progress, total);
44 
45   return CJob::ShouldCancel(progress, total);
46 }
47 
DoModal()48 bool CProgressJob::DoModal()
49 {
50   m_progress = NULL;
51 
52   // get a progress dialog if we don't already have one
53   if (m_progressDialog == NULL)
54   {
55     m_progressDialog = CServiceBroker::GetGUI()->GetWindowManager().GetWindow<CGUIDialogProgress>(WINDOW_DIALOG_PROGRESS);
56 
57     if (m_progressDialog == NULL)
58       return false;
59   }
60 
61   m_modal = true;
62 
63   // do the work
64   bool result = DoWork();
65 
66   // mark the progress dialog as finished (will close it)
67   MarkFinished();
68   m_modal = false;
69 
70   return result;
71 }
72 
SetProgressIndicators(CGUIDialogProgressBarHandle * progressBar,CGUIDialogProgress * progressDialog,bool updateProgress,bool updateInformation)73 void CProgressJob::SetProgressIndicators(CGUIDialogProgressBarHandle* progressBar, CGUIDialogProgress* progressDialog, bool updateProgress /* = true */, bool updateInformation /* = true */)
74 {
75   SetProgressBar(progressBar);
76   SetProgressDialog(progressDialog);
77   SetUpdateProgress(updateProgress);
78   SetUpdateInformation(updateInformation);
79 
80   // disable auto-closing
81   SetAutoClose(false);
82 }
83 
ShowProgressDialog() const84 void CProgressJob::ShowProgressDialog() const
85 {
86   if (!IsModal() || m_progressDialog == NULL ||
87       m_progressDialog->IsDialogRunning())
88     return;
89 
90   // show the progress dialog as a modal dialog with a progress bar
91   m_progressDialog->Open();
92   m_progressDialog->ShowProgressBar(true);
93 }
94 
SetTitle(const std::string & title)95 void CProgressJob::SetTitle(const std::string &title)
96 {
97   if (!m_updateInformation)
98     return;
99 
100   if (m_progress != NULL)
101     m_progress->SetTitle(title);
102   else if (m_progressDialog != NULL)
103   {
104     m_progressDialog->SetHeading(CVariant{title});
105 
106     ShowProgressDialog();
107   }
108 }
109 
SetText(const std::string & text)110 void CProgressJob::SetText(const std::string &text)
111 {
112   if (!m_updateInformation)
113     return;
114 
115   if (m_progress != NULL)
116     m_progress->SetText(text);
117   else if (m_progressDialog != NULL)
118   {
119     m_progressDialog->SetText(CVariant{text});
120 
121     ShowProgressDialog();
122   }
123 }
124 
SetProgress(float percentage) const125 void CProgressJob::SetProgress(float percentage) const
126 {
127   if (!m_updateProgress)
128     return;
129 
130   if (m_progress != NULL)
131     m_progress->SetPercentage(percentage);
132   else if (m_progressDialog != NULL)
133   {
134     ShowProgressDialog();
135 
136     int iPercentage = static_cast<int>(ceil(percentage));
137     // only change and update the progress bar if its percentage value changed
138     // (this can have a huge impact on performance if it's called a lot)
139     if (iPercentage != m_progressDialog->GetPercentage())
140     {
141       m_progressDialog->SetPercentage(iPercentage);
142       m_progressDialog->Progress();
143     }
144   }
145 }
146 
SetProgress(int currentStep,int totalSteps) const147 void CProgressJob::SetProgress(int currentStep, int totalSteps) const
148 {
149   if (!m_updateProgress)
150     return;
151 
152   if (m_progress != NULL)
153     m_progress->SetProgress(currentStep, totalSteps);
154   else if (m_progressDialog != NULL)
155     SetProgress((static_cast<float>(currentStep) * 100.0f) / totalSteps);
156 }
157 
MarkFinished()158 void CProgressJob::MarkFinished()
159 {
160   if (m_progress != NULL)
161   {
162     if (m_updateProgress)
163     {
164       m_progress->MarkFinished();
165       // We don't own this pointer and it will be deleted after it's marked finished
166       // just set it to nullptr so we don't try to use it again
167       m_progress = nullptr;
168     }
169   }
170   else if (m_progressDialog != NULL && m_autoClose)
171     m_progressDialog->Close();
172 }
173 
IsCancelled() const174 bool CProgressJob::IsCancelled() const
175 {
176   if (m_progressDialog != NULL)
177     return m_progressDialog->IsCanceled();
178 
179   return false;
180 }
181 
HasProgressIndicator() const182 bool CProgressJob::HasProgressIndicator() const
183 {
184   return m_progress != nullptr || m_progressDialog != nullptr;
185 }
186