• Skip to content
  • Skip to link menu
KDE 4.2 API Reference
  • KDE API Reference
  • kdepim
  • Sitemap
  • Contact Us
 

akregator

articleformatter.cpp

Go to the documentation of this file.
00001 /*
00002     This file is part of Akregator.
00003 
00004     Copyright (C) 2006 Frank Osterfeld <osterfeld@kde.org>
00005 
00006     This program is free software; you can redistribute it and/or modify
00007     it under the terms of the GNU General Public License as published by
00008     the Free Software Foundation; either version 2 of the License, or
00009     (at your option) any later version.
00010 
00011     This program is distributed in the hope that it will be useful,
00012     but WITHOUT ANY WARRANTY; without even the implied warranty of
00013     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
00014     GNU General Public License for more details.
00015 
00016     You should have received a copy of the GNU General Public License
00017     along with this program; if not, write to the Free Software
00018     Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
00019 
00020     As a special exception, permission is given to link this program
00021     with any edition of Qt, and distribute the resulting executable,
00022     without including the source code for Qt in the source distribution.
00023 */
00024 
00025 #include "akregatorconfig.h"
00026 #include "article.h"
00027 #include "articleformatter.h"
00028 #include "feed.h"
00029 #include "folder.h"
00030 #include "treenode.h"
00031 #include "treenodevisitor.h"
00032 #include "utils.h"
00033 
00034 #include <kglobal.h>
00035 #include <klocale.h>
00036 
00037 #include <QApplication>
00038 #include <QPaintDevice>
00039 #include <QPalette>
00040 #include <QString>
00041 
00042 namespace Akregator {
00043 
00044 class ArticleFormatter::Private
00045 {
00046     public:
00047         explicit Private( QPaintDevice* device_ );
00048         QPaintDevice* device;
00049         class SummaryVisitor;
00050 };
00051 
00052 ArticleFormatter::Private::Private( QPaintDevice* device_ ) : device( device_ )
00053 {
00054 }
00055 
00056 ArticleFormatter::ArticleFormatter( QPaintDevice* device ) : d( new Private( device ) )
00057 {
00058 }
00059 
00060 ArticleFormatter::~ArticleFormatter()
00061 {
00062     delete d;
00063 }
00064 
00065 void ArticleFormatter::setPaintDevice(QPaintDevice* device)
00066 {
00067     d->device = device;
00068 }
00069 
00070 int ArticleFormatter::pointsToPixel(int pointSize) const
00071 {
00072     return ( pointSize * d->device->logicalDpiY() + 36 ) / 72 ;
00073 }
00074 
00075 class DefaultNormalViewFormatter::SummaryVisitor : public TreeNodeVisitor
00076 {
00077     public:
00078         SummaryVisitor(DefaultNormalViewFormatter* p) : parent(p) {}
00079         virtual bool visitFeed(Feed* node)
00080         {
00081             text = QString("<div class=\"headerbox\" dir=\"%1\">\n").arg(QApplication::isRightToLeft() ? "rtl" : "ltr");
00082 
00083             text += QString("<div class=\"headertitle\" dir=\"%1\">").arg(Utils::directionOf(Utils::stripTags(node->title())));
00084             text += node->title();
00085             if(node->unread() == 0)
00086                 text += i18n(" (no unread articles)");
00087             else
00088                 text += i18np(" (1 unread article)", " (%1 unread articles)", node->unread());
00089             text += "</div>\n"; // headertitle
00090             text += "</div>\n"; // /headerbox
00091 
00092             if (!node->image().isNull()) // image
00093             {
00094                 text += QString("<div class=\"body\">");
00095                 QString file = Utils::fileNameForUrl(node->xmlUrl());
00096                 KUrl u(parent->m_imageDir);
00097                 u.setFileName(file);
00098                 text += QString("<a href=\"%1\"><img class=\"headimage\" src=\"%2.png\"></a>\n").arg(node->htmlUrl(), u.url());
00099             }
00100             else text += "<div class=\"body\">";
00101 
00102 
00103             if( !node->description().isEmpty() )
00104             {
00105                 text += QString("<div dir=\"%1\">").arg(Utils::stripTags(Utils::directionOf(node->description())));
00106                 text += i18n("<b>Description:</b> %1<br /><br />", node->description());
00107                 text += "</div>\n"; // /description
00108             }
00109 
00110             if ( !node->htmlUrl().isEmpty() )
00111             {
00112                 text += QString("<div dir=\"%1\">").arg(Utils::directionOf(node->htmlUrl()));
00113                 text += i18n("<b>Homepage:</b> <a href=\"%1\">%2</a>", node->htmlUrl(), node->htmlUrl());
00114                 text += "</div>\n"; // / link
00115             }
00116 
00117         //text += i18n("<b>Unread articles:</b> %1").arg(node->unread());
00118             text += "</div>"; // /body
00119 
00120             return true;
00121         }
00122 
00123         virtual bool visitFolder(Folder* node)
00124         {
00125             text = QString("<div class=\"headerbox\" dir=\"%1\">\n").arg(QApplication::isRightToLeft() ? "rtl" : "ltr");
00126             text += QString("<div class=\"headertitle\" dir=\"%1\">%2").arg(Utils::directionOf(Utils::stripTags(node->title())), node->title());
00127             if(node->unread() == 0)
00128                 text += i18n(" (no unread articles)");
00129             else
00130                 text += i18np(" (1 unread article)", " (%1 unread articles)", node->unread());
00131             text += QString("</div>\n");
00132             text += "</div>\n"; // /headerbox
00133 
00134             return true;
00135         }
00136 
00137         QString formatSummary(TreeNode* node)
00138         {
00139             text = QString();
00140             visit(node);
00141             return text;
00142         }
00143 
00144         QString text;
00145         DefaultNormalViewFormatter* parent;
00146 };
00147 
00148 QString DefaultNormalViewFormatter::formatArticle(const Article& article, IconOption icon) const
00149 {
00150     QString text;
00151     text = QString("<div class=\"headerbox\" dir=\"%1\">\n").arg(QApplication::isRightToLeft() ? "rtl" : "ltr");
00152 
00153     if (!article.title().isEmpty())
00154     {
00155         text += QString("<div class=\"headertitle\" dir=\"%1\">\n").arg(Utils::directionOf(Utils::stripTags(article.title())));
00156         if (article.link().isValid())
00157             text += "<a href=\""+article.link().url()+"\">";
00158         text += article.title().replace("<", "&lt;").replace(">", "&gt;"); // TODO: better leave things escaped in the parser
00159         if (article.link().isValid())
00160             text += "</a>";
00161         text += "</div>\n";
00162     }
00163     if (article.pubDate().isValid())
00164     {
00165         text += QString("<span class=\"header\" dir=\"%1\">").arg(Utils::directionOf(i18n("Date")));
00166         text += QString ("%1:").arg(i18n("Date"));
00167         text += "</span><span class=\"headertext\">";
00168         text += KGlobal::locale()->formatDateTime(article.pubDate(), KLocale::LongDate, false)+"</span>\n"; // TODO: might need RTL?
00169     }
00170     const QString author = article.authorAsHtml();
00171     if (!author.isEmpty())
00172     {
00173         text += QString("<br/><span class=\"header\" dir=\"%1\">").arg(Utils::directionOf(i18n("Author")));
00174         text += QString ("%1:").arg(i18n("Author"));
00175         text += "</span><span class=\"headertext\">";
00176         text += author+"</span>\n"; // TODO: might need RTL?
00177     }
00178     text += "</div>\n"; // end headerbox
00179 
00180 
00181     if (icon == ShowIcon && article.feed() && !article.feed()->image().isNull())
00182     {
00183         const Feed* feed = article.feed();
00184         QString file = Utils::fileNameForUrl(feed->xmlUrl());
00185         KUrl u(m_imageDir);
00186         u.setFileName(file);
00187         text += QString("<a href=\"%1\"><img class=\"headimage\" src=\"%2.png\"></a>\n").arg(feed->htmlUrl(), u.url());
00188     }
00189 
00190     const QString content = article.content( Article::DescriptionAsFallback );
00191     if (!content.isEmpty())
00192     {
00193         text += QString("<div dir=\"%1\">").arg(Utils::directionOf(Utils::stripTags(content)) );
00194         text += "<span class=\"content\">"+content+"</span>";
00195         text += "</div>";
00196     }
00197 
00198     text += "<div class=\"body\">";
00199 
00200     if (article.commentsLink().isValid())
00201     {
00202         text += "<a class=\"contentlink\" href=\"";
00203         text += article.commentsLink().url();
00204         text += "\">" + i18n( "Comments");
00205         if (article.comments())
00206         {
00207             text += " ("+ QString::number(article.comments()) +')';
00208         }
00209         text += "</a>";
00210     }
00211 
00212     if (article.link().isValid() || (article.guidIsPermaLink() && KUrl(article.guid()).isValid()))
00213     {
00214         text += "<p><a class=\"contentlink\" href=\"";
00215         // in case link isn't valid, fall back to the guid permaLink.
00216         if (article.link().isValid())
00217         {
00218             text += article.link().url();
00219         }
00220         else
00221         {
00222             text += article.guid();
00223         }
00224         text += "\">" + i18n( "Complete Story" ) + "</a></p>";
00225     }
00226     text += "</div>";
00227 
00228 
00229 //    if (!article.enclosure().isNull())
00230   //  {
00231         //QString url = article.enclosure().url();
00232         //QString type = article.enclosure().type();
00233         //int length = article.enclosure().length();
00234         //QString lengthStr = KIO::convertSize(length);
00235 
00236         //text += QString("<hr><div><a href=\"%1\">%2</a> (%3, %4)</div>").arg(url).arg(url).arg(lengthStr).arg(type);
00237    // }
00238     //kDebug() << text;
00239     return text;
00240 }
00241 
00242 QString DefaultNormalViewFormatter::getCss() const
00243 {
00244     const QPalette & pal = QApplication::palette();
00245 
00246     // from kmail::headerstyle.cpp
00247     QString css = QString (
00248             "<style type=\"text/css\">\n"
00249             "@media screen, print {"
00250             "body {\n"
00251             "  font-family: \"%1\" ! important;\n"
00252             "  font-size: %2 ! important;\n"
00253             "  color: %3 ! important;\n"
00254             "  background: %4 ! important;\n"
00255             "}\n\n")
00256             .arg( Settings::standardFont(),
00257                   QString::number(pointsToPixel(Settings::mediumFontSize()))+"px",
00258                   pal.color( QPalette::Text ).name(),
00259                   pal.color( QPalette::Base ).name() );
00260     css += (
00261             "a {\n"
00262             + QString("  color: %1 ! important;\n")
00263             + QString(!Settings::underlineLinks() ? " text-decoration: none ! important;\n" : "")
00264             +       "}\n\n"
00265             +".headerbox {\n"
00266             +"  background: %2 ! important;\n"
00267             +"  color: %3 ! important;\n"
00268             +"  border:1px solid #000;\n"
00269             +"  margin-bottom: 10pt;\n"
00270             +        "}\n\n")
00271             .arg( pal.color( QPalette::Link ).name(),
00272                   pal.color( QPalette::Background ).name(),
00273                   pal.color( QPalette::Text ).name() );
00274     css += QString(".headertitle a:link { color: %1 ! important;\n text-decoration: none ! important;\n }\n"
00275             ".headertitle a:visited { color: %1 ! important;\n text-decoration: none ! important;\n }\n"
00276             ".headertitle a:hover{ color: %1 ! important;\n text-decoration: none ! important;\n }\n"
00277             ".headertitle a:active { color: %1 ! important;\n  text-decoration: none ! important;\n }\n" )
00278             .arg( pal.color( QPalette::HighlightedText ).name() );
00279     css += QString(
00280             ".headertitle {\n"
00281             "  background: %1 ! important;\n"
00282             "  padding:2px;\n"
00283             "  color: %2 ! important;\n"
00284             "  font-weight: bold;\n"
00285             "  text-decoration: none ! important;\n"
00286             "}\n\n"
00287             ".header {\n"
00288             "  font-weight: bold;\n"
00289             "  padding:2px;\n"
00290             "  margin-right: 5px;\n"
00291             "  text-decoration: none ! important;\n"
00292             "}\n\n"
00293             ".headertext a {\n"
00294             "  text-decoration: none ! important;\n"
00295             "}\n\n"
00296             ".headimage {\n"
00297             "  float: right;\n"
00298             "  margin-left: 5px;\n"
00299             "}\n\n").arg(
00300                     pal.color( QPalette::Highlight ).name(),
00301                     pal.color( QPalette::HighlightedText ).name() );
00302 
00303     css += QString(
00304             "body { clear: none; }\n\n"
00305             ".content {\n"
00306             "  display: block;\n"
00307             "  margin-bottom: 6px;\n"
00308             "}\n\n"
00309     // these rules make sure that there is no leading space between the header and the first of the text
00310             ".content > P:first-child {\n margin-top: 1px; }\n"
00311             ".content > DIV:first-child {\n margin-top: 1px; }\n"
00312             ".content > BR:first-child {\n display: none;  }\n"
00313     //".contentlink {\n display: block; }\n"
00314             "}\n\n" // @media screen, print
00315     // Why did we need that, bug #108187?
00316     //"@media screen { body { overflow: auto; } }\n"
00317             "\n\n");
00318 
00319     return css;
00320 }
00321 
00322 DefaultCombinedViewFormatter::DefaultCombinedViewFormatter(const KUrl& imageDir, QPaintDevice* device ) : ArticleFormatter( device ), m_imageDir(imageDir)
00323 {
00324 }
00325 
00326 DefaultNormalViewFormatter::DefaultNormalViewFormatter(const KUrl& imageDir, QPaintDevice* device )
00327     : ArticleFormatter( device ),
00328     m_imageDir( imageDir ),
00329     m_summaryVisitor( new SummaryVisitor( this ) )
00330 {
00331 }
00332 
00333 DefaultNormalViewFormatter::~DefaultNormalViewFormatter()
00334 {
00335     delete m_summaryVisitor;
00336 }
00337 
00338 QString DefaultCombinedViewFormatter::formatArticle(const Article& article, IconOption icon) const
00339 {
00340     QString text;
00341     text = QString("<div class=\"headerbox\" dir=\"%1\">\n").arg(QApplication::isRightToLeft() ? "rtl" : "ltr");
00342 
00343     if (!article.title().isEmpty())
00344     {
00345         text += QString("<div class=\"headertitle\" dir=\"%1\">\n").arg(Utils::directionOf(Utils::stripTags(article.title())));
00346         if (article.link().isValid())
00347             text += "<a href=\""+article.link().url()+"\">";
00348         text += article.title().replace("<", "&lt;").replace(">", "&gt;"); // TODO: better leave things escaped in the parser
00349         if (article.link().isValid())
00350             text += "</a>";
00351         text += "</div>\n";
00352     }
00353     if (article.pubDate().isValid())
00354     {
00355         text += QString("<span class=\"header\" dir=\"%1\">").arg(Utils::directionOf(i18n("Date")));
00356         text += QString ("%1:").arg(i18n("Date"));
00357         text += "</span><span class=\"headertext\">";
00358         text += KGlobal::locale()->formatDateTime(article.pubDate(), KLocale::LongDate, false)+"</span>\n"; // TODO: might need RTL?
00359     }
00360 
00361     const QString author = article.authorAsHtml();
00362     if (!author.isEmpty())
00363     {
00364         text += QString("<br/><span class=\"header\" dir=\"%1\">").arg(Utils::directionOf(i18n("Author")));
00365         text += QString ("%1:").arg(i18n("Author"));
00366         text += "</span><span class=\"headertext\">";
00367         text += author+"</span>\n"; // TODO: might need RTL?
00368     }
00369 
00370     text += "</div>\n"; // end headerbox
00371 
00372     if (icon == ShowIcon && article.feed() && !article.feed()->image().isNull())
00373     {
00374         const Feed* feed = article.feed();
00375         QString file = Utils::fileNameForUrl(feed->xmlUrl());
00376         KUrl u(m_imageDir);
00377         u.setFileName(file);
00378         text += QString("<a href=\"%1\"><img class=\"headimage\" src=\"%2.png\"></a>\n").arg(feed->htmlUrl(), u.url());
00379     }
00380 
00381 
00382     const QString content = article.content( Article::DescriptionAsFallback );
00383     if (!content.isEmpty())
00384     {
00385         text += QString("<div dir=\"%1\">").arg(Utils::directionOf(Utils::stripTags(content)) );
00386         text += "<span class=\"content\">"+content+"</span>";
00387         text += "</div>";
00388     }
00389 
00390     text += "<div class=\"body\">";
00391 
00392     if (article.commentsLink().isValid())
00393     {
00394         text += "<a class=\"contentlink\" href=\"";
00395         text += article.commentsLink().url();
00396         text += "\">" + i18n( "Comments");
00397         if (article.comments())
00398         {
00399             text += " ("+ QString::number(article.comments()) +')';
00400         }
00401         text += "</a>";
00402     }
00403 
00404     if (article.link().isValid() || (article.guidIsPermaLink() && KUrl(article.guid()).isValid()))
00405     {
00406         text += "<p><a class=\"contentlink\" href=\"";
00407         // in case link isn't valid, fall back to the guid permaLink.
00408         if (article.link().isValid())
00409         {
00410             text += article.link().url();
00411         }
00412         else
00413         {
00414             text += article.guid();
00415         }
00416         text += "\">" + i18n( "Complete Story" ) + "</a></p>";
00417     }
00418     text += "</div>";
00419     //kDebug() << text;
00420     return text;
00421 }
00422 
00423 QString DefaultCombinedViewFormatter::getCss() const
00424 {
00425     const QPalette &pal = QApplication::palette();
00426 
00427     // from kmail::headerstyle.cpp
00428     QString css = QString (
00429             "<style type=\"text/css\">\n"
00430             "@media screen, print {"
00431             "body {\n"
00432             "  font-family: \"%1\" ! important;\n"
00433             "  font-size: %2 ! important;\n"
00434             "  color: %3 ! important;\n"
00435             "  background: %4 ! important;\n"
00436             "}\n\n").arg(Settings::standardFont(),
00437                          QString::number(pointsToPixel(Settings::mediumFontSize()))+"px",
00438                          pal.color( QPalette::Text ).name(),
00439                          pal.color( QPalette::Base ).name() );
00440     css += (
00441             "a {\n"
00442             + QString("  color: %1 ! important;\n")
00443             + QString(!Settings::underlineLinks() ? " text-decoration: none ! important;\n" : "")
00444             +       "}\n\n"
00445             +".headerbox {\n"
00446             +"  background: %2 ! important;\n"
00447             +"  color: %3 ! important;\n"
00448             +"  border:1px solid #000;\n"
00449             +"  margin-bottom: 10pt;\n"
00450 //    +"  width: 99%;\n"
00451             +        "}\n\n")
00452             .arg( pal.color( QPalette::Link ).name(),
00453                   pal.color( QPalette::Background ).name(),
00454                   pal.color( QPalette::Text ).name() );
00455 
00456     css += QString(".headertitle a:link { color: %1  ! important; text-decoration: none ! important;\n }\n"
00457             ".headertitle a:visited { color: %1 ! important; text-decoration: none ! important;\n }\n"
00458             ".headertitle a:hover{ color: %1 ! important; text-decoration: none ! important;\n }\n"
00459             ".headertitle a:active { color: %1 ! important; text-decoration: none ! important;\n }\n")
00460             .arg( pal.color( QPalette::HighlightedText ).name() );
00461     css += QString(
00462             ".headertitle {\n"
00463             "  background: %1 ! important;\n"
00464             "  padding:2px;\n"
00465             "  color: %2 ! important;\n"
00466             "  font-weight: bold;\n"
00467             "  text-decoration: none ! important;\n"
00468             "}\n\n"
00469             ".header {\n"
00470             "  font-weight: bold;\n"
00471             "  padding:2px;\n"
00472             "  margin-right: 5px;\n"
00473             "  text-decoration: none ! important;\n"
00474             "}\n\n"
00475             ".headertext {\n"
00476             "  text-decoration: none ! important;\n"
00477             "}\n\n"
00478             ".headimage {\n"
00479             "  float: right;\n"
00480             "  margin-left: 5px;\n"
00481             "}\n\n").arg( pal.color( QPalette::Highlight ).name(),
00482                           pal.color( QPalette::HighlightedText ).name() );
00483 
00484     css += QString(
00485             "body { clear: none; }\n\n"
00486             ".content {\n"
00487             "  display: block;\n"
00488             "  margin-bottom: 6px;\n"
00489             "}\n\n"
00490     // these rules make sure that there is no leading space between the header and the first of the text
00491             ".content > P:first-child {\n margin-top: 1px; }\n"
00492             ".content > DIV:first-child {\n margin-top: 1px; }\n"
00493             ".content > BR:first-child {\n display: none;  }\n"
00494     //".contentlink {\n display: block; }\n"
00495             "}\n\n" // @media screen, print
00496     // Why did we need that, bug #108187?
00497     //"@media screen { body { overflow: auto; } }\n"
00498             "\n\n");
00499 
00500     return css;
00501 }
00502 
00503 QString DefaultNormalViewFormatter::formatSummary(TreeNode* node) const
00504 {
00505     return m_summaryVisitor->formatSummary(node);
00506 }
00507 
00508 QString DefaultCombinedViewFormatter::formatSummary(TreeNode*) const
00509 {
00510     return QString();
00511 }
00512 
00513 } // namespace Akregator

akregator

Skip menu "akregator"
  • Main Page
  • Namespace List
  • Class Hierarchy
  • Alphabetical List
  • Class List
  • File List
  • Namespace Members
  • Class Members

kdepim

Skip menu "kdepim"
  • akonadi
  •   clients
  •   kabc
  •   kcal
  •   kcm
  • akregator
  • console
  •   kabcclient
  •   konsolekalendar
  • kaddressbook
  • kalarm
  •   lib
  • kdgantt
  • kdgantt1
  • kjots
  • kleopatra
  • kmail
  • kmobiletools
  • knode
  • knotes
  • kontact
  • kontactinterfaces
  • korganizer
  •   korgac
  • kpilot
  • ktimetracker
  •   doc
  • libkdepim
  • libkholidays
  • libkleo
  • libkpgp
  • maildir
Generated for kdepim by doxygen 1.5.4
This website is maintained by Adriaan de Groot and Allen Winter.
KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal