00001
00002 #include "viewscheduled.h"
00003
00004 #include <QCoreApplication>
00005
00006 #include "customedit.h"
00007 #include "recordinginfo.h"
00008 #include "tv_play.h"
00009 #include "recordingrule.h"
00010 #include "mythlogging.h"
00011 #include "mythcorecontext.h"
00012 #include "remoteutil.h"
00013 #include "mythuitext.h"
00014 #include "mythuistatetype.h"
00015 #include "mythuibuttonlist.h"
00016 #include "mythdialogbox.h"
00017 #include "mythmainwindow.h"
00018
00019 void *ViewScheduled::RunViewScheduled(void *player, bool showTV)
00020 {
00021 MythScreenStack *mainStack = GetMythMainWindow()->GetMainStack();
00022 ViewScheduled *vsb = new ViewScheduled(mainStack, static_cast<TV*>(player),
00023 showTV);
00024
00025 if (vsb->Create())
00026 mainStack->AddScreen(vsb, (player == NULL));
00027 else
00028 delete vsb;
00029
00030 return NULL;
00031 }
00032
00033 ViewScheduled::ViewScheduled(MythScreenStack *parent, TV* player, bool showTV)
00034 : ScheduleCommon(parent, "ViewScheduled")
00035 {
00036 m_showAll = !gCoreContext->GetNumSetting("ViewSchedShowLevel", 0);
00037
00038 m_player = player;
00039
00040 m_inEvent = false;
00041 m_inFill = false;
00042 m_needFill = false;
00043
00044 m_curcard = 0;
00045 m_maxcard = 0;
00046 m_curinput = 0;
00047 m_maxinput = 0;
00048
00049 m_defaultGroup = QDate();
00050 m_currentGroup = m_defaultGroup;
00051
00052 gCoreContext->addListener(this);
00053 }
00054
00055 ViewScheduled::~ViewScheduled()
00056 {
00057 gCoreContext->removeListener(this);
00058 gCoreContext->SaveSetting("ViewSchedShowLevel", !m_showAll);
00059
00060
00061 if (m_player)
00062 {
00063 QString message = QString("VIEWSCHEDULED_EXITING");
00064 qApp->postEvent(m_player, new MythEvent(message));
00065 }
00066 }
00067
00068 bool ViewScheduled::Create()
00069 {
00070 if (!LoadWindowFromXML("schedule-ui.xml", "viewscheduled", this))
00071 return false;
00072
00073
00074
00075 m_groupList = dynamic_cast<MythUIButtonList *> (GetChild("groups"));
00076 m_schedulesList = dynamic_cast<MythUIButtonList *> (GetChild("schedules"));
00077
00078 if (!m_schedulesList)
00079 {
00080 LOG(VB_GENERAL, LOG_ERR, "Theme is missing critical theme elements.");
00081 return false;
00082 }
00083
00084 connect(m_schedulesList, SIGNAL(itemSelected(MythUIButtonListItem*)),
00085 SLOT(updateInfo(MythUIButtonListItem*)));
00086 connect(m_schedulesList, SIGNAL(itemClicked(MythUIButtonListItem*)),
00087 SLOT(selected(MythUIButtonListItem*)));
00088
00089 m_schedulesList->SetLCDTitles(tr("Scheduled Recordings"),
00090 "shortstarttimedate|channel|titlesubtitle|card");
00091 m_schedulesList->SetSearchFields("titlesubtitle");
00092
00093 if (m_groupList)
00094 {
00095 connect(m_groupList, SIGNAL(itemSelected(MythUIButtonListItem*)),
00096 SLOT(ChangeGroup(MythUIButtonListItem*)));
00097 connect(m_groupList, SIGNAL(itemClicked(MythUIButtonListItem*)),
00098 SLOT(SwitchList()));
00099 m_groupList->SetLCDTitles(tr("Group List"), "");
00100 }
00101
00102 BuildFocusList();
00103 LoadInBackground();
00104
00105 EmbedTVWindow();
00106
00107 return true;
00108 }
00109
00110 void ViewScheduled::Load(void)
00111 {
00112 LoadFromScheduler(m_recList, m_conflictBool);
00113 }
00114
00115 void ViewScheduled::Init()
00116 {
00117 LoadList(true);
00118 }
00119
00120 void ViewScheduled::Close()
00121 {
00122
00123 if (m_player)
00124 GetScreenStack()->PopScreen(this, false);
00125 else
00126 GetScreenStack()->PopScreen(this, true);
00127 }
00128
00129 void ViewScheduled::SwitchList()
00130 {
00131 if (GetFocusWidget() == m_groupList)
00132 SetFocusWidget(m_schedulesList);
00133 else if (GetFocusWidget() == m_schedulesList)
00134 SetFocusWidget(m_groupList);
00135 }
00136
00137 bool ViewScheduled::keyPressEvent(QKeyEvent *event)
00138 {
00139
00140 if (m_inEvent)
00141 return true;
00142
00143 m_inEvent = true;
00144
00145 if (GetFocusWidget()->keyPressEvent(event))
00146 {
00147 m_inEvent = false;
00148 return true;
00149 }
00150
00151 bool handled = false;
00152 QStringList actions;
00153 handled = GetMythMainWindow()->TranslateKeyPress("TV Frontend", event,
00154 actions);
00155
00156 for (int i = 0; i < actions.size() && !handled; i++)
00157 {
00158 QString action = actions[i];
00159 handled = true;
00160
00161 if (action == "EDIT")
00162 edit();
00163 else if (action == "CUSTOMEDIT")
00164 customEdit();
00165 else if (action == "DELETE")
00166 deleteRule();
00167 else if (action == "UPCOMING")
00168 upcoming();
00169 else if (action == "VIEWSCHEDULED")
00170 upcomingScheduled();
00171 else if (action == "DETAILS" || action == "INFO")
00172 details();
00173 else if (action == "1")
00174 setShowAll(true);
00175 else if (action == "2")
00176 setShowAll(false);
00177 else if (action == "PREVVIEW" || action == "NEXTVIEW")
00178 setShowAll(!m_showAll);
00179 else if (action == "VIEWCARD")
00180 viewCards();
00181 else if (action == "VIEWINPUT")
00182 viewInputs();
00183 else
00184 handled = false;
00185 }
00186
00187 if (m_needFill)
00188 LoadList();
00189
00190 if (!handled && MythScreenType::keyPressEvent(event))
00191 handled = true;
00192
00193 m_inEvent = false;
00194
00195 return handled;
00196 }
00197
00198 void ViewScheduled::ShowMenu(void)
00199 {
00200 QString label = tr("Options");
00201
00202 MythScreenStack *popupStack = GetMythMainWindow()->GetStack("popup stack");
00203 MythDialogBox *menuPopup = new MythDialogBox(label, popupStack,
00204 "menuPopup");
00205
00206 if (menuPopup->Create())
00207 {
00208 menuPopup->SetReturnEvent(this, "menu");
00209
00210 if (m_showAll)
00211 menuPopup->AddButton(tr("Show Important"));
00212 else
00213 menuPopup->AddButton(tr("Show All"));
00214 menuPopup->AddButton(tr("Program Details"));
00215 menuPopup->AddButton(tr("Upcoming by title"));
00216 menuPopup->AddButton(tr("Upcoming scheduled"));
00217 menuPopup->AddButton(tr("Custom Edit"));
00218 menuPopup->AddButton(tr("Delete Rule"));
00219 menuPopup->AddButton(tr("Show Cards"));
00220 menuPopup->AddButton(tr("Show Inputs"));
00221
00222 popupStack->AddScreen(menuPopup);
00223 }
00224 else
00225 {
00226 delete menuPopup;
00227 }
00228 }
00229
00230 void ViewScheduled::LoadList(bool useExistingData)
00231 {
00232 if (m_inFill)
00233 return;
00234
00235 m_inFill = true;
00236
00237 MythUIButtonListItem *currentItem = m_schedulesList->GetItemCurrent();
00238
00239 QString callsign;
00240 QDateTime startts, recstartts;
00241
00242 if (currentItem)
00243 {
00244 ProgramInfo *currentpginfo = qVariantValue<ProgramInfo*>
00245 (currentItem->GetData());
00246 if (currentpginfo)
00247 {
00248 callsign = currentpginfo->GetChannelSchedulingID();
00249 startts = currentpginfo->GetScheduledStartTime();
00250 recstartts = currentpginfo->GetRecordingStartTime();
00251 }
00252 }
00253
00254 QDateTime now = QDateTime::currentDateTime();
00255
00256 QMap<int, int> toomanycounts;
00257
00258 m_schedulesList->Reset();
00259 if (m_groupList)
00260 m_groupList->Reset();
00261
00262 m_recgroupList.clear();
00263
00264 if (!useExistingData)
00265 LoadFromScheduler(m_recList, m_conflictBool);
00266
00267 ProgramList::iterator pit = m_recList.begin();
00268 QString currentDate;
00269 m_recgroupList[m_defaultGroup] = ProgramList(false);
00270 m_recgroupList[m_defaultGroup].setAutoDelete(false);
00271 while (pit != m_recList.end())
00272 {
00273 ProgramInfo *pginfo = *pit;
00274 const RecStatusType recstatus = pginfo->GetRecordingStatus();
00275 if ((pginfo->GetRecordingEndTime() >= now ||
00276 pginfo->GetScheduledEndTime() >= now) &&
00277 (m_showAll ||
00278 recstatus <= rsWillRecord ||
00279 recstatus == rsDontRecord ||
00280 (recstatus == rsTooManyRecordings &&
00281 ++toomanycounts[pginfo->GetRecordingRuleID()] <= 1) ||
00282 (recstatus > rsTooManyRecordings &&
00283 recstatus != rsRepeat &&
00284 recstatus != rsNeverRecord)))
00285 {
00286 m_cardref[pginfo->GetCardID()]++;
00287 if (pginfo->GetCardID() > m_maxcard)
00288 m_maxcard = pginfo->GetCardID();
00289
00290 m_inputref[pginfo->GetInputID()]++;
00291 if (pginfo->GetInputID() > m_maxinput)
00292 m_maxinput = pginfo->GetInputID();
00293
00294 QDate date = (pginfo->GetRecordingStartTime()).date();
00295 m_recgroupList[date].push_back(pginfo);
00296 m_recgroupList[date].setAutoDelete(false);
00297
00298 m_recgroupList[m_defaultGroup].push_back(pginfo);
00299
00300 ++pit;
00301 }
00302 else
00303 {
00304 pit = m_recList.erase(pit);
00305 continue;
00306 }
00307 }
00308
00309 if (m_groupList)
00310 {
00311 QString label;
00312 QMap<QDate,ProgramList>::iterator dateit = m_recgroupList.begin();
00313 while (dateit != m_recgroupList.end())
00314 {
00315 if (dateit.key().isNull())
00316 label = tr("All");
00317 else
00318 label = MythDateToString(dateit.key(), kDateFull | kSimplify);
00319
00320 new MythUIButtonListItem(m_groupList, label,
00321 qVariantFromValue(dateit.key()));
00322 ++dateit;
00323 }
00324 if (!m_recgroupList.contains(m_currentGroup))
00325 m_groupList->SetValueByData(qVariantFromValue(m_currentGroup));
00326 }
00327
00328 FillList();
00329
00330
00331 if (!callsign.isEmpty())
00332 {
00333 ProgramList plist;
00334
00335 if (!m_recgroupList.contains(m_currentGroup))
00336 m_currentGroup = m_defaultGroup;
00337
00338 plist = m_recgroupList[m_currentGroup];
00339
00340 int listPos = ((int) plist.size()) - 1;
00341 int i;
00342 for (i = listPos; i >= 0; --i)
00343 {
00344 ProgramInfo *pginfo = plist[i];
00345 if (callsign == pginfo->GetChannelSchedulingID() &&
00346 startts == pginfo->GetScheduledStartTime())
00347 {
00348 listPos = i;
00349 break;
00350 }
00351 else if (recstartts <= pginfo->GetRecordingStartTime())
00352 listPos = i;
00353 }
00354 m_schedulesList->SetItemCurrent(listPos);
00355 }
00356
00357 m_inFill = false;
00358 m_needFill = false;
00359 }
00360
00361
00362 void ViewScheduled::ChangeGroup(MythUIButtonListItem* item)
00363 {
00364 if (!item || m_recList.empty())
00365 return;
00366
00367 QDate group = qVariantValue<QDate>(item->GetData());
00368
00369 m_currentGroup = group;
00370
00371 if (!m_inFill)
00372 FillList();
00373 }
00374
00375 void ViewScheduled::FillList()
00376 {
00377 m_schedulesList->Reset();
00378
00379 MythUIText *norecordingText = dynamic_cast<MythUIText*>
00380 (GetChild("norecordings_info"));
00381
00382 if (norecordingText)
00383 norecordingText->SetVisible(m_recList.empty());
00384
00385 if (m_recList.empty())
00386 return;
00387
00388 ProgramList plist;
00389
00390 if (!m_recgroupList.contains(m_currentGroup))
00391 m_currentGroup = m_defaultGroup;
00392
00393 plist = m_recgroupList[m_currentGroup];
00394
00395 ProgramList::iterator pit = plist.begin();
00396 while (pit != plist.end())
00397 {
00398 ProgramInfo *pginfo = *pit;
00399 if (!pginfo)
00400 {
00401 ++pit;
00402 continue;
00403 }
00404
00405 QString state;
00406
00407 const RecStatusType recstatus = pginfo->GetRecordingStatus();
00408 if (recstatus == rsRecording ||
00409 recstatus == rsTuning ||
00410 recstatus == rsOtherRecording ||
00411 recstatus == rsOtherTuning)
00412 state = "running";
00413 else if (recstatus == rsConflict ||
00414 recstatus == rsOffLine ||
00415 recstatus == rsTunerBusy ||
00416 recstatus == rsFailed ||
00417 recstatus == rsAborted ||
00418 recstatus == rsMissed)
00419 state = "error";
00420 else if (recstatus == rsWillRecord ||
00421 recstatus == rsOtherShowing)
00422 {
00423 if ((m_curcard == 0 && m_curinput == 0) ||
00424 pginfo->GetCardID() == m_curcard ||
00425 pginfo->GetInputID() == m_curinput)
00426 {
00427 if (pginfo->GetRecordingPriority2() < 0)
00428 state = "warning";
00429 else
00430 state = "normal";
00431 }
00432 }
00433 else if (recstatus == rsRepeat ||
00434 recstatus == rsNeverRecord ||
00435 recstatus == rsDontRecord ||
00436 (recstatus != rsDontRecord &&
00437 recstatus <= rsEarlierShowing))
00438 state = "disabled";
00439 else
00440 state = "warning";
00441
00442 MythUIButtonListItem *item =
00443 new MythUIButtonListItem(m_schedulesList,"",
00444 qVariantFromValue(pginfo));
00445
00446 InfoMap infoMap;
00447 pginfo->ToMap(infoMap);
00448 item->SetTextFromMap(infoMap, state);
00449
00450 QString rating = QString::number(pginfo->GetStars(10));
00451 item->DisplayState(rating, "ratingstate");
00452 item->DisplayState(state, "status");
00453
00454 ++pit;
00455 }
00456
00457 MythUIText *statusText = dynamic_cast<MythUIText*>(GetChild("status"));
00458 if (statusText)
00459 {
00460 if (m_conflictBool)
00461 {
00462
00463 ProgramList::const_iterator it = plist.begin();
00464 for (; it != plist.end(); ++it)
00465 {
00466 ProgramInfo &p = **it;
00467 if (p.GetRecordingStatus() == rsConflict)
00468 {
00469 m_conflictDate = p.GetRecordingStartTime().date();
00470 break;
00471 }
00472 }
00473
00474
00475
00476 QString cstring = QString(tr("Conflict %1"))
00477 .arg(MythDateToString(m_conflictDate,
00478 kDateFull | kSimplify));
00479
00480 statusText->SetText(cstring);
00481 }
00482 else
00483 statusText->SetText(tr("No Conflicts"));
00484 }
00485
00486 MythUIText *filterText = dynamic_cast<MythUIText*>(GetChild("filter"));
00487 if (filterText)
00488 {
00489 if (m_showAll)
00490 filterText->SetText(tr("All"));
00491 else
00492 filterText->SetText(tr("Important"));
00493 }
00494 }
00495
00496 void ViewScheduled::updateInfo(MythUIButtonListItem *item)
00497 {
00498 if (!item)
00499 return;
00500
00501 ProgramInfo *pginfo = qVariantValue<ProgramInfo*> (item->GetData());
00502 if (pginfo)
00503 {
00504 InfoMap infoMap;
00505 pginfo->ToMap(infoMap);
00506 SetTextFromMap(infoMap);
00507
00508 MythUIStateType *ratingState = dynamic_cast<MythUIStateType*>
00509 (GetChild("ratingstate"));
00510 if (ratingState)
00511 {
00512 QString rating = QString::number(pginfo->GetStars(10));
00513 ratingState->DisplayState(rating);
00514 }
00515 }
00516 }
00517
00518 void ViewScheduled::edit()
00519 {
00520 MythUIButtonListItem *item = m_schedulesList->GetItemCurrent();
00521
00522 if (!item)
00523 return;
00524
00525 ProgramInfo *pginfo = qVariantValue<ProgramInfo*>(item->GetData());
00526 if (!pginfo)
00527 return;
00528
00529 EditScheduled(pginfo);
00530 }
00531
00532 void ViewScheduled::customEdit()
00533 {
00534 MythUIButtonListItem *item = m_schedulesList->GetItemCurrent();
00535
00536 if (!item)
00537 return;
00538
00539 ProgramInfo *pginfo = qVariantValue<ProgramInfo*>(item->GetData());
00540 EditCustom(pginfo);
00541 }
00542
00543 void ViewScheduled::deleteRule()
00544 {
00545 MythUIButtonListItem *item = m_schedulesList->GetItemCurrent();
00546
00547 if (!item)
00548 return;
00549
00550 ProgramInfo *pginfo = qVariantValue<ProgramInfo*>(item->GetData());
00551 if (!pginfo)
00552 return;
00553
00554 RecordingRule *record = new RecordingRule();
00555 if (!record->LoadByProgram(pginfo))
00556 {
00557 delete record;
00558 return;
00559 }
00560
00561 QString message = tr("Delete '%1' %2 rule?").arg(record->m_title)
00562 .arg(toString(pginfo->GetRecordingRuleType()));
00563
00564 MythScreenStack *popupStack = GetMythMainWindow()->GetStack("popup stack");
00565
00566 MythConfirmationDialog *okPopup = new MythConfirmationDialog(popupStack,
00567 message, true);
00568
00569 okPopup->SetReturnEvent(this, "deleterule");
00570 okPopup->SetData(qVariantFromValue(record));
00571
00572 if (okPopup->Create())
00573 popupStack->AddScreen(okPopup);
00574 else
00575 delete okPopup;
00576 }
00577
00578 void ViewScheduled::upcoming()
00579 {
00580 MythUIButtonListItem *item = m_schedulesList->GetItemCurrent();
00581 if (!item)
00582 return;
00583
00584 ProgramInfo *pginfo = qVariantValue<ProgramInfo*>(item->GetData());
00585
00586 ShowUpcoming(pginfo);
00587
00588
00589
00590 }
00591
00592 void ViewScheduled::upcomingScheduled()
00593 {
00594 MythUIButtonListItem *item = m_schedulesList->GetItemCurrent();
00595 if (!item)
00596 return;
00597
00598 ProgramInfo *pginfo = qVariantValue<ProgramInfo*>(item->GetData());
00599
00600 ShowUpcomingScheduled(pginfo);
00601
00602
00603
00604 }
00605
00606 void ViewScheduled::details()
00607 {
00608 MythUIButtonListItem *item = m_schedulesList->GetItemCurrent();
00609
00610 if (!item)
00611 return;
00612
00613 ProgramInfo *pginfo = qVariantValue<ProgramInfo*>(item->GetData());
00614 if (pginfo)
00615 ShowDetails(pginfo);
00616
00617 EmbedTVWindow();
00618 }
00619
00620 void ViewScheduled::selected(MythUIButtonListItem *item)
00621 {
00622 if (!item)
00623 return;
00624
00625 ProgramInfo *pginfo = qVariantValue<ProgramInfo*> (item->GetData());
00626 if (!pginfo)
00627 return;
00628
00629 EditRecording(pginfo);
00630 }
00631
00632 void ViewScheduled::setShowAll(bool all)
00633 {
00634 m_showAll = all;
00635 m_needFill = true;
00636 }
00637
00638 void ViewScheduled::viewCards()
00639 {
00640 m_curinput = 0;
00641 m_needFill = true;
00642
00643 m_curcard++;
00644 while (m_curcard <= m_maxcard)
00645 {
00646 if (m_cardref[m_curcard] > 0)
00647 return;
00648 m_curcard++;
00649 }
00650 m_curcard = 0;
00651 }
00652
00653 void ViewScheduled::viewInputs()
00654 {
00655 m_curcard = 0;
00656 m_needFill = true;
00657
00658 m_curinput++;
00659 while (m_curinput <= m_maxinput)
00660 {
00661 if (m_inputref[m_curinput] > 0)
00662 return;
00663 m_curinput++;
00664 }
00665 m_curinput = 0;
00666 }
00667
00668 void ViewScheduled::EmbedTVWindow(void)
00669 {
00670 if (m_player)
00671 m_player->StartEmbedding(QRect());
00672 }
00673
00674 void ViewScheduled::customEvent(QEvent *event)
00675 {
00676 if ((MythEvent::Type)(event->type()) == MythEvent::MythEventMessage)
00677 {
00678 MythEvent *me = (MythEvent *)event;
00679 QString message = me->Message();
00680
00681 if (message != "SCHEDULE_CHANGE")
00682 return;
00683
00684 m_needFill = true;
00685
00686 if (m_inEvent)
00687 return;
00688
00689 m_inEvent = true;
00690
00691 LoadList();
00692
00693 m_inEvent = false;
00694 }
00695 else if (event->type() == DialogCompletionEvent::kEventType)
00696 {
00697 DialogCompletionEvent *dce = (DialogCompletionEvent*)(event);
00698
00699 QString resultid = dce->GetId();
00700 QString resulttext = dce->GetResultText();
00701 int buttonnum = dce->GetResult();
00702
00703 if (resultid == "deleterule")
00704 {
00705 RecordingRule *record =
00706 qVariantValue<RecordingRule *>(dce->GetData());
00707 if (record)
00708 {
00709 if (buttonnum > 0)
00710 {
00711 if (!record->Delete())
00712 LOG(VB_GENERAL, LOG_ERR,
00713 "Failed to delete recording rule");
00714 }
00715 delete record;
00716 }
00717
00718 EmbedTVWindow();
00719 }
00720 else if (resultid == "menu")
00721 {
00722 if (resulttext == tr("Show Important"))
00723 {
00724 setShowAll(false);
00725 }
00726 else if (resulttext == tr("Show All"))
00727 {
00728 setShowAll(true);
00729 }
00730 else if (resulttext == tr("Program Details"))
00731 {
00732 details();
00733 }
00734 else if (resulttext == tr("Upcoming by title"))
00735 {
00736 upcoming();
00737 }
00738 else if (resulttext == tr("Upcoming scheduled"))
00739 {
00740 upcomingScheduled();
00741 }
00742 else if (resulttext == tr("Custom Edit"))
00743 {
00744 customEdit();
00745 }
00746 else if (resulttext == tr("Delete Rule"))
00747 {
00748 deleteRule();
00749 }
00750 else if (resulttext == tr("Show Cards"))
00751 {
00752 viewCards();
00753 }
00754 else if (resulttext == tr("Show Inputs"))
00755 {
00756 viewInputs();
00757 }
00758
00759 if (m_needFill)
00760 LoadList();
00761 }
00762 else
00763 ScheduleCommon::customEvent(event);
00764 }
00765 }