~ubuntu-branches/ubuntu/lucid/kdebase/lucid

« back to all changes in this revision

Viewing changes to apps/konqueror/src/konqbookmarkbar.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Ana Beatriz Guerrero Lopez
  • Date: 2009-04-05 05:22:13 UTC
  • mfrom: (0.4.2 experimental) (0.2.2 upstream)
  • mto: This revision was merged to the branch mainline in revision 235.
  • Revision ID: james.westby@ubuntu.com-20090405052213-39thr4l6p2ss07uj
Tags: 4:4.2.2-1
* New upstream release:
  - khtml fixes. (Closes: #290285, #359680)
  - Default konsole sessions can be deleted. (Closes: #286342)
  - Tag widget uses standard application palette. (Closes: #444800)
  - ... and surely many more but we have lost track...

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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>
 
6
 
 
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.
 
11
 
 
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.
 
16
 
 
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.
 
21
*/
 
22
 
 
23
#include "konqbookmarkbar.h"
 
24
 
 
25
#include <QApplication>
 
26
#include <QDebug>
 
27
#include <QDropEvent>
 
28
#include <QEvent>
 
29
#include <QFile>
 
30
#include <QRegExp>
 
31
 
 
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>
 
39
 
 
40
#include "konqbookmarkmenu.h"
 
41
#include "kbookmarkimporter.h"
 
42
#include "kbookmarkdombuilder.h"
 
43
 
 
44
 
 
45
 
 
46
class KBookmarkBarPrivate
 
47
{
 
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;
 
55
 
 
56
    KBookmarkBarPrivate() :
 
57
        m_sepIndex( -1 )
 
58
    {
 
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 );
 
64
    }
 
65
};
 
66
 
 
67
 
 
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 )
 
73
{
 
74
    m_toolBar->setAcceptDrops( true );
 
75
    m_toolBar->installEventFilter( this ); // for drops
 
76
 
 
77
    if (d->m_contextMenu)
 
78
    {
 
79
        m_toolBar->setContextMenuPolicy(Qt::CustomContextMenu);
 
80
        connect(m_toolBar, SIGNAL(customContextMenuRequested(const QPoint &)), this, SLOT(contextMenu(const QPoint &)));
 
81
    }
 
82
 
 
83
    connect( mgr, SIGNAL( changed(const QString &, const QString &) ),
 
84
             SLOT( slotBookmarksChanged(const QString &) ) );
 
85
    connect( mgr, SIGNAL( configChanged() ),
 
86
             SLOT( slotConfigChanged() ) );
 
87
 
 
88
    KBookmarkGroup toolbar = getToolbar();
 
89
    fillBookmarkBar( toolbar );
 
90
    m_toolBarSeparator = new QAction(this);
 
91
}
 
92
 
 
93
QString KBookmarkBar::parentAddress()
 
94
{
 
95
    if(d->m_filteredToolbar)
 
96
        return "";
 
97
    else
 
98
        return m_pManager->toolbar().address();
 
99
}
 
100
 
 
101
 
 
102
KBookmarkGroup KBookmarkBar::getToolbar()
 
103
{
 
104
    if(d->m_filteredToolbar)
 
105
        return m_pManager->root();
 
106
    else
 
107
        return m_pManager->toolbar();
 
108
}
 
109
 
 
110
KBookmarkBar::~KBookmarkBar()
 
111
{
 
112
    //clear();
 
113
    qDeleteAll( d->m_actions );
 
114
    qDeleteAll( m_lstSubMenus );
 
115
    delete d;
 
116
}
 
117
 
 
118
void KBookmarkBar::clear()
 
119
{
 
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();
 
126
}
 
127
 
 
128
void KBookmarkBar::slotBookmarksChanged( const QString & group )
 
129
{
 
130
    KBookmarkGroup tb = getToolbar(); // heavy for non cached toolbar version
 
131
    kDebug(7043) << "KBookmarkBar::slotBookmarksChanged( " << group << " )";
 
132
 
 
133
    if ( tb.isNull() )
 
134
        return;
 
135
 
 
136
    if( d->m_filteredToolbar )
 
137
    {
 
138
        clear();
 
139
        fillBookmarkBar( tb );
 
140
    }
 
141
    else if ( KBookmark::commonParent(group, tb.address()) == group)  // Is group a parent of tb.address?
 
142
    {
 
143
        clear();
 
144
        fillBookmarkBar( tb );
 
145
    }
 
146
    else
 
147
    {
 
148
        // Iterate recursively into child menus
 
149
        for ( QList<KBookmarkMenu *>::ConstIterator smit = m_lstSubMenus.constBegin(), smend = m_lstSubMenus.constEnd();
 
150
              smit != smend; ++smit )
 
151
        {
 
152
            (*smit)->slotBookmarksChanged( group );
 
153
        }
 
154
    }
 
155
}
 
156
 
 
157
void KBookmarkBar::slotConfigChanged()
 
158
{
 
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());
 
165
}
 
166
 
 
167
void KBookmarkBar::fillBookmarkBar(const KBookmarkGroup & parent)
 
168
{
 
169
    if (parent.isNull())
 
170
        return;
 
171
 
 
172
    for (KBookmark bm = parent.first(); !bm.isNull(); bm = parent.next(bm))
 
173
    {
 
174
        // Filtered special cases
 
175
        if(d->m_filteredToolbar)
 
176
        {
 
177
            if(bm.isGroup() && !bm.showInToolbar() )
 
178
                fillBookmarkBar(bm.toGroup());
 
179
 
 
180
            if(!bm.showInToolbar())
 
181
                continue;
 
182
        }
 
183
 
 
184
 
 
185
        if (!bm.isGroup())
 
186
        {
 
187
            if ( bm.isSeparator() )
 
188
                m_toolBar->addSeparator();
 
189
            else
 
190
            {
 
191
                KAction *action = new KBookmarkAction( bm, m_pOwner, 0 );
 
192
                m_toolBar->addAction(action);
 
193
                d->m_actions.append( action );
 
194
            }
 
195
        }
 
196
        else
 
197
        {
 
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 );
 
204
        }
 
205
    }
 
206
}
 
207
 
 
208
void KBookmarkBar::removeTempSep()
 
209
{
 
210
    if (m_toolBarSeparator)
 
211
        m_toolBar->removeAction(m_toolBarSeparator);
 
212
 
 
213
}
 
214
 
 
215
/**
 
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
 
222
 */
 
223
bool KBookmarkBar::handleToolbarDragMoveEvent(const QPoint& p, const QList<KAction *>& actions, const QString &text)
 
224
{
 
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();
 
231
 
 
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);
 
237
 
 
238
    // Empty toolbar
 
239
    if(actions.isEmpty())
 
240
    {
 
241
        d->m_sepIndex = 0;
 
242
        m_toolBar->addAction(m_toolBarSeparator);
 
243
        m_toolBar->setUpdatesEnabled(true);
 
244
        return true;
 
245
    }
 
246
 
 
247
    // else find the toolbar button
 
248
    for(int i = 0; i < d->widgetPositions.count(); ++i)
 
249
    {
 
250
        if( rtl ^ (pos <= d->widgetPositions[i]) )
 
251
        {
 
252
            foundWidget = true;
 
253
            d->m_sepIndex = i;
 
254
            break;
 
255
        }
 
256
    }
 
257
 
 
258
    QString address;
 
259
 
 
260
    if (foundWidget) // found the containing button
 
261
    {
 
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) )
 
265
        {
 
266
            // if in second half of button then
 
267
            // we jump to next index
 
268
            d->m_sepIndex++;
 
269
        }
 
270
        if(d->m_sepIndex != actions.count())
 
271
        {
 
272
            QAction *before = m_toolBar->actions()[d->m_sepIndex];
 
273
            m_toolBar->insertAction(before, m_toolBarSeparator);
 
274
        }
 
275
        else
 
276
        {
 
277
            m_toolBar->addAction(m_toolBarSeparator);
 
278
        }
 
279
        m_toolBar->setUpdatesEnabled(true);
 
280
        return true;
 
281
    }
 
282
    else // (!foundWidget)
 
283
    {
 
284
        // if !b and not past last button, we didn't find button
 
285
        if (rtl ^ (pos <= d->widgetPositions[d->widgetPositions.count()-1]) )
 
286
        {
 
287
            m_toolBar->setUpdatesEnabled(true);
 
288
            return false;
 
289
        }
 
290
        else // location is beyond last action, assuming we want to add in the end
 
291
        {
 
292
            d->m_sepIndex = actions.count();
 
293
            m_toolBar->addAction(m_toolBarSeparator);
 
294
            m_toolBar->setUpdatesEnabled(true);
 
295
            return true;
 
296
        }
 
297
    }
 
298
}
 
299
 
 
300
void KBookmarkBar::contextMenu(const QPoint & pos)
 
301
{
 
302
    KBookmarkActionInterface * action = dynamic_cast<KBookmarkActionInterface *>( m_toolBar->actionAt(pos) );
 
303
    if(!action)
 
304
    {
 
305
        //Show default (ktoolbar) menu
 
306
        m_toolBar->setContextMenuPolicy( Qt::DefaultContextMenu );
 
307
        //Recreate event with the same position
 
308
        QContextMenuEvent evt( QContextMenuEvent::Other, pos );
 
309
        QCoreApplication::sendEvent( m_toolBar, &evt );
 
310
        //Reassign custom context menu
 
311
        m_toolBar->setContextMenuPolicy( Qt::CustomContextMenu );
 
312
    }
 
313
    else
 
314
    {
 
315
        KMenu * menu = new KonqBookmarkContextMenu(action->bookmark(), m_pManager, m_pOwner);
 
316
        menu->setAttribute(Qt::WA_DeleteOnClose);
 
317
        menu->popup(m_toolBar->mapToGlobal(pos));
 
318
    }
 
319
}
 
320
 
 
321
// TODO    *** drop improvements ***
 
322
// open submenus on drop interactions
 
323
bool KBookmarkBar::eventFilter( QObject *, QEvent *e )
 
324
{
 
325
    if (d->m_filteredToolbar)
 
326
        return false; // todo: make this limit the actions
 
327
 
 
328
    if ( e->type() == QEvent::DragLeave )
 
329
    {
 
330
        removeTempSep();
 
331
    }
 
332
    else if ( e->type() == QEvent::Drop )
 
333
    {
 
334
        removeTempSep();
 
335
 
 
336
        QDropEvent *dev = static_cast<QDropEvent*>( e );
 
337
        QList<KBookmark> list = KBookmark::List::fromMimeData( dev->mimeData() );
 
338
        if ( list.isEmpty() )
 
339
            return false;
 
340
        if (list.count() > 1)
 
341
            kWarning(7043) << "Sorry, currently you can only drop one address "
 
342
                "onto the bookmark bar!";
 
343
        KBookmark toInsert = list.first();
 
344
 
 
345
        KBookmarkGroup parentBookmark = getToolbar();
 
346
 
 
347
        if(d->m_sepIndex == 0)
 
348
        {
 
349
            KBookmark newBookmark = parentBookmark.addBookmark(toInsert.fullText(), toInsert.url() );
 
350
 
 
351
            parentBookmark.moveBookmark( newBookmark, KBookmark() );
 
352
            m_pManager->emitChanged( parentBookmark );
 
353
            return true;
 
354
        }
 
355
        else
 
356
        {
 
357
            KBookmark after = parentBookmark.first();
 
358
 
 
359
            for(int i=0; i < d->m_sepIndex - 1 ; ++i)
 
360
                after = parentBookmark.next(after);
 
361
            KBookmark newBookmark = parentBookmark.addBookmark(toInsert.fullText(), toInsert.url() );
 
362
 
 
363
            parentBookmark.moveBookmark( newBookmark, after );
 
364
            m_pManager->emitChanged( parentBookmark );
 
365
            return true;
 
366
        }
 
367
    }
 
368
    else if ( e->type() == QEvent::DragMove || e->type() == QEvent::DragEnter )
 
369
    {
 
370
        QDragMoveEvent *dme = static_cast<QDragMoveEvent*>( e );
 
371
        if (!KBookmark::List::canDecode( dme->mimeData() ))
 
372
            return false;
 
373
 
 
374
        //cache text, save positions (inserting the temporary widget changes the positions)
 
375
        if(e->type() == QEvent::DragEnter)
 
376
        {
 
377
            QList<KBookmark> list = KBookmark::List::fromMimeData( dme->mimeData() );
 
378
            if ( list.isEmpty() )
 
379
                return false;
 
380
            d->tempLabel  = list.first().url().pathOrUrl();
 
381
 
 
382
            d->widgetPositions.clear();
 
383
 
 
384
            for (int i = 0; i < m_toolBar->actions().count(); ++i)
 
385
                if (QWidget* button = m_toolBar->widgetForAction(m_toolBar->actions()[i])) {
 
386
                    if(m_toolBar->orientation() == Qt::Horizontal) {
 
387
                        if(QApplication::isLeftToRight()) {
 
388
                            d->widgetPositions.push_back(button->geometry().right());
 
389
                        } else {
 
390
                            d->widgetPositions.push_back(button->geometry().left());
 
391
                        }
 
392
                    } else {
 
393
                        d->widgetPositions.push_back(button->geometry().bottom());
 
394
                    }
 
395
                }
 
396
        }
 
397
 
 
398
        bool accept = handleToolbarDragMoveEvent(dme->pos(), d->m_actions, d->tempLabel);
 
399
        if (accept)
 
400
        {
 
401
            dme->accept();
 
402
            return true; //Really?
 
403
        }
 
404
    }
 
405
    return false;
 
406
}
 
407
 
 
408
#include "konqbookmarkbar.moc"