/* This file is part of Akregator. Copyright (C) 2004 Stanislav Karchebny This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. As a special exception, permission is given to link this program with any edition of TQt, and distribute the resulting executable, without including the source code for TQt in the source distribution. */ #include "dragobjects.h" #include "folder.h" #include "folderitem.h" #include "tagfolder.h" #include "tagfolderitem.h" #include "feedlistview.h" #include "feed.h" #include "feeditem.h" #include "feedlist.h" #include "tag.h" #include "tagnode.h" #include "tagnodeitem.h" #include "tagnodelist.h" #include "treenode.h" #include "treenodeitem.h" #include "treenodevisitor.h" #include #include #include #include #include #include #include #include #include #include #include #include #include namespace Akregator { class NodeListView::NodeListViewPrivate { public: /** used for finding the item belonging to a node */ TQPtrDict itemDict; NodeList* nodeList; bool showTagFolders; // Drag and Drop variables TQListViewItem *tqparent; TQListViewItem *afterme; TQTimer autoopentimer; ConnectNodeVisitor* connectNodeVisitor; DisconnectNodeVisitor* disconnectNodeVisitor; CreateItemVisitor* createItemVisitor; DeleteItemVisitor* deleteItemVisitor; }; class NodeListView::ConnectNodeVisitor : public TreeNodeVisitor { public: ConnectNodeVisitor(NodeListView* view) : m_view(view) {} virtual bool visitTreeNode(TreeNode* node) { connect(node, TQT_SIGNAL(signalDestroyed(TreeNode*)), m_view, TQT_SLOT(slotNodeDestroyed(TreeNode*) )); connect(node, TQT_SIGNAL(signalChanged(TreeNode*)), m_view, TQT_SLOT(slotNodeChanged(TreeNode*) )); return true; } virtual bool visitFolder(Folder* node) { visitTreeNode(node); connect(node, TQT_SIGNAL(signalChildAdded(TreeNode*)), m_view, TQT_SLOT(slotNodeAdded(TreeNode*) )); connect(node, TQT_SIGNAL(signalChildRemoved(Folder*, TreeNode*)), m_view, TQT_SLOT(slotNodeRemoved(Folder*, TreeNode*) )); return true; } virtual bool visitFeed(Feed* node) { visitTreeNode(node); connect(node, TQT_SIGNAL(fetchStarted(Feed*)), m_view, TQT_SLOT(slotFeedFetchStarted(Feed*))); connect(node, TQT_SIGNAL(fetchAborted(Feed*)), m_view, TQT_SLOT(slotFeedFetchAborted(Feed*))); connect(node, TQT_SIGNAL(fetchError(Feed*)), m_view, TQT_SLOT(slotFeedFetchError(Feed*))); connect(node, TQT_SIGNAL(fetched(Feed*)), m_view, TQT_SLOT(slotFeedFetchCompleted(Feed*))); return true; } private: NodeListView* m_view; }; class NodeListView::DisconnectNodeVisitor : public TreeNodeVisitor { public: DisconnectNodeVisitor(NodeListView* view) : m_view(view) {} virtual bool visitTagNode(TagNode* node) { disconnect(node, TQT_SIGNAL(signalDestroyed(TreeNode*)), m_view, TQT_SLOT(slotNodeDestroyed(TreeNode*) )); disconnect(node, TQT_SIGNAL(signalChanged(TreeNode*)), m_view, TQT_SLOT(slotNodeChanged(TreeNode*) )); return true; } virtual bool visitFolder(Folder* node) { disconnect(node, TQT_SIGNAL(signalChildAdded(TreeNode*)), m_view, TQT_SLOT(slotNodeAdded(TreeNode*) )); disconnect(node, TQT_SIGNAL(signalChildRemoved(Folder*, TreeNode*)), m_view, TQT_SLOT(slotNodeRemoved(Folder*, TreeNode*) )); disconnect(node, TQT_SIGNAL(signalDestroyed(TreeNode*)), m_view, TQT_SLOT(slotNodeDestroyed(TreeNode*) )); disconnect(node, TQT_SIGNAL(signalChanged(TreeNode*)), m_view, TQT_SLOT(slotNodeChanged(TreeNode*) )); return true; } virtual bool visitFeed(Feed* node) { disconnect(node, TQT_SIGNAL(signalDestroyed(TreeNode*)), m_view, TQT_SLOT(slotNodeDestroyed(TreeNode*) )); disconnect(node, TQT_SIGNAL(signalChanged(TreeNode*)), m_view, TQT_SLOT(slotNodeChanged(TreeNode*) )); disconnect(node, TQT_SIGNAL(fetchStarted(Feed*)), m_view, TQT_SLOT(slotFeedFetchStarted(Feed*))); disconnect(node, TQT_SIGNAL(fetchAborted(Feed*)), m_view, TQT_SLOT(slotFeedFetchAborted(Feed*))); disconnect(node, TQT_SIGNAL(fetchError(Feed*)), m_view, TQT_SLOT(slotFeedFetchError(Feed*))); disconnect(node, TQT_SIGNAL(fetched(Feed*)), m_view, TQT_SLOT(slotFeedFetchCompleted(Feed*))); return true; } private: NodeListView* m_view; }; class NodeListView::DeleteItemVisitor : public TreeNodeVisitor { public: DeleteItemVisitor(NodeListView* view) : m_view(view) {} virtual bool visitTreeNode(TreeNode* node) { TreeNodeItem* item = m_view->d->itemDict.take(node); if (!item) return true; if ( m_selectNeighbour && item->isSelected() ) { if (item->itemBelow()) m_view->setSelected(item->itemBelow(), true); else if (item->itemAbove()) m_view->setSelected(item->itemAbove(), true); else m_view->setSelected(item, false); } m_view->disconnectFromNode(node); delete item; return true; } virtual bool visitFolder(Folder* node) { // delete child items recursively before deleting tqparent TQValueList tqchildren = node->tqchildren(); for (TQValueList::ConstIterator it = tqchildren.begin(); it != tqchildren.end(); ++it ) visit(*it); visitTreeNode(node); return true; } void deleteItem(TreeNode* node, bool selectNeighbour) { m_selectNeighbour = selectNeighbour; visit(node); } private: NodeListView* m_view; bool m_selectNeighbour; }; class NodeListView::CreateItemVisitor : public TreeNodeVisitor { public: CreateItemVisitor(NodeListView* view) : m_view(view) {} virtual bool visitTagNode(TagNode* node) { if (m_view->findNodeItem(node)) return true; TagNodeItem* item = 0; TreeNode* prev = node->prevSibling(); FolderItem* parentItem = static_cast(m_view->findNodeItem(node->tqparent())); if (parentItem) { if (prev) { item = new TagNodeItem( parentItem, m_view->findNodeItem(prev), node); } else item = new TagNodeItem( parentItem, node); } else { if (prev) { item = new TagNodeItem(m_view, m_view->findNodeItem(prev), node); } else item = new TagNodeItem(m_view, node); } item->nodeChanged(); m_view->d->itemDict.insert(node, item); m_view->connectToNode(node); if (parentItem) parentItem->sortChildItems(0, true); return true; } virtual bool visitTagFolder(TagFolder* node) { if (m_view->findNodeItem(node)) return true; TagFolderItem* item = 0; TreeNode* prev = node->prevSibling(); FolderItem* parentItem = static_cast(m_view->findNodeItem(node->tqparent())); if (parentItem) { if (prev) { item = new TagFolderItem( parentItem, m_view->findNodeItem(prev), node); } else item = new TagFolderItem(parentItem, node); } else { if (prev) { item = new TagFolderItem(m_view, m_view->findNodeItem(prev), node); } else item = new TagFolderItem(m_view, node); } m_view->d->itemDict.insert(node, item); TQValueList tqchildren = node->tqchildren(); // add tqchildren recursively for (TQValueList::ConstIterator it = tqchildren.begin(); it != tqchildren.end(); ++it ) visit(*it); m_view->connectToNode(node); return true; } virtual bool visitFolder(Folder* node) { if (m_view->findNodeItem(node)) return true; FolderItem* item = 0; TreeNode* prev = node->prevSibling(); FolderItem* parentItem = static_cast(m_view->findNodeItem(node->tqparent())); if (parentItem) { if (prev) { item = new FolderItem( parentItem, m_view->findNodeItem(prev), node); } else item = new FolderItem(parentItem, node); } else { if (prev) { item = new FolderItem(m_view, m_view->findNodeItem(prev), node); } else item = new FolderItem(m_view, node); } m_view->d->itemDict.insert(node, item); // add tqchildren recursively TQValueList tqchildren = node->tqchildren(); for (TQValueList::ConstIterator it = tqchildren.begin(); it != tqchildren.end(); ++it ) visit(*it); m_view->connectToNode(node); return true; } virtual bool visitFeed(Feed* node) { if (m_view->findNodeItem(node)) return true; FeedItem* item = 0; TreeNode* prev = node->prevSibling(); FolderItem* parentItem = static_cast(m_view->findNodeItem(node->tqparent())); if (parentItem) { if (prev) { item = new FeedItem( parentItem, m_view->findNodeItem(prev), node); } else item = new FeedItem( parentItem, node); } else { if (prev) { item = new FeedItem(m_view, m_view->findNodeItem(prev), node); } else item = new FeedItem(m_view, node); } item->nodeChanged(); m_view->d->itemDict.insert(node, item); m_view->connectToNode(node); return true; } private: NodeListView* m_view; }; NodeListView::NodeListView( TQWidget *tqparent, const char *name) : KListView(tqparent, name), d(new NodeListViewPrivate) { d->showTagFolders = true; d->connectNodeVisitor = new ConnectNodeVisitor(this), d->disconnectNodeVisitor = new DisconnectNodeVisitor(this); d->createItemVisitor = new CreateItemVisitor(this); d->deleteItemVisitor = new DeleteItemVisitor(this); setMinimumSize(150, 150); addColumn(i18n("Feeds")); setRootIsDecorated(false); setItemsRenameable(false); // NOTE: setting this this to true collides with setRenameEnabled() in items and breaks in-place renaming in strange ways. Do not enable! setItemMargin(2); setFullWidth(true); setSorting(-1); setDragAutoScroll(true); setDropVisualizer(true); //setDropHighlighter(false); setDragEnabled(true); setAcceptDrops(true); setItemsMovable(true); connect( this, TQT_SIGNAL(dropped(TQDropEvent*, TQListViewItem*)), this, TQT_SLOT(slotDropped(TQDropEvent*, TQListViewItem*)) ); connect( this, TQT_SIGNAL(selectionChanged(TQListViewItem*)), this, TQT_SLOT(slotSelectionChanged(TQListViewItem*)) ); connect( this, TQT_SIGNAL(itemRenamed(TQListViewItem*, int, const TQString&)), this, TQT_SLOT(slotItemRenamed(TQListViewItem*, int, const TQString&)) ); connect( this, TQT_SIGNAL(contextMenu(KListView*, TQListViewItem*, const TQPoint&)), this, TQT_SLOT(slotContextMenu(KListView*, TQListViewItem*, const TQPoint&)) ); connect( &(d->autoopentimer), TQT_SIGNAL( timeout() ), this, TQT_SLOT( openFolder() ) ); clear(); TQWhatsThis::add(this, i18n("

Feeds tree

" "Here you can browse tree of feeds. " "You can also add feeds or feed groups (folders) " "using right-click menu, or reorganize them using " "drag and drop.")); setUpdatesEnabled(true); } NodeListView::~NodeListView() { delete d->connectNodeVisitor; delete d->disconnectNodeVisitor; delete d->createItemVisitor; delete d->deleteItemVisitor; delete d; d = 0; } void NodeListView::setNodeList(NodeList* nodeList) { if (nodeList == d->nodeList) return; clear(); disconnectFromNodeList(d->nodeList); if (!nodeList) return; d->nodeList = nodeList; connectToNodeList(nodeList); Folder* rootNode = nodeList->rootNode(); if (!rootNode) return; slotNodeAdded(rootNode); slotRootNodeChanged(rootNode); } Folder* NodeListView::rootNode() { return d->nodeList ? d->nodeList->rootNode() : 0; } TreeNode* NodeListView::selectedNode() { TreeNodeItem* item = dynamic_cast (selectedItem()); return ( item ? item->node() : 0) ; } void NodeListView::setSelectedNode(TreeNode* node) { TreeNodeItem* item = findNodeItem(node); if ( node && item ) setSelected(item, true); } TreeNode* NodeListView::findNodeByTitle(const TQString& title) { TreeNodeItem* item = dynamic_cast(findItemByTitle(title, 0)); if (!item) return 0; else return item->node(); } TreeNodeItem* NodeListView::findNodeItem(TreeNode* node) { return d->itemDict.find(node); } TreeNodeItem* NodeListView::findItemByTitle(const TQString& text, int column, ComparisonFlags compare) const { return dynamic_cast (KListView::findItem(text, column, compare)); } void NodeListView::ensureNodeVisible(TreeNode* node) { ensureItemVisible(findNodeItem(node)); } void NodeListView::startNodeRenaming(TreeNode* node) { TreeNodeItem* item = findNodeItem(node); if (item) { item->startRename(0); } } void NodeListView::clear() { TQPtrDictIterator it(d->itemDict); for( ; it.current(); ++it ) disconnectFromNode( it.current()->node() ); d->itemDict.clear(); d->nodeList = 0; KListView::clear(); } void NodeListView::drawContentsOffset( TQPainter * p, int ox, int oy, int cx, int cy, int cw, int ch ) { bool oldUpdatesEnabled = isUpdatesEnabled(); setUpdatesEnabled(false); KListView::drawContentsOffset( p, ox, oy, cx, cy, cw, ch ); setUpdatesEnabled(oldUpdatesEnabled); } void NodeListView::slotDropped( TQDropEvent *e, TQListViewItem* /*after*/) { d->autoopentimer.stop(); if (e->source() != viewport()) { openFolder(); if (KURLDrag::canDecode(e)) { FolderItem* tqparent = dynamic_cast (d->tqparent); TreeNodeItem* afterMe = 0; if(d->afterme) afterMe = dynamic_cast (d->afterme); KURL::List urls; KURLDrag::decode( e, urls ); e->accept(); emit signalDropped( urls, afterMe ? afterMe->node() : 0, tqparent ? tqparent->node() : 0); } } else { } } void NodeListView::movableDropEvent(TQListViewItem* /*tqparent*/, TQListViewItem* /*afterme*/) { d->autoopentimer.stop(); if (d->tqparent) { openFolder(); Folder* parentNode = (dynamic_cast (d->tqparent))->node(); TreeNode* afterMeNode = 0; TreeNode* current = selectedNode(); if (d->afterme) afterMeNode = (dynamic_cast (d->afterme))->node(); current->tqparent()->removeChild(current); parentNode->insertChild(current, afterMeNode); KListView::movableDropEvent(d->tqparent, d->afterme); } } void NodeListView::setShowTagFolders(bool enabled) { d->showTagFolders = enabled; } void NodeListView::contentsDragMoveEvent(TQDragMoveEvent* event) { TQPoint vp = contentsToViewport(event->pos()); TQListViewItem *i = itemAt(vp); TQListViewItem *qitqparent; TQListViewItem *qiafterme; findDrop( event->pos(), qitqparent, qiafterme ); if (event->source() == viewport()) { // disable any drops where the result would be top level nodes if (i && !i->tqparent()) { event->ignore(); d->autoopentimer.stop(); return; } // prevent dragging nodes from All Feeds to My Tags or vice versa TQListViewItem* root1 = i; while (root1 && root1->tqparent()) root1 = root1->tqparent(); TQListViewItem* root2 = selectedItem(); while (root2 && root2->tqparent()) root2 = root2->tqparent(); if (root1 != root2) { event->ignore(); d->autoopentimer.stop(); return; } // don't drop node into own subtree TQListViewItem* p = qitqparent; while (p) if (p == selectedItem()) { event->ignore(); d->autoopentimer.stop(); return; } else { p = p->tqparent(); } // disable drags onto the item itself if (selectedItem() == i) { event->ignore(); d->autoopentimer.stop(); return; } } // what the hell was this good for? -fo // if (!i || event->pos().x() > header()->cellPos(header()->mapToIndex(0)) + // treeStepSize() * (i->depth() + 1) + itemMargin() || // event->pos().x() < header()->cellPos(header()->mapToIndex(0))) // {} else // do we want to move inside the old tqparent or do we want to move to a new tqparent if (i && (itemAt(vp - TQPoint(0,5)) == i && itemAt(vp + TQPoint(0,5)) == i)) { setDropVisualizer(false); setDropHighlighter(true); cleanDropVisualizer(); TreeNode *iNode = (dynamic_cast (i))->node(); if (iNode->isGroup()) { if (i != d->tqparent) d->autoopentimer.start(750); d->tqparent = i; d->afterme = 0; } else { event->ignore(); d->autoopentimer.stop(); d->afterme = i; return; } } else { setDropVisualizer(true); setDropHighlighter(false); cleanItemHighlighter(); d->tqparent = qitqparent; d->afterme = qiafterme; d->autoopentimer.stop(); } // the rest is handled by KListView. KListView::contentsDragMoveEvent(event); } bool NodeListView::acceptDrag(TQDropEvent *e) const { if (!acceptDrops() || !itemsMovable()) return false; if (e->source() != viewport()) { return KURLDrag::canDecode(e); } else { // disable dragging of top-level nodes (All Feeds, My Tags) if (selectedItem() && !selectedItem()->tqparent()) return false; else return true; } return true; } void NodeListView::slotItemUp() { if (selectedItem() && selectedItem()->itemAbove()) { setSelected( selectedItem()->itemAbove(), true ); ensureItemVisible(selectedItem()); } } void NodeListView::slotItemDown() { if (selectedItem() && selectedItem()->itemBelow()) { setSelected( selectedItem()->itemBelow(), true ); ensureItemVisible(selectedItem()); } } void NodeListView::slotItemBegin() { setSelected( firstChild(), true ); ensureItemVisible(firstChild()); } void NodeListView::slotItemEnd() { TQListViewItem* elt = firstChild(); if (elt) while (elt->itemBelow()) elt = elt->itemBelow(); setSelected( elt, true ); ensureItemVisible(elt); } void NodeListView::slotItemLeft() { TQListViewItem* sel = selectedItem(); if (!sel || sel == findNodeItem(rootNode())) return; if (sel->isOpen()) sel->setOpen(false); else { if (sel->tqparent()) setSelected( sel->tqparent(), true ); } ensureItemVisible( selectedItem() ); } void NodeListView::slotItemRight() { TQListViewItem* sel = selectedItem(); if (!sel) { setSelected( firstChild(), true ); sel = firstChild(); } if (sel->isExpandable() && !sel->isOpen()) sel->setOpen(true); else { if (sel->firstChild()) setSelected( sel->firstChild(), true ); } ensureItemVisible( selectedItem() ); } void NodeListView::slotPrevFeed() { for (TQListViewItemIterator it( selectedItem()); it.current(); --it ) { TreeNodeItem* tni = dynamic_cast(*it); if (tni && !tni->isSelected() && !tni->node()->isGroup() ) { setSelected(tni, true); ensureItemVisible(tni); return; } } } void NodeListView::slotNextFeed() { for (TQListViewItemIterator it( selectedItem()); it.current(); ++it ) { TreeNodeItem* tni = dynamic_cast(*it); if ( tni && !tni->isSelected() && !tni->node()->isGroup() ) { setSelected(tni, true); ensureItemVisible(tni); return; } } } void NodeListView::slotPrevUnreadFeed() { if (!firstChild() || !firstChild()->firstChild()) return; if ( !selectedItem() ) slotNextUnreadFeed(); TQListViewItemIterator it( selectedItem() ); for ( ; it.current(); --it ) { TreeNodeItem* tni = dynamic_cast (it.current()); if (!tni) break; if ( !tni->isSelected() && !tni->node()->isGroup() && tni->node()->unread() > 0) { setSelected(tni, true); ensureItemVisible(tni); return; } } // reached when there is no unread feed above the selected one // => cycle: go to end of list... if (rootNode()->unread() > 0) { it = TQListViewItemIterator(lastItem()); for ( ; it.current(); --it) { TreeNodeItem* tni = dynamic_cast (it.current()); if (!tni) break; if (!tni->isSelected() && !tni->node()->isGroup() && tni->node()->unread() > 0) { setSelected(tni, true); ensureItemVisible(tni); return; } } } } void NodeListView::slotNextUnreadFeed() { TQListViewItemIterator it; if ( !selectedItem() ) { // if all feeds doesnt exists or is empty, return if (!firstChild() || !firstChild()->firstChild()) return; else it = TQListViewItemIterator( firstChild()->firstChild()); } else it = TQListViewItemIterator( selectedItem() ); for ( ; it.current(); ++it ) { TreeNodeItem* tni = dynamic_cast (it.current()); if (!tni) break; if ( !tni->isSelected() && !tni->node()->isGroup() && tni->node()->unread() > 0) { setSelected(tni, true); ensureItemVisible(tni); return; } } // if reached, we are at the end of the list++ if (rootNode()->unread() > 0) { clearSelection(); slotNextUnreadFeed(); } } void NodeListView::slotSelectionChanged(TQListViewItem* item) { TreeNodeItem* ni = dynamic_cast (item); if (ni) { emit signalNodeSelected(ni->node()); } } void NodeListView::slotItemRenamed(TQListViewItem* item, int col, const TQString& text) { TreeNodeItem* ni = dynamic_cast (item); if ( !ni || !ni->node() ) return; if (col == 0) { if (text != ni->node()->title()) { ni->node()->setTitle(text); } } } void NodeListView::slotContextMenu(KListView* list, TQListViewItem* item, const TQPoint& p) { TreeNodeItem* ti = dynamic_cast(item); emit signalContextMenu(list, ti ? ti->node() : 0, p); if (ti) ti->showContextMenu(p); } void NodeListView::slotFeedFetchStarted(Feed* feed) { // Disable icon to show it is fetching. if (!feed->favicon().isNull()) { TreeNodeItem* item = findNodeItem(feed); if (item) { KIconEffect iconEffect; TQPixmap tempIcon = iconEffect.apply(feed->favicon(), KIcon::Small, KIcon::DisabledState); item->setPixmap(0, tempIcon); } } } void NodeListView::slotFeedFetchAborted(Feed* feed) { TreeNodeItem* item = findNodeItem(feed); if (item) item->nodeChanged(); } void NodeListView::slotFeedFetchError(Feed* feed) { TreeNodeItem* item = findNodeItem(feed); if (item) item->nodeChanged(); } void NodeListView::slotFeedFetchCompleted(Feed* feed) { TreeNodeItem* item = findNodeItem(feed); if (item) item->nodeChanged(); } void NodeListView::slotNodeAdded(TreeNode* node) { if (node) d->createItemVisitor->visit(node); } void NodeListView::slotNodeRemoved(Folder* /*tqparent*/, TreeNode* node) { if (node) d->deleteItemVisitor->deleteItem(node, false); } void NodeListView::connectToNode(TreeNode* node) { if (node) d->connectNodeVisitor->visit(node); } void NodeListView::connectToNodeList(NodeList* list) { if (!list) return; connect(list, TQT_SIGNAL(signalDestroyed(NodeList*)), this, TQT_SLOT(slotNodeListDestroyed(NodeList*)) ); connect(list->rootNode(), TQT_SIGNAL(signalChanged(TreeNode*)), this, TQT_SLOT(slotRootNodeChanged(TreeNode*))); } void NodeListView::disconnectFromNodeList(NodeList* list) { if (!list) return; disconnect(list, TQT_SIGNAL(signalDestroyed(NodeList*)), this, TQT_SLOT(slotNodeListDestroyed(NodeList*)) ); disconnect(list->rootNode(), TQT_SIGNAL(signalChanged(TreeNode*)), this, TQT_SLOT(slotRootNodeChanged(TreeNode*))); } void NodeListView::disconnectFromNode(TreeNode* node) { if (node) d->disconnectNodeVisitor->visit(node); } void NodeListView::slotNodeListDestroyed(NodeList* list) { if (list != d->nodeList) return; setNodeList(0); } void NodeListView::slotNodeDestroyed(TreeNode* node) { if (node) d->deleteItemVisitor->deleteItem(node, true); } void NodeListView::slotRootNodeChanged(TreeNode* rootNode) { emit signalRootNodeChanged(this, rootNode); } void NodeListView::slotNodeChanged(TreeNode* node) { TreeNodeItem* item = findNodeItem(node); if (item) { item->nodeChanged(); triggerUpdate(); } } TQDragObject *NodeListView::dragObject() { KMultipleDrag *md = new KMultipleDrag(viewport()); TQDragObject *obj = KListView::dragObject(); if (obj) { md->addDragObject(obj); } TreeNodeItem *i = dynamic_cast(currentItem()); if (i) { md->setPixmap(*(i->pixmap(0))); FeedItem *fi = dynamic_cast(i); if (fi) { md->addDragObject(new KURLDrag(KURL(fi->node()->xmlUrl()), 0L)); } } return md; } void NodeListView::openFolder() { d->autoopentimer.stop(); if (d->tqparent && !d->tqparent->isOpen()) { d->tqparent->setOpen(true); } } } // namespace Akregator #include "feedlistview.moc"