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