00001
00002 #include "channelrecpriority.h"
00003
00004 #include <algorithm>
00005 #include <vector>
00006 using namespace std;
00007
00008 #include "tv.h"
00009
00010 #include "mythcorecontext.h"
00011 #include "mythdb.h"
00012 #include "mythlogging.h"
00013 #include "scheduledrecording.h"
00014 #include "proglist.h"
00015 #include "dbchannelinfo.h"
00016
00017 #include "mythuihelper.h"
00018 #include "mythuitext.h"
00019 #include "mythuiimage.h"
00020 #include "mythuibuttonlist.h"
00021 #include "mythdialogbox.h"
00022 #include "mythmainwindow.h"
00023
00024 typedef struct RecPriorityInfo
00025 {
00026 ChannelInfo *chan;
00027 int cnt;
00028 } RecPriorityInfo;
00029
00030 class channelSort
00031 {
00032 public:
00033 bool operator()(const RecPriorityInfo &a, const RecPriorityInfo &b)
00034 {
00035 if (a.chan->chanstr.toInt() == b.chan->chanstr.toInt())
00036 return(a.chan->sourceid > b.chan->sourceid);
00037 return(a.chan->chanstr.toInt() > b.chan->chanstr.toInt());
00038 }
00039 };
00040
00041 class channelRecPrioritySort
00042 {
00043 public:
00044 bool operator()(const RecPriorityInfo &a, const RecPriorityInfo &b)
00045 {
00046 if (a.chan->recpriority.toInt() == b.chan->recpriority.toInt())
00047 return (a.chan->chanstr.toInt() > b.chan->chanstr.toInt());
00048 return (a.chan->recpriority.toInt() < b.chan->recpriority.toInt());
00049 }
00050 };
00051
00052 ChannelRecPriority::ChannelRecPriority(MythScreenStack *parent)
00053 : MythScreenType(parent, "ChannelRecPriority"),
00054 m_channelList(NULL), m_chanstringText(NULL),
00055 m_channameText(NULL), m_channumText(NULL),
00056 m_callsignText(NULL), m_sourcenameText(NULL),
00057 m_sourceidText(NULL), m_priorityText(NULL),
00058 m_iconImage(NULL)
00059 {
00060 m_sortType = (SortType)gCoreContext->GetNumSetting("ChannelRecPrioritySorting",
00061 (int)byChannel);
00062
00063 m_currentItem = NULL;
00064
00065 gCoreContext->addListener(this);
00066 }
00067
00068 ChannelRecPriority::~ChannelRecPriority()
00069 {
00070 saveRecPriority();
00071 gCoreContext->SaveSetting("ChannelRecPrioritySorting",
00072 (int)m_sortType);
00073 gCoreContext->removeListener(this);
00074 }
00075
00076 bool ChannelRecPriority::Create()
00077 {
00078 if (!LoadWindowFromXML("schedule-ui.xml", "channelrecpriority", this))
00079 return false;
00080
00081 m_channelList = dynamic_cast<MythUIButtonList *> (GetChild("channels"));
00082
00083 m_chanstringText = dynamic_cast<MythUIText *> (GetChild("chanstring"));
00084 m_priorityText = dynamic_cast<MythUIText *> (GetChild("priority"));
00085
00086 m_iconImage = dynamic_cast<MythUIImage *> (GetChild("icon"));
00087
00088 if (!m_channelList)
00089 {
00090 LOG(VB_GENERAL, LOG_ERR, "Theme is missing critical theme elements.");
00091 return false;
00092 }
00093
00094 connect(m_channelList, SIGNAL(itemSelected(MythUIButtonListItem*)),
00095 SLOT(updateInfo(MythUIButtonListItem*)));
00096
00097 FillList();
00098
00099 BuildFocusList();
00100
00101 return true;
00102 }
00103
00104 bool ChannelRecPriority::keyPressEvent(QKeyEvent *event)
00105 {
00106 if (GetFocusWidget()->keyPressEvent(event))
00107 return true;
00108
00109 bool handled = false;
00110 QStringList actions;
00111 handled = GetMythMainWindow()->TranslateKeyPress("TV Frontend", event, actions);
00112
00113 for (int i = 0; i < actions.size() && !handled; i++)
00114 {
00115 QString action = actions[i];
00116 handled = true;
00117
00118 if (action == "UPCOMING")
00119 upcoming();
00120 else if (action == "RANKINC")
00121 changeRecPriority(1);
00122 else if (action == "RANKDEC")
00123 changeRecPriority(-1);
00124 else if (action == "1")
00125 {
00126 if (m_sortType != byChannel)
00127 {
00128 m_sortType = byChannel;
00129 SortList();
00130 }
00131 }
00132 else if (action == "2")
00133 {
00134 if (m_sortType != byRecPriority)
00135 {
00136 m_sortType = byRecPriority;
00137 SortList();
00138 }
00139 }
00140 else if (action == "PREVVIEW" || action == "NEXTVIEW")
00141 {
00142 if (m_sortType == byChannel)
00143 m_sortType = byRecPriority;
00144 else
00145 m_sortType = byChannel;
00146 SortList();
00147 }
00148 else
00149 handled = false;
00150 }
00151
00152 if (!handled && MythScreenType::keyPressEvent(event))
00153 handled = true;
00154
00155 return handled;
00156 }
00157
00158 void ChannelRecPriority::ShowMenu()
00159 {
00160 MythUIButtonListItem *item = m_channelList->GetItemCurrent();
00161
00162 if (!item)
00163 return;
00164
00165 QString label = tr("Channel Options");
00166
00167 MythScreenStack *popupStack = GetMythMainWindow()->GetStack("popup stack");
00168
00169 MythDialogBox *menuPopup = new MythDialogBox(label, popupStack,
00170 "chanrecmenupopup");
00171
00172 if (!menuPopup->Create())
00173 {
00174 delete menuPopup;
00175 menuPopup = NULL;
00176 return;
00177 }
00178
00179 menuPopup->SetReturnEvent(this, "options");
00180
00181 menuPopup->AddButton(tr("Program List"));
00182
00183
00184 popupStack->AddScreen(menuPopup);
00185 }
00186
00187 void ChannelRecPriority::changeRecPriority(int howMuch)
00188 {
00189 MythUIButtonListItem *item = m_channelList->GetItemCurrent();
00190
00191 if (!item)
00192 return;
00193
00194 ChannelInfo *chanInfo = qVariantValue<ChannelInfo *>(item->GetData());
00195
00196
00197 int tempRecPriority = chanInfo->recpriority.toInt() + howMuch;
00198 if (tempRecPriority > -100 && tempRecPriority < 100)
00199 {
00200 chanInfo->recpriority = QString::number(tempRecPriority);
00201
00202
00203 if (m_sortType == byRecPriority)
00204 SortList();
00205 else
00206 {
00207 item->SetText(chanInfo->recpriority, "priority");
00208 updateInfo(item);
00209 }
00210 }
00211 }
00212
00213 void ChannelRecPriority::applyChannelRecPriorityChange(QString chanid,
00214 const QString &newrecpriority)
00215 {
00216 MSqlQuery query(MSqlQuery::InitCon());
00217 query.prepare("UPDATE channel SET recpriority = :RECPRI "
00218 "WHERE chanid = :CHANID ;");
00219 query.bindValue(":RECPRI", newrecpriority);
00220 query.bindValue(":CHANID", chanid);
00221
00222 if (!query.exec() || !query.isActive())
00223 MythDB::DBError("Save recpriority update", query);
00224 }
00225
00226 void ChannelRecPriority::saveRecPriority(void)
00227 {
00228 QMap<QString, ChannelInfo>::Iterator it;
00229
00230 for (it = m_channelData.begin(); it != m_channelData.end(); ++it)
00231 {
00232 ChannelInfo *chanInfo = &(*it);
00233 QString key = QString::number(chanInfo->chanid);
00234
00235
00236
00237 if (chanInfo->recpriority != m_origRecPriorityData[key])
00238 applyChannelRecPriorityChange(QString::number(chanInfo->chanid),
00239 chanInfo->recpriority);
00240 }
00241 ScheduledRecording::ReschedulePlace("SaveChannelPriority");
00242 }
00243
00244 void ChannelRecPriority::FillList(void)
00245 {
00246 QMap<int, QString> srcMap;
00247
00248 m_channelData.clear();
00249 m_sortedChannel.clear();
00250 m_visMap.clear();
00251
00252 MSqlQuery result(MSqlQuery::InitCon());
00253 result.prepare("SELECT sourceid, name FROM videosource;");
00254
00255 if (result.exec())
00256 {
00257 while (result.next())
00258 {
00259 srcMap[result.value(0).toInt()] = result.value(1).toString();
00260 }
00261 }
00262 result.prepare("SELECT chanid, channum, sourceid, callsign, "
00263 "icon, recpriority, name, visible FROM channel;");
00264
00265 if (result.exec())
00266 {
00267 int cnt = 999;
00268 while (result.next())
00269 {
00270 ChannelInfo *chaninfo = new ChannelInfo;
00271 chaninfo->chanid = result.value(0).toInt();
00272 chaninfo->chanstr = result.value(1).toString();
00273 chaninfo->sourceid = result.value(2).toInt();
00274 chaninfo->callsign = result.value(3).toString();
00275 chaninfo->iconpath = result.value(4).toString();
00276 chaninfo->recpriority = result.value(5).toString();
00277 chaninfo->channame = result.value(6).toString();
00278 if (result.value(7).toInt() > 0)
00279 m_visMap[chaninfo->chanid] = true;
00280 chaninfo->sourcename = srcMap[chaninfo->sourceid];
00281
00282 m_channelData[QString::number(cnt)] = *chaninfo;
00283
00284
00285
00286 m_origRecPriorityData[QString::number(chaninfo->chanid)] =
00287 chaninfo->recpriority;
00288
00289 cnt--;
00290 }
00291 }
00292 else if (!result.isActive())
00293 MythDB::DBError("Get channel recording priorities query", result);
00294
00295 SortList();
00296 }
00297
00298 void ChannelRecPriority::updateList()
00299 {
00300 m_channelList->Reset();
00301
00302 QMap<QString, ChannelInfo*>::Iterator it;
00303 MythUIButtonListItem *item;
00304 for (it = m_sortedChannel.begin(); it != m_sortedChannel.end(); ++it)
00305 {
00306 ChannelInfo *chanInfo = *it;
00307
00308 item = new MythUIButtonListItem(m_channelList, "",
00309 qVariantFromValue(chanInfo));
00310
00311 QString fontState = "default";
00312 if (!m_visMap[chanInfo->chanid])
00313 fontState = "disabled";
00314
00315 item->SetText(chanInfo->GetFormatted(ChannelInfo::kChannelLong),
00316 fontState);
00317
00318 InfoMap infomap;
00319 chanInfo->ToMap(infomap);
00320 item->SetTextFromMap(infomap, fontState);
00321
00322 if (m_visMap[chanInfo->chanid])
00323 item->DisplayState("normal", "status");
00324 else
00325 item->DisplayState("disabled", "status");
00326
00327 item->SetImage(chanInfo->iconpath, "icon");
00328 item->SetImage(chanInfo->iconpath);
00329
00330 item->SetText(chanInfo->recpriority, "priority", fontState);
00331
00332 if (m_currentItem == chanInfo)
00333 m_channelList->SetItemCurrent(item);
00334 }
00335
00336 MythUIText *norecordingText = dynamic_cast<MythUIText*>
00337 (GetChild("norecordings_info"));
00338
00339 if (norecordingText)
00340 norecordingText->SetVisible(m_channelData.isEmpty());
00341 }
00342
00343
00344 void ChannelRecPriority::SortList()
00345 {
00346 MythUIButtonListItem *item = m_channelList->GetItemCurrent();
00347
00348 if (item)
00349 {
00350 ChannelInfo *channelItem = qVariantValue<ChannelInfo *>(item->GetData());
00351 m_currentItem = channelItem;
00352 }
00353
00354 int i, j;
00355 vector<RecPriorityInfo> sortingList;
00356 QMap<QString, ChannelInfo>::iterator pit;
00357 vector<RecPriorityInfo>::iterator sit;
00358 ChannelInfo *chanInfo;
00359 RecPriorityInfo *recPriorityInfo;
00360
00361
00362 for (i = 0, pit = m_channelData.begin(); pit != m_channelData.end();
00363 ++pit, ++i)
00364 {
00365 chanInfo = &(*pit);
00366 RecPriorityInfo tmp = {chanInfo, i};
00367 sortingList.push_back(tmp);
00368 }
00369
00370 switch(m_sortType)
00371 {
00372 case byRecPriority:
00373 sort(sortingList.begin(), sortingList.end(),
00374 channelRecPrioritySort());
00375 break;
00376 case byChannel:
00377 default:
00378 sort(sortingList.begin(), sortingList.end(),
00379 channelSort());
00380 break;
00381 }
00382
00383 m_sortedChannel.clear();
00384
00385
00386 for (i = 0, sit = sortingList.begin(); sit != sortingList.end(); i++, ++sit)
00387 {
00388 recPriorityInfo = &(*sit);
00389
00390
00391 for (j = 0, pit = m_channelData.begin(); j !=recPriorityInfo->cnt; j++, ++pit);
00392
00393 m_sortedChannel[QString::number(999-i)] = &(*pit);
00394 }
00395
00396 updateList();
00397 }
00398
00399 void ChannelRecPriority::updateInfo(MythUIButtonListItem *item)
00400 {
00401 if (!item)
00402 return;
00403
00404 ChannelInfo *channelItem = qVariantValue<ChannelInfo *>(item->GetData());
00405 if (!m_channelData.isEmpty() && channelItem)
00406 {
00407 QString rectype;
00408 if (m_iconImage)
00409 {
00410 m_iconImage->SetFilename(channelItem->iconpath);
00411 m_iconImage->Load();
00412 }
00413
00414 InfoMap chanmap;
00415 channelItem->ToMap(chanmap);
00416 SetTextFromMap(chanmap);
00417
00418 if (m_chanstringText)
00419 m_chanstringText->SetText(channelItem->GetFormatted(ChannelInfo::kChannelLong));
00420 }
00421
00422 MythUIText *norecordingText = dynamic_cast<MythUIText*>
00423 (GetChild("norecordings_info"));
00424
00425 if (norecordingText)
00426 norecordingText->SetVisible(m_channelData.isEmpty());
00427 }
00428
00429 void ChannelRecPriority::upcoming()
00430 {
00431 MythUIButtonListItem *item = m_channelList->GetItemCurrent();
00432
00433 if (!item)
00434 return;
00435
00436 ChannelInfo *chanInfo = qVariantValue<ChannelInfo *>(item->GetData());
00437
00438 if (!chanInfo || chanInfo->chanid < 1)
00439 return;
00440
00441 QString chanID = QString("%1").arg(chanInfo->chanid);
00442 MythScreenStack *mainStack = GetMythMainWindow()->GetMainStack();
00443 ProgLister *pl = new ProgLister(mainStack, plChannel, chanID, "");
00444 if (pl->Create())
00445 mainStack->AddScreen(pl);
00446 else
00447 delete pl;
00448 }
00449
00450
00451 void ChannelRecPriority::customEvent(QEvent *event)
00452 {
00453 if (event->type() == DialogCompletionEvent::kEventType)
00454 {
00455 DialogCompletionEvent *dce = (DialogCompletionEvent*)(event);
00456
00457 QString resultid = dce->GetId();
00458 int buttonnum = dce->GetResult();
00459
00460 if (resultid == "options")
00461 {
00462 switch (buttonnum)
00463 {
00464 case 0:
00465 upcoming();
00466 break;
00467 }
00468 }
00469 }
00470 }
00471