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