2021-09-19 16:38:54 +03:00
/****************************************************************************
* *
* * Copyright ( C ) 2015 The Qt Company Ltd .
* * Copyright ( C ) 2016 Ivailo Monev
* *
* * This file is part of the test suite of the Katie Toolkit .
* *
* * $ QT_BEGIN_LICENSE : LGPL $
* *
* * GNU Lesser General Public License Usage
* * This file may be used under the terms of the GNU Lesser
* * General Public License version 2.1 as published by the Free Software
* * Foundation and appearing in the file LICENSE . LGPL included in the
* * packaging of this file . Please review the following information to
* * ensure the GNU Lesser General Public License version 2.1 requirements
* * will be met : http : //www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
* *
* * $ QT_END_LICENSE $
* *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
# include <QtTest/QtTest>
# include <QtGui>
//TESTED_CLASS=
//TESTED_FILES=
class tst_QBoxLayout : public QObject
{
Q_OBJECT
public :
tst_QBoxLayout ( ) ;
virtual ~ tst_QBoxLayout ( ) ;
public slots :
void initTestCase ( ) ;
void cleanupTestCase ( ) ;
void init ( ) ;
void cleanup ( ) ;
private slots :
void insertSpacerItem ( ) ;
void insertLayout ( ) ;
void sizeHint ( ) ;
void sizeConstraints ( ) ;
void setGeometry ( ) ;
void setStyleShouldChangeSpacing ( ) ;
void testLayoutEngine_data ( ) ;
void testLayoutEngine ( ) ;
void taskQTBUG_7103_minMaxWidthNotRespected ( ) ;
void taskQTBUG_27420_takeAtShouldUnparentLayout ( ) ;
} ;
2022-02-26 22:24:40 +02:00
# ifndef QT_NO_STYLE_WINDOWS
2021-09-19 16:38:54 +03:00
class CustomLayoutStyle : public QWindowsStyle
{
Q_OBJECT
public :
CustomLayoutStyle ( ) : QWindowsStyle ( )
{
hspacing = 5 ;
vspacing = 10 ;
}
virtual int pixelMetric ( PixelMetric metric , const QStyleOption * option = 0 ,
const QWidget * widget = 0 ) const ;
int hspacing ;
int vspacing ;
} ;
int CustomLayoutStyle : : pixelMetric ( PixelMetric metric , const QStyleOption * option /*= 0*/ ,
const QWidget * widget /*= 0*/ ) const
{
switch ( metric ) {
case PM_LayoutLeftMargin :
return 0 ;
case PM_LayoutTopMargin :
return 3 ;
case PM_LayoutRightMargin :
return 6 ;
case PM_LayoutBottomMargin :
return 9 ;
case PM_LayoutHorizontalSpacing :
return hspacing ;
case PM_LayoutVerticalSpacing :
return vspacing ;
default :
break ;
}
return QWindowsStyle : : pixelMetric ( metric , option , widget ) ;
}
2022-02-26 22:24:40 +02:00
# endif // QT_NO_STYLE_WINDOWS
2021-09-19 16:38:54 +03:00
tst_QBoxLayout : : tst_QBoxLayout ( )
{
}
tst_QBoxLayout : : ~ tst_QBoxLayout ( )
{
}
void tst_QBoxLayout : : initTestCase ( )
{
}
void tst_QBoxLayout : : cleanupTestCase ( )
{
}
void tst_QBoxLayout : : init ( )
{
}
void tst_QBoxLayout : : cleanup ( )
{
}
void tst_QBoxLayout : : insertSpacerItem ( )
{
2022-06-05 15:40:57 +03:00
QWidget window ;
2021-09-19 16:38:54 +03:00
QSpacerItem * spacer1 = new QSpacerItem ( 20 , 10 , QSizePolicy : : Expanding , QSizePolicy : : Expanding ) ;
QSpacerItem * spacer2 = new QSpacerItem ( 40 , 20 , QSizePolicy : : Expanding , QSizePolicy : : Expanding ) ;
QBoxLayout * layout = new QHBoxLayout ;
layout - > addWidget ( new QLineEdit ( " Foooooooooooooooooooooooooo " ) ) ;
layout - > addSpacerItem ( spacer1 ) ;
layout - > addWidget ( new QLineEdit ( " Baaaaaaaaaaaaaaaaaaaaaaaaar " ) ) ;
layout - > insertSpacerItem ( 0 , spacer2 ) ;
2022-06-05 15:40:57 +03:00
window . setLayout ( layout ) ;
2021-09-19 16:38:54 +03:00
QVERIFY ( layout - > itemAt ( 0 ) = = spacer2 ) ;
QVERIFY ( layout - > itemAt ( 2 ) = = spacer1 ) ;
2022-06-05 15:40:57 +03:00
window . show ( ) ;
2021-09-19 16:38:54 +03:00
}
void tst_QBoxLayout : : insertLayout ( )
{
2022-06-05 15:40:57 +03:00
QWidget window ;
QVBoxLayout * vbox = new QVBoxLayout ( & window ) ;
2021-09-19 16:38:54 +03:00
QVBoxLayout * dummyParentLayout = new QVBoxLayout ;
QHBoxLayout * subLayout = new QHBoxLayout ;
dummyParentLayout - > addLayout ( subLayout ) ;
QCOMPARE ( subLayout - > parent ( ) , dummyParentLayout ) ;
QCOMPARE ( dummyParentLayout - > count ( ) , 1 ) ;
// add subLayout to another layout
QTest : : ignoreMessage ( QtWarningMsg , " QLayout::addChildLayout: layout \" \" already has a parent " ) ;
vbox - > addLayout ( subLayout ) ;
QCOMPARE ( ( subLayout - > parent ( ) = = vbox ) , ( vbox - > count ( ) = = 1 ) ) ;
delete dummyParentLayout ;
}
void tst_QBoxLayout : : sizeHint ( )
{
2022-06-05 15:40:57 +03:00
QWidget window ;
2021-09-19 16:38:54 +03:00
QHBoxLayout * lay1 = new QHBoxLayout ;
QHBoxLayout * lay2 = new QHBoxLayout ;
QLabel * label = new QLabel ( " widget twooooooooooooooooooooooooooooooooooooooooooooooooooooooo " ) ;
lay2 - > addWidget ( label ) ;
lay1 - > addLayout ( lay2 ) ;
2022-06-05 15:40:57 +03:00
window . setLayout ( lay1 ) ;
window . show ( ) ;
2021-09-19 16:38:54 +03:00
label - > setText ( " foooooooo baaaaaaar " ) ;
QSize sh = lay1 - > sizeHint ( ) ;
QApplication : : processEvents ( ) ;
// Note that this is not strictly required behaviour - actually
// the preferred behaviour would be that sizeHint returns
// the same value regardless of what's lying in the event queue.
// (i.e. we would check for equality here instead)
QVERIFY ( lay1 - > sizeHint ( ) ! = sh ) ;
}
void tst_QBoxLayout : : sizeConstraints ( )
{
2022-06-05 15:40:57 +03:00
QWidget window ;
2021-09-19 16:38:54 +03:00
QHBoxLayout * lay = new QHBoxLayout ;
lay - > addWidget ( new QLabel ( " foooooooooooooooooooooooooooooooooooo " ) ) ;
lay - > addWidget ( new QLabel ( " baaaaaaaaaaaaaaaaaaaaaaaaaaaaaar " ) ) ;
lay - > setSizeConstraint ( QLayout : : SetFixedSize ) ;
2022-06-05 15:40:57 +03:00
window . setLayout ( lay ) ;
window . show ( ) ;
2021-09-19 16:38:54 +03:00
QApplication : : processEvents ( ) ;
2022-06-05 15:40:57 +03:00
QSize sh = window . sizeHint ( ) ;
2021-09-19 16:38:54 +03:00
lay - > takeAt ( 1 ) ;
2022-06-05 15:40:57 +03:00
QVERIFY ( sh . width ( ) > = window . sizeHint ( ) . width ( ) & &
sh . height ( ) > = window . sizeHint ( ) . height ( ) ) ;
2021-09-19 16:38:54 +03:00
}
void tst_QBoxLayout : : setGeometry ( )
{
2022-02-24 23:55:39 +02:00
# ifdef QT_NO_DIAL
QSKIP ( " Katie compiled without dial support (QT_NO_DIAL) " , SkipAll ) ;
# else
2021-09-19 16:38:54 +03:00
QWidget toplevel ;
QWidget w ( & toplevel ) ;
QVBoxLayout * lay = new QVBoxLayout ;
lay - > setMargin ( 0 ) ;
lay - > setSpacing ( 0 ) ;
QHBoxLayout * lay2 = new QHBoxLayout ;
QDial * dial = new QDial ;
lay2 - > addWidget ( dial ) ;
lay2 - > setAlignment ( Qt : : AlignTop ) ;
lay2 - > setAlignment ( Qt : : AlignRight ) ;
lay - > addLayout ( lay2 ) ;
w . setLayout ( lay ) ;
toplevel . show ( ) ;
QRect newGeom ( 0 , 0 , 70 , 70 ) ;
lay2 - > setGeometry ( newGeom ) ;
QVERIFY2 ( newGeom . contains ( dial - > geometry ( ) ) , " dial->geometry() should be smaller and within newGeom " ) ;
2022-02-24 23:55:39 +02:00
# endif // QT_NO_DIAL
2021-09-19 16:38:54 +03:00
}
void tst_QBoxLayout : : setStyleShouldChangeSpacing ( )
{
2022-02-26 22:24:40 +02:00
# ifndef QT_NO_STYLE_WINDOWS
2022-06-05 15:40:57 +03:00
QWidget window ;
QHBoxLayout * hbox = new QHBoxLayout ( & window ) ;
2021-09-19 16:38:54 +03:00
QPushButton * pb1 = new QPushButton ( tr ( " The spacing between this " ) ) ;
QPushButton * pb2 = new QPushButton ( tr ( " and this button should depend on the style of the parent widget " ) ) ; ;
pb1 - > setAttribute ( Qt : : WA_LayoutUsesWidgetRect ) ;
pb2 - > setAttribute ( Qt : : WA_LayoutUsesWidgetRect ) ;
hbox - > addWidget ( pb1 ) ;
hbox - > addWidget ( pb2 ) ;
2022-06-05 15:40:57 +03:00
QScopedPointer < CustomLayoutStyle > style1 ( new CustomLayoutStyle ( ) ) ;
2021-09-19 16:38:54 +03:00
style1 - > hspacing = 6 ;
2022-06-05 15:40:57 +03:00
window . setStyle ( style1 . data ( ) ) ;
window . show ( ) ;
2021-09-19 16:38:54 +03:00
QTest : : qWait ( 100 ) ;
int spacing = pb2 - > geometry ( ) . left ( ) - pb1 - > geometry ( ) . right ( ) - 1 ;
QCOMPARE ( spacing , 6 ) ;
2022-06-05 15:40:57 +03:00
QScopedPointer < CustomLayoutStyle > style2 ( new CustomLayoutStyle ( ) ) ;
2021-09-19 16:38:54 +03:00
style2 - > hspacing = 10 ;
2022-06-05 15:40:57 +03:00
window . setStyle ( style2 . data ( ) ) ;
2021-09-19 16:38:54 +03:00
QTest : : qWait ( 100 ) ;
spacing = pb2 - > geometry ( ) . left ( ) - pb1 - > geometry ( ) . right ( ) - 1 ;
QCOMPARE ( spacing , 10 ) ;
2022-02-26 22:24:40 +02:00
# else // QT_NO_STYLE_WINDOWS
QSKIP ( " Katie compiled without windows style support (QT_NO_STYLE_WINDOWS) " , SkipAll ) ;
# endif // QT_NO_STYLE_WINDOWS
2021-09-19 16:38:54 +03:00
}
void tst_QBoxLayout : : taskQTBUG_7103_minMaxWidthNotRespected ( )
{
2022-02-26 22:24:40 +02:00
QLabel * label = new QLabel ( " Katie uses standard C++, but makes extensive use of the C pre-processor to enrich the language. Qt can also be used in several other programming languages via language bindings. It runs on all major platforms, and has extensive internationalization support. Non-GUI features include SQL database access, XML parsing, thread management, network support and a unified cross-platform API for file handling. " ) ;
2021-09-19 16:38:54 +03:00
label - > setWordWrap ( true ) ;
label - > setFixedWidth ( 200 ) ;
QVBoxLayout * layout = new QVBoxLayout ;
layout - > addWidget ( label ) ;
layout - > addSpacerItem ( new QSpacerItem ( 1 , 1 , QSizePolicy : : Fixed , QSizePolicy : : Expanding ) ) ;
QWidget widget ;
widget . setLayout ( layout ) ;
widget . show ( ) ;
QTest : : qWaitForWindowShown ( & widget ) ;
int height = label - > height ( ) ;
QRect g = widget . geometry ( ) ;
g . setWidth ( 600 ) ;
widget . setGeometry ( g ) ;
QTest : : qWait ( 50 ) ;
QCOMPARE ( label - > height ( ) , height ) ;
}
void tst_QBoxLayout : : taskQTBUG_27420_takeAtShouldUnparentLayout ( )
{
QSharedPointer < QHBoxLayout > outer ( new QHBoxLayout ) ;
QPointer < QVBoxLayout > inner = new QVBoxLayout ;
outer - > addLayout ( inner ) ;
QCOMPARE ( outer - > count ( ) , 1 ) ;
QCOMPARE ( inner - > parent ( ) , outer . data ( ) ) ;
QLayoutItem * item = outer - > takeAt ( 0 ) ;
QCOMPARE ( item - > layout ( ) , inner . data ( ) ) ;
QVERIFY ( ! item - > layout ( ) - > parent ( ) ) ;
outer . clear ( ) ;
if ( inner )
delete item ; // success: a taken item/layout should not be deleted when the old parent is deleted
else
QVERIFY ( ! inner . isNull ( ) ) ;
}
struct Descr
{
Descr ( int min , int sh , int max = - 1 , bool exp = false , int _stretch = 0 , bool _empty = false )
: minimumSize ( min ) , sizeHint ( sh ) , maximumSize ( max < 0 ? QLAYOUTSIZE_MAX : max ) ,
expanding ( exp ) , stretch ( _stretch ) , empty ( _empty )
{ }
int minimumSize ;
int sizeHint ;
int maximumSize ;
bool expanding ;
int stretch ;
bool empty ;
} ;
typedef QList < Descr > DescrList ;
Q_DECLARE_METATYPE ( DescrList ) ;
typedef QList < int > SizeList ;
Q_DECLARE_METATYPE ( SizeList ) ;
typedef QList < int > PosList ;
class LayoutItem : public QLayoutItem
{
public :
LayoutItem ( const Descr & descr ) : m_descr ( descr ) { }
QSize sizeHint ( ) const { return QSize ( m_descr . sizeHint , 100 ) ; }
QSize minimumSize ( ) const { return QSize ( m_descr . minimumSize , 0 ) ; }
QSize maximumSize ( ) const { return QSize ( m_descr . maximumSize , QLAYOUTSIZE_MAX ) ; }
Qt : : Orientations expandingDirections ( ) const
{ return m_descr . expanding ? Qt : : Horizontal : Qt : : Orientations ( 0 ) ; }
void setGeometry ( const QRect & r ) { m_pos = r . x ( ) ; m_size = r . width ( ) ; }
QRect geometry ( ) const { return QRect ( m_pos , 0 , m_size , 100 ) ; }
bool isEmpty ( ) const { return m_descr . empty ; }
private :
Descr m_descr ;
int m_pos ;
int m_size ;
} ;
void tst_QBoxLayout : : testLayoutEngine_data ( )
{
// (int min, int sh, int max = -1, bool exp= false, int _stretch = 0, bool _empty = false)
QTest : : addColumn < DescrList > ( " itemDescriptions " ) ;
QTest : : addColumn < int > ( " size " ) ;
QTest : : addColumn < int > ( " spacing " ) ;
QTest : : addColumn < PosList > ( " expectedPositions " ) ;
QTest : : addColumn < SizeList > ( " expectedSizes " ) ;
QTest : : newRow ( " Just one " )
< < ( DescrList ( ) < < Descr ( 0 , 100 ) )
< < 200
< < 0
< < ( PosList ( ) < < 0 )
< < ( SizeList ( ) < < 200 ) ;
QTest : : newRow ( " Two non-exp " )
< < ( DescrList ( ) < < Descr ( 0 , 100 ) < < Descr ( 0 , 100 ) )
< < 400
< < 0
< < ( PosList ( ) < < 0 < < 200 )
< < ( SizeList ( ) < < 200 < < 200 ) ;
QTest : : newRow ( " Exp + non-exp " )
< < ( DescrList ( ) < < Descr ( 0 , 100 , - 1 , true ) < < Descr ( 0 , 100 ) )
< < 400
< < 0
< < ( PosList ( ) < < 0 < < 300 )
< < ( SizeList ( ) < < 300 < < 100 ) ;
QTest : : newRow ( " Stretch " )
< < ( DescrList ( ) < < Descr ( 0 , 100 , - 1 , false , 1 ) < < Descr ( 0 , 100 , - 1 , false , 2 ) )
< < 300
< < 0
< < ( PosList ( ) < < 0 < < 100 )
< < ( SizeList ( ) < < 100 < < 200 ) ;
QTest : : newRow ( " Spacing " )
< < ( DescrList ( ) < < Descr ( 0 , 100 ) < < Descr ( 0 , 100 ) )
< < 400
< < 10
< < ( PosList ( ) < < 0 < < 205 )
< < ( SizeList ( ) < < 195 < < 195 ) ;
QTest : : newRow ( " Less than minimum " )
< < ( DescrList ( ) < < Descr ( 100 , 100 , 100 , false ) < < Descr ( 50 , 100 , 100 , false ) )
< < 100
< < 0
< < ( PosList ( ) < < 0 < < 50 )
< < ( SizeList ( ) < < 50 < < 50 ) ;
QTest : : newRow ( " Less than sizehint " )
< < ( DescrList ( ) < < Descr ( 100 , 200 , 100 , false ) < < Descr ( 50 , 200 , 100 , false ) )
< < 200
< < 0
< < ( PosList ( ) < < 0 < < 100 )
< < ( SizeList ( ) < < 100 < < 100 ) ;
QTest : : newRow ( " Too much space " )
< < ( DescrList ( ) < < Descr ( 0 , 100 , 100 , false ) < < Descr ( 0 , 100 , 100 , false ) )
< < 500
< < 0
< < ( PosList ( ) < < 100 < < 300 )
< < ( SizeList ( ) < < 100 < < 100 ) ;
QTest : : newRow ( " Empty " )
< < ( DescrList ( ) < < Descr ( 0 , 100 , 100 ) < < Descr ( 0 , 0 , - 1 , false , 0 , true ) < < Descr ( 0 , 100 , 100 ) )
< < 500
< < 0
< < ( PosList ( ) < < 100 < < 300 < < 300 )
< < ( SizeList ( ) < < 100 < < 0 < < 100 ) ;
QTest : : newRow ( " QTBUG-33104 " )
< < ( DescrList ( ) < < Descr ( 11 , 75 , 75 , true ) < < Descr ( 75 , 75 ) )
< < 200
< < 0
< < ( PosList ( ) < < 0 < < 75 )
< < ( SizeList ( ) < < 75 < < 125 ) ;
QTest : : newRow ( " Expanding with maximumSize " )
< < ( DescrList ( ) < < Descr ( 11 , 75 , 100 , true ) < < Descr ( 75 , 75 ) )
< < 200
< < 0
< < ( PosList ( ) < < 0 < < 100 )
< < ( SizeList ( ) < < 100 < < 100 ) ;
QTest : : newRow ( " Stretch with maximumSize " )
< < ( DescrList ( ) < < Descr ( 11 , 75 , 100 , false , 1 ) < < Descr ( 75 , 75 ) )
< < 200
< < 0
< < ( PosList ( ) < < 0 < < 100 )
< < ( SizeList ( ) < < 100 < < 100 ) ;
QTest : : newRow ( " Stretch with maximumSize last " )
< < ( DescrList ( ) < < Descr ( 75 , 75 ) < < Descr ( 11 , 75 , 100 , false , 1 ) )
< < 200
< < 0
< < ( PosList ( ) < < 0 < < 100 )
< < ( SizeList ( ) < < 100 < < 100 ) ;
}
void tst_QBoxLayout : : testLayoutEngine ( )
{
QFETCH ( DescrList , itemDescriptions ) ;
QFETCH ( int , size ) ;
QFETCH ( int , spacing ) ;
QFETCH ( PosList , expectedPositions ) ;
QFETCH ( SizeList , expectedSizes ) ;
QHBoxLayout box ;
box . setSpacing ( spacing ) ;
int i ;
for ( i = 0 ; i < itemDescriptions . count ( ) ; + + i ) {
Descr descr = itemDescriptions . at ( i ) ;
LayoutItem * li = new LayoutItem ( descr ) ;
box . addItem ( li ) ;
box . setStretch ( i , descr . stretch ) ;
}
box . setGeometry ( QRect ( 0 , 0 , size , 100 ) ) ;
for ( i = 0 ; i < expectedSizes . count ( ) ; + + i ) {
int xSize = expectedSizes . at ( i ) ;
int xPos = expectedPositions . at ( i ) ;
QLayoutItem * item = box . itemAt ( i ) ;
QCOMPARE ( item - > geometry ( ) . width ( ) , xSize ) ;
QCOMPARE ( item - > geometry ( ) . x ( ) , xPos ) ;
}
}
QTEST_MAIN ( tst_QBoxLayout )
# include "moc_tst_qboxlayout.cpp"