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 <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
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 );
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();
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
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
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
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
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;
00257 m_pOwner->openBookmarkURL( sender()->property("url").toString() );
00258 }
00259
00260 static const int const_sepId = -9999;
00261
00262
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;
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 (pos.x() < ((r.left() + r.right())/2))
00313 {
00314
00315
00316 if ( index == 0 )
00317 atFirst = true;
00318 else {
00319 index--;
00320 b = tb->getButton(tb->idAt(index));
00321 }
00322 }
00323 }
00324 else if (actions.isEmpty())
00325 {
00326 atFirst = true;
00327 index = 0;
00328
00329
00330
00331
00332
00333 p->m_sepIndex = 0;
00334 goto skipact;
00335 }
00336 else
00337 {
00338 index = actions.count() - 1;
00339 b = tb->getButton(tb->idAt(index));
00340
00341 if (pos.x() <= b->geometry().left())
00342 goto skipact;
00343 }
00344
00345 if ( !b )
00346 return QString::null;
00347
00348 a = findPluggedAction(actions, tb, b->id());
00349 Q_ASSERT(a);
00350 address = a->property("address").toString();
00351 p->m_sepIndex = index + (atFirst ? 0 : 1);
00352
00353 #if 0
00354 {
00355 KBookmark bk = mgr->findByAddress( address );
00356 if (bk.isGroup())
00357 {
00358 kdDebug() << "kbookmarkbar:: popping up " << bk.text() << endl;
00359 KBookmarkActionMenu *menu = dynamic_cast<KBookmarkActionMenu*>(a);
00360 Q_ASSERT(menu);
00361 menu->popup(tb->mapToGlobal(b->geometry().center()));
00362 }
00363 }
00364 #endif
00365
00366 skipact:
00367 tb->insertLineSeparator(p->m_sepIndex, const_sepId);
00368 return address;
00369 }
00370
00371
00372 static KAction* handleToolbarMouseButton(QPoint pos, QPtrList<KAction> actions,
00373 KBookmarkManager * , QPoint & pt)
00374 {
00375 KAction *act = actions.first();
00376 if (!act) {
00377 return 0;
00378 }
00379
00380 KToolBar *tb = dynamic_cast<KToolBar*>(act->container(0));
00381 Q_ASSERT(tb);
00382
00383 KToolBarButton *b;
00384 b = dynamic_cast<KToolBarButton*>(tb->childAt(pos));
00385 if (!b)
00386 return 0;
00387
00388 KAction *a = 0;
00389 a = findPluggedAction(actions, tb, b->id());
00390 Q_ASSERT(a);
00391 pt = tb->mapToGlobal(pos);
00392
00393 return a;
00394 }
00395
00396
00397
00398
00399
00400
00401
00402 class KBookmarkBarRMBAssoc : public dPtrTemplate<KBookmarkBar, RMB> { };
00403 template<> QPtrDict<RMB>* dPtrTemplate<KBookmarkBar, RMB>::d_ptr = 0;
00404
00405 static RMB* rmbSelf(KBookmarkBar *m) { return KBookmarkBarRMBAssoc::d(m); }
00406
00407 void RMB::begin_rmb_action(KBookmarkBar *self)
00408 {
00409 RMB *s = rmbSelf(self);
00410 s->recv = self;
00411 s->m_parentAddress = self->parentAddress();
00412 s->s_highlightedAddress = self->dptr()->m_highlightedAddress;
00413 s->m_pManager = self->m_pManager;
00414 s->m_pOwner = self->m_pOwner;
00415 s->m_parentMenu = 0;
00416 }
00417
00418 void KBookmarkBar::slotRMBActionEditAt( int val )
00419 { RMB::begin_rmb_action(this); rmbSelf(this)->slotRMBActionEditAt( val ); }
00420
00421 void KBookmarkBar::slotRMBActionProperties( int val )
00422 { RMB::begin_rmb_action(this); rmbSelf(this)->slotRMBActionProperties( val ); }
00423
00424 void KBookmarkBar::slotRMBActionInsert( int val )
00425 { RMB::begin_rmb_action(this); rmbSelf(this)->slotRMBActionInsert( val ); }
00426
00427 void KBookmarkBar::slotRMBActionRemove( int val )
00428 { RMB::begin_rmb_action(this); rmbSelf(this)->slotRMBActionRemove( val ); }
00429
00430 void KBookmarkBar::slotRMBActionCopyLocation( int val )
00431 { RMB::begin_rmb_action(this); rmbSelf(this)->slotRMBActionCopyLocation( val ); }
00432
00433 bool KBookmarkBar::eventFilter( QObject *o, QEvent *e )
00434 {
00435 if (dptr()->m_readOnly || dptr()->m_filteredMgr)
00436
00437 return false;
00438
00439 if ( (e->type() == QEvent::MouseButtonRelease) || (e->type() == QEvent::MouseButtonPress) )
00440 {
00441 QMouseEvent *mev = (QMouseEvent*)e;
00442
00443 QPoint pt;
00444 KAction *_a;
00445
00446
00447 _a = handleToolbarMouseButton( mev->pos(), dptr()->m_actions, m_pManager, pt );
00448 if (_a && mev->button() == Qt::RightButton)
00449 {
00450 dptr()->m_highlightedAddress = _a->property("address").toString();
00451 KBookmark bookmark = m_pManager->findByAddress( dptr()->m_highlightedAddress );
00452 RMB::begin_rmb_action(this);
00453 KPopupMenu *pm = new KPopupMenu;
00454 rmbSelf(this)->fillContextMenu( pm, dptr()->m_highlightedAddress, 0 );
00455 emit aboutToShowContextMenu( rmbSelf(this)->atAddress( dptr()->m_highlightedAddress ), pm );
00456 rmbSelf(this)->fillContextMenu2( pm, dptr()->m_highlightedAddress, 0 );
00457 pm->popup( pt );
00458 mev->accept();
00459 }
00460
00461 return !!_a;
00462 }
00463 else if ( e->type() == QEvent::DragLeave )
00464 {
00465 removeTempSep(dptr());
00466 dptr()->m_dropAddress = QString::null;
00467 }
00468 else if ( e->type() == QEvent::Drop )
00469 {
00470 removeTempSep(dptr());
00471 QDropEvent *dev = (QDropEvent*)e;
00472 if ( !KBookmarkDrag::canDecode( dev ) )
00473 return false;
00474 QValueList<KBookmark> list = KBookmarkDrag::decode( dev );
00475 if (list.count() > 1)
00476 kdWarning(7043) << "Sorry, currently you can only drop one address "
00477 "onto the bookmark bar!" << endl;
00478 KBookmark toInsert = list.first();
00479 KBookmark bookmark = m_pManager->findByAddress( dptr()->m_dropAddress );
00480 Q_ASSERT(!bookmark.isNull());
00481 kdDebug(7043) << "inserting "
00482 << QString(dptr()->m_atFirst ? "before" : "after")
00483 << " dptr()->m_dropAddress == " << dptr()->m_dropAddress << endl;
00484 KBookmarkGroup parentBookmark = bookmark.parentGroup();
00485 Q_ASSERT(!parentBookmark.isNull());
00486 KBookmark newBookmark = parentBookmark.addBookmark(
00487 m_pManager, toInsert.fullText(),
00488 toInsert.url() );
00489 parentBookmark.moveItem( newBookmark, dptr()->m_atFirst ? KBookmark() : bookmark );
00490 m_pManager->emitChanged( parentBookmark );
00491 return true;
00492 }
00493 else if ( e->type() == QEvent::DragMove )
00494 {
00495 QDragMoveEvent *dme = (QDragMoveEvent*)e;
00496 if (!KBookmarkDrag::canDecode( dme ))
00497 return false;
00498 bool _atFirst;
00499 QString dropAddress;
00500 KToolBar *tb = (KToolBar*)o;
00501 dropAddress = handleToolbarDragMoveEvent(dptr(), tb, dme->pos(), dptr()->m_actions, _atFirst, m_pManager);
00502 if (!dropAddress.isNull())
00503 {
00504 dptr()->m_dropAddress = dropAddress;
00505 dptr()->m_atFirst = _atFirst;
00506 dme->accept();
00507 }
00508 }
00509 return false;
00510 }
00511
00512 static bool showInToolbar( const KBookmark &bk ) {
00513 return (bk.internalElement().attributes().namedItem("showintoolbar").toAttr().value() == "yes");
00514 }
00515
00516 void ToolbarFilter::visit( const KBookmark &bk ) {
00517
00518 if ( m_visible || showInToolbar(bk) )
00519 KXBELBookmarkImporterImpl::visit(bk);
00520 }
00521
00522 void ToolbarFilter::visitEnter( const KBookmarkGroup &grp ) {
00523
00524 if ( !m_visible && showInToolbar(grp) )
00525 {
00526 m_visibleStart = grp;
00527 m_visible = true;
00528 }
00529 if ( m_visible )
00530 KXBELBookmarkImporterImpl::visitEnter(grp);
00531 }
00532
00533 void ToolbarFilter::visitLeave( const KBookmarkGroup &grp ) {
00534
00535 if ( m_visible )
00536 KXBELBookmarkImporterImpl::visitLeave(grp);
00537 if ( m_visible && grp.address() == m_visibleStart.address() )
00538 m_visible = false;
00539 }
00540
00541 #include "kbookmarkbar.moc"