MythTV  0.28pre
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Groups Pages
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 "mythuistatetype.h"
28 #include "mythuispinbox.h"
29 #include "mythuicheckbox.h"
30 #include "mythdialogbox.h"
31 #include "mythprogressdialog.h"
32 #include "mythuifilebrowser.h"
33 #include "mythuimetadataresults.h"
34 #include "mythuiimageresults.h"
35 #include "videoutils.h"
36 #include "mythuiutils.h"
37 #include "mythtypes.h"
38 
39 #include "metadataimagehelper.h"
40 
41 // Mythfrontend
42 #include "proglist.h"
43 #include "viewschedulediff.h"
44 
45 #define ENUM_TO_QVARIANT(a) qVariantFromValue(static_cast<int>(a))
46 
47 //static const QString _Location = QObject::tr("Schedule Editor");
48 
49 // Define the strings inserted into the recordfilter table in the
50 // database. This should make them available to the translators.
51 static QString fs0(QT_TRANSLATE_NOOP("SchedFilterEditor", "New episode"));
52 static QString fs1(QT_TRANSLATE_NOOP("SchedFilterEditor", "Identifiable episode"));
53 static QString fs2(QT_TRANSLATE_NOOP("SchedFilterEditor", "First showing"));
54 static QString fs3(QT_TRANSLATE_NOOP("SchedFilterEditor", "Prime time"));
55 static QString fs4(QT_TRANSLATE_NOOP("SchedFilterEditor", "Commercial free"));
56 static QString fs5(QT_TRANSLATE_NOOP("SchedFilterEditor", "High definition"));
57 static QString fs6(QT_TRANSLATE_NOOP("SchedFilterEditor", "This episode"));
58 static QString fs7(QT_TRANSLATE_NOOP("SchedFilterEditor", "This series"));
59 static QString fs8(QT_TRANSLATE_NOOP("SchedFilterEditor", "This time"));
60 static QString fs9(QT_TRANSLATE_NOOP("SchedFilterEditor", "This day and time"));
61 static QString fs10(QT_TRANSLATE_NOOP("SchedFilterEditor", "This channel"));
62 
63 void *ScheduleEditor::RunScheduleEditor(ProgramInfo *proginfo, void *player)
64 {
65  RecordingRule *rule = new RecordingRule();
66  rule->LoadByProgram(proginfo);
67 
69  ScheduleEditor *se = new ScheduleEditor(mainStack, rule,
70  static_cast<TV*>(player));
71 
72  if (se->Create())
73  mainStack->AddScreen(se, (player == NULL));
74  else
75  delete se;
76 
77  return NULL;
78 }
79 
86  RecordingInfo *recInfo, TV *player)
87  : ScheduleCommon(parent, "ScheduleEditor"),
88  SchedOptMixin(*this, NULL), FilterOptMixin(*this, NULL),
89  StoreOptMixin(*this, NULL), PostProcMixin(*this, NULL),
90  m_recInfo(new RecordingInfo(*recInfo)), m_recordingRule(NULL),
91  m_sendSig(false),
92  m_saveButton(NULL), m_cancelButton(NULL), m_rulesList(NULL),
93  m_schedOptButton(NULL), m_storeOptButton(NULL),
94  m_postProcButton(NULL), m_schedInfoButton(NULL),
95  m_previewButton(NULL), m_metadataButton(NULL),
96  m_filtersButton(NULL),
97  m_player(player), m_loaded(false), m_view(kMainView), m_child(NULL)
98 {
105 }
106 
108  RecordingRule *recRule, TV *player)
109  : ScheduleCommon(parent, "ScheduleEditor"),
110  SchedOptMixin(*this, recRule),
111  FilterOptMixin(*this, recRule),
112  StoreOptMixin(*this, recRule),
113  PostProcMixin(*this, recRule),
114  m_recInfo(NULL), m_recordingRule(recRule),
115  m_sendSig(false),
116  m_saveButton(NULL), m_cancelButton(NULL), m_rulesList(NULL),
117  m_schedOptButton(NULL), m_storeOptButton(NULL),
118  m_postProcButton(NULL), m_schedInfoButton(NULL),
119  m_previewButton(NULL), m_metadataButton(NULL),
120  m_filtersButton(NULL),
121  m_player(player), m_loaded(false), m_view(kMainView), m_child(NULL)
122 {
123 }
124 
126 {
127  delete m_recordingRule;
128 
129  // if we have a player, we need to tell we are done
130  if (m_player)
131  {
132  QString message = QString("VIEWSCHEDULED_EXITING");
133  qApp->postEvent(m_player, new MythEvent(message));
134  }
135 }
136 
138 {
139  if (!LoadWindowFromXML("schedule-ui.xml", "scheduleeditor", this))
140  return false;
141 
142  bool err = false;
143 
144  UIUtilE::Assign(this, m_rulesList, "rules", &err);
145 
146  UIUtilW::Assign(this, m_schedOptButton, "schedoptions");
147  UIUtilW::Assign(this, m_storeOptButton, "storeoptions");
148  UIUtilW::Assign(this, m_postProcButton, "postprocessing");
149  UIUtilW::Assign(this, m_metadataButton, "metadata");
150  UIUtilW::Assign(this, m_schedInfoButton, "schedinfo");
151  UIUtilW::Assign(this, m_previewButton, "preview");
152  UIUtilW::Assign(this, m_filtersButton, "filters");
153 
154  SchedOptMixin::Create(&err);
156  StoreOptMixin::Create(&err);
157  PostProcMixin::Create(&err);
158 
159  UIUtilW::Assign(this, m_cancelButton, "cancel");
160  UIUtilE::Assign(this, m_saveButton, "save", &err);
161 
162  if (err)
163  {
164  LOG(VB_GENERAL, LOG_ERR, "ScheduleEditor, theme is missing "
165  "required elements");
166  return false;
167  }
168 
169  connect(m_rulesList, SIGNAL(itemSelected(MythUIButtonListItem *)),
171 
172  if (m_schedOptButton)
173  connect(m_schedOptButton, SIGNAL(Clicked()), SLOT(ShowSchedOpt()));
174  if (m_filtersButton)
175  connect(m_filtersButton, SIGNAL(Clicked()), SLOT(ShowFilters()));
176  if (m_storeOptButton)
177  connect(m_storeOptButton, SIGNAL(Clicked()), SLOT(ShowStoreOpt()));
178  if (m_postProcButton)
179  connect(m_postProcButton, SIGNAL(Clicked()), SLOT(ShowPostProc()));
180  if (m_schedInfoButton)
181  connect(m_schedInfoButton, SIGNAL(Clicked()), SLOT(ShowSchedInfo()));
182  if (m_previewButton)
183  connect(m_previewButton, SIGNAL(Clicked()), SLOT(ShowPreview()));
184  if (m_metadataButton)
185  connect(m_metadataButton, SIGNAL(Clicked()), SLOT(ShowMetadataOptions()));
186 
187  if (m_cancelButton)
188  connect(m_cancelButton, SIGNAL(Clicked()), SLOT(Close()));
189  connect(m_saveButton, SIGNAL(Clicked()), SLOT(Save()));
190 
191  if (m_schedInfoButton)
193  if (m_previewButton)
195 
196  if (m_dupmethodList)
197  connect(m_dupmethodList, SIGNAL(itemSelected(MythUIButtonListItem *)),
199  if (m_filtersList)
200  connect(m_filtersList, SIGNAL(itemClicked(MythUIButtonListItem *)),
202  if (m_maxepSpin)
203  connect(m_maxepSpin, SIGNAL(itemSelected(MythUIButtonListItem *)),
205  if (m_recgroupList)
206  connect(m_recgroupList, SIGNAL(LosingFocus()),
207  SLOT(PromptForRecGroup()));
208  if (m_transcodeCheck)
209  connect(m_transcodeCheck, SIGNAL(toggled(bool)),
210  SLOT(TranscodeChanged(bool)));
211 
212  BuildFocusList();
213 
214  if (!m_recordingRule->IsLoaded())
215  {
216  if (m_recInfo)
218  else if (m_recordingRule->m_recordID)
220 
221  if (!m_recordingRule->IsLoaded())
222  {
223  LOG(VB_GENERAL, LOG_ERR,
224  "ScheduleEditor::Create() - Failed to load recording rule");
225  return false;
226  }
227  }
228 
229  if (m_player)
230  m_player->StartEmbedding(QRect());
231 
232  return true;
233 }
234 
236 {
237  if (m_child)
238  m_child->Close();
239 
240  // don't fade the screen if we are returning to the player
241  if (m_player)
242  GetScreenStack()->PopScreen(this, false);
243  else
244  GetScreenStack()->PopScreen(this, true);
245 }
246 
248 {
253 
254  if (!m_loaded)
255  {
256  // Copy this now, it will change briefly after the first item
257  // is inserted into the list by design of
258  // MythUIButtonList::itemSelected()
260 
261  // Rules List
263  {
265  .compare("Default", Qt::CaseInsensitive) != 0)
266  {
268  tr("Delete this recording rule template"),
269  ENUM_TO_QVARIANT(kNotRecording));
270  }
273  ENUM_TO_QVARIANT(kTemplateRecord));
274  }
275  else if (m_recordingRule->m_isOverride)
276  {
278  tr("Record this showing with normal options"),
279  ENUM_TO_QVARIANT(kNotRecording));
282  ENUM_TO_QVARIANT(kOverrideRecord));
285  ENUM_TO_QVARIANT(kDontRecord));
286  }
287  else
288  {
289  bool hasChannel = !m_recordingRule->m_station.isEmpty();
290  bool isManual = (m_recordingRule->m_searchType == kManualSearch);
291 
294  ENUM_TO_QVARIANT(kNotRecording));
295  if (hasChannel)
298  ENUM_TO_QVARIANT(kSingleRecord));
299  if (!isManual)
302  ENUM_TO_QVARIANT(kOneRecord));
303  if (!hasChannel || isManual)
306  ENUM_TO_QVARIANT(kWeeklyRecord));
307  if (!hasChannel || isManual)
310  ENUM_TO_QVARIANT(kDailyRecord));
311  if (!isManual)
314  ENUM_TO_QVARIANT(kAllRecord));
315  }
316 
318  }
319  m_rulesList->SetValueByData(ENUM_TO_QVARIANT(m_recordingRule->m_type));
320 
321  InfoMap progMap;
322 
323  m_recordingRule->ToMap(progMap);
324 
325  if (m_recInfo)
326  m_recInfo->ToMap(progMap);
327 
328  SetTextFromMap(progMap);
329 
330  m_loaded = true;
331 }
332 
334 {
336  Load();
337  emit templateLoaded();
338 }
339 
341 {
342  if (!item)
343  return;
344 
345  m_recordingRule->m_type = static_cast<RecordingType>
346  (item->GetData().toInt());
347 
348  bool isScheduled = (m_recordingRule->m_type != kNotRecording &&
350 
351  if (m_schedOptButton)
352  m_schedOptButton->SetEnabled(isScheduled);
353  if (m_filtersButton)
354  m_filtersButton->SetEnabled(isScheduled);
355  if (m_storeOptButton)
356  m_storeOptButton->SetEnabled(isScheduled);
357  if (m_postProcButton)
358  m_postProcButton->SetEnabled(isScheduled);
359  if (m_metadataButton)
360  m_metadataButton->SetEnabled(isScheduled &&
362 
367 }
368 
370 {
372 }
373 
375 {
377 }
378 
380 {
382 }
383 
385 {
387 }
388 
390 {
392 }
393 
395 {
396  if (m_child)
397  m_child->Close();
398 
400  {
401  int recid = m_recordingRule->m_recordID;
402  DeleteRule();
403  if (recid)
404  emit ruleDeleted(recid);
405  Close();
406  return;
407  }
408 
413  m_recordingRule->Save(true);
415 
416  Close();
417 }
418 
420 {
422 }
423 
425 {
428  return;
429 
430  if (m_child)
431  m_child->Close();
432 
434 
436  SchedOptEditor *schedoptedit = new SchedOptEditor(mainStack, *this,
438  if (!schedoptedit->Create())
439  {
440  delete schedoptedit;
441  return;
442  }
443 
445  m_child = schedoptedit;
446  mainStack->AddScreen(schedoptedit);
447 }
448 
450 {
453  return;
454 
455  if (m_child)
456  m_child->Close();
457 
459 
461  StoreOptEditor *storeoptedit = new StoreOptEditor(mainStack, *this,
463  if (!storeoptedit->Create())
464  {
465  delete storeoptedit;
466  return;
467  }
468 
470  m_child = storeoptedit;
471  mainStack->AddScreen(storeoptedit);
472 }
473 
475 {
478  return;
479 
480  if (m_child)
481  m_child->Close();
482 
484 
486  PostProcEditor *ppedit = new PostProcEditor(mainStack, *this,
488  if (!ppedit->Create())
489  {
490  delete ppedit;
491  return;
492  }
493 
495  m_child = ppedit;
496  mainStack->AddScreen(ppedit);
497 }
498 
500 {
502  return;
503 
504  QString label = tr("Schedule Information");
505 
506  MythScreenStack *popupStack = GetMythMainWindow()->GetStack("popup stack");
507  MythDialogBox *menuPopup = new MythDialogBox(label, popupStack, "menuPopup");
508 
509  if (menuPopup->Create())
510  {
511  menuPopup->SetReturnEvent(this, "schedinfo");
512 
513  if (m_recInfo)
514  menuPopup->AddButton(tr("Program Details"));
515  menuPopup->AddButton(tr("Upcoming Episodes"));
516  menuPopup->AddButton(tr("Upcoming Recordings"));
518  menuPopup->AddButton(tr("Previously Recorded"));
519 
520  popupStack->AddScreen(menuPopup);
521  }
522  else
523  delete menuPopup;
524 }
525 
526 bool ScheduleEditor::keyPressEvent(QKeyEvent *event)
527 {
528  if (GetFocusWidget()->keyPressEvent(event))
529  return true;
530 
531  bool handled = false;
532  QStringList actions;
533  handled = GetMythMainWindow()->
534  TranslateKeyPress("TV Frontend", event, actions);
535 
536  for (int i = 0; i < actions.size() && !handled; i++)
537  {
538  QString action = actions[i];
539  handled = true;
540 
541  if (action == "MENU")
542  showMenu();
543  else if (action == "INFO")
544  ShowDetails();
545  else if (action == "GUIDE")
546  ShowGuide();
547  else if (action == "UPCOMING")
549  else if (action == "PREVVIEW")
551  else if (action == "NEXTVIEW")
552  ShowNextView();
553  else
554  handled = false;
555  }
556 
557  if (!handled && MythScreenType::keyPressEvent(event))
558  handled = true;
559 
560  return handled;
561 }
562 
563 void ScheduleEditor::customEvent(QEvent *event)
564 {
565  if (event->type() == DialogCompletionEvent::kEventType)
566  {
568 
569  QString resultid = dce->GetId();
570  QString resulttext = dce->GetResultText();
571 
572  if (resultid == "menu")
573  {
574  if (resulttext == tr("Main Options"))
575  m_child->Close();
576  if (resulttext == tr("Schedule Options"))
577  ShowSchedOpt();
578  else if (resulttext == tr("Filter Options"))
579  ShowFilters();
580  else if (resulttext == tr("Storage Options"))
581  ShowStoreOpt();
582  else if (resulttext == tr("Post Processing"))
583  ShowPostProc();
584  else if (resulttext == tr("Metadata Options"))
586  else if (resulttext == tr("Use Template"))
588  else if (resulttext == tr("Schedule Info"))
589  ShowSchedInfo();
590  else if (resulttext == tr("Preview Changes"))
591  ShowPreview();
592  }
593  else if (resultid == "templatemenu")
594  {
595  LoadTemplate(resulttext);
596  }
597  else if (resultid == "schedinfo")
598  {
599  if (resulttext == tr("Program Details"))
600  ShowDetails();
601  else if (resulttext == tr("Upcoming Episodes"))
603  else if (resulttext == tr("Upcoming Recordings"))
605  else if (resulttext == tr("Previously Recorded"))
606  ShowPrevious();
607  }
608  else if (resultid == "newrecgroup")
609  {
610  int groupID = CreateRecordingGroup(resulttext);
611  StoreOptMixin::SetRecGroup(groupID, resulttext);
612  }
613  }
614 }
615 
617 {
619  return;
620 
621  // No rule? Search by title
622  if (m_recordingRule->m_recordID <= 0)
623  {
625  return;
626  }
627 
629  ProgLister *pl = new ProgLister(mainStack, plRecordid,
630  QString::number(m_recordingRule->m_recordID),
631  "");
632 
633  if (pl->Create())
634  mainStack->AddScreen(pl);
635  else
636  delete pl;
637 }
638 
640 {
642  return;
643 
644  // Existing rule and search? Search by rule
645  if (m_recordingRule->m_recordID > 0 &&
648 
649  QString title = m_recordingRule->m_title;
650 
652  title.remove(QRegExp(" \\(.*\\)$"));
653 
655 }
656 
658 {
660  return;
661 
662  if (m_child)
663  {
664  m_child->Save();
665  if (m_view == kSchedOptView)
667  else if (m_view == kStoreOptView)
669  else if (m_view == kPostProcView)
671  }
672 
677 
678  QString ttable = "record_tmp";
679  m_recordingRule->UseTempTable(true, ttable);
680 
682  ViewScheduleDiff *vsd = new ViewScheduleDiff(mainStack, ttable,
685  if (vsd->Create())
686  mainStack->AddScreen(vsd);
687  else
688  delete vsd;
689 
691 }
692 
694 {
698  return;
699 
700  if (m_child)
701  m_child->Close();
702 
704  MetadataOptions *rad = new MetadataOptions(mainStack, *this,
706  if (!rad->Create())
707  {
708  delete rad;
709  return;
710  }
711 
713  m_child = rad;
714  mainStack->AddScreen(rad);
715 }
716 
718 {
721  return;
722 
723  if (m_child)
724  m_child->Close();
725 
727 
729  SchedFilterEditor *schedfilteredit = new SchedFilterEditor(mainStack,
730  *this, *m_recordingRule, m_recInfo);
731  if (!schedfilteredit->Create())
732  {
733  delete schedfilteredit;
734  return;
735  }
736 
738  m_child = schedfilteredit;
739  mainStack->AddScreen(schedfilteredit);
740 }
741 
743 {
746  return;
747 
750  else if (m_view == kMainView)
751  ShowPostProc();
752  else if (m_view == kSchedOptView)
753  m_child->Close();
754  else if (m_view == kFilterView)
755  ShowSchedOpt();
756  else if (m_view == kStoreOptView)
757  ShowFilters();
758  else if (m_view == kPostProcView)
759  ShowStoreOpt();
760  else if (m_view == kMetadataView)
761  ShowPostProc();
762 }
763 
765 {
768  return;
769 
770  if (m_view == kMainView)
771  ShowSchedOpt();
772  else if (m_view == kSchedOptView)
773  ShowFilters();
774  else if (m_view == kFilterView)
775  ShowStoreOpt();
776  else if (m_view == kStoreOptView)
777  ShowPostProc();
780  else if (m_view == kPostProcView)
781  m_child->Close();
782  else if (m_view == kMetadataView)
783  m_child->Close();
784 }
785 
787 {
788  if (m_view == kSchedOptView)
790  else if (m_view == kFilterView)
792  else if (m_view == kStoreOptView)
794  else if (m_view == kPostProcView)
796 
797  m_child = NULL;
798  m_view = kMainView;
799 }
800 
802 {
803  QString label = tr("Options");
804  MythScreenStack *popupStack = GetMythMainWindow()->GetStack("popup stack");
805  MythDialogBox *menuPopup =
806  new MythDialogBox(label, popupStack, "menuPopup");
807 
809  RecordingType type = static_cast<RecordingType>(item->GetData().toInt());
810  bool isScheduled = (type != kNotRecording && type != kDontRecord);
811 
812  if (menuPopup->Create())
813  {
814  menuPopup->SetReturnEvent(this, "menu");
815  if (m_view != kMainView)
816  menuPopup->AddButton(tr("Main Options"));
817  if (isScheduled && m_view != kSchedOptView)
818  menuPopup->AddButton(tr("Schedule Options"));
819  if (isScheduled && m_view != kFilterView)
820  menuPopup->AddButton(tr("Filter Options"));
821  if (isScheduled && m_view != kStoreOptView)
822  menuPopup->AddButton(tr("Storage Options"));
823  if (isScheduled && m_view != kPostProcView)
824  menuPopup->AddButton(tr("Post Processing"));
825  if (isScheduled && !m_recordingRule->m_isTemplate &&
827  menuPopup->AddButton(tr("Metadata Options"));
829  menuPopup->AddButton(tr("Schedule Info"));
831  menuPopup->AddButton(tr("Preview Changes"));
832  menuPopup->AddButton(tr("Use Template"));
833  popupStack->AddScreen(menuPopup);
834  }
835  else
836  {
837  delete menuPopup;
838  }
839 }
840 
842 {
843  QStringList templates = RecordingRule::GetTemplateNames();
844  if (templates.empty())
845  {
846  ShowOkPopup(tr("No templates available"));
847  return;
848  }
849 
850  QString label = tr("Template Options");
851  MythScreenStack *popupStack = GetMythMainWindow()->GetStack("popup stack");
852  MythDialogBox *menuPopup =
853  new MythDialogBox(label, popupStack, "menuPopup");
854 
855  if (menuPopup->Create())
856  {
857  menuPopup->SetReturnEvent(this, "templatemenu");
858  while (!templates.empty())
859  {
860  QString name = templates.front();
861  if (name == "Default")
862  menuPopup->AddButton(tr("Default"));
863  else
864  menuPopup->AddButton(name);
865  templates.pop_front();
866  }
867  popupStack->AddScreen(menuPopup);
868  }
869  else
870  {
871  delete menuPopup;
872  }
873 }
874 
876 
882  ScheduleEditor &editor, RecordingRule &rule,
883  RecordingInfo *recInfo)
884  : MythScreenType(parent, name),
885  m_editor(&editor), m_recordingRule(&rule), m_recInfo(recInfo),
886  m_backButton(NULL), m_saveButton(NULL), m_previewButton(NULL)
887 {
888 }
889 
891 {
892 }
893 
894 bool SchedEditChild::keyPressEvent(QKeyEvent *event)
895 {
896  if (GetFocusWidget()->keyPressEvent(event))
897  return true;
898 
899  bool handled = false;
900  QStringList actions;
901  handled = GetMythMainWindow()->
902  TranslateKeyPress("TV Frontend", event, actions);
903 
904  for (int i = 0; i < actions.size() && !handled; i++)
905  {
906  QString action = actions[i];
907  handled = true;
908 
909  if (action == "MENU")
910  m_editor->showMenu();
911  else if (action == "INFO")
913  else if (action == "UPCOMING")
915  if (action == "ESCAPE")
916  Close();
917  else if (action == "PREVVIEW")
919  else if (action == "NEXTVIEW")
921  else
922  handled = false;
923  }
924 
925  if (!handled && MythScreenType::keyPressEvent(event))
926  handled = true;
927 
928  return handled;
929 }
930 
932  const QString xmlfile, const QString winname, bool isTemplate)
933 {
934  if (!LoadWindowFromXML(xmlfile, winname, this))
935  return false;
936 
937  UIUtilW::Assign(this, m_backButton, "back");
938  UIUtilW::Assign(this, m_saveButton, "save");
939  UIUtilW::Assign(this, m_previewButton, "preview");
940 
941  connect(this, SIGNAL(Closing()), m_editor, SLOT(ChildClosing()));
942  connect(m_editor, SIGNAL(templateLoaded()), SLOT(Load()));
943 
944  if (m_backButton)
945  connect(m_backButton, SIGNAL(Clicked()), SLOT(Close()));
946  if (m_saveButton)
947  connect(m_saveButton, SIGNAL(Clicked()), m_editor, SLOT(Save()));
948  if (m_previewButton)
949  connect(m_previewButton, SIGNAL(Clicked()),
950  m_editor, SLOT(ShowPreview()));
951 
952  if (m_previewButton)
953  m_previewButton->SetEnabled(!isTemplate);
954 
955  return true;
956 }
957 
959 {
960  InfoMap progMap;
961 
962  m_recordingRule->ToMap(progMap);
963 
964  if (m_recInfo)
965  m_recInfo->ToMap(progMap);
966 
967  SetTextFromMap(progMap);
968 }
969 
971 {
972  Save();
973  emit Closing();
975 }
976 
978 
985  ScheduleEditor &editor,
986  RecordingRule &rule,
987  RecordingInfo *recInfo)
988  : SchedEditChild(parent, "ScheduleOptionsEditor", editor, rule, recInfo),
989  SchedOptMixin(*this, &rule, &editor), m_filtersButton(NULL)
990 {
991 }
992 
994 {
995 }
996 
998 {
1000  "schedule-ui.xml", "scheduleoptionseditor",
1002  {
1003  return false;
1004  }
1005 
1006  bool err = false;
1007 
1008  SchedOptMixin::Create(&err);
1009 
1010  UIUtilW::Assign(this, m_filtersButton, "filters");
1011 
1012  if (err)
1013  {
1014  LOG(VB_GENERAL, LOG_ERR, "SchedOptEditor, theme is missing "
1015  "required elements");
1016  return false;
1017  }
1018 
1019  if (m_dupmethodList)
1020  connect(m_dupmethodList, SIGNAL(itemSelected(MythUIButtonListItem *)),
1022 
1023  if (m_filtersButton)
1024  connect(m_filtersButton, SIGNAL(Clicked()),
1025  m_editor, SLOT(ShowFilters()));
1026 
1027  BuildFocusList();
1028 
1029  return true;
1030 }
1031 
1033 {
1035  SetTextFromMaps();
1036 }
1037 
1039 {
1041 }
1042 
1044 {
1046 }
1047 
1049 
1056  ScheduleEditor &editor,
1057  RecordingRule &rule,
1058  RecordingInfo *recInfo)
1059  : SchedEditChild(parent, "ScheduleFilterEditor", editor, rule, recInfo),
1060  FilterOptMixin(*this, &rule, &editor)
1061 {
1062 }
1063 
1065 {
1066 }
1067 
1069 {
1071  "schedule-ui.xml", "schedulefiltereditor",
1073  {
1074  return false;
1075  }
1076 
1077  bool err = false;
1078 
1079  FilterOptMixin::Create(&err);
1080 
1081  if (err)
1082  {
1083  LOG(VB_GENERAL, LOG_ERR, "SchedFilterEditor, theme is missing "
1084  "required elements");
1085  return false;
1086  }
1087 
1088  connect(m_filtersList, SIGNAL(itemClicked(MythUIButtonListItem *)),
1090 
1091  BuildFocusList();
1092 
1093  return true;
1094 }
1095 
1097 {
1099  SetTextFromMaps();
1100 }
1101 
1103 {
1105 }
1106 
1108 {
1110 }
1111 
1113 
1120  ScheduleEditor &editor,
1121  RecordingRule &rule,
1122  RecordingInfo *recInfo)
1123  : SchedEditChild(parent, "StorageOptionsEditor", editor, rule, recInfo),
1124  StoreOptMixin(*this, &rule, &editor)
1125 {
1126 }
1127 
1129 {
1130 }
1131 
1133 {
1135  "schedule-ui.xml", "storageoptionseditor",
1137  {
1138  return false;
1139  }
1140 
1141  bool err = false;
1142 
1143  StoreOptMixin::Create(&err);
1144 
1145  if (err)
1146  {
1147  LOG(VB_GENERAL, LOG_ERR, "StoreOptEditor, theme is missing "
1148  "required elements");
1149  return false;
1150  }
1151 
1152  if (m_maxepSpin)
1153  connect(m_maxepSpin, SIGNAL(itemSelected(MythUIButtonListItem *)),
1155  if (m_recgroupList)
1156  connect(m_recgroupList, SIGNAL(LosingFocus()),
1157  SLOT(PromptForRecGroup()));
1158 
1159  BuildFocusList();
1160 
1161  return true;
1162 }
1163 
1165 {
1167  SetTextFromMaps();
1168 }
1169 
1171 {
1173 }
1174 
1176 {
1178 }
1179 
1180 void StoreOptEditor::customEvent(QEvent *event)
1181 {
1182  if (event->type() == DialogCompletionEvent::kEventType)
1183  {
1185 
1186  QString resultid = dce->GetId();
1187  QString resulttext = dce->GetResultText();
1188 
1189  if (resultid == "newrecgroup")
1190  {
1191  int groupID = CreateRecordingGroup(resulttext);
1192  StoreOptMixin::SetRecGroup(groupID, resulttext);
1193  }
1194  }
1195 }
1196 
1198 {
1200 }
1201 
1203 
1210  ScheduleEditor &editor,
1211  RecordingRule &rule,
1212  RecordingInfo *recInfo)
1213  : SchedEditChild(parent, "PostProcOptionsEditor", editor, rule, recInfo),
1214  PostProcMixin(*this, &rule, &editor)
1215 {
1216 }
1217 
1219 {
1220 }
1221 
1223 {
1225  "schedule-ui.xml", "postproceditor",
1227  {
1228  return false;
1229  }
1230 
1231  bool err = false;
1232 
1233  PostProcMixin::Create(&err);
1234 
1235  if (err)
1236  {
1237  LOG(VB_GENERAL, LOG_ERR, "PostProcEditor, theme is missing "
1238  "required elements");
1239  return false;
1240  }
1241 
1242  if (m_transcodeCheck)
1243  connect(m_transcodeCheck, SIGNAL(toggled(bool)),
1244  SLOT(TranscodeChanged(bool)));
1245 
1246  BuildFocusList();
1247 
1248  return true;
1249 }
1250 
1252 {
1254  SetTextFromMaps();
1255 }
1256 
1258 {
1260 }
1261 
1263 {
1265 }
1266 
1268 
1275  ScheduleEditor &editor,
1276  RecordingRule &rule,
1277  RecordingInfo *recInfo)
1278  : SchedEditChild(parent, "MetadataOptions", editor, rule, recInfo),
1279  m_busyPopup(NULL), m_fanart(NULL), m_coverart(NULL),
1280  m_banner(NULL), m_inetrefEdit(NULL), m_seasonSpin(NULL),
1281  m_episodeSpin(NULL), m_queryButton(NULL), m_localFanartButton(NULL),
1282  m_localCoverartButton(NULL), m_localBannerButton(NULL),
1283  m_onlineFanartButton(NULL), m_onlineCoverartButton(NULL),
1284  m_onlineBannerButton(NULL)
1285 {
1286  m_popupStack = GetMythMainWindow()->GetStack("popup stack");
1287 
1288  m_metadataFactory = new MetadataFactory(this);
1289  m_imageLookup = new MetadataDownload(this);
1291 
1294 }
1295 
1297 {
1298  if (m_imageLookup)
1299  {
1300  m_imageLookup->cancel();
1301  delete m_imageLookup;
1302  m_imageLookup = NULL;
1303  }
1304 
1305  if (m_imageDownload)
1306  {
1308  delete m_imageDownload;
1309  m_imageDownload = NULL;
1310  }
1311 }
1312 
1314 {
1316  "schedule-ui.xml", "metadataoptions",
1318  {
1319  return false;
1320  }
1321 
1322  bool err = false;
1323 
1324  UIUtilE::Assign(this, m_inetrefEdit, "inetref_edit", &err);
1325  UIUtilE::Assign(this, m_seasonSpin, "season_spinbox", &err);
1326  UIUtilE::Assign(this, m_episodeSpin, "episode_spinbox", &err);
1327  UIUtilE::Assign(this, m_queryButton, "query_button", &err);
1328  UIUtilE::Assign(this, m_localFanartButton, "local_fanart_button", &err);
1329  UIUtilE::Assign(this, m_localCoverartButton, "local_coverart_button", &err);
1330  UIUtilE::Assign(this, m_localBannerButton, "local_banner_button", &err);
1331  UIUtilE::Assign(this, m_onlineFanartButton, "online_fanart_button", &err);
1332  UIUtilE::Assign(this, m_onlineCoverartButton, "online_coverart_button", &err);
1333  UIUtilE::Assign(this, m_onlineBannerButton, "online_banner_button", &err);
1334  UIUtilW::Assign(this, m_fanart, "fanart");
1335  UIUtilW::Assign(this, m_coverart, "coverart");
1336  UIUtilW::Assign(this, m_banner, "banner");
1337 
1338  if (err)
1339  {
1340  LOG(VB_GENERAL, LOG_ERR, "MetadataOptions, theme is missing "
1341  "required elements");
1342  return false;
1343  }
1344 
1345  connect(m_queryButton, SIGNAL(Clicked()),
1346  SLOT(PerformQuery()));
1347  connect(m_localFanartButton, SIGNAL(Clicked()),
1348  SLOT(SelectLocalFanart()));
1349  connect(m_localCoverartButton, SIGNAL(Clicked()),
1350  SLOT(SelectLocalCoverart()));
1351  connect(m_localBannerButton, SIGNAL(Clicked()),
1352  SLOT(SelectLocalBanner()));
1353  connect(m_onlineFanartButton, SIGNAL(Clicked()),
1354  SLOT(SelectOnlineFanart()));
1355  connect(m_onlineCoverartButton, SIGNAL(Clicked()),
1356  SLOT(SelectOnlineCoverart()));
1357  connect(m_onlineBannerButton, SIGNAL(Clicked()),
1358  SLOT(SelectOnlineBanner()));
1359 
1360  connect(m_seasonSpin, SIGNAL(itemSelected(MythUIButtonListItem*)),
1361  SLOT(ValuesChanged()));
1362 
1363  // InetRef
1365 
1366  // Season
1367  m_seasonSpin->SetRange(0,9999,1,5);
1369 
1370  // Episode
1371  m_episodeSpin->SetRange(0,9999,1,10);
1373 
1374  if (m_coverart)
1375  {
1377  m_coverart->Load();
1378  }
1379 
1380  if (m_fanart)
1381  {
1383  m_fanart->Load();
1384  }
1385 
1386  if (m_banner)
1387  {
1389  m_banner->Load();
1390  }
1391 
1392  BuildFocusList();
1393 
1394  return true;
1395 }
1396 
1398 {
1399  SetTextFromMaps();
1400 }
1401 
1403 {
1404  if (m_busyPopup)
1405  return;
1406 
1407  QString message = title;
1408 
1409  m_busyPopup = new MythUIBusyDialog(message, m_popupStack,
1410  "metaoptsdialog");
1411 
1412  if (m_busyPopup->Create())
1414 }
1415 
1417 {
1418  CreateBusyDialog(tr("Trying to manually find this "
1419  "recording online..."));
1420 
1422 
1423  lookup->SetAutomatic(false);
1424  m_metadataFactory->Lookup(lookup);
1425 }
1426 
1428 {
1429  QueryComplete(lookup);
1430 }
1431 
1434 {
1435  QString msg = tr("Downloading selected artwork...");
1436  CreateBusyDialog(msg);
1437 
1438  MetadataLookup *lookup = new MetadataLookup();
1439 
1440  lookup->SetType(kMetadataVideo);
1442  lookup->SetAutomatic(true);
1443  lookup->SetData(qVariantFromValue<VideoArtworkType>(type));
1444 
1445  ArtworkMap downloads;
1446  downloads.insert(type, info);
1447  lookup->SetDownloads(downloads);
1448  lookup->SetAllowOverwrites(true);
1449  lookup->SetTitle(m_recordingRule->m_title);
1451  lookup->SetInetref(m_inetrefEdit->GetText());
1452  lookup->SetSeason(m_seasonSpin->GetIntValue());
1453  lookup->SetEpisode(m_episodeSpin->GetIntValue());
1454 
1455  m_imageDownload->addDownloads(lookup);
1456 }
1457 
1459 {
1460  if (!CanSetArtwork())
1461  return;
1462 
1463  QString url = generate_file_url("Fanart",
1465  "");
1466  FindImagePopup(url,"",*this, "fanart");
1467 }
1468 
1470 {
1471  if (!CanSetArtwork())
1472  return;
1473 
1474  QString url = generate_file_url("Coverart",
1476  "");
1477  FindImagePopup(url,"",*this, "coverart");
1478 }
1479 
1481 {
1482  if (!CanSetArtwork())
1483  return;
1484 
1485  QString url = generate_file_url("Banners",
1487  "");
1488  FindImagePopup(url,"",*this, "banner");
1489 }
1490 
1492 {
1494 }
1495 
1497 {
1499 }
1500 
1502 {
1504 }
1505 
1507 {
1508  // Season
1509  if (m_seasonSpin)
1511 
1512  // Episode
1513  if (m_episodeSpin)
1515 
1516  // InetRef
1517  if (m_inetrefEdit)
1519 }
1520 
1522 {
1523  if (!lookup)
1524  return;
1525 
1526  // InetRef
1527  m_inetrefEdit->SetText(lookup->GetInetref());
1528 
1529  // Season
1530  m_seasonSpin->SetValue(lookup->GetSeason());
1531 
1532  // Episode
1533  m_episodeSpin->SetValue(lookup->GetEpisode());
1534 
1535  InfoMap metadataMap;
1536  lookup->toMap(metadataMap);
1537  SetTextFromMap(metadataMap);
1538 }
1539 
1541  const QString &prefixAlt,
1542  QObject &inst,
1543  const QString &returnEvent)
1544 {
1545  QString fp;
1546 
1547  if (prefix.startsWith("myth://"))
1548  fp = prefix;
1549  else
1550  fp = prefix.isEmpty() ? prefixAlt : prefix;
1551 
1552  MythScreenStack *popupStack =
1553  GetMythMainWindow()->GetStack("popup stack");
1554 
1555  MythUIFileBrowser *fb = new MythUIFileBrowser(popupStack, fp);
1557  if (fb->Create())
1558  {
1559  fb->SetReturnEvent(&inst, returnEvent);
1560  popupStack->AddScreen(fb);
1561  }
1562  else
1563  delete fb;
1564 }
1565 
1567 {
1568  QStringList ret;
1569 
1570  QList<QByteArray> exts = QImageReader::supportedImageFormats();
1571  for (QList<QByteArray>::iterator p = exts.begin(); p != exts.end(); ++p)
1572  {
1573  ret.append(QString("*.").append(*p));
1574  }
1575 
1576  return ret;
1577 }
1578 
1580 {
1581  if (m_inetrefEdit->GetText().isEmpty())
1582  {
1583  ShowOkPopup(tr("You must set a reference number "
1584  "on this rule to set artwork. For items "
1585  "without a metadata source, you can set "
1586  "any unique value."));
1587  return false;
1588  }
1589 
1590  return true;
1591 }
1592 
1594 {
1595  MetadataLookup *lookup = new MetadataLookup();
1596  lookup->SetStep(kLookupSearch);
1597  lookup->SetType(mtype);
1599 
1600  if (type == kUnknownVideo)
1601  {
1603  (m_seasonSpin->GetIntValue() == 0 &&
1604  m_episodeSpin->GetIntValue() == 0))
1605  {
1606  lookup->SetSubtype(kProbableMovie);
1607  }
1608  else
1609  {
1611  }
1612  }
1613  else
1614  {
1615  // we could determine the type from the inetref
1616  lookup->SetSubtype(type);
1617  }
1618  lookup->SetAllowGeneric(true);
1619  lookup->SetHandleImages(false);
1621  lookup->SetTitle(m_recordingRule->m_title);
1623  lookup->SetInetref(m_inetrefEdit->GetText());
1625  lookup->SetSeason(m_seasonSpin->GetIntValue());
1626  lookup->SetEpisode(m_episodeSpin->GetIntValue());
1627 
1628  return lookup;
1629 }
1630 
1632 {
1633  if (!CanSetArtwork())
1634  return;
1635 
1636  QString msg = tr("Searching for available artwork...");
1637  CreateBusyDialog(msg);
1638 
1640 
1641  lookup->SetAutomatic(true);
1642  lookup->SetData(qVariantFromValue<VideoArtworkType>(type));
1643  m_imageLookup->addLookup(lookup);
1644 }
1645 
1647 {
1648  if (!lookup)
1649  return;
1650 
1651  if (m_busyPopup)
1652  {
1653  m_busyPopup->Close();
1654  m_busyPopup = NULL;
1655  }
1656 
1657  VideoArtworkType type = lookup->GetData().value<VideoArtworkType>();
1658  ArtworkList list = lookup->GetArtwork(type);
1659 
1660  if (list.isEmpty())
1661  {
1662  MythWarningNotification n(tr("No image found"), tr("Schedule Editor"));
1664  return;
1665  }
1666 
1667  ImageSearchResultsDialog *resultsdialog =
1668  new ImageSearchResultsDialog(m_popupStack, list, type);
1669 
1670  connect(resultsdialog, SIGNAL(haveResult(ArtworkInfo, VideoArtworkType)),
1672 
1673  if (resultsdialog->Create())
1674  m_popupStack->AddScreen(resultsdialog);
1675 }
1676 
1678 {
1679  if (!lookup)
1680  return;
1681 
1682  DownloadMap map = lookup->GetDownloads();
1683 
1684  if (map.isEmpty())
1685  return;
1686 
1687  for (DownloadMap::const_iterator i = map.begin(); i != map.end(); ++i)
1688  {
1689  VideoArtworkType type = i.key();
1690  ArtworkInfo info = i.value();
1691 
1692  if (type == kArtworkCoverart)
1693  m_artworkMap.replace(kArtworkCoverart, info);
1694  else if (type == kArtworkFanart)
1695  m_artworkMap.replace(kArtworkFanart, info);
1696  else if (type == kArtworkBanner)
1697  m_artworkMap.replace(kArtworkBanner, info);
1698  }
1699 
1702 
1703  ValuesChanged();
1704 }
1705 
1707 {
1710 
1711  if (m_coverart)
1712  {
1714  m_coverart->Load();
1715  }
1716 
1717  if (m_fanart)
1718  {
1720  m_fanart->Load();
1721  }
1722 
1723  if (m_banner)
1724  {
1726  m_banner->Load();
1727  }
1728 }
1729 
1730 void MetadataOptions::customEvent(QEvent *levent)
1731 {
1732  if (levent->type() == MetadataFactoryMultiResult::kEventType)
1733  {
1734  if (m_busyPopup)
1735  {
1736  m_busyPopup->Close();
1737  m_busyPopup = NULL;
1738  }
1739 
1740  MetadataFactoryMultiResult *mfmr = dynamic_cast<MetadataFactoryMultiResult*>(levent);
1741 
1742  if (!mfmr)
1743  return;
1744 
1745  MetadataLookupList list = mfmr->results;
1746 
1747  if (list.count() > 1)
1748  {
1749  int yearindex = -1;
1750 
1751  for (int p = 0; p != list.size(); ++p)
1752  {
1753  if (!m_recordingRule->m_seriesid.isEmpty() &&
1754  m_recordingRule->m_seriesid == (list[p])->GetTMSref())
1755  {
1756  MetadataLookup *lookup = list[p];
1757  QueryComplete(lookup);
1758  return;
1759  }
1760  else if (m_recInfo &&
1762  (list[p])->GetYear() != 0 &&
1763  m_recInfo->GetYearOfInitialRelease() == (list[p])->GetYear())
1764  {
1765  if (yearindex > -1)
1766  {
1767  LOG(VB_GENERAL, LOG_INFO, "Multiple results matched on year. No definite "
1768  "match could be found based on year alone.");
1769  yearindex = -2;
1770  }
1771  else if (yearindex == -1)
1772  {
1773  LOG(VB_GENERAL, LOG_INFO, "Matched based on year. ");
1774  yearindex = p;
1775  }
1776  }
1777  }
1778 
1779  if (yearindex > -1)
1780  {
1781  MetadataLookup *lookup = list[yearindex];
1782  QueryComplete(lookup);
1783  return;
1784  }
1785 
1786  LOG(VB_GENERAL, LOG_INFO, "Falling through to selection dialog.");
1787  MetadataResultsDialog *resultsdialog =
1789 
1790  connect(resultsdialog, SIGNAL(haveResult(RefCountHandler<MetadataLookup>)),
1792  Qt::QueuedConnection);
1793 
1794  if (resultsdialog->Create())
1795  m_popupStack->AddScreen(resultsdialog);
1796  }
1797  }
1798  else if (levent->type() == MetadataFactorySingleResult::kEventType)
1799  {
1800  if (m_busyPopup)
1801  {
1802  m_busyPopup->Close();
1803  m_busyPopup = NULL;
1804  }
1805 
1806  MetadataFactorySingleResult *mfsr = dynamic_cast<MetadataFactorySingleResult*>(levent);
1807 
1808  if (!mfsr)
1809  return;
1810 
1811  MetadataLookup *lookup = mfsr->result;
1812 
1813  if (!lookup)
1814  return;
1815 
1816  QueryComplete(lookup);
1817  }
1818  else if (levent->type() == MetadataFactoryNoResult::kEventType)
1819  {
1820  if (m_busyPopup)
1821  {
1822  m_busyPopup->Close();
1823  m_busyPopup = NULL;
1824  }
1825 
1826  MetadataFactoryNoResult *mfnr = dynamic_cast<MetadataFactoryNoResult*>(levent);
1827 
1828  if (!mfnr)
1829  return;
1830 
1831  QString title = tr("No match found for this recording. You can "
1832  "try entering a TVDB/TMDB number, season, and "
1833  "episode manually.");
1834 
1835  MythConfirmationDialog *okPopup =
1836  new MythConfirmationDialog(m_popupStack, title, false);
1837 
1838  if (okPopup->Create())
1839  m_popupStack->AddScreen(okPopup);
1840  }
1841  else if (levent->type() == MetadataLookupEvent::kEventType)
1842  {
1843  if (m_busyPopup)
1844  {
1845  m_busyPopup->Close();
1846  m_busyPopup = NULL;
1847  }
1848 
1849  MetadataLookupEvent *lue = (MetadataLookupEvent *)levent;
1850 
1851  MetadataLookupList lul = lue->lookupList;
1852 
1853  if (lul.isEmpty())
1854  return;
1855 
1856  if (lul.count() >= 1)
1857  {
1858  OnArtworkSearchDone(lul[0]);
1859  }
1860  }
1861  else if (levent->type() == MetadataLookupFailure::kEventType)
1862  {
1863  if (m_busyPopup)
1864  {
1865  m_busyPopup->Close();
1866  m_busyPopup = NULL;
1867  }
1868 
1870 
1871  MetadataLookupList lul = luf->lookupList;
1872 
1873  if (lul.size())
1874  {
1875  QString title = tr("This number, season, and episode combination "
1876  "does not appear to be valid (or the site may "
1877  "be down). Check your information and try "
1878  "again.");
1879 
1880  MythConfirmationDialog *okPopup =
1881  new MythConfirmationDialog(m_popupStack, title, false);
1882 
1883  if (okPopup->Create())
1884  m_popupStack->AddScreen(okPopup);
1885  }
1886  }
1887  else if (levent->type() == ImageDLEvent::kEventType)
1888  {
1889  if (m_busyPopup)
1890  {
1891  m_busyPopup->Close();
1892  m_busyPopup = NULL;
1893  }
1894 
1895  ImageDLEvent *ide = (ImageDLEvent *)levent;
1896 
1897  MetadataLookup *lookup = ide->item;
1898 
1899  if (!lookup)
1900  return;
1901 
1902  HandleDownloadedImages(lookup);
1903  }
1904  else if (levent->type() == ImageDLFailureEvent::kEventType)
1905  {
1906  if (m_busyPopup)
1907  {
1908  m_busyPopup->Close();
1909  m_busyPopup = NULL;
1910  }
1911  MythErrorNotification n(tr("Failed to retrieve image(s)"),
1912  tr("Schedule Editor"),
1913  tr("Check logs"));
1915  }
1916  else if (levent->type() == DialogCompletionEvent::kEventType)
1917  {
1918  DialogCompletionEvent *dce = (DialogCompletionEvent*)(levent);
1919 
1920  const QString resultid = dce->GetId();
1921  ArtworkInfo info;
1922  info.url = dce->GetResultText();
1923 
1924  if (resultid == "coverart")
1925  {
1926  m_artworkMap.replace(kArtworkCoverart, info);
1927  }
1928  else if (resultid == "fanart")
1929  {
1930  m_artworkMap.replace(kArtworkFanart, info);
1931  }
1932  else if (resultid == "banner")
1933  {
1934  m_artworkMap.replace(kArtworkBanner, info);
1935  }
1936 
1939 
1940  ValuesChanged();
1941  }
1942 
1943 }
1944 
1946 
1953  SchedOptMixin *other)
1954  : m_prioritySpin(NULL), m_startoffsetSpin(NULL), m_endoffsetSpin(NULL),
1955  m_dupmethodList(NULL), m_dupscopeList(NULL), m_inputList(NULL),
1956  m_ruleactiveCheck(NULL), m_newrepeatList(NULL),
1957  m_screen(&screen), m_rule(rule), m_other(other), m_loaded(false),
1958  m_haveRepeats(gCoreContext->GetNumSetting("HaveRepeats", 0))
1959 {
1960 }
1961 
1962 void SchedOptMixin::Create(bool *err)
1963 {
1964  if (!m_rule)
1965  return;
1966 
1967  if (m_other && !m_other->m_prioritySpin)
1968  UIUtilE::Assign(m_screen, m_prioritySpin, "priority", err);
1969  else
1970  UIUtilW::Assign(m_screen, m_prioritySpin, "priority");
1971 
1973  UIUtilE::Assign(m_screen, m_startoffsetSpin, "startoffset", err);
1974  else
1975  UIUtilW::Assign(m_screen, m_startoffsetSpin, "startoffset");
1976 
1977  if (m_other && !m_other->m_endoffsetSpin)
1978  UIUtilE::Assign(m_screen, m_endoffsetSpin, "endoffset", err);
1979  else
1980  UIUtilW::Assign(m_screen, m_endoffsetSpin, "endoffset");
1981 
1982  if (m_other && !m_other->m_dupmethodList)
1983  UIUtilE::Assign(m_screen, m_dupmethodList, "dupmethod", err);
1984  else
1985  UIUtilW::Assign(m_screen, m_dupmethodList, "dupmethod");
1986 
1987  if (m_other && !m_other->m_dupscopeList)
1988  UIUtilE::Assign(m_screen, m_dupscopeList, "dupscope", err);
1989  else
1990  UIUtilW::Assign(m_screen, m_dupscopeList, "dupscope");
1991 
1992  if (m_other && !m_other->m_inputList)
1993  UIUtilE::Assign(m_screen, m_inputList, "input", err);
1994  else
1996 
1998  UIUtilE::Assign(m_screen, m_ruleactiveCheck, "ruleactive", err);
1999  else
2000  UIUtilW::Assign(m_screen, m_ruleactiveCheck, "ruleactive");
2001 
2002  UIUtilW::Assign(m_screen, m_newrepeatList, "newrepeat");
2003 }
2004 
2006 {
2007  if (!m_rule)
2008  return;
2009 
2010  // Priority
2011  if (m_prioritySpin)
2012  {
2013  if (!m_loaded)
2014  m_prioritySpin->SetRange(-99,99,1,5);
2016  }
2017 
2018  // Start Offset
2019  if (m_startoffsetSpin)
2020  {
2021  if (!m_loaded)
2022  m_startoffsetSpin->SetRange(480,-480,1,10);
2024  }
2025 
2026  // End Offset
2027  if (m_endoffsetSpin)
2028  {
2029  if (!m_loaded)
2030  m_endoffsetSpin->SetRange(-480,480,1,10);
2032  }
2033 
2034  // Duplicate Match Type
2035  if (m_dupmethodList)
2036  {
2037  if (!m_loaded)
2038  {
2040 
2043  ENUM_TO_QVARIANT(kDupCheckSubDesc));
2046  ENUM_TO_QVARIANT(kDupCheckSubThenDesc));
2049  ENUM_TO_QVARIANT(kDupCheckSub));
2052  ENUM_TO_QVARIANT(kDupCheckDesc));
2055  ENUM_TO_QVARIANT(kDupCheckNone));
2056 
2057  m_rule->m_dupMethod = dupMethod;
2058  }
2059  m_dupmethodList->SetValueByData(ENUM_TO_QVARIANT(m_rule->m_dupMethod));
2060  }
2061 
2062  // Duplicate Matching Scope
2063  if (m_dupscopeList)
2064  {
2065  if (!m_loaded)
2066  {
2069  ENUM_TO_QVARIANT(kDupsInAll));
2072  ENUM_TO_QVARIANT(kDupsInRecorded));
2075  ENUM_TO_QVARIANT(kDupsInOldRecorded));
2076  if (m_haveRepeats && !m_newrepeatList &&
2078  {
2081  ENUM_TO_QVARIANT(kDupsNewEpi|kDupsInAll));
2082  }
2083  }
2084  m_dupscopeList->SetValueByData(ENUM_TO_QVARIANT(m_rule->m_dupIn));
2085  }
2086 
2087  // Preferred Input
2088  if (m_inputList)
2089  {
2090  if (!m_loaded)
2091  {
2093  QObject::tr("Use any available input"),
2094  qVariantFromValue(0));
2095 
2096  vector<uint> inputids = CardUtil::GetAllInputIDs();
2097  for (uint i = 0; i < inputids.size(); ++i)
2098  {
2100  QObject::tr("Prefer input %1")
2101  .arg(CardUtil::GetDisplayName(inputids[i])), inputids[i]);
2102  }
2103  }
2105  }
2106 
2107  // Active/Disabled
2108  if (m_ruleactiveCheck)
2109  {
2111  }
2112 
2113  // Record new and repeat
2114  if (m_newrepeatList)
2115  {
2116  if (!m_loaded)
2117  {
2119  QObject::tr("Record new and repeat "
2120  "episodes"), ENUM_TO_QVARIANT(0));
2122  QObject::tr("Record new episodes only"),
2123  ENUM_TO_QVARIANT(kDupsNewEpi));
2124  }
2125  m_newrepeatList->SetValueByData(ENUM_TO_QVARIANT
2126  (m_rule->m_dupIn & kDupsNewEpi));
2127  }
2128 
2129  m_loaded = true;
2130 
2131  RuleChanged();
2132 }
2133 
2135 {
2136  if (!m_rule)
2137  return;
2138 
2139  if (m_prioritySpin)
2141  if (m_startoffsetSpin)
2143  if (m_endoffsetSpin)
2145  if (m_dupmethodList)
2146  m_rule->m_dupMethod = static_cast<RecordingDupMethodType>
2147  (m_dupmethodList->GetDataValue().toInt());
2148  if (m_dupscopeList)
2149  {
2150  int mask = ((m_other && m_other->m_newrepeatList) ||
2151  m_newrepeatList) ? kDupsInAll : ~0;
2152  int val = ((m_rule->m_dupIn & ~mask) |
2153  m_dupscopeList->GetDataValue().toInt());
2154  m_rule->m_dupIn = static_cast<RecordingDupInType>(val);
2155  }
2156  if (m_inputList)
2158  if (m_ruleactiveCheck)
2160  if (m_newrepeatList)
2161  {
2162  int val = ((m_rule->m_dupIn & ~kDupsNewEpi) |
2163  m_newrepeatList->GetDataValue().toInt());
2164  m_rule->m_dupIn = static_cast<RecordingDupInType>(val);
2165  }
2166 }
2167 
2169 {
2170  if (!m_rule)
2171  return;
2172 
2173  bool isScheduled = (m_rule->m_type != kNotRecording &&
2174  m_rule->m_type != kDontRecord);
2175  bool isSingle = (m_rule->m_type == kSingleRecord ||
2177 
2178  if (m_prioritySpin)
2179  m_prioritySpin->SetEnabled(isScheduled);
2180  if (m_startoffsetSpin)
2181  m_startoffsetSpin->SetEnabled(isScheduled);
2182  if (m_endoffsetSpin)
2183  m_endoffsetSpin->SetEnabled(isScheduled);
2184  if (m_dupmethodList)
2185  m_dupmethodList->SetEnabled(isScheduled && !isSingle);
2186  if (m_dupscopeList)
2187  m_dupscopeList->SetEnabled(isScheduled && !isSingle &&
2189  if (m_inputList)
2190  m_inputList->SetEnabled(isScheduled);
2191  if (m_ruleactiveCheck)
2192  m_ruleactiveCheck->SetEnabled(isScheduled);
2193  if (m_newrepeatList)
2194  m_newrepeatList->SetEnabled(isScheduled && !isSingle && m_haveRepeats);
2195 }
2196 
2198 {
2199  if (!item || !m_rule)
2200  return;
2201 
2202  m_rule->m_dupMethod = static_cast<RecordingDupMethodType>
2203  (item->GetData().toInt());
2204 
2205  if (m_dupscopeList)
2207 }
2208 
2210 
2217  FilterOptMixin *other)
2218  : m_filtersList(NULL), m_activeFiltersList(NULL),
2219  m_screen(&screen), m_rule(rule), m_other(other), m_loaded(false)
2220 {
2221 }
2222 
2223 void FilterOptMixin::Create(bool *err)
2224 {
2225  if (!m_rule)
2226  return;
2227 
2228  if (m_other && !m_other->m_filtersList)
2229  UIUtilE::Assign(m_screen, m_filtersList, "filters", err);
2230  else
2231  UIUtilW::Assign(m_screen, m_filtersList, "filters");
2232 
2233  UIUtilW::Assign(m_screen, m_activeFiltersList, "activefilters");
2234  if (m_activeFiltersList)
2236 }
2237 
2239 {
2240  if (!m_rule)
2241  return;
2242 
2243  if (!m_loaded)
2244  {
2245  MSqlQuery query(MSqlQuery::InitCon());
2246 
2247  query.prepare("SELECT filterid, description, newruledefault "
2248  "FROM recordfilter ORDER BY filterid");
2249 
2250  if (query.exec())
2251  {
2252  while (query.next())
2253  {
2254  m_descriptions << QObject::tr(query.value(1).toString()
2255  .toUtf8().constData());
2256  }
2257  }
2258  m_loaded = true;
2259  }
2260 
2261  if (m_activeFiltersList)
2263 
2264  MythUIButtonListItem *button;
2265  QStringList::iterator Idesc;
2266  int idx;
2267  bool active;
2268  bool not_empty = m_filtersList && !m_filtersList->IsEmpty();
2269  for (Idesc = m_descriptions.begin(), idx = 0;
2270  Idesc != m_descriptions.end(); ++Idesc, ++idx)
2271  {
2272  active = m_rule->m_filter & (1 << idx);
2273  if (m_filtersList)
2274  {
2275  if (not_empty)
2276  button = m_filtersList->GetItemAt(idx);
2277  else
2278  button = new MythUIButtonListItem(m_filtersList, *Idesc, idx);
2279  button->setCheckable(true);
2282  }
2283  if (active && m_activeFiltersList)
2284  {
2285  /* Create a simple list of active filters the theme can
2286  use for informational purposes. */
2288  *Idesc, idx);
2289  button->setCheckable(false);
2290  }
2291  }
2292 
2294  {
2296  QObject::tr("None"), idx);
2297  button->setCheckable(false);
2298  }
2299 
2300  RuleChanged();
2301 }
2302 
2304 {
2305  if (!m_rule || !m_filtersList)
2306  return;
2307 
2308  // Iterate through button list, and build the mask
2309  MythUIButtonListItem *button;
2310  uint32_t filter_mask = 0;
2311  int idx, end;
2312 
2313  end = m_filtersList->GetCount();
2314  for (idx = 0; idx < end; ++idx)
2315  {
2316  if ((button = m_filtersList->GetItemAt(idx)) &&
2318  filter_mask |= (1 << button->GetData().value<uint32_t>());
2319  }
2320  m_rule->m_filter = filter_mask;
2321 }
2322 
2324 {
2325  if (!m_rule)
2326  return;
2327 
2328  bool enabled = m_rule->m_type != kNotRecording &&
2330  if (m_filtersList)
2331  m_filtersList->SetEnabled(enabled);
2332  if (m_activeFiltersList)
2333  m_activeFiltersList->SetEnabled(enabled);
2334 }
2335 
2337 {
2341 }
2342 
2343 
2345 
2352  StoreOptMixin *other)
2353  : m_recprofileList(NULL), m_recgroupList(NULL), m_storagegroupList(NULL),
2354  m_playgroupList(NULL), m_maxepSpin(NULL), m_maxbehaviourList(NULL),
2355  m_autoexpireCheck(NULL),
2356  m_screen(&screen), m_rule(rule), m_other(other), m_loaded(false)
2357 {
2358 }
2359 
2360 void StoreOptMixin::Create(bool *err)
2361 {
2362  if (!m_rule)
2363  return;
2364 
2365  if (m_other && !m_other->m_recprofileList)
2366  UIUtilE::Assign(m_screen, m_recprofileList, "recprofile", err);
2367  else
2368  UIUtilW::Assign(m_screen, m_recprofileList, "recprofile");
2369 
2370  if (m_other && !m_other->m_recgroupList)
2371  UIUtilE::Assign(m_screen, m_recgroupList, "recgroup", err);
2372  else
2373  UIUtilW::Assign(m_screen, m_recgroupList, "recgroup");
2374 
2376  UIUtilE::Assign(m_screen, m_storagegroupList, "storagegroup", err);
2377  else
2378  UIUtilW::Assign(m_screen, m_storagegroupList, "storagegroup");
2379 
2380  if (m_other && !m_other->m_playgroupList)
2381  UIUtilE::Assign(m_screen, m_playgroupList, "playgroup", err);
2382  else
2383  UIUtilW::Assign(m_screen, m_playgroupList, "playgroup");
2384 
2385  if (m_other && !m_other->m_maxepSpin)
2386  UIUtilE::Assign(m_screen, m_maxepSpin, "maxepisodes", err);
2387  else
2388  UIUtilW::Assign(m_screen, m_maxepSpin, "maxepisodes");
2389 
2391  UIUtilE::Assign(m_screen, m_maxbehaviourList, "maxnewest", err);
2392  else
2394 
2396  UIUtilE::Assign(m_screen, m_autoexpireCheck, "autoexpire", err);
2397  else
2398  UIUtilW::Assign(m_screen, m_autoexpireCheck, "autoexpire");
2399 }
2400 
2402 {
2403  if (!m_rule)
2404  return;
2405 
2406  QString label;
2407  QStringList groups;
2408  QStringList::Iterator it;
2409  MSqlQuery query(MSqlQuery::InitCon());
2410 
2411  // Recording Profile
2412  if (m_recprofileList)
2413  {
2414  if (!m_loaded)
2415  {
2416  label = QObject::tr("Record using the %1 profile");
2417 
2419  label.arg(QObject::tr("Default")),
2420  qVariantFromValue(QString("Default")));
2421  // LiveTV profile - it's for LiveTV not scheduled recordings??
2423  label.arg(QObject::tr("LiveTV")),
2424  qVariantFromValue(QString("LiveTV")));
2426  label.arg(QObject::tr("High Quality")),
2427  qVariantFromValue(QString("High Quality")));
2429  label.arg(QObject::tr("Low Quality")),
2430  qVariantFromValue(QString("Low Quality")));
2431  }
2433  }
2434 
2435  // Recording Group
2436  if (m_recgroupList)
2437  {
2438  if (!m_loaded)
2439  {
2440  label = QObject::tr("Include in the \"%1\" recording group");
2442  QObject::tr("Create a new recording group"),
2443  qVariantFromValue(QString("__NEW_GROUP__")));
2444 
2445  query.prepare("SELECT recgroupid, recgroup FROM recgroups "
2446  "WHERE recgroup <> 'Deleted' AND "
2447  " recgroup <> 'LiveTV' "
2448  "ORDER BY special DESC, recgroup ASC"); // Special groups first
2449  if (query.exec())
2450  {
2451  while (query.next())
2452  {
2453  int id = query.value(0).toInt();
2454  QString name = query.value(1).toString();
2455 
2456  if (name == "Default")
2457  name = QObject::tr("Default");
2458  new MythUIButtonListItem(m_recgroupList, label.arg(name),
2459  qVariantFromValue(id));
2460  }
2461  }
2462 
2463  }
2465  }
2466 
2467  // Storage Group
2468  if (m_storagegroupList)
2469  {
2470  if (!m_loaded)
2471  {
2472  label = QObject::tr("Store in the \"%1\" storage group");
2474  label.arg(QObject::tr("Default")),
2475  qVariantFromValue(QString("Default")));
2476 
2478  for (it = groups.begin(); it != groups.end(); ++it)
2479  {
2480  if ((*it).compare("Default", Qt::CaseInsensitive) != 0)
2482  label.arg(*it), qVariantFromValue(*it));
2483  }
2484  }
2486  }
2487 
2488  // Playback Group
2489  if (m_playgroupList)
2490  {
2491  if (!m_loaded)
2492  {
2493  label = QObject::tr("Use \"%1\" playback group settings");
2495  label.arg(QObject::tr("Default")),
2496  qVariantFromValue(QString("Default")));
2497 
2498  groups = PlayGroup::GetNames();
2499  for (it = groups.begin(); it != groups.end(); ++it)
2500  {
2501  new MythUIButtonListItem(m_playgroupList, label.arg(*it),
2502  qVariantFromValue(*it));
2503  }
2504  }
2506  }
2507 
2508  // Max Episodes
2509  if (m_maxepSpin)
2510  {
2511  if (!m_loaded)
2512  {
2513  int maxEpisodes = m_rule->m_maxEpisodes;
2514  m_maxepSpin->SetRange(0,100,1,5);
2515  m_rule->m_maxEpisodes = maxEpisodes;
2516  }
2518  }
2519 
2520  // Max Episode Behaviour
2521  if (m_maxbehaviourList)
2522  {
2523  if (!m_loaded)
2524  {
2526  QObject::tr("Don't record if this would exceed the max "
2527  "episodes"), qVariantFromValue(false));
2529  QObject::tr("Delete oldest if this would exceed the max "
2530  "episodes"), qVariantFromValue(true));
2531  }
2533  }
2534 
2535  // Auto-Expire
2536  if (m_autoexpireCheck)
2537  {
2539  }
2540 
2541  m_loaded = true;
2542 
2543  RuleChanged();
2544 }
2545 
2547 {
2548  if (!m_rule)
2549  return;
2550 
2551  if (m_recprofileList)
2553 
2554  if (m_recgroupList)
2555  {
2556  // If the user selected 'Create a new regroup' but failed to enter a
2557  // name when prompted, restore the original value
2558  if (m_recgroupList->GetDataValue().toString() == "__NEW_GROUP__")
2561  }
2562 
2563  if (m_storagegroupList)
2565 
2566  if (m_playgroupList)
2568 
2569  if (m_maxepSpin)
2571 
2572  if (m_maxbehaviourList)
2574 
2575  if (m_autoexpireCheck)
2577 }
2578 
2580 {
2581  if (!m_rule)
2582  return;
2583 
2584  bool isScheduled = (m_rule->m_type != kNotRecording &&
2585  m_rule->m_type != kDontRecord);
2586  bool isSingle = (m_rule->m_type == kSingleRecord ||
2588 
2589  if (m_recprofileList)
2590  m_recprofileList->SetEnabled(isScheduled);
2591  if (m_recgroupList)
2592  m_recgroupList->SetEnabled(isScheduled);
2593  if (m_storagegroupList)
2594  m_storagegroupList->SetEnabled(isScheduled);
2595  if (m_playgroupList)
2596  m_playgroupList->SetEnabled(isScheduled);
2597  if (m_maxepSpin)
2598  m_maxepSpin->SetEnabled(isScheduled && !isSingle);
2599  if (m_maxbehaviourList)
2600  m_maxbehaviourList->SetEnabled(isScheduled && !isSingle &&
2601  m_rule->m_maxEpisodes != 0);
2602  if (m_autoexpireCheck)
2603  m_autoexpireCheck->SetEnabled(isScheduled);
2604 }
2605 
2607 {
2608  if (!item || !m_rule)
2609  return;
2610 
2611  m_rule->m_maxEpisodes = item->GetData().toInt();
2612 
2613  if (m_maxbehaviourList)
2615 }
2616 
2618 {
2619  if (!m_rule)
2620  return;
2621 
2622  if (m_recgroupList->GetDataValue().toString() != "__NEW_GROUP__")
2623  return;
2624 
2625  MythScreenStack *popupStack = GetMythMainWindow()->GetStack("popup stack");
2626 
2627  QString label =
2628  QObject::tr("New Recording group name: ");
2629 
2630  MythTextInputDialog *textDialog =
2631  new MythTextInputDialog(popupStack, label,
2632  static_cast<InputFilter>(FilterSymbols | FilterPunct));
2633 
2634  textDialog->SetReturnEvent(m_screen, "newrecgroup");
2635 
2636  if (textDialog->Create())
2637  popupStack->AddScreen(textDialog, false);
2638 }
2639 
2640 void StoreOptMixin::SetRecGroup(int recgroupID, QString recgroup)
2641 {
2642  if (!m_rule || recgroupID <= 0)
2643  return;
2644 
2645  if (m_recgroupList)
2646  {
2647  recgroup = recgroup.trimmed();
2648  if (recgroup.isEmpty())
2649  return;
2650 
2651  QString label = QObject::tr("Include in the \"%1\" recording group");
2652  MythUIButtonListItem *item =
2653  new MythUIButtonListItem(m_recgroupList, label.arg(recgroup),
2654  qVariantFromValue(recgroup));
2656 
2657  if (m_other && m_other->m_recgroupList)
2658  {
2660  label.arg(recgroup), qVariantFromValue(recgroupID));
2662  }
2663  }
2664 }
2665 
2666 int StoreOptMixin::CreateRecordingGroup(const QString& groupName)
2667 {
2668  int groupID = -1;
2669  MSqlQuery query(MSqlQuery::InitCon());
2670 
2671  query.prepare("INSERT INTO recgroups SET recgroup = :NAME, "
2672  "displayname = :DISPLAYNAME");
2673  query.bindValue(":NAME", groupName);
2674  query.bindValue(":DISPLAYNAME", groupName);
2675 
2676  if (query.exec())
2677  groupID = query.lastInsertId().toInt();
2678 
2679  if (groupID <= 0)
2680  LOG(VB_GENERAL, LOG_ERR, QString("Could not create recording group (%1). "
2681  "Does it already exist?").arg(groupName));
2682 
2683  return groupID;
2684 }
2685 
2687 
2694  PostProcMixin *other)
2695  : m_commflagCheck(NULL), m_transcodeCheck(NULL),
2696  m_transcodeprofileList(NULL), m_userjob1Check(NULL),
2697  m_userjob2Check(NULL), m_userjob3Check(NULL), m_userjob4Check(NULL),
2698  m_metadataLookupCheck(NULL),
2699  m_screen(&screen), m_rule(rule), m_other(other), m_loaded(false)
2700 {
2701 }
2702 
2703 void PostProcMixin::Create(bool *err)
2704 {
2705  if (!m_rule)
2706  return;
2707 
2708  if (m_other && !m_other->m_commflagCheck)
2709  UIUtilE::Assign(m_screen, m_commflagCheck, "autocommflag", err);
2710  else
2711  UIUtilW::Assign(m_screen, m_commflagCheck, "autocommflag");
2712 
2713  if (m_other && !m_other->m_transcodeCheck)
2714  UIUtilE::Assign(m_screen, m_transcodeCheck, "autotranscode", err);
2715  else
2716  UIUtilW::Assign(m_screen, m_transcodeCheck, "autotranscode");
2717 
2719  UIUtilE::Assign(m_screen, m_transcodeprofileList, "transcodeprofile", err);
2720  else
2721  UIUtilW::Assign(m_screen, m_transcodeprofileList, "transcodeprofile");
2722 
2723  if (m_other && !m_other->m_userjob1Check)
2724  UIUtilE::Assign(m_screen, m_userjob1Check, "userjob1", err);
2725  else
2727 
2728  if (m_other && !m_other->m_userjob2Check)
2729  UIUtilE::Assign(m_screen, m_userjob2Check, "userjob2", err);
2730  else
2732 
2733  if (m_other && !m_other->m_userjob3Check)
2734  UIUtilE::Assign(m_screen, m_userjob3Check, "userjob3", err);
2735  else
2737 
2738  if (m_other && !m_other->m_userjob4Check)
2739  UIUtilE::Assign(m_screen, m_userjob4Check, "userjob4", err);
2740  else
2742 
2743  UIUtilW::Assign(m_screen, m_metadataLookupCheck, "metadatalookup");
2744 }
2745 
2747 {
2748  if (!m_rule)
2749  return;
2750 
2751  // Auto-commflag
2752  if (m_commflagCheck)
2753  {
2755  }
2756 
2757  // Auto-transcode
2758  if (m_transcodeCheck)
2759  {
2761  }
2762 
2763  // Transcode Method
2765  {
2766  if (!m_loaded)
2767  {
2768  QMap<int, QString> profiles = RecordingProfile::GetTranscodingProfiles();
2769  QMap<int, QString>::iterator it;
2770  for (it = profiles.begin(); it != profiles.end(); ++it)
2771  {
2773  qVariantFromValue(it.key()));
2774  }
2775  }
2777  }
2778 
2779  // User Job #1
2780  if (m_userjob1Check)
2781  {
2782  if (!m_loaded)
2783  {
2784  MythUIText *userjob1Text = NULL;
2785  UIUtilW::Assign(m_screen, userjob1Text, "userjob1text");
2786  if (userjob1Text)
2787  userjob1Text->SetText(QObject::tr("Run '%1'")
2788  .arg(gCoreContext->GetSetting("UserJobDesc1"), "User Job 1"));
2789  }
2791  }
2792 
2793  // User Job #2
2794  if (m_userjob2Check)
2795  {
2796  if (!m_loaded)
2797  {
2798  MythUIText *userjob2Text = NULL;
2799  UIUtilW::Assign(m_screen, userjob2Text, "userjob2text");
2800  if (userjob2Text)
2801  userjob2Text->SetText(QObject::tr("Run '%1'")
2802  .arg(gCoreContext->GetSetting("UserJobDesc2"), "User Job 2"));
2803  }
2805  }
2806 
2807  // User Job #3
2808  if (m_userjob3Check)
2809  {
2810  if (!m_loaded)
2811  {
2812  MythUIText *userjob3Text = NULL;
2813  UIUtilW::Assign(m_screen, userjob3Text, "userjob3text");
2814  if (userjob3Text)
2815  userjob3Text->SetText(QObject::tr("Run '%1'")
2816  .arg(gCoreContext->GetSetting("UserJobDesc3"), "User Job 3"));
2817  }
2819  }
2820 
2821  // User Job #4
2822  if (m_userjob4Check)
2823  {
2824  if (!m_loaded)
2825  {
2826  MythUIText *userjob4Text = NULL;
2827  UIUtilW::Assign(m_screen, userjob4Text, "userjob4text");
2828  if (userjob4Text)
2829  userjob4Text->SetText(QObject::tr("Run '%1'")
2830  .arg(gCoreContext->GetSetting("UserJobDesc4"), "User Job 4"));
2831  }
2833  }
2834 
2835  // Auto Metadata Lookup
2837  {
2839  }
2840 
2841  m_loaded = true;
2842 
2843  RuleChanged();
2844 }
2845 
2847 {
2848  if (!m_rule)
2849  return;
2850 
2851  if (m_commflagCheck)
2853  if (m_transcodeCheck)
2857  if (m_userjob1Check)
2859  if (m_userjob2Check)
2861  if (m_userjob3Check)
2863  if (m_userjob4Check)
2868 }
2869 
2871 {
2872  if (!m_rule)
2873  return;
2874 
2875  bool isScheduled = (m_rule->m_type != kNotRecording &&
2876  m_rule->m_type != kDontRecord);
2877 
2878  if (m_commflagCheck)
2879  m_commflagCheck->SetEnabled(isScheduled);
2880  if (m_transcodeCheck)
2881  m_transcodeCheck->SetEnabled(isScheduled);
2883  m_transcodeprofileList->SetEnabled(isScheduled &&
2885  if (m_userjob1Check)
2886  m_userjob1Check->SetEnabled(isScheduled);
2887  if (m_userjob2Check)
2888  m_userjob2Check->SetEnabled(isScheduled);
2889  if (m_userjob3Check)
2890  m_userjob3Check->SetEnabled(isScheduled);
2891  if (m_userjob4Check)
2892  m_userjob4Check->SetEnabled(isScheduled);
2894  m_metadataLookupCheck->SetEnabled(isScheduled);
2895 }
2896 
2898 {
2899  if (!m_rule)
2900  return;
2901 
2902  m_rule->m_autoTranscode = enable;
2903 
2906 }
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:26
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:406
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:8556
ScheduleEditor(MythScreenStack *parent, RecordingInfo *recinfo, TV *player=NULL)
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:27
MetadataType
ArtworkMap m_artworkMap
MythUISpinBox * m_prioritySpin
PostProcEditor(MythScreenStack *parent, ScheduleEditor &editor, RecordingRule &rule, RecordingInfo *recinfo)
QString toDescription(RecStatusType recstatus, RecordingType rectype, const QDateTime &recstartts)
Converts "recstatus" into a long human readable description.
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...
AllMusic * parent
MythScreenStack * GetStack(const QString &stackname)
RecordingInfo * m_recInfo
void CreateBusyDialog(QString title)
unsigned int uint
Definition: compat.h:139
MythCoreContext * gCoreContext
This global variable contains the MythCoreContext instance for the app.
GLint GLenum GLsizei GLint GLenum GLenum type
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:435
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:72
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's original state, should not reset changes made by the theme.
RecordingRule * m_rule
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)
StoreOptEditor(MythScreenStack *parent, ScheduleEditor &editor, RecordingRule &rule, RecordingInfo *recinfo)
uint GetSeason(void) const
Definition: programinfo.h:349
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.
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)
const char * name
Definition: ParseText.cpp:338
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)
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
virtual bool CreateEditChild(QString xmlfile, QString winname, bool isTemplate)
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:350
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
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:421
MythUIButton * m_saveButton
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:148
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)
MythUIButton * m_storeOptButton
StoreOptMixin * m_other
static vector< uint > GetAllInputIDs(void)
Definition: cardutil.cpp:1209
void SetCanTakeFocus(bool set=true)
Set whether this widget can take focus.
Definition: mythuitype.cpp:355
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"))
MythUIButton * m_cancelButton
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:1132
void HandleDownloadedImages(MetadataLookup *lookup)