kio Library API Documentation

kbookmarkbar.cc

00001 // -*- c-basic-offset:4; indent-tabs-mode:nil -*- 00002 // vim: set ts=4 sts=4 sw=4 et: 00003 /* This file is part of the KDE project 00004 Copyright (C) 1999 Kurt Granroth <granroth@kde.org> 00005 Copyright (C) 1998, 1999 Torben Weis <weis@kde.org> 00006 00007 This library is free software; you can redistribute it and/or 00008 modify it under the terms of the GNU Library General Public 00009 License as published by the Free Software Foundation; either 00010 version 2 of the License, or (at your option) any later version. 00011 00012 This library is distributed in the hope that it will be useful, 00013 but WITHOUT ANY WARRANTY; without even the implied warranty of 00014 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00015 Library General Public License for more details. 00016 00017 You should have received a copy of the GNU Library General Public License 00018 along with this library; see the file COPYING.LIB. If not, write to 00019 the Free Software Foundation, Inc., 59 Temple Place - Suite 330, 00020 Boston, MA 02111-1307, USA. 00021 */ 00022 #include <qregexp.h> 00023 #include <qfile.h> 00024 00025 #include <kbookmarkbar.h> 00026 #include <kbookmarkdrag.h> 00027 00028 #include <kaction.h> 00029 #include <kbookmarkmenu.h> 00030 #include <kdebug.h> 00031 00032 #include <ktoolbar.h> 00033 #include <ktoolbarbutton.h> 00034 00035 #include <kconfig.h> 00036 #include <kpopupmenu.h> 00037 00038 #include "kbookmarkdrag.h" 00039 #include "kbookmarkmenu_p.h" 00040 #include "kbookmarkdombuilder.h" 00041 00042 #include "dptrtemplate.h" 00043 00044 #include <qapplication.h> 00045 00046 class KBookmarkBarPrivate : public dPtrTemplate<KBookmarkBar, KBookmarkBarPrivate> 00047 { 00048 public: 00049 QPtrList<KAction> m_actions; 00050 bool m_readOnly; 00051 KBookmarkManager* m_filteredMgr; 00052 KToolBar* m_sepToolBar; 00053 int m_sepIndex; 00054 bool m_atFirst; 00055 QString m_dropAddress; 00056 QString m_highlightedAddress; 00057 public: 00058 KBookmarkBarPrivate() { 00059 m_readOnly = false; 00060 m_filteredMgr = 0; 00061 m_sepToolBar = 0; 00062 m_sepIndex = -1; 00063 m_atFirst = false; 00064 } 00065 }; 00066 template<> QPtrDict<KBookmarkBarPrivate>* dPtrTemplate<KBookmarkBar, KBookmarkBarPrivate>::d_ptr = 0; 00067 00068 KBookmarkBarPrivate* KBookmarkBar::dptr() const 00069 { 00070 return KBookmarkBarPrivate::d( this ); 00071 } 00072 00073 // usage of KXBELBookmarkImporterImpl is just plain evil, but it reduces code dup. so... 00074 class ToolbarFilter : public KXBELBookmarkImporterImpl 00075 { 00076 public: 00077 ToolbarFilter() : m_visible(false) { ; } 00078 void filter( const KBookmarkGroup &grp ) { traverse(grp); } 00079 private: 00080 virtual void visit( const KBookmark & ); 00081 virtual void visitEnter( const KBookmarkGroup & ); 00082 virtual void visitLeave( const KBookmarkGroup & ); 00083 private: 00084 bool m_visible; 00085 KBookmarkGroup m_visibleStart; 00086 }; 00087 00088 KBookmarkBar::KBookmarkBar( KBookmarkManager* mgr, 00089 KBookmarkOwner *_owner, KToolBar *_toolBar, 00090 KActionCollection *coll, 00091 QObject *parent, const char *name ) 00092 : QObject( parent, name ), m_pOwner(_owner), m_toolBar(_toolBar), 00093 m_actionCollection( coll ), m_pManager(mgr) 00094 { 00095 m_lstSubMenus.setAutoDelete( true ); 00096 00097 m_toolBar->setAcceptDrops( true ); 00098 m_toolBar->installEventFilter( this ); // for drops 00099 00100 dptr()->m_actions.setAutoDelete( true ); 00101 00102 connect( mgr, SIGNAL( changed(const QString &, const QString &) ), 00103 SLOT( slotBookmarksChanged(const QString &) ) ); 00104 00105 KBookmarkGroup toolbar = getToolbar(); 00106 fillBookmarkBar( toolbar ); 00107 } 00108 00109 QString KBookmarkBar::parentAddress() 00110 { 00111 return dptr()->m_filteredMgr ? QString::null : m_pManager->toolbar().address(); 00112 } 00113 00114 #define CURRENT_TOOLBAR() ( \ 00115 dptr()->m_filteredMgr ? dptr()->m_filteredMgr->root() \ 00116 : m_pManager->toolbar() ) 00117 00118 #define CURRENT_MANAGER() ( \ 00119 dptr()->m_filteredMgr ? dptr()->m_filteredMgr \ 00120 : m_pManager ) 00121 00122 KBookmarkGroup KBookmarkBar::getToolbar() 00123 { 00124 if ( KBookmarkSettings::self()->m_filteredtoolbar ) 00125 { 00126 if ( !dptr()->m_filteredMgr ) { 00127 dptr()->m_filteredMgr = KBookmarkManager::createTempManager(); 00128 } else { 00129 KBookmarkGroup bkRoot = dptr()->m_filteredMgr->root(); 00130 QValueList<KBookmark> bks; 00131 for (KBookmark bm = bkRoot.first(); !bm.isNull(); bm = bkRoot.next(bm)) 00132 bks << bm; 00133 for ( QValueListConstIterator<KBookmark> it = bks.begin(); it != bks.end(); ++it ) 00134 bkRoot.deleteBookmark( (*it) ); 00135 } 00136 ToolbarFilter filter; 00137 KBookmarkDomBuilder builder( dptr()->m_filteredMgr->root(), 00138 dptr()->m_filteredMgr ); 00139 builder.connectImporter( &filter ); 00140 filter.filter( m_pManager->root() ); 00141 } 00142 00143 return CURRENT_TOOLBAR(); 00144 } 00145 00146 KBookmarkBar::~KBookmarkBar() 00147 { 00148 clear(); 00149 KBookmarkBarPrivate::delete_d(this); 00150 } 00151 00152 void KBookmarkBar::clear() 00153 { 00154 QPtrListIterator<KAction> it( dptr()->m_actions ); 00155 for (; it.current(); ++it ) { 00156 (*it)->unplugAll(); 00157 } 00158 dptr()->m_actions.clear(); 00159 m_lstSubMenus.clear(); 00160 } 00161 00162 void KBookmarkBar::slotBookmarksChanged( const QString & group ) 00163 { 00164 KBookmarkGroup tb = getToolbar(); // heavy for non cached toolbar version 00165 kdDebug(7043) << "slotBookmarksChanged( " << group << " )" << endl; 00166 00167 if ( tb.isNull() ) 00168 return; 00169 00170 if ( tb.address() == group || KBookmarkSettings::self()->m_filteredtoolbar ) 00171 { 00172 clear(); 00173 fillBookmarkBar( tb ); 00174 } 00175 else 00176 { 00177 // Iterate recursively into child menus 00178 QPtrListIterator<KBookmarkMenu> it( m_lstSubMenus ); 00179 for (; it.current(); ++it ) 00180 { 00181 it.current()->slotBookmarksChanged( group ); 00182 } 00183 } 00184 } 00185 00186 void KBookmarkBar::fillBookmarkBar(KBookmarkGroup & parent) 00187 { 00188 if (parent.isNull()) 00189 return; 00190 00191 for (KBookmark bm = parent.first(); !bm.isNull(); bm = parent.next(bm)) 00192 { 00193 QString text = bm.text(); 00194 text.replace( '&', "&&" ); 00195 if (!bm.isGroup()) 00196 { 00197 if ( bm.isSeparator() ) 00198 m_toolBar->insertLineSeparator(); 00199 else 00200 { 00201 // create a normal URL item, with ID as a name 00202 KAction *action = new KBookmarkAction( text, bm.icon(), 0, 00203 this, SLOT(slotBookmarkSelected()), 00204 m_actionCollection, 0 ); 00205 00206 action->setProperty( "url", bm.url().url() ); 00207 action->setProperty( "address", bm.address() ); 00208 00209 // ummm.... this doesn't appear do anything... 00210 action->setToolTip( bm.url().prettyURL() ); 00211 00212 action->plug(m_toolBar); 00213 00214 dptr()->m_actions.append( action ); 00215 } 00216 } 00217 else 00218 { 00219 KActionMenu *action = new KBookmarkActionMenu( text, bm.icon(), 00220 m_actionCollection, 00221 "bookmarkbar-actionmenu"); 00222 action->setProperty( "address", bm.address() ); 00223 action->setProperty( "readOnly", dptr()->m_readOnly ); 00224 action->setDelayed( false ); 00225 00226 // this flag doesn't have any UI yet 00227 KGlobal::config()->setGroup( "Settings" ); 00228 bool addEntriesBookmarkBar = KGlobal::config()->readBoolEntry("AddEntriesBookmarkBar",true); 00229 00230 KBookmarkMenu *menu = new KBookmarkMenu(CURRENT_MANAGER(), m_pOwner, action->popupMenu(), 00231 m_actionCollection, false, addEntriesBookmarkBar, 00232 bm.address()); 00233 connect(menu, SIGNAL( aboutToShowContextMenu(const KBookmark &, QPopupMenu * ) ), 00234 this, SIGNAL( aboutToShowContextMenu(const KBookmark &, QPopupMenu * ) )); 00235 menu->fillBookmarkMenu(); 00236 action->plug(m_toolBar); 00237 m_lstSubMenus.append( menu ); 00238 00239 dptr()->m_actions.append( action ); 00240 } 00241 } 00242 } 00243 00244 void KBookmarkBar::setReadOnly(bool readOnly) 00245 { 00246 dptr()->m_readOnly = readOnly; 00247 } 00248 00249 bool KBookmarkBar::isReadOnly() const 00250 { 00251 return dptr()->m_readOnly; 00252 } 00253 00254 void KBookmarkBar::slotBookmarkSelected() 00255 { 00256 if (!m_pOwner) return; // this view doesn't handle bookmarks... 00257 m_pOwner->openBookmarkURL( sender()->property("url").toString() ); 00258 } 00259 00260 static const int const_sepId = -9999; // FIXME this is ugly, 00261 // surely there is another 00262 // way of doing this... 00263 00264 static void removeTempSep(KBookmarkBarPrivate* p) 00265 { 00266 if (p->m_sepToolBar) { 00267 p->m_sepToolBar->removeItem(const_sepId); 00268 p->m_sepToolBar = 0; // needed? 00269 } 00270 } 00271 00272 static KAction* findPluggedAction(QPtrList<KAction> actions, KToolBar *tb, int id) 00273 { 00274 QPtrListIterator<KAction> it( actions ); 00275 for (; (*it); ++it ) 00276 if ((*it)->isPlugged(tb, id)) 00277 return (*it); 00278 return 0; 00279 } 00280 00291 static QString handleToolbarDragMoveEvent( 00292 KBookmarkBarPrivate *p, KToolBar *tb, QPoint pos, QPtrList<KAction> actions, 00293 bool &atFirst, KBookmarkManager *mgr 00294 ) { 00295 Q_UNUSED( mgr ); 00296 Q_ASSERT( actions.isEmpty() || (tb == dynamic_cast<KToolBar*>(actions.first()->container(0))) ); 00297 p->m_sepToolBar = tb; 00298 p->m_sepToolBar->removeItemDelayed(const_sepId); 00299 00300 int index; 00301 KToolBarButton* b; 00302 00303 b = dynamic_cast<KToolBarButton*>(tb->childAt(pos)); 00304 KAction *a = 0; 00305 QString address; 00306 atFirst = false; 00307 00308 if (b) 00309 { 00310 index = tb->itemIndex(b->id()); 00311 QRect r = b->geometry(); 00312 if (index == 0) 00313 atFirst = true; 00314 else if (pos.x() < ((r.left() + r.right())/2)) 00315 { 00316 // if in first half of button then 00317 // we jump to previous index 00318 index--; 00319 b = tb->getButton(tb->idAt(index)); 00320 } 00321 } 00322 else if (actions.isEmpty()) 00323 { 00324 atFirst = true; 00325 index = 0; 00326 // we skip the action related stuff 00327 // and do what it should have... 00328 // FIXME - here we want to get the 00329 // parent address of the bookmark 00330 // bar itself and return that + "/0" 00331 p->m_sepIndex = 0; 00332 goto skipact; 00333 } 00334 else // (!b) 00335 { 00336 index = actions.count() - 1; 00337 b = tb->getButton(tb->idAt(index)); 00338 // if !b and not past last button, we didn't find button 00339 if (pos.x() <= b->geometry().left()) 00340 goto skipact; // TODO - rename 00341 } 00342 00343 a = findPluggedAction(actions, tb, b->id()); 00344 Q_ASSERT(a); 00345 address = a->property("address").toString(); 00346 p->m_sepIndex = index + (atFirst ? 0 : 1); 00347 00348 #if 0 00349 { // ugly workaround to fix the goto scoping problems... 00350 KBookmark bk = mgr->findByAddress( address ); 00351 if (bk.isGroup()) // TODO - fix this ****!!!, manhatten distance should be used!!! 00352 { 00353 kdDebug() << "kbookmarkbar:: popping up " << bk.text() << endl; 00354 KBookmarkActionMenu *menu = dynamic_cast<KBookmarkActionMenu*>(a); 00355 Q_ASSERT(menu); 00356 menu->popup(tb->mapToGlobal(b->geometry().center())); 00357 } 00358 } 00359 #endif 00360 00361 skipact: 00362 tb->insertLineSeparator(p->m_sepIndex, const_sepId); 00363 return address; 00364 } 00365 00366 // TODO - document!!!! 00367 static KAction* handleToolbarMouseButton(QPoint pos, QPtrList<KAction> actions, 00368 KBookmarkManager * /*mgr*/, QPoint & pt) 00369 { 00370 KAction *act = actions.first(); 00371 if (!act) { 00372 return 0; 00373 } 00374 00375 KToolBar *tb = dynamic_cast<KToolBar*>(act->container(0)); 00376 Q_ASSERT(tb); 00377 00378 KToolBarButton *b; 00379 b = dynamic_cast<KToolBarButton*>(tb->childAt(pos)); 00380 if (!b) 00381 return 0; 00382 00383 KAction *a = 0; 00384 a = findPluggedAction(actions, tb, b->id()); 00385 Q_ASSERT(a); 00386 pt = tb->mapToGlobal(pos); 00387 00388 return a; 00389 } 00390 00391 // TODO *** drop improvements *** 00392 // open submenus on drop interactions 00393 00394 // TODO *** generic rmb improvements *** 00395 // don't *ever* show the rmb on press, always relase, possible??? 00396 00397 class KBookmarkBarRMBAssoc : public dPtrTemplate<KBookmarkBar, RMB> { }; 00398 template<> QPtrDict<RMB>* dPtrTemplate<KBookmarkBar, RMB>::d_ptr = 0; 00399 00400 static RMB* rmbSelf(KBookmarkBar *m) { return KBookmarkBarRMBAssoc::d(m); } 00401 00402 void RMB::begin_rmb_action(KBookmarkBar *self) 00403 { 00404 RMB *s = rmbSelf(self); 00405 s->recv = self; 00406 s->m_parentAddress = self->parentAddress(); 00407 s->s_highlightedAddress = self->dptr()->m_highlightedAddress; // rename in RMB 00408 s->m_pManager = self->m_pManager; 00409 s->m_pOwner = self->m_pOwner; 00410 s->m_parentMenu = 0; 00411 } 00412 00413 void KBookmarkBar::slotRMBActionEditAt( int val ) 00414 { RMB::begin_rmb_action(this); rmbSelf(this)->slotRMBActionEditAt( val ); } 00415 00416 void KBookmarkBar::slotRMBActionProperties( int val ) 00417 { RMB::begin_rmb_action(this); rmbSelf(this)->slotRMBActionProperties( val ); } 00418 00419 void KBookmarkBar::slotRMBActionInsert( int val ) 00420 { RMB::begin_rmb_action(this); rmbSelf(this)->slotRMBActionInsert( val ); } 00421 00422 void KBookmarkBar::slotRMBActionRemove( int val ) 00423 { RMB::begin_rmb_action(this); rmbSelf(this)->slotRMBActionRemove( val ); } 00424 00425 void KBookmarkBar::slotRMBActionCopyLocation( int val ) 00426 { RMB::begin_rmb_action(this); rmbSelf(this)->slotRMBActionCopyLocation( val ); } 00427 00428 bool KBookmarkBar::eventFilter( QObject *o, QEvent *e ) 00429 { 00430 if (dptr()->m_readOnly || dptr()->m_filteredMgr) // note, we assume m_pManager in various places, 00431 // this shouldn't really be the case 00432 return false; // todo: make this limit the actions 00433 00434 if ( (e->type() == QEvent::MouseButtonRelease) || (e->type() == QEvent::MouseButtonPress) ) // FIXME, which one? 00435 { 00436 QMouseEvent *mev = (QMouseEvent*)e; 00437 00438 QPoint pt; 00439 KAction *_a; 00440 00441 // FIXME, see how this holds up on an empty toolbar 00442 _a = handleToolbarMouseButton( mev->pos(), dptr()->m_actions, m_pManager, pt ); 00443 if (_a && mev->button() == Qt::RightButton) 00444 { 00445 dptr()->m_highlightedAddress = _a->property("address").toString(); 00446 KBookmark bookmark = m_pManager->findByAddress( dptr()->m_highlightedAddress ); 00447 RMB::begin_rmb_action(this); 00448 KPopupMenu *pm = new KPopupMenu; 00449 rmbSelf(this)->fillContextMenu( pm, dptr()->m_highlightedAddress, 0 ); 00450 emit aboutToShowContextMenu( rmbSelf(this)->atAddress( dptr()->m_highlightedAddress ), pm ); 00451 rmbSelf(this)->fillContextMenu2( pm, dptr()->m_highlightedAddress, 0 ); 00452 pm->popup( pt ); 00453 mev->accept(); 00454 } 00455 00456 return !!_a; // ignore the event if we didn't find the button 00457 } 00458 else if ( e->type() == QEvent::DragLeave ) 00459 { 00460 removeTempSep(dptr()); 00461 dptr()->m_dropAddress = QString::null; 00462 } 00463 else if ( e->type() == QEvent::Drop ) 00464 { 00465 removeTempSep(dptr()); 00466 QDropEvent *dev = (QDropEvent*)e; 00467 if ( !KBookmarkDrag::canDecode( dev ) ) 00468 return false; 00469 QValueList<KBookmark> list = KBookmarkDrag::decode( dev ); 00470 if (list.count() > 1) 00471 kdWarning(7043) << "Sorry, currently you can only drop one address " 00472 "onto the bookmark bar!" << endl; 00473 KBookmark toInsert = list.first(); 00474 KBookmark bookmark = m_pManager->findByAddress( dptr()->m_dropAddress ); 00475 Q_ASSERT(!bookmark.isNull()); 00476 kdDebug(7043) << "inserting " 00477 << QString(dptr()->m_atFirst ? "before" : "after") 00478 << " dptr()->m_dropAddress == " << dptr()->m_dropAddress << endl; 00479 KBookmarkGroup parentBookmark = bookmark.parentGroup(); 00480 Q_ASSERT(!parentBookmark.isNull()); 00481 KBookmark newBookmark = parentBookmark.addBookmark( 00482 m_pManager, toInsert.fullText(), 00483 toInsert.url() ); 00484 parentBookmark.moveItem( newBookmark, dptr()->m_atFirst ? KBookmark() : bookmark ); 00485 m_pManager->emitChanged( parentBookmark ); 00486 return true; 00487 } 00488 else if ( e->type() == QEvent::DragMove ) 00489 { 00490 QDragMoveEvent *dme = (QDragMoveEvent*)e; 00491 if (!KBookmarkDrag::canDecode( dme )) 00492 return false; 00493 bool _atFirst; 00494 QString dropAddress; 00495 KToolBar *tb = (KToolBar*)o; 00496 dropAddress = handleToolbarDragMoveEvent(dptr(), tb, dme->pos(), dptr()->m_actions, _atFirst, m_pManager); 00497 if (!dropAddress.isNull()) 00498 { 00499 dptr()->m_dropAddress = dropAddress; 00500 dptr()->m_atFirst = _atFirst; 00501 dme->accept(); 00502 } 00503 } 00504 return false; 00505 } 00506 00507 static bool showInToolbar( const KBookmark &bk ) { 00508 return (bk.internalElement().attributes().namedItem("showintoolbar").toAttr().value() == "yes"); 00509 } 00510 00511 void ToolbarFilter::visit( const KBookmark &bk ) { 00512 //kdDebug() << "visit(" << bk.text() << ")" << endl; 00513 if ( m_visible || showInToolbar(bk) ) 00514 KXBELBookmarkImporterImpl::visit(bk); 00515 } 00516 00517 void ToolbarFilter::visitEnter( const KBookmarkGroup &grp ) { 00518 //kdDebug() << "visitEnter(" << grp.text() << ")" << endl; 00519 if ( !m_visible && showInToolbar(grp) ) 00520 { 00521 m_visibleStart = grp; 00522 m_visible = true; 00523 } 00524 if ( m_visible ) 00525 KXBELBookmarkImporterImpl::visitEnter(grp); 00526 } 00527 00528 void ToolbarFilter::visitLeave( const KBookmarkGroup &grp ) { 00529 //kdDebug() << "visitLeave()" << endl; 00530 if ( m_visible ) 00531 KXBELBookmarkImporterImpl::visitLeave(grp); 00532 if ( m_visible && grp.address() == m_visibleStart.address() ) 00533 m_visible = false; 00534 } 00535 00536 #include "kbookmarkbar.moc"
KDE Logo
This file is part of the documentation for kio Library Version 3.2.3.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Sat Jun 12 15:08:43 2004 by doxygen 1.3.7 written by Dimitri van Heesch, © 1997-2003