00001 #include <qapplication.h>
00002
00003 #include <stdlib.h>
00004
00005 #include <mythtv/mythcontext.h>
00006 #include <mythtv/uitypes.h>
00007
00008 #include "globals.h"
00009 #include "videotree.h"
00010 #include "videofilter.h"
00011 #include "videolist.h"
00012 #include "metadata.h"
00013 #include "videoutils.h"
00014 #include "imagecache.h"
00015 #include "parentalcontrols.h"
00016 #include "videoui-common.h"
00017
00018 class VideoTreeImp
00019 {
00020 public:
00021 UIManagedTreeListType *video_tree_list;
00022 UITextType *video_title;
00023 UITextType *video_file;
00024 UITextType *video_plot;
00025 UITextType *video_cast;
00026 UITextType *video_player;
00027 UITextType *pl_value;
00028 UIImageType *video_poster;
00029
00030 UITextType *m_director;
00031 UITextType *m_rating;
00032 UITextType *m_inetref;
00033 UITextType *m_year;
00034 UITextType *m_userrating;
00035 UITextType *m_length;
00036 UITextType *m_coverfile;
00037 UITextType *m_child_id;
00038 UITextType *m_browseable;
00039 UITextType *m_category;
00040 UITextType *m_level;
00041
00042 bool m_use_arrow_accel;
00043 bool m_remember_position;
00044
00045 public:
00046 VideoTreeImp() :
00047 video_tree_list(NULL), video_title(NULL),
00048 video_file(NULL), video_plot(NULL), video_cast(NULL), video_player(NULL),
00049 pl_value(NULL), video_poster(NULL), m_director(NULL), m_rating(NULL),
00050 m_inetref(NULL), m_year(NULL), m_userrating(NULL), m_length(NULL),
00051 m_coverfile(NULL), m_child_id(NULL), m_browseable(NULL),
00052 m_category(NULL), m_level(NULL)
00053 {
00054 m_use_arrow_accel = gContext->GetNumSetting("UseArrowAccels", 1);
00055 m_remember_position =
00056 gContext->GetNumSetting("mythvideo.VideoTreeRemember", 0);
00057 }
00058
00059 void update_info(const Metadata *item)
00060 {
00061 if (item)
00062 update_screen(item);
00063 else
00064 reset_screen();
00065 }
00066
00067 void wireUpTheme(VideoTree *vt)
00068 {
00069
00070 assign(vt, video_tree_list, "videotreelist");
00071 if (!video_tree_list)
00072 {
00073
00074 exit(0);
00075 }
00076 video_tree_list->showWholeTree(true);
00077 video_tree_list->colorSelectables(true);
00078
00079
00080 assign(vt, video_title, "video_title");
00081 assign(vt, video_file, "video_file");
00082 assign(vt, video_player, "video_player");
00083
00084
00085 assign(vt, pl_value, "pl_value");
00086
00087
00088 assign(vt, video_poster, "video_poster");
00089
00090
00091 assign(vt, m_director, "director", false);
00092 assign(vt, video_plot, "plot", false);
00093 assign(vt, video_cast, "cast", false);
00094 assign(vt, m_rating, "rating", false);
00095 assign(vt, m_inetref, "inetref", false);
00096 assign(vt, m_year, "year", false);
00097 assign(vt, m_userrating, "userrating", false);
00098 assign(vt, m_length, "length", false);
00099 assign(vt, m_coverfile, "coverfile", false);
00100 assign(vt, m_child_id, "child_id", false);
00101 assign(vt, m_browseable, "browseable", false);
00102 assign(vt, m_category, "category", false);
00103 assign(vt, m_level, "level", false);
00104 }
00105
00106 private:
00107 void reset_screen()
00108 {
00109 checkedSetText(video_title, "");
00110 checkedSetText(video_file, "");
00111 checkedSetText(video_player, "");
00112
00113 if (video_poster)
00114 video_poster->ResetImage();
00115
00116 checkedSetText(m_director, "");
00117 checkedSetText(video_plot, "");
00118 checkedSetText(video_cast, "");
00119 checkedSetText(m_rating, "");
00120 checkedSetText(m_inetref, "");
00121 checkedSetText(m_year, "");
00122 checkedSetText(m_userrating, "");
00123 checkedSetText(m_length, "");
00124 checkedSetText(m_coverfile, "");
00125 checkedSetText(m_child_id, "");
00126 checkedSetText(m_browseable, "");
00127 checkedSetText(m_category, "");
00128 checkedSetText(m_level, "");
00129 }
00130
00131 void update_screen(const Metadata *item)
00132 {
00133 checkedSetText(video_title, item->Title());
00134 checkedSetText(video_file, item->Filename().section("/", -1));
00135 checkedSetText(video_plot, item->Plot());
00136 checkedSetText(video_cast, GetCast(*item));
00137 checkedSetText(video_player, Metadata::getPlayer(item));
00138
00139 if (!isDefaultCoverFile(item->CoverFile()))
00140 {
00141 QSize img_size = video_poster->GetSize(true);
00142 const QPixmap *img = ImageCache::getImageCache()
00143 .load(item->CoverFile(), img_size.width(),
00144 img_size.height(), QImage::ScaleFree);
00145 if (img)
00146 {
00147 video_poster->SetImage(*img);
00148 if (!video_poster->isShown())
00149 video_poster->show();
00150 }
00151 else
00152 {
00153 video_poster->ResetImage();
00154 }
00155 }
00156 else
00157 {
00158 if (video_poster->isShown())
00159 video_poster->hide();
00160 }
00161
00162 checkedSetText(m_director, item->Director());
00163 checkedSetText(m_rating, getDisplayRating(item->Rating()));
00164 checkedSetText(m_inetref, item->InetRef());
00165 checkedSetText(m_year, getDisplayYear(item->Year()));
00166 checkedSetText(m_userrating, getDisplayUserRating(item->UserRating()));
00167 checkedSetText(m_length, getDisplayLength(item->Length()));
00168 checkedSetText(m_coverfile, item->CoverFile());
00169 checkedSetText(m_child_id, QString::number(item->ChildID()));
00170 checkedSetText(m_browseable, getDisplayBrowse(item->Browse()));
00171 checkedSetText(m_category, item->Category());
00172 checkedSetText(m_level, QString::number(item->ShowLevel()));
00173 }
00174
00175 template <typename T>
00176 void getType(VideoTree *vt, T *&value, const QString &name)
00177 {
00178 value = NULL;
00179 VERBOSE(VB_IMPORTANT, QString("Error: unknown theme element type"));
00180 }
00181
00182 template <typename UIType>
00183 bool assign(VideoTree *vt, UIType *&type, const QString &name,
00184 bool warn = true)
00185 {
00186
00187 getType<UIType>(vt, type, name);
00188 if (!type && warn)
00189 {
00190 VERBOSE(VB_IMPORTANT,
00191 QString("%1: Could not find theme element called %2 "
00192 "in your theme").arg(__FILE__).arg(name));
00193 }
00194 return type != NULL;
00195 }
00196 };
00197
00198 template <>
00199 void VideoTreeImp::getType(VideoTree *vt, UIManagedTreeListType *&value,
00200 const QString &name)
00201 {
00202 value = vt->getUIManagedTreeListType(name);
00203 }
00204
00205 template <>
00206 void VideoTreeImp::getType(VideoTree *vt, UITextType *&value,
00207 const QString &name)
00208 {
00209 value = vt->getUITextType(name);
00210 }
00211
00212 template <>
00213 void VideoTreeImp::getType(VideoTree *vt, UIImageType *&value,
00214 const QString &name)
00215 {
00216 value = vt->getUIImageType(name);
00217 }
00218
00219 VideoTree::VideoTree(MythMainWindow *lparent, const QString &window_name,
00220 const QString &theme_filename, const QString &lname,
00221 VideoList *video_list) :
00222 MythThemedDialog(lparent, window_name, theme_filename, lname),
00223 popup(NULL), expectingPopup(false), curitem(NULL),
00224 m_video_list(video_list), video_tree_root(NULL), m_exit_type(0)
00225 {
00226 m_imp.reset(new VideoTreeImp);
00227
00228 current_parental_level.reset(new ParentalLevel(
00229 gContext->GetNumSetting("VideoDefaultParentalLevel", 1)));
00230
00231
00232
00233 if (!checkParentPassword(current_parental_level->GetLevel()))
00234 {
00235 *current_parental_level = ParentalLevel::plLowest;
00236 }
00237
00238 file_browser = gContext->GetNumSetting("VideoTreeNoDB", 0);
00239 m_db_folders = gContext->GetNumSetting("mythvideo.db_folder_view", 1);
00240
00241
00242 m_imp->wireUpTheme(this);
00243
00244 checkedSetText(m_imp->pl_value,
00245 QString::number(current_parental_level->GetLevel()));
00246
00247 connect(m_imp->video_tree_list, SIGNAL(nodeSelected(int, IntVector*)), this,
00248 SLOT(handleTreeListSelection(int)));
00249 connect(m_imp->video_tree_list, SIGNAL(nodeEntered(int, IntVector*)), this,
00250 SLOT(handleTreeListEntry(int)));
00251
00252 VideoFilterSettings video_filter(true, "VideoTree");
00253 m_video_list->setCurrentVideoFilter(video_filter);
00254
00255 buildVideoList();
00256
00257 if (m_imp->m_remember_position)
00258 {
00259 QString routePath =
00260 gContext->GetSetting("mythvideo.VideoTreeLastActive", "");
00261 m_imp->video_tree_list->tryToSetCurrent(QStringList::split("\n",
00262 routePath));
00263 m_imp->video_tree_list->enter();
00264 }
00265 }
00266
00267 VideoTree::~VideoTree()
00268 {
00269 if (m_imp->m_remember_position)
00270 {
00271 QStringList path = m_imp->video_tree_list->getRouteToCurrent();
00272 gContext->SaveSetting("mythvideo.VideoTreeLastActive", path.join("\n"));
00273 }
00274 }
00275
00276 void VideoTree::keyPressEvent(QKeyEvent *e)
00277 {
00278 bool handled = false;
00279 QStringList actions;
00280 gContext->GetMainWindow()->TranslateKeyPress("Video", e, actions);
00281
00282 for (unsigned int i = 0; i < actions.size() && !handled; i++)
00283 {
00284 QString action = actions[i];
00285 handled = true;
00286
00287 if (action == "SELECT")
00288 m_imp->video_tree_list->select();
00289 else if (action == "UP")
00290 m_imp->video_tree_list->moveUp();
00291 else if (action == "DOWN")
00292 m_imp->video_tree_list->moveDown();
00293 else if (action == "LEFT")
00294 {
00295 if (m_imp->video_tree_list->getCurrentNode()->getParent() !=
00296 video_tree_root)
00297 {
00298 m_imp->video_tree_list->popUp();
00299 }
00300 else
00301 {
00302 if (m_imp->m_use_arrow_accel)
00303 {
00304 accept();
00305 }
00306 else
00307 handled = false;
00308 }
00309 }
00310 else if (action == "RIGHT")
00311 m_imp->video_tree_list->pushDown();
00312 else if (action == "PAGEUP")
00313 m_imp->video_tree_list->pageUp();
00314 else if (action == "PAGEDOWN")
00315 m_imp->video_tree_list->pageDown();
00316 else if (action == "INFO")
00317 doMenu(true);
00318 else if (action == "MENU")
00319 doMenu(false);
00320 else if (action == "INCPARENT")
00321 setParentalLevel(++ParentalLevel(*current_parental_level));
00322 else if (action == "DECPARENT")
00323 setParentalLevel(--ParentalLevel(*current_parental_level));
00324 else if (action == "1" || action == "2" || action == "3" ||
00325 action == "4")
00326 {
00327 setParentalLevel(ParentalLevel(action.toInt()));
00328 }
00329 else if (action == "FILTER")
00330 slotDoFilter();
00331 else
00332 handled = false;
00333 }
00334
00335 if (!handled)
00336 {
00337 gContext->GetMainWindow()->TranslateKeyPress("TV Frontend", e, actions);
00338
00339 for (unsigned int i = 0; i < actions.size() && !handled; i++)
00340 {
00341 QString action = actions[i];
00342 if (action == "PLAYBACK")
00343 {
00344 handled = true;
00345 playVideo(curitem);
00346 }
00347 }
00348 }
00349
00350 if (!handled)
00351 MythThemedDialog::keyPressEvent(e);
00352 }
00353
00354 void VideoTree::setParentalLevel(const ParentalLevel &which_level)
00355 {
00356 ParentalLevel::Level new_level = which_level.GetLevel();
00357 if (new_level == ParentalLevel::plNone)
00358 new_level = ParentalLevel::plLowest;
00359
00360 if (checkParentPassword(new_level, current_parental_level->GetLevel()))
00361 {
00362 *current_parental_level = new_level;
00363 buildVideoList();
00364 }
00365
00366 checkedSetText(m_imp->pl_value,
00367 QString::number(current_parental_level->GetLevel()));
00368 }
00369
00370 void VideoTree::buildVideoList()
00371 {
00372 video_tree_root = m_video_list->buildVideoList(file_browser, !m_db_folders,
00373 *current_parental_level,
00374 false);
00375 GenericTree *video_tree_data = 0;
00376
00377 if (video_tree_root->childCount() > 0)
00378 video_tree_data = video_tree_root->getChildAt(0,0);
00379 else
00380 video_tree_data = video_tree_root;
00381
00382 m_imp->video_tree_list->assignTreeData(video_tree_root);
00383
00384
00385
00386 m_imp->video_tree_list->setCurrentNode(video_tree_data);
00387 if (video_tree_data->childCount() > 0)
00388 {
00389 m_imp->video_tree_list->
00390 setCurrentNode(video_tree_data->getChildAt(0, 0));
00391 }
00392 updateForeground();
00393 m_imp->video_tree_list->enter();
00394 }
00395
00396 void VideoTree::handleTreeListEntry(int node_int)
00397 {
00398 if (node_int > -1)
00399 {
00400
00401
00402 curitem = m_video_list->getVideoListMetadata(node_int);
00403 }
00404 else
00405 {
00406
00407
00408 curitem = NULL;
00409 }
00410 m_imp->update_info(curitem);
00411
00412
00413
00414
00415
00416 updateForeground();
00417 }
00418
00419 void VideoTree::playVideo(int node_number)
00420 {
00421 if (node_number > -1)
00422 {
00423 playVideo(curitem);
00424 }
00425 }
00426
00427 void VideoTree::handleTreeListSelection(int node_int)
00428 {
00429 if (node_int > -1)
00430 {
00431 playVideo(node_int);
00432 }
00433 }
00434
00435 bool VideoTree::createPopup()
00436 {
00437 if (!popup)
00438 {
00439
00440 popup = new MythPopupBox(gContext->GetMainWindow(), "video popup");
00441
00442 expectingPopup = true;
00443
00444 popup->addLabel(tr("Select action"));
00445 popup->addLabel("");
00446 }
00447
00448 return (popup != NULL);
00449 }
00450
00451
00452 void VideoTree::doMenu(bool info)
00453 {
00454 if (createPopup())
00455 {
00456 QButton *focusButton = NULL;
00457 if (info)
00458 {
00459 focusButton = popup->addButton(tr("Watch This Video"), this,
00460 SLOT(slotWatchVideo()));
00461 popup->addButton(tr("View Full Plot"), this, SLOT(slotViewPlot()));
00462 popup->addButton(tr("View Cast"), this, SLOT(slotViewCast()));
00463 }
00464 else
00465 {
00466 focusButton = popup->addButton(tr("Filter Display"), this,
00467 SLOT(slotDoFilter()));
00468 popup->addButton(tr("Switch to Browse View"), this,
00469 SLOT(slotVideoBrowser()));
00470 popup->addButton(tr("Switch to Gallery View"), this,
00471 SLOT(slotVideoGallery()));
00472 }
00473
00474 popup->addButton(tr("Cancel"), this, SLOT(slotDoCancel()));
00475
00476 popup->ShowPopup(this, SLOT(slotDoCancel()));
00477
00478 focusButton->setFocus();
00479 }
00480 }
00481
00482 void VideoTree::slotVideoBrowser()
00483 {
00484 jumpTo(JUMP_VIDEO_BROWSER);
00485 }
00486
00487 void VideoTree::slotVideoGallery()
00488 {
00489 jumpTo(JUMP_VIDEO_GALLERY);
00490 }
00491
00492 void VideoTree::slotDoCancel(void)
00493 {
00494 if (!expectingPopup)
00495 return;
00496
00497 cancelPopup();
00498 }
00499
00500 void VideoTree::cancelPopup(void)
00501 {
00502
00503 expectingPopup = false;
00504
00505 if (popup)
00506 {
00507 popup->deleteLater();
00508
00509 popup = NULL;
00510
00511 updateForeground();
00512 qApp->processEvents();
00513 setActiveWindow();
00514 }
00515 }
00516
00517 void VideoTree::slotViewPlot()
00518 {
00519 cancelPopup();
00520
00521 if (curitem)
00522 {
00523
00524 MythPopupBox * plotbox = new MythPopupBox(gContext->GetMainWindow());
00525
00526 QLabel *plotLabel = plotbox->addLabel(curitem->Plot(),
00527 MythPopupBox::Small,true);
00528 plotLabel->setAlignment(Qt::AlignJustify | Qt::WordBreak);
00529
00530 QButton *okButton = plotbox->addButton(
00531 QObject::tr("OK"), plotbox, SLOT(accept()));
00532 okButton->setFocus();
00533
00534 plotbox->ExecPopup();
00535 plotbox->deleteLater();
00536
00537 }
00538 else
00539 {
00540 VERBOSE(VB_IMPORTANT, QString("no Item to view"));
00541 }
00542 }
00543
00544 void VideoTree::slotViewCast()
00545 {
00546 cancelPopup();
00547
00548 if (curitem)
00549 {
00550 ShowCastDialog(gContext->GetMainWindow(), *curitem);
00551 }
00552 else
00553 {
00554 VERBOSE(VB_IMPORTANT, QString("no item to view"));
00555 }
00556 }
00557
00558 void VideoTree::slotWatchVideo()
00559 {
00560 cancelPopup();
00561
00562 if (curitem)
00563 playVideo(curitem);
00564 else
00565 VERBOSE(VB_IMPORTANT, QString("no Item to watch"));
00566 }
00567
00568 void VideoTree::playVideo(Metadata *someItem)
00569 {
00570 if (!someItem)
00571 return;
00572
00573 PlayVideo(someItem->Filename(), m_video_list->getListCache());
00574
00575 m_imp->video_tree_list->deactivate();
00576 gContext->GetMainWindow()->raise();
00577 gContext->GetMainWindow()->setActiveWindow();
00578 if (gContext->GetMainWindow()->currentWidget())
00579 gContext->GetMainWindow()->currentWidget()->setFocus();
00580
00581 updateForeground();
00582 }
00583
00584 void VideoTree::slotDoFilter()
00585 {
00586 cancelPopup();
00587 BasicFilterSettingsProxy<VideoList> sp(*m_video_list);
00588 VideoFilterDialog *vfd =
00589 new VideoFilterDialog(&sp, gContext->GetMainWindow(),
00590 "filter", "video-", *m_video_list,
00591 "Video Filter Dialog");
00592 vfd->exec();
00593 delete vfd;
00594
00595 buildVideoList();
00596 }
00597
00598 void VideoTree::jumpTo(const QString &location)
00599 {
00600 cancelPopup();
00601 setExitType(SCREEN_EXIT_VIA_JUMP);
00602 gContext->GetMainWindow()->JumpTo(location);
00603 }