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 
16  bool mainstack)
17  : QObject(parent)
18 {
19  setObjectName(name);
20 
21  if (parent)
22  parent->AddScreenStack(this, mainstack);
23 
24  m_newTop = nullptr;
25  m_topScreen = nullptr;
26 
27  EnableEffects();
28  m_InNewTransition = false;
29 
30  m_DoInit = false;
31  m_InitTimerStarted = false;
32 }
33 
35 {
36  CheckDeletes(true);
37 
38  while (!m_Children.isEmpty())
39  {
40  MythScreenType *child = m_Children.back();
41  PopScreen(child, false, true); // Don't fade, do delete
42  }
43 }
44 
46 {
49 }
50 
52 {
53  return m_Children.count();
54 }
55 
56 void MythScreenStack::AddScreen(MythScreenType *screen, bool allowFade)
57 {
58  if (!screen)
59  return;
60 
61  m_DoInit = false;
62 
64  if (old && screen->IsFullscreen())
65  old->aboutToHide();
66 
67  m_Children.push_back(screen);
68 
69  if (allowFade && m_DoTransitions)
70  {
71  m_newTop = screen;
73  }
74  else
75  {
76  if (parent())
77  reinterpret_cast<MythMainWindow *>(parent())->update();
79  if (!screen->IsInitialized())
80  m_DoInit = true;
81  }
82 
83  screen->aboutToShow();
84 
85  m_topScreen = screen;
86 
88 }
89 
90 void MythScreenStack::PopScreen(MythScreenType *screen, bool allowFade,
91  bool deleteScreen)
92 {
93  if (!screen)
94  {
95  screen = m_topScreen;
96  }
97  if (!screen || screen->IsDeleting())
98  return;
99 
100  bool poppedFullscreen = screen->IsFullscreen();
101 
102  screen->aboutToHide();
103 
104  if (m_Children.isEmpty())
105  return;
106 
107  MythMainWindow *mainwindow = GetMythMainWindow();
108 
109  screen->setParent(nullptr);
110  if ((screen == m_topScreen) && allowFade && m_DoTransitions
111  && !mainwindow->IsExitingToMain())
112  {
113  screen->SetFullscreen(false);
114  if (deleteScreen)
115  {
116  screen->SetDeleting(true);
117  m_ToDelete.push_back(screen);
118  }
119  screen->AdjustAlpha(1, -kFadeVal);
120  }
121  else
122  {
123  for (int i = 0; i < m_Children.size(); ++i)
124  {
125  if (m_Children.at(i) == screen)
126  m_Children.remove(i);
127  }
128  if (deleteScreen)
129  screen->deleteLater();
130 
131  screen = nullptr;
132 
133  mainwindow->update();
134  if (mainwindow->IsExitingToMain())
135  {
136  QCoreApplication::postEvent(
137  mainwindow, new QEvent(MythEvent::kExitToMainMenuEventType));
138  }
139  }
140 
141  m_topScreen = nullptr;
142 
144 
145  // If we're fading it, we still want to draw it.
146  if (screen && !m_DrawOrder.contains(screen))
147  m_DrawOrder.push_back(screen);
148 
149  if (!m_Children.isEmpty())
150  {
151  QVector<MythScreenType *>::Iterator it;
152  for (it = m_DrawOrder.begin(); it != m_DrawOrder.end(); ++it)
153  {
154  if (*it != screen && !(*it)->IsDeleting())
155  {
156  m_topScreen = (*it);
157  (*it)->SetAlpha(255);
158  if (poppedFullscreen)
159  (*it)->aboutToShow();
160  }
161  }
162  }
163 
164  if (m_topScreen)
165  {
167 
168  if (!allowFade || !m_DoTransitions)
170  }
171  else
172  {
173  // Screen still needs to be redrawn if we have popped the last screen
174  // off the popup stack, or similar
175  if (mainwindow->GetMainStack())
176  {
177  MythScreenType *mainscreen = mainwindow->GetMainStack()->GetTopScreen();
178  if (mainscreen)
179  mainscreen->SetRedraw();
180  }
181 
182  if (!allowFade || !m_DoTransitions)
183  emit topScreenChanged(nullptr);
184  }
185 }
186 
188 {
189  if (m_topScreen)
190  return m_topScreen;
191  if (!m_DrawOrder.isEmpty())
192  return m_DrawOrder.back();
193  return nullptr;
194 }
195 
196 void MythScreenStack::GetDrawOrder(QVector<MythScreenType *> &screens)
197 {
198  if (m_InNewTransition)
200  CheckDeletes();
201 
202  screens = m_DrawOrder;
203 }
204 
205 void MythScreenStack::GetScreenList(QVector<MythScreenType *> &screens)
206 {
207  if (m_InNewTransition)
209  CheckDeletes();
210 
211  screens = m_Children;
212 }
213 
215 {
216  // make sure Init() is called outside the paintEvent
219  {
220  m_InitTimerStarted = true;
221  QTimer::singleShot(100, this, SLOT(doInit()));
222  }
223 }
224 
226 {
227  if (m_DoInit && m_topScreen)
228  {
229  m_DoInit = false;
230 
231  if (!m_topScreen->IsLoaded())
233 
234  if (!m_topScreen->IsInitialized())
235  m_topScreen->doInit();
236  }
237  m_InitTimerStarted = false;
238 }
239 
241 {
242  m_DrawOrder.clear();
243 
244  if (m_Children.isEmpty())
245  return;
246 
247  QVector<MythScreenType *>::Iterator it;
248 
249  for (it = m_Children.begin(); it != m_Children.end(); ++it)
250  {
251  MythScreenType *screen = (*it);
252 
253  if (screen->IsFullscreen())
254  m_DrawOrder.clear();
255 
256  m_DrawOrder.push_back(screen);
257  }
258 
259  if (m_DrawOrder.isEmpty())
260  {
261  MythScreenType *screen = GetTopScreen();
262  if (screen)
263  m_DrawOrder.push_back(screen);
264  }
265 }
266 
268 {
269  m_InNewTransition = true;
270  m_newTop->SetAlpha(0);
272 
273  if (m_newTop->IsFullscreen())
274  {
275  QVector<MythScreenType *>::Iterator it;
276  for (it = m_DrawOrder.begin(); it != m_DrawOrder.end(); ++it)
277  {
278  if (!(*it)->IsDeleting())
279  (*it)->AdjustAlpha(1, -kFadeVal);
280  }
281 
282  m_DrawOrder.push_back(m_newTop);
283  }
284  else
286 }
287 
289 {
290  if (!m_newTop)
291  {
292  m_InNewTransition = false;
293  return;
294  }
295 
296  if (m_newTop->GetAlpha() >= 255)
297  {
298  m_InNewTransition = false;
299  if (!m_newTop->IsInitialized())
300  m_DoInit = true;
301  m_newTop = nullptr;
302 
304  }
305 }
306 
308 {
309  if (m_ToDelete.isEmpty())
310  return;
311 
312  bool changed = false;
313 
314  QVector<MythScreenType *>::Iterator it = m_ToDelete.begin();
315  while (it != m_ToDelete.end() && !m_ToDelete.isEmpty())
316  {
317  bool deleteit = false;
318 
319  if (force || (*it)->GetAlpha() <= 0)
320  {
321  deleteit = true;
322  }
323 
324  if (!deleteit)
325  {
326  bool found = false;
327 
328  QVector<MythScreenType *>::Iterator test;
329  for (test = m_DrawOrder.begin(); test != m_DrawOrder.end(); ++test)
330  {
331  if (*it == *test)
332  {
333  found = true;
334  break;
335  }
336  }
337 
338  if (!found)
339  deleteit = true;
340  }
341 
342  if (deleteit)
343  {
344  QVector<MythScreenType *>::Iterator test;
345  for (test = m_Children.begin(); test != m_Children.end(); ++test)
346  {
347  if (*test == *it)
348  {
349  m_Children.erase(test);
350  break;
351  }
352  }
353 
354  if (*it == m_newTop)
355  m_newTop = nullptr;
356  delete (*it);
357  m_ToDelete.erase(it);
358  it = m_ToDelete.begin();
359  changed = true;
360  continue;
361  }
362 
363  ++it;
364  }
365 
366  if (changed)
367  {
370  }
371 }
372 
373 QString MythScreenStack::GetLocation(bool fullPath) const
374 {
375  if (fullPath)
376  {
377  QString path;
378  QVector<MythScreenType *>::const_iterator it;
379  for (it = m_Children.begin(); it != m_Children.end(); ++it)
380  {
381  if (!(*it)->IsDeleting())
382  {
383  if (path.isEmpty())
384  path = (*it)->objectName();
385  else
386  path += '/' + (*it)->objectName();
387  }
388  }
389  return path;
390  }
391  else
392  {
393  if (m_topScreen)
394  return m_topScreen->objectName();
395  }
396 
397  return QString();
398 }
399 
401 {
402  return GetMythPainter();
403 }
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:946
void SetRedraw(void)
Definition: mythuitype.cpp:318
bool IsFullscreen(void) const
MythScreenType * m_newTop
QString GetLocation(bool fullPath) const
MythPainter * GetMythPainter(void)
MythScreenStack * GetMainStack()
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)
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
virtual ~MythScreenStack()
void CheckDeletes(bool force=false)
const char * name
Definition: ParseText.cpp:339
virtual void RecalculateDrawOrder(void)
void AdjustAlpha(int mode, int alphachange, int minalpha=0, int maxalpha=255)
Definition: mythuitype.cpp:928
MythMainWindow * GetMythMainWindow(void)
bool IsLoading(void)
bool IsLoaded(void)
static Type kExitToMainMenuEventType
Definition: mythevent.h:68
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:955