summaryrefslogtreecommitdiffstats
path: root/xbmc/dialogs/GUIDialogExtendedProgressBar.cpp
blob: 9fc1c024ea11ad6cf3639f7e513ffb2d8f8e331a (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
/*
 *  Copyright (C) 2012-2018 Team Kodi
 *  This file is part of Kodi - https://kodi.tv
 *
 *  SPDX-License-Identifier: GPL-2.0-or-later
 *  See LICENSES/README.md for more information.
 */

#include "GUIDialogExtendedProgressBar.h"

#include "guilib/GUIMessage.h"
#include "guilib/GUIProgressControl.h"
#include "utils/TimeUtils.h"

#include <cmath>
#include <mutex>

#define CONTROL_LABELHEADER       30
#define CONTROL_LABELTITLE        31
#define CONTROL_PROGRESS          32

#define ITEM_SWITCH_TIME_MS       2000

std::string CGUIDialogProgressBarHandle::Text(void) const
{
  std::unique_lock<CCriticalSection> lock(m_critSection);
  std::string retVal(m_strText);
  return retVal;
}

void CGUIDialogProgressBarHandle::SetText(const std::string &strText)
{
  std::unique_lock<CCriticalSection> lock(m_critSection);
  m_strText = strText;
}

void CGUIDialogProgressBarHandle::SetTitle(const std::string &strTitle)
{
  std::unique_lock<CCriticalSection> lock(m_critSection);
  m_strTitle = strTitle;
}

void CGUIDialogProgressBarHandle::SetProgress(int currentItem, int itemCount)
{
  float fPercentage = (currentItem*100.0f)/itemCount;
  if (!std::isnan(fPercentage))
    m_fPercentage = std::min(100.0f, fPercentage);
}

CGUIDialogExtendedProgressBar::CGUIDialogExtendedProgressBar(void)
  : CGUIDialog(WINDOW_DIALOG_EXT_PROGRESS, "DialogExtendedProgressBar.xml", DialogModalityType::MODELESS)
{
  m_loadType        = LOAD_ON_GUI_INIT;
  m_iLastSwitchTime = 0;
  m_iCurrentItem    = 0;
}

CGUIDialogProgressBarHandle *CGUIDialogExtendedProgressBar::GetHandle(const std::string &strTitle)
{
  CGUIDialogProgressBarHandle *handle = new CGUIDialogProgressBarHandle(strTitle);
  {
    std::unique_lock<CCriticalSection> lock(m_critSection);
    m_handles.push_back(handle);
  }

  Open();

  return handle;
}

bool CGUIDialogExtendedProgressBar::OnMessage(CGUIMessage& message)
{
  switch (message.GetMessage())
  {
  case GUI_MSG_WINDOW_INIT:
    {
      m_iLastSwitchTime = CTimeUtils::GetFrameTime();
      m_iCurrentItem = 0;
      CGUIDialog::OnMessage(message);

      UpdateState(0);
      return true;
    }
    break;
  }

  return CGUIDialog::OnMessage(message);
}

void CGUIDialogExtendedProgressBar::Process(unsigned int currentTime, CDirtyRegionList &dirtyregions)
{
  if (m_active)
    UpdateState(currentTime);

  CGUIDialog::Process(currentTime, dirtyregions);
}

void CGUIDialogExtendedProgressBar::UpdateState(unsigned int currentTime)
{
  std::string strHeader;
  std::string strTitle;
  float  fProgress(-1.0f);

  {
    std::unique_lock<CCriticalSection> lock(m_critSection);

    // delete finished items
    for (int iPtr = m_handles.size() - 1; iPtr >= 0; iPtr--)
    {
      if (m_handles.at(iPtr)->IsFinished())
      {
        delete m_handles.at(iPtr);
        m_handles.erase(m_handles.begin() + iPtr);
      }
    }

    if (!m_handles.size())
    {
      Close(false, 0, true, false);
      return;
    }

    // ensure the current item is in our range
    if (m_iCurrentItem >= m_handles.size())
      m_iCurrentItem = m_handles.size() - 1;

    // update the current item ptr
    if (currentTime > m_iLastSwitchTime &&
        currentTime - m_iLastSwitchTime >= ITEM_SWITCH_TIME_MS)
    {
      m_iLastSwitchTime = currentTime;

      // select next item
      if (++m_iCurrentItem > m_handles.size() - 1)
        m_iCurrentItem = 0;
    }

    CGUIDialogProgressBarHandle *handle = m_handles.at(m_iCurrentItem);
    if (handle)
    {
      strTitle  = handle->Text();
      strHeader = handle->Title();
      fProgress = handle->Percentage();
    }
  }

  SET_CONTROL_LABEL(CONTROL_LABELHEADER, strHeader);
  SET_CONTROL_LABEL(CONTROL_LABELTITLE, strTitle);

  if (fProgress > -1.0f)
  {
    SET_CONTROL_VISIBLE(CONTROL_PROGRESS);
    CONTROL_SELECT_ITEM(CONTROL_PROGRESS, (unsigned int)fProgress);
  }
}