MythTV  0.25-pre
scheduleeditor.cpp
Go to the documentation of this file.
00001 
00002 #include "scheduleeditor.h"
00003 
00004 // QT
00005 #include <QString>
00006 #include <QHash>
00007 #include <QCoreApplication>
00008 
00009 // Libmyth
00010 #include "mythcorecontext.h"
00011 #include "storagegroup.h"
00012 #include "programtypes.h"
00013 
00014 // Libmythtv
00015 #include "playgroup.h"
00016 #include "tv_play.h"
00017 #include "recordingprofile.h"
00018 #include "cardutil.h"
00019 
00020 // Libmythui
00021 #include "mythmainwindow.h"
00022 #include "mythuihelper.h"
00023 #include "mythuibuttonlist.h"
00024 #include "mythuibutton.h"
00025 #include "mythuitext.h"
00026 #include "mythuistatetype.h"
00027 #include "mythuispinbox.h"
00028 #include "mythuicheckbox.h"
00029 #include "mythdialogbox.h"
00030 #include "mythprogressdialog.h"
00031 #include "mythuifilebrowser.h"
00032 #include "mythuimetadataresults.h"
00033 #include "mythuiimageresults.h"
00034 #include "videoutils.h"
00035 #include "mythuiutils.h"
00036 
00037 #include "metadataimagehelper.h"
00038 
00039 // Mythfrontend
00040 #include "proglist.h"
00041 #include "viewschedulediff.h"
00042 
00043 #define ENUM_TO_QVARIANT(a) qVariantFromValue(static_cast<int>(a))
00044 
00045 // Define the strings inserted into the recordfilter table in the
00046 // database.  This should make them available to the translators.
00047 static QString fs0(QT_TRANSLATE_NOOP("SchedFilterEditor", "New episode"));
00048 static QString fs1(QT_TRANSLATE_NOOP("SchedFilterEditor", "Identifiable episode"));
00049 static QString fs2(QT_TRANSLATE_NOOP("SchedFilterEditor", "First showing"));
00050 static QString fs3(QT_TRANSLATE_NOOP("SchedFilterEditor", "Prime time"));
00051 static QString fs4(QT_TRANSLATE_NOOP("SchedFilterEditor", "Commercial free"));
00052 static QString fs5(QT_TRANSLATE_NOOP("SchedFilterEditor", "High definition"));
00053 static QString fs6(QT_TRANSLATE_NOOP("SchedFilterEditor", "This episode"));
00054 static QString fs7(QT_TRANSLATE_NOOP("SchedFilterEditor", "This series"));
00055 
00056 void *ScheduleEditor::RunScheduleEditor(ProgramInfo *proginfo, void *player)
00057 {
00058     RecordingRule *rule = new RecordingRule();
00059     rule->LoadByProgram(proginfo);
00060 
00061     MythScreenStack *mainStack = GetMythMainWindow()->GetMainStack();
00062     ScheduleEditor *se = new ScheduleEditor(mainStack, rule,
00063                                             static_cast<TV*>(player));
00064 
00065     if (se->Create())
00066         mainStack->AddScreen(se, (player == NULL));
00067     else
00068         delete se;
00069 
00070     return NULL;
00071 }
00072 
00078 ScheduleEditor::ScheduleEditor(MythScreenStack *parent,
00079                                RecordingInfo *recInfo, TV *player)
00080           : ScheduleCommon(parent, "ScheduleEditor"),
00081             m_recInfo(new RecordingInfo(*recInfo)), m_recordingRule(NULL),
00082             m_sendSig(false),
00083             m_saveButton(NULL), m_cancelButton(NULL), m_rulesList(NULL),
00084             m_schedOptButton(NULL), m_storeOptButton(NULL),
00085             m_postProcButton(NULL), m_schedInfoButton(NULL),
00086             m_previewButton(NULL), m_metadataButton(NULL),
00087             m_player(player)
00088 {
00089     m_recordingRule = new RecordingRule();
00090     m_recordingRule->m_recordID = m_recInfo->GetRecordingRuleID();
00091 }
00092 
00093 ScheduleEditor::ScheduleEditor(MythScreenStack *parent,
00094                                RecordingRule *recRule, TV *player)
00095           : ScheduleCommon(parent, "ScheduleEditor"),
00096             m_recInfo(NULL), m_recordingRule(recRule),
00097             m_sendSig(false),
00098             m_saveButton(NULL), m_cancelButton(NULL), m_rulesList(NULL),
00099             m_schedOptButton(NULL), m_storeOptButton(NULL),
00100             m_postProcButton(NULL), m_schedInfoButton(NULL),
00101             m_previewButton(NULL), m_metadataButton(NULL),
00102             m_player(player)
00103 {
00104 }
00105 
00106 ScheduleEditor::~ScheduleEditor(void)
00107 {
00108     delete m_recordingRule;
00109 
00110     // if we have a player, we need to tell we are done
00111     if (m_player)
00112     {
00113         QString message = QString("VIEWSCHEDULED_EXITING");
00114         qApp->postEvent(m_player, new MythEvent(message));
00115     }
00116 }
00117 
00118 bool ScheduleEditor::Create()
00119 {
00120     if (!LoadWindowFromXML("schedule-ui.xml", "scheduleeditor", this))
00121         return false;
00122 
00123     bool err = false;
00124 
00125     UIUtilE::Assign(this, m_rulesList, "rules", &err);
00126 
00127     UIUtilE::Assign(this, m_schedOptButton, "schedoptions", &err);
00128     UIUtilE::Assign(this, m_storeOptButton, "storeoptions", &err);
00129     UIUtilE::Assign(this, m_postProcButton, "postprocessing", &err);
00130     UIUtilE::Assign(this, m_schedInfoButton, "schedinfo", &err);
00131     UIUtilE::Assign(this, m_previewButton, "preview", &err);
00132     UIUtilE::Assign(this, m_metadataButton, "metadata", &err);
00133 
00134     UIUtilE::Assign(this, m_cancelButton, "cancel", &err);
00135     UIUtilE::Assign(this, m_saveButton, "save", &err);
00136 
00137     if (err)
00138     {
00139         LOG(VB_GENERAL, LOG_ERR, "ScheduleEditor, theme is missing "
00140                                  "required elements");
00141         return false;
00142     }
00143 
00144     connect(m_rulesList, SIGNAL(itemSelected(MythUIButtonListItem *)),
00145                          SLOT(RuleChanged(MythUIButtonListItem *)));
00146 
00147     connect(m_schedOptButton, SIGNAL(Clicked()), SLOT(ShowSchedOpt()));
00148     connect(m_storeOptButton, SIGNAL(Clicked()), SLOT(ShowStoreOpt()));
00149     connect(m_postProcButton, SIGNAL(Clicked()), SLOT(ShowPostProc()));
00150     connect(m_schedInfoButton, SIGNAL(Clicked()), SLOT(ShowSchedInfo()));
00151     connect(m_previewButton, SIGNAL(Clicked()), SLOT(ShowPreview()));
00152     connect(m_metadataButton, SIGNAL(Clicked()), SLOT(ShowMetadataOptions()));
00153 
00154     connect(m_cancelButton, SIGNAL(Clicked()), SLOT(Close()));
00155     connect(m_saveButton, SIGNAL(Clicked()), SLOT(Save()));
00156 
00157     BuildFocusList();
00158 
00159     if (!m_recordingRule->IsLoaded())
00160     {
00161         if (m_recInfo)
00162             m_recordingRule->LoadByProgram(m_recInfo);
00163         else if (m_recordingRule->m_recordID)
00164             m_recordingRule->Load();
00165 
00166         if (!m_recordingRule->IsLoaded())
00167         {
00168             LOG(VB_GENERAL, LOG_ERR,
00169                 "ScheduleEditor::Create() - Failed to load recording rule");
00170             return false;
00171         }
00172     }
00173 
00174     if (m_player)
00175         m_player->StartEmbedding(QRect());
00176 
00177     return true;
00178 }
00179 
00180 void ScheduleEditor::Close()
00181 {
00182     // don't fade the screen if we are returning to the player
00183     if (m_player)
00184         GetScreenStack()->PopScreen(this, false);
00185     else
00186         GetScreenStack()->PopScreen(this, true);
00187 }
00188 
00189 void ScheduleEditor::Load()
00190 {
00191     // Copy this now, it will change briefly after the first item is inserted
00192     // into the list by design of MythUIButtonList::itemSelected()
00193     RecordingType type = m_recordingRule->m_type;
00194 
00195     // Rules List
00196     if (m_recordingRule->m_isOverride)
00197     {
00198         new MythUIButtonListItem(m_rulesList,
00199                                  tr("Record this showing with normal options"),
00200                                  ENUM_TO_QVARIANT(kNotRecording));
00201         new MythUIButtonListItem(m_rulesList,
00202                                  tr("Record this showing with override options"),
00203                                  ENUM_TO_QVARIANT(kOverrideRecord));
00204         new MythUIButtonListItem(m_rulesList,
00205                                  tr("Do not allow this showing to be recorded"),
00206                                  ENUM_TO_QVARIANT(kDontRecord));
00207     }
00208     else
00209     {
00210         bool hasChannel = !m_recordingRule->m_station.isEmpty();
00211         bool isManual = (m_recordingRule->m_searchType == kManualSearch);
00212 
00213         new MythUIButtonListItem(m_rulesList, tr("Do not record this program"),
00214                                  ENUM_TO_QVARIANT(kNotRecording));
00215 
00216         if (hasChannel)
00217             new MythUIButtonListItem(m_rulesList,
00218                                      tr("Record only this showing"),
00219                                      ENUM_TO_QVARIANT(kSingleRecord));
00220         if (!isManual)
00221             new MythUIButtonListItem(m_rulesList,
00222                                      tr("Record one showing of this title"),
00223                                      ENUM_TO_QVARIANT(kFindOneRecord));
00224         if (hasChannel)
00225             new MythUIButtonListItem(m_rulesList,
00226                                      tr("Record in this timeslot every week"),
00227                                      ENUM_TO_QVARIANT(kWeekslotRecord));
00228         if (!isManual)
00229             new MythUIButtonListItem(m_rulesList,
00230                                      tr("Record one showing of this title every week"),
00231                                      ENUM_TO_QVARIANT(kFindWeeklyRecord));
00232         if (hasChannel)
00233             new MythUIButtonListItem(m_rulesList,
00234                                      tr("Record in this timeslot every day"),
00235                                      ENUM_TO_QVARIANT(kTimeslotRecord));
00236         if (!isManual)
00237             new MythUIButtonListItem(m_rulesList,
00238                                      tr("Record one showing of this title every day"),
00239                                      ENUM_TO_QVARIANT(kFindDailyRecord));
00240         if (hasChannel && !isManual)
00241             new MythUIButtonListItem(m_rulesList,
00242                                      tr("Record at any time on this channel"),
00243                                      ENUM_TO_QVARIANT(kChannelRecord));
00244         if (!isManual)
00245             new MythUIButtonListItem(m_rulesList,
00246                                      tr("Record at any time on any channel"),
00247                                      ENUM_TO_QVARIANT(kAllRecord));
00248     }
00249     m_rulesList->SetValueByData(ENUM_TO_QVARIANT(type));
00250 
00251     InfoMap progMap;
00252     if (m_recInfo)
00253         m_recInfo->ToMap(progMap);
00254     else
00255         m_recordingRule->ToMap(progMap);
00256 
00257     switch (m_recordingRule->m_searchType)
00258     {
00259         case kPowerSearch:
00260             progMap["searchType"] = tr("Power Search");
00261             break;
00262         case kTitleSearch:
00263             progMap["searchType"] = tr("Title Search");
00264             break;
00265         case kKeywordSearch:
00266             progMap["searchType"] = tr("Keyword Search");
00267             break;
00268         case kPeopleSearch:
00269             progMap["searchType"] = tr("People Search");
00270             break;
00271         default:
00272             progMap["searchType"] = tr("Unknown Search");
00273             break;
00274     }
00275 
00276     SetTextFromMap(progMap);
00277 }
00278 
00279 void ScheduleEditor::RuleChanged(MythUIButtonListItem *item)
00280 {
00281     if (!item)
00282         return;
00283 
00284     RecordingType type = static_cast<RecordingType>(item->GetData().toInt());
00285 
00286     bool isScheduled = (type != kNotRecording);
00287 
00288     m_schedOptButton->SetEnabled(isScheduled);
00289     m_storeOptButton->SetEnabled(isScheduled);
00290     m_postProcButton->SetEnabled(isScheduled);
00291 
00292     m_recordingRule->m_type = type;
00293 }
00294 
00295 void ScheduleEditor::Save()
00296 {
00297     MythUIButtonListItem *item = m_rulesList->GetItemCurrent();
00298     if (item)
00299     {
00300         RecordingType type = static_cast<RecordingType>(item->GetData().toInt());
00301         if (type == kNotRecording)
00302         {
00303             DeleteRule();
00304             Close();
00305             return;
00306         }
00307         else
00308             m_recordingRule->m_type = type;
00309     }
00310 
00311     m_recordingRule->Save(true);
00312     emit ruleSaved(m_recordingRule->m_recordID);
00313     Close();
00314 }
00315 
00316 void ScheduleEditor::DeleteRule()
00317 {
00318     m_recordingRule->Delete();
00319 }
00320 
00321 void ScheduleEditor::ShowSchedOpt()
00322 {
00323     MythScreenStack *mainStack = GetMythMainWindow()->GetMainStack();
00324     SchedOptEditor *schedoptedit = new SchedOptEditor(mainStack, m_recInfo,
00325                                                       m_recordingRule);
00326     if (schedoptedit->Create())
00327         mainStack->AddScreen(schedoptedit);
00328     else
00329         delete schedoptedit;
00330 }
00331 
00332 void ScheduleEditor::ShowStoreOpt()
00333 {
00334     MythScreenStack *mainStack = GetMythMainWindow()->GetMainStack();
00335     StoreOptEditor *storeoptedit = new StoreOptEditor(mainStack, m_recInfo,
00336                                                       m_recordingRule);
00337     if (storeoptedit->Create())
00338         mainStack->AddScreen(storeoptedit);
00339     else
00340         delete storeoptedit;
00341 }
00342 
00343 void ScheduleEditor::ShowPostProc()
00344 {
00345     MythScreenStack *mainStack = GetMythMainWindow()->GetMainStack();
00346     PostProcEditor *ppedit = new PostProcEditor(mainStack, m_recInfo,
00347                                                 m_recordingRule);
00348     if (ppedit->Create())
00349         mainStack->AddScreen(ppedit);
00350     else
00351         delete ppedit;
00352 }
00353 
00354 void ScheduleEditor::ShowSchedInfo()
00355 {
00356     QString label = tr("Schedule Information");
00357 
00358     MythScreenStack *popupStack = GetMythMainWindow()->GetStack("popup stack");
00359     MythDialogBox *menuPopup = new MythDialogBox(label, popupStack, "menuPopup");
00360 
00361     if (menuPopup->Create())
00362     {
00363         menuPopup->SetReturnEvent(this, "schedinfo");
00364 
00365         menuPopup->AddButton(tr("Program Details"));
00366         menuPopup->AddButton(tr("Upcoming episodes"));
00367         menuPopup->AddButton(tr("Upcoming recordings"));
00368         menuPopup->AddButton(tr("Previously scheduled"));
00369 
00370         popupStack->AddScreen(menuPopup);
00371     }
00372     else
00373         delete menuPopup;
00374 }
00375 
00376 void ScheduleEditor::customEvent(QEvent *event)
00377 {
00378     if (event->type() == DialogCompletionEvent::kEventType)
00379     {
00380         DialogCompletionEvent *dce = (DialogCompletionEvent*)(event);
00381 
00382         QString resultid  = dce->GetId();
00383         int     buttonnum = dce->GetResult();
00384 
00385         if (resultid == "schedinfo")
00386         {
00387             switch (buttonnum)
00388             {
00389                 case 0 :
00390                     if (m_recInfo)
00391                         ShowDetails(m_recInfo);
00392                     break;
00393                 case 1 :
00394                     showUpcomingByTitle();
00395                     break;
00396                 case 2 :
00397                     showUpcomingByRule();
00398                     break;
00399                 case 3 :
00400                     showPrevious();
00401                     break;
00402             }
00403         }
00404     }
00405 }
00406 
00407 void ScheduleEditor::showPrevious(void)
00408 {
00409     QString title;
00410     if (m_recInfo)
00411         title = m_recInfo->GetTitle();
00412     MythScreenStack *mainStack = GetMythMainWindow()->GetMainStack();
00413     ProgLister *pl = new ProgLister(mainStack, m_recordingRule->m_recordID,
00414                                     title);
00415     if (pl->Create())
00416         mainStack->AddScreen(pl);
00417     else
00418         delete pl;
00419 }
00420 
00421 void ScheduleEditor::showUpcomingByRule(void)
00422 {
00423     // No rule? Search by title
00424     if (m_recordingRule->m_recordID <= 0)
00425     {
00426         showUpcomingByTitle();
00427         return;
00428     }
00429 
00430     MythScreenStack *mainStack = GetMythMainWindow()->GetMainStack();
00431     ProgLister *pl = new ProgLister(mainStack, plRecordid,
00432                                 QString::number(m_recordingRule->m_recordID),
00433                                     "");
00434 
00435     if (pl->Create())
00436         mainStack->AddScreen(pl);
00437     else
00438         delete pl;
00439 }
00440 
00441 void ScheduleEditor::showUpcomingByTitle(void)
00442 {
00443     QString title = m_recordingRule->m_title;
00444 
00445     if (m_recordingRule->m_searchType != kNoSearch)
00446         title.remove(QRegExp(" \\(.*\\)$"));
00447 
00448     ShowUpcoming(title, m_recordingRule->m_seriesid);
00449 }
00450 
00451 void ScheduleEditor::ShowPreview(void)
00452 {
00453     QString ttable = "record_tmp";
00454     m_recordingRule->UseTempTable(true, ttable);
00455 
00456     MythScreenStack *mainStack = GetMythMainWindow()->GetMainStack();
00457     ViewScheduleDiff *vsd = new ViewScheduleDiff(mainStack, ttable,
00458                                                  m_recordingRule->m_tempID,
00459                                                  m_recordingRule->m_title);
00460     if (vsd->Create())
00461         mainStack->AddScreen(vsd);
00462     else
00463         delete vsd;
00464 
00465     m_recordingRule->UseTempTable(false);
00466 }
00467 
00468 void ScheduleEditor::ShowMetadataOptions(void)
00469 {
00470     MythScreenStack *mainStack = GetMythMainWindow()->GetMainStack();
00471     MetadataOptions *rad = new MetadataOptions(mainStack, m_recInfo,
00472                                                     m_recordingRule);
00473     if (rad->Create())
00474         mainStack->AddScreen(rad);
00475     else
00476         delete rad;
00477 }
00478 
00480 
00486 SchedOptEditor::SchedOptEditor(MythScreenStack *parent,
00487                                RecordingInfo *recInfo,
00488                                RecordingRule *rule)
00489     : MythScreenType(parent, "ScheduleOptionsEditor"),
00490       m_recInfo(NULL), m_recordingRule(rule),
00491       m_backButton(NULL),
00492       m_prioritySpin(NULL), m_inputList(NULL), m_startoffsetSpin(NULL),
00493       m_endoffsetSpin(NULL), m_dupmethodList(NULL), m_dupscopeList(NULL),
00494       m_filtersButton(NULL), m_ruleactiveCheck(NULL)
00495 {
00496     if (recInfo)
00497         m_recInfo = new RecordingInfo(*recInfo);
00498 }
00499 
00500 SchedOptEditor::~SchedOptEditor(void)
00501 {
00502 }
00503 
00504 bool SchedOptEditor::Create()
00505 {
00506     if (!LoadWindowFromXML("schedule-ui.xml", "scheduleoptionseditor", this))
00507         return false;
00508 
00509     bool err = false;
00510 
00511     UIUtilE::Assign(this, m_prioritySpin, "priority", &err);
00512     UIUtilE::Assign(this, m_inputList, "input", &err);
00513     UIUtilE::Assign(this, m_startoffsetSpin, "startoffset", &err);
00514     UIUtilE::Assign(this, m_endoffsetSpin, "endoffset", &err);
00515     UIUtilE::Assign(this, m_dupmethodList, "dupmethod", &err);
00516     UIUtilE::Assign(this, m_dupscopeList, "dupscope", &err);
00517 
00518     UIUtilW::Assign(this, m_filtersButton, "filters");
00519     UIUtilW::Assign(this, m_backButton, "back");
00520 
00521     UIUtilE::Assign(this, m_ruleactiveCheck, "ruleactive", &err);
00522 
00523     if (err)
00524     {
00525         LOG(VB_GENERAL, LOG_ERR, "SchedOptEditor, theme is missing "
00526                                  "required elements");
00527         return false;
00528     }
00529 
00530     if (m_backButton)
00531         connect(m_backButton, SIGNAL(Clicked()), SLOT(Close()));
00532 
00533     if (m_filtersButton && m_recordingRule->m_type == kOverrideRecord)
00534         m_filtersButton->SetEnabled(false);
00535     if (m_recordingRule->m_type == kSingleRecord ||
00536         m_recordingRule->m_type == kOverrideRecord)
00537     {
00538         m_dupmethodList->SetEnabled(false);
00539         m_dupscopeList->SetEnabled(false);
00540     }
00541 
00542     connect(m_dupmethodList, SIGNAL(itemSelected(MythUIButtonListItem *)),
00543             SLOT(dupMatchChanged(MythUIButtonListItem *)));
00544 
00545     if (m_filtersButton)
00546         connect(m_filtersButton, SIGNAL(Clicked()), SLOT(ShowFilters()));
00547 
00548     BuildFocusList();
00549 
00550     return true;
00551 }
00552 
00553 void SchedOptEditor::Load()
00554 {
00555     MSqlQuery query(MSqlQuery::InitCon());
00556 
00557     // Priority
00558     m_prioritySpin->SetRange(-99,99,1,5);
00559     m_prioritySpin->SetValue(m_recordingRule->m_recPriority);
00560 
00561     // Preferred Input
00562     new MythUIButtonListItem(m_inputList, tr("Use any available input"),
00563                              qVariantFromValue(0));
00564 
00565     vector<uint> inputids = CardUtil::GetInputIDs(0);
00566     for (uint i = 0; i < inputids.size(); ++i)
00567     {
00568         new MythUIButtonListItem(m_inputList, tr("Prefer input %1")
00569                                  .arg(CardUtil::GetDisplayName(inputids[i]))
00570                                  .arg(inputids[i]));
00571     }
00572 
00573     m_inputList->SetValueByData(m_recordingRule->m_prefInput);
00574 
00575     // Start Offset
00576     m_startoffsetSpin->SetRange(480,-480,1,10);
00577     m_startoffsetSpin->SetValue(m_recordingRule->m_startOffset);
00578 
00579     // End Offset
00580     m_endoffsetSpin->SetRange(-480,480,1,10);
00581     m_endoffsetSpin->SetValue(m_recordingRule->m_endOffset);
00582 
00583     // Duplicate Match Type
00584     new MythUIButtonListItem(m_dupmethodList,
00585                              tr("Match duplicates using subtitle & "
00586                                 "description"),
00587                              ENUM_TO_QVARIANT(kDupCheckSubDesc));
00588     new MythUIButtonListItem(m_dupmethodList,
00589                              tr("Match duplicates using subtitle then "
00590                                 "description"),
00591                              ENUM_TO_QVARIANT(kDupCheckSubThenDesc));
00592     new MythUIButtonListItem(m_dupmethodList,
00593                              tr("Match duplicates using subtitle"),
00594                              ENUM_TO_QVARIANT(kDupCheckSub));
00595     new MythUIButtonListItem(m_dupmethodList,
00596                              tr("Match duplicates using description"),
00597                              ENUM_TO_QVARIANT(kDupCheckDesc));
00598     new MythUIButtonListItem(m_dupmethodList,
00599                              tr("Don't match duplicates"),
00600                              ENUM_TO_QVARIANT(kDupCheckNone));
00601 
00602     m_dupmethodList->SetValueByData(
00603                                 ENUM_TO_QVARIANT(m_recordingRule->m_dupMethod));
00604 
00605     // Duplicate Matching Scope
00606     new MythUIButtonListItem(m_dupscopeList,
00607                              tr("Look for duplicates in current and previous "
00608                                 "recordings"),
00609                              ENUM_TO_QVARIANT(kDupsInAll));
00610     new MythUIButtonListItem(m_dupscopeList,
00611                              tr("Look for duplicates in current recordings "
00612                                 "only"),
00613                              ENUM_TO_QVARIANT(kDupsInRecorded));
00614     new MythUIButtonListItem(m_dupscopeList,
00615                              tr("Look for duplicates in previous recordings "
00616                                 "only"),
00617                              ENUM_TO_QVARIANT(kDupsInOldRecorded));
00618 
00619     if (gCoreContext->GetNumSetting("HaveRepeats", 0))
00620     {
00621         new MythUIButtonListItem(m_dupscopeList,
00622                                  tr("Record new episodes only"),
00623                                  ENUM_TO_QVARIANT(kDupsNewEpi | kDupsInAll));
00624     }
00625 
00626     m_dupscopeList->SetValueByData(ENUM_TO_QVARIANT(m_recordingRule->m_dupIn));
00627 
00628     // Active/Disabled
00629     m_ruleactiveCheck->SetCheckState(!m_recordingRule->m_isInactive);
00630 
00631     InfoMap progMap;
00632     if (m_recInfo)
00633         m_recInfo->ToMap(progMap);
00634     else
00635         m_recordingRule->ToMap(progMap);
00636     SetTextFromMap(progMap);
00637 }
00638 
00639 void SchedOptEditor::dupMatchChanged(MythUIButtonListItem *item)
00640 {
00641     if (!item)
00642         return;
00643 
00644     int dupMethod = item->GetData().toInt();
00645 
00646     if (dupMethod <= 0)
00647         m_dupscopeList->SetEnabled(false);
00648     else
00649         m_dupscopeList->SetEnabled(true);
00650 }
00651 
00652 void SchedOptEditor::Save()
00653 {
00654     // Priority
00655     m_recordingRule->m_recPriority = m_prioritySpin->GetIntValue();
00656 
00657     // Preferred Input
00658     m_recordingRule->m_prefInput = m_inputList->GetDataValue().toInt();
00659 
00660     // Start Offset
00661     m_recordingRule->m_startOffset = m_startoffsetSpin->GetIntValue();
00662 
00663     // End Offset
00664     m_recordingRule->m_endOffset = m_endoffsetSpin->GetIntValue();
00665 
00666     // Duplicate Match Type
00667     m_recordingRule->m_dupMethod = static_cast<RecordingDupMethodType>
00668                                     (m_dupmethodList->GetDataValue().toInt());
00669 
00670     // Duplicate Matching Scope
00671     m_recordingRule->m_dupIn = static_cast<RecordingDupInType>
00672                                     (m_dupscopeList->GetDataValue().toInt());
00673 
00674     // Active/Disabled
00675     m_recordingRule->m_isInactive = (!m_ruleactiveCheck->GetBooleanCheckState());
00676 }
00677 
00678 void SchedOptEditor::Close()
00679 {
00680     Save();
00681     MythScreenType::Close();
00682 }
00683 
00684 void SchedOptEditor::ShowFilters(void)
00685 {
00686     MythScreenStack *mainStack = GetMythMainWindow()->GetMainStack();
00687     SchedFilterEditor *schedfilteredit = new SchedFilterEditor(mainStack,
00688                                                                m_recInfo,
00689                                                                m_recordingRule);
00690     if (schedfilteredit->Create())
00691         mainStack->AddScreen(schedfilteredit);
00692     else
00693         delete schedfilteredit;
00694 }
00695 
00697 
00703 SchedFilterEditor::SchedFilterEditor(MythScreenStack *parent,
00704                                      RecordingInfo *recInfo,
00705                                      RecordingRule *rule)
00706     : MythScreenType(parent, "ScheduleFilterEditor"),
00707       m_recInfo(NULL), m_recordingRule(rule),
00708       m_backButton(NULL), m_filtersList(NULL)
00709 {
00710     if (recInfo)
00711         m_recInfo = new RecordingInfo(*recInfo);
00712 }
00713 
00714 SchedFilterEditor::~SchedFilterEditor(void)
00715 {
00716 }
00717 
00718 bool SchedFilterEditor::Create()
00719 {
00720     if (!LoadWindowFromXML("schedule-ui.xml", "schedulefiltereditor", this))
00721         return false;
00722 
00723     bool err = false;
00724 
00725     UIUtilE::Assign(this, m_filtersList, "filters", &err);
00726     UIUtilW::Assign(this, m_backButton, "back");
00727 
00728     if (err)
00729     {
00730         LOG(VB_GENERAL, LOG_ERR, "SchedFilterEditor, theme is missing "
00731                                  "required elements");
00732         return false;
00733     }
00734 
00735     if (m_backButton)
00736         connect(m_backButton, SIGNAL(Clicked()), SLOT(Close()));
00737 
00738     connect(m_filtersList, SIGNAL(itemClicked(MythUIButtonListItem *)),
00739             SLOT(ToggleSelected(MythUIButtonListItem *)));
00740     BuildFocusList();
00741 
00742     return true;
00743 }
00744 
00745 void SchedFilterEditor::Load()
00746 {
00747     MSqlQuery query(MSqlQuery::InitCon());
00748 
00749     query.prepare("SELECT filterid, description, newruledefault "
00750                   "FROM recordfilter ORDER BY filterid");
00751 
00752     if (query.exec())
00753     {
00754         MythUIButtonListItem *button;
00755 
00756         while (query.next())
00757         {
00758             uint32_t filterid       = query.value(0).toInt();
00759             QString  description    = tr(query.value(1).toString()
00760                                          .toUtf8().constData());
00761             // bool     filter_default = query.value(2).toInt();
00762 
00763             // Fill in list of possible filters
00764             button = new MythUIButtonListItem(m_filtersList, description,
00765                                               filterid);
00766             button->setCheckable(true);
00767             button->setChecked(m_recordingRule->m_filter & (1 << filterid) ?
00768                                MythUIButtonListItem::FullChecked :
00769                                MythUIButtonListItem::NotChecked);
00770         }
00771     }
00772 
00773     InfoMap progMap;
00774     if (m_recInfo)
00775         m_recInfo->ToMap(progMap);
00776     else
00777         m_recordingRule->ToMap(progMap);
00778     SetTextFromMap(progMap);
00779 }
00780 
00781 void SchedFilterEditor::ToggleSelected(MythUIButtonListItem *item)
00782 {
00783     item->setChecked(item->state() == MythUIButtonListItem::FullChecked ?
00784                      MythUIButtonListItem::NotChecked :
00785                      MythUIButtonListItem::FullChecked);
00786 }
00787 
00788 void SchedFilterEditor::Save()
00789 {
00790     // Iterate through button list, and build the mask
00791     MythUIButtonListItem *button;
00792     uint32_t filter_mask = 0;
00793     int idx, end;
00794 
00795     end = m_filtersList->GetCount();
00796     for (idx = 0; idx < end; ++idx)
00797     {
00798         if ((button = m_filtersList->GetItemAt(idx)) &&
00799             button->state() == MythUIButtonListItem::FullChecked)
00800             filter_mask |= (1 << qVariantValue<uint32_t>(button->GetData()));
00801     }
00802     m_recordingRule->m_filter = filter_mask;
00803 }
00804 
00805 void SchedFilterEditor::Close()
00806 {
00807     Save();
00808     MythScreenType::Close();
00809 }
00810 
00812 
00818 StoreOptEditor::StoreOptEditor(MythScreenStack *parent,
00819                                RecordingInfo *recInfo,
00820                                RecordingRule *rule)
00821           : MythScreenType(parent, "StorageOptionsEditor"),
00822             m_recInfo(NULL), m_recordingRule(rule),
00823             m_backButton(NULL),
00824             m_recprofileList(NULL), m_recgroupList(NULL),
00825             m_storagegroupList(NULL), m_playgroupList(NULL),
00826             m_autoexpireCheck(NULL), m_maxepSpin(NULL), m_maxbehaviourList(NULL)
00827 {
00828     if (recInfo)
00829         m_recInfo = new RecordingInfo(*recInfo);
00830 }
00831 
00832 StoreOptEditor::~StoreOptEditor(void)
00833 {
00834 }
00835 
00836 bool StoreOptEditor::Create()
00837 {
00838     if (!LoadWindowFromXML("schedule-ui.xml", "storageoptionseditor", this))
00839         return false;
00840 
00841     bool err = false;
00842 
00843     UIUtilE::Assign(this, m_recprofileList, "recprofile", &err);
00844     UIUtilE::Assign(this, m_recgroupList, "recgroup", &err);
00845     UIUtilE::Assign(this, m_storagegroupList, "storagegroup", &err);
00846     UIUtilE::Assign(this, m_playgroupList, "playgroup", &err);
00847     UIUtilE::Assign(this, m_maxepSpin, "maxepisodes", &err);
00848     UIUtilE::Assign(this, m_maxbehaviourList, "maxnewest", &err);
00849 
00850     UIUtilE::Assign(this, m_autoexpireCheck, "autoexpire", &err);
00851     UIUtilW::Assign(this, m_backButton, "back");
00852 
00853     if (err)
00854     {
00855         LOG(VB_GENERAL, LOG_ERR, "StoreOptEditor, theme is missing "
00856                                  "required elements");
00857         return false;
00858     }
00859 
00860     if (m_backButton)
00861         connect(m_backButton, SIGNAL(Clicked()), SLOT(Close()));
00862 
00863     connect(m_maxepSpin, SIGNAL(itemSelected(MythUIButtonListItem *)),
00864                          SLOT(maxEpChanged(MythUIButtonListItem *)));
00865 
00866     connect(m_recgroupList, SIGNAL(LosingFocus()),
00867                             SLOT(PromptForRecgroup()));
00868 
00869     BuildFocusList();
00870 
00871     return true;
00872 }
00873 
00874 void StoreOptEditor::Load()
00875 {
00876     MSqlQuery query(MSqlQuery::InitCon());
00877 
00878     // Recording Profile
00879     QString label = tr("Record using the %1 profile");
00880     QMap<int, QString> profiles = RecordingProfile::listProfiles(0);
00881     QMap<int, QString>::iterator pit;
00882     for (pit = profiles.begin(); pit != profiles.end(); ++pit)
00883     {
00884         new MythUIButtonListItem(m_recprofileList, label.arg(pit.value()),
00885                                  qVariantFromValue(pit.value()));
00886     }
00887     m_recprofileList->SetValueByData(m_recordingRule->m_recProfile);
00888 
00889     // Recording Group
00890     QStringList groups;
00891     QStringList::Iterator it;
00892     QString value, dispValue;
00893     bool foundDefault = false;
00894 
00895         // Count the ways the following is _wrong_
00896 
00897     new MythUIButtonListItem(m_recgroupList,
00898                              tr("Create a new recording group"),
00899                              qVariantFromValue(QString("__NEW_GROUP__")));
00900 
00901     query.prepare("SELECT DISTINCT recgroup FROM recorded");
00902     if (query.exec())
00903     {
00904         while (query.next())
00905         {
00906             value = query.value(0).toString();
00907 
00908             if (value != "Deleted")
00909             {
00910                 groups += value;
00911                 if (value == "Default")
00912                     foundDefault = true;
00913             }
00914         }
00915     }
00916 
00917     query.prepare("SELECT DISTINCT recgroup FROM record");
00918     if (query.exec())
00919     {
00920         while (query.next())
00921         {
00922             value = query.value(0).toString();
00923             groups += value;
00924 
00925             if (value == "Default")
00926                 foundDefault = true;
00927         }
00928     }
00929 
00930     groups.sort();
00931     groups.removeDuplicates();
00932     for (it = groups.begin(); it != groups.end(); ++it)
00933     {
00934         label = tr("Include in the \"%1\" recording group");
00935         if (!foundDefault && *it > tr("Default"))
00936         {
00937             new MythUIButtonListItem(m_recgroupList, label.arg(tr("Default")),
00938                                      qVariantFromValue(QString("Default")));
00939             foundDefault = true;
00940         }
00941 
00942         if (*it == "Default")
00943             dispValue = tr("Default");
00944         else
00945             dispValue = *it;
00946 
00947         new MythUIButtonListItem(m_recgroupList, label.arg(dispValue),
00948                                  qVariantFromValue(*it));
00949     }
00950 
00951     m_recgroupList->SetValueByData(m_recordingRule->m_recGroup);
00952 
00953     // Storage Group
00954     groups = StorageGroup::getRecordingsGroups();
00955     foundDefault = false;
00956     for (it = groups.begin(); it != groups.end(); ++it)
00957     {
00958         if (*it == "Default")
00959             foundDefault = true;
00960     }
00961 
00962     for (it = groups.begin(); it != groups.end(); ++it)
00963     {
00964         label = tr("Store in the \"%1\" storage group");
00965         if (!foundDefault && *it > tr("Default"))
00966         {
00967             new MythUIButtonListItem(m_storagegroupList,
00968                                      label.arg(tr("Default")),
00969                                      qVariantFromValue(QString("Default")));
00970             foundDefault = true;
00971         }
00972 
00973         if (*it == "Default")
00974             dispValue = tr("Default");
00975         else if (*it == "LiveTV")
00976             dispValue = tr("Live TV");
00977         else
00978             dispValue = *it;
00979 
00980         new MythUIButtonListItem(m_storagegroupList, label.arg(dispValue),
00981                                  qVariantFromValue(*it));
00982     }
00983 
00984     m_storagegroupList->SetValueByData(m_recordingRule->m_storageGroup);
00985 
00986     // Playback Group
00987     label = tr("Use \"%1\" playback group settings");
00988     new MythUIButtonListItem(m_playgroupList, label.arg(tr("Default")),
00989                              qVariantFromValue(QString("Default")));
00990 
00991     groups = PlayGroup::GetNames();
00992 
00993     for (it = groups.begin(); it != groups.end(); ++it)
00994     {
00995         new MythUIButtonListItem(m_playgroupList, label.arg(*it),
00996                                  qVariantFromValue(*it));
00997     }
00998 
00999     m_playgroupList->SetValueByData(m_recordingRule->m_playGroup);
01000 
01001     // Auto-Expire
01002     m_autoexpireCheck->SetCheckState(m_recordingRule->m_autoExpire);
01003 
01004     // Max Episodes
01005     m_maxepSpin->SetRange(0,100,1,5);
01006     m_maxepSpin->SetValue(m_recordingRule->m_maxEpisodes);
01007 
01008     // Max Episode Behaviour
01009     new MythUIButtonListItem(m_maxbehaviourList,
01010                              tr("Don't record if this would exceed the max "
01011                                 "episodes"), qVariantFromValue(false));
01012     new MythUIButtonListItem(m_maxbehaviourList,
01013                              tr("Delete oldest if this would exceed the max "
01014                                 "episodes"), qVariantFromValue(true));
01015     m_maxbehaviourList->SetValueByData(m_recordingRule->m_maxNewest);
01016 
01017 
01018     InfoMap progMap;
01019     if (m_recInfo)
01020         m_recInfo->ToMap(progMap);
01021     else
01022         m_recordingRule->ToMap(progMap);
01023     SetTextFromMap(progMap);
01024 }
01025 
01026 void StoreOptEditor::maxEpChanged(MythUIButtonListItem *item)
01027 {
01028     if (!item)
01029         return;
01030 
01031     if (item->GetData().toInt() == 0)
01032         m_maxbehaviourList->SetEnabled(false);
01033     else
01034         m_maxbehaviourList->SetEnabled(true);
01035 }
01036 
01037 void StoreOptEditor::PromptForRecgroup()
01038 {
01039     if (m_recgroupList->GetDataValue().toString() != "__NEW_GROUP__")
01040         return;
01041 
01042     MythScreenStack *popupStack = GetMythMainWindow()->GetStack("popup stack");
01043 
01044     QString label = tr("Create New Recording Group. Enter group name: ");
01045 
01046     MythTextInputDialog *textDialog = new MythTextInputDialog(popupStack, label,
01047                          static_cast<InputFilter>(FilterSymbols | FilterPunct));
01048 
01049     textDialog->SetReturnEvent(this, "newrecgroup");
01050 
01051     if (textDialog->Create())
01052         popupStack->AddScreen(textDialog, false);
01053     return;
01054 }
01055 
01056 void StoreOptEditor::customEvent(QEvent *event)
01057 {
01058     if (event->type() == DialogCompletionEvent::kEventType)
01059     {
01060         DialogCompletionEvent *dce = (DialogCompletionEvent*)(event);
01061 
01062         QString resultid   = dce->GetId();
01063         QString resulttext = dce->GetResultText();
01064 
01065         if (resultid == "newrecgroup")
01066         {
01067             if (!resulttext.isEmpty())
01068             {
01069                 QString label = tr("Include in the \"%1\" recording group");
01070                 MythUIButtonListItem *item =
01071                                     new MythUIButtonListItem(m_recgroupList,
01072                                                 label.arg(resulttext),
01073                                                 qVariantFromValue(resulttext));
01074                 m_recgroupList->SetItemCurrent(item);
01075             }
01076             else
01077                 m_recgroupList->SetValueByData(m_recordingRule->m_recGroup);
01078         }
01079     }
01080 }
01081 
01082 void StoreOptEditor::Save()
01083 {
01084     // If the user has selected 'Create a new regroup' but failed to enter a
01085     // name when prompted, restore the original value
01086     if (m_recgroupList->GetDataValue().toString() == "__NEW_GROUP__")
01087         m_recgroupList->SetValueByData(m_recordingRule->m_recGroup);
01088 
01089     // Recording Profile
01090     m_recordingRule->m_recProfile = m_recprofileList->GetDataValue().toString();
01091 
01092     // Recording Group
01093     m_recordingRule->m_recGroup = m_recgroupList->GetDataValue().toString();
01094 
01095     // Storage Group
01096     m_recordingRule->m_storageGroup = m_storagegroupList->GetDataValue()
01097                                                                     .toString();
01098 
01099     // Playback Group
01100     m_recordingRule->m_playGroup = m_playgroupList->GetDataValue().toString();
01101 
01102     // Auto-Expire
01103     m_recordingRule->m_autoExpire = m_autoexpireCheck->GetBooleanCheckState();
01104 
01105     // Max Episodes
01106     m_recordingRule->m_maxEpisodes = m_maxepSpin->GetIntValue();
01107 
01108     // Max Episode Behaviour
01109     m_recordingRule->m_maxNewest = m_maxbehaviourList->GetDataValue().toBool();
01110 }
01111 
01112 void StoreOptEditor::Close()
01113 {
01114     Save();
01115     MythScreenType::Close();
01116 }
01117 
01119 
01125 PostProcEditor::PostProcEditor(MythScreenStack *parent,
01126                                RecordingInfo *recInfo,
01127                                RecordingRule *rule)
01128           : MythScreenType(parent, "PostProcOptionsEditor"),
01129             m_recInfo(NULL), m_recordingRule(rule),
01130             m_backButton(NULL),
01131             m_commflagCheck(NULL), m_transcodeCheck(NULL),
01132             m_transcodeprofileList(NULL), m_userjob1Check(NULL),
01133             m_userjob2Check(NULL), m_userjob3Check(NULL),
01134             m_userjob4Check(NULL), m_metadataLookupCheck(NULL)
01135 {
01136     if (recInfo)
01137         m_recInfo = new RecordingInfo(*recInfo);
01138 }
01139 
01140 PostProcEditor::~PostProcEditor(void)
01141 {
01142 }
01143 
01144 bool PostProcEditor::Create()
01145 {
01146     if (!LoadWindowFromXML("schedule-ui.xml", "postproceditor", this))
01147         return false;
01148 
01149     bool err = false;
01150 
01151     UIUtilE::Assign(this, m_commflagCheck, "autocommflag", &err);
01152     UIUtilE::Assign(this, m_transcodeCheck, "autotranscode", &err);
01153     UIUtilE::Assign(this, m_transcodeprofileList, "transcodeprofile", &err);
01154     UIUtilE::Assign(this, m_userjob1Check, "userjob1", &err);
01155     UIUtilE::Assign(this, m_userjob2Check, "userjob2", &err);
01156     UIUtilE::Assign(this, m_userjob3Check, "userjob3", &err);
01157     UIUtilE::Assign(this, m_userjob4Check, "userjob4", &err);
01158     UIUtilW::Assign(this, m_metadataLookupCheck, "metadatalookup");
01159     UIUtilW::Assign(this, m_backButton, "back");
01160 
01161     if (err)
01162     {
01163         LOG(VB_GENERAL, LOG_ERR, "PostProcEditor, theme is missing "
01164                                  "required elements");
01165         return false;
01166     }
01167 
01168     if (m_backButton)
01169         connect(m_backButton, SIGNAL(Clicked()), SLOT(Close()));
01170 
01171     connect(m_transcodeCheck, SIGNAL(toggled(bool)),
01172             SLOT(transcodeEnable(bool)));
01173 
01174     BuildFocusList();
01175 
01176     return true;
01177 }
01178 
01179 void PostProcEditor::Load()
01180 {
01181     // Auto-commflag
01182     m_commflagCheck->SetCheckState(m_recordingRule->m_autoCommFlag);
01183 
01184     // Auto-transcode
01185     m_transcodeCheck->SetCheckState(m_recordingRule->m_autoTranscode);
01186 
01187     // Transcode Method
01188     QMap<int, QString> profiles = RecordingProfile::listProfiles(
01189                                             RecordingProfile::TranscoderGroup);
01190     QMap<int, QString>::iterator it;
01191     for (it = profiles.begin(); it != profiles.end(); ++it)
01192     {
01193         new MythUIButtonListItem(m_transcodeprofileList, it.value(),
01194                                  qVariantFromValue(it.key()));
01195     }
01196     m_transcodeprofileList->SetValueByData(m_recordingRule->m_transcoder);
01197 
01198     // User Job #1
01199     m_userjob1Check->SetCheckState(m_recordingRule->m_autoUserJob1);
01200     MythUIText *userjob1Text = NULL;
01201     UIUtilW::Assign(this, userjob1Text, "userjob1text");
01202     if (userjob1Text)
01203         userjob1Text->SetText(tr("Run '%1'")
01204                     .arg(gCoreContext->GetSetting("UserJobDesc1"), "User Job 1"));
01205 
01206     // User Job #2
01207     m_userjob2Check->SetCheckState(m_recordingRule->m_autoUserJob2);
01208     MythUIText *userjob2Text = NULL;
01209     UIUtilW::Assign(this, userjob2Text, "userjob2text");
01210     if (userjob2Text)
01211         userjob2Text->SetText(tr("Run '%1'")
01212                     .arg(gCoreContext->GetSetting("UserJobDesc2", "User Job 2")));
01213 
01214     // User Job #3
01215     m_userjob3Check->SetCheckState(m_recordingRule->m_autoUserJob3);
01216     MythUIText *userjob3Text = NULL;
01217     UIUtilW::Assign(this, userjob3Text, "userjob3text");
01218     if (userjob3Text)
01219         userjob3Text->SetText(tr("Run '%1'")
01220                     .arg(gCoreContext->GetSetting("UserJobDesc3", "User Job 3")));
01221 
01222     // User Job #4
01223     m_userjob4Check->SetCheckState(m_recordingRule->m_autoUserJob4);
01224     MythUIText *userjob4Text = NULL;
01225     UIUtilW::Assign(this, userjob4Text, "userjob4text");
01226     if (userjob4Text)
01227         userjob4Text->SetText(tr("Run '%1'")
01228                     .arg(gCoreContext->GetSetting("UserJobDesc4", "User Job 4")));
01229 
01230     // Auto Metadata Lookup
01231     if (m_metadataLookupCheck)
01232         m_metadataLookupCheck->SetCheckState(m_recordingRule->m_autoMetadataLookup);
01233 
01234     InfoMap progMap;
01235     if (m_recInfo)
01236         m_recInfo->ToMap(progMap);
01237     else
01238         m_recordingRule->ToMap(progMap);
01239     SetTextFromMap(progMap);
01240 }
01241 
01242 void PostProcEditor::transcodeEnable(bool enable)
01243 {
01244     m_transcodeprofileList->SetEnabled(enable);
01245 }
01246 
01247 void PostProcEditor::Save()
01248 {
01249     // Auto-commflag
01250     m_recordingRule->m_autoCommFlag = m_commflagCheck->GetBooleanCheckState();
01251 
01252     // Auto-transcode
01253     m_recordingRule->m_autoTranscode = m_transcodeCheck->GetBooleanCheckState();
01254 
01255     // Transcode Method
01256     m_recordingRule->m_transcoder = m_transcodeprofileList->GetDataValue().toInt();
01257 
01258     // User Job #1
01259     m_recordingRule->m_autoUserJob1 = m_userjob1Check->GetBooleanCheckState();
01260 
01261     // User Job #2
01262     m_recordingRule->m_autoUserJob2 = m_userjob2Check->GetBooleanCheckState();
01263 
01264     // User Job #3
01265     m_recordingRule->m_autoUserJob3 = m_userjob3Check->GetBooleanCheckState();
01266 
01267     // User Job #4
01268     m_recordingRule->m_autoUserJob4 = m_userjob4Check->GetBooleanCheckState();
01269 
01270     // Auto Metadata Lookup
01271     if (m_metadataLookupCheck)
01272         m_recordingRule->m_autoMetadataLookup = m_metadataLookupCheck->GetBooleanCheckState();
01273 }
01274 
01275 void PostProcEditor::Close()
01276 {
01277     Save();
01278     MythScreenType::Close();
01279 }
01280 
01282 
01288 MetadataOptions::MetadataOptions(MythScreenStack *parent,
01289                                RecordingInfo *recInfo,
01290                                RecordingRule *rule)
01291           : MythScreenType(parent, "MetadataOptions"),
01292             m_recInfo(NULL), m_recordingRule(rule), m_lookup(NULL),
01293             m_busyPopup(NULL),  m_fanart(NULL), m_coverart(NULL),
01294             m_banner(NULL), m_inetrefEdit(NULL), m_seasonSpin(NULL),
01295             m_episodeSpin(NULL), m_queryButton(NULL), m_localFanartButton(NULL),
01296             m_localCoverartButton(NULL), m_localBannerButton(NULL),
01297             m_onlineFanartButton(NULL), m_onlineCoverartButton(NULL),
01298             m_onlineBannerButton(NULL), m_backButton(NULL)
01299 {
01300     m_popupStack = GetMythMainWindow()->GetStack("popup stack");
01301 
01302     m_metadataFactory = new MetadataFactory(this);
01303     m_imageLookup = new MetadataDownload(this);
01304     m_imageDownload = new MetadataImageDownload(this);
01305 
01306     m_artworkMap = GetArtwork(m_recordingRule->m_inetref,
01307                               m_recordingRule->m_season);
01308 
01309     if (recInfo)
01310         m_recInfo = new RecordingInfo(*recInfo);
01311 }
01312 
01313 MetadataOptions::~MetadataOptions(void)
01314 {
01315     if (m_imageLookup)
01316     {
01317         m_imageLookup->cancel();
01318         delete m_imageLookup;
01319         m_imageLookup = NULL;
01320     }
01321 
01322     if (m_imageDownload)
01323     {
01324         m_imageDownload->cancel();
01325         delete m_imageDownload;
01326         m_imageDownload = NULL;
01327     }
01328 }
01329 
01330 bool MetadataOptions::Create()
01331 {
01332     if (!LoadWindowFromXML("schedule-ui.xml", "metadataoptions", this))
01333         return false;
01334 
01335     bool err = false;
01336 
01337     UIUtilE::Assign(this, m_inetrefEdit, "inetref_edit", &err);
01338     UIUtilE::Assign(this, m_seasonSpin, "season_spinbox", &err);
01339     UIUtilE::Assign(this, m_episodeSpin, "episode_spinbox", &err);
01340     UIUtilE::Assign(this, m_queryButton, "query_button", &err);
01341     UIUtilE::Assign(this, m_localFanartButton, "local_fanart_button", &err);
01342     UIUtilE::Assign(this, m_localCoverartButton, "local_coverart_button", &err);
01343     UIUtilE::Assign(this, m_localBannerButton, "local_banner_button", &err);
01344     UIUtilE::Assign(this, m_onlineFanartButton, "online_fanart_button", &err);
01345     UIUtilE::Assign(this, m_onlineCoverartButton, "online_coverart_button", &err);
01346     UIUtilE::Assign(this, m_onlineBannerButton, "online_banner_button", &err);
01347     UIUtilW::Assign(this, m_fanart, "fanart");
01348     UIUtilW::Assign(this, m_coverart, "coverart");
01349     UIUtilW::Assign(this, m_banner, "banner");
01350     UIUtilW::Assign(this, m_backButton, "back");
01351 
01352     if (err)
01353     {
01354         LOG(VB_GENERAL, LOG_ERR, "MetadataOptions, theme is missing "
01355                                  "required elements");
01356         return false;
01357     }
01358 
01359     if (m_backButton)
01360         connect(m_backButton, SIGNAL(Clicked()), SLOT(Close()));
01361     connect(m_queryButton, SIGNAL(Clicked()),
01362             SLOT(PerformQuery()));
01363     connect(m_localFanartButton, SIGNAL(Clicked()),
01364             SLOT(SelectLocalFanart()));
01365     connect(m_localCoverartButton, SIGNAL(Clicked()),
01366             SLOT(SelectLocalCoverart()));
01367     connect(m_localBannerButton, SIGNAL(Clicked()),
01368             SLOT(SelectLocalBanner()));
01369     connect(m_onlineFanartButton, SIGNAL(Clicked()),
01370             SLOT(SelectOnlineFanart()));
01371     connect(m_onlineCoverartButton, SIGNAL(Clicked()),
01372             SLOT(SelectOnlineCoverart()));
01373     connect(m_onlineBannerButton, SIGNAL(Clicked()),
01374             SLOT(SelectOnlineBanner()));
01375 
01376     connect(m_seasonSpin, SIGNAL(itemSelected(MythUIButtonListItem*)),
01377                           SLOT(ValuesChanged()));
01378 
01379     // InetRef
01380     m_inetrefEdit->SetText(m_recordingRule->m_inetref);
01381 
01382     // Season
01383     m_seasonSpin->SetRange(0,9999,1,1);
01384     m_seasonSpin->SetValue(m_recordingRule->m_season);
01385 
01386     // Episode
01387     m_episodeSpin->SetRange(0,9999,1,1);
01388     m_episodeSpin->SetValue(m_recordingRule->m_episode);
01389 
01390     if (m_coverart)
01391     {
01392         m_coverart->SetFilename(m_artworkMap.value(kArtworkCoverart).url);
01393         m_coverart->Load();
01394     }
01395 
01396     if (m_fanart)
01397     {
01398         m_fanart->SetFilename(m_artworkMap.value(kArtworkFanart).url);
01399         m_fanart->Load();
01400     }
01401 
01402     if (m_banner)
01403     {
01404         m_banner->SetFilename(m_artworkMap.value(kArtworkBanner).url);
01405         m_banner->Load();
01406     }
01407 
01408     BuildFocusList();
01409 
01410     return true;
01411 }
01412 
01413 void MetadataOptions::Load()
01414 {
01415     if (m_recordingRule->m_inetref.isEmpty())
01416     {
01417         CreateBusyDialog("Trying to automatically find this "
01418                      "recording online...");
01419 
01420         m_metadataFactory->Lookup(m_recordingRule, false, false);
01421     }
01422 
01423     InfoMap progMap;
01424     if (m_recInfo)
01425         m_recInfo->ToMap(progMap);
01426     else
01427         m_recordingRule->ToMap(progMap);
01428     SetTextFromMap(progMap);
01429 }
01430 
01431 void MetadataOptions::CreateBusyDialog(QString title)
01432 {
01433     if (m_busyPopup)
01434         return;
01435 
01436     QString message = title;
01437 
01438     m_busyPopup = new MythUIBusyDialog(message, m_popupStack,
01439             "metaoptsdialog");
01440 
01441     if (m_busyPopup->Create())
01442         m_popupStack->AddScreen(m_busyPopup);
01443 }
01444 
01445 void MetadataOptions::PerformQuery()
01446 {
01447     m_lookup = new MetadataLookup();
01448 
01449     CreateBusyDialog("Trying to manually find this "
01450                      "recording online...");
01451 
01452     m_lookup->SetStep(kLookupSearch);
01453     m_lookup->SetType(kMetadataRecording);
01454     if (m_seasonSpin->GetIntValue() > 0 ||
01455            m_episodeSpin->GetIntValue() > 0)
01456         m_lookup->SetSubtype(kProbableTelevision);
01457     else
01458         m_lookup->SetSubtype(kProbableMovie);
01459     m_lookup->SetAutomatic(false);
01460     m_lookup->SetHandleImages(false);
01461     m_lookup->SetHost(gCoreContext->GetMasterHostName());
01462     m_lookup->SetTitle(m_recordingRule->m_title);
01463     m_lookup->SetSubtitle(m_recordingRule->m_subtitle);
01464     m_lookup->SetInetref(m_inetrefEdit->GetText());
01465     m_lookup->SetSeason(m_seasonSpin->GetIntValue());
01466     m_lookup->SetEpisode(m_episodeSpin->GetIntValue());
01467 
01468     m_metadataFactory->Lookup(m_lookup);
01469 }
01470 
01471 void MetadataOptions::OnSearchListSelection(MetadataLookup *lookup)
01472 {
01473     if (!lookup)
01474         return;
01475 
01476     m_lookup = lookup;
01477 
01478     m_metadataFactory->Lookup(lookup);
01479 }
01480 
01481 void MetadataOptions::OnImageSearchListSelection(ArtworkInfo info,
01482                                                  VideoArtworkType type)
01483 {
01484     QString msg = tr("Downloading selected artwork...");
01485     CreateBusyDialog(msg);
01486 
01487     m_lookup = new MetadataLookup();
01488     m_lookup->SetType(kMetadataVideo);
01489     m_lookup->SetHost(gCoreContext->GetMasterHostName());
01490     m_lookup->SetAutomatic(true);
01491     m_lookup->SetData(qVariantFromValue<VideoArtworkType>(type));
01492 
01493     ArtworkMap downloads;
01494     downloads.insert(type, info);
01495     m_lookup->SetDownloads(downloads);
01496     m_lookup->SetAllowOverwrites(true);
01497     m_lookup->SetTitle(m_recordingRule->m_title);
01498     m_lookup->SetSubtitle(m_recordingRule->m_subtitle);
01499     m_lookup->SetInetref(m_inetrefEdit->GetText());
01500     m_lookup->SetSeason(m_seasonSpin->GetIntValue());
01501     m_lookup->SetEpisode(m_episodeSpin->GetIntValue());
01502 
01503     m_imageDownload->addDownloads(m_lookup);
01504 }
01505 
01506 void MetadataOptions::SelectLocalFanart()
01507 {
01508     if (!CanSetArtwork())
01509         return;
01510 
01511     QString url = generate_file_url("Fanart",
01512                   gCoreContext->GetMasterHostName(),
01513                   "");
01514     FindImagePopup(url,"",*this, "fanart");
01515 }
01516 
01517 void MetadataOptions::SelectLocalCoverart()
01518 {
01519     if (!CanSetArtwork())
01520         return;
01521 
01522     QString url = generate_file_url("Coverart",
01523                   gCoreContext->GetMasterHostName(),
01524                   "");
01525     FindImagePopup(url,"",*this, "coverart");
01526 }
01527 
01528 void MetadataOptions::SelectLocalBanner()
01529 {
01530     if (!CanSetArtwork())
01531         return;
01532 
01533     QString url = generate_file_url("Banners",
01534                   gCoreContext->GetMasterHostName(),
01535                   "");
01536     FindImagePopup(url,"",*this, "banner");
01537 }
01538 
01539 void MetadataOptions::SelectOnlineFanart()
01540 {
01541     FindNetArt(kArtworkFanart);
01542 }
01543 
01544 void MetadataOptions::SelectOnlineCoverart()
01545 {
01546     FindNetArt(kArtworkCoverart);
01547 }
01548 
01549 void MetadataOptions::SelectOnlineBanner()
01550 {
01551     FindNetArt(kArtworkBanner);
01552 }
01553 
01554 void MetadataOptions::Close()
01555 {
01556     Save();
01557     MythScreenType::Close();
01558 }
01559 
01560 void MetadataOptions::Save()
01561 {
01562     // Season
01563     if (m_seasonSpin)
01564         m_recordingRule->m_season = m_seasonSpin->GetIntValue();
01565 
01566     // Episode
01567     if (m_episodeSpin)
01568         m_recordingRule->m_episode = m_episodeSpin->GetIntValue();
01569 
01570     // InetRef
01571     if (m_inetrefEdit)
01572         m_recordingRule->m_inetref = m_inetrefEdit->GetText();
01573 }
01574 
01575 void MetadataOptions::QueryComplete(MetadataLookup *lookup)
01576 {
01577     if (!lookup)
01578         return;
01579 
01580     m_lookup = lookup;
01581 
01582     // InetRef
01583     m_inetrefEdit->SetText(m_lookup->GetInetref());
01584 
01585     // Season
01586     m_seasonSpin->SetValue(m_lookup->GetSeason());
01587 
01588     // Episode
01589     m_episodeSpin->SetValue(m_lookup->GetEpisode());
01590 
01591     MetadataMap metadataMap;
01592     lookup->toMap(metadataMap);
01593     SetTextFromMap(metadataMap);
01594 }
01595 
01596 void MetadataOptions::FindImagePopup(const QString &prefix,
01597                                      const QString &prefixAlt,
01598                                      QObject &inst,
01599                                      const QString &returnEvent)
01600 {
01601     QString fp;
01602 
01603     if (prefix.startsWith("myth://"))
01604         fp = prefix;
01605     else
01606         fp = prefix.isEmpty() ? prefixAlt : prefix;
01607 
01608     MythScreenStack *popupStack =
01609             GetMythMainWindow()->GetStack("popup stack");
01610 
01611     MythUIFileBrowser *fb = new MythUIFileBrowser(popupStack, fp);
01612     fb->SetNameFilter(GetSupportedImageExtensionFilter());
01613     if (fb->Create())
01614     {
01615         fb->SetReturnEvent(&inst, returnEvent);
01616         popupStack->AddScreen(fb);
01617     }
01618     else
01619         delete fb;
01620 }
01621 
01622 QStringList MetadataOptions::GetSupportedImageExtensionFilter()
01623 {
01624     QStringList ret;
01625 
01626     QList<QByteArray> exts = QImageReader::supportedImageFormats();
01627     for (QList<QByteArray>::iterator p = exts.begin(); p != exts.end(); ++p)
01628     {
01629         ret.append(QString("*.").append(*p));
01630     }
01631 
01632     return ret;
01633 }
01634 
01635 bool MetadataOptions::CanSetArtwork()
01636 {
01637     if (m_inetrefEdit->GetText().isEmpty())
01638     {
01639         ShowOkPopup(tr("You must set a reference number "
01640                "on this rule to set artwork.  For items "
01641                "without a metadata source, you can set "
01642                "any unique value."));
01643         return false;
01644     }
01645 
01646     return true;
01647 }
01648 
01649 void MetadataOptions::FindNetArt(VideoArtworkType type)
01650 {
01651     if (!CanSetArtwork())
01652         return;
01653 
01654     m_lookup = new MetadataLookup();
01655 
01656     QString msg = tr("Searching for available artwork...");
01657     CreateBusyDialog(msg);
01658 
01659     m_lookup->SetStep(kLookupSearch);
01660     m_lookup->SetType(kMetadataVideo);
01661     m_lookup->SetAutomatic(true);
01662     m_lookup->SetHandleImages(false);
01663     if (m_seasonSpin->GetIntValue() > 0 ||
01664            m_episodeSpin->GetIntValue() > 0)
01665         m_lookup->SetSubtype(kProbableTelevision);
01666     else
01667         m_lookup->SetSubtype(kProbableMovie);
01668     m_lookup->SetData(qVariantFromValue<VideoArtworkType>(type));
01669     m_lookup->SetHost(gCoreContext->GetMasterHostName());
01670     m_lookup->SetTitle(m_recordingRule->m_title);
01671     m_lookup->SetSubtitle(m_recordingRule->m_subtitle);
01672     m_lookup->SetInetref(m_inetrefEdit->GetText());
01673     m_lookup->SetSeason(m_seasonSpin->GetIntValue());
01674     m_lookup->SetEpisode(m_episodeSpin->GetIntValue());
01675 
01676     m_imageLookup->addLookup(m_lookup);
01677 }
01678 
01679 void MetadataOptions::OnArtworkSearchDone(MetadataLookup *lookup)
01680 {
01681     if (!lookup)
01682         return;
01683 
01684     if (m_busyPopup)
01685     {
01686         m_busyPopup->Close();
01687         m_busyPopup = NULL;
01688     }
01689 
01690     VideoArtworkType type = qVariantValue<VideoArtworkType>(lookup->GetData());
01691     ArtworkList list = lookup->GetArtwork(type);
01692 
01693     if (list.count() == 0)
01694         return;
01695 
01696     ImageSearchResultsDialog *resultsdialog =
01697           new ImageSearchResultsDialog(m_popupStack, list, type);
01698 
01699     connect(resultsdialog, SIGNAL(haveResult(ArtworkInfo, VideoArtworkType)),
01700             SLOT(OnImageSearchListSelection(ArtworkInfo, VideoArtworkType)));
01701 
01702     if (resultsdialog->Create())
01703         m_popupStack->AddScreen(resultsdialog);
01704 }
01705 
01706 void MetadataOptions::HandleDownloadedImages(MetadataLookup *lookup)
01707 {
01708     if (!lookup)
01709         return;
01710 
01711     DownloadMap map = lookup->GetDownloads();
01712 
01713     if (!map.size())
01714         return;
01715 
01716     for (DownloadMap::const_iterator i = map.begin(); i != map.end(); ++i)
01717     {
01718         VideoArtworkType type = i.key();
01719         ArtworkInfo info = i.value();
01720 
01721         if (type == kArtworkCoverart)
01722             m_artworkMap.replace(kArtworkCoverart, info);
01723         else if (type == kArtworkFanart)
01724             m_artworkMap.replace(kArtworkFanart, info);
01725         else if (type == kArtworkBanner)
01726             m_artworkMap.replace(kArtworkBanner, info);
01727     }
01728 
01729     SetArtwork(m_inetrefEdit->GetText(), m_seasonSpin->GetIntValue(),
01730                gCoreContext->GetMasterHostName(), m_artworkMap);
01731 
01732     ValuesChanged();
01733 }
01734 
01735 void MetadataOptions::ValuesChanged()
01736 {
01737     m_artworkMap = GetArtwork(m_inetrefEdit->GetText(),
01738                               m_seasonSpin->GetIntValue());
01739 
01740     if (m_coverart)
01741     {
01742         m_coverart->SetFilename(m_artworkMap.value(kArtworkCoverart).url);
01743         m_coverart->Load();
01744     }
01745 
01746     if (m_fanart)
01747     {
01748         m_fanart->SetFilename(m_artworkMap.value(kArtworkFanart).url);
01749         m_fanart->Load();
01750     }
01751 
01752     if (m_banner)
01753     {
01754         m_banner->SetFilename(m_artworkMap.value(kArtworkBanner).url);
01755         m_banner->Load();
01756     }
01757 }
01758 
01759 void MetadataOptions::customEvent(QEvent *levent)
01760 {
01761     if (levent->type() == MetadataFactoryMultiResult::kEventType)
01762     {
01763         if (m_busyPopup)
01764         {
01765             m_busyPopup->Close();
01766             m_busyPopup = NULL;
01767         }
01768 
01769         MetadataFactoryMultiResult *mfmr = dynamic_cast<MetadataFactoryMultiResult*>(levent);
01770 
01771         if (!mfmr)
01772             return;
01773 
01774         MetadataLookupList list = mfmr->results;
01775 
01776         if (list.count() > 1)
01777         {
01778             int yearindex = -1;
01779 
01780             for (int p = 0; p != list.size(); ++p)
01781             {
01782                 if (!m_recordingRule->m_seriesid.isEmpty() &&
01783                     m_recordingRule->m_seriesid == (list[p])->GetTMSref())
01784                 {
01785                     MetadataLookup *lookup = list.takeAt(p);
01786                     QueryComplete(lookup);
01787                     qDeleteAll(list);
01788                     return;
01789                 }
01790                 else if (m_recInfo &&
01791                          m_recInfo->GetYearOfInitialRelease() != 0 &&
01792                          (list[p])->GetYear() != 0 &&
01793                          m_recInfo->GetYearOfInitialRelease() == (list[p])->GetYear())
01794                 {
01795                     if (yearindex > -1)
01796                     {
01797                         LOG(VB_GENERAL, LOG_INFO, "Multiple results matched on year. No definite "
01798                                       "match could be found based on year alone.");
01799                         yearindex = -2;
01800                     }
01801                     else if (yearindex == -1)
01802                     {
01803                         LOG(VB_GENERAL, LOG_INFO, "Matched based on year. ");
01804                         yearindex = p;
01805                     }
01806                 }
01807             }
01808 
01809             if (yearindex > -1)
01810             {
01811                 MetadataLookup *lookup = list.takeAt(yearindex);
01812                 QueryComplete(lookup);
01813                 qDeleteAll(list);
01814                 return;
01815             }
01816 
01817             LOG(VB_GENERAL, LOG_INFO, "Falling through to selection dialog.");
01818             MetadataResultsDialog *resultsdialog =
01819                   new MetadataResultsDialog(m_popupStack, list);
01820 
01821             connect(resultsdialog, SIGNAL(haveResult(MetadataLookup*)),
01822                     SLOT(OnSearchListSelection(MetadataLookup*)),
01823                     Qt::QueuedConnection);
01824 
01825             if (resultsdialog->Create())
01826                 m_popupStack->AddScreen(resultsdialog);
01827         }
01828     }
01829     else if (levent->type() == MetadataFactorySingleResult::kEventType)
01830     {
01831         if (m_busyPopup)
01832         {
01833             m_busyPopup->Close();
01834             m_busyPopup = NULL;
01835         }
01836 
01837         MetadataFactorySingleResult *mfsr = dynamic_cast<MetadataFactorySingleResult*>(levent);
01838 
01839         if (!mfsr)
01840             return;
01841 
01842         MetadataLookup *lookup = mfsr->result;
01843 
01844         if (!lookup)
01845             return;
01846 
01847         QueryComplete(lookup);
01848     }
01849     else if (levent->type() == MetadataFactoryNoResult::kEventType)
01850     {
01851         if (m_busyPopup)
01852         {
01853             m_busyPopup->Close();
01854             m_busyPopup = NULL;
01855         }
01856 
01857         MetadataFactoryNoResult *mfnr = dynamic_cast<MetadataFactoryNoResult*>(levent);
01858 
01859         if (!mfnr)
01860             return;
01861 
01862         MetadataLookup *lookup = mfnr->result;
01863 
01864         delete lookup;
01865         lookup = NULL;
01866 
01867         QString title = "No match found for this recording. You can "
01868                         "try entering a TVDB/TMDB number, season, and "
01869                         "episode manually.";
01870 
01871         MythConfirmationDialog *okPopup =
01872                 new MythConfirmationDialog(m_popupStack, title, false);
01873 
01874         if (okPopup->Create())
01875             m_popupStack->AddScreen(okPopup);
01876     }
01877     else if (levent->type() == MetadataLookupEvent::kEventType)
01878     {
01879         if (m_busyPopup)
01880         {
01881             m_busyPopup->Close();
01882             m_busyPopup = NULL;
01883         }
01884 
01885         MetadataLookupEvent *lue = (MetadataLookupEvent *)levent;
01886 
01887         MetadataLookupList lul = lue->lookupList;
01888 
01889         if (lul.isEmpty())
01890             return;
01891 
01892         if (lul.count() >= 1)
01893         {
01894             OnArtworkSearchDone(lul.takeFirst());
01895         }
01896     }
01897     else if (levent->type() == MetadataLookupFailure::kEventType)
01898     {
01899         if (m_busyPopup)
01900         {
01901             m_busyPopup->Close();
01902             m_busyPopup = NULL;
01903         }
01904 
01905         MetadataLookupFailure *luf = (MetadataLookupFailure *)levent;
01906 
01907         MetadataLookupList lul = luf->lookupList;
01908 
01909         if (lul.size())
01910         {
01911             MetadataLookup *lookup = lul.takeFirst();
01912 
01913             QString title = "This number, season, and episode combination "
01914                             "does not appear to be valid (or the site may "
01915                             "be down).  Check your information and try again.";
01916 
01917             MythConfirmationDialog *okPopup =
01918                     new MythConfirmationDialog(m_popupStack, title, false);
01919 
01920             if (okPopup->Create())
01921                 m_popupStack->AddScreen(okPopup);
01922 
01923             delete lookup;
01924             lookup = NULL;
01925         }
01926     }
01927     else if (levent->type() == ImageDLEvent::kEventType)
01928     {
01929         if (m_busyPopup)
01930         {
01931             m_busyPopup->Close();
01932             m_busyPopup = NULL;
01933         }
01934 
01935         ImageDLEvent *ide = (ImageDLEvent *)levent;
01936 
01937         MetadataLookup *lookup = ide->item;
01938 
01939         if (!lookup)
01940             return;
01941 
01942         HandleDownloadedImages(lookup);
01943     }
01944     else if (levent->type() == ImageDLFailureEvent::kEventType)
01945     {
01946         if (m_busyPopup)
01947         {
01948             m_busyPopup->Close();
01949             m_busyPopup = NULL;
01950         }
01951 
01952         ImageDLFailureEvent *ide = (ImageDLFailureEvent *)levent;
01953 
01954         MetadataLookup *lookup = ide->item;
01955 
01956         if (!lookup)
01957             return;
01958 
01959         delete lookup;
01960         lookup = NULL;
01961     }
01962     else if (levent->type() == DialogCompletionEvent::kEventType)
01963     {
01964         DialogCompletionEvent *dce = (DialogCompletionEvent*)(levent);
01965 
01966         const QString resultid = dce->GetId();
01967         ArtworkInfo info;
01968         info.url = dce->GetResultText();
01969 
01970         if (resultid == "coverart")
01971         {
01972             m_artworkMap.replace(kArtworkCoverart, info);
01973         }
01974         else if (resultid == "fanart")
01975         {
01976             m_artworkMap.replace(kArtworkFanart, info);
01977         }
01978         else if (resultid == "banner")
01979         {
01980             m_artworkMap.replace(kArtworkBanner, info);
01981         }
01982 
01983         SetArtwork(m_inetrefEdit->GetText(), m_seasonSpin->GetIntValue(),
01984                gCoreContext->GetMasterHostName(), m_artworkMap);
01985 
01986         ValuesChanged();
01987     }
01988 
01989 }
01990 
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends