File indexing completed on 2024-04-28 05:38:13

0001 /***************************************************************************
0002  *   Copyright (C) 2010 by Renaud Guezennec                                *
0003  *   https://rolisteam.org/contact                   *
0004  *                                                                         *
0005  *   rolisteam is free software; you can redistribute it and/or modify     *
0006  *   it under the terms of the GNU General Public License as published by  *
0007  *   the Free Software Foundation; either version 2 of the License, or     *
0008  *   (at your option) any later version.                                   *
0009  *                                                                         *
0010  *   This program is distributed in the hope that it will be useful,       *
0011  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
0012  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
0013  *   GNU General Public License for more details.                          *
0014  *                                                                         *
0015  *   You should have received a copy of the GNU General Public License     *
0016  *   along with this program; if not, write to the                         *
0017  *   Free Software Foundation, Inc.,                                       *
0018  *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
0019  ***************************************************************************/
0020 
0021 #include <QtWidgets>
0022 
0023 #include "flowlayout.h"
0024 FlowLayout::FlowLayout(QWidget* parent, int margin, int hSpacing, int vSpacing)
0025     : QLayout(parent), m_hSpace(hSpacing), m_vSpace(vSpacing)
0026 {
0027     setContentsMargins(margin, margin, margin, margin);
0028 }
0029 
0030 FlowLayout::FlowLayout(int margin, int hSpacing, int vSpacing) : m_hSpace(hSpacing), m_vSpace(vSpacing)
0031 {
0032     setContentsMargins(margin, margin, margin, margin);
0033 }
0034 
0035 FlowLayout::~FlowLayout()
0036 {
0037     QLayoutItem* item;
0038     while((item= takeAt(0)))
0039         delete item;
0040 }
0041 
0042 void FlowLayout::addItem(QLayoutItem* item)
0043 {
0044     itemList.append(item);
0045 }
0046 
0047 int FlowLayout::horizontalSpacing() const
0048 {
0049     if(m_hSpace >= 0)
0050     {
0051         return m_hSpace;
0052     }
0053     else
0054     {
0055         return smartSpacing(QStyle::PM_LayoutHorizontalSpacing);
0056     }
0057 }
0058 
0059 int FlowLayout::verticalSpacing() const
0060 {
0061     if(m_vSpace >= 0)
0062     {
0063         return m_vSpace;
0064     }
0065     else
0066     {
0067         return smartSpacing(QStyle::PM_LayoutVerticalSpacing);
0068     }
0069 }
0070 
0071 int FlowLayout::count() const
0072 {
0073     return itemList.size();
0074 }
0075 
0076 QLayoutItem* FlowLayout::itemAt(int index) const
0077 {
0078     return itemList.value(index);
0079 }
0080 
0081 QLayoutItem* FlowLayout::takeAt(int index)
0082 {
0083     if(index >= 0 && index < itemList.size())
0084         return itemList.takeAt(index);
0085     else
0086         return 0;
0087 }
0088 
0089 Qt::Orientations FlowLayout::expandingDirections() const
0090 {
0091     return Qt::Horizontal;
0092 }
0093 
0094 bool FlowLayout::hasHeightForWidth() const
0095 {
0096     return true;
0097 }
0098 
0099 int FlowLayout::heightForWidth(int width) const
0100 {
0101     int height= doLayout(QRect(0, 0, width, 0), true);
0102     return height;
0103 }
0104 
0105 void FlowLayout::setGeometry(const QRect& rect)
0106 {
0107     QLayout::setGeometry(rect);
0108     doLayout(rect, false);
0109 }
0110 
0111 QSize FlowLayout::sizeHint() const
0112 {
0113     return minimumSize();
0114 }
0115 
0116 QSize FlowLayout::minimumSize() const
0117 {
0118     QSize size;
0119     for(auto item : itemList)
0120         size= size.expandedTo(item->minimumSize());
0121     size+= QSize(contentsMargins().left() + contentsMargins().right(),
0122                  contentsMargins().top() + contentsMargins().bottom());
0123     return size;
0124 }
0125 
0126 int FlowLayout::doLayout(const QRect& rect, bool testOnly) const
0127 {
0128     int left, top, right, bottom;
0129     getContentsMargins(&left, &top, &right, &bottom);
0130     QRect effectiveRect= rect.adjusted(+left, +top, -right, -bottom);
0131     int x= effectiveRect.x();
0132     int y= effectiveRect.y();
0133     int lineHeight= 0;
0134 
0135     for(auto item : itemList)
0136     {
0137         QWidget* wid= item->widget();
0138         int spaceX= horizontalSpacing();
0139         if(spaceX == -1)
0140             spaceX= wid->style()->layoutSpacing(QSizePolicy::PushButton, QSizePolicy::PushButton, Qt::Horizontal);
0141         int spaceY= verticalSpacing();
0142         if(spaceY == -1)
0143             spaceY= wid->style()->layoutSpacing(QSizePolicy::PushButton, QSizePolicy::PushButton, Qt::Vertical);
0144         int nextX= x + item->sizeHint().width() + spaceX;
0145         if(nextX - spaceX > effectiveRect.right() && lineHeight > 0)
0146         {
0147             x= effectiveRect.x();
0148             y= y + lineHeight + spaceY;
0149             nextX= x + item->sizeHint().width() + spaceX;
0150             lineHeight= 0;
0151         }
0152 
0153         if(!testOnly)
0154             item->setGeometry(QRect(QPoint(x, y), item->sizeHint()));
0155 
0156         x= nextX;
0157         lineHeight= qMax(lineHeight, item->sizeHint().height());
0158     }
0159     return y + lineHeight - rect.y() + bottom;
0160 }
0161 int FlowLayout::smartSpacing(QStyle::PixelMetric pm) const
0162 {
0163     QObject* parent= this->parent();
0164     if(!parent)
0165     {
0166         return -1;
0167     }
0168     else if(parent->isWidgetType())
0169     {
0170         QWidget* pw= static_cast<QWidget*>(parent);
0171         return pw->style()->pixelMetric(pm, 0, pw);
0172     }
0173     else
0174     {
0175         return static_cast<QLayout*>(parent)->spacing();
0176     }
0177 }