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 else
00428 {
00429 d->noneSelected = true;
00430 }
00431
00432
00433 setUpdatesEnabled(true);
00434 triggerUpdate();
00435 }
00436
00437 void ArticleListView::slotArticlesRemoved(TreeNode* , const QValueList<Article>& list)
00438 {
00439
00440
00441 bool singleSelected = selectedArticles().count() == 1;
00442
00443 QListViewItem* next = 0;
00444
00445 setUpdatesEnabled(false);
00446
00447 for (QValueList<Article>::ConstIterator it = list.begin(); it != list.end(); ++it)
00448 {
00449 if (d->articleMap.contains(*it))
00450 {
00451 ArticleItem* ali = d->articleMap[*it];
00452 d->articleMap.remove(*it);
00453
00454 if (singleSelected && ali->isSelected())
00455 {
00456 if (ali->itemBelow())
00457 next = ali->itemBelow();
00458 else if (ali->itemAbove())
00459 next = ali->itemAbove();
00460 }
00461
00462 delete ali;
00463 }
00464 }
00465
00466
00467
00468 if (singleSelected && next != 0)
00469 {
00470 setSelected(next, true);
00471 setCurrentItem(next);
00472 }
00473 else
00474 {
00475 d->noneSelected = true;
00476 }
00477
00478 setUpdatesEnabled(true);
00479 triggerUpdate();
00480 }
00481
00482 void ArticleListView::connectToNode(TreeNode* node)
00483 {
00484 connect(node, SIGNAL(signalDestroyed(TreeNode*)), this, SLOT(slotClear()) );
00485 connect(node, SIGNAL(signalArticlesAdded(TreeNode*, const QValueList<Article>&)), this, SLOT(slotArticlesAdded(TreeNode*, const QValueList<Article>&)) );
00486 connect(node, SIGNAL(signalArticlesUpdated(TreeNode*, const QValueList<Article>&)), this, SLOT(slotArticlesUpdated(TreeNode*, const QValueList<Article>&)) );
00487 connect(node, SIGNAL(signalArticlesRemoved(TreeNode*, const QValueList<Article>&)), this, SLOT(slotArticlesRemoved(TreeNode*, const QValueList<Article>&)) );
00488 }
00489
00490 void ArticleListView::disconnectFromNode(TreeNode* node)
00491 {
00492 disconnect(node, SIGNAL(signalDestroyed(TreeNode*)), this, SLOT(slotClear()) );
00493 disconnect(node, SIGNAL(signalArticlesAdded(TreeNode*, const QValueList<Article>&)), this, SLOT(slotArticlesAdded(TreeNode*, const QValueList<Article>&)) );
00494 disconnect(node, SIGNAL(signalArticlesUpdated(TreeNode*, const QValueList<Article>&)), this, SLOT(slotArticlesUpdated(TreeNode*, const QValueList<Article>&)) );
00495 disconnect(node, SIGNAL(signalArticlesRemoved(TreeNode*, const QValueList<Article>&)), this, SLOT(slotArticlesRemoved(TreeNode*, const QValueList<Article>&)) );
00496 }
00497
00498 void ArticleListView::applyFilters()
00499 {
00500 bool statusActive = !(d->statusFilter.matchesAll());
00501 bool textActive = !(d->textFilter.matchesAll());
00502
00503 ArticleItem* ali = 0;
00504
00505 if (!statusActive && !textActive)
00506 {
00507 for (QListViewItemIterator it(this); it.current(); ++it)
00508 {
00509 (static_cast<ArticleItem*> (it.current()))->setVisible(true);
00510 }
00511 }
00512 else if (statusActive && !textActive)
00513 {
00514 for (QListViewItemIterator it(this); it.current(); ++it)
00515 {
00516 ali = static_cast<ArticleItem*> (it.current());
00517 ali->setVisible( d->statusFilter.matches( ali->article()) );
00518 }
00519 }
00520 else if (!statusActive && textActive)
00521 {
00522 for (QListViewItemIterator it(this); it.current(); ++it)
00523 {
00524 ali = static_cast<ArticleItem*> (it.current());
00525 ali->setVisible( d->textFilter.matches( ali->article()) );
00526 }
00527 }
00528 else
00529 {
00530 for (QListViewItemIterator it(this); it.current(); ++it)
00531 {
00532 ali = static_cast<ArticleItem*> (it.current());
00533 ali->setVisible( d->statusFilter.matches( ali->article())
00534 && d->textFilter.matches( ali->article()) );
00535 }
00536 }
00537
00538 }
00539
00540 int ArticleListView::visibleArticles()
00541 {
00542 int visible = 0;
00543 ArticleItem* ali = 0;
00544 for (QListViewItemIterator it(this); it.current(); ++it) {
00545 ali = static_cast<ArticleItem*> (it.current());
00546 visible += ali->isVisible() ? 1 : 0;
00547 }
00548 return visible;
00549 }
00550
00551
00552 void ArticleListView::paintInfoBox(const QString &message)
00553 {
00554 QPainter p( viewport() );
00555 QSimpleRichText t( message, QApplication::font() );
00556
00557 if ( t.width()+30 >= viewport()->width() || t.height()+30 >= viewport()->height() )
00558
00559 return;
00560
00561 const uint w = t.width();
00562 const uint h = t.height();
00563 const uint x = (viewport()->width() - w - 30) / 2 ;
00564 const uint y = (viewport()->height() - h - 30) / 2 ;
00565
00566 p.setBrush( colorGroup().background() );
00567 p.drawRoundRect( x, y, w+30, h+30, (8*200)/w, (8*200)/h );
00568 t.draw( &p, x+15, y+15, QRect(), colorGroup() );
00569 }
00570
00571 void ArticleListView::viewportPaintEvent(QPaintEvent *e)
00572 {
00573
00574 KListView::viewportPaintEvent(e);
00575
00576 if(!e)
00577 return;
00578
00579 QString message = QString::null;
00580
00581
00582
00583 if(childCount() != 0)
00584 {
00585 if (visibleArticles() == 0)
00586 {
00587 message = i18n("<div align=center>"
00588 "<h3>No matches</h3>"
00589 "Filter does not match any articles, "
00590 "please change your criteria and try again."
00591 "</div>");
00592 }
00593
00594 }
00595 else
00596 {
00597 if (!d->node)
00598 {
00599 message = i18n("<div align=center>"
00600 "<h3>No feed selected</h3>"
00601 "This area is article list. "
00602 "Select a feed from the feed list "
00603 "and you will see its articles here."
00604 "</div>");
00605 }
00606 else
00607 {
00608
00609 }
00610 }
00611
00612 if (!message.isNull())
00613 paintInfoBox(message);
00614 }
00615
00616 QDragObject *ArticleListView::dragObject()
00617 {
00618 QDragObject* d = 0;
00619 QValueList<Article> articles = selectedArticles();
00620 if (!articles.isEmpty())
00621 {
00622 d = new ArticleDrag(articles, this);
00623 }
00624 return d;
00625 }
00626
00627 void ArticleListView::slotPreviousArticle()
00628 {
00629 ArticleItem* ali = 0;
00630 if (!currentItem() || selectedItems().isEmpty())
00631 ali = dynamic_cast<ArticleItem*>(lastChild());
00632 else
00633 ali = dynamic_cast<ArticleItem*>(currentItem()->itemAbove());
00634
00635 if (ali)
00636 {
00637 Article a = ali->article();
00638 setCurrentItem(d->articleMap[a]);
00639 clearSelection();
00640 setSelected(d->articleMap[a], true);
00641 d->ensureCurrentItemVisible();
00642 }
00643 }
00644
00645 void ArticleListView::slotNextArticle()
00646 {
00647 ArticleItem* ali = 0;
00648 if (!currentItem() || selectedItems().isEmpty())
00649 ali = dynamic_cast<ArticleItem*>(firstChild());
00650 else
00651 ali = dynamic_cast<ArticleItem*>(currentItem()->itemBelow());
00652
00653 if (ali)
00654 {
00655 Article a = ali->article();
00656 setCurrentItem(d->articleMap[a]);
00657 clearSelection();
00658 setSelected(d->articleMap[a], true);
00659 d->ensureCurrentItemVisible();
00660 }
00661 }
00662
00663 void ArticleListView::slotNextUnreadArticle()
00664 {
00665 ArticleItem* start = 0L;
00666 if (!currentItem() || selectedItems().isEmpty())
00667 start = dynamic_cast<ArticleItem*>(firstChild());
00668 else
00669 start = dynamic_cast<ArticleItem*>(currentItem()->itemBelow() ? currentItem()->itemBelow() : firstChild());
00670
00671 ArticleItem* i = start;
00672 ArticleItem* unread = 0L;
00673
00674 do
00675 {
00676 if (i == 0L)
00677 i = static_cast<ArticleItem*>(firstChild());
00678 else
00679 {
00680 if (i->article().status() != Article::Read)
00681 unread = i;
00682 else
00683 i = static_cast<ArticleItem*>(i && i->itemBelow() ? i->itemBelow() : firstChild());
00684 }
00685 }
00686 while (!unread && i != start);
00687
00688 if (unread)
00689 {
00690 Article a = unread->article();
00691 setCurrentItem(d->articleMap[a]);
00692 clearSelection();
00693 setSelected(d->articleMap[a], true);
00694 d->ensureCurrentItemVisible();
00695 }
00696 }
00697
00698 void ArticleListView::slotPreviousUnreadArticle()
00699 {
00700 ArticleItem* start = 0L;
00701 if (!currentItem() || selectedItems().isEmpty())
00702 start = dynamic_cast<ArticleItem*>(lastChild());
00703 else
00704 start = dynamic_cast<ArticleItem*>(currentItem()->itemAbove() ? currentItem()->itemAbove() : firstChild());
00705
00706 ArticleItem* i = start;
00707 ArticleItem* unread = 0L;
00708
00709 do
00710 {
00711 if (i == 0L)
00712 i = static_cast<ArticleItem*>(lastChild());
00713 else
00714 {
00715 if (i->article().status() != Article::Read)
00716 unread = i;
00717 else
00718 i = static_cast<ArticleItem*>(i->itemAbove() ? i->itemAbove() : lastChild());
00719 }
00720 }
00721 while ( !(unread != 0L || i == start) );
00722
00723 if (unread)
00724 {
00725 Article a = unread->article();
00726 setCurrentItem(d->articleMap[a]);
00727 clearSelection();
00728 setSelected(d->articleMap[a], true);
00729 d->ensureCurrentItemVisible();
00730 }
00731 }
00732
00733 void ArticleListView::keyPressEvent(QKeyEvent* e)
00734 {
00735 e->ignore();
00736 }
00737
00738 void ArticleListView::slotSelectionChanged()
00739 {
00740
00741
00742
00743
00744
00745 if (d->noneSelected)
00746 {
00747 d->noneSelected = false;
00748 slotCurrentChanged(currentItem());
00749 }
00750 }
00751
00752 void ArticleListView::slotCurrentChanged(QListViewItem* item)
00753 {
00754 ArticleItem* ai = dynamic_cast<ArticleItem*> (item);
00755 if (ai)
00756 emit signalArticleChosen( ai->article() );
00757 else
00758 {
00759 d->noneSelected = true;
00760 emit signalArticleChosen( Article() );
00761 }
00762 }
00763
00764
00765 void ArticleListView::slotDoubleClicked(QListViewItem* item, const QPoint& p, int i)
00766 {
00767 ArticleItem* ali = dynamic_cast<ArticleItem*>(item);
00768 if (ali)
00769 emit signalDoubleClicked(ali->article(), p, i);
00770 }
00771
00772 void ArticleListView::slotContextMenu(KListView* , QListViewItem* , const QPoint& p)
00773 {
00774 QWidget* w = ActionManager::getInstance()->container("article_popup");
00775 QPopupMenu* popup = static_cast<QPopupMenu *>(w);
00776 if (popup)
00777 popup->exec(p);
00778 }
00779
00780 void ArticleListView::slotMouseButtonPressed(int button, QListViewItem* item, const QPoint& p, int column)
00781 {
00782 ArticleItem* ali = dynamic_cast<ArticleItem*>(item);
00783 if (ali)
00784 emit signalMouseButtonPressed(button, ali->article(), p, column);
00785 }
00786
00787 ArticleListView::~ArticleListView()
00788 {
00789 Settings::setTitleWidth(columnWidth(0));
00790 Settings::setFeedWidth(columnWidth(1) > 0 ? columnWidth(1) : d->feedWidth);
00791 Settings::setSortColumn(sortColumn());
00792 Settings::setSortAscending(sortOrder() == Ascending);
00793 Settings::writeConfig();
00794 delete d->columnLayoutVisitor;
00795 delete d;
00796 d = 0;
00797 }
00798
00799 QValueList<Article> ArticleListView::selectedArticles() const
00800 {
00801 QValueList<Article> ret;
00802 QPtrList<QListViewItem> items = selectedItems(false);
00803 for (QListViewItem* i = items.first(); i; i = items.next() )
00804 ret.append((static_cast<ArticleItem*>(i))->article());
00805 return ret;
00806 }
00807
00808 }
00809
00810 #include "articlelistview.moc"
00811