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 ret.reserve(exts.size());
1554 for (const auto & ext : std::as_const(exts))
1555 {
1556 ret.append(QString("*.").append(ext));
1557 }
1558
1559 return ret;
1560}
1561
1563{
1564 if (m_inetrefEdit->GetText().isEmpty())
1565 {
1566 ShowOkPopup(tr("You must set a reference number "
1567 "on this rule to set artwork. For items "
1568 "without a metadata source, you can set "
1569 "any unique value."));
1570 return false;
1571 }
1572
1573 return true;
1574}
1575
1577{
1578 auto *lookup = new MetadataLookup();
1579 lookup->SetStep(kLookupSearch);
1580 lookup->SetType(mtype);
1582
1583 if (type == kUnknownVideo)
1584 {
1586 (m_seasonSpin->GetIntValue() == 0 &&
1587 m_episodeSpin->GetIntValue() == 0))
1588 {
1589 lookup->SetSubtype(kProbableMovie);
1590 }
1591 else
1592 {
1593 lookup->SetSubtype(kProbableTelevision);
1594 }
1595 }
1596 else
1597 {
1598 // we could determine the type from the inetref
1599 lookup->SetSubtype(type);
1600 }
1601 lookup->SetAllowGeneric(true);
1602 lookup->SetHandleImages(false);
1603 lookup->SetHost(gCoreContext->GetMasterHostName());
1604 lookup->SetTitle(m_recordingRule->m_title);
1605 lookup->SetSubtitle(m_recordingRule->m_subtitle);
1606 lookup->SetInetref(m_inetrefEdit->GetText());
1607 lookup->SetCollectionref(m_inetrefEdit->GetText());
1608 lookup->SetSeason(m_seasonSpin->GetIntValue());
1609 lookup->SetEpisode(m_episodeSpin->GetIntValue());
1610
1611 return lookup;
1612}
1613
1615{
1616 if (!CanSetArtwork())
1617 return;
1618
1619 QString msg = tr("Searching for available artwork...");
1620 CreateBusyDialog(msg);
1621
1623
1624 lookup->SetAutomatic(true);
1625 lookup->SetData(QVariant::fromValue<VideoArtworkType>(type));
1626 m_imageLookup->addLookup(lookup);
1627}
1628
1630{
1631 if (!lookup)
1632 return;
1633
1634 if (m_busyPopup)
1635 {
1636 m_busyPopup->Close();
1637 m_busyPopup = nullptr;
1638 }
1639
1640 auto type = lookup->GetData().value<VideoArtworkType>();
1641 ArtworkList list = lookup->GetArtwork(type);
1642
1643 if (list.isEmpty())
1644 {
1645 MythWarningNotification n(tr("No image found"), tr("Schedule Editor"));
1647 return;
1648 }
1649
1650 auto *resultsdialog = new ImageSearchResultsDialog(m_popupStack, list, type);
1651
1652 connect(resultsdialog, &ImageSearchResultsDialog::haveResult,
1654
1655 if (resultsdialog->Create())
1656 m_popupStack->AddScreen(resultsdialog);
1657}
1658
1660{
1661 if (!lookup)
1662 return;
1663
1664 DownloadMap map = lookup->GetDownloads();
1665
1666 if (map.isEmpty())
1667 return;
1668
1669 for (DownloadMap::const_iterator i = map.cbegin(); i != map.cend(); ++i)
1670 {
1671 VideoArtworkType type = i.key();
1672 const ArtworkInfo& info = i.value();
1673
1674 if (type == kArtworkCoverart)
1676 else if (type == kArtworkFanart)
1678 else if (type == kArtworkBanner)
1680 }
1681
1684
1685 ValuesChanged();
1686}
1687
1689{
1692
1693 if (m_coverart)
1694 {
1696 m_coverart->Load();
1697 }
1698
1699 if (m_fanart)
1700 {
1702 m_fanart->Load();
1703 }
1704
1705 if (m_banner)
1706 {
1708 m_banner->Load();
1709 }
1710}
1711
1713{
1714 if (levent->type() == MetadataFactoryMultiResult::kEventType)
1715 {
1716 if (m_busyPopup)
1717 {
1718 m_busyPopup->Close();
1719 m_busyPopup = nullptr;
1720 }
1721
1722 auto *mfmr = dynamic_cast<MetadataFactoryMultiResult*>(levent);
1723 if (!mfmr)
1724 return;
1725
1726 MetadataLookupList list = mfmr->m_results;
1727
1728 if (list.count() > 1)
1729 {
1730 int yearindex = -1;
1731
1732 for (int p = 0; p != list.size(); ++p)
1733 {
1734 if (!m_recordingRule->m_seriesid.isEmpty() &&
1735 m_recordingRule->m_seriesid == (list[p])->GetTMSref())
1736 {
1737 MetadataLookup *lookup = list[p];
1738 QueryComplete(lookup);
1739 return;
1740 }
1741 if (m_recInfo &&
1743 (list[p])->GetYear() != 0 &&
1744 m_recInfo->GetYearOfInitialRelease() == (list[p])->GetYear())
1745 {
1746 if (yearindex > -1)
1747 {
1748 LOG(VB_GENERAL, LOG_INFO, "Multiple results matched on year. No definite "
1749 "match could be found based on year alone.");
1750 yearindex = -2;
1751 }
1752 else if (yearindex == -1)
1753 {
1754 LOG(VB_GENERAL, LOG_INFO, "Matched based on year. ");
1755 yearindex = p;
1756 }
1757 }
1758 }
1759
1760 if (yearindex > -1)
1761 {
1762 MetadataLookup *lookup = list[yearindex];
1763 QueryComplete(lookup);
1764 return;
1765 }
1766
1767 LOG(VB_GENERAL, LOG_INFO, "Falling through to selection dialog.");
1768 auto *resultsdialog = new MetadataResultsDialog(m_popupStack, list);
1769
1770 connect(resultsdialog, &MetadataResultsDialog::haveResult,
1772 Qt::QueuedConnection);
1773
1774 if (resultsdialog->Create())
1775 m_popupStack->AddScreen(resultsdialog);
1776 }
1777 }
1778 else if (levent->type() == MetadataFactorySingleResult::kEventType)
1779 {
1780 if (m_busyPopup)
1781 {
1782 m_busyPopup->Close();
1783 m_busyPopup = nullptr;
1784 }
1785
1786 auto *mfsr = dynamic_cast<MetadataFactorySingleResult*>(levent);
1787 if (!mfsr)
1788 return;
1789
1790 MetadataLookup *lookup = mfsr->m_result;
1791
1792 if (!lookup)
1793 return;
1794
1795 QueryComplete(lookup);
1796 }
1797 else if (levent->type() == MetadataFactoryNoResult::kEventType)
1798 {
1799 if (m_busyPopup)
1800 {
1801 m_busyPopup->Close();
1802 m_busyPopup = nullptr;
1803 }
1804
1805 auto *mfnr = dynamic_cast<MetadataFactoryNoResult*>(levent);
1806 if (!mfnr)
1807 return;
1808
1809 QString title = tr("No match found for this recording. You can "
1810 "try entering a TVDB/TMDB number, season, and "
1811 "episode manually.");
1812
1813 auto *okPopup = new MythConfirmationDialog(m_popupStack, title, false);
1814
1815 if (okPopup->Create())
1816 m_popupStack->AddScreen(okPopup);
1817 }
1818 else if (levent->type() == MetadataLookupEvent::kEventType)
1819 {
1820 if (m_busyPopup)
1821 {
1822 m_busyPopup->Close();
1823 m_busyPopup = nullptr;
1824 }
1825
1826 auto *lue = (MetadataLookupEvent *)levent;
1827
1828 MetadataLookupList lul = lue->m_lookupList;
1829
1830 if (lul.isEmpty())
1831 return;
1832
1833 if (lul.count() >= 1)
1834 {
1835 OnArtworkSearchDone(lul[0]);
1836 }
1837 }
1838 else if (levent->type() == MetadataLookupFailure::kEventType)
1839 {
1840 if (m_busyPopup)
1841 {
1842 m_busyPopup->Close();
1843 m_busyPopup = nullptr;
1844 }
1845
1846 auto *luf = (MetadataLookupFailure *)levent;
1847
1848 MetadataLookupList lul = luf->m_lookupList;
1849
1850 if (!lul.empty())
1851 {
1852 QString title = tr("This number, season, and episode combination "
1853 "does not appear to be valid (or the site may "
1854 "be down). Check your information and try "
1855 "again.");
1856
1857 auto *okPopup = new MythConfirmationDialog(m_popupStack, title, false);
1858
1859 if (okPopup->Create())
1860 m_popupStack->AddScreen(okPopup);
1861 }
1862 }
1863 else if (levent->type() == ImageDLEvent::kEventType)
1864 {
1865 if (m_busyPopup)
1866 {
1867 m_busyPopup->Close();
1868 m_busyPopup = nullptr;
1869 }
1870
1871 auto *ide = (ImageDLEvent *)levent;
1872
1873 MetadataLookup *lookup = ide->m_item;
1874
1875 if (!lookup)
1876 return;
1877
1878 HandleDownloadedImages(lookup);
1879 }
1880 else if (levent->type() == ImageDLFailureEvent::kEventType)
1881 {
1882 if (m_busyPopup)
1883 {
1884 m_busyPopup->Close();
1885 m_busyPopup = nullptr;
1886 }
1887 MythErrorNotification n(tr("Failed to retrieve image(s)"),
1888 tr("Schedule Editor"),
1889 tr("Check logs"));
1891 }
1892 else if (levent->type() == DialogCompletionEvent::kEventType)
1893 {
1894 auto *dce = (DialogCompletionEvent*)levent;
1895
1896 const QString resultid = dce->GetId();
1898 info.url = dce->GetResultText();
1899
1900 if (resultid == "coverart")
1901 {
1903 }
1904 else if (resultid == "fanart")
1905 {
1907 }
1908 else if (resultid == "banner")
1909 {
1911 }
1912
1915
1916 ValuesChanged();
1917 }
1918
1919}
1920
1922
1929 SchedOptMixin *other)
1930 : m_screen(&screen), m_rule(rule), m_other(other),
1931 m_haveRepeats(gCoreContext->GetBoolSetting("HaveRepeats", false))
1932{
1933}
1934
1936{
1937 if (!m_rule)
1938 return;
1939
1941 UIUtilE::Assign(m_screen, m_prioritySpin, "priority", err);
1942 else
1944
1946 UIUtilE::Assign(m_screen, m_startoffsetSpin, "startoffset", err);
1947 else
1949
1951 UIUtilE::Assign(m_screen, m_endoffsetSpin, "endoffset", err);
1952 else
1954
1956 UIUtilE::Assign(m_screen, m_dupmethodList, "dupmethod", err);
1957 else
1959
1961 UIUtilE::Assign(m_screen, m_dupscopeList, "dupscope", err);
1962 else
1964
1966 UIUtilE::Assign(m_screen, m_autoExtendList, "autoextend", err);
1967 else
1969
1970 if (m_other && !m_other->m_inputList)
1971 UIUtilE::Assign(m_screen, m_inputList, "input", err);
1972 else
1974
1976 UIUtilE::Assign(m_screen, m_ruleactiveCheck, "ruleactive", err);
1977 else
1979
1981}
1982
1984{
1985 if (!m_rule)
1986 return;
1987
1988 // Priority
1989 if (m_prioritySpin)
1990 {
1991 if (!m_loaded)
1992 m_prioritySpin->SetRange(-99,99,1,5);
1994 }
1995
1996 // Start Offset
1998 {
1999 if (!m_loaded)
2000 m_startoffsetSpin->SetRange(480,-480,1,10);
2002 }
2003
2004 // End Offset
2005 if (m_endoffsetSpin)
2006 {
2007 if (!m_loaded)
2008 m_endoffsetSpin->SetRange(-480,480,1,10);
2010 }
2011
2012 // Duplicate Match Type
2013 if (m_dupmethodList)
2014 {
2015 if (!m_loaded)
2016 {
2018
2034
2035 m_rule->m_dupMethod = dupMethod;
2036 }
2038 }
2039
2040 // Duplicate Matching Scope
2041 if (m_dupscopeList)
2042 {
2043 if (!m_loaded)
2044 {
2056 {
2057 int value = static_cast<int>(kDupsNewEpi|kDupsInAll);
2060 QVariant::fromValue(value));
2061 }
2062 }
2064 }
2065
2066 // Auto Extend Services
2067 if (m_autoExtendList)
2068 {
2069 if (!m_loaded)
2070 {
2080 }
2082 }
2083
2084 // Preferred Input
2085 if (m_inputList)
2086 {
2087 if (!m_loaded)
2088 {
2090 QObject::tr("Use any available input"),
2091 QVariant::fromValue(0));
2092
2093 std::vector<uint> inputids = CardUtil::GetSchedInputList();
2094 for (uint id : inputids)
2095 {
2097 QObject::tr("Prefer input %1")
2098 .arg(CardUtil::GetDisplayName(id)), id);
2099 }
2100 }
2102 }
2103
2104 bool isOverride = (m_rule->m_type != kNotRecording &&
2107
2108 // Active/Disabled
2110 {
2112 m_ruleactiveCheck->SetEnabled(isOverride);
2113 }
2114
2115 // Record new and repeat
2116 if (m_newrepeatList)
2117 {
2118 if (!m_loaded)
2119 {
2121 QObject::tr("Record new and repeat "
2122 "episodes"), toVariant(kDupsUnset));
2124 QObject::tr("Record new episodes only"),
2126 }
2127 RecordingDupInType value =
2130 }
2131
2132 m_loaded = true;
2133
2134 RuleChanged();
2135}
2136
2138{
2139 if (!m_rule)
2140 return;
2141
2142 if (m_prioritySpin)
2146 if (m_endoffsetSpin)
2148 if (m_dupmethodList)
2150 (m_dupmethodList->GetDataValue().toInt());
2151 if (m_dupscopeList)
2152 {
2153 int mask = ((m_other && m_other->m_newrepeatList) ||
2155 int val = ((m_rule->m_dupIn & ~mask) |
2156 m_dupscopeList->GetDataValue().toInt());
2157 m_rule->m_dupIn = static_cast<RecordingDupInType>(val);
2158 }
2159 if (m_autoExtendList)
2160 {
2161 int val = m_autoExtendList->GetDataValue().toInt();
2162 m_rule->m_autoExtend = static_cast<AutoExtendType>(val);
2163 }
2164 if (m_inputList)
2168 if (m_newrepeatList)
2169 {
2170 int val = ((m_rule->m_dupIn & ~kDupsNewEpi) |
2171 m_newrepeatList->GetDataValue().toInt());
2172 m_rule->m_dupIn = static_cast<RecordingDupInType>(val);
2173 }
2174}
2175
2177{
2178 if (!m_rule)
2179 return;
2180
2181 bool isScheduled = (m_rule->m_type != kNotRecording &&
2183 bool isSingle = (m_rule->m_type == kSingleRecord ||
2185 bool isManual = (m_rule->m_searchType == kManualSearch);
2186
2187 if (m_prioritySpin)
2188 m_prioritySpin->SetEnabled(isScheduled);
2190 m_startoffsetSpin->SetEnabled(isScheduled);
2191 if (m_endoffsetSpin)
2192 m_endoffsetSpin->SetEnabled(isScheduled);
2193 if (m_dupmethodList)
2194 {
2196 isScheduled && !isSingle &&
2197 (!isManual || m_rule->m_dupMethod != kDupCheckNone));
2198 }
2199 if (m_dupscopeList)
2200 m_dupscopeList->SetEnabled(isScheduled && !isSingle &&
2202 if (m_inputList)
2203 m_inputList->SetEnabled(isScheduled);
2204 bool isOverride = (m_rule->m_type != kNotRecording &&
2208 m_ruleactiveCheck->SetEnabled(isOverride);
2209 if (m_newrepeatList)
2210 m_newrepeatList->SetEnabled(isScheduled && !isSingle && m_haveRepeats);
2211}
2212
2214{
2215 if (!item || !m_rule)
2216 return;
2217
2219 (item->GetData().toInt());
2220
2221 if (m_dupscopeList)
2223}
2224
2226
2233{
2234 if (!m_rule)
2235 return;
2236
2237 if (m_other && !m_other->m_filtersList)
2238 UIUtilE::Assign(m_screen, m_filtersList, "filters", err);
2239 else
2241
2242 UIUtilW::Assign(m_screen, m_activeFiltersList, "activefilters");
2245}
2246
2248{
2249 if (!m_rule)
2250 return;
2251
2252 if (!m_loaded)
2253 {
2255
2256 query.prepare("SELECT filterid, description, newruledefault "
2257 "FROM recordfilter ORDER BY filterid");
2258
2259 if (query.exec())
2260 {
2261 while (query.next())
2262 {
2263 m_descriptions << QCoreApplication::translate("SchedFilterEditor",
2264 query.value(1).toString().toUtf8().constData());
2265 }
2266 }
2267 m_loaded = true;
2268 }
2269
2272
2273 MythUIButtonListItem *button = nullptr;
2274 QStringList::iterator Idesc;
2275 int idx = 0;
2276 bool not_empty = m_filtersList && !m_filtersList->IsEmpty();
2277 for (Idesc = m_descriptions.begin(), idx = 0;
2278 Idesc != m_descriptions.end(); ++Idesc, ++idx)
2279 {
2280 bool active = (m_rule->m_filter & (1 << idx)) != 0U;
2281 if (m_filtersList)
2282 {
2283 if (not_empty)
2284 button = m_filtersList->GetItemAt(idx);
2285 else
2286 button = new MythUIButtonListItem(m_filtersList, *Idesc, idx);
2287 button->setCheckable(true);
2290 }
2291 if (active && m_activeFiltersList)
2292 {
2293 /* Create a simple list of active filters the theme can
2294 use for informational purposes. */
2296 *Idesc, idx);
2297 button->setCheckable(false);
2298 }
2299 }
2300
2302 {
2304 QObject::tr("None"), idx);
2305 button->setCheckable(false);
2306 }
2307
2308 RuleChanged();
2309}
2310
2312{
2313 if (!m_rule || !m_filtersList)
2314 return;
2315
2316 // Iterate through button list, and build the mask
2317 uint32_t filter_mask = 0;
2318
2319 int end = m_filtersList->GetCount();
2320 for (int idx = 0; idx < end; ++idx)
2321 {
2323 if (button != nullptr &&
2325 filter_mask |= (1 << button->GetData().toUInt());
2326 }
2327 m_rule->m_filter = filter_mask;
2328}
2329
2331{
2332 if (!m_rule)
2333 return;
2334
2335 bool enabled = m_rule->m_type != kNotRecording &&
2337 if (m_filtersList)
2338 m_filtersList->SetEnabled(enabled);
2341}
2342
2344{
2348}
2349
2350
2352
2359{
2360 if (!m_rule)
2361 return;
2362
2364 UIUtilE::Assign(m_screen, m_recprofileList, "recprofile", err);
2365 else
2367
2369 UIUtilE::Assign(m_screen, m_recgroupList, "recgroup", err);
2370 else
2372
2374 UIUtilE::Assign(m_screen, m_storagegroupList, "storagegroup", err);
2375 else
2377
2379 UIUtilE::Assign(m_screen, m_playgroupList, "playgroup", err);
2380 else
2382
2383 if (m_other && !m_other->m_maxepSpin)
2384 UIUtilE::Assign(m_screen, m_maxepSpin, "maxepisodes", err);
2385 else
2386 UIUtilW::Assign(m_screen, m_maxepSpin, "maxepisodes");
2387
2389 UIUtilE::Assign(m_screen, m_maxbehaviourList, "maxnewest", err);
2390 else
2392
2394 UIUtilE::Assign(m_screen, m_autoexpireCheck, "autoexpire", err);
2395 else
2397}
2398
2400{
2401 if (!m_rule)
2402 return;
2403
2404 QString label;
2405 QStringList groups;
2406 QStringList::Iterator it;
2408
2409 // Recording Profile
2410 if (m_recprofileList)
2411 {
2412 if (!m_loaded)
2413 {
2414 label = QObject::tr("Record using the %1 profile");
2415
2417 label.arg(QObject::tr("Default")),
2418 QVariant::fromValue(QString("Default")));
2419 // LiveTV profile - it's for LiveTV not scheduled recordings??
2421 label.arg(QObject::tr("LiveTV")),
2422 QVariant::fromValue(QString("LiveTV")));
2424 label.arg(QObject::tr("High Quality")),
2425 QVariant::fromValue(QString("High Quality")));
2427 label.arg(QObject::tr("Low Quality")),
2428 QVariant::fromValue(QString("Low Quality")));
2429 }
2431 }
2432
2433 // Recording Group
2434 if (m_recgroupList)
2435 {
2436 if (!m_loaded)
2437 {
2438 label = QObject::tr("Include in the \"%1\" recording group");
2440 QObject::tr("Create a new recording group"),
2441 QVariant::fromValue(QString("__NEW_GROUP__")));
2442
2443 query.prepare("SELECT recgroupid, recgroup FROM recgroups "
2444 "WHERE recgroup <> 'Deleted' AND "
2445 " recgroup <> 'LiveTV' "
2446 "ORDER BY special DESC, recgroup ASC"); // Special groups first
2447 if (query.exec())
2448 {
2449 while (query.next())
2450 {
2451 int id = query.value(0).toInt();
2452 QString name = query.value(1).toString();
2453
2454 if (name == "Default")
2455 name = QObject::tr("Default");
2456 new MythUIButtonListItem(m_recgroupList, label.arg(name),
2457 QVariant::fromValue(id));
2458 }
2459 }
2460
2461 }
2463 }
2464
2465 // Storage Group
2467 {
2468 if (!m_loaded)
2469 {
2470 label = QObject::tr("Store in the \"%1\" storage group");
2472 label.arg(QObject::tr("Default")),
2473 QVariant::fromValue(QString("Default")));
2474
2476 for (it = groups.begin(); it != groups.end(); ++it)
2477 {
2478 if ((*it).compare("Default", Qt::CaseInsensitive) != 0)
2480 label.arg(*it), QVariant::fromValue(*it));
2481 }
2482 }
2484 }
2485
2486 // Playback Group
2487 if (m_playgroupList)
2488 {
2489 if (!m_loaded)
2490 {
2491 label = QObject::tr("Use \"%1\" playback group settings");
2493 label.arg(QObject::tr("Default")),
2494 QVariant::fromValue(QString("Default")));
2495
2496 groups = PlayGroup::GetNames();
2497 for (it = groups.begin(); it != groups.end(); ++it)
2498 {
2499 new MythUIButtonListItem(m_playgroupList, label.arg(*it),
2500 QVariant::fromValue(*it));
2501 }
2502 }
2504 }
2505
2506 // Max Episodes
2507 if (m_maxepSpin)
2508 {
2509 if (!m_loaded)
2510 {
2511 int maxEpisodes = m_rule->m_maxEpisodes;
2512 m_maxepSpin->SetRange(0,100,1,5);
2513 m_rule->m_maxEpisodes = maxEpisodes;
2514 }
2516 }
2517
2518 // Max Episode Behaviour
2520 {
2521 if (!m_loaded)
2522 {
2524 QObject::tr("Don't record if this would exceed the max "
2525 "episodes"), QVariant::fromValue(false));
2527 QObject::tr("Delete oldest if this would exceed the max "
2528 "episodes"), QVariant::fromValue(true));
2529 }
2531 }
2532
2533 // Auto-Expire
2535 {
2537 }
2538
2539 m_loaded = true;
2540
2541 RuleChanged();
2542}
2543
2545{
2546 if (!m_rule)
2547 return;
2548
2549 if (m_recprofileList)
2551
2552 if (m_recgroupList)
2553 {
2554 // If the user selected 'Create a new regroup' but failed to enter a
2555 // name when prompted, restore the original value
2556 if (m_recgroupList->GetDataValue().toString() == "__NEW_GROUP__")
2559 }
2560
2563
2564 if (m_playgroupList)
2566
2567 if (m_maxepSpin)
2569
2572
2575}
2576
2578{
2579 if (!m_rule)
2580 return;
2581
2582 bool isScheduled = (m_rule->m_type != kNotRecording &&
2584 bool isSingle = (m_rule->m_type == kSingleRecord ||
2586
2587 if (m_recprofileList)
2588 m_recprofileList->SetEnabled(isScheduled);
2589 if (m_recgroupList)
2590 m_recgroupList->SetEnabled(isScheduled);
2592 m_storagegroupList->SetEnabled(isScheduled);
2593 if (m_playgroupList)
2594 m_playgroupList->SetEnabled(isScheduled);
2595 if (m_maxepSpin)
2596 m_maxepSpin->SetEnabled(isScheduled && !isSingle);
2598 m_maxbehaviourList->SetEnabled(isScheduled && !isSingle &&
2599 m_rule->m_maxEpisodes != 0);
2601 m_autoexpireCheck->SetEnabled(isScheduled);
2602}
2603
2605{
2606 if (!item || !m_rule)
2607 return;
2608
2609 m_rule->m_maxEpisodes = item->GetData().toInt();
2610
2613}
2614
2616{
2617 if (!m_rule)
2618 return;
2619
2620 if (m_recgroupList->GetDataValue().toString() != "__NEW_GROUP__")
2621 return;
2622
2623 MythScreenStack *popupStack = GetMythMainWindow()->GetStack("popup stack");
2624
2625 QString label =
2626 QObject::tr("New Recording group name: ");
2627
2628 auto *textDialog = new MythTextInputDialog(popupStack, label,
2629 static_cast<InputFilter>(FilterSymbols | FilterPunct));
2630
2631 textDialog->SetReturnEvent(m_screen, "newrecgroup");
2632
2633 if (textDialog->Create())
2634 popupStack->AddScreen(textDialog, false);
2635}
2636
2637void StoreOptMixin::SetRecGroup(int recgroupID, QString recgroup)
2638{
2639 if (!m_rule || recgroupID <= 0)
2640 return;
2641
2642 if (m_recgroupList)
2643 {
2644 recgroup = recgroup.trimmed();
2645 if (recgroup.isEmpty())
2646 return;
2647
2648 QString label = QObject::tr("Include in the \"%1\" recording group");
2649 auto *item = new MythUIButtonListItem(m_recgroupList, label.arg(recgroup),
2650 QVariant::fromValue(recgroupID));
2652
2654 {
2656 label.arg(recgroup), QVariant::fromValue(recgroupID));
2658 }
2659 }
2660}
2661
2662int StoreOptMixin::CreateRecordingGroup(const QString& groupName)
2663{
2664 int groupID = -1;
2666
2667 query.prepare("INSERT INTO recgroups SET recgroup = :NAME, "
2668 "displayname = :DISPLAYNAME");
2669 query.bindValue(":NAME", groupName);
2670 query.bindValue(":DISPLAYNAME", groupName);
2671
2672 if (query.exec())
2673 groupID = query.lastInsertId().toInt();
2674
2675 if (groupID <= 0)
2676 LOG(VB_GENERAL, LOG_ERR, QString("Could not create recording group (%1). "
2677 "Does it already exist?").arg(groupName));
2678
2679 return groupID;
2680}
2681
2683
2690{
2691 if (!m_rule)
2692 return;
2693
2695 UIUtilE::Assign(m_screen, m_commflagCheck, "autocommflag", err);
2696 else
2697 UIUtilW::Assign(m_screen, m_commflagCheck, "autocommflag");
2698
2700 UIUtilE::Assign(m_screen, m_transcodeCheck, "autotranscode", err);
2701 else
2702 UIUtilW::Assign(m_screen, m_transcodeCheck, "autotranscode");
2703
2705 UIUtilE::Assign(m_screen, m_transcodeprofileList, "transcodeprofile", err);
2706 else
2707 UIUtilW::Assign(m_screen, m_transcodeprofileList, "transcodeprofile");
2708
2710 UIUtilE::Assign(m_screen, m_userjob1Check, "userjob1", err);
2711 else
2713
2715 UIUtilE::Assign(m_screen, m_userjob2Check, "userjob2", err);
2716 else
2718
2720 UIUtilE::Assign(m_screen, m_userjob3Check, "userjob3", err);
2721 else
2723
2725 UIUtilE::Assign(m_screen, m_userjob4Check, "userjob4", err);
2726 else
2728
2730}
2731
2733{
2734 if (!m_rule)
2735 return;
2736
2737 // Auto-commflag
2738 if (m_commflagCheck)
2739 {
2741 }
2742
2743 // Auto-transcode
2744 if (m_transcodeCheck)
2745 {
2747 }
2748
2749 // Transcode Method
2751 {
2752 if (!m_loaded)
2753 {
2754 QMap<int, QString> profiles = RecordingProfile::GetTranscodingProfiles();
2755 QMap<int, QString>::iterator it;
2756 for (it = profiles.begin(); it != profiles.end(); ++it)
2757 {
2759 QVariant::fromValue(it.key()));
2760 }
2761 }
2763 }
2764
2765 // User Job #1
2766 if (m_userjob1Check)
2767 {
2768 if (!m_loaded)
2769 {
2770 MythUIText *userjob1Text = nullptr;
2771 UIUtilW::Assign(m_screen, userjob1Text, "userjob1text");
2772 if (userjob1Text)
2773 userjob1Text->SetText(QObject::tr("Run '%1'")
2774 .arg(gCoreContext->GetSetting("UserJobDesc1", "User Job 1")));
2775 }
2777 }
2778
2779 // User Job #2
2780 if (m_userjob2Check)
2781 {
2782 if (!m_loaded)
2783 {
2784 MythUIText *userjob2Text = nullptr;
2785 UIUtilW::Assign(m_screen, userjob2Text, "userjob2text");
2786 if (userjob2Text)
2787 userjob2Text->SetText(QObject::tr("Run '%1'")
2788 .arg(gCoreContext->GetSetting("UserJobDesc2", "User Job 2")));
2789 }
2791 }
2792
2793 // User Job #3
2794 if (m_userjob3Check)
2795 {
2796 if (!m_loaded)
2797 {
2798 MythUIText *userjob3Text = nullptr;
2799 UIUtilW::Assign(m_screen, userjob3Text, "userjob3text");
2800 if (userjob3Text)
2801 userjob3Text->SetText(QObject::tr("Run '%1'")
2802 .arg(gCoreContext->GetSetting("UserJobDesc3", "User Job 3")));
2803 }
2805 }
2806
2807 // User Job #4
2808 if (m_userjob4Check)
2809 {
2810 if (!m_loaded)
2811 {
2812 MythUIText *userjob4Text = nullptr;
2813 UIUtilW::Assign(m_screen, userjob4Text, "userjob4text");
2814 if (userjob4Text)
2815 userjob4Text->SetText(QObject::tr("Run '%1'")
2816 .arg(gCoreContext->GetSetting("UserJobDesc4", "User Job 4")));
2817 }
2819 }
2820
2821 // Auto Metadata Lookup
2823 {
2825 }
2826
2827 m_loaded = true;
2828
2829 RuleChanged();
2830}
2831
2833{
2834 if (!m_rule)
2835 return;
2836
2837 if (m_commflagCheck)
2839 if (m_transcodeCheck)
2843 if (m_userjob1Check)
2845 if (m_userjob2Check)
2847 if (m_userjob3Check)
2849 if (m_userjob4Check)
2854}
2855
2857{
2858 if (!m_rule)
2859 return;
2860
2861 bool isScheduled = (m_rule->m_type != kNotRecording &&
2863
2864 if (m_commflagCheck)
2865 m_commflagCheck->SetEnabled(isScheduled);
2866 if (m_transcodeCheck)
2867 m_transcodeCheck->SetEnabled(isScheduled);
2869 m_transcodeprofileList->SetEnabled(isScheduled &&
2871 if (m_userjob1Check)
2872 m_userjob1Check->SetEnabled(isScheduled);
2873 if (m_userjob2Check)
2874 m_userjob2Check->SetEnabled(isScheduled);
2875 if (m_userjob3Check)
2876 m_userjob3Check->SetEnabled(isScheduled);
2877 if (m_userjob4Check)
2878 m_userjob4Check->SetEnabled(isScheduled);
2880 m_metadataLookupCheck->SetEnabled(isScheduled);
2881}
2882
2884{
2885 if (!m_rule)
2886 return;
2887
2888 m_rule->m_autoTranscode = enable;
2889
2892}
2893
2894#include "moc_scheduleeditor.cpp"
static std::vector< uint > GetSchedInputList(void)
Definition: cardutil.cpp:2943
static QString GetDisplayName(uint inputid)
Definition: cardutil.cpp:1887
Event dispatched from MythUI modal dialogs to a listening class containing a result of some form.
Definition: mythdialogbox.h:40
static const Type kEventType
Definition: mythdialogbox.h:55
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:129
bool prepare(const QString &query)
QSqlQuery::prepare() is not thread safe in Qt <= 3.3.2.
Definition: mythdbcon.cpp:839
QVariant value(int i) const
Definition: mythdbcon.h:205
bool exec(void)
Wrap QSqlQuery::exec() so we can display SQL.
Definition: mythdbcon.cpp:620
void bindValue(const QString &placeholder, const QVariant &val)
Add a single binding.
Definition: mythdbcon.cpp:890
QVariant lastInsertId()
Return the id of the last inserted row.
Definition: mythdbcon.cpp:937
bool next(void)
Wrap QSqlQuery::next() so we can display the query results.
Definition: mythdbcon.cpp:814
static MSqlQueryInfo InitCon(ConnectionReuse _reuse=kNormalConnection)
Only use this in combination with MSqlQuery constructor.
Definition: mythdbcon.cpp:552
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
Load data which will ultimately be displayed on-screen or used to determine what appears on-screen (S...
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:28
int GetIntValue(void) const override
Definition: mythuispinbox.h:35
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:348
void SetEnabled(bool enable)
void LosingFocus(void)
static QStringList GetNames(void)
Definition: playgroup.cpp:238
Select post-processing options.
void TranscodeChanged(bool enable)
bool Create(void) override
void Load(void) override
Load data which will ultimately be displayed on-screen or used to determine what appears on-screen (S...
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:75
uint GetRecordingRuleID(void) const
Definition: programinfo.h:461
uint GetEpisode(void) const
Definition: programinfo.h:375
uint GetYearOfInitialRelease(void) const
Definition: programinfo.h:432
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:450
uint GetSeason(void) const
Definition: programinfo.h:374
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:31
RecordingType m_type
QString m_station
void UseTempTable(bool usetemp, const QString &table="record_tmp")
QString m_category
Definition: recordingrule.h:84
QString m_inetref
Definition: recordingrule.h:89
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:72
RecordingDupInType m_dupIn
QString m_title
Definition: recordingrule.h:79
void ToMap(InfoMap &infoMap, uint date_format=0) const
QString m_recProfile
bool m_isInactive
Recording rule is enabled?
Definition: recordingrule.h:76
static QStringList GetTemplateNames(void)
QString m_playGroup
bool Save(bool sendSig=true)
QString m_subtitle
Definition: recordingrule.h:81
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:86
bool IsLoaded() const
Definition: recordingrule.h:57
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
Load data which will ultimately be displayed on-screen or used to determine what appears on-screen (S...
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
Load data which will ultimately be displayed on-screen or used to determine what appears on-screen (S...
bool Create(void) override
Select schedule options.
bool Create(void) override
void Load(void) override
Load data which will ultimately be displayed on-screen or used to determine what appears on-screen (S...
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
Load data which will ultimately be displayed on-screen or used to determine what appears on-screen (S...
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:158
static bool LoadWindowFromXML(const QString &xmlfile, const QString &windowname, MythUIType *parent)
unsigned int uint
Definition: compat.h:60
@ 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:80