You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
tdepim/akregator/src/feedlistview.cpp

1024 lines
29 KiB

/*
This file is part of Akregator.
Copyright (C) 2004 Stanislav Karchebny <Stanislav.Karchebny@kdemail.net>
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 <kdebug.h>
#include <kiconeffect.h>
#include <kiconloader.h>
#include <klocale.h>
#include <kmultipledrag.h>
#include <kstringhandler.h>
#include <kurldrag.h>
#include <tqfont.h>
#include <tqheader.h>
#include <tqpainter.h>
#include <tqptrdict.h>
#include <tqtimer.h>
#include <tqwhatsthis.h>
namespace Akregator {
class NodeListView::NodeListViewPrivate
{
public:
/** used for finding the item belonging to a node */
TQPtrDict<TreeNodeItem> 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<TreeNode*> tqchildren = node->tqchildren();
for (TQValueList<TreeNode*>::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<FolderItem*>(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<FolderItem*>(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<TreeNode*> tqchildren = node->tqchildren();
// add tqchildren recursively
for (TQValueList<TreeNode*>::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<FolderItem*>(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<TreeNode*> tqchildren = node->tqchildren();
for (TQValueList<TreeNode*>::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<FolderItem*>(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("<h2>Feeds tree</h2>"
"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<TreeNodeItem*> (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<TreeNodeItem*>(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<TreeNodeItem*> (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<TreeNodeItem> 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<FolderItem*> (d->tqparent);
TreeNodeItem* afterMe = 0;
if(d->afterme)
afterMe = dynamic_cast<TreeNodeItem*> (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<FolderItem*> (d->tqparent))->node();
TreeNode* afterMeNode = 0;
TreeNode* current = selectedNode();
if (d->afterme)
afterMeNode = (dynamic_cast<TreeNodeItem*> (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<TreeNodeItem*> (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<TreeNodeItem*>(*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<TreeNodeItem*>(*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<TreeNodeItem*> (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<TreeNodeItem*> (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<TreeNodeItem*> (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<TreeNodeItem*> (item);
if (ni)
{
emit signalNodeSelected(ni->node());
}
}
void NodeListView::slotItemRenamed(TQListViewItem* item, int col, const TQString& text)
{
TreeNodeItem* ni = dynamic_cast<TreeNodeItem*> (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<TreeNodeItem*>(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<TreeNodeItem*>(currentItem());
if (i) {
md->setPixmap(*(i->pixmap(0)));
FeedItem *fi = dynamic_cast<FeedItem*>(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"