00001
00002 #include "mythcorecontext.h"
00003 #include "mythlogging.h"
00004 #include "remoteutil.h"
00005 #include "recordinginfo.h"
00006
00007
00008 #include "mythuitext.h"
00009 #include "mythuibuttonlist.h"
00010 #include "mythmainwindow.h"
00011 #include "mythdialogbox.h"
00012
00013
00014 #include "scheduledrecording.h"
00015 #include "tv.h"
00016
00017
00018 #include "viewschedulediff.h"
00019
00020 ViewScheduleDiff::ViewScheduleDiff(MythScreenStack *parent, QString altTable,
00021 int recordidDiff, QString title)
00022 : MythScreenType(parent, "ViewScheduleDiff"),
00023 m_inEvent(false), m_inFill(false),
00024 m_altTable(altTable), m_title(title),
00025 m_conflictList(NULL), m_titleText(NULL),
00026 m_noChangesText(NULL), m_recordid(recordidDiff)
00027 {
00028 }
00029
00030 ViewScheduleDiff::~ViewScheduleDiff()
00031 {
00032 }
00033
00034 bool ViewScheduleDiff::Create()
00035 {
00036 if (!LoadWindowFromXML("schedule-ui.xml", "schedulediff", this))
00037 return false;
00038
00039 bool err = false;
00040 UIUtilE::Assign(this, m_conflictList, "conflictlist", &err);
00041
00042 UIUtilW::Assign(this, m_titleText, "titletext");
00043 UIUtilW::Assign(this, m_noChangesText, "nochanges");
00044
00045 if (err)
00046 {
00047 LOG(VB_GENERAL, LOG_ERR, "Cannot load screen 'schedulediff'");
00048 return false;
00049 }
00050
00051 connect(m_conflictList, SIGNAL(itemSelected(MythUIButtonListItem*)),
00052 SLOT(updateInfo(MythUIButtonListItem*)));
00053 connect(m_conflictList, SIGNAL(itemClicked(MythUIButtonListItem*)),
00054 SLOT(showStatus(MythUIButtonListItem*)));
00055
00056 if (m_titleText)
00057 m_titleText->SetText(m_title);
00058
00059 BuildFocusList();
00060 LoadInBackground();
00061
00062 return true;
00063 }
00064
00065 void ViewScheduleDiff::Load(void)
00066 {
00067 fillList();
00068 }
00069
00070 void ViewScheduleDiff::Init()
00071 {
00072 updateUIList();
00073 }
00074
00075 bool ViewScheduleDiff::keyPressEvent(QKeyEvent *e)
00076 {
00077 if (m_inEvent)
00078 return true;
00079
00080 m_inEvent = true;
00081
00082 bool handled = false;
00083 QStringList actions;
00084
00085 handled = GetMythMainWindow()->TranslateKeyPress("TV Frontend", e, actions);
00086
00087 if (!handled && MythScreenType::keyPressEvent(e))
00088 handled = true;
00089
00090 m_inEvent = false;
00091
00092 return handled;
00093 }
00094
00095 void ViewScheduleDiff::showStatus(MythUIButtonListItem *item)
00096 {
00097 ProgramInfo *pi = CurrentProgram();
00098 if (!pi)
00099 return;
00100
00101 QString timeFormat = gCoreContext->GetSetting("TimeFormat", "h:mm AP");
00102
00103 QString message = pi->toString(ProgramInfo::kTitleSubtitle, " - ");
00104 message += "\n\n";
00105 message += toDescription(pi->GetRecordingStatus(),
00106 pi->GetRecordingRuleType(),
00107 pi->GetRecordingStartTime());
00108
00109 if (pi->GetRecordingStatus() == rsConflict ||
00110 pi->GetRecordingStatus() == rsLaterShowing)
00111 {
00112 message += " " + QObject::tr("The following programs will be recorded "
00113 "instead:") + "\n\n";
00114
00115 ProgramList::const_iterator it = m_recListAfter.begin();
00116 for (; it != m_recListAfter.end(); ++it)
00117 {
00118 const ProgramInfo *pa = *it;
00119 if (pa->GetRecordingStartTime() >= pi->GetRecordingEndTime())
00120 break;
00121 if (pa->GetRecordingEndTime() > pi->GetRecordingStartTime() &&
00122 (pa->GetRecordingStatus() == rsWillRecord ||
00123 pa->GetRecordingStatus() == rsRecording))
00124 {
00125 message += QString("%1 - %2 %3\n")
00126 .arg(pa->GetRecordingStartTime().toString(timeFormat))
00127 .arg(pa->GetRecordingEndTime().toString(timeFormat))
00128 .arg(pa->toString(ProgramInfo::kTitleSubtitle, " - "));
00129 }
00130 }
00131 }
00132
00133 QString title = QObject::tr("Program Status");
00134 MythScreenStack *mainStack = GetMythMainWindow()->GetStack("main stack");
00135 MythDialogBox *dlg = new MythDialogBox(title, message, mainStack,
00136 "statusdialog", true);
00137
00138 if (dlg->Create())
00139 {
00140 dlg->AddButton(QObject::tr("OK"));
00141 mainStack->AddScreen(dlg);
00142 }
00143 else
00144 delete dlg;
00145 }
00146
00147 static int comp_recstart(const ProgramInfo *a, const ProgramInfo *b)
00148 {
00149 if (a->GetRecordingStartTime() != b->GetRecordingStartTime())
00150 {
00151 if (a->GetRecordingStartTime() > b->GetRecordingStartTime())
00152 return 1;
00153 else
00154 return -1;
00155 }
00156 if (a->GetRecordingEndTime() != b->GetRecordingEndTime())
00157 {
00158 if (a->GetRecordingEndTime() > b->GetRecordingEndTime())
00159 return 1;
00160 else
00161 return -1;
00162 }
00163 if (a->GetChannelSchedulingID() != b->GetChannelSchedulingID())
00164 {
00165 if (a->GetChannelSchedulingID() < b->GetChannelSchedulingID())
00166 return 1;
00167 else
00168 return -1;
00169 }
00170 if (a->GetRecordingPriority() != b->GetRecordingPriority() &&
00171 (a->GetRecordingStatus() == rsWillRecord ||
00172 b->GetRecordingStatus() == rsWillRecord))
00173 {
00174 if (a->GetRecordingPriority() < b->GetRecordingPriority())
00175 return 1;
00176 else
00177 return -1;
00178 }
00179 return 0;
00180 }
00181
00182 static bool comp_recstart_less_than(const ProgramInfo *a, const ProgramInfo *b)
00183 {
00184 return comp_recstart(a,b) < 0;
00185 }
00186
00187 void ViewScheduleDiff::fillList(void)
00188 {
00189 m_inFill = true;
00190
00191 QString callsign;
00192 QDateTime startts, recstartts;
00193 bool dummy;
00194
00195 LoadFromScheduler(m_recListBefore, dummy);
00196 LoadFromScheduler(m_recListAfter, dummy, m_altTable, m_recordid);
00197
00198 std::stable_sort(m_recListBefore.begin(), m_recListBefore.end(),
00199 comp_recstart_less_than);
00200 std::stable_sort(m_recListAfter.begin(), m_recListAfter.end(),
00201 comp_recstart_less_than);
00202
00203 QDateTime now = QDateTime::currentDateTime();
00204
00205 ProgramList::iterator it = m_recListBefore.begin();
00206 while (it != m_recListBefore.end())
00207 {
00208 if ((*it)->GetRecordingEndTime() >= now ||
00209 (*it)->GetScheduledEndTime() >= now)
00210 {
00211 ++it;
00212 }
00213 else
00214 {
00215 it = m_recListBefore.erase(it);
00216 }
00217 }
00218
00219 it = m_recListAfter.begin();
00220 while (it != m_recListAfter.end())
00221 {
00222 if ((*it)->GetRecordingEndTime() >= now ||
00223 (*it)->GetScheduledEndTime() >= now)
00224 {
00225 ++it;
00226 }
00227 else
00228 {
00229 it = m_recListAfter.erase(it);
00230 }
00231 }
00232
00233 ProgramList::iterator pb = m_recListBefore.begin();
00234 ProgramList::iterator pa = m_recListAfter.begin();
00235 ProgramStruct s;
00236
00237 m_recList.clear();
00238 while (pa != m_recListAfter.end() || pb != m_recListBefore.end())
00239 {
00240 s.before = (pb != m_recListBefore.end()) ? *pb : NULL;
00241 s.after = (pa != m_recListAfter.end()) ? *pa : NULL;
00242
00243 if (pa == m_recListAfter.end())
00244 {
00245 ++pb;
00246 }
00247 else if (pb == m_recListBefore.end())
00248 {
00249 ++pa;
00250 }
00251 else
00252 {
00253 switch (comp_recstart(*pb, *pa))
00254 {
00255 case 0:
00256 ++pb;
00257 ++pa;
00258 break;
00259 case -1:
00260 ++pb;
00261 s.after = NULL;
00262 break;
00263 case 1:
00264 s.before = NULL;
00265 ++pa;
00266 break;
00267 }
00268 }
00269
00270 if (s.before && s.after &&
00271 (s.before->GetCardID() == s.after->GetCardID()) &&
00272 (s.before->GetRecordingStatus() == s.after->GetRecordingStatus()))
00273 {
00274 continue;
00275 }
00276
00277 m_recList.push_back(s);
00278 }
00279
00280 m_inFill = false;
00281 }
00282
00283 void ViewScheduleDiff::updateUIList(void)
00284 {
00285 for (uint i = 0; i < m_recList.size(); i++)
00286 {
00287 class ProgramStruct s = m_recList[i];
00288 class ProgramInfo *pginfo = s.after;
00289 if (!pginfo)
00290 pginfo = s.before;
00291
00292 MythUIButtonListItem *item = new MythUIButtonListItem(
00293 m_conflictList, "", qVariantFromValue(pginfo));
00294
00295 InfoMap infoMap;
00296 pginfo->ToMap(infoMap);
00297
00298 QString state = toUIState(pginfo->GetRecordingStatus());
00299
00300 item->DisplayState(state, "status");
00301 item->SetTextFromMap(infoMap, state);
00302
00303 if (s.before)
00304 item->SetText(toString(s.before->GetRecordingStatus(),
00305 s.before->GetCardID()), "statusbefore",
00306 state);
00307 else
00308 item->SetText("-", "statusbefore");
00309
00310 if (s.after)
00311 item->SetText(toString(s.after->GetRecordingStatus(),
00312 s.after->GetCardID()), "statusafter",
00313 state);
00314 else
00315 item->SetText("-", "statusafter");
00316 }
00317
00318 if (m_noChangesText)
00319 {
00320 if (m_recList.empty())
00321 m_noChangesText->Show();
00322 else
00323 m_noChangesText->Hide();
00324 }
00325 }
00326
00327 void ViewScheduleDiff::updateInfo(MythUIButtonListItem *item)
00328 {
00329 if (!item)
00330 return;
00331
00332 ProgramInfo *pginfo = qVariantValue<ProgramInfo*> (item->GetData());
00333 if (pginfo)
00334 {
00335 InfoMap infoMap;
00336 pginfo->ToMap(infoMap);
00337 SetTextFromMap(infoMap);
00338 }
00339 }
00340
00341 ProgramInfo *ViewScheduleDiff::CurrentProgram()
00342 {
00343 int pos = m_conflictList->GetCurrentPos();
00344 if (pos >= (int)m_recList.size())
00345 return NULL;
00346
00347 ProgramStruct s = m_recList[pos];
00348
00349 if (s.after)
00350 return s.after;
00351 else
00352 return s.before;
00353 }