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