25 #include "dragobjects.h"
27 #include "folderitem.h"
28 #include "tagfolder.h"
29 #include "tagfolderitem.h"
30 #include "feedlistview.h"
36 #include "tagnodeitem.h"
37 #include "tagnodelist.h"
39 #include "treenodeitem.h"
40 #include "treenodevisitor.h"
43 #include <kiconeffect.h>
44 #include <kiconloader.h>
46 #include <kmultipledrag.h>
47 #include <kstringhandler.h>
52 #include <tqpainter.h>
53 #include <tqptrdict.h>
55 #include <tqwhatsthis.h>
59 class NodeListView::NodeListViewPrivate
63 TQPtrDict<TreeNodeItem> itemDict;
68 TQListViewItem *parent;
69 TQListViewItem *afterme;
70 TQTimer autoopentimer;
71 ConnectNodeVisitor* connectNodeVisitor;
72 DisconnectNodeVisitor* disconnectNodeVisitor;
73 CreateItemVisitor* createItemVisitor;
74 DeleteItemVisitor* deleteItemVisitor;
77 class NodeListView::ConnectNodeVisitor :
public TreeNodeVisitor
80 ConnectNodeVisitor(NodeListView* view) : m_view(view) {}
82 virtual bool visitTreeNode(TreeNode* node)
84 connect(node, TQT_SIGNAL(signalDestroyed(TreeNode*)), m_view, TQT_SLOT(slotNodeDestroyed(TreeNode*) ));
85 connect(node, TQT_SIGNAL(signalChanged(TreeNode*)), m_view, TQT_SLOT(slotNodeChanged(TreeNode*) ));
89 virtual bool visitFolder(Folder* node)
92 connect(node, TQT_SIGNAL(signalChildAdded(TreeNode*)), m_view, TQT_SLOT(slotNodeAdded(TreeNode*) ));
93 connect(node, TQT_SIGNAL(signalChildRemoved(Folder*, TreeNode*)), m_view, TQT_SLOT(slotNodeRemoved(Folder*, TreeNode*) ));
97 virtual bool visitFeed(Feed* node)
101 connect(node, TQT_SIGNAL(fetchStarted(Feed*)), m_view, TQT_SLOT(slotFeedFetchStarted(Feed*)));
102 connect(node, TQT_SIGNAL(fetchAborted(Feed*)), m_view, TQT_SLOT(slotFeedFetchAborted(Feed*)));
103 connect(node, TQT_SIGNAL(fetchError(Feed*)), m_view, TQT_SLOT(slotFeedFetchError(Feed*)));
104 connect(node, TQT_SIGNAL(fetched(Feed*)), m_view, TQT_SLOT(slotFeedFetchCompleted(Feed*)));
109 NodeListView* m_view;
113 class NodeListView::DisconnectNodeVisitor :
public TreeNodeVisitor
116 DisconnectNodeVisitor(NodeListView* view) : m_view(view) {}
118 virtual bool visitTagNode(TagNode* node)
120 disconnect(node, TQT_SIGNAL(signalDestroyed(TreeNode*)), m_view, TQT_SLOT(slotNodeDestroyed(TreeNode*) ));
121 disconnect(node, TQT_SIGNAL(signalChanged(TreeNode*)), m_view, TQT_SLOT(slotNodeChanged(TreeNode*) ));
125 virtual bool visitFolder(Folder* node)
127 disconnect(node, TQT_SIGNAL(signalChildAdded(TreeNode*)), m_view, TQT_SLOT(slotNodeAdded(TreeNode*) ));
128 disconnect(node, TQT_SIGNAL(signalChildRemoved(Folder*, TreeNode*)), m_view, TQT_SLOT(slotNodeRemoved(Folder*, TreeNode*) ));
130 disconnect(node, TQT_SIGNAL(signalDestroyed(TreeNode*)), m_view, TQT_SLOT(slotNodeDestroyed(TreeNode*) ));
131 disconnect(node, TQT_SIGNAL(signalChanged(TreeNode*)), m_view, TQT_SLOT(slotNodeChanged(TreeNode*) ));
135 virtual bool visitFeed(Feed* node)
138 disconnect(node, TQT_SIGNAL(signalDestroyed(TreeNode*)), m_view, TQT_SLOT(slotNodeDestroyed(TreeNode*) ));
139 disconnect(node, TQT_SIGNAL(signalChanged(TreeNode*)), m_view, TQT_SLOT(slotNodeChanged(TreeNode*) ));
140 disconnect(node, TQT_SIGNAL(fetchStarted(Feed*)), m_view, TQT_SLOT(slotFeedFetchStarted(Feed*)));
141 disconnect(node, TQT_SIGNAL(fetchAborted(Feed*)), m_view, TQT_SLOT(slotFeedFetchAborted(Feed*)));
142 disconnect(node, TQT_SIGNAL(fetchError(Feed*)), m_view, TQT_SLOT(slotFeedFetchError(Feed*)));
143 disconnect(node, TQT_SIGNAL(fetched(Feed*)), m_view, TQT_SLOT(slotFeedFetchCompleted(Feed*)));
148 NodeListView* m_view;
151 class NodeListView::DeleteItemVisitor :
public TreeNodeVisitor
155 DeleteItemVisitor(NodeListView* view) : m_view(view) {}
157 virtual bool visitTreeNode(TreeNode* node)
159 TreeNodeItem* item = m_view->d->itemDict.take(node);
164 if ( m_selectNeighbour && item->isSelected() )
166 if (item->itemBelow())
167 m_view->setSelected(item->itemBelow(),
true);
168 else if (item->itemAbove())
169 m_view->setSelected(item->itemAbove(),
true);
171 m_view->setSelected(item,
false);
174 m_view->disconnectFromNode(node);
180 virtual bool visitFolder(Folder* node)
183 TQValueList<TreeNode*> children = node->children();
184 for (TQValueList<TreeNode*>::ConstIterator it = children.begin(); it != children.end(); ++it )
192 void deleteItem(TreeNode* node,
bool selectNeighbour)
194 m_selectNeighbour = selectNeighbour;
199 NodeListView* m_view;
200 bool m_selectNeighbour;
203 class NodeListView::CreateItemVisitor :
public TreeNodeVisitor
206 CreateItemVisitor(NodeListView* view) : m_view(view) {}
208 virtual bool visitTagNode(TagNode* node)
210 if (m_view->findNodeItem(node))
213 TagNodeItem* item = 0;
214 TreeNode* prev = node->prevSibling();
215 FolderItem* parentItem =
static_cast<FolderItem*
>(m_view->findNodeItem(node->parent()));
220 item =
new TagNodeItem( parentItem, m_view->findNodeItem(prev), node);
223 item =
new TagNodeItem( parentItem, node);
229 item =
new TagNodeItem(m_view, m_view->findNodeItem(prev), node);
232 item =
new TagNodeItem(m_view, node);
235 m_view->d->itemDict.insert(node, item);
236 m_view->connectToNode(node);
238 parentItem->sortChildItems(0,
true);
242 virtual bool visitTagFolder(TagFolder* node)
244 if (m_view->findNodeItem(node))
247 TagFolderItem* item = 0;
248 TreeNode* prev = node->prevSibling();
249 FolderItem* parentItem =
static_cast<FolderItem*
>(m_view->findNodeItem(node->parent()));
254 item =
new TagFolderItem( parentItem, m_view->findNodeItem(prev), node);
257 item =
new TagFolderItem(parentItem, node);
263 item =
new TagFolderItem(m_view, m_view->findNodeItem(prev), node);
266 item =
new TagFolderItem(m_view, node);
269 m_view->d->itemDict.insert(node, item);
270 TQValueList<TreeNode*> children = node->children();
273 for (TQValueList<TreeNode*>::ConstIterator it = children.begin(); it != children.end(); ++it )
276 m_view->connectToNode(node);
280 virtual bool visitFolder(Folder* node)
282 if (m_view->findNodeItem(node))
285 FolderItem* item = 0;
286 TreeNode* prev = node->prevSibling();
287 FolderItem* parentItem =
static_cast<FolderItem*
>(m_view->findNodeItem(node->parent()));
292 item =
new FolderItem( parentItem, m_view->findNodeItem(prev), node);
295 item =
new FolderItem(parentItem, node);
301 item =
new FolderItem(m_view, m_view->findNodeItem(prev), node);
304 item =
new FolderItem(m_view, node);
306 m_view->d->itemDict.insert(node, item);
309 TQValueList<TreeNode*> children = node->children();
310 for (TQValueList<TreeNode*>::ConstIterator it = children.begin(); it != children.end(); ++it )
313 m_view->connectToNode(node);
317 virtual bool visitFeed(Feed* node)
319 if (m_view->findNodeItem(node))
323 TreeNode* prev = node->prevSibling();
324 FolderItem* parentItem =
static_cast<FolderItem*
>(m_view->findNodeItem(node->parent()));
330 item =
new FeedItem( parentItem, m_view->findNodeItem(prev), node);
333 item =
new FeedItem( parentItem, node);
339 item =
new FeedItem(m_view, m_view->findNodeItem(prev), node);
342 item =
new FeedItem(m_view, node);
346 m_view->d->itemDict.insert(node, item);
347 m_view->connectToNode(node);
352 NodeListView* m_view;
355 NodeListView::NodeListView( TQWidget *parent,
const char *name)
356 : KListView(parent, name), d(new NodeListViewPrivate)
358 d->showTagFolders =
true;
359 d->connectNodeVisitor =
new ConnectNodeVisitor(
this),
360 d->disconnectNodeVisitor =
new DisconnectNodeVisitor(
this);
361 d->createItemVisitor =
new CreateItemVisitor(
this);
362 d->deleteItemVisitor =
new DeleteItemVisitor(
this);
364 setMinimumSize(150, 150);
365 addColumn(i18n(
"Feeds"));
366 setRootIsDecorated(
false);
367 setItemsRenameable(
false);
372 setDragAutoScroll(
true);
373 setDropVisualizer(
true);
376 setDragEnabled(
true);
377 setAcceptDrops(
true);
378 setItemsMovable(
true);
380 connect(
this, TQT_SIGNAL(dropped(TQDropEvent*, TQListViewItem*)),
this, TQT_SLOT(slotDropped(TQDropEvent*, TQListViewItem*)) );
381 connect(
this, TQT_SIGNAL(selectionChanged(TQListViewItem*)),
this, TQT_SLOT(slotSelectionChanged(TQListViewItem*)) );
382 connect(
this, TQT_SIGNAL(itemRenamed(TQListViewItem*,
int,
const TQString&)),
this, TQT_SLOT(slotItemRenamed(TQListViewItem*,
int,
const TQString&)) );
383 connect(
this, TQT_SIGNAL(contextMenu(KListView*, TQListViewItem*,
const TQPoint&)),
this, TQT_SLOT(slotContextMenu(KListView*, TQListViewItem*,
const TQPoint&)) );
384 connect( &(d->autoopentimer), TQT_SIGNAL( timeout() ),
this, TQT_SLOT( openFolder() ) );
388 TQWhatsThis::add(
this, i18n(
"<h2>Feeds tree</h2>"
389 "Here you can browse tree of feeds. "
390 "You can also add feeds or feed groups (folders) "
391 "using right-click menu, or reorganize them using "
393 setUpdatesEnabled(
true);
396 NodeListView::~NodeListView()
398 delete d->connectNodeVisitor;
399 delete d->disconnectNodeVisitor;
400 delete d->createItemVisitor;
401 delete d->deleteItemVisitor;
406 void NodeListView::setNodeList(NodeList* nodeList)
408 if (nodeList == d->nodeList)
413 disconnectFromNodeList(d->nodeList);
418 d->nodeList = nodeList;
419 connectToNodeList(nodeList);
422 Folder* rootNode = nodeList->rootNode();
426 slotNodeAdded(rootNode);
427 slotRootNodeChanged(rootNode);
430 Folder* NodeListView::rootNode()
432 return d->nodeList ? d->nodeList->rootNode() : 0;
435 TreeNode* NodeListView::selectedNode()
437 TreeNodeItem* item =
dynamic_cast<TreeNodeItem*
> (selectedItem());
439 return ( item ? item->node() : 0) ;
442 void NodeListView::setSelectedNode(TreeNode* node)
444 TreeNodeItem* item = findNodeItem(node);
446 setSelected(item,
true);
449 TreeNode* NodeListView::findNodeByTitle(
const TQString& title)
451 TreeNodeItem* item =
dynamic_cast<TreeNodeItem*
>(findItemByTitle(title, 0));
458 TreeNodeItem* NodeListView::findNodeItem(TreeNode* node)
460 return d->itemDict.find(node);
463 TreeNodeItem* NodeListView::findItemByTitle(
const TQString& text,
int column, ComparisonFlags compare)
const
465 return dynamic_cast<TreeNodeItem*
> (KListView::findItem(text, column, compare));
468 void NodeListView::ensureNodeVisible(TreeNode* node)
470 ensureItemVisible(findNodeItem(node));
473 void NodeListView::startNodeRenaming(TreeNode* node)
475 TreeNodeItem* item = findNodeItem(node);
478 item->startRename(0);
482 void NodeListView::clear()
484 TQPtrDictIterator<TreeNodeItem> it(d->itemDict);
485 for( ; it.current(); ++it )
486 disconnectFromNode( it.current()->node() );
493 void NodeListView::drawContentsOffset( TQPainter * p,
int ox,
int oy,
494 int cx,
int cy,
int cw,
int ch )
496 bool oldUpdatesEnabled = isUpdatesEnabled();
497 setUpdatesEnabled(
false);
498 KListView::drawContentsOffset( p, ox, oy, cx, cy, cw, ch );
499 setUpdatesEnabled(oldUpdatesEnabled);
502 void NodeListView::slotDropped( TQDropEvent *e, TQListViewItem*
505 d->autoopentimer.stop();
507 if (e->source() != viewport())
511 if (KURLDrag::canDecode(e))
513 FolderItem* parent =
dynamic_cast<FolderItem*
> (d->parent);
514 TreeNodeItem* afterMe = 0;
517 afterMe =
dynamic_cast<TreeNodeItem*
> (d->afterme);
520 KURLDrag::decode( e, urls );
522 emit signalDropped( urls, afterMe ? afterMe->node() : 0, parent ? parent->node() : 0);
530 void NodeListView::movableDropEvent(TQListViewItem* , TQListViewItem* )
532 d->autoopentimer.stop();
537 Folder* parentNode = (
dynamic_cast<FolderItem*
> (d->parent))->node();
538 TreeNode* afterMeNode = 0;
539 TreeNode* current = selectedNode();
542 afterMeNode = (
dynamic_cast<TreeNodeItem*
> (d->afterme))->node();
544 current->parent()->removeChild(current);
545 parentNode->insertChild(current, afterMeNode);
546 KListView::movableDropEvent(d->parent, d->afterme);
550 void NodeListView::setShowTagFolders(
bool enabled)
552 d->showTagFolders = enabled;
555 void NodeListView::contentsDragMoveEvent(TQDragMoveEvent* event)
557 TQPoint vp = contentsToViewport(event->pos());
558 TQListViewItem *i = itemAt(vp);
560 TQListViewItem *qiparent;
561 TQListViewItem *qiafterme;
562 findDrop( event->pos(), qiparent, qiafterme );
564 if (event->source() == viewport()) {
566 if (i && !i->parent())
569 d->autoopentimer.stop();
574 TQListViewItem* root1 = i;
575 while (root1 && root1->parent())
576 root1 = root1->parent();
578 TQListViewItem* root2 = selectedItem();
579 while (root2 && root2->parent())
580 root2 = root2->parent();
585 d->autoopentimer.stop();
590 TQListViewItem* p = qiparent;
592 if (p == selectedItem())
595 d->autoopentimer.stop();
604 if (selectedItem() == i)
607 d->autoopentimer.stop();
619 if (i && (itemAt(vp - TQPoint(0,5)) == i && itemAt(vp + TQPoint(0,5)) == i))
621 setDropVisualizer(
false);
622 setDropHighlighter(
true);
623 cleanDropVisualizer();
625 TreeNode *iNode = (
dynamic_cast<TreeNodeItem*
> (i))->node();
626 if (iNode->isGroup())
629 d->autoopentimer.start(750);
637 d->autoopentimer.stop();
644 setDropVisualizer(
true);
645 setDropHighlighter(
false);
646 cleanItemHighlighter();
647 d->parent = qiparent;
648 d->afterme = qiafterme;
649 d->autoopentimer.stop();
653 KListView::contentsDragMoveEvent(event);
656 bool NodeListView::acceptDrag(TQDropEvent *e)
const
658 if (!acceptDrops() || !itemsMovable())
661 if (e->source() != viewport())
663 return KURLDrag::canDecode(e);
668 if (selectedItem() && !selectedItem()->parent())
677 void NodeListView::slotItemUp()
679 if (selectedItem() && selectedItem()->itemAbove())
681 setSelected( selectedItem()->itemAbove(),
true );
682 ensureItemVisible(selectedItem());
686 void NodeListView::slotItemDown()
688 if (selectedItem() && selectedItem()->itemBelow())
690 setSelected( selectedItem()->itemBelow(),
true );
691 ensureItemVisible(selectedItem());
695 void NodeListView::slotItemBegin()
697 setSelected( firstChild(),
true );
698 ensureItemVisible(firstChild());
701 void NodeListView::slotItemEnd()
703 TQListViewItem* elt = firstChild();
705 while (elt->itemBelow())
706 elt = elt->itemBelow();
707 setSelected( elt,
true );
708 ensureItemVisible(elt);
711 void NodeListView::slotItemLeft()
713 TQListViewItem* sel = selectedItem();
715 if (!sel || sel == findNodeItem(rootNode()))
723 setSelected( sel->parent(), true );
726 ensureItemVisible( selectedItem() );
729 void NodeListView::slotItemRight()
731 TQListViewItem* sel = selectedItem();
734 setSelected( firstChild(),
true );
737 if (sel->isExpandable() && !sel->isOpen())
741 if (sel->firstChild())
742 setSelected( sel->firstChild(), true );
744 ensureItemVisible( selectedItem() );
747 void NodeListView::slotPrevFeed()
749 for (TQListViewItemIterator it( selectedItem()); it.current(); --it )
751 TreeNodeItem* tni =
dynamic_cast<TreeNodeItem*
>(*it);
752 if (tni && !tni->isSelected() && !tni->node()->isGroup() )
754 setSelected(tni,
true);
755 ensureItemVisible(tni);
761 void NodeListView::slotNextFeed()
763 for (TQListViewItemIterator it( selectedItem()); it.current(); ++it )
765 TreeNodeItem* tni =
dynamic_cast<TreeNodeItem*
>(*it);
766 if ( tni && !tni->isSelected() && !tni->node()->isGroup() )
768 setSelected(tni,
true);
769 ensureItemVisible(tni);
775 void NodeListView::slotPrevUnreadFeed()
777 if (!firstChild() || !firstChild()->firstChild())
779 if ( !selectedItem() )
780 slotNextUnreadFeed();
782 TQListViewItemIterator it( selectedItem() );
784 for ( ; it.current(); --it )
786 TreeNodeItem* tni =
dynamic_cast<TreeNodeItem*
> (it.current());
789 if ( !tni->isSelected() && !tni->node()->isGroup() && tni->node()->unread() > 0)
791 setSelected(tni,
true);
792 ensureItemVisible(tni);
798 if (rootNode()->unread() > 0)
801 it = TQListViewItemIterator(lastItem());
803 for ( ; it.current(); --it)
806 TreeNodeItem* tni =
dynamic_cast<TreeNodeItem*
> (it.current());
811 if (!tni->isSelected() && !tni->node()->isGroup() && tni->node()->unread() > 0)
813 setSelected(tni,
true);
814 ensureItemVisible(tni);
821 void NodeListView::slotNextUnreadFeed()
823 TQListViewItemIterator it;
825 if ( !selectedItem() )
828 if (!firstChild() || !firstChild()->firstChild())
831 it = TQListViewItemIterator( firstChild()->firstChild());
834 it = TQListViewItemIterator( selectedItem() );
836 for ( ; it.current(); ++it )
838 TreeNodeItem* tni =
dynamic_cast<TreeNodeItem*
> (it.current());
841 if ( !tni->isSelected() && !tni->node()->isGroup() && tni->node()->unread() > 0)
843 setSelected(tni,
true);
844 ensureItemVisible(tni);
849 if (rootNode()->unread() > 0)
852 slotNextUnreadFeed();
856 void NodeListView::slotSelectionChanged(TQListViewItem* item)
858 TreeNodeItem* ni =
dynamic_cast<TreeNodeItem*
> (item);
862 emit signalNodeSelected(ni->node());
866 void NodeListView::slotItemRenamed(TQListViewItem* item,
int col,
const TQString& text)
868 TreeNodeItem* ni =
dynamic_cast<TreeNodeItem*
> (item);
869 if ( !ni || !ni->node() )
873 if (text != ni->node()->title())
875 ni->node()->setTitle(text);
879 void NodeListView::slotContextMenu(KListView* list, TQListViewItem* item,
const TQPoint& p)
881 TreeNodeItem* ti =
dynamic_cast<TreeNodeItem*
>(item);
882 emit signalContextMenu(list, ti ? ti->node() : 0, p);
884 ti->showContextMenu(p);
887 void NodeListView::slotFeedFetchStarted(Feed* feed)
890 if (!feed->favicon().isNull())
892 TreeNodeItem* item = findNodeItem(feed);
895 KIconEffect iconEffect;
896 TQPixmap tempIcon = iconEffect.apply(feed->favicon(), KIcon::Small, KIcon::DisabledState);
897 item->setPixmap(0, tempIcon);
903 void NodeListView::slotFeedFetchAborted(Feed* feed)
905 TreeNodeItem* item = findNodeItem(feed);
910 void NodeListView::slotFeedFetchError(Feed* feed)
912 TreeNodeItem* item = findNodeItem(feed);
917 void NodeListView::slotFeedFetchCompleted(Feed* feed)
919 TreeNodeItem* item = findNodeItem(feed);
924 void NodeListView::slotNodeAdded(TreeNode* node)
927 d->createItemVisitor->visit(node);
930 void NodeListView::slotNodeRemoved(Folder* , TreeNode* node)
933 d->deleteItemVisitor->deleteItem(node,
false);
936 void NodeListView::connectToNode(TreeNode* node)
939 d->connectNodeVisitor->visit(node);
942 void NodeListView::connectToNodeList(NodeList* list)
947 connect(list, TQT_SIGNAL(signalDestroyed(NodeList*)),
this, TQT_SLOT(slotNodeListDestroyed(NodeList*)) );
948 connect(list->rootNode(), TQT_SIGNAL(signalChanged(TreeNode*)),
this, TQT_SLOT(slotRootNodeChanged(TreeNode*)));
951 void NodeListView::disconnectFromNodeList(NodeList* list)
956 disconnect(list, TQT_SIGNAL(signalDestroyed(NodeList*)),
this, TQT_SLOT(slotNodeListDestroyed(NodeList*)) );
957 disconnect(list->rootNode(), TQT_SIGNAL(signalChanged(TreeNode*)),
this, TQT_SLOT(slotRootNodeChanged(TreeNode*)));
960 void NodeListView::disconnectFromNode(TreeNode* node)
963 d->disconnectNodeVisitor->visit(node);
966 void NodeListView::slotNodeListDestroyed(NodeList* list)
968 if (list != d->nodeList)
974 void NodeListView::slotNodeDestroyed(TreeNode* node)
977 d->deleteItemVisitor->deleteItem(node,
true);
980 void NodeListView::slotRootNodeChanged(TreeNode* rootNode)
982 emit signalRootNodeChanged(
this, rootNode);
985 void NodeListView::slotNodeChanged(TreeNode* node)
987 TreeNodeItem* item = findNodeItem(node);
995 TQDragObject *NodeListView::dragObject()
997 KMultipleDrag *md =
new KMultipleDrag(viewport());
998 TQDragObject *obj = KListView::dragObject();
1000 md->addDragObject(obj);
1002 TreeNodeItem *i =
dynamic_cast<TreeNodeItem*
>(currentItem());
1004 md->setPixmap(*(i->pixmap(0)));
1005 FeedItem *fi =
dynamic_cast<FeedItem*
>(i);
1007 md->addDragObject(
new KURLDrag(KURL(fi->node()->xmlUrl()), 0L));
1013 void NodeListView::openFolder() {
1014 d->autoopentimer.stop();
1015 if (d->parent && !d->parent->isOpen())
1017 d->parent->setOpen(
true);
1023 #include "feedlistview.moc"