MythTV  master
mythscreenstack.cpp
Go to the documentation of this file.
1 #include "mythscreenstack.h"
2 #include "mythmainwindow.h"
3 #include "mythscreentype.h"
4 #include "mythpainter.h"
5 #include "mythevent.h"
6 
7 #include <cassert>
8 
9 #include <QCoreApplication>
10 #include <QTimer>
11 #include <QString>
12 
13 const int kFadeVal = 20;
14 
15 MythScreenStack::MythScreenStack(MythMainWindow *parent, const QString &name,
16  bool mainstack)
17  : QObject(parent)
18 {
19  setObjectName(name);
20 
21  if (parent)
22  parent->AddScreenStack(this, mainstack);
23 
24  EnableEffects();
25 }
26 
28 {
29  CheckDeletes(true);
30 
31  while (!m_Children.isEmpty())
32  {
33  MythScreenType *child = m_Children.back();
34  MythScreenStack::PopScreen(child, false, true); // Don't fade, do delete
35  }
36 }
37 
39 {
42 }
43 
45 {
46  return m_Children.count();
47 }
48 
49 void MythScreenStack::AddScreen(MythScreenType *screen, bool allowFade)
50 {
51  if (!screen)
52  return;
53 
54  m_DoInit = false;
55 
57  if (old && screen->IsFullscreen())
58  old->aboutToHide();
59 
60  m_Children.push_back(screen);
61 
62  if (allowFade && m_DoTransitions)
63  {
64  m_newTop = screen;
66  }
67  else
68  {
69  if (parent())
70  reinterpret_cast<MythMainWindow *>(parent())->update();
72  if (!screen->IsInitialized())
73  m_DoInit = true;
74  }
75 
76  screen->aboutToShow();
77 
78  m_topScreen = screen;
79 
81 }
82 
83 void MythScreenStack::PopScreen(MythScreenType *screen, bool allowFade,
84  bool deleteScreen)
85 {
86  if (!screen)
87  {
88  screen = m_topScreen;
89  }
90  if (!screen || screen->IsDeleting())
91  return;
92 
93  bool poppedFullscreen = screen->IsFullscreen();
94 
95  screen->aboutToHide();
96 
97  if (m_Children.isEmpty())
98  return;
99 
100  MythMainWindow *mainwindow = GetMythMainWindow();
101 
102  screen->setParent(nullptr);
103  if ((screen == m_topScreen) && allowFade && m_DoTransitions
104  && !mainwindow->IsExitingToMain())
105  {
106  screen->SetFullscreen(false);
107  if (deleteScreen)
108  {
109  screen->SetDeleting(true);
110  m_ToDelete.push_back(screen);
111  }
112  screen->AdjustAlpha(1, -kFadeVal);
113  }
114  else
115  {
116  for (int i = 0; i < m_Children.size(); ++i)
117  {
118  if (m_Children.at(i) == screen)
119  m_Children.remove(i);
120  }
121  if (deleteScreen)
122  screen->deleteLater();
123 
124  screen = nullptr;
125 
126  mainwindow->update();
127  if (mainwindow->IsExitingToMain())
128  {
129  QCoreApplication::postEvent(
130  mainwindow, new QEvent(MythEvent::kExitToMainMenuEventType));
131  }
132  }
133 
134  m_topScreen = nullptr;
135 
137 
138  // If we're fading it, we still want to draw it.
139  if (screen && !m_DrawOrder.contains(screen))
140  m_DrawOrder.push_back(screen);
141 
142  if (!m_Children.isEmpty())
143  {
144  foreach (auto & draw, m_DrawOrder)
145  {
146  if (draw != screen && !draw->IsDeleting())
147  {
148  m_topScreen = draw;
149  draw->SetAlpha(255);
150  if (poppedFullscreen)
151  draw->aboutToShow();
152  }
153  }
154  }
155 
156  if (m_topScreen)
157  {
159 
160  if (!allowFade || !m_DoTransitions)
162  }
163  else
164  {
165  // Screen still needs to be redrawn if we have popped the last screen
166  // off the popup stack, or similar
167  if (mainwindow->GetMainStack())
168  {
169  MythScreenType *mainscreen = mainwindow->GetMainStack()->GetTopScreen();
170  if (mainscreen)
171  mainscreen->SetRedraw();
172  }
173 
174  if (!allowFade || !m_DoTransitions)
175  emit topScreenChanged(nullptr);
176  }
177 }
178 
180 {
181  if (m_topScreen)
182  return m_topScreen;
183  if (!m_DrawOrder.isEmpty())
184  return m_DrawOrder.back();
185  return nullptr;
186 }
187 
188 void MythScreenStack::GetDrawOrder(QVector<MythScreenType *> &screens)
189 {
190  if (m_InNewTransition)
192  CheckDeletes();
193 
194  screens = m_DrawOrder;
195 }
196 
197 void MythScreenStack::GetScreenList(QVector<MythScreenType *> &screens)
198 {
199  if (m_InNewTransition)
201  CheckDeletes();
202 
203  screens = m_Children;
204 }
205 
207 {
208  // make sure Init() is called outside the paintEvent
211  {
212  m_InitTimerStarted = true;
213  QTimer::singleShot(100, this, SLOT(doInit()));
214  }
215 }
216 
218 {
219  if (m_DoInit && m_topScreen)
220  {
221  m_DoInit = false;
222 
223  if (!m_topScreen->IsLoaded())
225 
226  if (!m_topScreen->IsInitialized())
227  m_topScreen->doInit();
228  }
229  m_InitTimerStarted = false;
230 }
231 
233 {
234  m_DrawOrder.clear();
235 
236  if (m_Children.isEmpty())
237  return;
238 
239  foreach (auto screen, m_Children)
240  {
241  if (screen->IsFullscreen())
242  m_DrawOrder.clear();
243 
244  m_DrawOrder.push_back(screen);
245  }
246 
247  if (m_DrawOrder.isEmpty())
248  {
249  MythScreenType *screen = GetTopScreen();
250  if (screen)
251  m_DrawOrder.push_back(screen);
252  }
253 }
254 
256 {
257  m_InNewTransition = true;
258  m_newTop->SetAlpha(0);
260 
261  if (m_newTop->IsFullscreen())
262  {
263  foreach (auto & draw, m_DrawOrder)
264  {
265  if (!draw->IsDeleting())
266  draw->AdjustAlpha(1, -kFadeVal);
267  }
268 
269  m_DrawOrder.push_back(m_newTop);
270  }
271  else
273 }
274 
276 {
277  if (!m_newTop)
278  {
279  m_InNewTransition = false;
280  return;
281  }
282 
283  if (m_newTop->GetAlpha() >= 255)
284  {
285  m_InNewTransition = false;
286  if (!m_newTop->IsInitialized())
287  m_DoInit = true;
288  m_newTop = nullptr;
289 
291  }
292 }
293 
295 {
296  if (m_ToDelete.isEmpty())
297  return;
298 
299  bool changed = false;
300 
301  QVector<MythScreenType *>::Iterator it = m_ToDelete.begin();
302  while (it != m_ToDelete.end() && !m_ToDelete.isEmpty())
303  {
304  bool deleteit = false;
305 
306  if (force || (*it)->GetAlpha() <= 0)
307  {
308  deleteit = true;
309  }
310 
311  if (!deleteit)
312  {
313  bool found = false;
314 
315  foreach (auto & test, m_DrawOrder)
316  {
317  if (*it == test)
318  {
319  found = true;
320  break;
321  }
322  }
323 
324  if (!found)
325  deleteit = true;
326  }
327 
328  if (deleteit)
329  {
330  for (auto *test = m_Children.begin();
331  test != m_Children.end();
332  ++test)
333  {
334  if (*test == *it)
335  {
336  m_Children.erase(test);
337  break;
338  }
339  }
340 
341  if (*it == m_newTop)
342  m_newTop = nullptr;
343  delete (*it);
344  m_ToDelete.erase(it);
345  it = m_ToDelete.begin();
346  changed = true;
347  continue;
348  }
349 
350  ++it;
351  }
352 
353  if (changed)
354  {
357  }
358 }
359 
360 QString MythScreenStack::GetLocation(bool fullPath) const
361 {
362  if (fullPath)
363  {
364  QString path;
365  foreach (auto child, m_Children)
366  {
367  if (!child->IsDeleting())
368  {
369  if (path.isEmpty())
370  path = child->objectName();
371  else
372  path += '/' + child->objectName();
373  }
374  }
375  return path;
376  }
377 
378  if (m_topScreen)
379  return m_topScreen->objectName();
380 
381  return QString();
382 }
383 
385 {
386  return GetMythPainter();
387 }
virtual void aboutToShow(void)
int TotalScreens() const
QVector< MythScreenType * > m_ToDelete
void ScheduleInitIfNeeded(void)
MythScreenType * m_topScreen
void GetDrawOrder(QVector< MythScreenType * > &screens)
const int kFadeVal
void SetAlpha(int newalpha)
Definition: mythuitype.cpp:925
void SetRedraw(void)
Definition: mythuitype.cpp:293
bool IsFullscreen(void) const
MythScreenType * m_newTop
QString GetLocation(bool fullPath) const
MythPainter * GetMythPainter(void)
MythScreenStack * GetMainStack()
~MythScreenStack() override
virtual bool SupportsAlpha(void)=0
bool IsInitialized(void) const
Has Init() been called on this screen?
virtual bool SupportsAnimation(void)=0
void LoadInForeground(void)
QVector< MythScreenType * > m_DrawOrder
MythScreenStack(MythMainWindow *parent, const QString &name, bool main=false)
static MythPainter * GetPainter(void)
virtual void AddScreen(MythScreenType *screen, bool allowFade=true)
void SetDeleting(bool deleting)
virtual MythScreenType * GetTopScreen(void) const
void SetFullscreen(bool full)
void GetScreenList(QVector< MythScreenType * > &screens)
bool IsExitingToMain(void) const
void CheckDeletes(bool force=false)
virtual void RecalculateDrawOrder(void)
void AdjustAlpha(int mode, int alphachange, int minalpha=0, int maxalpha=255)
Definition: mythuitype.cpp:907
MythMainWindow * GetMythMainWindow(void)
bool IsLoading(void)
bool IsLoaded(void)
static Type kExitToMainMenuEventType
Definition: mythevent.h:76
virtual void aboutToHide(void)
QVector< MythScreenType * > m_Children
virtual void PopScreen(MythScreenType *screen=nullptr, bool allowFade=true, bool deleteScreen=true)
void EnableEffects(void)
Screen in which all other widgets are contained and rendered.
void AddScreenStack(MythScreenStack *stack, bool main=false)
bool IsDeleting(void) const
void topScreenChanged(MythScreenType *screen)
int GetAlpha(void) const
Definition: mythuitype.cpp:934