1 /****************************************************************************
2 **
3 ** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
4 ** All rights reserved.
5 ** Contact: Nokia Corporation (qt-info@nokia.com)
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 qt-info@nokia.com.
44 **
45 ****************************************************************************/
46
47 #include "qttoolbardialog.h"
48 #include "ui_qttoolbardialog.h"
49 #include <QtCore/QSet>
50 #include <QAction>
51 #include <QToolBar>
52 #include <QMainWindow>
53 #include <QShowEvent>
54 #include <QHideEvent>
55 #include <QHeaderView>
56
57 class QtFullToolBarManagerPrivate
58 {
59 class QtFullToolBarManager *q_ptr;
60 Q_DECLARE_PUBLIC(QtFullToolBarManager)
61
62 public:
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
99 class QtFullToolBarManager : public QObject
100 {
101 Q_OBJECT
102 public:
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
146 public slots:
147
148 void resetToolBar(QToolBar *toolBar);
149 void resetAllToolBars();
150
151 signals:
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
163 private:
164 QtFullToolBarManagerPrivate *d_ptr;
165 Q_DECLARE_PRIVATE(QtFullToolBarManager)
166 Q_DISABLE_COPY(QtFullToolBarManager)
167 };
168
169
QtFullToolBarManagerPrivate()170 QtFullToolBarManagerPrivate::QtFullToolBarManagerPrivate()
171 : theMainWindow(0)
172 {
173 }
174
toolBarWidgetAction(QAction * action) const175 QToolBar *QtFullToolBarManagerPrivate::toolBarWidgetAction(QAction *action) const
176 {
177 if (widgetActions.contains(action))
178 return widgetActions.value(action);
179 return 0;
180 }
181
removeWidgetActions(const QMap<QToolBar *,QList<QAction * >> & actions)182 void 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
saveState(QDataStream & stream) const218 void 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
restoreState(QDataStream & stream) const289 bool 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
findDefaultToolBar(const QString & objectName) const371 QToolBar *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
findAction(const QString & actionName) const402 QAction *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
toolBarByName(const QString & toolBarName) const429 QToolBar *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
QtFullToolBarManager(QObject * parent)444 QtFullToolBarManager::QtFullToolBarManager(QObject *parent)
445 : QObject(parent)
446 {
447 d_ptr = new QtFullToolBarManagerPrivate;
448 d_ptr->q_ptr = this;
449 }
450
~QtFullToolBarManager()451 QtFullToolBarManager::~QtFullToolBarManager()
452 {
453 delete d_ptr;
454 }
455
setMainWindow(QMainWindow * mainWindow)456 void QtFullToolBarManager::setMainWindow(QMainWindow *mainWindow)
457 {
458 d_ptr->theMainWindow = mainWindow;
459 }
460
mainWindow() const461 QMainWindow *QtFullToolBarManager::mainWindow() const
462 {
463 return d_ptr->theMainWindow;
464 }
465
addCategory(const QString & category)466 void QtFullToolBarManager::addCategory(const QString &category)
467 {
468 d_ptr->categoryToActions[category] = QList<QAction *>();
469 }
470
hasCategory(const QString & category) const471 bool QtFullToolBarManager::hasCategory(const QString &category) const
472 {
473 return d_ptr->categoryToActions.contains(category);
474 }
475
categories() const476 QStringList QtFullToolBarManager::categories() const
477 {
478 return d_ptr->categoryToActions.keys();
479 }
480
categoryActions(const QString & category) const481 QList<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
actionCategory(QAction * action) const490 QString 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
addAction(QAction * action,const QString & category)498 void 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
removeAction(QAction * action)518 void 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
actions() const556 QSet<QAction *> QtFullToolBarManager::actions() const
557 {
558 return d_ptr->allActions;
559 }
560
isWidgetAction(QAction * action) const561 bool QtFullToolBarManager::isWidgetAction(QAction *action) const
562 {
563 if (d_ptr->widgetActions.contains(action))
564 return true;
565 return false;
566 }
567
addDefaultToolBar(QToolBar * toolBar,const QString & category)568 void 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
removeDefaultToolBar(QToolBar * toolBar)600 void 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
defaultToolBars() const625 QMap<QToolBar *, QList<QAction *> > QtFullToolBarManager::defaultToolBars() const
626 {
627 return d_ptr->defaultToolBars;
628 }
629
isDefaultToolBar(QToolBar * toolBar) const630 bool QtFullToolBarManager::isDefaultToolBar(QToolBar *toolBar) const
631 {
632 if (d_ptr->defaultToolBars.contains(toolBar))
633 return true;
634 return false;
635 }
636
createToolBar(const QString & toolBarName)637 QToolBar *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
deleteToolBar(QToolBar * toolBar)656 void 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
actions(QToolBar * toolBar) const670 QList<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
setToolBars(const QMap<QToolBar *,QList<QAction * >> & actions)677 void 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
setToolBar(QToolBar * toolBar,const QList<QAction * > & actions)686 void 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
toolBarsActions() const748 QMap<QToolBar *, QList<QAction *> > QtFullToolBarManager::toolBarsActions() const
749 {
750 return d_ptr->toolBars;
751 }
752
resetToolBar(QToolBar * toolBar)753 void QtFullToolBarManager::resetToolBar(QToolBar *toolBar)
754 {
755 if (!isDefaultToolBar(toolBar))
756 return;
757 setToolBar(toolBar, defaultToolBars().value(toolBar));
758 }
759
resetAllToolBars()760 void 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
saveState(int version) const770 QByteArray 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
restoreState(const QByteArray & state,int version)780 bool 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
793 class QtToolBarManagerPrivate
794 {
795 class QtToolBarManager *q_ptr;
796 Q_DECLARE_PUBLIC(QtToolBarManager)
797 public:
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 */
QtToolBarManager(QObject * parent)836 QtToolBarManager::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 */
~QtToolBarManager()848 QtToolBarManager::~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 */
setMainWindow(QMainWindow * mainWindow)857 void QtToolBarManager::setMainWindow(QMainWindow *mainWindow)
858 {
859 d_ptr->manager->setMainWindow(mainWindow);
860 }
861
862 /*!
863 Returns the main window associated this toolbar manager.
864 */
mainWindow() const865 QMainWindow *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 */
addAction(QAction * action,const QString & category)878 void 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 */
removeAction(QAction * action)891 void 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 */
addToolBar(QToolBar * toolBar,const QString & category)910 void 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 */
removeToolBar(QToolBar * toolBar)922 void QtToolBarManager::removeToolBar(QToolBar *toolBar)
923 {
924 d_ptr->manager->removeDefaultToolBar(toolBar);
925 }
926
927 /*!
928 Returns the manager's toolbar list.
929 */
toolBars() const930 QList<QToolBar *> QtToolBarManager::toolBars() const
931 {
932 return d_ptr->manager->toolBarsActions().keys();
933 }
934
935 /*
936 void QtToolBarManager::resetToolBar(QToolBar *toolBar)
937 {
938 d_ptr->manager->resetToolBar(toolBar);
939 }
940
941 void 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 */
saveState(int version) const961 QByteArray 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 */
restoreState(const QByteArray & state,int version)984 bool QtToolBarManager::restoreState(const QByteArray &state, int version)
985 {
986 return d_ptr->manager->restoreState(state, version);
987 }
988
989 //////////////////////
990
991 class ToolBarItem {
992 public:
ToolBarItem()993 ToolBarItem() : tb(0) {}
ToolBarItem(QToolBar * toolBar)994 ToolBarItem(QToolBar *toolBar) : tb(toolBar) {}
ToolBarItem(QToolBar * toolBar,const QString & toolBarName)995 ToolBarItem(QToolBar *toolBar, const QString &toolBarName)
996 : tb(toolBar), tbName(toolBarName) {}
ToolBarItem(const QString & toolBarName)997 ToolBarItem(const QString &toolBarName) : tb(0), tbName(toolBarName) {}
toolBar() const998 QToolBar *toolBar() const
999 { return tb; }
setToolBar(QToolBar * toolBar)1000 void setToolBar(QToolBar *toolBar)
1001 { tb = toolBar; }
toolBarName() const1002 QString toolBarName() const
1003 { return tbName; }
setToolBarName(const QString & toolBarName)1004 void setToolBarName(const QString &toolBarName)
1005 { tbName = toolBarName; }
1006 private:
1007 QToolBar *tb;
1008 QString tbName;
1009 };
1010
1011 class QtToolBarDialogPrivate {
1012 QtToolBarDialog *q_ptr;
1013 Q_DECLARE_PUBLIC(QtToolBarDialog)
1014 public:
QtToolBarDialogPrivate()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
createItem(QToolBar * toolBar)1075 ToolBarItem *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
createItem(const QString & toolBarName)1084 ToolBarItem *QtToolBarDialogPrivate::createItem(const QString &toolBarName)
1085 {
1086 ToolBarItem *item = new ToolBarItem(toolBarName);
1087 allToolBarItems.insert(item);
1088 return item;
1089 }
1090
deleteItem(ToolBarItem * item)1091 void QtToolBarDialogPrivate::deleteItem(ToolBarItem *item)
1092 {
1093 if (!allToolBarItems.contains(item))
1094 return;
1095 allToolBarItems.remove(item);
1096 delete item;
1097 }
1098
clearOld()1099 void 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
fillNew()1133 void 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
isDefaultToolBar(ToolBarItem * item) const1203 bool 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
setButtons()1212 void 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
newClicked()1245 void 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
removeToolBar(ToolBarItem * item)1263 void 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
removeClicked()1308 void 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
defaultClicked()1317 void 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
okClicked()1359 void QtToolBarDialogPrivate::okClicked()
1360 {
1361 applyClicked();
1362 q_ptr->accept();
1363 }
1364
applyClicked()1365 void 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
upClicked()1405 void 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
downClicked()1425 void 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
leftClicked()1445 void 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
rightClicked()1475 void 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
renameClicked()1529 void QtToolBarDialogPrivate::renameClicked()
1530 {
1531 if (!currentToolBar)
1532 return;
1533
1534 QListWidgetItem *item = toolBarToItem.value(currentToolBar);
1535 ui.toolBarList->editItem(item);
1536 }
1537
toolBarRenamed(QListWidgetItem * item)1538 void 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
currentActionChanged(QTreeWidgetItem * current)1550 void QtToolBarDialogPrivate::currentActionChanged(QTreeWidgetItem *current)
1551 {
1552 if (itemToAction.contains(current))
1553 currentAction = current;
1554 else
1555 currentAction = NULL;
1556 setButtons();
1557 }
1558
currentToolBarChanged(QListWidgetItem * current)1559 void 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
currentToolBarActionChanged(QListWidgetItem *)1593 void QtToolBarDialogPrivate::currentToolBarActionChanged(QListWidgetItem *)
1594 {
1595 setButtons();
1596 }
1597
cancelClicked()1598 void QtToolBarDialogPrivate::cancelClicked()
1599 {
1600 // just nothing
1601 q_ptr->reject();
1602 }
1603
1604 //////////////////////
1605 /*
1606 class FeedbackItemDelegate : public QItemDelegate
1607 {
1608 Q_OBJECT
1609 public:
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
1617 void 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
1641 QSize 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
1650 class QtToolBarListWidget : public QListWidget
1651 {
1652 Q_OBJECT
1653 public:
1654 QtToolBarListWidget(QWidget *parent) : QListWidget(parent), actionDrag(false) {}
1655
1656 protected:
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; }
1665 private:
1666 QPersistentModelIndex lastDropIndicator;
1667 QString actionName;
1668 bool actionDrag;
1669 };
1670
1671 void 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
1687 void 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
1697 void 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
1716 void QtToolBarListWidget::dragLeaveEvent(QDragLeaveEvent *)
1717 {
1718 if (actionDrag) {
1719 actionDrag = false;
1720 setIndicator(item, QtToolBarListWidget::None);
1721 }
1722 }
1723
1724 void 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 */
QtToolBarDialog(QWidget * parent,Qt::WindowFlags flags)1792 QtToolBarDialog::QtToolBarDialog(QWidget *parent, Qt::WindowFlags 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(":/qttoolbardialog/up.png"));
1814 d_ptr->ui.downButton->setIcon(QIcon(":/qttoolbardialog/down.png"));
1815 d_ptr->ui.leftButton->setIcon(QIcon(":/qttoolbardialog/back.png"));
1816 d_ptr->ui.rightButton->setIcon(QIcon(":/qttoolbardialog/forward.png"));
1817 d_ptr->ui.newButton->setIcon(QIcon(":/qttoolbardialog/plus.png"));
1818 d_ptr->ui.removeButton->setIcon(QIcon(":/qttoolbardialog/minus.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.defaultButton, SIGNAL(clicked()), this, SLOT(defaultClicked()));
1824 connect(d_ptr->ui.okButton, SIGNAL(clicked()), this, SLOT(okClicked()));
1825 connect(d_ptr->ui.applyButton, SIGNAL(clicked()), this, SLOT(applyClicked()));
1826 connect(d_ptr->ui.cancelButton, 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 */
~QtToolBarDialog()1851 QtToolBarDialog::~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 */
setToolBarManager(QtToolBarManager * toolBarManager)1862 void 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 */
showEvent(QShowEvent * event)1876 void QtToolBarDialog::showEvent(QShowEvent *event)
1877 {
1878 if (!event->spontaneous())
1879 d_ptr->fillNew();
1880 }
1881
1882 /*!
1883 \reimp
1884 */
hideEvent(QHideEvent * event)1885 void QtToolBarDialog::hideEvent(QHideEvent *event)
1886 {
1887 if (!event->spontaneous())
1888 d_ptr->clearOld();
1889 }
1890
1891 #include "moc_qttoolbardialog.cpp"
1892 #include "qttoolbardialog.moc"
1893