MythTV master
scheduleeditor.cpp
Go to the documentation of this file.
1// C++
2#include <utility>
3
4// Qt
5#include <QCoreApplication>
6#include <QHash>
7#include <QString>
8
9// MythTV
16#include "libmythtv/cardutil.h"
18#include "libmythtv/playgroup.h"
22#include "libmythtv/tv_play.h"
36
37// MythFrontend
38#include "proglist.h"
39#include "scheduleeditor.h"
40#include "viewschedulediff.h"
41
42//static const QString _Location = QObject::tr("Schedule Editor");
43
44// Define the strings inserted into the recordfilter table in the
45// database. This should make them available to the translators.
46static QString fs0(QT_TRANSLATE_NOOP("SchedFilterEditor", "New episode"));
47static QString fs1(QT_TRANSLATE_NOOP("SchedFilterEditor", "Identifiable episode"));
48static QString fs2(QT_TRANSLATE_NOOP("SchedFilterEditor", "First showing"));
49static QString fs3(QT_TRANSLATE_NOOP("SchedFilterEditor", "Prime time"));
50static QString fs4(QT_TRANSLATE_NOOP("SchedFilterEditor", "Commercial free"));
51static QString fs5(QT_TRANSLATE_NOOP("SchedFilterEditor", "High definition"));
52static QString fs6(QT_TRANSLATE_NOOP("SchedFilterEditor", "This episode"));
53static QString fs7(QT_TRANSLATE_NOOP("SchedFilterEditor", "This series"));
54static QString fs8(QT_TRANSLATE_NOOP("SchedFilterEditor", "This time"));
55static QString fs9(QT_TRANSLATE_NOOP("SchedFilterEditor", "This day and time"));
56static QString fs10(QT_TRANSLATE_NOOP("SchedFilterEditor", "This channel"));
57static QString fs11(QT_TRANSLATE_NOOP("SchedFilterEditor", "No episodes"));
58
59void *ScheduleEditor::RunScheduleEditor(ProgramInfo *proginfo, void *player)
60{
61 auto *rule = new RecordingRule();
62 rule->LoadByProgram(proginfo);
63
65 auto *se = new ScheduleEditor(mainStack, rule, static_cast<TV*>(player));
66
67 if (se->Create())
68 mainStack->AddScreen(se, (player == nullptr));
69 else
70 delete se;
71
72 return nullptr;
73}
74
81 RecordingInfo *recInfo, TV *player)
82 : ScheduleCommon(parent, "ScheduleEditor"),
83 SchedOptMixin(*this, nullptr), FilterOptMixin(*this, nullptr),
84 StoreOptMixin(*this, nullptr), PostProcMixin(*this, nullptr),
85 m_recInfo(new RecordingInfo(*recInfo)),
86 m_recordingRule(new RecordingRule()),
87 m_player(player)
88{
94
95 if (m_player)
97}
98
100 RecordingRule *recRule, TV *player)
101 : ScheduleCommon(parent, "ScheduleEditor"),
102 SchedOptMixin(*this, recRule),
103 FilterOptMixin(*this, recRule),
104 StoreOptMixin(*this, recRule),
105 PostProcMixin(*this, recRule),
106 m_recordingRule(recRule),
107 m_player(player)
108{
109 if (m_player)
110 m_player->IncrRef();
111}
112
114{
115 delete m_recordingRule;
116
117 // if we have a player, we need to tell we are done
118 if (m_player)
119 {
120 emit m_player->RequestEmbedding(false);
121 m_player->DecrRef();
122 }
123}
124
126{
127 if (!LoadWindowFromXML("schedule-ui.xml", "scheduleeditor", this))
128 return false;
129
130 bool err = false;
131
132 UIUtilE::Assign(this, m_rulesList, "rules", &err);
133
134 UIUtilW::Assign(this, m_schedOptButton, "schedoptions");
135 UIUtilW::Assign(this, m_storeOptButton, "storeoptions");
136 UIUtilW::Assign(this, m_postProcButton, "postprocessing");
137 UIUtilW::Assign(this, m_metadataButton, "metadata");
138 UIUtilW::Assign(this, m_schedInfoButton, "schedinfo");
139 UIUtilW::Assign(this, m_previewButton, "preview");
140 UIUtilW::Assign(this, m_filtersButton, "filters");
141
146
147 UIUtilW::Assign(this, m_cancelButton, "cancel");
148 UIUtilE::Assign(this, m_saveButton, "save", &err);
149
150 if (err)
151 {
152 LOG(VB_GENERAL, LOG_ERR, "ScheduleEditor, theme is missing "
153 "required elements");
154 return false;
155 }
156
159
162 if (m_filtersButton)
170 if (m_previewButton)
174
175 if (m_cancelButton)
178
181 if (m_previewButton)
183
184 if (m_dupmethodList)
187 if (m_filtersList)
190 if (m_maxepSpin)
193 if (m_recgroupList)
199
201
203 {
204 if (m_recInfo)
206 else if (m_recordingRule->m_recordID)
208
210 {
211 LOG(VB_GENERAL, LOG_ERR,
212 "ScheduleEditor::Create() - Failed to load recording rule");
213 return false;
214 }
215 }
216
217 if (m_player)
218 emit m_player->RequestEmbedding(true);
219
220 return true;
221}
222
224{
225 if (m_child)
226 m_child->Close();
227
228 // don't fade the screen if we are returning to the player
229 if (m_player)
230 GetScreenStack()->PopScreen(this, false);
231 else
232 GetScreenStack()->PopScreen(this, true);
233}
234
236{
241
242 if (!m_loaded)
243 {
244 // Copy this now, it will change briefly after the first item
245 // is inserted into the list by design of
246 // MythUIButtonList::itemSelected()
248
249 // Rules List
251 {
253 .compare("Default", Qt::CaseInsensitive) != 0)
254 {
256 tr("Delete this recording rule template"),
258 }
262 }
264 {
266 tr("Record this showing with normal options"),
274 }
275 else
276 {
277 bool hasChannel = !m_recordingRule->m_station.isEmpty();
278 bool isManual = (m_recordingRule->m_searchType == kManualSearch);
279
283 if (hasChannel)
284 {
288 }
289 if (!isManual)
290 {
294 }
295 if (!hasChannel || isManual)
296 {
303 }
304 if (!isManual)
305 {
309 }
310 }
311
313 }
315
316 InfoMap progMap;
317
318 m_recordingRule->ToMap(progMap);
319
320 if (m_recInfo)
321 m_recInfo->ToMap(progMap);
322
323 SetTextFromMap(progMap);
324
325 m_loaded = true;
326}
327
328void ScheduleEditor::LoadTemplate(const QString& name)
329{
331 Load();
332 emit templateLoaded();
333}
334
336{
337 if (!item)
338 return;
339
340 m_recordingRule->m_type = static_cast<RecordingType>
341 (item->GetData().toInt());
342
343 bool isScheduled = (m_recordingRule->m_type != kNotRecording &&
345
347 m_schedOptButton->SetEnabled(isScheduled);
348 if (m_filtersButton)
349 m_filtersButton->SetEnabled(isScheduled);
351 m_storeOptButton->SetEnabled(isScheduled);
353 m_postProcButton->SetEnabled(isScheduled);
355 m_metadataButton->SetEnabled(isScheduled &&
357
362}
363
365{
367}
368
370{
372}
373
375{
377}
378
380{
382}
383
385{
387}
388
390{
391 if (m_child)
392 m_child->Close();
393
395 {
396 int recid = m_recordingRule->m_recordID;
397 DeleteRule();
398 if (recid)
399 emit ruleDeleted(recid);
400 Close();
401 return;
402 }
403
408 m_recordingRule->Save(true);
410
411 Close();
412}
413
415{
417}
418
420{
423 return;
424
425 if (m_child)
426 m_child->Close();
427
429
431 auto *schedoptedit = new SchedOptEditor(mainStack, *this,
433 if (!schedoptedit->Create())
434 {
435 delete schedoptedit;
436 return;
437 }
438
440 m_child = schedoptedit;
441 mainStack->AddScreen(schedoptedit);
442}
443
445{
448 return;
449
450 if (m_child)
451 m_child->Close();
452
454
456 auto *storeoptedit = new StoreOptEditor(mainStack, *this,
458 if (!storeoptedit->Create())
459 {
460 delete storeoptedit;
461 return;
462 }
463
465 m_child = storeoptedit;
466 mainStack->AddScreen(storeoptedit);
467}
468
470{
473 return;
474
475 if (m_child)
476 m_child->Close();
477
479
481 auto *ppedit = new PostProcEditor(mainStack, *this,
483 if (!ppedit->Create())
484 {
485 delete ppedit;
486 return;
487 }
488
490 m_child = ppedit;
491 mainStack->AddScreen(ppedit);
492}
493
495{
497 return;
498
499 QString label = tr("Schedule Information");
500
501 MythScreenStack *popupStack = GetMythMainWindow()->GetStack("popup stack");
502 auto *menuPopup = new MythDialogBox(label, popupStack, "menuPopup");
503
504 if (menuPopup->Create())
505 {
506 menuPopup->SetReturnEvent(this, "schedinfo");
507
508 if (m_recInfo)
509 menuPopup->AddButton(tr("Program Details"));
510 menuPopup->AddButton(tr("Upcoming Episodes"));
511 menuPopup->AddButton(tr("Upcoming Recordings"));
513 menuPopup->AddButton(tr("Previously Recorded"));
514
515 popupStack->AddScreen(menuPopup);
516 }
517 else
518 {
519 delete menuPopup;
520 }
521}
522
523bool ScheduleEditor::keyPressEvent(QKeyEvent *event)
524{
525 if (GetFocusWidget()->keyPressEvent(event))
526 return true;
527
528 QStringList actions;
529 bool handled = GetMythMainWindow()->
530 TranslateKeyPress("TV Frontend", event, actions);
531
532 for (int i = 0; i < actions.size() && !handled; i++)
533 {
534 const QString& action = actions[i];
535 handled = true;
536
537 if (action == "MENU")
538 showMenu();
539 else if (action == "INFO")
540 ShowDetails();
541 else if (action == "GUIDE")
542 ShowGuide();
543 else if (action == "UPCOMING")
545 else if (action == "PREVVIEW")
547 else if (action == "NEXTVIEW")
548 ShowNextView();
549 else
550 handled = false;
551 }
552
553 if (!handled && MythScreenType::keyPressEvent(event))
554 handled = true;
555
556 return handled;
557}
558
560{
561 if (event->type() == DialogCompletionEvent::kEventType)
562 {
563 auto *dce = (DialogCompletionEvent*)(event);
564
565 QString resultid = dce->GetId();
566 QString resulttext = dce->GetResultText();
567
568 if (resultid == "menu")
569 {
570 if (resulttext == tr("Main Options"))
571 m_child->Close();
572 if (resulttext == tr("Schedule Options"))
573 ShowSchedOpt();
574 else if (resulttext == tr("Filter Options"))
575 ShowFilters();
576 else if (resulttext == tr("Storage Options"))
577 ShowStoreOpt();
578 else if (resulttext == tr("Post Processing"))
579 ShowPostProc();
580 else if (resulttext == tr("Metadata Options"))
582 else if (resulttext == tr("Use Template"))
584 else if (resulttext == tr("Schedule Info"))
586 else if (resulttext == tr("Preview Changes"))
587 ShowPreview();
588 }
589 else if (resultid == "templatemenu")
590 {
591 LoadTemplate(resulttext);
592 }
593 else if (resultid == "schedinfo")
594 {
595 if (resulttext == tr("Program Details"))
596 ShowDetails();
597 else if (resulttext == tr("Upcoming Episodes"))
599 else if (resulttext == tr("Upcoming Recordings"))
601 else if (resulttext == tr("Previously Recorded"))
604 }
605 else if (resultid == "newrecgroup")
606 {
607 int groupID = CreateRecordingGroup(resulttext);
608 StoreOptMixin::SetRecGroup(groupID, resulttext);
609 }
610 }
611}
612
614{
616 return;
617
618 // No rule? Search by title
619 if (m_recordingRule->m_recordID <= 0)
620 {
622 return;
623 }
624
626 auto *pl = new ProgLister(mainStack, plRecordid,
627 QString::number(m_recordingRule->m_recordID), "");
628
629 if (pl->Create())
630 mainStack->AddScreen(pl);
631 else
632 delete pl;
633}
634
636{
638 return;
639
640 // Existing rule and search? Search by rule
641 if (m_recordingRule->m_recordID > 0 &&
644
645 QString title = m_recordingRule->m_title;
646
649
651}
652
654{
656 return;
657
658 if (m_child)
659 {
660 m_child->Save();
661 if (m_view == kSchedOptView)
663 else if (m_view == kStoreOptView)
665 else if (m_view == kPostProcView)
667 }
668
673
674 QString ttable = "record_tmp";
675 m_recordingRule->UseTempTable(true, ttable);
676
678 auto *vsd = new ViewScheduleDiff(mainStack, ttable,
681 if (vsd->Create())
682 mainStack->AddScreen(vsd);
683 else
684 delete vsd;
685
687}
688
690{
694 return;
695
696 if (m_child)
697 m_child->Close();
698
700 auto *rad = new MetadataOptions(mainStack, *this,
702 if (!rad->Create())
703 {
704 delete rad;
705 return;
706 }
707
709 m_child = rad;
710 mainStack->AddScreen(rad);
711}
712
714{
717 return;
718
719 if (m_child)
720 m_child->Close();
721
723
725 auto *schedfilteredit = new SchedFilterEditor(mainStack, *this,
727 if (!schedfilteredit->Create())
728 {
729 delete schedfilteredit;
730 return;
731 }
732
734 m_child = schedfilteredit;
735 mainStack->AddScreen(schedfilteredit);
736}
737
739{
742 return;
743
746 else if ((m_view == kMainView) || (m_view == kMetadataView))
747 ShowPostProc();
748 else if (m_view == kSchedOptView)
749 m_child->Close();
750 else if (m_view == kFilterView)
751 ShowSchedOpt();
752 else if (m_view == kStoreOptView)
753 ShowFilters();
754 else if (m_view == kPostProcView)
755 ShowStoreOpt();
756}
757
759{
762 return;
763
764 if (m_view == kMainView)
765 ShowSchedOpt();
766 else if (m_view == kSchedOptView)
767 ShowFilters();
768 else if (m_view == kFilterView)
769 ShowStoreOpt();
770 else if (m_view == kStoreOptView)
771 ShowPostProc();
774 else if ((m_view == kPostProcView) || (m_view == kMetadataView))
775 m_child->Close();
776}
777
779{
780 if (m_view == kSchedOptView)
782 else if (m_view == kFilterView)
784 else if (m_view == kStoreOptView)
786 else if (m_view == kPostProcView)
788
789 m_child = nullptr;
791}
792
794{
795 QString label = tr("Options");
796 MythScreenStack *popupStack = GetMythMainWindow()->GetStack("popup stack");
797 auto *menuPopup = new MythDialogBox(label, popupStack, "menuPopup");
798
800 RecordingType type = static_cast<RecordingType>(item->GetData().toInt());
801 bool isScheduled = (type != kNotRecording && type != kDontRecord);
802
803 if (menuPopup->Create())
804 {
805 menuPopup->SetReturnEvent(this, "menu");
806 if (m_view != kMainView)
807 menuPopup->AddButton(tr("Main Options"));
808 if (isScheduled && m_view != kSchedOptView)
809 menuPopup->AddButton(tr("Schedule Options"));
810 if (isScheduled && m_view != kFilterView)
811 menuPopup->AddButton(tr("Filter Options"));
812 if (isScheduled && m_view != kStoreOptView)
813 menuPopup->AddButton(tr("Storage Options"));
814 if (isScheduled && m_view != kPostProcView)
815 menuPopup->AddButton(tr("Post Processing"));
816 if (isScheduled && !m_recordingRule->m_isTemplate &&
818 menuPopup->AddButton(tr("Metadata Options"));
820 {
821 menuPopup->AddButton(tr("Schedule Info"));
822 menuPopup->AddButton(tr("Preview Changes"));
823 }
824 menuPopup->AddButton(tr("Use Template"));
825 popupStack->AddScreen(menuPopup);
826 }
827 else
828 {
829 delete menuPopup;
830 }
831}
832
834{
835 QStringList templates = RecordingRule::GetTemplateNames();
836 if (templates.empty())
837 {
838 ShowOkPopup(tr("No templates available"));
839 return;
840 }
841
842 QString label = tr("Template Options");
843 MythScreenStack *popupStack = GetMythMainWindow()->GetStack("popup stack");
844 auto *menuPopup = new MythDialogBox(label, popupStack, "menuPopup");
845
846 if (menuPopup->Create())
847 {
848 menuPopup->SetReturnEvent(this, "templatemenu");
849 while (!templates.empty())
850 {
851 QString name = templates.front();
852 if (name == "Default")
853 menuPopup->AddButton(tr("Default"));
854 else
855 menuPopup->AddButton(name);
856 templates.pop_front();
857 }
858 popupStack->AddScreen(menuPopup);
859 }
860 else
861 {
862 delete menuPopup;
863 }
864}
865
867
873 ScheduleEditor &editor, RecordingRule &rule,
874 RecordingInfo *recInfo)
875 : MythScreenType(parent, name),
876 m_editor(&editor), m_recordingRule(&rule), m_recInfo(recInfo)
877{
878}
879
880bool SchedEditChild::keyPressEvent(QKeyEvent *event)
881{
882 if (GetFocusWidget()->keyPressEvent(event))
883 return true;
884
885 QStringList actions;
886 bool handled = GetMythMainWindow()->
887 TranslateKeyPress("TV Frontend", event, actions);
888
889 for (int i = 0; i < actions.size() && !handled; i++)
890 {
891 const QString& action = actions[i];
892 handled = true;
893
894 if (action == "MENU")
896 else if (action == "INFO")
898 else if (action == "UPCOMING")
900 if (action == "ESCAPE")
901 Close();
902 else if (action == "PREVVIEW")
904 else if (action == "NEXTVIEW")
906 else
907 handled = false;
908 }
909
910 if (!handled && MythScreenType::keyPressEvent(event))
911 handled = true;
912
913 return handled;
914}
915
917 const QString &xmlfile, const QString &winname, bool isTemplate)
918{
919 if (!LoadWindowFromXML(xmlfile, winname, this))
920 return false;
921
922 UIUtilW::Assign(this, m_backButton, "back");
923 UIUtilW::Assign(this, m_saveButton, "save");
924 UIUtilW::Assign(this, m_previewButton, "preview");
925
928
929 if (m_backButton)
931 if (m_saveButton)
933 if (m_previewButton)
934 {
937 m_previewButton->SetEnabled(!isTemplate);
938 }
939
940 return true;
941}
942
944{
945 InfoMap progMap;
946
947 m_recordingRule->ToMap(progMap);
948
949 if (m_recInfo)
950 m_recInfo->ToMap(progMap);
951
952 SetTextFromMap(progMap);
953}
954
956{
957 Save();
958 emit Closing();
960}
961
963
970 ScheduleEditor &editor,
971 RecordingRule &rule,
972 RecordingInfo *recInfo)
973 : SchedEditChild(parent, "ScheduleOptionsEditor", editor, rule, recInfo),
974 SchedOptMixin(*this, &rule, &editor)
975{
976}
977
979{
981 "schedule-ui.xml", "scheduleoptionseditor",
983 {
984 return false;
985 }
986
987 bool err = false;
988
990
991 UIUtilW::Assign(this, m_filtersButton, "filters");
992
993 if (err)
994 {
995 LOG(VB_GENERAL, LOG_ERR, "SchedOptEditor, theme is missing "
996 "required elements");
997 return false;
998 }
999
1000 if (m_dupmethodList)
1003
1004 if (m_filtersButton)
1007
1009
1010 return true;
1011}
1012
1014{
1017}
1018
1020{
1022}
1023
1025{
1027}
1028
1030
1037 ScheduleEditor &editor,
1038 RecordingRule &rule,
1039 RecordingInfo *recInfo)
1040 : SchedEditChild(parent, "ScheduleFilterEditor", editor, rule, recInfo),
1041 FilterOptMixin(*this, &rule, &editor)
1042{
1043}
1044
1046{
1048 "schedule-ui.xml", "schedulefiltereditor",
1050 {
1051 return false;
1052 }
1053
1054 bool err = false;
1055
1057
1058 if (err)
1059 {
1060 LOG(VB_GENERAL, LOG_ERR, "SchedFilterEditor, theme is missing "
1061 "required elements");
1062 return false;
1063 }
1064
1067
1069
1070 return true;
1071}
1072
1074{
1077}
1078
1080{
1082}
1083
1085{
1087}
1088
1090
1097 ScheduleEditor &editor,
1098 RecordingRule &rule,
1099 RecordingInfo *recInfo)
1100 : SchedEditChild(parent, "StorageOptionsEditor", editor, rule, recInfo),
1101 StoreOptMixin(*this, &rule, &editor)
1102{
1103}
1104
1106{
1108 "schedule-ui.xml", "storageoptionseditor",
1110 {
1111 return false;
1112 }
1113
1114 bool err = false;
1115
1117
1118 if (err)
1119 {
1120 LOG(VB_GENERAL, LOG_ERR, "StoreOptEditor, theme is missing "
1121 "required elements");
1122 return false;
1123 }
1124
1125 if (m_maxepSpin)
1128 if (m_recgroupList)
1131
1133
1134 return true;
1135}
1136
1138{
1141}
1142
1144{
1146}
1147
1149{
1151}
1152
1154{
1155 if (event->type() == DialogCompletionEvent::kEventType)
1156 {
1157 auto *dce = (DialogCompletionEvent*)(event);
1158
1159 QString resultid = dce->GetId();
1160 QString resulttext = dce->GetResultText();
1161
1162 if (resultid == "newrecgroup")
1163 {
1164 int groupID = CreateRecordingGroup(resulttext);
1165 StoreOptMixin::SetRecGroup(groupID, resulttext);
1166 }
1167 }
1168}
1169
1171{
1173}
1174
1176
1183 ScheduleEditor &editor,
1184 RecordingRule &rule,
1185 RecordingInfo *recInfo)
1186 : SchedEditChild(parent, "PostProcOptionsEditor", editor, rule, recInfo),
1187 PostProcMixin(*this, &rule, &editor)
1188{
1189}
1190
1192{
1194 "schedule-ui.xml", "postproceditor",
1196 {
1197 return false;
1198 }
1199
1200 bool err = false;
1201
1203
1204 if (err)
1205 {
1206 LOG(VB_GENERAL, LOG_ERR, "PostProcEditor, theme is missing "
1207 "required elements");
1208 return false;
1209 }
1210
1211 if (m_transcodeCheck)
1214
1216
1217 return true;
1218}
1219
1221{
1224}
1225
1227{
1229}
1230
1232{
1234}
1235
1237
1244 ScheduleEditor &editor,
1245 RecordingRule &rule,
1246 RecordingInfo *recInfo)
1247 : SchedEditChild(parent, "MetadataOptions", editor, rule, recInfo),
1248 m_metadataFactory(new MetadataFactory(this)),
1249 m_imageLookup(new MetadataDownload(this)),
1250 m_imageDownload(new MetadataImageDownload(this))
1251{
1252 m_popupStack = GetMythMainWindow()->GetStack("popup stack");
1255}
1256
1258{
1259 if (m_imageLookup)
1260 {
1262 delete m_imageLookup;
1263 m_imageLookup = nullptr;
1264 }
1265
1266 if (m_imageDownload)
1267 {
1269 delete m_imageDownload;
1270 m_imageDownload = nullptr;
1271 }
1272}
1273
1275{
1277 "schedule-ui.xml", "metadataoptions",
1279 {
1280 return false;
1281 }
1282
1283 bool err = false;
1284
1285 UIUtilE::Assign(this, m_inetrefEdit, "inetref_edit", &err);
1286 UIUtilW::Assign(this, m_inetrefClear, "inetref_clear", &err);
1287 UIUtilE::Assign(this, m_seasonSpin, "season_spinbox", &err);
1288 UIUtilE::Assign(this, m_episodeSpin, "episode_spinbox", &err);
1289 UIUtilE::Assign(this, m_queryButton, "query_button", &err);
1290 UIUtilE::Assign(this, m_localFanartButton, "local_fanart_button", &err);
1291 UIUtilE::Assign(this, m_localCoverartButton, "local_coverart_button", &err);
1292 UIUtilE::Assign(this, m_localBannerButton, "local_banner_button", &err);
1293 UIUtilE::Assign(this, m_onlineFanartButton, "online_fanart_button", &err);
1294 UIUtilE::Assign(this, m_onlineCoverartButton, "online_coverart_button", &err);
1295 UIUtilE::Assign(this, m_onlineBannerButton, "online_banner_button", &err);
1296 UIUtilW::Assign(this, m_fanart, "fanart");
1297 UIUtilW::Assign(this, m_coverart, "coverart");
1298 UIUtilW::Assign(this, m_banner, "banner");
1299
1300 if (err)
1301 {
1302 LOG(VB_GENERAL, LOG_ERR, "MetadataOptions, theme is missing "
1303 "required elements");
1304 return false;
1305 }
1306
1323
1326
1327 // InetRef
1329
1330 // Season
1331 m_seasonSpin->SetRange(0,9999,1,5);
1332 int season {0};
1333 if (m_recordingRule->m_season != 0)
1334 season = m_recordingRule->m_season;
1335 else if (m_recInfo)
1336 season = m_recInfo->GetSeason();
1337 m_seasonSpin->SetValue(season);
1338
1339 // Episode
1340 m_episodeSpin->SetRange(0,9999,1,10);
1341 int episode {0};
1342 if (m_recordingRule->m_episode != 0)
1343 episode = m_recordingRule->m_episode;
1344 else if (m_recInfo)
1345 episode = m_recInfo->GetEpisode();
1346 m_episodeSpin->SetValue(episode);
1347
1348 if (m_coverart)
1349 {
1351 m_coverart->Load();
1352 }
1353
1354 if (m_fanart)
1355 {
1357 m_fanart->Load();
1358 }
1359
1360 if (m_banner)
1361 {
1363 m_banner->Load();
1364 }
1365
1367
1368 return true;
1369}
1370
1372{
1374}
1375
1376void MetadataOptions::CreateBusyDialog(const QString& title)
1377{
1378 if (m_busyPopup)
1379 return;
1380
1381 const QString& message = title;
1382
1384 "metaoptsdialog");
1385
1386 if (m_busyPopup->Create())
1388}
1389
1391{
1392 m_recordingRule->m_inetref.clear();
1394}
1395
1397{
1398 CreateBusyDialog(tr("Trying to manually find this "
1399 "recording online..."));
1400
1402
1403 lookup->SetAutomatic(false);
1404 m_metadataFactory->Lookup(lookup);
1405}
1406
1408{
1409 QueryComplete(lookup);
1410}
1411
1414{
1415 QString msg = tr("Downloading selected artwork...");
1416 CreateBusyDialog(msg);
1417
1418 auto *lookup = new MetadataLookup();
1419
1420 lookup->SetType(kMetadataVideo);
1421 lookup->SetHost(gCoreContext->GetMasterHostName());
1422 lookup->SetAutomatic(true);
1423 lookup->SetData(QVariant::fromValue<VideoArtworkType>(type));
1424
1425 DownloadMap downloads;
1426 downloads.insert(type, info);
1427 lookup->SetDownloads(downloads);
1428 lookup->SetAllowOverwrites(true);
1429 lookup->SetTitle(m_recordingRule->m_title);
1430 lookup->SetSubtitle(m_recordingRule->m_subtitle);
1431 lookup->SetInetref(m_inetrefEdit->GetText());
1432 lookup->SetSeason(m_seasonSpin->GetIntValue());
1433 lookup->SetEpisode(m_episodeSpin->GetIntValue());
1434
1436}
1437
1439{
1440 if (!CanSetArtwork())
1441 return;
1442
1443 QString url = StorageGroup::generate_file_url("Fanart",
1445 "");
1446 FindImagePopup(url,"",*this, "fanart");
1447}
1448
1450{
1451 if (!CanSetArtwork())
1452 return;
1453
1454 QString url = StorageGroup::generate_file_url("Coverart",
1456 "");
1457 FindImagePopup(url,"",*this, "coverart");
1458}
1459
1461{
1462 if (!CanSetArtwork())
1463 return;
1464
1465 QString url = StorageGroup::generate_file_url("Banners",
1467 "");
1468 FindImagePopup(url,"",*this, "banner");
1469}
1470
1472{
1474}
1475
1477{
1479}
1480
1482{
1484}
1485
1487{
1488 // Season
1489 if (m_seasonSpin)
1491
1492 // Episode
1493 if (m_episodeSpin)
1495
1496 // InetRef
1497 if (m_inetrefEdit)
1499}
1500
1502{
1503 if (!lookup)
1504 return;
1505
1506 // InetRef
1507 m_inetrefEdit->SetText(lookup->GetInetref());
1508
1509 // Season
1510 m_seasonSpin->SetValue(lookup->GetSeason());
1511
1512 // Episode
1513 m_episodeSpin->SetValue(lookup->GetEpisode());
1514
1515 InfoMap metadataMap;
1516 lookup->toMap(metadataMap);
1517 SetTextFromMap(metadataMap);
1518}
1519
1521 const QString &prefixAlt,
1522 QObject &inst,
1523 const QString &returnEvent)
1524{
1525 QString fp;
1526
1527 if (prefix.startsWith("myth://"))
1528 fp = prefix;
1529 else
1530 fp = prefix.isEmpty() ? prefixAlt : prefix;
1531
1532 MythScreenStack *popupStack =
1533 GetMythMainWindow()->GetStack("popup stack");
1534
1535 auto *fb = new MythUIFileBrowser(popupStack, fp);
1536 fb->SetNameFilter(GetSupportedImageExtensionFilter());
1537 if (fb->Create())
1538 {
1539 fb->SetReturnEvent(&inst, returnEvent);
1540 popupStack->AddScreen(fb);
1541 }
1542 else
1543 {
1544 delete fb;
1545 }
1546}
1547
1549{
1550 QStringList ret;
1551
1552 QList<QByteArray> exts = QImageReader::supportedImageFormats();
1553 for (const auto & ext : std::as_const(exts))
1554 {
1555 ret.append(QString("*.").append(ext));
1556 }
1557
1558 return ret;
1559}
1560
1562{
1563 if (m_inetrefEdit->GetText().isEmpty())
1564 {
1565 ShowOkPopup(tr("You must set a reference number "
1566 "on this rule to set artwork. For items "
1567 "without a metadata source, you can set "
1568 "any unique value."));
1569 return false;
1570 }
1571
1572 return true;
1573}
1574
1576{
1577 auto *lookup = new MetadataLookup();
1578 lookup->SetStep(kLookupSearch);
1579 lookup->SetType(mtype);
1581
1582 if (type == kUnknownVideo)
1583 {
1585 (m_seasonSpin->GetIntValue() == 0 &&
1586 m_episodeSpin->GetIntValue() == 0))
1587 {
1588 lookup->SetSubtype(kProbableMovie);
1589 }
1590 else
1591 {
1592 lookup->SetSubtype(kProbableTelevision);
1593 }
1594 }
1595 else
1596 {
1597 // we could determine the type from the inetref
1598 lookup->SetSubtype(type);
1599 }
1600 lookup->SetAllowGeneric(true);
1601 lookup->SetHandleImages(false);
1602 lookup->SetHost(gCoreContext->GetMasterHostName());
1603 lookup->SetTitle(m_recordingRule->m_title);
1604 lookup->SetSubtitle(m_recordingRule->m_subtitle);
1605 lookup->SetInetref(m_inetrefEdit->GetText());
1606 lookup->SetCollectionref(m_inetrefEdit->GetText());
1607 lookup->SetSeason(m_seasonSpin->GetIntValue());
1608 lookup->SetEpisode(m_episodeSpin->GetIntValue());
1609
1610 return lookup;
1611}
1612
1614{
1615 if (!CanSetArtwork())
1616 return;
1617
1618 QString msg = tr("Searching for available artwork...");
1619 CreateBusyDialog(msg);
1620
1622
1623 lookup->SetAutomatic(true);
1624 lookup->SetData(QVariant::fromValue<VideoArtworkType>(type));
1625 m_imageLookup->addLookup(lookup);
1626}
1627
1629{
1630 if (!lookup)
1631 return;
1632
1633 if (m_busyPopup)
1634 {
1635 m_busyPopup->Close();
1636 m_busyPopup = nullptr;
1637 }
1638
1639 auto type = lookup->GetData().value<VideoArtworkType>();
1640 ArtworkList list = lookup->GetArtwork(type);
1641
1642 if (list.isEmpty())
1643 {
1644 MythWarningNotification n(tr("No image found"), tr("Schedule Editor"));
1646 return;
1647 }
1648
1649 auto *resultsdialog = new ImageSearchResultsDialog(m_popupStack, list, type);
1650
1651 connect(resultsdialog, &ImageSearchResultsDialog::haveResult,
1653
1654 if (resultsdialog->Create())
1655 m_popupStack->AddScreen(resultsdialog);
1656}
1657
1659{
1660 if (!lookup)
1661 return;
1662
1663 DownloadMap map = lookup->GetDownloads();
1664
1665 if (map.isEmpty())
1666 return;
1667
1668 for (DownloadMap::const_iterator i = map.cbegin(); i != map.cend(); ++i)
1669 {
1670 VideoArtworkType type = i.key();
1671 const ArtworkInfo& info = i.value();
1672
1673 if (type == kArtworkCoverart)
1675 else if (type == kArtworkFanart)
1677 else if (type == kArtworkBanner)
1679 }
1680
1683
1684 ValuesChanged();
1685}
1686
1688{
1691
1692 if (m_coverart)
1693 {
1695 m_coverart->Load();
1696 }
1697
1698 if (m_fanart)
1699 {
1701 m_fanart->Load();
1702 }
1703
1704 if (m_banner)
1705 {
1707 m_banner->Load();
1708 }
1709}
1710
1712{
1713 if (levent->type() == MetadataFactoryMultiResult::kEventType)
1714 {
1715 if (m_busyPopup)
1716 {
1717 m_busyPopup->Close();
1718 m_busyPopup = nullptr;
1719 }
1720
1721 auto *mfmr = dynamic_cast<MetadataFactoryMultiResult*>(levent);
1722 if (!mfmr)
1723 return;
1724
1725 MetadataLookupList list = mfmr->m_results;
1726
1727 if (list.count() > 1)
1728 {
1729 int yearindex = -1;
1730
1731 for (int p = 0; p != list.size(); ++p)
1732 {
1733 if (!m_recordingRule->m_seriesid.isEmpty() &&
1734 m_recordingRule->m_seriesid == (list[p])->GetTMSref())
1735 {
1736 MetadataLookup *lookup = list[p];
1737 QueryComplete(lookup);
1738 return;
1739 }
1740 if (m_recInfo &&
1742 (list[p])->GetYear() != 0 &&
1743 m_recInfo->GetYearOfInitialRelease() == (list[p])->GetYear())
1744 {
1745 if (yearindex > -1)
1746 {
1747 LOG(VB_GENERAL, LOG_INFO, "Multiple results matched on year. No definite "
1748 "match could be found based on year alone.");
1749 yearindex = -2;
1750 }
1751 else if (yearindex == -1)
1752 {
1753 LOG(VB_GENERAL, LOG_INFO, "Matched based on year. ");
1754 yearindex = p;
1755 }
1756 }
1757 }
1758
1759 if (yearindex > -1)
1760 {
1761 MetadataLookup *lookup = list[yearindex];
1762 QueryComplete(lookup);
1763 return;
1764 }
1765
1766 LOG(VB_GENERAL, LOG_INFO, "Falling through to selection dialog.");
1767 auto *resultsdialog = new MetadataResultsDialog(m_popupStack, list);
1768
1769 connect(resultsdialog, &MetadataResultsDialog::haveResult,
1771 Qt::QueuedConnection);
1772
1773 if (resultsdialog->Create())
1774 m_popupStack->AddScreen(resultsdialog);
1775 }
1776 }
1777 else if (levent->type() == MetadataFactorySingleResult::kEventType)
1778 {
1779 if (m_busyPopup)
1780 {
1781 m_busyPopup->Close();
1782 m_busyPopup = nullptr;
1783 }
1784
1785 auto *mfsr = dynamic_cast<MetadataFactorySingleResult*>(levent);
1786 if (!mfsr)
1787 return;
1788
1789 MetadataLookup *lookup = mfsr->m_result;
1790
1791 if (!lookup)
1792 return;
1793
1794 QueryComplete(lookup);
1795 }
1796 else if (levent->type() == MetadataFactoryNoResult::kEventType)
1797 {
1798 if (m_busyPopup)
1799 {
1800 m_busyPopup->Close();
1801 m_busyPopup = nullptr;
1802 }
1803
1804 auto *mfnr = dynamic_cast<MetadataFactoryNoResult*>(levent);
1805 if (!mfnr)
1806 return;
1807
1808 QString title = tr("No match found for this recording. You can "
1809 "try entering a TVDB/TMDB number, season, and "
1810 "episode manually.");
1811
1812 auto *okPopup = new MythConfirmationDialog(m_popupStack, title, false);
1813
1814 if (okPopup->Create())
1815 m_popupStack->AddScreen(okPopup);
1816 }
1817 else if (levent->type() == MetadataLookupEvent::kEventType)
1818 {
1819 if (m_busyPopup)
1820 {
1821 m_busyPopup->Close();
1822 m_busyPopup = nullptr;
1823 }
1824
1825 auto *lue = (MetadataLookupEvent *)levent;
1826
1827 MetadataLookupList lul = lue->m_lookupList;
1828
1829 if (lul.isEmpty())
1830 return;
1831
1832 if (lul.count() >= 1)
1833 {
1834 OnArtworkSearchDone(lul[0]);
1835 }
1836 }
1837 else if (levent->type() == MetadataLookupFailure::kEventType)
1838 {
1839 if (m_busyPopup)
1840 {
1841 m_busyPopup->Close();
1842 m_busyPopup = nullptr;
1843 }
1844
1845 auto *luf = (MetadataLookupFailure *)levent;
1846
1847 MetadataLookupList lul = luf->m_lookupList;
1848
1849 if (!lul.empty())
1850 {
1851 QString title = tr("This number, season, and episode combination "
1852 "does not appear to be valid (or the site may "
1853 "be down). Check your information and try "
1854 "again.");
1855
1856 auto *okPopup = new MythConfirmationDialog(m_popupStack, title, false);
1857
1858 if (okPopup->Create())
1859 m_popupStack->AddScreen(okPopup);
1860 }
1861 }
1862 else if (levent->type() == ImageDLEvent::kEventType)
1863 {
1864 if (m_busyPopup)
1865 {
1866 m_busyPopup->Close();
1867 m_busyPopup = nullptr;
1868 }
1869
1870 auto *ide = (ImageDLEvent *)levent;
1871
1872 MetadataLookup *lookup = ide->m_item;
1873
1874 if (!lookup)
1875 return;
1876
1877 HandleDownloadedImages(lookup);
1878 }
1879 else if (levent->type() == ImageDLFailureEvent::kEventType)
1880 {
1881 if (m_busyPopup)
1882 {
1883 m_busyPopup->Close();
1884 m_busyPopup = nullptr;
1885 }
1886 MythErrorNotification n(tr("Failed to retrieve image(s)"),
1887 tr("Schedule Editor"),
1888 tr("Check logs"));
1890 }
1891 else if (levent->type() == DialogCompletionEvent::kEventType)
1892 {
1893 auto *dce = (DialogCompletionEvent*)(levent);
1894
1895 const QString resultid = dce->GetId();
1897 info.url = dce->GetResultText();
1898
1899 if (resultid == "coverart")
1900 {
1902 }
1903 else if (resultid == "fanart")
1904 {
1906 }
1907 else if (resultid == "banner")
1908 {
1910 }
1911
1914
1915 ValuesChanged();
1916 }
1917
1918}
1919
1921
1928 SchedOptMixin *other)
1929 : m_screen(&screen), m_rule(rule), m_other(other),
1930 m_haveRepeats(gCoreContext->GetBoolSetting("HaveRepeats", false))
1931{
1932}
1933
1935{
1936 if (!m_rule)
1937 return;
1938
1940 UIUtilE::Assign(m_screen, m_prioritySpin, "priority", err);
1941 else
1943
1945 UIUtilE::Assign(m_screen, m_startoffsetSpin, "startoffset", err);
1946 else
1948
1950 UIUtilE::Assign(m_screen, m_endoffsetSpin, "endoffset", err);
1951 else
1953
1955 UIUtilE::Assign(m_screen, m_dupmethodList, "dupmethod", err);
1956 else
1958
1960 UIUtilE::Assign(m_screen, m_dupscopeList, "dupscope", err);
1961 else
1963
1965 UIUtilE::Assign(m_screen, m_autoExtendList, "autoextend", err);
1966 else
1968
1969 if (m_other && !m_other->m_inputList)
1970 UIUtilE::Assign(m_screen, m_inputList, "input", err);
1971 else
1973
1975 UIUtilE::Assign(m_screen, m_ruleactiveCheck, "ruleactive", err);
1976 else
1978
1980}
1981
1983{
1984 if (!m_rule)
1985 return;
1986
1987 // Priority
1988 if (m_prioritySpin)
1989 {
1990 if (!m_loaded)
1991 m_prioritySpin->SetRange(-99,99,1,5);
1993 }
1994
1995 // Start Offset
1997 {
1998 if (!m_loaded)
1999 m_startoffsetSpin->SetRange(480,-480,1,10);
2001 }
2002
2003 // End Offset
2004 if (m_endoffsetSpin)
2005 {
2006 if (!m_loaded)
2007 m_endoffsetSpin->SetRange(-480,480,1,10);
2009 }
2010
2011 // Duplicate Match Type
2012 if (m_dupmethodList)
2013 {
2014 if (!m_loaded)
2015 {
2017
2033
2034 m_rule->m_dupMethod = dupMethod;
2035 }
2037 }
2038
2039 // Duplicate Matching Scope
2040 if (m_dupscopeList)
2041 {
2042 if (!m_loaded)
2043 {
2055 {
2056 int value = static_cast<int>(kDupsNewEpi|kDupsInAll);
2059 QVariant::fromValue(value));
2060 }
2061 }
2063 }
2064
2065 // Auto Extend Services
2066 if (m_autoExtendList)
2067 {
2068 if (!m_loaded)
2069 {
2079 }
2081 }
2082
2083 // Preferred Input
2084 if (m_inputList)
2085 {
2086 if (!m_loaded)
2087 {
2089 QObject::tr("Use any available input"),
2090 QVariant::fromValue(0));
2091
2092 std::vector<uint> inputids = CardUtil::GetSchedInputList();
2093 for (uint id : inputids)
2094 {
2096 QObject::tr("Prefer input %1")
2097 .arg(CardUtil::GetDisplayName(id)), id);
2098 }
2099 }
2101 }
2102
2103 bool isOverride = (m_rule->m_type != kNotRecording &&
2106
2107 // Active/Disabled
2109 {
2111 m_ruleactiveCheck->SetEnabled(isOverride);
2112 }
2113
2114 // Record new and repeat
2115 if (m_newrepeatList)
2116 {
2117 if (!m_loaded)
2118 {
2120 QObject::tr("Record new and repeat "
2121 "episodes"), toVariant(kDupsUnset));
2123 QObject::tr("Record new episodes only"),
2125 }
2126 RecordingDupInType value =
2129 }
2130
2131 m_loaded = true;
2132
2133 RuleChanged();
2134}
2135
2137{
2138 if (!m_rule)
2139 return;
2140
2141 if (m_prioritySpin)
2145 if (m_endoffsetSpin)
2147 if (m_dupmethodList)
2149 (m_dupmethodList->GetDataValue().toInt());
2150 if (m_dupscopeList)
2151 {
2152 int mask = ((m_other && m_other->m_newrepeatList) ||
2154 int val = ((m_rule->m_dupIn & ~mask) |
2155 m_dupscopeList->GetDataValue().toInt());
2156 m_rule->m_dupIn = static_cast<RecordingDupInType>(val);
2157 }
2158 if (m_autoExtendList)
2159 {
2160 int val = m_autoExtendList->GetDataValue().toInt();
2161 m_rule->m_autoExtend = static_cast<AutoExtendType>(val);
2162 }
2163 if (m_inputList)
2167 if (m_newrepeatList)
2168 {
2169 int val = ((m_rule->m_dupIn & ~kDupsNewEpi) |
2170 m_newrepeatList->GetDataValue().toInt());
2171 m_rule->m_dupIn = static_cast<RecordingDupInType>(val);
2172 }
2173}
2174
2176{
2177 if (!m_rule)
2178 return;
2179
2180 bool isScheduled = (m_rule->m_type != kNotRecording &&
2182 bool isSingle = (m_rule->m_type == kSingleRecord ||
2184 bool isManual = (m_rule->m_searchType == kManualSearch);
2185
2186 if (m_prioritySpin)
2187 m_prioritySpin->SetEnabled(isScheduled);
2189 m_startoffsetSpin->SetEnabled(isScheduled);
2190 if (m_endoffsetSpin)
2191 m_endoffsetSpin->SetEnabled(isScheduled);
2192 if (m_dupmethodList)
2193 {
2195 isScheduled && !isSingle &&
2196 (!isManual || m_rule->m_dupMethod != kDupCheckNone));
2197 }
2198 if (m_dupscopeList)
2199 m_dupscopeList->SetEnabled(isScheduled && !isSingle &&
2201 if (m_inputList)
2202 m_inputList->SetEnabled(isScheduled);
2203 bool isOverride = (m_rule->m_type != kNotRecording &&
2207 m_ruleactiveCheck->SetEnabled(isOverride);
2208 if (m_newrepeatList)
2209 m_newrepeatList->SetEnabled(isScheduled && !isSingle && m_haveRepeats);
2210}
2211
2213{
2214 if (!item || !m_rule)
2215 return;
2216
2218 (item->GetData().toInt());
2219
2220 if (m_dupscopeList)
2222}
2223
2225
2232{
2233 if (!m_rule)
2234 return;
2235
2236 if (m_other && !m_other->m_filtersList)
2237 UIUtilE::Assign(m_screen, m_filtersList, "filters", err);
2238 else
2240
2241 UIUtilW::Assign(m_screen, m_activeFiltersList, "activefilters");
2244}
2245
2247{
2248 if (!m_rule)
2249 return;
2250
2251 if (!m_loaded)
2252 {
2254
2255 query.prepare("SELECT filterid, description, newruledefault "
2256 "FROM recordfilter ORDER BY filterid");
2257
2258 if (query.exec())
2259 {
2260 while (query.next())
2261 {
2262 m_descriptions << QCoreApplication::translate("SchedFilterEditor",
2263 query.value(1).toString().toUtf8().constData());
2264 }
2265 }
2266 m_loaded = true;
2267 }
2268
2271
2272 MythUIButtonListItem *button = nullptr;
2273 QStringList::iterator Idesc;
2274 int idx = 0;
2275 bool not_empty = m_filtersList && !m_filtersList->IsEmpty();
2276 for (Idesc = m_descriptions.begin(), idx = 0;
2277 Idesc != m_descriptions.end(); ++Idesc, ++idx)
2278 {
2279 bool active = (m_rule->m_filter & (1 << idx)) != 0U;
2280 if (m_filtersList)
2281 {
2282 if (not_empty)
2283 button = m_filtersList->GetItemAt(idx);
2284 else
2285 button = new MythUIButtonListItem(m_filtersList, *Idesc, idx);
2286 button->setCheckable(true);
2289 }
2290 if (active && m_activeFiltersList)
2291 {
2292 /* Create a simple list of active filters the theme can
2293 use for informational purposes. */
2295 *Idesc, idx);
2296 button->setCheckable(false);
2297 }
2298 }
2299
2301 {
2303 QObject::tr("None"), idx);
2304 button->setCheckable(false);
2305 }
2306
2307 RuleChanged();
2308}
2309
2311{
2312 if (!m_rule || !m_filtersList)
2313 return;
2314
2315 // Iterate through button list, and build the mask
2316 uint32_t filter_mask = 0;
2317
2318 int end = m_filtersList->GetCount();
2319 for (int idx = 0; idx < end; ++idx)
2320 {
2322 if (button != nullptr &&
2324 filter_mask |= (1 << button->GetData().value<uint32_t>());
2325 }
2326 m_rule->m_filter = filter_mask;
2327}
2328
2330{
2331 if (!m_rule)
2332 return;
2333
2334 bool enabled = m_rule->m_type != kNotRecording &&
2336 if (m_filtersList)
2337 m_filtersList->SetEnabled(enabled);
2340}
2341
2343{
2347}
2348
2349
2351
2358{
2359 if (!m_rule)
2360 return;
2361
2363 UIUtilE::Assign(m_screen, m_recprofileList, "recprofile", err);
2364 else
2366
2368 UIUtilE::Assign(m_screen, m_recgroupList, "recgroup", err);
2369 else
2371
2373 UIUtilE::Assign(m_screen, m_storagegroupList, "storagegroup", err);
2374 else
2376
2378 UIUtilE::Assign(m_screen, m_playgroupList, "playgroup", err);
2379 else
2381
2382 if (m_other && !m_other->m_maxepSpin)
2383 UIUtilE::Assign(m_screen, m_maxepSpin, "maxepisodes", err);
2384 else
2385 UIUtilW::Assign(m_screen, m_maxepSpin, "maxepisodes");
2386
2388 UIUtilE::Assign(m_screen, m_maxbehaviourList, "maxnewest", err);
2389 else
2391
2393 UIUtilE::Assign(m_screen, m_autoexpireCheck, "autoexpire", err);
2394 else
2396}
2397
2399{
2400 if (!m_rule)
2401 return;
2402
2403 QString label;
2404 QStringList groups;
2405 QStringList::Iterator it;
2407
2408 // Recording Profile
2409 if (m_recprofileList)
2410 {
2411 if (!m_loaded)
2412 {
2413 label = QObject::tr("Record using the %1 profile");
2414
2416 label.arg(QObject::tr("Default")),
2417 QVariant::fromValue(QString("Default")));
2418 // LiveTV profile - it's for LiveTV not scheduled recordings??
2420 label.arg(QObject::tr("LiveTV")),
2421 QVariant::fromValue(QString("LiveTV")));
2423 label.arg(QObject::tr("High Quality")),
2424 QVariant::fromValue(QString("High Quality")));
2426 label.arg(QObject::tr("Low Quality")),
2427 QVariant::fromValue(QString("Low Quality")));
2428 }
2430 }
2431
2432 // Recording Group
2433 if (m_recgroupList)
2434 {
2435 if (!m_loaded)
2436 {
2437 label = QObject::tr("Include in the \"%1\" recording group");
2439 QObject::tr("Create a new recording group"),
2440 QVariant::fromValue(QString("__NEW_GROUP__")));
2441
2442 query.prepare("SELECT recgroupid, recgroup FROM recgroups "
2443 "WHERE recgroup <> 'Deleted' AND "
2444 " recgroup <> 'LiveTV' "
2445 "ORDER BY special DESC, recgroup ASC"); // Special groups first
2446 if (query.exec())
2447 {
2448 while (query.next())
2449 {
2450 int id = query.value(0).toInt();
2451 QString name = query.value(1).toString();
2452
2453 if (name == "Default")
2454 name = QObject::tr("Default");
2455 new MythUIButtonListItem(m_recgroupList, label.arg(name),
2456 QVariant::fromValue(id));
2457 }
2458 }
2459
2460 }
2462 }
2463
2464 // Storage Group
2466 {
2467 if (!m_loaded)
2468 {
2469 label = QObject::tr("Store in the \"%1\" storage group");
2471 label.arg(QObject::tr("Default")),
2472 QVariant::fromValue(QString("Default")));
2473
2475 for (it = groups.begin(); it != groups.end(); ++it)
2476 {
2477 if ((*it).compare("Default", Qt::CaseInsensitive) != 0)
2479 label.arg(*it), QVariant::fromValue(*it));
2480 }
2481 }
2483 }
2484
2485 // Playback Group
2486 if (m_playgroupList)
2487 {
2488 if (!m_loaded)
2489 {
2490 label = QObject::tr("Use \"%1\" playback group settings");
2492 label.arg(QObject::tr("Default")),
2493 QVariant::fromValue(QString("Default")));
2494
2495 groups = PlayGroup::GetNames();
2496 for (it = groups.begin(); it != groups.end(); ++it)
2497 {
2498 new MythUIButtonListItem(m_playgroupList, label.arg(*it),
2499 QVariant::fromValue(*it));
2500 }
2501 }
2503 }
2504
2505 // Max Episodes
2506 if (m_maxepSpin)
2507 {
2508 if (!m_loaded)
2509 {
2510 int maxEpisodes = m_rule->m_maxEpisodes;
2511 m_maxepSpin->SetRange(0,100,1,5);
2512 m_rule->m_maxEpisodes = maxEpisodes;
2513 }
2515 }
2516
2517 // Max Episode Behaviour
2519 {
2520 if (!m_loaded)
2521 {
2523 QObject::tr("Don't record if this would exceed the max "
2524 "episodes"), QVariant::fromValue(false));
2526 QObject::tr("Delete oldest if this would exceed the max "
2527 "episodes"), QVariant::fromValue(true));
2528 }
2530 }
2531
2532 // Auto-Expire
2534 {
2536 }
2537
2538 m_loaded = true;
2539
2540 RuleChanged();
2541}
2542
2544{
2545 if (!m_rule)
2546 return;
2547
2548 if (m_recprofileList)
2550
2551 if (m_recgroupList)
2552 {
2553 // If the user selected 'Create a new regroup' but failed to enter a
2554 // name when prompted, restore the original value
2555 if (m_recgroupList->GetDataValue().toString() == "__NEW_GROUP__")
2558 }
2559
2562
2563 if (m_playgroupList)
2565
2566 if (m_maxepSpin)
2568
2571
2574}
2575
2577{
2578 if (!m_rule)
2579 return;
2580
2581 bool isScheduled = (m_rule->m_type != kNotRecording &&
2583 bool isSingle = (m_rule->m_type == kSingleRecord ||
2585
2586 if (m_recprofileList)
2587 m_recprofileList->SetEnabled(isScheduled);
2588 if (m_recgroupList)
2589 m_recgroupList->SetEnabled(isScheduled);
2591 m_storagegroupList->SetEnabled(isScheduled);
2592 if (m_playgroupList)
2593 m_playgroupList->SetEnabled(isScheduled);
2594 if (m_maxepSpin)
2595 m_maxepSpin->SetEnabled(isScheduled && !isSingle);
2597 m_maxbehaviourList->SetEnabled(isScheduled && !isSingle &&
2598 m_rule->m_maxEpisodes != 0);
2600 m_autoexpireCheck->SetEnabled(isScheduled);
2601}
2602
2604{
2605 if (!item || !m_rule)
2606 return;
2607
2608 m_rule->m_maxEpisodes = item->GetData().toInt();
2609
2612}
2613
2615{
2616 if (!m_rule)
2617 return;
2618
2619 if (m_recgroupList->GetDataValue().toString() != "__NEW_GROUP__")
2620 return;
2621
2622 MythScreenStack *popupStack = GetMythMainWindow()->GetStack("popup stack");
2623
2624 QString label =
2625 QObject::tr("New Recording group name: ");
2626
2627 auto *textDialog = new MythTextInputDialog(popupStack, label,
2628 static_cast<InputFilter>(FilterSymbols | FilterPunct));
2629
2630 textDialog->SetReturnEvent(m_screen, "newrecgroup");
2631
2632 if (textDialog->Create())
2633 popupStack->AddScreen(textDialog, false);
2634}
2635
2636void StoreOptMixin::SetRecGroup(int recgroupID, QString recgroup)
2637{
2638 if (!m_rule || recgroupID <= 0)
2639 return;
2640
2641 if (m_recgroupList)
2642 {
2643 recgroup = recgroup.trimmed();
2644 if (recgroup.isEmpty())
2645 return;
2646
2647 QString label = QObject::tr("Include in the \"%1\" recording group");
2648 auto *item = new MythUIButtonListItem(m_recgroupList, label.arg(recgroup),
2649 QVariant::fromValue(recgroupID));
2651
2653 {
2655 label.arg(recgroup), QVariant::fromValue(recgroupID));
2657 }
2658 }
2659}
2660
2661int StoreOptMixin::CreateRecordingGroup(const QString& groupName)
2662{
2663 int groupID = -1;
2665
2666 query.prepare("INSERT INTO recgroups SET recgroup = :NAME, "
2667 "displayname = :DISPLAYNAME");
2668 query.bindValue(":NAME", groupName);
2669 query.bindValue(":DISPLAYNAME", groupName);
2670
2671 if (query.exec())
2672 groupID = query.lastInsertId().toInt();
2673
2674 if (groupID <= 0)
2675 LOG(VB_GENERAL, LOG_ERR, QString("Could not create recording group (%1). "
2676 "Does it already exist?").arg(groupName));
2677
2678 return groupID;
2679}
2680
2682
2689{
2690 if (!m_rule)
2691 return;
2692
2694 UIUtilE::Assign(m_screen, m_commflagCheck, "autocommflag", err);
2695 else
2696 UIUtilW::Assign(m_screen, m_commflagCheck, "autocommflag");
2697
2699 UIUtilE::Assign(m_screen, m_transcodeCheck, "autotranscode", err);
2700 else
2701 UIUtilW::Assign(m_screen, m_transcodeCheck, "autotranscode");
2702
2704 UIUtilE::Assign(m_screen, m_transcodeprofileList, "transcodeprofile", err);
2705 else
2706 UIUtilW::Assign(m_screen, m_transcodeprofileList, "transcodeprofile");
2707
2709 UIUtilE::Assign(m_screen, m_userjob1Check, "userjob1", err);
2710 else
2712
2714 UIUtilE::Assign(m_screen, m_userjob2Check, "userjob2", err);
2715 else
2717
2719 UIUtilE::Assign(m_screen, m_userjob3Check, "userjob3", err);
2720 else
2722
2724 UIUtilE::Assign(m_screen, m_userjob4Check, "userjob4", err);
2725 else
2727
2729}
2730
2732{
2733 if (!m_rule)
2734 return;
2735
2736 // Auto-commflag
2737 if (m_commflagCheck)
2738 {
2740 }
2741
2742 // Auto-transcode
2743 if (m_transcodeCheck)
2744 {
2746 }
2747
2748 // Transcode Method
2750 {
2751 if (!m_loaded)
2752 {
2753 QMap<int, QString> profiles = RecordingProfile::GetTranscodingProfiles();
2754 QMap<int, QString>::iterator it;
2755 for (it = profiles.begin(); it != profiles.end(); ++it)
2756 {
2758 QVariant::fromValue(it.key()));
2759 }
2760 }
2762 }
2763
2764 // User Job #1
2765 if (m_userjob1Check)
2766 {
2767 if (!m_loaded)
2768 {
2769 MythUIText *userjob1Text = nullptr;
2770 UIUtilW::Assign(m_screen, userjob1Text, "userjob1text");
2771 if (userjob1Text)
2772 userjob1Text->SetText(QObject::tr("Run '%1'")
2773 .arg(gCoreContext->GetSetting("UserJobDesc1", "User Job 1")));
2774 }
2776 }
2777
2778 // User Job #2
2779 if (m_userjob2Check)
2780 {
2781 if (!m_loaded)
2782 {
2783 MythUIText *userjob2Text = nullptr;
2784 UIUtilW::Assign(m_screen, userjob2Text, "userjob2text");
2785 if (userjob2Text)
2786 userjob2Text->SetText(QObject::tr("Run '%1'")
2787 .arg(gCoreContext->GetSetting("UserJobDesc2", "User Job 2")));
2788 }
2790 }
2791
2792 // User Job #3
2793 if (m_userjob3Check)
2794 {
2795 if (!m_loaded)
2796 {
2797 MythUIText *userjob3Text = nullptr;
2798 UIUtilW::Assign(m_screen, userjob3Text, "userjob3text");
2799 if (userjob3Text)
2800 userjob3Text->SetText(QObject::tr("Run '%1'")
2801 .arg(gCoreContext->GetSetting("UserJobDesc3", "User Job 3")));
2802 }
2804 }
2805
2806 // User Job #4
2807 if (m_userjob4Check)
2808 {
2809 if (!m_loaded)
2810 {
2811 MythUIText *userjob4Text = nullptr;
2812 UIUtilW::Assign(m_screen, userjob4Text, "userjob4text");
2813 if (userjob4Text)
2814 userjob4Text->SetText(QObject::tr("Run '%1'")
2815 .arg(gCoreContext->GetSetting("UserJobDesc4", "User Job 4")));
2816 }
2818 }
2819
2820 // Auto Metadata Lookup
2822 {
2824 }
2825
2826 m_loaded = true;
2827
2828 RuleChanged();
2829}
2830
2832{
2833 if (!m_rule)
2834 return;
2835
2836 if (m_commflagCheck)
2838 if (m_transcodeCheck)
2842 if (m_userjob1Check)
2844 if (m_userjob2Check)
2846 if (m_userjob3Check)
2848 if (m_userjob4Check)
2853}
2854
2856{
2857 if (!m_rule)
2858 return;
2859
2860 bool isScheduled = (m_rule->m_type != kNotRecording &&
2862
2863 if (m_commflagCheck)
2864 m_commflagCheck->SetEnabled(isScheduled);
2865 if (m_transcodeCheck)
2866 m_transcodeCheck->SetEnabled(isScheduled);
2868 m_transcodeprofileList->SetEnabled(isScheduled &&
2870 if (m_userjob1Check)
2871 m_userjob1Check->SetEnabled(isScheduled);
2872 if (m_userjob2Check)
2873 m_userjob2Check->SetEnabled(isScheduled);
2874 if (m_userjob3Check)
2875 m_userjob3Check->SetEnabled(isScheduled);
2876 if (m_userjob4Check)
2877 m_userjob4Check->SetEnabled(isScheduled);
2879 m_metadataLookupCheck->SetEnabled(isScheduled);
2880}
2881
2883{
2884 if (!m_rule)
2885 return;
2886
2887 m_rule->m_autoTranscode = enable;
2888
2891}
static std::vector< uint > GetSchedInputList(void)
Definition: cardutil.cpp:2923
static QString GetDisplayName(uint inputid)
Definition: cardutil.cpp:1876
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
Mixin for Filters.
static void ToggleSelected(MythUIButtonListItem *item)
FilterOptMixin * m_other
MythUIButtonList * m_activeFiltersList
RecordingRule * m_rule
void Create(bool *err)
MythScreenType * m_screen
QStringList m_descriptions
void RuleChanged(void)
MythUIButtonList * m_filtersList
void SetRule(RecordingRule *rule)
static const Type kEventType
static const Type kEventType
void haveResult(ArtworkInfo, VideoArtworkType)
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
QVariant value(int i) const
Definition: mythdbcon.h:204
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
QVariant lastInsertId()
Return the id of the last inserted row.
Definition: mythdbcon.cpp:935
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
void addLookup(MetadataLookup *lookup)
addLookup: Add lookup to bottom of the queue MetadataDownload::m_lookupList takes ownership of the gi...
static const Type kEventType
static const Type kEventType
static const Type kEventType
void Lookup(ProgramInfo *pginfo, bool automatic=true, bool getimages=true, bool allowgeneric=false)
void addDownloads(MetadataLookup *lookup)
addLookup: Add lookup to bottom of the queue MetadataDownload::m_downloadList takes ownership of the ...
static const Type kEventType
static const Type kEventType
uint GetSeason() const
QVariant GetData() const
ArtworkList GetArtwork(VideoArtworkType type) const
void toMap(InfoMap &map)
void SetAutomatic(bool autom)
DownloadMap GetDownloads() const
QString GetInetref() const
void SetData(QVariant data)
uint GetEpisode() const
Select artwork and inetref for recordings.
bool Create(void) override
ArtworkMap m_artworkMap
void Load(void) override
MythUIButton * m_onlineFanartButton
void customEvent(QEvent *event) override
MythUIImage * m_fanart
void HandleDownloadedImages(MetadataLookup *lookup)
MythUIBusyDialog * m_busyPopup
MythUIButton * m_localCoverartButton
static QStringList GetSupportedImageExtensionFilter()
void FindNetArt(VideoArtworkType type)
void OnSearchListSelection(const RefCountHandler< MetadataLookup > &lookup)
MetadataImageDownload * m_imageDownload
MetadataOptions(MythScreenStack *parent, ScheduleEditor &editor, RecordingRule &rule, RecordingInfo *recinfo)
MythUIButton * m_inetrefClear
MythUIButton * m_localFanartButton
MythUIButton * m_queryButton
MythUISpinBox * m_seasonSpin
void OnArtworkSearchDone(MetadataLookup *lookup)
MythUIButton * m_onlineCoverartButton
bool CanSetArtwork(void)
void QueryComplete(MetadataLookup *lookup)
MythUITextEdit * m_inetrefEdit
~MetadataOptions() override
void OnImageSearchListSelection(const ArtworkInfo &info, VideoArtworkType type)
MetadataLookup * CreateLookup(MetadataType mtype)
static void FindImagePopup(const QString &prefix, const QString &prefixAlt, QObject &inst, const QString &returnEvent)
MythUISpinBox * m_episodeSpin
MetadataFactory * m_metadataFactory
MythUIButton * m_onlineBannerButton
void Save(void) override
MythUIImage * m_coverart
MythScreenStack * m_popupStack
MetadataDownload * m_imageLookup
void CreateBusyDialog(const QString &title)
MythUIButton * m_localBannerButton
MythUIImage * m_banner
void haveResult(RefCountHandler< MetadataLookup >)
Dialog asking for user confirmation.
QString GetSetting(const QString &key, const QString &defaultval="")
QString GetMasterHostName(void)
Basic menu dialog, message and a list of options.
MythScreenStack * GetMainStack()
MythScreenStack * GetStack(const QString &Stackname)
bool Queue(const MythNotification &notification)
Queue a notification Queue() is thread-safe and can be called from anywhere.
virtual void PopScreen(MythScreenType *screen=nullptr, bool allowFade=true, bool deleteScreen=true)
virtual void AddScreen(MythScreenType *screen, bool allowFade=true)
Screen in which all other widgets are contained and rendered.
void BuildFocusList(void)
MythUIType * GetFocusWidget(void) const
MythScreenStack * GetScreenStack() const
bool keyPressEvent(QKeyEvent *event) override
Key event handler.
virtual void Close()
Dialog prompting the user to enter a text string.
bool Create(void) override
void setCheckable(bool flag)
CheckState state() const
void setChecked(CheckState state)
MythUIButtonListItem * GetItemCurrent() const
void SetItemCurrent(MythUIButtonListItem *item)
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 SetValueByData(const QVariant &data)
QVariant GetDataValue() const
void itemSelected(MythUIButtonListItem *item)
void Clicked()
void SetCheckState(MythUIStateType::StateType state)
void toggled(bool)
bool GetBooleanCheckState(void) const
virtual void SetTextFromMap(const InfoMap &infoMap)
bool Load(bool allowLoadInBackground=true, bool forceStat=false)
Load the image(s), wraps ImageLoader::LoadImage()
void SetFilename(const QString &filename)
Must be followed by a call to Load() to load the image.
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
int GetIntValue(void) const override
Definition: mythuispinbox.h:39
QString GetText(void) const
void SetText(const QString &text, bool moveCursor=true)
All purpose text widget, displays a text string.
Definition: mythuitext.h:29
virtual void SetText(const QString &text)
Definition: mythuitext.cpp:115
void SetCanTakeFocus(bool set=true)
Set whether this widget can take focus.
Definition: mythuitype.cpp:362
void SetEnabled(bool enable)
void LosingFocus(void)
static QStringList GetNames(void)
Definition: playgroup.cpp:236
Select post-processing options.
void TranscodeChanged(bool enable)
bool Create(void) override
void Load(void) override
void Save(void) override
PostProcEditor(MythScreenStack *parent, ScheduleEditor &editor, RecordingRule &rule, RecordingInfo *recinfo)
Mixin for post processing.
PostProcMixin * m_other
MythScreenType * m_screen
void SetRule(RecordingRule *rule)
MythUICheckBox * m_userjob4Check
MythUICheckBox * m_transcodeCheck
MythUICheckBox * m_userjob2Check
MythUICheckBox * m_metadataLookupCheck
void RuleChanged(void)
MythUICheckBox * m_userjob1Check
void Create(bool *err)
RecordingRule * m_rule
MythUICheckBox * m_userjob3Check
MythUICheckBox * m_commflagCheck
MythUIButtonList * m_transcodeprofileList
void TranscodeChanged(bool enable)
Holds information on recordings and videos.
Definition: programinfo.h:70
uint GetRecordingRuleID(void) const
Definition: programinfo.h:455
uint GetEpisode(void) const
Definition: programinfo.h:370
uint GetYearOfInitialRelease(void) const
Definition: programinfo.h:426
virtual void ToMap(InfoMap &progMap, bool showrerecord=false, uint star_range=10, uint date_format=0) const
Converts ProgramInfo into QString QHash containing each field in ProgramInfo converted into localized...
CategoryType GetCategoryType(void) const
Definition: programinfo.h:444
uint GetSeason(void) const
Definition: programinfo.h:369
Holds information on a TV Program one might wish to record.
Definition: recordinginfo.h:36
static const QRegularExpression kReSearchTypeName
static QMap< int, QString > GetTranscodingProfiles()
Internal representation of a recording rule, mirrors the record table.
Definition: recordingrule.h:30
RecordingType m_type
QString m_station
Definition: recordingrule.h:99
void UseTempTable(bool usetemp, const QString &table="record_tmp")
QString m_category
Definition: recordingrule.h:83
QString m_inetref
Definition: recordingrule.h:88
bool LoadTemplate(const QString &title, const QString &category="Default", const QString &categoryType="Default")
RecSearchType m_searchType
bool LoadByProgram(const ProgramInfo *proginfo)
unsigned m_filter
QString m_storageGroup
int m_recordID
Unique Recording Rule ID.
Definition: recordingrule.h:71
RecordingDupInType m_dupIn
QString m_title
Definition: recordingrule.h:78
void ToMap(InfoMap &infoMap, uint date_format=0) const
QString m_recProfile
bool m_isInactive
Recording rule is enabled?
Definition: recordingrule.h:75
static QStringList GetTemplateNames(void)
QString m_playGroup
bool Save(bool sendSig=true)
QString m_subtitle
Definition: recordingrule.h:80
RecordingDupMethodType m_dupMethod
bool Load(bool asTemplate=false)
Load a single rule from the recorded table.
bool Delete(bool sendSig=true)
QString m_seriesid
Definition: recordingrule.h:85
bool IsLoaded() const
Definition: recordingrule.h:56
bool m_autoMetadataLookup
AutoExtendType m_autoExtend
virtual int DecrRef(void)
Decrements reference count and deletes on 0.
virtual int IncrRef(void)
Increments reference count.
SchedEditChild(MythScreenStack *parent, const QString &name, ScheduleEditor &editor, RecordingRule &rule, RecordingInfo *recinfo)
MythUIButton * m_previewButton
void Close(void) override
MythUIButton * m_saveButton
MythUIButton * m_backButton
RecordingRule * m_recordingRule
bool keyPressEvent(QKeyEvent *event) override
Key event handler.
ScheduleEditor * m_editor
void SetTextFromMaps(void)
virtual void Save(void)=0
RecordingInfo * m_recInfo
void Load(void) override=0
virtual bool CreateEditChild(const QString &xmlfile, const QString &winname, bool isTemplate)
void Closing(void)
Select schedule filters.
SchedFilterEditor(MythScreenStack *parent, ScheduleEditor &editor, RecordingRule &rule, RecordingInfo *recinfo)
static void ToggleSelected(MythUIButtonListItem *item)
void Save(void) override
void Load(void) override
bool Create(void) override
Select schedule options.
bool Create(void) override
void Load(void) override
void Save(void) override
MythUIButton * m_filtersButton
void DupMethodChanged(MythUIButtonListItem *item)
SchedOptEditor(MythScreenStack *parent, ScheduleEditor &editor, RecordingRule &rule, RecordingInfo *recinfo)
Mixin for schedule options.
MythUISpinBox * m_startoffsetSpin
MythUISpinBox * m_prioritySpin
SchedOptMixin * m_other
MythUICheckBox * m_ruleactiveCheck
void Create(bool *err)
MythUIButtonList * m_dupmethodList
MythUISpinBox * m_endoffsetSpin
void SetRule(RecordingRule *rule)
void DupMethodChanged(MythUIButtonListItem *item)
MythUIButtonList * m_dupscopeList
MythUIButtonList * m_newrepeatList
MythScreenType * m_screen
MythUIButtonList * m_autoExtendList
RecordingRule * m_rule
SchedOptMixin(MythScreenType &screen, RecordingRule *rule, SchedOptMixin *other=nullptr)
MythUIButtonList * m_inputList
void RuleChanged(void)
virtual void ShowDetails(void) const
Show the Program Details screen.
virtual void ShowGuide(void) const
Show the program guide.
virtual void ShowUpcoming(void) const
Show the upcoming recordings for this title.
virtual void ShowPrevious(void) const
Show the previous recordings for this recording rule.
Construct a recording schedule.
void TranscodeChanged(bool enable)
ScheduleEditor(MythScreenStack *parent, RecordingInfo *recinfo, TV *player=nullptr)
void ruleSaved(int ruleId)
MythUIButton * m_schedInfoButton
MythUIButtonList * m_rulesList
bool Create(void) override
MythUIButton * m_saveButton
void DupMethodChanged(MythUIButtonListItem *item)
RecordingRule * m_recordingRule
void ChildClosing(void)
void customEvent(QEvent *event) override
void ShowStoreOpt(void)
void ruleDeleted(int ruleId)
void ShowSchedOpt(void)
MythUIButton * m_schedOptButton
void PromptForRecGroup(void)
MythUIButton * m_postProcButton
void DeleteRule(void)
void templateLoaded(void)
void LoadTemplate(const QString &name)
void Load(void) override
Load data which will ultimately be displayed on-screen or used to determine what appears on-screen (S...
void showTemplateMenu(void)
void ShowPreviousView(void)
~ScheduleEditor() override
SchedEditChild * m_child
static void * RunScheduleEditor(ProgramInfo *proginfo, void *player=nullptr)
Callback.
void showUpcomingByTitle(void)
MythUIButton * m_storeOptButton
void ShowNextView(void)
void showMenu(void)
void MaxEpisodesChanged(MythUIButtonListItem *item)
void showUpcomingByRule(void)
void ShowPreview(void)
MythUIButton * m_metadataButton
MythUIButton * m_previewButton
void ShowFilters(void)
MythUIButton * m_cancelButton
RecordingInfo * m_recInfo
void ShowPostProc(void)
void Close(void) override
static void FilterChanged(MythUIButtonListItem *item)
bool keyPressEvent(QKeyEvent *event) override
Key event handler.
void ShowMetadataOptions(void)
MythUIButton * m_filtersButton
void ShowSchedInfo(void)
static QStringList getRecordingsGroups(void)
static QString generate_file_url(const QString &storage_group, const QString &host, const QString &path)
Select storage options.
StoreOptEditor(MythScreenStack *parent, ScheduleEditor &editor, RecordingRule &rule, RecordingInfo *recinfo)
void Save(void) override
void PromptForRecGroup(void)
void MaxEpisodesChanged(MythUIButtonListItem *item)
void Load(void) override
void customEvent(QEvent *event) override
bool Create(void) override
Mixin for storage options.
void SetRule(RecordingRule *rule)
MythUISpinBox * m_maxepSpin
void MaxEpisodesChanged(MythUIButtonListItem *item)
MythUIButtonList * m_recprofileList
void PromptForRecGroup(void)
void RuleChanged(void)
MythUIButtonList * m_storagegroupList
MythUIButtonList * m_maxbehaviourList
StoreOptMixin * m_other
RecordingRule * m_rule
MythScreenType * m_screen
MythUIButtonList * m_playgroupList
MythUIButtonList * m_recgroupList
MythUICheckBox * m_autoexpireCheck
static int CreateRecordingGroup(const QString &groupName)
void Create(bool *err)
void SetRecGroup(int recgroupID, QString recgroup)
void RequestEmbedding(bool Embed, const QRect &Rect={}, const QStringList &Data={})
Control TV playback.
Definition: tv_play.h:155
static bool LoadWindowFromXML(const QString &xmlfile, const QString &windowname, MythUIType *parent)
unsigned int uint
Definition: compat.h:68
@ kLookupSearch
LookupType
@ kProbableTelevision
@ kUnknownVideo
@ kProbableMovie
MetadataType
@ kMetadataRecording
@ kMetadataVideo
QMap< VideoArtworkType, ArtworkInfo > DownloadMap
LookupType GuessLookupType(ProgramInfo *pginfo)
ArtworkMap GetArtwork(const QString &inetref, uint season, bool strict)
bool SetArtwork(const QString &inetref, uint season, const QString &host, const QString &coverart, const QString &fanart, const QString &banner)
QList< ArtworkInfo > ArtworkList
VideoArtworkType
@ kArtworkFanart
@ kArtworkBanner
@ kArtworkCoverart
MythCoreContext * gCoreContext
This global variable contains the MythCoreContext instance for the app.
MythConfirmationDialog * ShowOkPopup(const QString &message, bool showCancel)
Non-blocking version of MythPopupBox::showOkPopup()
#define LOG(_MASK_, _LEVEL_, _QSTRING_)
Definition: mythlogging.h:39
MythNotificationCenter * GetNotificationCenter(void)
MythMainWindow * GetMythMainWindow(void)
QHash< QString, QString > InfoMap
Definition: mythtypes.h:15
InputFilter
@ FilterPunct
@ FilterSymbols
dictionary info
Definition: azlyrics.py:7
@ plRecordid
Definition: proglist.h:30
QString toDescription(RecordingType rectype)
Converts "rectype" into a human readable description.
static QVariant toVariant(RecordingType rectype)
@ kManualSearch
@ kNoSearch
AutoExtendType
RecordingDupInType
@ kDupsInAll
@ kDupsUnset
@ kDupsNewEpi
@ kDupsInRecorded
@ kDupsInOldRecorded
RecordingType
@ kOneRecord
@ kWeeklyRecord
@ kNotRecording
@ kAllRecord
@ kOverrideRecord
@ kSingleRecord
@ kDailyRecord
@ kTemplateRecord
@ kDontRecord
RecordingDupMethodType
@ kDupCheckSubDesc
@ kDupCheckSub
@ kDupCheckSubThenDesc
@ kDupCheckDesc
@ kDupCheckNone
static QString fs1(QT_TRANSLATE_NOOP("SchedFilterEditor", "Identifiable episode"))
static QString fs0(QT_TRANSLATE_NOOP("SchedFilterEditor", "New episode"))
static QString fs8(QT_TRANSLATE_NOOP("SchedFilterEditor", "This time"))
static QString fs7(QT_TRANSLATE_NOOP("SchedFilterEditor", "This series"))
static QString fs10(QT_TRANSLATE_NOOP("SchedFilterEditor", "This channel"))
static QString fs4(QT_TRANSLATE_NOOP("SchedFilterEditor", "Commercial free"))
static QString fs11(QT_TRANSLATE_NOOP("SchedFilterEditor", "No episodes"))
static QString fs3(QT_TRANSLATE_NOOP("SchedFilterEditor", "Prime time"))
static QString fs6(QT_TRANSLATE_NOOP("SchedFilterEditor", "This episode"))
static QString fs9(QT_TRANSLATE_NOOP("SchedFilterEditor", "This day and time"))
static QString fs5(QT_TRANSLATE_NOOP("SchedFilterEditor", "High definition"))
static QString fs2(QT_TRANSLATE_NOOP("SchedFilterEditor", "First showing"))
static bool Assign(ContainerType *container, UIType *&item, const QString &name, bool *err=nullptr)
Definition: mythuiutils.h:27
VERBOSE_PREAMBLE false
Definition: verbosedefs.h:89