mirror of
https://bitbucket.org/smil3y/katie.git
synced 2025-02-26 11:52:57 +00:00

the list of upstream commits is incomplete, the Qt(5) devs have taken care of many warnings and I have not scoped trough all of the repos and commits to find them out and list them. I've made some changes on my own too upstream commits:fece2474fe
e6799c6e33
64a7ac344e
Signed-off-by: Ivailo Monev <xakepa10@gmail.com>
2012 lines
57 KiB
C++
2012 lines
57 KiB
C++
/****************************************************************************
|
|
**
|
|
** Copyright (C) 2015 The Qt Company Ltd.
|
|
** Contact: http://www.qt.io/licensing/
|
|
**
|
|
** This file is part of the QtGui module of the Qt Toolkit.
|
|
**
|
|
** $QT_BEGIN_LICENSE:LGPL$
|
|
** Commercial License Usage
|
|
** Licensees holding valid commercial Qt licenses may use this file in
|
|
** accordance with the commercial license agreement provided with the
|
|
** Software or, alternatively, in accordance with the terms contained in
|
|
** a written agreement between you and The Qt Company. For licensing terms
|
|
** and conditions see http://www.qt.io/terms-conditions. For further
|
|
** information use the contact form at http://www.qt.io/contact-us.
|
|
**
|
|
** GNU Lesser General Public License Usage
|
|
** Alternatively, this file may be used under the terms of the GNU Lesser
|
|
** General Public License version 2.1 or version 3 as published by the Free
|
|
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
|
|
** LICENSE.LGPLv3 included in the packaging of this file. Please review the
|
|
** following information to ensure the GNU Lesser General Public License
|
|
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
|
|
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
|
**
|
|
** As a special exception, The Qt Company gives you certain additional
|
|
** rights. These rights are described in The Qt Company LGPL Exception
|
|
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
|
|
**
|
|
** GNU General Public License Usage
|
|
** Alternatively, this file may be used under the terms of the GNU
|
|
** General Public License version 3.0 as published by the Free Software
|
|
** Foundation and appearing in the file LICENSE.GPL included in the
|
|
** packaging of this file. Please review the following information to
|
|
** ensure the GNU General Public License version 3.0 requirements will be
|
|
** met: http://www.gnu.org/copyleft/gpl.html.
|
|
**
|
|
** $QT_END_LICENSE$
|
|
**
|
|
****************************************************************************/
|
|
|
|
#include "qmainwindowlayout_p.h"
|
|
#include "qdockarealayout_p.h"
|
|
|
|
#ifndef QT_NO_MAINWINDOW
|
|
#include "qdockwidget.h"
|
|
#include "qdockwidget_p.h"
|
|
#include "qtoolbar_p.h"
|
|
#include "qmainwindow.h"
|
|
#include "qmainwindowlayout_p.h"
|
|
#include "qtoolbar.h"
|
|
#include "qtoolbarlayout_p.h"
|
|
#include "qwidgetanimator_p.h"
|
|
#include "qrubberband.h"
|
|
#include "qdockwidget_p.h"
|
|
#include "qtabbar_p.h"
|
|
|
|
#include <qapplication.h>
|
|
#include <qstatusbar.h>
|
|
#include <qstring.h>
|
|
#include <qstyle.h>
|
|
#include <qvarlengtharray.h>
|
|
#include <qstack.h>
|
|
#include <qmap.h>
|
|
#include <qtimer.h>
|
|
|
|
#include <qdebug.h>
|
|
|
|
#include <qapplication_p.h>
|
|
#include <qlayoutengine_p.h>
|
|
#ifdef Q_WS_MAC
|
|
# include <qcore_mac_p.h>
|
|
# include <qt_cocoa_helpers_mac_p.h>
|
|
#endif
|
|
|
|
#ifdef QT_NO_DOCKWIDGET
|
|
extern QMainWindowLayout *qt_mainwindow_layout(const QMainWindow *window);
|
|
#endif
|
|
|
|
#ifdef Q_DEBUG_MAINWINDOW_LAYOUT
|
|
# include <QTextStream>
|
|
#endif
|
|
|
|
QT_BEGIN_NAMESPACE
|
|
|
|
/******************************************************************************
|
|
** debug
|
|
*/
|
|
|
|
#if defined(Q_DEBUG_MAINWINDOW_LAYOUT) && !defined(QT_NO_DOCKWIDGET)
|
|
|
|
static QTextStream qout(stderr, QIODevice::WriteOnly);
|
|
|
|
static void dumpLayout(QTextStream &qout, const QDockAreaLayoutInfo &layout, QString indent);
|
|
|
|
static void dumpLayout(QTextStream &qout, const QDockAreaLayoutItem &item, QString indent)
|
|
{
|
|
qout << indent << "QDockAreaLayoutItem: "
|
|
<< "pos: " << item.pos << " size:" << item.size
|
|
<< " gap:" << (item.flags & QDockAreaLayoutItem::GapItem)
|
|
<< " keepSize:" << (item.flags & QDockAreaLayoutItem::KeepSize) << '\n';
|
|
indent += QLatin1String(" ");
|
|
if (item.widgetItem != 0) {
|
|
qout << indent << "widget: "
|
|
<< item.widgetItem->widget()->metaObject()->className()
|
|
<< ' ' << item.widgetItem->widget()->windowTitle() << '\n';
|
|
} else if (item.subinfo != 0) {
|
|
qout << indent << "subinfo:\n";
|
|
dumpLayout(qout, *item.subinfo, indent + QLatin1String(" "));
|
|
} else if (item.placeHolderItem != 0) {
|
|
QRect r = item.placeHolderItem->topLevelRect;
|
|
qout << indent << "placeHolder: "
|
|
<< "pos: " << item.pos << " size:" << item.size
|
|
<< " gap:" << (item.flags & QDockAreaLayoutItem::GapItem)
|
|
<< " keepSize:" << (item.flags & QDockAreaLayoutItem::KeepSize)
|
|
<< " objectName:" << item.placeHolderItem->objectName
|
|
<< " hidden:" << item.placeHolderItem->hidden
|
|
<< " window:" << item.placeHolderItem->window
|
|
<< " rect:" << r.x() << ',' << r.y() << ' '
|
|
<< r.width() << 'x' << r.height() << '\n';
|
|
}
|
|
qout.flush();
|
|
}
|
|
|
|
static void dumpLayout(QTextStream &qout, const QDockAreaLayoutInfo &layout, QString indent)
|
|
{
|
|
qout << indent << "QDockAreaLayoutInfo: "
|
|
<< layout.rect.left() << ','
|
|
<< layout.rect.top() << ' '
|
|
<< layout.rect.width() << 'x'
|
|
<< layout.rect.height()
|
|
<< " orient:" << layout.o
|
|
<< " tabbed:" << layout.tabbed
|
|
<< " tbshape:" << layout.tabBarShape << '\n';
|
|
|
|
indent += QLatin1String(" ");
|
|
|
|
for (int i = 0; i < layout.item_list.count(); ++i) {
|
|
qout << indent << "Item: " << i << '\n';
|
|
dumpLayout(qout, layout.item_list.at(i), indent + QLatin1String(" "));
|
|
}
|
|
qout.flush();
|
|
};
|
|
|
|
static void dumpLayout(QTextStream &qout, const QDockAreaLayout &layout, QString indent)
|
|
{
|
|
qout << indent << "QDockAreaLayout: "
|
|
<< layout.rect.left() << ','
|
|
<< layout.rect.top() << ' '
|
|
<< layout.rect.width() << 'x'
|
|
<< layout.rect.height() << '\n';
|
|
|
|
qout << indent << "TopDockArea:\n";
|
|
dumpLayout(qout, layout.docks[QInternal::TopDock], indent + QLatin1String(" "));
|
|
qout << indent << "LeftDockArea:\n";
|
|
dumpLayout(qout, layout.docks[QInternal::LeftDock], indent + QLatin1String(" "));
|
|
qout << indent << "RightDockArea:\n";
|
|
dumpLayout(qout, layout.docks[QInternal::RightDock], indent + QLatin1String(" "));
|
|
qout << indent << "BottomDockArea:\n";
|
|
dumpLayout(qout, layout.docks[QInternal::BottomDock], indent + QLatin1String(" "));
|
|
|
|
qout.flush();
|
|
};
|
|
|
|
void qt_dumpLayout(QTextStream &qout, QMainWindow *window)
|
|
{
|
|
QMainWindowLayout *layout = qt_mainwindow_layout(window);
|
|
dumpLayout(qout, layout->layoutState.dockAreaLayout, QString());
|
|
}
|
|
|
|
#endif // Q_DEBUG_MAINWINDOW_LAYOUT && !QT_NO_DOCKWIDGET
|
|
|
|
/******************************************************************************
|
|
** QMainWindowLayoutState
|
|
*/
|
|
|
|
// we deal with all the #ifndefferry here so QMainWindowLayout code is clean
|
|
|
|
QMainWindowLayoutState::QMainWindowLayoutState(QMainWindow *win)
|
|
:
|
|
#ifndef QT_NO_TOOLBAR
|
|
toolBarAreaLayout(win),
|
|
#endif
|
|
#ifndef QT_NO_DOCKWIDGET
|
|
dockAreaLayout(win)
|
|
#else
|
|
centralWidgetItem(0)
|
|
#endif
|
|
|
|
{
|
|
mainWindow = win;
|
|
}
|
|
|
|
QSize QMainWindowLayoutState::sizeHint() const
|
|
{
|
|
|
|
QSize result(0, 0);
|
|
|
|
#ifndef QT_NO_DOCKWIDGET
|
|
result = dockAreaLayout.sizeHint();
|
|
#else
|
|
if (centralWidgetItem != 0)
|
|
result = centralWidgetItem->sizeHint();
|
|
#endif
|
|
|
|
#ifndef QT_NO_TOOLBAR
|
|
result = toolBarAreaLayout.sizeHint(result);
|
|
#endif // QT_NO_TOOLBAR
|
|
|
|
return result;
|
|
}
|
|
|
|
QSize QMainWindowLayoutState::minimumSize() const
|
|
{
|
|
QSize result(0, 0);
|
|
|
|
#ifndef QT_NO_DOCKWIDGET
|
|
result = dockAreaLayout.minimumSize();
|
|
#else
|
|
if (centralWidgetItem != 0)
|
|
result = centralWidgetItem->minimumSize();
|
|
#endif
|
|
|
|
#ifndef QT_NO_TOOLBAR
|
|
result = toolBarAreaLayout.minimumSize(result);
|
|
#endif // QT_NO_TOOLBAR
|
|
|
|
return result;
|
|
}
|
|
|
|
void QMainWindowLayoutState::apply(bool animated)
|
|
{
|
|
#ifndef QT_NO_TOOLBAR
|
|
toolBarAreaLayout.apply(animated);
|
|
#endif
|
|
|
|
#ifndef QT_NO_DOCKWIDGET
|
|
// dumpLayout(dockAreaLayout, QString());
|
|
dockAreaLayout.apply(animated);
|
|
#else
|
|
if (centralWidgetItem != 0) {
|
|
QMainWindowLayout *layout = qt_mainwindow_layout(mainWindow);
|
|
Q_ASSERT(layout != 0);
|
|
layout->widgetAnimator.animate(centralWidgetItem->widget(), centralWidgetRect, animated);
|
|
}
|
|
#endif
|
|
}
|
|
|
|
void QMainWindowLayoutState::fitLayout()
|
|
{
|
|
QRect r;
|
|
#ifdef QT_NO_TOOLBAR
|
|
r = rect;
|
|
#else
|
|
toolBarAreaLayout.rect = rect;
|
|
r = toolBarAreaLayout.fitLayout();
|
|
#endif // QT_NO_TOOLBAR
|
|
|
|
#ifndef QT_NO_DOCKWIDGET
|
|
dockAreaLayout.rect = r;
|
|
dockAreaLayout.fitLayout();
|
|
#else
|
|
centralWidgetRect = r;
|
|
#endif
|
|
}
|
|
|
|
void QMainWindowLayoutState::deleteAllLayoutItems()
|
|
{
|
|
#ifndef QT_NO_TOOLBAR
|
|
toolBarAreaLayout.deleteAllLayoutItems();
|
|
#endif
|
|
|
|
#ifndef QT_NO_DOCKWIDGET
|
|
dockAreaLayout.deleteAllLayoutItems();
|
|
#endif
|
|
}
|
|
|
|
void QMainWindowLayoutState::deleteCentralWidgetItem()
|
|
{
|
|
#ifndef QT_NO_DOCKWIDGET
|
|
delete dockAreaLayout.centralWidgetItem;
|
|
dockAreaLayout.centralWidgetItem = 0;
|
|
#else
|
|
delete centralWidgetItem;
|
|
centralWidgetItem = 0;
|
|
#endif
|
|
}
|
|
|
|
QLayoutItem *QMainWindowLayoutState::itemAt(int index, int *x) const
|
|
{
|
|
#ifndef QT_NO_TOOLBAR
|
|
if (QLayoutItem *ret = toolBarAreaLayout.itemAt(x, index))
|
|
return ret;
|
|
#endif
|
|
|
|
#ifndef QT_NO_DOCKWIDGET
|
|
if (QLayoutItem *ret = dockAreaLayout.itemAt(x, index))
|
|
return ret;
|
|
#else
|
|
if (centralWidgetItem != 0 && (*x)++ == index)
|
|
return centralWidgetItem;
|
|
#endif
|
|
|
|
return 0;
|
|
}
|
|
|
|
QLayoutItem *QMainWindowLayoutState::takeAt(int index, int *x)
|
|
{
|
|
#ifndef QT_NO_TOOLBAR
|
|
if (QLayoutItem *ret = toolBarAreaLayout.takeAt(x, index))
|
|
return ret;
|
|
#endif
|
|
|
|
#ifndef QT_NO_DOCKWIDGET
|
|
if (QLayoutItem *ret = dockAreaLayout.takeAt(x, index))
|
|
return ret;
|
|
#else
|
|
if (centralWidgetItem != 0 && (*x)++ == index) {
|
|
QLayoutItem *ret = centralWidgetItem;
|
|
centralWidgetItem = 0;
|
|
return ret;
|
|
}
|
|
#endif
|
|
|
|
return 0;
|
|
}
|
|
|
|
QList<int> QMainWindowLayoutState::indexOf(QWidget *widget) const
|
|
{
|
|
QList<int> result;
|
|
|
|
#ifndef QT_NO_TOOLBAR
|
|
// is it a toolbar?
|
|
if (QToolBar *toolBar = qobject_cast<QToolBar*>(widget)) {
|
|
result = toolBarAreaLayout.indexOf(toolBar);
|
|
if (!result.isEmpty())
|
|
result.prepend(0);
|
|
return result;
|
|
}
|
|
#endif
|
|
|
|
#ifndef QT_NO_DOCKWIDGET
|
|
// is it a dock widget?
|
|
if (QDockWidget *dockWidget = qobject_cast<QDockWidget *>(widget)) {
|
|
result = dockAreaLayout.indexOf(dockWidget);
|
|
if (!result.isEmpty())
|
|
result.prepend(1);
|
|
return result;
|
|
}
|
|
#endif //QT_NO_DOCKWIDGET
|
|
|
|
return result;
|
|
}
|
|
|
|
bool QMainWindowLayoutState::contains(QWidget *widget) const
|
|
{
|
|
#ifndef QT_NO_DOCKWIDGET
|
|
if (dockAreaLayout.centralWidgetItem != 0 && dockAreaLayout.centralWidgetItem->widget() == widget)
|
|
return true;
|
|
if (!dockAreaLayout.indexOf(widget).isEmpty())
|
|
return true;
|
|
#else
|
|
if (centralWidgetItem != 0 && centralWidgetItem->widget() == widget)
|
|
return true;
|
|
#endif
|
|
|
|
#ifndef QT_NO_TOOLBAR
|
|
if (!toolBarAreaLayout.indexOf(widget).isEmpty())
|
|
return true;
|
|
#endif
|
|
return false;
|
|
}
|
|
|
|
void QMainWindowLayoutState::setCentralWidget(QWidget *widget)
|
|
{
|
|
QLayoutItem *item = 0;
|
|
//make sure we remove the widget
|
|
deleteCentralWidgetItem();
|
|
|
|
if (widget != 0)
|
|
item = new QWidgetItemV2(widget);
|
|
|
|
#ifndef QT_NO_DOCKWIDGET
|
|
dockAreaLayout.centralWidgetItem = item;
|
|
#else
|
|
centralWidgetItem = item;
|
|
#endif
|
|
}
|
|
|
|
QWidget *QMainWindowLayoutState::centralWidget() const
|
|
{
|
|
QLayoutItem *item = 0;
|
|
|
|
#ifndef QT_NO_DOCKWIDGET
|
|
item = dockAreaLayout.centralWidgetItem;
|
|
#else
|
|
item = centralWidgetItem;
|
|
#endif
|
|
|
|
if (item != 0)
|
|
return item->widget();
|
|
return 0;
|
|
}
|
|
|
|
QList<int> QMainWindowLayoutState::gapIndex(QWidget *widget,
|
|
const QPoint &pos) const
|
|
{
|
|
QList<int> result;
|
|
|
|
#ifndef QT_NO_TOOLBAR
|
|
// is it a toolbar?
|
|
if (qobject_cast<QToolBar*>(widget) != 0) {
|
|
result = toolBarAreaLayout.gapIndex(pos);
|
|
if (!result.isEmpty())
|
|
result.prepend(0);
|
|
return result;
|
|
}
|
|
#endif
|
|
|
|
#ifndef QT_NO_DOCKWIDGET
|
|
// is it a dock widget?
|
|
if (qobject_cast<QDockWidget *>(widget) != 0) {
|
|
result = dockAreaLayout.gapIndex(pos);
|
|
if (!result.isEmpty())
|
|
result.prepend(1);
|
|
return result;
|
|
}
|
|
#endif //QT_NO_DOCKWIDGET
|
|
|
|
return result;
|
|
}
|
|
|
|
bool QMainWindowLayoutState::insertGap(const QList<int> &path, QLayoutItem *item)
|
|
{
|
|
if (path.isEmpty())
|
|
return false;
|
|
|
|
int i = path.first();
|
|
|
|
#ifndef QT_NO_TOOLBAR
|
|
if (i == 0) {
|
|
Q_ASSERT(qobject_cast<QToolBar*>(item->widget()) != 0);
|
|
return toolBarAreaLayout.insertGap(path.mid(1), item);
|
|
}
|
|
#endif
|
|
|
|
#ifndef QT_NO_DOCKWIDGET
|
|
if (i == 1) {
|
|
Q_ASSERT(qobject_cast<QDockWidget*>(item->widget()) != 0);
|
|
return dockAreaLayout.insertGap(path.mid(1), item);
|
|
}
|
|
#endif //QT_NO_DOCKWIDGET
|
|
|
|
return false;
|
|
}
|
|
|
|
void QMainWindowLayoutState::remove(const QList<int> &path)
|
|
{
|
|
int i = path.first();
|
|
|
|
#ifndef QT_NO_TOOLBAR
|
|
if (i == 0)
|
|
toolBarAreaLayout.remove(path.mid(1));
|
|
#endif
|
|
|
|
#ifndef QT_NO_DOCKWIDGET
|
|
if (i == 1)
|
|
dockAreaLayout.remove(path.mid(1));
|
|
#endif //QT_NO_DOCKWIDGET
|
|
}
|
|
|
|
void QMainWindowLayoutState::remove(QLayoutItem *item)
|
|
{
|
|
#ifndef QT_NO_TOOLBAR
|
|
toolBarAreaLayout.remove(item);
|
|
#endif
|
|
|
|
#ifndef QT_NO_DOCKWIDGET
|
|
// is it a dock widget?
|
|
if (QDockWidget *dockWidget = qobject_cast<QDockWidget *>(item->widget())) {
|
|
QList<int> path = dockAreaLayout.indexOf(dockWidget);
|
|
if (!path.isEmpty())
|
|
dockAreaLayout.remove(path);
|
|
}
|
|
#endif //QT_NO_DOCKWIDGET
|
|
}
|
|
|
|
void QMainWindowLayoutState::clear()
|
|
{
|
|
#ifndef QT_NO_TOOLBAR
|
|
toolBarAreaLayout.clear();
|
|
#endif
|
|
|
|
#ifndef QT_NO_DOCKWIDGET
|
|
dockAreaLayout.clear();
|
|
#else
|
|
centralWidgetRect = QRect();
|
|
#endif
|
|
|
|
rect = QRect();
|
|
}
|
|
|
|
bool QMainWindowLayoutState::isValid() const
|
|
{
|
|
return rect.isValid();
|
|
}
|
|
|
|
QLayoutItem *QMainWindowLayoutState::item(const QList<int> &path)
|
|
{
|
|
int i = path.first();
|
|
|
|
#ifndef QT_NO_TOOLBAR
|
|
if (i == 0) {
|
|
const QToolBarAreaLayoutItem *tbItem = toolBarAreaLayout.item(path.mid(1));
|
|
Q_ASSERT(tbItem);
|
|
return tbItem->widgetItem;
|
|
}
|
|
#endif
|
|
|
|
#ifndef QT_NO_DOCKWIDGET
|
|
if (i == 1)
|
|
return dockAreaLayout.item(path.mid(1)).widgetItem;
|
|
#endif //QT_NO_DOCKWIDGET
|
|
|
|
return 0;
|
|
}
|
|
|
|
QRect QMainWindowLayoutState::itemRect(const QList<int> &path) const
|
|
{
|
|
int i = path.first();
|
|
|
|
#ifndef QT_NO_TOOLBAR
|
|
if (i == 0)
|
|
return toolBarAreaLayout.itemRect(path.mid(1));
|
|
#endif
|
|
|
|
#ifndef QT_NO_DOCKWIDGET
|
|
if (i == 1)
|
|
return dockAreaLayout.itemRect(path.mid(1));
|
|
#endif //QT_NO_DOCKWIDGET
|
|
|
|
return QRect();
|
|
}
|
|
|
|
QRect QMainWindowLayoutState::gapRect(const QList<int> &path) const
|
|
{
|
|
int i = path.first();
|
|
|
|
#ifndef QT_NO_TOOLBAR
|
|
if (i == 0)
|
|
return toolBarAreaLayout.itemRect(path.mid(1));
|
|
#endif
|
|
|
|
#ifndef QT_NO_DOCKWIDGET
|
|
if (i == 1)
|
|
return dockAreaLayout.gapRect(path.mid(1));
|
|
#endif //QT_NO_DOCKWIDGET
|
|
|
|
return QRect();
|
|
}
|
|
|
|
QLayoutItem *QMainWindowLayoutState::plug(const QList<int> &path)
|
|
{
|
|
int i = path.first();
|
|
|
|
#ifndef QT_NO_TOOLBAR
|
|
if (i == 0)
|
|
return toolBarAreaLayout.plug(path.mid(1));
|
|
#endif
|
|
|
|
#ifndef QT_NO_DOCKWIDGET
|
|
if (i == 1)
|
|
return dockAreaLayout.plug(path.mid(1));
|
|
#endif //QT_NO_DOCKWIDGET
|
|
|
|
return 0;
|
|
}
|
|
|
|
QLayoutItem *QMainWindowLayoutState::unplug(const QList<int> &path, QMainWindowLayoutState *other)
|
|
{
|
|
int i = path.first();
|
|
|
|
#ifdef QT_NO_TOOLBAR
|
|
Q_UNUSED(other);
|
|
#else
|
|
if (i == 0)
|
|
return toolBarAreaLayout.unplug(path.mid(1), other ? &other->toolBarAreaLayout : 0);
|
|
#endif
|
|
|
|
#ifndef QT_NO_DOCKWIDGET
|
|
if (i == 1)
|
|
return dockAreaLayout.unplug(path.mid(1));
|
|
#endif //QT_NO_DOCKWIDGET
|
|
|
|
return 0;
|
|
}
|
|
|
|
void QMainWindowLayoutState::saveState(QDataStream &stream) const
|
|
{
|
|
#ifndef QT_NO_DOCKWIDGET
|
|
dockAreaLayout.saveState(stream);
|
|
#endif
|
|
#ifndef QT_NO_TOOLBAR
|
|
toolBarAreaLayout.saveState(stream);
|
|
#endif
|
|
}
|
|
|
|
template <typename T>
|
|
static QList<T> findChildrenHelper(const QObject *o)
|
|
{
|
|
const QObjectList &list = o->children();
|
|
QList<T> result;
|
|
|
|
for (int i=0; i < list.size(); ++i) {
|
|
if (T t = qobject_cast<T>(list[i])) {
|
|
result.append(t);
|
|
}
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
//pre4.3 tests the format that was used before 4.3
|
|
bool QMainWindowLayoutState::checkFormat(QDataStream &stream, bool pre43)
|
|
{
|
|
#ifdef QT_NO_TOOLBAR
|
|
Q_UNUSED(pre43);
|
|
#endif
|
|
while (!stream.atEnd()) {
|
|
uchar marker;
|
|
stream >> marker;
|
|
switch(marker)
|
|
{
|
|
#ifndef QT_NO_TOOLBAR
|
|
case QToolBarAreaLayout::ToolBarStateMarker:
|
|
case QToolBarAreaLayout::ToolBarStateMarkerEx:
|
|
{
|
|
QList<QToolBar *> toolBars = findChildrenHelper<QToolBar*>(mainWindow);
|
|
if (!toolBarAreaLayout.restoreState(stream, toolBars, marker,
|
|
pre43 /*testing 4.3 format*/, true /*testing*/)) {
|
|
return false;
|
|
}
|
|
}
|
|
break;
|
|
#endif // QT_NO_TOOLBAR
|
|
|
|
#ifndef QT_NO_DOCKWIDGET
|
|
case QDockAreaLayout::DockWidgetStateMarker:
|
|
{
|
|
QList<QDockWidget *> dockWidgets = findChildrenHelper<QDockWidget*>(mainWindow);
|
|
if (!dockAreaLayout.restoreState(stream, dockWidgets, true /*testing*/)) {
|
|
return false;
|
|
}
|
|
}
|
|
break;
|
|
#endif
|
|
default:
|
|
//there was an error during the parsing
|
|
return false;
|
|
}// switch
|
|
} //while
|
|
|
|
//everything went fine: it must be a pre-4.3 saved state
|
|
return true;
|
|
}
|
|
|
|
bool QMainWindowLayoutState::restoreState(QDataStream &_stream,
|
|
const QMainWindowLayoutState &oldState)
|
|
{
|
|
//make a copy of the data so that we can read it more than once
|
|
QByteArray copy;
|
|
while(!_stream.atEnd()) {
|
|
int length = 1024;
|
|
QByteArray ba(length, '\0');
|
|
length = _stream.readRawData(ba.data(), ba.size());
|
|
ba.resize(length);
|
|
copy += ba;
|
|
}
|
|
|
|
QDataStream ds(copy);
|
|
const bool oldFormat = !checkFormat(ds, false);
|
|
if (oldFormat) {
|
|
//we should try with the old format
|
|
QDataStream ds2(copy);
|
|
if (!checkFormat(ds2, true)) {
|
|
return false; //format unknown
|
|
}
|
|
}
|
|
|
|
QDataStream stream(copy);
|
|
|
|
while (!stream.atEnd()) {
|
|
uchar marker;
|
|
stream >> marker;
|
|
switch(marker)
|
|
{
|
|
#ifndef QT_NO_DOCKWIDGET
|
|
case QDockAreaLayout::DockWidgetStateMarker:
|
|
{
|
|
QList<QDockWidget *> dockWidgets = findChildrenHelper<QDockWidget*>(mainWindow);
|
|
if (!dockAreaLayout.restoreState(stream, dockWidgets))
|
|
return false;
|
|
|
|
for (int i = 0; i < dockWidgets.size(); ++i) {
|
|
QDockWidget *w = dockWidgets.at(i);
|
|
QList<int> path = dockAreaLayout.indexOf(w);
|
|
if (path.isEmpty()) {
|
|
QList<int> oldPath = oldState.dockAreaLayout.indexOf(w);
|
|
if (oldPath.isEmpty()) {
|
|
continue;
|
|
}
|
|
QDockAreaLayoutInfo *info = dockAreaLayout.info(oldPath);
|
|
if (info == 0) {
|
|
continue;
|
|
}
|
|
info->item_list.append(QDockAreaLayoutItem(new QDockWidgetItem(w)));
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
#endif // QT_NO_DOCKWIDGET
|
|
|
|
#ifndef QT_NO_TOOLBAR
|
|
case QToolBarAreaLayout::ToolBarStateMarker:
|
|
case QToolBarAreaLayout::ToolBarStateMarkerEx:
|
|
{
|
|
QList<QToolBar *> toolBars = findChildrenHelper<QToolBar*>(mainWindow);
|
|
if (!toolBarAreaLayout.restoreState(stream, toolBars, marker, oldFormat))
|
|
return false;
|
|
|
|
for (int i = 0; i < toolBars.size(); ++i) {
|
|
QToolBar *w = toolBars.at(i);
|
|
QList<int> path = toolBarAreaLayout.indexOf(w);
|
|
if (path.isEmpty()) {
|
|
QList<int> oldPath = oldState.toolBarAreaLayout.indexOf(w);
|
|
if (oldPath.isEmpty()) {
|
|
continue;
|
|
}
|
|
toolBarAreaLayout.docks[oldPath.at(0)].insertToolBar(0, w);
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
#endif //QT_NO_TOOLBAR
|
|
default:
|
|
return false;
|
|
}// switch
|
|
} //while
|
|
|
|
|
|
return true;
|
|
}
|
|
|
|
/******************************************************************************
|
|
** QMainWindowLayoutState - toolbars
|
|
*/
|
|
|
|
#ifndef QT_NO_TOOLBAR
|
|
|
|
static inline void validateToolBarArea(Qt::ToolBarArea &area)
|
|
{
|
|
switch (area) {
|
|
case Qt::LeftToolBarArea:
|
|
case Qt::RightToolBarArea:
|
|
case Qt::TopToolBarArea:
|
|
case Qt::BottomToolBarArea:
|
|
break;
|
|
default:
|
|
area = Qt::TopToolBarArea;
|
|
}
|
|
}
|
|
|
|
static QInternal::DockPosition toDockPos(Qt::ToolBarArea area)
|
|
{
|
|
switch (area) {
|
|
case Qt::LeftToolBarArea: return QInternal::LeftDock;
|
|
case Qt::RightToolBarArea: return QInternal::RightDock;
|
|
case Qt::TopToolBarArea: return QInternal::TopDock;
|
|
case Qt::BottomToolBarArea: return QInternal::BottomDock;
|
|
default:
|
|
break;
|
|
}
|
|
|
|
return QInternal::DockCount;
|
|
}
|
|
|
|
static Qt::ToolBarArea toToolBarArea(QInternal::DockPosition pos)
|
|
{
|
|
switch (pos) {
|
|
case QInternal::LeftDock: return Qt::LeftToolBarArea;
|
|
case QInternal::RightDock: return Qt::RightToolBarArea;
|
|
case QInternal::TopDock: return Qt::TopToolBarArea;
|
|
case QInternal::BottomDock: return Qt::BottomToolBarArea;
|
|
default: break;
|
|
}
|
|
return Qt::NoToolBarArea;
|
|
}
|
|
|
|
static inline Qt::ToolBarArea toToolBarArea(int pos)
|
|
{
|
|
return toToolBarArea(static_cast<QInternal::DockPosition>(pos));
|
|
}
|
|
|
|
void QMainWindowLayout::addToolBarBreak(Qt::ToolBarArea area)
|
|
{
|
|
validateToolBarArea(area);
|
|
|
|
layoutState.toolBarAreaLayout.addToolBarBreak(toDockPos(area));
|
|
if (savedState.isValid())
|
|
savedState.toolBarAreaLayout.addToolBarBreak(toDockPos(area));
|
|
|
|
invalidate();
|
|
}
|
|
|
|
void QMainWindowLayout::insertToolBarBreak(QToolBar *before)
|
|
{
|
|
layoutState.toolBarAreaLayout.insertToolBarBreak(before);
|
|
if (savedState.isValid())
|
|
savedState.toolBarAreaLayout.insertToolBarBreak(before);
|
|
invalidate();
|
|
}
|
|
|
|
void QMainWindowLayout::removeToolBarBreak(QToolBar *before)
|
|
{
|
|
layoutState.toolBarAreaLayout.removeToolBarBreak(before);
|
|
if (savedState.isValid())
|
|
savedState.toolBarAreaLayout.removeToolBarBreak(before);
|
|
invalidate();
|
|
}
|
|
|
|
void QMainWindowLayout::moveToolBar(QToolBar *toolbar, int pos)
|
|
{
|
|
layoutState.toolBarAreaLayout.moveToolBar(toolbar, pos);
|
|
if (savedState.isValid())
|
|
savedState.toolBarAreaLayout.moveToolBar(toolbar, pos);
|
|
invalidate();
|
|
}
|
|
|
|
/* Removes the toolbar from the mainwindow so that it can be added again. Does not
|
|
explicitly hide the toolbar. */
|
|
void QMainWindowLayout::removeToolBar(QToolBar *toolbar)
|
|
{
|
|
if (toolbar) {
|
|
QObject::disconnect(parentWidget(), SIGNAL(iconSizeChanged(QSize)),
|
|
toolbar, SLOT(_q_updateIconSize(QSize)));
|
|
QObject::disconnect(parentWidget(), SIGNAL(toolButtonStyleChanged(Qt::ToolButtonStyle)),
|
|
toolbar, SLOT(_q_updateToolButtonStyle(Qt::ToolButtonStyle)));
|
|
|
|
#ifdef Q_WS_MAC
|
|
if (usesHIToolBar(toolbar)) {
|
|
removeFromMacToolbar(toolbar);
|
|
} else
|
|
#endif // Q_WS_MAC
|
|
{
|
|
removeWidget(toolbar);
|
|
}
|
|
}
|
|
}
|
|
|
|
/*!
|
|
Adds \a toolbar to \a area, continuing the current line.
|
|
*/
|
|
void QMainWindowLayout::addToolBar(Qt::ToolBarArea area,
|
|
QToolBar *toolbar,
|
|
bool)
|
|
{
|
|
validateToolBarArea(area);
|
|
#ifdef Q_WS_MAC
|
|
if ((area == Qt::TopToolBarArea)
|
|
&& layoutState.mainWindow->unifiedTitleAndToolBarOnMac()) {
|
|
insertIntoMacToolbar(0, toolbar);
|
|
} else
|
|
#endif
|
|
{
|
|
//let's add the toolbar to the layout
|
|
addChildWidget(toolbar);
|
|
QLayoutItem * item = layoutState.toolBarAreaLayout.addToolBar(toDockPos(area), toolbar);
|
|
if (savedState.isValid() && item) {
|
|
// copy the toolbar also in the saved state
|
|
savedState.toolBarAreaLayout.insertItem(toDockPos(area), item);
|
|
}
|
|
invalidate();
|
|
|
|
//this ensures that the toolbar has the right window flags (not floating any more)
|
|
toolbar->d_func()->updateWindowFlags(false /*floating*/);
|
|
}
|
|
}
|
|
|
|
/*!
|
|
Adds \a toolbar before \a before
|
|
*/
|
|
void QMainWindowLayout::insertToolBar(QToolBar *before, QToolBar *toolbar)
|
|
{
|
|
#ifdef Q_WS_MAC
|
|
if (usesHIToolBar(before)) {
|
|
insertIntoMacToolbar(before, toolbar);
|
|
} else
|
|
#endif // Q_WS_MAC
|
|
{
|
|
addChildWidget(toolbar);
|
|
QLayoutItem * item = layoutState.toolBarAreaLayout.insertToolBar(before, toolbar);
|
|
if (savedState.isValid() && item) {
|
|
// copy the toolbar also in the saved state
|
|
savedState.toolBarAreaLayout.insertItem(before, item);
|
|
}
|
|
if (!currentGapPos.isEmpty() && currentGapPos.first() == 0) {
|
|
currentGapPos = layoutState.toolBarAreaLayout.currentGapIndex();
|
|
if (!currentGapPos.isEmpty()) {
|
|
currentGapPos.prepend(0);
|
|
currentGapRect = layoutState.itemRect(currentGapPos);
|
|
}
|
|
}
|
|
invalidate();
|
|
}
|
|
}
|
|
|
|
Qt::ToolBarArea QMainWindowLayout::toolBarArea(QToolBar *toolbar) const
|
|
{
|
|
QInternal::DockPosition pos = layoutState.toolBarAreaLayout.findToolBar(toolbar);
|
|
switch (pos) {
|
|
case QInternal::LeftDock: return Qt::LeftToolBarArea;
|
|
case QInternal::RightDock: return Qt::RightToolBarArea;
|
|
case QInternal::TopDock: return Qt::TopToolBarArea;
|
|
case QInternal::BottomDock: return Qt::BottomToolBarArea;
|
|
default: break;
|
|
}
|
|
#ifdef Q_WS_MAC
|
|
if (pos == QInternal::DockCount) {
|
|
if (qtoolbarsInUnifiedToolbarList.contains(toolbar))
|
|
return Qt::TopToolBarArea;
|
|
}
|
|
#endif
|
|
return Qt::NoToolBarArea;
|
|
}
|
|
|
|
bool QMainWindowLayout::toolBarBreak(QToolBar *toolBar) const
|
|
{
|
|
return layoutState.toolBarAreaLayout.toolBarBreak(toolBar);
|
|
}
|
|
|
|
void QMainWindowLayout::getStyleOptionInfo(QStyleOptionToolBar *option, QToolBar *toolBar) const
|
|
{
|
|
option->toolBarArea = toolBarArea(toolBar);
|
|
layoutState.toolBarAreaLayout.getStyleOptionInfo(option, toolBar);
|
|
}
|
|
|
|
void QMainWindowLayout::toggleToolBarsVisible()
|
|
{
|
|
bool updateNonUnifiedParts = true;
|
|
#ifdef Q_WS_MAC
|
|
if (layoutState.mainWindow->unifiedTitleAndToolBarOnMac()) {
|
|
// If we hit this case, someone has pressed the "toolbar button" which will
|
|
// toggle the unified toolbar visibility, because that's what the user wants.
|
|
// We might be in a situation where someone has hidden all the toolbars
|
|
// beforehand (maybe in construction), but now they've hit this button and
|
|
// and are expecting the items to show. What do we do?
|
|
// 1) Check the visibility of all the toolbars, if one is visible, do nothing, this
|
|
// preserves what people would expect (these toolbars were visible when I clicked last time).
|
|
// 2) If NONE are visible, then show them all. Again, this preserves the user expectation
|
|
// of, "I want to see the toolbars." The user may get more toolbars than expected, but this
|
|
// is better seeing nothing.
|
|
// Don't worry about any of this if we are going invisible. This does mean we may get
|
|
// into issues when switching into and out of fullscreen mode, but this is probably minor.
|
|
// If we ever need to do hiding, that would have to be taken care of after the unified toolbar
|
|
// has finished hiding.
|
|
// People can of course handle the QEvent::ToolBarChange event themselves and do
|
|
// WHATEVER they want if they don't like what we are doing (though the unified toolbar
|
|
// will fire regardless).
|
|
|
|
// Check if we REALLY need to update the geometry below. If we only have items in the
|
|
// unified toolbar, all the docks will be empty, so there's very little point
|
|
// in doing the geometry as Apple will do it (we also avoid flicker in Cocoa as well).
|
|
// FWIW, layoutState.toolBarAreaLayout.visible and the state of the unified toolbar
|
|
// visibility can get out of sync. I really don't think it's a big issue. It is kept
|
|
// to a minimum because we only change the visibility if we absolutely must.
|
|
// update the "non unified parts."
|
|
updateNonUnifiedParts = !layoutState.toolBarAreaLayout.isEmpty();
|
|
|
|
// We get this function before the unified toolbar does its thing.
|
|
// So, the value will be opposite of what we expect.
|
|
bool goingVisible = !macWindowToolbarIsVisible(qt_mac_window_for(layoutState.mainWindow));
|
|
if (goingVisible) {
|
|
const int ToolBarCount = qtoolbarsInUnifiedToolbarList.size();
|
|
bool needAllVisible = true;
|
|
for (int i = 0; i < ToolBarCount; ++i) {
|
|
if (!qtoolbarsInUnifiedToolbarList.at(i)->isHidden()) {
|
|
needAllVisible = false;
|
|
break;
|
|
}
|
|
}
|
|
if (needAllVisible) {
|
|
QBoolBlocker blocker(blockVisiblityCheck); // Disable the visibilty check because
|
|
// the toggle has already happened.
|
|
for (int i = 0; i < ToolBarCount; ++i)
|
|
qtoolbarsInUnifiedToolbarList.at(i)->setVisible(true);
|
|
}
|
|
}
|
|
if (!updateNonUnifiedParts)
|
|
layoutState.toolBarAreaLayout.visible = goingVisible;
|
|
}
|
|
#endif
|
|
if (updateNonUnifiedParts) {
|
|
layoutState.toolBarAreaLayout.visible = !layoutState.toolBarAreaLayout.visible;
|
|
if (!layoutState.mainWindow->isMaximized()) {
|
|
QPoint topLeft = parentWidget()->geometry().topLeft();
|
|
QRect r = parentWidget()->geometry();
|
|
r = layoutState.toolBarAreaLayout.rectHint(r);
|
|
r.moveTo(topLeft);
|
|
parentWidget()->setGeometry(r);
|
|
} else {
|
|
update();
|
|
}
|
|
}
|
|
}
|
|
|
|
#endif // QT_NO_TOOLBAR
|
|
|
|
/******************************************************************************
|
|
** QMainWindowLayoutState - dock areas
|
|
*/
|
|
|
|
#ifndef QT_NO_DOCKWIDGET
|
|
static QInternal::DockPosition toDockPos(Qt::DockWidgetArea area)
|
|
{
|
|
switch (area) {
|
|
case Qt::LeftDockWidgetArea: return QInternal::LeftDock;
|
|
case Qt::RightDockWidgetArea: return QInternal::RightDock;
|
|
case Qt::TopDockWidgetArea: return QInternal::TopDock;
|
|
case Qt::BottomDockWidgetArea: return QInternal::BottomDock;
|
|
default:
|
|
break;
|
|
}
|
|
|
|
return QInternal::DockCount;
|
|
}
|
|
|
|
static Qt::DockWidgetArea toDockWidgetArea(QInternal::DockPosition pos)
|
|
{
|
|
switch (pos) {
|
|
case QInternal::LeftDock : return Qt::LeftDockWidgetArea;
|
|
case QInternal::RightDock : return Qt::RightDockWidgetArea;
|
|
case QInternal::TopDock : return Qt::TopDockWidgetArea;
|
|
case QInternal::BottomDock : return Qt::BottomDockWidgetArea;
|
|
default:
|
|
break;
|
|
}
|
|
|
|
return Qt::NoDockWidgetArea;
|
|
}
|
|
|
|
inline static Qt::DockWidgetArea toDockWidgetArea(int pos)
|
|
{
|
|
return toDockWidgetArea(static_cast<QInternal::DockPosition>(pos));
|
|
}
|
|
|
|
void QMainWindowLayout::setCorner(Qt::Corner corner, Qt::DockWidgetArea area)
|
|
{
|
|
if (layoutState.dockAreaLayout.corners[corner] == area)
|
|
return;
|
|
layoutState.dockAreaLayout.corners[corner] = area;
|
|
if (savedState.isValid())
|
|
savedState.dockAreaLayout.corners[corner] = area;
|
|
invalidate();
|
|
}
|
|
|
|
Qt::DockWidgetArea QMainWindowLayout::corner(Qt::Corner corner) const
|
|
{
|
|
return layoutState.dockAreaLayout.corners[corner];
|
|
}
|
|
|
|
void QMainWindowLayout::addDockWidget(Qt::DockWidgetArea area,
|
|
QDockWidget *dockwidget,
|
|
Qt::Orientation orientation)
|
|
{
|
|
addChildWidget(dockwidget);
|
|
|
|
// If we are currently moving a separator, then we need to abort the move, since each
|
|
// time we move the mouse layoutState is replaced by savedState modified by the move.
|
|
if (!movingSeparator.isEmpty())
|
|
endSeparatorMove(movingSeparatorPos);
|
|
|
|
layoutState.dockAreaLayout.addDockWidget(toDockPos(area), dockwidget, orientation);
|
|
emit dockwidget->dockLocationChanged(area);
|
|
invalidate();
|
|
}
|
|
|
|
void QMainWindowLayout::tabifyDockWidget(QDockWidget *first, QDockWidget *second)
|
|
{
|
|
addChildWidget(second);
|
|
layoutState.dockAreaLayout.tabifyDockWidget(first, second);
|
|
emit second->dockLocationChanged(dockWidgetArea(first));
|
|
invalidate();
|
|
}
|
|
|
|
bool QMainWindowLayout::restoreDockWidget(QDockWidget *dockwidget)
|
|
{
|
|
addChildWidget(dockwidget);
|
|
if (!layoutState.dockAreaLayout.restoreDockWidget(dockwidget))
|
|
return false;
|
|
emit dockwidget->dockLocationChanged(dockWidgetArea(dockwidget));
|
|
invalidate();
|
|
return true;
|
|
}
|
|
|
|
#ifndef QT_NO_TABBAR
|
|
bool QMainWindowLayout::documentMode() const
|
|
{
|
|
return _documentMode;
|
|
}
|
|
|
|
void QMainWindowLayout::setDocumentMode(bool enabled)
|
|
{
|
|
if (_documentMode == enabled)
|
|
return;
|
|
|
|
_documentMode = enabled;
|
|
|
|
// Update the document mode for all tab bars
|
|
foreach (QTabBar *bar, usedTabBars)
|
|
bar->setDocumentMode(_documentMode);
|
|
foreach (QTabBar *bar, unusedTabBars)
|
|
bar->setDocumentMode(_documentMode);
|
|
}
|
|
#endif // QT_NO_TABBAR
|
|
|
|
void QMainWindowLayout::setVerticalTabsEnabled(bool enabled)
|
|
{
|
|
#ifdef QT_NO_TABBAR
|
|
Q_UNUSED(enabled);
|
|
#else
|
|
if (verticalTabsEnabled == enabled)
|
|
return;
|
|
|
|
verticalTabsEnabled = enabled;
|
|
|
|
updateTabBarShapes();
|
|
#endif // QT_NO_TABBAR
|
|
}
|
|
|
|
#ifndef QT_NO_TABWIDGET
|
|
QTabWidget::TabShape QMainWindowLayout::tabShape() const
|
|
{
|
|
return _tabShape;
|
|
}
|
|
|
|
void QMainWindowLayout::setTabShape(QTabWidget::TabShape tabShape)
|
|
{
|
|
if (_tabShape == tabShape)
|
|
return;
|
|
|
|
_tabShape = tabShape;
|
|
|
|
updateTabBarShapes();
|
|
}
|
|
|
|
QTabWidget::TabPosition QMainWindowLayout::tabPosition(Qt::DockWidgetArea area) const
|
|
{
|
|
return tabPositions[toDockPos(area)];
|
|
}
|
|
|
|
void QMainWindowLayout::setTabPosition(Qt::DockWidgetAreas areas, QTabWidget::TabPosition tabPosition)
|
|
{
|
|
const Qt::DockWidgetArea dockWidgetAreas[] = {
|
|
Qt::TopDockWidgetArea,
|
|
Qt::LeftDockWidgetArea,
|
|
Qt::BottomDockWidgetArea,
|
|
Qt::RightDockWidgetArea
|
|
};
|
|
const QInternal::DockPosition dockPositions[] = {
|
|
QInternal::TopDock,
|
|
QInternal::LeftDock,
|
|
QInternal::BottomDock,
|
|
QInternal::RightDock
|
|
};
|
|
|
|
for (int i = 0; i < QInternal::DockCount; ++i)
|
|
if (areas & dockWidgetAreas[i])
|
|
tabPositions[dockPositions[i]] = tabPosition;
|
|
|
|
updateTabBarShapes();
|
|
}
|
|
|
|
static inline QTabBar::Shape tabBarShapeFrom(QTabWidget::TabShape shape, QTabWidget::TabPosition position)
|
|
{
|
|
const bool rounded = (shape == QTabWidget::Rounded);
|
|
if (position == QTabWidget::North)
|
|
return rounded ? QTabBar::RoundedNorth : QTabBar::TriangularNorth;
|
|
if (position == QTabWidget::South)
|
|
return rounded ? QTabBar::RoundedSouth : QTabBar::TriangularSouth;
|
|
if (position == QTabWidget::East)
|
|
return rounded ? QTabBar::RoundedEast : QTabBar::TriangularEast;
|
|
if (position == QTabWidget::West)
|
|
return rounded ? QTabBar::RoundedWest : QTabBar::TriangularWest;
|
|
return QTabBar::RoundedNorth;
|
|
}
|
|
#endif // QT_NO_TABWIDGET
|
|
|
|
#ifndef QT_NO_TABBAR
|
|
void QMainWindowLayout::updateTabBarShapes()
|
|
{
|
|
#ifndef QT_NO_TABWIDGET
|
|
const QTabWidget::TabPosition vertical[] = {
|
|
QTabWidget::West,
|
|
QTabWidget::East,
|
|
QTabWidget::North,
|
|
QTabWidget::South
|
|
};
|
|
#else
|
|
const QTabBar::Shape vertical[] = {
|
|
QTabBar::RoundedWest,
|
|
QTabBar::RoundedEast,
|
|
QTabBar::RoundedNorth,
|
|
QTabBar::RoundedSouth
|
|
};
|
|
#endif
|
|
|
|
QDockAreaLayout &layout = layoutState.dockAreaLayout;
|
|
|
|
for (int i = 0; i < QInternal::DockCount; ++i) {
|
|
#ifndef QT_NO_TABWIDGET
|
|
QTabWidget::TabPosition pos = verticalTabsEnabled ? vertical[i] : tabPositions[i];
|
|
QTabBar::Shape shape = tabBarShapeFrom(_tabShape, pos);
|
|
#else
|
|
QTabBar::Shape shape = verticalTabsEnabled ? vertical[i] : QTabBar::RoundedSouth;
|
|
#endif
|
|
layout.docks[i].setTabBarShape(shape);
|
|
}
|
|
}
|
|
#endif // QT_NO_TABBAR
|
|
|
|
void QMainWindowLayout::splitDockWidget(QDockWidget *after,
|
|
QDockWidget *dockwidget,
|
|
Qt::Orientation orientation)
|
|
{
|
|
addChildWidget(dockwidget);
|
|
layoutState.dockAreaLayout.splitDockWidget(after, dockwidget, orientation);
|
|
emit dockwidget->dockLocationChanged(dockWidgetArea(after));
|
|
invalidate();
|
|
}
|
|
|
|
Qt::DockWidgetArea QMainWindowLayout::dockWidgetArea(QDockWidget *widget) const
|
|
{
|
|
QList<int> pathToWidget = layoutState.dockAreaLayout.indexOf(widget);
|
|
if (pathToWidget.isEmpty())
|
|
return Qt::NoDockWidgetArea;
|
|
return toDockWidgetArea(pathToWidget.first());
|
|
}
|
|
|
|
void QMainWindowLayout::keepSize(QDockWidget *w)
|
|
{
|
|
layoutState.dockAreaLayout.keepSize(w);
|
|
}
|
|
|
|
#ifndef QT_NO_TABBAR
|
|
|
|
class QMainWindowTabBar : public QTabBar
|
|
{
|
|
public:
|
|
QMainWindowTabBar(QWidget *parent);
|
|
protected:
|
|
bool event(QEvent *e);
|
|
};
|
|
|
|
QMainWindowTabBar::QMainWindowTabBar(QWidget *parent)
|
|
: QTabBar(parent)
|
|
{
|
|
setExpanding(false);
|
|
}
|
|
|
|
bool QMainWindowTabBar::event(QEvent *e)
|
|
{
|
|
// show the tooltip if tab is too small to fit label
|
|
|
|
if (e->type() != QEvent::ToolTip)
|
|
return QTabBar::event(e);
|
|
QSize size = this->size();
|
|
QSize hint = sizeHint();
|
|
if (shape() == QTabBar::RoundedWest || shape() == QTabBar::RoundedEast) {
|
|
size.transpose();
|
|
hint.transpose();
|
|
}
|
|
if (size.width() < hint.width())
|
|
return QTabBar::event(e);
|
|
e->accept();
|
|
return true;
|
|
}
|
|
|
|
QTabBar *QMainWindowLayout::getTabBar()
|
|
{
|
|
QTabBar *result = 0;
|
|
if (!unusedTabBars.isEmpty()) {
|
|
result = unusedTabBars.takeLast();
|
|
} else {
|
|
result = new QMainWindowTabBar(parentWidget());
|
|
result->setDrawBase(true);
|
|
result->setElideMode(Qt::ElideRight);
|
|
result->setDocumentMode(_documentMode);
|
|
connect(result, SIGNAL(currentChanged(int)), this, SLOT(tabChanged()));
|
|
}
|
|
|
|
usedTabBars.insert(result);
|
|
return result;
|
|
}
|
|
|
|
// Allocates a new separator widget if needed
|
|
QWidget *QMainWindowLayout::getSeparatorWidget()
|
|
{
|
|
QWidget *result = 0;
|
|
if (!unusedSeparatorWidgets.isEmpty()) {
|
|
result = unusedSeparatorWidgets.takeLast();
|
|
} else {
|
|
result = new QWidget(parentWidget());
|
|
result->setAttribute(Qt::WA_MouseNoMask, true);
|
|
result->setAutoFillBackground(false);
|
|
result->setObjectName(QLatin1String("qt_qmainwindow_extended_splitter"));
|
|
}
|
|
usedSeparatorWidgets.insert(result);
|
|
return result;
|
|
}
|
|
|
|
void QMainWindowLayout::tabChanged()
|
|
{
|
|
QTabBar *tb = qobject_cast<QTabBar*>(sender());
|
|
if (tb == 0)
|
|
return;
|
|
QDockAreaLayoutInfo *info = layoutState.dockAreaLayout.info(tb);
|
|
if (info == 0)
|
|
return;
|
|
info->apply(false);
|
|
|
|
if (QWidget *w = centralWidget())
|
|
w->raise();
|
|
}
|
|
#endif // QT_NO_TABBAR
|
|
|
|
bool QMainWindowLayout::startSeparatorMove(const QPoint &pos)
|
|
{
|
|
movingSeparator = layoutState.dockAreaLayout.findSeparator(pos);
|
|
|
|
if (movingSeparator.isEmpty())
|
|
return false;
|
|
|
|
savedState = layoutState;
|
|
movingSeparatorPos = movingSeparatorOrigin = pos;
|
|
|
|
return true;
|
|
}
|
|
|
|
bool QMainWindowLayout::separatorMove(const QPoint &pos)
|
|
{
|
|
if (movingSeparator.isEmpty())
|
|
return false;
|
|
movingSeparatorPos = pos;
|
|
separatorMoveTimer.start(0, this);
|
|
return true;
|
|
}
|
|
|
|
bool QMainWindowLayout::endSeparatorMove(const QPoint&)
|
|
{
|
|
if (movingSeparator.isEmpty())
|
|
return false;
|
|
movingSeparator.clear();
|
|
savedState.clear();
|
|
return true;
|
|
}
|
|
|
|
void QMainWindowLayout::raise(QDockWidget *widget)
|
|
{
|
|
QDockAreaLayoutInfo *info = layoutState.dockAreaLayout.info(widget);
|
|
if (info == 0)
|
|
return;
|
|
#ifndef QT_NO_TABBAR
|
|
if (!info->tabbed)
|
|
return;
|
|
info->setCurrentTab(widget);
|
|
#endif
|
|
}
|
|
|
|
#endif // QT_NO_DOCKWIDGET
|
|
|
|
|
|
/******************************************************************************
|
|
** QMainWindowLayoutState - layout interface
|
|
*/
|
|
|
|
int QMainWindowLayout::count() const
|
|
{
|
|
qWarning("QMainWindowLayout::count: ?");
|
|
return 0; //#################################################
|
|
}
|
|
|
|
QLayoutItem *QMainWindowLayout::itemAt(int index) const
|
|
{
|
|
int x = 0;
|
|
|
|
if (QLayoutItem *ret = layoutState.itemAt(index, &x))
|
|
return ret;
|
|
|
|
if (statusbar && x++ == index)
|
|
return statusbar;
|
|
|
|
return 0;
|
|
}
|
|
|
|
QLayoutItem *QMainWindowLayout::takeAt(int index)
|
|
{
|
|
int x = 0;
|
|
|
|
if (QLayoutItem *ret = layoutState.takeAt(index, &x)) {
|
|
// the widget might in fact have been destroyed by now
|
|
if (QWidget *w = ret->widget()) {
|
|
widgetAnimator.abort(w);
|
|
if (w == pluggingWidget)
|
|
pluggingWidget = 0;
|
|
}
|
|
|
|
if (savedState.isValid() ) {
|
|
//we need to remove the item also from the saved state to prevent crash
|
|
savedState.remove(ret);
|
|
//Also, the item may be contained several times as a gap item.
|
|
layoutState.remove(ret);
|
|
}
|
|
|
|
#ifndef QT_NO_TOOLBAR
|
|
if (!currentGapPos.isEmpty() && currentGapPos.first() == 0) {
|
|
currentGapPos = layoutState.toolBarAreaLayout.currentGapIndex();
|
|
if (!currentGapPos.isEmpty()) {
|
|
currentGapPos.prepend(0);
|
|
currentGapRect = layoutState.itemRect(currentGapPos);
|
|
}
|
|
}
|
|
#endif
|
|
|
|
return ret;
|
|
}
|
|
|
|
if (statusbar && x++ == index) {
|
|
QLayoutItem *ret = statusbar;
|
|
statusbar = 0;
|
|
return ret;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
void QMainWindowLayout::setGeometry(const QRect &_r)
|
|
{
|
|
if (savedState.isValid())
|
|
return;
|
|
|
|
QRect r = _r;
|
|
|
|
QLayout::setGeometry(r);
|
|
|
|
if (statusbar) {
|
|
QRect sbr(QPoint(0, 0),
|
|
QSize(r.width(), statusbar->heightForWidth(r.width()))
|
|
.expandedTo(statusbar->minimumSize()));
|
|
sbr.moveBottom(r.bottom());
|
|
QRect vr = QStyle::visualRect(parentWidget()->layoutDirection(), _r, sbr);
|
|
statusbar->setGeometry(vr);
|
|
r.setBottom(sbr.top() - 1);
|
|
}
|
|
|
|
layoutState.rect = r;
|
|
layoutState.fitLayout();
|
|
applyState(layoutState, false);
|
|
}
|
|
|
|
void QMainWindowLayout::addItem(QLayoutItem *)
|
|
{ qWarning("QMainWindowLayout::addItem: Please use the public QMainWindow API instead"); }
|
|
|
|
QSize QMainWindowLayout::sizeHint() const
|
|
{
|
|
if (!szHint.isValid()) {
|
|
szHint = layoutState.sizeHint();
|
|
const QSize sbHint = statusbar ? statusbar->sizeHint() : QSize(0, 0);
|
|
szHint = QSize(qMax(sbHint.width(), szHint.width()),
|
|
sbHint.height() + szHint.height());
|
|
}
|
|
return szHint;
|
|
}
|
|
|
|
QSize QMainWindowLayout::minimumSize() const
|
|
{
|
|
if (!minSize.isValid()) {
|
|
minSize = layoutState.minimumSize();
|
|
const QSize sbMin = statusbar ? statusbar->minimumSize() : QSize(0, 0);
|
|
minSize = QSize(qMax(sbMin.width(), minSize.width()),
|
|
sbMin.height() + minSize.height());
|
|
#ifdef Q_WS_MAC
|
|
const QSize storedSize = minSize;
|
|
int minWidth = 0;
|
|
foreach (QToolBar *toolbar, qtoolbarsInUnifiedToolbarList) {
|
|
minWidth += toolbar->sizeHint().width() + 20;
|
|
}
|
|
minSize = QSize(qMax(minWidth, storedSize.width()), storedSize.height());
|
|
#endif
|
|
}
|
|
return minSize;
|
|
}
|
|
|
|
void QMainWindowLayout::invalidate()
|
|
{
|
|
QLayout::invalidate();
|
|
minSize = szHint = QSize();
|
|
}
|
|
|
|
/******************************************************************************
|
|
** QMainWindowLayout - remaining stuff
|
|
*/
|
|
|
|
static void fixToolBarOrientation(QLayoutItem *item, int dockPos)
|
|
{
|
|
#ifndef QT_NO_TOOLBAR
|
|
QToolBar *toolBar = qobject_cast<QToolBar*>(item->widget());
|
|
if (toolBar == 0)
|
|
return;
|
|
|
|
QRect oldGeo = toolBar->geometry();
|
|
|
|
QInternal::DockPosition pos
|
|
= static_cast<QInternal::DockPosition>(dockPos);
|
|
Qt::Orientation o = pos == QInternal::TopDock || pos == QInternal::BottomDock
|
|
? Qt::Horizontal : Qt::Vertical;
|
|
if (o != toolBar->orientation())
|
|
toolBar->setOrientation(o);
|
|
|
|
QSize hint = toolBar->sizeHint().boundedTo(toolBar->maximumSize())
|
|
.expandedTo(toolBar->minimumSize());
|
|
|
|
if (toolBar->size() != hint) {
|
|
QRect newGeo(oldGeo.topLeft(), hint);
|
|
if (toolBar->layoutDirection() == Qt::RightToLeft)
|
|
newGeo.moveRight(oldGeo.right());
|
|
toolBar->setGeometry(newGeo);
|
|
}
|
|
|
|
#else
|
|
Q_UNUSED(item);
|
|
Q_UNUSED(dockPos);
|
|
#endif
|
|
}
|
|
|
|
void QMainWindowLayout::revert(QLayoutItem *widgetItem)
|
|
{
|
|
if (!savedState.isValid())
|
|
return;
|
|
|
|
QWidget *widget = widgetItem->widget();
|
|
layoutState = savedState;
|
|
currentGapPos = layoutState.indexOf(widget);
|
|
fixToolBarOrientation(widgetItem, currentGapPos.at(1));
|
|
layoutState.unplug(currentGapPos);
|
|
layoutState.fitLayout();
|
|
currentGapRect = layoutState.itemRect(currentGapPos);
|
|
|
|
plug(widgetItem);
|
|
}
|
|
|
|
bool QMainWindowLayout::plug(QLayoutItem *widgetItem)
|
|
{
|
|
if (!parentWidget()->isVisible() || parentWidget()->isMinimized() || currentGapPos.isEmpty())
|
|
return false;
|
|
|
|
fixToolBarOrientation(widgetItem, currentGapPos.at(1));
|
|
|
|
QWidget *widget = widgetItem->widget();
|
|
|
|
QList<int> previousPath = layoutState.indexOf(widget);
|
|
|
|
const QLayoutItem *it = layoutState.plug(currentGapPos);
|
|
if (!it)
|
|
return false;
|
|
Q_ASSERT(it == widgetItem);
|
|
if (!previousPath.isEmpty())
|
|
layoutState.remove(previousPath);
|
|
|
|
pluggingWidget = widget;
|
|
QRect globalRect = currentGapRect;
|
|
globalRect.moveTopLeft(parentWidget()->mapToGlobal(globalRect.topLeft()));
|
|
#ifndef QT_NO_DOCKWIDGET
|
|
if (qobject_cast<QDockWidget*>(widget) != 0) {
|
|
QDockWidgetLayout *layout = qobject_cast<QDockWidgetLayout*>(widget->layout());
|
|
if (layout->nativeWindowDeco()) {
|
|
globalRect.adjust(0, layout->titleHeight(), 0, 0);
|
|
} else {
|
|
int fw = widget->style()->pixelMetric(QStyle::PM_DockWidgetFrameWidth, 0, widget);
|
|
globalRect.adjust(-fw, -fw, fw, fw);
|
|
}
|
|
}
|
|
#endif
|
|
widgetAnimator.animate(widget, globalRect, dockOptions & QMainWindow::AnimatedDocks);
|
|
|
|
return true;
|
|
}
|
|
|
|
void QMainWindowLayout::animationFinished(QWidget *widget)
|
|
{
|
|
//this function is called from within the Widget Animator whenever an animation is finished
|
|
//on a certain widget
|
|
#ifndef QT_NO_TOOLBAR
|
|
if (QToolBar *tb = qobject_cast<QToolBar*>(widget)) {
|
|
QToolBarLayout *tbl = qobject_cast<QToolBarLayout*>(tb->layout());
|
|
if (tbl->animating) {
|
|
tbl->animating = false;
|
|
if (tbl->expanded)
|
|
tbl->layoutActions(tb->size());
|
|
tb->update();
|
|
}
|
|
}
|
|
#endif
|
|
|
|
if (widget == pluggingWidget) {
|
|
|
|
#ifndef QT_NO_DOCKWIDGET
|
|
if (QDockWidget *dw = qobject_cast<QDockWidget*>(widget))
|
|
dw->d_func()->plug(currentGapRect);
|
|
#endif
|
|
#ifndef QT_NO_TOOLBAR
|
|
if (QToolBar *tb = qobject_cast<QToolBar*>(widget))
|
|
tb->d_func()->plug(currentGapRect);
|
|
#endif
|
|
|
|
savedState.clear();
|
|
currentGapPos.clear();
|
|
pluggingWidget = 0;
|
|
//applying the state will make sure that the currentGap is updated correctly
|
|
//and all the geometries (especially the one from the central widget) is correct
|
|
layoutState.apply(false);
|
|
|
|
#ifndef QT_NO_DOCKWIDGET
|
|
#ifndef QT_NO_TABBAR
|
|
if (qobject_cast<QDockWidget*>(widget) != 0) {
|
|
// info() might return null if the widget is destroyed while
|
|
// animating but before the animationFinished signal is received.
|
|
if (QDockAreaLayoutInfo *info = layoutState.dockAreaLayout.info(widget))
|
|
info->setCurrentTab(widget);
|
|
}
|
|
#endif
|
|
#endif
|
|
}
|
|
|
|
if (!widgetAnimator.animating()) {
|
|
//all animations are finished
|
|
#ifndef QT_NO_DOCKWIDGET
|
|
parentWidget()->update(layoutState.dockAreaLayout.separatorRegion());
|
|
#ifndef QT_NO_TABBAR
|
|
foreach (QTabBar *tab_bar, usedTabBars)
|
|
tab_bar->show();
|
|
#endif // QT_NO_TABBAR
|
|
#endif // QT_NO_DOCKWIDGET
|
|
}
|
|
|
|
updateGapIndicator();
|
|
}
|
|
|
|
void QMainWindowLayout::restore(bool keepSavedState)
|
|
{
|
|
if (!savedState.isValid())
|
|
return;
|
|
|
|
layoutState = savedState;
|
|
applyState(layoutState);
|
|
if (!keepSavedState)
|
|
savedState.clear();
|
|
currentGapPos.clear();
|
|
pluggingWidget = 0;
|
|
updateGapIndicator();
|
|
}
|
|
|
|
QMainWindowLayout::QMainWindowLayout(QMainWindow *mainwindow, QLayout *parentLayout)
|
|
: QLayout(parentLayout ? static_cast<QWidget *>(0) : mainwindow)
|
|
, layoutState(mainwindow)
|
|
, savedState(mainwindow)
|
|
, dockOptions(QMainWindow::AnimatedDocks | QMainWindow::AllowTabbedDocks)
|
|
, statusbar(0)
|
|
#ifndef QT_NO_DOCKWIDGET
|
|
#ifndef QT_NO_TABBAR
|
|
, _documentMode(false)
|
|
, verticalTabsEnabled(false)
|
|
#ifndef QT_NO_TABWIDGET
|
|
, _tabShape(QTabWidget::Rounded)
|
|
#endif
|
|
#endif
|
|
#endif // QT_NO_DOCKWIDGET
|
|
, widgetAnimator(this)
|
|
, pluggingWidget(0)
|
|
#ifndef QT_NO_RUBBERBAND
|
|
, gapIndicator(new QRubberBand(QRubberBand::Rectangle, mainwindow))
|
|
#endif //QT_NO_RUBBERBAND
|
|
#ifdef Q_WS_MAC
|
|
, activateUnifiedToolbarAfterFullScreen(false)
|
|
, blockVisiblityCheck(false)
|
|
#endif
|
|
{
|
|
if (parentLayout)
|
|
setParent(parentLayout);
|
|
|
|
#ifndef QT_NO_DOCKWIDGET
|
|
#ifndef QT_NO_TABBAR
|
|
sep = mainwindow->style()->pixelMetric(QStyle::PM_DockWidgetSeparatorExtent, 0, mainwindow);
|
|
#endif
|
|
|
|
#ifndef QT_NO_TABWIDGET
|
|
for (int i = 0; i < QInternal::DockCount; ++i)
|
|
tabPositions[i] = QTabWidget::South;
|
|
#endif
|
|
#endif // QT_NO_DOCKWIDGET
|
|
|
|
#ifndef QT_NO_RUBBERBAND
|
|
// For accessibility to identify this special widget.
|
|
gapIndicator->setObjectName(QLatin1String("qt_rubberband"));
|
|
gapIndicator->hide();
|
|
#endif
|
|
pluggingWidget = 0;
|
|
|
|
setObjectName(mainwindow->objectName() + QLatin1String("_layout"));
|
|
}
|
|
|
|
QMainWindowLayout::~QMainWindowLayout()
|
|
{
|
|
layoutState.deleteAllLayoutItems();
|
|
layoutState.deleteCentralWidgetItem();
|
|
|
|
#ifdef Q_WS_MAC
|
|
cleanUpMacToolbarItems();
|
|
#endif
|
|
|
|
delete statusbar;
|
|
}
|
|
|
|
void QMainWindowLayout::setDockOptions(QMainWindow::DockOptions opts)
|
|
{
|
|
if (opts == dockOptions)
|
|
return;
|
|
|
|
dockOptions = opts;
|
|
|
|
#ifndef QT_NO_DOCKWIDGET
|
|
setVerticalTabsEnabled(opts & QMainWindow::VerticalTabs);
|
|
#endif
|
|
|
|
invalidate();
|
|
}
|
|
|
|
#ifndef QT_NO_STATUSBAR
|
|
QStatusBar *QMainWindowLayout::statusBar() const
|
|
{ return statusbar ? qobject_cast<QStatusBar *>(statusbar->widget()) : 0; }
|
|
|
|
void QMainWindowLayout::setStatusBar(QStatusBar *sb)
|
|
{
|
|
if (sb)
|
|
addChildWidget(sb);
|
|
delete statusbar;
|
|
statusbar = sb ? new QWidgetItemV2(sb) : 0;
|
|
invalidate();
|
|
}
|
|
#endif // QT_NO_STATUSBAR
|
|
|
|
QWidget *QMainWindowLayout::centralWidget() const
|
|
{
|
|
return layoutState.centralWidget();
|
|
}
|
|
|
|
void QMainWindowLayout::setCentralWidget(QWidget *widget)
|
|
{
|
|
if (widget != 0)
|
|
addChildWidget(widget);
|
|
layoutState.setCentralWidget(widget);
|
|
if (savedState.isValid()) {
|
|
#ifndef QT_NO_DOCKWIDGET
|
|
savedState.dockAreaLayout.centralWidgetItem = layoutState.dockAreaLayout.centralWidgetItem;
|
|
savedState.dockAreaLayout.fallbackToSizeHints = true;
|
|
#else
|
|
savedState.centralWidgetItem = layoutState.centralWidgetItem;
|
|
#endif
|
|
}
|
|
invalidate();
|
|
}
|
|
|
|
QLayoutItem *QMainWindowLayout::unplug(QWidget *widget)
|
|
{
|
|
QList<int> path = layoutState.indexOf(widget);
|
|
if (path.isEmpty())
|
|
return 0;
|
|
|
|
QLayoutItem *item = layoutState.item(path);
|
|
if (widget->isWindow())
|
|
return item;
|
|
|
|
QRect r = layoutState.itemRect(path);
|
|
savedState = layoutState;
|
|
|
|
#ifndef QT_NO_DOCKWIDGET
|
|
if (QDockWidget *dw = qobject_cast<QDockWidget*>(widget)) {
|
|
dw->d_func()->unplug(r);
|
|
}
|
|
#endif
|
|
#ifndef QT_NO_TOOLBAR
|
|
if (QToolBar *tb = qobject_cast<QToolBar*>(widget)) {
|
|
tb->d_func()->unplug(r);
|
|
}
|
|
#endif
|
|
|
|
|
|
layoutState.unplug(path ,&savedState);
|
|
savedState.fitLayout();
|
|
currentGapPos = path;
|
|
currentGapRect = r;
|
|
updateGapIndicator();
|
|
|
|
fixToolBarOrientation(item, currentGapPos.at(1));
|
|
|
|
return item;
|
|
}
|
|
|
|
void QMainWindowLayout::updateGapIndicator()
|
|
{
|
|
#ifndef QT_NO_RUBBERBAND
|
|
gapIndicator->setVisible(!widgetAnimator.animating() && !currentGapPos.isEmpty());
|
|
gapIndicator->setGeometry(currentGapRect);
|
|
#endif
|
|
}
|
|
|
|
QList<int> QMainWindowLayout::hover(QLayoutItem *widgetItem, const QPoint &mousePos)
|
|
{
|
|
if (!parentWidget()->isVisible() || parentWidget()->isMinimized()
|
|
|| pluggingWidget != 0 || widgetItem == 0)
|
|
return QList<int>();
|
|
|
|
QWidget *widget = widgetItem->widget();
|
|
QPoint pos = parentWidget()->mapFromGlobal(mousePos);
|
|
|
|
if (!savedState.isValid())
|
|
savedState = layoutState;
|
|
|
|
QList<int> path = savedState.gapIndex(widget, pos);
|
|
|
|
if (!path.isEmpty()) {
|
|
bool allowed = false;
|
|
|
|
#ifndef QT_NO_DOCKWIDGET
|
|
if (QDockWidget *dw = qobject_cast<QDockWidget*>(widget))
|
|
allowed = dw->isAreaAllowed(toDockWidgetArea(path.at(1)));
|
|
#endif
|
|
#ifndef QT_NO_TOOLBAR
|
|
if (QToolBar *tb = qobject_cast<QToolBar*>(widget))
|
|
allowed = tb->isAreaAllowed(toToolBarArea(path.at(1)));
|
|
#endif
|
|
|
|
if (!allowed)
|
|
path.clear();
|
|
}
|
|
|
|
if (path == currentGapPos)
|
|
return currentGapPos; // the gap is already there
|
|
|
|
currentGapPos = path;
|
|
if (path.isEmpty()) {
|
|
fixToolBarOrientation(widgetItem, 2); // 2 = top dock, ie. horizontal
|
|
restore(true);
|
|
return QList<int>();
|
|
}
|
|
|
|
fixToolBarOrientation(widgetItem, currentGapPos.at(1));
|
|
|
|
QMainWindowLayoutState newState = savedState;
|
|
|
|
if (!newState.insertGap(path, widgetItem)) {
|
|
restore(true); // not enough space
|
|
return QList<int>();
|
|
}
|
|
|
|
QSize min = newState.minimumSize();
|
|
QSize size = newState.rect.size();
|
|
|
|
if (min.width() > size.width() || min.height() > size.height()) {
|
|
restore(true);
|
|
return QList<int>();
|
|
}
|
|
|
|
newState.fitLayout();
|
|
|
|
currentGapRect = newState.gapRect(currentGapPos);
|
|
|
|
#ifndef QT_NO_DOCKWIDGET
|
|
parentWidget()->update(layoutState.dockAreaLayout.separatorRegion());
|
|
#endif
|
|
layoutState = newState;
|
|
applyState(layoutState);
|
|
|
|
updateGapIndicator();
|
|
|
|
return path;
|
|
}
|
|
|
|
void QMainWindowLayout::applyState(QMainWindowLayoutState &newState, bool animate)
|
|
{
|
|
#ifndef QT_NO_DOCKWIDGET
|
|
#ifndef QT_NO_TABBAR
|
|
QSet<QTabBar*> used = newState.dockAreaLayout.usedTabBars();
|
|
QSet<QTabBar*> retired = usedTabBars - used;
|
|
usedTabBars = used;
|
|
foreach (QTabBar *tab_bar, retired) {
|
|
tab_bar->hide();
|
|
while (tab_bar->count() > 0)
|
|
tab_bar->removeTab(0);
|
|
unusedTabBars.append(tab_bar);
|
|
}
|
|
|
|
if (sep == 1) {
|
|
QSet<QWidget*> usedSeps = newState.dockAreaLayout.usedSeparatorWidgets();
|
|
QSet<QWidget*> retiredSeps = usedSeparatorWidgets - usedSeps;
|
|
usedSeparatorWidgets = usedSeps;
|
|
foreach (QWidget *sepWidget, retiredSeps) {
|
|
unusedSeparatorWidgets.append(sepWidget);
|
|
}
|
|
}
|
|
|
|
|
|
#endif // QT_NO_TABBAR
|
|
#endif // QT_NO_DOCKWIDGET
|
|
newState.apply(dockOptions & QMainWindow::AnimatedDocks && animate);
|
|
}
|
|
|
|
void QMainWindowLayout::saveState(QDataStream &stream) const
|
|
{
|
|
layoutState.saveState(stream);
|
|
}
|
|
|
|
bool QMainWindowLayout::restoreState(QDataStream &stream)
|
|
{
|
|
savedState = layoutState;
|
|
layoutState.clear();
|
|
layoutState.rect = savedState.rect;
|
|
|
|
if (!layoutState.restoreState(stream, savedState)) {
|
|
layoutState.deleteAllLayoutItems();
|
|
layoutState = savedState;
|
|
if (parentWidget()->isVisible())
|
|
applyState(layoutState, false); // hides tabBars allocated by newState
|
|
return false;
|
|
}
|
|
|
|
if (parentWidget()->isVisible()) {
|
|
layoutState.fitLayout();
|
|
applyState(layoutState, false);
|
|
}
|
|
|
|
savedState.deleteAllLayoutItems();
|
|
savedState.clear();
|
|
|
|
#ifndef QT_NO_DOCKWIDGET
|
|
if (parentWidget()->isVisible()) {
|
|
#ifndef QT_NO_TABBAR
|
|
foreach (QTabBar *tab_bar, usedTabBars)
|
|
tab_bar->show();
|
|
|
|
#endif
|
|
}
|
|
#endif // QT_NO_DOCKWIDGET
|
|
|
|
return true;
|
|
}
|
|
|
|
|
|
// Returns if this toolbar *should* be using HIToolbar. Won't work for all in between cases
|
|
// for example, you have a toolbar in the top area and then you suddenly turn on
|
|
// HIToolbar.
|
|
bool QMainWindowLayout::usesHIToolBar(QToolBar *toolbar) const
|
|
{
|
|
#ifndef Q_WS_MAC
|
|
Q_UNUSED(toolbar);
|
|
return false;
|
|
#else
|
|
return qtoolbarsInUnifiedToolbarList.contains(toolbar)
|
|
|| ((toolBarArea(toolbar) == Qt::TopToolBarArea)
|
|
&& layoutState.mainWindow->unifiedTitleAndToolBarOnMac());
|
|
#endif
|
|
}
|
|
|
|
void QMainWindowLayout::timerEvent(QTimerEvent *e)
|
|
{
|
|
#ifndef QT_NO_DOCKWIDGET
|
|
if (e->timerId() == separatorMoveTimer.timerId()) {
|
|
//let's move the separators
|
|
separatorMoveTimer.stop();
|
|
if (movingSeparator.isEmpty())
|
|
return;
|
|
if (movingSeparatorOrigin == movingSeparatorPos)
|
|
return;
|
|
|
|
//when moving the separator, we need to update the previous position
|
|
parentWidget()->update(layoutState.dockAreaLayout.separatorRegion());
|
|
|
|
layoutState = savedState;
|
|
layoutState.dockAreaLayout.separatorMove(movingSeparator, movingSeparatorOrigin,
|
|
movingSeparatorPos);
|
|
movingSeparatorPos = movingSeparatorOrigin;
|
|
}
|
|
#endif
|
|
QLayout::timerEvent(e);
|
|
}
|
|
|
|
|
|
QT_END_NAMESPACE
|
|
|
|
|
|
#include "moc_qmainwindowlayout_p.h"
|
|
|
|
#endif // QT_NO_MAINWINDOW
|