00001
00002
00003
00004
00005
00006
00007 #include <unistd.h>
00008 #include <cstdlib>
00009 #include <stdlib.h>
00010 #include <unistd.h>
00011 #include <iostream>
00012
00013 using namespace std;
00014
00015
00016 #include <qdir.h>
00017 #include <qdom.h>
00018
00019
00020 #include <mythtv/mythcontext.h>
00021 #include <mythtv/mythwidgets.h>
00022 #include <mythtv/libmythtv/programinfo.h>
00023 #include <mythtv/libmythtv/remoteutil.h>
00024
00025
00026 #include "recordingselector.h"
00027 #include "archiveutil.h"
00028
00029 RecordingSelector::RecordingSelector(MythMainWindow *parent, QString window_name,
00030 QString theme_filename, const char *name)
00031 : MythThemedDialog(parent, window_name, theme_filename, name, true)
00032 {
00033 recordingList = NULL;
00034 wireUpTheme();
00035 assignFirstFocus();
00036 updateForeground();
00037 popupMenu = NULL;
00038 }
00039
00040 RecordingSelector::~RecordingSelector(void)
00041 {
00042 if (recordingList)
00043 delete recordingList;
00044 }
00045
00046 void RecordingSelector::keyPressEvent(QKeyEvent *e)
00047 {
00048 bool handled = false;
00049 QStringList actions;
00050 gContext->GetMainWindow()->TranslateKeyPress("Archive", e, actions);
00051
00052 for (unsigned int i = 0; i < actions.size() && !handled; i++)
00053 {
00054 QString action = actions[i];
00055 handled = true;
00056
00057 if (action == "ESCAPE")
00058 {
00059 done(kDialogCodeRejected);
00060 }
00061 else if (action == "DOWN")
00062 {
00063 if (getCurrentFocusWidget() == recording_list)
00064 {
00065 recording_list->MoveDown(UIListBtnType::MoveItem);
00066 recording_list->refresh();
00067 }
00068 else
00069 nextPrevWidgetFocus(true);
00070 }
00071 else if (action == "UP")
00072 {
00073 if (getCurrentFocusWidget() == recording_list)
00074 {
00075 recording_list->MoveUp(UIListBtnType::MoveItem);
00076 recording_list->refresh();
00077 }
00078 else
00079 nextPrevWidgetFocus(false);
00080 }
00081 else if (action == "PAGEDOWN")
00082 {
00083 if (getCurrentFocusWidget() == recording_list)
00084 {
00085 recording_list->MoveDown(UIListBtnType::MovePage);
00086 recording_list->refresh();
00087 }
00088 }
00089 else if (action == "PAGEUP")
00090 {
00091 if (getCurrentFocusWidget() == recording_list)
00092 {
00093 recording_list->MoveUp(UIListBtnType::MovePage);
00094 recording_list->refresh();
00095 }
00096 }
00097 else if (action == "LEFT")
00098 {
00099 if (getCurrentFocusWidget() == category_selector)
00100 category_selector->push(false);
00101 else
00102 nextPrevWidgetFocus(false);
00103 }
00104 else if (action == "RIGHT")
00105 {
00106 if (getCurrentFocusWidget() == category_selector)
00107 category_selector->push(true);
00108 else
00109 nextPrevWidgetFocus(true);
00110 }
00111 else if (action == "SELECT")
00112 {
00113 if (getCurrentFocusWidget() == recording_list)
00114 toggleSelectedState();
00115 else
00116 activateCurrent();
00117 }
00118 else if (action == "MENU")
00119 {
00120 showMenu();
00121 }
00122 else
00123 handled = false;
00124 }
00125
00126 if (!handled)
00127 MythThemedDialog::keyPressEvent(e);
00128 }
00129
00130 void RecordingSelector::showMenu()
00131 {
00132 if (popupMenu)
00133 return;
00134
00135 popupMenu = new MythPopupBox(gContext->GetMainWindow(),
00136 "popupMenu");
00137
00138 QButton *button;
00139 button = popupMenu->addButton(tr("Clear All"), this, SLOT(clearAll()));
00140 button->setFocus();
00141 popupMenu->addButton(tr("Select All"), this, SLOT(selectAll()));
00142 popupMenu->addButton(tr("Cancel"), this, SLOT(closePopupMenu()));
00143
00144 popupMenu->ShowPopup(this, SLOT(closePopupMenu()));
00145 }
00146
00147 void RecordingSelector::closePopupMenu(void)
00148 {
00149 if (popupMenu)
00150 {
00151 popupMenu->deleteLater();
00152 popupMenu = NULL;
00153 }
00154 }
00155
00156 void RecordingSelector::selectAll()
00157 {
00158 if (!popupMenu)
00159 return;
00160
00161 selectedList.clear();
00162
00163 ProgramInfo *p;
00164 vector<ProgramInfo *>::iterator i = recordingList->begin();
00165 for ( ; i != recordingList->end(); i++)
00166 {
00167 p = *i;
00168 selectedList.append(p);
00169 }
00170
00171 updateRecordingList();
00172 closePopupMenu();
00173 }
00174
00175 void RecordingSelector::clearAll()
00176 {
00177 if (!popupMenu)
00178 return;
00179
00180 selectedList.clear();
00181
00182 updateRecordingList();
00183 closePopupMenu();
00184 }
00185
00186 void RecordingSelector::toggleSelectedState()
00187 {
00188 UIListBtnTypeItem *item = recording_list->GetItemCurrent();
00189 if (item->state() == UIListBtnTypeItem:: FullChecked)
00190 {
00191 if (selectedList.find((ProgramInfo *) item->getData()) != -1)
00192 selectedList.remove((ProgramInfo *) item->getData());
00193 item->setChecked(UIListBtnTypeItem:: NotChecked);
00194 }
00195 else
00196 {
00197 if (selectedList.find((ProgramInfo *) item->getData()) == -1)
00198 selectedList.append((ProgramInfo *) item->getData());
00199
00200 item->setChecked(UIListBtnTypeItem:: FullChecked);
00201 }
00202
00203 recording_list->refresh();
00204 }
00205
00206 void RecordingSelector::wireUpTheme()
00207 {
00208
00209 ok_button = getUITextButtonType("ok_button");
00210 if (ok_button)
00211 {
00212 ok_button->setText(tr("OK"));
00213 connect(ok_button, SIGNAL(pushed()), this, SLOT(OKPressed()));
00214 }
00215
00216
00217 cancel_button = getUITextButtonType("cancel_button");
00218 if (cancel_button)
00219 {
00220 cancel_button->setText(tr("Cancel"));
00221 connect(cancel_button, SIGNAL(pushed()), this, SLOT(cancelPressed()));
00222 }
00223
00224
00225 category_selector = getUISelectorType("category_selector");
00226 if (category_selector)
00227 {
00228 connect(category_selector, SIGNAL(pushed(int)),
00229 this, SLOT(setCategory(int)));
00230 }
00231
00232 title_text = getUITextType("progtitle");
00233 datetime_text = getUITextType("progdatetime");
00234 description_text = getUITextType("progdescription");
00235 filesize_text = getUITextType("filesize");
00236 preview_image = getUIImageType("preview_image");
00237 cutlist_image = getUIImageType("cutlist_image");
00238
00239
00240 recording_list = getUIListBtnType("recordinglist");
00241 if (recording_list)
00242 {
00243 getRecordingList();
00244 connect(recording_list, SIGNAL(itemSelected(UIListBtnTypeItem *)),
00245 this, SLOT(titleChanged(UIListBtnTypeItem *)));
00246 }
00247
00248 if (!ok_button || !cancel_button || !category_selector || !title_text || !datetime_text
00249 || !description_text || !filesize_text || !preview_image || !cutlist_image || !recording_list)
00250 {
00251 VERBOSE(VB_IMPORTANT, "One or more UI elements is missing from your theme - bailing out!");
00252 QTimer::singleShot(100, this, SLOT(cancelPressed()));
00253 return;
00254 }
00255
00256 updateSelectedList();
00257 updateRecordingList();
00258
00259 buildFocusList();
00260 }
00261
00262 void RecordingSelector::titleChanged(UIListBtnTypeItem *item)
00263 {
00264 ProgramInfo *p;
00265
00266 p = (ProgramInfo *) item->getData();
00267
00268 if (!p)
00269 return;
00270
00271 if (title_text)
00272 title_text->SetText(p->title);
00273
00274 if (datetime_text)
00275 datetime_text->SetText(p->startts.toString("dd MMM yy (hh:mm)"));
00276
00277 if (description_text)
00278 description_text->SetText(
00279 (p->subtitle != "" ? p->subtitle + "\n" : "") + p->description);
00280
00281 if (filesize_text)
00282 {
00283 filesize_text->SetText(formatSize(p->filesize / 1024));
00284 }
00285
00286 if (cutlist_image)
00287 {
00288 if (p->programflags & FL_CUTLIST)
00289 cutlist_image->show();
00290 else
00291 cutlist_image->hide();
00292 }
00293
00294 if (preview_image)
00295 {
00296
00297 if (QFile::exists(p->pathname + ".png"))
00298 {
00299 preview_image->SetImage(p->pathname + ".png");
00300 preview_image->LoadImage();
00301 }
00302 else
00303 {
00304 preview_image->SetImage("blank.png");
00305 preview_image->LoadImage();
00306 }
00307 }
00308
00309 buildFocusList();
00310 }
00311
00312 void RecordingSelector::OKPressed()
00313 {
00314
00315 MSqlQuery query(MSqlQuery::InitCon());
00316 query.prepare("DELETE FROM archiveitems WHERE type = 'Recording'");
00317 query.exec();
00318
00319
00320 ProgramInfo *p;
00321
00322 for (p = selectedList.first(); p; p = selectedList.next())
00323 {
00324 query.prepare("INSERT INTO archiveitems (type, title, subtitle,"
00325 "description, startdate, starttime, size, filename, hascutlist) "
00326 "VALUES(:TYPE, :TITLE, :SUBTITLE, :DESCRIPTION, :STARTDATE, "
00327 ":STARTTIME, :SIZE, :FILENAME, :HASCUTLIST);");
00328 query.bindValue(":TYPE", "Recording");
00329 query.bindValue(":TITLE", p->title.utf8());
00330 query.bindValue(":SUBTITLE", p->subtitle.utf8());
00331 query.bindValue(":DESCRIPTION", p->description.utf8());
00332 query.bindValue(":STARTDATE", p->startts.toString("dd MMM yy"));
00333 query.bindValue(":STARTTIME", p->startts.toString("(hh:mm)"));
00334 query.bindValue(":SIZE", p->filesize);
00335 query.bindValue(":FILENAME", p->GetPlaybackURL(false, true));
00336 query.bindValue(":HASCUTLIST", (p->programflags & FL_CUTLIST));
00337 if (!query.exec())
00338 MythContext::DBError("archive item insert", query);
00339 }
00340
00341 done(Accepted);
00342 }
00343
00344 void RecordingSelector::cancelPressed()
00345 {
00346 reject();
00347 }
00348
00349 void RecordingSelector::updateRecordingList(void)
00350 {
00351 if (!recordingList || recordingList->size() == 0)
00352 return;
00353
00354 recording_list->Reset();
00355
00356 if (category_selector)
00357 {
00358 ProgramInfo *p;
00359 vector<ProgramInfo *>::iterator i = recordingList->begin();
00360 for ( ; i != recordingList->end(); i++)
00361 {
00362 p = *i;
00363
00364 if (p->title == category_selector->getCurrentString() ||
00365 category_selector->getCurrentString() == tr("All Recordings"))
00366 {
00367 UIListBtnTypeItem* item = new UIListBtnTypeItem(recording_list,
00368 p->title + " ~ " +
00369 p->startts.toString("dd MMM yy (hh:mm)"));
00370 item->setCheckable(true);
00371 if (selectedList.find((ProgramInfo *) p) != -1)
00372 {
00373 item->setChecked(UIListBtnTypeItem::FullChecked);
00374 }
00375 else
00376 {
00377 item->setChecked(UIListBtnTypeItem::NotChecked);
00378 }
00379
00380 item->setData(p);
00381 }
00382 }
00383 }
00384
00385 recording_list->SetItemCurrent(recording_list->GetItemFirst());
00386 titleChanged(recording_list->GetItemCurrent());
00387 recording_list->refresh();
00388 }
00389
00390 void RecordingSelector::getRecordingList(void)
00391 {
00392 ProgramInfo *p;
00393 recordingList = RemoteGetRecordedList(true);
00394 QStringList categories;
00395
00396 if (recordingList && recordingList->size() > 0)
00397 {
00398 vector<ProgramInfo *>::iterator i = recordingList->begin();
00399 for ( ; i != recordingList->end(); i++)
00400 {
00401 p = *i;
00402
00403
00404 if (p->GetPlaybackURL(false, true).startsWith("myth://"))
00405 {
00406 VERBOSE(VB_IMPORTANT,
00407 QString("MythArchive cannot handle this file because it isn't available locally - %1")
00408 .arg(p->GetPlaybackURL(false, true)));
00409 recordingList->erase(i);
00410 i--;
00411 continue;
00412 }
00413
00414
00415 if (p->recgroup == "LiveTV" || p->recgroup == "Deleted")
00416 {
00417 recordingList->erase(i);
00418 i--;
00419 continue;
00420 }
00421
00422 if (categories.find(p->title) == categories.end())
00423 categories.append(p->title);
00424 }
00425 }
00426
00427 if (!recordingList || recordingList->size() == 0)
00428 {
00429 MythPopupBox::showOkPopup(gContext->GetMainWindow(), tr("MythArchive"),
00430 tr("Either you don't have any recordings or no recordings are available locally!\n\nClick OK"));
00431 QTimer::singleShot(100, this, SLOT(cancelPressed()));
00432 return;
00433 }
00434
00435
00436 categories.sort();
00437
00438 if (category_selector)
00439 {
00440 category_selector->addItem(0, tr("All Recordings"));
00441 category_selector->setToItem(0);
00442 }
00443
00444 for (uint x = 1; x <= categories.count(); x++)
00445 {
00446 if (category_selector)
00447 category_selector->addItem(x, categories[x-1]);
00448 }
00449
00450 setCategory(0);
00451 }
00452
00453 void RecordingSelector::setCategory(int item)
00454 {
00455 item = item;
00456 updateRecordingList();
00457 }
00458
00459 void RecordingSelector::updateSelectedList()
00460 {
00461 if (!recordingList)
00462 return;
00463
00464 selectedList.clear();
00465 MSqlQuery query(MSqlQuery::InitCon());
00466 query.prepare("SELECT filename FROM archiveitems WHERE type = 'Recording'");
00467 query.exec();
00468 if (query.isActive() && query.numRowsAffected())
00469 {
00470 while (query.next())
00471 {
00472 QString filename = QString::fromUtf8(query.value(0).toString());
00473
00474 ProgramInfo *p;
00475 vector<ProgramInfo *>::iterator i = recordingList->begin();
00476 for ( ; i != recordingList->end(); i++)
00477 {
00478 p = *i;
00479 if (p->GetPlaybackURL(false, true) == filename)
00480 {
00481 if (selectedList.find(p) == -1)
00482 selectedList.append(p);
00483 break;
00484 }
00485 }
00486 }
00487 }
00488 }
00489