• Skip to content
  • Skip to link menu
KDE 3.5 API Reference
  • KDE API Reference
  • API Reference
  • Sitemap
  • Contact Us
 

kio

kbookmarkbar.cc

Go to the documentation of this file.
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., 51 Franklin Street, Fifth Floor,
00020    Boston, MA 02110-1301, USA.
00021 */
00022 #include <qregexp.h>
00023 #include <qfile.h>
00024 
00025 #include <kbookmarkbar.h>
00026 #include <kbookmarkdrag.h>
00027 
00028 #include <kbookmarkmenu.h>
00029 #include <kdebug.h>
00030 
00031 #include <ktoolbar.h>
00032 #include <ktoolbarbutton.h>
00033 
00034 #include <kconfig.h>
00035 #include <kpopupmenu.h>
00036 
00037 #include "kbookmarkdrag.h"
00038 #include "kbookmarkmenu_p.h"
00039 #include "kbookmarkdombuilder.h"
00040 
00041 #include "dptrtemplate.h"
00042 
00043 #include <qapplication.h>
00044 
00045 class KBookmarkBarPrivate : public dPtrTemplate<KBookmarkBar, KBookmarkBarPrivate>
00046 {
00047 public:
00048     QPtrList<KAction> m_actions;
00049     bool m_readOnly;
00050     KBookmarkManager* m_filteredMgr;
00051     KToolBar* m_sepToolBar;
00052     int m_sepIndex;
00053     bool m_atFirst;
00054     QString m_dropAddress;
00055     QString m_highlightedAddress;
00056 public:
00057     KBookmarkBarPrivate() {
00058         m_readOnly = false;
00059         m_filteredMgr = 0;
00060         m_sepToolBar = 0;
00061         m_sepIndex = -1;
00062         m_atFirst = false;
00063     }
00064 };
00065 template<> QPtrDict<KBookmarkBarPrivate>* dPtrTemplate<KBookmarkBar, KBookmarkBarPrivate>::d_ptr = 0;
00066 
00067 KBookmarkBarPrivate* KBookmarkBar::dptr() const
00068 {
00069     return KBookmarkBarPrivate::d( this );
00070 }
00071 
00072 // usage of KXBELBookmarkImporterImpl is just plain evil, but it reduces code dup. so...
00073 class ToolbarFilter : public KXBELBookmarkImporterImpl
00074 {
00075 public:
00076     ToolbarFilter() : m_visible(false) { ; }
00077     void filter( const KBookmarkGroup &grp ) { traverse(grp); }
00078 private:
00079     virtual void visit( const KBookmark & );
00080     virtual void visitEnter( const KBookmarkGroup & );
00081     virtual void visitLeave( const KBookmarkGroup & );
00082 private:
00083     bool m_visible;
00084     KBookmarkGroup m_visibleStart;
00085 };
00086 
00087 KBookmarkBar::KBookmarkBar( KBookmarkManager* mgr,
00088                             KBookmarkOwner *_owner, KToolBar *_toolBar,
00089                             KActionCollection *coll,
00090                             QObject *parent, const char *name )
00091     : QObject( parent, name ), m_pOwner(_owner), m_toolBar(_toolBar),
00092       m_actionCollection( coll ), m_pManager(mgr)
00093 {
00094     m_lstSubMenus.setAutoDelete( true );
00095 
00096     m_toolBar->setAcceptDrops( true );
00097     m_toolBar->installEventFilter( this ); // for drops
00098 
00099     dptr()->m_actions.setAutoDelete( true );
00100 
00101     connect( mgr, SIGNAL( changed(const QString &, const QString &) ),
00102              SLOT( slotBookmarksChanged(const QString &) ) );
00103 
00104     KBookmarkGroup toolbar = getToolbar();
00105     fillBookmarkBar( toolbar );
00106 }
00107 
00108 QString KBookmarkBar::parentAddress()
00109 {
00110     return dptr()->m_filteredMgr ? QString::null : m_pManager->toolbar().address();
00111 }
00112 
00113 #define CURRENT_TOOLBAR() ( \
00114     dptr()->m_filteredMgr ? dptr()->m_filteredMgr->root()  \
00115                           : m_pManager->toolbar() )
00116 
00117 #define CURRENT_MANAGER() ( \
00118     dptr()->m_filteredMgr ? dptr()->m_filteredMgr  \
00119                           : m_pManager )
00120 
00121 KBookmarkGroup KBookmarkBar::getToolbar()
00122 {
00123     if ( KBookmarkSettings::self()->m_filteredtoolbar )
00124     {
00125         if ( !dptr()->m_filteredMgr ) {
00126             dptr()->m_filteredMgr = KBookmarkManager::createTempManager();
00127         } else {
00128             KBookmarkGroup bkRoot = dptr()->m_filteredMgr->root();
00129             QValueList<KBookmark> bks;
00130             for (KBookmark bm = bkRoot.first(); !bm.isNull(); bm = bkRoot.next(bm))
00131                 bks << bm;
00132             for ( QValueListConstIterator<KBookmark> it = bks.begin(); it != bks.end(); ++it )
00133                 bkRoot.deleteBookmark( (*it) );
00134         }
00135         ToolbarFilter filter;
00136         KBookmarkDomBuilder builder( dptr()->m_filteredMgr->root(),
00137                                      dptr()->m_filteredMgr );
00138         builder.connectImporter( &filter );
00139         filter.filter( m_pManager->root() );
00140     }
00141 
00142     return CURRENT_TOOLBAR();
00143 }
00144 
00145 KBookmarkBar::~KBookmarkBar()
00146 {
00147     //clear();
00148     KBookmarkBarPrivate::delete_d(this);
00149 }
00150 
00151 void KBookmarkBar::clear()
00152 {
00153     QPtrListIterator<KAction> it( dptr()->m_actions );
00154     m_toolBar->clear();
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 ( KBookmark::commonParent(group, tb.address()) == group  // Is group a parent of tb.address?
00171          || KBookmarkSettings::self()->m_filteredtoolbar )
00172     {
00173         clear();
00174         fillBookmarkBar( tb );
00175     }
00176     else
00177     {
00178         // Iterate recursively into child menus
00179         QPtrListIterator<KBookmarkMenu> it( m_lstSubMenus );
00180         for (; it.current(); ++it )
00181         {
00182             it.current()->slotBookmarksChanged( group );
00183         }
00184     }
00185 }
00186 
00187 void KBookmarkBar::fillBookmarkBar(KBookmarkGroup & parent)
00188 {
00189     if (parent.isNull())
00190         return;
00191 
00192     for (KBookmark bm = parent.first(); !bm.isNull(); bm = parent.next(bm))
00193     {
00194         QString text = bm.text();
00195         text.replace( '&', "&&" );
00196         if (!bm.isGroup())
00197         {
00198             if ( bm.isSeparator() )
00199                 m_toolBar->insertLineSeparator();
00200             else
00201             {
00202                 KAction *action = new KBookmarkAction( text, bm.icon(), 0, m_actionCollection, 0 );
00203                 connect(action, SIGNAL( activated ( KAction::ActivationReason, Qt::ButtonState )),
00204                         this, SLOT( slotBookmarkSelected( KAction::ActivationReason, Qt::ButtonState ) ));
00205 
00206                 action->setProperty( "url", bm.url().url() );
00207                 action->setProperty( "address", bm.address() );
00208 
00209                 action->setToolTip( bm.url().pathOrURL() );
00210 
00211                 action->plug(m_toolBar);
00212 
00213                 dptr()->m_actions.append( action );
00214             }
00215         }
00216         else
00217         {
00218             KActionMenu *action = new KBookmarkActionMenu( text, bm.icon(),
00219                                                            m_actionCollection,
00220                                                            "bookmarkbar-actionmenu");
00221             action->setProperty( "address", bm.address() );
00222             action->setProperty( "readOnly", dptr()->m_readOnly );
00223             action->setDelayed( false );
00224 
00225             // this flag doesn't have any UI yet
00226             KGlobal::config()->setGroup( "Settings" );
00227             bool addEntriesBookmarkBar = KGlobal::config()->readBoolEntry("AddEntriesBookmarkBar",true);
00228 
00229             KBookmarkMenu *menu = new KBookmarkMenu(CURRENT_MANAGER(), m_pOwner, action->popupMenu(),
00230                                                     m_actionCollection, false, addEntriesBookmarkBar,
00231                                                     bm.address());
00232             connect(menu, SIGNAL( aboutToShowContextMenu(const KBookmark &, QPopupMenu * ) ),
00233                     this, SIGNAL( aboutToShowContextMenu(const KBookmark &, QPopupMenu * ) ));
00234             connect(menu, SIGNAL( openBookmark( const QString &, Qt::ButtonState) ),
00235                     this, SIGNAL( openBookmark( const QString &, Qt::ButtonState) ));
00236             menu->fillBookmarkMenu();
00237             action->plug(m_toolBar);
00238             m_lstSubMenus.append( menu );
00239 
00240             dptr()->m_actions.append( action );
00241         }
00242     }
00243 }
00244 
00245 void KBookmarkBar::setReadOnly(bool readOnly)
00246 {
00247     dptr()->m_readOnly = readOnly;
00248 }
00249 
00250 bool KBookmarkBar::isReadOnly() const
00251 {
00252     return dptr()->m_readOnly;
00253 }
00254 
00255 void KBookmarkBar::slotBookmarkSelected( KAction::ActivationReason /*reason*/, Qt::ButtonState state )
00256 {
00257     if (!m_pOwner) return; // this view doesn't handle bookmarks...
00258 
00259     const KAction* action = dynamic_cast<const KAction *>(sender());
00260     if(action)
00261     {
00262         const QString & url = sender()->property("url").toString();
00263         m_pOwner->openBookmarkURL(url);
00264         emit openBookmark( url, state );
00265     }
00266 }
00267 
00268 void KBookmarkBar::slotBookmarkSelected()
00269 {
00270     slotBookmarkSelected(KAction::ToolBarActivation, Qt::NoButton);
00271 }
00272 
00273 static const int const_sepId = -9999; // FIXME this is ugly,
00274                                       // surely there is another
00275                                       // way of doing this...
00276 
00277 static void removeTempSep(KBookmarkBarPrivate* p)
00278 {
00279     if (p->m_sepToolBar) {
00280         p->m_sepToolBar->removeItem(const_sepId);
00281         p->m_sepToolBar = 0; // needed?
00282     }
00283 }
00284 
00285 static KAction* findPluggedAction(QPtrList<KAction> actions, KToolBar *tb, int id)
00286 {
00287     QPtrListIterator<KAction> it( actions );
00288     for (; (*it); ++it )
00289         if ((*it)->isPlugged(tb, id))
00290             return (*it);
00291     return 0;
00292 }
00293 
00304 static QString handleToolbarDragMoveEvent(
00305     KBookmarkBarPrivate *p, KToolBar *tb, QPoint pos, QPtrList<KAction> actions,
00306     bool &atFirst, KBookmarkManager *mgr
00307 ) {
00308     Q_UNUSED( mgr );
00309     Q_ASSERT( actions.isEmpty() || (tb == dynamic_cast<KToolBar*>(actions.first()->container(0))) );
00310     p->m_sepToolBar = tb;
00311     p->m_sepToolBar->removeItemDelayed(const_sepId);
00312 
00313     int index = 0;
00314     KToolBarButton* b;
00315 
00316     b = dynamic_cast<KToolBarButton*>(tb->childAt(pos));
00317     KAction *a = 0;
00318     QString address;
00319     atFirst = false;
00320 
00321     if (b)
00322     {
00323         index = tb->itemIndex(b->id());
00324         QRect r = b->geometry();
00325         if (pos.x() < ((r.left() + r.right())/2))
00326         {
00327             // if in first half of button then
00328             // we jump to previous index
00329             if ( index == 0 )
00330                 atFirst = true;
00331             else {
00332                 index--;
00333                 b = tb->getButton(tb->idAt(index));
00334             }
00335         }
00336     }
00337     else if (actions.isEmpty())
00338     {
00339         atFirst = true;
00340         index = 0;
00341         // we skip the action related stuff
00342         // and do what it should have...
00343         // FIXME - here we want to get the
00344         // parent address of the bookmark
00345         // bar itself and return that + "/0"
00346         p->m_sepIndex = 0;
00347         goto skipact;
00348     }
00349     else // (!b)
00350     {
00351         index = actions.count() - 1;
00352         b = tb->getButton(tb->idAt(index));
00353         // if !b and not past last button, we didn't find button
00354         if (pos.x() <= b->geometry().left())
00355             goto skipact; // TODO - rename
00356     }
00357 
00358     if ( !b )
00359         return QString::null; // TODO Make it works for that case
00360 
00361     a = findPluggedAction(actions, tb, b->id());
00362     Q_ASSERT(a);
00363     address = a->property("address").toString();
00364     p->m_sepIndex = index + (atFirst ? 0 : 1);
00365 
00366 #if 0
00367     { // ugly workaround to fix the goto scoping problems...
00368         KBookmark bk = mgr->findByAddress( address );
00369         if (bk.isGroup()) // TODO - fix this ****!!!, manhatten distance should be used!!!
00370         {
00371             kdDebug() << "kbookmarkbar:: popping up " << bk.text() << endl;
00372             KBookmarkActionMenu *menu = dynamic_cast<KBookmarkActionMenu*>(a);
00373             Q_ASSERT(menu);
00374             menu->popup(tb->mapToGlobal(b->geometry().center()));
00375         }
00376     }
00377 #endif
00378 
00379 skipact:
00380     tb->insertLineSeparator(p->m_sepIndex, const_sepId);
00381     return address;
00382 }
00383 
00384 // TODO - document!!!!
00385 static KAction* handleToolbarMouseButton(QPoint pos, QPtrList<KAction> actions,
00386                                          KBookmarkManager * /*mgr*/, QPoint & pt)
00387 {
00388     KAction *act = actions.first();
00389     if (!act) {
00390         return 0;
00391     }
00392 
00393     KToolBar *tb = dynamic_cast<KToolBar*>(act->container(0));
00394     Q_ASSERT(tb);
00395 
00396     KToolBarButton *b;
00397     b = dynamic_cast<KToolBarButton*>(tb->childAt(pos));
00398     if (!b)
00399         return 0;
00400 
00401     KAction *a = 0;
00402     a = findPluggedAction(actions, tb, b->id());
00403     Q_ASSERT(a);
00404     pt = tb->mapToGlobal(pos);
00405 
00406     return a;
00407 }
00408 
00409 // TODO    *** drop improvements ***
00410 // open submenus on drop interactions
00411 
00412 // TODO    *** generic rmb improvements ***
00413 // don't *ever* show the rmb on press, always relase, possible???
00414 
00415 class KBookmarkBarRMBAssoc : public dPtrTemplate<KBookmarkBar, RMB> { };
00416 template<> QPtrDict<RMB>* dPtrTemplate<KBookmarkBar, RMB>::d_ptr = 0;
00417 
00418 static RMB* rmbSelf(KBookmarkBar *m) { return KBookmarkBarRMBAssoc::d(m); }
00419 
00420 void RMB::begin_rmb_action(KBookmarkBar *self)
00421 {
00422     RMB *s = rmbSelf(self);
00423     s->recv = self;
00424     s->m_parentAddress = self->parentAddress();
00425     s->s_highlightedAddress = self->dptr()->m_highlightedAddress; // rename in RMB
00426     s->m_pManager = self->m_pManager;
00427     s->m_pOwner = self->m_pOwner;
00428     s->m_parentMenu = 0;
00429 }
00430 
00431 void KBookmarkBar::slotRMBActionEditAt( int val )
00432 { RMB::begin_rmb_action(this); rmbSelf(this)->slotRMBActionEditAt( val ); }
00433 
00434 void KBookmarkBar::slotRMBActionProperties( int val )
00435 { RMB::begin_rmb_action(this); rmbSelf(this)->slotRMBActionProperties( val ); }
00436 
00437 void KBookmarkBar::slotRMBActionInsert( int val )
00438 { RMB::begin_rmb_action(this); rmbSelf(this)->slotRMBActionInsert( val ); }
00439 
00440 void KBookmarkBar::slotRMBActionRemove( int val )
00441 { RMB::begin_rmb_action(this); rmbSelf(this)->slotRMBActionRemove( val ); }
00442 
00443 void KBookmarkBar::slotRMBActionCopyLocation( int val )
00444 { RMB::begin_rmb_action(this); rmbSelf(this)->slotRMBActionCopyLocation( val ); }
00445 
00446 bool KBookmarkBar::eventFilter( QObject *o, QEvent *e )
00447 {
00448     if (dptr()->m_readOnly || dptr()->m_filteredMgr) // note, we assume m_pManager in various places,
00449                                                      // this shouldn't really be the case
00450         return false; // todo: make this limit the actions
00451 
00452     if ( (e->type() == QEvent::MouseButtonRelease) || (e->type() == QEvent::MouseButtonPress) ) // FIXME, which one?
00453     {
00454         QMouseEvent *mev = (QMouseEvent*)e;
00455 
00456         QPoint pt;
00457         KAction *_a;
00458 
00459         // FIXME, see how this holds up on an empty toolbar
00460         _a = handleToolbarMouseButton( mev->pos(), dptr()->m_actions, m_pManager, pt );
00461         if (_a && mev->button() == Qt::RightButton)
00462         {
00463             dptr()->m_highlightedAddress = _a->property("address").toString();
00464             KBookmark bookmark = m_pManager->findByAddress( dptr()->m_highlightedAddress );
00465             RMB::begin_rmb_action(this);
00466             KPopupMenu *pm = new KPopupMenu;
00467             rmbSelf(this)->fillContextMenu( pm, dptr()->m_highlightedAddress, 0 );
00468             emit aboutToShowContextMenu( rmbSelf(this)->atAddress( dptr()->m_highlightedAddress ), pm );
00469             rmbSelf(this)->fillContextMenu2( pm, dptr()->m_highlightedAddress, 0 );
00470             pm->popup( pt );
00471             mev->accept();
00472         }
00473 
00474         return !!_a; // ignore the event if we didn't find the button
00475     }
00476     else if ( e->type() == QEvent::DragLeave )
00477     {
00478         removeTempSep(dptr());
00479         dptr()->m_dropAddress = QString::null;
00480     }
00481     else if ( e->type() == QEvent::Drop )
00482     {
00483         removeTempSep(dptr());
00484         QDropEvent *dev = (QDropEvent*)e;
00485         if ( !KBookmarkDrag::canDecode( dev ) )
00486             return false;
00487         QValueList<KBookmark> list = KBookmarkDrag::decode( dev );
00488         if (list.count() > 1)
00489             kdWarning(7043) << "Sorry, currently you can only drop one address "
00490                 "onto the bookmark bar!" << endl;
00491         KBookmark toInsert = list.first();
00492         KBookmark bookmark = m_pManager->findByAddress( dptr()->m_dropAddress );
00493         Q_ASSERT(!bookmark.isNull());
00494         kdDebug(7043) << "inserting "
00495             << QString(dptr()->m_atFirst ? "before" : "after")
00496             << " dptr()->m_dropAddress == " << dptr()->m_dropAddress << endl;
00497         KBookmarkGroup parentBookmark = bookmark.parentGroup();
00498         Q_ASSERT(!parentBookmark.isNull());
00499         KBookmark newBookmark = parentBookmark.addBookmark(
00500                 m_pManager, toInsert.fullText(),
00501                 toInsert.url() );
00502         parentBookmark.moveItem( newBookmark, dptr()->m_atFirst ? KBookmark() : bookmark );
00503         m_pManager->emitChanged( parentBookmark );
00504         return true;
00505     }
00506     else if ( e->type() == QEvent::DragMove )
00507     {
00508         QDragMoveEvent *dme = (QDragMoveEvent*)e;
00509         if (!KBookmarkDrag::canDecode( dme ))
00510             return false;
00511         bool _atFirst;
00512         QString dropAddress;
00513         KToolBar *tb = (KToolBar*)o;
00514         dropAddress = handleToolbarDragMoveEvent(dptr(), tb, dme->pos(), dptr()->m_actions, _atFirst, m_pManager);
00515         if (!dropAddress.isNull())
00516         {
00517             dptr()->m_dropAddress = dropAddress;
00518             dptr()->m_atFirst = _atFirst;
00519             dme->accept();
00520         }
00521     }
00522     return false;
00523 }
00524 
00525 static bool showInToolbar( const KBookmark &bk ) {
00526     return (bk.internalElement().attributes().namedItem("showintoolbar").toAttr().value() == "yes");
00527 }
00528 
00529 void ToolbarFilter::visit( const KBookmark &bk ) {
00530     //kdDebug() << "visit(" << bk.text() << ")" << endl;
00531     if ( m_visible || showInToolbar(bk) )
00532         KXBELBookmarkImporterImpl::visit(bk);
00533 }
00534 
00535 void ToolbarFilter::visitEnter( const KBookmarkGroup &grp ) {
00536     //kdDebug() << "visitEnter(" << grp.text() << ")" << endl;
00537     if ( !m_visible && showInToolbar(grp) )
00538     {
00539         m_visibleStart = grp;
00540         m_visible = true;
00541     }
00542     if ( m_visible )
00543         KXBELBookmarkImporterImpl::visitEnter(grp);
00544 }
00545 
00546 void ToolbarFilter::visitLeave( const KBookmarkGroup &grp ) {
00547     //kdDebug() << "visitLeave()" << endl;
00548     if ( m_visible )
00549         KXBELBookmarkImporterImpl::visitLeave(grp);
00550     if ( m_visible && grp.address() == m_visibleStart.address() )
00551         m_visible = false;
00552 }
00553 
00554 #include "kbookmarkbar.moc"

kio

Skip menu "kio"
  • Main Page
  • Modules
  • Namespace List
  • Class Hierarchy
  • Alphabetical List
  • Class List
  • File List
  • Namespace Members
  • Class Members
  • Related Pages

API Reference

Skip menu "API Reference"
  • dcop
  • DNSSD
  • interfaces
  • Kate
  • kconf_update
  • KDECore
  • KDED
  • kdefx
  • KDEsu
  • kdeui
  • KDocTools
  • KHTML
  • KImgIO
  • KInit
  • kio
  • kioslave
  • KJS
  • KNewStuff
  • KParts
  • KUtils
Generated for API Reference by doxygen 1.5.9
This website is maintained by Adriaan de Groot and Allen Winter.
KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal