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>
45 #include <tdelocale.h>
46 #include <tdemultipledrag.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) {}
81 virtual ~ConnectNodeVisitor() {}
83 virtual bool visitTreeNode(TreeNode* node)
85 connect(node, TQ_SIGNAL(signalDestroyed(TreeNode*)), m_view, TQ_SLOT(slotNodeDestroyed(TreeNode*) ));
86 connect(node, TQ_SIGNAL(signalChanged(TreeNode*)), m_view, TQ_SLOT(slotNodeChanged(TreeNode*) ));
90 virtual bool visitFolder(Folder* node)
93 connect(node, TQ_SIGNAL(signalChildAdded(TreeNode*)), m_view, TQ_SLOT(slotNodeAdded(TreeNode*) ));
94 connect(node, TQ_SIGNAL(signalChildRemoved(Folder*, TreeNode*)), m_view, TQ_SLOT(slotNodeRemoved(Folder*, TreeNode*) ));
98 virtual bool visitFeed(Feed* node)
102 connect(node, TQ_SIGNAL(fetchStarted(Feed*)), m_view, TQ_SLOT(slotFeedFetchStarted(Feed*)));
103 connect(node, TQ_SIGNAL(fetchAborted(Feed*)), m_view, TQ_SLOT(slotFeedFetchAborted(Feed*)));
104 connect(node, TQ_SIGNAL(fetchError(Feed*)), m_view, TQ_SLOT(slotFeedFetchError(Feed*)));
105 connect(node, TQ_SIGNAL(fetched(Feed*)), m_view, TQ_SLOT(slotFeedFetchCompleted(Feed*)));
110 NodeListView* m_view;
114 class NodeListView::DisconnectNodeVisitor :
public TreeNodeVisitor
117 DisconnectNodeVisitor(NodeListView* view) : m_view(view) {}
118 virtual ~DisconnectNodeVisitor() {}
120 virtual bool visitTagNode(TagNode* node)
122 disconnect(node, TQ_SIGNAL(signalDestroyed(TreeNode*)), m_view, TQ_SLOT(slotNodeDestroyed(TreeNode*) ));
123 disconnect(node, TQ_SIGNAL(signalChanged(TreeNode*)), m_view, TQ_SLOT(slotNodeChanged(TreeNode*) ));
127 virtual bool visitFolder(Folder* node)
129 disconnect(node, TQ_SIGNAL(signalChildAdded(TreeNode*)), m_view, TQ_SLOT(slotNodeAdded(TreeNode*) ));
130 disconnect(node, TQ_SIGNAL(signalChildRemoved(Folder*, TreeNode*)), m_view, TQ_SLOT(slotNodeRemoved(Folder*, TreeNode*) ));
132 disconnect(node, TQ_SIGNAL(signalDestroyed(TreeNode*)), m_view, TQ_SLOT(slotNodeDestroyed(TreeNode*) ));
133 disconnect(node, TQ_SIGNAL(signalChanged(TreeNode*)), m_view, TQ_SLOT(slotNodeChanged(TreeNode*) ));
137 virtual bool visitFeed(Feed* node)
140 disconnect(node, TQ_SIGNAL(signalDestroyed(TreeNode*)), m_view, TQ_SLOT(slotNodeDestroyed(TreeNode*) ));
141 disconnect(node, TQ_SIGNAL(signalChanged(TreeNode*)), m_view, TQ_SLOT(slotNodeChanged(TreeNode*) ));
142 disconnect(node, TQ_SIGNAL(fetchStarted(Feed*)), m_view, TQ_SLOT(slotFeedFetchStarted(Feed*)));
143 disconnect(node, TQ_SIGNAL(fetchAborted(Feed*)), m_view, TQ_SLOT(slotFeedFetchAborted(Feed*)));
144 disconnect(node, TQ_SIGNAL(fetchError(Feed*)), m_view, TQ_SLOT(slotFeedFetchError(Feed*)));
145 disconnect(node, TQ_SIGNAL(fetched(Feed*)), m_view, TQ_SLOT(slotFeedFetchCompleted(Feed*)));
150 NodeListView* m_view;
153 class NodeListView::DeleteItemVisitor :
public TreeNodeVisitor
157 DeleteItemVisitor(NodeListView* view) : m_view(view) {}
158 virtual ~DeleteItemVisitor() {}
160 virtual bool visitTreeNode(TreeNode* node)
162 TreeNodeItem* item = m_view->d->itemDict.take(node);
167 if ( m_selectNeighbour && item->isSelected() )
169 if (item->itemBelow())
170 m_view->setSelected(item->itemBelow(),
true);
171 else if (item->itemAbove())
172 m_view->setSelected(item->itemAbove(),
true);
174 m_view->setSelected(item,
false);
177 m_view->disconnectFromNode(node);
183 virtual bool visitFolder(Folder* node)
186 TQValueList<TreeNode*> children = node->children();
187 for (TQValueList<TreeNode*>::ConstIterator it = children.begin(); it != children.end(); ++it )
195 void deleteItem(TreeNode* node,
bool selectNeighbour)
197 m_selectNeighbour = selectNeighbour;
202 NodeListView* m_view;
203 bool m_selectNeighbour;
206 class NodeListView::CreateItemVisitor :
public TreeNodeVisitor
209 CreateItemVisitor(NodeListView* view) : m_view(view) {}
210 virtual ~CreateItemVisitor() {}
212 virtual bool visitTagNode(TagNode* node)
214 if (m_view->findNodeItem(node))
217 TagNodeItem* item = 0;
218 TreeNode* prev = node->prevSibling();
219 FolderItem* parentItem =
static_cast<FolderItem*
>(m_view->findNodeItem(node->parent()));
224 item =
new TagNodeItem( parentItem, m_view->findNodeItem(prev), node);
227 item =
new TagNodeItem( parentItem, node);
233 item =
new TagNodeItem(m_view, m_view->findNodeItem(prev), node);
236 item =
new TagNodeItem(m_view, node);
239 m_view->d->itemDict.insert(node, item);
240 m_view->connectToNode(node);
242 parentItem->sortChildItems(0,
true);
246 virtual bool visitTagFolder(TagFolder* node)
248 if (m_view->findNodeItem(node))
251 TagFolderItem* item = 0;
252 TreeNode* prev = node->prevSibling();
253 FolderItem* parentItem =
static_cast<FolderItem*
>(m_view->findNodeItem(node->parent()));
258 item =
new TagFolderItem( parentItem, m_view->findNodeItem(prev), node);
261 item =
new TagFolderItem(parentItem, node);
267 item =
new TagFolderItem(m_view, m_view->findNodeItem(prev), node);
270 item =
new TagFolderItem(m_view, node);
273 m_view->d->itemDict.insert(node, item);
274 TQValueList<TreeNode*> children = node->children();
277 for (TQValueList<TreeNode*>::ConstIterator it = children.begin(); it != children.end(); ++it )
280 m_view->connectToNode(node);
284 virtual bool visitFolder(Folder* node)
286 if (m_view->findNodeItem(node))
289 FolderItem* item = 0;
290 TreeNode* prev = node->prevSibling();
291 FolderItem* parentItem =
static_cast<FolderItem*
>(m_view->findNodeItem(node->parent()));
296 item =
new FolderItem( parentItem, m_view->findNodeItem(prev), node);
299 item =
new FolderItem(parentItem, node);
305 item =
new FolderItem(m_view, m_view->findNodeItem(prev), node);
308 item =
new FolderItem(m_view, node);
310 m_view->d->itemDict.insert(node, item);
313 TQValueList<TreeNode*> children = node->children();
314 for (TQValueList<TreeNode*>::ConstIterator it = children.begin(); it != children.end(); ++it )
317 m_view->connectToNode(node);
321 virtual bool visitFeed(Feed* node)
323 if (m_view->findNodeItem(node))
327 TreeNode* prev = node->prevSibling();
328 FolderItem* parentItem =
static_cast<FolderItem*
>(m_view->findNodeItem(node->parent()));
334 item =
new FeedItem( parentItem, m_view->findNodeItem(prev), node);
337 item =
new FeedItem( parentItem, node);
343 item =
new FeedItem(m_view, m_view->findNodeItem(prev), node);
346 item =
new FeedItem(m_view, node);
350 m_view->d->itemDict.insert(node, item);
351 m_view->connectToNode(node);
356 NodeListView* m_view;
359 NodeListView::NodeListView( TQWidget *parent,
const char *name)
360 : TDEListView(parent, name), d(new NodeListViewPrivate)
362 d->showTagFolders =
true;
363 d->connectNodeVisitor =
new ConnectNodeVisitor(
this),
364 d->disconnectNodeVisitor =
new DisconnectNodeVisitor(
this);
365 d->createItemVisitor =
new CreateItemVisitor(
this);
366 d->deleteItemVisitor =
new DeleteItemVisitor(
this);
368 setMinimumSize(150, 150);
369 addColumn(i18n(
"Feeds"));
370 setRootIsDecorated(
false);
371 setItemsRenameable(
false);
376 setDragAutoScroll(
true);
377 setDropVisualizer(
true);
380 setDragEnabled(
true);
381 setAcceptDrops(
true);
382 setItemsMovable(
true);
384 connect(
this, TQ_SIGNAL(dropped(TQDropEvent*, TQListViewItem*)),
this, TQ_SLOT(slotDropped(TQDropEvent*, TQListViewItem*)) );
385 connect(
this, TQ_SIGNAL(selectionChanged(TQListViewItem*)),
this, TQ_SLOT(slotSelectionChanged(TQListViewItem*)) );
386 connect(
this, TQ_SIGNAL(itemRenamed(TQListViewItem*,
int,
const TQString&)),
this, TQ_SLOT(slotItemRenamed(TQListViewItem*,
int,
const TQString&)) );
387 connect(
this, TQ_SIGNAL(contextMenu(TDEListView*, TQListViewItem*,
const TQPoint&)),
this, TQ_SLOT(slotContextMenu(TDEListView*, TQListViewItem*,
const TQPoint&)) );
388 connect( &(d->autoopentimer), TQ_SIGNAL( timeout() ),
this, TQ_SLOT( openFolder() ) );
392 TQWhatsThis::add(
this, i18n(
"<h2>Feeds tree</h2>"
393 "Here you can browse tree of feeds. "
394 "You can also add feeds or feed groups (folders) "
395 "using right-click menu, or reorganize them using "
397 setUpdatesEnabled(
true);
400 NodeListView::~NodeListView()
402 delete d->connectNodeVisitor;
403 delete d->disconnectNodeVisitor;
404 delete d->createItemVisitor;
405 delete d->deleteItemVisitor;
410 void NodeListView::setNodeList(NodeList* nodeList)
412 if (nodeList == d->nodeList)
417 disconnectFromNodeList(d->nodeList);
422 d->nodeList = nodeList;
423 connectToNodeList(nodeList);
426 Folder* rootNode = nodeList->rootNode();
430 slotNodeAdded(rootNode);
431 slotRootNodeChanged(rootNode);
434 Folder* NodeListView::rootNode()
436 return d->nodeList ? d->nodeList->rootNode() : 0;
439 TreeNode* NodeListView::selectedNode()
441 TreeNodeItem* item =
dynamic_cast<TreeNodeItem*
> (selectedItem());
443 return ( item ? item->node() : 0) ;
446 void NodeListView::setSelectedNode(TreeNode* node)
448 TreeNodeItem* item = findNodeItem(node);
450 setSelected(item,
true);
453 TreeNode* NodeListView::findNodeByTitle(
const TQString& title)
455 TreeNodeItem* item =
dynamic_cast<TreeNodeItem*
>(findItemByTitle(title, 0));
462 TreeNodeItem* NodeListView::findNodeItem(TreeNode* node)
464 return d->itemDict.find(node);
467 TreeNodeItem* NodeListView::findItemByTitle(
const TQString& text,
int column, ComparisonFlags compare)
const
469 return dynamic_cast<TreeNodeItem*
> (TDEListView::findItem(text, column, compare));
472 void NodeListView::ensureNodeVisible(TreeNode* node)
474 ensureItemVisible(findNodeItem(node));
477 void NodeListView::startNodeRenaming(TreeNode* node)
479 TreeNodeItem* item = findNodeItem(node);
482 item->startRename(0);
486 void NodeListView::clear()
488 TQPtrDictIterator<TreeNodeItem> it(d->itemDict);
489 for( ; it.current(); ++it )
490 disconnectFromNode( it.current()->node() );
494 TDEListView::clear();
497 void NodeListView::drawContentsOffset( TQPainter * p,
int ox,
int oy,
498 int cx,
int cy,
int cw,
int ch )
500 bool oldUpdatesEnabled = isUpdatesEnabled();
501 setUpdatesEnabled(
false);
502 TDEListView::drawContentsOffset( p, ox, oy, cx, cy, cw, ch );
503 setUpdatesEnabled(oldUpdatesEnabled);
506 void NodeListView::slotDropped( TQDropEvent *e, TQListViewItem*
509 d->autoopentimer.stop();
511 if (e->source() != viewport())
515 if (KURLDrag::canDecode(e))
517 FolderItem* parent =
dynamic_cast<FolderItem*
> (d->parent);
518 TreeNodeItem* afterMe = 0;
521 afterMe =
dynamic_cast<TreeNodeItem*
> (d->afterme);
524 KURLDrag::decode( e, urls );
526 emit signalDropped( urls, afterMe ? afterMe->node() : 0, parent ? parent->node() : 0);
534 void NodeListView::movableDropEvent(TQListViewItem* , TQListViewItem* )
536 d->autoopentimer.stop();
541 Folder* parentNode = (
dynamic_cast<FolderItem*
> (d->parent))->node();
542 TreeNode* afterMeNode = 0;
543 TreeNode* current = selectedNode();
546 afterMeNode = (
dynamic_cast<TreeNodeItem*
> (d->afterme))->node();
548 current->parent()->removeChild(current);
549 parentNode->insertChild(current, afterMeNode);
550 TDEListView::movableDropEvent(d->parent, d->afterme);
554 void NodeListView::setShowTagFolders(
bool enabled)
556 d->showTagFolders = enabled;
559 void NodeListView::contentsDragMoveEvent(TQDragMoveEvent* event)
561 TQPoint vp = contentsToViewport(event->pos());
562 TQListViewItem *i = itemAt(vp);
564 TQListViewItem *qiparent;
565 TQListViewItem *qiafterme;
566 findDrop( event->pos(), qiparent, qiafterme );
568 if (event->source() == viewport()) {
570 if (i && !i->parent())
573 d->autoopentimer.stop();
578 TQListViewItem* root1 = i;
579 while (root1 && root1->parent())
580 root1 = root1->parent();
582 TQListViewItem* root2 = selectedItem();
583 while (root2 && root2->parent())
584 root2 = root2->parent();
589 d->autoopentimer.stop();
594 TQListViewItem* p = qiparent;
596 if (p == selectedItem())
599 d->autoopentimer.stop();
608 if (selectedItem() == i)
611 d->autoopentimer.stop();
623 if (i && (itemAt(vp - TQPoint(0,5)) == i && itemAt(vp + TQPoint(0,5)) == i))
625 setDropVisualizer(
false);
626 setDropHighlighter(
true);
627 cleanDropVisualizer();
629 TreeNode *iNode = (
dynamic_cast<TreeNodeItem*
> (i))->node();
630 if (iNode->isGroup())
633 d->autoopentimer.start(750);
641 d->autoopentimer.stop();
648 setDropVisualizer(
true);
649 setDropHighlighter(
false);
650 cleanItemHighlighter();
651 d->parent = qiparent;
652 d->afterme = qiafterme;
653 d->autoopentimer.stop();
657 TDEListView::contentsDragMoveEvent(event);
660 bool NodeListView::acceptDrag(TQDropEvent *e)
const
662 if (!acceptDrops() || !itemsMovable())
665 if (e->source() != viewport())
667 return KURLDrag::canDecode(e);
672 if (selectedItem() && !selectedItem()->parent())
681 void NodeListView::slotItemUp()
683 if (selectedItem() && selectedItem()->itemAbove())
685 setSelected( selectedItem()->itemAbove(),
true );
686 ensureItemVisible(selectedItem());
690 void NodeListView::slotItemDown()
692 if (selectedItem() && selectedItem()->itemBelow())
694 setSelected( selectedItem()->itemBelow(),
true );
695 ensureItemVisible(selectedItem());
699 void NodeListView::slotItemBegin()
701 setSelected( firstChild(),
true );
702 ensureItemVisible(firstChild());
705 void NodeListView::slotItemEnd()
707 TQListViewItem* elt = firstChild();
709 while (elt->itemBelow())
710 elt = elt->itemBelow();
711 setSelected( elt,
true );
712 ensureItemVisible(elt);
715 void NodeListView::slotItemLeft()
717 TQListViewItem* sel = selectedItem();
719 if (!sel || sel == findNodeItem(rootNode()))
727 setSelected( sel->parent(),
true );
730 ensureItemVisible( selectedItem() );
733 void NodeListView::slotItemRight()
735 TQListViewItem* sel = selectedItem();
738 setSelected( firstChild(),
true );
741 if (sel->isExpandable() && !sel->isOpen())
745 if (sel->firstChild())
746 setSelected( sel->firstChild(),
true );
748 ensureItemVisible( selectedItem() );
751 void NodeListView::slotPrevFeed()
753 for (TQListViewItemIterator it( selectedItem()); it.current(); --it )
755 TreeNodeItem* tni =
dynamic_cast<TreeNodeItem*
>(*it);
756 if (tni && !tni->isSelected() && !tni->node()->isGroup() )
758 setSelected(tni,
true);
759 ensureItemVisible(tni);
765 void NodeListView::slotNextFeed()
767 for (TQListViewItemIterator it( selectedItem()); it.current(); ++it )
769 TreeNodeItem* tni =
dynamic_cast<TreeNodeItem*
>(*it);
770 if ( tni && !tni->isSelected() && !tni->node()->isGroup() )
772 setSelected(tni,
true);
773 ensureItemVisible(tni);
779 void NodeListView::slotPrevUnreadFeed()
781 if (!firstChild() || !firstChild()->firstChild())
783 if ( !selectedItem() )
784 slotNextUnreadFeed();
786 TQListViewItemIterator it( selectedItem() );
788 for ( ; it.current(); --it )
790 TreeNodeItem* tni =
dynamic_cast<TreeNodeItem*
> (it.current());
793 if ( !tni->isSelected() && !tni->node()->isGroup() && tni->node()->unread() > 0)
795 setSelected(tni,
true);
796 ensureItemVisible(tni);
802 if (rootNode()->unread() > 0)
805 it = TQListViewItemIterator(lastItem());
807 for ( ; it.current(); --it)
810 TreeNodeItem* tni =
dynamic_cast<TreeNodeItem*
> (it.current());
815 if (!tni->isSelected() && !tni->node()->isGroup() && tni->node()->unread() > 0)
817 setSelected(tni,
true);
818 ensureItemVisible(tni);
825 void NodeListView::slotNextUnreadFeed()
827 TQListViewItemIterator it;
829 if ( !selectedItem() )
832 if (!firstChild() || !firstChild()->firstChild())
835 it = TQListViewItemIterator( firstChild()->firstChild());
838 it = TQListViewItemIterator( selectedItem() );
840 for ( ; it.current(); ++it )
842 TreeNodeItem* tni =
dynamic_cast<TreeNodeItem*
> (it.current());
845 if ( !tni->isSelected() && !tni->node()->isGroup() && tni->node()->unread() > 0)
847 setSelected(tni,
true);
848 ensureItemVisible(tni);
853 if (rootNode()->unread() > 0)
856 slotNextUnreadFeed();
860 void NodeListView::slotSelectionChanged(TQListViewItem* item)
862 TreeNodeItem* ni =
dynamic_cast<TreeNodeItem*
> (item);
866 emit signalNodeSelected(ni->node());
870 void NodeListView::slotItemRenamed(TQListViewItem* item,
int col,
const TQString& text)
872 TreeNodeItem* ni =
dynamic_cast<TreeNodeItem*
> (item);
873 if ( !ni || !ni->node() )
877 if (text != ni->node()->title())
879 ni->node()->setTitle(text);
883 void NodeListView::slotContextMenu(TDEListView* list, TQListViewItem* item,
const TQPoint& p)
885 TreeNodeItem* ti =
dynamic_cast<TreeNodeItem*
>(item);
886 emit signalContextMenu(list, ti ? ti->node() : 0, p);
888 ti->showContextMenu(p);
891 void NodeListView::slotFeedFetchStarted(Feed* feed)
894 if (!feed->favicon().isNull())
896 TreeNodeItem* item = findNodeItem(feed);
899 TDEIconEffect iconEffect;
900 TQPixmap tempIcon = iconEffect.apply(feed->favicon(), TDEIcon::Small, TDEIcon::DisabledState);
901 item->setPixmap(0, tempIcon);
907 void NodeListView::slotFeedFetchAborted(Feed* feed)
909 TreeNodeItem* item = findNodeItem(feed);
914 void NodeListView::slotFeedFetchError(Feed* feed)
916 TreeNodeItem* item = findNodeItem(feed);
921 void NodeListView::slotFeedFetchCompleted(Feed* feed)
923 TreeNodeItem* item = findNodeItem(feed);
928 void NodeListView::slotNodeAdded(TreeNode* node)
931 d->createItemVisitor->visit(node);
934 void NodeListView::slotNodeRemoved(Folder* , TreeNode* node)
937 d->deleteItemVisitor->deleteItem(node,
false);
940 void NodeListView::connectToNode(TreeNode* node)
943 d->connectNodeVisitor->visit(node);
946 void NodeListView::connectToNodeList(NodeList* list)
951 connect(list, TQ_SIGNAL(signalDestroyed(NodeList*)),
this, TQ_SLOT(slotNodeListDestroyed(NodeList*)) );
952 connect(list->rootNode(), TQ_SIGNAL(signalChanged(TreeNode*)),
this, TQ_SLOT(slotRootNodeChanged(TreeNode*)));
955 void NodeListView::disconnectFromNodeList(NodeList* list)
960 disconnect(list, TQ_SIGNAL(signalDestroyed(NodeList*)),
this, TQ_SLOT(slotNodeListDestroyed(NodeList*)) );
961 disconnect(list->rootNode(), TQ_SIGNAL(signalChanged(TreeNode*)),
this, TQ_SLOT(slotRootNodeChanged(TreeNode*)));
964 void NodeListView::disconnectFromNode(TreeNode* node)
967 d->disconnectNodeVisitor->visit(node);
970 void NodeListView::slotNodeListDestroyed(NodeList* list)
972 if (list != d->nodeList)
978 void NodeListView::slotNodeDestroyed(TreeNode* node)
981 d->deleteItemVisitor->deleteItem(node,
true);
984 void NodeListView::slotRootNodeChanged(TreeNode* rootNode)
986 emit signalRootNodeChanged(
this, rootNode);
989 void NodeListView::slotNodeChanged(TreeNode* node)
991 TreeNodeItem* item = findNodeItem(node);
999 TQDragObject *NodeListView::dragObject()
1001 KMultipleDrag *md =
new KMultipleDrag(viewport());
1002 TQDragObject *obj = TDEListView::dragObject();
1004 md->addDragObject(obj);
1006 TreeNodeItem *i =
dynamic_cast<TreeNodeItem*
>(currentItem());
1008 md->setPixmap(*(i->pixmap(0)));
1009 FeedItem *fi =
dynamic_cast<FeedItem*
>(i);
1011 md->addDragObject(
new KURLDrag(KURL(fi->node()->xmlUrl()), 0L));
1017 void NodeListView::openFolder() {
1018 d->autoopentimer.stop();
1019 if (d->parent && !d->parent->isOpen())
1021 d->parent->setOpen(
true);
1027 #include "feedlistview.moc"