MythTV  0.26-pre
nettree.cpp
Go to the documentation of this file.
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("&amp;", "&");
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("&amp;", "&");
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 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends