qmdiarea.cpp

Absolute File Name:/home/qt/qt5_coco/qt5/qtbase/src/widgets/widgets/qmdiarea.cpp
Source codeSwitch to Preprocessed file
LineSourceCount
1/****************************************************************************-
2**-
3** Copyright (C) 2016 The Qt Company Ltd.-
4** Contact: https://www.qt.io/licensing/-
5**-
6** This file is part of the QtWidgets module of the Qt Toolkit.-
7**-
8** $QT_BEGIN_LICENSE:LGPL$-
9** Commercial License Usage-
10** Licensees holding valid commercial Qt licenses may use this file in-
11** accordance with the commercial license agreement provided with the-
12** Software or, alternatively, in accordance with the terms contained in-
13** a written agreement between you and The Qt Company. For licensing terms-
14** and conditions see https://www.qt.io/terms-conditions. For further-
15** information use the contact form at https://www.qt.io/contact-us.-
16**-
17** GNU Lesser General Public License Usage-
18** Alternatively, this file may be used under the terms of the GNU Lesser-
19** General Public License version 3 as published by the Free Software-
20** Foundation and appearing in the file LICENSE.LGPL3 included in the-
21** packaging of this file. Please review the following information to-
22** ensure the GNU Lesser General Public License version 3 requirements-
23** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.-
24**-
25** GNU General Public License Usage-
26** Alternatively, this file may be used under the terms of the GNU-
27** General Public License version 2.0 or (at your option) the GNU General-
28** Public license version 3 or any later version approved by the KDE Free-
29** Qt Foundation. The licenses are as published by the Free Software-
30** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3-
31** included in the packaging of this file. Please review the following-
32** information to ensure the GNU General Public License requirements will-
33** be met: https://www.gnu.org/licenses/gpl-2.0.html and-
34** https://www.gnu.org/licenses/gpl-3.0.html.-
35**-
36** $QT_END_LICENSE$-
37**-
38****************************************************************************/-
39-
40/*!-
41 \class QMdiArea-
42 \brief The QMdiArea widget provides an area in which MDI windows are displayed.-
43 \since 4.3-
44 \ingroup mainwindow-classes-
45 \inmodule QtWidgets-
46-
47 QMdiArea functions, essentially, like a window manager for MDI-
48 windows. For instance, it draws the windows it manages on itself-
49 and arranges them in a cascading or tile pattern. QMdiArea is-
50 commonly used as the center widget in a QMainWindow to create MDI-
51 applications, but can also be placed in any layout. The following-
52 code adds an area to a main window:-
53-
54 \snippet mdiareasnippets.cpp 0-
55-
56 Unlike the window managers for top-level windows, all window flags-
57 (Qt::WindowFlags) are supported by QMdiArea as long as the flags-
58 are supported by the current widget style. If a specific flag is-
59 not supported by the style (e.g., the-
60 \l{Qt::}{WindowShadeButtonHint}), you can still shade the window-
61 with showShaded().-
62-
63 Subwindows in QMdiArea are instances of QMdiSubWindow. They-
64 are added to an MDI area with addSubWindow(). It is common to pass-
65 a QWidget, which is set as the internal widget, to this function,-
66 but it is also possible to pass a QMdiSubWindow directly.The class-
67 inherits QWidget, and you can use the same API as with a normal-
68 top-level window when programming. QMdiSubWindow also has behavior-
69 that is specific to MDI windows. See the QMdiSubWindow class-
70 description for more details.-
71-
72 A subwindow becomes active when it gets the keyboard focus, or-
73 when setFocus() is called. The user activates a window by moving-
74 focus in the usual ways. The MDI area emits the-
75 subWindowActivated() signal when the active window changes, and-
76 the activeSubWindow() function returns the active subwindow.-
77-
78 The convenience function subWindowList() returns a list of all-
79 subwindows. This information could be used in a popup menu-
80 containing a list of windows, for example.-
81-
82 The subwindows are sorted by the current-
83 \l{QMdiArea::}{WindowOrder}. This is used for the subWindowList()-
84 and for activateNextSubWindow() and activatePreviousSubWindow().-
85 Also, it is used when cascading or tiling the windows with-
86 cascadeSubWindows() and tileSubWindows().-
87-
88 QMdiArea provides two built-in layout strategies for-
89 subwindows: cascadeSubWindows() and tileSubWindows(). Both are-
90 slots and are easily connected to menu entries.-
91-
92 \table-
93 \row \li \inlineimage mdi-cascade.png-
94 \li \inlineimage mdi-tile.png-
95 \endtable-
96-
97 \note The default scroll bar property for QMdiArea is Qt::ScrollBarAlwaysOff.-
98-
99 \sa QMdiSubWindow-
100*/-
101-
102/*!-
103 \fn QMdiArea::subWindowActivated(QMdiSubWindow *window)-
104-
105 QMdiArea emits this signal after \a window has been activated. When \a-
106 window is 0, QMdiArea has just deactivated its last active window, and-
107 there are no active windows on the workspace.-
108-
109 \sa QMdiArea::activeSubWindow()-
110*/-
111-
112/*!-
113 \enum QMdiArea::AreaOption-
114-
115 This enum describes options that customize the behavior of the-
116 QMdiArea.-
117-
118 \value DontMaximizeSubWindowOnActivation When the active subwindow-
119 is maximized, the default behavior is to maximize the next-
120 subwindow that is activated. Set this option if you do not want-
121 this behavior.-
122*/-
123-
124/*!-
125 \enum QMdiArea::WindowOrder-
126-
127 Specifies the criteria to use for ordering the list of child windows-
128 returned by subWindowList(). The functions cascadeSubWindows() and-
129 tileSubWindows() follow this order when arranging the windows.-
130-
131 \value CreationOrder The windows are returned in the order of-
132 their creation.-
133-
134 \value StackingOrder The windows are returned in the order in-
135 which they are stacked, with the top-most window being last in-
136 the list.-
137-
138 \value ActivationHistoryOrder The windows are returned in the order in-
139 which they were activated.-
140-
141 \sa subWindowList()-
142*/-
143-
144/*!-
145 \enum QMdiArea::ViewMode-
146 \since 4.4-
147-
148 This enum describes the view mode of the area; i.e. how sub-windows-
149 will be displayed.-
150-
151 \value SubWindowView Display sub-windows with window frames (default).-
152 \value TabbedView Display sub-windows with tabs in a tab bar.-
153-
154 \sa setViewMode()-
155*/-
156-
157#include "qmdiarea_p.h"-
158-
159#ifndef QT_NO_MDIAREA-
160-
161#include <QApplication>-
162#include <QStyle>-
163#if defined(Q_DEAD_CODE_FROM_QT4_MAC) && !defined(QT_NO_STYLE_MAC)-
164#include <private/qmacstyle_mac_p.h>-
165#endif-
166#include <QChildEvent>-
167#include <QResizeEvent>-
168#include <QScrollBar>-
169#include <QtAlgorithms>-
#include <QMutableVectorIterator>
170#include <QPainter>-
171#include <QFontMetrics>-
172#include <QStyleOption>-
173#include <QDesktopWidget>-
174#include <QDebug>-
175#include <qmath.h>-
176#include <private/qlayoutengine_p.h>-
177-
178#include <algorithm>-
179-
180QT_BEGIN_NAMESPACE-
181-
182using namespace QMdi;-
183-
184// Asserts in debug mode, gives warning otherwise.-
185static bool sanityCheck(const QMdiSubWindow * const child, const char *where)-
186{-
187 if (Q_UNLIKELY(!child))) {
__builtin_expe...child), false)Description
TRUEnever evaluated
FALSEnever evaluated
0
188 const char error[] = "null pointer";-
189 Q_ASSERT_X(false, where, error);-
190 qWarning("%s:%s", where, error);-
191 return false;
never executed: return false;
0
192 }-
193 return true;
never executed: return true;
0
194}-
195-
196static bool sanityCheck(const QList<QWidget *> &widgets, const int index, const char *where)-
197{-
198 if (Q_UNLIKELY(index < 0 || index >= widgets.size())())) {
__builtin_expe...ize()), false)Description
TRUEnever evaluated
FALSEnever evaluated
0
199 const char error[] = "index out of range";-
200 Q_ASSERT_X(false, where, error);-
201 qWarning("%s:%s", where, error);-
202 return false;
never executed: return false;
0
203 }-
204 if (Q_UNLIKELY(!widgets.at(index))))) {
__builtin_expe...ndex)), false)Description
TRUEnever evaluated
FALSEnever evaluated
0
205 const char error[] = "null pointer";-
206 Q_ASSERT_X(false, where, error);-
207 qWarning("%s:%s", where, error);-
208 return false;
never executed: return false;
0
209 }-
210 return true;
never executed: return true;
0
211}-
212-
213static void setIndex(int *index, int candidate, int min, int max, bool isIncreasing)-
214{-
215 if (!index)-
216 return;-
217-
218 if (isIncreasing) {-
219 if (candidate > max)-
220 *index = min;-
221 else-
222 *index = qMax(candidate, min);-
223 } else {-
224 if (candidate < min)-
225 *index = max;-
226 else-
227 *index = qMin(candidate, max);-
228 }-
229 Q_ASSERT(*index >= min && *index <= max);-
230}-
231-
232static inline bool useScrollBar(const QRect &childrenRect, const QSize &maxViewportSize,-
233 Qt::Orientation orientation)-
234{-
235 if (orientation == Qt::Horizontal)-
236 return childrenRect.width() > maxViewportSize.width()-
237 || childrenRect.left() < 0-
238 || childrenRect.right() >= maxViewportSize.width();-
239 else-
240 return childrenRect.height() > maxViewportSize.height()-
241 || childrenRect.top() < 0-
242 || childrenRect.bottom() >= maxViewportSize.height();-
243}-
244-
245// Returns the closest mdi area containing the widget (if any).-
246static inline QMdiArea *mdiAreaParent(QWidget *widget)-
247{-
248 if (!widget)-
249 return 0;-
250-
251 QWidget *parent = widget->parentWidget();-
252 while (parent) {-
253 if (QMdiArea *area = qobject_cast<QMdiArea *>(parent))-
254 return area;-
255 parent = parent->parentWidget();-
256 }-
257 return 0;-
258}-
259-
260#ifndef QT_NO_TABWIDGET-
261static inline QTabBar::Shape tabBarShapeFrom(QTabWidget::TabShape shape, QTabWidget::TabPosition position)-
262{-
263 const bool rounded = (shape == QTabWidget::Rounded);-
264 if (position == QTabWidget::North)-
265 return rounded ? QTabBar::RoundedNorth : QTabBar::TriangularNorth;-
266 if (position == QTabWidget::South)-
267 return rounded ? QTabBar::RoundedSouth : QTabBar::TriangularSouth;-
268 if (position == QTabWidget::East)-
269 return rounded ? QTabBar::RoundedEast : QTabBar::TriangularEast;-
270 if (position == QTabWidget::West)-
271 return rounded ? QTabBar::RoundedWest : QTabBar::TriangularWest;-
272 return QTabBar::RoundedNorth;-
273}-
274#endif // QT_NO_TABWIDGET-
275-
276static inline QString tabTextFor(QMdiSubWindow *subWindow)-
277{-
278 if (!subWindow)-
279 return QString();-
280-
281 QString title = subWindow->windowTitle();-
282 if (subWindow->isWindowModified()) {-
283 title.replace(QLatin1String("[*]"), QLatin1String("*"));-
284 } else {-
285 extern QString qt_setWindowTitle_helperHelper(const QString&, const QWidget*);-
286 title = qt_setWindowTitle_helperHelper(title, subWindow);-
287 }-
288-
289 return title.isEmpty() ? QMdiArea::tr("(Untitled)") : title;-
290}-
291-
292/*!-
293 \internal-
294*/-
295void RegularTiler::rearrange(QList<QWidget *> &widgets, const QRect &domain) const-
296{-
297 if (widgets.isEmpty())-
298 return;-
299-
300 const int n = widgets.size();-
301 const int ncols = qMax(qCeil(qSqrt(qreal(n))), 1);-
302 const int nrows = qMax((n % ncols) ? (n / ncols + 1) : (n / ncols), 1);-
303 const int nspecial = (n % ncols) ? (ncols - n % ncols) : 0;-
304 const int dx = domain.width() / ncols;-
305 const int dy = domain.height() / nrows;-
306-
307 int i = 0;-
308 for (int row = 0; row < nrows; ++row) {-
309 const int y1 = int(row * (dy + 1));-
310 for (int col = 0; col < ncols; ++col) {-
311 if (row == 1 && col < nspecial)-
312 continue;-
313 const int x1 = int(col * (dx + 1));-
314 int x2 = int(x1 + dx);-
315 int y2 = int(y1 + dy);-
316 if (row == 0 && col < nspecial) {-
317 y2 *= 2;-
318 if (nrows != 2)-
319 y2 += 1;-
320 else-
321 y2 = domain.bottom();-
322 }-
323 if (col == ncols - 1 && x2 != domain.right())-
324 x2 = domain.right();-
325 if (row == nrows - 1 && y2 != domain.bottom())-
326 y2 = domain.bottom();-
327 if (!sanityCheck(widgets, i, "RegularTiler"))-
328 continue;-
329 QWidget *widget = widgets.at(i++);-
330 QRect newGeometry = QRect(QPoint(x1, y1), QPoint(x2, y2));-
331 widget->setGeometry(QStyle::visualRect(widget->layoutDirection(), domain, newGeometry));-
332 }-
333 }-
334}-
335-
336/*!-
337 \internal-
338*/-
339void SimpleCascader::rearrange(QList<QWidget *> &widgets, const QRect &domain) const-
340{-
341 if (widgets.isEmpty())-
342 return;-
343-
344 // Tunables:-
345 const int topOffset = 0;-
346 const int bottomOffset = 50;-
347 const int leftOffset = 0;-
348 const int rightOffset = 100;-
349 const int dx = 10;-
350-
351 QStyleOptionTitleBar options;-
352 options.initFrom(widgets.at(0));-
353 int titleBarHeight = widgets.at(0)->style()->pixelMetric(QStyle::PM_TitleBarHeight, &options, widgets.at(0));-
354 const QFontMetrics fontMetrics = QFontMetrics(QApplication::font("QMdiSubWindowTitleBar"));-
355 const int dy = qMax(titleBarHeight - (titleBarHeight - fontMetrics.height()) / 2, 1)-
356 + widgets.at(0)->style()->pixelMetric(QStyle::PM_FocusFrameVMargin, 0, widgets.at(0));-
357-
358 const int n = widgets.size();-
359 const int nrows = qMax((domain.height() - (topOffset + bottomOffset)) / dy, 1);-
360 const int ncols = qMax(n / nrows + ((n % nrows) ? 1 : 0), 1);-
361 const int dcol = (domain.width() - (leftOffset + rightOffset)) / ncols;-
362-
363 int i = 0;-
364 for (int row = 0; row < nrows; ++row) {-
365 for (int col = 0; col < ncols; ++col) {-
366 const int x = leftOffset + row * dx + col * dcol;-
367 const int y = topOffset + row * dy;-
368 if (!sanityCheck(widgets, i, "SimpleCascader"))-
369 continue;-
370 QWidget *widget = widgets.at(i++);-
371 QRect newGeometry = QRect(QPoint(x, y), widget->sizeHint());-
372 widget->setGeometry(QStyle::visualRect(widget->layoutDirection(), domain, newGeometry));-
373 if (i == n)-
374 return;-
375 }-
376 }-
377}-
378-
379/*!-
380 \internal-
381*/-
382void IconTiler::rearrange(QList<QWidget *> &widgets, const QRect &domain) const-
383{-
384 if (widgets.isEmpty() || !sanityCheck(widgets, 0, "IconTiler"))
widgets.isEmpty()Description
TRUEnever evaluated
FALSEnever evaluated
!sanityCheck(w..., "IconTiler")Description
TRUEnever evaluated
FALSEnever evaluated
0
385 return;
never executed: return;
0
386-
387 const int n = widgets.size();-
388 const int width = qMax(widgets.at(0)->width();(), 1);-
389 const int height = widgets.at(0)->height();-
390 const int ncols = qMax(domain.width() / width, 1);-
391 const int nrows = n / ncols + ((n % ncols) ? 1 : 0);
(n % ncols)Description
TRUEnever evaluated
FALSEnever evaluated
0
392-
393 int i = 0;-
394 for (int row = 0; row < nrows; ++row) {
row < nrowsDescription
TRUEnever evaluated
FALSEnever evaluated
0
395 for (int col = 0; col < ncols; ++col) {
col < ncolsDescription
TRUEnever evaluated
FALSEnever evaluated
0
396 const int x = col * width;-
397 const int y = domain.height() - height - row * height;-
398 if (!sanityCheck(widgets, i, "IconTiler"))
!sanityCheck(w..., "IconTiler")Description
TRUEnever evaluated
FALSEnever evaluated
0
399 continue;
never executed: continue;
0
400 QWidget *widget = widgets.at(i++);-
401 QPoint newPos(x, y);-
402 QRect newGeometry = QRect(newPos.x(), newPos.y(), widget->width(), widget->height());-
403 widget->setGeometry(QStyle::visualRect(widget->layoutDirection(), domain, newGeometry));-
404 if (i == n)
i == nDescription
TRUEnever evaluated
FALSEnever evaluated
0
405 return;
never executed: return;
0
406 }
never executed: end of block
0
407 }
never executed: end of block
0
408}
never executed: end of block
0
409-
410/*!-
411 \internal-
412 Calculates the accumulated overlap (intersection area) between 'source' and 'rects'.-
413*/-
414int MinOverlapPlacer::accumulatedOverlap(const QRect &source, const QVector<QRect> &rects)-
415{-
416 int accOverlap = 0;-
417 foreachfor (const QRect &rect ,: rects) {-
418 QRect intersection = source.intersected(rect);-
419 accOverlap += intersection.width() * intersection.height();-
420 }
never executed: end of block
0
421 return accOverlap;
never executed: return accOverlap;
0
422}-
423-
424-
425/*!-
426 \internal-
427 Finds among 'source' the rectangle with the minimum accumulated overlap with the-
428 rectangles in 'rects'.-
429*/-
430QRect MinOverlapPlacer::findMinOverlapRect(const QVector<QRect> &source, const QVector<QRect> &rects)-
431{-
432 int minAccOverlap = -1;-
433 QRect minAccOverlapRect;-
434 foreachfor (const QRect &srcRect ,: source) {-
435 const int accOverlap = accumulatedOverlap(srcRect, rects);-
436 if (accOverlap < minAccOverlap || minAccOverlap == -1) {
accOverlap < minAccOverlapDescription
TRUEnever evaluated
FALSEnever evaluated
minAccOverlap == -1Description
TRUEnever evaluated
FALSEnever evaluated
0
437 minAccOverlap = accOverlap;-
438 minAccOverlapRect = srcRect;-
439 }
never executed: end of block
0
440 }
never executed: end of block
0
441 return minAccOverlapRect;
never executed: return minAccOverlapRect;
0
442}-
443-
444/*!-
445 \internal-
446 Gets candidates for the final placement.-
447*/-
448QVector<QRect> MinOverlapPlacer::getCandidatePlacements(const QSize &size, const QVector<QRect> &rects,-
449 const QRect &domain)-
450{-
451 QVector<QRect> result;-
452-
453 QVector<int> xlist;-
454 xlist.reserve(2 + rects.size());-
455 xlist << domain.left() << domain.right() - size.width() + 1;-
456-
457 QVector<int> ylist;-
458 ylist.reserve(2 + rects.size());-
459 ylist << domain.top();-
460 if (domain.bottom() - size.height() + 1 >= 0)
domain.bottom(...ght() + 1 >= 0Description
TRUEnever evaluated
FALSEnever evaluated
0
461 ylist << domain.bottom() - size.height() + 1;
never executed: ylist << domain.bottom() - size.height() + 1;
0
462-
463 foreachfor (const QRect &rect ,: rects) {-
464 xlist << rect.right() + 1;-
465 ylist << rect.bottom() + 1;-
466 }
never executed: end of block
0
467-
468 std::sort(xlist.begin(), xlist.end());-
469 xlist.erase(std::unique(xlist.begin(), xlist.end()), xlist.end());-
470-
471 std::sort(ylist.begin(), ylist.end());-
472 ylist.erase(std::unique(ylist.begin(), ylist.end()), ylist.end());-
473-
474 result.reserve(ylist.size() * xlist.size());-
475 foreach (int y, ylist)-
476 foreach (int x, xlist)-
477 result << QRect(QPoint(x, y), size);
never executed: result << QRect(QPoint(x, y), size);
0
478 return result;
never executed: return result;
0
479}-
480-
481/*!-
482 \internal-
483 Finds all rectangles in 'source' not completely inside 'domain'. The result is stored-
484 in 'result' and also removed from 'source'.-
485*/-
486QVector<QRect> MinOverlapPlacer::findNonInsiders(const QRect &domain, QVector<QRect> &source)-
487{-
488 const auto containedInDomain =-
489 [domain](const QRect &srcRect
never executed: return domain.contains(srcRect);
) { return domain.contains(srcRect); };
never executed: return domain.contains(srcRect);
0
490-
491 const auto firstOut = std::stable_partition(source.begin(), source.end(), containedInDomain);-
492-
493 QVector<QRect> result;-
494 result.reserve(source.size());-
QMutableVectorIterator<QRect> it(sourceend() - firstOut);
495 whilestd::copy(it.hasNext()) {-
const QRect srcRect = it.next();
if (!domainfirstOut, source.containsend(), std::back_inserter(srcRect)) {result<< srcRect;
it));
496-
497 source.remove();-
}
}erase(firstOut, source.end());
498-
499 return result;
never executed: return result;
0
500}-
501-
502/*!-
503 \internal-
504 Finds all rectangles in 'source' that overlaps 'domain' by the maximum overlap area-
505 between 'domain' and any rectangle in 'source'. The result is stored in 'result'.-
506*/-
507QVector<QRect> MinOverlapPlacer::findMaxOverlappers(const QRect &domain, const QVector<QRect> &source)-
508{-
509 QVector<QRect> result;-
510 result.reserve(source.size());-
511-
512 int maxOverlap = -1;-
513 foreachfor (const QRect &srcRect ,: source) {-
514 QRect intersection = domain.intersected(srcRect);-
515 const int overlap = intersection.width() * intersection.height();-
516 if (overlap >= maxOverlap || maxOverlap == -1) {
overlap >= maxOverlapDescription
TRUEnever evaluated
FALSEnever evaluated
maxOverlap == -1Description
TRUEnever evaluated
FALSEnever evaluated
0
517 if (overlap > maxOverlap) {
overlap > maxOverlapDescription
TRUEnever evaluated
FALSEnever evaluated
0
518 maxOverlap = overlap;-
519 result.clear();-
520 }
never executed: end of block
0
521 result << srcRect;-
522 }
never executed: end of block
0
523 }
never executed: end of block
0
524-
525 return result;
never executed: return result;
0
526}-
527-
528/*!-
529 \internal-
530 Finds among the rectangles in 'source' the best placement. Here, 'best' means the-
531 placement that overlaps the rectangles in 'rects' as little as possible while at the-
532 same time being as much as possible inside 'domain'.-
533*/-
534QPoint MinOverlapPlacer::findBestPlacement(const QRect &domain, const QVector<QRect> &rects,-
535 QVector<QRect> &source)-
536{-
537 const QVector<QRect> nonInsiders = findNonInsiders(domain, source);-
538-
539 if (!source.empty())-
540 return findMinOverlapRect(source, rects).topLeft();-
541-
542 QVector<QRect> maxOverlappers = findMaxOverlappers(domain, nonInsiders);-
543 return findMinOverlapRect(maxOverlappers, rects).topLeft();-
544}-
545-
546-
547/*!-
548 \internal-
549 Places the rectangle defined by 'size' relative to 'rects' and 'domain' so that it-
550 overlaps 'rects' as little as possible and 'domain' as much as possible.-
551 Returns the position of the resulting rectangle.-
552*/-
553QPoint MinOverlapPlacer::place(const QSize &size, const QVector<QRect> &rects,-
554 const QRect &domain) const-
555{-
556 if (size.isEmpty() || !domain.isValid())
size.isEmpty()Description
TRUEnever evaluated
FALSEnever evaluated
!domain.isValid()Description
TRUEnever evaluated
FALSEnever evaluated
0
557 return QPoint();
never executed: return QPoint();
0
558 foreachfor (const QRect &rect ,: rects) {-
559 if (!rect.isValid())
!rect.isValid()Description
TRUEnever evaluated
FALSEnever evaluated
0
560 return QPoint();
never executed: return QPoint();
0
561 }
never executed: end of block
0
562-
563 QVector<QRect> candidates = getCandidatePlacements(size, rects, domain);-
564 return findBestPlacement(domain, rects, candidates);
never executed: return findBestPlacement(domain, rects, candidates);
0
565}-
566-
567#ifndef QT_NO_TABBAR-
568class QMdiAreaTabBar : public QTabBar-
569{-
570public:-
571 QMdiAreaTabBar(QWidget *parent) : QTabBar(parent) {}-
572-
573protected:-
574 void mousePressEvent(QMouseEvent *event) Q_DECL_OVERRIDE;-
575#ifndef QT_NO_CONTEXTMENU-
576 void contextMenuEvent(QContextMenuEvent *event) Q_DECL_OVERRIDE;-
577#endif-
578-
579private:-
580 QMdiSubWindow *subWindowFromIndex(int index) const;-
581};-
582-
583/*!-
584 \internal-
585*/-
586void QMdiAreaTabBar::mousePressEvent(QMouseEvent *event)-
587{-
588 if (event->button() != Qt::MidButton) {-
589 QTabBar::mousePressEvent(event);-
590 return;-
591 }-
592-
593 QMdiSubWindow *subWindow = subWindowFromIndex(tabAt(event->pos()));-
594 if (!subWindow) {-
595 event->ignore();-
596 return;-
597 }-
598-
599 subWindow->close();-
600}-
601-
602#ifndef QT_NO_CONTEXTMENU-
603/*!-
604 \internal-
605*/-
606void QMdiAreaTabBar::contextMenuEvent(QContextMenuEvent *event)-
607{-
608 QPointer<QMdiSubWindow> subWindow = subWindowFromIndex(tabAt(event->pos()));-
609 if (!subWindow || subWindow->isHidden()) {-
610 event->ignore();-
611 return;-
612 }-
613-
614#ifndef QT_NO_MENU-
615 QMdiSubWindowPrivate *subWindowPrivate = subWindow->d_func();-
616 if (!subWindowPrivate->systemMenu) {-
617 event->ignore();-
618 return;-
619 }-
620-
621 QMdiSubWindow *currentSubWindow = subWindowFromIndex(currentIndex());-
622 Q_ASSERT(currentSubWindow);-
623-
624 // We don't want these actions to show up in the system menu when the-
625 // current sub-window is maximized, i.e. covers the entire viewport.-
626 if (currentSubWindow->isMaximized()) {-
627 subWindowPrivate->setVisible(QMdiSubWindowPrivate::MoveAction, false);-
628 subWindowPrivate->setVisible(QMdiSubWindowPrivate::ResizeAction, false);-
629 subWindowPrivate->setVisible(QMdiSubWindowPrivate::MinimizeAction, false);-
630 subWindowPrivate->setVisible(QMdiSubWindowPrivate::MaximizeAction, false);-
631 subWindowPrivate->setVisible(QMdiSubWindowPrivate::RestoreAction, false);-
632 subWindowPrivate->setVisible(QMdiSubWindowPrivate::StayOnTopAction, false);-
633 }-
634-
635 // Show system menu.-
636 subWindowPrivate->systemMenu->exec(event->globalPos());-
637 if (!subWindow)-
638 return;-
639-
640 // Restore action visibility.-
641 subWindowPrivate->updateActions();-
642#endif // QT_NO_MENU-
643}-
644#endif // QT_NO_CONTEXTMENU-
645-
646/*!-
647 \internal-
648*/-
649QMdiSubWindow *QMdiAreaTabBar::subWindowFromIndex(int index) const-
650{-
651 if (index < 0 || index >= count())-
652 return 0;-
653-
654 QMdiArea *mdiArea = qobject_cast<QMdiArea *>(parentWidget());-
655 Q_ASSERT(mdiArea);-
656-
657 const QList<QMdiSubWindow *> subWindows = mdiArea->subWindowList();-
658 Q_ASSERT(index < subWindows.size());-
659-
660 QMdiSubWindow *subWindow = mdiArea->subWindowList().at(index);-
661 Q_ASSERT(subWindow);-
662-
663 return subWindow;-
664}-
665#endif // QT_NO_TABBAR-
666-
667/*!-
668 \internal-
669*/-
670QMdiAreaPrivate::QMdiAreaPrivate()-
671 : cascader(0),-
672 regularTiler(0),-
673 iconTiler(0),-
674 placer(0),-
675#ifndef QT_NO_RUBBERBAND-
676 rubberBand(0),-
677#endif-
678#ifndef QT_NO_TABBAR-
679 tabBar(0),-
680#endif-
681 activationOrder(QMdiArea::CreationOrder),-
682 viewMode(QMdiArea::SubWindowView),-
683#ifndef QT_NO_TABBAR-
684 documentMode(false),-
685 tabsClosable(false),-
686 tabsMovable(false),-
687#endif-
688#ifndef QT_NO_TABWIDGET-
689 tabShape(QTabWidget::Rounded),-
690 tabPosition(QTabWidget::North),-
691#endif-
692 ignoreGeometryChange(false),-
693 ignoreWindowStateChange(false),-
694 isActivated(false),-
695 isSubWindowsTiled(false),-
696 showActiveWindowMaximized(false),-
697 tileCalledFromResizeEvent(false),-
698 updatesDisabledByUs(false),-
699 inViewModeChange(false),-
700 indexToNextWindow(-1),-
701 indexToPreviousWindow(-1),-
702 indexToHighlighted(-1),-
703 indexToLastActiveTab(-1),-
704 resizeTimerId(-1),-
705 tabToPreviousTimerId(-1)-
706{-
707}-
708-
709/*!-
710 \internal-
711*/-
712void QMdiAreaPrivate::_q_deactivateAllWindows(QMdiSubWindow *aboutToActivate)-
713{-
714 if (ignoreWindowStateChange)-
715 return;-
716-
717 Q_Q(QMdiArea);-
718 if (!aboutToActivate)-
719 aboutToBecomeActive = qobject_cast<QMdiSubWindow *>(q->sender());-
720 else-
721 aboutToBecomeActive = aboutToActivate;-
722 Q_ASSERT(aboutToBecomeActive);-
723-
724 foreach (QMdiSubWindow *child, childWindows) {-
725 if (!sanityCheck(child, "QMdiArea::deactivateAllWindows") || aboutToBecomeActive == child)-
726 continue;-
727 // We don't want to handle signals caused by child->showNormal().-
728 ignoreWindowStateChange = true;-
729 if(!(options & QMdiArea::DontMaximizeSubWindowOnActivation) && !showActiveWindowMaximized)-
730 showActiveWindowMaximized = child->isMaximized() && child->isVisible();-
731 if (showActiveWindowMaximized && child->isMaximized()) {-
732 if (q->updatesEnabled()) {-
733 updatesDisabledByUs = true;-
734 q->setUpdatesEnabled(false);-
735 }-
736 child->showNormal();-
737 }-
738 if (child->isMinimized() && !child->isShaded() && !windowStaysOnTop(child))-
739 child->lower();-
740 ignoreWindowStateChange = false;-
741 child->d_func()->setActive(false);-
742 }-
743}-
744-
745/*!-
746 \internal-
747*/-
748void QMdiAreaPrivate::_q_processWindowStateChanged(Qt::WindowStates oldState,-
749 Qt::WindowStates newState)-
750{-
751 if (ignoreWindowStateChange)-
752 return;-
753-
754 Q_Q(QMdiArea);-
755 QMdiSubWindow *child = qobject_cast<QMdiSubWindow *>(q->sender());-
756 if (!child)-
757 return;-
758-
759 // windowActivated-
760 if (!(oldState & Qt::WindowActive) && (newState & Qt::WindowActive))-
761 emitWindowActivated(child);-
762 // windowDeactivated-
763 else if ((oldState & Qt::WindowActive) && !(newState & Qt::WindowActive))-
764 resetActiveWindow(child);-
765-
766 // windowMinimized-
767 if (!(oldState & Qt::WindowMinimized) && (newState & Qt::WindowMinimized)) {-
768 isSubWindowsTiled = false;-
769 arrangeMinimizedSubWindows();-
770 // windowMaximized-
771 } else if (!(oldState & Qt::WindowMaximized) && (newState & Qt::WindowMaximized)) {-
772 internalRaise(child);-
773 // windowRestored-
774 } else if (!(newState & (Qt::WindowMaximized | Qt::WindowMinimized))) {-
775 internalRaise(child);-
776 if (oldState & Qt::WindowMinimized)-
777 arrangeMinimizedSubWindows();-
778 }-
779}-
780-
781void QMdiAreaPrivate::_q_currentTabChanged(int index)-
782{-
783#ifdef QT_NO_TABBAR-
784 Q_UNUSED(index);-
785#else-
786 if (!tabBar || index < 0)-
787 return;-
788-
789 // If the previous active sub-window was hidden, disable the tab.-
790 if (indexToLastActiveTab >= 0 && indexToLastActiveTab < tabBar->count()-
791 && indexToLastActiveTab < childWindows.count()) {-
792 QMdiSubWindow *lastActive = childWindows.at(indexToLastActiveTab);-
793 if (lastActive && lastActive->isHidden())-
794 tabBar->setTabEnabled(indexToLastActiveTab, false);-
795 }-
796-
797 indexToLastActiveTab = index;-
798 Q_ASSERT(childWindows.size() > index);-
799 QMdiSubWindow *subWindow = childWindows.at(index);-
800 Q_ASSERT(subWindow);-
801 activateWindow(subWindow);-
802#endif // QT_NO_TABBAR-
803}-
804-
805void QMdiAreaPrivate::_q_closeTab(int index)-
806{-
807#ifdef QT_NO_TABBAR-
808 Q_UNUSED(index);-
809#else-
810 QMdiSubWindow *subWindow = childWindows.at(index);-
811 Q_ASSERT(subWindow);-
812 subWindow->close();-
813#endif // QT_NO_TABBAR-
814}-
815-
816void QMdiAreaPrivate::_q_moveTab(int from, int to)-
817{-
818#ifdef QT_NO_TABBAR-
819 Q_UNUSED(from);-
820 Q_UNUSED(to);-
821#else-
822 childWindows.move(from, to);-
823#endif // QT_NO_TABBAR-
824}-
825-
826/*!-
827 \internal-
828*/-
829void QMdiAreaPrivate::appendChild(QMdiSubWindow *child)-
830{-
831 Q_Q(QMdiArea);-
832 Q_ASSERT(child && childWindows.indexOf(child) == -1);-
833-
834 if (child->parent() != viewport)-
835 child->setParent(viewport, child->windowFlags());-
836 childWindows.append(QPointer<QMdiSubWindow>(child));-
837-
838 if (!child->testAttribute(Qt::WA_Resized) && q->isVisible()) {-
839 QSize newSize(child->sizeHint().boundedTo(viewport->size()));-
840 child->resize(newSize.expandedTo(qSmartMinSize(child)));-
841 }-
842-
843 if (!placer)-
844 placer = new MinOverlapPlacer;-
845 place(placer, child);-
846-
847 if (hbarpolicy != Qt::ScrollBarAlwaysOff)-
848 child->setOption(QMdiSubWindow::AllowOutsideAreaHorizontally, true);-
849 else-
850 child->setOption(QMdiSubWindow::AllowOutsideAreaHorizontally, false);-
851-
852 if (vbarpolicy != Qt::ScrollBarAlwaysOff)-
853 child->setOption(QMdiSubWindow::AllowOutsideAreaVertically, true);-
854 else-
855 child->setOption(QMdiSubWindow::AllowOutsideAreaVertically, false);-
856-
857 internalRaise(child);-
858 indicesToActivatedChildren.prepend(childWindows.size() - 1);-
859 Q_ASSERT(indicesToActivatedChildren.size() == childWindows.size());-
860-
861#ifndef QT_NO_TABBAR-
862 if (tabBar) {-
863 tabBar->addTab(child->windowIcon(), tabTextFor(child));-
864 updateTabBarGeometry();-
865 if (childWindows.count() == 1 && !(options & QMdiArea::DontMaximizeSubWindowOnActivation))-
866 showActiveWindowMaximized = true;-
867 }-
868#endif-
869-
870 if (!(child->windowFlags() & Qt::SubWindow))-
871 child->setWindowFlags(Qt::SubWindow);-
872 child->installEventFilter(q);-
873-
874 QObject::connect(child, SIGNAL(aboutToActivate()), q, SLOT(_q_deactivateAllWindows()));-
875 QObject::connect(child, SIGNAL(windowStateChanged(Qt::WindowStates,Qt::WindowStates)),-
876 q, SLOT(_q_processWindowStateChanged(Qt::WindowStates,Qt::WindowStates)));-
877}-
878-
879/*!-
880 \internal-
881*/-
882void QMdiAreaPrivate::place(Placer *placer, QMdiSubWindow *child)-
883{-
884 if (!placer || !child)-
885 return;-
886-
887 Q_Q(QMdiArea);-
888 if (!q->isVisible()) {-
889 // The window is only laid out when it's added to QMdiArea,-
890 // so there's no need to check that we don't have it in the-
891 // list already. appendChild() ensures that.-
892 pendingPlacements.append(child);-
893 return;-
894 }-
895-
896 QVector<QRect> rects;-
897 rects.reserve(childWindows.size());-
898 QRect parentRect = q->rect();-
899 foreach (QMdiSubWindow *window, childWindows) {-
900 if (!sanityCheck(window, "QMdiArea::place") || window == child || !window->isVisibleTo(q)-
901 || !window->testAttribute(Qt::WA_Moved)) {-
902 continue;-
903 }-
904 QRect occupiedGeometry;-
905 if (window->isMaximized()) {-
906 occupiedGeometry = QRect(window->d_func()->oldGeometry.topLeft(),-
907 window->d_func()->restoreSize);-
908 } else {-
909 occupiedGeometry = window->geometry();-
910 }-
911 rects.append(QStyle::visualRect(child->layoutDirection(), parentRect, occupiedGeometry));-
912 }-
913 QPoint newPos = placer->place(child->size(), rects, parentRect);-
914 QRect newGeometry = QRect(newPos.x(), newPos.y(), child->width(), child->height());-
915 child->setGeometry(QStyle::visualRect(child->layoutDirection(), parentRect, newGeometry));-
916}-
917-
918/*!-
919 \internal-
920*/-
921void QMdiAreaPrivate::rearrange(Rearranger *rearranger)-
922{-
923 if (!rearranger)
!rearrangerDescription
TRUEnever evaluated
FALSEnever evaluated
0
924 return;
never executed: return;
0
925-
926 Q_Q(QMdiArea);-
927 if (!q->isVisible()) {
!q->isVisible()Description
TRUEnever evaluated
FALSEnever evaluated
0
928 // Compress if we already have the rearranger in the list.-
929 int index = pendingRearrangements.indexOf(rearranger);-
930 if (index != -1)
index != -1Description
TRUEnever evaluated
FALSEnever evaluated
0
931 pendingRearrangements.move(index, pendingRearrangements.size() - 1);
never executed: pendingRearrangements.move(index, pendingRearrangements.size() - 1);
0
932 else-
933 pendingRearrangements.append(rearranger);
never executed: pendingRearrangements.append(rearranger);
0
934 return;
never executed: return;
0
935 }-
936-
937 QList<QWidget *> widgets;-
938 const bool reverseList = rearranger->type() == Rearranger::RegularTiler;-
939 const QList<QMdiSubWindow *> subWindows = subWindowList(activationOrder, reverseList);-
940 QSize minSubWindowSize;-
941 foreach (QMdiSubWindow *child, subWindows) {-
942 if (!sanityCheck(child, "QMdiArea::rearrange") || !child->isVisible())
!sanityCheck(c...a::rearrange")Description
TRUEnever evaluated
FALSEnever evaluated
!child->isVisible()Description
TRUEnever evaluated
FALSEnever evaluated
0
943 continue;
never executed: continue;
0
944 if (rearranger->type() == Rearranger::IconTiler) {
rearranger->ty...ger::IconTilerDescription
TRUEnever evaluated
FALSEnever evaluated
0
945 if (child->isMinimized() && !child->isShaded() && !(child->windowFlags() & Qt::FramelessWindowHint))())
child->isMinimized()Description
TRUEnever evaluated
FALSEnever evaluated
!child->isShaded()Description
TRUEnever evaluated
FALSEnever evaluated
0
946 widgets.append(child);
never executed: widgets.append(child);
0
947 } else {
never executed: end of block
0
948 if (child->isMinimized() && !child->isShaded())
child->isMinimized()Description
TRUEnever evaluated
FALSEnever evaluated
!child->isShaded()Description
TRUEnever evaluated
FALSEnever evaluated
0
949 continue;
never executed: continue;
0
950 if (child->isMaximized() || child->isShaded())
child->isMaximized()Description
TRUEnever evaluated
FALSEnever evaluated
child->isShaded()Description
TRUEnever evaluated
FALSEnever evaluated
0
951 child->showNormal();
never executed: child->showNormal();
0
952 minSubWindowSize = minSubWindowSize.expandedTo(child->minimumSize())-
953 .expandedTo(child->d_func()->internalMinimumSize);-
954 widgets.append(child);-
955 }
never executed: end of block
0
956 }-
957-
958 if (active && rearranger->type() == Rearranger::RegularTiler) {
activeDescription
TRUEnever evaluated
FALSEnever evaluated
rearranger->ty...::RegularTilerDescription
TRUEnever evaluated
FALSEnever evaluated
0
959 // Move active window in front if necessary. That's the case if we-
960 // have any windows with staysOnTopHint set.-
961 int indexToActive = widgets.indexOf((QWidget *)active);-
962 if (indexToActive > 0)
indexToActive > 0Description
TRUEnever evaluated
FALSEnever evaluated
0
963 widgets.move(indexToActive, 0);
never executed: widgets.move(indexToActive, 0);
0
964 }
never executed: end of block
0
965-
966 QRect domain = viewport->rect();-
967 if (rearranger->type() == Rearranger::RegularTiler && !widgets.isEmpty())
rearranger->ty...::RegularTilerDescription
TRUEnever evaluated
FALSEnever evaluated
!widgets.isEmpty()Description
TRUEnever evaluated
FALSEnever evaluated
0
968 domain = resizeToMinimumTileSize(minSubWindowSize, widgets.count());
never executed: domain = resizeToMinimumTileSize(minSubWindowSize, widgets.count());
0
969-
970 rearranger->rearrange(widgets, domain);-
971-
972 if (rearranger->type() == Rearranger::RegularTiler && !widgets.isEmpty()) {
rearranger->ty...::RegularTilerDescription
TRUEnever evaluated
FALSEnever evaluated
!widgets.isEmpty()Description
TRUEnever evaluated
FALSEnever evaluated
0
973 isSubWindowsTiled = true;-
974 updateScrollBars();-
975 } else if (rearranger->type() == Rearranger::SimpleCascader) {
never executed: end of block
rearranger->ty...SimpleCascaderDescription
TRUEnever evaluated
FALSEnever evaluated
0
976 isSubWindowsTiled = false;-
977 }
never executed: end of block
0
978}
never executed: end of block
0
979-
980/*!-
981 \internal-
982-
983 Arranges all minimized windows at the bottom of the workspace.-
984*/-
985void QMdiAreaPrivate::arrangeMinimizedSubWindows()-
986{-
987 if (!iconTiler)-
988 iconTiler = new IconTiler;-
989 rearrange(iconTiler);-
990}-
991-
992/*!-
993 \internal-
994*/-
995void QMdiAreaPrivate::activateWindow(QMdiSubWindow *child)-
996{-
997 if (childWindows.isEmpty()) {-
998 Q_ASSERT(!child);-
999 Q_ASSERT(!active);-
1000 return;-
1001 }-
1002-
1003 if (!child) {-
1004 if (active) {-
1005 Q_ASSERT(active->d_func()->isActive);-
1006 active->d_func()->setActive(false);-
1007 resetActiveWindow();-
1008 }-
1009 return;-
1010 }-
1011-
1012 if (child->isHidden() || child == active)-
1013 return;-
1014 child->d_func()->setActive(true);-
1015}-
1016-
1017/*!-
1018 \internal-
1019*/-
1020void QMdiAreaPrivate::activateCurrentWindow()-
1021{-
1022 QMdiSubWindow *current = q_func()->currentSubWindow();-
1023 if (current && !isExplicitlyDeactivated(current)) {-
1024 current->d_func()->activationEnabled = true;-
1025 current->d_func()->setActive(true, /*changeFocus=*/false);-
1026 }-
1027}-
1028-
1029void QMdiAreaPrivate::activateHighlightedWindow()-
1030{-
1031 if (indexToHighlighted < 0)-
1032 return;-
1033-
1034 Q_ASSERT(indexToHighlighted < childWindows.size());-
1035 if (tabToPreviousTimerId != -1)-
1036 activateWindow(nextVisibleSubWindow(-1, QMdiArea::ActivationHistoryOrder));-
1037 else-
1038 activateWindow(childWindows.at(indexToHighlighted));-
1039#ifndef QT_NO_RUBBERBAND-
1040 hideRubberBand();-
1041#endif-
1042}-
1043-
1044/*!-
1045 \internal-
1046*/-
1047void QMdiAreaPrivate::emitWindowActivated(QMdiSubWindow *activeWindow)-
1048{-
1049 Q_Q(QMdiArea);-
1050 Q_ASSERT(activeWindow);-
1051 if (activeWindow == active)-
1052 return;-
1053 Q_ASSERT(activeWindow->d_func()->isActive);-
1054-
1055 if (!aboutToBecomeActive)-
1056 _q_deactivateAllWindows(activeWindow);-
1057 Q_ASSERT(aboutToBecomeActive);-
1058-
1059 // This is true only if 'DontMaximizeSubWindowOnActivation' is disabled-
1060 // and the previous active window was maximized.-
1061 if (showActiveWindowMaximized) {-
1062 if (!activeWindow->isMaximized())-
1063 activeWindow->showMaximized();-
1064 showActiveWindowMaximized = false;-
1065 }-
1066-
1067 // Put in front to update activation order.-
1068 const int indexToActiveWindow = childWindows.indexOf(activeWindow);-
1069 Q_ASSERT(indexToActiveWindow != -1);-
1070 const int index = indicesToActivatedChildren.indexOf(indexToActiveWindow);-
1071 Q_ASSERT(index != -1);-
1072 indicesToActivatedChildren.move(index, 0);-
1073 internalRaise(activeWindow);-
1074-
1075 if (updatesDisabledByUs) {-
1076 q->setUpdatesEnabled(true);-
1077 updatesDisabledByUs = false;-
1078 }-
1079-
1080 Q_ASSERT(aboutToBecomeActive == activeWindow);-
1081 active = activeWindow;-
1082 aboutToBecomeActive = 0;-
1083 Q_ASSERT(active->d_func()->isActive);-
1084-
1085#ifndef QT_NO_TABBAR-
1086 if (tabBar && tabBar->currentIndex() != indexToActiveWindow)-
1087 tabBar->setCurrentIndex(indexToActiveWindow);-
1088#endif-
1089-
1090 if (active->isMaximized() && scrollBarsEnabled())-
1091 updateScrollBars();-
1092-
1093 emit q->subWindowActivated(active);-
1094}-
1095-
1096/*!-
1097 \internal-
1098*/-
1099void QMdiAreaPrivate::resetActiveWindow(QMdiSubWindow *deactivatedWindow)-
1100{-
1101 Q_Q(QMdiArea);-
1102 if (deactivatedWindow) {-
1103 if (deactivatedWindow != active)-
1104 return;-
1105 active = 0;-
1106 if ((aboutToBecomeActive || isActivated || lastWindowAboutToBeDestroyed())-
1107 && !isExplicitlyDeactivated(deactivatedWindow) && !q->window()->isMinimized()) {-
1108 return;-
1109 }-
1110 emit q->subWindowActivated(0);-
1111 return;-
1112 }-
1113-
1114 if (aboutToBecomeActive)-
1115 return;-
1116-
1117 active = 0;-
1118 emit q->subWindowActivated(0);-
1119}-
1120-
1121/*!-
1122 \internal-
1123*/-
1124void QMdiAreaPrivate::updateActiveWindow(int removedIndex, bool activeRemoved)-
1125{-
1126 Q_ASSERT(indicesToActivatedChildren.size() == childWindows.size());-
1127-
1128#ifndef QT_NO_TABBAR-
1129 if (tabBar && removedIndex >= 0) {-
1130 const QSignalBlocker blocker(tabBar);-
1131 tabBar->removeTab(removedIndex);-
1132 updateTabBarGeometry();-
1133 }-
1134#endif-
1135-
1136 if (childWindows.isEmpty()) {-
1137 showActiveWindowMaximized = false;-
1138 resetActiveWindow();-
1139 return;-
1140 }-
1141-
1142 if (indexToHighlighted >= 0) {-
1143#ifndef QT_NO_RUBBERBAND-
1144 // Hide rubber band if highlighted window is removed.-
1145 if (indexToHighlighted == removedIndex)-
1146 hideRubberBand();-
1147 else-
1148#endif-
1149 // or update index if necessary.-
1150 if (indexToHighlighted > removedIndex)-
1151 --indexToHighlighted;-
1152 }-
1153-
1154 // Update indices list-
1155 for (int i = 0; i < indicesToActivatedChildren.size(); ++i) {-
1156 int *index = &indicesToActivatedChildren[i];-
1157 if (*index > removedIndex)-
1158 --*index;-
1159 }-
1160-
1161 if (!activeRemoved)-
1162 return;-
1163-
1164 // Activate next window.-
1165 QMdiSubWindow *next = nextVisibleSubWindow(0, activationOrder, removedIndex);-
1166 if (next)-
1167 activateWindow(next);-
1168}-
1169-
1170/*!-
1171 \internal-
1172*/-
1173void QMdiAreaPrivate::updateScrollBars()-
1174{-
1175 if (ignoreGeometryChange || !scrollBarsEnabled())-
1176 return;-
1177-
1178 Q_Q(QMdiArea);-
1179 QSize maxSize = q->maximumViewportSize();-
1180 QSize hbarExtent = hbar->sizeHint();-
1181 QSize vbarExtent = vbar->sizeHint();-
1182-
1183 if (q->style()->styleHint(QStyle::SH_ScrollView_FrameOnlyAroundContents, 0, q)) {-
1184 const int doubleFrameWidth = frameWidth * 2;-
1185 if (hbarpolicy == Qt::ScrollBarAlwaysOn)-
1186 maxSize.rheight() -= doubleFrameWidth;-
1187 if (vbarpolicy == Qt::ScrollBarAlwaysOn)-
1188 maxSize.rwidth() -= doubleFrameWidth;-
1189 hbarExtent.rheight() += doubleFrameWidth;-
1190 vbarExtent.rwidth() += doubleFrameWidth;-
1191 }-
1192-
1193 const QRect childrenRect = active && active->isMaximized()-
1194 ? active->geometry() : viewport->childrenRect();-
1195 bool useHorizontalScrollBar = useScrollBar(childrenRect, maxSize, Qt::Horizontal);-
1196 bool useVerticalScrollBar = useScrollBar(childrenRect, maxSize, Qt::Vertical);-
1197-
1198 if (useHorizontalScrollBar && !useVerticalScrollBar) {-
1199 const QSize max = maxSize - QSize(0, hbarExtent.height());-
1200 useVerticalScrollBar = useScrollBar(childrenRect, max, Qt::Vertical);-
1201 }-
1202-
1203 if (useVerticalScrollBar && !useHorizontalScrollBar) {-
1204 const QSize max = maxSize - QSize(vbarExtent.width(), 0);-
1205 useHorizontalScrollBar = useScrollBar(childrenRect, max, Qt::Horizontal);-
1206 }-
1207-
1208 if (useHorizontalScrollBar && hbarpolicy != Qt::ScrollBarAlwaysOn)-
1209 maxSize.rheight() -= hbarExtent.height();-
1210 if (useVerticalScrollBar && vbarpolicy != Qt::ScrollBarAlwaysOn)-
1211 maxSize.rwidth() -= vbarExtent.width();-
1212-
1213 QRect viewportRect(QPoint(0, 0), maxSize);-
1214 const int startX = q->isLeftToRight() ? childrenRect.left() : viewportRect.right()-
1215 - childrenRect.right();-
1216-
1217 // Horizontal scroll bar.-
1218 if (isSubWindowsTiled && hbar->value() != 0)-
1219 hbar->setValue(0);-
1220 const int xOffset = startX + hbar->value();-
1221 hbar->setRange(qMin(0, xOffset),-
1222 qMax(0, xOffset + childrenRect.width() - viewportRect.width()));-
1223 hbar->setPageStep(childrenRect.width());-
1224 hbar->setSingleStep(childrenRect.width() / 20);-
1225-
1226 // Vertical scroll bar.-
1227 if (isSubWindowsTiled && vbar->value() != 0)-
1228 vbar->setValue(0);-
1229 const int yOffset = childrenRect.top() + vbar->value();-
1230 vbar->setRange(qMin(0, yOffset),-
1231 qMax(0, yOffset + childrenRect.height() - viewportRect.height()));-
1232 vbar->setPageStep(childrenRect.height());-
1233 vbar->setSingleStep(childrenRect.height() / 20);-
1234}-
1235-
1236/*!-
1237 \internal-
1238*/-
1239void QMdiAreaPrivate::internalRaise(QMdiSubWindow *mdiChild) const-
1240{-
1241 if (!sanityCheck(mdiChild, "QMdiArea::internalRaise") || childWindows.size() < 2)
!sanityCheck(m...nternalRaise")Description
TRUEnever evaluated
FALSEnever evaluated
childWindows.size() < 2Description
TRUEnever evaluated
FALSEnever evaluated
0
1242 return;
never executed: return;
0
1243-
1244 QMdiSubWindow *stackUnderChild = 0;-
1245 if (!windowStaysOnTop(mdiChild)) {
!windowStaysOnTop(mdiChild)Description
TRUEnever evaluated
FALSEnever evaluated
0
1246 foreachconst auto children = viewport->children(); // take a copy, as raising/stacking under changes the order-
1247 for (QObject *object , viewport->: children())) {-
1248 QMdiSubWindow *child = qobject_cast<QMdiSubWindow *>(object);-
1249 if (!child || !childWindows.contains(child))
!childDescription
TRUEnever evaluated
FALSEnever evaluated
!childWindows.contains(child)Description
TRUEnever evaluated
FALSEnever evaluated
0
1250 continue;
never executed: continue;
0
1251 if (!child->isHidden() && windowStaysOnTop(child)) {
!child->isHidden()Description
TRUEnever evaluated
FALSEnever evaluated
windowStaysOnTop(child)Description
TRUEnever evaluated
FALSEnever evaluated
0
1252 if (stackUnderChild)
stackUnderChildDescription
TRUEnever evaluated
FALSEnever evaluated
0
1253 child->stackUnder(stackUnderChild);
never executed: child->stackUnder(stackUnderChild);
0
1254 else-
1255 child->raise();
never executed: child->raise();
0
1256 stackUnderChild = child;-
1257 }
never executed: end of block
0
1258 }
never executed: end of block
0
1259 }
never executed: end of block
0
1260-
1261 if (stackUnderChild)
stackUnderChildDescription
TRUEnever evaluated
FALSEnever evaluated
0
1262 mdiChild->stackUnder(stackUnderChild);
never executed: mdiChild->stackUnder(stackUnderChild);
0
1263 else-
1264 mdiChild->raise();
never executed: mdiChild->raise();
0
1265}-
1266-
1267QRect QMdiAreaPrivate::resizeToMinimumTileSize(const QSize &minSubWindowSize, int subWindowCount)-
1268{-
1269 Q_Q(QMdiArea);-
1270 if (!minSubWindowSize.isValid() || subWindowCount <= 0)-
1271 return viewport->rect();-
1272-
1273 // Calculate minimum size.-
1274 const int columns = qMax(qCeil(qSqrt(qreal(subWindowCount))), 1);-
1275 const int rows = qMax((subWindowCount % columns) ? (subWindowCount / columns + 1)-
1276 : (subWindowCount / columns), 1);-
1277 const int minWidth = minSubWindowSize.width() * columns;-
1278 const int minHeight = minSubWindowSize.height() * rows;-
1279-
1280 // Increase area size if necessary. Scroll bars are provided if we're not able-
1281 // to resize to the minimum size.-
1282 if (!tileCalledFromResizeEvent) {-
1283 QWidget *topLevel = q;-
1284 // Find the topLevel for this area, either a real top-level or a sub-window.-
1285 while (topLevel && !topLevel->isWindow() && topLevel->windowType() != Qt::SubWindow)-
1286 topLevel = topLevel->parentWidget();-
1287 // We don't want sub-subwindows to be placed at the edge, thus add 2 pixels.-
1288 int minAreaWidth = minWidth + left + right + 2;-
1289 int minAreaHeight = minHeight + top + bottom + 2;-
1290 if (hbar->isVisible())-
1291 minAreaHeight += hbar->height();-
1292 if (vbar->isVisible())-
1293 minAreaWidth += vbar->width();-
1294 if (q->style()->styleHint(QStyle::SH_ScrollView_FrameOnlyAroundContents, 0, q)) {-
1295 const int frame = q->style()->pixelMetric(QStyle::PM_DefaultFrameWidth, 0, q);-
1296 minAreaWidth += 2 * frame;-
1297 minAreaHeight += 2 * frame;-
1298 }-
1299 const QSize diff = QSize(minAreaWidth, minAreaHeight).expandedTo(q->size()) - q->size();-
1300 topLevel->resize(topLevel->size() + diff);-
1301 }-
1302-
1303 QRect domain = viewport->rect();-
1304-
1305 // Adjust domain width and provide horizontal scroll bar.-
1306 if (domain.width() < minWidth) {-
1307 domain.setWidth(minWidth);-
1308 if (hbarpolicy == Qt::ScrollBarAlwaysOff)-
1309 q->setHorizontalScrollBarPolicy(Qt::ScrollBarAsNeeded);-
1310 else-
1311 hbar->setValue(0);-
1312 }-
1313 // Adjust domain height and provide vertical scroll bar.-
1314 if (domain.height() < minHeight) {-
1315 domain.setHeight(minHeight);-
1316 if (vbarpolicy == Qt::ScrollBarAlwaysOff)-
1317 q->setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded);-
1318 else-
1319 vbar->setValue(0);-
1320 }-
1321 return domain;-
1322}-
1323-
1324/*!-
1325 \internal-
1326*/-
1327bool QMdiAreaPrivate::scrollBarsEnabled() const-
1328{-
1329 return hbarpolicy != Qt::ScrollBarAlwaysOff || vbarpolicy != Qt::ScrollBarAlwaysOff;-
1330}-
1331-
1332/*!-
1333 \internal-
1334*/-
1335bool QMdiAreaPrivate::lastWindowAboutToBeDestroyed() const-
1336{-
1337 if (childWindows.count() != 1)-
1338 return false;-
1339-
1340 QMdiSubWindow *last = childWindows.at(0);-
1341 if (!last)-
1342 return true;-
1343-
1344 if (!last->testAttribute(Qt::WA_DeleteOnClose))-
1345 return false;-
1346-
1347 return last->d_func()->data.is_closing;-
1348}-
1349-
1350/*!-
1351 \internal-
1352*/-
1353void QMdiAreaPrivate::setChildActivationEnabled(bool enable, bool onlyNextActivationEvent) const-
1354{-
1355 foreach (QMdiSubWindow *subWindow, childWindows) {-
1356 if (!subWindow || !subWindow->isVisible())-
1357 continue;-
1358 if (onlyNextActivationEvent)-
1359 subWindow->d_func()->ignoreNextActivationEvent = !enable;-
1360 else-
1361 subWindow->d_func()->activationEnabled = enable;-
1362 }-
1363}-
1364-
1365/*!-
1366 \internal-
1367 \reimp-
1368*/-
1369void QMdiAreaPrivate::scrollBarPolicyChanged(Qt::Orientation orientation, Qt::ScrollBarPolicy policy)-
1370{-
1371 if (childWindows.isEmpty())-
1372 return;-
1373-
1374 const QMdiSubWindow::SubWindowOption option = orientation == Qt::Horizontal ?-
1375 QMdiSubWindow::AllowOutsideAreaHorizontally : QMdiSubWindow::AllowOutsideAreaVertically;-
1376 const bool enable = policy != Qt::ScrollBarAlwaysOff;-
1377 foreach (QMdiSubWindow *child, childWindows) {-
1378 if (!sanityCheck(child, "QMdiArea::scrollBarPolicyChanged"))-
1379 continue;-
1380 child->setOption(option, enable);-
1381 }-
1382 updateScrollBars();-
1383}-
1384-
1385QList<QMdiSubWindow*>-
1386QMdiAreaPrivate::subWindowList(QMdiArea::WindowOrder order, bool reversed) const-
1387{-
1388 QList<QMdiSubWindow *> list;-
1389 if (childWindows.isEmpty())
childWindows.isEmpty()Description
TRUEnever evaluated
FALSEnever evaluated
0
1390 return list;
never executed: return list;
0
1391-
1392 if (order == QMdiArea::CreationOrder) {
order == QMdiA...:CreationOrderDescription
TRUEnever evaluated
FALSEnever evaluated
0
1393 foreach (QMdiSubWindow *child, childWindows) {-
1394 if (!child)
!childDescription
TRUEnever evaluated
FALSEnever evaluated
0
1395 continue;
never executed: continue;
0
1396 if (!reversed)
!reversedDescription
TRUEnever evaluated
FALSEnever evaluated
0
1397 list.append(child);
never executed: list.append(child);
0
1398 else-
1399 list.prepend(child);
never executed: list.prepend(child);
0
1400 }-
1401 } else if (order == QMdiArea::StackingOrder) {
never executed: end of block
order == QMdiA...:StackingOrderDescription
TRUEnever evaluated
FALSEnever evaluated
0
1402 foreachfor (QObject *object ,: viewport->children()) {-
1403 QMdiSubWindow *child = qobject_cast<QMdiSubWindow *>(object);-
1404 if (!child || !childWindows.contains(child))
!childDescription
TRUEnever evaluated
FALSEnever evaluated
!childWindows.contains(child)Description
TRUEnever evaluated
FALSEnever evaluated
0
1405 continue;
never executed: continue;
0
1406 if (!reversed)
!reversedDescription
TRUEnever evaluated
FALSEnever evaluated
0
1407 list.append(child);
never executed: list.append(child);
0
1408 else-
1409 list.prepend(child);
never executed: list.prepend(child);
0
1410 }-
1411 } else { // ActivationHistoryOrder
never executed: end of block
0
1412 Q_ASSERT(indicesToActivatedChildren.size() == childWindows.size());-
1413 for (int i = indicesToActivatedChildren.count() - 1; i >= 0; --i) {
i >= 0Description
TRUEnever evaluated
FALSEnever evaluated
0
1414 QMdiSubWindow *child = childWindows.at(indicesToActivatedChildren.at(i));-
1415 if (!child)
!childDescription
TRUEnever evaluated
FALSEnever evaluated
0
1416 continue;
never executed: continue;
0
1417 if (!reversed)
!reversedDescription
TRUEnever evaluated
FALSEnever evaluated
0
1418 list.append(child);
never executed: list.append(child);
0
1419 else-
1420 list.prepend(child);
never executed: list.prepend(child);
0
1421 }-
1422 }
never executed: end of block
0
1423 return list;
never executed: return list;
0
1424}-
1425-
1426/*!-
1427 \internal-
1428*/-
1429void QMdiAreaPrivate::disconnectSubWindow(QObject *subWindow)-
1430{-
1431 if (!subWindow)-
1432 return;-
1433-
1434 Q_Q(QMdiArea);-
1435 QObject::disconnect(subWindow, 0, q, 0);-
1436 subWindow->removeEventFilter(q);-
1437}-
1438-
1439/*!-
1440 \internal-
1441*/-
1442QMdiSubWindow *QMdiAreaPrivate::nextVisibleSubWindow(int increaseFactor, QMdiArea::WindowOrder order,-
1443 int removedIndex, int fromIndex) const-
1444{-
1445 if (childWindows.isEmpty())-
1446 return 0;-
1447-
1448 Q_Q(const QMdiArea);-
1449 const QList<QMdiSubWindow *> subWindows = q->subWindowList(order);-
1450 QMdiSubWindow *current = 0;-
1451-
1452 if (removedIndex < 0) {-
1453 if (fromIndex >= 0 && fromIndex < subWindows.size())-
1454 current = childWindows.at(fromIndex);-
1455 else-
1456 current = q->currentSubWindow();-
1457 }-
1458-
1459 // There's no current sub-window (removed or deactivated),-
1460 // so we have to pick the last active or the next in creation order.-
1461 if (!current) {-
1462 if (removedIndex >= 0 && order == QMdiArea::CreationOrder) {-
1463 int candidateIndex = -1;-
1464 setIndex(&candidateIndex, removedIndex, 0, subWindows.size() - 1, true);-
1465 current = childWindows.at(candidateIndex);-
1466 } else {-
1467 current = subWindows.back();-
1468 }-
1469 }-
1470 Q_ASSERT(current);-
1471-
1472 // Find the index for the current sub-window in the given activation order-
1473 const int indexToCurrent = subWindows.indexOf(current);-
1474 const bool increasing = increaseFactor > 0;-
1475-
1476 // and use that index + increseFactor as a candidate.-
1477 int index = -1;-
1478 setIndex(&index, indexToCurrent + increaseFactor, 0, subWindows.size() - 1, increasing);-
1479 Q_ASSERT(index != -1);-
1480-
1481 // Try to find another window if the candidate is hidden.-
1482 while (subWindows.at(index)->isHidden()) {-
1483 setIndex(&index, index + increaseFactor, 0, subWindows.size() - 1, increasing);-
1484 if (index == indexToCurrent)-
1485 break;-
1486 }-
1487-
1488 if (!subWindows.at(index)->isHidden())-
1489 return subWindows.at(index);-
1490 return 0;-
1491}-
1492-
1493/*!-
1494 \internal-
1495*/-
1496void QMdiAreaPrivate::highlightNextSubWindow(int increaseFactor)-
1497{-
1498 if (childWindows.size() == 1)-
1499 return;-
1500-
1501 Q_Q(QMdiArea);-
1502 // There's no highlighted sub-window atm, use current.-
1503 if (indexToHighlighted < 0) {-
1504 QMdiSubWindow *current = q->currentSubWindow();-
1505 if (!current)-
1506 return;-
1507 indexToHighlighted = childWindows.indexOf(current);-
1508 }-
1509-
1510 Q_ASSERT(indexToHighlighted >= 0);-
1511 Q_ASSERT(indexToHighlighted < childWindows.size());-
1512-
1513 QMdiSubWindow *highlight = nextVisibleSubWindow(increaseFactor, activationOrder, -1, indexToHighlighted);-
1514 if (!highlight)-
1515 return;-
1516-
1517#ifndef QT_NO_RUBBERBAND-
1518 if (!rubberBand) {-
1519 rubberBand = new QRubberBand(QRubberBand::Rectangle, q);-
1520 // For accessibility to identify this special widget.-
1521 rubberBand->setObjectName(QLatin1String("qt_rubberband"));-
1522 rubberBand->setWindowFlags(rubberBand->windowFlags() | Qt::WindowStaysOnTopHint);-
1523 }-
1524#endif-
1525-
1526 // Only highlight if we're not switching back to the previously active window (Ctrl-Tab once).-
1527#ifndef QT_NO_RUBBERBAND-
1528 if (tabToPreviousTimerId == -1)-
1529 showRubberBandFor(highlight);-
1530#endif-
1531-
1532 indexToHighlighted = childWindows.indexOf(highlight);-
1533 Q_ASSERT(indexToHighlighted >= 0);-
1534}-
1535-
1536void QMdiAreaPrivate::showRubberBandFor(QMdiSubWindow *subWindow)-
1537{-
1538 if (!subWindow || !rubberBand)-
1539 return;-
1540-
1541 if (viewMode == QMdiArea::TabbedView)-
1542 rubberBand->setGeometry(tabBar->tabRect(childWindows.indexOf(subWindow)));-
1543 else-
1544 rubberBand->setGeometry(subWindow->geometry());-
1545-
1546 rubberBand->raise();-
1547 rubberBand->show();-
1548}-
1549-
1550/*!-
1551 \internal-
1552 \since 4.4-
1553*/-
1554void QMdiAreaPrivate::setViewMode(QMdiArea::ViewMode mode)-
1555{-
1556 Q_Q(QMdiArea);-
1557 if (viewMode == mode || inViewModeChange)-
1558 return;-
1559-
1560 // Just a guard since we cannot set viewMode = mode here.-
1561 inViewModeChange = true;-
1562-
1563#ifndef QT_NO_TABBAR-
1564 if (mode == QMdiArea::TabbedView) {-
1565 Q_ASSERT(!tabBar);-
1566 tabBar = new QMdiAreaTabBar(q);-
1567 tabBar->setDocumentMode(documentMode);-
1568 tabBar->setTabsClosable(tabsClosable);-
1569 tabBar->setMovable(tabsMovable);-
1570#ifndef QT_NO_TABWIDGET-
1571 tabBar->setShape(tabBarShapeFrom(tabShape, tabPosition));-
1572#endif-
1573-
1574 isSubWindowsTiled = false;-
1575-
1576 foreach (QMdiSubWindow *subWindow, childWindows)-
1577 tabBar->addTab(subWindow->windowIcon(), tabTextFor(subWindow));-
1578-
1579 QMdiSubWindow *current = q->currentSubWindow();-
1580 if (current) {-
1581 tabBar->setCurrentIndex(childWindows.indexOf(current));-
1582 // Restore sub-window (i.e. cleanup buttons in menu bar and window title).-
1583 if (current->isMaximized())-
1584 current->showNormal();-
1585-
1586 viewMode = mode;-
1587-
1588 // Now, maximize it.-
1589 if (!q->testOption(QMdiArea::DontMaximizeSubWindowOnActivation)) {-
1590 current->showMaximized();-
1591 }-
1592 } else {-
1593 viewMode = mode;-
1594 }-
1595-
1596 if (q->isVisible())-
1597 tabBar->show();-
1598 updateTabBarGeometry();-
1599-
1600 QObject::connect(tabBar, SIGNAL(currentChanged(int)), q, SLOT(_q_currentTabChanged(int)));-
1601 QObject::connect(tabBar, SIGNAL(tabCloseRequested(int)), q, SLOT(_q_closeTab(int)));-
1602 QObject::connect(tabBar, SIGNAL(tabMoved(int,int)), q, SLOT(_q_moveTab(int,int)));-
1603 } else-
1604#endif // QT_NO_TABBAR-
1605 { // SubWindowView-
1606#ifndef QT_NO_TABBAR-
1607 delete tabBar;-
1608 tabBar = 0;-
1609#endif // QT_NO_TABBAR-
1610-
1611 viewMode = mode;-
1612 q->setViewportMargins(0, 0, 0, 0);-
1613 indexToLastActiveTab = -1;-
1614-
1615 QMdiSubWindow *current = q->currentSubWindow();-
1616 if (current && current->isMaximized())-
1617 current->showNormal();-
1618 }-
1619-
1620 Q_ASSERT(viewMode == mode);-
1621 inViewModeChange = false;-
1622}-
1623-
1624#ifndef QT_NO_TABBAR-
1625/*!-
1626 \internal-
1627*/-
1628void QMdiAreaPrivate::updateTabBarGeometry()-
1629{-
1630 if (!tabBar)-
1631 return;-
1632-
1633 Q_Q(QMdiArea);-
1634#ifndef QT_NO_TABWIDGET-
1635 Q_ASSERT(tabBarShapeFrom(tabShape, tabPosition) == tabBar->shape());-
1636#endif-
1637 const QSize tabBarSizeHint = tabBar->sizeHint();-
1638-
1639 int areaHeight = q->height();-
1640 if (hbar && hbar->isVisible())-
1641 areaHeight -= hbar->height();-
1642-
1643 int areaWidth = q->width();-
1644 if (vbar && vbar->isVisible())-
1645 areaWidth -= vbar->width();-
1646-
1647 QRect tabBarRect;-
1648#ifndef QT_NO_TABWIDGET-
1649 switch (tabPosition) {-
1650 case QTabWidget::North:-
1651 q->setViewportMargins(0, tabBarSizeHint.height(), 0, 0);-
1652 tabBarRect = QRect(0, 0, areaWidth, tabBarSizeHint.height());-
1653 break;-
1654 case QTabWidget::South:-
1655 q->setViewportMargins(0, 0, 0, tabBarSizeHint.height());-
1656 tabBarRect = QRect(0, areaHeight - tabBarSizeHint.height(), areaWidth, tabBarSizeHint.height());-
1657 break;-
1658 case QTabWidget::East:-
1659 if (q->layoutDirection() == Qt::LeftToRight)-
1660 q->setViewportMargins(0, 0, tabBarSizeHint.width(), 0);-
1661 else-
1662 q->setViewportMargins(tabBarSizeHint.width(), 0, 0, 0);-
1663 tabBarRect = QRect(areaWidth - tabBarSizeHint.width(), 0, tabBarSizeHint.width(), areaHeight);-
1664 break;-
1665 case QTabWidget::West:-
1666 if (q->layoutDirection() == Qt::LeftToRight)-
1667 q->setViewportMargins(tabBarSizeHint.width(), 0, 0, 0);-
1668 else-
1669 q->setViewportMargins(0, 0, tabBarSizeHint.width(), 0);-
1670 tabBarRect = QRect(0, 0, tabBarSizeHint.width(), areaHeight);-
1671 break;-
1672 default:-
1673 break;-
1674 }-
1675#endif // QT_NO_TABWIDGET-
1676-
1677 tabBar->setGeometry(QStyle::visualRect(q->layoutDirection(), q->contentsRect(), tabBarRect));-
1678}-
1679-
1680/*!-
1681 \internal-
1682*/-
1683void QMdiAreaPrivate::refreshTabBar()-
1684{-
1685 if (!tabBar)-
1686 return;-
1687-
1688 tabBar->setDocumentMode(documentMode);-
1689 tabBar->setTabsClosable(tabsClosable);-
1690 tabBar->setMovable(tabsMovable);-
1691#ifndef QT_NO_TABWIDGET-
1692 tabBar->setShape(tabBarShapeFrom(tabShape, tabPosition));-
1693#endif-
1694 updateTabBarGeometry();-
1695}-
1696#endif // QT_NO_TABBAR-
1697-
1698/*!-
1699 Constructs an empty mdi area. \a parent is passed to QWidget's-
1700 constructor.-
1701*/-
1702QMdiArea::QMdiArea(QWidget *parent)-
1703 : QAbstractScrollArea(*new QMdiAreaPrivate, parent)-
1704{-
1705 setBackground(palette().brush(QPalette::Dark));-
1706 setFrameStyle(QFrame::NoFrame);-
1707 setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);-
1708 setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);-
1709 setViewport(0);-
1710 setFocusPolicy(Qt::NoFocus);-
1711 QApplication::instance()->installEventFilter(this);-
1712}-
1713-
1714/*!-
1715 Destroys the MDI area.-
1716*/-
1717QMdiArea::~QMdiArea()-
1718{-
1719 Q_D(QMdiArea);-
1720 delete d->cascader;-
1721 d->cascader = 0;-
1722-
1723 delete d->regularTiler;-
1724 d->regularTiler = 0;-
1725-
1726 delete d->iconTiler;-
1727 d->iconTiler = 0;-
1728-
1729 delete d->placer;-
1730 d->placer = 0;-
1731}-
1732-
1733/*!-
1734 \reimp-
1735*/-
1736QSize QMdiArea::sizeHint() const-
1737{-
1738 // Calculate a proper scale factor for QDesktopWidget::size().-
1739 // This also takes into account that we can have nested workspaces.-
1740 int nestedCount = 0;-
1741 QWidget *widget = this->parentWidget();-
1742 while (widget) {
widgetDescription
TRUEnever evaluated
FALSEnever evaluated
0
1743 if (qobject_cast<QMdiArea *>(widget))
qobject_cast<Q...rea *>(widget)Description
TRUEnever evaluated
FALSEnever evaluated
0
1744 ++nestedCount;
never executed: ++nestedCount;
0
1745 widget = widget->parentWidget();-
1746 }
never executed: end of block
0
1747 const int scaleFactor = 3 * (nestedCount + 1);-
1748-
1749 QSize desktopSize = QApplication::desktop()->size();-
1750 QSize size(desktopSize.width() * 2 / scaleFactor, desktopSize.height() * 2 / scaleFactor);-
1751 foreachfor (QMdiSubWindow *child ,: d_func()->childWindows) {-
1752 if (!sanityCheck(child, "QMdiArea::sizeHint"))
!sanityCheck(c...ea::sizeHint")Description
TRUEnever evaluated
FALSEnever evaluated
0
1753 continue;
never executed: continue;
0
1754 size = size.expandedTo(child->sizeHint());-
1755 }
never executed: end of block
0
1756 return size.expandedTo(QApplication::globalStrut());
never executed: return size.expandedTo(QApplication::globalStrut());
0
1757}-
1758-
1759/*!-
1760 \reimp-
1761*/-
1762QSize QMdiArea::minimumSizeHint() const-
1763{-
1764 Q_D(const QMdiArea);-
1765 QSize size(style()->pixelMetric(QStyle::PM_MdiSubWindowMinimizedWidth, 0, this),-
1766 style()->pixelMetric(QStyle::PM_TitleBarHeight, 0, this));-
1767 size = size.expandedTo(QAbstractScrollArea::minimumSizeHint());-
1768 if (!d->scrollBarsEnabled()) {
!d->scrollBarsEnabled()Description
TRUEnever evaluated
FALSEnever evaluated
0
1769 foreachfor (QMdiSubWindow *child ,: d->childWindows) {-
1770 if (!sanityCheck(child, "QMdiArea::sizeHint"))
!sanityCheck(c...ea::sizeHint")Description
TRUEnever evaluated
FALSEnever evaluated
0
1771 continue;
never executed: continue;
0
1772 size = size.expandedTo(child->minimumSizeHint());-
1773 }
never executed: end of block
0
1774 }
never executed: end of block
0
1775 return size.expandedTo(QApplication::globalStrut());
never executed: return size.expandedTo(QApplication::globalStrut());
0
1776}-
1777-
1778/*!-
1779 Returns a pointer to the current subwindow, or 0 if there is-
1780 no current subwindow.-
1781-
1782 This function will return the same as activeSubWindow() if-
1783 the QApplication containing QMdiArea is active.-
1784-
1785 \sa activeSubWindow(), QApplication::activeWindow()-
1786*/-
1787QMdiSubWindow *QMdiArea::currentSubWindow() const-
1788{-
1789 Q_D(const QMdiArea);-
1790 if (d->childWindows.isEmpty())-
1791 return 0;-
1792-
1793 if (d->active)-
1794 return d->active;-
1795-
1796 if (d->isActivated && !window()->isMinimized())-
1797 return 0;-
1798-
1799 Q_ASSERT(d->indicesToActivatedChildren.count() > 0);-
1800 int index = d->indicesToActivatedChildren.at(0);-
1801 Q_ASSERT(index >= 0 && index < d->childWindows.size());-
1802 QMdiSubWindow *current = d->childWindows.at(index);-
1803 Q_ASSERT(current);-
1804 return current;-
1805}-
1806-
1807/*!-
1808 Returns a pointer to the current active subwindow. If no-
1809 window is currently active, 0 is returned.-
1810-
1811 Subwindows are treated as top-level windows with respect to-
1812 window state, i.e., if a widget outside the MDI area is the active-
1813 window, no subwindow will be active. Note that if a widget in the-
1814 window in which the MDI area lives gains focus, the window will be-
1815 activated.-
1816-
1817 \sa setActiveSubWindow(), Qt::WindowState-
1818*/-
1819QMdiSubWindow *QMdiArea::activeSubWindow() const-
1820{-
1821 Q_D(const QMdiArea);-
1822 return d->active;-
1823}-
1824-
1825/*!-
1826 Activates the subwindow \a window. If \a window is 0, any-
1827 current active window is deactivated.-
1828-
1829 \sa activeSubWindow()-
1830*/-
1831void QMdiArea::setActiveSubWindow(QMdiSubWindow *window)-
1832{-
1833 Q_D(QMdiArea);-
1834 if (!window) {
!windowDescription
TRUEnever evaluated
FALSEnever evaluated
0
1835 d->activateWindow(0);-
1836 return;
never executed: return;
0
1837 }-
1838-
1839 if (Q_UNLIKELY(d->childWindows.isEmpty())())) {
__builtin_expe...pty()), false)Description
TRUEnever evaluated
FALSEnever evaluated
0
1840 qWarning("QMdiArea::setActiveSubWindow: workspace is empty");-
1841 return;
never executed: return;
0
1842 }-
1843-
1844 if (Q_UNLIKELY(d->childWindows.indexOf(window) == -1))) {
__builtin_expe...== -1), false)Description
TRUEnever evaluated
FALSEnever evaluated
0
1845 qWarning("QMdiArea::setActiveSubWindow: window is not inside workspace");-
1846 return;
never executed: return;
0
1847 }-
1848-
1849 d->activateWindow(window);-
1850}
never executed: end of block
0
1851-
1852/*!-
1853 Closes the active subwindow.-
1854-
1855 \sa closeAllSubWindows()-
1856*/-
1857void QMdiArea::closeActiveSubWindow()-
1858{-
1859 Q_D(QMdiArea);-
1860 if (d->active)-
1861 d->active->close();-
1862}-
1863-
1864/*!-
1865 Returns a list of all subwindows in the MDI area. If \a order is-
1866 CreationOrder (the default), the windows are sorted in the order-
1867 in which they were inserted into the workspace. If \a order is-
1868 StackingOrder, the windows are listed in their stacking order,-
1869 with the topmost window as the last item in the list. If \a order-
1870 is ActivationHistoryOrder, the windows are listed according to-
1871 their recent activation history.-
1872-
1873 \sa WindowOrder-
1874*/-
1875QList<QMdiSubWindow *> QMdiArea::subWindowList(WindowOrder order) const-
1876{-
1877 Q_D(const QMdiArea);-
1878 return d->subWindowList(order, false);-
1879}-
1880-
1881/*!-
1882 Closes all subwindows by sending a QCloseEvent to each window.-
1883 You may receive subWindowActivated() signals from subwindows-
1884 before they are closed (if the MDI area activates the subwindow-
1885 when another is closing).-
1886-
1887 Subwindows that ignore the close event will remain open.-
1888-
1889 \sa closeActiveSubWindow()-
1890*/-
1891void QMdiArea::closeAllSubWindows()-
1892{-
1893 Q_D(QMdiArea);-
1894 if (d->childWindows.isEmpty())-
1895 return;-
1896-
1897 d->isSubWindowsTiled = false;-
1898 foreach (QMdiSubWindow *child, d->childWindows) {-
1899 if (!sanityCheck(child, "QMdiArea::closeAllSubWindows"))-
1900 continue;-
1901 child->close();-
1902 }-
1903-
1904 d->updateScrollBars();-
1905}-
1906-
1907/*!-
1908 Gives the keyboard focus to another window in the list of child-
1909 windows. The window activated will be the next one determined-
1910 by the current \l{QMdiArea::WindowOrder} {activation order}.-
1911-
1912 \sa activatePreviousSubWindow(), QMdiArea::WindowOrder-
1913*/-
1914void QMdiArea::activateNextSubWindow()-
1915{-
1916 Q_D(QMdiArea);-
1917 if (d->childWindows.isEmpty())-
1918 return;-
1919-
1920 QMdiSubWindow *next = d->nextVisibleSubWindow(1, d->activationOrder);-
1921 if (next)-
1922 d->activateWindow(next);-
1923}-
1924-
1925/*!-
1926 Gives the keyboard focus to another window in the list of child-
1927 windows. The window activated will be the previous one determined-
1928 by the current \l{QMdiArea::WindowOrder} {activation order}.-
1929-
1930 \sa activateNextSubWindow(), QMdiArea::WindowOrder-
1931*/-
1932void QMdiArea::activatePreviousSubWindow()-
1933{-
1934 Q_D(QMdiArea);-
1935 if (d->childWindows.isEmpty())-
1936 return;-
1937-
1938 QMdiSubWindow *previous = d->nextVisibleSubWindow(-1, d->activationOrder);-
1939 if (previous)-
1940 d->activateWindow(previous);-
1941}-
1942-
1943/*!-
1944 Adds \a widget as a new subwindow to the MDI area. If \a-
1945 windowFlags are non-zero, they will override the flags set on the-
1946 widget.-
1947-
1948 The \a widget can be either a QMdiSubWindow or another QWidget-
1949 (in which case the MDI area will create a subwindow and set the \a-
1950 widget as the internal widget).-
1951-
1952 \note Once the subwindow has been added, its parent will be the-
1953 \e{viewport widget} of the QMdiArea.-
1954-
1955 \snippet mdiareasnippets.cpp 1-
1956-
1957 When you create your own subwindow, you must set the-
1958 Qt::WA_DeleteOnClose widget attribute if you want the window to be-
1959 deleted when closed in the MDI area. If not, the window will be-
1960 hidden and the MDI area will not activate the next subwindow.-
1961-
1962 Returns the QMdiSubWindow that is added to the MDI area.-
1963-
1964 \sa removeSubWindow()-
1965*/-
1966QMdiSubWindow *QMdiArea::addSubWindow(QWidget *widget, Qt::WindowFlags windowFlags)-
1967{-
1968 if (Q_UNLIKELY(!widget))) {
__builtin_expe...idget), false)Description
TRUEnever evaluated
FALSEnever evaluated
0
1969 qWarning("QMdiArea::addSubWindow: null pointer to widget");-
1970 return 0;
never executed: return 0;
0
1971 }-
1972-
1973 Q_D(QMdiArea);-
1974 // QWidget::setParent clears focusWidget so store it-
1975 QWidget *childFocus = widget->focusWidget();-
1976 QMdiSubWindow *child = qobject_cast<QMdiSubWindow *>(widget);-
1977-
1978 // Widget is already a QMdiSubWindow-
1979 if (child) {
childDescription
TRUEnever evaluated
FALSEnever evaluated
0
1980 if (Q_UNLIKELY(d->childWindows.indexOf(child) != -1))) {
__builtin_expe...!= -1), false)Description
TRUEnever evaluated
FALSEnever evaluated
0
1981 qWarning("QMdiArea::addSubWindow: window is already added");-
1982 return child;
never executed: return child;
0
1983 }-
1984 child->setParent(viewport(), windowFlags ? windowFlags : child->windowFlags());-
1985 // Create a QMdiSubWindow-
1986 } else {
never executed: end of block
0
1987 child = new QMdiSubWindow(viewport(), windowFlags);-
1988 child->setAttribute(Qt::WA_DeleteOnClose);-
1989 child->setWidget(widget);-
1990 Q_ASSERT(child->testAttribute(Qt::WA_DeleteOnClose));-
1991 }
never executed: end of block
0
1992-
1993 if (childFocus)
childFocusDescription
TRUEnever evaluated
FALSEnever evaluated
0
1994 childFocus->setFocus();
never executed: childFocus->setFocus();
0
1995 d->appendChild(child);-
1996 return child;
never executed: return child;
0
1997}-
1998-
1999/*!-
2000 Removes \a widget from the MDI area. The \a widget must be-
2001 either a QMdiSubWindow or a widget that is the internal widget of-
2002 a subwindow. Note \a widget is never actually deleted by QMdiArea.-
2003 If a QMdiSubWindow is passed in its parent is set to 0 and it is-
2004 removed, but if an internal widget is passed in the child widget-
2005 is set to 0 but the QMdiSubWindow is not removed.-
2006-
2007 \sa addSubWindow()-
2008*/-
2009void QMdiArea::removeSubWindow(QWidget *widget)-
2010{-
2011 if (Q_UNLIKELY(!widget))) {
__builtin_expe...idget), false)Description
TRUEnever evaluated
FALSEnever evaluated
0
2012 qWarning("QMdiArea::removeSubWindow: null pointer to widget");-
2013 return;
never executed: return;
0
2014 }-
2015-
2016 Q_D(QMdiArea);-
2017 if (d->childWindows.isEmpty())
d->childWindows.isEmpty()Description
TRUEnever evaluated
FALSEnever evaluated
0
2018 return;
never executed: return;
0
2019-
2020 if (QMdiSubWindow *child = qobject_cast<QMdiSubWindow *>(widget)) {
QMdiSubWindow ...dow *>(widget)Description
TRUEnever evaluated
FALSEnever evaluated
0
2021 int index = d->childWindows.indexOf(child);-
2022 if (Q_UNLIKELY(index == -1))) {
__builtin_expe...== -1), false)Description
TRUEnever evaluated
FALSEnever evaluated
0
2023 qWarning("QMdiArea::removeSubWindow: window is not inside workspace");-
2024 return;
never executed: return;
0
2025 }-
2026 d->disconnectSubWindow(child);-
2027 d->childWindows.removeAll(child);-
2028 d->indicesToActivatedChildren.removeAll(index);-
2029 d->updateActiveWindow(index, d->active == child);-
2030 child->setParent(0);-
2031 return;
never executed: return;
0
2032 }-
2033-
2034 bool found = false;-
2035 foreach (QMdiSubWindow *child, d->childWindows) {-
2036 if (!sanityCheck(child, "QMdiArea::removeSubWindow"))
!sanityCheck(c...oveSubWindow")Description
TRUEnever evaluated
FALSEnever evaluated
0
2037 continue;
never executed: continue;
0
2038 if (child->widget() == widget) {
child->widget() == widgetDescription
TRUEnever evaluated
FALSEnever evaluated
0
2039 child->setWidget(0);-
2040 Q_ASSERT(!child->widget());-
2041 found = true;-
2042 break;
never executed: break;
0
2043 }-
2044 }
never executed: end of block
0
2045-
2046 if (Q_UNLIKELY(!found)))
__builtin_expe...found), false)Description
TRUEnever evaluated
FALSEnever evaluated
0
2047 qWarning("QMdiArea::removeSubWindow: widget is not child of any window inside QMdiArea");
never executed: QMessageLogger(__FILE__, 2047, __PRETTY_FUNCTION__).warning("QMdiArea::removeSubWindow: widget is not child of any window inside QMdiArea");
0
2048}
never executed: end of block
0
2049-
2050/*!-
2051 \property QMdiArea::background-
2052 \brief the background brush for the workspace-
2053-
2054 This property sets the background brush for the workspace area-
2055 itself. By default, it is a gray color, but can be any brush-
2056 (e.g., colors, gradients or pixmaps).-
2057*/-
2058QBrush QMdiArea::background() const-
2059{-
2060 return d_func()->background;-
2061}-
2062-
2063void QMdiArea::setBackground(const QBrush &brush)-
2064{-
2065 Q_D(QMdiArea);-
2066 if (d->background != brush) {-
2067 d->background = brush;-
2068 d->viewport->setAttribute(Qt::WA_OpaquePaintEvent, brush.isOpaque());-
2069 d->viewport->update();-
2070 }-
2071}-
2072-
2073-
2074/*!-
2075 \property QMdiArea::activationOrder-
2076 \brief the ordering criteria for subwindow lists-
2077 \since 4.4-
2078-
2079 This property specifies the ordering criteria for the list of-
2080 subwindows returned by subWindowList(). By default, it is the window-
2081 creation order.-
2082-
2083 \sa subWindowList()-
2084*/-
2085QMdiArea::WindowOrder QMdiArea::activationOrder() const-
2086{-
2087 Q_D(const QMdiArea);-
2088 return d->activationOrder;-
2089}-
2090-
2091void QMdiArea::setActivationOrder(WindowOrder order)-
2092{-
2093 Q_D(QMdiArea);-
2094 if (order != d->activationOrder)-
2095 d->activationOrder = order;-
2096}-
2097-
2098/*!-
2099 If \a on is true, \a option is enabled on the MDI area; otherwise-
2100 it is disabled. See AreaOption for the effect of each option.-
2101-
2102 \sa AreaOption, testOption()-
2103*/-
2104void QMdiArea::setOption(AreaOption option, bool on)-
2105{-
2106 Q_D(QMdiArea);-
2107 if (on && !(d->options & option))d->options|= option;-
else if (!on &&.setFlag(d->options & option))
d->options &= ~option;, on);
2108}
never executed: end of block
0
2109-
2110/*!-
2111 Returns \c true if \a option is enabled; otherwise returns \c false.-
2112-
2113 \sa AreaOption, setOption()-
2114*/-
2115bool QMdiArea::testOption(AreaOption option) const-
2116{-
2117 return d_func()->options & option;-
2118}-
2119-
2120/*!-
2121 \property QMdiArea::viewMode-
2122 \brief the way sub-windows are displayed in the QMdiArea.-
2123 \since 4.4-
2124-
2125 By default, the SubWindowView is used to display sub-windows.-
2126-
2127 \sa ViewMode, setTabShape(), setTabPosition()-
2128*/-
2129QMdiArea::ViewMode QMdiArea::viewMode() const-
2130{-
2131 Q_D(const QMdiArea);-
2132 return d->viewMode;-
2133}-
2134-
2135void QMdiArea::setViewMode(ViewMode mode)-
2136{-
2137 Q_D(QMdiArea);-
2138 d->setViewMode(mode);-
2139}-
2140-
2141#ifndef QT_NO_TABBAR-
2142/*!-
2143 \property QMdiArea::documentMode-
2144 \brief whether the tab bar is set to document mode in tabbed view mode.-
2145 \since 4.5-
2146-
2147 Document mode is disabled by default.-
2148-
2149 \sa QTabBar::documentMode, setViewMode()-
2150*/-
2151bool QMdiArea::documentMode() const-
2152{-
2153 Q_D(const QMdiArea);-
2154 return d->documentMode;-
2155}-
2156-
2157void QMdiArea::setDocumentMode(bool enabled)-
2158{-
2159 Q_D(QMdiArea);-
2160 if (d->documentMode == enabled)-
2161 return;-
2162-
2163 d->documentMode = enabled;-
2164 d->refreshTabBar();-
2165}-
2166-
2167/*!-
2168 \property QMdiArea::tabsClosable-
2169 \brief whether the tab bar should place close buttons on each tab in tabbed view mode.-
2170 \since 4.8-
2171-
2172 Tabs are not closable by default.-
2173-
2174 \sa QTabBar::tabsClosable, setViewMode()-
2175*/-
2176bool QMdiArea::tabsClosable() const-
2177{-
2178 Q_D(const QMdiArea);-
2179 return d->tabsClosable;-
2180}-
2181-
2182void QMdiArea::setTabsClosable(bool closable)-
2183{-
2184 Q_D(QMdiArea);-
2185 if (d->tabsClosable == closable)-
2186 return;-
2187-
2188 d->tabsClosable = closable;-
2189 d->refreshTabBar();-
2190}-
2191-
2192/*!-
2193 \property QMdiArea::tabsMovable-
2194 \brief whether the user can move the tabs within the tabbar area in tabbed view mode.-
2195 \since 4.8-
2196-
2197 Tabs are not movable by default.-
2198-
2199 \sa QTabBar::movable, setViewMode()-
2200*/-
2201bool QMdiArea::tabsMovable() const-
2202{-
2203 Q_D(const QMdiArea);-
2204 return d->tabsMovable;-
2205}-
2206-
2207void QMdiArea::setTabsMovable(bool movable)-
2208{-
2209 Q_D(QMdiArea);-
2210 if (d->tabsMovable == movable)-
2211 return;-
2212-
2213 d->tabsMovable = movable;-
2214 d->refreshTabBar();-
2215}-
2216#endif // QT_NO_TABBAR-
2217-
2218#ifndef QT_NO_TABWIDGET-
2219/*!-
2220 \property QMdiArea::tabShape-
2221 \brief the shape of the tabs in tabbed view mode.-
2222 \since 4.4-
2223-
2224 Possible values for this property are QTabWidget::Rounded-
2225 (default) or QTabWidget::Triangular.-
2226-
2227 \sa QTabWidget::TabShape, setViewMode()-
2228*/-
2229QTabWidget::TabShape QMdiArea::tabShape() const-
2230{-
2231 Q_D(const QMdiArea);-
2232 return d->tabShape;-
2233}-
2234-
2235void QMdiArea::setTabShape(QTabWidget::TabShape shape)-
2236{-
2237 Q_D(QMdiArea);-
2238 if (d->tabShape == shape)-
2239 return;-
2240-
2241 d->tabShape = shape;-
2242 d->refreshTabBar();-
2243}-
2244-
2245/*!-
2246 \property QMdiArea::tabPosition-
2247 \brief the position of the tabs in tabbed view mode.-
2248 \since 4.4-
2249-
2250 Possible values for this property are described by the-
2251 QTabWidget::TabPosition enum.-
2252-
2253 \sa QTabWidget::TabPosition, setViewMode()-
2254*/-
2255QTabWidget::TabPosition QMdiArea::tabPosition() const-
2256{-
2257 Q_D(const QMdiArea);-
2258 return d->tabPosition;-
2259}-
2260-
2261void QMdiArea::setTabPosition(QTabWidget::TabPosition position)-
2262{-
2263 Q_D(QMdiArea);-
2264 if (d->tabPosition == position)-
2265 return;-
2266-
2267 d->tabPosition = position;-
2268 d->refreshTabBar();-
2269}-
2270#endif // QT_NO_TABWIDGET-
2271-
2272/*!-
2273 \reimp-
2274*/-
2275void QMdiArea::childEvent(QChildEvent *childEvent)-
2276{-
2277 Q_D(QMdiArea);-
2278 if (childEvent->type() == QEvent::ChildPolished) {-
2279 if (QMdiSubWindow *mdiChild = qobject_cast<QMdiSubWindow *>(childEvent->child())) {-
2280 if (d->childWindows.indexOf(mdiChild) == -1)-
2281 d->appendChild(mdiChild);-
2282 }-
2283 }-
2284}-
2285-
2286/*!-
2287 \reimp-
2288*/-
2289void QMdiArea::resizeEvent(QResizeEvent *resizeEvent)-
2290{-
2291 Q_D(QMdiArea);-
2292 if (d->childWindows.isEmpty()) {-
2293 resizeEvent->ignore();-
2294 return;-
2295 }-
2296-
2297#ifndef QT_NO_TABBAR-
2298 d->updateTabBarGeometry();-
2299#endif-
2300-
2301 // Re-tile the views if we're in tiled mode. Re-tile means we will change-
2302 // the geometry of the children, which in turn means 'isSubWindowsTiled'-
2303 // is set to false, so we have to update the state at the end.-
2304 if (d->isSubWindowsTiled) {-
2305 d->tileCalledFromResizeEvent = true;-
2306 tileSubWindows();-
2307 d->tileCalledFromResizeEvent = false;-
2308 d->isSubWindowsTiled = true;-
2309 d->startResizeTimer();-
2310 // We don't have scroll bars or any maximized views.-
2311 return;-
2312 }-
2313-
2314 // Resize maximized views.-
2315 bool hasMaximizedSubWindow = false;-
2316 foreach (QMdiSubWindow *child, d->childWindows) {-
2317 if (sanityCheck(child, "QMdiArea::resizeEvent") && child->isMaximized()-
2318 && child->size() != resizeEvent->size()) {-
2319 child->resize(resizeEvent->size());-
2320 if (!hasMaximizedSubWindow)-
2321 hasMaximizedSubWindow = true;-
2322 }-
2323 }-
2324-
2325 d->updateScrollBars();-
2326-
2327 // Minimized views are stacked under maximized views so there's-
2328 // no need to re-arrange minimized views on-demand. Start a timer-
2329 // just to make things faster with subsequent resize events.-
2330 if (hasMaximizedSubWindow)-
2331 d->startResizeTimer();-
2332 else-
2333 d->arrangeMinimizedSubWindows();-
2334}-
2335-
2336/*!-
2337 \reimp-
2338*/-
2339void QMdiArea::timerEvent(QTimerEvent *timerEvent)-
2340{-
2341 Q_D(QMdiArea);-
2342 if (timerEvent->timerId() == d->resizeTimerId) {-
2343 killTimer(d->resizeTimerId);-
2344 d->resizeTimerId = -1;-
2345 d->arrangeMinimizedSubWindows();-
2346 } else if (timerEvent->timerId() == d->tabToPreviousTimerId) {-
2347 killTimer(d->tabToPreviousTimerId);-
2348 d->tabToPreviousTimerId = -1;-
2349 if (d->indexToHighlighted < 0)-
2350 return;-
2351#ifndef QT_NO_RUBBERBAND-
2352 // We're not doing a "quick switch" ... show rubber band.-
2353 Q_ASSERT(d->indexToHighlighted < d->childWindows.size());-
2354 Q_ASSERT(d->rubberBand);-
2355 d->showRubberBandFor(d->childWindows.at(d->indexToHighlighted));-
2356#endif-
2357 }-
2358}-
2359-
2360/*!-
2361 \reimp-
2362*/-
2363void QMdiArea::showEvent(QShowEvent *showEvent)-
2364{-
2365 Q_D(QMdiArea);-
2366 if (!d->pendingRearrangements.isEmpty()) {-
2367 bool skipPlacement = false;-
2368 foreach (Rearranger *rearranger, d->pendingRearrangements) {-
2369 // If this is the case, we don't have to lay out pending child windows-
2370 // since the rearranger will find a placement for them.-
2371 if (rearranger->type() != Rearranger::IconTiler && !skipPlacement)-
2372 skipPlacement = true;-
2373 d->rearrange(rearranger);-
2374 }-
2375 d->pendingRearrangements.clear();-
2376-
2377 if (skipPlacement && !d->pendingPlacements.isEmpty())-
2378 d->pendingPlacements.clear();-
2379 }-
2380-
2381 if (!d->pendingPlacements.isEmpty()) {-
2382 foreach (QMdiSubWindow *window, d->pendingPlacements) {-
2383 if (!window)-
2384 continue;-
2385 if (!window->testAttribute(Qt::WA_Resized)) {-
2386 QSize newSize(window->sizeHint().boundedTo(viewport()->size()));-
2387 window->resize(newSize.expandedTo(qSmartMinSize(window)));-
2388 }-
2389 if (!window->testAttribute(Qt::WA_Moved) && !window->isMinimized()-
2390 && !window->isMaximized()) {-
2391 d->place(d->placer, window);-
2392 }-
2393 }-
2394 d->pendingPlacements.clear();-
2395 }-
2396-
2397 d->setChildActivationEnabled(true);-
2398 d->activateCurrentWindow();-
2399-
2400 QAbstractScrollArea::showEvent(showEvent);-
2401}-
2402-
2403/*!-
2404 \reimp-
2405*/-
2406bool QMdiArea::viewportEvent(QEvent *event)-
2407{-
2408 Q_D(QMdiArea);-
2409 switch (event->type()) {-
2410 case QEvent::ChildRemoved: {-
2411 d->isSubWindowsTiled = false;-
2412 QObject *removedChild = static_cast<QChildEvent *>(event)->child();-
2413 for (int i = 0; i < d->childWindows.size(); ++i) {-
2414 QObject *child = d->childWindows.at(i);-
2415 if (!child || child == removedChild || !child->parent()-
2416 || child->parent() != viewport()) {-
2417 if (!testOption(DontMaximizeSubWindowOnActivation)) {-
2418 // In this case we can only rely on the child being a QObject-
2419 // (or 0), but let's try and see if we can get more information.-
2420 QWidget *mdiChild = qobject_cast<QWidget *>(removedChild);-
2421 if (mdiChild && mdiChild->isMaximized())-
2422 d->showActiveWindowMaximized = true;-
2423 }-
2424 d->disconnectSubWindow(child);-
2425 const bool activeRemoved = i == d->indicesToActivatedChildren.at(0);-
2426 d->childWindows.removeAt(i);-
2427 d->indicesToActivatedChildren.removeAll(i);-
2428 d->updateActiveWindow(i, activeRemoved);-
2429 d->arrangeMinimizedSubWindows();-
2430 break;-
2431 }-
2432 }-
2433 d->updateScrollBars();-
2434 break;-
2435 }-
2436 case QEvent::Destroy:-
2437 d->isSubWindowsTiled = false;-
2438 d->resetActiveWindow();-
2439 d->childWindows.clear();-
2440 qWarning("QMdiArea: Deleting the view port is undefined, use setViewport instead.");-
2441 break;-
2442 default:-
2443 break;-
2444 }-
2445 return QAbstractScrollArea::viewportEvent(event);-
2446}-
2447-
2448/*!-
2449 \reimp-
2450*/-
2451void QMdiArea::scrollContentsBy(int dx, int dy)-
2452{-
2453 Q_D(QMdiArea);-
2454 const bool wasSubWindowsTiled = d->isSubWindowsTiled;-
2455 d->ignoreGeometryChange = true;-
2456 viewport()->scroll(isLeftToRight() ? dx : -dx, dy);-
2457 d->arrangeMinimizedSubWindows();-
2458 d->ignoreGeometryChange = false;-
2459 if (wasSubWindowsTiled)-
2460 d->isSubWindowsTiled = true;-
2461}-
2462-
2463/*!-
2464 Arranges all child windows in a tile pattern.-
2465-
2466 \sa cascadeSubWindows()-
2467*/-
2468void QMdiArea::tileSubWindows()-
2469{-
2470 Q_D(QMdiArea);-
2471 if (!d->regularTiler)-
2472 d->regularTiler = new RegularTiler;-
2473 d->rearrange(d->regularTiler);-
2474}-
2475-
2476/*!-
2477 Arranges all the child windows in a cascade pattern.-
2478-
2479 \sa tileSubWindows()-
2480*/-
2481void QMdiArea::cascadeSubWindows()-
2482{-
2483 Q_D(QMdiArea);-
2484 if (!d->cascader)-
2485 d->cascader = new SimpleCascader;-
2486 d->rearrange(d->cascader);-
2487}-
2488-
2489/*!-
2490 \reimp-
2491*/-
2492bool QMdiArea::event(QEvent *event)-
2493{-
2494 Q_D(QMdiArea);-
2495 switch (event->type()) {-
2496#ifdef Q_DEAD_CODE_FROM_QT4_WIN-
2497 // QWidgetPrivate::hide_helper activates another sub-window when closing a-
2498 // modal dialog on Windows (see activateWindow() inside the ifdef).-
2499 case QEvent::WindowUnblocked:-
2500 d->activateCurrentWindow();-
2501 break;-
2502#endif-
2503 case QEvent::WindowActivate: {-
2504 d->isActivated = true;-
2505 if (d->childWindows.isEmpty())-
2506 break;-
2507 if (!d->active)-
2508 d->activateCurrentWindow();-
2509 d->setChildActivationEnabled(false, true);-
2510 break;-
2511 }-
2512 case QEvent::WindowDeactivate:-
2513 d->isActivated = false;-
2514 d->setChildActivationEnabled(false, true);-
2515 break;-
2516 case QEvent::StyleChange:-
2517 // Re-tile the views if we're in tiled mode. Re-tile means we will change-
2518 // the geometry of the children, which in turn means 'isSubWindowsTiled'-
2519 // is set to false, so we have to update the state at the end.-
2520 if (d->isSubWindowsTiled) {-
2521 tileSubWindows();-
2522 d->isSubWindowsTiled = true;-
2523 }-
2524 break;-
2525 case QEvent::WindowIconChange:-
2526 foreach (QMdiSubWindow *window, d->childWindows) {-
2527 if (sanityCheck(window, "QMdiArea::WindowIconChange"))-
2528 QApplication::sendEvent(window, event);-
2529 }-
2530 break;-
2531 case QEvent::Hide:-
2532 d->setActive(d->active, false, false);-
2533 d->setChildActivationEnabled(false);-
2534 break;-
2535#ifndef QT_NO_TABBAR-
2536 case QEvent::LayoutDirectionChange:-
2537 d->updateTabBarGeometry();-
2538 break;-
2539#endif-
2540 default:-
2541 break;-
2542 }-
2543 return QAbstractScrollArea::event(event);-
2544}-
2545-
2546/*!-
2547 \reimp-
2548*/-
2549bool QMdiArea::eventFilter(QObject *object, QEvent *event)-
2550{-
2551 if (!object)-
2552 return QAbstractScrollArea::eventFilter(object, event);-
2553-
2554 Q_D(QMdiArea);-
2555 // Global key events with Ctrl modifier.-
2556 if (event->type() == QEvent::KeyPress || event->type() == QEvent::KeyRelease) {-
2557-
2558 QKeyEvent *keyEvent = static_cast<QKeyEvent *>(event);-
2559 // Ingore key events without a Ctrl modifier (except for press/release on the modifier itself).-
2560#ifdef Q_DEAD_CODE_FROM_QT4_MAC-
2561 if (!(keyEvent->modifiers() & Qt::MetaModifier) && keyEvent->key() != Qt::Key_Meta)-
2562#else-
2563 if (!(keyEvent->modifiers() & Qt::ControlModifier) && keyEvent->key() != Qt::Key_Control)-
2564#endif-
2565 return QAbstractScrollArea::eventFilter(object, event);-
2566-
2567 // Find closest mdi area (in case we have a nested workspace).-
2568 QMdiArea *area = mdiAreaParent(static_cast<QWidget *>(object));-
2569 if (!area)-
2570 return QAbstractScrollArea::eventFilter(object, event);-
2571-
2572 const bool keyPress = (event->type() == QEvent::KeyPress);-
2573-
2574 // 1) Ctrl-Tab once -> activate the previously active window.-
2575 // 2) Ctrl-Tab (Tab, Tab, ...) -> iterate through all windows (activateNextSubWindow()).-
2576 // 3) Ctrl-Shift-Tab (Tab, Tab, ...) -> iterate through all windows in the opposite-
2577 // direction (activatePreviousSubWindow())-
2578 switch (keyEvent->key()) {-
2579#ifdef Q_DEAD_CODE_FROM_QT4_MAC-
2580 case Qt::Key_Meta:-
2581#else-
2582 case Qt::Key_Control:-
2583#endif-
2584 if (keyPress)-
2585 area->d_func()->startTabToPreviousTimer();-
2586 else-
2587 area->d_func()->activateHighlightedWindow();-
2588 break;-
2589 case Qt::Key_Tab:-
2590 case Qt::Key_Backtab:-
2591 if (keyPress)-
2592 area->d_func()->highlightNextSubWindow(keyEvent->key() == Qt::Key_Tab ? 1 : -1);-
2593 return true;-
2594#ifndef QT_NO_RUBBERBAND-
2595 case Qt::Key_Escape:-
2596 area->d_func()->hideRubberBand();-
2597 break;-
2598#endif-
2599 default:-
2600 break;-
2601 }-
2602 return QAbstractScrollArea::eventFilter(object, event);-
2603 }-
2604-
2605 QMdiSubWindow *subWindow = qobject_cast<QMdiSubWindow *>(object);-
2606-
2607 if (!subWindow) {-
2608 // QApplication events:-
2609 if (event->type() == QEvent::ApplicationActivate && !d->active-
2610 && isVisible() && !window()->isMinimized()) {-
2611 d->activateCurrentWindow();-
2612 } else if (event->type() == QEvent::ApplicationDeactivate && d->active) {-
2613 d->setActive(d->active, false, false);-
2614 }-
2615 return QAbstractScrollArea::eventFilter(object, event);-
2616 }-
2617-
2618 if (subWindow->mdiArea() != this)-
2619 return QAbstractScrollArea::eventFilter(object, event);-
2620-
2621 // QMdiSubWindow events:-
2622 switch (event->type()) {-
2623 case QEvent::Move:-
2624 case QEvent::Resize:-
2625 if (d->tileCalledFromResizeEvent)-
2626 break;-
2627 d->updateScrollBars();-
2628 if (!subWindow->isMinimized())-
2629 d->isSubWindowsTiled = false;-
2630 break;-
2631 case QEvent::Show:-
2632#ifndef QT_NO_TABBAR-
2633 if (d->tabBar) {-
2634 const int tabIndex = d->childWindows.indexOf(subWindow);-
2635 if (!d->tabBar->isTabEnabled(tabIndex))-
2636 d->tabBar->setTabEnabled(tabIndex, true);-
2637 }-
2638#endif // QT_NO_TABBAR-
2639 // fall through-
2640 case QEvent::Hide:-
2641 d->isSubWindowsTiled = false;-
2642 break;-
2643#ifndef QT_NO_RUBBERBAND-
2644 case QEvent::Close:-
2645 if (d->childWindows.indexOf(subWindow) == d->indexToHighlighted)-
2646 d->hideRubberBand();-
2647 break;-
2648#endif-
2649#ifndef QT_NO_TABBAR-
2650 case QEvent::WindowTitleChange:-
2651 case QEvent::ModifiedChange:-
2652 if (d->tabBar)-
2653 d->tabBar->setTabText(d->childWindows.indexOf(subWindow), tabTextFor(subWindow));-
2654 break;-
2655 case QEvent::WindowIconChange:-
2656 if (d->tabBar)-
2657 d->tabBar->setTabIcon(d->childWindows.indexOf(subWindow), subWindow->windowIcon());-
2658 break;-
2659#endif // QT_NO_TABBAR-
2660 default:-
2661 break;-
2662 }-
2663 return QAbstractScrollArea::eventFilter(object, event);-
2664}-
2665-
2666/*!-
2667 \reimp-
2668*/-
2669void QMdiArea::paintEvent(QPaintEvent *paintEvent)-
2670{-
2671 Q_D(QMdiArea);-
2672 QPainter painter(d->viewport);-
2673 const QVector<QRect> &exposedRects = paintEvent->region().rects();-
2674 for (int i = 0; i < exposedRects.size(); ++i)-
2675 painter.fillRect(exposedRects.at(i), d->background);-
2676}-
2677-
2678/*!-
2679 This slot is called by QAbstractScrollArea after setViewport() has been-
2680 called. Reimplement this function in a subclass of QMdiArea to-
2681 initialize the new \a viewport before it is used.-
2682-
2683 \sa setViewport()-
2684*/-
2685void QMdiArea::setupViewport(QWidget *viewport)-
2686{-
2687 Q_D(QMdiArea);-
2688 if (viewport)-
2689 viewport->setAttribute(Qt::WA_OpaquePaintEvent, d->background.isOpaque());-
2690 foreach (QMdiSubWindow *child, d->childWindows) {-
2691 if (!sanityCheck(child, "QMdiArea::setupViewport"))-
2692 continue;-
2693 child->setParent(viewport, child->windowFlags());-
2694 }-
2695}-
2696-
2697QT_END_NAMESPACE-
2698-
2699#include "moc_qmdiarea.cpp"-
2700-
2701#endif // QT_NO_MDIAREA-
Source codeSwitch to Preprocessed file

Generated by Squish Coco Non-Commercial 4.3.0-BETA-master-30-08-2018-4cb69e9