MythTV  0.26-pre
channelrecpriority.cpp
Go to the documentation of this file.
00001 
00002 #include "channelrecpriority.h"
00003 
00004 #include <algorithm> // For std::sort()
00005 #include <vector> // For std::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")); // Deprecated, use mapped text
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     //menuPopup->AddButton(tr("Reset All Priorities"));
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     // inc/dec recording priority
00197     int tempRecPriority = chanInfo->recpriority.toInt() + howMuch;
00198     if (tempRecPriority > -100 && tempRecPriority < 100)
00199     {
00200         chanInfo->recpriority = QString::number(tempRecPriority);
00201 
00202         // order may change if sorting by recoring priority, so resort
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         // if this channel's recording priority changed from when we entered
00236         // save new value out to db
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             // save recording priority value in map so we don't have to save
00285             // all channel's recording priority values when we exit
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     // copy m_channelData into sortingList
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     // rebuild m_channelData in sortingList order from m_sortedChannel
00386     for (i = 0, sit = sortingList.begin(); sit != sortingList.end(); i++, ++sit)
00387     {
00388         recPriorityInfo = &(*sit);
00389 
00390         // find recPriorityInfo[i] in m_sortedChannel
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 
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends