MythTV  0.26-pre
mythnews.cpp
Go to the documentation of this file.
00001 // POSIX headers
00002 #include <unistd.h>
00003 
00004 // C headers
00005 #include <cmath>
00006 
00007 // QT headers
00008 #include <QApplication>
00009 #include <QDateTime>
00010 #include <QDir>
00011 #include <QTimer>
00012 #include <QRegExp>
00013 #include <QUrl>
00014 
00015 // MythTV headers
00016 #include <mythuitext.h>
00017 #include <mythuiimage.h>
00018 #include <mythdialogbox.h>
00019 #include <mythuibuttonlist.h>
00020 #include <mythprogressdialog.h>
00021 
00022 #include <mythmainwindow.h>
00023 #include <mythmiscutil.h>
00024 #include <httpcomms.h>
00025 #include <mythcontext.h>
00026 #include <mythdb.h>
00027 #include <mythdirs.h>
00028 
00029 // MythNews headers
00030 #include "mythnews.h"
00031 #include "mythnewseditor.h"
00032 #include "newsdbutil.h"
00033 #include "mythnewsconfig.h"
00034 
00035 #define LOC      QString("MythNews: ")
00036 #define LOC_WARN QString("MythNews, Warning: ")
00037 #define LOC_ERR  QString("MythNews, Error: ")
00038 
00043 MythNews::MythNews(MythScreenStack *parent, const QString &name) :
00044     MythScreenType(parent, name),
00045     m_lock(QMutex::Recursive)
00046 {
00047     // Setup cache directory
00048 
00049     QString fileprefix = GetConfDir();
00050 
00051     QDir dir(fileprefix);
00052     if (!dir.exists())
00053         dir.mkdir(fileprefix);
00054     fileprefix += "/MythNews";
00055     dir = QDir(fileprefix);
00056     if (!dir.exists())
00057         dir.mkdir(fileprefix);
00058 
00059     m_zoom = gCoreContext->GetSetting("WebBrowserZoomLevel", "1.4");
00060     m_browser = gCoreContext->GetSetting("WebBrowserCommand", "");
00061 
00062     // Initialize variables
00063 
00064     m_sitesList = m_articlesList = NULL;
00065     m_updatedText = m_titleText = m_descText = NULL;
00066     m_thumbnailImage = m_downloadImage = m_enclosureImage = NULL;
00067     m_menuPopup = NULL;
00068     m_progressPopup = NULL;
00069 
00070     m_TimerTimeout = 10*60*1000;
00071     m_httpGrabber = NULL;
00072 
00073     // Now do the actual work
00074     m_RetrieveTimer = new QTimer(this);
00075     connect(m_RetrieveTimer, SIGNAL(timeout()),
00076             this, SLOT(slotRetrieveNews()));
00077     m_UpdateFreq = gCoreContext->GetNumSetting("NewsUpdateFrequency", 30);
00078 
00079     m_RetrieveTimer->stop();
00080     m_RetrieveTimer->setSingleShot(false);
00081     m_RetrieveTimer->start(m_TimerTimeout);
00082 }
00083 
00084 MythNews::~MythNews()
00085 {
00086     QMutexLocker locker(&m_lock);
00087 }
00088 
00089 bool MythNews::Create(void)
00090 {
00091     QMutexLocker locker(&m_lock);
00092 
00093     bool foundtheme = false;
00094 
00095     // Load the theme for this screen
00096     foundtheme = LoadWindowFromXML("news-ui.xml", "news", this);
00097 
00098     if (!foundtheme)
00099         return false;
00100 
00101     bool err = false;
00102     UIUtilE::Assign(this, m_sitesList, "siteslist", &err);
00103     UIUtilE::Assign(this, m_articlesList, "articleslist", &err);
00104     UIUtilE::Assign(this, m_titleText, "title", &err);
00105     UIUtilE::Assign(this, m_descText, "description", &err);
00106 
00107     // these are all optional
00108     UIUtilW::Assign(this, m_nositesText, "nosites", &err);
00109     UIUtilW::Assign(this, m_updatedText, "updated", &err);
00110     UIUtilW::Assign(this, m_thumbnailImage, "thumbnail", &err);
00111     UIUtilW::Assign(this, m_enclosureImage, "enclosures", &err);
00112     UIUtilW::Assign(this, m_downloadImage, "download", &err);
00113     UIUtilW::Assign(this, m_podcastImage, "ispodcast", &err);
00114 
00115     if (err)
00116     {
00117         LOG(VB_GENERAL, LOG_ERR, "Cannot load screen 'news'");
00118         return false;
00119     }
00120 
00121     if (m_nositesText)
00122     {
00123         m_nositesText->SetText(tr("You haven't configured MythNews to use any sites."));
00124         m_nositesText->Hide();
00125     }
00126 
00127     BuildFocusList();
00128 
00129     SetFocusWidget(m_sitesList);
00130 
00131     loadSites();
00132     updateInfoView(m_sitesList->GetItemFirst());
00133 
00134     connect(m_sitesList, SIGNAL(itemSelected(MythUIButtonListItem*)),
00135             this, SLOT( slotSiteSelected(MythUIButtonListItem*)));
00136     connect(m_articlesList, SIGNAL(itemSelected( MythUIButtonListItem*)),
00137             this, SLOT( updateInfoView(MythUIButtonListItem*)));
00138     connect(m_articlesList, SIGNAL(itemClicked( MythUIButtonListItem*)),
00139             this, SLOT( slotViewArticle(MythUIButtonListItem*)));
00140 
00141     return true;
00142 }
00143 
00144 void MythNews::clearSites(void)
00145 {
00146     m_NewsSites.clear();
00147     m_sitesList->Reset();
00148     m_articles.clear();
00149     m_articlesList->Reset();
00150 
00151     m_titleText->Reset();
00152     m_descText->Reset();
00153 
00154     if (m_updatedText)
00155         m_updatedText->Reset();
00156 
00157     if (m_downloadImage)
00158         m_downloadImage->Hide();
00159 
00160     if (m_enclosureImage)
00161         m_enclosureImage->Hide();
00162 
00163     if (m_podcastImage)
00164         m_podcastImage->Hide();
00165 
00166     if (m_thumbnailImage)
00167         m_thumbnailImage->Hide();
00168 }
00169 
00170 void MythNews::loadSites(void)
00171 {
00172     QMutexLocker locker(&m_lock);
00173 
00174     clearSites();
00175 
00176     MSqlQuery query(MSqlQuery::InitCon());
00177     query.prepare(
00178         "SELECT name, url, ico, updated, podcast "
00179         "FROM newssites "
00180         "ORDER BY name");
00181 
00182     if (!query.exec())
00183     {
00184         MythDB::DBError(LOC_ERR + "Could not load sites from DB", query);
00185         return;
00186     }
00187 
00188     while (query.next())
00189     {
00190         QString name = query.value(0).toString();
00191         QString url  = query.value(1).toString();
00192         QString icon = query.value(2).toString();
00193         QDateTime time; time.setTime_t(query.value(3).toUInt());
00194         bool podcast = query.value(4).toInt();
00195         m_NewsSites.push_back(new NewsSite(name, url, time, podcast));
00196     }
00197 
00198     NewsSite::List::iterator it = m_NewsSites.begin();
00199     for (; it != m_NewsSites.end(); ++it)
00200     {
00201         MythUIButtonListItem *item =
00202             new MythUIButtonListItem(m_sitesList, (*it)->name());
00203         item->SetData(qVariantFromValue(*it));
00204 
00205         connect(*it, SIGNAL(finished(NewsSite*)),
00206                 this, SLOT(slotNewsRetrieved(NewsSite*)));
00207     }
00208 
00209     slotRetrieveNews();
00210 
00211     if (m_nositesText)
00212     {
00213         if (m_NewsSites.size() == 0)
00214             m_nositesText->Show();
00215         else
00216             m_nositesText->Hide();
00217     }
00218 }
00219 
00220 void MythNews::updateInfoView(MythUIButtonListItem *selected)
00221 {
00222     QMutexLocker locker(&m_lock);
00223 
00224     if (!selected)
00225         return;
00226 
00227     NewsSite *site = NULL;
00228     NewsArticle article;
00229 
00230     if (GetFocusWidget() == m_articlesList)
00231     {
00232         article = m_articles[selected];
00233         if (m_sitesList->GetItemCurrent())
00234             site = qVariantValue<NewsSite*>
00235                 (m_sitesList->GetItemCurrent()->GetData());
00236     }
00237     else
00238     {
00239         site = qVariantValue<NewsSite*>(selected->GetData());
00240         if (m_articlesList->GetItemCurrent())
00241             article = m_articles[m_articlesList->GetItemCurrent()];
00242     }
00243 
00244     if (GetFocusWidget() == m_articlesList)
00245     {
00246         if (!article.title().isEmpty())
00247         {
00248 
00249             if (m_titleText)
00250                 m_titleText->SetText(article.title());
00251 
00252             if (m_descText)
00253             {
00254                 QString artText = article.description();
00255                 // Replace paragraph and break HTML with newlines
00256                 if( artText.indexOf(QRegExp("</(p|P)>")) )
00257                 {
00258                     artText.replace( QRegExp("<(p|P)>"), "");
00259                     artText.replace( QRegExp("</(p|P)>"), "\n\n");
00260                 }
00261                 else
00262                 {
00263                     artText.replace( QRegExp("<(p|P)>"), "\n\n");
00264                     artText.replace( QRegExp("</(p|P)>"), "");
00265                 }
00266                 artText.replace( QRegExp("<(br|BR|)/>"), "\n");
00267                 artText.replace( QRegExp("<(br|BR|)>"), "\n");
00268                 // These are done instead of simplifyWhitespace
00269                 // because that function also strips out newlines
00270                 // Replace tab characters with nothing
00271                 artText.replace( QRegExp("\t"), "");
00272                 // Replace double space with single
00273                 artText.replace( QRegExp("  "), "");
00274                 // Replace whitespace at beginning of lines with newline
00275                 artText.replace( QRegExp("\n "), "\n");
00276                 // Remove any remaining HTML tags
00277                 QRegExp removeHTML(QRegExp("</?.+>"));
00278                 removeHTML.setMinimal(true);
00279                 artText.remove((const QRegExp&) removeHTML);
00280                 artText = artText.trimmed();
00281                 m_descText->SetText(artText);
00282             }
00283 
00284             if (!article.thumbnail().isEmpty())
00285             {
00286                 QString fileprefix = GetConfDir();
00287 
00288                 QDir dir(fileprefix);
00289                 if (!dir.exists())
00290                         dir.mkdir(fileprefix);
00291 
00292                 fileprefix += "/MythNews/tcache";
00293 
00294                 dir = QDir(fileprefix);
00295                 if (!dir.exists())
00296                     dir.mkdir(fileprefix);
00297 
00298                 QString url = article.thumbnail();
00299                 QString sFilename = QString("%1/%2")
00300                     .arg(fileprefix)
00301                     .arg(qChecksum(url.toLocal8Bit().constData(),
00302                                    url.toLocal8Bit().size()));
00303 
00304                 bool exists = QFile::exists(sFilename);
00305                 if (!exists)
00306                     HttpComms::getHttpFile(sFilename, url, 20000, 1, 2);
00307 
00308                 if (m_thumbnailImage)
00309                 {
00310                     m_thumbnailImage->SetFilename(sFilename);
00311                     m_thumbnailImage->Load();
00312 
00313                     if (!m_thumbnailImage->IsVisible())
00314                         m_thumbnailImage->Show();
00315                 }
00316             }
00317             else
00318             {
00319                 if (m_thumbnailImage)
00320                     m_thumbnailImage->Hide();
00321 
00322                 if (!site->imageURL().isEmpty())
00323                 {
00324                     QString fileprefix = GetConfDir();
00325 
00326                     QDir dir(fileprefix);
00327                     if (!dir.exists())
00328                         dir.mkdir(fileprefix);
00329 
00330                     fileprefix += "/MythNews/scache";
00331 
00332                     dir = QDir(fileprefix);
00333                     if (!dir.exists())
00334                         dir.mkdir(fileprefix);
00335 
00336                     QString url = site->imageURL();
00337                     QString extension = url.section('.', -1);
00338 
00339                     QString sitename = site->name();
00340                     QString sFilename = QString("%1/%2.%3").arg(fileprefix)
00341                                                            .arg(sitename)
00342                                                            .arg(extension);
00343 
00344                     bool exists = QFile::exists(sFilename);
00345                     if (!exists)
00346                         HttpComms::getHttpFile(sFilename, url, 20000, 1, 2);
00347 
00348                     if (m_thumbnailImage)
00349                     {
00350                         m_thumbnailImage->SetFilename(sFilename);
00351                         m_thumbnailImage->Load();
00352 
00353                         if (!m_thumbnailImage->IsVisible())
00354                             m_thumbnailImage->Show();
00355                     }
00356                 }
00357             }
00358 
00359             if (m_downloadImage)
00360             {
00361                 if (!article.enclosure().isEmpty())
00362                 {
00363                     if (!m_downloadImage->IsVisible())
00364                         m_downloadImage->Show();
00365                 }
00366                 else
00367                     m_downloadImage->Hide();
00368             }
00369 
00370             if (m_enclosureImage)
00371             {
00372                 if (!article.enclosure().isEmpty())
00373                 {
00374                     if (!m_enclosureImage->IsVisible())
00375                         m_enclosureImage->Show();
00376                 }
00377                 else
00378                     m_enclosureImage->Hide();
00379             }
00380 
00381             if (m_podcastImage)
00382                 m_podcastImage->Hide();
00383         }
00384     }
00385     else
00386     {
00387         if (m_downloadImage)
00388             m_downloadImage->Hide();
00389 
00390         if (m_enclosureImage)
00391             m_enclosureImage->Hide();
00392 
00393         if (m_podcastImage)
00394             m_podcastImage->Hide();
00395 
00396         if (site)
00397         {
00398             if (m_titleText)
00399                 m_titleText->SetText(site->name());
00400 
00401             if (m_descText)
00402                 m_descText->SetText(site->description());
00403 
00404             if (m_thumbnailImage && m_thumbnailImage->IsVisible())
00405                 m_thumbnailImage->Hide();
00406 
00407             if (m_podcastImage && site->podcast() == 1)
00408                 m_podcastImage->Show();
00409 
00410             if (!site->imageURL().isEmpty())
00411             {
00412                 QString fileprefix = GetConfDir();
00413 
00414                 QDir dir(fileprefix);
00415                 if (!dir.exists())
00416                         dir.mkdir(fileprefix);
00417 
00418                 fileprefix += "/MythNews/scache";
00419 
00420                 dir = QDir(fileprefix);
00421                 if (!dir.exists())
00422                     dir.mkdir(fileprefix);
00423 
00424                 QString url = site->imageURL();
00425                 QString extension = url.section('.', -1);
00426 
00427                 QString sitename = site->name();
00428                 QString sFilename = QString("%1/%2.%3").arg(fileprefix)
00429                                                         .arg(sitename)
00430                                                         .arg(extension);
00431 
00432                 bool exists = QFile::exists(sFilename);
00433                 if (!exists)
00434                     HttpComms::getHttpFile(sFilename, url, 20000, 1, 2);
00435 
00436                 if (m_thumbnailImage)
00437                 {
00438                     m_thumbnailImage->SetFilename(sFilename);
00439                     m_thumbnailImage->Load();
00440 
00441                     if (!m_thumbnailImage->IsVisible())
00442                         m_thumbnailImage->Show();
00443                 }
00444             }
00445         }
00446     }
00447 
00448     if (m_updatedText)
00449     {
00450 
00451         if (site)
00452         {
00453             QString text(tr("Updated") + " - ");
00454             QDateTime updated(site->lastUpdated());
00455             if (updated.toTime_t() != 0) {
00456                 text += MythDateTimeToString(site->lastUpdated(),
00457                                              kDateTimeFull | kSimplify);
00458             }
00459             else
00460                 text += tr("Unknown");
00461             m_updatedText->SetText(text);
00462         }
00463 
00464         if (m_httpGrabber != NULL)
00465         {
00466             int progress = m_httpGrabber->getProgress();
00467             int total = m_httpGrabber->getTotal();
00468             if ((progress > 0) && (total > 0) && (progress < total))
00469             {
00470                 float fProgress = (float)progress/total;
00471                 QString text = tr("%1 of %2 (%3 percent)")
00472                         .arg(formatSize(progress, 2))
00473                         .arg(formatSize(total, 2))
00474                         .arg(floor(fProgress*100));
00475                 m_updatedText->SetText(text);
00476             }
00477         }
00478     }
00479 }
00480 
00481 QString MythNews::formatSize(long long bytes, int prec)
00482 {
00483     long long sizeKB = bytes / 1024;
00484 
00485     if (sizeKB>1024*1024*1024) // Terabytes
00486     {
00487         double sizeGB = sizeKB/(1024*1024*1024.0);
00488         return QString("%1 TB").arg(sizeGB, 0, 'f', (sizeGB>10)?0:prec);
00489     }
00490     else if (sizeKB>1024*1024) // Gigabytes
00491     {
00492         double sizeGB = sizeKB/(1024*1024.0);
00493         return QString("%1 GB").arg(sizeGB, 0, 'f', (sizeGB>10)?0:prec);
00494     }
00495     else if (sizeKB>1024) // Megabytes
00496     {
00497         double sizeMB = sizeKB/1024.0;
00498         return QString("%1 MB").arg(sizeMB, 0, 'f', (sizeMB>10)?0:prec);
00499     }
00500     // Kilobytes
00501     return QString("%1 KB").arg(sizeKB);
00502 }
00503 
00504 bool MythNews::keyPressEvent(QKeyEvent *event)
00505 {
00506     if (GetFocusWidget() && GetFocusWidget()->keyPressEvent(event))
00507         return true;
00508 
00509     bool handled = false;
00510     QStringList actions;
00511     handled = GetMythMainWindow()->TranslateKeyPress("News", event, actions);
00512 
00513     for (int i = 0; i < actions.size() && !handled; i++)
00514     {
00515         QString action = actions[i];
00516         handled = true;
00517 
00518         if (action == "RETRIEVENEWS")
00519             slotRetrieveNews();
00520         else if (action == "CANCEL")
00521             cancelRetrieve();
00522         else if (action == "MENU")
00523             ShowMenu();
00524         else if (action == "EDIT")
00525             ShowEditDialog(true);
00526         else if (action == "DELETE")
00527             deleteNewsSite();
00528         else if (action == "ESCAPE")
00529         {
00530             {
00531                 QMutexLocker locker(&m_lock);
00532 
00533                 if (m_progressPopup)
00534                 {
00535                     m_progressPopup->Close();
00536                     m_progressPopup = NULL;
00537                 }
00538 
00539                 m_RetrieveTimer->stop();
00540 
00541                 if (m_httpGrabber)
00542                     m_abortHttp = true;
00543             }
00544 
00545             Close();
00546         }
00547         else
00548             handled = false;
00549     }
00550 
00551     if (!handled && MythScreenType::keyPressEvent(event))
00552         handled = true;
00553 
00554     return handled;
00555 }
00556 
00557 void MythNews::slotRetrieveNews(void)
00558 {
00559     QMutexLocker locker(&m_lock);
00560 
00561     if (m_NewsSites.empty())
00562         return;
00563 
00564     m_RetrieveTimer->stop();
00565 
00566     NewsSite::List::iterator it = m_NewsSites.begin();
00567     for (; it != m_NewsSites.end(); ++it)
00568     {
00569         if ((*it)->timeSinceLastUpdate() > m_UpdateFreq)
00570             (*it)->retrieve();
00571         else
00572             processAndShowNews(*it);
00573     }
00574 
00575     m_RetrieveTimer->stop();
00576     m_RetrieveTimer->setSingleShot(false);
00577     m_RetrieveTimer->start(m_TimerTimeout);
00578 }
00579 
00580 void MythNews::slotNewsRetrieved(NewsSite *site)
00581 {
00582     unsigned int updated = site->lastUpdated().toTime_t();
00583 
00584     MSqlQuery query(MSqlQuery::InitCon());
00585     query.prepare("UPDATE newssites SET updated = :UPDATED "
00586                   "WHERE name = :NAME ;");
00587     query.bindValue(":UPDATED", updated);
00588     query.bindValue(":NAME", site->name());
00589     if (!query.exec() || !query.isActive())
00590         MythDB::DBError("news update time", query);
00591 
00592     processAndShowNews(site);
00593 }
00594 
00595 void MythNews::cancelRetrieve(void)
00596 {
00597     QMutexLocker locker(&m_lock);
00598 
00599     NewsSite::List::iterator it = m_NewsSites.begin();
00600     for (; it != m_NewsSites.end(); ++it)
00601     {
00602         (*it)->stop();
00603         processAndShowNews(*it);
00604     }
00605 }
00606 
00607 void MythNews::processAndShowNews(NewsSite *site)
00608 {
00609     QMutexLocker locker(&m_lock);
00610 
00611     if (!site)
00612         return;
00613 
00614     site->process();
00615 
00616     MythUIButtonListItem *siteUIItem = m_sitesList->GetItemCurrent();
00617     if (!siteUIItem)
00618         return;
00619 
00620     if (site != qVariantValue<NewsSite*>(siteUIItem->GetData()))
00621         return;
00622 
00623     m_articlesList->Reset();
00624     m_articles.clear();
00625 
00626     NewsArticle::List articles = site->GetArticleList();
00627     NewsArticle::List::iterator it = articles.begin();
00628     for (; it != articles.end(); ++it)
00629     {
00630         MythUIButtonListItem *item =
00631             new MythUIButtonListItem(m_articlesList, (*it).title());
00632         m_articles[item] = *it;
00633     }
00634 }
00635 
00636 void MythNews::slotSiteSelected(MythUIButtonListItem *item)
00637 {
00638     QMutexLocker locker(&m_lock);
00639 
00640     if (!item || item->GetData().isNull())
00641         return;
00642 
00643     NewsSite *site = qVariantValue<NewsSite*>(item->GetData());
00644     if (!site)
00645         return;
00646 
00647     m_articlesList->Reset();
00648     m_articles.clear();
00649 
00650     NewsArticle::List articles = site->GetArticleList();
00651     NewsArticle::List::iterator it = articles.begin();
00652     for (; it != articles.end(); ++it)
00653     {
00654         MythUIButtonListItem *item =
00655             new MythUIButtonListItem(m_articlesList, (*it).title());
00656         m_articles[item] = *it;
00657     }
00658 
00659     updateInfoView(item);
00660 }
00661 
00662 void MythNews::slotProgressCancelled(void)
00663 {
00664     QMutexLocker locker(&m_lock);
00665 
00666     m_abortHttp = true;
00667 }
00668 
00669 void MythNews::createProgress(const QString &title)
00670 {
00671     QMutexLocker locker(&m_lock);
00672 
00673     if (m_progressPopup)
00674         return;
00675 
00676     QString message = title;
00677 
00678     MythScreenStack *popupStack = GetMythMainWindow()->GetStack("popup stack");
00679 
00680     m_progressPopup = new MythUIProgressDialog(message, popupStack,
00681                                                "mythnewsprogressdialog");
00682 
00683     if (m_progressPopup->Create())
00684         popupStack->AddScreen(m_progressPopup, false);
00685     else
00686     {
00687         delete m_progressPopup;
00688         m_progressPopup = NULL;
00689     }
00690 }
00691 
00692 bool MythNews::getHttpFile(const QString &sFilename, const QString &cmdURL)
00693 {
00694     QMutexLocker locker(&m_lock);
00695 
00696     int redirectCount = 0;
00697     QByteArray data(0);
00698     bool res = false;
00699     m_httpGrabber = NULL;
00700     QString hostname;
00701     QString fileUrl = cmdURL;
00702 
00703     createProgress(QObject::tr("Downloading media..."));
00704     while (1)
00705     {
00706         QUrl qurl(fileUrl);
00707         if (hostname.isEmpty())
00708             hostname = qurl.host();  // hold onto original host
00709 
00710         if (qurl.host().isEmpty()) // can occur on redirects to partial paths
00711             qurl.setHost(hostname);
00712 
00713         if (m_httpGrabber != NULL)
00714             delete m_httpGrabber;
00715 
00716         m_httpGrabber = new HttpComms;
00717         m_abortHttp = false;
00718 
00719         m_httpGrabber->request(qurl, -1, true);
00720 
00721         while ((!m_httpGrabber->isDone()) && (!m_abortHttp))
00722         {
00723             int progress = m_httpGrabber->getProgress();
00724             int total = m_httpGrabber->getTotal();
00725             if ((progress > 0) && (total > 5120) && (progress < total)) // Ignore total less than 5kb as we're probably looking at a redirect page or similar
00726             {
00727                 m_progressPopup->SetTotal(total);
00728                 m_progressPopup->SetProgress(progress);
00729                 float fProgress = (float)progress/total;
00730                 QString text = tr("%1 of %2 (%3 percent)")
00731                         .arg(formatSize(progress, 2))
00732                         .arg(formatSize(total, 2))
00733                         .arg(floor(fProgress*100));
00734                 if (m_updatedText)
00735                     m_updatedText->SetText(text);
00736             }
00737             qApp->processEvents();
00738             usleep(100000);
00739         }
00740 
00741         if (m_abortHttp)
00742             break;
00743 
00744         // Check for redirection
00745         if (!m_httpGrabber->getRedirectedURL().isEmpty())
00746         {
00747             if (redirectCount++ < 3)
00748                 fileUrl = m_httpGrabber->getRedirectedURL();
00749 
00750             // Try again
00751             continue;
00752         }
00753 
00754         if (m_httpGrabber->getStatusCode() > 400)
00755         {
00756             // Error, request failed
00757             break;
00758         }
00759 
00760         data = m_httpGrabber->getRawData();
00761 
00762         if (data.size() > 0)
00763         {
00764             QFile file(sFilename);
00765             if (file.open(QIODevice::WriteOnly))
00766             {
00767                 file.write(data);
00768                 file.close();
00769                 res = true;
00770             }
00771         }
00772         break;
00773     }
00774 
00775     if (m_progressPopup)
00776     {
00777         m_progressPopup->Close();
00778         m_progressPopup = NULL;
00779     }
00780 
00781     delete m_httpGrabber;
00782     m_httpGrabber = NULL;
00783     return res;
00784 
00785 }
00786 
00787 void MythNews::slotViewArticle(MythUIButtonListItem *articlesListItem)
00788 {
00789     QMutexLocker locker(&m_lock);
00790 
00791     QMap<MythUIButtonListItem*,NewsArticle>::const_iterator it =
00792         m_articles.find(articlesListItem);
00793 
00794     if (it == m_articles.end())
00795         return;
00796 
00797     const NewsArticle article = *it;
00798 
00799     if (article.articleURL().isEmpty())
00800         return;
00801 
00802     if (article.enclosure().isEmpty())
00803     {
00804         QString cmdUrl(article.articleURL());
00805 
00806         if (m_browser.isEmpty())
00807         {
00808             ShowOkPopup(tr("No browser command set! MythNews needs MythBrowser to be installed."));
00809             return;
00810         }
00811 
00812         // display the web page
00813         if (m_browser.toLower() == "internal")
00814         {
00815             GetMythMainWindow()->HandleMedia("WebBrowser", cmdUrl);
00816             return;
00817         }
00818         else
00819         {
00820             QString cmd = m_browser;
00821             cmd.replace("%ZOOM%", m_zoom);
00822             cmd.replace("%URL%", cmdUrl);
00823             cmd.replace('\'', "%27");
00824             cmd.replace("&","\\&");
00825             cmd.replace(";","\\;");
00826 
00827             GetMythMainWindow()->AllowInput(false);
00828             myth_system(cmd, kMSDontDisableDrawing);
00829             GetMythMainWindow()->AllowInput(true);
00830             return;
00831         }
00832     }
00833 
00834     playVideo(article);
00835 }
00836 
00837 void MythNews::ShowEditDialog(bool edit)
00838 {
00839     QMutexLocker locker(&m_lock);
00840 
00841     NewsSite *site = NULL;
00842 
00843     if (edit)
00844     {
00845         MythUIButtonListItem *siteListItem = m_sitesList->GetItemCurrent();
00846 
00847         if (!siteListItem || siteListItem->GetData().isNull())
00848             return;
00849 
00850         site = qVariantValue<NewsSite*>(siteListItem->GetData());
00851     }
00852 
00853     MythScreenStack *mainStack = GetMythMainWindow()->GetMainStack();
00854 
00855     MythNewsEditor *mythnewseditor = new MythNewsEditor(site, edit, mainStack,
00856                                                         "mythnewseditor");
00857 
00858     if (mythnewseditor->Create())
00859     {
00860         connect(mythnewseditor, SIGNAL(Exiting()), SLOT(loadSites()));
00861         mainStack->AddScreen(mythnewseditor);
00862     }
00863     else
00864         delete mythnewseditor;
00865 }
00866 
00867 void MythNews::ShowFeedManager()
00868 {
00869     MythScreenStack *mainStack = GetMythMainWindow()->GetMainStack();
00870 
00871     MythNewsConfig *mythnewsconfig = new MythNewsConfig(mainStack,
00872                                                         "mythnewsconfig");
00873 
00874     if (mythnewsconfig->Create())
00875     {
00876         connect(mythnewsconfig, SIGNAL(Exiting()), SLOT(loadSites()));
00877         mainStack->AddScreen(mythnewsconfig);
00878     }
00879     else
00880         delete mythnewsconfig;
00881 }
00882 
00883 void MythNews::ShowMenu(void)
00884 {
00885     QMutexLocker locker(&m_lock);
00886 
00887     QString label = tr("Options");
00888 
00889     MythScreenStack *popupStack =
00890                             GetMythMainWindow()->GetStack("popup stack");
00891 
00892     m_menuPopup = new MythDialogBox(label, popupStack, "mythnewsmenupopup");
00893 
00894     if (m_menuPopup->Create())
00895     {
00896         popupStack->AddScreen(m_menuPopup);
00897 
00898         m_menuPopup->SetReturnEvent(this, "options");
00899 
00900         m_menuPopup->AddButton(tr("Manage Feeds"));
00901         m_menuPopup->AddButton(tr("Add Feed"));
00902         if (m_NewsSites.size() > 0)
00903         {
00904             m_menuPopup->AddButton(tr("Edit Feed"));
00905             m_menuPopup->AddButton(tr("Delete Feed"));
00906         }
00907     }
00908     else
00909     {
00910         delete m_menuPopup;
00911         m_menuPopup = NULL;
00912     }
00913 }
00914 
00915 void MythNews::deleteNewsSite(void)
00916 {
00917     QMutexLocker locker(&m_lock);
00918 
00919     MythUIButtonListItem *siteUIItem = m_sitesList->GetItemCurrent();
00920 
00921     if (siteUIItem && !siteUIItem->GetData().isNull())
00922     {
00923         NewsSite *site = qVariantValue<NewsSite*>(siteUIItem->GetData());
00924         if (site)
00925         {
00926             removeFromDB(site->name());
00927             loadSites();
00928         }
00929     }
00930 }
00931 
00932 // does not need locking
00933 void MythNews::playVideo(const NewsArticle &article)
00934 {
00935     GetMythMainWindow()->HandleMedia("Internal", article.enclosure(),
00936                                      article.description(), article.title());
00937 }
00938 
00939 // does not need locking
00940 void MythNews::customEvent(QEvent *event)
00941 {
00942     if (event->type() == DialogCompletionEvent::kEventType)
00943     {
00944         DialogCompletionEvent *dce = (DialogCompletionEvent*)(event);
00945 
00946         QString resultid  = dce->GetId();
00947         int     buttonnum = dce->GetResult();
00948 
00949         if (resultid == "options")
00950         {
00951             if (m_NewsSites.size() > 0)
00952             {
00953                 if (buttonnum == 0)
00954                     ShowFeedManager();
00955                 else if (buttonnum == 1)
00956                     ShowEditDialog(false);
00957                 else if (buttonnum == 2)
00958                     ShowEditDialog(true);
00959                 else if (buttonnum == 3)
00960                     deleteNewsSite();
00961             }
00962             else
00963                 if (buttonnum == 0)
00964                     ShowEditDialog(false);
00965         }
00966 
00967         m_menuPopup = NULL;
00968     }
00969 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends