feedlistview.cpp
00001 /* 00002 This file is part of Akregator. 00003 00004 Copyright (C) 2004 Stanislav Karchebny <Stanislav.Karchebny@kdemail.net> 00005 00006 This program is free software; you can redistribute it and/or modify 00007 it under the terms of the GNU General Public License as published by 00008 the Free Software Foundation; either version 2 of the License, or 00009 (at your option) any later version. 00010 00011 This program is distributed in the hope that it will be useful, 00012 but WITHOUT ANY WARRANTY; without even the implied warranty of 00013 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00014 GNU General Public License for more details. 00015 00016 You should have received a copy of the GNU General Public License 00017 along with this program; if not, write to the Free Software 00018 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 00019 00020 As a special exception, permission is given to link this program 00021 with any edition of TQt, and distribute the resulting executable, 00022 without including the source code for TQt in the source distribution. 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 <tdelocale.h> 00046 #include <tdemultipledrag.h> 00047 #include <kstringhandler.h> 00048 #include <kurldrag.h> 00049 00050 #include <tqfont.h> 00051 #include <tqheader.h> 00052 #include <tqpainter.h> 00053 #include <tqptrdict.h> 00054 #include <tqtimer.h> 00055 #include <tqwhatsthis.h> 00056 00057 namespace Akregator { 00058 00059 class NodeListView::NodeListViewPrivate 00060 { 00061 public: 00063 TQPtrDict<TreeNodeItem> itemDict; 00064 NodeList* nodeList; 00065 bool showTagFolders; 00066 00067 // Drag and Drop variables 00068 TQListViewItem *parent; 00069 TQListViewItem *afterme; 00070 TQTimer autoopentimer; 00071 ConnectNodeVisitor* connectNodeVisitor; 00072 DisconnectNodeVisitor* disconnectNodeVisitor; 00073 CreateItemVisitor* createItemVisitor; 00074 DeleteItemVisitor* deleteItemVisitor; 00075 }; 00076 00077 class NodeListView::ConnectNodeVisitor : public TreeNodeVisitor 00078 { 00079 public: 00080 ConnectNodeVisitor(NodeListView* view) : m_view(view) {} 00081 virtual ~ConnectNodeVisitor() {} 00082 00083 virtual bool visitTreeNode(TreeNode* node) 00084 { 00085 connect(node, TQT_SIGNAL(signalDestroyed(TreeNode*)), m_view, TQT_SLOT(slotNodeDestroyed(TreeNode*) )); 00086 connect(node, TQT_SIGNAL(signalChanged(TreeNode*)), m_view, TQT_SLOT(slotNodeChanged(TreeNode*) )); 00087 return true; 00088 } 00089 00090 virtual bool visitFolder(Folder* node) 00091 { 00092 visitTreeNode(node); 00093 connect(node, TQT_SIGNAL(signalChildAdded(TreeNode*)), m_view, TQT_SLOT(slotNodeAdded(TreeNode*) )); 00094 connect(node, TQT_SIGNAL(signalChildRemoved(Folder*, TreeNode*)), m_view, TQT_SLOT(slotNodeRemoved(Folder*, TreeNode*) )); 00095 return true; 00096 } 00097 00098 virtual bool visitFeed(Feed* node) 00099 { 00100 visitTreeNode(node); 00101 00102 connect(node, TQT_SIGNAL(fetchStarted(Feed*)), m_view, TQT_SLOT(slotFeedFetchStarted(Feed*))); 00103 connect(node, TQT_SIGNAL(fetchAborted(Feed*)), m_view, TQT_SLOT(slotFeedFetchAborted(Feed*))); 00104 connect(node, TQT_SIGNAL(fetchError(Feed*)), m_view, TQT_SLOT(slotFeedFetchError(Feed*))); 00105 connect(node, TQT_SIGNAL(fetched(Feed*)), m_view, TQT_SLOT(slotFeedFetchCompleted(Feed*))); 00106 return true; 00107 } 00108 private: 00109 00110 NodeListView* m_view; 00111 00112 }; 00113 00114 class NodeListView::DisconnectNodeVisitor : public TreeNodeVisitor 00115 { 00116 public: 00117 DisconnectNodeVisitor(NodeListView* view) : m_view(view) {} 00118 virtual ~DisconnectNodeVisitor() {} 00119 00120 virtual bool visitTagNode(TagNode* node) 00121 { 00122 disconnect(node, TQT_SIGNAL(signalDestroyed(TreeNode*)), m_view, TQT_SLOT(slotNodeDestroyed(TreeNode*) )); 00123 disconnect(node, TQT_SIGNAL(signalChanged(TreeNode*)), m_view, TQT_SLOT(slotNodeChanged(TreeNode*) )); 00124 return true; 00125 } 00126 00127 virtual bool visitFolder(Folder* node) 00128 { 00129 disconnect(node, TQT_SIGNAL(signalChildAdded(TreeNode*)), m_view, TQT_SLOT(slotNodeAdded(TreeNode*) )); 00130 disconnect(node, TQT_SIGNAL(signalChildRemoved(Folder*, TreeNode*)), m_view, TQT_SLOT(slotNodeRemoved(Folder*, TreeNode*) )); 00131 00132 disconnect(node, TQT_SIGNAL(signalDestroyed(TreeNode*)), m_view, TQT_SLOT(slotNodeDestroyed(TreeNode*) )); 00133 disconnect(node, TQT_SIGNAL(signalChanged(TreeNode*)), m_view, TQT_SLOT(slotNodeChanged(TreeNode*) )); 00134 return true; 00135 } 00136 00137 virtual bool visitFeed(Feed* node) 00138 { 00139 00140 disconnect(node, TQT_SIGNAL(signalDestroyed(TreeNode*)), m_view, TQT_SLOT(slotNodeDestroyed(TreeNode*) )); 00141 disconnect(node, TQT_SIGNAL(signalChanged(TreeNode*)), m_view, TQT_SLOT(slotNodeChanged(TreeNode*) )); 00142 disconnect(node, TQT_SIGNAL(fetchStarted(Feed*)), m_view, TQT_SLOT(slotFeedFetchStarted(Feed*))); 00143 disconnect(node, TQT_SIGNAL(fetchAborted(Feed*)), m_view, TQT_SLOT(slotFeedFetchAborted(Feed*))); 00144 disconnect(node, TQT_SIGNAL(fetchError(Feed*)), m_view, TQT_SLOT(slotFeedFetchError(Feed*))); 00145 disconnect(node, TQT_SIGNAL(fetched(Feed*)), m_view, TQT_SLOT(slotFeedFetchCompleted(Feed*))); 00146 return true; 00147 } 00148 private: 00149 00150 NodeListView* m_view; 00151 }; 00152 00153 class NodeListView::DeleteItemVisitor : public TreeNodeVisitor 00154 { 00155 public: 00156 00157 DeleteItemVisitor(NodeListView* view) : m_view(view) {} 00158 virtual ~DeleteItemVisitor() {} 00159 00160 virtual bool visitTreeNode(TreeNode* node) 00161 { 00162 TreeNodeItem* item = m_view->d->itemDict.take(node); 00163 00164 if (!item) 00165 return true; 00166 00167 if ( m_selectNeighbour && item->isSelected() ) 00168 { 00169 if (item->itemBelow()) 00170 m_view->setSelected(item->itemBelow(), true); 00171 else if (item->itemAbove()) 00172 m_view->setSelected(item->itemAbove(), true); 00173 else 00174 m_view->setSelected(item, false); 00175 } 00176 00177 m_view->disconnectFromNode(node); 00178 delete item; 00179 return true; 00180 00181 } 00182 00183 virtual bool visitFolder(Folder* node) 00184 { 00185 // delete child items recursively before deleting parent 00186 TQValueList<TreeNode*> children = node->children(); 00187 for (TQValueList<TreeNode*>::ConstIterator it = children.begin(); it != children.end(); ++it ) 00188 visit(*it); 00189 00190 visitTreeNode(node); 00191 00192 return true; 00193 } 00194 00195 void deleteItem(TreeNode* node, bool selectNeighbour) 00196 { 00197 m_selectNeighbour = selectNeighbour; 00198 visit(node); 00199 } 00200 00201 private: 00202 NodeListView* m_view; 00203 bool m_selectNeighbour; 00204 }; 00205 00206 class NodeListView::CreateItemVisitor : public TreeNodeVisitor 00207 { 00208 public: 00209 CreateItemVisitor(NodeListView* view) : m_view(view) {} 00210 virtual ~CreateItemVisitor() {} 00211 00212 virtual bool visitTagNode(TagNode* node) 00213 { 00214 if (m_view->findNodeItem(node)) 00215 return true; 00216 00217 TagNodeItem* item = 0; 00218 TreeNode* prev = node->prevSibling(); 00219 FolderItem* parentItem = static_cast<FolderItem*>(m_view->findNodeItem(node->parent())); 00220 if (parentItem) 00221 { 00222 if (prev) 00223 { 00224 item = new TagNodeItem( parentItem, m_view->findNodeItem(prev), node); 00225 } 00226 else 00227 item = new TagNodeItem( parentItem, node); 00228 } 00229 else 00230 { 00231 if (prev) 00232 { 00233 item = new TagNodeItem(m_view, m_view->findNodeItem(prev), node); 00234 } 00235 else 00236 item = new TagNodeItem(m_view, node); 00237 } 00238 item->nodeChanged(); 00239 m_view->d->itemDict.insert(node, item); 00240 m_view->connectToNode(node); 00241 if (parentItem) 00242 parentItem->sortChildItems(0, true); 00243 return true; 00244 } 00245 00246 virtual bool visitTagFolder(TagFolder* node) 00247 { 00248 if (m_view->findNodeItem(node)) 00249 return true; 00250 00251 TagFolderItem* item = 0; 00252 TreeNode* prev = node->prevSibling(); 00253 FolderItem* parentItem = static_cast<FolderItem*>(m_view->findNodeItem(node->parent())); 00254 if (parentItem) 00255 { 00256 if (prev) 00257 { 00258 item = new TagFolderItem( parentItem, m_view->findNodeItem(prev), node); 00259 } 00260 else 00261 item = new TagFolderItem(parentItem, node); 00262 } 00263 else 00264 { 00265 if (prev) 00266 { 00267 item = new TagFolderItem(m_view, m_view->findNodeItem(prev), node); 00268 } 00269 else 00270 item = new TagFolderItem(m_view, node); 00271 00272 } 00273 m_view->d->itemDict.insert(node, item); 00274 TQValueList<TreeNode*> children = node->children(); 00275 00276 // add children recursively 00277 for (TQValueList<TreeNode*>::ConstIterator it = children.begin(); it != children.end(); ++it ) 00278 visit(*it); 00279 00280 m_view->connectToNode(node); 00281 return true; 00282 } 00283 00284 virtual bool visitFolder(Folder* node) 00285 { 00286 if (m_view->findNodeItem(node)) 00287 return true; 00288 00289 FolderItem* item = 0; 00290 TreeNode* prev = node->prevSibling(); 00291 FolderItem* parentItem = static_cast<FolderItem*>(m_view->findNodeItem(node->parent())); 00292 if (parentItem) 00293 { 00294 if (prev) 00295 { 00296 item = new FolderItem( parentItem, m_view->findNodeItem(prev), node); 00297 } 00298 else 00299 item = new FolderItem(parentItem, node); 00300 } 00301 else 00302 { 00303 if (prev) 00304 { 00305 item = new FolderItem(m_view, m_view->findNodeItem(prev), node); 00306 } 00307 else 00308 item = new FolderItem(m_view, node); 00309 } 00310 m_view->d->itemDict.insert(node, item); 00311 00312 // add children recursively 00313 TQValueList<TreeNode*> children = node->children(); 00314 for (TQValueList<TreeNode*>::ConstIterator it = children.begin(); it != children.end(); ++it ) 00315 visit(*it); 00316 00317 m_view->connectToNode(node); 00318 return true; 00319 } 00320 00321 virtual bool visitFeed(Feed* node) 00322 { 00323 if (m_view->findNodeItem(node)) 00324 return true; 00325 00326 FeedItem* item = 0; 00327 TreeNode* prev = node->prevSibling(); 00328 FolderItem* parentItem = static_cast<FolderItem*>(m_view->findNodeItem(node->parent())); 00329 00330 if (parentItem) 00331 { 00332 if (prev) 00333 { 00334 item = new FeedItem( parentItem, m_view->findNodeItem(prev), node); 00335 } 00336 else 00337 item = new FeedItem( parentItem, node); 00338 } 00339 else 00340 { 00341 if (prev) 00342 { 00343 item = new FeedItem(m_view, m_view->findNodeItem(prev), node); 00344 } 00345 else 00346 item = new FeedItem(m_view, node); 00347 } 00348 00349 item->nodeChanged(); 00350 m_view->d->itemDict.insert(node, item); 00351 m_view->connectToNode(node); 00352 return true; 00353 } 00354 00355 private: 00356 NodeListView* m_view; 00357 }; 00358 00359 NodeListView::NodeListView( TQWidget *parent, const char *name) 00360 : TDEListView(parent, name), d(new NodeListViewPrivate) 00361 { 00362 d->showTagFolders = true; 00363 d->connectNodeVisitor = new ConnectNodeVisitor(this), 00364 d->disconnectNodeVisitor = new DisconnectNodeVisitor(this); 00365 d->createItemVisitor = new CreateItemVisitor(this); 00366 d->deleteItemVisitor = new DeleteItemVisitor(this); 00367 00368 setMinimumSize(150, 150); 00369 addColumn(i18n("Feeds")); 00370 setRootIsDecorated(false); 00371 setItemsRenameable(false); // NOTE: setting this this to true collides with setRenameEnabled() in items and breaks in-place renaming in strange ways. Do not enable! 00372 setItemMargin(2); 00373 00374 setFullWidth(true); 00375 setSorting(-1); 00376 setDragAutoScroll(true); 00377 setDropVisualizer(true); 00378 //setDropHighlighter(false); 00379 00380 setDragEnabled(true); 00381 setAcceptDrops(true); 00382 setItemsMovable(true); 00383 00384 connect( this, TQT_SIGNAL(dropped(TQDropEvent*, TQListViewItem*)), this, TQT_SLOT(slotDropped(TQDropEvent*, TQListViewItem*)) ); 00385 connect( this, TQT_SIGNAL(selectionChanged(TQListViewItem*)), this, TQT_SLOT(slotSelectionChanged(TQListViewItem*)) ); 00386 connect( this, TQT_SIGNAL(itemRenamed(TQListViewItem*, int, const TQString&)), this, TQT_SLOT(slotItemRenamed(TQListViewItem*, int, const TQString&)) ); 00387 connect( this, TQT_SIGNAL(contextMenu(TDEListView*, TQListViewItem*, const TQPoint&)), this, TQT_SLOT(slotContextMenu(TDEListView*, TQListViewItem*, const TQPoint&)) ); 00388 connect( &(d->autoopentimer), TQT_SIGNAL( timeout() ), this, TQT_SLOT( openFolder() ) ); 00389 00390 clear(); 00391 00392 TQWhatsThis::add(this, i18n("<h2>Feeds tree</h2>" 00393 "Here you can browse tree of feeds. " 00394 "You can also add feeds or feed groups (folders) " 00395 "using right-click menu, or reorganize them using " 00396 "drag and drop.")); 00397 setUpdatesEnabled(true); 00398 } 00399 00400 NodeListView::~NodeListView() 00401 { 00402 delete d->connectNodeVisitor; 00403 delete d->disconnectNodeVisitor; 00404 delete d->createItemVisitor; 00405 delete d->deleteItemVisitor; 00406 delete d; 00407 d = 0; 00408 } 00409 00410 void NodeListView::setNodeList(NodeList* nodeList) 00411 { 00412 if (nodeList == d->nodeList) 00413 return; 00414 00415 clear(); 00416 00417 disconnectFromNodeList(d->nodeList); 00418 00419 if (!nodeList) 00420 return; 00421 00422 d->nodeList = nodeList; 00423 connectToNodeList(nodeList); 00424 00425 00426 Folder* rootNode = nodeList->rootNode(); 00427 if (!rootNode) 00428 return; 00429 00430 slotNodeAdded(rootNode); 00431 slotRootNodeChanged(rootNode); 00432 } 00433 00434 Folder* NodeListView::rootNode() 00435 { 00436 return d->nodeList ? d->nodeList->rootNode() : 0; 00437 } 00438 00439 TreeNode* NodeListView::selectedNode() 00440 { 00441 TreeNodeItem* item = dynamic_cast<TreeNodeItem*> (selectedItem()); 00442 00443 return ( item ? item->node() : 0) ; 00444 } 00445 00446 void NodeListView::setSelectedNode(TreeNode* node) 00447 { 00448 TreeNodeItem* item = findNodeItem(node); 00449 if ( node && item ) 00450 setSelected(item, true); 00451 } 00452 00453 TreeNode* NodeListView::findNodeByTitle(const TQString& title) 00454 { 00455 TreeNodeItem* item = dynamic_cast<TreeNodeItem*>(findItemByTitle(title, 0)); 00456 if (!item) 00457 return 0; 00458 else 00459 return item->node(); 00460 } 00461 00462 TreeNodeItem* NodeListView::findNodeItem(TreeNode* node) 00463 { 00464 return d->itemDict.find(node); 00465 } 00466 00467 TreeNodeItem* NodeListView::findItemByTitle(const TQString& text, int column, ComparisonFlags compare) const 00468 { 00469 return dynamic_cast<TreeNodeItem*> (TDEListView::findItem(text, column, compare)); 00470 } 00471 00472 void NodeListView::ensureNodeVisible(TreeNode* node) 00473 { 00474 ensureItemVisible(findNodeItem(node)); 00475 } 00476 00477 void NodeListView::startNodeRenaming(TreeNode* node) 00478 { 00479 TreeNodeItem* item = findNodeItem(node); 00480 if (item) 00481 { 00482 item->startRename(0); 00483 } 00484 } 00485 00486 void NodeListView::clear() 00487 { 00488 TQPtrDictIterator<TreeNodeItem> it(d->itemDict); 00489 for( ; it.current(); ++it ) 00490 disconnectFromNode( it.current()->node() ); 00491 d->itemDict.clear(); 00492 d->nodeList = 0; 00493 00494 TDEListView::clear(); 00495 } 00496 00497 void NodeListView::drawContentsOffset( TQPainter * p, int ox, int oy, 00498 int cx, int cy, int cw, int ch ) 00499 { 00500 bool oldUpdatesEnabled = isUpdatesEnabled(); 00501 setUpdatesEnabled(false); 00502 TDEListView::drawContentsOffset( p, ox, oy, cx, cy, cw, ch ); 00503 setUpdatesEnabled(oldUpdatesEnabled); 00504 } 00505 00506 void NodeListView::slotDropped( TQDropEvent *e, TQListViewItem* 00507 /*after*/) 00508 { 00509 d->autoopentimer.stop(); 00510 00511 if (e->source() != viewport()) 00512 { 00513 openFolder(); 00514 00515 if (KURLDrag::canDecode(e)) 00516 { 00517 FolderItem* parent = dynamic_cast<FolderItem*> (d->parent); 00518 TreeNodeItem* afterMe = 0; 00519 00520 if(d->afterme) 00521 afterMe = dynamic_cast<TreeNodeItem*> (d->afterme); 00522 00523 KURL::List urls; 00524 KURLDrag::decode( e, urls ); 00525 e->accept(); 00526 emit signalDropped( urls, afterMe ? afterMe->node() : 0, parent ? parent->node() : 0); 00527 } 00528 } 00529 else 00530 { 00531 } 00532 } 00533 00534 void NodeListView::movableDropEvent(TQListViewItem* /*parent*/, TQListViewItem* /*afterme*/) 00535 { 00536 d->autoopentimer.stop(); 00537 if (d->parent) 00538 { 00539 openFolder(); 00540 00541 Folder* parentNode = (dynamic_cast<FolderItem*> (d->parent))->node(); 00542 TreeNode* afterMeNode = 0; 00543 TreeNode* current = selectedNode(); 00544 00545 if (d->afterme) 00546 afterMeNode = (dynamic_cast<TreeNodeItem*> (d->afterme))->node(); 00547 00548 current->parent()->removeChild(current); 00549 parentNode->insertChild(current, afterMeNode); 00550 TDEListView::movableDropEvent(d->parent, d->afterme); 00551 } 00552 } 00553 00554 void NodeListView::setShowTagFolders(bool enabled) 00555 { 00556 d->showTagFolders = enabled; 00557 } 00558 00559 void NodeListView::contentsDragMoveEvent(TQDragMoveEvent* event) 00560 { 00561 TQPoint vp = contentsToViewport(event->pos()); 00562 TQListViewItem *i = itemAt(vp); 00563 00564 TQListViewItem *qiparent; 00565 TQListViewItem *qiafterme; 00566 findDrop( event->pos(), qiparent, qiafterme ); 00567 00568 if (event->source() == viewport()) { 00569 // disable any drops where the result would be top level nodes 00570 if (i && !i->parent()) 00571 { 00572 event->ignore(); 00573 d->autoopentimer.stop(); 00574 return; 00575 } 00576 00577 // prevent dragging nodes from All Feeds to My Tags or vice versa 00578 TQListViewItem* root1 = i; 00579 while (root1 && root1->parent()) 00580 root1 = root1->parent(); 00581 00582 TQListViewItem* root2 = selectedItem(); 00583 while (root2 && root2->parent()) 00584 root2 = root2->parent(); 00585 00586 if (root1 != root2) 00587 { 00588 event->ignore(); 00589 d->autoopentimer.stop(); 00590 return; 00591 } 00592 00593 // don't drop node into own subtree 00594 TQListViewItem* p = qiparent; 00595 while (p) 00596 if (p == selectedItem()) 00597 { 00598 event->ignore(); 00599 d->autoopentimer.stop(); 00600 return; 00601 } 00602 else 00603 { 00604 p = p->parent(); 00605 } 00606 00607 // disable drags onto the item itself 00608 if (selectedItem() == i) 00609 { 00610 event->ignore(); 00611 d->autoopentimer.stop(); 00612 return; 00613 } 00614 } 00615 00616 // what the hell was this good for? -fo 00617 // if (!i || event->pos().x() > header()->cellPos(header()->mapToIndex(0)) + 00618 // treeStepSize() * (i->depth() + 1) + itemMargin() || 00619 // event->pos().x() < header()->cellPos(header()->mapToIndex(0))) 00620 // {} else 00621 00622 // do we want to move inside the old parent or do we want to move to a new parent 00623 if (i && (itemAt(vp - TQPoint(0,5)) == i && itemAt(vp + TQPoint(0,5)) == i)) 00624 { 00625 setDropVisualizer(false); 00626 setDropHighlighter(true); 00627 cleanDropVisualizer(); 00628 00629 TreeNode *iNode = (dynamic_cast<TreeNodeItem*> (i))->node(); 00630 if (iNode->isGroup()) 00631 { 00632 if (i != d->parent) 00633 d->autoopentimer.start(750); 00634 00635 d->parent = i; 00636 d->afterme = 0; 00637 } 00638 else 00639 { 00640 event->ignore(); 00641 d->autoopentimer.stop(); 00642 d->afterme = i; 00643 return; 00644 } 00645 } 00646 else 00647 { 00648 setDropVisualizer(true); 00649 setDropHighlighter(false); 00650 cleanItemHighlighter(); 00651 d->parent = qiparent; 00652 d->afterme = qiafterme; 00653 d->autoopentimer.stop(); 00654 } 00655 00656 // the rest is handled by TDEListView. 00657 TDEListView::contentsDragMoveEvent(event); 00658 } 00659 00660 bool NodeListView::acceptDrag(TQDropEvent *e) const 00661 { 00662 if (!acceptDrops() || !itemsMovable()) 00663 return false; 00664 00665 if (e->source() != viewport()) 00666 { 00667 return KURLDrag::canDecode(e); 00668 } 00669 else 00670 { 00671 // disable dragging of top-level nodes (All Feeds, My Tags) 00672 if (selectedItem() && !selectedItem()->parent()) 00673 return false; 00674 else 00675 return true; 00676 } 00677 00678 return true; 00679 } 00680 00681 void NodeListView::slotItemUp() 00682 { 00683 if (selectedItem() && selectedItem()->itemAbove()) 00684 { 00685 setSelected( selectedItem()->itemAbove(), true ); 00686 ensureItemVisible(selectedItem()); 00687 } 00688 } 00689 00690 void NodeListView::slotItemDown() 00691 { 00692 if (selectedItem() && selectedItem()->itemBelow()) 00693 { 00694 setSelected( selectedItem()->itemBelow(), true ); 00695 ensureItemVisible(selectedItem()); 00696 } 00697 } 00698 00699 void NodeListView::slotItemBegin() 00700 { 00701 setSelected( firstChild(), true ); 00702 ensureItemVisible(firstChild()); 00703 } 00704 00705 void NodeListView::slotItemEnd() 00706 { 00707 TQListViewItem* elt = firstChild(); 00708 if (elt) 00709 while (elt->itemBelow()) 00710 elt = elt->itemBelow(); 00711 setSelected( elt, true ); 00712 ensureItemVisible(elt); 00713 } 00714 00715 void NodeListView::slotItemLeft() 00716 { 00717 TQListViewItem* sel = selectedItem(); 00718 00719 if (!sel || sel == findNodeItem(rootNode())) 00720 return; 00721 00722 if (sel->isOpen()) 00723 sel->setOpen(false); 00724 else 00725 { 00726 if (sel->parent()) 00727 setSelected( sel->parent(), true ); 00728 } 00729 00730 ensureItemVisible( selectedItem() ); 00731 } 00732 00733 void NodeListView::slotItemRight() 00734 { 00735 TQListViewItem* sel = selectedItem(); 00736 if (!sel) 00737 { 00738 setSelected( firstChild(), true ); 00739 sel = firstChild(); 00740 } 00741 if (sel->isExpandable() && !sel->isOpen()) 00742 sel->setOpen(true); 00743 else 00744 { 00745 if (sel->firstChild()) 00746 setSelected( sel->firstChild(), true ); 00747 } 00748 ensureItemVisible( selectedItem() ); 00749 } 00750 00751 void NodeListView::slotPrevFeed() 00752 { 00753 for (TQListViewItemIterator it( selectedItem()); it.current(); --it ) 00754 { 00755 TreeNodeItem* tni = dynamic_cast<TreeNodeItem*>(*it); 00756 if (tni && !tni->isSelected() && !tni->node()->isGroup() ) 00757 { 00758 setSelected(tni, true); 00759 ensureItemVisible(tni); 00760 return; 00761 } 00762 } 00763 } 00764 00765 void NodeListView::slotNextFeed() 00766 { 00767 for (TQListViewItemIterator it( selectedItem()); it.current(); ++it ) 00768 { 00769 TreeNodeItem* tni = dynamic_cast<TreeNodeItem*>(*it); 00770 if ( tni && !tni->isSelected() && !tni->node()->isGroup() ) 00771 { 00772 setSelected(tni, true); 00773 ensureItemVisible(tni); 00774 return; 00775 } 00776 } 00777 } 00778 00779 void NodeListView::slotPrevUnreadFeed() 00780 { 00781 if (!firstChild() || !firstChild()->firstChild()) 00782 return; 00783 if ( !selectedItem() ) 00784 slotNextUnreadFeed(); 00785 00786 TQListViewItemIterator it( selectedItem() ); 00787 00788 for ( ; it.current(); --it ) 00789 { 00790 TreeNodeItem* tni = dynamic_cast<TreeNodeItem*> (it.current()); 00791 if (!tni) 00792 break; 00793 if ( !tni->isSelected() && !tni->node()->isGroup() && tni->node()->unread() > 0) 00794 { 00795 setSelected(tni, true); 00796 ensureItemVisible(tni); 00797 return; 00798 } 00799 } 00800 // reached when there is no unread feed above the selected one 00801 // => cycle: go to end of list... 00802 if (rootNode()->unread() > 0) 00803 { 00804 00805 it = TQListViewItemIterator(lastItem()); 00806 00807 for ( ; it.current(); --it) 00808 { 00809 00810 TreeNodeItem* tni = dynamic_cast<TreeNodeItem*> (it.current()); 00811 00812 if (!tni) 00813 break; 00814 00815 if (!tni->isSelected() && !tni->node()->isGroup() && tni->node()->unread() > 0) 00816 { 00817 setSelected(tni, true); 00818 ensureItemVisible(tni); 00819 return; 00820 } 00821 } 00822 } 00823 } 00824 00825 void NodeListView::slotNextUnreadFeed() 00826 { 00827 TQListViewItemIterator it; 00828 00829 if ( !selectedItem() ) 00830 { 00831 // if all feeds doesnt exists or is empty, return 00832 if (!firstChild() || !firstChild()->firstChild()) 00833 return; 00834 else 00835 it = TQListViewItemIterator( firstChild()->firstChild()); 00836 } 00837 else 00838 it = TQListViewItemIterator( selectedItem() ); 00839 00840 for ( ; it.current(); ++it ) 00841 { 00842 TreeNodeItem* tni = dynamic_cast<TreeNodeItem*> (it.current()); 00843 if (!tni) 00844 break; 00845 if ( !tni->isSelected() && !tni->node()->isGroup() && tni->node()->unread() > 0) 00846 { 00847 setSelected(tni, true); 00848 ensureItemVisible(tni); 00849 return; 00850 } 00851 } 00852 // if reached, we are at the end of the list++ 00853 if (rootNode()->unread() > 0) 00854 { 00855 clearSelection(); 00856 slotNextUnreadFeed(); 00857 } 00858 } 00859 00860 void NodeListView::slotSelectionChanged(TQListViewItem* item) 00861 { 00862 TreeNodeItem* ni = dynamic_cast<TreeNodeItem*> (item); 00863 00864 if (ni) 00865 { 00866 emit signalNodeSelected(ni->node()); 00867 } 00868 } 00869 00870 void NodeListView::slotItemRenamed(TQListViewItem* item, int col, const TQString& text) 00871 { 00872 TreeNodeItem* ni = dynamic_cast<TreeNodeItem*> (item); 00873 if ( !ni || !ni->node() ) 00874 return; 00875 if (col == 0) 00876 { 00877 if (text != ni->node()->title()) 00878 { 00879 ni->node()->setTitle(text); 00880 } 00881 } 00882 } 00883 void NodeListView::slotContextMenu(TDEListView* list, TQListViewItem* item, const TQPoint& p) 00884 { 00885 TreeNodeItem* ti = dynamic_cast<TreeNodeItem*>(item); 00886 emit signalContextMenu(list, ti ? ti->node() : 0, p); 00887 if (ti) 00888 ti->showContextMenu(p); 00889 } 00890 00891 void NodeListView::slotFeedFetchStarted(Feed* feed) 00892 { 00893 // Disable icon to show it is fetching. 00894 if (!feed->favicon().isNull()) 00895 { 00896 TreeNodeItem* item = findNodeItem(feed); 00897 if (item) 00898 { 00899 TDEIconEffect iconEffect; 00900 TQPixmap tempIcon = iconEffect.apply(feed->favicon(), TDEIcon::Small, TDEIcon::DisabledState); 00901 item->setPixmap(0, tempIcon); 00902 } 00903 } 00904 00905 } 00906 00907 void NodeListView::slotFeedFetchAborted(Feed* feed) 00908 { 00909 TreeNodeItem* item = findNodeItem(feed); 00910 if (item) 00911 item->nodeChanged(); 00912 } 00913 00914 void NodeListView::slotFeedFetchError(Feed* feed) 00915 { 00916 TreeNodeItem* item = findNodeItem(feed); 00917 if (item) 00918 item->nodeChanged(); 00919 } 00920 00921 void NodeListView::slotFeedFetchCompleted(Feed* feed) 00922 { 00923 TreeNodeItem* item = findNodeItem(feed); 00924 if (item) 00925 item->nodeChanged(); 00926 } 00927 00928 void NodeListView::slotNodeAdded(TreeNode* node) 00929 { 00930 if (node) 00931 d->createItemVisitor->visit(node); 00932 } 00933 00934 void NodeListView::slotNodeRemoved(Folder* /*parent*/, TreeNode* node) 00935 { 00936 if (node) 00937 d->deleteItemVisitor->deleteItem(node, false); 00938 } 00939 00940 void NodeListView::connectToNode(TreeNode* node) 00941 { 00942 if (node) 00943 d->connectNodeVisitor->visit(node); 00944 } 00945 00946 void NodeListView::connectToNodeList(NodeList* list) 00947 { 00948 if (!list) 00949 return; 00950 00951 connect(list, TQT_SIGNAL(signalDestroyed(NodeList*)), this, TQT_SLOT(slotNodeListDestroyed(NodeList*)) ); 00952 connect(list->rootNode(), TQT_SIGNAL(signalChanged(TreeNode*)), this, TQT_SLOT(slotRootNodeChanged(TreeNode*))); 00953 } 00954 00955 void NodeListView::disconnectFromNodeList(NodeList* list) 00956 { 00957 if (!list) 00958 return; 00959 00960 disconnect(list, TQT_SIGNAL(signalDestroyed(NodeList*)), this, TQT_SLOT(slotNodeListDestroyed(NodeList*)) ); 00961 disconnect(list->rootNode(), TQT_SIGNAL(signalChanged(TreeNode*)), this, TQT_SLOT(slotRootNodeChanged(TreeNode*))); 00962 } 00963 00964 void NodeListView::disconnectFromNode(TreeNode* node) 00965 { 00966 if (node) 00967 d->disconnectNodeVisitor->visit(node); 00968 } 00969 00970 void NodeListView::slotNodeListDestroyed(NodeList* list) 00971 { 00972 if (list != d->nodeList) 00973 return; 00974 00975 setNodeList(0); 00976 } 00977 00978 void NodeListView::slotNodeDestroyed(TreeNode* node) 00979 { 00980 if (node) 00981 d->deleteItemVisitor->deleteItem(node, true); 00982 } 00983 00984 void NodeListView::slotRootNodeChanged(TreeNode* rootNode) 00985 { 00986 emit signalRootNodeChanged(this, rootNode); 00987 } 00988 00989 void NodeListView::slotNodeChanged(TreeNode* node) 00990 { 00991 TreeNodeItem* item = findNodeItem(node); 00992 if (item) 00993 { 00994 item->nodeChanged(); 00995 triggerUpdate(); 00996 } 00997 } 00998 00999 TQDragObject *NodeListView::dragObject() 01000 { 01001 KMultipleDrag *md = new KMultipleDrag(viewport()); 01002 TQDragObject *obj = TDEListView::dragObject(); 01003 if (obj) { 01004 md->addDragObject(obj); 01005 } 01006 TreeNodeItem *i = dynamic_cast<TreeNodeItem*>(currentItem()); 01007 if (i) { 01008 md->setPixmap(*(i->pixmap(0))); 01009 FeedItem *fi = dynamic_cast<FeedItem*>(i); 01010 if (fi) { 01011 md->addDragObject(new KURLDrag(KURL(fi->node()->xmlUrl()), 0L)); 01012 } 01013 } 01014 return md; 01015 } 01016 01017 void NodeListView::openFolder() { 01018 d->autoopentimer.stop(); 01019 if (d->parent && !d->parent->isOpen()) 01020 { 01021 d->parent->setOpen(true); 01022 } 01023 } 01024 01025 } // namespace Akregator 01026 01027 #include "feedlistview.moc"