Fix crash if key bindings specified in profile cannot be found. Improve
[personal-kdebase.git] / apps / konqueror / src / konqbookmarkbar.cpp
blobe41b0f5b488185d27df0ce6f0707cced33aa2b89
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.constBegin(), smend = m_lstSubMenus.constEnd();
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 for (KBookmark bm = parent.first(); !bm.isNull(); bm = parent.next(bm))
174 // Filtered special cases
175 if(d->m_filteredToolbar)
177 if(bm.isGroup() && !bm.showInToolbar() )
178 fillBookmarkBar(bm.toGroup());
180 if(!bm.showInToolbar())
181 continue;
185 if (!bm.isGroup())
187 if ( bm.isSeparator() )
188 m_toolBar->addSeparator();
189 else
191 KAction *action = new KBookmarkAction( bm, m_pOwner, 0 );
192 m_toolBar->addAction(action);
193 d->m_actions.append( action );
196 else
198 KBookmarkActionMenu *action = new KBookmarkActionMenu(bm, 0);
199 action->setDelayed( false );
200 m_toolBar->addAction(action);
201 d->m_actions.append( action );
202 KBookmarkMenu *menu = new KonqBookmarkMenu(m_pManager, m_pOwner, action, bm.address());
203 m_lstSubMenus.append( menu );
208 void KBookmarkBar::removeTempSep()
210 if (m_toolBarSeparator)
211 m_toolBar->removeAction(m_toolBarSeparator);
216 * Handle a QDragMoveEvent event on a toolbar drop
217 * @return true if the event should be accepted, false if the event should be ignored
218 * @param pos the current QDragMoveEvent position
219 * @param the toolbar
220 * @param actions the list of actions plugged into the bar
221 * returned action was dropped on
223 bool KBookmarkBar::handleToolbarDragMoveEvent(const QPoint& p, const QList<KAction *>& actions, const QString &text)
225 if(d->m_filteredToolbar)
226 return false;
227 int pos = m_toolBar->orientation() == Qt::Horizontal ? p.x() : p.y();
228 Q_ASSERT( actions.isEmpty() || (m_toolBar == qobject_cast<KToolBar*>(actions.first()->associatedWidgets().value(0))) );
229 m_toolBar->setUpdatesEnabled(false);
230 removeTempSep();
232 bool foundWidget = false;
233 // Right To Left
234 // only relevant if the toolbar is Horizontal!
235 bool rtl = QApplication::isRightToLeft() && m_toolBar->orientation() == Qt::Horizontal;
236 m_toolBarSeparator->setText(text);
238 // Empty toolbar
239 if(actions.isEmpty())
241 d->m_sepIndex = 0;
242 m_toolBar->addAction(m_toolBarSeparator);
243 m_toolBar->setUpdatesEnabled(true);
244 return true;
247 // else find the toolbar button
248 for(int i = 0; i < d->widgetPositions.count(); ++i)
250 if( rtl ^ (pos <= d->widgetPositions[i]) )
252 foundWidget = true;
253 d->m_sepIndex = i;
254 break;
258 QString address;
260 if (foundWidget) // found the containing button
262 int leftOrTop = d->m_sepIndex == 0 ? 0 : d->widgetPositions[d->m_sepIndex-1];
263 int rightOrBottom = d->widgetPositions[d->m_sepIndex];
264 if ( rtl ^ (pos >= (leftOrTop + rightOrBottom)/2) )
266 // if in second half of button then
267 // we jump to next index
268 d->m_sepIndex++;
270 if(d->m_sepIndex != actions.count())
272 QAction *before = m_toolBar->actions()[d->m_sepIndex];
273 m_toolBar->insertAction(before, m_toolBarSeparator);
275 else
277 m_toolBar->addAction(m_toolBarSeparator);
279 m_toolBar->setUpdatesEnabled(true);
280 return true;
282 else // (!foundWidget)
284 // if !b and not past last button, we didn't find button
285 if (rtl ^ (pos <= d->widgetPositions[d->widgetPositions.count()-1]) )
287 m_toolBar->setUpdatesEnabled(true);
288 return false;
290 else // location is beyond last action, assuming we want to add in the end
292 d->m_sepIndex = actions.count();
293 m_toolBar->addAction(m_toolBarSeparator);
294 m_toolBar->setUpdatesEnabled(true);
295 return true;
300 void KBookmarkBar::contextMenu(const QPoint & pos)
302 KBookmarkActionInterface * action = dynamic_cast<KBookmarkActionInterface *>( m_toolBar->actionAt(pos) );
303 if(!action)
304 return;
305 KMenu * menu = new KonqBookmarkContextMenu(action->bookmark(), m_pManager, m_pOwner);
306 menu->setAttribute(Qt::WA_DeleteOnClose);
307 menu->popup(m_toolBar->mapToGlobal(pos));
310 // TODO *** drop improvements ***
311 // open submenus on drop interactions
312 bool KBookmarkBar::eventFilter( QObject *, QEvent *e )
314 if (d->m_filteredToolbar)
315 return false; // todo: make this limit the actions
317 if ( e->type() == QEvent::DragLeave )
319 removeTempSep();
321 else if ( e->type() == QEvent::Drop )
323 removeTempSep();
325 QDropEvent *dev = static_cast<QDropEvent*>( e );
326 QList<KBookmark> list = KBookmark::List::fromMimeData( dev->mimeData() );
327 if ( list.isEmpty() )
328 return false;
329 if (list.count() > 1)
330 kWarning(7043) << "Sorry, currently you can only drop one address "
331 "onto the bookmark bar!";
332 KBookmark toInsert = list.first();
334 KBookmarkGroup parentBookmark = getToolbar();
336 if(d->m_sepIndex == 0)
338 KBookmark newBookmark = parentBookmark.addBookmark(toInsert.fullText(), toInsert.url() );
340 parentBookmark.moveBookmark( newBookmark, KBookmark() );
341 m_pManager->emitChanged( parentBookmark );
342 return true;
344 else
346 KBookmark after = parentBookmark.first();
348 for(int i=0; i < d->m_sepIndex - 1 ; ++i)
349 after = parentBookmark.next(after);
350 KBookmark newBookmark = parentBookmark.addBookmark(toInsert.fullText(), toInsert.url() );
352 parentBookmark.moveBookmark( newBookmark, after );
353 m_pManager->emitChanged( parentBookmark );
354 return true;
357 else if ( e->type() == QEvent::DragMove || e->type() == QEvent::DragEnter )
359 QDragMoveEvent *dme = static_cast<QDragMoveEvent*>( e );
360 if (!KBookmark::List::canDecode( dme->mimeData() ))
361 return false;
363 //cache text, save positions (inserting the temporary widget changes the positions)
364 if(e->type() == QEvent::DragEnter)
366 QList<KBookmark> list = KBookmark::List::fromMimeData( dme->mimeData() );
367 if ( list.isEmpty() )
368 return false;
369 d->tempLabel = list.first().url().pathOrUrl();
371 d->widgetPositions.clear();
373 for (int i = 0; i < m_toolBar->actions().count(); ++i)
374 if (QWidget* button = m_toolBar->widgetForAction(m_toolBar->actions()[i])) {
375 if(m_toolBar->orientation() == Qt::Horizontal) {
376 if(QApplication::isLeftToRight()) {
377 d->widgetPositions.push_back(button->geometry().right());
378 } else {
379 d->widgetPositions.push_back(button->geometry().left());
381 } else {
382 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"