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/mythdbcon.h>
00023
00024
00025 #include "videoselector.h"
00026 #include "archiveutil.h"
00027
00028 VideoSelector::VideoSelector(MythMainWindow *parent, QString window_name,
00029 QString theme_filename, const char *name)
00030 : MythThemedDialog(parent, window_name, theme_filename, name, true)
00031 {
00032 currentParentalLevel = 1;
00033 videoList = NULL;
00034 wireUpTheme();
00035 assignFirstFocus();
00036 updateForeground();
00037 }
00038
00039 VideoSelector::~VideoSelector(void)
00040 {
00041 if (videoList)
00042 delete videoList;
00043 }
00044
00045 void VideoSelector::keyPressEvent(QKeyEvent *e)
00046 {
00047 bool handled = false;
00048 QStringList actions;
00049 gContext->GetMainWindow()->TranslateKeyPress("Burn", e, actions);
00050
00051 for (unsigned int i = 0; i < actions.size() && !handled; i++)
00052 {
00053 QString action = actions[i];
00054 handled = true;
00055
00056 if (action == "ESCAPE")
00057 {
00058 reject();
00059 }
00060 else if (action == "DOWN")
00061 {
00062 if (getCurrentFocusWidget() == video_list)
00063 {
00064 video_list->MoveDown(UIListBtnType::MoveItem);
00065 video_list->refresh();
00066 }
00067 else
00068 nextPrevWidgetFocus(true);
00069 }
00070 else if (action == "UP")
00071 {
00072 if (getCurrentFocusWidget() == video_list)
00073 {
00074 video_list->MoveUp(UIListBtnType::MoveItem);
00075 video_list->refresh();
00076 }
00077 else
00078 nextPrevWidgetFocus(false);
00079 }
00080 else if (action == "PAGEDOWN")
00081 {
00082 if (getCurrentFocusWidget() == video_list)
00083 {
00084 video_list->MoveDown(UIListBtnType::MovePage);
00085 video_list->refresh();
00086 }
00087 }
00088 else if (action == "PAGEUP")
00089 {
00090 if (getCurrentFocusWidget() == video_list)
00091 {
00092 video_list->MoveUp(UIListBtnType::MovePage);
00093 video_list->refresh();
00094 }
00095 }
00096 else if (action == "LEFT")
00097 {
00098 if (getCurrentFocusWidget() == category_selector)
00099 category_selector->push(false);
00100 else
00101 nextPrevWidgetFocus(false);
00102 }
00103 else if (action == "RIGHT")
00104 {
00105 if (getCurrentFocusWidget() == category_selector)
00106 category_selector->push(true);
00107 else
00108 nextPrevWidgetFocus(true);
00109 }
00110 else if (action == "SELECT")
00111 {
00112 if (getCurrentFocusWidget() == video_list)
00113 toggleSelectedState();
00114 else
00115 activateCurrent();
00116 }
00117 else if (action == "MENU")
00118 {
00119 showMenu();
00120 }
00121 else if (action == "1")
00122 {
00123 setParentalLevel(1);
00124 }
00125 else if (action == "2")
00126 {
00127 setParentalLevel(2);
00128 }
00129 else if (action == "3")
00130 {
00131 setParentalLevel(3);
00132 }
00133 else if (action == "4")
00134 {
00135 setParentalLevel(4);
00136 }
00137 else
00138 handled = false;
00139 }
00140
00141 if (!handled)
00142 MythThemedDialog::keyPressEvent(e);
00143 }
00144
00145 void VideoSelector::showMenu()
00146 {
00147 if (popupMenu)
00148 return;
00149
00150 popupMenu = new MythPopupBox(gContext->GetMainWindow(),
00151 "popupMenu");
00152
00153 QButton *button;
00154 button = popupMenu->addButton(tr("Clear All"), this, SLOT(clearAll()));
00155 button->setFocus();
00156 popupMenu->addButton(tr("Select All"), this, SLOT(selectAll()));
00157 popupMenu->addButton(tr("Cancel"), this, SLOT(closePopupMenu()));
00158
00159 popupMenu->ShowPopup(this, SLOT(closePopupMenu()));
00160 }
00161
00162 void VideoSelector::closePopupMenu()
00163 {
00164 if (!popupMenu)
00165 return;
00166
00167 popupMenu->deleteLater();
00168 popupMenu = NULL;
00169 }
00170
00171 void VideoSelector::selectAll()
00172 {
00173 if (!popupMenu)
00174 return;
00175
00176 selectedList.clear();
00177
00178 VideoInfo *v;
00179 vector<VideoInfo *>::iterator i = videoList->begin();
00180 for ( ; i != videoList->end(); i++)
00181 {
00182 v = *i;
00183 selectedList.append(v);
00184 }
00185
00186 updateVideoList();
00187 closePopupMenu();
00188 }
00189
00190 void VideoSelector::clearAll()
00191 {
00192 if (!popupMenu)
00193 return;
00194
00195 selectedList.clear();
00196
00197 updateVideoList();
00198 closePopupMenu();
00199 }
00200
00201 void VideoSelector::toggleSelectedState()
00202 {
00203 UIListBtnTypeItem *item = video_list->GetItemCurrent();
00204
00205 if (!item)
00206 return;
00207
00208 if (item->state() == UIListBtnTypeItem:: FullChecked)
00209 {
00210 if (selectedList.find((VideoInfo *) item->getData()) != -1)
00211 selectedList.remove((VideoInfo *) item->getData());
00212 item->setChecked(UIListBtnTypeItem:: NotChecked);
00213 }
00214 else
00215 {
00216 if (selectedList.find((VideoInfo *) item->getData()) == -1)
00217 selectedList.append((VideoInfo *) item->getData());
00218
00219 item->setChecked(UIListBtnTypeItem:: FullChecked);
00220 }
00221
00222 video_list->refresh();
00223 }
00224
00225 void VideoSelector::wireUpTheme()
00226 {
00227
00228 ok_button = getUITextButtonType("ok_button");
00229 if (ok_button)
00230 {
00231 ok_button->setText(tr("OK"));
00232 connect(ok_button, SIGNAL(pushed()), this, SLOT(OKPressed()));
00233 }
00234
00235
00236 cancel_button = getUITextButtonType("cancel_button");
00237 if (cancel_button)
00238 {
00239 cancel_button->setText(tr("Cancel"));
00240 connect(cancel_button, SIGNAL(pushed()), this, SLOT(cancelPressed()));
00241 }
00242
00243
00244 category_selector = getUISelectorType("category_selector");
00245 if (category_selector)
00246 {
00247 connect(category_selector, SIGNAL(pushed(int)),
00248 this, SLOT(setCategory(int)));
00249 }
00250
00251 title_text = getUITextType("videotitle");
00252 plot_text = getUITextType("videoplot");
00253 filesize_text = getUITextType("filesize");
00254 cover_image = getUIImageType("cover_image");
00255 warning_text = getUITextType("warning_text");
00256 pl_text = getUITextType("parentallevel_text");
00257
00258 video_list = getUIListBtnType("videolist");
00259 if (video_list)
00260 {
00261 getVideoList();
00262 connect(video_list, SIGNAL(itemSelected(UIListBtnTypeItem *)),
00263 this, SLOT(titleChanged(UIListBtnTypeItem *)));
00264 }
00265
00266 updateSelectedList();
00267 updateVideoList();
00268 buildFocusList();
00269 }
00270
00271 void VideoSelector::titleChanged(UIListBtnTypeItem *item)
00272 {
00273 VideoInfo *v;
00274
00275 v = (VideoInfo *) item->getData();
00276
00277 if (!v)
00278 return;
00279
00280 if (title_text)
00281 title_text->SetText(v->title);
00282
00283 if (plot_text)
00284 plot_text->SetText(v->plot);
00285
00286 if (cover_image)
00287 {
00288 if (v->coverfile != "" && v->coverfile != "No Cover")
00289 {
00290 cover_image->SetImage(v->coverfile);
00291 cover_image->LoadImage();
00292 }
00293 else
00294 {
00295 cover_image->SetImage("blank.png");
00296 cover_image->LoadImage();
00297 }
00298 }
00299
00300 if (filesize_text)
00301 {
00302 if (v->size == 0)
00303 {
00304 QFile file(v->filename);
00305 if (file.exists())
00306 v->size = (unsigned long long)file.size();
00307 else
00308 cout << "VideoSelector: Cannot find file: " << v->filename << endl;
00309 }
00310
00311 filesize_text->SetText(formatSize(v->size / 1024));
00312 }
00313
00314 buildFocusList();
00315 }
00316
00317 void VideoSelector::OKPressed()
00318 {
00319
00320 MSqlQuery query(MSqlQuery::InitCon());
00321 query.prepare("DELETE FROM archiveitems WHERE type = 'Video'");
00322 query.exec();
00323
00324
00325 VideoInfo *v;
00326
00327 for (v = selectedList.first(); v; v = selectedList.next())
00328 {
00329 QFile file(v->filename);
00330 if (file.exists())
00331 {
00332 query.prepare("INSERT INTO archiveitems (type, title, subtitle, "
00333 "description, startdate, starttime, size, filename, hascutlist) "
00334 "VALUES(:TYPE, :TITLE, :SUBTITLE, :DESCRIPTION, :STARTDATE, "
00335 ":STARTTIME, :SIZE, :FILENAME, :HASCUTLIST);");
00336 query.bindValue(":TYPE", "Video");
00337 query.bindValue(":TITLE", v->title.utf8());
00338 query.bindValue(":SUBTITLE", "");
00339 query.bindValue(":DESCRIPTION", v->plot.utf8());
00340 query.bindValue(":STARTDATE", "");
00341 query.bindValue(":STARTTIME", "");
00342 query.bindValue(":SIZE", (long long)file.size());
00343 query.bindValue(":FILENAME", v->filename);
00344 query.bindValue(":HASCUTLIST", 0);
00345 if (!query.exec())
00346 MythContext::DBError("archive item insert", query);
00347 }
00348 }
00349
00350 done(Accepted);
00351 }
00352
00353 void VideoSelector::cancelPressed()
00354 {
00355 reject();
00356 }
00357
00358 void VideoSelector::updateVideoList(void)
00359 {
00360 if (!videoList)
00361 return;
00362
00363 video_list->Reset();
00364
00365 if (category_selector)
00366 {
00367 VideoInfo *v;
00368 vector<VideoInfo *>::iterator i = videoList->begin();
00369 for ( ; i != videoList->end(); i++)
00370 {
00371 v = *i;
00372
00373 if (v->category == category_selector->getCurrentString() ||
00374 category_selector->getCurrentString() == tr("All Videos"))
00375 {
00376 if (v->parentalLevel <= currentParentalLevel)
00377 {
00378 UIListBtnTypeItem* item = new UIListBtnTypeItem(
00379 video_list, v->title);
00380 item->setCheckable(true);
00381 if (selectedList.find((VideoInfo *) v) != -1)
00382 {
00383 item->setChecked(UIListBtnTypeItem::FullChecked);
00384 }
00385 else
00386 {
00387 item->setChecked(UIListBtnTypeItem::NotChecked);
00388 }
00389
00390 item->setData(v);
00391 }
00392 }
00393 }
00394 }
00395
00396 if (video_list->GetCount() > 0)
00397 {
00398 video_list->SetItemCurrent(video_list->GetItemFirst());
00399 titleChanged(video_list->GetItemCurrent());
00400 warning_text->hide();
00401 }
00402 else
00403 {
00404 warning_text->show();
00405 title_text->SetText("");
00406 plot_text->SetText("");
00407 cover_image->SetImage("blank.png");
00408 cover_image->LoadImage();
00409 filesize_text->SetText("");
00410 }
00411
00412 video_list->refresh();
00413 }
00414
00415 vector<VideoInfo *> *VideoSelector::getVideoListFromDB(void)
00416 {
00417
00418 typedef QMap<int, QString> CategoryMap;
00419 CategoryMap categoryMap;
00420 MSqlQuery query(MSqlQuery::InitCon());
00421 query.prepare("SELECT intid, category FROM videocategory");
00422 query.exec();
00423 if (query.isActive() && query.numRowsAffected())
00424 {
00425 while (query.next())
00426 {
00427 int id = query.value(0).toInt();
00428 QString category = QString::fromUtf8(query.value(1).toString());
00429 categoryMap.insert(id, category);
00430 }
00431 }
00432
00433 vector<VideoInfo*> *videoList = new vector<VideoInfo*>;
00434
00435 query.prepare("SELECT intid, title, plot, length, filename, coverfile, "
00436 "category, showlevel "
00437 "FROM videometadata ORDER BY title");
00438 query.exec();
00439 if (query.isActive() && query.numRowsAffected())
00440 {
00441 QString artist, genre;
00442 while (query.next())
00443 {
00444 VideoInfo *info = new VideoInfo;
00445
00446 info->id = query.value(0).toInt();
00447 info->title = QString::fromUtf8(query.value(1).toString());
00448 info->plot = QString::fromUtf8(query.value(2).toString());
00449 info->size = 0;
00450 info->filename = QString::fromUtf8(query.value(4).toString());
00451 info->coverfile = QString::fromUtf8(query.value(5).toString());
00452 info->category = categoryMap[query.value(6).toInt()];
00453 info->parentalLevel = query.value(7).toInt();
00454 if (info->category == "")
00455 info->category = "(None)";
00456 videoList->push_back(info);
00457 }
00458 }
00459 else
00460 {
00461 cout << "VideoSelector: Failed to get any video's" << endl;
00462 return NULL;
00463 }
00464
00465 return videoList;
00466 }
00467
00468 void VideoSelector::getVideoList(void)
00469 {
00470 VideoInfo *v;
00471 videoList = getVideoListFromDB();
00472 QStringList categories;
00473
00474 if (videoList && videoList->size() > 0)
00475 {
00476 vector<VideoInfo *>::iterator i = videoList->begin();
00477 for ( ; i != videoList->end(); i++)
00478 {
00479 v = *i;
00480
00481 if (categories.find(v->category) == categories.end())
00482 categories.append(v->category);
00483 }
00484 }
00485 else
00486 {
00487 MythPopupBox::showOkPopup(gContext->GetMainWindow(), tr("Video Selector"),
00488 tr("You don't have any videos!\n\nClick OK"));
00489 QTimer::singleShot(100, this, SLOT(cancelPressed()));
00490 return;
00491 }
00492
00493
00494 categories.sort();
00495
00496 if (category_selector)
00497 {
00498 category_selector->addItem(0, tr("All Videos"));
00499 category_selector->setToItem(0);
00500 }
00501
00502 for (uint x = 1; x <= categories.count(); x++)
00503 {
00504 if (category_selector)
00505 category_selector->addItem(x, categories[x-1]);
00506 }
00507
00508 setCategory(0);
00509 }
00510
00511 void VideoSelector::setCategory(int item)
00512 {
00513 (void) item;
00514 updateVideoList();
00515 }
00516
00517 void VideoSelector::updateSelectedList()
00518 {
00519 if (!videoList)
00520 return;
00521
00522 selectedList.clear();
00523 MSqlQuery query(MSqlQuery::InitCon());
00524 query.prepare("SELECT filename FROM archiveitems WHERE type = 'Video'");
00525 query.exec();
00526 if (query.isActive() && query.numRowsAffected())
00527 {
00528 while (query.next())
00529 {
00530 QString filename = QString::fromUtf8(query.value(0).toString());
00531
00532 VideoInfo *v;
00533 vector<VideoInfo *>::iterator i = videoList->begin();
00534 for ( ; i != videoList->end(); i++)
00535 {
00536 v = *i;
00537 if (v->filename == filename)
00538 {
00539 if (selectedList.find(v) == -1)
00540 selectedList.append(v);
00541 break;
00542 }
00543 }
00544 }
00545 }
00546 }
00547
00548 void VideoSelector::setParentalLevel(int which_level)
00549 {
00550 if (which_level < 1)
00551 which_level = 1;
00552
00553 if (which_level > 4)
00554 which_level = 4;
00555
00556 if ((which_level > currentParentalLevel) && !checkParentPassword())
00557 which_level = currentParentalLevel;
00558
00559
00560 if (currentParentalLevel != which_level)
00561 {
00562 currentParentalLevel = which_level;
00563 updateVideoList();
00564 pl_text->SetText(QString::number(which_level));
00565 }
00566 }
00567
00568 bool VideoSelector::checkParentPassword()
00569 {
00570 QDateTime curr_time = QDateTime::currentDateTime();
00571 QString last_time_stamp = gContext->GetSetting("VideoPasswordTime");
00572 QString password = gContext->GetSetting("VideoAdminPassword");
00573 if (password.length() < 1)
00574 {
00575 return true;
00576 }
00577
00578
00579 if (last_time_stamp.length() < 1)
00580 {
00581
00582 }
00583 else
00584 {
00585 QDateTime last_time = QDateTime::fromString(last_time_stamp, Qt::TextDate);
00586 if (last_time.secsTo(curr_time) < 120)
00587 {
00588
00589 last_time_stamp = curr_time.toString(Qt::TextDate);
00590 gContext->SetSetting("VideoPasswordTime", last_time_stamp);
00591 gContext->SaveSetting("VideoPasswordTime", last_time_stamp);
00592 return true;
00593 }
00594 }
00595
00596
00597 if (password.length() > 0)
00598 {
00599 bool ok = false;
00600 MythPasswordDialog *pwd = new MythPasswordDialog(tr("Parental Pin:"),
00601 &ok,
00602 password,
00603 gContext->GetMainWindow());
00604 pwd->exec();
00605 pwd->deleteLater();
00606 if (ok)
00607 {
00608
00609 last_time_stamp = curr_time.toString(Qt::TextDate);
00610 gContext->SetSetting("VideoPasswordTime", last_time_stamp);
00611 gContext->SaveSetting("VideoPasswordTime", last_time_stamp);
00612 return true;
00613 }
00614 }
00615 else
00616 {
00617 return true;
00618 }
00619
00620 return false;
00621 }
00622