MythTV  master
weather.cpp
Go to the documentation of this file.
1 
2 // C headers
3 #include <unistd.h>
4 #include <cstdlib>
5 
6 // QT headers
7 #include <QApplication>
8 
9 // MythTV headers
10 #include <mythdb.h>
11 #include <mythcontext.h>
12 
13 #include <mythuitext.h>
14 #include <mythdate.h>
15 
16 // MythWeather headers
17 #include "weatherScreen.h"
18 #include "sourceManager.h"
19 #include "weatherSetup.h"
20 #include "weather.h"
21 
22 Weather::Weather(MythScreenStack *parent, const QString &name, SourceManager *srcMan)
23  : MythScreenType(parent, name),
24  m_weatherStack(new MythScreenStack(GetMythMainWindow(), "weather stack")),
25  m_nextpageInterval(gCoreContext->GetNumSetting("weatherTimeout", 10)),
26  m_nextpage_Timer(new QTimer(this))
27 {
28  if (!srcMan)
29  {
30  m_srcMan = new SourceManager();
31  // No point in doing this as the very first thing we are going to do
32  // is destroy the sources and reload them.
33 #if 0
35  m_srcMan->doUpdate();
36 #endif
37  m_createdSrcMan = true;
38  }
39  else
40  {
41  m_srcMan = srcMan;
42  m_createdSrcMan = false;
43  }
44 
45  connect(m_nextpage_Timer, SIGNAL(timeout()), SLOT(nextpage_timeout()) );
46 
48 }
49 
51 {
52  if (m_createdSrcMan)
53  delete m_srcMan;
54 
55  clearScreens();
56 
57  if (m_weatherStack)
59 }
60 
62 {
63  // Load the theme for this screen
64  bool foundtheme = LoadWindowFromXML("weather-ui.xml", "weatherbase", this);
65  if (!foundtheme)
66  {
67  LOG(VB_GENERAL, LOG_ERR, "Missing required window - weatherbase.");
68  return false;
69  }
70 
71  bool err = false;
72 
73  UIUtilE::Assign(this, m_pauseText, "pause_text", &err);
74  UIUtilE::Assign(this, m_headerText, "header", &err);
75  UIUtilE::Assign(this, m_updatedText, "update_text", &err);
76 
77  if (err)
78  {
79  LOG(VB_GENERAL, LOG_ERR,
80  "Window weatherbase is missing required elements.");
81  return false;
82  }
83 
84  if (m_pauseText)
85  {
86  m_pauseText->SetText(tr("Paused"));
87  m_pauseText->Hide();
88  }
89 
90  return true;
91 }
92 
94 {
95  m_currScreen = nullptr;
96 
97  m_cur_screen = 0;
98  while (!m_screens.empty())
99  {
100  WeatherScreen *screen = m_screens.back();
101  m_weatherStack->PopScreen(screen, false, false);
102  m_screens.pop_back();
103  delete screen;
104  }
105 }
106 
108 {
109  SetupScreens();
110 }
111 
113 {
114  // Delete any existing screens
115  clearScreens();
116 
117  m_paused = false;
118  m_pauseText->Hide();
119 
120  // Refresh sources
124 
126  QString query =
127  "SELECT screen_id, container, units, draworder FROM weatherscreens "
128  " WHERE hostname = :HOST ORDER BY draworder;";
129  db.prepare(query);
130  db.bindValue(":HOST", gCoreContext->GetHostName());
131  if (!db.exec())
132  {
133  MythDB::DBError("Selecting weather screens.", db);
134  return false;
135  }
136 
137  if (!db.size())
138  {
139  if (m_firstSetup)
140  {
141  m_firstSetup = false;
142  // If no screens exist, run the setup
144 
145  auto *ssetup = new ScreenSetup(mainStack, "weatherscreensetup",
146  m_srcMan);
147 
148  connect(ssetup, SIGNAL(Exiting()), this, SLOT(setupScreens()));
149 
150  if (ssetup->Create())
151  {
152  mainStack->AddScreen(ssetup);
153  }
154  else
155  {
156  delete ssetup;
157  }
158  }
159  else
160  {
161  Close();
162  }
163  }
164  else
165  {
166  while (db.next())
167  {
168  int id = db.value(0).toInt();
169  QString container = db.value(1).toString();
170  units_t units = db.value(2).toUInt();
171  uint draworder = db.value(3).toUInt();
172 
173  ScreenListInfo &screenListInfo = m_allScreens[container];
174 
175  WeatherScreen *ws = WeatherScreen::loadScreen(m_weatherStack, &screenListInfo, id);
176  if (!ws->Create())
177  {
178  delete ws;
179  continue;
180  }
181 
182  ws->setUnits(units);
183  ws->setInUse(true);
184  m_screens.insert(draworder, ws);
185  connect(ws, SIGNAL(screenReady(WeatherScreen *)), this,
186  SLOT(screenReady(WeatherScreen *)));
187  m_srcMan->connectScreen(id, ws);
188  }
189 
190  if( m_screens.empty() )
191  {
192  // We rejected every screen... sit on this and rotate.
193  LOG(VB_GENERAL, LOG_ERR, "No weather screens left, aborting.");
194  m_nextpage_Timer->stop();
195  if( m_updatedText )
196  {
197  m_updatedText->SetText(tr("None of the configured screens are complete in this theme (missing copyright information)."));
198  m_updatedText->Show();
199  return true;
200  }
201  return false;
202  }
203 
205  m_srcMan->doUpdate(true);
206  }
207 
208  return true;
209 }
210 
212 {
213  if (m_firstRun && !m_screens.empty() && ws == m_screens[m_cur_screen])
214  {
215  m_firstRun = false;
216  showScreen(ws);
217  m_nextpage_Timer->start(1000 * m_nextpageInterval);
218  }
219  disconnect(ws, SIGNAL(screenReady(WeatherScreen *)), this,
220  SLOT(screenReady(WeatherScreen *)));
221 }
222 
224 {
225  if (m_screens.empty())
226  return nullptr;
227 
228  m_cur_screen = (m_cur_screen + 1) % m_screens.size();
229  return m_screens[m_cur_screen];
230 }
231 
233 {
234  if (m_screens.empty())
235  return nullptr;
236 
237  m_cur_screen = (m_cur_screen < 0) ? 0 : m_cur_screen;
238  m_cur_screen = (m_cur_screen + m_screens.size() - 1) % m_screens.size();
239  return m_screens[m_cur_screen];
240 }
241 
242 bool Weather::keyPressEvent(QKeyEvent *event)
243 {
244  if (GetFocusWidget() && GetFocusWidget()->keyPressEvent(event))
245  return true;
246 
247  QStringList actions;
248  bool handled = GetMythMainWindow()->TranslateKeyPress("Weather", event, actions);
249 
250  for (int i = 0; i < actions.size() && !handled; i++)
251  {
252  QString action = actions[i];
253  handled = true;
254 
255  if (action == "LEFT")
256  cursorLeft();
257  else if (action == "RIGHT")
258  cursorRight();
259  else if (action == "PAUSE")
260  holdPage();
261  else if (action == "MENU")
262  setupPage();
263  else if (action == "UPDATE")
264  {
265  m_srcMan->doUpdate();
266  }
267  else if (action == "ESCAPE")
268  {
269  m_nextpage_Timer->stop();
270  hideScreen();
271  Close();
272  }
273  else
274  handled = false;
275  }
276 
277  if (!handled && MythScreenType::keyPressEvent(event))
278  handled = true;
279 
280  return handled;
281 }
282 
284 {
285  if (!ws)
286  return;
287 
288  m_currScreen = ws;
290  m_headerText->SetText(m_currScreen->objectName());
291  m_updatedText->SetText(m_currScreen->getValue("updatetime"));
292 }
293 
295 {
296  if (!m_currScreen)
297  return;
298 
299  m_weatherStack->PopScreen(nullptr, false,false);
300 }
301 
303 {
304  if (!m_nextpage_Timer->isActive())
305  m_nextpage_Timer->start(1000 * m_nextpageInterval);
306  else
307  m_nextpage_Timer->stop();
308 
309  m_paused = !m_paused;
310 
311  if (m_pauseText)
312  {
313  if (m_paused)
314  m_pauseText->Show();
315  else
316  m_pauseText->Hide();
317  }
318 }
319 
321 {
322  m_srcMan->stopTimers();
323  m_nextpage_Timer->stop();
326 
328 
329  auto *ssetup = new ScreenSetup(mainStack, "weatherscreensetup", m_srcMan);
330 
331  connect(ssetup, SIGNAL(Exiting()), this, SLOT(setupScreens()));
332 
333  if (ssetup->Create())
334  {
335  clearScreens();
336  mainStack->AddScreen(ssetup);
337  }
338  else
339  {
340  delete ssetup;
341  }
342 
343  m_firstRun = true;
344 }
345 
347 {
348  WeatherScreen *ws = nextScreen();
349  if (ws && ws->canShowScreen())
350  {
351  hideScreen();
352  showScreen(ws);
353  if (!m_paused)
354  m_nextpage_Timer->start(1000 * m_nextpageInterval);
355  }
356 }
357 
359 {
360  WeatherScreen *ws = prevScreen();
361  if (ws && ws->canShowScreen())
362  {
363  hideScreen();
364  showScreen(ws);
365  if (!m_paused)
366  m_nextpage_Timer->start(1000 * m_nextpageInterval);
367  }
368 }
369 
371 {
372  WeatherScreen *nxt = nextScreen();
373 
374  if (nxt && nxt->canShowScreen())
375  {
376  hideScreen();
377  showScreen(nxt);
378  }
379  else
380  LOG(VB_GENERAL, LOG_ERR, "Next screen not ready");
381 
382  m_nextpage_Timer->start(1000 * m_nextpageInterval);
383 }
384 
385 /*
386  * vim:ts=4:sw=4:ai:et:si:sts=4
387  */
bool next(void)
Wrap QSqlQuery::next() so we can display the query results.
Definition: mythdbcon.cpp:781
int m_nextpageInterval
Definition: weather.h:57
bool m_paused
Definition: weather.h:70
void holdPage()
Definition: weather.cpp:302
void bindValue(const QString &placeholder, const QVariant &val)
Add a single binding.
Definition: mythdbcon.cpp:862
void Show(void)
void setupScreens()
Definition: weather.cpp:107
void showScreen(WeatherScreen *ws)
Definition: weather.cpp:283
ScreenListMap m_allScreens
Definition: weather.h:68
bool m_createdSrcMan
Definition: weather.h:63
bool TranslateKeyPress(const QString &context, QKeyEvent *e, QStringList &actions, bool allowJumps=true)
Get a list of actions for a keypress in the given context.
void setUnits(units_t units)
Definition: weatherScreen.h:44
void cursorLeft()
Definition: weather.cpp:358
bool m_firstSetup
Definition: weather.h:61
QSqlQuery wrapper that fetches a DB connection from the connection pool.
Definition: mythdbcon.h:125
void cursorRight()
Definition: weather.cpp:346
int size(void) const
Definition: mythdbcon.h:203
virtual void SetText(const QString &text)
Definition: mythuitext.cpp:135
static WeatherScreen * loadScreen(MythScreenStack *parent, ScreenListInfo *screenDefn, int id)
bool SetupScreens()
Definition: weather.cpp:112
MythCoreContext * gCoreContext
This global variable contains the MythCoreContext instance for the app.
MythScreenStack * GetMainStack()
void clearScreens()
Definition: weather.cpp:93
WeatherScreen * nextScreen()
Definition: weather.cpp:223
void setupPage()
Definition: weather.cpp:320
int m_cur_screen
Definition: weather.h:66
MythScreenStack * m_weatherStack
Definition: weather.h:54
void Hide(void)
QVariant value(int i) const
Definition: mythdbcon.h:198
virtual void Close()
bool findScriptsDB()
virtual void AddScreen(MythScreenType *screen, bool allowFade=true)
bool Create(void) override
Definition: weather.cpp:61
void nextpage_timeout()
Definition: weather.cpp:370
MythUIText * m_headerText
Definition: weather.h:73
ScreenList m_screens
Definition: weather.h:65
static bool Assign(ContainerType *container, UIType *&item, const QString &name, bool *err=nullptr)
Definition: mythuiutils.h:27
QTimer * m_nextpage_Timer
Definition: weather.h:59
unsigned int uint
Definition: compat.h:140
static MSqlQueryInfo InitCon(ConnectionReuse=kNormalConnection)
Only use this in combination with MSqlQuery constructor.
Definition: mythdbcon.cpp:534
MythUIText * m_pauseText
Definition: weather.h:72
static bool LoadWindowFromXML(const QString &xmlfile, const QString &windowname, MythUIType *parent)
MythUIType * GetFocusWidget(void) const
MythMainWindow * GetMythMainWindow(void)
bool Create(void) override
bool m_firstRun
Definition: weather.h:56
WeatherScreen * prevScreen()
Definition: weather.cpp:232
WeatherScreen * m_currScreen
Definition: weather.h:69
void screenReady(WeatherScreen *ws)
Definition: weather.cpp:211
bool prepare(const QString &query)
QSqlQuery::prepare() is not thread safe in Qt <= 3.3.2.
Definition: mythdbcon.cpp:806
void setInUse(bool inuse)
Definition: weatherScreen.h:48
bool keyPressEvent(QKeyEvent *) override
Key event handler.
#define LOG(_MASK_, _LEVEL_, _STRING_)
Definition: mythlogging.h:41
virtual bool canShowScreen()
virtual void PopScreen(MythScreenType *screen=nullptr, bool allowFade=true, bool deleteScreen=true)
unsigned char units_t
Definition: weatherUtils.h:22
ScreenListMap loadScreens()
~Weather()
Definition: weather.cpp:50
void doUpdate(bool forceUpdate=false)
MythUIText * m_updatedText
Definition: weather.h:74
bool connectScreen(uint id, WeatherScreen *screen)
SourceManager * m_srcMan
Definition: weather.h:64
bool exec(void)
Wrap QSqlQuery::exec() so we can display SQL.
Definition: mythdbcon.cpp:602
static void DBError(const QString &where, const MSqlQuery &query)
Definition: mythdb.cpp:179
Weather(MythScreenStack *parent, const QString &name, SourceManager *srcMan)
Definition: weather.cpp:22
Screen in which all other widgets are contained and rendered.
void hideScreen(void)
Definition: weather.cpp:294
Weather screen.
Definition: weatherScreen.h:26
QString GetHostName(void)
QString getValue(const QString &key)
Definition: weatherScreen.h:41
bool keyPressEvent(QKeyEvent *) override
Key event handler.
Definition: weather.cpp:242