00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025 #include <qdatetime.h>
00026 #include <qevent.h>
00027 #include <qscrollview.h>
00028 #include <qvaluelist.h>
00029
00030 #include <kaction.h>
00031 #include <kapplication.h>
00032 #include <kdebug.h>
00033 #include <kglobalsettings.h>
00034 #include <khtmlview.h>
00035 #include <klocale.h>
00036 #include <kprocess.h>
00037 #include <krun.h>
00038 #include <kstandarddirs.h>
00039 #include <kshell.h>
00040 #include <kmessagebox.h>
00041 #include <kio/netaccess.h>
00042 #include <libkdepim/kfileio.h>
00043
00044 #include "aboutdata.h"
00045 #include "akregator_run.h"
00046 #include "akregatorconfig.h"
00047 #include "articleviewer.h"
00048 #include "feed.h"
00049 #include "folder.h"
00050 #include "article.h"
00051 #include "treenode.h"
00052 #include "treenodevisitor.h"
00053 #include "tagnode.h"
00054 #include "utils.h"
00055
00056 namespace Akregator {
00057
00058
00059 static inline QString directionOf(const QString &str)
00060 {
00061 return str.isRightToLeft() ? "rtl" : "ltr" ;
00062 }
00063
00064 class ArticleViewer::ShowSummaryVisitor : public TreeNodeVisitor
00065 {
00066 public:
00067
00068 ShowSummaryVisitor(ArticleViewer* view) : m_view(view) {}
00069
00070 virtual bool visitFeed(Feed* node)
00071 {
00072 m_view->m_link = QString();
00073
00074 QString text;
00075 text = QString("<div class=\"headerbox\" dir=\"%1\">\n").arg(QApplication::reverseLayout() ? "rtl" : "ltr");
00076
00077 text += QString("<div class=\"headertitle\" dir=\"%1\">").arg(directionOf(Utils::stripTags(node->title())));
00078 text += node->title();
00079 if(node->unread() == 0)
00080 text += i18n(" (no unread articles)");
00081 else
00082 text += i18n(" (1 unread article)", " (%n unread articles)", node->unread());
00083 text += "</div>\n";
00084 text += "</div>\n";
00085
00086 if (!node->image().isNull())
00087 {
00088 text += QString("<div class=\"body\">");
00089 QString url=node->xmlUrl();
00090 QString file = url.replace("/", "_").replace(":", "_");
00091 KURL u(m_view->m_imageDir);
00092 u.setFileName(file);
00093 text += QString("<a href=\"%1\"><img class=\"headimage\" src=\"%2.png\"></a>\n").arg(node->htmlUrl()).arg(u.url());
00094 }
00095 else text += "<div class=\"body\">";
00096
00097
00098 if( !node->description().isEmpty() )
00099 {
00100 text += QString("<div dir=\"%1\">").arg(Utils::stripTags(directionOf(node->description())));
00101 text += i18n("<b>Description:</b> %1<br><br>").arg(node->description());
00102 text += "</div>\n";
00103 }
00104
00105 if ( !node->htmlUrl().isEmpty() )
00106 {
00107 text += QString("<div dir=\"%1\">").arg(directionOf(node->htmlUrl()));
00108 text += i18n("<b>Homepage:</b> <a href=\"%1\">%2</a>").arg(node->htmlUrl()).arg(node->htmlUrl());
00109 text += "</div>\n";
00110 }
00111
00112
00113 text += "</div>";
00114
00115 m_view->renderContent(text);
00116 return true;
00117 }
00118
00119 virtual bool visitFolder(Folder* node)
00120 {
00121 m_view->m_link = QString();
00122
00123 QString text;
00124 text = QString("<div class=\"headerbox\" dir=\"%1\">\n").arg(QApplication::reverseLayout() ? "rtl" : "ltr");
00125 text += QString("<div class=\"headertitle\" dir=\"%1\">%2").arg(directionOf(Utils::stripTags(node->title()))).arg(node->title());
00126 if(node->unread() == 0)
00127 text += i18n(" (no unread articles)");
00128 else
00129 text += i18n(" (1 unread article)", " (%n unread articles)", node->unread());
00130 text += QString("</div>\n");
00131 text += "</div>\n";
00132
00133 m_view->renderContent(text);
00134 return true;
00135 }
00136
00137 virtual bool visitTagNode(TagNode* node)
00138 {
00139 m_view->m_link = QString();
00140
00141 QString text;
00142 text = QString("<div class=\"headerbox\" dir=\"%1\">\n").arg(QApplication::reverseLayout() ? "rtl" : "ltr");
00143 text += QString("<div class=\"headertitle\" dir=\"%1\">%2").arg(directionOf(Utils::stripTags(node->title()))).arg(node->title());
00144 if(node->unread() == 0)
00145 text += i18n(" (no unread articles)");
00146 else
00147 text += i18n(" (1 unread article)", " (%n unread articles)", node->unread());
00148 text += QString("</div>\n");
00149 text += "</div>\n";
00150
00151 m_view->renderContent(text);
00152 return true;
00153 }
00154
00155 private:
00156
00157 ArticleViewer* m_view;
00158 };
00159
00160 ArticleViewer::ArticleViewer(QWidget *parent, const char *name)
00161 : Viewer(parent, name), m_htmlFooter(), m_currentText(), m_node(0), m_viewMode(NormalView)
00162 {
00163 m_showSummaryVisitor = new ShowSummaryVisitor(this);
00164 setXMLFile(locate("data", "akregator/articleviewer.rc"), true);
00165
00166 generateNormalModeCSS();
00167 generateCombinedModeCSS();
00168 new KAction( i18n("&Scroll Up"), QString::null, "Up", this, SLOT(slotScrollUp()), actionCollection(), "articleviewer_scroll_up" );
00169 new KAction( i18n("&Scroll Down"), QString::null, "Down", this, SLOT(slotScrollDown()), actionCollection(), "articleviewer_scroll_down" );
00170
00171 connect(this, SIGNAL(selectionChanged()), this, SLOT(slotSelectionChanged()));
00172
00173 connect(kapp, SIGNAL(kdisplayPaletteChanged()), this, SLOT(slotPaletteOrFontChanged()) );
00174 connect(kapp, SIGNAL(kdisplayFontChanged()), this, SLOT(slotPaletteOrFontChanged()) );
00175
00176 m_imageDir.setPath(KGlobal::dirs()->saveLocation("cache", "akregator/Media/"));
00177 m_htmlFooter = "</body></html>";
00178 }
00179
00180 ArticleViewer::~ArticleViewer()
00181 {
00182 delete m_showSummaryVisitor;
00183 }
00184
00185 void ArticleViewer::generateNormalModeCSS()
00186 {
00187 const QColorGroup & cg = QApplication::palette().active();
00188
00189
00190 m_normalModeCSS = QString (
00191 "<style type=\"text/css\">\n"
00192 "@media screen, print {"
00193 "body {\n"
00194 " font-family: \"%1\" ! important;\n"
00195 " font-size: %2 ! important;\n"
00196 " color: %3 ! important;\n"
00197 " background: %4 ! important;\n"
00198 "}\n\n").arg(Settings::standardFont())
00199 .arg(QString::number(pointsToPixel(Settings::mediumFontSize()))+"px")
00200 .arg(cg.text().name())
00201 .arg(cg.base().name());
00202 m_normalModeCSS += (
00203 "a {\n"
00204 + QString(" color: %1 ! important;\n")
00205 + QString(!Settings::underlineLinks() ? " text-decoration: none ! important;\n" : "")
00206 + "}\n\n"
00207 +".headerbox {\n"
00208 +" background: %2 ! important;\n"
00209 +" color: %3 ! important;\n"
00210 +" border:1px solid #000;\n"
00211 +" margin-bottom: 10pt;\n"
00212
00213 + "}\n\n")
00214 .arg(cg.link().name())
00215 .arg(cg.background().name())
00216 .arg(cg.text().name());
00217
00218 m_normalModeCSS += QString(".headertitle a:link { color: %1 ! important; }\n"
00219 ".headertitle a:visited { color: %2 ! important; }\n"
00220 ".headertitle a:hover{ color: %3 ! important; }\n"
00221 ".headertitle a:active { color: %4 ! important; }\n")
00222 .arg(cg.highlightedText().name())
00223 .arg(cg.highlightedText().name())
00224 .arg(cg.highlightedText().name())
00225 .arg(cg.highlightedText().name());
00226 m_normalModeCSS += QString(
00227 ".headertitle {\n"
00228 " background: %1 ! important;\n"
00229 " padding:2px;\n"
00230 " color: %2 ! important;\n"
00231 " font-weight: bold;\n"
00232 "}\n\n"
00233 ".header {\n"
00234 " font-weight: bold;\n"
00235 " padding:2px;\n"
00236 " margin-right: 5px;\n"
00237 "}\n\n"
00238 ".headertext {\n"
00239 "}\n\n"
00240 ".headimage {\n"
00241 " float: right;\n"
00242 " margin-left: 5px;\n"
00243 "}\n\n").arg(cg.highlight().name())
00244 .arg(cg.highlightedText().name());
00245
00246 m_normalModeCSS += QString(
00247 "body { clear: none; }\n\n"
00248 ".content {\n"
00249 " display: block;\n"
00250 " margin-bottom: 6px;\n"
00251 "}\n\n"
00252
00253 ".content > P:first-child {\n margin-top: 1px; }\n"
00254 ".content > DIV:first-child {\n margin-top: 1px; }\n"
00255 ".content > BR:first-child {\n display: none; }\n"
00256
00257 "}\n\n"
00258
00259
00260 "\n\n");
00261 }
00262
00263 void ArticleViewer::generateCombinedModeCSS()
00264 {
00265 const QColorGroup & cg = QApplication::palette().active();
00266
00267
00268 m_combinedModeCSS = QString (
00269 "<style type=\"text/css\">\n"
00270 "@media screen, print {"
00271 "body {\n"
00272 " font-family: \"%1\" ! important;\n"
00273 " font-size: %2 ! important;\n"
00274 " color: %3 ! important;\n"
00275 " background: %4 ! important;\n"
00276 "}\n\n").arg(Settings::standardFont())
00277 .arg(QString::number(pointsToPixel(Settings::mediumFontSize()))+"px")
00278 .arg(cg.text().name())
00279 .arg(cg.base().name());
00280 m_combinedModeCSS += (
00281 "a {\n"
00282 + QString(" color: %1 ! important;\n")
00283 + QString(!Settings::underlineLinks() ? " text-decoration: none ! important;\n" : "")
00284 + "}\n\n"
00285 +".headerbox {\n"
00286 +" background: %2 ! important;\n"
00287 +" color: %3 ! important;\n"
00288 +" border:1px solid #000;\n"
00289 +" margin-bottom: 10pt;\n"
00290
00291 + "}\n\n")
00292 .arg(cg.link().name())
00293 .arg(cg.background().name())
00294 .arg(cg.text().name());
00295
00296 m_combinedModeCSS += QString(".headertitle a:link { color: %1 ! important; }\n"
00297 ".headertitle a:visited { color: %2 ! important; }\n"
00298 ".headertitle a:hover{ color: %3 ! important; }\n"
00299 ".headertitle a:active { color: %4 ! important; }\n")
00300 .arg(cg.highlightedText().name())
00301 .arg(cg.highlightedText().name())
00302 .arg(cg.highlightedText().name())
00303 .arg(cg.highlightedText().name());
00304 m_combinedModeCSS += QString(
00305 ".headertitle {\n"
00306 " background: %1 ! important;\n"
00307 " padding:2px;\n"
00308 " color: %2 ! important;\n"
00309 " font-weight: bold;\n"
00310 "}\n\n"
00311 ".header {\n"
00312 " font-weight: bold;\n"
00313 " padding:2px;\n"
00314 " margin-right: 5px;\n"
00315 "}\n\n"
00316 ".headertext {\n"
00317 "}\n\n"
00318 ".headimage {\n"
00319 " float: right;\n"
00320 " margin-left: 5px;\n"
00321 "}\n\n").arg(cg.highlight().name())
00322 .arg(cg.highlightedText().name());
00323
00324 m_combinedModeCSS += QString(
00325 "body { clear: none; }\n\n"
00326 ".content {\n"
00327 " display: block;\n"
00328 " margin-bottom: 6px;\n"
00329 "}\n\n"
00330
00331 ".content > P:first-child {\n margin-top: 1px; }\n"
00332 ".content > DIV:first-child {\n margin-top: 1px; }\n"
00333 ".content > BR:first-child {\n display: none; }\n"
00334
00335 "}\n\n"
00336
00337
00338 "\n\n");
00339 }
00340
00341 void ArticleViewer::reload()
00342 {
00343 beginWriting();
00344 write(m_currentText);
00345 endWriting();
00346 }
00347
00348 bool ArticleViewer::openURL(const KURL& url)
00349 {
00350 if (!m_article.isNull() && m_article.feed()->loadLinkedWebsite())
00351 {
00352 return Viewer::openURL(url);
00353 }
00354 else
00355 {
00356 reload();
00357 return true;
00358 }
00359 }
00360
00361 void ArticleViewer::displayAboutPage()
00362 {
00363 QString location = locate("data", "akregator/about/main.html");
00364 QString content = KPIM::kFileToString(location);
00365 content = content.arg( locate( "data", "libkdepim/about/kde_infopage.css" ) );
00366 if ( kapp->reverseLayout() )
00367 content = content.arg( "@import \"%1\";" ).arg( locate( "data", "libkdepim/about/kde_infopage_rtl.css" ) );
00368 else
00369 content = content.arg( "" );
00370
00371 begin(KURL( location ));
00372 QString info =
00373 i18n("%1: Akregator version; %2: help:// URL; %3: homepage URL; "
00374 "--- end of comment ---",
00375 "<h2 style='margin-top: 0px;'>Welcome to Akregator %1</h2>"
00376 "<p>Akregator is an RSS feed aggregator for the K Desktop Environment. "
00377 "Feed aggregators provide a convenient way to browse different kinds of "
00378 "content, including news, blogs, and other content from online sites. "
00379 "Instead of checking all your favorite web sites manually for updates, "
00380 "Akregator collects the content for you.</p>"
00381 "<p>For more information about using Akregator, check the "
00382 "<a href=\"%3\">Akregator website</a>. If you do not want to see this page anymore, <a href=\"config:/disable_introduction\">click here</a>.</p>"
00383 "<p>We hope that you will enjoy Akregator.</p>\n"
00384 "<p>Thank you,</p>\n"
00385 "<p style='margin-bottom: 0px'> The Akregator Team</p>\n")
00386 .arg(AKREGATOR_VERSION)
00387 .arg("http://akregator.sourceforge.net/");
00388
00389 QString fontSize = QString::number( pointsToPixel( Settings::mediumFontSize() ));
00390 QString appTitle = i18n("Akregator");
00391 QString catchPhrase = "";
00392 QString quickDescription = i18n("An RSS feed reader for the K Desktop Environment.");
00393 write(content.arg(fontSize).arg(appTitle).arg(catchPhrase).arg(quickDescription).arg(info));
00394 end();
00395 }
00396
00397 QString ArticleViewer::formatArticleNormalMode(Feed* feed, const Article& article)
00398 {
00399 QString text;
00400 text = QString("<div class=\"headerbox\" dir=\"%1\">\n").arg(QApplication::reverseLayout() ? "rtl" : "ltr");
00401
00402 if (!article.title().isEmpty())
00403 {
00404 text += QString("<div class=\"headertitle\" dir=\"%1\">\n").arg(directionOf(Utils::stripTags(article.title())));
00405 if (article.link().isValid())
00406 text += "<a href=\""+article.link().url()+"\">";
00407 text += article.title().replace("<", "<").replace(">", ">");
00408 if (article.link().isValid())
00409 text += "</a>";
00410 text += "</div>\n";
00411 }
00412 if (article.pubDate().isValid())
00413 {
00414 text += QString("<span class=\"header\" dir=\"%1\">").arg(directionOf(i18n("Date")));
00415 text += QString ("%1:").arg(i18n("Date"));
00416 text += "</span><span class=\"headertext\">";
00417 text += KGlobal::locale()->formatDateTime(article.pubDate(), false, false)+"</span>\n";
00418 }
00419 QString author = article.author();
00420 if (!author.isEmpty())
00421 {
00422 text += QString("<br/><span class=\"header\" dir=\"%1\">").arg(directionOf(i18n("Author")));
00423 text += QString ("%1:").arg(i18n("Author"));
00424 text += "</span><span class=\"headertext\">";
00425 text += author+"</span>\n";
00426 }
00427 text += "</div>\n";
00428
00429 if (feed && !feed->image().isNull())
00430 {
00431 QString url=feed->xmlUrl();
00432 QString file = url.replace("/", "_").replace(":", "_");
00433 KURL u(m_imageDir);
00434 u.setFileName(file);
00435 text += QString("<a href=\"%1\"><img class=\"headimage\" src=\"%2.png\"></a>\n").arg(feed->htmlUrl()).arg(u.url());
00436 }
00437
00438
00439
00440 if (!article.description().isEmpty())
00441 {
00442 text += QString("<div dir=\"%1\">").arg(directionOf(Utils::stripTags(article.description())) );
00443 text += "<span class=\"content\">"+article.description()+"</span>";
00444 text += "</div>";
00445 }
00446
00447 text += "<div class=\"body\">";
00448
00449 if (article.commentsLink().isValid())
00450 {
00451 text += "<a class=\"contentlink\" href=\"";
00452 text += article.commentsLink().url();
00453 text += "\">" + i18n( "Comments");
00454 if (article.comments())
00455 {
00456 text += " ("+ QString::number(article.comments()) +")";
00457 }
00458 text += "</a>";
00459 }
00460
00461 if (article.link().isValid() || (article.guidIsPermaLink() && KURL(article.guid()).isValid()))
00462 {
00463 text += "<p><a class=\"contentlink\" href=\"";
00464
00465 if (article.link().isValid())
00466 {
00467 text += article.link().url();
00468 }
00469 else
00470 {
00471 text += article.guid();
00472 }
00473 text += "\">" + i18n( "Complete Story" ) + "</a></p>";
00474 }
00475 text += "</div>";
00476
00477 if (!article.enclosure().isNull())
00478 {
00479
00480
00481
00482
00483
00484
00485 }
00486
00487 return text;
00488
00489 }
00490
00491 QString ArticleViewer::formatArticleCombinedMode(Feed* feed, const Article& article)
00492 {
00493 QString text;
00494 text = QString("<div class=\"headerbox\" dir=\"%1\">\n").arg(QApplication::reverseLayout() ? "rtl" : "ltr");
00495
00496 if (!article.title().isEmpty())
00497 {
00498 text += QString("<div class=\"headertitle\" dir=\"%1\">\n").arg(directionOf(Utils::stripTags(article.title())));
00499 if (article.link().isValid())
00500 text += "<a href=\""+article.link().url()+"\">";
00501 text += article.title().replace("<", "<").replace(">", ">");
00502 if (article.link().isValid())
00503 text += "</a>";
00504 text += "</div>\n";
00505 }
00506 if (article.pubDate().isValid())
00507 {
00508 text += QString("<span class=\"header\" dir=\"%1\">").arg(directionOf(i18n("Date")));
00509 text += QString ("%1:").arg(i18n("Date"));
00510 text += "</span><span class=\"headertext\">";
00511 text += KGlobal::locale()->formatDateTime(article.pubDate(), false, false)+"</span>\n";
00512 }
00513
00514 QString author = article.author();
00515 if (!author.isEmpty())
00516 {
00517 text += QString("<br/><span class=\"header\" dir=\"%1\">").arg(directionOf(i18n("Author")));
00518 text += QString ("%1:").arg(i18n("Author"));
00519 text += "</span><span class=\"headertext\">";
00520 text += author+"</span>\n";
00521 }
00522
00523 text += "</div>\n";
00524
00525 if (feed && !feed->image().isNull())
00526 {
00527 QString url=feed->xmlUrl();
00528 QString file = url.replace("/", "_").replace(":", "_");
00529 KURL u(m_imageDir);
00530 u.setFileName(file);
00531 text += QString("<a href=\"%1\"><img class=\"headimage\" src=\"%2.png\"></a>\n").arg(feed->htmlUrl()).arg(u.url());
00532 }
00533
00534
00535
00536 if (!article.description().isEmpty())
00537 {
00538 text += QString("<div dir=\"%1\">").arg(directionOf(Utils::stripTags(article.description())) );
00539 text += "<span class=\"content\">"+article.description()+"</span>";
00540 text += "</div>";
00541 }
00542
00543 text += "<div class=\"body\">";
00544
00545 if (article.commentsLink().isValid())
00546 {
00547 text += "<a class=\"contentlink\" href=\"";
00548 text += article.commentsLink().url();
00549 text += "\">" + i18n( "Comments");
00550 if (article.comments())
00551 {
00552 text += " ("+ QString::number(article.comments()) +")";
00553 }
00554 text += "</a>";
00555 }
00556
00557 if (article.link().isValid() || (article.guidIsPermaLink() && KURL(article.guid()).isValid()))
00558 {
00559 text += "<p><a class=\"contentlink\" href=\"";
00560
00561 if (article.link().isValid())
00562 {
00563 text += article.link().url();
00564 }
00565 else
00566 {
00567 text += article.guid();
00568 }
00569 text += "\">" + i18n( "Complete Story" ) + "</a></p>";
00570 }
00571 text += "</div>";
00572
00573 return text;
00574
00575 }
00576
00577 void ArticleViewer::renderContent(const QString& text)
00578 {
00579 closeURL();
00580 m_currentText = text;
00581 beginWriting();
00582
00583 write(text);
00584 endWriting();
00585 }
00586
00587 void ArticleViewer::beginWriting()
00588 {
00589 QString head = QString("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\">\n <html><head><title>.</title>");
00590
00591 if (m_viewMode == CombinedView)
00592 head += m_combinedModeCSS;
00593 else
00594 head += m_normalModeCSS;
00595
00596 head += "</style></head><body>";
00597 view()->setContentsPos(0,0);
00598 begin(m_link);
00599 write(head);
00600 }
00601
00602 void ArticleViewer::endWriting()
00603 {
00604 write(m_htmlFooter);
00605
00606 end();
00607 }
00608
00609 void ArticleViewer::slotShowSummary(TreeNode* node)
00610 {
00611 m_viewMode = SummaryView;
00612
00613 if (!node)
00614 {
00615 slotClear();
00616 return;
00617 }
00618
00619 if (node != m_node)
00620 {
00621 disconnectFromNode(m_node);
00622 connectToNode(node);
00623 m_node = node;
00624 }
00625 m_showSummaryVisitor->visit(node);
00626 }
00627
00628
00629 void ArticleViewer::slotShowArticle(const Article& article)
00630 {
00631 m_viewMode = NormalView;
00632 disconnectFromNode(m_node);
00633 m_article = article;
00634 m_node = 0;
00635 m_link = article.link();
00636 if (article.feed()->loadLinkedWebsite())
00637 openURL(article.link());
00638 else
00639 renderContent( formatArticleNormalMode(article.feed(), article) );
00640 }
00641
00642 void ArticleViewer::slotSetFilter(const Akregator::Filters::ArticleMatcher& textFilter, const Akregator::Filters::ArticleMatcher& statusFilter)
00643 {
00644 if (m_statusFilter == statusFilter && m_textFilter == textFilter)
00645 return;
00646
00647 m_textFilter = textFilter;
00648 m_statusFilter = statusFilter;
00649
00650 slotUpdateCombinedView();
00651 }
00652
00653 void ArticleViewer::slotUpdateCombinedView()
00654 {
00655 if (m_viewMode != CombinedView)
00656 return;
00657
00658 if (!m_node)
00659 return slotClear();
00660
00661 QValueList<Article> articles = m_node->articles();
00662 qHeapSort(articles);
00663 QValueList<Article>::ConstIterator end = articles.end();
00664 QValueList<Article>::ConstIterator it = articles.begin();
00665
00666 QString text;
00667
00668 int num = 0;
00669 QTime spent;
00670 spent.start();
00671
00672 for ( ; it != end; ++it)
00673 {
00674 if ( !(*it).isDeleted() && m_textFilter.matches(*it) && m_statusFilter.matches(*it) )
00675 {
00676 text += "<p><div class=\"article\">"+formatArticleCombinedMode(0, *it)+"</div><p>";
00677 ++num;
00678 }
00679 }
00680
00681 renderContent(text);
00682
00683
00684
00685 }
00686
00687 void ArticleViewer::slotArticlesUpdated(TreeNode* , const QValueList<Article>& )
00688 {
00689 if (m_viewMode == CombinedView)
00690 slotUpdateCombinedView();
00691 }
00692
00693 void ArticleViewer::slotArticlesAdded(TreeNode* , const QValueList<Article>& )
00694 {
00695 }
00696
00697 void ArticleViewer::slotArticlesRemoved(TreeNode* , const QValueList<Article>& )
00698 {
00699 }
00700
00701
00702
00703
00704
00705
00706
00707
00708
00709 void ArticleViewer::slotClear()
00710 {
00711 disconnectFromNode(m_node);
00712 m_node = 0;
00713 m_article = Article();
00714
00715 renderContent(QString());
00716 }
00717
00718 void ArticleViewer::slotShowNode(TreeNode* node)
00719 {
00720 m_viewMode = CombinedView;
00721
00722 if (node != m_node)
00723 disconnectFromNode(m_node);
00724
00725 connectToNode(node);
00726
00727 m_article = Article();
00728 m_node = node;
00729
00730 if (node && !node->articles().isEmpty())
00731 m_link = node->articles().first().link();
00732 else
00733 m_link = KURL();
00734
00735 slotUpdateCombinedView();
00736 }
00737
00738 void ArticleViewer::keyPressEvent(QKeyEvent* e)
00739 {
00740 e->ignore();
00741 }
00742
00743 void ArticleViewer::urlSelected(const QString &url, int button, int state, const QString& _target, KParts::URLArgs args)
00744 {
00745 if(url == "config:/disable_introduction") {
00746 if(KMessageBox::questionYesNo( widget(), i18n("Are you sure you want to disable this introduction page?"), i18n("Disable Introduction Page"), i18n("Disable"), i18n("Keep Enabled") ) == KMessageBox::Yes) {
00747 KConfig *conf = Settings::self()->config();
00748 conf->setGroup("General");
00749 conf->writeEntry("Disable Introduction", "true");
00750 }
00751 }
00752 else
00753 Viewer::urlSelected(url, button, state, _target, args);
00754 }
00755
00756 void ArticleViewer::slotPaletteOrFontChanged()
00757 {
00758 generateNormalModeCSS();
00759 generateCombinedModeCSS();
00760 reload();
00761 }
00762
00763 void ArticleViewer::connectToNode(TreeNode* node)
00764 {
00765 if (node)
00766 {
00767 if (m_viewMode == CombinedView)
00768 {
00769
00770 connect( node, SIGNAL(signalArticlesAdded(TreeNode*, const QValueList<Article>&)), this, SLOT(slotArticlesAdded(TreeNode*, const QValueList<Article>&)));
00771 connect( node, SIGNAL(signalArticlesRemoved(TreeNode*, const QValueList<Article>&)), this, SLOT(slotArticlesRemoved(TreeNode*, const QValueList<Article>&)));
00772 connect( node, SIGNAL(signalArticlesUpdated(TreeNode*, const QValueList<Article>&)), this, SLOT(slotArticlesUpdated(TreeNode*, const QValueList<Article>&)));
00773 }
00774 if (m_viewMode == SummaryView)
00775 connect( node, SIGNAL(signalChanged(TreeNode*)), this, SLOT(slotShowSummary(TreeNode*) ) );
00776
00777 connect( node, SIGNAL(signalDestroyed(TreeNode*)), this, SLOT(slotClear() ) );
00778 }
00779 }
00780
00781 void ArticleViewer::disconnectFromNode(TreeNode* node)
00782 {
00783 if (node)
00784 {
00785
00786 disconnect( node, SIGNAL(signalDestroyed(TreeNode*)), this, SLOT(slotClear() ) );
00787 disconnect( node, SIGNAL(signalChanged(TreeNode*)), this, SLOT(slotShowSummary(TreeNode*) ) );
00788 disconnect( node, SIGNAL(signalArticlesAdded(TreeNode*, const QValueList<Article>&)), this, SLOT(slotArticlesAdded(TreeNode*, const QValueList<Article>&)));
00789 disconnect( node, SIGNAL(signalArticlesRemoved(TreeNode*, const QValueList<Article>&)), this, SLOT(slotArticlesRemoved(TreeNode*, const QValueList<Article>&)));
00790 disconnect( node, SIGNAL(signalArticlesUpdated(TreeNode*, const QValueList<Article>&)), this, SLOT(slotArticlesUpdated(TreeNode*, const QValueList<Article>&)));
00791
00792 }
00793 }
00794
00795 }
00796 #include "articleviewer.moc"
00797