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 "akregatorconfig.h"
00026 #include "actionmanager.h"
00027 #include "articlelistview.h"
00028 #include "article.h"
00029 #include "articlefilter.h"
00030 #include "dragobjects.h"
00031 #include "feed.h"
00032 #include "treenode.h"
00033 #include "treenodevisitor.h"
00034
00035 #include <kstandarddirs.h>
00036 #include <kdebug.h>
00037 #include <kglobal.h>
00038 #include <kiconloader.h>
00039 #include <klocale.h>
00040 #include <kcharsets.h>
00041 #include <kurl.h>
00042
00043 #include <tqdatetime.h>
00044 #include <tqpixmap.h>
00045 #include <tqpopupmenu.h>
00046 #include <tqptrlist.h>
00047 #include <tqvaluelist.h>
00048 #include <tqwhatsthis.h>
00049 #include <tqheader.h>
00050 #include <tqdragobject.h>
00051 #include <tqsimplerichtext.h>
00052 #include <tqpainter.h>
00053 #include <tqapplication.h>
00054
00055 #include <ctime>
00056
00057 namespace Akregator {
00058
00059 class ArticleListView::ArticleListViewPrivate
00060 {
00061 public:
00062
00063 ArticleListViewPrivate(ArticleListView* parent) : m_parent(parent) { }
00064
00065 void ensureCurrentItemVisible()
00066 {
00067 if (m_parent->currentItem())
00068 {
00069 m_parent->center( m_parent->contentsX(), m_parent->itemPos(m_parent->currentItem()), 0, 9.0 );
00070 }
00071 }
00072
00073 ArticleListView* m_parent;
00074
00076 TQMap<Article, ArticleItem*> articleMap;
00077 TreeNode* node;
00078 Akregator::Filters::ArticleMatcher textFilter;
00079 Akregator::Filters::ArticleMatcher statusFilter;
00080 enum ColumnMode { groupMode, feedMode };
00081 ColumnMode columnMode;
00082 int feedWidth;
00083 bool noneSelected;
00084
00085 ColumnLayoutVisitor* columnLayoutVisitor;
00086 };
00087
00088 class ArticleListView::ColumnLayoutVisitor : public TreeNodeVisitor
00089 {
00090 public:
00091 ColumnLayoutVisitor(ArticleListView* view) : m_view(view) {}
00092
00093 virtual bool visitTagNode(TagNode* )
00094 {
00095 if (m_view->d->columnMode == ArticleListViewPrivate::feedMode)
00096 {
00097 m_view->setColumnWidth(1, m_view->d->feedWidth);
00098 m_view->d->columnMode = ArticleListViewPrivate::groupMode;
00099 }
00100 return true;
00101 }
00102
00103 virtual bool visitFolder(Folder* )
00104 {
00105 if (m_view->d->columnMode == ArticleListViewPrivate::feedMode)
00106 {
00107 m_view->setColumnWidth(1, m_view->d->feedWidth);
00108 m_view->d->columnMode = ArticleListViewPrivate::groupMode;
00109 }
00110 return true;
00111 }
00112
00113 virtual bool visitFeed(Feed* )
00114 {
00115 if (m_view->d->columnMode == ArticleListViewPrivate::groupMode)
00116 {
00117 m_view->d->feedWidth = m_view->columnWidth(1);
00118 m_view->hideColumn(1);
00119 m_view->d->columnMode = ArticleListViewPrivate::feedMode;
00120 }
00121 return true;
00122 }
00123 private:
00124
00125 ArticleListView* m_view;
00126
00127 };
00128
00129 class ArticleListView::ArticleItem : public KListViewItem
00130 {
00131 friend class ArticleListView;
00132
00133 public:
00134 ArticleItem( TQListView *parent, const Article& a);
00135 ~ArticleItem();
00136
00137 Article& article();
00138
00139 void paintCell ( TQPainter * p, const TQColorGroup & cg, int column, int width, int align );
00140 virtual int compare(TQListViewItem *i, int col, bool ascending) const;
00141
00142 void updateItem(const Article& article);
00143
00144 virtual ArticleItem* itemAbove() { return static_cast<ArticleItem*>(KListViewItem::itemAbove()); }
00145
00146 virtual ArticleItem* nextSibling() { return static_cast<ArticleItem*>(KListViewItem::nextSibling()); }
00147
00148 private:
00149 Article m_article;
00150 time_t m_pubDate;
00151 static TQPixmap keepFlag() {
00152 static TQPixmap s_keepFlag = TQPixmap(locate("data", "akregator/pics/akregator_flag.png"));
00153 return s_keepFlag;
00154 }
00155 };
00156
00157
00158 ArticleListView::ArticleItem::ArticleItem( TQListView *parent, const Article& a)
00159 : KListViewItem( parent, KCharsets::resolveEntities(a.title()), a.feed()->title(), KGlobal::locale()->formatDateTime(a.pubDate(), true, false) ), m_article(a), m_pubDate(a.pubDate().toTime_t())
00160 {
00161 if (a.keep())
00162 setPixmap(0, keepFlag());
00163 }
00164
00165 ArticleListView::ArticleItem::~ArticleItem()
00166 {
00167 }
00168
00169 Article& ArticleListView::ArticleItem::article()
00170 {
00171 return m_article;
00172 }
00173
00174
00175 void ArticleListView::ArticleItem::paintCell ( TQPainter * p, const TQColorGroup & cg, int column, int width, int align )
00176 {
00177 if (article().status() == Article::Read)
00178 KListViewItem::paintCell( p, cg, column, width, align );
00179 else
00180 {
00181
00182 TQColorGroup cg2(cg);
00183
00184 if (article().status() == Article::Unread)
00185 cg2.setColor(TQColorGroup::Text, Qt::blue);
00186 else
00187 cg2.setColor(TQColorGroup::Text, Qt::red);
00188
00189 KListViewItem::paintCell( p, cg2, column, width, align );
00190 }
00191
00192 }
00193
00194 void ArticleListView::ArticleItem::updateItem(const Article& article)
00195 {
00196 m_article = article;
00197 setPixmap(0, m_article.keep() ? keepFlag() : TQPixmap());
00198 setText(0, KCharsets::resolveEntities(m_article.title()));
00199 setText(1, m_article.feed()->title());
00200 setText(2, KGlobal::locale()->formatDateTime(m_article.pubDate(), true, false));
00201 }
00202
00203 int ArticleListView::ArticleItem::compare(TQListViewItem *i, int col, bool ascending) const {
00204 if (col == 2)
00205 {
00206 ArticleItem* item = static_cast<ArticleItem*>(i);
00207 if (m_pubDate == item->m_pubDate)
00208 return 0;
00209 return (m_pubDate > item->m_pubDate) ? 1 : -1;
00210 }
00211 return KListViewItem::compare(i, col, ascending);
00212 }
00213
00214
00215
00216 ArticleListView::ArticleListView(TQWidget *parent, const char *name)
00217 : KListView(parent, name)
00218 {
00219 d = new ArticleListViewPrivate(this);
00220 d->noneSelected = true;
00221 d->node = 0;
00222 d->columnMode = ArticleListViewPrivate::feedMode;
00223
00224 d->columnLayoutVisitor = new ColumnLayoutVisitor(this);
00225 setMinimumSize(250, 150);
00226 addColumn(i18n("Article"));
00227 addColumn(i18n("Feed"));
00228 addColumn(i18n("Date"));
00229 setSelectionMode(TQListView::Extended);
00230 setColumnWidthMode(2, TQListView::Maximum);
00231 setColumnWidthMode(1, TQListView::Manual);
00232 setColumnWidthMode(0, TQListView::Manual);
00233 setRootIsDecorated(false);
00234 setItemsRenameable(false);
00235 setItemsMovable(false);
00236 setAllColumnsShowFocus(true);
00237 setDragEnabled(true);
00238 setAcceptDrops(false);
00239 setFullWidth(false);
00240
00241 setShowSortIndicator(true);
00242 setDragAutoScroll(true);
00243 setDropHighlighter(false);
00244
00245 int c = Settings::sortColumn();
00246 setSorting((c >= 0 && c <= 2) ? c : 2, Settings::sortAscending());
00247
00248 int w;
00249 w = Settings::titleWidth();
00250 if (w > 0) {
00251 setColumnWidth(0, w);
00252 }
00253
00254 w = Settings::feedWidth();
00255 if (w > 0) {
00256 setColumnWidth(1, w);
00257 }
00258
00259 w = Settings::dateWidth();
00260 if (w > 0) {
00261 setColumnWidth(2, w);
00262 }
00263
00264 d->feedWidth = columnWidth(1);
00265 hideColumn(1);
00266
00267 header()->setStretchEnabled(true, 0);
00268
00269 TQWhatsThis::add(this, i18n("<h2>Article list</h2>"
00270 "Here you can browse articles from the currently selected feed. "
00271 "You can also manage articles, as marking them as persistent (\"Keep Article\") or delete them, using the right mouse button menu."
00272 "To view the web page of the article, you can open the article internally in a tab or in an external browser window."));
00273
00274 connect(this, TQT_SIGNAL(currentChanged(TQListViewItem*)), this, TQT_SLOT(slotCurrentChanged(TQListViewItem* )));
00275 connect(this, TQT_SIGNAL(selectionChanged()), this, TQT_SLOT(slotSelectionChanged()));
00276 connect(this, TQT_SIGNAL(doubleClicked(TQListViewItem*, const TQPoint&, int)), this, TQT_SLOT(slotDoubleClicked(TQListViewItem*, const TQPoint&, int)) );
00277 connect(this, TQT_SIGNAL(contextMenu(KListView*, TQListViewItem*, const TQPoint&)),
00278 this, TQT_SLOT(slotContextMenu(KListView*, TQListViewItem*, const TQPoint&)));
00279
00280 connect(this, TQT_SIGNAL(mouseButtonPressed(int, TQListViewItem *, const TQPoint &, int)), this, TQT_SLOT(slotMouseButtonPressed(int, TQListViewItem *, const TQPoint &, int)));
00281 }
00282
00283 Article ArticleListView::currentArticle() const
00284 {
00285 ArticleItem* ci = dynamic_cast<ArticleItem*>(KListView::currentItem());
00286 return (ci && !selectedItems().isEmpty()) ? ci->article() : Article();
00287 }
00288
00289 void ArticleListView::slotSetFilter(const Akregator::Filters::ArticleMatcher& textFilter, const Akregator::Filters::ArticleMatcher& statusFilter)
00290 {
00291 if ( (textFilter != d->textFilter) || (statusFilter != d->statusFilter) )
00292 {
00293 d->textFilter = textFilter;
00294 d->statusFilter = statusFilter;
00295
00296 applyFilters();
00297 }
00298 }
00299
00300 void ArticleListView::slotShowNode(TreeNode* node)
00301 {
00302 if (node == d->node)
00303 return;
00304
00305 slotClear();
00306
00307 if (!node)
00308 return;
00309
00310 d->node = node;
00311 connectToNode(node);
00312
00313 d->columnLayoutVisitor->visit(node);
00314
00315 setUpdatesEnabled(false);
00316
00317 TQValueList<Article> articles = d->node->articles();
00318
00319 TQValueList<Article>::ConstIterator end = articles.end();
00320 TQValueList<Article>::ConstIterator it = articles.begin();
00321
00322 for (; it != end; ++it)
00323 {
00324 if (!(*it).isNull() && !(*it).isDeleted())
00325 {
00326 ArticleItem* ali = new ArticleItem(this, *it);
00327 d->articleMap.insert(*it, ali);
00328 }
00329 }
00330
00331 sort();
00332 applyFilters();
00333 d->noneSelected = true;
00334 setUpdatesEnabled(true);
00335 triggerUpdate();
00336 }
00337
00338 void ArticleListView::slotClear()
00339 {
00340 if (d->node)
00341 disconnectFromNode(d->node);
00342
00343 d->node = 0;
00344 d->articleMap.clear();
00345 clear();
00346 }
00347
00348 void ArticleListView::slotArticlesAdded(TreeNode* , const TQValueList<Article>& list)
00349 {
00350 setUpdatesEnabled(false);
00351
00352 bool statusActive = !(d->statusFilter.matchesAll());
00353 bool textActive = !(d->textFilter.matchesAll());
00354
00355 for (TQValueList<Article>::ConstIterator it = list.begin(); it != list.end(); ++it)
00356 {
00357 if (!d->articleMap.contains(*it))
00358 {
00359 if (!(*it).isNull() && !(*it).isDeleted())
00360 {
00361 ArticleItem* ali = new ArticleItem(this, *it);
00362 ali->setVisible( (!statusActive || d->statusFilter.matches( ali->article()))
00363 && (!textActive || d->textFilter.matches( ali->article())) );
00364 d->articleMap.insert(*it, ali);
00365 }
00366 }
00367 }
00368 setUpdatesEnabled(true);
00369 triggerUpdate();
00370 }
00371
00372 void ArticleListView::slotArticlesUpdated(TreeNode* , const TQValueList<Article>& list)
00373 {
00374 setUpdatesEnabled(false);
00375
00376
00377
00378 bool singleSelected = selectedArticles().count() == 1;
00379
00380 bool statusActive = !(d->statusFilter.matchesAll());
00381 bool textActive = !(d->textFilter.matchesAll());
00382
00383 TQListViewItem* next = 0;
00384
00385 for (TQValueList<Article>::ConstIterator it = list.begin(); it != list.end(); ++it)
00386 {
00387
00388 if (!(*it).isNull() && d->articleMap.contains(*it))
00389 {
00390 ArticleItem* ali = d->articleMap[*it];
00391
00392 if (ali)
00393 {
00394 if ((*it).isDeleted())
00395 {
00396 if (singleSelected && ali->isSelected())
00397 {
00398 if (ali->itemBelow())
00399 next = ali->itemBelow();
00400 else if (ali->itemAbove())
00401 next = ali->itemAbove();
00402 }
00403
00404 d->articleMap.remove(*it);
00405 delete ali;
00406 }
00407 else
00408 {
00409 ali->updateItem(*it);
00410
00411
00412
00413 if ((!statusActive || d->statusFilter.matches(ali->article()))
00414 && (!textActive || d->textFilter.matches( ali->article())) )
00415 ali->setVisible(true);
00416 }
00417 }
00418 }
00419 }
00420
00421
00422
00423 if (singleSelected && next != 0)
00424 {
00425 setSelected(next, true);
00426 setCurrentItem(next);
00427 }
00428 else
00429 {
00430 d->noneSelected = true;
00431 }
00432
00433
00434 setUpdatesEnabled(true);
00435 triggerUpdate();
00436 }
00437
00438 void ArticleListView::slotArticlesRemoved(TreeNode* , const TQValueList<Article>& list)
00439 {
00440
00441
00442 bool singleSelected = selectedArticles().count() == 1;
00443
00444 TQListViewItem* next = 0;
00445
00446 setUpdatesEnabled(false);
00447
00448 for (TQValueList<Article>::ConstIterator it = list.begin(); it != list.end(); ++it)
00449 {
00450 if (d->articleMap.contains(*it))
00451 {
00452 ArticleItem* ali = d->articleMap[*it];
00453 d->articleMap.remove(*it);
00454
00455 if (singleSelected && ali->isSelected())
00456 {
00457 if (ali->itemBelow())
00458 next = ali->itemBelow();
00459 else if (ali->itemAbove())
00460 next = ali->itemAbove();
00461 }
00462
00463 delete ali;
00464 }
00465 }
00466
00467
00468
00469 if (singleSelected && next != 0)
00470 {
00471 setSelected(next, true);
00472 setCurrentItem(next);
00473 }
00474 else
00475 {
00476 d->noneSelected = true;
00477 }
00478
00479 setUpdatesEnabled(true);
00480 triggerUpdate();
00481 }
00482
00483 void ArticleListView::connectToNode(TreeNode* node)
00484 {
00485 connect(node, TQT_SIGNAL(signalDestroyed(TreeNode*)), this, TQT_SLOT(slotClear()) );
00486 connect(node, TQT_SIGNAL(signalArticlesAdded(TreeNode*, const TQValueList<Article>&)), this, TQT_SLOT(slotArticlesAdded(TreeNode*, const TQValueList<Article>&)) );
00487 connect(node, TQT_SIGNAL(signalArticlesUpdated(TreeNode*, const TQValueList<Article>&)), this, TQT_SLOT(slotArticlesUpdated(TreeNode*, const TQValueList<Article>&)) );
00488 connect(node, TQT_SIGNAL(signalArticlesRemoved(TreeNode*, const TQValueList<Article>&)), this, TQT_SLOT(slotArticlesRemoved(TreeNode*, const TQValueList<Article>&)) );
00489 }
00490
00491 void ArticleListView::disconnectFromNode(TreeNode* node)
00492 {
00493 disconnect(node, TQT_SIGNAL(signalDestroyed(TreeNode*)), this, TQT_SLOT(slotClear()) );
00494 disconnect(node, TQT_SIGNAL(signalArticlesAdded(TreeNode*, const TQValueList<Article>&)), this, TQT_SLOT(slotArticlesAdded(TreeNode*, const TQValueList<Article>&)) );
00495 disconnect(node, TQT_SIGNAL(signalArticlesUpdated(TreeNode*, const TQValueList<Article>&)), this, TQT_SLOT(slotArticlesUpdated(TreeNode*, const TQValueList<Article>&)) );
00496 disconnect(node, TQT_SIGNAL(signalArticlesRemoved(TreeNode*, const TQValueList<Article>&)), this, TQT_SLOT(slotArticlesRemoved(TreeNode*, const TQValueList<Article>&)) );
00497 }
00498
00499 void ArticleListView::applyFilters()
00500 {
00501 bool statusActive = !(d->statusFilter.matchesAll());
00502 bool textActive = !(d->textFilter.matchesAll());
00503
00504 ArticleItem* ali = 0;
00505
00506 if (!statusActive && !textActive)
00507 {
00508 for (TQListViewItemIterator it(this); it.current(); ++it)
00509 {
00510 (static_cast<ArticleItem*> (it.current()))->setVisible(true);
00511 }
00512 }
00513 else if (statusActive && !textActive)
00514 {
00515 for (TQListViewItemIterator it(this); it.current(); ++it)
00516 {
00517 ali = static_cast<ArticleItem*> (it.current());
00518 ali->setVisible( d->statusFilter.matches( ali->article()) );
00519 }
00520 }
00521 else if (!statusActive && textActive)
00522 {
00523 for (TQListViewItemIterator it(this); it.current(); ++it)
00524 {
00525 ali = static_cast<ArticleItem*> (it.current());
00526 ali->setVisible( d->textFilter.matches( ali->article()) );
00527 }
00528 }
00529 else
00530 {
00531 for (TQListViewItemIterator it(this); it.current(); ++it)
00532 {
00533 ali = static_cast<ArticleItem*> (it.current());
00534 ali->setVisible( d->statusFilter.matches( ali->article())
00535 && d->textFilter.matches( ali->article()) );
00536 }
00537 }
00538
00539 }
00540
00541 int ArticleListView::visibleArticles()
00542 {
00543 int visible = 0;
00544 ArticleItem* ali = 0;
00545 for (TQListViewItemIterator it(this); it.current(); ++it) {
00546 ali = static_cast<ArticleItem*> (it.current());
00547 visible += ali->isVisible() ? 1 : 0;
00548 }
00549 return visible;
00550 }
00551
00552
00553 void ArticleListView::paintInfoBox(const TQString &message)
00554 {
00555 TQPainter p( viewport() );
00556 TQSimpleRichText t( message, TQApplication::font() );
00557
00558 if ( t.width()+30 >= viewport()->width() || t.height()+30 >= viewport()->height() )
00559
00560 return;
00561
00562 const uint w = t.width();
00563 const uint h = t.height();
00564 const uint x = (viewport()->width() - w - 30) / 2 ;
00565 const uint y = (viewport()->height() - h - 30) / 2 ;
00566
00567 p.setBrush( colorGroup().background() );
00568 p.drawRoundRect( x, y, w+30, h+30, (8*200)/w, (8*200)/h );
00569 t.draw( &p, x+15, y+15, TQRect(), colorGroup() );
00570 }
00571
00572 void ArticleListView::viewportPaintEvent(TQPaintEvent *e)
00573 {
00574
00575 KListView::viewportPaintEvent(e);
00576
00577 if(!e)
00578 return;
00579
00580 TQString message = TQString::null;
00581
00582
00583
00584 if(childCount() != 0)
00585 {
00586 if (visibleArticles() == 0)
00587 {
00588 message = i18n("<div align=center>"
00589 "<h3>No matches</h3>"
00590 "Filter does not match any articles, "
00591 "please change your criteria and try again."
00592 "</div>");
00593 }
00594
00595 }
00596 else
00597 {
00598 if (!d->node)
00599 {
00600 message = i18n("<div align=center>"
00601 "<h3>No feed selected</h3>"
00602 "This area is article list. "
00603 "Select a feed from the feed list "
00604 "and you will see its articles here."
00605 "</div>");
00606 }
00607 else
00608 {
00609
00610 }
00611 }
00612
00613 if (!message.isNull())
00614 paintInfoBox(message);
00615 }
00616
00617 TQDragObject *ArticleListView::dragObject()
00618 {
00619 TQDragObject* d = 0;
00620 TQValueList<Article> articles = selectedArticles();
00621 if (!articles.isEmpty())
00622 {
00623 d = new ArticleDrag(articles, this);
00624 }
00625 return d;
00626 }
00627
00628 void ArticleListView::slotPreviousArticle()
00629 {
00630 ArticleItem* ali = 0;
00631 if (!currentItem() || selectedItems().isEmpty())
00632 ali = dynamic_cast<ArticleItem*>(lastChild());
00633 else
00634 ali = dynamic_cast<ArticleItem*>(currentItem()->itemAbove());
00635
00636 if (ali)
00637 {
00638 Article a = ali->article();
00639 setCurrentItem(d->articleMap[a]);
00640 clearSelection();
00641 setSelected(d->articleMap[a], true);
00642 d->ensureCurrentItemVisible();
00643 }
00644 }
00645
00646 void ArticleListView::slotNextArticle()
00647 {
00648 ArticleItem* ali = 0;
00649 if (!currentItem() || selectedItems().isEmpty())
00650 ali = dynamic_cast<ArticleItem*>(firstChild());
00651 else
00652 ali = dynamic_cast<ArticleItem*>(currentItem()->itemBelow());
00653
00654 if (ali)
00655 {
00656 Article a = ali->article();
00657 setCurrentItem(d->articleMap[a]);
00658 clearSelection();
00659 setSelected(d->articleMap[a], true);
00660 d->ensureCurrentItemVisible();
00661 }
00662 }
00663
00664 void ArticleListView::slotNextUnreadArticle()
00665 {
00666 ArticleItem* start = 0L;
00667 if (!currentItem() || selectedItems().isEmpty())
00668 start = dynamic_cast<ArticleItem*>(firstChild());
00669 else
00670 start = dynamic_cast<ArticleItem*>(currentItem()->itemBelow() ? currentItem()->itemBelow() : firstChild());
00671
00672 ArticleItem* i = start;
00673 ArticleItem* unread = 0L;
00674
00675 do
00676 {
00677 if (i == 0L)
00678 i = static_cast<ArticleItem*>(firstChild());
00679 else
00680 {
00681 if (i->article().status() != Article::Read)
00682 unread = i;
00683 else
00684 i = static_cast<ArticleItem*>(i && i->itemBelow() ? i->itemBelow() : firstChild());
00685 }
00686 }
00687 while (!unread && i != start);
00688
00689 if (unread)
00690 {
00691 Article a = unread->article();
00692 setCurrentItem(d->articleMap[a]);
00693 clearSelection();
00694 setSelected(d->articleMap[a], true);
00695 d->ensureCurrentItemVisible();
00696 }
00697 }
00698
00699 void ArticleListView::slotPreviousUnreadArticle()
00700 {
00701 ArticleItem* start = 0L;
00702 if (!currentItem() || selectedItems().isEmpty())
00703 start = dynamic_cast<ArticleItem*>(lastChild());
00704 else
00705 start = dynamic_cast<ArticleItem*>(currentItem()->itemAbove() ? currentItem()->itemAbove() : firstChild());
00706
00707 ArticleItem* i = start;
00708 ArticleItem* unread = 0L;
00709
00710 do
00711 {
00712 if (i == 0L)
00713 i = static_cast<ArticleItem*>(lastChild());
00714 else
00715 {
00716 if (i->article().status() != Article::Read)
00717 unread = i;
00718 else
00719 i = static_cast<ArticleItem*>(i->itemAbove() ? i->itemAbove() : lastChild());
00720 }
00721 }
00722 while ( !(unread != 0L || i == start) );
00723
00724 if (unread)
00725 {
00726 Article a = unread->article();
00727 setCurrentItem(d->articleMap[a]);
00728 clearSelection();
00729 setSelected(d->articleMap[a], true);
00730 d->ensureCurrentItemVisible();
00731 }
00732 }
00733
00734 void ArticleListView::keyPressEvent(TQKeyEvent* e)
00735 {
00736 e->ignore();
00737 }
00738
00739 void ArticleListView::slotSelectionChanged()
00740 {
00741
00742
00743
00744
00745
00746 if (d->noneSelected)
00747 {
00748 d->noneSelected = false;
00749 slotCurrentChanged(currentItem());
00750 }
00751 }
00752
00753 void ArticleListView::slotCurrentChanged(TQListViewItem* item)
00754 {
00755 ArticleItem* ai = dynamic_cast<ArticleItem*> (item);
00756 if (ai)
00757 emit signalArticleChosen( ai->article() );
00758 else
00759 {
00760 d->noneSelected = true;
00761 emit signalArticleChosen( Article() );
00762 }
00763 }
00764
00765
00766 void ArticleListView::slotDoubleClicked(TQListViewItem* item, const TQPoint& p, int i)
00767 {
00768 ArticleItem* ali = dynamic_cast<ArticleItem*>(item);
00769 if (ali)
00770 emit signalDoubleClicked(ali->article(), p, i);
00771 }
00772
00773 void ArticleListView::slotContextMenu(KListView* , TQListViewItem* , const TQPoint& p)
00774 {
00775 TQWidget* w = ActionManager::getInstance()->container("article_popup");
00776 TQPopupMenu* popup = static_cast<TQPopupMenu *>(w);
00777 if (popup)
00778 popup->exec(p);
00779 }
00780
00781 void ArticleListView::slotMouseButtonPressed(int button, TQListViewItem* item, const TQPoint& p, int column)
00782 {
00783 ArticleItem* ali = dynamic_cast<ArticleItem*>(item);
00784 if (ali)
00785 emit signalMouseButtonPressed(button, ali->article(), p, column);
00786 }
00787
00788 ArticleListView::~ArticleListView()
00789 {
00790 Settings::setTitleWidth(columnWidth(0));
00791 Settings::setFeedWidth(columnWidth(1) > 0 ? columnWidth(1) : d->feedWidth);
00792 Settings::setSortColumn(sortColumn());
00793 Settings::setSortAscending(sortOrder() == Ascending);
00794 Settings::writeConfig();
00795 delete d->columnLayoutVisitor;
00796 delete d;
00797 d = 0;
00798 }
00799
00800 TQValueList<Article> ArticleListView::selectedArticles() const
00801 {
00802 TQValueList<Article> ret;
00803 TQPtrList<TQListViewItem> items = selectedItems(false);
00804 for (TQListViewItem* i = items.first(); i; i = items.next() )
00805 ret.append((static_cast<ArticleItem*>(i))->article());
00806 return ret;
00807 }
00808
00809 }
00810
00811 #include "articlelistview.moc"
00812