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 <tqdatetime.h>
00026 #include <tqevent.h>
00027 #include <tqscrollview.h>
00028 #include <tqvaluelist.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 TQString directionOf(const TQString &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 = TQString();
00073
00074 TQString text;
00075 text = TQString("<div class=\"headerbox\" dir=\"%1\">\n").arg(TQApplication::reverseLayout() ? "rtl" : "ltr");
00076
00077 text += TQString("<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 += TQString("<div class=\"body\">");
00089 TQString url=node->xmlUrl();
00090 TQString file = url.replace("/", "_").replace(":", "_");
00091 KURL u(m_view->m_imageDir);
00092 u.setFileName(file);
00093 text += TQString("<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 += TQString("<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 += TQString("<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 = TQString();
00122
00123 TQString text;
00124 text = TQString("<div class=\"headerbox\" dir=\"%1\">\n").arg(TQApplication::reverseLayout() ? "rtl" : "ltr");
00125 text += TQString("<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 += TQString("</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 = TQString();
00140
00141 TQString text;
00142 text = TQString("<div class=\"headerbox\" dir=\"%1\">\n").arg(TQApplication::reverseLayout() ? "rtl" : "ltr");
00143 text += TQString("<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 += TQString("</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(TQWidget *parent, const char *name)
00161 : Viewer(parent, name), m_htmlFooter(), m_currentText(), m_node(0), m_viewMode(NormalView)
00162 {
00163 setJScriptEnabled(false);
00164 setJavaEnabled(false);
00165 setPluginsEnabled(false);
00166
00167 m_showSummaryVisitor = new ShowSummaryVisitor(this);
00168 setXMLFile(locate("data", "akregator/articleviewer.rc"), true);
00169
00170 generateNormalModeCSS();
00171 generateCombinedModeCSS();
00172 new KAction( i18n("&Scroll Up"), TQString::null, "Up", this, TQT_SLOT(slotScrollUp()), actionCollection(), "articleviewer_scroll_up" );
00173 new KAction( i18n("&Scroll Down"), TQString::null, "Down", this, TQT_SLOT(slotScrollDown()), actionCollection(), "articleviewer_scroll_down" );
00174
00175 connect(this, TQT_SIGNAL(selectionChanged()), this, TQT_SLOT(slotSelectionChanged()));
00176
00177 connect(kapp, TQT_SIGNAL(kdisplayPaletteChanged()), this, TQT_SLOT(slotPaletteOrFontChanged()) );
00178 connect(kapp, TQT_SIGNAL(kdisplayFontChanged()), this, TQT_SLOT(slotPaletteOrFontChanged()) );
00179
00180 m_imageDir.setPath(KGlobal::dirs()->saveLocation("cache", "akregator/Media/"));
00181 m_htmlFooter = "</body></html>";
00182 }
00183
00184 ArticleViewer::~ArticleViewer()
00185 {
00186 delete m_showSummaryVisitor;
00187 }
00188
00189 void ArticleViewer::generateNormalModeCSS()
00190 {
00191 const TQColorGroup & cg = TQApplication::palette().active();
00192
00193
00194 m_normalModeCSS = TQString(
00195 "@media screen, print {"
00196 "body {\n"
00197 " font-family: \"%1\" ! important;\n"
00198 " font-size: %2 ! important;\n"
00199 " color: %3 ! important;\n"
00200 " background: %4 ! important;\n"
00201 "}\n\n").arg(Settings::standardFont())
00202 .arg(TQString::number(pointsToPixel(Settings::mediumFontSize()))+"px")
00203 .arg(cg.text().name())
00204 .arg(cg.base().name());
00205 m_normalModeCSS += TQString(
00206 "a {\n"
00207 + TQString(" color: %1 ! important;\n")
00208 + TQString(!Settings::underlineLinks() ? " text-decoration: none ! important;\n" : "")
00209 + "}\n\n"
00210 +".headerbox {\n"
00211 +" background: %2 ! important;\n"
00212 +" color: %3 ! important;\n"
00213 +" border:1px solid #000;\n"
00214 +" margin-bottom: 10pt;\n"
00215
00216 + "}\n\n")
00217 .arg(cg.link().name())
00218 .arg(cg.background().name())
00219 .arg(cg.text().name());
00220
00221 m_normalModeCSS += TQString(".headertitle a:link { color: %1 ! important; }\n"
00222 ".headertitle a:visited { color: %2 ! important; }\n"
00223 ".headertitle a:hover{ color: %3 ! important; }\n"
00224 ".headertitle a:active { color: %4 ! important; }\n")
00225 .arg(cg.highlightedText().name())
00226 .arg(cg.highlightedText().name())
00227 .arg(cg.highlightedText().name())
00228 .arg(cg.highlightedText().name());
00229
00230 m_normalModeCSS += TQString(
00231 ".headertitle {\n"
00232 " background: %1 ! important;\n"
00233 " padding:2px;\n"
00234 " color: %2 ! important;\n"
00235 " font-weight: bold;\n"
00236 "}\n\n"
00237 ".header {\n"
00238 " font-weight: bold;\n"
00239 " padding:2px;\n"
00240 " margin-right: 5px;\n"
00241 "}\n\n"
00242 ".headertext {\n"
00243 "}\n\n"
00244 ".headimage {\n"
00245 " float: right;\n"
00246 " margin-left: 5px;\n"
00247 "}\n\n").arg(cg.highlight().name())
00248 .arg(cg.highlightedText().name());
00249
00250 m_normalModeCSS += TQString(
00251 "body { clear: none; }\n\n"
00252 ".content {\n"
00253 " display: block;\n"
00254 " margin-bottom: 6px;\n"
00255 "}\n\n"
00256
00257 ".content > P:first-child {\n margin-top: 1px; }\n"
00258 ".content > DIV:first-child {\n margin-top: 1px; }\n"
00259 ".content > BR:first-child {\n display: none; }\n"
00260 "iframe {display: none !important; }\n"
00261 "frame {display: none !important; }\n"
00262 "frameset {display: none !important; }\n"
00263 "object {display: none !important; }\n"
00264 "applet {display: none !important; }\n"
00265 "}\n\n");
00266 }
00267
00268 void ArticleViewer::generateCombinedModeCSS()
00269 {
00270 const TQColorGroup & cg = TQApplication::palette().active();
00271
00272
00273 m_combinedModeCSS = TQString (
00274
00275 "@media screen, print {"
00276 "body {\n"
00277 " font-family: \"%1\" ! important;\n"
00278 " font-size: %2 ! important;\n"
00279 " color: %3 ! important;\n"
00280 " background: %4 ! important;\n"
00281 "}\n\n").arg(Settings::standardFont())
00282 .arg(TQString::number(pointsToPixel(Settings::mediumFontSize()))+"px")
00283 .arg(cg.text().name())
00284 .arg(cg.base().name());
00285 m_combinedModeCSS += (
00286 "a {\n"
00287 + TQString(" color: %1 ! important;\n")
00288 + TQString(!Settings::underlineLinks() ? " text-decoration: none ! important;\n" : "")
00289 + "}\n\n"
00290 +".headerbox {\n"
00291 +" background: %2 ! important;\n"
00292 +" color: %3 ! important;\n"
00293 +" border:1px solid #000;\n"
00294 +" margin-bottom: 10pt;\n"
00295
00296 + "}\n\n")
00297 .arg(cg.link().name())
00298 .arg(cg.background().name())
00299 .arg(cg.text().name());
00300
00301 m_combinedModeCSS += TQString(".headertitle a:link { color: %1 ! important; }\n"
00302 ".headertitle a:visited { color: %2 ! important; }\n"
00303 ".headertitle a:hover{ color: %3 ! important; }\n"
00304 ".headertitle a:active { color: %4 ! important; }\n")
00305 .arg(cg.highlightedText().name())
00306 .arg(cg.highlightedText().name())
00307 .arg(cg.highlightedText().name())
00308 .arg(cg.highlightedText().name());
00309 m_combinedModeCSS += TQString(
00310 ".headertitle {\n"
00311 " background: %1 ! important;\n"
00312 " padding:2px;\n"
00313 " color: %2 ! important;\n"
00314 " font-weight: bold;\n"
00315 "}\n\n"
00316 ".header {\n"
00317 " font-weight: bold;\n"
00318 " padding:2px;\n"
00319 " margin-right: 5px;\n"
00320 "}\n\n"
00321 ".headertext {\n"
00322 "}\n\n"
00323 ".headimage {\n"
00324 " float: right;\n"
00325 " margin-left: 5px;\n"
00326 "}\n\n").arg(cg.highlight().name())
00327 .arg(cg.highlightedText().name());
00328
00329 m_combinedModeCSS += TQString(
00330 "body { clear: none; }\n\n"
00331 ".content {\n"
00332 " display: block;\n"
00333 " margin-bottom: 6px;\n"
00334 "}\n\n"
00335
00336 ".content > P:first-child {\n margin-top: 1px; }\n"
00337 ".content > DIV:first-child {\n margin-top: 1px; }\n"
00338 ".content > BR:first-child {\n display: none; }\n"
00339 "iframe {display: none !important; }\n"
00340 "frame {display: none !important; }\n"
00341 "frameset {display: none !important; }\n"
00342 "object {display: none !important; }\n"
00343 "applet {display: none !important; }\n"
00344 "}\n\n");
00345 }
00346
00347 void ArticleViewer::reload()
00348 {
00349 beginWriting();
00350 write(m_currentText);
00351 endWriting();
00352 }
00353
00354 bool ArticleViewer::openURL(const KURL& url)
00355 {
00356 if (!m_article.isNull() && m_article.feed()->loadLinkedWebsite())
00357 {
00358 return Viewer::openURL(url);
00359 }
00360 else
00361 {
00362 reload();
00363 return true;
00364 }
00365 }
00366
00367 void ArticleViewer::displayAboutPage()
00368 {
00369 TQString location = locate("data", "akregator/about/main.html");
00370 TQString content = KPIM::kFileToString(location);
00371 content = content.arg( locate( "data", "libkdepim/about/kde_infopage.css" ) );
00372 if ( kapp->reverseLayout() )
00373 content = content.arg( "@import \"%1\";" ).arg( locate( "data", "libkdepim/about/kde_infopage_rtl.css" ) );
00374 else
00375 content = content.arg( "" );
00376
00377 begin(KURL( location ));
00378 TQString info =
00379 i18n("%1: Akregator version; %2: help:// URL; %3: homepage URL; "
00380 "--- end of comment ---",
00381 "<h2 style='margin-top: 0px;'>Welcome to Akregator %1</h2>"
00382 "<p>Akregator is an RSS feed aggregator for the K Desktop Environment. "
00383 "Feed aggregators provide a convenient way to browse different kinds of "
00384 "content, including news, blogs, and other content from online sites. "
00385 "Instead of checking all your favorite web sites manually for updates, "
00386 "Akregator collects the content for you.</p>"
00387 "<p>For more information about using Akregator, check the "
00388 "<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>"
00389 "<p>We hope that you will enjoy Akregator.</p>\n"
00390 "<p>Thank you,</p>\n"
00391 "<p style='margin-bottom: 0px'> The Akregator Team</p>\n")
00392 .arg(AKREGATOR_VERSION)
00393 .arg("http://akregator.kde.org/");
00394
00395 TQString fontSize = TQString::number( pointsToPixel( Settings::mediumFontSize() ));
00396 TQString appTitle = i18n("Akregator");
00397 TQString catchPhrase = "";
00398 TQString quickDescription = i18n("An RSS feed reader for the K Desktop Environment.");
00399 write(content.arg(fontSize).arg(appTitle).arg(catchPhrase).arg(quickDescription).arg(info));
00400 end();
00401 }
00402
00403 TQString ArticleViewer::formatArticleNormalMode(Feed* feed, const Article& article)
00404 {
00405 TQString text;
00406 text = TQString("<div class=\"headerbox\" dir=\"%1\">\n").arg(TQApplication::reverseLayout() ? "rtl" : "ltr");
00407
00408 if (!article.title().isEmpty())
00409 {
00410 text += TQString("<div class=\"headertitle\" dir=\"%1\">\n").arg(directionOf(Utils::stripTags(article.title())));
00411 if (article.link().isValid())
00412 text += "<a href=\""+article.link().url()+"\">";
00413 text += article.title().replace("<", "<").replace(">", ">");
00414 if (article.link().isValid())
00415 text += "</a>";
00416 text += "</div>\n";
00417 }
00418 if (article.pubDate().isValid())
00419 {
00420 text += TQString("<span class=\"header\" dir=\"%1\">").arg(directionOf(i18n("Date")));
00421 text += TQString ("%1:").arg(i18n("Date"));
00422 text += "</span><span class=\"headertext\">";
00423 text += KGlobal::locale()->formatDateTime(article.pubDate(), false, false)+"</span>\n";
00424 }
00425 TQString author = article.author();
00426 if (!author.isEmpty())
00427 {
00428 text += TQString("<br/><span class=\"header\" dir=\"%1\">").arg(directionOf(i18n("Author")));
00429 text += TQString ("%1:").arg(i18n("Author"));
00430 text += "</span><span class=\"headertext\">";
00431 text += author+"</span>\n";
00432 }
00433 text += "</div>\n";
00434
00435 if (feed && !feed->image().isNull())
00436 {
00437 TQString file = Utils::fileNameForUrl(feed->xmlUrl());
00438 KURL u(m_imageDir);
00439 u.setFileName(file);
00440 text += TQString("<a href=\"%1\"><img class=\"headimage\" src=\"%2.png\"></a>\n").arg(feed->htmlUrl()).arg(u.url());
00441 }
00442
00443
00444
00445 if (!article.description().isEmpty())
00446 {
00447 text += TQString("<div dir=\"%1\">").arg(directionOf(Utils::stripTags(article.description())) );
00448 text += "<span class=\"content\">"+article.description()+"</span>";
00449 text += "</div>";
00450 }
00451
00452 text += "<div class=\"body\">";
00453
00454 if (article.commentsLink().isValid())
00455 {
00456 text += "<a class=\"contentlink\" href=\"";
00457 text += article.commentsLink().url();
00458 text += "\">" + i18n( "Comments");
00459 if (article.comments())
00460 {
00461 text += " ("+ TQString::number(article.comments()) +")";
00462 }
00463 text += "</a>";
00464 }
00465
00466 if (article.link().isValid() || (article.guidIsPermaLink() && KURL(article.guid()).isValid()))
00467 {
00468 text += "<p><a class=\"contentlink\" href=\"";
00469
00470 if (article.link().isValid())
00471 {
00472 text += article.link().url();
00473 }
00474 else
00475 {
00476 text += article.guid();
00477 }
00478 text += "\">" + i18n( "Complete Story" ) + "</a></p>";
00479 }
00480 text += "</div>";
00481
00482 if (!article.enclosure().isNull())
00483 {
00484
00485
00486
00487
00488
00489
00490 }
00491
00492 return text;
00493
00494 }
00495
00496 TQString ArticleViewer::formatArticleCombinedMode(Feed* feed, const Article& article)
00497 {
00498 TQString text;
00499 text = TQString("<div class=\"headerbox\" dir=\"%1\">\n").arg(TQApplication::reverseLayout() ? "rtl" : "ltr");
00500
00501 KURL link = article.link();
00502
00503 if (!article.title().isEmpty())
00504 {
00505 text += TQString("<div class=\"headertitle\" dir=\"%1\">\n").arg(directionOf(Utils::stripTags(article.title())));
00506 if (link.isValid())
00507 text += "<a href=\""+link.url()+"\">";
00508 text += article.title().replace("<", "<").replace(">", ">");
00509 if (link.isValid())
00510 text += "</a>";
00511 text += "</div>\n";
00512 }
00513 if (article.pubDate().isValid())
00514 {
00515 text += TQString("<span class=\"header\" dir=\"%1\">").arg(directionOf(i18n("Date")));
00516 text += TQString ("%1:").arg(i18n("Date"));
00517 text += "</span><span class=\"headertext\">";
00518 text += KGlobal::locale()->formatDateTime(article.pubDate(), false, false)+"</span>\n";
00519 }
00520
00521 TQString author = article.author();
00522 if (!author.isEmpty())
00523 {
00524 text += TQString("<br/><span class=\"header\" dir=\"%1\">").arg(directionOf(i18n("Author")));
00525 text += TQString ("%1:").arg(i18n("Author"));
00526 text += "</span><span class=\"headertext\">";
00527 text += author+"</span>\n";
00528 }
00529
00530 text += "</div>\n";
00531
00532 if (feed && !feed->image().isNull())
00533 {
00534 TQString file = Utils::fileNameForUrl(feed->xmlUrl());
00535 KURL u(m_imageDir);
00536 u.setFileName(file);
00537 text += TQString("<a href=\"%1\"><img class=\"headimage\" src=\"%2.png\"></a>\n").arg(feed->htmlUrl()).arg(u.url());
00538 }
00539
00540
00541
00542 if (!article.description().isEmpty())
00543 {
00544 text += TQString("<div dir=\"%1\">").arg(directionOf(Utils::stripTags(article.description())) );
00545 text += "<span class=\"content\">"+article.description()+"</span>";
00546 text += "</div>";
00547 }
00548
00549 text += "<div class=\"body\">";
00550
00551 if (article.commentsLink().isValid())
00552 {
00553 text += "<a class=\"contentlink\" href=\"";
00554 text += article.commentsLink().url();
00555 text += "\">" + i18n( "Comments");
00556 if (article.comments())
00557 {
00558 text += " ("+ TQString::number(article.comments()) +")";
00559 }
00560 text += "</a>";
00561 }
00562
00563 if (link.isValid() || (article.guidIsPermaLink() && KURL(article.guid()).isValid()))
00564 {
00565 text += "<p><a class=\"contentlink\" href=\"";
00566
00567 if (link.isValid())
00568 {
00569 text += link.url();
00570 }
00571 else
00572 {
00573 text += article.guid();
00574 }
00575 text += "\">" + i18n( "Complete Story" ) + "</a></p>";
00576 }
00577 text += "</div>";
00578
00579 return text;
00580
00581 }
00582
00583 void ArticleViewer::renderContent(const TQString& text)
00584 {
00585 closeURL();
00586 m_currentText = text;
00587 beginWriting();
00588
00589 write(text);
00590 endWriting();
00591 }
00592
00593 void ArticleViewer::beginWriting()
00594 {
00595 TQString head = TQString("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\">\n <html><head><title>.</title></head>");
00596 view()->setContentsPos(0,0);
00597 begin(m_link);
00598 setUserStyleSheet(m_viewMode == CombinedView ? m_combinedModeCSS : m_normalModeCSS);
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 TQValueList<Article> articles = m_node->articles();
00662 qHeapSort(articles);
00663 TQValueList<Article>::ConstIterator end = articles.end();
00664 TQValueList<Article>::ConstIterator it = articles.begin();
00665
00666 TQString text;
00667
00668 int num = 0;
00669 TQTime 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 TQValueList<Article>& )
00688 {
00689 if (m_viewMode == CombinedView)
00690 slotUpdateCombinedView();
00691 }
00692
00693 void ArticleViewer::slotArticlesAdded(TreeNode* , const TQValueList<Article>& )
00694 {
00695 }
00696
00697 void ArticleViewer::slotArticlesRemoved(TreeNode* , const TQValueList<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(TQString());
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(TQKeyEvent* e)
00739 {
00740 e->ignore();
00741 }
00742
00743 void ArticleViewer::urlSelected(const TQString &url, int button, int state, const TQString& _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, TQT_SIGNAL(signalArticlesAdded(TreeNode*, const TQValueList<Article>&)), this, TQT_SLOT(slotArticlesAdded(TreeNode*, const TQValueList<Article>&)));
00771 connect( node, TQT_SIGNAL(signalArticlesRemoved(TreeNode*, const TQValueList<Article>&)), this, TQT_SLOT(slotArticlesRemoved(TreeNode*, const TQValueList<Article>&)));
00772 connect( node, TQT_SIGNAL(signalArticlesUpdated(TreeNode*, const TQValueList<Article>&)), this, TQT_SLOT(slotArticlesUpdated(TreeNode*, const TQValueList<Article>&)));
00773 }
00774 if (m_viewMode == SummaryView)
00775 connect( node, TQT_SIGNAL(signalChanged(TreeNode*)), this, TQT_SLOT(slotShowSummary(TreeNode*) ) );
00776
00777 connect( node, TQT_SIGNAL(signalDestroyed(TreeNode*)), this, TQT_SLOT(slotClear() ) );
00778 }
00779 }
00780
00781 void ArticleViewer::disconnectFromNode(TreeNode* node)
00782 {
00783 if (node)
00784 {
00785
00786 disconnect( node, TQT_SIGNAL(signalDestroyed(TreeNode*)), this, TQT_SLOT(slotClear() ) );
00787 disconnect( node, TQT_SIGNAL(signalChanged(TreeNode*)), this, TQT_SLOT(slotShowSummary(TreeNode*) ) );
00788 disconnect( node, TQT_SIGNAL(signalArticlesAdded(TreeNode*, const TQValueList<Article>&)), this, TQT_SLOT(slotArticlesAdded(TreeNode*, const TQValueList<Article>&)));
00789 disconnect( node, TQT_SIGNAL(signalArticlesRemoved(TreeNode*, const TQValueList<Article>&)), this, TQT_SLOT(slotArticlesRemoved(TreeNode*, const TQValueList<Article>&)));
00790 disconnect( node, TQT_SIGNAL(signalArticlesUpdated(TreeNode*, const TQValueList<Article>&)), this, TQT_SLOT(slotArticlesUpdated(TreeNode*, const TQValueList<Article>&)));
00791
00792 }
00793 }
00794
00795 }
00796 #include "articleviewer.moc"
00797