MythTV  0.26-pre
recordingselector.cpp
Go to the documentation of this file.
00001 
00002 // c
00003 #include <cstdlib>
00004 #include <stdlib.h>
00005 #include <unistd.h>
00006 
00007 // qt
00008 #include <QDir>
00009 #include <QKeyEvent>
00010 #include <QTimer>
00011 #include <QApplication>
00012 
00013 // mythtv
00014 #include <mythcontext.h>
00015 #include <mythdb.h>
00016 #include <mthread.h>
00017 #include <programinfo.h>
00018 #include <remoteutil.h>
00019 #include <mythtimer.h>
00020 #include <mythuitext.h>
00021 #include <mythuibutton.h>
00022 #include <mythuiimage.h>
00023 #include <mythuibuttonlist.h>
00024 #include <mythmainwindow.h>
00025 #include <mythprogressdialog.h>
00026 #include <mythdialogbox.h>
00027 #include <mythlogging.h>
00028 #include <mythmiscutil.h>
00029 #include <netutils.h>
00030 
00031 // mytharchive
00032 #include "recordingselector.h"
00033 #include "archiveutil.h"
00034 
00035 class GetRecordingListThread : public MThread
00036 {
00037   public:
00038     GetRecordingListThread(RecordingSelector *parent) :
00039         MThread("GetRecordingList"), m_parent(parent)
00040     {
00041         start();
00042     }
00043 
00044     virtual void run(void)
00045     {
00046         RunProlog();
00047         m_parent->getRecordingList();
00048         RunEpilog();
00049     }
00050 
00051     RecordingSelector *m_parent;
00052 };
00053 
00054 RecordingSelector::RecordingSelector(
00055     MythScreenStack *parent, QList<ArchiveItem *> *archiveList) :
00056     MythScreenType(parent, "RecordingSelector"),
00057     m_archiveList(archiveList),
00058     m_recordingList(NULL),
00059     m_recordingButtonList(NULL),
00060     m_okButton(NULL),
00061     m_cancelButton(NULL),
00062     m_categorySelector(NULL),
00063     m_titleText(NULL),
00064     m_datetimeText(NULL),
00065     m_filesizeText(NULL),
00066     m_descriptionText(NULL),
00067     m_previewImage(NULL),
00068     m_cutlistImage(NULL)
00069 {
00070 }
00071 
00072 RecordingSelector::~RecordingSelector(void)
00073 {
00074     if (m_recordingList)
00075         delete m_recordingList;
00076 
00077     while (!m_selectedList.isEmpty())
00078         delete m_selectedList.takeFirst();
00079 }
00080 
00081 bool RecordingSelector::Create(void)
00082 {
00083     bool foundtheme = false;
00084 
00085     // Load the theme for this screen
00086     foundtheme = LoadWindowFromXML("mytharchive-ui.xml", "recording_selector", this);
00087 
00088     if (!foundtheme)
00089         return false;
00090 
00091     bool err = false;
00092     UIUtilE::Assign(this, m_okButton, "ok_button", &err);
00093     UIUtilE::Assign(this, m_cancelButton, "cancel_button", &err);
00094     UIUtilE::Assign(this, m_categorySelector, "category_selector", &err);
00095     UIUtilE::Assign(this, m_recordingButtonList, "recordinglist", &err);
00096 
00097     UIUtilW::Assign(this, m_titleText, "progtitle", &err);
00098     UIUtilW::Assign(this, m_datetimeText, "progdatetime", &err);
00099     UIUtilW::Assign(this, m_descriptionText, "progdescription", &err);
00100     UIUtilW::Assign(this, m_filesizeText, "filesize", &err);
00101     UIUtilW::Assign(this, m_previewImage, "preview_image", &err);
00102     UIUtilW::Assign(this, m_cutlistImage, "cutlist_image", &err);
00103 
00104     if (err)
00105     {
00106         LOG(VB_GENERAL, LOG_ERR, "Cannot load screen 'recording_selector'");
00107         return false;
00108     }
00109 
00110     connect(m_okButton, SIGNAL(Clicked()), this, SLOT(OKPressed()));
00111     connect(m_cancelButton, SIGNAL(Clicked()), this, SLOT(cancelPressed()));
00112 
00113     new MythUIButtonListItem(m_categorySelector, tr("All Recordings"));
00114     connect(m_categorySelector, SIGNAL(itemSelected(MythUIButtonListItem *)),
00115             this, SLOT(setCategory(MythUIButtonListItem *)));
00116 
00117     connect(m_recordingButtonList, SIGNAL(itemSelected(MythUIButtonListItem *)),
00118             this, SLOT(titleChanged(MythUIButtonListItem *)));
00119     connect(m_recordingButtonList, SIGNAL(itemClicked(MythUIButtonListItem *)),
00120             this, SLOT(toggleSelected(MythUIButtonListItem *)));
00121 
00122     if (m_cutlistImage)
00123         m_cutlistImage->Hide();
00124 
00125     BuildFocusList();
00126 
00127     SetFocusWidget(m_recordingButtonList);
00128 
00129     return true;
00130 }
00131 
00132 void RecordingSelector::Init(void)
00133 {
00134     QString message = tr("Retrieving Recording List.\nPlease Wait...");
00135 
00136     MythScreenStack *popupStack = GetMythMainWindow()->GetStack("popup stack");
00137 
00138     MythUIBusyDialog *busyPopup = new
00139             MythUIBusyDialog(message, popupStack, "recordingselectorbusydialog");
00140 
00141     if (busyPopup->Create())
00142         popupStack->AddScreen(busyPopup, false);
00143     else
00144     {
00145         delete busyPopup;
00146         busyPopup = NULL;
00147     }
00148 
00149     GetRecordingListThread *thread = new GetRecordingListThread(this);
00150     while (thread->isRunning())
00151     {
00152         qApp->processEvents();
00153         usleep(2000);
00154     }
00155 
00156     if (!m_recordingList || m_recordingList->empty())
00157     {
00158         ShowOkPopup(tr("Either you don't have any recordings or "
00159                        "no recordings are available locally!"));
00160         if (busyPopup)
00161             busyPopup->Close();
00162 
00163         Close();
00164         return;
00165     }
00166 
00167     updateCategorySelector();
00168     updateSelectedList();
00169     updateRecordingList();
00170 
00171     if (busyPopup)
00172         busyPopup->Close();
00173 }
00174 
00175 bool RecordingSelector::keyPressEvent(QKeyEvent *event)
00176 {
00177     if (GetFocusWidget()->keyPressEvent(event))
00178         return true;
00179 
00180     bool handled = false;
00181     QStringList actions;
00182     handled = GetMythMainWindow()->TranslateKeyPress("Global", event, actions);
00183 
00184     for (int i = 0; i < actions.size() && !handled; i++)
00185     {
00186         QString action = actions[i];
00187         handled = true;
00188 
00189         if (action == "MENU")
00190         {
00191             showMenu();
00192         }
00193         else
00194             handled = false;
00195     }
00196 
00197     if (!handled && MythScreenType::keyPressEvent(event))
00198         handled = true;
00199 
00200     return handled;
00201 }
00202 
00203 void RecordingSelector::showMenu()
00204 {
00205     MythScreenStack *popupStack = GetMythMainWindow()->GetStack("popup stack");
00206 
00207     MythDialogBox *menuPopup = new MythDialogBox(tr("Menu"), popupStack, "actionmenu");
00208 
00209     if (menuPopup->Create())
00210         popupStack->AddScreen(menuPopup);
00211 
00212     menuPopup->SetReturnEvent(this, "action");
00213 
00214     menuPopup->AddButton(tr("Clear All"), SLOT(clearAll()));
00215     menuPopup->AddButton(tr("Select All"), SLOT(selectAll()));
00216 }
00217 
00218 void RecordingSelector::selectAll()
00219 {
00220     while (!m_selectedList.isEmpty())
00221          m_selectedList.takeFirst();
00222     m_selectedList.clear();
00223 
00224     ProgramInfo *p;
00225     vector<ProgramInfo *>::iterator i = m_recordingList->begin();
00226     for ( ; i != m_recordingList->end(); ++i)
00227     {
00228         p = *i;
00229         m_selectedList.append(p);
00230     }
00231 
00232     updateRecordingList();
00233 }
00234 
00235 void RecordingSelector::clearAll()
00236 {
00237     while (!m_selectedList.isEmpty())
00238          m_selectedList.takeFirst();
00239     m_selectedList.clear();
00240 
00241     updateRecordingList();
00242 }
00243 
00244 void RecordingSelector::toggleSelected(MythUIButtonListItem *item)
00245 {
00246     if (item->state() == MythUIButtonListItem:: FullChecked)
00247     {
00248         int index = m_selectedList.indexOf(
00249                                 qVariantValue<ProgramInfo *>(item->GetData()));
00250         if (index != -1)
00251             m_selectedList.takeAt(index);
00252         item->setChecked(MythUIButtonListItem:: NotChecked);
00253     }
00254     else
00255     {
00256         int index = m_selectedList.indexOf(
00257                                 qVariantValue<ProgramInfo *>(item->GetData()));
00258         if (index == -1)
00259             m_selectedList.append(qVariantValue<ProgramInfo *>(item->GetData()));
00260 
00261         item->setChecked(MythUIButtonListItem::FullChecked);
00262     }
00263 }
00264 
00265 void RecordingSelector::titleChanged(MythUIButtonListItem *item)
00266 {
00267     ProgramInfo *p;
00268 
00269     p = qVariantValue<ProgramInfo *>(item->GetData());
00270 
00271     if (!p)
00272         return;
00273 
00274     if (m_titleText)
00275         m_titleText->SetText(p->GetTitle());
00276 
00277     if (m_datetimeText)
00278         m_datetimeText->SetText(p->GetScheduledStartTime()
00279                                 .toString("dd MMM yy (hh:mm)"));
00280 
00281     if (m_descriptionText)
00282     {
00283         m_descriptionText->SetText(
00284             ((!p->GetSubtitle().isEmpty()) ? p->GetSubtitle() + "\n" : "") +
00285             p->GetDescription());
00286     }
00287 
00288     if (m_filesizeText)
00289     {
00290         m_filesizeText->SetText(formatSize(p->GetFilesize() / 1024));
00291     }
00292 
00293     if (m_cutlistImage)
00294     {
00295         if (p->HasCutlist())
00296             m_cutlistImage->Show();
00297         else
00298             m_cutlistImage->Hide();
00299     }
00300 
00301     if (m_previewImage)
00302     {
00303         // try to locate a preview image
00304         if (QFile::exists(p->GetPathname() + ".png"))
00305         {
00306             m_previewImage->SetFilename(p->GetPathname() + ".png");
00307             m_previewImage->Load();
00308         }
00309         else
00310         {
00311             m_previewImage->SetFilename("blank.png");
00312             m_previewImage->Load();
00313         }
00314     }
00315 }
00316 
00317 void RecordingSelector::OKPressed()
00318 {
00319     // loop though selected recordings and add them to the list
00320     ProgramInfo *p;
00321     ArchiveItem *a;
00322 
00323     // remove any items that have been removed from the list
00324     QList<ArchiveItem *> tempAList;
00325     for (int x = 0; x < m_archiveList->size(); x++)
00326     {
00327         a = m_archiveList->at(x);
00328         bool found = false;
00329 
00330         for (int y = 0; y < m_selectedList.size(); y++)
00331         {
00332             p = m_selectedList.at(y);
00333             if (a->type != "Recording" || a->filename == p->GetPlaybackURL(false, true))
00334             {
00335                 found = true;
00336                 break;
00337             }
00338         }
00339 
00340         if (!found)
00341             tempAList.append(a);
00342     }
00343 
00344     for (int x = 0; x < tempAList.size(); x++)
00345         m_archiveList->removeAll(tempAList.at(x));
00346 
00347     // remove any items that are already in the list
00348     QList<ProgramInfo *> tempSList;
00349     for (int x = 0; x < m_selectedList.size(); x++)
00350     {
00351         p = m_selectedList.at(x);
00352 
00353         for (int y = 0; y < m_archiveList->size(); y++)
00354         {
00355             a = m_archiveList->at(y);
00356             if (a->filename == p->GetPlaybackURL(false, true))
00357             {
00358                 tempSList.append(p);
00359                 break;
00360             }
00361         }
00362     }
00363 
00364     for (int x = 0; x < tempSList.size(); x++)
00365         m_selectedList.removeAll(tempSList.at(x));
00366 
00367     // add all that are left
00368     for (int x = 0; x < m_selectedList.size(); x++)
00369     {
00370         p = m_selectedList.at(x);
00371         a = new ArchiveItem;
00372         a->type = "Recording";
00373         a->title = p->GetTitle();
00374         a->subtitle = p->GetSubtitle();
00375         a->description = p->GetDescription();
00376         a->startDate = p->GetScheduledStartTime().toString("dd MMM yy");
00377         a->startTime = p->GetScheduledStartTime().toString("(hh:mm)");
00378         a->size = p->GetFilesize();
00379         a->filename = p->GetPlaybackURL(false, true);
00380         a->hasCutlist = p->HasCutlist();
00381         a->useCutlist = false;
00382         a->duration = 0;
00383         a->cutDuration = 0;
00384         a->videoWidth = 0;
00385         a->videoHeight = 0;
00386         a->fileCodec = "";
00387         a->videoCodec = "";
00388         a->encoderProfile = NULL;
00389         a->editedDetails = false;
00390         m_archiveList->append(a);
00391     }
00392 
00393     emit haveResult(true);
00394     Close();
00395 }
00396 
00397 void RecordingSelector::cancelPressed()
00398 {
00399     emit haveResult(false);
00400     Close();
00401 }
00402 
00403 void RecordingSelector::updateRecordingList(void)
00404 {
00405     if (!m_recordingList || m_recordingList->empty())
00406         return;
00407 
00408     m_recordingButtonList->Reset();
00409 
00410     if (m_categorySelector)
00411     {
00412         ProgramInfo *p;
00413         vector<ProgramInfo *>::iterator i = m_recordingList->begin();
00414         for ( ; i != m_recordingList->end(); ++i)
00415         {
00416             p = *i;
00417 
00418             if (p->GetTitle() == m_categorySelector->GetValue() ||
00419                 m_categorySelector->GetValue() == tr("All Recordings"))
00420             {
00421                 MythUIButtonListItem* item = new MythUIButtonListItem(
00422                     m_recordingButtonList,
00423                     p->GetTitle() + " ~ " +
00424                     p->GetScheduledStartTime().toString("dd MMM yy (hh:mm)"));
00425                 item->setCheckable(true);
00426                 if (m_selectedList.indexOf((ProgramInfo *) p) != -1)
00427                 {
00428                     item->setChecked(MythUIButtonListItem::FullChecked);
00429                 }
00430                 else
00431                 {
00432                     item->setChecked(MythUIButtonListItem::NotChecked);
00433                 }
00434 
00435                 QString title = p->GetTitle();
00436                 QString subtitle = p->GetSubtitle();
00437 
00438                 QDateTime recstartts = p->GetScheduledStartTime();
00439                 QDateTime recendts   = p->GetScheduledEndTime();
00440 
00441                 QString timedate = QString("%1 - %2")
00442                                    .arg(MythDateTimeToString
00443                                         (recstartts, kDateTimeFull))
00444                                    .arg(MythDateTimeToString(recendts, kTime));
00445 
00446                 uint season = p->GetSeason();
00447                 uint episode = p->GetEpisode();
00448                 QString seasone, seasonx;
00449 
00450                 if (season && episode)
00451                 {
00452                     seasone = QString("s%1e%2")
00453                                 .arg(GetDisplaySeasonEpisode(season, 2))
00454                                 .arg(GetDisplaySeasonEpisode(episode, 2));
00455                     seasonx = QString("%1x%2")
00456                               .arg(GetDisplaySeasonEpisode(season, 1))
00457                               .arg(GetDisplaySeasonEpisode(episode, 2));
00458                 }
00459 
00460                 item->SetText(title, "title");
00461                 item->SetText(subtitle, "subtitle");
00462                 if (subtitle.isEmpty())
00463                     item->SetText(title, "titlesubtitle");
00464                 else
00465                     item->SetText(title + " - \"" + subtitle + '"',
00466                                   "titlesubtitle");
00467 
00468                 item->SetText(timedate, "timedate");
00469                 item->SetText(p->GetDescription(), "description");
00470                 item->SetText(formatSize(p->GetFilesize() / 1024),
00471                               "filesize_str");
00472 
00473                 item->SetText(QString::number(season), "season");
00474                 item->SetText(QString::number(episode), "episode");
00475                 item->SetText(seasonx, "00x00");
00476                 item->SetText(seasone, "s00e00");
00477 
00478                 item->DisplayState(p->HasCutlist() ? "yes" : "no", "cutlist");
00479 
00480                 item->SetData(qVariantFromValue(p));
00481             }
00482             qApp->processEvents();
00483         }
00484     }
00485 
00486     m_recordingButtonList->SetItemCurrent(m_recordingButtonList->GetItemFirst());
00487     titleChanged(m_recordingButtonList->GetItemCurrent());
00488 }
00489 
00490 void RecordingSelector::getRecordingList(void)
00491 {
00492     ProgramInfo *p;
00493     m_recordingList = RemoteGetRecordedList(-1);
00494     m_categories.clear();
00495 
00496     if (m_recordingList && !m_recordingList->empty())
00497     {
00498         vector<ProgramInfo *>::iterator i = m_recordingList->begin();
00499         for ( ; i != m_recordingList->end(); ++i)
00500         {
00501             p = *i;
00502             // ignore live tv and deleted recordings
00503             if (p->GetRecordingGroup() == "LiveTV" ||
00504                 p->GetRecordingGroup() == "Deleted")
00505             {
00506                 i = m_recordingList->erase(i);
00507                 --i;
00508                 continue;
00509             }
00510 
00511             if (m_categories.indexOf(p->GetTitle()) == -1)
00512                 m_categories.append(p->GetTitle());
00513         }
00514     }
00515 }
00516 
00517 void RecordingSelector::updateCategorySelector(void)
00518 {
00519     // sort and add categories to selector
00520     m_categories.sort();
00521 
00522     if (m_categorySelector)
00523     {
00524         new MythUIButtonListItem(m_categorySelector, tr("All Recordings"));
00525         m_categorySelector->SetItemCurrent(0);
00526 
00527         for (int x = 0; x < m_categories.count(); x++)
00528         {
00529             new MythUIButtonListItem(m_categorySelector, m_categories[x]);
00530         }
00531     }
00532 }
00533 
00534 void RecordingSelector::setCategory(MythUIButtonListItem *item)
00535 {
00536     (void)item;
00537     updateRecordingList();
00538 }
00539 
00540 void RecordingSelector::updateSelectedList()
00541 {
00542     if (!m_recordingList)
00543         return;
00544 
00545     m_selectedList.clear();
00546 
00547     ProgramInfo *p;
00548     ArchiveItem *a;
00549     for (int x = 0; x < m_archiveList->size(); x++)
00550     {
00551         a = m_archiveList->at(x);
00552         for (uint y = 0; y < m_recordingList->size(); y++)
00553         {
00554             p = m_recordingList->at(y);
00555             if (p->GetPlaybackURL(false, true) == a->filename)
00556             {
00557                 if (m_selectedList.indexOf(p) == -1)
00558                     m_selectedList.append(p);
00559                 break;
00560             }
00561 
00562             qApp->processEvents();
00563         }
00564     }
00565 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends