MythTV  0.28pre
mythscreentype.cpp
Go to the documentation of this file.
1 
2 #include "mythscreentype.h"
3 
4 #include <QCoreApplication>
5 #include <QDomDocument>
6 #include <QRunnable>
7 
8 #include "mythcorecontext.h"
9 #include "mythobservable.h"
10 #include "mthreadpool.h"
11 
12 #include "mythscreenstack.h"
13 #include "mythmainwindow.h"
14 #include "mythuihelper.h"
15 #include "mythprogressdialog.h"
16 #include "mythuigroup.h"
17 #include "mythuistatetype.h"
18 #include "mythlogging.h"
19 #include "mythgesture.h"
20 #include "mythuitext.h"
21 
23 {
24  public:
25  SemaphoreLocker(QSemaphore *lock) : m_lock(lock)
26  {
27  if (m_lock)
28  m_lock->acquire();
29  }
31  {
32  if (m_lock)
33  m_lock->release();
34  }
35  private:
36  QSemaphore *m_lock;
37 };
38 
40  (QEvent::Type) QEvent::registerEventType();
41 
42 class ScreenLoadTask : public QRunnable
43 {
44  public:
46 
47  private:
48  void run(void)
49  {
50  m_parent.Load();
51  m_parent.m_IsLoaded = true;
52  m_parent.m_IsLoading = false;
53  m_parent.m_LoadLock.release();
54  }
55 
57 };
58 
60  MythScreenStack *parent, const QString &name, bool fullscreen) :
61  MythUIComposite(parent, name), m_LoadLock(1)
62 {
63  m_FullScreen = fullscreen;
64  m_CurrentFocusWidget = NULL;
65 
67  m_BusyPopup = NULL;
68  m_IsDeleting = false;
69  m_IsLoading = false;
70  m_IsLoaded = false;
71  m_IsInitialized = false;
72 
73  // Can be overridden, of course, but default to full sized.
75 
76  if (QCoreApplication::applicationName() == MYTH_APPNAME_MYTHFRONTEND)
78  QString("SCREEN_TYPE CREATED %1").arg(name));
79 }
80 
82  MythUIType *parent, const QString &name, bool fullscreen) :
83  MythUIComposite(parent, name), m_LoadLock(1)
84 {
85  m_FullScreen = fullscreen;
86  m_CurrentFocusWidget = NULL;
87 
88  m_ScreenStack = NULL;
89  m_BusyPopup = NULL;
90  m_IsDeleting = false;
91  m_IsLoading = false;
92  m_IsLoaded = false;
93  m_IsInitialized = false;
94 
96 
97  if (QCoreApplication::applicationName() == MYTH_APPNAME_MYTHFRONTEND)
99  QString("SCREEN_TYPE CREATED %1").arg(name));
100 }
101 
103 {
104  if (QCoreApplication::applicationName() == MYTH_APPNAME_MYTHFRONTEND)
106  QString("SCREEN_TYPE DESTROYED %1").arg(objectName()));
107 
108  // locking ensures background screen load can finish running
109  SemaphoreLocker locker(&m_LoadLock);
110 
111  m_CurrentFocusWidget = NULL;
112  emit Exiting();
113 }
114 
116 {
117  return m_FullScreen;
118 }
119 
121 {
122  m_FullScreen = full;
123 }
124 
126 {
127  return m_CurrentFocusWidget;
128 }
129 
131 {
132  if (!widget || !widget->IsVisible())
133  {
134  QMap<int, MythUIType *>::iterator it = m_FocusWidgetList.begin();
136 
137  while (it != m_FocusWidgetList.end())
138  {
139  current = *it;
140 
141  if (current->CanTakeFocus() && current->IsVisible())
142  {
143  widget = current;
144  break;
145  }
146  ++it;
147  }
148  }
149 
150  if (!widget)
151  return false;
152 
153  if (m_CurrentFocusWidget == widget)
154  return true;
155 
156  MythUIText *helpText = dynamic_cast<MythUIText *>(GetChild("helptext"));
157  if (helpText)
158  helpText->Reset();
159 
162  m_CurrentFocusWidget = widget;
164 
165  if (helpText && !widget->GetHelpText().isEmpty())
166  helpText->SetText(widget->GetHelpText());
167 
168  return true;
169 }
170 
172 {
173  if (!m_CurrentFocusWidget || m_FocusWidgetList.isEmpty())
174  return SetFocusWidget(NULL);
175 
176  bool reachedCurrent = false;
177  bool looped = false;
178 
179  QMap<int, MythUIType *>::iterator it = m_FocusWidgetList.begin();
181 
182  // There is probably a more efficient way to do this, but the list
183  // is never going to be that big so it will do for now
184  if (up)
185  {
186  while (it != m_FocusWidgetList.end())
187  {
188  current = *it;
189 
190  if ((looped || reachedCurrent) &&
191  current->IsVisible() && current->IsEnabled())
192  return SetFocusWidget(current);
193 
194  if (current == m_CurrentFocusWidget)
195  reachedCurrent = true;
196 
197  ++it;
198 
199  if (it == m_FocusWidgetList.end())
200  {
201  if (looped)
202  return false;
203  else
204  {
205  looped = true;
206  it = m_FocusWidgetList.begin();
207  }
208  }
209  }
210  }
211  else
212  {
213  it = m_FocusWidgetList.end() - 1;
214  while (it != m_FocusWidgetList.begin() - 1)
215  {
216  current = *it;
217 
218  if ((looped || reachedCurrent) &&
219  current->IsVisible() && current->IsEnabled())
220  return SetFocusWidget(current);
221 
222  if (current == m_CurrentFocusWidget)
223  reachedCurrent = true;
224 
225  --it;
226 
227  if (it == m_FocusWidgetList.begin() - 1)
228  {
229  if (looped)
230  return false;
231  else
232  {
233  looped = true;
234  it = m_FocusWidgetList.end() - 1;
235  }
236  }
237  }
238  }
239 
240  return false;
241 }
242 
244 {
245  m_FocusWidgetList.clear();
246  m_CurrentFocusWidget = NULL;
247 
249 
250  if (m_FocusWidgetList.size() > 0)
251  SetFocusWidget();
252 }
253 
255 {
256  return m_ScreenStack;
257 }
258 
260 {
261  if (!m_FullScreen)
262  {
263  if (!GetMythMainWindow()->GetPaintWindow()->mask().isEmpty())
264  {
265  // remove this screen's area from the mask so any embedded video is
266  // shown which was covered by this screen
267  if (!m_SavedMask.isEmpty())
269  }
270  }
271 
273 }
274 
276 {
277  if (!m_FullScreen)
278  {
279  if (!GetMythMainWindow()->GetPaintWindow()->mask().isEmpty())
280  {
281  // add this screens area to the mask so any embedded video isn't
282  // shown in front of this screen
283  QRegion region = GetMythMainWindow()->GetPaintWindow()->mask();
284  m_SavedMask = region;
285  region = region.united(QRegion(m_Area));
286  GetMythMainWindow()->GetPaintWindow()->setMask(region);
287  }
288  }
289 
291 }
292 
294 {
295  return m_IsDeleting;
296 }
297 
298 void MythScreenType::SetDeleting(bool deleting)
299 {
300  m_IsDeleting = deleting;
301 }
302 
304 {
305  return true;
306 }
307 
319 {
320  // Virtual
321 }
322 
323 void MythScreenType::LoadInBackground(QString message)
324 {
325  m_LoadLock.acquire();
326 
327  m_IsLoading = true;
328  m_IsLoaded = false;
329 
331 
332  OpenBusyPopup(message);
333 
334  ScreenLoadTask *loadTask = new ScreenLoadTask(*this);
335  MThreadPool::globalInstance()->start(loadTask, "ScreenLoad");
336 }
337 
339 {
340  SemaphoreLocker locker(&m_LoadLock);
341 
342  m_IsLoading = true;
343  m_IsLoaded = false;
344 
346  Load();
347  m_IsLoaded = true;
348  m_IsLoading = false;
349 }
350 
352 {
353  m_IsInitialized = false;
355 }
356 
357 void MythScreenType::OpenBusyPopup(QString message)
358 {
359  if (m_BusyPopup)
360  return;
361 
362  QString msg(tr("Loading..."));
363  if (!message.isEmpty())
364  msg = message;
365 
366  MythScreenStack *popupStack =
367  GetMythMainWindow()->GetStack("popup stack");
368  m_BusyPopup =
369  new MythUIBusyDialog(msg, popupStack, "mythscreentypebusydialog");
370 
371  if (m_BusyPopup->Create())
372  popupStack->AddScreen(m_BusyPopup, false);
373 }
374 
376 {
377  if (m_BusyPopup)
378  m_BusyPopup->Close();
379  m_BusyPopup = NULL;
380 }
381 
382 void MythScreenType::SetBusyPopupMessage(const QString &message)
383 {
384  if (m_BusyPopup)
385  m_BusyPopup->SetMessage(message);
386 }
387 
389 {
390  if (m_BusyPopup)
391  m_BusyPopup->Reset();
392 }
393 
398 {
399  return m_IsInitialized;
400 }
401 
403 {
404  SemaphoreLocker locker(&m_LoadLock); // don't run while loading..
405 
406  CloseBusyPopup();
407  Init();
408  m_IsInitialized = true;
409 }
410 
419 {
420  // Virtual
421 }
422 
424 {
425  CloseBusyPopup();
426  if (GetScreenStack())
427  GetScreenStack()->PopScreen(this);
428 }
429 
431 {
432  // Virtual
433 }
434 
435 bool MythScreenType::keyPressEvent(QKeyEvent *event)
436 {
438  return true;
439 
440  bool handled = false;
441  QStringList actions;
442  handled = GetMythMainWindow()->TranslateKeyPress("Global", event, actions);
443 
444  for (int i = 0; i < actions.size() && !handled; i++)
445  {
446  QString action = actions[i];
447  handled = true;
448 
449  if (action == "LEFT" || action == "UP" || action == "PREVIOUS")
450  {
451  if (!NextPrevWidgetFocus(false))
452  handled = false;
453  }
454  else if (action == "RIGHT" || action == "DOWN" || action == "NEXT")
455  {
456  if (!NextPrevWidgetFocus(true))
457  handled = false;
458  }
459  else if (action == "ESCAPE")
460  Close();
461  else if (action == "MENU")
462  ShowMenu();
463  else if (action.startsWith("SYSEVENT"))
464  gCoreContext->SendSystemEvent(QString("KEY_%1").arg(action.mid(8)));
465  else if (action == ACTION_SCREENSHOT)
467  else if (action == ACTION_TVPOWERON)
469  else if (action == ACTION_TVPOWEROFF)
471  else
472  handled = false;
473  }
474 
475  return handled;
476 }
477 
479 {
480  bool handled = false;
481  if (event->gesture() == MythGestureEvent::Click)
482  {
483  switch (event->GetButton())
484  {
486  ShowMenu();
487  handled = true;
488  break;
489  default :
490  break;
491  }
492 
493  }
494 
495  if (!handled)
496  {
497  MythUIType *clicked = GetChildAt(event->GetPosition());
498  if (clicked && clicked->IsEnabled())
499  {
500  SetFocusWidget(clicked);
501  if (clicked->gestureEvent(event))
502  handled = true;
503  }
504  }
505 
506  return handled;
507 }
508 
513  const QString &filename, QDomElement &element, bool showWarnings)
514 {
515  if (element.tagName() == "area")
516  {
517  MythRect rect = parseRect(element, false);
518  MythRect rectN = parseRect(element);
519  QRect screenArea = GetMythMainWindow()->GetUIScreenRect();
520 
521  if (rect.x() == -1)
522  rectN.moveLeft((screenArea.width() - rectN.width()) / 2);
523 
524  if (rect.y() == -1)
525  rectN.moveTop((screenArea.height() - rectN.height()) / 2);
526 
527  SetArea(rectN);
528 
529  if (m_Area.width() < screenArea.width() ||
530  m_Area.height() < screenArea.height())
531  {
532  m_FullScreen = false;
533  }
534  else
535  {
536  m_FullScreen = true;
537  }
538  }
539  else
540  {
541  return MythUIType::ParseElement(filename, element, showWarnings);
542  }
543 
544  return true;
545 }
546 
551 {
552  MythScreenType *st = dynamic_cast<MythScreenType *>(base);
553  if (!st)
554  {
555  LOG(VB_GENERAL, LOG_ERR, "ERROR, bad parsing");
556  return;
557  }
558 
560  m_IsDeleting = false;
561 
562  MythUIType::CopyFrom(base);
563 
564  ConnectDependants(true);
565 
566  BuildFocusList();
567 };
568 
576 {
577  LOG(VB_GENERAL, LOG_ERR, "CreateCopy called on screentype - bad.");
578 }
579 
581 {
582  if (m_Painter)
583  return m_Painter;
584  if (m_ScreenStack)
585  return m_ScreenStack->GetPainter();
586  return GetMythPainter();
587 }
SemaphoreLocker(QSemaphore *lock)
virtual void aboutToShow(void)
QSemaphore * m_lock
void SetMessage(const QString &message)
virtual void ShowMenu(void)
void start(QRunnable *runnable, QString debugName, int priority=0)
volatile bool m_IsLoading
All purpose text widget, displays a text string.
Definition: mythuitext.h:28
QPoint GetPosition() const
Definition: mythgesture.h:110
virtual bool Create(void)
void LoseFocus()
bool IsFullscreen(void) const
ScreenLoadTask(MythScreenType &parent)
void Reset(void)
Reset the widget to it's original state, should not reset changes made by the theme.
Definition: mythuitext.cpp:114
void Reset(void)
Reset the widget to it's original state, should not reset changes made by the theme.
virtual void SetText(const QString &text)
Definition: mythuitext.cpp:166
MythPainter * GetMythPainter(void)
MythUIBusyDialog * m_BusyPopup
MythUIType * GetChildAt(const QPoint &p, bool recursive=true, bool focusable=true) const
Return the first MythUIType which accepts focus found at the given coordinates.
Definition: mythuitype.cpp:241
AllMusic * parent
MythUIType * m_CurrentFocusWidget
Button GetButton(void) const
Definition: mythgesture.h:113
bool IsDeleting(void) const
MythScreenStack * GetStack(const QString &stackname)
const char * filename
Definition: ioapi.h:135
virtual void CreateCopy(MythUIType *parent)
Copy the state of this widget to the one given, it must be of the same type.
MythCoreContext * gCoreContext
This global variable contains the MythCoreContext instance for the app.
bool ScreenShot(int w=0, int h=0, QString filename="")
void ConnectDependants(bool recurse=false)
MythScreenType(MythScreenStack *parent, const QString &name, bool fullscreen=true)
void HandleTVPower(bool poweron)
The base class on which all widgets and screens are based.
Definition: mythuitype.h:64
void BuildFocusList(void)
void AddFocusableChildrenToList(QMap< int, MythUIType * > &focusList)
bool IsInitialized(void) const
Has Init() been called on this screen?
void LoadInForeground(void)
MythPainter * GetPainter(void)
virtual void Close()
virtual void CopyFrom(MythUIType *base)
Copy this widgets state from another.
bool CanTakeFocus(void) const
Return if this widget can accept input focus.
Definition: mythuitype.cpp:354
virtual void AddScreen(MythScreenType *screen, bool allowFade=true)
void SetDeleting(bool deleting)
bool IsVisible(bool recurse=false) const
Definition: mythuitype.cpp:898
void SetFullscreen(bool full)
MythScreenType & m_parent
A C++ ripoff of the stroke library for MythTV.
QDateTime current(bool stripped)
Returns current Date and Time in UTC.
Definition: mythdate.cpp:10
virtual bool NextPrevWidgetFocus(bool up_or_down)
MythUIType * GetChild(const QString &name) const
Get a named child of this UIType.
Definition: mythuitype.cpp:150
QWidget * GetPaintWindow()
virtual bool keyPressEvent(QKeyEvent *)
Key event handler.
Definition: mythuitype.cpp:988
QMap< int, MythUIType * > m_FocusWidgetList
Wrapper around QRect allowing us to handle percentage and other relative values for areas in mythui...
Definition: mythrect.h:17
void AllowReInit(void)
void ReloadInBackground(void)
bool IsEnabled(void) const
Definition: mythuitype.h:95
void moveLeft(const QString &sX)
Definition: mythrect.cpp:235
MythRect m_Area
Definition: mythuitype.h:245
virtual ~MythScreenType()
void SetBusyPopupMessage(const QString &message)
Gesture gesture(void) const
Get the gesture type.
Definition: mythgesture.h:101
A custom event that represents a mouse gesture.
Definition: mythgesture.h:37
const char * name
Definition: ParseText.cpp:338
QString GetHelpText(void) const
Definition: mythuitype.h:150
MythPainter * m_Painter
Definition: mythuitype.h:267
MythScreenStack * GetScreenStack() const
MythUIType * GetFocusWidget(void) const
friend class ScreenLoadTask
virtual bool gestureEvent(MythGestureEvent *)
Mouse click/movement handler, receives mouse gesture events from the QCoreApplication event loop...
virtual bool gestureEvent(MythGestureEvent *)
Mouse click/movement handler, receives mouse gesture events from the QCoreApplication event loop...
MythMainWindow * GetMythMainWindow(void)
static MThreadPool * globalInstance(void)
QSemaphore m_LoadLock
virtual void SetArea(const MythRect &rect)
Definition: mythuitype.cpp:608
virtual void aboutToHide(void)
void CloseBusyPopup(void)
virtual bool keyPressEvent(QKeyEvent *)
Key event handler.
MythScreenStack * m_ScreenStack
bool SetFocusWidget(MythUIType *widget=NULL)
bool TranslateKeyPress(const QString &context, QKeyEvent *e, QStringList &actions, bool allowJumps=true) MUNUSED_RESULT
Get a list of actions for a keypress in the given context.
virtual void CopyFrom(MythUIType *base)
Copy this widgets state from another.
virtual void Init(void)
Used after calling Load() to assign data to widgets and other UI initilisation which is prohibited in...
volatile bool m_IsLoaded
static MythRect parseRect(const QString &text, bool normalize=true)
virtual void Load(void)
Load data which will ultimately be displayed on-screen or used to determine what appears on-screen (S...
virtual void PopScreen(MythScreenType *screen=NULL, bool allowFade=true, bool deleteScreen=true)
void OpenBusyPopup(QString message="")
bool TakeFocus()
Screen in which all other widgets are contained and rendered.
void moveTop(const QString &sX)
Definition: mythrect.cpp:245
void ActivateAnimations(MythUIAnimation::Trigger trigger)
Definition: mythuitype.cpp:288
void SendSystemEvent(const QString &msg)
virtual MythPainter * GetPainter(void)
virtual bool ParseElement(const QString &filename, QDomElement &element, bool showWarnings)
Parse the xml definition of this widget setting the state of the object accordingly.
virtual bool ParseElement(const QString &filename, QDomElement &element, bool showWarnings)
Parse the xml definition of this widget setting the state of the object accordingly.
void ResetBusyPopup(void)
void LoadInBackground(QString message="")