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 "dragobjects.h"
00026 #include "folder.h"
00027 #include "folderitem.h"
00028 #include "tagfolder.h"
00029 #include "tagfolderitem.h"
00030 #include "feedlistview.h"
00031 #include "feed.h"
00032 #include "feeditem.h"
00033 #include "feedlist.h"
00034 #include "tag.h"
00035 #include "tagnode.h"
00036 #include "tagnodeitem.h"
00037 #include "tagnodelist.h"
00038 #include "treenode.h"
00039 #include "treenodeitem.h"
00040 #include "treenodevisitor.h"
00041
00042 #include <kdebug.h>
00043 #include <kiconeffect.h>
00044 #include <kiconloader.h>
00045 #include <klocale.h>
00046 #include <kmultipledrag.h>
00047 #include <kstringhandler.h>
00048 #include <kurldrag.h>
00049
00050 #include <qfont.h>
00051 #include <qheader.h>
00052 #include <qpainter.h>
00053 #include <qptrdict.h>
00054 #include <qtimer.h>
00055 #include <qwhatsthis.h>
00056
00057 namespace Akregator {
00058
00059 class NodeListView::NodeListViewPrivate
00060 {
00061 public:
00063 QPtrDict<TreeNodeItem> itemDict;
00064 NodeList* nodeList;
00065 bool showTagFolders;
00066
00067
00068 QListViewItem *parent;
00069 QListViewItem *afterme;
00070 QTimer autoopentimer;
00071 ConnectNodeVisitor* connectNodeVisitor;
00072 DisconnectNodeVisitor* disconnectNodeVisitor;
00073 CreateItemVisitor* createItemVisitor;
00074 DeleteItemVisitor* deleteItemVisitor;
00075 };
00076
00077 class NodeListView::ConnectNodeVisitor : public TreeNodeVisitor
00078 {
00079 public:
00080 ConnectNodeVisitor(NodeListView* view) : m_view(view) {}
00081
00082 virtual bool visitTreeNode(TreeNode* node)
00083 {
00084 connect(node, SIGNAL(signalDestroyed(TreeNode*)), m_view, SLOT(slotNodeDestroyed(TreeNode*) ));
00085 connect(node, SIGNAL(signalChanged(TreeNode*)), m_view, SLOT(slotNodeChanged(TreeNode*) ));
00086 return true;
00087 }
00088
00089 virtual bool visitFolder(Folder* node)
00090 {
00091 visitTreeNode(node);
00092 connect(node, SIGNAL(signalChildAdded(TreeNode*)), m_view, SLOT(slotNodeAdded(TreeNode*) ));
00093 connect(node, SIGNAL(signalChildRemoved(Folder*, TreeNode*)), m_view, SLOT(slotNodeRemoved(Folder*, TreeNode*) ));
00094 return true;
00095 }
00096
00097 virtual bool visitFeed(Feed* node)
00098 {
00099 visitTreeNode(node);
00100
00101 connect(node, SIGNAL(fetchStarted(Feed*)), m_view, SLOT(slotFeedFetchStarted(Feed*)));
00102 connect(node, SIGNAL(fetchAborted(Feed*)), m_view, SLOT(slotFeedFetchAborted(Feed*)));
00103 connect(node, SIGNAL(fetchError(Feed*)), m_view, SLOT(slotFeedFetchError(Feed*)));
00104 connect(node, SIGNAL(fetched(Feed*)), m_view, SLOT(slotFeedFetchCompleted(Feed*)));
00105 return true;
00106 }
00107 private:
00108
00109 NodeListView* m_view;
00110
00111 };
00112
00113 class NodeListView::DisconnectNodeVisitor : public TreeNodeVisitor
00114 {
00115 public:
00116 DisconnectNodeVisitor(NodeListView* view) : m_view(view) {}
00117
00118 virtual bool visitTagNode(TagNode* node)
00119 {
00120 disconnect(node, SIGNAL(signalDestroyed(TreeNode*)), m_view, SLOT(slotNodeDestroyed(TreeNode*) ));
00121 disconnect(node, SIGNAL(signalChanged(TreeNode*)), m_view, SLOT(slotNodeChanged(TreeNode*) ));
00122 return true;
00123 }
00124
00125 virtual bool visitFolder(Folder* node)
00126 {
00127 disconnect(node, SIGNAL(signalChildAdded(TreeNode*)), m_view, SLOT(slotNodeAdded(TreeNode*) ));
00128 disconnect(node, SIGNAL(signalChildRemoved(Folder*, TreeNode*)), m_view, SLOT(slotNodeRemoved(Folder*, TreeNode*) ));
00129
00130 disconnect(node, SIGNAL(signalDestroyed(TreeNode*)), m_view, SLOT(slotNodeDestroyed(TreeNode*) ));
00131 disconnect(node, SIGNAL(signalChanged(TreeNode*)), m_view, SLOT(slotNodeChanged(TreeNode*) ));
00132 return true;
00133 }
00134
00135 virtual bool visitFeed(Feed* node)
00136 {
00137
00138 disconnect(node, SIGNAL(signalDestroyed(TreeNode*)), m_view, SLOT(slotNodeDestroyed(TreeNode*) ));
00139 disconnect(node, SIGNAL(signalChanged(TreeNode*)), m_view, SLOT(slotNodeChanged(TreeNode*) ));
00140 disconnect(node, SIGNAL(fetchStarted(Feed*)), m_view, SLOT(slotFeedFetchStarted(Feed*)));
00141 disconnect(node, SIGNAL(fetchAborted(Feed*)), m_view, SLOT(slotFeedFetchAborted(Feed*)));
00142 disconnect(node, SIGNAL(fetchError(Feed*)), m_view, SLOT(slotFeedFetchError(Feed*)));
00143 disconnect(node, SIGNAL(fetched(Feed*)), m_view, SLOT(slotFeedFetchCompleted(Feed*)));
00144 return true;
00145 }
00146 private:
00147
00148 NodeListView* m_view;
00149 };
00150
00151 class NodeListView::DeleteItemVisitor : public TreeNodeVisitor
00152 {
00153 public:
00154
00155 DeleteItemVisitor(NodeListView* view) : m_view(view) {}
00156
00157 virtual bool visitTreeNode(TreeNode* node)
00158 {
00159 TreeNodeItem* item = m_view->d->itemDict.take(node);
00160
00161 if (!item)
00162 return true;
00163
00164 if ( m_selectNeighbour && item->isSelected() )
00165 {
00166 if (item->itemBelow())
00167 m_view->setSelected(item->itemBelow(), true);
00168 else if (item->itemAbove())
00169 m_view->setSelected(item->itemAbove(), true);
00170 else
00171 m_view->setSelected(item, false);
00172 }
00173
00174 m_view->disconnectFromNode(node);
00175 delete item;
00176 return true;
00177
00178 }
00179
00180 virtual bool visitFolder(Folder* node)
00181 {
00182
00183 QValueList<TreeNode*> children = node->children();
00184 for (QValueList<TreeNode*>::ConstIterator it = children.begin(); it != children.end(); ++it )
00185 visit(*it);
00186
00187 visitTreeNode(node);
00188
00189 return true;
00190 }
00191
00192 void deleteItem(TreeNode* node, bool selectNeighbour)
00193 {
00194 m_selectNeighbour = selectNeighbour;
00195 visit(node);
00196 }
00197
00198 private:
00199 NodeListView* m_view;
00200 bool m_selectNeighbour;
00201 };
00202
00203 class NodeListView::CreateItemVisitor : public TreeNodeVisitor
00204 {
00205 public:
00206 CreateItemVisitor(NodeListView* view) : m_view(view) {}
00207
00208 virtual bool visitTagNode(TagNode* node)
00209 {
00210 if (m_view->findNodeItem(node))
00211 return true;
00212
00213 TagNodeItem* item = 0;
00214 TreeNode* prev = node->prevSibling();
00215 FolderItem* parentItem = static_cast<FolderItem*>(m_view->findNodeItem(node->parent()));
00216 if (parentItem)
00217 {
00218 if (prev)
00219 {
00220 item = new TagNodeItem( parentItem, m_view->findNodeItem(prev), node);
00221 }
00222 else
00223 item = new TagNodeItem( parentItem, node);
00224 }
00225 else
00226 {
00227 if (prev)
00228 {
00229 item = new TagNodeItem(m_view, m_view->findNodeItem(prev), node);
00230 }
00231 else
00232 item = new TagNodeItem(m_view, node);
00233 }
00234 item->nodeChanged();
00235 m_view->d->itemDict.insert(node, item);
00236 m_view->connectToNode(node);
00237 if (parentItem)
00238 parentItem->sortChildItems(0, true);
00239 return true;
00240 }
00241
00242 virtual bool visitTagFolder(TagFolder* node)
00243 {
00244 if (m_view->findNodeItem(node))
00245 return true;
00246
00247 TagFolderItem* item = 0;
00248 TreeNode* prev = node->prevSibling();
00249 FolderItem* parentItem = static_cast<FolderItem*>(m_view->findNodeItem(node->parent()));
00250 if (parentItem)
00251 {
00252 if (prev)
00253 {
00254 item = new TagFolderItem( parentItem, m_view->findNodeItem(prev), node);
00255 }
00256 else
00257 item = new TagFolderItem(parentItem, node);
00258 }
00259 else
00260 {
00261 if (prev)
00262 {
00263 item = new TagFolderItem(m_view, m_view->findNodeItem(prev), node);
00264 }
00265 else
00266 item = new TagFolderItem(m_view, node);
00267
00268 }
00269 m_view->d->itemDict.insert(node, item);
00270 QValueList<TreeNode*> children = node->children();
00271
00272
00273 for (QValueList<TreeNode*>::ConstIterator it = children.begin(); it != children.end(); ++it )
00274 visit(*it);
00275
00276 m_view->connectToNode(node);
00277 return true;
00278 }
00279
00280 virtual bool visitFolder(Folder* node)
00281 {
00282 if (m_view->findNodeItem(node))
00283 return true;
00284
00285 FolderItem* item = 0;
00286 TreeNode* prev = node->prevSibling();
00287 FolderItem* parentItem = static_cast<FolderItem*>(m_view->findNodeItem(node->parent()));
00288 if (parentItem)
00289 {
00290 if (prev)
00291 {
00292 item = new FolderItem( parentItem, m_view->findNodeItem(prev), node);
00293 }
00294 else
00295 item = new FolderItem(parentItem, node);
00296 }
00297 else
00298 {
00299 if (prev)
00300 {
00301 item = new FolderItem(m_view, m_view->findNodeItem(prev), node);
00302 }
00303 else
00304 item = new FolderItem(m_view, node);
00305 }
00306 m_view->d->itemDict.insert(node, item);
00307
00308
00309 QValueList<TreeNode*> children = node->children();
00310 for (QValueList<TreeNode*>::ConstIterator it = children.begin(); it != children.end(); ++it )
00311 visit(*it);
00312
00313 m_view->connectToNode(node);
00314 return true;
00315 }
00316
00317 virtual bool visitFeed(Feed* node)
00318 {
00319 if (m_view->findNodeItem(node))
00320 return true;
00321
00322 FeedItem* item = 0;
00323 TreeNode* prev = node->prevSibling();
00324 FolderItem* parentItem = static_cast<FolderItem*>(m_view->findNodeItem(node->parent()));
00325
00326 if (parentItem)
00327 {
00328 if (prev)
00329 {
00330 item = new FeedItem( parentItem, m_view->findNodeItem(prev), node);
00331 }
00332 else
00333 item = new FeedItem( parentItem, node);
00334 }
00335 else
00336 {
00337 if (prev)
00338 {
00339 item = new FeedItem(m_view, m_view->findNodeItem(prev), node);
00340 }
00341 else
00342 item = new FeedItem(m_view, node);
00343 }
00344
00345 item->nodeChanged();
00346 m_view->d->itemDict.insert(node, item);
00347 m_view->connectToNode(node);
00348 return true;
00349 }
00350
00351 private:
00352 NodeListView* m_view;
00353 };
00354
00355 NodeListView::NodeListView( QWidget *parent, const char *name)
00356 : KListView(parent, name), d(new NodeListViewPrivate)
00357 {
00358 d->showTagFolders = true;
00359 d->connectNodeVisitor = new ConnectNodeVisitor(this),
00360 d->disconnectNodeVisitor = new DisconnectNodeVisitor(this);
00361 d->createItemVisitor = new CreateItemVisitor(this);
00362 d->deleteItemVisitor = new DeleteItemVisitor(this);
00363
00364 setMinimumSize(150, 150);
00365 addColumn(i18n("Feeds"));
00366 setRootIsDecorated(false);
00367 setItemsRenameable(false);
00368 setItemMargin(2);
00369
00370 setFullWidth(true);
00371 setSorting(-1);
00372 setDragAutoScroll(true);
00373 setDropVisualizer(true);
00374
00375
00376 setDragEnabled(true);
00377 setAcceptDrops(true);
00378 setItemsMovable(true);
00379
00380 connect( this, SIGNAL(dropped(QDropEvent*, QListViewItem*)), this, SLOT(slotDropped(QDropEvent*, QListViewItem*)) );
00381 connect( this, SIGNAL(selectionChanged(QListViewItem*)), this, SLOT(slotSelectionChanged(QListViewItem*)) );
00382 connect( this, SIGNAL(itemRenamed(QListViewItem*, int, const QString&)), this, SLOT(slotItemRenamed(QListViewItem*, int, const QString&)) );
00383 connect( this, SIGNAL(contextMenu(KListView*, QListViewItem*, const QPoint&)), this, SLOT(slotContextMenu(KListView*, QListViewItem*, const QPoint&)) );
00384 connect( &(d->autoopentimer), SIGNAL( timeout() ), this, SLOT( openFolder() ) );
00385
00386 clear();
00387
00388 QWhatsThis::add(this, i18n("<h2>Feeds tree</h2>"
00389 "Here you can browse tree of feeds. "
00390 "You can also add feeds or feed groups (folders) "
00391 "using right-click menu, or reorganize them using "
00392 "drag and drop."));
00393 setUpdatesEnabled(true);
00394 }
00395
00396 NodeListView::~NodeListView()
00397 {
00398 delete d->connectNodeVisitor;
00399 delete d->disconnectNodeVisitor;
00400 delete d->createItemVisitor;
00401 delete d->deleteItemVisitor;
00402 delete d;
00403 d = 0;
00404 }
00405
00406 void NodeListView::setNodeList(NodeList* nodeList)
00407 {
00408 if (nodeList == d->nodeList)
00409 return;
00410
00411 clear();
00412
00413 disconnectFromNodeList(d->nodeList);
00414
00415 if (!nodeList)
00416 return;
00417
00418 d->nodeList = nodeList;
00419 connectToNodeList(nodeList);
00420
00421
00422 Folder* rootNode = nodeList->rootNode();
00423 if (!rootNode)
00424 return;
00425
00426 slotNodeAdded(rootNode);
00427 slotRootNodeChanged(rootNode);
00428 }
00429
00430 Folder* NodeListView::rootNode()
00431 {
00432 return d->nodeList ? d->nodeList->rootNode() : 0;
00433 }
00434
00435 TreeNode* NodeListView::selectedNode()
00436 {
00437 TreeNodeItem* item = dynamic_cast<TreeNodeItem*> (selectedItem());
00438
00439 return ( item ? item->node() : 0) ;
00440 }
00441
00442 void NodeListView::setSelectedNode(TreeNode* node)
00443 {
00444 TreeNodeItem* item = findNodeItem(node);
00445 if ( node && item )
00446 setSelected(item, true);
00447 }
00448
00449 TreeNode* NodeListView::findNodeByTitle(const QString& title)
00450 {
00451 TreeNodeItem* item = dynamic_cast<TreeNodeItem*>(findItemByTitle(title, 0));
00452 if (!item)
00453 return 0;
00454 else
00455 return item->node();
00456 }
00457
00458 TreeNodeItem* NodeListView::findNodeItem(TreeNode* node)
00459 {
00460 return d->itemDict.find(node);
00461 }
00462
00463 TreeNodeItem* NodeListView::findItemByTitle(const QString& text, int column, ComparisonFlags compare) const
00464 {
00465 return dynamic_cast<TreeNodeItem*> (KListView::findItem(text, column, compare));
00466 }
00467
00468 void NodeListView::ensureNodeVisible(TreeNode* node)
00469 {
00470 ensureItemVisible(findNodeItem(node));
00471 }
00472
00473 void NodeListView::startNodeRenaming(TreeNode* node)
00474 {
00475 TreeNodeItem* item = findNodeItem(node);
00476 if (item)
00477 {
00478 item->startRename(0);
00479 }
00480 }
00481
00482 void NodeListView::clear()
00483 {
00484 QPtrDictIterator<TreeNodeItem> it(d->itemDict);
00485 for( ; it.current(); ++it )
00486 disconnectFromNode( it.current()->node() );
00487 d->itemDict.clear();
00488 d->nodeList = 0;
00489
00490 KListView::clear();
00491 }
00492
00493 void NodeListView::drawContentsOffset( QPainter * p, int ox, int oy,
00494 int cx, int cy, int cw, int ch )
00495 {
00496 bool oldUpdatesEnabled = isUpdatesEnabled();
00497 setUpdatesEnabled(false);
00498 KListView::drawContentsOffset( p, ox, oy, cx, cy, cw, ch );
00499 setUpdatesEnabled(oldUpdatesEnabled);
00500 }
00501
00502 void NodeListView::slotDropped( QDropEvent *e, QListViewItem*
00503 )
00504 {
00505 d->autoopentimer.stop();
00506
00507 if (e->source() != viewport())
00508 {
00509 openFolder();
00510
00511 if (KURLDrag::canDecode(e))
00512 {
00513 FolderItem* parent = dynamic_cast<FolderItem*> (d->parent);
00514 TreeNodeItem* afterMe = 0;
00515
00516 if(d->afterme)
00517 afterMe = dynamic_cast<TreeNodeItem*> (d->afterme);
00518
00519 KURL::List urls;
00520 KURLDrag::decode( e, urls );
00521 e->accept();
00522 emit signalDropped( urls, afterMe ? afterMe->node() : 0, parent ? parent->node() : 0);
00523 }
00524 }
00525 else
00526 {
00527 }
00528 }
00529
00530 void NodeListView::movableDropEvent(QListViewItem* , QListViewItem* )
00531 {
00532 d->autoopentimer.stop();
00533 if (d->parent)
00534 {
00535 openFolder();
00536
00537 Folder* parentNode = (dynamic_cast<FolderItem*> (d->parent))->node();
00538 TreeNode* afterMeNode = 0;
00539 TreeNode* current = selectedNode();
00540
00541 if (d->afterme)
00542 afterMeNode = (dynamic_cast<TreeNodeItem*> (d->afterme))->node();
00543
00544 current->parent()->removeChild(current);
00545 parentNode->insertChild(current, afterMeNode);
00546 KListView::movableDropEvent(d->parent, d->afterme);
00547 }
00548 }
00549
00550 void NodeListView::setShowTagFolders(bool enabled)
00551 {
00552 d->showTagFolders = enabled;
00553 }
00554
00555 void NodeListView::contentsDragMoveEvent(QDragMoveEvent* event)
00556 {
00557 QPoint vp = contentsToViewport(event->pos());
00558 QListViewItem *i = itemAt(vp);
00559
00560 QListViewItem *qiparent;
00561 QListViewItem *qiafterme;
00562 findDrop( event->pos(), qiparent, qiafterme );
00563
00564 if (event->source() == viewport()) {
00565
00566 if (i && !i->parent())
00567 {
00568 event->ignore();
00569 d->autoopentimer.stop();
00570 return;
00571 }
00572
00573
00574 QListViewItem* root1 = i;
00575 while (root1 && root1->parent())
00576 root1 = root1->parent();
00577
00578 QListViewItem* root2 = selectedItem();
00579 while (root2 && root2->parent())
00580 root2 = root2->parent();
00581
00582 if (root1 != root2)
00583 {
00584 event->ignore();
00585 d->autoopentimer.stop();
00586 return;
00587 }
00588
00589
00590 QListViewItem* p = qiparent;
00591 while (p)
00592 if (p == selectedItem())
00593 {
00594 event->ignore();
00595 d->autoopentimer.stop();
00596 return;
00597 }
00598 else
00599 {
00600 p = p->parent();
00601 }
00602
00603
00604 if (selectedItem() == i)
00605 {
00606 event->ignore();
00607 d->autoopentimer.stop();
00608 return;
00609 }
00610 }
00611
00612
00613
00614
00615
00616
00617
00618
00619 if (i && (itemAt(vp - QPoint(0,5)) == i && itemAt(vp + QPoint(0,5)) == i))
00620 {
00621 setDropVisualizer(false);
00622 setDropHighlighter(true);
00623 cleanDropVisualizer();
00624
00625 TreeNode *iNode = (dynamic_cast<TreeNodeItem*> (i))->node();
00626 if (iNode->isGroup())
00627 {
00628 if (i != d->parent)
00629 d->autoopentimer.start(750);
00630
00631 d->parent = i;
00632 d->afterme = 0;
00633 }
00634 else
00635 {
00636 event->ignore();
00637 d->autoopentimer.stop();
00638 d->afterme = i;
00639 return;
00640 }
00641 }
00642 else
00643 {
00644 setDropVisualizer(true);
00645 setDropHighlighter(false);
00646 cleanItemHighlighter();
00647 d->parent = qiparent;
00648 d->afterme = qiafterme;
00649 d->autoopentimer.stop();
00650 }
00651
00652
00653 KListView::contentsDragMoveEvent(event);
00654 }
00655
00656 bool NodeListView::acceptDrag(QDropEvent *e) const
00657 {
00658 if (!acceptDrops() || !itemsMovable())
00659 return false;
00660
00661 if (e->source() != viewport())
00662 {
00663 return KURLDrag::canDecode(e);
00664 }
00665 else
00666 {
00667
00668 if (selectedItem() && !selectedItem()->parent())
00669 return false;
00670 else
00671 return true;
00672 }
00673
00674 return true;
00675 }
00676
00677 void NodeListView::slotItemUp()
00678 {
00679 if (selectedItem() && selectedItem()->itemAbove())
00680 {
00681 setSelected( selectedItem()->itemAbove(), true );
00682 ensureItemVisible(selectedItem());
00683 }
00684 }
00685
00686 void NodeListView::slotItemDown()
00687 {
00688 if (selectedItem() && selectedItem()->itemBelow())
00689 {
00690 setSelected( selectedItem()->itemBelow(), true );
00691 ensureItemVisible(selectedItem());
00692 }
00693 }
00694
00695 void NodeListView::slotItemBegin()
00696 {
00697 setSelected( firstChild(), true );
00698 ensureItemVisible(firstChild());
00699 }
00700
00701 void NodeListView::slotItemEnd()
00702 {
00703 QListViewItem* elt = firstChild();
00704 if (elt)
00705 while (elt->itemBelow())
00706 elt = elt->itemBelow();
00707 setSelected( elt, true );
00708 ensureItemVisible(elt);
00709 }
00710
00711 void NodeListView::slotItemLeft()
00712 {
00713 QListViewItem* sel = selectedItem();
00714
00715 if (!sel || sel == findNodeItem(rootNode()))
00716 return;
00717
00718 if (sel->isOpen())
00719 sel->setOpen(false);
00720 else
00721 {
00722 if (sel->parent())
00723 setSelected( sel->parent(), true );
00724 }
00725
00726 ensureItemVisible( selectedItem() );
00727 }
00728
00729 void NodeListView::slotItemRight()
00730 {
00731 QListViewItem* sel = selectedItem();
00732 if (!sel)
00733 {
00734 setSelected( firstChild(), true );
00735 sel = firstChild();
00736 }
00737 if (sel->isExpandable() && !sel->isOpen())
00738 sel->setOpen(true);
00739 else
00740 {
00741 if (sel->firstChild())
00742 setSelected( sel->firstChild(), true );
00743 }
00744 ensureItemVisible( selectedItem() );
00745 }
00746
00747 void NodeListView::slotPrevFeed()
00748 {
00749 for (QListViewItemIterator it( selectedItem()); it.current(); --it )
00750 {
00751 TreeNodeItem* tni = dynamic_cast<TreeNodeItem*>(*it);
00752 if (tni && !tni->isSelected() && !tni->node()->isGroup() )
00753 {
00754 setSelected(tni, true);
00755 ensureItemVisible(tni);
00756 return;
00757 }
00758 }
00759 }
00760
00761 void NodeListView::slotNextFeed()
00762 {
00763 for (QListViewItemIterator it( selectedItem()); it.current(); ++it )
00764 {
00765 TreeNodeItem* tni = dynamic_cast<TreeNodeItem*>(*it);
00766 if ( tni && !tni->isSelected() && !tni->node()->isGroup() )
00767 {
00768 setSelected(tni, true);
00769 ensureItemVisible(tni);
00770 return;
00771 }
00772 }
00773 }
00774
00775 void NodeListView::slotPrevUnreadFeed()
00776 {
00777 if (!firstChild() || !firstChild()->firstChild())
00778 return;
00779 if ( !selectedItem() )
00780 slotNextUnreadFeed();
00781
00782 QListViewItemIterator it( selectedItem() );
00783
00784 for ( ; it.current(); --it )
00785 {
00786 TreeNodeItem* tni = dynamic_cast<TreeNodeItem*> (it.current());
00787 if (!tni)
00788 break;
00789 if ( !tni->isSelected() && !tni->node()->isGroup() && tni->node()->unread() > 0)
00790 {
00791 setSelected(tni, true);
00792 ensureItemVisible(tni);
00793 return;
00794 }
00795 }
00796
00797
00798 if (rootNode()->unread() > 0)
00799 {
00800
00801 it = QListViewItemIterator(lastItem());
00802
00803 for ( ; it.current(); --it)
00804 {
00805
00806 TreeNodeItem* tni = dynamic_cast<TreeNodeItem*> (it.current());
00807
00808 if (!tni)
00809 break;
00810
00811 if (!tni->isSelected() && !tni->node()->isGroup() && tni->node()->unread() > 0)
00812 {
00813 setSelected(tni, true);
00814 ensureItemVisible(tni);
00815 return;
00816 }
00817 }
00818 }
00819 }
00820
00821 void NodeListView::slotNextUnreadFeed()
00822 {
00823 QListViewItemIterator it;
00824
00825 if ( !selectedItem() )
00826 {
00827
00828 if (!firstChild() || !firstChild()->firstChild())
00829 return;
00830 else
00831 it = QListViewItemIterator( firstChild()->firstChild());
00832 }
00833 else
00834 it = QListViewItemIterator( selectedItem() );
00835
00836 for ( ; it.current(); ++it )
00837 {
00838 TreeNodeItem* tni = dynamic_cast<TreeNodeItem*> (it.current());
00839 if (!tni)
00840 break;
00841 if ( !tni->isSelected() && !tni->node()->isGroup() && tni->node()->unread() > 0)
00842 {
00843 setSelected(tni, true);
00844 ensureItemVisible(tni);
00845 return;
00846 }
00847 }
00848
00849 if (rootNode()->unread() > 0)
00850 {
00851 clearSelection();
00852 slotNextUnreadFeed();
00853 }
00854 }
00855
00856 void NodeListView::slotSelectionChanged(QListViewItem* item)
00857 {
00858 TreeNodeItem* ni = dynamic_cast<TreeNodeItem*> (item);
00859
00860 if (ni)
00861 {
00862 emit signalNodeSelected(ni->node());
00863 }
00864 }
00865
00866 void NodeListView::slotItemRenamed(QListViewItem* item, int col, const QString& text)
00867 {
00868 TreeNodeItem* ni = dynamic_cast<TreeNodeItem*> (item);
00869 if ( !ni || !ni->node() )
00870 return;
00871 if (col == 0)
00872 {
00873 if (text != ni->node()->title())
00874 {
00875 ni->node()->setTitle(text);
00876 }
00877 }
00878 }
00879 void NodeListView::slotContextMenu(KListView* list, QListViewItem* item, const QPoint& p)
00880 {
00881 TreeNodeItem* ti = dynamic_cast<TreeNodeItem*>(item);
00882 emit signalContextMenu(list, ti ? ti->node() : 0, p);
00883 if (ti)
00884 ti->showContextMenu(p);
00885 }
00886
00887 void NodeListView::slotFeedFetchStarted(Feed* feed)
00888 {
00889
00890 if (!feed->favicon().isNull())
00891 {
00892 TreeNodeItem* item = findNodeItem(feed);
00893 if (item)
00894 {
00895 KIconEffect iconEffect;
00896 QPixmap tempIcon = iconEffect.apply(feed->favicon(), KIcon::Small, KIcon::DisabledState);
00897 item->setPixmap(0, tempIcon);
00898 }
00899 }
00900
00901 }
00902
00903 void NodeListView::slotFeedFetchAborted(Feed* feed)
00904 {
00905 TreeNodeItem* item = findNodeItem(feed);
00906 if (item)
00907 item->nodeChanged();
00908 }
00909
00910 void NodeListView::slotFeedFetchError(Feed* feed)
00911 {
00912 TreeNodeItem* item = findNodeItem(feed);
00913 if (item)
00914 item->nodeChanged();
00915 }
00916
00917 void NodeListView::slotFeedFetchCompleted(Feed* feed)
00918 {
00919 TreeNodeItem* item = findNodeItem(feed);
00920 if (item)
00921 item->nodeChanged();
00922 }
00923
00924 void NodeListView::slotNodeAdded(TreeNode* node)
00925 {
00926 if (node)
00927 d->createItemVisitor->visit(node);
00928 }
00929
00930 void NodeListView::slotNodeRemoved(Folder* , TreeNode* node)
00931 {
00932 if (node)
00933 d->deleteItemVisitor->deleteItem(node, false);
00934 }
00935
00936 void NodeListView::connectToNode(TreeNode* node)
00937 {
00938 if (node)
00939 d->connectNodeVisitor->visit(node);
00940 }
00941
00942 void NodeListView::connectToNodeList(NodeList* list)
00943 {
00944 if (!list)
00945 return;
00946
00947 connect(list, SIGNAL(signalDestroyed(NodeList*)), this, SLOT(slotNodeListDestroyed(NodeList*)) );
00948 connect(list->rootNode(), SIGNAL(signalChanged(TreeNode*)), this, SLOT(slotRootNodeChanged(TreeNode*)));
00949 }
00950
00951 void NodeListView::disconnectFromNodeList(NodeList* list)
00952 {
00953 if (!list)
00954 return;
00955
00956 disconnect(list, SIGNAL(signalDestroyed(NodeList*)), this, SLOT(slotNodeListDestroyed(NodeList*)) );
00957 disconnect(list->rootNode(), SIGNAL(signalChanged(TreeNode*)), this, SLOT(slotRootNodeChanged(TreeNode*)));
00958 }
00959
00960 void NodeListView::disconnectFromNode(TreeNode* node)
00961 {
00962 if (node)
00963 d->disconnectNodeVisitor->visit(node);
00964 }
00965
00966 void NodeListView::slotNodeListDestroyed(NodeList* list)
00967 {
00968 if (list != d->nodeList)
00969 return;
00970
00971 setNodeList(0);
00972 }
00973
00974 void NodeListView::slotNodeDestroyed(TreeNode* node)
00975 {
00976 if (node)
00977 d->deleteItemVisitor->deleteItem(node, true);
00978 }
00979
00980 void NodeListView::slotRootNodeChanged(TreeNode* rootNode)
00981 {
00982 emit signalRootNodeChanged(this, rootNode);
00983 }
00984
00985 void NodeListView::slotNodeChanged(TreeNode* node)
00986 {
00987 TreeNodeItem* item = findNodeItem(node);
00988 if (item)
00989 {
00990 item->nodeChanged();
00991 triggerUpdate();
00992 }
00993 }
00994
00995 QDragObject *NodeListView::dragObject()
00996 {
00997 KMultipleDrag *md = new KMultipleDrag(viewport());
00998 QDragObject *obj = KListView::dragObject();
00999 if (obj) {
01000 md->addDragObject(obj);
01001 }
01002 TreeNodeItem *i = dynamic_cast<TreeNodeItem*>(currentItem());
01003 if (i) {
01004 md->setPixmap(*(i->pixmap(0)));
01005 FeedItem *fi = dynamic_cast<FeedItem*>(i);
01006 if (fi) {
01007 md->addDragObject(new KURLDrag(KURL(fi->node()->xmlUrl()), 0L));
01008 }
01009 }
01010 return md;
01011 }
01012
01013 void NodeListView::openFolder() {
01014 d->autoopentimer.stop();
01015 if (d->parent && !d->parent->isOpen())
01016 {
01017 d->parent->setOpen(true);
01018 }
01019 }
01020
01021 }
01022
01023 #include "feedlistview.moc"