Honour max-size when docking

Layout will choose a suitable size for the dock widget when
addDockWidget() is called
This commit is contained in:
Sergio Martins
2020-05-29 08:50:04 +01:00
parent a086713bb6
commit 4e88b3742d
4 changed files with 91 additions and 28 deletions

View File

@@ -562,6 +562,11 @@ int Item::minLength(Qt::Orientation o) const
return Layouting::length(minSize(), o);
}
int Item::maxLengthHint(Qt::Orientation o) const
{
return Layouting::length(maxSizeHint(), o);
}
void Item::setLength(int length, Qt::Orientation o)
{
Q_ASSERT(length > 0);
@@ -833,6 +838,8 @@ void Item::onWidgetLayoutRequested()
if (w->minSize() != minSize()) {
setMinSize(m_guest->minSize());
}
setMaxSizeHint(w->maxSizeHint());
}
}
@@ -1797,8 +1804,8 @@ QSize ItemContainer::minSize() const
QSize ItemContainer::maxSizeHint() const
{
int maxW = 0;
int maxH = 0;
int maxW = KDDOCKWIDGETS_MAX_WIDTH;
int maxH = KDDOCKWIDGETS_MAX_HEIGHT;
if (!isEmpty()) {
const Item::List visibleChildren = this->visibleChildren();
@@ -1819,7 +1826,7 @@ QSize ItemContainer::maxSizeHint() const
maxW += separatorWaste;
}
return { maxW, maxH };
return QSize(maxW, maxH).expandedTo(minSize());
}
void ItemContainer::Private::resizeChildren(QSize oldSize, QSize newSize, SizingInfo::List &childSizes,
@@ -2087,7 +2094,7 @@ void ItemContainer::restoreChild(Item *item, NeighbourSqueezeStrategy neighbourS
const int available = availableOnSide(item, Side1) + availableOnSide(item, Side2) - Item::separatorThickness;
const int max = available;
const int max = qMin(available, item->maxLengthHint(d->m_orientation));
const int min = item->minLength(d->m_orientation);
const int proposed = Layouting::length(item->size(), d->m_orientation);
const int newLength = qBound(min, proposed, max);
@@ -2289,7 +2296,7 @@ void ItemContainer::layoutEqually(SizingInfo::List &sizes)
const int newItemLenght = qBound(size.minLength(d->m_orientation),
size.length(d->m_orientation) + suggestedToGive,
size.maxLength(d->m_orientation));
size.maxLengthHint(d->m_orientation));
const int toGive = newItemLenght - size.length(d->m_orientation);
if (toGive == 0) {

View File

@@ -138,8 +138,8 @@ struct SizingInfo {
return Layouting::length(minSize, o);
}
int maxLength(Qt::Orientation o) const {
return Layouting::length(maxSizeHint, o);
int maxLengthHint(Qt::Orientation o) const {
return qMax(minLength(o), Layouting::length(maxSizeHint, o));
}
int availableLength(Qt::Orientation o) const {
@@ -193,7 +193,7 @@ struct SizingInfo {
}
int availableToGrow(Qt::Orientation o) const {
return maxLength(o) - length(o);
return maxLengthHint(o) - length(o);
}
QVariantMap toVariantMap() const;
@@ -294,6 +294,7 @@ public:
int refCount() const;
int minLength(Qt::Orientation) const;
int maxLengthHint(Qt::Orientation) const;
QObject *host() const;
Widget *hostWidget() const;

View File

@@ -69,6 +69,19 @@ public:
}
}
void setMaxSize(QSize sz)
{
if (sz != m_maxSize) {
m_maxSize = sz;
Q_EMIT layoutInvalidated();
}
}
QSize maxSizeHint() const override {
return m_maxSize;
}
void resizeEvent(QResizeEvent *ev) override
{
QWidget::resizeEvent(ev);
@@ -97,6 +110,7 @@ Q_SIGNALS:
void layoutInvalidated();
private:
QSize m_minSize = QSize(200, 200);
QSize m_maxSize = QSize(KDDOCKWIDGETS_MAX_WIDTH, KDDOCKWIDGETS_MAX_HEIGHT);
};
static void fatalWarningsMessageHandler(QtMsgType t, const QMessageLogContext &context, const QString &msg)
@@ -181,6 +195,7 @@ private Q_SLOTS:
void tst_closeAndRestorePreservesPosition();
void tst_minSizeChangedBeforeRestore();
void tst_separatorMoveCrash();
void tst_maxSizeHonoured1();
};
class MyHostWidget : public QWidget
@@ -1528,6 +1543,24 @@ void TestMultiSplitter::tst_separatorMoveCrash()
c->requestSeparatorMove(separator, available5 + 10);
}
void TestMultiSplitter::tst_maxSizeHonoured1()
{
// Tests that the suggested rect honours max size when adding an item to a layout.
auto root = createRoot();
auto item1 = createItem();
auto item2 = createItem();
root->insertItem(item1, Item::Location_OnTop);
root->setSize_recursive(QSize(3000, 3000));
auto guest2 = static_cast<MyGuestWidget*>(item2->guestWidget());
const int maxHeight = 250;
guest2->setMaxSize(QSize(250, maxHeight));
root->insertItem(item2, Item::Location_OnBottom);
QCOMPARE(item2->height(), maxHeight);
}
int main(int argc, char *argv[])
{
bool qpaPassed = false;

View File

@@ -355,6 +355,7 @@ private Q_SLOTS:
void tst_lastFloatingPositionIsRestored();
void tst_moreTitleBarCornerCases();
void tst_maxSizePropagates();
void tst_maxSizeHonouredWhenDropped();
private:
std::unique_ptr<MultiSplitter> createMultiSplitterFromSetup(MultiSplitterSetup setup, QHash<QWidget *, Frame *> &frameMap) const;
@@ -5332,34 +5333,55 @@ void TestDocks::tst_moreTitleBarCornerCases()
void TestDocks::tst_maxSizePropagates()
{
{
// Tests that the DockWidget gets the min and max size of its guest widget
// Tests that the DockWidget gets the min and max size of its guest widget
EnsureTopLevelsDeleted e;
auto dock1 = new DockWidget("dock1");
auto dock1 = new DockWidget("dock1");
auto w = new QWidget();
w->setMinimumSize(120, 120);
w->setMaximumSize(500, 500);
dock1->setWidget(w);
dock1->show();
auto w = new QWidget();
w->setMinimumSize(120, 120);
w->setMaximumSize(500, 500);
dock1->setWidget(w);
dock1->show();
QCOMPARE(Widget_qwidget::widgetMinSize(dock1), Widget_qwidget::widgetMinSize(w));
QCOMPARE(dock1->maximumSize(), w->maximumSize());
QCOMPARE(Widget_qwidget::widgetMinSize(dock1), Widget_qwidget::widgetMinSize(w));
QCOMPARE(dock1->maximumSize(), w->maximumSize());
w->setMinimumSize(121, 121);
w->setMaximumSize(501, 501);
w->setMinimumSize(121, 121);
w->setMaximumSize(501, 501);
Testing::waitForEvent(w, QEvent::LayoutRequest);
Testing::waitForEvent(w, QEvent::LayoutRequest);
QCOMPARE(Widget_qwidget::widgetMinSize(dock1), Widget_qwidget::widgetMinSize(w));
QCOMPARE(dock1->maximumSize(), w->maximumSize());
QCOMPARE(Widget_qwidget::widgetMinSize(dock1), Widget_qwidget::widgetMinSize(w));
QCOMPARE(dock1->maximumSize(), w->maximumSize());
// Now let's see if our Frame also has proper size-constraints
Frame *frame = dock1->frame();
QCOMPARE(frame->maximumSize().expandedTo(w->maximumSize()), frame->maximumSize());
// Now let's see if our Frame also has proper size-constraints
Frame *frame = dock1->frame();
QCOMPARE(frame->maximumSize().expandedTo(w->maximumSize()), frame->maximumSize());
delete dock1->window();
}
delete dock1->window();
}
void TestDocks::tst_maxSizeHonouredWhenDropped()
{
EnsureTopLevelsDeleted e;
auto m1 = createMainWindow();
auto dock1 = new DockWidget("dock1");
auto dock2 = new DockWidget("dock2");
m1->addDockWidget(dock1, Location_OnTop);
m1->resize(2000, 2000);
dock2->setWidget(new QWidget);
const int maxWidth = 200;
dock2->widget()->setMaximumSize(maxWidth, 200);
m1->addDockWidget(dock2, Location_OnLeft);
const int droppedWidth = dock2->frame()->width();
QVERIFY(droppedWidth < maxWidth + 50); // +50 to cover any margins and waste by QTabWidget
// Try again, but now dropping a multisplitter
dock2->setFloating(true);
auto fw = qobject_cast<FloatingWindow*>(dock2->window());
m1->dropArea()->drop(fw, Location_OnLeft, nullptr);
QCOMPARE(dock2->frame()->width(), droppedWidth);
}
int main(int argc, char *argv[])