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"));
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 
75 ScreenSetup::ScreenSetup(MythScreenStack *parent, const QString &name,
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 
148 
150 
151  m_finishButton->SetText(tr("Finish"));
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  auto *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"), sources.join(", "));
211  }
212  else if (list == m_activeList)
213  {
215  if (!item)
216  return;
217 
218  auto *si = item->GetData().value<ScreenListInfo *>();
219  if (!si)
220  return;
221 
222  text += si->m_title + "\n";
223  if (si->m_hasUnits)
224  {
225  text += tr("Units: ");
226  text += (ENG_UNITS == si->m_units) ?
227  tr("English Units") : tr("SI Units");
228  text += " ";
229  }
230  if (!si->m_multiLoc && !si->m_types.empty())
231  {
232  TypeListInfo ti = *si->m_types.begin();
233  text += tr("Location: ");
234  text += (ti.m_location.isEmpty()) ? tr("Not Defined") : ti.m_location;
235  text += "\n";
236  text += tr("Source: " );
237  text += (ti.m_src) ? ti.m_src->name : tr("Not Defined");
238  text += "\n";
239  }
240  text += "\n" + tr("Press SELECT to ");
241  if (!si->m_multiLoc)
242  text += tr("change location; ");
243  if (si->m_hasUnits)
244  text += tr("change units; ");
245  text += tr("move screen up or down; or remove screen.");
246  }
247 
248  m_helpText->SetText(text);
249 }
250 
252 {
253  QStringList types;
254 
255  ScreenListMap screenListMap = loadScreens();
256 
257  // Fill the inactive screen button list.
258  ScreenListMap::const_iterator i = screenListMap.constBegin();
259  while (i != screenListMap.constEnd())
260  {
261  ScreenListInfo *si = &screenListMap[i.key()];
262  types = si->m_dataTypes;
263  si->m_units = ENG_UNITS;
264 
265  QStringList type_strs;
266  for (const QString& type : qAsConst(types))
267  {
268  TypeListInfo ti(type);
269  si->m_types.insert(type, ti);
270  type_strs << type;
271  }
272 
273  QList<ScriptInfo *> scriptList;
274  // Only add a screen to the list if we have a source
275  // available to satisfy the requirements.
276  if (m_sourceManager->findPossibleSources(type_strs, scriptList))
277  {
278  for (const auto *script : qAsConst(scriptList))
279  si->m_sources.append(script->name);
280  auto *item = new MythUIButtonListItem(m_inactiveList, si->m_title);
281  item->SetData(QVariant::fromValue(new ScreenListInfo(*si)));
282  }
283 
284  ++i;
285  }
286 
287  QMap<long, ScreenListInfo*> active_screens;
288 
290  QString query = "SELECT weatherscreens.container, weatherscreens.units, "
291  "weatherdatalayout.dataitem, weatherdatalayout.location, "
292  "weathersourcesettings.source_name, weatherscreens.draworder "
293  "FROM weatherscreens, weatherdatalayout, weathersourcesettings "
294  "WHERE weatherscreens.hostname = :HOST "
295  "AND weatherscreens.screen_id = weatherdatalayout.weatherscreens_screen_id "
296  "AND weathersourcesettings.sourceid = weatherdatalayout.weathersourcesettings_sourceid "
297  "ORDER BY weatherscreens.draworder;";
298  db.prepare(query);
299  db.bindValue(":HOST", gCoreContext->GetHostName());
300  if (!db.exec())
301  {
302  LOG(VB_GENERAL, LOG_ERR, db.lastError().text());
303  return;
304  }
305 
306  // Fill the active screen button list.
307  while (db.next())
308  {
309  QString name = db.value(0).toString();
310  units_t units = db.value(1).toUInt();
311  QString dataitem = db.value(2).toString();
312  QString location = db.value(3).toString();
313  QString src = db.value(4).toString();
314  uint draworder = db.value(5).toUInt();
315 
316  types = screenListMap[name].m_dataTypes;
317 
318  TypeListInfo ti(dataitem, location,
320 
321  if (active_screens.find(draworder) == active_screens.end())
322  {
323  auto *si = new ScreenListInfo(screenListMap[name]);
324  // Clear types first as we will re-insert the values from the database
325  si->m_types.clear();
326  si->m_units = units;
327 
328  auto *item = new MythUIButtonListItem(m_activeList, si->m_title);
329 
330  // Only insert types meant for this screen
331  for (const auto & type : qAsConst(types))
332  {
333  if (type == dataitem)
334  si->m_types.insert(dataitem, ti);
335  }
336 
337  item->SetData(QVariant::fromValue(si));
338  active_screens.insert(draworder, si);
339  }
340  else
341  {
342  ScreenListInfo *si = active_screens[draworder];
343  for (const auto & type : qAsConst(types))
344  {
345  if (type == dataitem)
346  {
347  si->m_types.insert(dataitem, ti);
348  }
349  }
350  }
351  }
352 }
353 
355 {
356  // check if all active screens have sources/locations defined
357  QStringList notDefined;
358 
359  for (int i=0; i < m_activeList->GetCount(); i++)
360  {
362  auto *si = item->GetData().value<ScreenListInfo *>();
363  for (const auto & type : qAsConst(si->m_types))
364  {
365  if (type.m_src)
366  continue;
367 
368  notDefined << type.m_name;
369  LOG(VB_GENERAL, LOG_ERR, QString("Not defined %1").arg(type.m_name));
370  }
371  }
372 
373  if (!notDefined.empty())
374  {
375  LOG(VB_GENERAL, LOG_ERR, "A Selected screen has data items with no "
376  "sources defined.");
377  return;
378  }
379 
382  QString query = "DELETE FROM weatherscreens WHERE hostname=:HOST";
383  db.prepare(query);
384  db.bindValue(":HOST", gCoreContext->GetHostName());
385  if (!db.exec())
386  MythDB::DBError("ScreenSetup::saveData - delete weatherscreens", db);
387 
388  query = "INSERT into weatherscreens (draworder, container, units, hostname) "
389  "VALUES (:DRAW, :CONT, :UNITS, :HOST);";
390  db.prepare(query);
391 
392  int draworder = 0;
393  for (int i=0; i < m_activeList->GetCount(); i++)
394  {
396  auto *si = item->GetData().value<ScreenListInfo *>();
397  db.bindValue(":DRAW", draworder);
398  db.bindValue(":CONT", si->m_name);
399  db.bindValue(":UNITS", si->m_units);
400  db.bindValue(":HOST", gCoreContext->GetHostName());
401  if (db.exec())
402  {
403  // TODO see comment in dbcheck.cpp for way to improve
404  QString query2 = "SELECT screen_id FROM weatherscreens "
405  "WHERE draworder = :DRAW AND hostname = :HOST;";
406  db2.prepare(query2);
407  db2.bindValue(":DRAW", draworder);
408  db2.bindValue(":HOST", gCoreContext->GetHostName());
409  if (!db2.exec() || !db2.next())
410  {
411  LOG(VB_GENERAL, LOG_ERR, db2.executedQuery());
412  LOG(VB_GENERAL, LOG_ERR, db2.lastError().text());
413  return;
414  }
415 
416  int screen_id = db2.value(0).toInt();
417 
418  query2 = "INSERT INTO weatherdatalayout (location, dataitem, "
419  "weatherscreens_screen_id, weathersourcesettings_sourceid) "
420  "VALUES (:LOC, :ITEM, :SCREENID, :SRCID);";
421  db2.prepare(query2);
422  for (const auto & type : qAsConst(si->m_types))
423  {
424  db2.bindValue(":LOC", type.m_location);
425  db2.bindValue(":ITEM", type.m_name);
426  db2.bindValue(":SCREENID", screen_id);
427  db2.bindValue(":SRCID", type.m_src->id);
428  if (!db2.exec())
429  {
430  LOG(VB_GENERAL, LOG_ERR, db2.executedQuery());
431  LOG(VB_GENERAL, LOG_ERR, db2.lastError().text());
432  return;
433  }
434  }
435  }
436  else
437  {
438  LOG(VB_GENERAL, LOG_ERR, db.executedQuery());
439  LOG(VB_GENERAL, LOG_ERR, db.lastError().text());
440  return;
441  }
442 
443  ++draworder;
444  }
445 
446  Close();
447 }
448 
450 {
451  if (!selected)
452  return;
453 
454  if (GetFocusWidget() == m_activeList)
455  {
456  auto *si = selected->GetData().value<ScreenListInfo *>();
457 
458  QString label = tr("Manipulate Screen");
459 
460  MythScreenStack *popupStack =
461  GetMythMainWindow()->GetStack("popup stack");
462 
463  auto *menuPopup = new MythDialogBox(label, popupStack,
464  "screensetupmenupopup");
465 
466  if (menuPopup->Create())
467  {
468  popupStack->AddScreen(menuPopup);
469 
470  menuPopup->SetReturnEvent(this, "options");
471 
472  menuPopup->AddButtonV(tr("Move Up"), QVariant::fromValue(selected));
473  menuPopup->AddButtonV(tr("Move Down"), QVariant::fromValue(selected));
474  menuPopup->AddButtonV(tr("Remove"), QVariant::fromValue(selected));
475  menuPopup->AddButtonV(tr("Change Location"), QVariant::fromValue(selected));
476  if (si->m_hasUnits)
477  menuPopup->AddButtonV(tr("Change Units"), QVariant::fromValue(selected));
478  menuPopup->AddButtonV(tr("Cancel"), QVariant::fromValue(selected));
479  }
480  else
481  {
482  delete menuPopup;
483  }
484 
485  }
486  else if (GetFocusWidget() == m_inactiveList)
487  {
488  auto *si = selected->GetData().value<ScreenListInfo *>();
489  QStringList type_strs;
490 
492  // NOLINTNEXTLINE(modernize-loop-convert)
493  for (auto it = si->m_types.begin(); it != si->m_types.end(); ++it)
494  {
495  types.insert(it.key(), *it);
496  type_strs << it.key();
497  }
498  bool hasUnits = si->m_hasUnits;
499 
500  QList<ScriptInfo *> tmp;
501  if (m_sourceManager->findPossibleSources(type_strs, tmp))
502  {
503  if (!m_inactiveList->GetCount())
504  {
505  //m_inactiveList->SetActive(false);
506  NextPrevWidgetFocus(true);
507  }
508  if (hasUnits)
509  showUnitsPopup(selected->GetText(), si);
510  else
511  doLocationDialog(si);
512  }
513  else
514  LOG(VB_GENERAL, LOG_ERR, "Screen cannot be used, not all required "
515  "data is supplied by existing sources");
516  }
517 }
518 
520 {
521  MythScreenStack *mainStack =
523 
524  auto *locdialog = new LocationDialog(mainStack, "locationdialog",
525  this, si, m_sourceManager);
526 
527  if (locdialog->Create())
528  mainStack->AddScreen(locdialog);
529  else
530  delete locdialog;
531 }
532 
533 void ScreenSetup::showUnitsPopup(const QString &name, ScreenListInfo *si)
534 {
535  if (!si)
536  return;
537 
538  QString label = QString("%1 %2").arg(name, tr("Change Units"));
539 
540  MythScreenStack *popupStack = GetMythMainWindow()->GetStack("popup stack");
541 
542  auto *menuPopup = new MythDialogBox(label, popupStack, "weatherunitspopup");
543 
544  if (menuPopup->Create())
545  {
546  popupStack->AddScreen(menuPopup);
547 
548  menuPopup->SetReturnEvent(this, "units");
549 
550  menuPopup->AddButtonV(tr("English Units"), QVariant::fromValue(si));
551  menuPopup->AddButtonV(tr("SI Units"), QVariant::fromValue(si));
552  }
553  else
554  {
555  delete menuPopup;
556  }
557 }
558 
560 {
562  if (item)
563  {
564  if (item->GetData().isValid())
565  delete item->GetData().value<ScreenListInfo *>();
566 
567  delete item;
568  }
569 
570  if (!m_activeList->GetCount())
571  {
572  NextPrevWidgetFocus(false);
573  m_activeList->SetEnabled(false);
574  }
575 }
576 
577 void ScreenSetup::customEvent(QEvent *event)
578 {
579  if (event->type() == DialogCompletionEvent::kEventType)
580  {
581  auto *dce = dynamic_cast<DialogCompletionEvent*>(event);
582  if (dce == nullptr)
583  return;
584 
585  QString resultid = dce->GetId();
586  int buttonnum = dce->GetResult();
587 
588  if (resultid == "options")
589  {
590  if (buttonnum > -1)
591  {
592  auto *item = dce->GetData().value<MythUIButtonListItem *>();
593  auto *si = item->GetData().value<ScreenListInfo *>();
594 
595  if (buttonnum == 0)
596  {
597  m_activeList->MoveItemUpDown(item, true);
598  }
599  else if (buttonnum == 1)
600  {
601  m_activeList->MoveItemUpDown(item, false);
602  }
603  else if (buttonnum == 2)
604  {
605  deleteScreen();
606  }
607  else if (buttonnum == 3)
608  {
609  si->m_updating = true;
610  doLocationDialog(si);
611  }
612  else if (si->m_hasUnits && buttonnum == 4)
613  {
614  si->m_updating = true;
615  showUnitsPopup(item->GetText(), si);
616  updateHelpText();
617  }
618  }
619  }
620  else if (resultid == "units")
621  {
622  if (buttonnum > -1)
623  {
624  auto *si = dce->GetData().value<ScreenListInfo *>();
625 
626  if (buttonnum == 0)
627  {
628  si->m_units = ENG_UNITS;
629  }
630  else if (buttonnum == 1)
631  {
632  si->m_units = SI_UNITS;
633  }
634 
635  updateHelpText();
636 
637  if (si->m_updating)
638  si->m_updating = false;
639  else
640  doLocationDialog(si);
641  }
642  }
643  else if (resultid == "location")
644  {
645  auto *si = dce->GetData().value<ScreenListInfo *>();
646 
647  auto emptyloc = [](const auto & type)
648  { return type.m_location.isEmpty(); };
649  if (std::any_of(si->m_types.cbegin(), si->m_types.cend(), emptyloc))
650  return;
651 
652  if (si->m_updating)
653  {
654  si->m_updating = false;
656  if (item)
657  item->SetData(QVariant::fromValue(si));
658  }
659  else
660  {
661  auto *item = new MythUIButtonListItem(m_activeList, si->m_title);
662  item->SetData(QVariant::fromValue(si));
663  }
664 
665  if (m_activeList->GetCount())
666  m_activeList->SetEnabled(true);
667  }
668  }
669 }
670 
672 
673 SourceSetup::SourceSetup(MythScreenStack *parent, const QString &name)
674  : MythScreenType(parent, name)
675 {
676  m_sourceList = nullptr;
678  m_finishButton = nullptr;
679  m_sourceText = nullptr;
680 }
681 
683 {
684  for (int i=0; i < m_sourceList->GetCount(); i++)
685  {
687  if (item->GetData().isValid())
688  delete item->GetData().value<SourceListInfo *>();
689  }
690 }
691 
693 {
694  // Load the theme for this screen
695  bool foundtheme = LoadWindowFromXML("weather-ui.xml", "source-setup", this);
696  if (!foundtheme)
697  return false;
698 
699  m_sourceList = dynamic_cast<MythUIButtonList *> (GetChild("srclist"));
700  m_updateSpinbox = dynamic_cast<MythUISpinBox *> (GetChild("update_spinbox"));
701  m_retrieveSpinbox = dynamic_cast<MythUISpinBox *> (GetChild("retrieve_spinbox"));
702  m_finishButton = dynamic_cast<MythUIButton *> (GetChild("finishbutton"));
703  m_sourceText = dynamic_cast<MythUIText *> (GetChild("srcinfo"));
704 
707  {
708  LOG(VB_GENERAL, LOG_ERR, "Theme is missing required elements.");
709  return false;
710  }
711 
712  BuildFocusList();
714 
716  this, qOverload<MythUIButtonListItem *>(&SourceSetup::sourceListItemSelected));
717 #if 0
719  this, qOverload<>(&SourceSetup::sourceListItemSelected));
720 #endif
721 
722  // 12 Hour max interval
723  m_updateSpinbox->SetRange(10, 720, 10);
726 
727  // 2 Minute retrieval timeout max
728  m_retrieveSpinbox->SetRange(10, 120, 5);
731 
732  m_finishButton->SetText(tr("Finish"));
734 
735  loadData();
736 
737  return true;
738 }
739 
741 {
743  QString query =
744  "SELECT DISTINCT sourceid, source_name, update_timeout, retrieve_timeout, "
745  "author, email, version FROM weathersourcesettings, weatherdatalayout "
746  "WHERE weathersourcesettings.sourceid = weatherdatalayout.weathersourcesettings_sourceid "
747  "AND hostname=:HOST;";
748  db.prepare(query);
749  db.bindValue(":HOST", gCoreContext->GetHostName());
750  if (!db.exec())
751  {
752  LOG(VB_GENERAL, LOG_ERR, db.lastError().text());
753  return false;
754  }
755 
756  if (!db.size())
757  {
758  return false;
759  }
760 
761  while (db.next())
762  {
763  auto *si = new SourceListInfo;
764  si->id = db.value(0).toUInt();
765  si->name = db.value(1).toString();
766  si->update_timeout = std::chrono::minutes(db.value(2).toUInt() / 60);
767  si->retrieve_timeout = std::chrono::seconds(db.value(3).toUInt());
768  si->author = db.value(4).toString();
769  si->email = db.value(5).toString();
770  si->version = db.value(6).toString();
771 
772  new MythUIButtonListItem(m_sourceList, si->name, QVariant::fromValue(si));
773  }
774 
775  return true;
776 }
777 
779 {
781 
782  if (curritem)
783  {
784  auto *si = curritem->GetData().value<SourceListInfo *>();
785  si->update_timeout = m_updateSpinbox->GetDuration<std::chrono::minutes>();
786  si->retrieve_timeout = m_retrieveSpinbox->GetDuration<std::chrono::seconds>();
787  }
788 
790  QString query = "UPDATE weathersourcesettings "
791  "SET update_timeout = :UPDATE, retrieve_timeout = :RETRIEVE "
792  "WHERE sourceid = :ID;";
793  db.prepare(query);
794 
795  for (int i=0; i < m_sourceList->GetCount(); i++)
796  {
798  auto *si = item->GetData().value<SourceListInfo *>();
799  db.bindValue(":ID", si->id);
800  db.bindValue(":UPDATE", (int)duration_cast<std::chrono::seconds>(si->update_timeout).count());
801  db.bindValue(":RETRIEVE", (int)si->retrieve_timeout.count());
802  if (!db.exec())
803  {
804  LOG(VB_GENERAL, LOG_ERR, db.lastError().text());
805  return;
806  }
807  }
808 
809  Close();
810 }
811 
813 {
815  {
816  auto *si = m_sourceList->GetItemCurrent()->GetData().value<SourceListInfo *>();
817  si->update_timeout = m_updateSpinbox->GetDuration<std::chrono::minutes>();
818  }
819 }
820 
822 {
824  {
825  auto *si = m_sourceList->GetItemCurrent()->GetData().value<SourceListInfo *>();
826  si->retrieve_timeout = m_retrieveSpinbox->GetDuration<std::chrono::seconds>();
827  }
828 }
829 
831 {
832  if (!item)
833  item = m_sourceList->GetItemCurrent();
834 
835  if (!item)
836  return;
837 
838  auto *si = item->GetData().value<SourceListInfo *>();
839  if (!si)
840  return;
841 
842  m_updateSpinbox->SetDuration<std::chrono::minutes>(si->update_timeout);
843  m_retrieveSpinbox->SetDuration<std::chrono::seconds>(si->retrieve_timeout);
844  QString txt = tr("Author: ");
845  txt += si->author;
846  txt += "\n" + tr("Email: ") + si->email;
847  txt += "\n" + tr("Version: ") + si->version;
848  m_sourceText->SetText(txt);
849 }
850 
852 
853 LocationDialog::LocationDialog(MythScreenStack *parent, const QString &name,
854  MythScreenType *retScreen, ScreenListInfo *si,
855  SourceManager *srcman)
856  : MythScreenType(parent, name),
857  m_screenListInfo(new ScreenListInfo(*si)), m_sourceManager(srcman),
858  m_retScreen(retScreen), m_locationList(nullptr),
859  m_locationEdit(nullptr),m_searchButton(nullptr),
860  m_resultsText(nullptr), m_sourceText(nullptr)
861 {
862  for (const auto & type : qAsConst(si->m_types))
863  m_types << type.m_name;
864 }
865 
867 {
868  if(m_locationList)
869  clearResults();
870 
871  delete m_screenListInfo;
872 }
873 
875 {
876  // Load the theme for this screen
877  bool foundtheme = LoadWindowFromXML("weather-ui.xml", "setup-location", this);
878  if (!foundtheme)
879  return false;
880 
881  m_sourceText = dynamic_cast<MythUIText *> (GetChild("source"));
882  m_resultsText = dynamic_cast<MythUIText *> (GetChild("numresults"));
883  m_locationEdit = dynamic_cast<MythUITextEdit *> (GetChild("loc-edit"));
884  m_locationList = dynamic_cast<MythUIButtonList *> (GetChild("results"));
885  m_searchButton = dynamic_cast<MythUIButton *> (GetChild("searchbtn"));
886 
887 
889  || !m_searchButton)
890  {
891  LOG(VB_GENERAL, LOG_ERR, "Theme is missing required elements.");
892  return false;
893  }
894 
895  BuildFocusList();
897 
899  m_searchButton->SetText(tr("Search"));
904 
905  return true;
906 }
907 
909 {
910  QString busymessage = tr("Searching...");
911 
912  MythScreenStack *popupStack = GetMythMainWindow()->GetStack("popup stack");
913 
914  auto *busyPopup = new MythUIBusyDialog(busymessage, popupStack,
915  "mythweatherbusydialog");
916 
917  if (busyPopup->Create())
918  {
919  popupStack->AddScreen(busyPopup, false);
920  }
921  else
922  {
923  delete busyPopup;
924  busyPopup = nullptr;
925  }
926 
927 
928  QHash<ScriptInfo *, QStringList> result_cache;
929  int numresults = 0;
930  clearResults();
931 
932  QString searchingresults = tr("Searching... Results: %1");
933 
934  m_resultsText->SetText(searchingresults.arg(0));
935  QCoreApplication::processEvents();
936 
937  QList<ScriptInfo *> sources;
938  // if a screen makes it this far, theres at least one source for it
940  QString search = m_locationEdit->GetText();
941  for (auto *si : qAsConst(sources))
942  {
943  if (!result_cache.contains(si))
944  {
945  QStringList results = m_sourceManager->getLocationList(si, search);
946  result_cache[si] = results;
947  numresults += results.size();
948  m_resultsText->SetText(searchingresults.arg(numresults));
949  QCoreApplication::processEvents();
950  }
951  }
952 
953  for (auto it = result_cache.begin(); it != result_cache.end(); ++it)
954  {
955  ScriptInfo *si = it.key();
956  QStringList results = it.value();
957  QString name = si->name;
958  QStringList::iterator rit;
959  for (rit = results.begin(); rit != results.end(); ++rit)
960  {
961  QStringList tmp = (*rit).split("::");
962  if (tmp.size() < 2)
963  {
964  LOG(VB_GENERAL, LOG_WARNING,
965  QString("Invalid line in Location Search reponse "
966  "from %1: %2").arg(name, *rit));
967  continue;
968  }
969  QString resultstring = QString("%1 (%2)").arg(tmp[1], name);
970  auto *item = new MythUIButtonListItem(m_locationList, resultstring);
971  auto *ri = new ResultListInfo;
972  ri->idstr = tmp[0];
973  ri->src = si;
974  item->SetData(QVariant::fromValue(ri));
975  QCoreApplication::processEvents();
976  }
977  }
978 
979  if (busyPopup)
980  {
981  busyPopup->Close();
982  busyPopup = nullptr;
983  }
984 
985  m_resultsText->SetText(tr("Search Complete. Results: %1").arg(numresults));
986  if (numresults)
988 }
989 
991 {
992  for (int i=0; i < m_locationList->GetCount(); i++)
993  {
995  if (item->GetData().isValid())
996  delete item->GetData().value<ResultListInfo *>();
997  }
998 
1000 }
1001 
1003 {
1004  auto *ri = item->GetData().value<ResultListInfo *>();
1005  if (ri)
1006  m_sourceText->SetText(tr("Source: %1").arg(ri->src->name));
1007 }
1008 
1010 {
1011  auto *ri = item->GetData().value<ResultListInfo *>();
1012  if (ri)
1013  {
1014  // NOLINTNEXTLINE(modernize-loop-convert)
1015  for (auto it = m_screenListInfo->m_types.begin();
1016  it != m_screenListInfo->m_types.end(); ++it)
1017  {
1018  (*it).m_location = ri->idstr;
1019  (*it).m_src = ri->src;
1020  }
1021  }
1022 
1023  auto *dce = new DialogCompletionEvent("location", 0, "",
1024  QVariant::fromValue(new ScreenListInfo(*m_screenListInfo)));
1025  QApplication::postEvent(m_retScreen, dce);
1026 
1027  Close();
1028 }
TypeListInfo::m_location
QString m_location
Definition: weatherUtils.h:42
MythUIButton::Clicked
void Clicked()
LocationDialog::clearResults
void clearResults()
Definition: weatherSetup.cpp:990
MythUIButtonList::GetItemAt
MythUIButtonListItem * GetItemAt(int pos) const
Definition: mythuibuttonlist.cpp:1676
MSqlQuery::next
bool next(void)
Wrap QSqlQuery::next() so we can display the query results.
Definition: mythdbcon.cpp:802
MSqlQuery
QSqlQuery wrapper that fetches a DB connection from the connection pool.
Definition: mythdbcon.h:124
MythMainWindow::GetMainStack
MythScreenStack * GetMainStack()
Definition: mythmainwindow.cpp:314
SourceSetup::m_sourceList
MythUIButtonList * m_sourceList
Definition: weatherSetup.h:122
MSqlQuery::size
int size(void) const
Definition: mythdbcon.h:211
SourceListInfo::update_timeout
std::chrono::minutes update_timeout
Definition: weatherSetup.h:30
MythUIButtonList::GetItemCurrent
MythUIButtonListItem * GetItemCurrent() const
Definition: mythuibuttonlist.cpp:1590
hardwareprofile.smolt.timeout
float timeout
Definition: smolt.py:103
LocationDialog::m_screenListInfo
ScreenListInfo * m_screenListInfo
Definition: weatherSetup.h:160
ScreenSetup::m_activeList
MythUIButtonList * m_activeList
Definition: weatherSetup.h:93
sourceManager.h
ScreenSetup::m_finishButton
MythUIButton * m_finishButton
Definition: weatherSetup.h:95
MythScreenType::NextPrevWidgetFocus
virtual bool NextPrevWidgetFocus(bool up_or_down)
Definition: mythscreentype.cpp:152
DialogCompletionEvent::GetId
QString GetId()
Definition: mythdialogbox.h:52
GlobalSetup::loadData
void loadData(void)
Definition: weatherSetup.cpp:50
ScreenSetup::doListSelect
void doListSelect(MythUIButtonListItem *selected)
Definition: weatherSetup.cpp:449
mythdb.h
SourceListInfo::id
uint id
Definition: weatherSetup.h:32
SourceSetup::sourceListItemSelected
void sourceListItemSelected(MythUIButtonListItem *item)
Definition: weatherSetup.cpp:830
SourceSetup::m_finishButton
MythUIButton * m_finishButton
Definition: weatherSetup.h:123
GlobalSetup::saveData
void saveData(void)
Definition: weatherSetup.cpp:61
MythScreenType::Close
virtual void Close()
Definition: mythscreentype.cpp:385
ScreenSetup::saveData
void saveData(void)
Definition: weatherSetup.cpp:354
ScreenSetup::updateHelpText
void updateHelpText(void)
Definition: weatherSetup.cpp:187
MythUIType::GetChild
MythUIType * GetChild(const QString &name) const
Get a named child of this UIType.
Definition: mythuitype.cpp:131
ScreenSetup::~ScreenSetup
~ScreenSetup() override
Definition: weatherSetup.cpp:87
DialogCompletionEvent::kEventType
static Type kEventType
Definition: mythdialogbox.h:57
MythUIButtonList::itemSelected
void itemSelected(MythUIButtonListItem *item)
ResultListInfo
Definition: weatherSetup.h:127
ScreenSetup::Create
bool Create(void) override
Definition: weatherSetup.cpp:110
MSqlQuery::value
QVariant value(int i) const
Definition: mythdbcon.h:201
MythScreenStack
Definition: mythscreenstack.h:16
ScreenSetup::customEvent
void customEvent(QEvent *event) override
Definition: weatherSetup.cpp:577
MSqlQuery::exec
bool exec(void)
Wrap QSqlQuery::exec() so we can display SQL.
Definition: mythdbcon.cpp:603
MythUITextEdit
A text entry and edit widget.
Definition: mythuitextedit.h:32
types
static const struct wl_interface * types[]
Definition: idle_inhibit_unstable_v1.c:39
LOG
#define LOG(_MASK_, _LEVEL_, _QSTRING_)
Definition: mythlogging.h:23
MythScreenType
Screen in which all other widgets are contained and rendered.
Definition: mythscreentype.h:44
ScreenSetup::showUnitsPopup
void showUnitsPopup(const QString &name, ScreenListInfo *si)
Definition: weatherSetup.cpp:533
MythUITextEdit::GetText
QString GetText(void) const
Definition: mythuitextedit.h:47
ScreenSetup::loadData
void loadData(void)
Definition: weatherSetup.cpp:251
ResultListInfo::idstr
QString idstr
Definition: weatherSetup.h:129
weatherSource.h
MythUISpinBox::SetRange
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.
Definition: mythuispinbox.cpp:25
ScreenSetup::m_sourceManager
SourceManager * m_sourceManager
Definition: weatherSetup.h:90
MythUIButtonList::GetCount
int GetCount() const
Definition: mythuibuttonlist.cpp:1655
TypeListMap
QMultiHash< QString, TypeListInfo > TypeListMap
Definition: weatherUtils.h:45
GlobalSetup::m_finishButton
MythUIButton * m_finishButton
Definition: weatherSetup.h:61
mythprogressdialog.h
ScreenListInfo::m_sources
QStringList m_sources
Definition: weatherUtils.h:61
tmp
static guint32 * tmp
Definition: goom_core.cpp:31
SourceSetup::updateSpinboxUpdate
void updateSpinboxUpdate(void)
Definition: weatherSetup.cpp:812
MythScreenType::GetFocusWidget
MythUIType * GetFocusWidget(void) const
Definition: mythscreentype.cpp:112
GlobalSetup::m_backgroundCheckbox
MythUICheckBox * m_backgroundCheckbox
Definition: weatherSetup.h:58
MythUIType::TakingFocus
void TakingFocus()
hardwareprofile.os_detect.results
results
Definition: os_detect.py:296
LocationDialog::Create
bool Create(void) override
Definition: weatherSetup.cpp:874
TypeListInfo::m_src
ScriptInfo * m_src
Definition: weatherUtils.h:43
MythUIButtonListItem
Definition: mythuibuttonlist.h:34
loadScreens
ScreenListMap loadScreens()
Definition: weatherUtils.cpp:40
weatherSetup.h
SourceSetup::m_retrieveSpinbox
MythUISpinBox * m_retrieveSpinbox
Definition: weatherSetup.h:121
MythUISpinBox::SetValue
void SetValue(int val) override
Definition: mythuispinbox.h:26
LocationDialog::m_retScreen
MythScreenType * m_retScreen
Definition: weatherSetup.h:163
MythUIButtonList::MoveItemUpDown
bool MoveItemUpDown(MythUIButtonListItem *item, bool up)
Definition: mythuibuttonlist.cpp:2313
LocationDialog::m_resultsText
MythUIText * m_resultsText
Definition: weatherSetup.h:168
GlobalSetup::m_timeout
int m_timeout
Definition: weatherSetup.h:60
SourceManager::findScripts
bool findScripts()
Definition: sourceManager.cpp:81
ScreenListInfo::m_units
units_t m_units
Definition: weatherUtils.h:62
LocationDialog
Definition: weatherSetup.h:137
SourceSetup::m_updateSpinbox
MythUISpinBox * m_updateSpinbox
Definition: weatherSetup.h:120
MythUIButtonList::itemClicked
void itemClicked(MythUIButtonListItem *item)
MythMainWindow::TranslateKeyPress
bool TranslateKeyPress(const QString &Context, QKeyEvent *Event, QStringList &Actions, bool AllowJumps=true)
Get a list of actions for a keypress in the given context.
Definition: mythmainwindow.cpp:1102
LocationDialog::m_locationEdit
MythUITextEdit * m_locationEdit
Definition: weatherSetup.h:166
SourceSetup::Create
bool Create(void) override
Definition: weatherSetup.cpp:692
MythScreenType::SetFocusWidget
bool SetFocusWidget(MythUIType *widget=nullptr)
Definition: mythscreentype.cpp:117
SI_UNITS
#define SI_UNITS
Definition: weatherUtils.h:17
MythDialogBox
Basic menu dialog, message and a list of options.
Definition: mythdialogbox.h:166
MythUIButton::SetText
void SetText(const QString &msg)
Definition: mythuibutton.cpp:227
MSqlQuery::InitCon
static MSqlQueryInfo InitCon(ConnectionReuse _reuse=kNormalConnection)
Only use this in combination with MSqlQuery constructor.
Definition: mythdbcon.cpp:535
SourceListInfo::retrieve_timeout
std::chrono::seconds retrieve_timeout
Definition: weatherSetup.h:31
MythUISpinBox::GetDuration
std::enable_if< std::chrono::__is_duration< T >::value, T >::type GetDuration()
Definition: mythuispinbox.h:39
MythUISpinBox::GetIntValue
int GetIntValue(void) const override
Definition: mythuispinbox.h:33
MythDB::DBError
static void DBError(const QString &where, const MSqlQuery &query)
Definition: mythdb.cpp:200
GlobalSetup::Create
bool Create(void) override
Definition: weatherSetup.cpp:22
MythScreenType::BuildFocusList
void BuildFocusList(void)
Definition: mythscreentype.cpp:205
ScreenSetup::doLocationDialog
void doLocationDialog(ScreenListInfo *si)
Definition: weatherSetup.cpp:519
MythUIButton
A single button widget.
Definition: mythuibutton.h:21
ENG_UNITS
#define ENG_UNITS
Definition: weatherUtils.h:18
LocationDialog::m_types
QStringList m_types
Definition: weatherSetup.h:159
SourceSetup::loadData
bool loadData(void)
Definition: weatherSetup.cpp:740
ScreenSetup::ScreenSetup
ScreenSetup(MythScreenStack *parent, const QString &name, SourceManager *srcman)
Definition: weatherSetup.cpp:75
SourceSetup::SourceSetup
SourceSetup(MythScreenStack *parent, const QString &name)
Definition: weatherSetup.cpp:673
LocationDialog::itemClicked
void itemClicked(MythUIButtonListItem *item)
Definition: weatherSetup.cpp:1009
TypeListInfo
Definition: weatherUtils.h:27
ScreenSetup::m_helpText
MythUIText * m_helpText
Definition: weatherSetup.h:92
ScreenListInfo
Definition: weatherUtils.h:47
MythUIBusyDialog
Definition: mythprogressdialog.h:36
MythUIType::SetEnabled
void SetEnabled(bool enable)
Definition: mythuitype.cpp:1124
ScreenListMap
QMap< QString, ScreenListInfo > ScreenListMap
Definition: weatherUtils.h:70
MythUIStateType::Full
@ Full
Definition: mythuistatetype.h:25
SourceManager::clearSources
void clearSources()
Definition: sourceManager.cpp:154
MythUIButtonListItem::GetData
QVariant GetData()
Definition: mythuibuttonlist.cpp:3648
uint
unsigned int uint
Definition: compat.h:144
gCoreContext
MythCoreContext * gCoreContext
This global variable contains the MythCoreContext instance for the app.
Definition: mythcorecontext.cpp:60
MythUICheckBox
A checkbox widget supporting three check states - on,off,half and two conditions - selected and unsel...
Definition: mythuicheckbox.h:15
LocationDialog::LocationDialog
LocationDialog(MythScreenStack *parent, const QString &name, MythScreenType *retScreen, ScreenListInfo *si, SourceManager *srcman)
Definition: weatherSetup.cpp:853
MythCoreContext::GetNumSetting
int GetNumSetting(const QString &key, int defaultval=0)
Definition: mythcorecontext.cpp:936
units_t
unsigned char units_t
Definition: weatherUtils.h:24
SourceListInfo
Definition: weatherSetup.h:24
MythUIType
The base class on which all widgets and screens are based.
Definition: mythuitype.h:84
SourceManager::getSourceByName
ScriptInfo * getSourceByName(const QString &name)
Definition: sourceManager.cpp:196
MSqlQuery::lastError
QSqlError lastError(void) const
Definition: mythdbcon.h:210
MythUIButtonListItem::GetText
QString GetText(const QString &name="") const
Definition: mythuibuttonlist.cpp:3318
LocationDialog::m_searchButton
MythUIButton * m_searchButton
Definition: weatherSetup.h:167
MythUIText
All purpose text widget, displays a text string.
Definition: mythuitext.h:30
MythScreenType::keyPressEvent
bool keyPressEvent(QKeyEvent *event) override
Key event handler.
Definition: mythscreentype.cpp:397
SourceManager::getLocationList
QStringList getLocationList(ScriptInfo *si, const QString &str)
Definition: sourceManager.cpp:216
LocationDialog::itemSelected
void itemSelected(MythUIButtonListItem *item)
Definition: weatherSetup.cpp:1002
SourceSetup::retrieveSpinboxUpdate
void retrieveSpinboxUpdate(void)
Definition: weatherSetup.cpp:821
MSqlQuery::executedQuery
QString executedQuery(void) const
Definition: mythdbcon.h:202
MythUICheckBox::SetCheckState
void SetCheckState(MythUIStateType::StateType state)
Definition: mythuicheckbox.cpp:66
XMLParseBase::LoadWindowFromXML
static bool LoadWindowFromXML(const QString &xmlfile, const QString &windowname, MythUIType *parent)
Definition: xmlparsebase.cpp:692
ScreenSetup::m_createdSrcMan
bool m_createdSrcMan
Definition: weatherSetup.h:91
MSqlQuery::bindValue
void bindValue(const QString &placeholder, const QVariant &val)
Add a single binding.
Definition: mythdbcon.cpp:878
ScreenListInfo::m_dataTypes
QStringList m_dataTypes
Definition: weatherUtils.h:59
DialogCompletionEvent
Event dispatched from MythUI modal dialogs to a listening class containing a result of some form.
Definition: mythdialogbox.h:41
LocationDialog::m_sourceText
MythUIText * m_sourceText
Definition: weatherSetup.h:169
ScreenListInfo::m_types
TypeListMap m_types
Definition: weatherUtils.h:58
MythUIText::SetText
virtual void SetText(const QString &text)
Definition: mythuitext.cpp:133
ScreenListInfo::m_title
QString m_title
Definition: weatherUtils.h:57
LocationDialog::m_locationList
MythUIButtonList * m_locationList
Definition: weatherSetup.h:165
MythUIButtonList::Reset
void Reset() override
Reset the widget to it's original state, should not reset changes made by the theme.
Definition: mythuibuttonlist.cpp:114
GetMythMainWindow
MythMainWindow * GetMythMainWindow(void)
Definition: mythmainwindow.cpp:101
build_compdb.action
action
Definition: build_compdb.py:9
MythUISpinBox
A widget for offering a range of numerical values where only the the bounding values and interval are...
Definition: mythuispinbox.h:16
SourceSetup::m_sourceText
MythUIText * m_sourceText
Definition: weatherSetup.h:124
SourceManager::findPossibleSources
bool findPossibleSources(QStringList types, QList< ScriptInfo * > &sources)
Definition: sourceManager.cpp:281
SourceSetup::saveData
void saveData(void)
Definition: weatherSetup.cpp:778
MythMainWindow::GetStack
MythScreenStack * GetStack(const QString &Stackname)
Definition: mythmainwindow.cpp:319
ScreenSetup::keyPressEvent
bool keyPressEvent(QKeyEvent *event) override
Key event handler.
Definition: weatherSetup.cpp:159
ScreenSetup::m_inactiveList
MythUIButtonList * m_inactiveList
Definition: weatherSetup.h:94
ScriptInfo::name
QString name
Definition: weatherSource.h:21
MythCoreContext::GetHostName
QString GetHostName(void)
Definition: mythcorecontext.cpp:862
LocationDialog::~LocationDialog
~LocationDialog() override
Definition: weatherSetup.cpp:866
weatherScreen.h
LocationDialog::m_sourceManager
SourceManager * m_sourceManager
Definition: weatherSetup.h:161
MythCoreContext::SaveSetting
void SaveSetting(const QString &key, int newValue)
Definition: mythcorecontext.cpp:905
ScreenSetup::deleteScreen
void deleteScreen(void)
Definition: weatherSetup.cpp:559
MythUICheckBox::GetCheckState
MythUIStateType::StateType GetCheckState() const
Definition: mythuicheckbox.cpp:98
MythUIType::LosingFocus
void LosingFocus()
ScriptInfo
Definition: serverSideScripting.h:36
GlobalSetup::m_timeoutSpinbox
MythUISpinBox * m_timeoutSpinbox
Definition: weatherSetup.h:59
MythUIButtonList
List widget, displays list items in a variety of themeable arrangements and can trigger signals when ...
Definition: mythuibuttonlist.h:177
SourceSetup::~SourceSetup
~SourceSetup() override
Definition: weatherSetup.cpp:682
LocationDialog::doSearch
void doSearch(void)
Definition: weatherSetup.cpp:908
MythUIButtonListItem::SetData
void SetData(QVariant data)
Definition: mythuibuttonlist.cpp:3643
MythScreenStack::AddScreen
virtual void AddScreen(MythScreenType *screen, bool allowFade=true)
Definition: mythscreenstack.cpp:50
MythUISpinBox::SetDuration
std::enable_if< std::chrono::__is_duration< T >::value, void >::type SetDuration(T val)
Definition: mythuispinbox.h:43
SourceManager
Definition: sourceManager.h:18
MSqlQuery::prepare
bool prepare(const QString &query)
QSqlQuery::prepare() is not thread safe in Qt <= 3.3.2.
Definition: mythdbcon.cpp:827