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>
33 #include <kactionmenu.h>
38 #include <kconfiggroup.h>
40 #include "konqbookmarkmenu.h"
41 #include "kbookmarkimporter.h"
42 #include "kbookmarkdombuilder.h"
46 class KBookmarkBarPrivate
49 QList
<KAction
*> m_actions
;
51 QList
<int> widgetPositions
; //right edge, bottom edge
53 bool m_filteredToolbar
;
56 KBookmarkBarPrivate() :
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
,
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
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
)
98 return m_pManager
->toolbar().address();
102 KBookmarkGroup
KBookmarkBar::getToolbar()
104 if(d
->m_filteredToolbar
)
105 return m_pManager
->root();
107 return m_pManager
->toolbar();
110 KBookmarkBar::~KBookmarkBar()
113 qDeleteAll( d
->m_actions
);
114 qDeleteAll( m_lstSubMenus
);
118 void KBookmarkBar::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
<< " )";
136 if( d
->m_filteredToolbar
)
139 fillBookmarkBar( tb
);
141 else if ( KBookmark::commonParent(group
, tb
.address()) == group
) // Is group a parent of tb.address?
144 fillBookmarkBar( tb
);
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 );
164 fillBookmarkBar(getToolbar());
167 void KBookmarkBar::fillBookmarkBar(const KBookmarkGroup
& parent
)
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())
190 if ( bm
.isSeparator() )
191 m_toolBar
->addSeparator();
194 KAction
*action
= new KBookmarkAction( bm
, m_pOwner
, 0 );
195 m_toolBar
->addAction(action
);
196 d
->m_actions
.append( action
);
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
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
)
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);
235 bool foundWidget
= false;
237 // only relevant if the toolbar is Horizontal!
238 bool rtl
= QApplication::isRightToLeft() && m_toolBar
->orientation() == Qt::Horizontal
;
239 m_toolBarSeparator
->setText(text
);
242 if(actions
.isEmpty())
245 m_toolBar
->addAction(m_toolBarSeparator
);
246 m_toolBar
->setUpdatesEnabled(true);
250 // else find the toolbar button
251 for(int i
= 0; i
< d
->widgetPositions
.count(); ++i
)
253 if( rtl
^ (pos
<= d
->widgetPositions
[i
]) )
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
273 if(d
->m_sepIndex
!= actions
.count())
275 QAction
*before
= m_toolBar
->actions()[d
->m_sepIndex
];
276 m_toolBar
->insertAction(before
, m_toolBarSeparator
);
280 m_toolBar
->addAction(m_toolBarSeparator
);
282 m_toolBar
->setUpdatesEnabled(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);
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);
303 void KBookmarkBar::contextMenu(const QPoint
& pos
)
305 KBookmarkActionInterface
* action
= dynamic_cast<KBookmarkActionInterface
*>( m_toolBar
->actionAt(pos
) );
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
)
324 else if ( e
->type() == QEvent::Drop
)
328 QDropEvent
*dev
= static_cast<QDropEvent
*>( e
);
329 QList
<KBookmark
> list
= KBookmark::List::fromMimeData( dev
->mimeData() );
330 if ( list
.isEmpty() )
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
);
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
);
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() ))
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() )
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());
382 d
->widgetPositions
.push_back(button
->geometry().left());
384 d
->widgetPositions
.push_back(button
->geometry().bottom());
387 bool accept
= handleToolbarDragMoveEvent(dme
->pos(), d
->m_actions
, d
->tempLabel
);
391 return true; //Really?
397 #include "konqbookmarkbar.moc"