MythTV  0.28pre
scheduleeditor.cpp
Go to the documentation of this file.
1 
2 #include "scheduleeditor.h"
3 
4 // QT
5 #include <QString>
6 #include <QHash>
7 #include <QCoreApplication>
8 
9 // Libmyth
10 #include "mythcorecontext.h"
11 #include "storagegroup.h"
12 #include "programtypes.h"
13 #include "recordingtypes.h"
14 
15 // Libmythtv
16 #include "playgroup.h"
17 #include "tv_play.h"
18 #include "recordingprofile.h"
19 #include "cardutil.h"
20 
21 // Libmythui
22 #include "mythmainwindow.h"
23 #include "mythuihelper.h"
24 #include "mythuibuttonlist.h"
25 #include "mythuibutton.h"
26 #include "mythuitext.h"
27 #include "mythuiimage.h"
28 #include "mythuistatetype.h"
29 #include "mythuispinbox.h"
30 #include "mythuicheckbox.h"
31 #include "mythdialogbox.h"
32 #include "mythprogressdialog.h"
33 #include "mythuifilebrowser.h"
34 #include "mythuimetadataresults.h"
35 #include "mythuiimageresults.h"
36 #include "videoutils.h"
37 #include "mythuiutils.h"
38 #include "mythtypes.h"
39 
40 #include "metadataimagehelper.h"
41 
42 // Mythfrontend
43 #include "proglist.h"
44 #include "viewschedulediff.h"
45 
46 #define ENUM_TO_QVARIANT(a) qVariantFromValue(static_cast<int>(a))
47 
48 //static const QString _Location = QObject::tr("Schedule Editor");
49 
50 // Define the strings inserted into the recordfilter table in the
51 // database. This should make them available to the translators.
52 static QString fs0(QT_TRANSLATE_NOOP("SchedFilterEditor", "New episode"));
53 static QString fs1(QT_TRANSLATE_NOOP("SchedFilterEditor", "Identifiable episode"));
54 static QString fs2(QT_TRANSLATE_NOOP("SchedFilterEditor", "First showing"));
55 static QString fs3(QT_TRANSLATE_NOOP("SchedFilterEditor", "Prime time"));
56 static QString fs4(QT_TRANSLATE_NOOP("SchedFilterEditor", "Commercial free"));
57 static QString fs5(QT_TRANSLATE_NOOP("SchedFilterEditor", "High definition"));
58 static QString fs6(QT_TRANSLATE_NOOP("SchedFilterEditor", "This episode"));
59 static QString fs7(QT_TRANSLATE_NOOP("SchedFilterEditor", "This series"));
60 static QString fs8(QT_TRANSLATE_NOOP("SchedFilterEditor", "This time"));
61 static QString fs9(QT_TRANSLATE_NOOP("SchedFilterEditor", "This day and time"));
62 static QString fs10(QT_TRANSLATE_NOOP("SchedFilterEditor", "This channel"));
63 static QString fs11(QT_TRANSLATE_NOOP("SchedFilterEditor", "No episodes"));
64 
65 void *ScheduleEditor::RunScheduleEditor(ProgramInfo *proginfo, void *player)
66 {
67  RecordingRule *rule = new RecordingRule();
68  rule->LoadByProgram(proginfo);
69 
71  ScheduleEditor *se = new ScheduleEditor(mainStack, rule,
72  static_cast<TV*>(player));
73 
74  if (se->Create())
75  mainStack->AddScreen(se, (player == NULL));
76  else
77  delete se;
78 
79  return NULL;
80 }
81 
88  RecordingInfo *recInfo, TV *player)
89  : ScheduleCommon(parent, "ScheduleEditor"),
90  SchedOptMixin(*this, NULL), FilterOptMixin(*this, NULL),
91  StoreOptMixin(*this, NULL), PostProcMixin(*this, NULL),
92  m_recInfo(new RecordingInfo(*recInfo)), m_recordingRule(NULL),
94  m_saveButton(NULL), m_cancelButton(NULL), m_rulesList(NULL),
97  m_previewButton(NULL), m_metadataButton(NULL),
98  m_filtersButton(NULL),
99  m_player(player), m_loaded(false), m_view(kMainView), m_child(NULL)
100 {
107 }
108 
110  RecordingRule *recRule, TV *player)
111  : ScheduleCommon(parent, "ScheduleEditor"),
112  SchedOptMixin(*this, recRule),
113  FilterOptMixin(*this, recRule),
114  StoreOptMixin(*this, recRule),
115  PostProcMixin(*this, recRule),
116  m_recInfo(NULL), m_recordingRule(recRule),
117  m_sendSig(false),
118  m_saveButton(NULL), m_cancelButton(NULL), m_rulesList(NULL),
119  m_schedOptButton(NULL), m_storeOptButton(NULL),
120  m_postProcButton(NULL), m_schedInfoButton(NULL),
121  m_previewButton(NULL), m_metadataButton(NULL),
122  m_filtersButton(NULL),
123  m_player(player), m_loaded(false), m_view(kMainView), m_child(NULL)
124 {
125 }
126 
128 {
129  delete m_recordingRule;
130 
131  // if we have a player, we need to tell we are done
132  if (m_player)
133  {
134  QString message = QString("VIEWSCHEDULED_EXITING");
135  qApp->postEvent(m_player, new MythEvent(message));
136  }
137 }
138 
140 {
141  if (!LoadWindowFromXML("schedule-ui.xml", "scheduleeditor", this))
142  return false;
143 
144  bool err = false;
145 
146  UIUtilE::Assign(this, m_rulesList, "rules", &err);
147 
148  UIUtilW::Assign(this, m_schedOptButton, "schedoptions");
149  UIUtilW::Assign(this, m_storeOptButton, "storeoptions");
150  UIUtilW::Assign(this, m_postProcButton, "postprocessing");
151  UIUtilW::Assign(this, m_metadataButton, "metadata");
152  UIUtilW::Assign(this, m_schedInfoButton, "schedinfo");
153  UIUtilW::Assign(this, m_previewButton, "preview");
154  UIUtilW::Assign(this, m_filtersButton, "filters");
155 
156  SchedOptMixin::Create(&err);
158  StoreOptMixin::Create(&err);
159  PostProcMixin::Create(&err);
160 
161  UIUtilW::Assign(this, m_cancelButton, "cancel");
162  UIUtilE::Assign(this, m_saveButton, "save", &err);
163 
164  if (err)
165  {
166  LOG(VB_GENERAL, LOG_ERR, "ScheduleEditor, theme is missing "
167  "required elements");
168  return false;
169  }
170 
171  connect(m_rulesList, SIGNAL(itemSelected(MythUIButtonListItem *)),
173 
174  if (m_schedOptButton)
175  connect(m_schedOptButton, SIGNAL(Clicked()), SLOT(ShowSchedOpt()));
176  if (m_filtersButton)
177  connect(m_filtersButton, SIGNAL(Clicked()), SLOT(ShowFilters()));
178  if (m_storeOptButton)
179  connect(m_storeOptButton, SIGNAL(Clicked()), SLOT(ShowStoreOpt()));
180  if (m_postProcButton)
181  connect(m_postProcButton, SIGNAL(Clicked()), SLOT(ShowPostProc()));
182  if (m_schedInfoButton)
183  connect(m_schedInfoButton, SIGNAL(Clicked()), SLOT(ShowSchedInfo()));
184  if (m_previewButton)
185  connect(m_previewButton, SIGNAL(Clicked()), SLOT(ShowPreview()));
186  if (m_metadataButton)
187  connect(m_metadataButton, SIGNAL(Clicked()), SLOT(ShowMetadataOptions()));
188 
189  if (m_cancelButton)
190  connect(m_cancelButton, SIGNAL(Clicked()), SLOT(Close()));
191  connect(m_saveButton, SIGNAL(Clicked()), SLOT(Save()));
192 
193  if (m_schedInfoButton)
195  if (m_previewButton)
197 
198  if (m_dupmethodList)
199  connect(m_dupmethodList, SIGNAL(itemSelected(MythUIButtonListItem *)),
201  if (m_filtersList)
202  connect(m_filtersList, SIGNAL(itemClicked(MythUIButtonListItem *)),
204  if (m_maxepSpin)
205  connect(m_maxepSpin, SIGNAL(itemSelected(MythUIButtonListItem *)),
207  if (m_recgroupList)
208  connect(m_recgroupList, SIGNAL(LosingFocus()),
209  SLOT(PromptForRecGroup()));
210  if (m_transcodeCheck)
211  connect(m_transcodeCheck, SIGNAL(toggled(bool)),
212  SLOT(TranscodeChanged(bool)));
213 
214  BuildFocusList();
215 
216  if (!m_recordingRule->IsLoaded())
217  {
218  if (m_recInfo)
220  else if (m_recordingRule->m_recordID)
222 
223  if (!m_recordingRule->IsLoaded())
224  {
225  LOG(VB_GENERAL, LOG_ERR,
226  "ScheduleEditor::Create() - Failed to load recording rule");
227  return false;
228  }
229  }
230 
231  if (m_player)
232  m_player->StartEmbedding(QRect());
233 
234  return true;
235 }
236 
238 {
239  if (m_child)
240  m_child->Close();
241 
242  // don't fade the screen if we are returning to the player
243  if (m_player)
244  GetScreenStack()->PopScreen(this, false);
245  else
246  GetScreenStack()->PopScreen(this, true);
247 }
248 
250 {
255 
256  if (!m_loaded)
257  {
258  // Copy this now, it will change briefly after the first item
259  // is inserted into the list by design of
260  // MythUIButtonList::itemSelected()
262 
263  // Rules List
265  {
267  .compare("Default", Qt::CaseInsensitive) != 0)
268  {
270  tr("Delete this recording rule template"),
271  ENUM_TO_QVARIANT(kNotRecording));
272  }
275  ENUM_TO_QVARIANT(kTemplateRecord));
276  }
277  else if (m_recordingRule->m_isOverride)
278  {
280  tr("Record this showing with normal options"),
281  ENUM_TO_QVARIANT(kNotRecording));
284  ENUM_TO_QVARIANT(kOverrideRecord));
287  ENUM_TO_QVARIANT(kDontRecord));
288  }
289  else
290  {
291  bool hasChannel = !m_recordingRule->m_station.isEmpty();
292  bool isManual = (m_recordingRule->m_searchType == kManualSearch);
293 
296  ENUM_TO_QVARIANT(kNotRecording));
297  if (hasChannel)
300  ENUM_TO_QVARIANT(kSingleRecord));
301  if (!isManual)
304  ENUM_TO_QVARIANT(kOneRecord));
305  if (!hasChannel || isManual)
308  ENUM_TO_QVARIANT(kWeeklyRecord));
309  if (!hasChannel || isManual)
312  ENUM_TO_QVARIANT(kDailyRecord));
313  if (!isManual)
316  ENUM_TO_QVARIANT(kAllRecord));
317  }
318 
320  }
321  m_rulesList->SetValueByData(ENUM_TO_QVARIANT(m_recordingRule->m_type));
322 
323  InfoMap progMap;
324 
325  m_recordingRule->ToMap(progMap);
326 
327  if (m_recInfo)
328  m_recInfo->ToMap(progMap);
329 
330  SetTextFromMap(progMap);
331 
332  m_loaded = true;
333 }
334 
336 {
338  Load();
339  emit templateLoaded();
340 }
341 
343 {
344  if (!item)
345  return;
346 
347  m_recordingRule->m_type = static_cast<RecordingType>
348  (item->GetData().toInt());
349 
350  bool isScheduled = (m_recordingRule->m_type != kNotRecording &&
352 
353  if (m_schedOptButton)
354  m_schedOptButton->SetEnabled(isScheduled);
355  if (m_filtersButton)
356  m_filtersButton->SetEnabled(isScheduled);
357  if (m_storeOptButton)
358  m_storeOptButton->SetEnabled(isScheduled);
359  if (m_postProcButton)
360  m_postProcButton->SetEnabled(isScheduled);
361  if (m_metadataButton)
362  m_metadataButton->SetEnabled(isScheduled &&
364 
369 }
370 
372 {
374 }
375 
377 {
379 }
380 
382 {
384 }
385 
387 {
389 }
390 
392 {
394 }
395 
397 {
398  if (m_child)
399  m_child->Close();
400 
402  {
403  int recid = m_recordingRule->m_recordID;
404  DeleteRule();
405  if (recid)
406  emit ruleDeleted(recid);
407  Close();
408  return;
409  }
410 
415  m_recordingRule->Save(true);
417 
418  Close();
419 }
420 
422 {
424 }
425 
427 {
430  return;
431 
432  if (m_child)
433  m_child->Close();
434 
436 
438  SchedOptEditor *schedoptedit = new SchedOptEditor(mainStack, *this,
440  if (!schedoptedit->Create())
441  {
442  delete schedoptedit;
443  return;
444  }
445 
447  m_child = schedoptedit;
448  mainStack->AddScreen(schedoptedit);
449 }
450 
452 {
455  return;
456 
457  if (m_child)
458  m_child->Close();
459 
461 
463  StoreOptEditor *storeoptedit = new StoreOptEditor(mainStack, *this,
465  if (!storeoptedit->Create())
466  {
467  delete storeoptedit;
468  return;
469  }
470 
472  m_child = storeoptedit;
473  mainStack->AddScreen(storeoptedit);
474 }
475 
477 {
480  return;
481 
482  if (m_child)
483  m_child->Close();
484 
486 
488  PostProcEditor *ppedit = new PostProcEditor(mainStack, *this,
490  if (!ppedit->Create())
491  {
492  delete ppedit;
493  return;
494  }
495 
497  m_child = ppedit;
498  mainStack->AddScreen(ppedit);
499 }
500 
502 {
504  return;
505 
506  QString label = tr("Schedule Information");
507 
508  MythScreenStack *popupStack = GetMythMainWindow()->GetStack("popup stack");
509  MythDialogBox *menuPopup = new MythDialogBox(label, popupStack, "menuPopup");
510 
511  if (menuPopup->Create())
512  {
513  menuPopup->SetReturnEvent(this, "schedinfo");
514 
515  if (m_recInfo)
516  menuPopup->AddButton(tr("Program Details"));
517  menuPopup->AddButton(tr("Upcoming Episodes"));
518  menuPopup->AddButton(tr("Upcoming Recordings"));
520  menuPopup->AddButton(tr("Previously Recorded"));
521 
522  popupStack->AddScreen(menuPopup);
523  }
524  else
525  delete menuPopup;
526 }
527 
528 bool ScheduleEditor::keyPressEvent(QKeyEvent *event)
529 {
530  if (GetFocusWidget()->keyPressEvent(event))
531  return true;
532 
533  bool handled = false;
534  QStringList actions;
535  handled = GetMythMainWindow()->
536  TranslateKeyPress("TV Frontend", event, actions);
537 
538  for (int i = 0; i < actions.size() && !handled; i++)
539  {
540  QString action = actions[i];
541  handled = true;
542 
543  if (action == "MENU")
544  showMenu();
545  else if (action == "INFO")
546  ShowDetails();
547  else if (action == "GUIDE")
548  ShowGuide();
549  else if (action == "UPCOMING")
551  else if (action == "PREVVIEW")
553  else if (action == "NEXTVIEW")
554  ShowNextView();
555  else
556  handled = false;
557  }
558 
559  if (!handled && MythScreenType::keyPressEvent(event))
560  handled = true;
561 
562  return handled;
563 }
564 
565 void ScheduleEditor::customEvent(QEvent *event)
566 {
567  if (event->type() == DialogCompletionEvent::kEventType)
568  {
570 
571  QString resultid = dce->GetId();
572  QString resulttext = dce->GetResultText();
573 
574  if (resultid == "menu")
575  {
576  if (resulttext == tr("Main Options"))
577  m_child->Close();
578  if (resulttext == tr("Schedule Options"))
579  ShowSchedOpt();
580  else if (resulttext == tr("Filter Options"))
581  ShowFilters();
582  else if (resulttext == tr("Storage Options"))
583  ShowStoreOpt();
584  else if (resulttext == tr("Post Processing"))
585  ShowPostProc();
586  else if (resulttext == tr("Metadata Options"))
588  else if (resulttext == tr("Use Template"))
590  else if (resulttext == tr("Schedule Info"))
591  ShowSchedInfo();
592  else if (resulttext == tr("Preview Changes"))
593  ShowPreview();
594  }
595  else if (resultid == "templatemenu")
596  {
597  LoadTemplate(resulttext);
598  }
599  else if (resultid == "schedinfo")
600  {
601  if (resulttext == tr("Program Details"))
602  ShowDetails();
603  else if (resulttext == tr("Upcoming Episodes"))
605  else if (resulttext == tr("Upcoming Recordings"))
607  else if (resulttext == tr("Previously Recorded"))
608  ShowPrevious();
609  }
610  else if (resultid == "newrecgroup")
611  {
612  int groupID = CreateRecordingGroup(resulttext);
613  StoreOptMixin::SetRecGroup(groupID, resulttext);
614  }
615  }
616 }
617 
619 {
621  return;
622 
623  // No rule? Search by title
624  if (m_recordingRule->m_recordID <= 0)
625  {
627  return;
628  }
629 
631  ProgLister *pl = new ProgLister(mainStack, plRecordid,
632  QString::number(m_recordingRule->m_recordID),
633  "");
634 
635  if (pl->Create())
636  mainStack->AddScreen(pl);
637  else
638  delete pl;
639 }
640 
642 {
644  return;
645 
646  // Existing rule and search? Search by rule
647  if (m_recordingRule->m_recordID > 0 &&
650 
651  QString title = m_recordingRule->m_title;
652 
654  title.remove(QRegExp(" \\(.*\\)$"));
655 
657 }
658 
660 {
662  return;
663 
664  if (m_child)
665  {
666  m_child->Save();
667  if (m_view == kSchedOptView)
669  else if (m_view == kStoreOptView)
671  else if (m_view == kPostProcView)
673  }
674 
679 
680  QString ttable = "record_tmp";
681  m_recordingRule->UseTempTable(true, ttable);
682 
684  ViewScheduleDiff *vsd = new ViewScheduleDiff(mainStack, ttable,
687  if (vsd->Create())
688  mainStack->AddScreen(vsd);
689  else
690  delete vsd;
691 
693 }
694 
696 {
700  return;
701 
702  if (m_child)
703  m_child->Close();
704 
706  MetadataOptions *rad = new MetadataOptions(mainStack, *this,
708  if (!rad->Create())
709  {
710  delete rad;
711  return;
712  }
713 
715  m_child = rad;
716  mainStack->AddScreen(rad);
717 }
718 
720 {
723  return;
724 
725  if (m_child)
726  m_child->Close();
727 
729 
731  SchedFilterEditor *schedfilteredit = new SchedFilterEditor(mainStack,
732  *this, *m_recordingRule, m_recInfo);
733  if (!schedfilteredit->Create())
734  {
735  delete schedfilteredit;
736  return;
737  }
738 
740  m_child = schedfilteredit;
741  mainStack->AddScreen(schedfilteredit);
742 }
743 
745 {
748  return;
749 
752  else if (m_view == kMainView)
753  ShowPostProc();
754  else if (m_view == kSchedOptView)
755  m_child->Close();
756  else if (m_view == kFilterView)
757  ShowSchedOpt();
758  else if (m_view == kStoreOptView)
759  ShowFilters();
760  else if (m_view == kPostProcView)
761  ShowStoreOpt();
762  else if (m_view == kMetadataView)
763  ShowPostProc();
764 }
765 
767 {
770  return;
771 
772  if (m_view == kMainView)
773  ShowSchedOpt();
774  else if (m_view == kSchedOptView)
775  ShowFilters();
776  else if (m_view == kFilterView)
777  ShowStoreOpt();
778  else if (m_view == kStoreOptView)
779  ShowPostProc();
782  else if (m_view == kPostProcView)
783  m_child->Close();
784  else if (m_view == kMetadataView)
785  m_child->Close();
786 }
787 
789 {
790  if (m_view == kSchedOptView)
792  else if (m_view == kFilterView)
794  else if (m_view == kStoreOptView)
796  else if (m_view == kPostProcView)
798 
799  m_child = NULL;
800  m_view = kMainView;
801 }
802 
804 {
805  QString label = tr("Options");
806  MythScreenStack *popupStack = GetMythMainWindow()->GetStack("popup stack");
807  MythDialogBox *menuPopup =
808  new MythDialogBox(label, popupStack, "menuPopup");
809 
811  RecordingType type = static_cast<RecordingType>(item->GetData().toInt());
812  bool isScheduled = (type != kNotRecording && type != kDontRecord);
813 
814  if (menuPopup->Create())
815  {
816  menuPopup->SetReturnEvent(this, "menu");
817  if (m_view != kMainView)
818  menuPopup->AddButton(tr("Main Options"));
819  if (isScheduled && m_view != kSchedOptView)
820  menuPopup->AddButton(tr("Schedule Options"));
821  if (isScheduled && m_view != kFilterView)
822  menuPopup->AddButton(tr("Filter Options"));
823  if (isScheduled && m_view != kStoreOptView)
824  menuPopup->AddButton(tr("Storage Options"));
825  if (isScheduled && m_view != kPostProcView)
826  menuPopup->AddButton(tr("Post Processing"));
827  if (isScheduled && !m_recordingRule->m_isTemplate &&
829  menuPopup->AddButton(tr("Metadata Options"));
831  menuPopup->AddButton(tr("Schedule Info"));
833  menuPopup->AddButton(tr("Preview Changes"));
834  menuPopup->AddButton(tr("Use Template"));
835  popupStack->AddScreen(menuPopup);
836  }
837  else
838  {
839  delete menuPopup;
840  }
841 }
842 
844 {
845  QStringList templates = RecordingRule::GetTemplateNames();
846  if (templates.empty())
847  {
848  ShowOkPopup(tr("No templates available"));
849  return;
850  }
851 
852  QString label = tr("Template Options");
853  MythScreenStack *popupStack = GetMythMainWindow()->GetStack("popup stack");
854  MythDialogBox *menuPopup =
855  new MythDialogBox(label, popupStack, "menuPopup");
856 
857  if (menuPopup->Create())
858  {
859  menuPopup->SetReturnEvent(this, "templatemenu");
860  while (!templates.empty())
861  {
862  QString name = templates.front();
863  if (name == "Default")
864  menuPopup->AddButton(tr("Default"));
865  else
866  menuPopup->AddButton(name);
867  templates.pop_front();
868  }
869  popupStack->AddScreen(menuPopup);
870  }
871  else
872  {
873  delete menuPopup;
874  }
875 }
876 
878 
884  ScheduleEditor &editor, RecordingRule &rule,
885  RecordingInfo *recInfo)
886  : MythScreenType(parent, name),
887  m_editor(&editor), m_recordingRule(&rule), m_recInfo(recInfo),
888  m_backButton(NULL), m_saveButton(NULL), m_previewButton(NULL)
889 {
890 }
891 
893 {
894 }
895 
896 bool SchedEditChild::keyPressEvent(QKeyEvent *event)
897 {
898  if (GetFocusWidget()->keyPressEvent(event))
899  return true;
900 
901  bool handled = false;
902  QStringList actions;
903  handled = GetMythMainWindow()->
904  TranslateKeyPress("TV Frontend", event, actions);
905 
906  for (int i = 0; i < actions.size() && !handled; i++)
907  {
908  QString action = actions[i];
909  handled = true;
910 
911  if (action == "MENU")
912  m_editor->showMenu();
913  else if (action == "INFO")
915  else if (action == "UPCOMING")
917  if (action == "ESCAPE")
918  Close();
919  else if (action == "PREVVIEW")
921  else if (action == "NEXTVIEW")
923  else
924  handled = false;
925  }
926 
927  if (!handled && MythScreenType::keyPressEvent(event))
928  handled = true;
929 
930  return handled;
931 }
932 
934  const QString &xmlfile, const QString &winname, bool isTemplate)
935 {
936  if (!LoadWindowFromXML(xmlfile, winname, this))
937  return false;
938 
939  UIUtilW::Assign(this, m_backButton, "back");
940  UIUtilW::Assign(this, m_saveButton, "save");
941  UIUtilW::Assign(this, m_previewButton, "preview");
942 
943  connect(this, SIGNAL(Closing()), m_editor, SLOT(ChildClosing()));
944  connect(m_editor, SIGNAL(templateLoaded()), SLOT(Load()));
945 
946  if (m_backButton)
947  connect(m_backButton, SIGNAL(Clicked()), SLOT(Close()));
948  if (m_saveButton)
949  connect(m_saveButton, SIGNAL(Clicked()), m_editor, SLOT(Save()));
950  if (m_previewButton)
951  connect(m_previewButton, SIGNAL(Clicked()),
952  m_editor, SLOT(ShowPreview()));
953 
954  if (m_previewButton)
955  m_previewButton->SetEnabled(!isTemplate);
956 
957  return true;
958 }
959 
961 {
962  InfoMap progMap;
963 
964  m_recordingRule->ToMap(progMap);
965 
966  if (m_recInfo)
967  m_recInfo->ToMap(progMap);
968 
969  SetTextFromMap(progMap);
970 }
971 
973 {
974  Save();
975  emit Closing();
977 }
978 
980 
987  ScheduleEditor &editor,
988  RecordingRule &rule,
989  RecordingInfo *recInfo)
990  : SchedEditChild(parent, "ScheduleOptionsEditor", editor, rule, recInfo),
991  SchedOptMixin(*this, &rule, &editor), m_filtersButton(NULL)
992 {
993 }
994 
996 {
997 }
998 
1000 {
1002  "schedule-ui.xml", "scheduleoptionseditor",
1004  {
1005  return false;
1006  }
1007 
1008  bool err = false;
1009 
1010  SchedOptMixin::Create(&err);
1011 
1012  UIUtilW::Assign(this, m_filtersButton, "filters");
1013 
1014  if (err)
1015  {
1016  LOG(VB_GENERAL, LOG_ERR, "SchedOptEditor, theme is missing "
1017  "required elements");
1018  return false;
1019  }
1020 
1021  if (m_dupmethodList)
1022  connect(m_dupmethodList, SIGNAL(itemSelected(MythUIButtonListItem *)),
1024 
1025  if (m_filtersButton)
1026  connect(m_filtersButton, SIGNAL(Clicked()),
1027  m_editor, SLOT(ShowFilters()));
1028 
1029  BuildFocusList();
1030 
1031  return true;
1032 }
1033 
1035 {
1037  SetTextFromMaps();
1038 }
1039 
1041 {
1043 }
1044 
1046 {
1048 }
1049 
1051 
1058  ScheduleEditor &editor,
1059  RecordingRule &rule,
1060  RecordingInfo *recInfo)
1061  : SchedEditChild(parent, "ScheduleFilterEditor", editor, rule, recInfo),
1062  FilterOptMixin(*this, &rule, &editor)
1063 {
1064 }
1065 
1067 {
1068 }
1069 
1071 {
1073  "schedule-ui.xml", "schedulefiltereditor",
1075  {
1076  return false;
1077  }
1078 
1079  bool err = false;
1080 
1081  FilterOptMixin::Create(&err);
1082 
1083  if (err)
1084  {
1085  LOG(VB_GENERAL, LOG_ERR, "SchedFilterEditor, theme is missing "
1086  "required elements");
1087  return false;
1088  }
1089 
1090  connect(m_filtersList, SIGNAL(itemClicked(MythUIButtonListItem *)),
1092 
1093  BuildFocusList();
1094 
1095  return true;
1096 }
1097 
1099 {
1101  SetTextFromMaps();
1102 }
1103 
1105 {
1107 }
1108 
1110 {
1112 }
1113 
1115 
1122  ScheduleEditor &editor,
1123  RecordingRule &rule,
1124  RecordingInfo *recInfo)
1125  : SchedEditChild(parent, "StorageOptionsEditor", editor, rule, recInfo),
1126  StoreOptMixin(*this, &rule, &editor)
1127 {
1128 }
1129 
1131 {
1132 }
1133 
1135 {
1137  "schedule-ui.xml", "storageoptionseditor",
1139  {
1140  return false;
1141  }
1142 
1143  bool err = false;
1144 
1145  StoreOptMixin::Create(&err);
1146 
1147  if (err)
1148  {
1149  LOG(VB_GENERAL, LOG_ERR, "StoreOptEditor, theme is missing "
1150  "required elements");
1151  return false;
1152  }
1153 
1154  if (m_maxepSpin)
1155  connect(m_maxepSpin, SIGNAL(itemSelected(MythUIButtonListItem *)),
1157  if (m_recgroupList)
1158  connect(m_recgroupList, SIGNAL(LosingFocus()),
1159  SLOT(PromptForRecGroup()));
1160 
1161  BuildFocusList();
1162 
1163  return true;
1164 }
1165 
1167 {
1169  SetTextFromMaps();
1170 }
1171 
1173 {
1175 }
1176 
1178 {
1180 }
1181 
1182 void StoreOptEditor::customEvent(QEvent *event)
1183 {
1184  if (event->type() == DialogCompletionEvent::kEventType)
1185  {
1187 
1188  QString resultid = dce->GetId();
1189  QString resulttext = dce->GetResultText();
1190 
1191  if (resultid == "newrecgroup")
1192  {
1193  int groupID = CreateRecordingGroup(resulttext);
1194  StoreOptMixin::SetRecGroup(groupID, resulttext);
1195  }
1196  }
1197 }
1198 
1200 {
1202 }
1203 
1205 
1212  ScheduleEditor &editor,
1213  RecordingRule &rule,
1214  RecordingInfo *recInfo)
1215  : SchedEditChild(parent, "PostProcOptionsEditor", editor, rule, recInfo),
1216  PostProcMixin(*this, &rule, &editor)
1217 {
1218 }
1219 
1221 {
1222 }
1223 
1225 {
1227  "schedule-ui.xml", "postproceditor",
1229  {
1230  return false;
1231  }
1232 
1233  bool err = false;
1234 
1235  PostProcMixin::Create(&err);
1236 
1237  if (err)
1238  {
1239  LOG(VB_GENERAL, LOG_ERR, "PostProcEditor, theme is missing "
1240  "required elements");
1241  return false;
1242  }
1243 
1244  if (m_transcodeCheck)
1245  connect(m_transcodeCheck, SIGNAL(toggled(bool)),
1246  SLOT(TranscodeChanged(bool)));
1247 
1248  BuildFocusList();
1249 
1250  return true;
1251 }
1252 
1254 {
1256  SetTextFromMaps();
1257 }
1258 
1260 {
1262 }
1263 
1265 {
1267 }
1268 
1270 
1277  ScheduleEditor &editor,
1278  RecordingRule &rule,
1279  RecordingInfo *recInfo)
1280  : SchedEditChild(parent, "MetadataOptions", editor, rule, recInfo),
1281  m_busyPopup(NULL), m_fanart(NULL), m_coverart(NULL),
1282  m_banner(NULL), m_inetrefEdit(NULL), m_seasonSpin(NULL),
1283  m_episodeSpin(NULL), m_queryButton(NULL), m_localFanartButton(NULL),
1284  m_localCoverartButton(NULL), m_localBannerButton(NULL),
1285  m_onlineFanartButton(NULL), m_onlineCoverartButton(NULL),
1286  m_onlineBannerButton(NULL)
1287 {
1288  m_popupStack = GetMythMainWindow()->GetStack("popup stack");
1289 
1290  m_metadataFactory = new MetadataFactory(this);
1291  m_imageLookup = new MetadataDownload(this);
1293 
1296 }
1297 
1299 {
1300  if (m_imageLookup)
1301  {
1302  m_imageLookup->cancel();
1303  delete m_imageLookup;
1304  m_imageLookup = NULL;
1305  }
1306 
1307  if (m_imageDownload)
1308  {
1310  delete m_imageDownload;
1311  m_imageDownload = NULL;
1312  }
1313 }
1314 
1316 {
1318  "schedule-ui.xml", "metadataoptions",
1320  {
1321  return false;
1322  }
1323 
1324  bool err = false;
1325 
1326  UIUtilE::Assign(this, m_inetrefEdit, "inetref_edit", &err);
1327  UIUtilE::Assign(this, m_seasonSpin, "season_spinbox", &err);
1328  UIUtilE::Assign(this, m_episodeSpin, "episode_spinbox", &err);
1329  UIUtilE::Assign(this, m_queryButton, "query_button", &err);
1330  UIUtilE::Assign(this, m_localFanartButton, "local_fanart_button", &err);
1331  UIUtilE::Assign(this, m_localCoverartButton, "local_coverart_button", &err);
1332  UIUtilE::Assign(this, m_localBannerButton, "local_banner_button", &err);
1333  UIUtilE::Assign(this, m_onlineFanartButton, "online_fanart_button", &err);
1334  UIUtilE::Assign(this, m_onlineCoverartButton, "online_coverart_button", &err);
1335  UIUtilE::Assign(this, m_onlineBannerButton, "online_banner_button", &err);
1336  UIUtilW::Assign(this, m_fanart, "fanart");
1337  UIUtilW::Assign(this, m_coverart, "coverart");
1338  UIUtilW::Assign(this, m_banner, "banner");
1339 
1340  if (err)
1341  {
1342  LOG(VB_GENERAL, LOG_ERR, "MetadataOptions, theme is missing "
1343  "required elements");
1344  return false;
1345  }
1346 
1347  connect(m_queryButton, SIGNAL(Clicked()),
1348  SLOT(PerformQuery()));
1349  connect(m_localFanartButton, SIGNAL(Clicked()),
1350  SLOT(SelectLocalFanart()));
1351  connect(m_localCoverartButton, SIGNAL(Clicked()),
1352  SLOT(SelectLocalCoverart()));
1353  connect(m_localBannerButton, SIGNAL(Clicked()),
1354  SLOT(SelectLocalBanner()));
1355  connect(m_onlineFanartButton, SIGNAL(Clicked()),
1356  SLOT(SelectOnlineFanart()));
1357  connect(m_onlineCoverartButton, SIGNAL(Clicked()),
1358  SLOT(SelectOnlineCoverart()));
1359  connect(m_onlineBannerButton, SIGNAL(Clicked()),
1360  SLOT(SelectOnlineBanner()));
1361 
1362  connect(m_seasonSpin, SIGNAL(itemSelected(MythUIButtonListItem*)),
1363  SLOT(ValuesChanged()));
1364 
1365  // InetRef
1367 
1368  // Season
1369  m_seasonSpin->SetRange(0,9999,1,5);
1371 
1372  // Episode
1373  m_episodeSpin->SetRange(0,9999,1,10);
1375 
1376  if (m_coverart)
1377  {
1379  m_coverart->Load();
1380  }
1381 
1382  if (m_fanart)
1383  {
1385  m_fanart->Load();
1386  }
1387 
1388  if (m_banner)
1389  {
1391  m_banner->Load();
1392  }
1393 
1394  BuildFocusList();
1395 
1396  return true;
1397 }
1398 
1400 {
1401  SetTextFromMaps();
1402 }
1403 
1405 {
1406  if (m_busyPopup)
1407  return;
1408 
1409  QString message = title;
1410 
1411  m_busyPopup = new MythUIBusyDialog(message, m_popupStack,
1412  "metaoptsdialog");
1413 
1414  if (m_busyPopup->Create())
1416 }
1417 
1419 {
1420  CreateBusyDialog(tr("Trying to manually find this "
1421  "recording online..."));
1422 
1424 
1425  lookup->SetAutomatic(false);
1426  m_metadataFactory->Lookup(lookup);
1427 }
1428 
1430 {
1431  QueryComplete(lookup);
1432 }
1433 
1436 {
1437  QString msg = tr("Downloading selected artwork...");
1438  CreateBusyDialog(msg);
1439 
1440  MetadataLookup *lookup = new MetadataLookup();
1441 
1442  lookup->SetType(kMetadataVideo);
1444  lookup->SetAutomatic(true);
1445  lookup->SetData(qVariantFromValue<VideoArtworkType>(type));
1446 
1447  ArtworkMap downloads;
1448  downloads.insert(type, info);
1449  lookup->SetDownloads(downloads);
1450  lookup->SetAllowOverwrites(true);
1451  lookup->SetTitle(m_recordingRule->m_title);
1453  lookup->SetInetref(m_inetrefEdit->GetText());
1454  lookup->SetSeason(m_seasonSpin->GetIntValue());
1455  lookup->SetEpisode(m_episodeSpin->GetIntValue());
1456 
1457  m_imageDownload->addDownloads(lookup);
1458 }
1459 
1461 {
1462  if (!CanSetArtwork())
1463  return;
1464 
1465  QString url = generate_file_url("Fanart",
1467  "");
1468  FindImagePopup(url,"",*this, "fanart");
1469 }
1470 
1472 {
1473  if (!CanSetArtwork())
1474  return;
1475 
1476  QString url = generate_file_url("Coverart",
1478  "");
1479  FindImagePopup(url,"",*this, "coverart");
1480 }
1481 
1483 {
1484  if (!CanSetArtwork())
1485  return;
1486 
1487  QString url = generate_file_url("Banners",
1489  "");
1490  FindImagePopup(url,"",*this, "banner");
1491 }
1492 
1494 {
1496 }
1497 
1499 {
1501 }
1502 
1504 {
1506 }
1507 
1509 {
1510  // Season
1511  if (m_seasonSpin)
1513 
1514  // Episode
1515  if (m_episodeSpin)
1517 
1518  // InetRef
1519  if (m_inetrefEdit)
1521 }
1522 
1524 {
1525  if (!lookup)
1526  return;
1527 
1528  // InetRef
1529  m_inetrefEdit->SetText(lookup->GetInetref());
1530 
1531  // Season
1532  m_seasonSpin->SetValue(lookup->GetSeason());
1533 
1534  // Episode
1535  m_episodeSpin->SetValue(lookup->GetEpisode());
1536 
1537  InfoMap metadataMap;
1538  lookup->toMap(metadataMap);
1539  SetTextFromMap(metadataMap);
1540 }
1541 
1543  const QString &prefixAlt,
1544  QObject &inst,
1545  const QString &returnEvent)
1546 {
1547  QString fp;
1548 
1549  if (prefix.startsWith("myth://"))
1550  fp = prefix;
1551  else
1552  fp = prefix.isEmpty() ? prefixAlt : prefix;
1553 
1554  MythScreenStack *popupStack =
1555  GetMythMainWindow()->GetStack("popup stack");
1556 
1557  MythUIFileBrowser *fb = new MythUIFileBrowser(popupStack, fp);
1559  if (fb->Create())
1560  {
1561  fb->SetReturnEvent(&inst, returnEvent);
1562  popupStack->AddScreen(fb);
1563  }
1564  else
1565  delete fb;
1566 }
1567 
1569 {
1570  QStringList ret;
1571 
1572  QList<QByteArray> exts = QImageReader::supportedImageFormats();
1573  for (QList<QByteArray>::iterator p = exts.begin(); p != exts.end(); ++p)
1574  {
1575  ret.append(QString("*.").append(*p));
1576  }
1577 
1578  return ret;
1579 }
1580 
1582 {
1583  if (m_inetrefEdit->GetText().isEmpty())
1584  {
1585  ShowOkPopup(tr("You must set a reference number "
1586  "on this rule to set artwork. For items "
1587  "without a metadata source, you can set "
1588  "any unique value."));
1589  return false;
1590  }
1591 
1592  return true;
1593 }
1594 
1596 {
1597  MetadataLookup *lookup = new MetadataLookup();
1598  lookup->SetStep(kLookupSearch);
1599  lookup->SetType(mtype);
1601 
1602  if (type == kUnknownVideo)
1603  {
1605  (m_seasonSpin->GetIntValue() == 0 &&
1606  m_episodeSpin->GetIntValue() == 0))
1607  {
1608  lookup->SetSubtype(kProbableMovie);
1609  }
1610  else
1611  {
1613  }
1614  }
1615  else
1616  {
1617  // we could determine the type from the inetref
1618  lookup->SetSubtype(type);
1619  }
1620  lookup->SetAllowGeneric(true);
1621  lookup->SetHandleImages(false);
1623  lookup->SetTitle(m_recordingRule->m_title);
1625  lookup->SetInetref(m_inetrefEdit->GetText());
1627  lookup->SetSeason(m_seasonSpin->GetIntValue());
1628  lookup->SetEpisode(m_episodeSpin->GetIntValue());
1629 
1630  return lookup;
1631 }
1632 
1634 {
1635  if (!CanSetArtwork())
1636  return;
1637 
1638  QString msg = tr("Searching for available artwork...");
1639  CreateBusyDialog(msg);
1640 
1642 
1643  lookup->SetAutomatic(true);
1644  lookup->SetData(qVariantFromValue<VideoArtworkType>(type));
1645  m_imageLookup->addLookup(lookup);
1646 }
1647 
1649 {
1650  if (!lookup)
1651  return;
1652 
1653  if (m_busyPopup)
1654  {
1655  m_busyPopup->Close();
1656  m_busyPopup = NULL;
1657  }
1658 
1659  VideoArtworkType type = lookup->GetData().value<VideoArtworkType>();
1660  ArtworkList list = lookup->GetArtwork(type);
1661 
1662  if (list.isEmpty())
1663  {
1664  MythWarningNotification n(tr("No image found"), tr("Schedule Editor"));
1666  return;
1667  }
1668 
1669  ImageSearchResultsDialog *resultsdialog =
1670  new ImageSearchResultsDialog(m_popupStack, list, type);
1671 
1672  connect(resultsdialog, SIGNAL(haveResult(ArtworkInfo, VideoArtworkType)),
1674 
1675  if (resultsdialog->Create())
1676  m_popupStack->AddScreen(resultsdialog);
1677 }
1678 
1680 {
1681  if (!lookup)
1682  return;
1683 
1684  DownloadMap map = lookup->GetDownloads();
1685 
1686  if (map.isEmpty())
1687  return;
1688 
1689  for (DownloadMap::const_iterator i = map.begin(); i != map.end(); ++i)
1690  {
1691  VideoArtworkType type = i.key();
1692  ArtworkInfo info = i.value();
1693 
1694  if (type == kArtworkCoverart)
1695  m_artworkMap.replace(kArtworkCoverart, info);
1696  else if (type == kArtworkFanart)
1697  m_artworkMap.replace(kArtworkFanart, info);
1698  else if (type == kArtworkBanner)
1699  m_artworkMap.replace(kArtworkBanner, info);
1700  }
1701 
1704 
1705  ValuesChanged();
1706 }
1707 
1709 {
1712 
1713  if (m_coverart)
1714  {
1716  m_coverart->Load();
1717  }
1718 
1719  if (m_fanart)
1720  {
1722  m_fanart->Load();
1723  }
1724 
1725  if (m_banner)
1726  {
1728  m_banner->Load();
1729  }
1730 }
1731 
1732 void MetadataOptions::customEvent(QEvent *levent)
1733 {
1734  if (levent->type() == MetadataFactoryMultiResult::kEventType)
1735  {
1736  if (m_busyPopup)
1737  {
1738  m_busyPopup->Close();
1739  m_busyPopup = NULL;
1740  }
1741 
1742  MetadataFactoryMultiResult *mfmr = dynamic_cast<MetadataFactoryMultiResult*>(levent);
1743 
1744  if (!mfmr)
1745  return;
1746 
1747  MetadataLookupList list = mfmr->results;
1748 
1749  if (list.count() > 1)
1750  {
1751  int yearindex = -1;
1752 
1753  for (int p = 0; p != list.size(); ++p)
1754  {
1755  if (!m_recordingRule->m_seriesid.isEmpty() &&
1756  m_recordingRule->m_seriesid == (list[p])->GetTMSref())
1757  {
1758  MetadataLookup *lookup = list[p];
1759  QueryComplete(lookup);
1760  return;
1761  }
1762  else if (m_recInfo &&
1764  (list[p])->GetYear() != 0 &&
1765  m_recInfo->GetYearOfInitialRelease() == (list[p])->GetYear())
1766  {
1767  if (yearindex > -1)
1768  {
1769  LOG(VB_GENERAL, LOG_INFO, "Multiple results matched on year. No definite "
1770  "match could be found based on year alone.");
1771  yearindex = -2;
1772  }
1773  else if (yearindex == -1)
1774  {
1775  LOG(VB_GENERAL, LOG_INFO, "Matched based on year. ");
1776  yearindex = p;
1777  }
1778  }
1779  }
1780 
1781  if (yearindex > -1)
1782  {
1783  MetadataLookup *lookup = list[yearindex];
1784  QueryComplete(lookup);
1785  return;
1786  }
1787 
1788  LOG(VB_GENERAL, LOG_INFO, "Falling through to selection dialog.");
1789  MetadataResultsDialog *resultsdialog =
1791 
1792  connect(resultsdialog, SIGNAL(haveResult(RefCountHandler<MetadataLookup>)),
1794  Qt::QueuedConnection);
1795 
1796  if (resultsdialog->Create())
1797  m_popupStack->AddScreen(resultsdialog);
1798  }
1799  }
1800  else if (levent->type() == MetadataFactorySingleResult::kEventType)
1801  {
1802  if (m_busyPopup)
1803  {
1804  m_busyPopup->Close();
1805  m_busyPopup = NULL;
1806  }
1807 
1808  MetadataFactorySingleResult *mfsr = dynamic_cast<MetadataFactorySingleResult*>(levent);
1809 
1810  if (!mfsr)
1811  return;
1812 
1813  MetadataLookup *lookup = mfsr->result;
1814 
1815  if (!lookup)
1816  return;
1817 
1818  QueryComplete(lookup);
1819  }
1820  else if (levent->type() == MetadataFactoryNoResult::kEventType)
1821  {
1822  if (m_busyPopup)
1823  {
1824  m_busyPopup->Close();
1825  m_busyPopup = NULL;
1826  }
1827 
1828  MetadataFactoryNoResult *mfnr = dynamic_cast<MetadataFactoryNoResult*>(levent);
1829 
1830  if (!mfnr)
1831  return;
1832 
1833  QString title = tr("No match found for this recording. You can "
1834  "try entering a TVDB/TMDB number, season, and "
1835  "episode manually.");
1836 
1837  MythConfirmationDialog *okPopup =
1838  new MythConfirmationDialog(m_popupStack, title, false);
1839 
1840  if (okPopup->Create())
1841  m_popupStack->AddScreen(okPopup);
1842  }
1843  else if (levent->type() == MetadataLookupEvent::kEventType)
1844  {
1845  if (m_busyPopup)
1846  {
1847  m_busyPopup->Close();
1848  m_busyPopup = NULL;
1849  }
1850 
1851  MetadataLookupEvent *lue = (MetadataLookupEvent *)levent;
1852 
1853  MetadataLookupList lul = lue->lookupList;
1854 
1855  if (lul.isEmpty())
1856  return;
1857 
1858  if (lul.count() >= 1)
1859  {
1860  OnArtworkSearchDone(lul[0]);
1861  }
1862  }
1863  else if (levent->type() == MetadataLookupFailure::kEventType)
1864  {
1865  if (m_busyPopup)
1866  {
1867  m_busyPopup->Close();
1868  m_busyPopup = NULL;
1869  }
1870 
1872 
1873  MetadataLookupList lul = luf->lookupList;
1874 
1875  if (lul.size())
1876  {
1877  QString title = tr("This number, season, and episode combination "
1878  "does not appear to be valid (or the site may "
1879  "be down). Check your information and try "
1880  "again.");
1881 
1882  MythConfirmationDialog *okPopup =
1883  new MythConfirmationDialog(m_popupStack, title, false);
1884 
1885  if (okPopup->Create())
1886  m_popupStack->AddScreen(okPopup);
1887  }
1888  }
1889  else if (levent->type() == ImageDLEvent::kEventType)
1890  {
1891  if (m_busyPopup)
1892  {
1893  m_busyPopup->Close();
1894  m_busyPopup = NULL;
1895  }
1896 
1897  ImageDLEvent *ide = (ImageDLEvent *)levent;
1898 
1899  MetadataLookup *lookup = ide->item;
1900 
1901  if (!lookup)
1902  return;
1903 
1904  HandleDownloadedImages(lookup);
1905  }
1906  else if (levent->type() == ImageDLFailureEvent::kEventType)
1907  {
1908  if (m_busyPopup)
1909  {
1910  m_busyPopup->Close();
1911  m_busyPopup = NULL;
1912  }
1913  MythErrorNotification n(tr("Failed to retrieve image(s)"),
1914  tr("Schedule Editor"),
1915  tr("Check logs"));
1917  }
1918  else if (levent->type() == DialogCompletionEvent::kEventType)
1919  {
1920  DialogCompletionEvent *dce = (DialogCompletionEvent*)(levent);
1921 
1922  const QString resultid = dce->GetId();
1923  ArtworkInfo info;
1924  info.url = dce->GetResultText();
1925 
1926  if (resultid == "coverart")
1927  {
1928  m_artworkMap.replace(kArtworkCoverart, info);
1929  }
1930  else if (resultid == "fanart")
1931  {
1932  m_artworkMap.replace(kArtworkFanart, info);
1933  }
1934  else if (resultid == "banner")
1935  {
1936  m_artworkMap.replace(kArtworkBanner, info);
1937  }
1938 
1941 
1942  ValuesChanged();
1943  }
1944 
1945 }
1946 
1948 
1955  SchedOptMixin *other)
1956  : m_prioritySpin(NULL), m_startoffsetSpin(NULL), m_endoffsetSpin(NULL),
1957  m_dupmethodList(NULL), m_dupscopeList(NULL), m_inputList(NULL),
1958  m_ruleactiveCheck(NULL), m_newrepeatList(NULL),
1959  m_screen(&screen), m_rule(rule), m_other(other), m_loaded(false),
1960  m_haveRepeats(gCoreContext->GetNumSetting("HaveRepeats", 0))
1961 {
1962 }
1963 
1964 void SchedOptMixin::Create(bool *err)
1965 {
1966  if (!m_rule)
1967  return;
1968 
1969  if (m_other && !m_other->m_prioritySpin)
1970  UIUtilE::Assign(m_screen, m_prioritySpin, "priority", err);
1971  else
1972  UIUtilW::Assign(m_screen, m_prioritySpin, "priority");
1973 
1975  UIUtilE::Assign(m_screen, m_startoffsetSpin, "startoffset", err);
1976  else
1977  UIUtilW::Assign(m_screen, m_startoffsetSpin, "startoffset");
1978 
1979  if (m_other && !m_other->m_endoffsetSpin)
1980  UIUtilE::Assign(m_screen, m_endoffsetSpin, "endoffset", err);
1981  else
1982  UIUtilW::Assign(m_screen, m_endoffsetSpin, "endoffset");
1983 
1984  if (m_other && !m_other->m_dupmethodList)
1985  UIUtilE::Assign(m_screen, m_dupmethodList, "dupmethod", err);
1986  else
1987  UIUtilW::Assign(m_screen, m_dupmethodList, "dupmethod");
1988 
1989  if (m_other && !m_other->m_dupscopeList)
1990  UIUtilE::Assign(m_screen, m_dupscopeList, "dupscope", err);
1991  else
1992  UIUtilW::Assign(m_screen, m_dupscopeList, "dupscope");
1993 
1994  if (m_other && !m_other->m_inputList)
1995  UIUtilE::Assign(m_screen, m_inputList, "input", err);
1996  else
1998 
2000  UIUtilE::Assign(m_screen, m_ruleactiveCheck, "ruleactive", err);
2001  else
2002  UIUtilW::Assign(m_screen, m_ruleactiveCheck, "ruleactive");
2003 
2004  UIUtilW::Assign(m_screen, m_newrepeatList, "newrepeat");
2005 }
2006 
2008 {
2009  if (!m_rule)
2010  return;
2011 
2012  // Priority
2013  if (m_prioritySpin)
2014  {
2015  if (!m_loaded)
2016  m_prioritySpin->SetRange(-99,99,1,5);
2018  }
2019 
2020  // Start Offset
2021  if (m_startoffsetSpin)
2022  {
2023  if (!m_loaded)
2024  m_startoffsetSpin->SetRange(480,-480,1,10);
2026  }
2027 
2028  // End Offset
2029  if (m_endoffsetSpin)
2030  {
2031  if (!m_loaded)
2032  m_endoffsetSpin->SetRange(-480,480,1,10);
2034  }
2035 
2036  // Duplicate Match Type
2037  if (m_dupmethodList)
2038  {
2039  if (!m_loaded)
2040  {
2042 
2045  ENUM_TO_QVARIANT(kDupCheckSubDesc));
2048  ENUM_TO_QVARIANT(kDupCheckSubThenDesc));
2051  ENUM_TO_QVARIANT(kDupCheckSub));
2054  ENUM_TO_QVARIANT(kDupCheckDesc));
2057  ENUM_TO_QVARIANT(kDupCheckNone));
2058 
2059  m_rule->m_dupMethod = dupMethod;
2060  }
2061  m_dupmethodList->SetValueByData(ENUM_TO_QVARIANT(m_rule->m_dupMethod));
2062  }
2063 
2064  // Duplicate Matching Scope
2065  if (m_dupscopeList)
2066  {
2067  if (!m_loaded)
2068  {
2071  ENUM_TO_QVARIANT(kDupsInAll));
2074  ENUM_TO_QVARIANT(kDupsInRecorded));
2077  ENUM_TO_QVARIANT(kDupsInOldRecorded));
2078  if (m_haveRepeats && !m_newrepeatList &&
2080  {
2083  ENUM_TO_QVARIANT(kDupsNewEpi|kDupsInAll));
2084  }
2085  }
2086  m_dupscopeList->SetValueByData(ENUM_TO_QVARIANT(m_rule->m_dupIn));
2087  }
2088 
2089  // Preferred Input
2090  if (m_inputList)
2091  {
2092  if (!m_loaded)
2093  {
2095  QObject::tr("Use any available input"),
2096  qVariantFromValue(0));
2097 
2098  vector<uint> inputids = CardUtil::GetInputList();
2099  for (uint i = 0; i < inputids.size(); ++i)
2100  {
2102  QObject::tr("Prefer input %1")
2103  .arg(CardUtil::GetDisplayName(inputids[i])), inputids[i]);
2104  }
2105  }
2107  }
2108 
2109  // Active/Disabled
2110  if (m_ruleactiveCheck)
2111  {
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"), ENUM_TO_QVARIANT(0));
2124  QObject::tr("Record new episodes only"),
2125  ENUM_TO_QVARIANT(kDupsNewEpi));
2126  }
2127  m_newrepeatList->SetValueByData(ENUM_TO_QVARIANT
2128  (m_rule->m_dupIn & kDupsNewEpi));
2129  }
2130 
2131  m_loaded = true;
2132 
2133  RuleChanged();
2134 }
2135 
2137 {
2138  if (!m_rule)
2139  return;
2140 
2141  if (m_prioritySpin)
2143  if (m_startoffsetSpin)
2145  if (m_endoffsetSpin)
2147  if (m_dupmethodList)
2148  m_rule->m_dupMethod = static_cast<RecordingDupMethodType>
2149  (m_dupmethodList->GetDataValue().toInt());
2150  if (m_dupscopeList)
2151  {
2152  int mask = ((m_other && m_other->m_newrepeatList) ||
2153  m_newrepeatList) ? kDupsInAll : ~0;
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_inputList)
2160  if (m_ruleactiveCheck)
2162  if (m_newrepeatList)
2163  {
2164  int val = ((m_rule->m_dupIn & ~kDupsNewEpi) |
2165  m_newrepeatList->GetDataValue().toInt());
2166  m_rule->m_dupIn = static_cast<RecordingDupInType>(val);
2167  }
2168 }
2169 
2171 {
2172  if (!m_rule)
2173  return;
2174 
2175  bool isScheduled = (m_rule->m_type != kNotRecording &&
2176  m_rule->m_type != kDontRecord);
2177  bool isSingle = (m_rule->m_type == kSingleRecord ||
2179 
2180  if (m_prioritySpin)
2181  m_prioritySpin->SetEnabled(isScheduled);
2182  if (m_startoffsetSpin)
2183  m_startoffsetSpin->SetEnabled(isScheduled);
2184  if (m_endoffsetSpin)
2185  m_endoffsetSpin->SetEnabled(isScheduled);
2186  if (m_dupmethodList)
2187  m_dupmethodList->SetEnabled(isScheduled && !isSingle);
2188  if (m_dupscopeList)
2189  m_dupscopeList->SetEnabled(isScheduled && !isSingle &&
2191  if (m_inputList)
2192  m_inputList->SetEnabled(isScheduled);
2193  if (m_ruleactiveCheck)
2194  m_ruleactiveCheck->SetEnabled(isScheduled);
2195  if (m_newrepeatList)
2196  m_newrepeatList->SetEnabled(isScheduled && !isSingle && m_haveRepeats);
2197 }
2198 
2200 {
2201  if (!item || !m_rule)
2202  return;
2203 
2204  m_rule->m_dupMethod = static_cast<RecordingDupMethodType>
2205  (item->GetData().toInt());
2206 
2207  if (m_dupscopeList)
2209 }
2210 
2212 
2219  FilterOptMixin *other)
2220  : m_filtersList(NULL), m_activeFiltersList(NULL),
2221  m_screen(&screen), m_rule(rule), m_other(other), m_loaded(false)
2222 {
2223 }
2224 
2225 void FilterOptMixin::Create(bool *err)
2226 {
2227  if (!m_rule)
2228  return;
2229 
2230  if (m_other && !m_other->m_filtersList)
2231  UIUtilE::Assign(m_screen, m_filtersList, "filters", err);
2232  else
2233  UIUtilW::Assign(m_screen, m_filtersList, "filters");
2234 
2235  UIUtilW::Assign(m_screen, m_activeFiltersList, "activefilters");
2236  if (m_activeFiltersList)
2238 }
2239 
2241 {
2242  if (!m_rule)
2243  return;
2244 
2245  if (!m_loaded)
2246  {
2247  MSqlQuery query(MSqlQuery::InitCon());
2248 
2249  query.prepare("SELECT filterid, description, newruledefault "
2250  "FROM recordfilter ORDER BY filterid");
2251 
2252  if (query.exec())
2253  {
2254  while (query.next())
2255  {
2256  m_descriptions << QObject::tr(query.value(1).toString()
2257  .toUtf8().constData());
2258  }
2259  }
2260  m_loaded = true;
2261  }
2262 
2263  if (m_activeFiltersList)
2265 
2266  MythUIButtonListItem *button;
2267  QStringList::iterator Idesc;
2268  int idx;
2269  bool active;
2270  bool not_empty = m_filtersList && !m_filtersList->IsEmpty();
2271  for (Idesc = m_descriptions.begin(), idx = 0;
2272  Idesc != m_descriptions.end(); ++Idesc, ++idx)
2273  {
2274  active = m_rule->m_filter & (1 << idx);
2275  if (m_filtersList)
2276  {
2277  if (not_empty)
2278  button = m_filtersList->GetItemAt(idx);
2279  else
2280  button = new MythUIButtonListItem(m_filtersList, *Idesc, idx);
2281  button->setCheckable(true);
2284  }
2285  if (active && m_activeFiltersList)
2286  {
2287  /* Create a simple list of active filters the theme can
2288  use for informational purposes. */
2290  *Idesc, idx);
2291  button->setCheckable(false);
2292  }
2293  }
2294 
2296  {
2298  QObject::tr("None"), idx);
2299  button->setCheckable(false);
2300  }
2301 
2302  RuleChanged();
2303 }
2304 
2306 {
2307  if (!m_rule || !m_filtersList)
2308  return;
2309 
2310  // Iterate through button list, and build the mask
2311  MythUIButtonListItem *button;
2312  uint32_t filter_mask = 0;
2313  int idx, end;
2314 
2315  end = m_filtersList->GetCount();
2316  for (idx = 0; idx < end; ++idx)
2317  {
2318  if ((button = m_filtersList->GetItemAt(idx)) &&
2320  filter_mask |= (1 << button->GetData().value<uint32_t>());
2321  }
2322  m_rule->m_filter = filter_mask;
2323 }
2324 
2326 {
2327  if (!m_rule)
2328  return;
2329 
2330  bool enabled = m_rule->m_type != kNotRecording &&
2332  if (m_filtersList)
2333  m_filtersList->SetEnabled(enabled);
2334  if (m_activeFiltersList)
2335  m_activeFiltersList->SetEnabled(enabled);
2336 }
2337 
2339 {
2343 }
2344 
2345 
2347 
2354  StoreOptMixin *other)
2355  : m_recprofileList(NULL), m_recgroupList(NULL), m_storagegroupList(NULL),
2356  m_playgroupList(NULL), m_maxepSpin(NULL), m_maxbehaviourList(NULL),
2357  m_autoexpireCheck(NULL),
2358  m_screen(&screen), m_rule(rule), m_other(other), m_loaded(false)
2359 {
2360 }
2361 
2362 void StoreOptMixin::Create(bool *err)
2363 {
2364  if (!m_rule)
2365  return;
2366 
2367  if (m_other && !m_other->m_recprofileList)
2368  UIUtilE::Assign(m_screen, m_recprofileList, "recprofile", err);
2369  else
2370  UIUtilW::Assign(m_screen, m_recprofileList, "recprofile");
2371 
2372  if (m_other && !m_other->m_recgroupList)
2373  UIUtilE::Assign(m_screen, m_recgroupList, "recgroup", err);
2374  else
2375  UIUtilW::Assign(m_screen, m_recgroupList, "recgroup");
2376 
2378  UIUtilE::Assign(m_screen, m_storagegroupList, "storagegroup", err);
2379  else
2380  UIUtilW::Assign(m_screen, m_storagegroupList, "storagegroup");
2381 
2382  if (m_other && !m_other->m_playgroupList)
2383  UIUtilE::Assign(m_screen, m_playgroupList, "playgroup", err);
2384  else
2385  UIUtilW::Assign(m_screen, m_playgroupList, "playgroup");
2386 
2387  if (m_other && !m_other->m_maxepSpin)
2388  UIUtilE::Assign(m_screen, m_maxepSpin, "maxepisodes", err);
2389  else
2390  UIUtilW::Assign(m_screen, m_maxepSpin, "maxepisodes");
2391 
2393  UIUtilE::Assign(m_screen, m_maxbehaviourList, "maxnewest", err);
2394  else
2396 
2398  UIUtilE::Assign(m_screen, m_autoexpireCheck, "autoexpire", err);
2399  else
2400  UIUtilW::Assign(m_screen, m_autoexpireCheck, "autoexpire");
2401 }
2402 
2404 {
2405  if (!m_rule)
2406  return;
2407 
2408  QString label;
2409  QStringList groups;
2410  QStringList::Iterator it;
2411  MSqlQuery query(MSqlQuery::InitCon());
2412 
2413  // Recording Profile
2414  if (m_recprofileList)
2415  {
2416  if (!m_loaded)
2417  {
2418  label = QObject::tr("Record using the %1 profile");
2419 
2421  label.arg(QObject::tr("Default")),
2422  qVariantFromValue(QString("Default")));
2423  // LiveTV profile - it's for LiveTV not scheduled recordings??
2425  label.arg(QObject::tr("LiveTV")),
2426  qVariantFromValue(QString("LiveTV")));
2428  label.arg(QObject::tr("High Quality")),
2429  qVariantFromValue(QString("High Quality")));
2431  label.arg(QObject::tr("Low Quality")),
2432  qVariantFromValue(QString("Low Quality")));
2433  }
2435  }
2436 
2437  // Recording Group
2438  if (m_recgroupList)
2439  {
2440  if (!m_loaded)
2441  {
2442  label = QObject::tr("Include in the \"%1\" recording group");
2444  QObject::tr("Create a new recording group"),
2445  qVariantFromValue(QString("__NEW_GROUP__")));
2446 
2447  query.prepare("SELECT recgroupid, recgroup FROM recgroups "
2448  "WHERE recgroup <> 'Deleted' AND "
2449  " recgroup <> 'LiveTV' "
2450  "ORDER BY special DESC, recgroup ASC"); // Special groups first
2451  if (query.exec())
2452  {
2453  while (query.next())
2454  {
2455  int id = query.value(0).toInt();
2456  QString name = query.value(1).toString();
2457 
2458  if (name == "Default")
2459  name = QObject::tr("Default");
2460  new MythUIButtonListItem(m_recgroupList, label.arg(name),
2461  qVariantFromValue(id));
2462  }
2463  }
2464 
2465  }
2467  }
2468 
2469  // Storage Group
2470  if (m_storagegroupList)
2471  {
2472  if (!m_loaded)
2473  {
2474  label = QObject::tr("Store in the \"%1\" storage group");
2476  label.arg(QObject::tr("Default")),
2477  qVariantFromValue(QString("Default")));
2478 
2480  for (it = groups.begin(); it != groups.end(); ++it)
2481  {
2482  if ((*it).compare("Default", Qt::CaseInsensitive) != 0)
2484  label.arg(*it), qVariantFromValue(*it));
2485  }
2486  }
2488  }
2489 
2490  // Playback Group
2491  if (m_playgroupList)
2492  {
2493  if (!m_loaded)
2494  {
2495  label = QObject::tr("Use \"%1\" playback group settings");
2497  label.arg(QObject::tr("Default")),
2498  qVariantFromValue(QString("Default")));
2499 
2500  groups = PlayGroup::GetNames();
2501  for (it = groups.begin(); it != groups.end(); ++it)
2502  {
2503  new MythUIButtonListItem(m_playgroupList, label.arg(*it),
2504  qVariantFromValue(*it));
2505  }
2506  }
2508  }
2509 
2510  // Max Episodes
2511  if (m_maxepSpin)
2512  {
2513  if (!m_loaded)
2514  {
2515  int maxEpisodes = m_rule->m_maxEpisodes;
2516  m_maxepSpin->SetRange(0,100,1,5);
2517  m_rule->m_maxEpisodes = maxEpisodes;
2518  }
2520  }
2521 
2522  // Max Episode Behaviour
2523  if (m_maxbehaviourList)
2524  {
2525  if (!m_loaded)
2526  {
2528  QObject::tr("Don't record if this would exceed the max "
2529  "episodes"), qVariantFromValue(false));
2531  QObject::tr("Delete oldest if this would exceed the max "
2532  "episodes"), qVariantFromValue(true));
2533  }
2535  }
2536 
2537  // Auto-Expire
2538  if (m_autoexpireCheck)
2539  {
2541  }
2542 
2543  m_loaded = true;
2544 
2545  RuleChanged();
2546 }
2547 
2549 {
2550  if (!m_rule)
2551  return;
2552 
2553  if (m_recprofileList)
2555 
2556  if (m_recgroupList)
2557  {
2558  // If the user selected 'Create a new regroup' but failed to enter a
2559  // name when prompted, restore the original value
2560  if (m_recgroupList->GetDataValue().toString() == "__NEW_GROUP__")
2563  }
2564 
2565  if (m_storagegroupList)
2567 
2568  if (m_playgroupList)
2570 
2571  if (m_maxepSpin)
2573 
2574  if (m_maxbehaviourList)
2576 
2577  if (m_autoexpireCheck)
2579 }
2580 
2582 {
2583  if (!m_rule)
2584  return;
2585 
2586  bool isScheduled = (m_rule->m_type != kNotRecording &&
2587  m_rule->m_type != kDontRecord);
2588  bool isSingle = (m_rule->m_type == kSingleRecord ||
2590 
2591  if (m_recprofileList)
2592  m_recprofileList->SetEnabled(isScheduled);
2593  if (m_recgroupList)
2594  m_recgroupList->SetEnabled(isScheduled);
2595  if (m_storagegroupList)
2596  m_storagegroupList->SetEnabled(isScheduled);
2597  if (m_playgroupList)
2598  m_playgroupList->SetEnabled(isScheduled);
2599  if (m_maxepSpin)
2600  m_maxepSpin->SetEnabled(isScheduled && !isSingle);
2601  if (m_maxbehaviourList)
2602  m_maxbehaviourList->SetEnabled(isScheduled && !isSingle &&
2603  m_rule->m_maxEpisodes != 0);
2604  if (m_autoexpireCheck)
2605  m_autoexpireCheck->SetEnabled(isScheduled);
2606 }
2607 
2609 {
2610  if (!item || !m_rule)
2611  return;
2612 
2613  m_rule->m_maxEpisodes = item->GetData().toInt();
2614 
2615  if (m_maxbehaviourList)
2617 }
2618 
2620 {
2621  if (!m_rule)
2622  return;
2623 
2624  if (m_recgroupList->GetDataValue().toString() != "__NEW_GROUP__")
2625  return;
2626 
2627  MythScreenStack *popupStack = GetMythMainWindow()->GetStack("popup stack");
2628 
2629  QString label =
2630  QObject::tr("New Recording group name: ");
2631 
2632  MythTextInputDialog *textDialog =
2633  new MythTextInputDialog(popupStack, label,
2634  static_cast<InputFilter>(FilterSymbols | FilterPunct));
2635 
2636  textDialog->SetReturnEvent(m_screen, "newrecgroup");
2637 
2638  if (textDialog->Create())
2639  popupStack->AddScreen(textDialog, false);
2640 }
2641 
2642 void StoreOptMixin::SetRecGroup(int recgroupID, QString recgroup)
2643 {
2644  if (!m_rule || recgroupID <= 0)
2645  return;
2646 
2647  if (m_recgroupList)
2648  {
2649  recgroup = recgroup.trimmed();
2650  if (recgroup.isEmpty())
2651  return;
2652 
2653  QString label = QObject::tr("Include in the \"%1\" recording group");
2654  MythUIButtonListItem *item =
2655  new MythUIButtonListItem(m_recgroupList, label.arg(recgroup),
2656  qVariantFromValue(recgroup));
2658 
2659  if (m_other && m_other->m_recgroupList)
2660  {
2662  label.arg(recgroup), qVariantFromValue(recgroupID));
2664  }
2665  }
2666 }
2667 
2668 int StoreOptMixin::CreateRecordingGroup(const QString& groupName)
2669 {
2670  int groupID = -1;
2671  MSqlQuery query(MSqlQuery::InitCon());
2672 
2673  query.prepare("INSERT INTO recgroups SET recgroup = :NAME, "
2674  "displayname = :DISPLAYNAME");
2675  query.bindValue(":NAME", groupName);
2676  query.bindValue(":DISPLAYNAME", groupName);
2677 
2678  if (query.exec())
2679  groupID = query.lastInsertId().toInt();
2680 
2681  if (groupID <= 0)
2682  LOG(VB_GENERAL, LOG_ERR, QString("Could not create recording group (%1). "
2683  "Does it already exist?").arg(groupName));
2684 
2685  return groupID;
2686 }
2687 
2689 
2696  PostProcMixin *other)
2697  : m_commflagCheck(NULL), m_transcodeCheck(NULL),
2698  m_transcodeprofileList(NULL), m_userjob1Check(NULL),
2699  m_userjob2Check(NULL), m_userjob3Check(NULL), m_userjob4Check(NULL),
2700  m_metadataLookupCheck(NULL),
2701  m_screen(&screen), m_rule(rule), m_other(other), m_loaded(false)
2702 {
2703 }
2704 
2705 void PostProcMixin::Create(bool *err)
2706 {
2707  if (!m_rule)
2708  return;
2709 
2710  if (m_other && !m_other->m_commflagCheck)
2711  UIUtilE::Assign(m_screen, m_commflagCheck, "autocommflag", err);
2712  else
2713  UIUtilW::Assign(m_screen, m_commflagCheck, "autocommflag");
2714 
2715  if (m_other && !m_other->m_transcodeCheck)
2716  UIUtilE::Assign(m_screen, m_transcodeCheck, "autotranscode", err);
2717  else
2718  UIUtilW::Assign(m_screen, m_transcodeCheck, "autotranscode");
2719 
2721  UIUtilE::Assign(m_screen, m_transcodeprofileList, "transcodeprofile", err);
2722  else
2723  UIUtilW::Assign(m_screen, m_transcodeprofileList, "transcodeprofile");
2724 
2725  if (m_other && !m_other->m_userjob1Check)
2726  UIUtilE::Assign(m_screen, m_userjob1Check, "userjob1", err);
2727  else
2729 
2730  if (m_other && !m_other->m_userjob2Check)
2731  UIUtilE::Assign(m_screen, m_userjob2Check, "userjob2", err);
2732  else
2734 
2735  if (m_other && !m_other->m_userjob3Check)
2736  UIUtilE::Assign(m_screen, m_userjob3Check, "userjob3", err);
2737  else
2739 
2740  if (m_other && !m_other->m_userjob4Check)
2741  UIUtilE::Assign(m_screen, m_userjob4Check, "userjob4", err);
2742  else
2744 
2745  UIUtilW::Assign(m_screen, m_metadataLookupCheck, "metadatalookup");
2746 }
2747 
2749 {
2750  if (!m_rule)
2751  return;
2752 
2753  // Auto-commflag
2754  if (m_commflagCheck)
2755  {
2757  }
2758 
2759  // Auto-transcode
2760  if (m_transcodeCheck)
2761  {
2763  }
2764 
2765  // Transcode Method
2767  {
2768  if (!m_loaded)
2769  {
2770  QMap<int, QString> profiles = RecordingProfile::GetTranscodingProfiles();
2771  QMap<int, QString>::iterator it;
2772  for (it = profiles.begin(); it != profiles.end(); ++it)
2773  {
2775  qVariantFromValue(it.key()));
2776  }
2777  }
2779  }
2780 
2781  // User Job #1
2782  if (m_userjob1Check)
2783  {
2784  if (!m_loaded)
2785  {
2786  MythUIText *userjob1Text = NULL;
2787  UIUtilW::Assign(m_screen, userjob1Text, "userjob1text");
2788  if (userjob1Text)
2789  userjob1Text->SetText(QObject::tr("Run '%1'")
2790  .arg(gCoreContext->GetSetting("UserJobDesc1", "User Job 1")));
2791  }
2793  }
2794 
2795  // User Job #2
2796  if (m_userjob2Check)
2797  {
2798  if (!m_loaded)
2799  {
2800  MythUIText *userjob2Text = NULL;
2801  UIUtilW::Assign(m_screen, userjob2Text, "userjob2text");
2802  if (userjob2Text)
2803  userjob2Text->SetText(QObject::tr("Run '%1'")
2804  .arg(gCoreContext->GetSetting("UserJobDesc2", "User Job 2")));
2805  }
2807  }
2808 
2809  // User Job #3
2810  if (m_userjob3Check)
2811  {
2812  if (!m_loaded)
2813  {
2814  MythUIText *userjob3Text = NULL;
2815  UIUtilW::Assign(m_screen, userjob3Text, "userjob3text");
2816  if (userjob3Text)
2817  userjob3Text->SetText(QObject::tr("Run '%1'")
2818  .arg(gCoreContext->GetSetting("UserJobDesc3", "User Job 3")));
2819  }
2821  }
2822 
2823  // User Job #4
2824  if (m_userjob4Check)
2825  {
2826  if (!m_loaded)
2827  {
2828  MythUIText *userjob4Text = NULL;
2829  UIUtilW::Assign(m_screen, userjob4Text, "userjob4text");
2830  if (userjob4Text)
2831  userjob4Text->SetText(QObject::tr("Run '%1'")
2832  .arg(gCoreContext->GetSetting("UserJobDesc4", "User Job 4")));
2833  }
2835  }
2836 
2837  // Auto Metadata Lookup
2839  {
2841  }
2842 
2843  m_loaded = true;
2844 
2845  RuleChanged();
2846 }
2847 
2849 {
2850  if (!m_rule)
2851  return;
2852 
2853  if (m_commflagCheck)
2855  if (m_transcodeCheck)
2859  if (m_userjob1Check)
2861  if (m_userjob2Check)
2863  if (m_userjob3Check)
2865  if (m_userjob4Check)
2870 }
2871 
2873 {
2874  if (!m_rule)
2875  return;
2876 
2877  bool isScheduled = (m_rule->m_type != kNotRecording &&
2878  m_rule->m_type != kDontRecord);
2879 
2880  if (m_commflagCheck)
2881  m_commflagCheck->SetEnabled(isScheduled);
2882  if (m_transcodeCheck)
2883  m_transcodeCheck->SetEnabled(isScheduled);
2885  m_transcodeprofileList->SetEnabled(isScheduled &&
2887  if (m_userjob1Check)
2888  m_userjob1Check->SetEnabled(isScheduled);
2889  if (m_userjob2Check)
2890  m_userjob2Check->SetEnabled(isScheduled);
2891  if (m_userjob3Check)
2892  m_userjob3Check->SetEnabled(isScheduled);
2893  if (m_userjob4Check)
2894  m_userjob4Check->SetEnabled(isScheduled);
2896  m_metadataLookupCheck->SetEnabled(isScheduled);
2897 }
2898 
2900 {
2901  if (!m_rule)
2902  return;
2903 
2904  m_rule->m_autoTranscode = enable;
2905 
2908 }
QString m_subtitle
Definition: recordingrule.h:76
MetadataFactory * m_metadataFactory
MythScreenType * m_screen
void Create(bool *err)
bool next(void)
Wrap QSqlQuery::next() so we can display the query results.
Definition: mythdbcon.cpp:785
static bool Assign(ContainerType *container, UIType *&item, const QString &name, bool *err=NULL)
Definition: mythuiutils.h:27
MythUICheckBox * m_commflagCheck
void SetTitle(const QString &title)
void SetHandleImages(bool handle)
void MaxEpisodesChanged(MythUIButtonListItem *)
virtual void ShowUpcoming(void) const
Show the upcoming recordings for this title.
Select post-processing options.
void ruleDeleted(int ruleId)
static QString fs8(QT_TRANSLATE_NOOP("SchedFilterEditor","This time"))
void showUpcomingByTitle(void)
void bindValue(const QString &placeholder, const QVariant &val)
Definition: mythdbcon.cpp:884
MythUICheckBox * m_ruleactiveCheck
void RuleChanged(void)
uint GetYearOfInitialRelease(void) const
Definition: programinfo.h:401
virtual void ShowGuide(void) const
Show the program guide.
void DupMethodChanged(MythUIButtonListItem *)
void SetSubtitle(const QString &subtitle)
MetadataLookupList results
void SetAutomatic(bool autom)
void UseTempTable(bool usetemp, QString table="record_tmp")
MythUISpinBox * m_endoffsetSpin
bool StartEmbedding(const QRect &)
Definition: tv_play.cpp:8663
ScheduleEditor(MythScreenStack *parent, RecordingInfo *recinfo, TV *player=NULL)
QString toDescription(RecordingType rectype)
Converts "rectype" into a human readable description.
VERBOSE_PREAMBLE false
Definition: verbosedefs.h:83
bool LoadByProgram(const ProgramInfo *proginfo)
MythUIButton * m_localFanartButton
Dialog asking for user confirmation.
Select schedule filters.
void ToggleSelected(MythUIButtonListItem *item)
void LosingFocus()
void SetEnabled(bool enable)
Select artwork and inetref for recordings.
bool Delete(bool sendSig=true)
virtual bool keyPressEvent(QKeyEvent *event)
Key event handler.
bool IsLoaded() const
Definition: recordingrule.h:55
void TranscodeChanged(bool enable)
RecordingRule * m_recordingRule
MythScreenType * m_screen
MythUIButtonList * m_filtersList
MythConfirmationDialog * ShowOkPopup(const QString &message, QObject *parent, const char *slot, bool showCancel)
Non-blocking version of MythPopupBox::showOkPopup()
void showUpcomingByRule(void)
All purpose text widget, displays a text string.
Definition: mythuitext.h:28
MetadataType
ArtworkMap m_artworkMap
MythUISpinBox * m_prioritySpin
PostProcEditor(MythScreenStack *parent, ScheduleEditor &editor, RecordingRule &rule, RecordingInfo *recinfo)
QVariant value(int i) const
Definition: mythdbcon.h:182
enum RecordingDupInTypes RecordingDupInType
int GetIntValue(void) const
Definition: mythuispinbox.h:29
void templateLoaded(void)
virtual void Close(void)
void SetInetref(const QString &inetref)
MetadataLookupList lookupList
void FindImagePopup(const QString &prefix, const QString &prefixAlt, QObject &inst, const QString &returnEvent)
void SetData(QVariant data)
void MaxEpisodesChanged(MythUIButtonListItem *)
QSqlQuery wrapper that fetches a DB connection from the connection pool.
Definition: mythdbcon.h:125
static QString fs0(QT_TRANSLATE_NOOP("SchedFilterEditor","New episode"))
void SetAllowOverwrites(bool allow)
MythUIButtonList * m_playgroupList
void ToMap(InfoMap &infoMap) const
void TranscodeChanged(bool enable)
LookupType GuessLookupType(ProgramInfo *pginfo)
Basic menu dialog, message and a list of options.
void SetRule(RecordingRule *rule)
void Create(bool *err)
void SetReturnEvent(QObject *retobject, const QString &resultid)
VideoArtworkType
MythUICheckBox * m_userjob4Check
MythUIButton * m_filtersButton
QString m_storageGroup
static QStringList getRecordingsGroups(void)
virtual bool Create(void)
bool SetArtwork(const QString &inetref, uint season, const QString &host, const QString &coverart, const QString &fanart, const QString &banner)
QString m_station
Definition: recordingrule.h:93
virtual void SetText(const QString &text)
Definition: mythuitext.cpp:166
Holds information on a TV Program one might wish to record.
Definition: recordinginfo.h:33
void ToggleSelected(MythUIButtonListItem *item)
void Load(void)
Load data which will ultimately be displayed on-screen or used to determine what appears on-screen (S...
MythScreenStack * GetStack(const QString &stackname)
RecordingInfo * m_recInfo
void CreateBusyDialog(QString title)
unsigned int uint
Definition: compat.h:136
MythCoreContext * gCoreContext
This global variable contains the MythCoreContext instance for the app.
ArtworkList GetArtwork(VideoArtworkType type) const
static QString fs6(QT_TRANSLATE_NOOP("SchedFilterEditor","This episode"))
RecordingType m_type
Definition: recordingrule.h:99
MythScreenStack * GetMainStack()
MythUIButton * m_schedOptButton
void showTemplateMenu(void)
SchedEditChild * m_child
RecordingDupMethodType m_dupMethod
void ShowSchedInfo(void)
uint GetRecordingRuleID(void) const
Definition: programinfo.h:428
Select schedule options.
void SetRule(RecordingRule *rule)
MythUIButtonListItem * GetItemCurrent() const
SchedEditChild(MythScreenStack *parent, const QString &name, ScheduleEditor &editor, RecordingRule &rule, RecordingInfo *recinfo)
static QString fs2(QT_TRANSLATE_NOOP("SchedFilterEditor","First showing"))
void customEvent(QEvent *event)
MythUITextEdit * m_inetrefEdit
void DeleteRule(void)
bool Load(bool allowLoadInBackground=true, bool forceStat=false)
Load the image(s), wraps ImageLoader::LoadImage()
Mixin for schedule options.
void BuildFocusList(void)
static Type kEventType
Definition: mythdialogbox.h:45
MetadataLookup * item
RecordingRule * m_recordingRule
QVariant GetDataValue() const
MetadataLookup * CreateLookup(MetadataType mtype)
MythUICheckBox * m_metadataLookupCheck
MythUIImage * m_fanart
uint GetEpisode() const
void SetStep(LookupStep step)
RecordingDupMethodType
void SetNameFilter(QStringList filter)
void MaxEpisodesChanged(MythUIButtonListItem *)
virtual void Close()
MythUIButton * m_cancelButton
void setCheckable(bool flag)
MythScreenType * m_screen
MythUIButton * m_onlineFanartButton
void AddButton(const QString &title, QVariant data=0, bool newMenu=false, bool setCurrent=false)
bool Save(bool sendSig=true)
Holds information on recordings and videos.
Definition: programinfo.h:65
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.
RecordingRule * m_rule
void OnArtworkSearchDone(MetadataLookup *lookup)
virtual void AddScreen(MythScreenType *screen, bool allowFade=true)
Select storage options.
void toMap(InfoMap &map)
MythUIButton * m_metadataButton
void SetValueByData(QVariant data)
MythUICheckBox * m_transcodeCheck
This class is used as a container for messages.
Definition: mythevent.h:15
void DupMethodChanged(MythUIButtonListItem *)
MythUIButton * m_saveButton
void Reset()
Reset the widget to it&#39;s original state, should not reset changes made by the theme.
RecordingRule * m_rule
const char * name
Definition: ParseText.cpp:338
virtual void Load(void)=0
MythUIButtonList * m_storagegroupList
void FilterChanged(MythUIButtonListItem *)
void ruleSaved(int ruleId)
QVariant lastInsertId()
Return the id of the last inserted row.
Definition: mythdbcon.cpp:911
Mixin for Filters.
MythUIButton * m_filtersButton
QHash< QString, QString > InfoMap
Definition: mythtypes.h:15
MythUIImage * m_coverart
void customEvent(QEvent *event)
void SetAllowGeneric(bool allow)
uint GetSeason() const
Construct a recording schedule.
bool m_autoMetadataLookup
QString GetSetting(const QString &key, const QString &defaultval="")
void RuleChanged(void)
MythUICheckBox * m_autoexpireCheck
void SetReturnEvent(QObject *retobject, const QString &resultid)
void addDownloads(MetadataLookup *lookup)
addLookup: Add lookup to bottom of the queue MetadataDownload::m_downloadList takes ownership of the ...
QString m_playGroup
void Create(bool *err)
MythUIButtonList * m_inputList
MythUIButton * m_backButton
void ShowPostProc(void)
__u64 val
Definition: videodev2.h:1041
StoreOptEditor(MythScreenStack *parent, ScheduleEditor &editor, RecordingRule &rule, RecordingInfo *recinfo)
uint GetSeason(void) const
Definition: programinfo.h:344
MythUIButton * m_schedInfoButton
virtual void SetTextFromMap(const InfoMap &infoMap)
Control TV playback TVPlaybackAborted(void)
Definition: tv_play.h:291
QString GetMasterHostName(void)
RecordingRule * m_rule
MythUIButton * m_saveButton
static QString fs3(QT_TRANSLATE_NOOP("SchedFilterEditor","Prime time"))
bool Queue(const MythNotification &notification)
Queue a notification Queue() is thread-safe and can be called from anywhere.
virtual bool CreateEditChild(const QString &xmlfile, const QString &winname, bool isTemplate)
Mixin for storage options.
void SetRule(RecordingRule *rule)
void Closing(void)
virtual void ShowDetails(void) const
Show the Program Details screen.
static MSqlQueryInfo InitCon(ConnectionReuse=kNormalConnection)
Only use this in combination with MSqlQuery constructor.
Definition: mythdbcon.cpp:542
void FindNetArt(VideoArtworkType type)
MythUIBusyDialog * m_busyPopup
static QString fs9(QT_TRANSLATE_NOOP("SchedFilterEditor","This day and time"))
Internal representation of a recording rule, mirrors the record table.
Definition: recordingrule.h:31
void SetDownloads(ArtworkMap map)
void SetRecGroup(int recgroupID, QString recgroup)
void ShowSchedOpt(void)
void ShowFilters(void)
FilterOptMixin * m_other
MythScreenStack * GetScreenStack() const
void ShowMetadataOptions(void)
QString m_seriesid
Definition: recordingrule.h:87
MythUIType * GetFocusWidget(void) const
MythUIButton * m_localBannerButton
MythUIButton * m_previewButton
static void * RunScheduleEditor(ProgramInfo *proginfo, void *player=NULL)
Callback.
void SetSeason(uint season)
RecordingRule * m_rule
MythUIButtonList * m_newrepeatList
RecordingInfo * m_recInfo
void PromptForRecGroup(void)
MythUIButton * m_postProcButton
void SetCollectionref(const QString &collectionref)
static bool LoadWindowFromXML(const QString &xmlfile, const QString &windowname, MythUIType *parent)
RecordingDupInType m_dupIn
bool keyPressEvent(QKeyEvent *event)
Key event handler.
void ChildClosing(void)
void SetText(const QString &text, bool moveCursor=true)
static vector< uint > GetInputList(void)
Definition: cardutil.cpp:1984
QString m_inetref
Definition: recordingrule.h:89
QString GetText(void) const
MythMainWindow * GetMythMainWindow(void)
void Create(bool *err)
QStringList GetSupportedImageExtensionFilter()
QVariant GetData() const
MythScreenType * m_screen
virtual void ShowPrevious(void) const
Show the previous recordings for this recording rule.
QList< ArtworkInfo > ArtworkList
MythUIImage * m_banner
MetadataDownload * m_imageLookup
void PromptForRecGroup(void)
MythUISpinBox * m_startoffsetSpin
static QString fs7(QT_TRANSLATE_NOOP("SchedFilterEditor","This series"))
MythUISpinBox * m_seasonSpin
MythUIButton * m_onlineBannerButton
MythUIButtonList * m_transcodeprofileList
Dialog prompting the user to enter a text string.
void TranscodeChanged(bool enable)
bool prepare(const QString &query)
QSqlQuery::prepare() is not thread safe in Qt <= 3.3.2.
Definition: mythdbcon.cpp:810
void DupMethodChanged(MythUIButtonListItem *item)
MythUICheckBox * m_userjob3Check
QMap< VideoArtworkType, ArtworkInfo > DownloadMap
static Type kEventType
void OnSearchListSelection(RefCountHandler< MetadataLookup > lookup)
void QueryComplete(MetadataLookup *lookup)
QString m_title
Recording rule is enabled?
Definition: recordingrule.h:75
void SetHost(const QString &host)
virtual void ToMap(InfoMap &progMap, bool showrerecord=false, uint star_range=10) const
Converts ProgramInfo into QString QHash containing each field in ProgramInfo converted into localized...
void RuleChanged(void)
virtual bool keyPressEvent(QKeyEvent *)
Key event handler.
void ShowStoreOpt(void)
MythUIButton * m_onlineCoverartButton
void SetFilename(const QString &filename)
Must be followed by a call to Load() to load the image.
bool GetBooleanCheckState(void) const
void SetReturnEvent(QObject *retobject, const QString &resultid)
void showMenu(void)
uint GetEpisode(void) const
Definition: programinfo.h:345
MythUICheckBox * m_userjob2Check
void Lookup(ProgramInfo *pginfo, bool automatic=true, bool getimages=true, bool allowgeneric=false)
CheckState state() const
void OnImageSearchListSelection(ArtworkInfo info, VideoArtworkType type)
void SetSubtype(LookupType subtype)
void SetValue(int val)
Definition: mythuispinbox.h:25
MythUIButtonList * m_maxbehaviourList
QString m_recProfile
void SetRule(RecordingRule *rule)
MetadataLookupList lookupList
MythUIButton * m_previewButton
QStringList m_descriptions
GLint GLenum GLsizei GLint GLenum GLenum type
MythScreenStack * m_popupStack
bool CanSetArtwork(void)
static QStringList GetNames(void)
Definition: playgroup.cpp:173
SchedFilterEditor(MythScreenStack *parent, ScheduleEditor &editor, RecordingRule &rule, RecordingInfo *recinfo)
void SetCheckState(MythUIStateType::StateType state)
MythUIButtonList * m_dupscopeList
bool Load(bool asTemplate=false)
void SetType(MetadataType type)
unsigned m_filter
QString generate_file_url(const QString &storage_group, const QString &host, const QString &path)
Definition: videoutils.h:65
FilterOptMixin(MythScreenType &screen, RecordingRule *rule, FilterOptMixin *other=NULL)
QString m_category
Definition: recordingrule.h:80
MythUICheckBox * m_userjob1Check
void LoadTemplate(QString name)
void SetItemCurrent(MythUIButtonListItem *item)
bool LoadTemplate(QString category, QString categoryType="Default")
MythUIButton * m_queryButton
static QString fs10(QT_TRANSLATE_NOOP("SchedFilterEditor","This channel"))
static QMap< int, QString > GetTranscodingProfiles()
virtual void PopScreen(MythScreenType *screen=NULL, bool allowFade=true, bool deleteScreen=true)
MetadataImageDownload * m_imageDownload
QString GetInetref() const
MythUIButton * m_localCoverartButton
static QStringList GetTemplateNames(void)
void PromptForRecGroup(void)
bool exec(void)
Wrap QSqlQuery::exec() so we can display SQL.
Definition: mythdbcon.cpp:610
MythUIButtonList * m_dupmethodList
CategoryType GetCategoryType(void) const
Definition: programinfo.h:416
void SetEpisode(uint episode)
static QString fs1(QT_TRANSLATE_NOOP("SchedFilterEditor","Identifiable episode"))
Screen in which all other widgets are contained and rendered.
MythUISpinBox * m_maxepSpin
void customEvent(QEvent *event)
bool Create(void)
Definition: proglist.cpp:153
ScheduleEditor * m_editor
MythUIButtonList * m_activeFiltersList
void addLookup(MetadataLookup *lookup)
addLookup: Add lookup to bottom of the queue MetadataDownload::m_lookupList takes ownership of the gi...
ArtworkMap GetArtwork(QString inetref, uint season, bool strict)
MythUISpinBox * m_episodeSpin
QMultiMap< VideoArtworkType, ArtworkInfo > ArtworkMap
virtual void Save(void)=0
LookupType
Event dispatched from MythUI modal dialogs to a listening class containing a result of some form...
Definition: mythdialogbox.h:32
void ShowNextView(void)
static QString fs11(QT_TRANSLATE_NOOP("SchedFilterEditor","No episodes"))
MythUIButton * m_storeOptButton
StoreOptMixin * m_other
void SetCanTakeFocus(bool set=true)
Set whether this widget can take focus.
Definition: mythuitype.cpp:362
void ShowPreviousView(void)
PostProcMixin(MythScreenType &screen, RecordingRule *rule, PostProcMixin *other=NULL)
MythUIButtonList * m_recprofileList
MetadataOptions(MythScreenStack *parent, ScheduleEditor &editor, RecordingRule &rule, RecordingInfo *recinfo)
PostProcMixin * m_other
static QString fs4(QT_TRANSLATE_NOOP("SchedFilterEditor","Commercial free"))
SchedOptMixin(MythScreenType &screen, RecordingRule *rule, SchedOptMixin *other=NULL)
void setChecked(CheckState state)
int CreateRecordingGroup(const QString &groupName)
SchedOptMixin * m_other
MythUIButtonList * m_recgroupList
void ShowPreview(void)
RecSearchType m_searchType
Mixin for post processing.
MythNotificationCenter * GetNotificationCenter(void)
MythUIButtonList * m_rulesList
DownloadMap GetDownloads() const
SchedOptEditor(MythScreenStack *parent, ScheduleEditor &editor, RecordingRule &rule, RecordingInfo *recinfo)
MythUIButtonListItem * GetItemAt(int pos) const
void SetTextFromMaps(void)
static QString fs5(QT_TRANSLATE_NOOP("SchedFilterEditor","High definition"))
void RuleChanged(void)
StoreOptMixin(MythScreenType &screen, RecordingRule *rule, StoreOptMixin *other=NULL)
static QString GetDisplayName(uint inputid)
Definition: cardutil.cpp:1052
void HandleDownloadedImages(MetadataLookup *lookup)