Fix flowLayout

This commit is contained in:
Markus Koch 2022-01-03 16:55:33 +01:00
parent 9ebd0da3f2
commit ed8a481b84
3 changed files with 289 additions and 244 deletions

View File

@ -1,195 +1,228 @@
/**************************************************************************** /****************************************************************************
** **
** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). ** Copyright (C) 2016 The Qt Company Ltd.
** All rights reserved. ** Contact: https://www.qt.io/licensing/
** Contact: Nokia Corporation (qt-info@nokia.com) **
** ** This file is part of the examples of the Qt Toolkit.
** This file is part of the examples of the Qt Toolkit. **
** ** $QT_BEGIN_LICENSE:BSD$
** $QT_BEGIN_LICENSE:BSD$ ** Commercial License Usage
** You may use this file under the terms of the BSD license as follows: ** Licensees holding valid commercial Qt licenses may use this file in
** ** accordance with the commercial license agreement provided with the
** "Redistribution and use in source and binary forms, with or without ** Software or, alternatively, in accordance with the terms contained in
** modification, are permitted provided that the following conditions are ** a written agreement between you and The Qt Company. For licensing terms
** met: ** and conditions see https://www.qt.io/terms-conditions. For further
** * Redistributions of source code must retain the above copyright ** information use the contact form at https://www.qt.io/contact-us.
** notice, this list of conditions and the following disclaimer. **
** * Redistributions in binary form must reproduce the above copyright ** BSD License Usage
** notice, this list of conditions and the following disclaimer in ** Alternatively, you may use this file under the terms of the BSD license
** the documentation and/or other materials provided with the ** as follows:
** distribution. **
** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor ** "Redistribution and use in source and binary forms, with or without
** the names of its contributors may be used to endorse or promote ** modification, are permitted provided that the following conditions are
** products derived from this software without specific prior written ** met:
** permission. ** * Redistributions of source code must retain the above copyright
** ** notice, this list of conditions and the following disclaimer.
** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ** * Redistributions in binary form must reproduce the above copyright
** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ** notice, this list of conditions and the following disclaimer in
** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ** the documentation and/or other materials provided with the
** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ** distribution.
** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ** * Neither the name of The Qt Company Ltd nor the names of its
** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ** contributors may be used to endorse or promote products derived
** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ** from this software without specific prior written permission.
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY **
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT **
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
** $QT_END_LICENSE$ ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
** ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
****************************************************************************/ ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include <QtGui> //#include <QtWidget>
#include <QWidget>
#include "flowlayout.h" #include "flowlayout.h"
FlowLayout::FlowLayout(QWidget *parent, int margin, int hSpacing, int vSpacing) //! [1]
: QLayout(parent), m_hSpace(hSpacing), m_vSpace(vSpacing) FlowLayout::FlowLayout(QWidget *parent, int margin, int hSpacing, int vSpacing)
{ : QLayout(parent), m_hSpace(hSpacing), m_vSpace(vSpacing)
setContentsMargins(margin, margin, margin, margin); {
} setContentsMargins(margin, margin, margin, margin);
}
FlowLayout::FlowLayout(int margin, int hSpacing, int vSpacing) FlowLayout::FlowLayout(int margin, int hSpacing, int vSpacing)
: m_hSpace(hSpacing), m_vSpace(vSpacing) : m_hSpace(hSpacing), m_vSpace(vSpacing)
{ {
setContentsMargins(margin, margin, margin, margin); setContentsMargins(margin, margin, margin, margin);
} }
//! [1]
FlowLayout::~FlowLayout() //! [2]
{ FlowLayout::~FlowLayout()
QLayoutItem *item; {
while ((item = takeAt(0))) QLayoutItem *item;
delete item; while ((item = takeAt(0)))
} delete item;
}
//! [2]
void FlowLayout::addItem(QLayoutItem *item) void FlowLayout::addWidgetAt(QWidget *w, int pos)
{ {
itemList.append(item); addWidget(w);
} this->itemList.move(this->itemList.count()-1, 0);
}
int FlowLayout::horizontalSpacing() const //! [3]
{ void FlowLayout::addItem(QLayoutItem *item)
if (m_hSpace >= 0) { {
return m_hSpace; itemList.append(item);
} else { }
return smartSpacing(QStyle::PM_LayoutHorizontalSpacing); //! [3]
}
}
int FlowLayout::verticalSpacing() const //! [4]
{ int FlowLayout::horizontalSpacing() const
if (m_vSpace >= 0) { {
return m_vSpace; if (m_hSpace >= 0) {
} else { return m_hSpace;
return smartSpacing(QStyle::PM_LayoutVerticalSpacing); } else {
} return smartSpacing(QStyle::PM_LayoutHorizontalSpacing);
} }
}
int FlowLayout::count() const int FlowLayout::verticalSpacing() const
{ {
return itemList.size(); if (m_vSpace >= 0) {
} return m_vSpace;
} else {
return smartSpacing(QStyle::PM_LayoutVerticalSpacing);
}
}
//! [4]
QLayoutItem *FlowLayout::itemAt(int index) const //! [5]
{ int FlowLayout::count() const
return itemList.value(index); {
} return itemList.size();
}
QLayoutItem *FlowLayout::takeAt(int index) QLayoutItem *FlowLayout::itemAt(int index) const
{ {
if (index >= 0 && index < itemList.size()) return itemList.value(index);
return itemList.takeAt(index); }
else
return 0;
}
Qt::Orientations FlowLayout::expandingDirections() const QLayoutItem *FlowLayout::takeAt(int index)
{ {
return 0; if (index >= 0 && index < itemList.size())
} return itemList.takeAt(index);
return nullptr;
}
//! [5]
bool FlowLayout::hasHeightForWidth() const //! [6]
{ Qt::Orientations FlowLayout::expandingDirections() const
return true; {
} return { };
}
//! [6]
int FlowLayout::heightForWidth(int width) const //! [7]
{ bool FlowLayout::hasHeightForWidth() const
int height = doLayout(QRect(0, 0, width, 0), true); {
return height; return true;
} }
void FlowLayout::setGeometry(const QRect &rect) int FlowLayout::heightForWidth(int width) const
{ {
QLayout::setGeometry(rect); int height = doLayout(QRect(0, 0, width, 0), true);
doLayout(rect, false); return height;
} }
//! [7]
QSize FlowLayout::sizeHint() const //! [8]
{ void FlowLayout::setGeometry(const QRect &rect)
return minimumSize(); {
} QLayout::setGeometry(rect);
doLayout(rect, false);
}
QSize FlowLayout::minimumSize() const QSize FlowLayout::sizeHint() const
{ {
QSize size; return minimumSize();
QLayoutItem *item; }
foreach (item, itemList)
size = size.expandedTo(item->minimumSize());
size += QSize(2*margin(), 2*margin()); QSize FlowLayout::minimumSize() const
return size; {
} QSize size;
for (const QLayoutItem *item : itemList)
size = size.expandedTo(item->minimumSize());
int FlowLayout::doLayout(const QRect &rect, bool testOnly) const const QMargins margins = contentsMargins();
{ size += QSize(margins.left() + margins.right(), margins.top() + margins.bottom());
int left, top, right, bottom; return size;
getContentsMargins(&left, &top, &right, &bottom); }
QRect effectiveRect = rect.adjusted(+left, +top, -right, -bottom); //! [8]
int x = effectiveRect.x();
int y = effectiveRect.y();
int lineHeight = 0;
QLayoutItem *item; //! [9]
foreach (item, itemList) { int FlowLayout::doLayout(const QRect &rect, bool testOnly) const
QWidget *wid = item->widget(); {
int spaceX = horizontalSpacing(); int left, top, right, bottom;
if (spaceX == -1) getContentsMargins(&left, &top, &right, &bottom);
spaceX = wid->style()->layoutSpacing( QRect effectiveRect = rect.adjusted(+left, +top, -right, -bottom);
QSizePolicy::PushButton, QSizePolicy::PushButton, Qt::Horizontal); int x = effectiveRect.x();
int spaceY = verticalSpacing(); int y = effectiveRect.y();
if (spaceY == -1) int lineHeight = 0;
spaceY = wid->style()->layoutSpacing( //! [9]
QSizePolicy::PushButton, QSizePolicy::PushButton, Qt::Vertical);
int nextX = x + item->sizeHint().width() + spaceX;
if (nextX - spaceX > effectiveRect.right() && lineHeight > 0) {
x = effectiveRect.x();
y = y + lineHeight + spaceY;
nextX = x + item->sizeHint().width() + spaceX;
lineHeight = 0;
}
if (!testOnly) //! [10]
item->setGeometry(QRect(QPoint(x, y), item->sizeHint())); for (QLayoutItem *item : itemList) {
const QWidget *wid = item->widget();
int spaceX = horizontalSpacing();
if (spaceX == -1)
spaceX = wid->style()->layoutSpacing(
QSizePolicy::PushButton, QSizePolicy::PushButton, Qt::Horizontal);
int spaceY = verticalSpacing();
if (spaceY == -1)
spaceY = wid->style()->layoutSpacing(
QSizePolicy::PushButton, QSizePolicy::PushButton, Qt::Vertical);
//! [10]
//! [11]
int nextX = x + item->sizeHint().width() + spaceX;
if (nextX - spaceX > effectiveRect.right() && lineHeight > 0) {
x = effectiveRect.x();
y = y + lineHeight + spaceY;
nextX = x + item->sizeHint().width() + spaceX;
lineHeight = 0;
}
x = nextX; if (!testOnly)
lineHeight = qMax(lineHeight, item->sizeHint().height()); item->setGeometry(QRect(QPoint(x, y), item->sizeHint()));
}
return y + lineHeight - rect.y() + bottom; x = nextX;
} lineHeight = qMax(lineHeight, item->sizeHint().height());
int FlowLayout::smartSpacing(QStyle::PixelMetric pm) const }
{ return y + lineHeight - rect.y() + bottom;
QObject *parent = this->parent(); }
if (!parent) { //! [11]
return -1; //! [12]
} else if (parent->isWidgetType()) { int FlowLayout::smartSpacing(QStyle::PixelMetric pm) const
QWidget *pw = static_cast<QWidget *>(parent); {
return pw->style()->pixelMetric(pm, 0, pw); QObject *parent = this->parent();
} else { if (!parent) {
return static_cast<QLayout *>(parent)->spacing(); return -1;
} } else if (parent->isWidgetType()) {
} QWidget *pw = static_cast<QWidget *>(parent);
void FlowLayout::insertWidgetAt(QWidget *widget, int index) return pw->style()->pixelMetric(pm, nullptr, pw);
{ } else {
addWidget(widget); return static_cast<QLayout *>(parent)->spacing();
this->itemList.move(this->itemList.count()-1, 0); }
//this->itemList.insert(index, new QWidgetItem(widget)); }
} //! [12]

View File

@ -1,77 +1,89 @@
/**************************************************************************** /****************************************************************************
** **
** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). ** Copyright (C) 2016 The Qt Company Ltd.
** All rights reserved. ** Contact: https://www.qt.io/licensing/
** Contact: Nokia Corporation (qt-info@nokia.com) **
** ** This file is part of the examples of the Qt Toolkit.
** This file is part of the examples of the Qt Toolkit. **
** ** $QT_BEGIN_LICENSE:BSD$
** $QT_BEGIN_LICENSE:BSD$ ** Commercial License Usage
** You may use this file under the terms of the BSD license as follows: ** Licensees holding valid commercial Qt licenses may use this file in
** ** accordance with the commercial license agreement provided with the
** "Redistribution and use in source and binary forms, with or without ** Software or, alternatively, in accordance with the terms contained in
** modification, are permitted provided that the following conditions are ** a written agreement between you and The Qt Company. For licensing terms
** met: ** and conditions see https://www.qt.io/terms-conditions. For further
** * Redistributions of source code must retain the above copyright ** information use the contact form at https://www.qt.io/contact-us.
** notice, this list of conditions and the following disclaimer. **
** * Redistributions in binary form must reproduce the above copyright ** BSD License Usage
** notice, this list of conditions and the following disclaimer in ** Alternatively, you may use this file under the terms of the BSD license
** the documentation and/or other materials provided with the ** as follows:
** distribution. **
** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor ** "Redistribution and use in source and binary forms, with or without
** the names of its contributors may be used to endorse or promote ** modification, are permitted provided that the following conditions are
** products derived from this software without specific prior written ** met:
** permission. ** * Redistributions of source code must retain the above copyright
** ** notice, this list of conditions and the following disclaimer.
** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ** * Redistributions in binary form must reproduce the above copyright
** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ** notice, this list of conditions and the following disclaimer in
** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ** the documentation and/or other materials provided with the
** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ** distribution.
** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ** * Neither the name of The Qt Company Ltd nor the names of its
** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ** contributors may be used to endorse or promote products derived
** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ** from this software without specific prior written permission.
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY **
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT **
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
** $QT_END_LICENSE$ ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
** ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
****************************************************************************/ ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
**
** $QT_END_LICENSE$
**
****************************************************************************/
#ifndef FLOWLAYOUT_H #ifndef FLOWLAYOUT_H
#define FLOWLAYOUT_H #define FLOWLAYOUT_H
#include <QLayout> #include <QLayout>
#include <QRect> #include <QRect>
#include <QWidgetItem> #include <QStyle>
class FlowLayout : public QLayout //! [0]
{ class FlowLayout : public QLayout
public: {
FlowLayout(QWidget *parent, int margin = -1, int hSpacing = -1, int vSpacing = -1); public:
FlowLayout(int margin = -1, int hSpacing = -1, int vSpacing = -1); explicit FlowLayout(QWidget *parent, int margin = -1, int hSpacing = -1, int vSpacing = -1);
~FlowLayout(); explicit FlowLayout(int margin = -1, int hSpacing = -1, int vSpacing = -1);
~FlowLayout();
void addItem(QLayoutItem *item); void addWidgetAt(QWidget *w, int pos);
int horizontalSpacing() const; void addItem(QLayoutItem *item) override;
int verticalSpacing() const; int horizontalSpacing() const;
Qt::Orientations expandingDirections() const; int verticalSpacing() const;
bool hasHeightForWidth() const; Qt::Orientations expandingDirections() const override;
int heightForWidth(int) const; bool hasHeightForWidth() const override;
int count() const; int heightForWidth(int) const override;
QLayoutItem *itemAt(int index) const; int count() const override;
QSize minimumSize() const; QLayoutItem *itemAt(int index) const override;
void setGeometry(const QRect &rect); QSize minimumSize() const override;
QSize sizeHint() const; void setGeometry(const QRect &rect) override;
QLayoutItem *takeAt(int index); QSize sizeHint() const override;
void insertWidgetAt(QWidget *widget, int index); QLayoutItem *takeAt(int index) override;
private: private:
int doLayout(const QRect &rect, bool testOnly) const; int doLayout(const QRect &rect, bool testOnly) const;
int smartSpacing(QStyle::PixelMetric pm) const; int smartSpacing(QStyle::PixelMetric pm) const;
QList<QLayoutItem *> itemList; QList<QLayoutItem *> itemList;
int m_hSpace; int m_hSpace;
int m_vSpace; int m_vSpace;
}; };
//! [0]
#endif #endif // FLOWLAYOUT_H

View File

@ -173,7 +173,7 @@ void MainWindow::searchFinished(KonaSearch *ks) {
KonaPreviewImageView *temp = new KonaPreviewImageView(); KonaPreviewImageView *temp = new KonaPreviewImageView();
temp->setObjectName(QString::number(ki->getId())); temp->setObjectName(QString::number(ki->getId()));
if (insertAtBeginning) { if (insertAtBeginning) {
flowLayout->insertWidgetAt(temp, 0); // Add @ beginning flowLayout->addWidgetAt(temp, 0); // Add @ beginning
} }
else { else {
flowLayout->addWidget(temp); // Add @ end flowLayout->addWidget(temp); // Add @ end