|
MythTV
0.26-pre
|
00001 // qt 00002 #include <QString> 00003 #include <QFileInfo> 00004 #include <QtAlgorithms> 00005 00006 // myth 00007 #include <mythdb.h> 00008 #include <mythcontext.h> 00009 #include <mythdirs.h> 00010 #include <mythsystem.h> 00011 #include <remoteutil.h> 00012 #include <remotefile.h> 00013 #include <mythprogressdialog.h> 00014 #include <rssparse.h> 00015 #include <netutils.h> 00016 #include <mythrssmanager.h> 00017 #include <netgrabbermanager.h> 00018 #include <mythcoreutil.h> 00019 #include <metadata/videoutils.h> 00020 00021 // mythnetvision 00022 #include "treeeditor.h" 00023 #include "nettree.h" 00024 #include "rsseditor.h" 00025 #include "netcommon.h" 00026 00027 class ResultItem; 00028 class GrabberScript; 00029 00030 const QString NetTree::RSSNode = tr("RSS Feeds"); 00031 const QString NetTree::SearchNode = tr("Searches"); 00032 const QString NetTree::DownloadNode = tr("Downloaded Files"); 00033 00034 namespace 00035 { 00036 MythGenericTree *GetNodePtrFromButton(MythUIButtonListItem *item) 00037 { 00038 if (item) 00039 return item->GetData().value<MythGenericTree *>(); 00040 00041 return 0; 00042 } 00043 } 00044 00045 NetTree::NetTree(DialogType type, MythScreenStack *parent, const char *name) 00046 : MythScreenType(parent, name), 00047 m_siteMap(NULL), m_siteButtonList(NULL), 00048 m_noSites(NULL), m_thumbImage(NULL), 00049 m_downloadable(NULL), m_busyPopup(NULL), 00050 m_menuPopup(NULL), m_popupStack(), 00051 m_progressDialog(NULL), m_downloadFile(QString()), 00052 m_type(type) 00053 { 00054 m_imageDownload = new MetadataImageDownload(this); 00055 m_gdt = new GrabberDownloadThread(this); 00056 m_popupStack = GetMythMainWindow()->GetStack("popup stack"); 00057 m_updateFreq = gCoreContext->GetNumSetting( 00058 "mythNetTree.updateFreq", 6); 00059 m_rssAutoUpdate = gCoreContext->GetNumSetting( 00060 "mythnetvision.rssBackgroundFetch", 0); 00061 m_treeAutoUpdate = gCoreContext->GetNumSetting( 00062 "mythnetvision.backgroundFetch", 0); 00063 gCoreContext->addListener(this); 00064 } 00065 00066 bool NetTree::Create() 00067 { 00068 QString windowName = "gallery"; 00069 00070 switch (m_type) 00071 { 00072 case DLG_GALLERY: 00073 windowName = "gallery"; 00074 break; 00075 case DLG_BROWSER: 00076 windowName = "browser"; 00077 break; 00078 case DLG_TREE: 00079 windowName = "tree"; 00080 break; 00081 case DLG_DEFAULT: 00082 default: 00083 break; 00084 } 00085 00086 if (!LoadWindowFromXML("netvision-ui.xml", windowName, this)) 00087 return false; 00088 00089 bool err = false; 00090 if (m_type == DLG_TREE) 00091 UIUtilE::Assign(this, m_siteMap, "videos", &err); 00092 else 00093 UIUtilE::Assign(this, m_siteButtonList, "videos", &err); 00094 00095 UIUtilW::Assign(this, m_noSites, "nosites"); 00096 00097 UIUtilW::Assign(this, m_thumbImage, "preview"); 00098 00099 UIUtilW::Assign(this, m_downloadable, "downloadable"); 00100 00101 m_siteGeneric = new MythGenericTree("site root", 0, false); 00102 m_currentNode = m_siteGeneric; 00103 00104 if (err) 00105 { 00106 LOG(VB_GENERAL, LOG_ERR, "Cannot load screen '" + windowName + "'"); 00107 return false; 00108 } 00109 00110 BuildFocusList(); 00111 00112 LoadInBackground(); 00113 00114 if (m_type == DLG_TREE) 00115 { 00116 SetFocusWidget(m_siteMap); 00117 00118 connect(m_siteMap, SIGNAL(itemClicked(MythUIButtonListItem *)), 00119 SLOT(streamWebVideo(void))); 00120 connect(m_siteMap, SIGNAL(itemSelected(MythUIButtonListItem *)), 00121 SLOT(slotItemChanged(void))); 00122 connect(m_siteMap, SIGNAL(nodeChanged(MythGenericTree *)), 00123 SLOT(slotItemChanged(void))); 00124 } 00125 else 00126 { 00127 SetFocusWidget(m_siteButtonList); 00128 00129 connect(m_siteButtonList, SIGNAL(itemClicked(MythUIButtonListItem *)), 00130 SLOT(handleSelect(MythUIButtonListItem *))); 00131 connect(m_siteButtonList, SIGNAL(itemSelected(MythUIButtonListItem *)), 00132 SLOT(slotItemChanged(void))); 00133 } 00134 00135 return true; 00136 } 00137 00138 void NetTree::Load() 00139 { 00140 m_grabberList = findAllDBTreeGrabbersByHost(VIDEO_FILE); 00141 m_rssList = findAllDBRSS(); 00142 00143 fillTree(); 00144 } 00145 00146 void NetTree::SetCurrentNode(MythGenericTree *node) 00147 { 00148 if (!node) 00149 return; 00150 00151 m_currentNode = node; 00152 } 00153 00154 void NetTree::Init() 00155 { 00156 loadData(); 00157 } 00158 00159 NetTree::~NetTree() 00160 { 00161 qDeleteAll(m_grabberList); 00162 m_grabberList.clear(); 00163 00164 if (m_siteGeneric) 00165 { 00166 delete m_siteGeneric; 00167 m_siteGeneric = NULL; 00168 } 00169 00170 cleanThumbnailCacheDir(); 00171 00172 if (m_imageDownload) 00173 { 00174 delete m_imageDownload; 00175 m_imageDownload = NULL; 00176 } 00177 00178 if (m_gdt) 00179 { 00180 delete m_gdt; 00181 m_gdt = NULL; 00182 } 00183 00184 m_rssList.clear(); 00185 00186 qDeleteAll(m_videos); 00187 m_videos.clear(); 00188 00189 cleanCacheDir(); 00190 00191 gCoreContext->removeListener(this); 00192 } 00193 00194 void NetTree::cleanCacheDir() 00195 { 00196 QString cache = QString("%1/thumbcache") 00197 .arg(GetConfDir()); 00198 QDir cacheDir(cache); 00199 QStringList thumbs = cacheDir.entryList(QDir::Files); 00200 00201 for (QStringList::const_iterator i = thumbs.end() - 1; 00202 i != thumbs.begin() - 1; --i) 00203 { 00204 QString filename = QString("%1/%2").arg(cache).arg(*i); 00205 LOG(VB_GENERAL, LOG_DEBUG, QString("Deleting file %1").arg(filename)); 00206 QFileInfo fi(filename); 00207 QDateTime lastmod = fi.lastModified(); 00208 if (lastmod.addDays(7) < QDateTime::currentDateTime()) 00209 QFile::remove(filename); 00210 } 00211 } 00212 00213 void NetTree::loadData(void) 00214 { 00215 if (m_type == DLG_TREE) 00216 m_siteMap->AssignTree(m_siteGeneric); 00217 else 00218 { 00219 m_siteButtonList->Reset(); 00220 00221 if (!m_currentNode) 00222 SetCurrentNode(m_siteGeneric); 00223 00224 if (!m_currentNode) 00225 return; 00226 00227 MythGenericTree *selectedNode = m_currentNode->getSelectedChild(); 00228 00229 typedef QList<MythGenericTree *> MGTreeChildList; 00230 MGTreeChildList *lchildren = m_currentNode->getAllChildren(); 00231 00232 for (MGTreeChildList::const_iterator p = lchildren->begin(); 00233 p != lchildren->end(); ++p) 00234 { 00235 if (*p != NULL) 00236 { 00237 MythUIButtonListItem *item = 00238 new MythUIButtonListItem(m_siteButtonList, QString(), 0, 00239 true, MythUIButtonListItem::NotChecked); 00240 00241 item->SetData(qVariantFromValue(*p)); 00242 00243 UpdateItem(item); 00244 00245 if (*p == selectedNode) 00246 m_siteButtonList->SetItemCurrent(item); 00247 } 00248 } 00249 00250 slotItemChanged(); 00251 } 00252 00253 if (m_siteGeneric->childCount() == 0 && m_noSites) 00254 m_noSites->SetVisible(true); 00255 else if (m_noSites) 00256 m_noSites->SetVisible(false); 00257 00258 if (m_siteGeneric->childCount() == 0) 00259 runTreeEditor(); 00260 } 00261 00262 void NetTree::UpdateItem(MythUIButtonListItem *item) 00263 { 00264 if (!item) 00265 return; 00266 00267 MythGenericTree *node = GetNodePtrFromButton(item); 00268 00269 if (!node) 00270 return; 00271 00272 RSSSite *site = qVariantValue<RSSSite *>(node->GetData()); 00273 ResultItem *video = qVariantValue<ResultItem *>(node->GetData()); 00274 00275 int nodeInt = node->getInt(); 00276 00277 if (nodeInt == kSubFolder) 00278 { 00279 item->SetText(QString("%1").arg(node->visibleChildCount()), "childcount"); 00280 item->DisplayState("subfolder", "nodetype"); 00281 item->SetText(node->getString(), "title"); 00282 item->SetText(node->getString()); 00283 item->SetImage(node->GetData().toString()); 00284 } 00285 else if (nodeInt == kUpFolder) 00286 { 00287 item->DisplayState("upfolder", "nodetype"); 00288 item->SetText(node->getString(), "title"); 00289 item->SetText(node->getString()); 00290 } 00291 00292 if (site) 00293 { 00294 item->SetText(site->GetTitle()); 00295 item->SetText(site->GetDescription(), "description"); 00296 item->SetText(site->GetURL(), "url"); 00297 item->SetImage(site->GetImage()); 00298 } 00299 else if (video) 00300 { 00301 item->SetText(video->GetTitle()); 00302 00303 MetadataMap metadataMap; 00304 video->toMap(metadataMap); 00305 item->SetTextFromMap(metadataMap); 00306 00307 int pos; 00308 if (m_type == DLG_TREE) 00309 pos = 0; 00310 else 00311 pos = m_siteButtonList->GetItemPos(item); 00312 00313 QString dlfile = video->GetThumbnail(); 00314 if (dlfile.contains("%SHAREDIR%")) 00315 dlfile.replace("%SHAREDIR%", GetShareDir()); 00316 else 00317 dlfile = getDownloadFilename(video->GetTitle(), 00318 video->GetThumbnail()); 00319 00320 if (QFile::exists(dlfile)) 00321 item->SetImage(dlfile); 00322 else if (video->GetThumbnail().startsWith("http")) 00323 m_imageDownload->addThumb(video->GetTitle(), video->GetThumbnail(), 00324 qVariantFromValue<uint>(pos)); 00325 } 00326 else 00327 { 00328 item->SetText(node->getString()); 00329 if (!node->GetData().toString().isEmpty()) 00330 { 00331 QString tpath = node->GetData().toString(); 00332 if (tpath.startsWith("http://")) 00333 { 00334 uint pos; 00335 if (m_type == DLG_TREE) 00336 pos = 0; 00337 else 00338 pos = m_siteButtonList->GetItemPos(item); 00339 00340 QString dlfile = GetThumbnailFilename(tpath, 00341 node->getString()); 00342 if (QFile::exists(dlfile)) 00343 item->SetImage(dlfile); 00344 else 00345 m_imageDownload->addThumb(node->getString(), tpath, 00346 qVariantFromValue<uint>(pos)); 00347 } 00348 else if (tpath != "0") 00349 { 00350 QString filename = node->GetData().toString(); 00351 if (filename.contains("%SHAREDIR%")) 00352 filename.replace("%SHAREDIR%", GetShareDir()); 00353 item->SetImage(filename); 00354 } 00355 } 00356 } 00357 } 00358 00359 void NetTree::handleSelect(MythUIButtonListItem *item) 00360 { 00361 MythGenericTree *node = GetNodePtrFromButton(item); 00362 int nodeInt = node->getInt(); 00363 00364 switch (nodeInt) 00365 { 00366 case kSubFolder: 00367 handleDirSelect(node); 00368 break; 00369 case kUpFolder: 00370 goBack(); 00371 break; 00372 default: 00373 { 00374 streamWebVideo(); 00375 } 00376 }; 00377 slotItemChanged(); 00378 } 00379 00380 void NetTree::handleDirSelect(MythGenericTree *node) 00381 { 00382 if (m_imageDownload && m_imageDownload->isRunning()) 00383 m_imageDownload->cancel(); 00384 00385 SetCurrentNode(node); 00386 loadData(); 00387 } 00388 00389 bool NetTree::goBack() 00390 { 00391 bool handled = false; 00392 00393 if (m_imageDownload && m_imageDownload->isRunning()) 00394 m_imageDownload->cancel(); 00395 00396 if (m_currentNode != m_siteGeneric) 00397 { 00398 MythGenericTree *lparent = m_currentNode->getParent(); 00399 if (lparent) 00400 { 00401 SetCurrentNode(lparent); 00402 handled = true; 00403 } 00404 } 00405 00406 loadData(); 00407 00408 return handled; 00409 } 00410 00411 bool NetTree::keyPressEvent(QKeyEvent *event) 00412 { 00413 if (GetFocusWidget()->keyPressEvent(event)) 00414 return true; 00415 00416 bool handled = false; 00417 QStringList actions; 00418 handled = GetMythMainWindow()->TranslateKeyPress("Internet Video", event, actions); 00419 00420 for (int i = 0; i < actions.size() && !handled; i++) 00421 { 00422 QString action = actions[i]; 00423 handled = true; 00424 00425 if (action == "MENU") 00426 { 00427 showMenu(); 00428 } 00429 else if (action == "ESCAPE") 00430 { 00431 if (m_type != DLG_TREE 00432 && !GetMythMainWindow()->IsExitingToMain() 00433 && m_currentNode != m_siteGeneric) 00434 handled = goBack(); 00435 else 00436 handled = false; 00437 } 00438 else 00439 handled = false; 00440 } 00441 00442 if (!handled && MythScreenType::keyPressEvent(event)) 00443 handled = true; 00444 00445 return handled; 00446 } 00447 00448 void NetTree::createBusyDialog(QString title) 00449 { 00450 if (m_busyPopup) 00451 return; 00452 00453 QString message = title; 00454 00455 m_busyPopup = new MythUIBusyDialog(message, m_popupStack, 00456 "nettreebusydialog"); 00457 00458 if (m_busyPopup->Create()) 00459 m_popupStack->AddScreen(m_busyPopup); 00460 else 00461 { 00462 delete m_busyPopup; 00463 m_busyPopup = NULL; 00464 } 00465 } 00466 00467 void NetTree::showMenu(void) 00468 { 00469 QString label = tr("Playback/Download Options"); 00470 00471 MythMenu *menu = new MythMenu(label, this, "options"); 00472 00473 ResultItem *item = NULL; 00474 if (m_type == DLG_TREE) 00475 { 00476 MythGenericTree *node = m_siteMap->GetCurrentNode(); 00477 00478 if (node) 00479 item = qVariantValue<ResultItem *>(node->GetData()); 00480 } 00481 else 00482 { 00483 MythGenericTree *node = GetNodePtrFromButton(m_siteButtonList->GetItemCurrent()); 00484 00485 if (node) 00486 item = qVariantValue<ResultItem *>(node->GetData()); 00487 } 00488 00489 if (item) 00490 { 00491 if (item->GetDownloadable()) 00492 menu->AddItem(tr("Stream Video"), SLOT(streamWebVideo())); 00493 menu->AddItem(tr("Open Web Link"), SLOT(showWebVideo())); 00494 00495 if (item->GetDownloadable()) 00496 menu->AddItem(tr("Save This Video"), SLOT(doDownloadAndPlay())); 00497 } 00498 00499 menu->AddItem(tr("Scan/Manage Subscriptions"), NULL, createShowManageMenu()); 00500 menu->AddItem(tr("Change View"), NULL, createShowViewMenu()); 00501 00502 MythDialogBox *menuPopup = new MythDialogBox(menu, m_popupStack, "mythnettreemenupopup"); 00503 00504 if (menuPopup->Create()) 00505 m_popupStack->AddScreen(menuPopup); 00506 else 00507 delete menuPopup; 00508 } 00509 00510 MythMenu* NetTree::createShowViewMenu() 00511 { 00512 QString label = tr("View Options"); 00513 00514 MythMenu *menu = new MythMenu(label, this, "options"); 00515 00516 if (m_type != DLG_TREE) 00517 menu->AddItem(tr("Switch to List View"), SLOT(switchTreeView())); 00518 if (m_type != DLG_GALLERY) 00519 menu->AddItem(tr("Switch to Gallery View"), SLOT(switchGalleryView())); 00520 if (m_type != DLG_BROWSER) 00521 menu->AddItem(tr("Switch to Browse View"), SLOT(switchBrowseView())); 00522 00523 return menu; 00524 } 00525 00526 MythMenu* NetTree::createShowManageMenu() 00527 { 00528 QString label = tr("Subscription Management"); 00529 00530 MythMenu *menu = new MythMenu(label, this, "options"); 00531 00532 00533 menu->AddItem(tr("Update Site Maps"), SLOT(updateTrees())); 00534 menu->AddItem(tr("Update RSS"), SLOT(updateRSS())); 00535 menu->AddItem(tr("Manage Site Subscriptions"), SLOT(runTreeEditor())); 00536 menu->AddItem(tr("Manage RSS Subscriptions"), SLOT(runRSSEditor())); 00537 if (!m_treeAutoUpdate) 00538 menu->AddItem(tr("Enable Automatic Site Updates"), SLOT(toggleTreeUpdates())); 00539 else 00540 menu->AddItem(tr("Disable Automatic Site Updates"), SLOT(toggleTreeUpdates())); 00541 // if (!m_rssAutoUpdate) 00542 // menu->AddItem(tr("Enable Automatic RSS Updates"), SLOT(toggleRSSUpdates())); 00543 // else 00544 // menu->AddItem(tr("Disable Automatic RSS Updates"), SLOT(toggleRSSUpdates())); 00545 00546 return menu; 00547 } 00548 00549 void NetTree::switchTreeView() 00550 { 00551 m_type = DLG_TREE; 00552 switchView(); 00553 } 00554 00555 void NetTree::switchGalleryView() 00556 { 00557 m_type = DLG_GALLERY; 00558 switchView(); 00559 } 00560 00561 void NetTree::switchBrowseView() 00562 { 00563 m_type = DLG_BROWSER; 00564 switchView(); 00565 } 00566 00567 void NetTree::switchView() 00568 { 00569 NetTree *nettree = 00570 new NetTree(m_type, GetMythMainWindow()->GetMainStack(), "nettree"); 00571 00572 if (nettree->Create()) 00573 { 00574 gCoreContext->SaveSetting("mythnetvision.ViewMode", m_type); 00575 MythScreenStack *screenStack = GetScreenStack(); 00576 screenStack->AddScreen(nettree); 00577 screenStack->PopScreen(this, false, false); 00578 deleteLater(); 00579 } 00580 else 00581 delete nettree; 00582 } 00583 00584 void NetTree::fillTree() 00585 { 00586 // First let's add all the RSS 00587 00588 m_rssGeneric = new MythGenericTree( 00589 RSSNode, kSubFolder, false); 00590 00591 // Add an upfolder 00592 if (m_type != DLG_TREE) 00593 { 00594 m_rssGeneric->addNode(QString(tr("Back")), kUpFolder, true, false); 00595 } 00596 00597 m_rssGeneric->SetData(QString("%1/mythnetvision/icons/rss.png") 00598 .arg(GetShareDir())); 00599 00600 RSSSite::rssList::iterator i = m_rssList.begin(); 00601 for (; i != m_rssList.end(); ++i) 00602 { 00603 ResultItem::resultList items = 00604 getRSSArticles((*i)->GetTitle(), VIDEO_PODCAST); 00605 MythGenericTree *ret = new MythGenericTree( 00606 (*i)->GetTitle(), kSubFolder, false); 00607 ret->SetData(qVariantFromValue(*i)); 00608 m_rssGeneric->addNode(ret); 00609 00610 // Add an upfolder 00611 if (m_type != DLG_TREE) 00612 { 00613 ret->addNode(QString(tr("Back")), kUpFolder, true, false); 00614 } 00615 00616 ResultItem::resultList::iterator it = items.begin(); 00617 for (; it != items.end(); ++it) 00618 { 00619 AddFileNode(ret, *it); 00620 } 00621 } 00622 00623 if (m_rssList.count() > 0) 00624 m_siteGeneric->addNode(m_rssGeneric); 00625 else 00626 { 00627 delete m_rssGeneric; 00628 m_rssGeneric = NULL; 00629 } 00630 00631 // Now let's add all the grabber trees 00632 00633 for (GrabberScript::scriptList::iterator i = m_grabberList.begin(); 00634 i != m_grabberList.end(); ++i) 00635 { 00636 00637 QMultiMap<QPair<QString,QString>, ResultItem*> treePathsNodes = 00638 getTreeArticles((*i)->GetTitle(), VIDEO_FILE); 00639 00640 QList< QPair<QString,QString> > paths = treePathsNodes.uniqueKeys(); 00641 00642 MythGenericTree *ret = new MythGenericTree( 00643 (*i)->GetTitle(), kSubFolder, false); 00644 QString thumb = QString("%1mythnetvision/icons/%2").arg(GetShareDir()) 00645 .arg((*i)->GetImage()); 00646 ret->SetData(qVariantFromValue(thumb)); 00647 00648 // Add an upfolder 00649 if (m_type != DLG_TREE) 00650 { 00651 ret->addNode(QString(tr("Back")), kUpFolder, true, false); 00652 } 00653 00654 for (QList<QPair<QString, QString> >::iterator i = paths.begin(); 00655 i != paths.end(); ++i) 00656 { 00657 QStringList curPaths = (*i).first.split("/"); 00658 QString dirthumb = (*i).second; 00659 QList<ResultItem*> videos = treePathsNodes.values(*i); 00660 buildGenericTree(ret, curPaths, dirthumb, videos); 00661 } 00662 m_siteGeneric->addNode(ret); 00663 } 00664 } 00665 00666 void NetTree::buildGenericTree(MythGenericTree *dst, QStringList paths, 00667 QString dirthumb, QList<ResultItem*> videos) 00668 { 00669 MythGenericTree *folder = NULL; 00670 00671 // A little loop to determine what path of the provided path might 00672 // already exist in the tree. 00673 00674 while (folder == NULL && paths.size()) 00675 { 00676 QString curPath = paths.takeFirst(); 00677 curPath.replace("|", "/"); 00678 MythGenericTree *tmp = dst->getChildByName(curPath); 00679 if (tmp) 00680 dst = tmp; 00681 else 00682 folder = new MythGenericTree( 00683 curPath, kSubFolder, false); 00684 } 00685 00686 if (!folder) 00687 return; 00688 00689 folder->SetData(dirthumb); 00690 dst->addNode(folder); 00691 00692 // Add an upfolder 00693 if (m_type != DLG_TREE) 00694 { 00695 folder->addNode(QString(tr("Back")), kUpFolder, true, false); 00696 } 00697 00698 if (paths.size()) 00699 buildGenericTree(folder, paths, dirthumb, videos); 00700 else 00701 { 00702 // File Handling 00703 for (QList<ResultItem*>::iterator it = videos.begin(); 00704 it != videos.end(); ++it) 00705 AddFileNode(folder, *it); 00706 } 00707 } 00708 00709 MythGenericTree *NetTree::AddDirNode(MythGenericTree *where_to_add, 00710 QString name, QString thumbnail) 00711 { 00712 QString title = name; 00713 title.replace("&", "&"); 00714 MythGenericTree *sub_node = 00715 where_to_add->addNode(title, kSubFolder, false); 00716 sub_node->SetData(thumbnail); 00717 return sub_node; 00718 } 00719 00720 int NetTree::AddFileNode(MythGenericTree *where_to_add, ResultItem *video) 00721 { 00722 QString title = video->GetTitle(); 00723 title.replace("&", "&"); 00724 MythGenericTree *sub_node = where_to_add-> 00725 addNode(title, 0, true); 00726 sub_node->SetData(qVariantFromValue(video)); 00727 m_videos.append(video); 00728 return 1; 00729 } 00730 00731 void NetTree::streamWebVideo() 00732 { 00733 ResultItem *item; 00734 00735 if (m_type == DLG_TREE) 00736 item = qVariantValue<ResultItem *>(m_siteMap->GetCurrentNode()->GetData()); 00737 else 00738 { 00739 MythGenericTree *node = GetNodePtrFromButton(m_siteButtonList->GetItemCurrent()); 00740 00741 if (!node) 00742 return; 00743 00744 item = qVariantValue<ResultItem *>(node->GetData()); 00745 } 00746 00747 if (!item) 00748 return; 00749 00750 if (!item->GetDownloadable()) 00751 { 00752 showWebVideo(); 00753 return; 00754 } 00755 00756 GetMythMainWindow()->HandleMedia("Internal", item->GetMediaURL(), 00757 item->GetDescription(), item->GetTitle(), item->GetSubtitle(), QString(), 00758 item->GetSeason(), item->GetEpisode(), QString(), item->GetTime().toInt(), 00759 item->GetDate().toString("yyyy")); 00760 } 00761 00762 void NetTree::showWebVideo() 00763 { 00764 ResultItem *item; 00765 00766 if (m_type == DLG_TREE) 00767 item = qVariantValue<ResultItem *>(m_siteMap->GetCurrentNode()->GetData()); 00768 else 00769 { 00770 MythGenericTree *node = GetNodePtrFromButton(m_siteButtonList->GetItemCurrent()); 00771 00772 if (!node) 00773 return; 00774 00775 item = qVariantValue<ResultItem *>(node->GetData()); 00776 } 00777 00778 if (!item) 00779 return; 00780 00781 if (!item->GetPlayer().isEmpty()) 00782 { 00783 QString cmd = item->GetPlayer(); 00784 QStringList args = item->GetPlayerArguments(); 00785 if (!args.size()) 00786 { 00787 args += item->GetMediaURL(); 00788 if (!args.size()) 00789 args += item->GetURL(); 00790 } 00791 else 00792 { 00793 args.replaceInStrings("%DIR%", QString(GetConfDir() + "/MythNetvision")); 00794 args.replaceInStrings("%MEDIAURL%", item->GetMediaURL()); 00795 args.replaceInStrings("%URL%", item->GetURL()); 00796 args.replaceInStrings("%TITLE%", item->GetTitle()); 00797 } 00798 QString playerCommand = cmd + " " + args.join(" "); 00799 00800 myth_system(playerCommand); 00801 } 00802 else 00803 { 00804 QString url = item->GetURL(); 00805 00806 LOG(VB_GENERAL, LOG_DEBUG, QString("Web URL = %1").arg(url)); 00807 00808 if (url.isEmpty()) 00809 return; 00810 00811 QString browser = gCoreContext->GetSetting("WebBrowserCommand", ""); 00812 QString zoom = gCoreContext->GetSetting("WebBrowserZoomLevel", "1.0"); 00813 00814 if (browser.isEmpty()) 00815 { 00816 ShowOkPopup(tr("No browser command set! MythNetTree needs MythBrowser " 00817 "installed to display the video.")); 00818 return; 00819 } 00820 00821 if (browser.toLower() == "internal") 00822 { 00823 GetMythMainWindow()->HandleMedia("WebBrowser", url); 00824 return; 00825 } 00826 else 00827 { 00828 QString cmd = browser; 00829 cmd.replace("%ZOOM%", zoom); 00830 cmd.replace("%URL%", url); 00831 cmd.replace('\'', "%27"); 00832 cmd.replace("&","\\&"); 00833 cmd.replace(";","\\;"); 00834 00835 GetMythMainWindow()->AllowInput(false); 00836 myth_system(cmd, kMSDontDisableDrawing); 00837 GetMythMainWindow()->AllowInput(true); 00838 return; 00839 } 00840 } 00841 } 00842 00843 void NetTree::doPlayVideo(QString filename) 00844 { 00845 ResultItem *item; 00846 if (m_type == DLG_TREE) 00847 item = qVariantValue<ResultItem *>(m_siteMap->GetCurrentNode()->GetData()); 00848 else 00849 { 00850 MythGenericTree *node = GetNodePtrFromButton(m_siteButtonList->GetItemCurrent()); 00851 00852 if (!node) 00853 return; 00854 00855 item = qVariantValue<ResultItem *>(node->GetData()); 00856 } 00857 00858 if (!item) 00859 return; 00860 00861 GetMythMainWindow()->HandleMedia("Internal", filename); 00862 } 00863 00864 void NetTree::slotDeleteVideo() 00865 { 00866 QString message = tr("Are you sure you want to delete this file?"); 00867 00868 MythConfirmationDialog *confirmdialog = 00869 new MythConfirmationDialog(m_popupStack,message); 00870 00871 if (confirmdialog->Create()) 00872 { 00873 m_popupStack->AddScreen(confirmdialog); 00874 connect(confirmdialog, SIGNAL(haveResult(bool)), 00875 SLOT(doDeleteVideo(bool))); 00876 } 00877 else 00878 delete confirmdialog; 00879 } 00880 00881 void NetTree::doDeleteVideo(bool remove) 00882 { 00883 if (!remove) 00884 return; 00885 00886 ResultItem *item; 00887 if (m_type == DLG_TREE) 00888 item = qVariantValue<ResultItem *>(m_siteMap->GetCurrentNode()->GetData()); 00889 else 00890 { 00891 MythGenericTree *node = GetNodePtrFromButton(m_siteButtonList->GetItemCurrent()); 00892 00893 if (!node) 00894 return; 00895 00896 item = qVariantValue<ResultItem *>(node->GetData()); 00897 } 00898 00899 if (!item) 00900 return; 00901 00902 QString filename = GetDownloadFilename(item->GetTitle(), 00903 item->GetMediaURL()); 00904 00905 if (filename.startsWith("myth://")) 00906 RemoteFile::DeleteFile(filename); 00907 else 00908 { 00909 QFile file(filename); 00910 file.remove(); 00911 } 00912 } 00913 00914 void NetTree::doDownloadAndPlay() 00915 { 00916 ResultItem *item; 00917 if (m_type == DLG_TREE) 00918 item = qVariantValue<ResultItem *>(m_siteMap->GetCurrentNode()->GetData()); 00919 else 00920 { 00921 MythGenericTree *node = GetNodePtrFromButton(m_siteButtonList->GetItemCurrent()); 00922 00923 if (!node) 00924 return; 00925 00926 item = qVariantValue<ResultItem *>(node->GetData()); 00927 } 00928 00929 if (!item) 00930 return; 00931 00932 QString baseFilename = GetDownloadFilename(item->GetTitle(), 00933 item->GetMediaURL()); 00934 00935 QString finalFilename = generate_file_url("Default", 00936 gCoreContext->GetMasterHostName(), 00937 baseFilename); 00938 00939 LOG(VB_GENERAL, LOG_INFO, QString("Downloading %1 to %2") 00940 .arg(item->GetMediaURL()) .arg(finalFilename)); 00941 00942 // Does the file already exist? 00943 bool exists = RemoteFile::Exists(finalFilename); 00944 00945 if (exists) 00946 { 00947 doPlayVideo(finalFilename); 00948 return; 00949 } 00950 else 00951 DownloadVideo(item->GetMediaURL(), baseFilename); 00952 } 00953 00954 void NetTree::DownloadVideo(QString url, QString dest) 00955 { 00956 initProgressDialog(); 00957 m_downloadFile = RemoteDownloadFile(url, "Default", dest); 00958 } 00959 00960 void NetTree::initProgressDialog() 00961 { 00962 QString message = tr("Downloading Video..."); 00963 m_progressDialog = new MythUIProgressDialog(message, 00964 m_popupStack, "videodownloadprogressdialog"); 00965 00966 if (m_progressDialog->Create()) 00967 { 00968 m_popupStack->AddScreen(m_progressDialog, false); 00969 } 00970 else 00971 { 00972 delete m_progressDialog; 00973 m_progressDialog = NULL; 00974 } 00975 } 00976 00977 void NetTree::slotItemChanged() 00978 { 00979 ResultItem *item; 00980 RSSSite *site; 00981 00982 if (m_type == DLG_TREE) 00983 { 00984 item = qVariantValue<ResultItem *>(m_siteMap->GetCurrentNode()->GetData()); 00985 site = qVariantValue<RSSSite *>(m_siteMap->GetCurrentNode()->GetData()); 00986 } 00987 else 00988 { 00989 MythGenericTree *node = GetNodePtrFromButton(m_siteButtonList->GetItemCurrent()); 00990 00991 if (!node) 00992 return; 00993 00994 item = qVariantValue<ResultItem *>(node->GetData()); 00995 site = qVariantValue<RSSSite *>(node->GetData()); 00996 } 00997 00998 if (item) 00999 { 01000 MetadataMap metadataMap; 01001 item->toMap(metadataMap); 01002 SetTextFromMap(metadataMap); 01003 01004 if (!item->GetThumbnail().isEmpty() && m_thumbImage) 01005 { 01006 m_thumbImage->Reset(); 01007 QString dlfile = item->GetThumbnail(); 01008 if (dlfile.contains("%SHAREDIR%")) 01009 { 01010 dlfile.replace("%SHAREDIR%", GetShareDir()); 01011 m_thumbImage->SetFilename(dlfile); 01012 m_thumbImage->Load(); 01013 } 01014 else 01015 { 01016 QString sFilename = getDownloadFilename(item->GetTitle(), item->GetThumbnail()); 01017 01018 bool exists = QFile::exists(sFilename); 01019 if (exists) 01020 { 01021 m_thumbImage->SetFilename(sFilename); 01022 m_thumbImage->Load(); 01023 } 01024 } 01025 } 01026 else if (m_thumbImage) 01027 m_thumbImage->Reset(); 01028 01029 if (m_downloadable) 01030 { 01031 if (item->GetDownloadable()) 01032 m_downloadable->DisplayState("yes"); 01033 else 01034 m_downloadable->DisplayState("no"); 01035 } 01036 } 01037 else if (site) 01038 { 01039 ResultItem *res = new ResultItem(site->GetTitle(), QString(), site->GetDescription(), 01040 site->GetURL(), site->GetImage(), QString(), site->GetAuthor(), QDateTime(), 01041 0, 0, -1, QString(), QStringList(), QString(), QStringList(), 0, 0, QString(), 01042 0, QStringList(), 0, 0, 0); 01043 01044 MetadataMap metadataMap; 01045 res->toMap(metadataMap); 01046 SetTextFromMap(metadataMap); 01047 01048 if (!site->GetImage().isEmpty() && m_thumbImage) 01049 { 01050 m_thumbImage->SetFilename(site->GetImage()); 01051 m_thumbImage->Load(); 01052 } 01053 else if (m_thumbImage) 01054 m_thumbImage->Reset(); 01055 01056 if (m_downloadable) 01057 { 01058 m_downloadable->Reset(); 01059 } 01060 } 01061 else 01062 { 01063 QString title; 01064 01065 if (m_type == DLG_TREE) 01066 title = m_siteMap->GetItemCurrent()->GetText(); 01067 else 01068 title = m_siteButtonList->GetItemCurrent()->GetText(); 01069 01070 QString thumb; 01071 if (m_type == DLG_TREE) 01072 thumb = m_siteMap->GetCurrentNode()-> 01073 GetData().toString(); 01074 else 01075 { 01076 MythGenericTree *node = GetNodePtrFromButton(m_siteButtonList->GetItemCurrent()); 01077 01078 if (node) 01079 thumb = node->GetData().toString(); 01080 } 01081 01082 ResultItem *res = new ResultItem(title, QString(), QString(), 01083 QString(), thumb, QString(), QString(), QDateTime(), 01084 0, 0, -1, QString(), QStringList(), QString(), QStringList(), 0, 0, QString(), 01085 0, QStringList(), 0, 0, 0); 01086 01087 MetadataMap metadataMap; 01088 res->toMap(metadataMap); 01089 SetTextFromMap(metadataMap); 01090 01091 if (m_thumbImage) 01092 { 01093 if (!thumb.startsWith("http://")) 01094 { 01095 if (thumb.contains("%SHAREDIR%")) 01096 thumb.replace("%SHAREDIR%", GetShareDir()); 01097 01098 bool exists = QFile::exists(thumb); 01099 01100 if (exists) 01101 { 01102 m_thumbImage->SetFilename(thumb); 01103 m_thumbImage->Load(); 01104 } 01105 else 01106 m_thumbImage->Reset(); 01107 } 01108 else 01109 { 01110 01111 QString url = thumb; 01112 QString title; 01113 if (m_type == DLG_TREE) 01114 title = m_siteMap->GetItemCurrent()->GetText(); 01115 else 01116 title = m_siteButtonList->GetItemCurrent()->GetText(); 01117 01118 QString sFilename = GetDownloadFilename(title, url); 01119 01120 bool exists = QFile::exists(sFilename); 01121 if (exists && !url.isEmpty()) 01122 { 01123 m_thumbImage->SetFilename(sFilename); 01124 m_thumbImage->Load(); 01125 } 01126 else 01127 m_thumbImage->Reset(); 01128 } 01129 } 01130 01131 if (m_downloadable) 01132 m_downloadable->Reset(); 01133 } 01134 } 01135 01136 void NetTree::runTreeEditor() 01137 { 01138 MythScreenStack *mainStack = GetMythMainWindow()->GetMainStack(); 01139 01140 TreeEditor *treeedit = new TreeEditor(mainStack, "mythnettreeedit"); 01141 01142 if (treeedit->Create()) 01143 { 01144 connect(treeedit, SIGNAL(itemsChanged()), this, 01145 SLOT(doTreeRefresh())); 01146 01147 mainStack->AddScreen(treeedit); 01148 } 01149 else 01150 { 01151 delete treeedit; 01152 } 01153 } 01154 01155 void NetTree::runRSSEditor() 01156 { 01157 MythScreenStack *mainStack = GetMythMainWindow()->GetMainStack(); 01158 01159 RSSEditor *rssedit = new RSSEditor(mainStack, "mythnetrssedit"); 01160 01161 if (rssedit->Create()) 01162 { 01163 connect(rssedit, SIGNAL(itemsChanged()), this, 01164 SLOT(updateRSS())); 01165 01166 mainStack->AddScreen(rssedit); 01167 } 01168 else 01169 { 01170 delete rssedit; 01171 } 01172 } 01173 01174 void NetTree::doTreeRefresh() 01175 { 01176 if (m_busyPopup) 01177 { 01178 m_busyPopup->Close(); 01179 m_busyPopup = NULL; 01180 } 01181 01182 TreeRefresh(); 01183 } 01184 01185 void NetTree::TreeRefresh() 01186 { 01187 m_siteGeneric = new MythGenericTree("site root", 0, false); 01188 m_currentNode = m_siteGeneric; 01189 01190 m_grabberList = findAllDBTreeGrabbers(); 01191 m_rssList = findAllDBRSS(); 01192 01193 fillTree(); 01194 loadData(); 01195 switchView(); 01196 } 01197 01198 void NetTree::updateRSS() 01199 { 01200 if (!findAllDBRSS().count()) 01201 return; 01202 01203 QString title(tr("Updating RSS. This could take a while...")); 01204 createBusyDialog(title); 01205 01206 RSSManager *rssMan = new RSSManager(); 01207 connect(rssMan, SIGNAL(finished()), this, 01208 SLOT(doTreeRefresh())); 01209 rssMan->startTimer(); 01210 rssMan->doUpdate(); 01211 } 01212 01213 void NetTree::updateTrees() 01214 { 01215 if (m_grabberList.count() == 0) 01216 return; 01217 01218 QString title(tr("Updating Site Maps. This could take a while...")); 01219 createBusyDialog(title); 01220 m_gdt->refreshAll(); 01221 } 01222 01223 void NetTree::toggleRSSUpdates() 01224 { 01225 m_rssAutoUpdate = !m_rssAutoUpdate; 01226 gCoreContext->SaveSetting("mythnetvision.rssBackgroundFetch", 01227 m_rssAutoUpdate); 01228 } 01229 01230 void NetTree::toggleTreeUpdates() 01231 { 01232 m_treeAutoUpdate = !m_treeAutoUpdate; 01233 gCoreContext->SaveSetting("mythnetvision.backgroundFetch", 01234 m_treeAutoUpdate); 01235 } 01236 01237 void NetTree::customEvent(QEvent *event) 01238 { 01239 if (event->type() == ThumbnailDLEvent::kEventType) 01240 { 01241 ThumbnailDLEvent *tde = (ThumbnailDLEvent *)event; 01242 01243 if (!tde) 01244 return; 01245 01246 ThumbnailData *data = tde->thumb; 01247 01248 if (!data) 01249 return; 01250 01251 QString title = data->title; 01252 QString file = data->url; 01253 uint pos = qVariantValue<uint>(data->data); 01254 01255 if (file.isEmpty()) 01256 return; 01257 01258 if (m_type == DLG_TREE) 01259 { 01260 if (title == m_siteMap->GetCurrentNode()->getString() && 01261 m_thumbImage) 01262 { 01263 m_thumbImage->SetFilename(file); 01264 m_thumbImage->Load(); 01265 m_thumbImage->Show(); 01266 } 01267 } 01268 else 01269 { 01270 if (!((uint)m_siteButtonList->GetCount() >= pos)) 01271 { 01272 delete data; 01273 return; 01274 } 01275 01276 MythUIButtonListItem *item = 01277 m_siteButtonList->GetItemAt(pos); 01278 01279 if (item && item->GetText() == title) 01280 { 01281 item->SetImage(file); 01282 } 01283 } 01284 01285 delete data; 01286 } 01287 else if (event->type() == kGrabberUpdateEventType) 01288 { 01289 doTreeRefresh(); 01290 } 01291 else if ((MythEvent::Type)(event->type()) == MythEvent::MythEventMessage) 01292 { 01293 MythEvent *me = (MythEvent *)event; 01294 QStringList tokens = me->Message().split(" ", QString::SkipEmptyParts); 01295 01296 if (tokens.isEmpty()) 01297 return; 01298 01299 if (tokens[0] == "DOWNLOAD_FILE") 01300 { 01301 QStringList args = me->ExtraDataList(); 01302 if ((tokens.size() != 2) || 01303 (args[1] != m_downloadFile)) 01304 return; 01305 01306 if (tokens[1] == "UPDATE") 01307 { 01308 QString message = tr("Downloading Video...\n" 01309 "(%1 of %2 MB)") 01310 .arg(QString::number(args[2].toInt() / 1024.0 / 1024.0, 'f', 2)) 01311 .arg(QString::number(args[3].toInt() / 1024.0 / 1024.0, 'f', 2)); 01312 m_progressDialog->SetMessage(message); 01313 m_progressDialog->SetTotal(args[3].toInt()); 01314 m_progressDialog->SetProgress(args[2].toInt()); 01315 } 01316 else if (tokens[1] == "FINISHED") 01317 { 01318 int fileSize = args[2].toInt(); 01319 int errorCode = args[4].toInt(); 01320 01321 if (m_progressDialog) 01322 m_progressDialog->Close(); 01323 01324 QFileInfo file(m_downloadFile); 01325 if ((m_downloadFile.startsWith("myth://"))) 01326 { 01327 if ((errorCode == 0) && 01328 (fileSize > 0)) 01329 { 01330 doPlayVideo(m_downloadFile); 01331 } 01332 else 01333 { 01334 ShowOkPopup(tr("Error downloading video to backend.")); 01335 } 01336 } 01337 } 01338 } 01339 } 01340 01341 }
1.7.6.1