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