Add QMainWindow::resizeDocks

This API allows to programatically resize QDockWidgets

Task-number: QTBUG-32001
Change-Id: I58072a391f8e7f325a26745b5bedd3fe49508e91
Reviewed-by: Jocelyn Turcotte (Woboq GmbH) <jturcotte@woboq.com>
This commit is contained in:
Olivier Goffart 2015-03-19 17:47:13 +01:00 committed by Olivier Goffart (Woboq GmbH)
parent 385202c27c
commit f029468b8d
5 changed files with 173 additions and 0 deletions

View File

@ -3101,6 +3101,53 @@ void QDockAreaLayout::tabifyDockWidget(QDockWidget *first, QDockWidget *second)
remove(index);
}
void QDockAreaLayout::resizeDocks(const QList<QDockWidget *> &docks,
const QList<int> &sizes, Qt::Orientation o)
{
if (docks.count() != sizes.count()) {
qWarning("QMainWidget::resizeDocks: size of the lists are not the same");
return;
}
int count = docks.count();
fallbackToSizeHints = false;
for (int i = 0; i < count; ++i) {
QList<int> path = indexOf(docks[i]);
if (path.isEmpty()) {
qWarning("QMainWidget::resizeDocks: one QDockWidget is not part of the layout");
continue;
}
int size = sizes[i];
if (size <= 0) {
qWarning("QMainWidget::resizeDocks: all sizes need to be larger than 0");
size = 1;
}
while (path.size() > 1) {
QDockAreaLayoutInfo *info = this->info(path);
if (!info->tabbed && info->o == o) {
info->item_list[path.last()].size = size;
int totalSize = 0;
foreach (const QDockAreaLayoutItem &item, info->item_list) {
if (!item.skip()) {
if (totalSize != 0)
totalSize += sep;
totalSize += item.size == -1 ? pick(o, item.sizeHint()) : item.size;
}
}
size = totalSize;
}
path.removeLast();
}
const int dockNum = path.first();
Q_ASSERT(dockNum < QInternal::DockCount);
QRect &r = this->docks[dockNum].rect;
QSize s = r.size();
rpick(o, s) = size;
r.setSize(s);
}
}
void QDockAreaLayout::splitDockWidget(QDockWidget *after,
QDockWidget *dockWidget,
Qt::Orientation orientation)

View File

@ -268,6 +268,7 @@ public:
void splitDockWidget(QDockWidget *after, QDockWidget *dockWidget,
Qt::Orientation orientation);
void tabifyDockWidget(QDockWidget *first, QDockWidget *second);
void resizeDocks(const QList<QDockWidget *> &docks, const QList<int> &sizes, Qt::Orientation o);
void apply(bool animate);

View File

@ -1237,6 +1237,35 @@ void QMainWindow::removeDockWidget(QDockWidget *dockwidget)
Qt::DockWidgetArea QMainWindow::dockWidgetArea(QDockWidget *dockwidget) const
{ return d_func()->layout->dockWidgetArea(dockwidget); }
/*!
\since 5.6
Resizes the dock widgets in the list \a docks to the corresponding size in
pixels from the list \a sizes. If \a orientation is Qt::Horizontal, adjusts
the width, otherwise adjusts the height of the dock widgets.
The sizes will be adjusted such that the maximum and the minimum sizes are
respected and the QMainWindow itself will not be resized.
Any additional/missing space is distributed amongst the widgets according
to the relative weight of the sizes.
Example:
\code
resizeDocks({blueWidget, yellowWidget}, {20 , 40}, Qt::Horizontal);
\endcode
If the blue and the yellow widget are nested on the same level they will be
resized such that the yellowWidget is twice as big as the blueWidget
If some widgets are grouped in tabs, only one widget per group should be
specified. Widgets not in the list might be changed to repect the constraints.
*/
void QMainWindow::resizeDocks(const QList<QDockWidget *> &docks,
const QList<int> &sizes, Qt::Orientation orientation)
{
d_func()->layout->layoutState.dockAreaLayout.resizeDocks(docks, sizes, orientation);
d_func()->layout->invalidate();
}
#endif // QT_NO_DOCKWIDGET
/*!

View File

@ -165,6 +165,9 @@ public:
bool restoreDockWidget(QDockWidget *dockwidget);
Qt::DockWidgetArea dockWidgetArea(QDockWidget *dockwidget) const;
void resizeDocks(const QList<QDockWidget *> &docks,
const QList<int> &sizes, Qt::Orientation orientation);
#endif // QT_NO_DOCKWIDGET
QByteArray saveState(int version = 0) const;

View File

@ -149,6 +149,8 @@ private slots:
void toggleUnifiedTitleAndToolBarOnMac();
#endif
void QTBUG21378_animationFinished();
void resizeDocks();
void resizeDocks_data();
};
@ -1950,5 +1952,96 @@ void tst_QMainWindow::QTBUG21378_animationFinished()
delete mwClickTimer;
QVERIFY(true);
}
Q_DECLARE_METATYPE(Qt::Orientation)
void tst_QMainWindow::resizeDocks_data()
{
QTest::addColumn<Qt::Orientation>("orientation");
QTest::addColumn<QStringList>("docks");
QTest::addColumn<QList<int> >("sizes");
QTest::newRow("1") << Qt::Horizontal
<< (QStringList() << "blue" << "orange" << "green" << "gray")
<< (QList<int>() << 190 << 190 << 320 << 160);
QTest::newRow("2") << Qt::Vertical
<< (QStringList() << "yellow" << "orange")
<< (QList<int>() << 147 << 133 );
QTest::newRow("3") << Qt::Horizontal
<< (QStringList() << "blue" << "yellow")
<< (QList<int>() << 190 << 600);
}
void tst_QMainWindow::resizeDocks()
{
AddList addList;
addList
<< AddDockWidget("blue", Qt::LeftDockWidgetArea)
<< AddDockWidget("red", Qt::TopDockWidgetArea)
<< AddDockWidget("pink", "red")
<< AddDockWidget("yellow", Qt::RightDockWidgetArea)
<< AddDockWidget("orange", Qt::RightDockWidgetArea)
<< AddDockWidget("green", "orange", Qt::Horizontal)
<< AddDockWidget("gray", "orange", Qt::Horizontal);
/*
+--------------------------------+
| red/pink |
+------+-+-----------------------+
| | | yellow |
| blue + +--------+------+-------+
| | | orange | gray | green |
+------+-+--------+------+-------+
*/
QMainWindow mw(0, Qt::BypassWindowManagerHint);
mw.setDockNestingEnabled(true);
mw.resize(1800, 600);
foreach (const AddDockWidget &i, addList)
i.apply(&mw);
foreach (QDockWidget *dw, mw.findChildren<QDockWidget *>())
dw->setStyleSheet( "* { background-color: " + dw->objectName() +" }");
mw.setCentralWidget(new QTextEdit);
mw.show();
QTest::qWaitForWindowExposed(&mw);
QFETCH(Qt::Orientation, orientation);
QFETCH(QStringList, docks);
QFETCH(QList<int>, sizes);
QList<QDockWidget *> list;
foreach (const QString &name, docks) {
QDockWidget *d = mw.findChild<QDockWidget *>(name);
QVERIFY(d);
list << d;
}
mw.resizeDocks(list, sizes, orientation);
qApp->processEvents();
int totalFromList = 0;
int actualTotal = 0;
for (int i = 0; i < docks.count(); ++i) {
totalFromList += sizes[i];
QSize s = list[i]->size();
actualTotal += (orientation == Qt::Horizontal) ? s.width() : s.height();
// qDebug() << list[i] << list[i]->size() << sizes[i];
}
for (int i = 0; i < docks.count(); ++i) {
QSize s = list[i]->size();
int value = (orientation == Qt::Horizontal) ? s.width() : s.height();
QCOMPARE(value, qRound(sizes[i]*actualTotal/double(totalFromList)));
}
}
QTEST_MAIN(tst_QMainWindow)
#include "tst_qmainwindow.moc"