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