source: tspsg/src/3rdparty/qttoolbardialog-2.2_1-opensource/src/qttoolbardialog.cpp @ 7bb19df196

0.1.3.145-beta1-symbian0.1.4.170-beta2-bb10appveyorimgbotreadme
Last change on this file since 7bb19df196 was 7bb19df196, checked in by Oleksii Serdiuk, 14 years ago

Finished toolbar customization feature.
It is not available on handheld devices (mainly, because the customization dialog is too big for a small screen).

  • Property mode set to 100644
File size: 60.7 KB
Line 
1/****************************************************************************
2**
3** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
4** All rights reserved.
5** Contact: Nokia Corporation ([email protected])
6**
7** This file is part of a Qt Solutions component.
8**
9** Commercial Usage 
10** Licensees holding valid Qt Commercial licenses may use this file in
11** accordance with the Qt Solutions Commercial License Agreement provided
12** with the Software or, alternatively, in accordance with the terms
13** contained in a written agreement between you and Nokia.
14**
15** GNU Lesser General Public License Usage
16** Alternatively, this file may be used under the terms of the GNU Lesser
17** General Public License version 2.1 as published by the Free Software
18** Foundation and appearing in the file LICENSE.LGPL included in the
19** packaging of this file.  Please review the following information to
20** ensure the GNU Lesser General Public License version 2.1 requirements
21** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
22**
23** In addition, as a special exception, Nokia gives you certain
24** additional rights. These rights are described in the Nokia Qt LGPL
25** Exception version 1.1, included in the file LGPL_EXCEPTION.txt in this
26** package.
27**
28** GNU General Public License Usage
29** Alternatively, this file may be used under the terms of the GNU
30** General Public License version 3.0 as published by the Free Software
31** Foundation and appearing in the file LICENSE.GPL included in the
32** packaging of this file.  Please review the following information to
33** ensure the GNU General Public License version 3.0 requirements will be
34** met: http://www.gnu.org/copyleft/gpl.html.
35**
36** Please note Third Party Software included with Qt Solutions may impose
37** additional restrictions and it is the user's responsibility to ensure
38** that they have met the licensing requirements of the GPL, LGPL, or Qt
39** Solutions Commercial license and the relevant license of the Third
40** Party Software they are using.
41**
42** If you are unsure which license is appropriate for your use, please
43** contact Nokia at [email protected].
44**
45****************************************************************************/
46
47#include "qttoolbardialog.h"
48#include "ui_qttoolbardialog.h"
49#include <QtCore/QSet>
50#include <QtGui/QAction>
51#include <QtGui/QToolBar>
52#include <QtGui/QMainWindow>
53#include <QtGui/QShowEvent>
54#include <QtGui/QHideEvent>
55#include <QtGui/QHeaderView>
56
57class QtFullToolBarManagerPrivate
58{
59    class QtFullToolBarManager *q_ptr;
60    Q_DECLARE_PUBLIC(QtFullToolBarManager)
61
62public:
63
64    QToolBar *toolBarWidgetAction(QAction *action) const;
65    void removeWidgetActions(const QMap<QToolBar *, QList<QAction *> > &actions);
66
67    enum {
68        VersionMarker = 0xff,
69        ToolBarMarker = 0xfe,
70        CustomToolBarMarker = 0xfd,
71    };
72
73    void saveState(QDataStream &stream) const;
74    bool restoreState(QDataStream &stream) const;
75    QToolBar *findDefaultToolBar(const QString &objectName) const;
76    QAction *findAction(const QString &actionName) const;
77
78    QToolBar *toolBarByName(const QString &toolBarName) const;
79
80    QtFullToolBarManagerPrivate();
81
82    QMap<QString, QList<QAction *> > categoryToActions;
83    QMap<QAction *, QString>         actionToCategory;
84
85    QSet<QAction *> allActions;
86    QMap<QAction *, QToolBar *> widgetActions;
87    QSet<QAction *> regularActions;
88    QMap<QAction *, QList<QToolBar *> > actionToToolBars;
89
90    QMap<QToolBar *, QList<QAction *> > toolBars;
91    QMap<QToolBar *, QList<QAction *> > toolBarsWithSeparators;
92    QMap<QToolBar *, QList<QAction *> > defaultToolBars;
93    QList<QToolBar *> customToolBars;
94
95    QMainWindow *theMainWindow;
96};
97
98
99class QtFullToolBarManager : public QObject
100{
101    Q_OBJECT
102public:
103    QtFullToolBarManager(QObject *parent);
104    ~QtFullToolBarManager();
105
106    void setMainWindow(QMainWindow *mainWindow);
107    QMainWindow *mainWindow() const;
108
109    void addCategory(const QString &category);
110    bool hasCategory(const QString &category) const;
111    QStringList categories() const;
112    QList<QAction *> categoryActions(const QString &category) const;
113    QString actionCategory(QAction *action) const;
114
115    // only non-separator
116    void addAction(QAction *action, const QString &category);
117
118    void removeAction(QAction *action);
119
120    QSet<QAction *> actions() const;
121    bool isWidgetAction(QAction *action) const;
122
123    /*
124    Adds (registers) toolBar. Adds (registers) actions that already exists in toolBar.
125    Remembers toolbar and its actions as a default.
126    */
127    void addDefaultToolBar(QToolBar *toolBar, const QString &category);
128
129    void removeDefaultToolBar(QToolBar *toolBar);
130    // NULL on action list means separator.
131    QMap<QToolBar *, QList<QAction *> > defaultToolBars() const;
132    bool isDefaultToolBar(QToolBar *toolBar) const;
133
134    QToolBar *createToolBar(const QString &toolBarName);
135    void deleteToolBar(QToolBar *toolBar); // only those which were created, not added
136
137    QList<QAction *> actions(QToolBar *toolBar) const;
138
139    void setToolBars(const QMap<QToolBar *, QList<QAction *> > &actions);
140    void setToolBar(QToolBar *toolBar, const QList<QAction *> &actions);
141
142    QMap<QToolBar *, QList<QAction *> > toolBarsActions() const;
143    QByteArray saveState(int version = 0) const;
144    bool restoreState(const QByteArray &state, int version = 0);
145
146public slots:
147
148    void resetToolBar(QToolBar *toolBar);
149    void resetAllToolBars();
150
151signals:
152    void toolBarCreated(QToolBar *toolBar);
153    void toolBarRemoved(QToolBar *toolBar);
154
155    /*
156    If QToolBarWidgetAction was in another tool bar and is inserted into
157    this toolBar, toolBarChanged is first emited for other toolbar - without
158    that action. (Another approach may be that user first must call setToolBar
159    without that action for old tool bar)
160    */
161    void toolBarChanged(QToolBar *toolBar, const QList<QAction *> &actions);
162
163private:
164    QtFullToolBarManagerPrivate *d_ptr;
165    Q_DECLARE_PRIVATE(QtFullToolBarManager)
166    Q_DISABLE_COPY(QtFullToolBarManager)
167};
168
169
170QtFullToolBarManagerPrivate::QtFullToolBarManagerPrivate()
171    : theMainWindow(0)
172{
173}
174
175QToolBar *QtFullToolBarManagerPrivate::toolBarWidgetAction(QAction *action) const
176{
177    if (widgetActions.contains(action))
178        return widgetActions.value(action);
179    return 0;
180}
181
182void QtFullToolBarManagerPrivate::removeWidgetActions(const QMap<QToolBar *, QList<QAction *> >
183            &actions)
184{
185    QMap<QToolBar *, QList<QAction *> >::ConstIterator itToolBar = actions.constBegin();
186    while (itToolBar != actions.constEnd()) {
187        QToolBar *toolBar = itToolBar.key();
188        QList<QAction *> newActions = toolBars.value(toolBar);
189        QList<QAction *> newActionsWithSeparators = toolBarsWithSeparators.value(toolBar);
190
191        QList<QAction *> removedActions;
192        QList<QAction *> actionList = itToolBar.value();
193        QListIterator<QAction *> itAction(actionList);
194        while (itAction.hasNext()) {
195            QAction *action = itAction.next();
196            if (newActions.contains(action) && toolBarWidgetAction(action) == toolBar) {
197                newActions.removeAll(action);
198                newActionsWithSeparators.removeAll(action);
199                removedActions.append(action);
200            }
201        }
202
203        //emit q_ptr->toolBarChanged(toolBar, newActions);
204
205        toolBars.insert(toolBar, newActions);
206        toolBarsWithSeparators.insert(toolBar, newActionsWithSeparators);
207        QListIterator<QAction *> itRemovedAction(removedActions);
208        while (itRemovedAction.hasNext()) {
209            QAction *oldAction = itRemovedAction.next();
210            widgetActions.insert(oldAction, 0);
211            actionToToolBars[oldAction].removeAll(toolBar);
212        }
213
214        itToolBar++;
215    }
216}
217
218void QtFullToolBarManagerPrivate::saveState(QDataStream &stream) const
219{
220    stream << (uchar) ToolBarMarker;
221    stream << defaultToolBars.size();
222    QMap<QToolBar *, QList<QAction *> >::ConstIterator itToolBar =
223                defaultToolBars.constBegin();
224    while (itToolBar != defaultToolBars.constEnd()) {
225        QToolBar *tb = itToolBar.key();
226        if (tb->objectName().isEmpty()) {
227            qWarning("QtToolBarManager::saveState(): 'objectName' not set for QToolBar "
228                "%p '%s', using 'windowTitle' instead",
229            tb, tb->windowTitle().toLocal8Bit().constData());
230            stream << tb->windowTitle();
231        } else {
232            stream << tb->objectName();
233        }
234
235        stream << toolBars[tb].size();
236        QListIterator<QAction *> itAction(toolBars[tb]);
237        while (itAction.hasNext()) {
238            QAction *action = itAction.next();
239
240            if (action) {
241                if (action->objectName().isEmpty()) {
242                    qWarning("QtToolBarManager::saveState(): 'objectName' not set for QAction "
243                                "%p '%s', using 'text' instead",
244                            action, action->text().toLocal8Bit().constData());
245                    stream << action->text();
246                } else {
247                    stream << action->objectName();
248                }
249            } else {
250                stream << QString();
251            }
252        }
253        itToolBar++;
254    }
255
256
257    stream << (uchar) CustomToolBarMarker;
258    stream << toolBars.size() - defaultToolBars.size();
259    itToolBar = toolBars.constBegin();
260    while (itToolBar != toolBars.constEnd()) {
261        QToolBar *tb = itToolBar.key();
262        if (!defaultToolBars.contains(tb)) {
263            stream << tb->objectName();
264            stream << tb->windowTitle();
265
266            stream << toolBars[tb].size();
267            QListIterator<QAction *> itAction(toolBars[tb]);
268            while (itAction.hasNext()) {
269                QAction *action = itAction.next();
270
271                if (action) {
272                    if (action->objectName().isEmpty()) {
273                        qWarning("QtToolBarManager::saveState(): 'objectName' not set for QAction "
274                                    "%p '%s', using 'text' instead",
275                                action, action->text().toLocal8Bit().constData());
276                        stream << action->text();
277                    } else {
278                        stream << action->objectName();
279                    }
280                } else {
281                    stream << QString();
282                }
283            }
284        }
285        itToolBar++;
286    }
287}
288
289bool QtFullToolBarManagerPrivate::restoreState(QDataStream &stream) const
290{
291    uchar tmarker;
292    stream >> tmarker;
293    if (tmarker != ToolBarMarker)
294        return false;
295
296    int toolBars;
297    stream >> toolBars;
298    for (int i = 0; i < toolBars; i++) {
299        QString objectName;
300        stream >> objectName;
301        int actionCount;
302        stream >> actionCount;
303        QList<QAction *> actions;
304        for (int j = 0; j < actionCount; j++) {
305            QString actionName;
306            stream >> actionName;
307
308            if (actionName.isEmpty())
309                actions.append(0);
310            else {
311                QAction *action = findAction(actionName);
312                if (action)
313                    actions.append(action);
314            }
315        }
316
317        QToolBar *toolBar = findDefaultToolBar(objectName);
318        if (toolBar)
319            q_ptr->setToolBar(toolBar, actions);
320    }
321
322
323
324    uchar ctmarker;
325    stream >> ctmarker;
326    if (ctmarker != CustomToolBarMarker)
327        return false;
328
329    QList<QToolBar *> oldCustomToolBars = customToolBars;
330
331    stream >> toolBars;
332    for (int i = 0; i < toolBars; i++) {
333        QString objectName;
334        QString toolBarName;
335        int actionCount;
336        stream >> objectName;
337        stream >> toolBarName;
338        stream >> actionCount;
339        QList<QAction *> actions;
340        for (int j = 0; j < actionCount; j++) {
341            QString actionName;
342            stream >> actionName;
343
344            if (actionName.isEmpty())
345                actions.append(0);
346            else {
347                QAction *action = findAction(actionName);
348                if (action)
349                    actions.append(action);
350            }
351        }
352
353        QToolBar *toolBar = toolBarByName(objectName);
354        if (toolBar) {
355            toolBar->setWindowTitle(toolBarName);
356            oldCustomToolBars.removeAll(toolBar);
357        }
358        else
359            toolBar = q_ptr->createToolBar(toolBarName);
360        if (toolBar) {
361            toolBar->setObjectName(objectName);
362            q_ptr->setToolBar(toolBar, actions);
363        }
364    }
365    QListIterator<QToolBar *> itToolBar(oldCustomToolBars);
366    while (itToolBar.hasNext())
367        q_ptr->deleteToolBar(itToolBar.next());
368    return true;
369}
370
371QToolBar *QtFullToolBarManagerPrivate::findDefaultToolBar(const QString &objectName) const
372{
373    QMap<QToolBar *, QList<QAction *> >::ConstIterator itToolBar =
374                defaultToolBars.constBegin();
375    while (itToolBar != defaultToolBars.constEnd()) {
376        QToolBar *tb = itToolBar.key();
377        if (tb->objectName() == objectName)
378            return tb;
379
380        itToolBar++;
381    }
382
383    qWarning("QtToolBarManager::restoreState(): cannot find a QToolBar named "
384        "'%s', trying to match using 'windowTitle' instead.",
385        objectName.toLocal8Bit().constData());
386
387    itToolBar = defaultToolBars.constBegin();
388    while (itToolBar != defaultToolBars.constEnd()) {
389        QToolBar *tb = itToolBar.key();
390        if (tb->windowTitle() == objectName)
391            return tb;
392
393        itToolBar++;
394    }
395    qWarning("QtToolBarManager::restoreState(): cannot find a QToolBar with "
396        "matching 'windowTitle' (looking for '%s').",
397        objectName.toLocal8Bit().constData());
398
399    return 0;
400}
401
402QAction *QtFullToolBarManagerPrivate::findAction(const QString &actionName) const
403{
404    QSetIterator<QAction *> itAction(allActions);
405    while (itAction.hasNext()) {
406        QAction *action = itAction.next();
407
408        if (action->objectName() == actionName)
409            return action;
410    }
411    qWarning("QtToolBarManager::restoreState(): cannot find a QAction named "
412        "'%s', trying to match using 'text' instead.",
413        actionName.toLocal8Bit().constData());
414
415    itAction.toFront();
416    while (itAction.hasNext()) {
417        QAction *action = itAction.next();
418
419        if (action->text() == actionName)
420            return action;
421    }
422    qWarning("QtToolBarManager::restoreState(): cannot find a QAction with "
423        "matching 'text' (looking for '%s').",
424        actionName.toLocal8Bit().constData());
425
426    return 0;
427}
428
429QToolBar *QtFullToolBarManagerPrivate::toolBarByName(const QString &toolBarName) const
430{
431    QMap<QToolBar *, QList<QAction *> >::ConstIterator itToolBar = toolBars.constBegin();
432    while (itToolBar != toolBars.constEnd()) {
433        QToolBar *toolBar = itToolBar.key();
434        if (toolBar->objectName() == toolBarName)
435            return toolBar;
436
437        itToolBar++;
438    }
439    return 0;
440}
441
442//////////////////////////////
443
444QtFullToolBarManager::QtFullToolBarManager(QObject *parent)
445    : QObject(parent)
446{
447    d_ptr = new QtFullToolBarManagerPrivate;
448    d_ptr->q_ptr = this;
449}
450
451QtFullToolBarManager::~QtFullToolBarManager()
452{
453    delete d_ptr;
454}
455
456void QtFullToolBarManager::setMainWindow(QMainWindow *mainWindow)
457{
458    d_ptr->theMainWindow = mainWindow;
459}
460
461QMainWindow *QtFullToolBarManager::mainWindow() const
462{
463    return d_ptr->theMainWindow;
464}
465
466void QtFullToolBarManager::addCategory(const QString &category)
467{
468    d_ptr->categoryToActions[category] = QList<QAction *>();
469}
470
471bool QtFullToolBarManager::hasCategory(const QString &category) const
472{
473    return d_ptr->categoryToActions.contains(category);
474}
475
476QStringList QtFullToolBarManager::categories() const
477{
478    return d_ptr->categoryToActions.keys();
479}
480
481QList<QAction *> QtFullToolBarManager::categoryActions(const QString &category) const
482{
483    QMap<QString, QList<QAction *> >::ConstIterator it =
484                d_ptr->categoryToActions.find(category);
485    if (it != d_ptr->categoryToActions.constEnd())
486        return it.value();
487    return QList<QAction *>();
488}
489
490QString QtFullToolBarManager::actionCategory(QAction *action) const
491{
492    QMap<QAction *, QString>::ConstIterator it = d_ptr->actionToCategory.find(action);
493    if (it != d_ptr->actionToCategory.constEnd())
494        return it.value();
495    return QString();
496}
497
498void QtFullToolBarManager::addAction(QAction *action, const QString &category)
499{
500    if (!action)
501        return;
502//    if (!d_ptr->categoryToActions.contains(category))
503//        return;
504    if (action->isSeparator())
505        return;
506    if (d_ptr->allActions.contains(action))
507        return;
508    if (QLatin1String(action->metaObject()->className()) ==
509                QLatin1String("QToolBarWidgetAction"))
510        d_ptr->widgetActions.insert(action, 0);
511    else
512        d_ptr->regularActions.insert(action);
513    d_ptr->allActions.insert(action);
514    d_ptr->categoryToActions[category].append(action);
515    d_ptr->actionToCategory[action] = category;
516}
517
518void QtFullToolBarManager::removeAction(QAction *action)
519{
520    if (!d_ptr->allActions.contains(action))
521        return;
522
523    QList<QToolBar *> toolBars = d_ptr->actionToToolBars[action];
524    QListIterator<QToolBar *> itToolBar(toolBars);
525    while (itToolBar.hasNext()) {
526        QToolBar *toolBar = itToolBar.next();
527
528        d_ptr->toolBars[toolBar].removeAll(action);
529        d_ptr->toolBarsWithSeparators[toolBar].removeAll(action);
530
531        toolBar->removeAction(action);
532    }
533
534    QMap<QToolBar *, QList<QAction *> >::ConstIterator itDefault =
535            d_ptr->defaultToolBars.constBegin();
536    while (itDefault != d_ptr->defaultToolBars.constEnd()) {
537        if (itDefault.value().contains(action))
538            d_ptr->defaultToolBars[itDefault.key()].removeAll(action);
539
540        itDefault++;
541    }
542
543    d_ptr->allActions.remove(action);
544    d_ptr->widgetActions.remove(action);
545    d_ptr->regularActions.remove(action);
546    d_ptr->actionToToolBars.remove(action);
547
548    QString category = d_ptr->actionToCategory.value(action);
549    d_ptr->actionToCategory.remove(action);
550    d_ptr->categoryToActions[category].removeAll(action);
551
552    if (d_ptr->categoryToActions[category].isEmpty())
553        d_ptr->categoryToActions.remove(category);
554}
555
556QSet<QAction *> QtFullToolBarManager::actions() const
557{
558    return d_ptr->allActions;
559}
560
561bool QtFullToolBarManager::isWidgetAction(QAction *action) const
562{
563    if (d_ptr->widgetActions.contains(action))
564        return true;
565    return false;
566}
567
568void QtFullToolBarManager::addDefaultToolBar(QToolBar *toolBar, const QString &category)
569{
570    if (!toolBar)
571        return;
572    if (d_ptr->toolBars.contains(toolBar))
573        return;
574//    if (!d_ptr->categoryToActions.contains(category))
575//        return;
576    // could be also checked if toolBar belongs to mainwindow
577
578    QList<QAction *> newActionsWithSeparators;
579    QList<QAction *> newActions;
580    QList<QAction *> actions = toolBar->actions();
581    QListIterator<QAction *> itAction(actions);
582    while (itAction.hasNext()) {
583        QAction *action = itAction.next();
584        addAction(action, category);
585        if (d_ptr->widgetActions.contains(action))
586            d_ptr->widgetActions.insert(action, toolBar);
587        newActionsWithSeparators.append(action);
588        if (action->isSeparator())
589            action = 0;
590        else
591            d_ptr->actionToToolBars[action].append(toolBar);
592        newActions.append(action);
593    }
594    d_ptr->defaultToolBars.insert(toolBar, newActions);
595    //Below could be done by call setToolBar() if we want signal emission here.
596    d_ptr->toolBars.insert(toolBar, newActions);
597    d_ptr->toolBarsWithSeparators.insert(toolBar, newActionsWithSeparators);
598}
599
600void QtFullToolBarManager::removeDefaultToolBar(QToolBar *toolBar)
601{
602    if (!d_ptr->defaultToolBars.contains(toolBar))
603        return;
604
605    QList<QAction *> defaultActions = d_ptr->defaultToolBars[toolBar];
606    setToolBar(toolBar, QList<QAction *>());
607    QListIterator<QAction *> itAction(defaultActions);
608    while (itAction.hasNext())
609        removeAction(itAction.next());
610
611    d_ptr->toolBars.remove(toolBar);
612    d_ptr->toolBarsWithSeparators.remove(toolBar);
613    d_ptr->defaultToolBars.remove(toolBar);
614
615    itAction.toFront();
616    while (itAction.hasNext()) {
617        QAction *action = itAction.next();
618        if (action)
619            toolBar->insertAction(0, action);
620        else
621            toolBar->insertSeparator(0);
622    }
623}
624
625QMap<QToolBar *, QList<QAction *> > QtFullToolBarManager::defaultToolBars() const
626{
627    return d_ptr->defaultToolBars;
628}
629
630bool QtFullToolBarManager::isDefaultToolBar(QToolBar *toolBar) const
631{
632    if (d_ptr->defaultToolBars.contains(toolBar))
633        return true;
634    return false;
635}
636
637QToolBar *QtFullToolBarManager::createToolBar(const QString &toolBarName)
638{
639    if (!mainWindow())
640        return 0;
641    QToolBar *toolBar = new QToolBar(toolBarName, mainWindow());
642    int i = 1;
643    QLatin1String prefix("_Custom_Toolbar_");
644    QString name = QString("%1%2").arg(prefix).arg(i);
645    while (d_ptr->toolBarByName(name))
646        name = QString("%1%2").arg(prefix).arg(++i);
647    toolBar->setObjectName(name);
648    mainWindow()->addToolBar(toolBar);
649    d_ptr->customToolBars.append(toolBar);
650    d_ptr->toolBars.insert(toolBar, QList<QAction *>());
651    d_ptr->toolBarsWithSeparators.insert(toolBar, QList<QAction *>());
652    //emit toolBarCreated(toolBar);
653    return toolBar;
654}
655
656void QtFullToolBarManager::deleteToolBar(QToolBar *toolBar)
657{
658    if (!d_ptr->toolBars.contains(toolBar))
659        return;
660    if (d_ptr->defaultToolBars.contains(toolBar))
661        return;
662    setToolBar(toolBar, QList<QAction *>());
663    //emit toolBarRemoved(toolBar);
664    d_ptr->customToolBars.removeAll(toolBar);
665    d_ptr->toolBars.remove(toolBar);
666    d_ptr->toolBarsWithSeparators.remove(toolBar);
667    delete toolBar;
668}
669
670QList<QAction *> QtFullToolBarManager::actions(QToolBar *toolBar) const
671{
672    if (d_ptr->toolBars.contains(toolBar))
673        return d_ptr->toolBars.value(toolBar);
674    return QList<QAction *>();
675}
676
677void QtFullToolBarManager::setToolBars(const QMap<QToolBar *, QList<QAction *> > &actions)
678{
679    QMap<QToolBar *, QList<QAction *> >::ConstIterator it = actions.constBegin();
680    while (it != actions.constEnd()) {
681        setToolBar(it.key(), it.value());
682        it++;
683    }
684}
685
686void QtFullToolBarManager::setToolBar(QToolBar *toolBar, const QList<QAction *> &actions)
687{
688    if (!toolBar)
689        return;
690    if (!d_ptr->toolBars.contains(toolBar))
691        return;
692
693    if (actions == d_ptr->toolBars[toolBar])
694        return;
695
696    QMap<QToolBar *, QList<QAction *> > toRemove;
697
698    QList<QAction *> newActions;
699    QListIterator<QAction *> itAction(actions);
700    while (itAction.hasNext()) {
701        QAction *action = itAction.next();
702        if (!action || (!newActions.contains(action) && d_ptr->allActions.contains(action)))
703            newActions.append(action);
704
705        QToolBar *oldToolBar = d_ptr->toolBarWidgetAction(action);
706        if (oldToolBar && oldToolBar != toolBar)
707            toRemove[oldToolBar].append(action);
708    }
709
710    d_ptr->removeWidgetActions(toRemove);
711    //emit toolBarChanged(toolBar, newActions);
712
713    QList<QAction *> oldActions = d_ptr->toolBarsWithSeparators.value(toolBar);
714    QListIterator<QAction *> itOldAction(oldActions);
715    while (itOldAction.hasNext()) {
716        QAction *action = itOldAction.next();
717        /*
718        When addDefaultToolBar() separator actions could be checked if they are
719        inserted in other toolbars - if yes then create new one.
720        */
721        if (d_ptr->toolBarWidgetAction(action) == toolBar)
722            d_ptr->widgetActions.insert(action, 0);
723        toolBar->removeAction(action);
724        if (action->isSeparator())
725            delete action;
726        else
727            d_ptr->actionToToolBars[action].removeAll(toolBar);
728    }
729
730    QList<QAction *> newActionsWithSeparators;
731    QListIterator<QAction *> itNewActions(newActions);
732    while (itNewActions.hasNext()) {
733        QAction *action = itNewActions.next();
734        QAction *newAction = 0;
735        if (!action)
736            newAction = toolBar->insertSeparator(0);
737        if (d_ptr->allActions.contains(action)) {
738            toolBar->insertAction(0, action);
739            newAction = action;
740            d_ptr->actionToToolBars[action].append(toolBar);
741        }
742        newActionsWithSeparators.append(newAction);
743    }
744    d_ptr->toolBars.insert(toolBar, newActions);
745    d_ptr->toolBarsWithSeparators.insert(toolBar, newActionsWithSeparators);
746}
747
748QMap<QToolBar *, QList<QAction *> > QtFullToolBarManager::toolBarsActions() const
749{
750    return d_ptr->toolBars;
751}
752
753void QtFullToolBarManager::resetToolBar(QToolBar *toolBar)
754{
755    if (!isDefaultToolBar(toolBar))
756        return;
757    setToolBar(toolBar, defaultToolBars().value(toolBar));
758}
759
760void QtFullToolBarManager::resetAllToolBars()
761{
762    setToolBars(defaultToolBars());
763    QList<QToolBar *> oldCustomToolBars = d_ptr->customToolBars;
764    QListIterator<QToolBar *> itToolBar(oldCustomToolBars);
765    while (itToolBar.hasNext()) {
766        deleteToolBar(itToolBar.next());
767    }
768}
769
770QByteArray QtFullToolBarManager::saveState(int version) const
771{
772    QByteArray data;
773    QDataStream stream(&data, QIODevice::WriteOnly);
774    stream << QtFullToolBarManagerPrivate::VersionMarker;
775    stream << version;
776    d_ptr->saveState(stream);
777    return data;
778}
779
780bool QtFullToolBarManager::restoreState(const QByteArray &state, int version)
781{
782    QByteArray sd = state;
783    QDataStream stream(&sd, QIODevice::ReadOnly);
784    int marker, v;
785    stream >> marker;
786    stream >> v;
787    if (marker != QtFullToolBarManagerPrivate::VersionMarker || v != version)
788        return false;
789    return d_ptr->restoreState(stream);
790}
791
792
793class QtToolBarManagerPrivate
794{
795    class QtToolBarManager *q_ptr;
796    Q_DECLARE_PUBLIC(QtToolBarManager)
797public:
798    QtFullToolBarManager *manager;
799};
800
801//////////////////////////////////////
802
803/*! \class QtToolBarManager
804
805    \brief The QtToolBarManager class provides toolbar management for
806    main windows.
807
808    The QtToolBarManager is typically used with a QtToolBarDialog
809    which allows the user to customize the toolbars for a given main
810    window. The QtToolBarDialog class's functionality is controlled by
811    an instance of the QtToolBarManager class, and the main window is
812    specified using the QtToolBarManager class's setMainWindow()
813    function.
814
815    The currently specified main window can be retrieved using the
816    mainWindow() function.
817
818    The toolbar manager holds lists of the given main window's actions
819    and toolbars, and can add actions and toolbars to these
820    lists using the addAction() and addToolBar() functions
821    respectively. The actions can in addition be categorized
822    acccording to the user's preferences. The toolbar manager can also
823    remove custom actions and toolbars using the removeAction() and
824    removeToolBar() functions.
825
826    Finally, the QtToolBarManager is able to save the customized state
827    of its toolbars using the saveState() function as well as restore
828    the toolbars' saved state using restoreState() function.
829
830    \sa QtToolBarDialog
831*/
832
833/*!
834    Creates a toolbar manager with the given \a parent.
835*/
836QtToolBarManager::QtToolBarManager(QObject *parent)
837    : QObject(parent)
838{
839    d_ptr = new QtToolBarManagerPrivate;
840    d_ptr->q_ptr = this;
841
842    d_ptr->manager = new QtFullToolBarManager(this);
843}
844
845/*!
846    Destroys the toolbar manager.
847*/
848QtToolBarManager::~QtToolBarManager()
849{
850    delete d_ptr;
851}
852
853/*!
854    Sets the main window upon which the toolbar manager operates, to
855    be the given \a mainWindow.
856*/
857void QtToolBarManager::setMainWindow(QMainWindow *mainWindow)
858{
859    d_ptr->manager->setMainWindow(mainWindow);
860}
861
862/*!
863    Returns the main window associated this toolbar manager.
864*/
865QMainWindow *QtToolBarManager::mainWindow() const
866{
867    return d_ptr->manager->mainWindow();
868}
869
870/*!
871    Adds the given \a action to the given \a category in the manager's
872    list of actions. If the \a category doesn't exist it is created.
873    Only non separator actions can be added. If the action is already
874    added to the list, the function doesn't do anything.
875
876    \sa removeAction()
877*/
878void QtToolBarManager::addAction(QAction *action, const QString &category)
879{
880    d_ptr->manager->addAction(action, category);
881}
882
883/*!
884    Removes the specified \a action from the manager's list of
885    actions. The action is also removed from all the registered
886    toolbars.  If the specified \a action is the only action in its
887    category, that category is removed as well.
888
889    \sa addAction()
890*/
891void QtToolBarManager::removeAction(QAction *action)
892{
893    d_ptr->manager->removeAction(action);
894}
895
896/*!
897    Adds the given \a toolBar to the manager's toolbar list.
898
899    All the \a toolBar's actions are automatically added to the given
900    \a category in the manager's list of actions if they're not
901    already there. The manager remembers which toolbar the actions
902    belonged to, so, when the \a toolBar is removed, its actions will
903    be removed as well.
904
905    Custom toolbars are created with the main window returned by
906    the mainWindow() function, as its parent.
907
908    \sa removeToolBar()
909*/
910void QtToolBarManager::addToolBar(QToolBar *toolBar, const QString &category)
911{
912    d_ptr->manager->addDefaultToolBar(toolBar, category);
913}
914
915/*!
916    Removes the specified \a toolBar from the manager's list. All the
917    actions that existed in the specified \a toolBar when it was
918    added are removed as well.
919
920    \sa addToolBar()
921*/
922void QtToolBarManager::removeToolBar(QToolBar *toolBar)
923{
924    d_ptr->manager->removeDefaultToolBar(toolBar);
925}
926
927/*!
928    Returns the manager's toolbar list.
929*/
930QList<QToolBar *> QtToolBarManager::toolBars() const
931{
932    return d_ptr->manager->toolBarsActions().keys();
933}
934
935/*
936void QtToolBarManager::resetToolBar(QToolBar *toolBar)
937{
938    d_ptr->manager->resetToolBar(toolBar);
939}
940
941void QtToolBarManager::resetAllToolBars()
942{
943    d_ptr->manager->resetAllToolBars();
944}
945*/
946
947/*!
948    Saves the state of the toolbar manager's toolbars. The \a version
949    number is stored as part of the data.
950
951    Identifies all the QToolBar and QAction objects by their object
952    name property. Ensure that this property is unique for each
953    QToolBar and QAction that you add using the QtToolBarManager.
954
955    Returns an identifier for the state which can be passed along with
956    the version number to the restoreState() function to restore the
957    saved state.
958
959    \sa restoreState()
960*/
961QByteArray QtToolBarManager::saveState(int version) const
962{
963    return d_ptr->manager->saveState(version);
964}
965
966/*!
967    Restores the saved state of the toolbar manager's toolbars.  The
968    \a version number is compared with the version number of the
969    stored \a state.
970
971    Returns true if the version numbers are matching and the toolbar
972    manager's state is restored; otherwise the toolbar manager's state
973    is left unchanged and the function returns false.
974
975    Note that the state of the toolbar manager's toolbars should be
976    restored before restoring the state of the main window's toolbars
977    and dockwidgets using the QMainWindow::restoreState() function. In
978    that way the restoreState() function can create the custom
979    toolbars before the QMainWindow::restoreState() function restores
980    the custom toolbars' positions.
981
982    \sa saveState()
983*/
984bool QtToolBarManager::restoreState(const QByteArray &state, int version)
985{
986    return d_ptr->manager->restoreState(state, version);
987}
988
989//////////////////////
990
991class ToolBarItem {
992public:
993    ToolBarItem() : tb(0) {}
994    ToolBarItem(QToolBar *toolBar) : tb(toolBar) {}
995    ToolBarItem(QToolBar *toolBar, const QString &toolBarName)
996            : tb(toolBar), tbName(toolBarName) {}
997    ToolBarItem(const QString &toolBarName) : tb(0), tbName(toolBarName) {}
998    QToolBar *toolBar() const
999        { return tb; }
1000    void setToolBar(QToolBar *toolBar)
1001        { tb = toolBar; }
1002    QString toolBarName() const
1003        { return tbName; }
1004    void setToolBarName(const QString &toolBarName)
1005        { tbName = toolBarName; }
1006private:
1007    QToolBar *tb;
1008    QString tbName;
1009};
1010
1011class QtToolBarDialogPrivate {
1012    QtToolBarDialog *q_ptr;
1013    Q_DECLARE_PUBLIC(QtToolBarDialog)
1014public:
1015    QtToolBarDialogPrivate()
1016        : toolBarManager(0),
1017          currentAction(0),
1018          currentToolBar(0)
1019          { }
1020
1021    ToolBarItem *createItem(QToolBar *toolBar);
1022    ToolBarItem *createItem(const QString &toolBarName);
1023    void deleteItem(ToolBarItem *item);
1024
1025    void newClicked();
1026    void removeClicked();
1027    void defaultClicked();
1028    void okClicked();
1029    void applyClicked();
1030    void cancelClicked();
1031    void upClicked();
1032    void downClicked();
1033    void leftClicked();
1034    void rightClicked();
1035    void renameClicked();
1036    void toolBarRenamed(QListWidgetItem *item);
1037    void currentActionChanged(QTreeWidgetItem *current);
1038    void currentToolBarChanged(QListWidgetItem *current);
1039    void currentToolBarActionChanged(QListWidgetItem *current);
1040
1041    void removeToolBar(ToolBarItem *item);
1042    bool isDefaultToolBar(ToolBarItem *item) const;
1043    void setButtons();
1044    void clearOld();
1045    void fillNew();
1046    QtFullToolBarManager *toolBarManager;
1047    QMap<ToolBarItem *, QList<QAction *> > currentState;
1048    QMap<QToolBar *, ToolBarItem *> toolBarItems;
1049    QSet<ToolBarItem *> createdItems;
1050    QSet<ToolBarItem *> removedItems;
1051
1052    QSet<ToolBarItem *> allToolBarItems;
1053
1054    // static
1055    QTreeWidgetItem *currentAction;
1056    QMap<QAction *, QTreeWidgetItem *> actionToItem;
1057    QMap<QTreeWidgetItem *, QAction *> itemToAction;
1058
1059    // dynamic
1060    ToolBarItem *currentToolBar;
1061    QMap<ToolBarItem *, QListWidgetItem *> toolBarToItem;
1062    QMap<QListWidgetItem *, ToolBarItem *> itemToToolBar;
1063
1064    // dynamic
1065    QMap<QAction *, QListWidgetItem *> actionToCurrentItem;
1066    QMap<QListWidgetItem *, QAction *> currentItemToAction;
1067
1068    QMap<QAction *, ToolBarItem *> widgetActionToToolBar;
1069    QMap<ToolBarItem *, QSet<QAction *> > toolBarToWidgetActions;
1070
1071    QString separatorText;
1072    Ui::QtToolBarDialog ui;
1073};
1074
1075ToolBarItem *QtToolBarDialogPrivate::createItem(QToolBar *toolBar)
1076{
1077    if (!toolBar)
1078        return 0;
1079    ToolBarItem *item = new ToolBarItem(toolBar, toolBar->windowTitle());
1080    allToolBarItems.insert(item);
1081    return item;
1082}
1083
1084ToolBarItem *QtToolBarDialogPrivate::createItem(const QString &toolBarName)
1085{
1086    ToolBarItem *item = new ToolBarItem(toolBarName);
1087    allToolBarItems.insert(item);
1088    return item;
1089}
1090
1091void QtToolBarDialogPrivate::deleteItem(ToolBarItem *item)
1092{
1093    if (!allToolBarItems.contains(item))
1094        return;
1095    allToolBarItems.remove(item);
1096    delete item;
1097}
1098
1099void QtToolBarDialogPrivate::clearOld()
1100{
1101    ui.actionTree->clear();
1102    ui.toolBarList->clear();
1103    ui.currentToolBarList->clear();
1104    ui.removeButton->setEnabled(false);
1105    ui.newButton->setEnabled(false);
1106    ui.upButton->setEnabled(false);
1107    ui.downButton->setEnabled(false);
1108    ui.leftButton->setEnabled(false);
1109    ui.rightButton->setEnabled(false);
1110
1111    actionToItem.clear();
1112    itemToAction.clear();
1113    toolBarToItem.clear();
1114    itemToToolBar.clear();
1115    actionToCurrentItem.clear();
1116    currentItemToAction.clear();
1117    widgetActionToToolBar.clear();
1118    toolBarToWidgetActions.clear();
1119
1120    toolBarItems.clear();
1121    currentState.clear();
1122    createdItems.clear();
1123    removedItems.clear();
1124    QSetIterator<ToolBarItem *> itItem(allToolBarItems);
1125    while (itItem.hasNext())
1126        delete itItem.next();
1127    allToolBarItems.clear();
1128
1129    currentToolBar = 0;
1130    currentAction = 0;
1131}
1132
1133void QtToolBarDialogPrivate::fillNew()
1134{
1135    if (!toolBarManager)
1136        return;
1137
1138    QTreeWidgetItem *item = new QTreeWidgetItem(ui.actionTree);
1139    item->setText(0, separatorText);
1140    ui.actionTree->setCurrentItem(item);
1141    currentAction = item;
1142    actionToItem.insert(0, item);
1143    itemToAction.insert(item, 0);
1144    QStringList categories = toolBarManager->categories();
1145    QStringListIterator itCategory(categories);
1146    while (itCategory.hasNext()) {
1147        QString category = itCategory.next();
1148        QTreeWidgetItem *categoryItem = new QTreeWidgetItem(ui.actionTree);
1149        categoryItem->setText(0, category);
1150        QList<QAction *> actions = toolBarManager->categoryActions(category);
1151        QListIterator<QAction *> itAction(actions);
1152        while (itAction.hasNext()) {
1153            QAction *action = itAction.next();
1154            item = new QTreeWidgetItem(categoryItem);
1155            item->setText(0, action->text());
1156            item->setIcon(0, action->icon());
1157            item->setTextAlignment(0, Qt::AlignLeft | Qt::AlignVCenter | Qt::TextShowMnemonic);
1158            actionToItem.insert(action, item);
1159            itemToAction.insert(item, action);
1160            if (toolBarManager->isWidgetAction(action)) {
1161                item->setData(0, Qt::TextColorRole, QColor(Qt::blue));
1162                widgetActionToToolBar.insert(action, 0);
1163            }
1164            item->setFlags(item->flags() | Qt::ItemIsDragEnabled);
1165        }
1166        ui.actionTree->setItemExpanded(categoryItem, true);
1167    }
1168    //ui.actionTree->sortItems(0, Qt::AscendingOrder);
1169
1170    QMap<QToolBar *, QList<QAction *> > toolBars = toolBarManager->toolBarsActions();
1171    QMap<QToolBar *, QList<QAction *> >::ConstIterator it = toolBars.constBegin();
1172    while (it != toolBars.constEnd()) {
1173        QToolBar *toolBar = it.key();
1174        ToolBarItem *tbItem = createItem(toolBar);
1175        toolBarItems.insert(toolBar, tbItem);
1176        QListWidgetItem *item = new QListWidgetItem(toolBar->windowTitle(),
1177                ui.toolBarList);
1178        toolBarToItem.insert(tbItem, item);
1179        itemToToolBar.insert(item, tbItem);
1180        QList<QAction *> actions = it.value();
1181        QListIterator<QAction *> itAction(actions);
1182        while (itAction.hasNext()) {
1183            QAction *action = itAction.next();
1184            if (toolBarManager->isWidgetAction(action)) {
1185                widgetActionToToolBar.insert(action, tbItem);
1186                toolBarToWidgetActions[tbItem].insert(action);
1187            }
1188        }
1189        currentState.insert(tbItem, actions);
1190        if (it == toolBars.constBegin())
1191            ui.toolBarList->setCurrentItem(item);
1192        if (isDefaultToolBar(tbItem))
1193            item->setData(Qt::TextColorRole, QColor(Qt::darkGreen));
1194        else
1195            item->setFlags(item->flags() | Qt::ItemIsEditable);
1196
1197        it++;
1198    }
1199    ui.toolBarList->sortItems();
1200    setButtons();
1201}
1202
1203bool QtToolBarDialogPrivate::isDefaultToolBar(ToolBarItem *item) const
1204{
1205    if (!item)
1206        return false;
1207    if (!item->toolBar())
1208        return false;
1209    return toolBarManager->isDefaultToolBar(item->toolBar());
1210}
1211
1212void QtToolBarDialogPrivate::setButtons()
1213{
1214    bool newEnabled = false;
1215    bool removeEnabled = false;
1216    bool renameEnabled = false;
1217    bool upEnabled = false;
1218    bool downEnabled = false;
1219    bool leftEnabled = false;
1220    bool rightEnabled = false;
1221
1222    if (toolBarManager) {
1223        newEnabled = true;
1224        removeEnabled = !isDefaultToolBar(currentToolBar);
1225        renameEnabled = removeEnabled;
1226        QListWidgetItem *currentToolBarAction = ui.currentToolBarList->currentItem();
1227        if (currentToolBarAction) {
1228            int row = ui.currentToolBarList->row(currentToolBarAction);
1229            upEnabled = row > 0;
1230            downEnabled = row < ui.currentToolBarList->count() - 1;
1231            leftEnabled = true;
1232        }
1233        if (currentAction && currentToolBar)
1234            rightEnabled = true;
1235    }
1236    ui.newButton->setEnabled(newEnabled);
1237    ui.removeButton->setEnabled(removeEnabled);
1238    ui.renameButton->setEnabled(renameEnabled);
1239    ui.upButton->setEnabled(upEnabled);
1240    ui.downButton->setEnabled(downEnabled);
1241    ui.leftButton->setEnabled(leftEnabled);
1242    ui.rightButton->setEnabled(rightEnabled);
1243}
1244
1245void QtToolBarDialogPrivate::newClicked()
1246{
1247    QString toolBarName = q_ptr->tr("Custom Toolbar"); // = QInputDialog::getString();
1248    // produce unique name
1249    ToolBarItem *item = createItem(toolBarName);
1250    currentState.insert(item, QList<QAction *>());
1251    createdItems.insert(item);
1252    QListWidgetItem *i = new QListWidgetItem(toolBarName, ui.toolBarList);
1253    i->setFlags(i->flags() | Qt::ItemIsEditable);
1254    ui.toolBarList->setCurrentItem(i);
1255    itemToToolBar.insert(i, item);
1256    toolBarToItem.insert(item, i);
1257    ui.toolBarList->sortItems();
1258    ui.toolBarList->setCurrentItem(i);
1259    currentToolBarChanged(i);
1260    renameClicked();
1261}
1262
1263void QtToolBarDialogPrivate::removeToolBar(ToolBarItem *item)
1264{
1265    if (!item)
1266        return;
1267    if (item->toolBar() && toolBarManager->isDefaultToolBar(item->toolBar()))
1268        return;
1269    if (!toolBarToItem.contains(item))
1270        return;
1271    QListWidgetItem *i = toolBarToItem.value(item);
1272    bool wasCurrent = false;
1273    if (i == ui.toolBarList->currentItem())
1274        wasCurrent = true;
1275    int row = ui.toolBarList->row(i);
1276    QMap<ToolBarItem *, QSet<QAction *> >::ConstIterator itToolBar =
1277            toolBarToWidgetActions.find(item);
1278    if (itToolBar != toolBarToWidgetActions.constEnd()) {
1279        QSet<QAction *> actions = itToolBar.value();
1280        QSetIterator<QAction *> itAction(actions);
1281        while (itAction.hasNext()) {
1282            QAction *action = itAction.next();
1283            widgetActionToToolBar.insert(action, 0);
1284        }
1285        toolBarToWidgetActions.remove(item);
1286    }
1287
1288    currentState.remove(item);
1289    createdItems.remove(item);
1290    toolBarToItem.remove(item);
1291    itemToToolBar.remove(i);
1292    delete i;
1293    if (item->toolBar())
1294        removedItems.insert(item);
1295    else
1296        deleteItem(item);
1297    if (wasCurrent) {
1298        if (row == ui.toolBarList->count())
1299            row--;
1300        if (row < 0)
1301            ;
1302        else
1303            ui.toolBarList->setCurrentRow(row);
1304    }
1305    setButtons();
1306}
1307
1308void QtToolBarDialogPrivate::removeClicked()
1309{
1310    QListWidgetItem *i = ui.toolBarList->currentItem();
1311    if (!i)
1312        return;
1313    ToolBarItem *item = itemToToolBar.value(i);
1314    removeToolBar(item);
1315}
1316
1317void QtToolBarDialogPrivate::defaultClicked()
1318{
1319    QMap<QToolBar *, QList<QAction *> > defaultToolBars = toolBarManager->defaultToolBars();
1320    QMap<QToolBar *, QList<QAction *> >::ConstIterator itToolBar = defaultToolBars.constBegin();
1321    while (itToolBar != defaultToolBars.constEnd()) {
1322        QToolBar *toolBar = itToolBar.key();
1323        ToolBarItem *toolBarItem = toolBarItems.value(toolBar);
1324
1325        if (toolBarToWidgetActions.contains(toolBarItem)) {
1326            QSetIterator<QAction *> itAction(toolBarToWidgetActions.value(toolBarItem));
1327            while (itAction.hasNext())
1328                widgetActionToToolBar.insert(itAction.next(), 0);
1329            toolBarToWidgetActions.remove(toolBarItem);
1330        }
1331
1332        currentState.remove(toolBarItem);
1333
1334        QListIterator<QAction *> itAction(itToolBar.value());
1335        while (itAction.hasNext()) {
1336            QAction *action = itAction.next();
1337            if (toolBarManager->isWidgetAction(action)) {
1338                ToolBarItem *otherToolBar = widgetActionToToolBar.value(action);
1339                if (otherToolBar) {
1340                    toolBarToWidgetActions[otherToolBar].remove(action);
1341                    currentState[otherToolBar].removeAll(action);
1342                }
1343                widgetActionToToolBar.insert(action, toolBarItem);
1344                toolBarToWidgetActions[toolBarItem].insert(action);
1345            }
1346        }
1347        currentState.insert(toolBarItem, itToolBar.value());
1348
1349        itToolBar++;
1350    }
1351    currentToolBarChanged(toolBarToItem.value(currentToolBar));
1352
1353    QList<ToolBarItem *> toolBars = currentState.keys();
1354    QListIterator<ToolBarItem *> itTb(toolBars);
1355    while (itTb.hasNext())
1356        removeToolBar(itTb.next());
1357}
1358
1359void QtToolBarDialogPrivate::okClicked()
1360{
1361    applyClicked();
1362    q_ptr->accept();
1363}
1364
1365void QtToolBarDialogPrivate::applyClicked()
1366{
1367    QMap<ToolBarItem *, QList<QAction *> > toolBars = currentState;
1368    QMap<ToolBarItem *, QList<QAction *> >::ConstIterator itToolBar = toolBars.constBegin();
1369    while (itToolBar != toolBars.constEnd()) {
1370        ToolBarItem *item = itToolBar.key();
1371        QToolBar *toolBar = item->toolBar();
1372        if (toolBar) {
1373            toolBarManager->setToolBar(toolBar, itToolBar.value());
1374            toolBar->setWindowTitle(item->toolBarName());
1375        }
1376
1377        itToolBar++;
1378    }
1379
1380    QSet<ToolBarItem *> toRemove = removedItems;
1381    QSetIterator<ToolBarItem *> itRemove(toRemove);
1382    while (itRemove.hasNext()) {
1383        ToolBarItem *item = itRemove.next();
1384        QToolBar *toolBar = item->toolBar();
1385        removedItems.remove(item);
1386        currentState.remove(item);
1387        deleteItem(item);
1388        if (toolBar)
1389            toolBarManager->deleteToolBar(toolBar);
1390    }
1391
1392    QSet<ToolBarItem *> toCreate = createdItems;
1393    QSetIterator<ToolBarItem *> itCreate(toCreate);
1394    while (itCreate.hasNext()) {
1395        ToolBarItem *item = itCreate.next();
1396        QString toolBarName = item->toolBarName();
1397        createdItems.remove(item);
1398        QList<QAction *> actions = currentState.value(item);
1399        QToolBar *toolBar = toolBarManager->createToolBar(toolBarName);
1400        item->setToolBar(toolBar);
1401        toolBarManager->setToolBar(toolBar, actions);
1402    }
1403}
1404
1405void QtToolBarDialogPrivate::upClicked()
1406{
1407    QListWidgetItem *currentToolBarAction = ui.currentToolBarList->currentItem();
1408    if (!currentToolBarAction)
1409        return;
1410    int row = ui.currentToolBarList->row(currentToolBarAction);
1411    if (row == 0)
1412        return;
1413    ui.currentToolBarList->takeItem(row);
1414    int newRow = row - 1;
1415    ui.currentToolBarList->insertItem(newRow, currentToolBarAction);
1416    QList<QAction *> actions = currentState.value(currentToolBar);
1417    QAction *action = actions.at(row);
1418    actions.removeAt(row);
1419    actions.insert(newRow, action);
1420    currentState.insert(currentToolBar, actions);
1421    ui.currentToolBarList->setCurrentItem(currentToolBarAction);
1422    setButtons();
1423}
1424
1425void QtToolBarDialogPrivate::downClicked()
1426{
1427    QListWidgetItem *currentToolBarAction = ui.currentToolBarList->currentItem();
1428    if (!currentToolBarAction)
1429        return;
1430    int row = ui.currentToolBarList->row(currentToolBarAction);
1431    if (row == ui.currentToolBarList->count() - 1)
1432        return;
1433    ui.currentToolBarList->takeItem(row);
1434    int newRow = row + 1;
1435    ui.currentToolBarList->insertItem(newRow, currentToolBarAction);
1436    QList<QAction *> actions = currentState.value(currentToolBar);
1437    QAction *action = actions.at(row);
1438    actions.removeAt(row);
1439    actions.insert(newRow, action);
1440    currentState.insert(currentToolBar, actions);
1441    ui.currentToolBarList->setCurrentItem(currentToolBarAction);
1442    setButtons();
1443}
1444
1445void QtToolBarDialogPrivate::leftClicked()
1446{
1447    QListWidgetItem *currentToolBarAction = ui.currentToolBarList->currentItem();
1448    if (!currentToolBarAction)
1449        return;
1450    int row = ui.currentToolBarList->row(currentToolBarAction);
1451    currentState[currentToolBar].removeAt(row);
1452    QAction *action = currentItemToAction.value(currentToolBarAction);
1453    if (widgetActionToToolBar.contains(action)) {
1454        ToolBarItem *item = widgetActionToToolBar.value(action);
1455        if (item == currentToolBar) { // have to be
1456            toolBarToWidgetActions[item].remove(action);
1457            if (toolBarToWidgetActions[item].empty())
1458                toolBarToWidgetActions.remove(item);
1459        }
1460        widgetActionToToolBar.insert(action, 0);
1461    }
1462    if (action)
1463        actionToCurrentItem.remove(action);
1464    currentItemToAction.remove(currentToolBarAction);
1465    delete currentToolBarAction;
1466    if (row == ui.currentToolBarList->count())
1467        row--;
1468    if (row >= 0) {
1469        QListWidgetItem *item = ui.currentToolBarList->item(row);
1470        ui.currentToolBarList->setCurrentItem(item);
1471    }
1472    setButtons();
1473}
1474
1475void QtToolBarDialogPrivate::rightClicked()
1476{
1477    if (!currentAction)
1478        return;
1479    if (!currentToolBar)
1480        return;
1481    QListWidgetItem *currentToolBarAction = ui.currentToolBarList->currentItem();
1482
1483    QAction *action = itemToAction.value(currentAction);
1484    QListWidgetItem *item = 0;
1485    if (action) {
1486        if (currentState[currentToolBar].contains(action)) {
1487            item = actionToCurrentItem.value(action);
1488            if (item == currentToolBarAction)
1489                return;
1490            int row = ui.currentToolBarList->row(item);
1491            ui.currentToolBarList->takeItem(row);
1492            currentState[currentToolBar].removeAt(row);
1493            // only reorder here
1494        } else {
1495            item = new QListWidgetItem(action->text());
1496            item->setIcon(action->icon());
1497            item->setTextAlignment(Qt::AlignLeft | Qt::AlignVCenter | Qt::TextShowMnemonic);
1498            currentItemToAction.insert(item, action);
1499            actionToCurrentItem.insert(action, item);
1500            if (widgetActionToToolBar.contains(action)) {
1501                item->setData(Qt::TextColorRole, QColor(Qt::blue));
1502                ToolBarItem *toolBar = widgetActionToToolBar.value(action);
1503                if (toolBar) {
1504                    currentState[toolBar].removeAll(action);
1505                    toolBarToWidgetActions[toolBar].remove(action);
1506                    if (toolBarToWidgetActions[toolBar].empty())
1507                        toolBarToWidgetActions.remove(toolBar);
1508                }
1509                widgetActionToToolBar.insert(action, currentToolBar);
1510                toolBarToWidgetActions[currentToolBar].insert(action);
1511            }
1512        }
1513    } else {
1514        item = new QListWidgetItem(separatorText);
1515        currentItemToAction.insert(item, 0);
1516    }
1517
1518    int row = ui.currentToolBarList->count();
1519    if (currentToolBarAction) {
1520        row = ui.currentToolBarList->row(currentToolBarAction) + 1;
1521    }
1522    ui.currentToolBarList->insertItem(row, item);
1523    currentState[currentToolBar].insert(row, action);
1524    ui.currentToolBarList->setCurrentItem(item);
1525
1526    setButtons();
1527}
1528
1529void QtToolBarDialogPrivate::renameClicked()
1530{
1531    if (!currentToolBar)
1532        return;
1533
1534    QListWidgetItem *item = toolBarToItem.value(currentToolBar);
1535    ui.toolBarList->editItem(item);
1536}
1537
1538void QtToolBarDialogPrivate::toolBarRenamed(QListWidgetItem *item)
1539{
1540    if (!currentToolBar)
1541        return;
1542
1543    ToolBarItem *tbItem = itemToToolBar.value(item);
1544    if (!tbItem)
1545        return;
1546    tbItem->setToolBarName(item->text());
1547    //ui.toolBarList->sortItems();
1548}
1549
1550void QtToolBarDialogPrivate::currentActionChanged(QTreeWidgetItem *current)
1551{
1552    if (itemToAction.contains(current))
1553        currentAction = current;
1554    else
1555        currentAction = NULL;
1556    setButtons();
1557}
1558
1559void QtToolBarDialogPrivate::currentToolBarChanged(QListWidgetItem *current)
1560{
1561    currentToolBar = itemToToolBar.value(current);
1562    ui.currentToolBarList->clear();
1563    actionToCurrentItem.clear();
1564    currentItemToAction.clear();
1565    setButtons();
1566    if (!currentToolBar) {
1567        return;
1568    }
1569    QList<QAction *> actions = currentState.value(currentToolBar);
1570    QListIterator<QAction *> itAction(actions);
1571    QListWidgetItem *first = 0;
1572    while (itAction.hasNext()) {
1573        QAction *action = itAction.next();
1574        QString actionName = separatorText;
1575        if (action)
1576            actionName = action->text();
1577        QListWidgetItem *item = new QListWidgetItem(actionName, ui.currentToolBarList);
1578        if (action) {
1579            item->setIcon(action->icon());
1580            item->setTextAlignment(Qt::AlignLeft | Qt::AlignVCenter | Qt::TextShowMnemonic);
1581            actionToCurrentItem.insert(action, item);
1582            if (widgetActionToToolBar.contains(action))
1583                item->setData(Qt::TextColorRole, QColor(Qt::blue));
1584        }
1585        currentItemToAction.insert(item, action);
1586        if (!first)
1587            first = item;
1588    }
1589    if (first)
1590        ui.currentToolBarList->setCurrentItem(first);
1591}
1592
1593void QtToolBarDialogPrivate::currentToolBarActionChanged(QListWidgetItem *)
1594{
1595    setButtons();
1596}
1597
1598void QtToolBarDialogPrivate::cancelClicked()
1599{
1600    // just nothing
1601    q_ptr->reject();
1602}
1603
1604//////////////////////
1605/*
1606class FeedbackItemDelegate : public QItemDelegate
1607{
1608    Q_OBJECT
1609public:
1610    FeedbackItemDelegate(QObject *parent = 0) : QItemDelegate(parent) { }
1611
1612    virtual void paint(QPainter *painter, const QStyleOptionViewItem &option,
1613                    const QModelIndex & index) const;
1614    virtual QSize sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const;
1615};
1616
1617void FeedbackItemDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option,
1618                            const QModelIndex &index) const
1619{
1620    if ()
1621    painter->save();
1622    QRect r = option.rect;
1623    float yCentral = r.height() / 2.0;
1624    float margin = 2.0;
1625    float arrowWidth = 5.0;
1626    float width = 20;
1627    qDebug("rect: x %d, y %d, w %d, h %d", r.x(), r.y(), r.width(), r.height());
1628    QLineF lineBase(0.0 + margin, r.y() + yCentral, width - margin, r.y() + yCentral);
1629    QLineF lineArrowLeft(width - margin - arrowWidth, r.y() + yCentral - arrowWidth,
1630                    width - margin, r.y() + yCentral);
1631    QLineF lineArrowRight(width - margin - arrowWidth, r.y() + yCentral + arrowWidth,
1632                    width - margin, r.y() + yCentral);
1633    painter->drawLine(lineBase);
1634    painter->drawLine(lineArrowLeft);
1635    painter->drawLine(lineArrowRight);
1636    painter->translate(QPoint(width, 0));
1637    QItemDelegate::paint(painter, option, index);
1638    painter->restore();
1639}
1640
1641QSize FeedbackItemDelegate::sizeHint(const QStyleOptionViewItem &option,
1642            const QModelIndex &index) const
1643{
1644    //return QItemDelegate::sizeHint(option, index);
1645    QSize s = QItemDelegate::sizeHint(option, index);
1646    s.setWidth(s.width() - 20);
1647    return s;
1648}
1649
1650class QtToolBarListWidget : public QListWidget
1651{
1652    Q_OBJECT
1653public:
1654    QtToolBarListWidget(QWidget *parent) : QListWidget(parent), actionDrag(false) {}
1655
1656protected:
1657    void startDrag(Qt::DropActions supportedActions);
1658
1659    void dragEnterEvent(QDragEnterEvent *event);
1660    void dragMoveEvent(QDragMoveEvent *event);
1661    void dragLeaveEvent(QDragLeaveEvent *);
1662    void dropEvent(QDropEvent *event);
1663
1664    void setDragAction(const QString *action) { actionName = action; }
1665private:
1666    QPersistentModelIndex lastDropIndicator;
1667    QString actionName;
1668    bool actionDrag;
1669};
1670
1671void QtToolBarListWidget::startDrag(Qt::DropActions supportedActions)
1672{
1673    QListWidgetItem *item = currentItem();
1674    if (item) {
1675        actionName = QString();
1676        emit aboutToDrag(item);
1677        if (!actionName.isEmpty()) {
1678            QDrag *drag = new QDrag(this);
1679            QMimeData *data = new QMimeData;
1680            data->setData("action", actionName.toLocal8Bit().constData());
1681            drag->setMimeData(data);
1682            drag->start(supportedActions);
1683        }
1684    }
1685}
1686
1687void QtToolBarListWidget::dragEnterEvent(QDragEnterEvent *event)
1688{
1689    const QMimeData *mime = event->mimeData();
1690    actionDrag = mime->hasFormat("action");
1691    if (actionDrag)
1692        event->accept();
1693    else
1694        event->ignore();
1695}
1696
1697void QtToolBarListWidget::dragMoveEvent(QDragMoveEvent *event)
1698{
1699    event->ignore();
1700    if (actionDrag) {
1701        QPoint p = event->pos();
1702        QListWidgetItem *item = itemAt(p);
1703        Indicator indic = QtToolBarListWidget::None;
1704        if (item) {
1705            QRect rect = visualItemRect(item);
1706            if (p.y() - rect.top() < rect.height() / 2)
1707                indic = QtToolBarListWidget::Above;
1708            else
1709                indic = QtToolBarListWidget::Below;
1710        }
1711        setIndicator(item, indic);
1712        event->accept();
1713    }
1714}
1715
1716void QtToolBarListWidget::dragLeaveEvent(QDragLeaveEvent *)
1717{
1718    if (actionDrag) {
1719        actionDrag = false;
1720        setIndicator(item, QtToolBarListWidget::None);
1721    }
1722}
1723
1724void QtToolBarListWidget::dropEvent(QDropEvent *event)
1725{
1726    if (actionDrag) {
1727        QListWidgetItem *item = indicatorItem();
1728        Indicator indic = indicator();
1729        QByteArray array = event->mimeData()->data("action");
1730        QDataStream stream(&array, QIODevice::ReadOnly);
1731        QString action;
1732        stream >> action;
1733        emit actionDropped(action, item, );
1734
1735        actionDrag = false;
1736        setIndicator(item, QtToolBarListWidget::None);
1737    }
1738}
1739*/
1740
1741/*! \class QtToolBarDialog
1742
1743    \brief The QtToolBarDialog class provides a dialog for customizing
1744    toolbars.
1745
1746    QtToolBarDialog allows the user to customize the toolbars for a
1747    given main window.
1748
1749    \image qttoolbardialog.png
1750
1751    The dialog lets the users add, rename and remove custom toolbars.
1752    Note that built-in toolbars are marked with a green color, and
1753    cannot be removed or renamed.
1754
1755    The users can also add and remove actions from the toolbars. An
1756    action can be added to many toolbars, but a toolbar can only
1757    contain one instance of each action. Actions that contains a
1758    widget are marked with a blue color in the list of actions, and
1759    can only be added to one single toolbar.
1760
1761    Finally, the users can add separators to the toolbars.
1762
1763    The original toolbars can be restored by clicking the \gui
1764    {Restore all} button. All custom toolbars will then be removed,
1765    and all built-in toolbars will be restored to their original state.
1766
1767    The QtToolBarDialog class's functionality is controlled by an
1768    instance of the QtToolBarManager class, and the main window is
1769    specified using the QtToolBarManager::setMainWindow() function.
1770
1771    All you need to do to use QtToolBarDialog is to specify an
1772    QtToolBarManager instance and call the QDialog::exec() slot:
1773
1774    \code
1775    QtToolBarManager *toolBarManager;
1776
1777    void MyMainWindow::customize()
1778        {
1779            QtToolBarDialog dialog(this);
1780            dialog.setToolBarManager(toolBarManager);
1781            dialog.exec();
1782        }
1783    \endcode
1784
1785    \sa QtToolBarManager
1786*/
1787
1788/*!
1789    Creates a toolbar dialog with the given \a parent and the specifed
1790    window \a flags.
1791*/
1792QtToolBarDialog::QtToolBarDialog(QWidget *parent, Qt::WFlags flags)
1793    : QDialog(parent, flags)
1794{
1795    d_ptr = new QtToolBarDialogPrivate;
1796    d_ptr->q_ptr = this;
1797    d_ptr->ui.setupUi(this);
1798    d_ptr->separatorText = tr("< S E P A R A T O R >");
1799
1800    d_ptr->ui.actionTree->setColumnCount(1);
1801    d_ptr->ui.actionTree->setRootIsDecorated(false);
1802    d_ptr->ui.actionTree->header()->hide();
1803/*
1804    ui.toolBarList->setEditTriggers(QAbstractItemView::DoubleClicked |
1805                QAbstractItemView::EditKeyPressed);
1806*/
1807
1808//    ui.actionList->setDragEnabled(true);
1809//    FeedbackItemDelegate *del = new FeedbackItemDelegate(this);
1810//    ui.currentToolBarList->setItemDelegate(del);
1811//    ui.currentToolBarList->setAcceptDrops(true);
1812
1813        d_ptr->ui.upButton->setIcon(QIcon(":/images/icons/go-up.png"));
1814        d_ptr->ui.downButton->setIcon(QIcon(":/images/icons/go-down.png"));
1815        d_ptr->ui.leftButton->setIcon(QIcon(":/images/icons/go-previous.png"));
1816        d_ptr->ui.rightButton->setIcon(QIcon(":/images/icons/go-next.png"));
1817        d_ptr->ui.newButton->setIcon(QIcon(":/images/icons/list-add.png"));
1818        d_ptr->ui.removeButton->setIcon(QIcon(":/images/icons/list-remove.png"));
1819
1820    connect(d_ptr->ui.newButton, SIGNAL(clicked()), this, SLOT(newClicked()));
1821    connect(d_ptr->ui.removeButton, SIGNAL(clicked()), this, SLOT(removeClicked()));
1822    connect(d_ptr->ui.renameButton, SIGNAL(clicked()), this, SLOT(renameClicked()));
1823        connect(d_ptr->ui.buttonBox->button(QDialogButtonBox::RestoreDefaults), SIGNAL(clicked()), this, SLOT(defaultClicked()));
1824        connect(d_ptr->ui.buttonBox->button(QDialogButtonBox::Save), SIGNAL(clicked()), this, SLOT(okClicked()));
1825        connect(d_ptr->ui.buttonBox->button(QDialogButtonBox::Apply), SIGNAL(clicked()), this, SLOT(applyClicked()));
1826        connect(d_ptr->ui.buttonBox->button(QDialogButtonBox::Close), SIGNAL(clicked()), this, SLOT(cancelClicked()));
1827    connect(d_ptr->ui.upButton, SIGNAL(clicked()), this, SLOT(upClicked()));
1828    connect(d_ptr->ui.downButton, SIGNAL(clicked()), this, SLOT(downClicked()));
1829    connect(d_ptr->ui.leftButton, SIGNAL(clicked()), this, SLOT(leftClicked()));
1830    connect(d_ptr->ui.rightButton, SIGNAL(clicked()), this, SLOT(rightClicked()));
1831
1832    connect(d_ptr->ui.actionTree, SIGNAL(currentItemChanged(QTreeWidgetItem *, QTreeWidgetItem *)),
1833                    this, SLOT(currentActionChanged(QTreeWidgetItem *)));
1834    connect(d_ptr->ui.toolBarList, SIGNAL(currentItemChanged(QListWidgetItem *, QListWidgetItem *)),
1835                    this, SLOT(currentToolBarChanged(QListWidgetItem *)));
1836    connect(d_ptr->ui.currentToolBarList,
1837                    SIGNAL(currentItemChanged(QListWidgetItem *, QListWidgetItem *)),
1838                    this, SLOT(currentToolBarActionChanged(QListWidgetItem *)));
1839
1840    connect(d_ptr->ui.actionTree, SIGNAL(itemDoubleClicked(QTreeWidgetItem *, int)),
1841                    this, SLOT(rightClicked()));
1842    connect(d_ptr->ui.currentToolBarList, SIGNAL(itemDoubleClicked(QListWidgetItem *)),
1843                    this, SLOT(leftClicked()));
1844    connect(d_ptr->ui.toolBarList, SIGNAL(itemChanged(QListWidgetItem *)),
1845                    this, SLOT(toolBarRenamed(QListWidgetItem *)));
1846}
1847
1848/*!
1849    Destroys the toolbar dialog.
1850*/
1851QtToolBarDialog::~QtToolBarDialog()
1852{
1853    d_ptr->clearOld();
1854    delete d_ptr;
1855}
1856
1857/*!
1858    Connects the toolbar dialog to the given \a toolBarManager. Then,
1859    when exec() is called, the toolbar dialog will operate using the
1860    given \a toolBarManager.
1861*/
1862void QtToolBarDialog::setToolBarManager(QtToolBarManager *toolBarManager)
1863{
1864    if (d_ptr->toolBarManager == toolBarManager->d_ptr->manager)
1865        return;
1866    if (isVisible())
1867        d_ptr->clearOld();
1868    d_ptr->toolBarManager = toolBarManager->d_ptr->manager;
1869    if (isVisible())
1870        d_ptr->fillNew();
1871}
1872
1873/*!
1874    \reimp
1875*/
1876void QtToolBarDialog::showEvent(QShowEvent *event)
1877{
1878    if (!event->spontaneous())
1879        d_ptr->fillNew();
1880}
1881
1882/*!
1883    \reimp
1884*/
1885void QtToolBarDialog::hideEvent(QHideEvent *event)
1886{
1887    if (!event->spontaneous())
1888        d_ptr->clearOld();
1889}
1890
1891#include "moc_qttoolbardialog.cpp"
1892#include "qttoolbardialog.moc"
Note: See TracBrowser for help on using the repository browser.