source: trunk/src/gui/widgets/qtoolbararealayout.cpp@ 5

Last change on this file since 5 was 2, checked in by Dmitry A. Kuminov, 16 years ago

Initially imported qt-all-opensource-src-4.5.1 from Trolltech.

File size: 42.0 KB
Line 
1/****************************************************************************
2**
3** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
4** Contact: Qt Software Information (qt-info@nokia.com)
5**
6** This file is part of the QtGui module of the Qt Toolkit.
7**
8** $QT_BEGIN_LICENSE:LGPL$
9** Commercial Usage
10** Licensees holding valid Qt Commercial licenses may use this file in
11** accordance with the Qt Commercial License Agreement provided with the
12** Software or, alternatively, in accordance with the terms contained in
13** 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.0, 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** If you are unsure which license is appropriate for your use, please
37** contact the sales department at qt-sales@nokia.com.
38** $QT_END_LICENSE$
39**
40****************************************************************************/
41
42#include <QWidgetItem>
43#include <QToolBar>
44#include <QStyleOption>
45#include <QApplication>
46#include <qdebug.h>
47
48#include "qtoolbararealayout_p.h"
49#include "qmainwindowlayout_p.h"
50#include "qwidgetanimator_p.h"
51#include "qtoolbarlayout_p.h"
52#include "qtoolbar_p.h"
53
54/******************************************************************************
55** QToolBarAreaLayoutItem
56*/
57
58#ifndef QT_NO_TOOLBAR
59
60QT_BEGIN_NAMESPACE
61
62QSize QToolBarAreaLayoutItem::minimumSize() const
63{
64 if (skip())
65 return QSize(0, 0);
66 return qSmartMinSize(static_cast<QWidgetItem*>(widgetItem));
67}
68
69QSize QToolBarAreaLayoutItem::sizeHint() const
70{
71 if (skip())
72 return QSize(0, 0);
73
74 return realSizeHint();
75}
76
77//returns the real size hint not taking into account the visibility of the widget
78QSize QToolBarAreaLayoutItem::realSizeHint() const
79{
80 QWidget *wid = widgetItem->widget();
81 QSize s = wid->sizeHint().expandedTo(wid->minimumSizeHint());
82 if (wid->sizePolicy().horizontalPolicy() == QSizePolicy::Ignored)
83 s.setWidth(0);
84 if (wid->sizePolicy().verticalPolicy() == QSizePolicy::Ignored)
85 s.setHeight(0);
86 s = s.boundedTo(wid->maximumSize())
87 .expandedTo(wid->minimumSize());
88 return s;
89}
90
91bool QToolBarAreaLayoutItem::skip() const
92{
93 if (gap)
94 return false;
95 return widgetItem == 0 || widgetItem->isEmpty();
96}
97
98/******************************************************************************
99** QToolBarAreaLayoutLine
100*/
101
102QToolBarAreaLayoutLine::QToolBarAreaLayoutLine(Qt::Orientation orientation)
103 : o(orientation)
104{
105}
106
107QSize QToolBarAreaLayoutLine::sizeHint() const
108{
109 int a = 0, b = 0;
110 for (int i = 0; i < toolBarItems.count(); ++i) {
111 const QToolBarAreaLayoutItem &item = toolBarItems.at(i);
112 if (item.skip())
113 continue;
114
115 QSize sh = item.sizeHint();
116 a += pick(o, sh) + item.extraSpace;
117 b = qMax(b, perp(o, sh));
118 }
119
120 QSize result;
121 rpick(o, result) = a;
122 rperp(o, result) = b;
123
124 return result;
125}
126
127QSize QToolBarAreaLayoutLine::minimumSize() const
128{
129 int a = 0, b = 0;
130 for (int i = 0; i < toolBarItems.count(); ++i) {
131 const QToolBarAreaLayoutItem &item = toolBarItems[i];
132 if (item.skip())
133 continue;
134
135 QSize ms = item.minimumSize();
136 a += pick(o, ms);
137 b = qMax(b, perp(o, ms));
138 }
139
140 QSize result;
141 rpick(o, result) = a;
142 rperp(o, result) = b;
143
144 return result;
145}
146
147void QToolBarAreaLayoutLine::fitLayout()
148{
149 int last = -1;
150 int min = pick(o, minimumSize());
151 int space = pick(o, rect.size());
152 int extra = qMax(0, space - min);
153
154 for (int i = 0; i < toolBarItems.count(); ++i) {
155 QToolBarAreaLayoutItem &item = toolBarItems[i];
156 if (item.skip())
157 continue;
158
159 QToolBarLayout *tblayout = qobject_cast<QToolBarLayout*>(item.widgetItem->widget()->layout());
160 if (tblayout)
161 tblayout->checkUsePopupMenu();
162
163 int itemMin = pick(o, item.minimumSize());
164 int itemHint = pick(o, item.sizeHint());
165 //we ensure the extraspace is not too low
166 item.extraSpace = qMax(itemMin - itemHint, item.extraSpace);
167 itemHint += item.extraSpace;
168 int itemExtra = qMin(itemHint - itemMin, extra);
169
170 item.size = itemMin + itemExtra;
171 extra -= itemExtra;
172
173 last = i;
174 }
175
176 // calculate the positions from the sizes
177 int pos = 0;
178 for (int i = 0; i < toolBarItems.count(); ++i) {
179 QToolBarAreaLayoutItem &item = toolBarItems[i];
180 if (item.skip())
181 continue;
182
183 item.pos = pos;
184 if (i == last) // stretch the last item to the end of the line
185 item.size = qMax(0, pick(o, rect.size()) - item.pos);
186 pos += item.size;
187 }
188}
189
190bool QToolBarAreaLayoutLine::skip() const
191{
192 for (int i = 0; i < toolBarItems.count(); ++i) {
193 if (!toolBarItems.at(i).skip())
194 return false;
195 }
196 return true;
197}
198
199/******************************************************************************
200** QToolBarAreaLayoutInfo
201*/
202
203QToolBarAreaLayoutInfo::QToolBarAreaLayoutInfo(QInternal::DockPosition pos)
204 : dockPos(pos), dirty(false)
205{
206 switch (pos) {
207 case QInternal::LeftDock:
208 case QInternal::RightDock:
209 o = Qt::Vertical;
210 break;
211 case QInternal::TopDock:
212 case QInternal::BottomDock:
213 o = Qt::Horizontal;
214 break;
215 default:
216 o = Qt::Horizontal;
217 break;
218 }
219}
220
221QSize QToolBarAreaLayoutInfo::sizeHint() const
222{
223 int a = 0, b = 0;
224 for (int i = 0; i < lines.count(); ++i) {
225 const QToolBarAreaLayoutLine &l = lines.at(i);
226 if (l.skip())
227 continue;
228
229 QSize hint = l.sizeHint();
230 a = qMax(a, pick(o, hint));
231 b += perp(o, hint);
232 }
233
234 QSize result;
235 rpick(o, result) = a;
236 rperp(o, result) = b;
237
238 return result;
239}
240
241QSize QToolBarAreaLayoutInfo::minimumSize() const
242{
243 int a = 0, b = 0;
244 for (int i = 0; i < lines.count(); ++i) {
245 const QToolBarAreaLayoutLine &l = lines.at(i);
246 if (l.skip())
247 continue;
248
249 QSize m = l.minimumSize();
250 a = qMax(a, pick(o, m));
251 b += perp(o, m);
252 }
253
254 QSize result;
255 rpick(o, result) = a;
256 rperp(o, result) = b;
257
258 return result;
259}
260
261void QToolBarAreaLayoutInfo::fitLayout()
262{
263 dirty = false;
264
265 int b = 0;
266
267 bool reverse = dockPos == QInternal::RightDock || dockPos == QInternal::BottomDock;
268
269 int i = reverse ? lines.count() - 1 : 0;
270 for (;;) {
271 if ((reverse && i < 0) || (!reverse && i == lines.count()))
272 break;
273
274 QToolBarAreaLayoutLine &l = lines[i];
275 if (!l.skip()) {
276 if (o == Qt::Horizontal) {
277 l.rect.setLeft(rect.left());
278 l.rect.setRight(rect.right());
279 l.rect.setTop(b + rect.top());
280 b += l.sizeHint().height();
281 l.rect.setBottom(b - 1 + rect.top());
282 } else {
283 l.rect.setTop(rect.top());
284 l.rect.setBottom(rect.bottom());
285 l.rect.setLeft(b + rect.left());
286 b += l.sizeHint().width();
287 l.rect.setRight(b - 1 + rect.left());
288 }
289
290 l.fitLayout();
291 }
292
293 i += reverse ? -1 : 1;
294 }
295}
296
297QLayoutItem *QToolBarAreaLayoutInfo::insertToolBar(QToolBar *before, QToolBar *toolBar)
298{
299 toolBar->setOrientation(o);
300 QLayoutItem *item = new QWidgetItemV2(toolBar);
301 insertItem(before, item);
302 return item;
303}
304
305void QToolBarAreaLayoutInfo::insertItem(QToolBar *before, QLayoutItem *item)
306{
307 if (before == 0) {
308 if (lines.isEmpty())
309 lines.append(QToolBarAreaLayoutLine(o));
310 lines.last().toolBarItems.append(item);
311 return;
312 }
313
314 for (int j = 0; j < lines.count(); ++j) {
315 QToolBarAreaLayoutLine &line = lines[j];
316
317 for (int k = 0; k < line.toolBarItems.count(); ++k) {
318 if (line.toolBarItems.at(k).widgetItem->widget() == before) {
319 line.toolBarItems.insert(k, item);
320 return;
321 }
322 }
323 }
324}
325
326void QToolBarAreaLayoutInfo::removeToolBar(QToolBar *toolBar)
327{
328 for (int j = 0; j < lines.count(); ++j) {
329 QToolBarAreaLayoutLine &line = lines[j];
330
331 for (int k = 0; k < line.toolBarItems.count(); ++k) {
332 QToolBarAreaLayoutItem &item = line.toolBarItems[k];
333 if (item.widgetItem->widget() == toolBar) {
334 delete item.widgetItem;
335 item.widgetItem = 0;
336 line.toolBarItems.removeAt(k);
337
338 if (line.toolBarItems.isEmpty() && j < lines.count() - 1)
339 lines.removeAt(j);
340
341 return;
342 }
343 }
344 }
345}
346
347void QToolBarAreaLayoutInfo::insertToolBarBreak(QToolBar *before)
348{
349 if (before == 0) {
350 if (!lines.isEmpty() && lines.last().toolBarItems.isEmpty())
351 return;
352 lines.append(QToolBarAreaLayoutLine(o));
353 return;
354 }
355
356 for (int j = 0; j < lines.count(); ++j) {
357 QToolBarAreaLayoutLine &line = lines[j];
358
359 for (int k = 0; k < line.toolBarItems.count(); ++k) {
360 if (line.toolBarItems.at(k).widgetItem->widget() == before) {
361 if (k == 0)
362 return;
363
364 QToolBarAreaLayoutLine newLine(o);
365 newLine.toolBarItems = line.toolBarItems.mid(k);
366 line.toolBarItems = line.toolBarItems.mid(0, k);
367 lines.insert(j + 1, newLine);
368
369 return;
370 }
371 }
372 }
373}
374
375void QToolBarAreaLayoutInfo::removeToolBarBreak(QToolBar *before)
376{
377 for (int j = 0; j < lines.count(); ++j) {
378 const QToolBarAreaLayoutLine &line = lines.at(j);
379
380 for (int k = 0; k < line.toolBarItems.count(); ++k) {
381 if (line.toolBarItems.at(k).widgetItem->widget() == before) {
382 if (k != 0)
383 return;
384 if (j == 0)
385 return;
386
387 lines[j - 1].toolBarItems += lines[j].toolBarItems;
388 lines.removeAt(j);
389
390 return;
391 }
392 }
393 }
394}
395
396void QToolBarAreaLayoutInfo::moveToolBar(QToolBar *toolbar, int pos)
397{
398 if (dirty) {
399 fitLayout();
400 }
401
402 dirty = true;
403
404 if (o == Qt::Vertical) {
405 pos -= rect.top();
406 }
407
408 //here we actually update the extraSpace for the line containing the toolbar so that we move it
409 for (int j = 0; j < lines.count(); ++j) {
410 QToolBarAreaLayoutLine &line = lines[j];
411
412 int previousIndex = -1;
413 int minPos = 0;
414 for (int k = 0; k < line.toolBarItems.count(); ++k) {
415 QToolBarAreaLayoutItem &current = line.toolBarItems[k];
416 if (current.widgetItem->widget() == toolbar) {
417 int newPos = current.pos;
418
419 if (previousIndex >= 0) {
420 QToolBarAreaLayoutItem &previous = line.toolBarItems[previousIndex];
421 if (pos < current.pos) {
422 newPos = qMax(pos, minPos);
423 } else {
424 //we check the max value for the position (until everything at the right is "compressed")
425 int maxPos = pick(o, rect.size());
426 for(int l = k; l < line.toolBarItems.count(); ++l) {
427 const QToolBarAreaLayoutItem &item = line.toolBarItems.at(l);
428 if (!item.skip()) {
429 maxPos -= pick(o, item.minimumSize());
430 }
431 }
432 newPos = qMin(pos, maxPos);
433 }
434
435 //let's update the previous extra space
436 int extra = newPos - current.pos;
437
438 if (qAbs(previous.extraSpace + extra) < QApplication::startDragDistance()) {
439 //we stick to the default space
440 extra = 0;
441 }
442
443 //update for the current item
444 current.extraSpace -= extra;
445 //this ensures the toolbars to be pushed to the right when necessary
446 current.extraSpace = qMax(pick(o,current.minimumSize())- pick(o,current.sizeHint()), current.extraSpace);
447
448 if (extra >= 0) {
449 previous.extraSpace += extra;
450
451 } else {
452 //we need to push the toolbars on the left starting with previous
453 extra = -extra; // we just need to know the number of pixels
454 ///at this point we need to get extra pixels from the toolbars at the left
455 for(int l = previousIndex; l >=0; --l) {
456 QToolBarAreaLayoutItem &item = line.toolBarItems[l];
457 if (!item.skip()) {
458 const int minExtraSpace = pick(o, item.minimumSize()) - pick(o, item.sizeHint());
459 const int margin = item.extraSpace - minExtraSpace;
460 if (margin < extra) {
461 item.extraSpace = minExtraSpace;
462 extra -= margin;
463 } else {
464 item.extraSpace -= extra;
465 extra = 0;
466 }
467 }
468 }
469 Q_ASSERT(extra == 0);
470 }
471 } else {
472 //the item is the first one, it should be at position 0
473 }
474
475 return;
476
477 } else if (!current.skip()) {
478 previousIndex = k;
479 minPos += pick(o, current.minimumSize());
480 }
481 }
482 }
483}
484
485
486QList<int> QToolBarAreaLayoutInfo::gapIndex(const QPoint &pos) const
487{
488 int p = pick(o, pos);
489
490 if (rect.contains(pos)) {
491 for (int j = 0; j < lines.count(); ++j) {
492 const QToolBarAreaLayoutLine &line = lines.at(j);
493 if (line.skip())
494 continue;
495 if (!line.rect.contains(pos))
496 continue;
497
498 int k = 0;
499 for (; k < line.toolBarItems.count(); ++k) {
500 const QToolBarAreaLayoutItem &item = line.toolBarItems.at(k);
501 if (item.skip())
502 continue;
503
504 int size = qMin(item.size, pick(o, item.sizeHint()));
505
506 if (p > item.pos + size)
507 continue;
508 if (p > item.pos + size/2)
509 ++k;
510 break;
511 }
512
513 QList<int> result;
514 result << j << k;
515 return result;
516 }
517 } else if (appendLineDropRect().contains(pos)) {
518 QList<int> result;
519 result << lines.count() << 0;
520 return result;
521 }
522
523 return QList<int>();
524}
525
526bool QToolBarAreaLayoutInfo::insertGap(QList<int> path, QLayoutItem *item)
527{
528 int j = path.at(0);
529 if (j == lines.count())
530 lines.append(QToolBarAreaLayoutLine(o));
531
532 QToolBarAreaLayoutLine &line = lines[j];
533 const int k = path.at(1);
534
535 QToolBarAreaLayoutItem gap_item;
536 gap_item.gap = true;
537 gap_item.widgetItem = item;
538
539 //update the previous item's extra space
540 for(int p = k - 1 ; p >= 0; --p) {
541 QToolBarAreaLayoutItem &previous = line.toolBarItems[p];
542 if (!previous.skip()) {
543 //we found the previous one
544 gap_item.extraSpace = qMax(0, previous.extraSpace - pick(o, gap_item.sizeHint()));
545 previous.extraSpace = qMin(previous.extraSpace, 0);
546 break;
547 }
548 }
549
550 line.toolBarItems.insert(k, gap_item);
551 return true;
552
553}
554
555void QToolBarAreaLayoutInfo::clear()
556{
557 lines.clear();
558 rect = QRect(0, 0, -1, -1);
559}
560
561QRect QToolBarAreaLayoutInfo::itemRect(QList<int> path) const
562{
563 int j = path.at(0);
564 int k = path.at(1);
565
566 const QToolBarAreaLayoutLine &line = lines.at(j);
567 const QToolBarAreaLayoutItem &item = line.toolBarItems.at(k);
568
569 QRect result = line.rect;
570
571 if (o == Qt::Horizontal) {
572 result.setLeft(item.pos + line.rect.left());
573 result.setWidth(item.size);
574 } else {
575 result.setTop(item.pos + line.rect.top());
576 result.setHeight(item.size);
577 }
578
579 return result;
580}
581
582QRect QToolBarAreaLayoutInfo::appendLineDropRect() const
583{
584 QRect result;
585
586 switch (dockPos) {
587 case QInternal::LeftDock:
588 result = QRect(rect.right(), rect.top(),
589 EmptyDockAreaSize, rect.height());
590 break;
591 case QInternal::RightDock:
592 result = QRect(rect.left() - EmptyDockAreaSize, rect.top(),
593 EmptyDockAreaSize, rect.height());
594 break;
595 case QInternal::TopDock:
596 result = QRect(rect.left(), rect.bottom() + 1,
597 rect.width(), EmptyDockAreaSize);
598 break;
599 case QInternal::BottomDock:
600 result = QRect(rect.left(), rect.top() - EmptyDockAreaSize,
601 rect.width(), EmptyDockAreaSize);
602 break;
603 default:
604 break;
605 }
606
607 return result;
608}
609
610/******************************************************************************
611** QToolBarAreaLayout
612*/
613
614QToolBarAreaLayout::QToolBarAreaLayout(QMainWindow *win)
615{
616 visible = true;
617 mainWindow = win;
618 for (int i = 0; i < QInternal::DockCount; ++i) {
619 QInternal::DockPosition pos = static_cast<QInternal::DockPosition>(i);
620 docks[i] = QToolBarAreaLayoutInfo(pos);
621 }
622}
623
624QRect QToolBarAreaLayout::fitLayout()
625{
626 if (!visible)
627 return rect;
628
629 QSize left_hint = docks[QInternal::LeftDock].sizeHint();
630 QSize right_hint = docks[QInternal::RightDock].sizeHint();
631 QSize top_hint = docks[QInternal::TopDock].sizeHint();
632 QSize bottom_hint = docks[QInternal::BottomDock].sizeHint();
633
634 QRect center = rect.adjusted(left_hint.width(), top_hint.height(),
635 -right_hint.width(), -bottom_hint.height());
636
637 docks[QInternal::TopDock].rect = QRect(rect.left(), rect.top(),
638 rect.width(), top_hint.height());
639 docks[QInternal::LeftDock].rect = QRect(rect.left(), center.top(),
640 left_hint.width(), center.height());
641 docks[QInternal::RightDock].rect = QRect(center.right() + 1, center.top(),
642 right_hint.width(), center.height());
643 docks[QInternal::BottomDock].rect = QRect(rect.left(), center.bottom() + 1,
644 rect.width(), bottom_hint.height());
645
646 if (!mainWindow->unifiedTitleAndToolBarOnMac()) {
647 docks[QInternal::TopDock].fitLayout();
648 }
649 docks[QInternal::LeftDock].fitLayout();
650 docks[QInternal::RightDock].fitLayout();
651 docks[QInternal::BottomDock].fitLayout();
652
653 return center;
654}
655
656QSize QToolBarAreaLayout::minimumSize(const QSize &centerMin) const
657{
658 if (!visible)
659 return centerMin;
660
661 QSize result = centerMin;
662
663 QSize left_min = docks[QInternal::LeftDock].minimumSize();
664 QSize right_min = docks[QInternal::RightDock].minimumSize();
665 QSize top_min = docks[QInternal::TopDock].minimumSize();
666 QSize bottom_min = docks[QInternal::BottomDock].minimumSize();
667
668 result.setWidth(qMax(top_min.width(), result.width()));
669 result.setWidth(qMax(bottom_min.width(), result.width()));
670 result.setHeight(qMax(left_min.height(), result.height()));
671 result.setHeight(qMax(right_min.height(), result.height()));
672
673 result.rwidth() += left_min.width() + right_min.width();
674 result.rheight() += top_min.height() + bottom_min.height();
675
676 return result;
677}
678
679QSize QToolBarAreaLayout::sizeHint(const QSize &centerHint) const
680{
681 if (!visible)
682 return centerHint;
683
684 QSize result = centerHint;
685
686 QSize left_hint = docks[QInternal::LeftDock].sizeHint();
687 QSize right_hint = docks[QInternal::RightDock].sizeHint();
688 QSize top_hint = docks[QInternal::TopDock].sizeHint();
689 QSize bottom_hint = docks[QInternal::BottomDock].sizeHint();
690
691 result.setWidth(qMax(top_hint.width(), result.width()));
692 result.setWidth(qMax(bottom_hint.width(), result.width()));
693 result.setHeight(qMax(left_hint.height(), result.height()));
694 result.setHeight(qMax(right_hint.height(), result.height()));
695
696 result.rwidth() += left_hint.width() + right_hint.width();
697 result.rheight() += top_hint.height() + bottom_hint.height();
698
699 return result;
700}
701
702QRect QToolBarAreaLayout::rectHint(const QRect &r) const
703{
704 int coef = visible ? 1 : -1;
705
706 QRect result = r;
707
708 QSize left_hint = docks[QInternal::LeftDock].sizeHint();
709 QSize right_hint = docks[QInternal::RightDock].sizeHint();
710 QSize top_hint = docks[QInternal::TopDock].sizeHint();
711 QSize bottom_hint = docks[QInternal::BottomDock].sizeHint();
712
713 result.adjust(-left_hint.width()*coef, -top_hint.height()*coef,
714 right_hint.width()*coef, bottom_hint.height()*coef);
715
716 return result;
717}
718
719QLayoutItem *QToolBarAreaLayout::itemAt(int *x, int index) const
720{
721 Q_ASSERT(x != 0);
722
723 for (int i = 0; i < QInternal::DockCount; ++i) {
724 const QToolBarAreaLayoutInfo &dock = docks[i];
725
726 for (int j = 0; j < dock.lines.count(); ++j) {
727 const QToolBarAreaLayoutLine &line = dock.lines.at(j);
728
729 for (int k = 0; k < line.toolBarItems.count(); ++k) {
730 if ((*x)++ == index)
731 return line.toolBarItems.at(k).widgetItem;
732 }
733 }
734 }
735
736 return 0;
737}
738
739QLayoutItem *QToolBarAreaLayout::takeAt(int *x, int index)
740{
741 Q_ASSERT(x != 0);
742
743 for (int i = 0; i < QInternal::DockCount; ++i) {
744 QToolBarAreaLayoutInfo &dock = docks[i];
745
746 for (int j = 0; j < dock.lines.count(); ++j) {
747 QToolBarAreaLayoutLine &line = dock.lines[j];
748
749 for (int k = 0; k < line.toolBarItems.count(); ++k) {
750 if ((*x)++ == index) {
751 QLayoutItem *result = line.toolBarItems.takeAt(k).widgetItem;
752 if (line.toolBarItems.isEmpty())
753 dock.lines.removeAt(j);
754 return result;
755 }
756 }
757 }
758 }
759
760 return 0;
761}
762
763void QToolBarAreaLayout::deleteAllLayoutItems()
764{
765 for (int i = 0; i < QInternal::DockCount; ++i) {
766 QToolBarAreaLayoutInfo &dock = docks[i];
767
768 for (int j = 0; j < dock.lines.count(); ++j) {
769 QToolBarAreaLayoutLine &line = dock.lines[j];
770
771 for (int k = 0; k < line.toolBarItems.count(); ++k) {
772 QToolBarAreaLayoutItem &item = line.toolBarItems[k];
773 delete item.widgetItem;
774 item.widgetItem = 0;
775 }
776 }
777 }
778}
779
780QInternal::DockPosition QToolBarAreaLayout::findToolBar(QToolBar *toolBar) const
781{
782 for (int i = 0; i < QInternal::DockCount; ++i) {
783 const QToolBarAreaLayoutInfo &dock = docks[i];
784
785 for (int j = 0; j < dock.lines.count(); ++j) {
786 const QToolBarAreaLayoutLine &line = dock.lines.at(j);
787
788 for (int k = 0; k < line.toolBarItems.count(); ++k) {
789 if (line.toolBarItems.at(k).widgetItem->widget() == toolBar)
790 return static_cast<QInternal::DockPosition>(i);
791 }
792 }
793 }
794
795 return QInternal::DockCount;
796}
797
798QLayoutItem *QToolBarAreaLayout::insertToolBar(QToolBar *before, QToolBar *toolBar)
799{
800 QInternal::DockPosition pos = findToolBar(before);
801 if (pos == QInternal::DockCount)
802 return 0;
803
804 return docks[pos].insertToolBar(before, toolBar);
805}
806
807void QToolBarAreaLayout::removeToolBar(QToolBar *toolBar)
808{
809 QInternal::DockPosition pos = findToolBar(toolBar);
810 if (pos == QInternal::DockCount)
811 return;
812 docks[pos].removeToolBar(toolBar);
813}
814
815QLayoutItem *QToolBarAreaLayout::addToolBar(QInternal::DockPosition pos, QToolBar *toolBar)
816{
817 return docks[pos].insertToolBar(0, toolBar);
818}
819
820void QToolBarAreaLayout::insertToolBarBreak(QToolBar *before)
821{
822 QInternal::DockPosition pos = findToolBar(before);
823 if (pos == QInternal::DockCount)
824 return;
825 docks[pos].insertToolBarBreak(before);
826}
827
828void QToolBarAreaLayout::removeToolBarBreak(QToolBar *before)
829{
830 QInternal::DockPosition pos = findToolBar(before);
831 if (pos == QInternal::DockCount)
832 return;
833 docks[pos].removeToolBarBreak(before);
834}
835
836void QToolBarAreaLayout::addToolBarBreak(QInternal::DockPosition pos)
837{
838 docks[pos].insertToolBarBreak(0);
839}
840
841void QToolBarAreaLayout::moveToolBar(QToolBar *toolbar, int p)
842{
843 QInternal::DockPosition pos = findToolBar(toolbar);
844 if (pos == QInternal::DockCount)
845 return;
846 docks[pos].moveToolBar(toolbar, p);
847}
848
849
850void QToolBarAreaLayout::insertItem(QInternal::DockPosition pos, QLayoutItem *item)
851{
852 if (docks[pos].lines.isEmpty())
853 docks[pos].lines.append(QToolBarAreaLayoutLine(docks[pos].o));
854 docks[pos].lines.last().toolBarItems.append(item);
855}
856
857void QToolBarAreaLayout::insertItem(QToolBar *before, QLayoutItem *item)
858{
859 QInternal::DockPosition pos = findToolBar(before);
860 if (pos == QInternal::DockCount)
861 return;
862
863 docks[pos].insertItem(before, item);
864}
865
866void QToolBarAreaLayout::apply(bool animate)
867{
868 QMainWindowLayout *layout = qobject_cast<QMainWindowLayout*>(mainWindow->layout());
869 Q_ASSERT(layout != 0);
870
871 Qt::LayoutDirection dir = mainWindow->layoutDirection();
872
873 for (int i = 0; i < QInternal::DockCount; ++i) {
874 const QToolBarAreaLayoutInfo &dock = docks[i];
875
876 for (int j = 0; j < dock.lines.count(); ++j) {
877 const QToolBarAreaLayoutLine &line = dock.lines.at(j);
878 if (line.skip())
879 continue;
880
881 for (int k = 0; k < line.toolBarItems.count(); ++k) {
882 const QToolBarAreaLayoutItem &item = line.toolBarItems.at(k);
883 if (item.skip() || item.gap)
884 continue;
885
886 QRect geo;
887 if (visible) {
888 if (line.o == Qt::Horizontal) {
889 geo.setTop(line.rect.top());
890 geo.setBottom(line.rect.bottom());
891 geo.setLeft(line.rect.left() + item.pos);
892 geo.setRight(line.rect.left() + item.pos + item.size - 1);
893 } else {
894 geo.setLeft(line.rect.left());
895 geo.setRight(line.rect.right());
896 geo.setTop(line.rect.top() + item.pos);
897 geo.setBottom(line.rect.top() + item.pos + item.size - 1);
898 }
899 }
900
901 QWidget *widget = item.widgetItem->widget();
902 if (QToolBar *toolBar = qobject_cast<QToolBar*>(widget)) {
903 QToolBarLayout *tbl = qobject_cast<QToolBarLayout*>(toolBar->layout());
904 if (tbl->expanded) {
905 QPoint tr = geo.topRight();
906 QSize size = tbl->expandedSize(geo.size());
907 geo.setSize(size);
908 geo.moveTopRight(tr);
909 if (geo.bottom() > rect.bottom())
910 geo.moveBottom(rect.bottom());
911 if (geo.right() > rect.right())
912 geo.moveRight(rect.right());
913 if (geo.left() < 0)
914 geo.moveLeft(0);
915 if (geo.top() < 0)
916 geo.moveTop(0);
917 }
918 }
919
920 if (visible && dock.o == Qt::Horizontal)
921 geo = QStyle::visualRect(dir, line.rect, geo);
922
923 layout->widgetAnimator->animate(widget, geo, animate);
924 }
925 }
926 }
927}
928
929bool QToolBarAreaLayout::toolBarBreak(QToolBar *toolBar) const
930{
931 for (int i = 0; i < QInternal::DockCount; ++i) {
932 const QToolBarAreaLayoutInfo &dock = docks[i];
933
934 for (int j = 0; j < dock.lines.count(); ++j) {
935 const QToolBarAreaLayoutLine &line = dock.lines.at(j);
936
937 for (int k = 0; k < line.toolBarItems.count(); ++k) {
938 if (line.toolBarItems.at(k).widgetItem->widget() == toolBar)
939 return j > 0 && k == 0;
940 }
941 }
942 }
943
944 return false;
945}
946
947void QToolBarAreaLayout::getStyleOptionInfo(QStyleOptionToolBar *option, QToolBar *toolBar) const
948{
949 for (int i = 0; i < QInternal::DockCount; ++i) {
950 const QToolBarAreaLayoutInfo &dock = docks[i];
951
952 for (int j = 0; j < dock.lines.count(); ++j) {
953 const QToolBarAreaLayoutLine &line = dock.lines.at(j);
954
955 for (int k = 0; k < line.toolBarItems.count(); ++k) {
956 if (line.toolBarItems.at(k).widgetItem->widget() == toolBar) {
957 if (line.toolBarItems.count() == 1)
958 option->positionWithinLine = QStyleOptionToolBar::OnlyOne;
959 else if (k == 0)
960 option->positionWithinLine = QStyleOptionToolBar::Beginning;
961 else if (k == line.toolBarItems.count() - 1)
962 option->positionWithinLine = QStyleOptionToolBar::End;
963 else
964 option->positionWithinLine = QStyleOptionToolBar::Middle;
965
966 if (dock.lines.count() == 1)
967 option->positionOfLine = QStyleOptionToolBar::OnlyOne;
968 else if (j == 0)
969 option->positionOfLine = QStyleOptionToolBar::Beginning;
970 else if (j == dock.lines.count() - 1)
971 option->positionOfLine = QStyleOptionToolBar::End;
972 else
973 option->positionOfLine = QStyleOptionToolBar::Middle;
974
975 return;
976 }
977 }
978 }
979 }
980}
981
982QList<int> QToolBarAreaLayout::indexOf(QWidget *toolBar) const
983{
984 QList<int> result;
985
986 bool found = false;
987
988 for (int i = 0; i < QInternal::DockCount; ++i) {
989 const QToolBarAreaLayoutInfo &dock = docks[i];
990
991 for (int j = 0; j < dock.lines.count(); ++j) {
992 const QToolBarAreaLayoutLine &line = dock.lines.at(j);
993
994 for (int k = 0; k < line.toolBarItems.count(); ++k) {
995 const QToolBarAreaLayoutItem &item = line.toolBarItems.at(k);
996 if (!item.gap && item.widgetItem->widget() == toolBar) {
997 found = true;
998 result.prepend(k);
999 break;
1000 }
1001 }
1002
1003 if (found) {
1004 result.prepend(j);
1005 break;
1006 }
1007 }
1008
1009 if (found) {
1010 result.prepend(i);
1011 break;
1012 }
1013 }
1014
1015 return result;
1016}
1017
1018QList<int> QToolBarAreaLayout::gapIndex(const QPoint &pos) const
1019{
1020 Qt::LayoutDirection dir = mainWindow->layoutDirection();
1021 for (int i = 0; i < QInternal::DockCount; ++i) {
1022 QPoint p = pos;
1023 if (docks[i].o == Qt::Horizontal)
1024 p = QStyle::visualPos(dir, docks[i].rect, p);
1025 QList<int> result = docks[i].gapIndex(p);
1026 if (!result.isEmpty()) {
1027 result.prepend(i);
1028 return result;
1029 }
1030 }
1031
1032 return QList<int>();
1033}
1034
1035QList<int> QToolBarAreaLayout::currentGapIndex() const
1036{
1037 for (int i = 0; i < QInternal::DockCount; ++i) {
1038 const QToolBarAreaLayoutInfo &dock = docks[i];
1039
1040 for (int j = 0; j < dock.lines.count(); ++j) {
1041 const QToolBarAreaLayoutLine &line = dock.lines[j];
1042
1043 for (int k = 0; k < line.toolBarItems.count(); k++) {
1044 if (line.toolBarItems[k].gap) {
1045 QList<int> result;
1046 result << i << j << k;
1047 return result;
1048 }
1049 }
1050 }
1051 }
1052 return QList<int>();
1053}
1054
1055bool QToolBarAreaLayout::insertGap(QList<int> path, QLayoutItem *item)
1056{
1057 Q_ASSERT(!path.isEmpty());
1058 int i = path.takeFirst();
1059 Q_ASSERT(i >= 0 && i < QInternal::DockCount);
1060 return docks[i].insertGap(path, item);
1061}
1062
1063void QToolBarAreaLayout::remove(QList<int> path)
1064{
1065 docks[path.at(0)].lines[path.at(1)].toolBarItems.removeAt(path.at(2));
1066}
1067
1068void QToolBarAreaLayout::remove(QLayoutItem *item)
1069{
1070 for (int i = 0; i < QInternal::DockCount; ++i) {
1071 QToolBarAreaLayoutInfo &dock = docks[i];
1072
1073 for (int j = 0; j < dock.lines.count(); ++j) {
1074 QToolBarAreaLayoutLine &line = dock.lines[j];
1075
1076 for (int k = 0; k < line.toolBarItems.count(); k++) {
1077 if (line.toolBarItems[k].widgetItem == item) {
1078 line.toolBarItems.removeAt(k);
1079 if (line.toolBarItems.isEmpty())
1080 dock.lines.removeAt(j);
1081 return;
1082 }
1083 }
1084 }
1085 }
1086}
1087
1088void QToolBarAreaLayout::clear()
1089{
1090 for (int i = 0; i < QInternal::DockCount; ++i)
1091 docks[i].clear();
1092 rect = QRect(0, 0, -1, -1);
1093}
1094
1095QToolBarAreaLayoutItem &QToolBarAreaLayout::item(QList<int> path)
1096{
1097 Q_ASSERT(path.count() == 3);
1098
1099 Q_ASSERT(path.at(0) >= 0 && path.at(0) < QInternal::DockCount);
1100 QToolBarAreaLayoutInfo &info = docks[path.at(0)];
1101 Q_ASSERT(path.at(1) >= 0 && path.at(1) < info.lines.count());
1102 QToolBarAreaLayoutLine &line = info.lines[path.at(1)];
1103 Q_ASSERT(path.at(2) >= 0 && path.at(2) < line.toolBarItems.count());
1104 return line.toolBarItems[path.at(2)];
1105}
1106
1107QRect QToolBarAreaLayout::itemRect(QList<int> path) const
1108{
1109 int i = path.takeFirst();
1110
1111 QRect r = docks[i].itemRect(path);
1112 if (docks[i].o == Qt::Horizontal)
1113 r = QStyle::visualRect(mainWindow->layoutDirection(),
1114 docks[i].rect, r);
1115 return r;
1116}
1117
1118QLayoutItem *QToolBarAreaLayout::plug(QList<int> path)
1119{
1120 QToolBarAreaLayoutItem &item = this->item(path);
1121 Q_ASSERT(item.gap);
1122 Q_ASSERT(item.widgetItem != 0);
1123 item.gap = false;
1124 return item.widgetItem;
1125}
1126
1127QLayoutItem *QToolBarAreaLayout::unplug(QList<int> path, QToolBarAreaLayout *other)
1128{
1129 //other needs to be update as well
1130 QToolBarAreaLayoutItem &item = this->item(path);
1131
1132 //update the leading space here
1133 QToolBarAreaLayoutInfo &info = docks[path.at(0)];
1134 QToolBarAreaLayoutLine &line = info.lines[path.at(1)];
1135 if (item.extraSpace != 0) {
1136 int newExtraSpace = 0;
1137 for (int i = path.at(2) - 1; i >= 0; --i) {
1138 QToolBarAreaLayoutItem &previous = line.toolBarItems[i];
1139 if (!previous.skip()) {
1140 for (int j = path.at(2) + 1; j < line.toolBarItems.count(); ++j) {
1141 const QToolBarAreaLayoutItem &next = line.toolBarItems.at(j);
1142 if (!next.skip()) {
1143 newExtraSpace = previous.extraSpace = next.pos - previous.pos - pick(line.o, previous.sizeHint());
1144 }
1145 break;
1146 }
1147 break;
1148 }
1149 }
1150
1151 if (other) {
1152 QToolBarAreaLayoutInfo &info = other->docks[path.at(0)];
1153 QToolBarAreaLayoutLine &line = info.lines[path.at(1)];
1154 for (int i = path.at(2) - 1; i >= 0; --i) {
1155 QToolBarAreaLayoutItem &previous = line.toolBarItems[i];
1156 if (!previous.skip()) {
1157 previous.extraSpace = newExtraSpace;
1158 break;
1159 }
1160 }
1161
1162 }
1163 }
1164
1165
1166 Q_ASSERT(!item.gap);
1167 item.gap = true;
1168 return item.widgetItem;
1169}
1170
1171static QRect unpackRect(uint geom0, uint geom1, bool *floating)
1172{
1173 *floating = geom0 & 1;
1174 if (!*floating)
1175 return QRect();
1176
1177 geom0 >>= 1;
1178
1179 int x = (int)(geom0 & 0x0000ffff) - 0x7FFF;
1180 int y = (int)(geom1 & 0x0000ffff) - 0x7FFF;
1181
1182 geom0 >>= 16;
1183 geom1 >>= 16;
1184
1185 int w = geom0 & 0x0000ffff;
1186 int h = geom1 & 0x0000ffff;
1187
1188 return QRect(x, y, w, h);
1189}
1190
1191static void packRect(uint *geom0, uint *geom1, const QRect &rect, bool floating)
1192{
1193 *geom0 = 0;
1194 *geom1 = 0;
1195
1196 if (!floating)
1197 return;
1198
1199 // The 0x7FFF is half of 0xFFFF. We add it so we can handle negative coordinates on
1200 // dual monitors. It's subtracted when unpacking.
1201
1202 *geom0 |= qMax(0, rect.width()) & 0x0000ffff;
1203 *geom1 |= qMax(0, rect.height()) & 0x0000ffff;
1204
1205 *geom0 <<= 16;
1206 *geom1 <<= 16;
1207
1208 *geom0 |= qMax(0, rect.x() + 0x7FFF) & 0x0000ffff;
1209 *geom1 |= qMax(0, rect.y() + 0x7FFF) & 0x0000ffff;
1210
1211 // yeah, we chop one bit off the width, but it still has a range up to 32512
1212
1213 *geom0 <<= 1;
1214 *geom0 |= 1;
1215}
1216
1217
1218void QToolBarAreaLayout::saveState(QDataStream &stream) const
1219{
1220 // save toolbar state
1221 stream << (uchar) ToolBarStateMarkerEx;
1222
1223 int lineCount = 0;
1224 for (int i = 0; i < QInternal::DockCount; ++i)
1225 lineCount += docks[i].lines.count();
1226
1227 stream << lineCount;
1228
1229 for (int i = 0; i < QInternal::DockCount; ++i) {
1230 const QToolBarAreaLayoutInfo &dock = docks[i];
1231
1232 for (int j = 0; j < dock.lines.count(); ++j) {
1233 const QToolBarAreaLayoutLine &line = dock.lines.at(j);
1234
1235 stream << i << line.toolBarItems.count();
1236
1237 for (int k = 0; k < line.toolBarItems.count(); ++k) {
1238 const QToolBarAreaLayoutItem &item = line.toolBarItems.at(k);
1239 QWidget *widget = const_cast<QLayoutItem*>(item.widgetItem)->widget();
1240 QString objectName = widget->objectName();
1241 if (objectName.isEmpty()) {
1242 qWarning("QMainWindow::saveState(): 'objectName' not set for QToolBar %p '%s'",
1243 widget, widget->windowTitle().toLocal8Bit().constData());
1244 }
1245 stream << objectName;
1246 // we store information as:
1247 // 1st bit: 1 if shown
1248 // 2nd bit: 1 if orientation is vertical (default is horizontal)
1249 uchar shownOrientation = (uchar)!widget->isHidden();
1250 if (QToolBar * tb= qobject_cast<QToolBar*>(widget)) {
1251 if (tb->orientation() == Qt::Vertical)
1252 shownOrientation |= 2;
1253 }
1254 stream << shownOrientation;
1255 stream << item.pos;
1256 //if extraSpace is 0 the item has its "normal" size, so no need to store the size (we store -1)
1257 stream << (item.extraSpace == 0 ? -1 : (pick(line.o, item.realSizeHint()) + item.extraSpace));
1258
1259 uint geom0, geom1;
1260 packRect(&geom0, &geom1, widget->geometry(), widget->isWindow());
1261 stream << geom0 << geom1;
1262 }
1263 }
1264 }
1265}
1266
1267static inline int getInt(QDataStream &stream, Qt::Orientation o, bool pre43)
1268{
1269 if (pre43) {
1270 QPoint p;
1271 stream >> p;
1272 return pick(o, p);
1273 } else {
1274 int x;
1275 stream >> x;
1276 return x;
1277 }
1278}
1279
1280
1281bool QToolBarAreaLayout::restoreState(QDataStream &stream, const QList<QToolBar*> &_toolBars, uchar tmarker, bool pre43, bool testing)
1282{
1283 QList<QToolBar*> toolBars = _toolBars;
1284 int lines;
1285 stream >> lines;
1286
1287 for (int j = 0; j < lines; ++j) {
1288 int pos;
1289 stream >> pos;
1290 if (pos < 0 || pos >= QInternal::DockCount)
1291 return false;
1292 int cnt;
1293 stream >> cnt;
1294
1295 QToolBarAreaLayoutInfo &dock = docks[pos];
1296 QToolBarAreaLayoutLine line(dock.o);
1297
1298 for (int k = 0; k < cnt; ++k) {
1299 QToolBarAreaLayoutItem item;
1300
1301 QString objectName;
1302 stream >> objectName;
1303 uchar shown;
1304 stream >> shown;
1305 item.pos = getInt(stream, dock.o, pre43);
1306 item.size = getInt(stream, dock.o, pre43);
1307
1308 /*
1309 4.3.0 added floating toolbars, but failed to add the ability to restore them.
1310 We need to store there geometry (four ints). We cannot change the format in a
1311 patch release (4.3.1) by adding ToolBarStateMarkerEx2 to signal extra data. So
1312 for now we'll pack it in the two legacy ints we no longer used in Qt4.3.0.
1313 In 4.4, we should add ToolBarStateMarkerEx2 and fix this properly.
1314 */
1315
1316 QRect rect;
1317 bool floating = false;
1318 uint geom0, geom1;
1319 geom0 = getInt(stream, dock.o, pre43);
1320 if (tmarker == ToolBarStateMarkerEx) {
1321 geom1 = getInt(stream, dock.o, pre43);
1322 rect = unpackRect(geom0, geom1, &floating);
1323 }
1324
1325 QToolBar *toolBar = 0;
1326 for (int x = 0; x < toolBars.count(); ++x) {
1327 if (toolBars.at(x)->objectName() == objectName) {
1328 toolBar = toolBars.takeAt(x);
1329 break;
1330 }
1331 }
1332 if (toolBar == 0) {
1333 continue;
1334 }
1335
1336 if (!testing) {
1337 item.widgetItem = new QWidgetItemV2(toolBar);
1338 toolBar->setOrientation(floating ? ((shown & 2) ? Qt::Vertical : Qt::Horizontal) : dock.o);
1339 toolBar->setVisible(shown & 1);
1340 toolBar->d_func()->setWindowState(floating, true, rect);
1341
1342 //if it is -1, it means we should use the default size
1343 item.extraSpace = (item.size == -1) ? 0 : item.size - pick(line.o, item.realSizeHint());
1344
1345
1346 line.toolBarItems.append(item);
1347 }
1348 }
1349
1350 if (!testing) {
1351 dock.lines.append(line);
1352 }
1353 }
1354
1355
1356 return stream.status() == QDataStream::Ok;
1357}
1358
1359bool QToolBarAreaLayout::isEmpty() const
1360{
1361 for (int i = 0; i < QInternal::DockCount; ++i) {
1362 if (!docks[i].lines.isEmpty())
1363 return false;
1364 }
1365 return true;
1366}
1367
1368QT_END_NAMESPACE
1369
1370#endif // QT_NO_TOOLBAR
Note: See TracBrowser for help on using the repository browser.