Make a branch to make krunner Good Enough For Aaron™.
[kdebase/uwolfer.git] / apps / konqueror / src / konqbookmarkbar.cpp
blob15f50df68b5b140eac1c9dc127fd10e092c8c8c6
1 // -*- c-basic-offset:4; indent-tabs-mode:nil -*-
2 // vim: set ts=4 sts=4 sw=4 et:
3 /* This file is part of the KDE project
4 Copyright (C) 1999 Kurt Granroth <granroth@kde.org>
5 Copyright (C) 1998, 1999 Torben Weis <weis@kde.org>
7 This library is free software; you can redistribute it and/or
8 modify it under the terms of the GNU Library General Public
9 License as published by the Free Software Foundation; either
10 version 2 of the License, or (at your option) any later version.
12 This library is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 Library General Public License for more details.
17 You should have received a copy of the GNU Library General Public License
18 along with this library; see the file COPYING.LIB. If not, write to
19 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
20 Boston, MA 02110-1301, USA.
23 #include "konqbookmarkbar.h"
25 #include <QApplication>
26 #include <QDebug>
27 #include <QDropEvent>
28 #include <QEvent>
29 #include <QFile>
30 #include <QRegExp>
32 #include <ktoolbar.h>
33 #include <kactionmenu.h>
34 #include <kconfig.h>
35 #include <kglobal.h>
36 #include <kmenu.h>
37 #include <kdebug.h>
38 #include <kconfiggroup.h>
40 #include "konqbookmarkmenu.h"
41 #include "kbookmarkimporter.h"
42 #include "kbookmarkdombuilder.h"
46 class KBookmarkBarPrivate
48 public:
49 QList<KAction *> m_actions;
50 int m_sepIndex;
51 QList<int> widgetPositions; //right edge, bottom edge
52 QString tempLabel;
53 bool m_filteredToolbar;
54 bool m_contextMenu;
56 KBookmarkBarPrivate() :
57 m_sepIndex( -1 )
59 // see KBookmarkSettings::readSettings in kio
60 KConfig config("kbookmarkrc", KConfig::NoGlobals);
61 KConfigGroup cg(&config, "Bookmarks");
62 m_filteredToolbar = cg.readEntry( "FilteredToolbar", false );
63 m_contextMenu = cg.readEntry( "ContextMenuActions", true );
68 KBookmarkBar::KBookmarkBar( KBookmarkManager* mgr,
69 KonqBookmarkOwner *_owner, KToolBar *_toolBar,
70 QObject *parent )
71 : QObject( parent ), m_pOwner(_owner), m_toolBar(_toolBar),
72 m_pManager( mgr ), d( new KBookmarkBarPrivate )
74 m_toolBar->setAcceptDrops( true );
75 m_toolBar->installEventFilter( this ); // for drops
77 if (d->m_contextMenu)
79 m_toolBar->setContextMenuPolicy(Qt::CustomContextMenu);
80 connect(m_toolBar, SIGNAL(customContextMenuRequested(const QPoint &)), this, SLOT(contextMenu(const QPoint &)));
83 connect( mgr, SIGNAL( changed(const QString &, const QString &) ),
84 SLOT( slotBookmarksChanged(const QString &) ) );
85 connect( mgr, SIGNAL( configChanged() ),
86 SLOT( slotConfigChanged() ) );
88 KBookmarkGroup toolbar = getToolbar();
89 fillBookmarkBar( toolbar );
90 m_toolBarSeparator = new QAction(this);
93 QString KBookmarkBar::parentAddress()
95 if(d->m_filteredToolbar)
96 return "";
97 else
98 return m_pManager->toolbar().address();
102 KBookmarkGroup KBookmarkBar::getToolbar()
104 if(d->m_filteredToolbar)
105 return m_pManager->root();
106 else
107 return m_pManager->toolbar();
110 KBookmarkBar::~KBookmarkBar()
112 //clear();
113 qDeleteAll( d->m_actions );
114 qDeleteAll( m_lstSubMenus );
115 delete d;
118 void KBookmarkBar::clear()
120 if (m_toolBar)
121 m_toolBar->clear();
122 qDeleteAll(d->m_actions);
123 d->m_actions.clear();
124 qDeleteAll( m_lstSubMenus );
125 m_lstSubMenus.clear();
128 void KBookmarkBar::slotBookmarksChanged( const QString & group )
130 KBookmarkGroup tb = getToolbar(); // heavy for non cached toolbar version
131 kDebug(7043) << "KBookmarkBar::slotBookmarksChanged( " << group << " )";
133 if ( tb.isNull() )
134 return;
136 if( d->m_filteredToolbar )
138 clear();
139 fillBookmarkBar( tb );
141 else if ( KBookmark::commonParent(group, tb.address()) == group) // Is group a parent of tb.address?
143 clear();
144 fillBookmarkBar( tb );
146 else
148 // Iterate recursively into child menus
149 for ( QList<KBookmarkMenu *>::ConstIterator smit = m_lstSubMenus.begin(), smend = m_lstSubMenus.end();
150 smit != smend; ++smit )
152 (*smit)->slotBookmarksChanged( group );
157 void KBookmarkBar::slotConfigChanged()
159 KConfig config("kbookmarkrc", KConfig::NoGlobals);
160 KConfigGroup cg(&config, "Bookmarks");
161 d->m_filteredToolbar = cg.readEntry( "FilteredToolbar", false );
162 d->m_contextMenu = cg.readEntry( "ContextMenuActions", true );
163 clear();
164 fillBookmarkBar(getToolbar());
167 void KBookmarkBar::fillBookmarkBar(const KBookmarkGroup & parent)
169 if (parent.isNull())
170 return;
172 qDebug()<<"fillBookmarkBar"<<parent.text();
174 for (KBookmark bm = parent.first(); !bm.isNull(); bm = parent.next(bm))
176 qDebug()<<"bm is "<<bm.text();
177 // Filtered special cases
178 if(d->m_filteredToolbar)
180 if(bm.isGroup() && !bm.showInToolbar() )
181 fillBookmarkBar(bm.toGroup());
183 if(!bm.showInToolbar())
184 continue;
188 if (!bm.isGroup())
190 if ( bm.isSeparator() )
191 m_toolBar->addSeparator();
192 else
194 KAction *action = new KBookmarkAction( bm, m_pOwner, 0 );
195 m_toolBar->addAction(action);
196 d->m_actions.append( action );
199 else
201 KBookmarkActionMenu *action = new KBookmarkActionMenu(bm, 0);
202 action->setDelayed( false );
203 m_toolBar->addAction(action);
204 d->m_actions.append( action );
205 KBookmarkMenu *menu = new KonqBookmarkMenu(m_pManager, m_pOwner, action, bm.address());
206 m_lstSubMenus.append( menu );
211 void KBookmarkBar::removeTempSep()
213 if (m_toolBarSeparator)
214 m_toolBar->removeAction(m_toolBarSeparator);
219 * Handle a QDragMoveEvent event on a toolbar drop
220 * @return true if the event should be accepted, false if the event should be ignored
221 * @param pos the current QDragMoveEvent position
222 * @param the toolbar
223 * @param actions the list of actions plugged into the bar
224 * returned action was dropped on
226 bool KBookmarkBar::handleToolbarDragMoveEvent(const QPoint& p, const QList<KAction *>& actions, const QString &text)
228 if(d->m_filteredToolbar)
229 return false;
230 int pos = m_toolBar->orientation() == Qt::Horizontal ? p.x() : p.y();
231 Q_ASSERT( actions.isEmpty() || (m_toolBar == qobject_cast<KToolBar*>(actions.first()->associatedWidgets().value(0))) );
232 m_toolBar->setUpdatesEnabled(false);
233 removeTempSep();
235 bool foundWidget = false;
236 // Right To Left
237 // only relevant if the toolbar is Horizontal!
238 bool rtl = QApplication::isRightToLeft() && m_toolBar->orientation() == Qt::Horizontal;
239 m_toolBarSeparator->setText(text);
241 // Empty toolbar
242 if(actions.isEmpty())
244 d->m_sepIndex = 0;
245 m_toolBar->addAction(m_toolBarSeparator);
246 m_toolBar->setUpdatesEnabled(true);
247 return true;
250 // else find the toolbar button
251 for(int i = 0; i < d->widgetPositions.count(); ++i)
253 if( rtl ^ (pos <= d->widgetPositions[i]) )
255 foundWidget = true;
256 d->m_sepIndex = i;
257 break;
261 QString address;
263 if (foundWidget) // found the containing button
265 int leftOrTop = d->m_sepIndex == 0 ? 0 : d->widgetPositions[d->m_sepIndex-1];
266 int rightOrBottom = d->widgetPositions[d->m_sepIndex];
267 if ( rtl ^ (pos >= (leftOrTop + rightOrBottom)/2) )
269 // if in second half of button then
270 // we jump to next index
271 d->m_sepIndex++;
273 if(d->m_sepIndex != actions.count())
275 QAction *before = m_toolBar->actions()[d->m_sepIndex];
276 m_toolBar->insertAction(before, m_toolBarSeparator);
278 else
280 m_toolBar->addAction(m_toolBarSeparator);
282 m_toolBar->setUpdatesEnabled(true);
283 return true;
285 else // (!foundWidget)
287 // if !b and not past last button, we didn't find button
288 if (rtl ^ (pos <= d->widgetPositions[d->widgetPositions.count()-1]) )
290 m_toolBar->setUpdatesEnabled(true);
291 return false;
293 else // location is beyond last action, assuming we want to add in the end
295 d->m_sepIndex = actions.count();
296 m_toolBar->addAction(m_toolBarSeparator);
297 m_toolBar->setUpdatesEnabled(true);
298 return true;
303 void KBookmarkBar::contextMenu(const QPoint & pos)
305 KBookmarkActionInterface * action = dynamic_cast<KBookmarkActionInterface *>( m_toolBar->actionAt(pos) );
306 if(!action)
307 return;
308 KMenu * menu = new KonqBookmarkContextMenu(action->bookmark(), m_pManager, m_pOwner);
309 menu->setAttribute(Qt::WA_DeleteOnClose);
310 menu->popup(m_toolBar->mapToGlobal(pos));
313 // TODO *** drop improvements ***
314 // open submenus on drop interactions
315 bool KBookmarkBar::eventFilter( QObject *, QEvent *e )
317 if (d->m_filteredToolbar)
318 return false; // todo: make this limit the actions
320 if ( e->type() == QEvent::DragLeave )
322 removeTempSep();
324 else if ( e->type() == QEvent::Drop )
326 removeTempSep();
328 QDropEvent *dev = static_cast<QDropEvent*>( e );
329 QList<KBookmark> list = KBookmark::List::fromMimeData( dev->mimeData() );
330 if ( list.isEmpty() )
331 return false;
332 if (list.count() > 1)
333 kWarning(7043) << "Sorry, currently you can only drop one address "
334 "onto the bookmark bar!" << endl;
335 KBookmark toInsert = list.first();
337 KBookmarkGroup parentBookmark = getToolbar();
339 if(d->m_sepIndex == 0)
341 KBookmark newBookmark = parentBookmark.addBookmark(toInsert.fullText(), toInsert.url() );
343 parentBookmark.moveBookmark( newBookmark, KBookmark() );
344 m_pManager->emitChanged( parentBookmark );
345 return true;
347 else
349 KBookmark after = parentBookmark.first();
351 for(int i=0; i < d->m_sepIndex - 1 ; ++i)
352 after = parentBookmark.next(after);
353 KBookmark newBookmark = parentBookmark.addBookmark(toInsert.fullText(), toInsert.url() );
355 parentBookmark.moveBookmark( newBookmark, after );
356 m_pManager->emitChanged( parentBookmark );
357 return true;
360 else if ( e->type() == QEvent::DragMove || e->type() == QEvent::DragEnter )
362 QDragMoveEvent *dme = static_cast<QDragMoveEvent*>( e );
363 if (!KBookmark::List::canDecode( dme->mimeData() ))
364 return false;
366 //cache text, save positions (inserting the temporary widget changes the positions)
367 if(e->type() == QEvent::DragEnter)
369 QList<KBookmark> list = KBookmark::List::fromMimeData( dme->mimeData() );
370 if ( list.isEmpty() )
371 return false;
372 d->tempLabel = list.first().url().pathOrUrl();
374 d->widgetPositions.clear();
376 for (int i = 0; i < m_toolBar->actions().count(); ++i)
377 if (QWidget* button = m_toolBar->widgetForAction(m_toolBar->actions()[i]))
378 if(m_toolBar->orientation() == Qt::Horizontal)
379 if(QApplication::isLeftToRight())
380 d->widgetPositions.push_back(button->geometry().right());
381 else
382 d->widgetPositions.push_back(button->geometry().left());
383 else
384 d->widgetPositions.push_back(button->geometry().bottom());
387 bool accept = handleToolbarDragMoveEvent(dme->pos(), d->m_actions, d->tempLabel);
388 if (accept)
390 dme->accept();
391 return true; //Really?
394 return false;
397 #include "konqbookmarkbar.moc"