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