00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
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
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 );
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
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();
00165 kdDebug(7043) << "slotBookmarksChanged( " << group << " )" << endl;
00166
00167 if ( tb.isNull() )
00168 return;
00169
00170 if ( KBookmark::commonParent(group, tb.address()) == group
00171 || KBookmarkSettings::self()->m_filteredtoolbar )
00172 {
00173 clear();
00174 fillBookmarkBar( tb );
00175 }
00176 else
00177 {
00178
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
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 , Qt::ButtonState state )
00256 {
00257 if (!m_pOwner) return;
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;
00274
00275
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;
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
00328
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
00342
00343
00344
00345
00346 p->m_sepIndex = 0;
00347 goto skipact;
00348 }
00349 else
00350 {
00351 index = actions.count() - 1;
00352 b = tb->getButton(tb->idAt(index));
00353
00354 if (pos.x() <= b->geometry().left())
00355 goto skipact;
00356 }
00357
00358 if ( !b )
00359 return QString::null;
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 {
00368 KBookmark bk = mgr->findByAddress( address );
00369 if (bk.isGroup())
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
00385 static KAction* handleToolbarMouseButton(QPoint pos, QPtrList<KAction> actions,
00386 KBookmarkManager * , 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
00410
00411
00412
00413
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;
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)
00449
00450 return false;
00451
00452 if ( (e->type() == QEvent::MouseButtonRelease) || (e->type() == QEvent::MouseButtonPress) )
00453 {
00454 QMouseEvent *mev = (QMouseEvent*)e;
00455
00456 QPoint pt;
00457 KAction *_a;
00458
00459
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;
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
00531 if ( m_visible || showInToolbar(bk) )
00532 KXBELBookmarkImporterImpl::visit(bk);
00533 }
00534
00535 void ToolbarFilter::visitEnter( const KBookmarkGroup &grp ) {
00536
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
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"