MythTV  master
weatherSetup.cpp
Go to the documentation of this file.
1 
2 // MythWeather headers
3 #include "weatherScreen.h"
4 #include "weatherSource.h"
5 #include "sourceManager.h"
6 #include "weatherSetup.h"
7 
8 // MythTV headers
9 //#include <mythdbcon.h>
10 #include <mythdb.h>
11 #include <mythprogressdialog.h>
12 
13 // QT headers
14 #include <QApplication>
15 #include <QSqlError>
16 #include <QVariant>
17 
18 #define GLBL_SCREEN 0
19 #define SCREEN_SETUP_SCREEN 1
20 #define SRC_SCREEN 2
21 
23 {
24  // Load the theme for this screen
25  bool foundtheme = LoadWindowFromXML("weather-ui.xml", "global-setup", this);
26  if (!foundtheme)
27  return false;
28 
29  m_timeoutSpinbox = dynamic_cast<MythUISpinBox *> (GetChild("timeout_spinbox"));
30 
31  m_backgroundCheckbox = dynamic_cast<MythUICheckBox *> (GetChild("backgroundcheck"));
32  m_finishButton = dynamic_cast<MythUIButton *> (GetChild("finishbutton"));
33 
35  {
36  LOG(VB_GENERAL, LOG_ERR, "Theme is missing required elements.");
37  return false;
38  }
39 
41 
42  m_finishButton->SetText(tr("Finish"));
43  connect(m_finishButton, SIGNAL(Clicked()), this, SLOT(saveData()));
44 
45  loadData();
46 
47  return true;
48 }
49 
51 {
52  int setting = gCoreContext->GetNumSetting("weatherbackgroundfetch", 0);
53  if (setting == 1)
55 
56  m_timeout = gCoreContext->GetNumSetting("weatherTimeout", 10);
57  m_timeoutSpinbox->SetRange(5, 120, 5);
59 }
60 
62 {
64  gCoreContext->SaveSetting("weatherTimeout", timeout);
65 
66  int checkstate = 0;
68  checkstate = 1;
69  gCoreContext->SaveSetting("weatherbackgroundfetch", checkstate);
70  Close();
71 }
72 
74 
76  SourceManager *srcman)
77  : MythScreenType(parent, name),
78  m_sourceManager(srcman ? srcman : new SourceManager()),
79  m_createdSrcMan(srcman == nullptr),
80  m_helpText(nullptr), m_activeList(nullptr),
81  m_inactiveList(nullptr), m_finishButton(nullptr)
82 {
85 }
86 
88 {
89  if (m_createdSrcMan)
90  delete m_sourceManager;
91  m_sourceManager = nullptr;
92 
93  // Deallocate the ScreenListInfo objects created for the inactive screen list.
94  for (int i=0; i < m_inactiveList->GetCount(); i++)
95  {
97  if (item->GetData().isValid())
98  delete item->GetData().value<ScreenListInfo *>();
99  }
100 
101  // Deallocate the ScreenListInfo objects created for the active screen list.
102  for (int i=0; i < m_activeList->GetCount(); i++)
103  {
105  if (item->GetData().isValid())
106  delete item->GetData().value<ScreenListInfo *>();
107  }
108 }
109 
111 {
112  // Load the theme for this screen
113  bool foundtheme = LoadWindowFromXML("weather-ui.xml", "screen-setup", this);
114  if (!foundtheme)
115  return false;
116 
117  m_helpText = dynamic_cast<MythUIText *> (GetChild("helptxt"));
118 
119  m_activeList = dynamic_cast<MythUIButtonList *> (GetChild("activelist"));
120  m_inactiveList = dynamic_cast<MythUIButtonList *> (GetChild("inactivelist"));
121 
122  m_finishButton = dynamic_cast<MythUIButton *> (GetChild("finishbutton"));
123 
124  MythUIText *activeheader = dynamic_cast<MythUIText *> (GetChild("activehdr"));
125  if (activeheader)
126  activeheader->SetText(tr("Active Screens"));
127 
128  MythUIText *inactiveheader = dynamic_cast<MythUIText *> (GetChild("inactivehdr"));
129  if (inactiveheader)
130  inactiveheader->SetText(tr("Inactive Screens"));
131 
133  {
134  LOG(VB_GENERAL, LOG_ERR, "Theme is missing required elements.");
135  return false;
136  }
137 
138  BuildFocusList();
139 
140  connect(m_activeList, SIGNAL(itemSelected(MythUIButtonListItem *)),
141  this, SLOT(updateHelpText()));
142  connect(m_activeList, SIGNAL(itemClicked(MythUIButtonListItem *)),
143  this, SLOT(doListSelect(MythUIButtonListItem *)));
144  connect(m_inactiveList, SIGNAL(itemSelected(MythUIButtonListItem *)),
145  this, SLOT(updateHelpText()));
146  connect(m_inactiveList, SIGNAL(itemClicked(MythUIButtonListItem *)),
147  this, SLOT(doListSelect(MythUIButtonListItem *)));
148 
150 
151  m_finishButton->SetText(tr("Finish"));
152  connect(m_finishButton, SIGNAL(Clicked()), this, SLOT(saveData()));
153 
154  loadData();
155 
156  return true;
157 }
158 
159 bool ScreenSetup::keyPressEvent(QKeyEvent *event)
160 {
161  if (GetFocusWidget() && GetFocusWidget()->keyPressEvent(event))
162  return true;
163 
164  QStringList actions;
165  bool handled = GetMythMainWindow()->TranslateKeyPress("Weather", event, actions);
166 
167  for (int i = 0; i < actions.size() && !handled; i++)
168  {
169  QString action = actions[i];
170  handled = true;
171 
172  if (action == "DELETE")
173  {
174  if (GetFocusWidget() == m_activeList)
175  deleteScreen();
176  }
177  else
178  handled = false;
179  }
180 
181  if (!handled && MythScreenType::keyPressEvent(event))
182  handled = true;
183 
184  return handled;
185 }
186 
188 {
189  MythUIType *list = GetFocusWidget();
190  QString text;
191  if (!list)
192  return;
193 
194  if (list == m_inactiveList)
195  {
196 
198  if (!item)
199  return;
200 
201  ScreenListInfo *si = item->GetData().value<ScreenListInfo *>();
202  if (!si)
203  return;
204 
205  QStringList sources = si->m_sources;
206 
207  text = tr("Add desired screen to the Active Screens list "
208  "by pressing SELECT.") + "\n";
209  text += si->m_title + "\n";
210  text += QString("%1: %2").arg(tr("Sources"))
211  .arg(sources.join(", "));
212  }
213  else if (list == m_activeList)
214  {
216  if (!item)
217  return;
218 
219  ScreenListInfo *si = item->GetData().value<ScreenListInfo *>();
220  if (!si)
221  return;
222 
223  text += si->m_title + "\n";
224  if (si->m_hasUnits)
225  {
226  text += tr("Units: ");
227  text += (ENG_UNITS == si->m_units) ?
228  tr("English Units") : tr("SI Units");
229  text += " ";
230  }
231  if (!si->m_multiLoc && !si->m_types.empty())
232  {
233  TypeListInfo ti = *si->m_types.begin();
234  text += tr("Location: ");
235  text += (ti.m_location.isEmpty()) ? tr("Not Defined") : ti.m_location;
236  text += "\n";
237  text += tr("Source: " );
238  text += (ti.m_src) ? ti.m_src->name : tr("Not Defined");
239  text += "\n";
240  }
241  text += "\n" + tr("Press SELECT to ");
242  if (!si->m_multiLoc)
243  text += tr("change location; ");
244  if (si->m_hasUnits)
245  text += tr("change units; ");
246  text += tr("move screen up or down; or remove screen.");
247  }
248 
249  m_helpText->SetText(text);
250 }
251 
253 {
254  ScreenListInfo *si;
255 
256  QStringList types;
257 
258  ScreenListMap screenListMap = loadScreens();
259 
260  // Fill the inactive screen button list.
261  ScreenListMap::const_iterator i = screenListMap.constBegin();
262  while (i != screenListMap.constEnd())
263  {
264 
265  si = &screenListMap[i.key()];
266  types = si->m_dataTypes;
267  si->m_units = ENG_UNITS;
268 
269  QStringList type_strs;
270  for (int typei = 0; typei < types.size(); ++typei)
271  {
272  TypeListInfo ti(types[typei]);
273  si->m_types.insert(types[typei], ti);
274  type_strs << types[typei];
275  }
276 
277  QList<ScriptInfo *> scriptList;
278  // Only add a screen to the list if we have a source
279  // available to satisfy the requirements.
280  if (m_sourceManager->findPossibleSources(type_strs, scriptList))
281  {
282  for (int x = 0; x < scriptList.size(); x++)
283  {
284  ScriptInfo *script = scriptList.at(x);
285  si->m_sources.append(script->name);
286  }
287  MythUIButtonListItem *item =
289  item->SetData(qVariantFromValue(new ScreenListInfo(*si)));
290  }
291 
292  ++i;
293  }
294 
295  QMap<long, ScreenListInfo*> active_screens;
296 
298  QString query = "SELECT weatherscreens.container, weatherscreens.units, "
299  "weatherdatalayout.dataitem, weatherdatalayout.location, "
300  "weathersourcesettings.source_name, weatherscreens.draworder "
301  "FROM weatherscreens, weatherdatalayout, weathersourcesettings "
302  "WHERE weatherscreens.hostname = :HOST "
303  "AND weatherscreens.screen_id = weatherdatalayout.weatherscreens_screen_id "
304  "AND weathersourcesettings.sourceid = weatherdatalayout.weathersourcesettings_sourceid "
305  "ORDER BY weatherscreens.draworder;";
306  db.prepare(query);
307  db.bindValue(":HOST", gCoreContext->GetHostName());
308  if (!db.exec())
309  {
310  LOG(VB_GENERAL, LOG_ERR, db.lastError().text());
311  return;
312  }
313 
314  // Fill the active screen button list.
315  while (db.next())
316  {
317  QString name = db.value(0).toString();
318  units_t units = db.value(1).toUInt();
319  QString dataitem = db.value(2).toString();
320  QString location = db.value(3).toString();
321  QString src = db.value(4).toString();
322  uint draworder = db.value(5).toUInt();
323 
324  types = screenListMap[name].m_dataTypes;
325 
326  TypeListInfo ti(dataitem, location,
328 
329  if (active_screens.find(draworder) == active_screens.end())
330  {
331  si = new ScreenListInfo(screenListMap[name]);
332  // Clear types first as we will re-insert the values from the database
333  si->m_types.clear();
334  si->m_units = units;
335 
336  MythUIButtonListItem *item =
338 
339 
340  // Only insert types meant for this screen
341  for (QStringList::Iterator type_i = types.begin();
342  type_i != types.end(); ++type_i )
343  {
344  if (*type_i == dataitem)
345  si->m_types.insert(dataitem, ti);
346  }
347 
348  item->SetData(qVariantFromValue(si));
349  active_screens.insert(draworder, si);
350  }
351  else
352  {
353  si = active_screens[draworder];
354  for (QStringList::Iterator type_i = types.begin();
355  type_i != types.end(); ++type_i )
356  {
357  if (*type_i == dataitem)
358  {
359  si->m_types.insert(dataitem, ti);
360  }
361  }
362  }
363  }
364 }
365 
367 {
368  // check if all active screens have sources/locations defined
369  QStringList notDefined;
370 
371  for (int i=0; i < m_activeList->GetCount(); i++)
372  {
374  ScreenListInfo *si = item->GetData().value<ScreenListInfo *>();
375  TypeListMap::iterator it = si->m_types.begin();
376  for (; it != si->m_types.end(); ++it)
377  {
378  if ((*it).m_src)
379  continue;
380 
381  notDefined << (*it).m_name;
382  LOG(VB_GENERAL, LOG_ERR, QString("Not defined %1").arg((*it).m_name));
383  }
384  }
385 
386  if (!notDefined.empty())
387  {
388  LOG(VB_GENERAL, LOG_ERR, "A Selected screen has data items with no "
389  "sources defined.");
390  return;
391  }
392 
395  QString query = "DELETE FROM weatherscreens WHERE hostname=:HOST";
396  db.prepare(query);
397  db.bindValue(":HOST", gCoreContext->GetHostName());
398  if (!db.exec())
399  MythDB::DBError("ScreenSetup::saveData - delete weatherscreens", db);
400 
401  query = "INSERT into weatherscreens (draworder, container, units, hostname) "
402  "VALUES (:DRAW, :CONT, :UNITS, :HOST);";
403  db.prepare(query);
404 
405  int draworder = 0;
406  for (int i=0; i < m_activeList->GetCount(); i++)
407  {
409  ScreenListInfo *si = item->GetData().value<ScreenListInfo *>();
410  db.bindValue(":DRAW", draworder);
411  db.bindValue(":CONT", si->m_name);
412  db.bindValue(":UNITS", si->m_units);
413  db.bindValue(":HOST", gCoreContext->GetHostName());
414  if (db.exec())
415  {
416  // TODO see comment in dbcheck.cpp for way to improve
417  QString query2 = "SELECT screen_id FROM weatherscreens "
418  "WHERE draworder = :DRAW AND hostname = :HOST;";
419  db2.prepare(query2);
420  db2.bindValue(":DRAW", draworder);
421  db2.bindValue(":HOST", gCoreContext->GetHostName());
422  if (!db2.exec() || !db2.next())
423  {
424  LOG(VB_GENERAL, LOG_ERR, db2.executedQuery());
425  LOG(VB_GENERAL, LOG_ERR, db2.lastError().text());
426  return;
427  }
428 
429  int screen_id = db2.value(0).toInt();
430 
431  query2 = "INSERT INTO weatherdatalayout (location, dataitem, "
432  "weatherscreens_screen_id, weathersourcesettings_sourceid) "
433  "VALUES (:LOC, :ITEM, :SCREENID, :SRCID);";
434  db2.prepare(query2);
435  TypeListMap::iterator it = si->m_types.begin();
436  for (; it != si->m_types.end(); ++it)
437  {
438  db2.bindValue(":LOC", (*it).m_location);
439  db2.bindValue(":ITEM", (*it).m_name);
440  db2.bindValue(":SCREENID", screen_id);
441  db2.bindValue(":SRCID", (*it).m_src->id);
442  if (!db2.exec())
443  {
444  LOG(VB_GENERAL, LOG_ERR, db2.executedQuery());
445  LOG(VB_GENERAL, LOG_ERR, db2.lastError().text());
446  return;
447  }
448  }
449  }
450  else
451  {
452  LOG(VB_GENERAL, LOG_ERR, db.executedQuery());
453  LOG(VB_GENERAL, LOG_ERR, db.lastError().text());
454  return;
455  }
456 
457  ++draworder;
458  }
459 
460  Close();
461 }
462 
464 {
465  if (!selected)
466  return;
467 
468  QString txt = selected->GetText();
469  if (GetFocusWidget() == m_activeList)
470  {
471  ScreenListInfo *si = selected->GetData().value<ScreenListInfo *>();
472 
473  QString label = tr("Manipulate Screen");
474 
475  MythScreenStack *popupStack =
476  GetMythMainWindow()->GetStack("popup stack");
477 
478  MythDialogBox *menuPopup = new MythDialogBox(label, popupStack,
479  "screensetupmenupopup");
480 
481  if (menuPopup->Create())
482  {
483  popupStack->AddScreen(menuPopup);
484 
485  menuPopup->SetReturnEvent(this, "options");
486 
487  menuPopup->AddButton(tr("Move Up"), qVariantFromValue(selected));
488  menuPopup->AddButton(tr("Move Down"), qVariantFromValue(selected));
489  menuPopup->AddButton(tr("Remove"), qVariantFromValue(selected));
490  menuPopup->AddButton(tr("Change Location"), qVariantFromValue(selected));
491  if (si->m_hasUnits)
492  menuPopup->AddButton(tr("Change Units"), qVariantFromValue(selected));
493  menuPopup->AddButton(tr("Cancel"), qVariantFromValue(selected));
494  }
495  else
496  {
497  delete menuPopup;
498  }
499 
500  }
501  else if (GetFocusWidget() == m_inactiveList)
502  {
503  ScreenListInfo *si = selected->GetData().value<ScreenListInfo *>();
504  QStringList type_strs;
505 
506  TypeListMap::iterator it = si->m_types.begin();
507  TypeListMap types;
508  for (; it != si->m_types.end(); ++it)
509  {
510  types.insert(it.key(), *it);
511  type_strs << it.key();
512  }
513  bool hasUnits = si->m_hasUnits;
514 
515  QList<ScriptInfo *> tmp;
516  if (m_sourceManager->findPossibleSources(type_strs, tmp))
517  {
518  if (!m_inactiveList->GetCount())
519  {
520  //m_inactiveList->SetActive(false);
521  NextPrevWidgetFocus(true);
522  }
523  if (hasUnits)
524  showUnitsPopup(selected->GetText(), si);
525  else
526  doLocationDialog(si);
527  }
528  else
529  LOG(VB_GENERAL, LOG_ERR, "Screen cannot be used, not all required "
530  "data is supplied by existing sources");
531  }
532 }
533 
535 {
536  MythScreenStack *mainStack =
538 
539  LocationDialog *locdialog = new LocationDialog(mainStack, "locationdialog",
540  this, si, m_sourceManager);
541 
542  if (locdialog->Create())
543  mainStack->AddScreen(locdialog);
544  else
545  delete locdialog;
546 }
547 
549 {
550  if (!si)
551  return;
552 
553  QString label = QString("%1 %2").arg(name).arg(tr("Change Units"));
554 
555  MythScreenStack *popupStack = GetMythMainWindow()->GetStack("popup stack");
556 
557  MythDialogBox *menuPopup = new MythDialogBox(label, popupStack,
558  "weatherunitspopup");
559 
560  if (menuPopup->Create())
561  {
562  popupStack->AddScreen(menuPopup);
563 
564  menuPopup->SetReturnEvent(this, "units");
565 
566  menuPopup->AddButton(tr("English Units"), qVariantFromValue(si));
567  menuPopup->AddButton(tr("SI Units"), qVariantFromValue(si));
568  }
569  else
570  {
571  delete menuPopup;
572  }
573 }
574 
576 {
578  if (item)
579  {
580  if (item->GetData().isValid())
581  delete item->GetData().value<ScreenListInfo *>();
582 
583  delete item;
584  }
585 
586  if (!m_activeList->GetCount())
587  {
588  NextPrevWidgetFocus(false);
589  m_activeList->SetEnabled(false);
590  }
591 }
592 
593 void ScreenSetup::customEvent(QEvent *event)
594 {
595  if (event->type() == DialogCompletionEvent::kEventType)
596  {
598 
599  QString resultid = dce->GetId();
600  int buttonnum = dce->GetResult();
601 
602  if (resultid == "options")
603  {
604  if (buttonnum > -1)
605  {
606  MythUIButtonListItem *item =
607  dce->GetData().value<MythUIButtonListItem *>();
608 
609  ScreenListInfo *si = item->GetData().value<ScreenListInfo *>();
610 
611  if (buttonnum == 0)
612  {
613  m_activeList->MoveItemUpDown(item, true);
614  }
615  else if (buttonnum == 1)
616  {
617  m_activeList->MoveItemUpDown(item, false);
618  }
619  else if (buttonnum == 2)
620  {
621  deleteScreen();
622  }
623  else if (buttonnum == 3)
624  {
625  si->m_updating = true;
626  doLocationDialog(si);
627  }
628  else if (si->m_hasUnits && buttonnum == 4)
629  {
630  si->m_updating = true;
631  showUnitsPopup(item->GetText(), si);
632  updateHelpText();
633  }
634  }
635  }
636  else if (resultid == "units")
637  {
638  if (buttonnum > -1)
639  {
640  ScreenListInfo *si = dce->GetData().value<ScreenListInfo *>();
641 
642  if (buttonnum == 0)
643  {
644  si->m_units = ENG_UNITS;
645  }
646  else if (buttonnum == 1)
647  {
648  si->m_units = SI_UNITS;
649  }
650 
651  updateHelpText();
652 
653  if (si->m_updating)
654  si->m_updating = false;
655  else
656  doLocationDialog(si);
657  }
658  }
659  else if (resultid == "location")
660  {
661  ScreenListInfo *si = dce->GetData().value<ScreenListInfo *>();
662 
663  TypeListMap::iterator it = si->m_types.begin();
664  for (; it != si->m_types.end(); ++it)
665  {
666  if ((*it).m_location.isEmpty())
667  return;
668  }
669 
670  if (si->m_updating)
671  {
672  si->m_updating = false;
674  if (item)
675  item->SetData(qVariantFromValue(si));
676  }
677  else
678  {
679  MythUIButtonListItem *item =
681  item->SetData(qVariantFromValue(si));
682  }
683 
684  if (m_activeList->GetCount())
685  m_activeList->SetEnabled(true);
686  }
687  }
688 }
689 
691 
693  : MythScreenType(parent, name)
694 {
695  m_sourceList = nullptr;
697  m_finishButton = nullptr;
698  m_sourceText = nullptr;
699 }
700 
702 {
703  for (int i=0; i < m_sourceList->GetCount(); i++)
704  {
706  if (item->GetData().isValid())
707  delete item->GetData().value<SourceListInfo *>();
708  }
709 }
710 
712 {
713  // Load the theme for this screen
714  bool foundtheme = LoadWindowFromXML("weather-ui.xml", "source-setup", this);
715  if (!foundtheme)
716  return false;
717 
718  m_sourceList = dynamic_cast<MythUIButtonList *> (GetChild("srclist"));
719  m_updateSpinbox = dynamic_cast<MythUISpinBox *> (GetChild("update_spinbox"));
720  m_retrieveSpinbox = dynamic_cast<MythUISpinBox *> (GetChild("retrieve_spinbox"));
721  m_finishButton = dynamic_cast<MythUIButton *> (GetChild("finishbutton"));
722  m_sourceText = dynamic_cast<MythUIText *> (GetChild("srcinfo"));
723 
726  {
727  LOG(VB_GENERAL, LOG_ERR, "Theme is missing required elements.");
728  return false;
729  }
730 
731  BuildFocusList();
733 
734  connect(m_sourceList, SIGNAL(itemSelected(MythUIButtonListItem *)),
736 #if 0
737  connect(m_sourceList, SIGNAL(TakingFocus()),
738  this, SLOT(sourceListItemSelected()));
739 #endif
740 
741  // 12 Hour max interval
742  m_updateSpinbox->SetRange(10, 720, 10);
743  connect(m_updateSpinbox, SIGNAL(LosingFocus()),
744  SLOT(updateSpinboxUpdate()));
745 
746  // 2 Minute retrieval timeout max
747  m_retrieveSpinbox->SetRange(10, 120, 5);
748  connect(m_retrieveSpinbox, SIGNAL(LosingFocus()),
749  SLOT(retrieveSpinboxUpdate()));
750 
751  m_finishButton->SetText(tr("Finish"));
752  connect(m_finishButton, SIGNAL(Clicked()), SLOT(saveData()));
753 
754  loadData();
755 
756  return true;
757 }
758 
760 {
762  QString query =
763  "SELECT DISTINCT sourceid, source_name, update_timeout, retrieve_timeout, "
764  "author, email, version FROM weathersourcesettings, weatherdatalayout "
765  "WHERE weathersourcesettings.sourceid = weatherdatalayout.weathersourcesettings_sourceid "
766  "AND hostname=:HOST;";
767  db.prepare(query);
768  db.bindValue(":HOST", gCoreContext->GetHostName());
769  if (!db.exec())
770  {
771  LOG(VB_GENERAL, LOG_ERR, db.lastError().text());
772  return false;
773  }
774 
775  if (!db.size())
776  {
777  return false;
778  }
779 
780  while (db.next())
781  {
782  SourceListInfo *si = new SourceListInfo;
783  si->id = db.value(0).toUInt();
784  si->name = db.value(1).toString();
785  si->update_timeout = db.value(2).toUInt() / 60;
786  si->retrieve_timeout = db.value(3).toUInt();
787  si->author = db.value(4).toString();
788  si->email = db.value(5).toString();
789  si->version = db.value(6).toString();
790 
791  new MythUIButtonListItem(m_sourceList, si->name, qVariantFromValue(si));
792  }
793 
794  return true;
795 }
796 
798 {
800 
801  if (curritem)
802  {
803  SourceListInfo *si = curritem->GetData().value<SourceListInfo *>();
806  }
807 
809  QString query = "UPDATE weathersourcesettings "
810  "SET update_timeout = :UPDATE, retrieve_timeout = :RETRIEVE "
811  "WHERE sourceid = :ID;";
812  db.prepare(query);
813 
814  for (int i=0; i < m_sourceList->GetCount(); i++)
815  {
817  SourceListInfo *si = item->GetData().value<SourceListInfo *>();
818  db.bindValue(":ID", si->id);
819  db.bindValue(":UPDATE", si->update_timeout * 60);
820  db.bindValue(":RETRIEVE", si->retrieve_timeout);
821  if (!db.exec())
822  {
823  LOG(VB_GENERAL, LOG_ERR, db.lastError().text());
824  return;
825  }
826  }
827 
828  Close();
829 }
830 
832 {
834  {
837  }
838 }
839 
841 {
843  {
846  }
847 }
848 
850 {
851  if (!item)
852  item = m_sourceList->GetItemCurrent();
853 
854  if (!item)
855  return;
856 
857  SourceListInfo *si = item->GetData().value<SourceListInfo *>();
858  if (!si)
859  return;
860 
863  QString txt = tr("Author: ");
864  txt += si->author;
865  txt += "\n" + tr("Email: ") + si->email;
866  txt += "\n" + tr("Version: ") + si->version;
867  m_sourceText->SetText(txt);
868 }
869 
871 
873  MythScreenType *retScreen, ScreenListInfo *si,
874  SourceManager *srcman)
875  : MythScreenType(parent, name),
876  m_screenListInfo(new ScreenListInfo(*si)), m_sourceManager(srcman),
877  m_retScreen(retScreen), m_locationList(nullptr),
878  m_locationEdit(nullptr),m_searchButton(nullptr),
879  m_resultsText(nullptr), m_sourceText(nullptr)
880 {
881  TypeListMap::iterator it = si->m_types.begin();
882  for (; it != si->m_types.end(); ++it)
883  m_types << (*it).m_name;
884 }
885 
887 {
888  if(m_locationList)
889  clearResults();
890 
891  delete m_screenListInfo;
892 }
893 
895 {
896  // Load the theme for this screen
897  bool foundtheme = LoadWindowFromXML("weather-ui.xml", "setup-location", this);
898  if (!foundtheme)
899  return false;
900 
901  m_sourceText = dynamic_cast<MythUIText *> (GetChild("source"));
902  m_resultsText = dynamic_cast<MythUIText *> (GetChild("numresults"));
903  m_locationEdit = dynamic_cast<MythUITextEdit *> (GetChild("loc-edit"));
904  m_locationList = dynamic_cast<MythUIButtonList *> (GetChild("results"));
905  m_searchButton = dynamic_cast<MythUIButton *> (GetChild("searchbtn"));
906 
907 
909  || !m_searchButton)
910  {
911  LOG(VB_GENERAL, LOG_ERR, "Theme is missing required elements.");
912  return false;
913  }
914 
915  BuildFocusList();
917 
918  connect(m_searchButton, SIGNAL(Clicked()), this, SLOT(doSearch()));
919  m_searchButton->SetText(tr("Search"));
921  this, SLOT(itemSelected(MythUIButtonListItem *)));
922  connect(m_locationList, SIGNAL(itemClicked(MythUIButtonListItem *)),
923  this, SLOT(itemClicked(MythUIButtonListItem *)));
924 
925  return true;
926 }
927 
929 {
930  QString busymessage = tr("Searching...");
931 
932  MythScreenStack *popupStack = GetMythMainWindow()->GetStack("popup stack");
933 
934  MythUIBusyDialog *busyPopup = new MythUIBusyDialog(busymessage, popupStack,
935  "mythweatherbusydialog");
936 
937  if (busyPopup->Create())
938  {
939  popupStack->AddScreen(busyPopup, false);
940  }
941  else
942  {
943  delete busyPopup;
944  busyPopup = nullptr;
945  }
946 
947 
948  QMap<ScriptInfo *, QStringList> result_cache;
949  int numresults = 0;
950  clearResults();
951 
952  QString searchingresults = tr("Searching... Results: %1");
953 
954  m_resultsText->SetText(searchingresults.arg(0));
955  qApp->processEvents();
956 
957  QList<ScriptInfo *> sources;
958  // if a screen makes it this far, theres at least one source for it
960  QString search = m_locationEdit->GetText();
961  ScriptInfo *si;
962  for (int x = 0; x < sources.size(); x++)
963  {
964  si = sources.at(x);
965  if (!result_cache.contains(si))
966  {
967  QStringList results = m_sourceManager->getLocationList(si, search);
968  result_cache[si] = results;
969  numresults += results.size();
970  m_resultsText->SetText(searchingresults.arg(numresults));
971  qApp->processEvents();
972  }
973  }
974 
975  QMap<ScriptInfo *, QStringList>::iterator it;
976  for (it = result_cache.begin(); it != result_cache.end(); ++it)
977  {
978  si = it.key();
979  QStringList results = it.value();
980  QString name = si->name;
981  QStringList::iterator rit;
982  for (rit = results.begin(); rit != results.end(); ++rit)
983  {
984  QStringList tmp = (*rit).split("::");
985  if (tmp.size() < 2)
986  {
987  LOG(VB_GENERAL, LOG_WARNING,
988  QString("Invalid line in Location Search reponse "
989  "from %1: %2")
990  .arg(name).arg(*rit));
991  continue;
992  }
993  QString resultstring = QString("%1 (%2)").arg(tmp[1]).arg(name);
994  MythUIButtonListItem *item =
995  new MythUIButtonListItem(m_locationList, resultstring);
996  ResultListInfo *ri = new ResultListInfo;
997  ri->idstr = tmp[0];
998  ri->src = si;
999  item->SetData(qVariantFromValue(ri));
1000  qApp->processEvents();
1001  }
1002  }
1003 
1004  if (busyPopup)
1005  {
1006  busyPopup->Close();
1007  busyPopup = nullptr;
1008  }
1009 
1010  m_resultsText->SetText(tr("Search Complete. Results: %1").arg(numresults));
1011  if (numresults)
1013 }
1014 
1016 {
1017  for (int i=0; i < m_locationList->GetCount(); i++)
1018  {
1020  if (item->GetData().isValid())
1021  delete item->GetData().value<ResultListInfo *>();
1022  }
1023 
1024  m_locationList->Reset();
1025 }
1026 
1028 {
1029  ResultListInfo *ri = item->GetData().value<ResultListInfo *>();
1030  if (ri)
1031  m_sourceText->SetText(tr("Source: %1").arg(ri->src->name));
1032 }
1033 
1035 {
1036  ResultListInfo *ri = item->GetData().value<ResultListInfo *>();
1037 
1038  if (ri)
1039  {
1040  TypeListMap::iterator it = m_screenListInfo->m_types.begin();
1041  for (; it != m_screenListInfo->m_types.end(); ++it)
1042  {
1043  (*it).m_location = ri->idstr;
1044  (*it).m_src = ri->src;
1045  }
1046  }
1047 
1048  DialogCompletionEvent *dce =
1049  new DialogCompletionEvent("location", 0, "",
1050  qVariantFromValue(new ScreenListInfo(*m_screenListInfo)));
1051  QApplication::postEvent(m_retScreen, dce);
1052 
1053  Close();
1054 }
QMultiHash< QString, TypeListInfo > TypeListMap
Definition: weatherUtils.h:44
bool next(void)
Wrap QSqlQuery::next() so we can display the query results.
Definition: mythdbcon.cpp:782
MythUIButtonList * m_sourceList
Definition: weatherSetup.h:120
void doListSelect(MythUIButtonListItem *selected)
MythUIButton * m_searchButton
Definition: weatherSetup.h:165
MythUIButton * m_finishButton
Definition: weatherSetup.h:121
QStringList m_sources
Definition: weatherUtils.h:70
TypeListMap m_types
Definition: weatherUtils.h:67
#define ENG_UNITS
Definition: weatherUtils.h:16
MythUISpinBox * m_timeoutSpinbox
Definition: weatherSetup.h:59
void bindValue(const QString &placeholder, const QVariant &val)
Add a single binding.
Definition: mythdbcon.cpp:863
QString author
Definition: weatherSetup.h:27
MythUIStateType::StateType GetCheckState() const
void saveData(void)
SourceManager * m_sourceManager
Definition: weatherSetup.h:159
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 showUnitsPopup(const QString &name, ScreenListInfo *si)
void LosingFocus()
void SetEnabled(bool enable)
MythUIButton * m_finishButton
Definition: weatherSetup.h:96
QString name
Definition: weatherSource.h:21
All purpose text widget, displays a text string.
Definition: mythuitext.h:28
ScreenListInfo * m_screenListInfo
Definition: weatherSetup.h:158
void SetData(QVariant data)
void SaveSetting(const QString &key, int newValue)
SourceManager * m_sourceManager
Definition: weatherSetup.h:91
void saveData(void)
QSqlQuery wrapper that fetches a DB connection from the connection pool.
Definition: mythdbcon.h:125
Basic menu dialog, message and a list of options.
void updateHelpText(void)
uint retrieve_timeout
Definition: weatherSetup.h:31
int size(void) const
Definition: mythdbcon.h:203
virtual void SetText(const QString &text)
Definition: mythuitext.cpp:136
MythScreenStack * GetStack(const QString &stackname)
unsigned int uint
Definition: compat.h:140
MythCoreContext * gCoreContext
This global variable contains the MythCoreContext instance for the app.
void SetValue(int val) override
Definition: mythuispinbox.h:26
MythScreenStack * GetMainStack()
void doSearch(void)
MythUIButtonListItem * GetItemAt(int pos) const
MythUICheckBox * m_backgroundCheckbox
Definition: weatherSetup.h:58
MythUISpinBox * m_retrieveSpinbox
Definition: weatherSetup.h:119
QMap< QString, ScreenListInfo > ScreenListMap
Definition: weatherUtils.h:79
QString version
Definition: weatherSetup.h:29
static guint32 * tmp
Definition: goom_core.c:35
The base class on which all widgets and screens are based.
Definition: mythuitype.h:63
void BuildFocusList(void)
MythScreenType * m_retScreen
Definition: weatherSetup.h:161
static Type kEventType
Definition: mythdialogbox.h:50
bool Create(void) override
int GetIntValue(void) const override
Definition: mythuispinbox.h:33
MythUIButton * m_finishButton
Definition: weatherSetup.h:62
QVariant value(int i) const
Definition: mythdbcon.h:198
virtual void Close()
void AddButton(const QString &title, QVariant data=0, bool newMenu=false, bool setCurrent=false)
void SetRange(int low, int high, int step, uint pageMultiple=5)
Set the lower and upper bounds of the spinbox, the interval and page amount.
bool Create(void) override
void itemClicked(MythUIButtonListItem *item)
virtual void AddScreen(MythScreenType *screen, bool allowFade=true)
MythUIText * m_sourceText
Definition: weatherSetup.h:167
MythUISpinBox * m_updateSpinbox
Definition: weatherSetup.h:118
void loadData(void)
void TakingFocus()
QString m_name
Definition: weatherUtils.h:65
bool Create(void) override
QSqlError lastError(void) const
Definition: mythdbcon.h:202
ScreenSetup(MythScreenStack *parent, const QString &name, SourceManager *srcman)
void itemSelected(MythUIButtonListItem *item)
virtual bool NextPrevWidgetFocus(bool up_or_down)
bool loadData(void)
void updateSpinboxUpdate(void)
void doLocationDialog(ScreenListInfo *si)
MythUITextEdit * m_locationEdit
Definition: weatherSetup.h:164
bool findPossibleSources(QStringList types, QList< ScriptInfo * > &sources)
MythUIText * m_resultsText
Definition: weatherSetup.h:166
static MSqlQueryInfo InitCon(ConnectionReuse=kNormalConnection)
Only use this in combination with MSqlQuery constructor.
Definition: mythdbcon.cpp:535
const char * name
Definition: ParseText.cpp:328
bool m_createdSrcMan
Definition: weatherSetup.h:92
ScriptInfo * src
Definition: weatherSetup.h:128
void customEvent(QEvent *) override
bool Create(void) override
SourceSetup(MythScreenStack *parent, const QString &name)
MythUIButtonList * m_locationList
Definition: weatherSetup.h:163
bool Create(void) override
LocationDialog(MythScreenStack *parent, const QString &name, MythScreenType *retScreen, ScreenListInfo *si, SourceManager *srcman)
static bool LoadWindowFromXML(const QString &xmlfile, const QString &windowname, MythUIType *parent)
MythUIType * GetFocusWidget(void) const
bool MoveItemUpDown(MythUIButtonListItem *item, bool up)
void Reset() override
Reset the widget to it's original state, should not reset changes made by the theme.
MythMainWindow * GetMythMainWindow(void)
QString GetText(const QString &name="") const
units_t m_units
Definition: weatherUtils.h:71
QStringList m_dataTypes
Definition: weatherUtils.h:68
int GetNumSetting(const QString &key, int defaultval=0)
unsigned char units_t
Definition: weatherUtils.h:20
void sourceListItemSelected(MythUIButtonListItem *item=nullptr)
MythUIText * m_helpText
Definition: weatherSetup.h:93
MythUIButtonList * m_inactiveList
Definition: weatherSetup.h:95
bool prepare(const QString &query)
QSqlQuery::prepare() is not thread safe in Qt <= 3.3.2.
Definition: mythdbcon.cpp:807
bool keyPressEvent(QKeyEvent *) override
Key event handler.
#define LOG(_MASK_, _LEVEL_, _STRING_)
Definition: mythlogging.h:41
void deleteScreen(void)
void SetReturnEvent(QObject *retobject, const QString &resultid)
ScreenListMap loadScreens()
void retrieveSpinboxUpdate(void)
ScriptInfo * getSourceByName(const QString &name)
void SetCheckState(MythUIStateType::StateType state)
bool keyPressEvent(QKeyEvent *) override
Key event handler.
QString executedQuery(void) const
Definition: mythdbcon.h:199
bool SetFocusWidget(MythUIType *widget=nullptr)
QString m_location
Definition: weatherUtils.h:41
bool exec(void)
Wrap QSqlQuery::exec() so we can display SQL.
Definition: mythdbcon.cpp:603
QString m_title
Definition: weatherUtils.h:66
QStringList m_types
Definition: weatherSetup.h:157
MythUIText * m_sourceText
Definition: weatherSetup.h:122
static void DBError(const QString &where, const MSqlQuery &query)
Definition: mythdb.cpp:179
Screen in which all other widgets are contained and rendered.
MythUIButtonList * m_activeList
Definition: weatherSetup.h:94
void saveData(void)
#define SI_UNITS
Definition: weatherUtils.h:15
QString GetHostName(void)
void SetText(const QString &msg)
Event dispatched from MythUI modal dialogs to a listening class containing a result of some form.
Definition: mythdialogbox.h:37
MythUIType * GetChild(const QString &name) const
Get a named child of this UIType.
Definition: mythuitype.cpp:132
void loadData(void)
QStringList getLocationList(ScriptInfo *si, const QString &str)
QString GetText(void) const
MythUIButtonListItem * GetItemCurrent() const
ScriptInfo * m_src
Definition: weatherUtils.h:42
bool Create(void) override