00001
00002 #include <cstdlib>
00003 #include <stdlib.h>
00004 #include <unistd.h>
00005
00006
00007 #include <QDir>
00008 #include <QTimer>
00009
00010
00011 #include <mythcontext.h>
00012 #include <dialogbox.h>
00013 #include <mythdb.h>
00014 #include <mythuitext.h>
00015 #include <mythuibutton.h>
00016 #include <mythuiimage.h>
00017 #include <mythuibuttonlist.h>
00018 #include <mythmainwindow.h>
00019 #include <mythdialogbox.h>
00020
00021
00022 #include "videoselector.h"
00023 #include "archiveutil.h"
00024
00025 using namespace std;
00026
00027 VideoSelector::VideoSelector(MythScreenStack *parent, QList<ArchiveItem *> *archiveList)
00028 :MythScreenType(parent, "VideoSelector")
00029 {
00030 m_archiveList = archiveList;
00031 m_currentParentalLevel = ParentalLevel::plNone;
00032 m_videoList = NULL;
00033
00034 m_parentalLevelChecker = new ParentalLevelChangeChecker();
00035 connect(m_parentalLevelChecker, SIGNAL(SigResultReady(bool, ParentalLevel::Level)),
00036 this, SLOT(parentalLevelChanged(bool, ParentalLevel::Level)));
00037 }
00038
00039 VideoSelector::~VideoSelector(void)
00040 {
00041 if (m_videoList)
00042 delete m_videoList;
00043
00044 while (!m_selectedList.isEmpty())
00045 delete m_selectedList.takeFirst();
00046 m_selectedList.clear();
00047
00048 delete m_parentalLevelChecker;
00049 }
00050
00051 bool VideoSelector::Create(void)
00052 {
00053 bool foundtheme = false;
00054
00055
00056 foundtheme = LoadWindowFromXML("mytharchive-ui.xml", "video_selector", this);
00057
00058 if (!foundtheme)
00059 return false;
00060
00061 bool err = false;
00062 UIUtilE::Assign(this, m_okButton, "ok_button", &err);
00063 UIUtilE::Assign(this, m_cancelButton, "cancel_button", &err);
00064 UIUtilE::Assign(this, m_categorySelector, "category_selector", &err);
00065 UIUtilE::Assign(this, m_videoButtonList, "videolist", &err);
00066 UIUtilE::Assign(this, m_titleText, "videotitle", &err);
00067 UIUtilE::Assign(this, m_plotText, "videoplot", &err);
00068 UIUtilE::Assign(this, m_filesizeText, "filesize", &err);
00069 UIUtilE::Assign(this, m_coverImage, "cover_image", &err);
00070 UIUtilE::Assign(this, m_warningText, "warning_text", &err);
00071 UIUtilE::Assign(this, m_plText, "parentallevel_text", &err);
00072
00073 if (err)
00074 {
00075 LOG(VB_GENERAL, LOG_ERR, "Cannot load screen 'video_selector'");
00076 return false;
00077 }
00078
00079 connect(m_okButton, SIGNAL(Clicked()), SLOT(OKPressed()));
00080 connect(m_cancelButton, SIGNAL(Clicked()), SLOT(cancelPressed()));
00081
00082 connect(m_categorySelector, SIGNAL(itemSelected(MythUIButtonListItem *)),
00083 SLOT(setCategory(MythUIButtonListItem *)));
00084
00085 getVideoList();
00086 connect(m_videoButtonList, SIGNAL(itemSelected(MythUIButtonListItem *)),
00087 SLOT(titleChanged(MythUIButtonListItem *)));
00088 connect(m_videoButtonList, SIGNAL(itemClicked(MythUIButtonListItem *)),
00089 SLOT(toggleSelected(MythUIButtonListItem *)));
00090
00091 BuildFocusList();
00092
00093 SetFocusWidget(m_videoButtonList);
00094
00095 setParentalLevel(ParentalLevel::plLowest);
00096
00097 updateSelectedList();
00098 updateVideoList();
00099
00100 return true;
00101 }
00102
00103 bool VideoSelector::keyPressEvent(QKeyEvent *event)
00104 {
00105 if (GetFocusWidget()->keyPressEvent(event))
00106 return true;
00107
00108 bool handled = false;
00109 QStringList actions;
00110 handled = GetMythMainWindow()->TranslateKeyPress("Global", event, actions);
00111
00112 for (int i = 0; i < actions.size() && !handled; i++)
00113 {
00114 QString action = actions[i];
00115 handled = true;
00116
00117 if (action == "MENU")
00118 {
00119 showMenu();
00120 }
00121 else if (action == "1")
00122 {
00123 setParentalLevel(ParentalLevel::plLowest);
00124 }
00125 else if (action == "2")
00126 {
00127 setParentalLevel(ParentalLevel::plLow);
00128 }
00129 else if (action == "3")
00130 {
00131 setParentalLevel(ParentalLevel::plMedium);
00132 }
00133 else if (action == "4")
00134 {
00135 setParentalLevel(ParentalLevel::plHigh);
00136 }
00137 else
00138 handled = false;
00139 }
00140
00141 if (!handled && MythScreenType::keyPressEvent(event))
00142 handled = true;
00143
00144 return handled;
00145 }
00146
00147 void VideoSelector::showMenu()
00148 {
00149 MythScreenStack *popupStack = GetMythMainWindow()->GetStack("popup stack");
00150
00151 MythDialogBox *menuPopup = new MythDialogBox(tr("Menu"), popupStack, "actionmenu");
00152
00153 if (menuPopup->Create())
00154 popupStack->AddScreen(menuPopup);
00155
00156 menuPopup->SetReturnEvent(this, "action");
00157
00158 menuPopup->AddButton(tr("Clear All"), SLOT(clearAll()));
00159 menuPopup->AddButton(tr("Select All"), SLOT(selectAll()));
00160 }
00161
00162 void VideoSelector::selectAll()
00163 {
00164 while (!m_selectedList.isEmpty())
00165 m_selectedList.takeFirst();
00166 m_selectedList.clear();
00167
00168 VideoInfo *v;
00169 vector<VideoInfo *>::iterator i = m_videoList->begin();
00170 for ( ; i != m_videoList->end(); ++i)
00171 {
00172 v = *i;
00173 m_selectedList.append(v);
00174 }
00175
00176 updateVideoList();
00177 }
00178
00179 void VideoSelector::clearAll()
00180 {
00181 while (!m_selectedList.isEmpty())
00182 m_selectedList.takeFirst();
00183 m_selectedList.clear();
00184
00185 updateVideoList();
00186 }
00187
00188 void VideoSelector::toggleSelected(MythUIButtonListItem *item)
00189 {
00190 if (item->state() == MythUIButtonListItem::FullChecked)
00191 {
00192 int index = m_selectedList.indexOf(
00193 qVariantValue<VideoInfo *>(item->GetData()));
00194 if (index != -1)
00195 m_selectedList.takeAt(index);
00196 item->setChecked(MythUIButtonListItem::NotChecked);
00197 }
00198 else
00199 {
00200 int index = m_selectedList.indexOf(
00201 qVariantValue<VideoInfo *>(item->GetData()));
00202 if (index == -1)
00203 m_selectedList.append(qVariantValue<VideoInfo *>(item->GetData()));
00204
00205 item->setChecked(MythUIButtonListItem::FullChecked);
00206 }
00207 }
00208
00209 void VideoSelector::titleChanged(MythUIButtonListItem *item)
00210 {
00211 VideoInfo *v;
00212
00213 v = qVariantValue<VideoInfo *>(item->GetData());
00214
00215 if (!v)
00216 return;
00217
00218 if (m_titleText)
00219 m_titleText->SetText(v->title);
00220
00221 if (m_plotText)
00222 m_plotText->SetText(v->plot);
00223
00224 if (m_coverImage)
00225 {
00226 if (v->coverfile != "" && v->coverfile != "No Cover")
00227 {
00228 m_coverImage->SetFilename(v->coverfile);
00229 m_coverImage->Load();
00230 }
00231 else
00232 {
00233 m_coverImage->SetFilename("blank.png");
00234 m_coverImage->Load();
00235 }
00236 }
00237
00238 if (m_filesizeText)
00239 {
00240 if (v->size == 0)
00241 {
00242 QFile file(v->filename);
00243 if (file.exists())
00244 v->size = (uint64_t)file.size();
00245 else
00246 LOG(VB_GENERAL, LOG_ERR,
00247 QString("VideoSelector: Cannot find file: %1")
00248 .arg(v->filename));
00249 }
00250
00251 m_filesizeText->SetText(formatSize(v->size / 1024));
00252 }
00253 }
00254
00255 void VideoSelector::OKPressed()
00256 {
00257
00258 VideoInfo *v;
00259 ArchiveItem *a;
00260
00261
00262 QList<ArchiveItem *> tempAList;
00263 for (int x = 0; x < m_archiveList->size(); x++)
00264 {
00265 a = m_archiveList->at(x);
00266 bool found = false;
00267
00268 for (int y = 0; y < m_selectedList.size(); y++)
00269 {
00270 v = m_selectedList.at(y);
00271 if (a->type != "Video" || a->filename == v->filename)
00272 {
00273 found = true;
00274 break;
00275 }
00276 }
00277
00278 if (!found)
00279 tempAList.append(a);
00280 }
00281
00282 for (int x = 0; x < tempAList.size(); x++)
00283 m_archiveList->removeAll(tempAList.at(x));
00284
00285
00286 QList<VideoInfo *> tempSList;
00287 for (int x = 0; x < m_selectedList.size(); x++)
00288 {
00289 v = m_selectedList.at(x);
00290
00291 for (int y = 0; y < m_archiveList->size(); y++)
00292 {
00293 a = m_archiveList->at(y);
00294 if (a->filename == v->filename)
00295 {
00296 tempSList.append(v);
00297 break;
00298 }
00299 }
00300 }
00301
00302 for (int x = 0; x < tempSList.size(); x++)
00303 m_selectedList.removeAll(tempSList.at(x));
00304
00305
00306 for (int x = 0; x < m_selectedList.size(); x++)
00307 {
00308 v = m_selectedList.at(x);
00309 a = new ArchiveItem;
00310 a->type = "Video";
00311 a->title = v->title;
00312 a->subtitle = "";
00313 a->description = v->plot;
00314 a->startDate = "";
00315 a->startTime = "";
00316 a->size = v->size;
00317 a->filename = v->filename;
00318 a->hasCutlist = false;
00319 a->useCutlist = false;
00320 a->duration = 0;
00321 a->cutDuration = 0;
00322 a->videoWidth = 0;
00323 a->videoHeight = 0;
00324 a->fileCodec = "";
00325 a->videoCodec = "";
00326 a->encoderProfile = NULL;
00327 a->editedDetails = false;
00328 m_archiveList->append(a);
00329 }
00330
00331 emit haveResult(true);
00332 Close();
00333 }
00334
00335 void VideoSelector::cancelPressed()
00336 {
00337 emit haveResult(false);
00338 Close();
00339 }
00340
00341 void VideoSelector::updateVideoList(void)
00342 {
00343 if (!m_videoList)
00344 return;
00345
00346 m_videoButtonList->Reset();
00347
00348 if (m_categorySelector)
00349 {
00350 VideoInfo *v;
00351 vector<VideoInfo *>::iterator i = m_videoList->begin();
00352 for ( ; i != m_videoList->end(); ++i)
00353 {
00354 v = *i;
00355
00356 if (v->category == m_categorySelector->GetValue() ||
00357 m_categorySelector->GetValue() == tr("All Videos"))
00358 {
00359 if (v->parentalLevel <= m_currentParentalLevel)
00360 {
00361 MythUIButtonListItem* item = new MythUIButtonListItem(
00362 m_videoButtonList, v->title);
00363 item->setCheckable(true);
00364 if (m_selectedList.indexOf((VideoInfo *) v) != -1)
00365 {
00366 item->setChecked(MythUIButtonListItem::FullChecked);
00367 }
00368 else
00369 {
00370 item->setChecked(MythUIButtonListItem::NotChecked);
00371 }
00372
00373 item->SetData(qVariantFromValue(v));
00374 }
00375 }
00376 }
00377 }
00378
00379 if (m_videoButtonList->GetCount() > 0)
00380 {
00381 m_videoButtonList->SetItemCurrent(m_videoButtonList->GetItemFirst());
00382 titleChanged(m_videoButtonList->GetItemCurrent());
00383 m_warningText->Hide();
00384 }
00385 else
00386 {
00387 m_warningText->Show();
00388 m_titleText->Reset();
00389 m_plotText->Reset();
00390 m_coverImage->SetFilename("blank.png");
00391 m_coverImage->Load();
00392 m_filesizeText->Reset();
00393 }
00394 }
00395
00396 vector<VideoInfo *> *VideoSelector::getVideoListFromDB(void)
00397 {
00398
00399 typedef QMap<int, QString> CategoryMap;
00400 CategoryMap categoryMap;
00401 MSqlQuery query(MSqlQuery::InitCon());
00402 query.prepare("SELECT intid, category FROM videocategory");
00403
00404 if (query.exec())
00405 {
00406 while (query.next())
00407 {
00408 int id = query.value(0).toInt();
00409 QString category = query.value(1).toString();
00410 categoryMap.insert(id, category);
00411 }
00412 }
00413
00414 vector<VideoInfo*> *videoList = new vector<VideoInfo*>;
00415
00416 query.prepare("SELECT intid, title, plot, length, filename, coverfile, "
00417 "category, showlevel, subtitle, season, episode "
00418 "FROM videometadata ORDER BY title,season,episode");
00419
00420 if (query.exec() && query.size())
00421 {
00422 QString artist, genre, episode;
00423 while (query.next())
00424 {
00425 VideoInfo *info = new VideoInfo;
00426
00427 info->id = query.value(0).toInt();
00428 if (query.value(9).toInt() > 0)
00429 {
00430 episode = query.value(10).toString();
00431 if (episode.size() < 2)
00432 episode.prepend("0");
00433 info->title = QString("%1 %2x%3 - %4")
00434 .arg(query.value(1).toString())
00435 .arg(query.value(9).toString())
00436 .arg(episode)
00437 .arg(query.value(8).toString());
00438 }
00439 else
00440 info->title = query.value(1).toString();
00441
00442 info->plot = query.value(2).toString();
00443 info->size = 0;
00444 info->filename = query.value(4).toString();
00445 info->coverfile = query.value(5).toString();
00446 info->category = categoryMap[query.value(6).toInt()];
00447 info->parentalLevel = query.value(7).toInt();
00448 if (info->category.isEmpty())
00449 info->category = "(None)";
00450 videoList->push_back(info);
00451 }
00452 }
00453 else
00454 {
00455 LOG(VB_GENERAL, LOG_ERR, "VideoSelector: Failed to get any video's");
00456 return NULL;
00457 }
00458
00459 return videoList;
00460 }
00461
00462 void VideoSelector::getVideoList(void)
00463 {
00464 VideoInfo *v;
00465 m_videoList = getVideoListFromDB();
00466 QStringList categories;
00467
00468 if (m_videoList && !m_videoList->empty())
00469 {
00470 vector<VideoInfo *>::iterator i = m_videoList->begin();
00471 for ( ; i != m_videoList->end(); ++i)
00472 {
00473 v = *i;
00474
00475 if (categories.indexOf(v->category) == -1)
00476 categories.append(v->category);
00477 }
00478 }
00479 else
00480 {
00481 QTimer::singleShot(100, this, SLOT(cancelPressed()));
00482 return;
00483 }
00484
00485
00486 categories.sort();
00487
00488 if (m_categorySelector)
00489 {
00490 new MythUIButtonListItem(m_categorySelector, tr("All Videos"));
00491 m_categorySelector->SetItemCurrent(0);
00492
00493 for (int x = 0; x < categories.count(); x++)
00494 {
00495 new MythUIButtonListItem(m_categorySelector, categories[x]);
00496 }
00497 }
00498
00499 setCategory(0);
00500 }
00501
00502 void VideoSelector::setCategory(MythUIButtonListItem *item)
00503 {
00504 (void)item;
00505 updateVideoList();
00506 }
00507
00508 void VideoSelector::updateSelectedList()
00509 {
00510 if (!m_videoList)
00511 return;
00512
00513 m_selectedList.clear();
00514
00515 ArchiveItem *a;
00516 VideoInfo *v;
00517 for (int x = 0; x < m_archiveList->size(); x++)
00518 {
00519 a = m_archiveList->at(x);
00520 for (uint y = 0; y < m_videoList->size(); y++)
00521 {
00522 v = m_videoList->at(y);
00523 if (v->filename == a->filename)
00524 {
00525 if (m_selectedList.indexOf(v) == -1)
00526 m_selectedList.append(v);
00527 break;
00528 }
00529 }
00530 }
00531 }
00532
00533 void VideoSelector::setParentalLevel(ParentalLevel::Level level)
00534 {
00535 m_parentalLevelChecker->Check(m_currentParentalLevel, level);
00536 }
00537
00538 void VideoSelector::parentalLevelChanged(bool passwordValid, ParentalLevel::Level newLevel)
00539 {
00540 if (passwordValid)
00541 {
00542 m_currentParentalLevel = newLevel;
00543 updateVideoList();
00544 m_plText->SetText(QString::number(newLevel));
00545 }
00546 else
00547 ShowOkPopup(tr("You need to enter a valid password for this parental level"));
00548 }
00549