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
.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 );
164 fillBookmarkBar(getToolbar());
167 void KBookmarkBar::fillBookmarkBar(const KBookmarkGroup
& parent
)
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())
187 if ( bm
.isSeparator() )
188 m_toolBar
->addSeparator();
191 KAction
*action
= new KBookmarkAction( bm
, m_pOwner
, 0 );
192 m_toolBar
->addAction(action
);
193 d
->m_actions
.append( action
);
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
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
)
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);
232 bool foundWidget
= false;
234 // only relevant if the toolbar is Horizontal!
235 bool rtl
= QApplication::isRightToLeft() && m_toolBar
->orientation() == Qt::Horizontal
;
236 m_toolBarSeparator
->setText(text
);
239 if(actions
.isEmpty())
242 m_toolBar
->addAction(m_toolBarSeparator
);
243 m_toolBar
->setUpdatesEnabled(true);
247 // else find the toolbar button
248 for(int i
= 0; i
< d
->widgetPositions
.count(); ++i
)
250 if( rtl
^ (pos
<= d
->widgetPositions
[i
]) )
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
270 if(d
->m_sepIndex
!= actions
.count())
272 QAction
*before
= m_toolBar
->actions()[d
->m_sepIndex
];
273 m_toolBar
->insertAction(before
, m_toolBarSeparator
);
277 m_toolBar
->addAction(m_toolBarSeparator
);
279 m_toolBar
->setUpdatesEnabled(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);
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);
300 void KBookmarkBar::contextMenu(const QPoint
& pos
)
302 KBookmarkActionInterface
* action
= dynamic_cast<KBookmarkActionInterface
*>( m_toolBar
->actionAt(pos
) );
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
)
321 else if ( e
->type() == QEvent::Drop
)
325 QDropEvent
*dev
= static_cast<QDropEvent
*>( e
);
326 QList
<KBookmark
> list
= KBookmark::List::fromMimeData( dev
->mimeData() );
327 if ( list
.isEmpty() )
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
);
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
);
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() ))
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() )
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());
379 d
->widgetPositions
.push_back(button
->geometry().left());
382 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"