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  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  QVector<MythScreenType *>::Iterator it;
145  for (it = m_DrawOrder.begin(); it != m_DrawOrder.end(); ++it)
146  {
147  if (*it != screen && !(*it)->IsDeleting())
148  {
149  m_topScreen = (*it);
150  (*it)->SetAlpha(255);
151  if (poppedFullscreen)
152  (*it)->aboutToShow();
153  }
154  }
155  }
156 
157  if (m_topScreen)
158  {
160 
161  if (!allowFade || !m_DoTransitions)
163  }
164  else
165  {
166  // Screen still needs to be redrawn if we have popped the last screen
167  // off the popup stack, or similar
168  if (mainwindow->GetMainStack())
169  {
170  MythScreenType *mainscreen = mainwindow->GetMainStack()->GetTopScreen();
171  if (mainscreen)
172  mainscreen->SetRedraw();
173  }
174 
175  if (!allowFade || !m_DoTransitions)
176  emit topScreenChanged(nullptr);
177  }
178 }
179 
181 {
182  if (m_topScreen)
183  return m_topScreen;
184  if (!m_DrawOrder.isEmpty())
185  return m_DrawOrder.back();
186  return nullptr;
187 }
188 
189 void MythScreenStack::GetDrawOrder(QVector<MythScreenType *> &screens)
190 {
191  if (m_InNewTransition)
193  CheckDeletes();
194 
195  screens = m_DrawOrder;
196 }
197 
198 void MythScreenStack::GetScreenList(QVector<MythScreenType *> &screens)
199 {
200  if (m_InNewTransition)
202  CheckDeletes();
203 
204  screens = m_Children;
205 }
206 
208 {
209  // make sure Init() is called outside the paintEvent
212  {
213  m_InitTimerStarted = true;
214  QTimer::singleShot(100, this, SLOT(doInit()));
215  }
216 }
217 
219 {
220  if (m_DoInit && m_topScreen)
221  {
222  m_DoInit = false;
223 
224  if (!m_topScreen->IsLoaded())
226 
227  if (!m_topScreen->IsInitialized())
228  m_topScreen->doInit();
229  }
230  m_InitTimerStarted = false;
231 }
232 
234 {
235  m_DrawOrder.clear();
236 
237  if (m_Children.isEmpty())
238  return;
239 
240  QVector<MythScreenType *>::Iterator it;
241 
242  for (it = m_Children.begin(); it != m_Children.end(); ++it)
243  {
244  MythScreenType *screen = (*it);
245 
246  if (screen->IsFullscreen())
247  m_DrawOrder.clear();
248 
249  m_DrawOrder.push_back(screen);
250  }
251 
252  if (m_DrawOrder.isEmpty())
253  {
254  MythScreenType *screen = GetTopScreen();
255  if (screen)
256  m_DrawOrder.push_back(screen);
257  }
258 }
259 
261 {
262  m_InNewTransition = true;
263  m_newTop->SetAlpha(0);
265 
266  if (m_newTop->IsFullscreen())
267  {
268  QVector<MythScreenType *>::Iterator it;
269  for (it = m_DrawOrder.begin(); it != m_DrawOrder.end(); ++it)
270  {
271  if (!(*it)->IsDeleting())
272  (*it)->AdjustAlpha(1, -kFadeVal);
273  }
274 
275  m_DrawOrder.push_back(m_newTop);
276  }
277  else
279 }
280 
282 {
283  if (!m_newTop)
284  {
285  m_InNewTransition = false;
286  return;
287  }
288 
289  if (m_newTop->GetAlpha() >= 255)
290  {
291  m_InNewTransition = false;
292  if (!m_newTop->IsInitialized())
293  m_DoInit = true;
294  m_newTop = nullptr;
295 
297  }
298 }
299 
301 {
302  if (m_ToDelete.isEmpty())
303  return;
304 
305  bool changed = false;
306 
307  QVector<MythScreenType *>::Iterator it = m_ToDelete.begin();
308  while (it != m_ToDelete.end() && !m_ToDelete.isEmpty())
309  {
310  bool deleteit = false;
311 
312  if (force || (*it)->GetAlpha() <= 0)
313  {
314  deleteit = true;
315  }
316 
317  if (!deleteit)
318  {
319  bool found = false;
320 
321  QVector<MythScreenType *>::Iterator test;
322  for (test = m_DrawOrder.begin(); test != m_DrawOrder.end(); ++test)
323  {
324  if (*it == *test)
325  {
326  found = true;
327  break;
328  }
329  }
330 
331  if (!found)
332  deleteit = true;
333  }
334 
335  if (deleteit)
336  {
337  QVector<MythScreenType *>::Iterator test;
338  for (test = m_Children.begin(); test != m_Children.end(); ++test)
339  {
340  if (*test == *it)
341  {
342  m_Children.erase(test);
343  break;
344  }
345  }
346 
347  if (*it == m_newTop)
348  m_newTop = nullptr;
349  delete (*it);
350  m_ToDelete.erase(it);
351  it = m_ToDelete.begin();
352  changed = true;
353  continue;
354  }
355 
356  ++it;
357  }
358 
359  if (changed)
360  {
363  }
364 }
365 
366 QString MythScreenStack::GetLocation(bool fullPath) const
367 {
368  if (fullPath)
369  {
370  QString path;
371  QVector<MythScreenType *>::const_iterator it;
372  for (it = m_Children.begin(); it != m_Children.end(); ++it)
373  {
374  if (!(*it)->IsDeleting())
375  {
376  if (path.isEmpty())
377  path = (*it)->objectName();
378  else
379  path += '/' + (*it)->objectName();
380  }
381  }
382  return path;
383  }
384 
385  if (m_topScreen)
386  return m_topScreen->objectName();
387 
388  return QString();
389 }
390 
392 {
393  return GetMythPainter();
394 }
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:924
void SetRedraw(void)
Definition: mythuitype.cpp:295
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:328
virtual void RecalculateDrawOrder(void)
void AdjustAlpha(int mode, int alphachange, int minalpha=0, int maxalpha=255)
Definition: mythuitype.cpp:906
MythMainWindow * GetMythMainWindow(void)
bool IsLoading(void)
bool IsLoaded(void)
static Type kExitToMainMenuEventType
Definition: mythevent.h:69
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:933