401 lines
11 KiB
C++
Raw Normal View History

/******************************************************************************
* QSkinny - Copyright (C) 2016 Uwe Rathmann
* This file may be used under the terms of the 3-clause BSD License
*****************************************************************************/
#include "TestBox.h"
2019-07-25 18:39:50 +02:00
#include <QskSizePolicy.h>
2020-03-13 13:32:22 +01:00
#include <QskFunctions.h>
2019-07-25 18:39:50 +02:00
#include <QApplication>
2019-07-29 17:34:46 +02:00
#include <QListWidget>
2019-07-25 18:39:50 +02:00
#include <QDebug>
2019-07-29 17:34:46 +02:00
#include <functional>
#include <vector>
class Box : public TestBox
{
public:
2019-07-29 17:34:46 +02:00
Box( QWidget* parent = nullptr )
: TestBox( parent )
{
2019-07-29 17:34:46 +02:00
m_tests =
2019-07-23 18:35:51 +02:00
{
2019-07-29 17:34:46 +02:00
&Box::test0, &Box::test1, &Box::test2,
&Box::test3, &Box::test4, &Box::test5,
&Box::test6, &Box::test7, &Box::test8,
&Box::test9, &Box::test10, &Box::test11,
&Box::test12
2019-07-25 18:39:50 +02:00
};
2019-07-29 17:34:46 +02:00
}
void showTest( int id )
{
reset();
2019-07-29 17:34:46 +02:00
id = qBound( 0, id, count() - 1 );
m_tests[id]( *this );
2019-07-25 18:39:50 +02:00
2019-07-29 17:34:46 +02:00
updateLabels();
}
2019-07-23 18:35:51 +02:00
2019-07-29 17:34:46 +02:00
int count() const
{
return m_tests.size();
2019-07-25 18:39:50 +02:00
}
2019-07-23 18:35:51 +02:00
2019-07-29 17:34:46 +02:00
private:
2019-07-25 18:39:50 +02:00
void insert( const char* colorName, int row, int column )
{
2019-07-25 18:39:50 +02:00
insert( colorName, row, column, 1, 1 );
}
2019-07-25 18:39:50 +02:00
using TestBox::insert;
void test0();
void test1();
void test2();
void test3();
void test4();
void test5();
void test6();
void test7();
void test8();
2019-07-27 12:37:48 +02:00
void test9();
2019-07-29 17:34:46 +02:00
void test10();
void test11();
void test12();
2019-07-29 17:34:46 +02:00
std::vector< std::function< void( Box& ) > > m_tests;
};
2019-07-29 17:34:46 +02:00
void Box::test0()
2019-07-23 18:35:51 +02:00
{
// something, that works with all layouts
2019-07-25 18:39:50 +02:00
insert( "PaleVioletRed", 0, 0 );
insert( "DarkSeaGreen", 1, 1 );
insert( "SkyBlue", 2, 1 );
insert( "Coral", 2, 2 );
2019-07-23 18:35:51 +02:00
insert( "NavajoWhite", 3, 0, 1, 3 );
}
2019-07-29 17:34:46 +02:00
void Box::test1()
2019-07-23 18:35:51 +02:00
{
/*
2019-07-25 18:39:50 +02:00
Graphics layout adds the extra space to the stretchables
2019-07-23 18:35:51 +02:00
while the other layouts use the extra space for reaching
a ratio according to the stretch factor first,
That leads to column 0 being too large.
*/
setColumns( 1 );
2019-07-25 18:39:50 +02:00
// Quick layouts do not support row/column hints
enableGrid( Quick, false );
2019-07-23 18:35:51 +02:00
2019-07-25 18:39:50 +02:00
insert( "PaleVioletRed", 0, 0 );
insert( "DarkSeaGreen", 1, 1 );
insert( "SkyBlue", 2, 1 );
insert( "Coral", 2, 2 );
setSizePolicyAt( 0, Qt::Horizontal, QskSizePolicy::Expanding );
setSizePolicyAt( 1, Qt::Horizontal, QskSizePolicy::Fixed );
setSizePolicyAt( 2, Qt::Horizontal, QskSizePolicy::Expanding );
setSizePolicyAt( 3, Qt::Horizontal, QskSizePolicy::Fixed );
2019-07-23 18:35:51 +02:00
setColumnSizeHint( 1, Qt::MinimumSize, 100 );
}
2019-07-29 17:34:46 +02:00
void Box::test2()
2019-07-25 18:39:50 +02:00
{
setColumns( 1 );
insert( "PaleVioletRed", 0, 0 );
insert( "DarkSeaGreen", 1, 1 );
insert( "SkyBlue", 2, 1 );
insert( "Coral", 2, 2 );
setSizePolicyAt( 0, Qt::Horizontal, QskSizePolicy::Expanding );
setSizePolicyAt( 1, Qt::Horizontal, QskSizePolicy::Fixed );
setSizePolicyAt( 2, Qt::Horizontal, QskSizePolicy::Expanding );
setSizePolicyAt( 3, Qt::Horizontal, QskSizePolicy::Fixed );
setMinimumWidthAt( 1, 100 );
setMinimumWidthAt( 2, 100 );
}
2019-07-29 17:34:46 +02:00
void Box::test3()
2019-07-23 18:35:51 +02:00
{
/*
The Graphics layout uses a "magic" formula for how to apply
the stretch factors, while the other layouts result in
2019-07-28 17:07:29 +02:00
predictable sizes.
2019-07-23 18:35:51 +02:00
In the specific situation column 1 in the Graphics layout is
larger than twice of columns 0.
*/
2019-07-25 18:39:50 +02:00
setColumns( 3 );
2019-07-23 18:35:51 +02:00
2019-07-25 18:39:50 +02:00
// Quick layouts do not support row/column hints
enableGrid( Quick, false );
insert( "PaleVioletRed", 0, 0 );
insert( "DarkSeaGreen", 1, 0 );
2019-07-23 18:35:51 +02:00
setRowStretchFactor( 0, 1 );
setRowStretchFactor( 1, 2 );
}
2019-07-29 17:34:46 +02:00
void Box::test4()
2019-07-23 18:35:51 +02:00
{
/*
When setting a maximum size together with an alignment the expected result
would be a cell that can grow beyond the maximum, while the content stays
at its maximum, being aligned inside the cell.
But with widgets, the cell size gets always bounded to the preferred size
2019-07-28 17:07:29 +02:00
as soon as an alignment has been set.
2019-07-23 18:35:51 +02:00
2019-07-28 17:07:29 +02:00
With graphics we have the effect, that the cells gets bounded to the
2019-07-23 18:35:51 +02:00
maximum size and we always end up with being aligned Top | Left.
*/
setColumns( 1 );
2019-07-25 18:39:50 +02:00
insert( "PaleVioletRed", 0, 0 );
2019-07-23 18:35:51 +02:00
2019-07-25 18:39:50 +02:00
setPreferredSizeAt( 0, QSize( 10, 10 ) );
2019-07-28 17:07:29 +02:00
setMaximumSizeAt( 0, QSize( 80, 80 ) );
2019-07-23 18:35:51 +02:00
setAlignmentAt( 0, Qt::AlignCenter );
}
2019-07-29 17:34:46 +02:00
void Box::test5()
2019-07-25 18:39:50 +02:00
{
/*
QGridLayoutEngine does not work correctly when putting more
than one element into the same cell. For the specific situation
below we have a wrong preferredSize for Quick and Graphic as only the
last element being inserted one cell goes into the calculation.
The reason behind this limitation is a second list for the elements
organized according to row/column that can only store one
element per cell. Unfortunately the implementation iterates in several
situations over rows/columns using this list.
Iterating over the elements instead avoids this limitation and would
be more efficient as well.
Actually the row/column organized list is ony useful for faster lookups,
2019-07-27 12:37:48 +02:00
when retrieving an item at a specific cell - beside that it
2019-07-25 18:39:50 +02:00
complicates the code without offering extra benefits.
The position of the rectangles differs because the systems have
default alignments.
*/
insert( "PaleVioletRed", 0, 0 );
insert( "DarkSeaGreen", 0, 0 );
setFixedSizeAt( 0, QSize( 100, 100 ) );
setFixedSizeAt( 1, QSize( 50, 50 ) );
2019-07-29 17:34:46 +02:00
setAlignmentAt( 0, Qt::AlignCenter );
setAlignmentAt( 1, Qt::AlignCenter );
2019-07-25 18:39:50 +02:00
}
2019-07-29 17:34:46 +02:00
void Box::test6()
2019-07-25 18:39:50 +02:00
{
/*
QGridLayoutEngine ignores the first column coming from
the multicell element at the bottom
*/
insert( "DarkSeaGreen", 1, 1 );
insert( "Coral", 2, 2 );
insert( "NavajoWhite", 3, 0, 1, 3 );
2019-07-28 17:07:29 +02:00
//setSpacing( 0 );
2019-07-25 18:39:50 +02:00
}
2019-07-29 17:34:46 +02:00
void Box::test7()
2019-07-25 18:39:50 +02:00
{
/*
This test is very similar to test6, but here we can see a
difference between Quick and Graphic. The hidden element has
an effect on the layout for Graphic, what is actually wrong, when
setRetainSizeWhenHidden is not set. The preferred width also
includes a wrong contribution from the hidden element.
*/
insert( "PaleVioletRed", 0, 0 );
insert( "DarkSeaGreen", 1, 1 );
insert( "Coral", 2, 2 );
insert( "NavajoWhite", 3, 0, 1, 3 );
2019-07-27 12:37:48 +02:00
2019-07-25 18:39:50 +02:00
setVisibleAt( 0, false );
//setRetainSizeWhenHiddenAt( 0, true );
2019-07-27 12:37:48 +02:00
}
2019-07-25 18:39:50 +02:00
2019-07-29 17:34:46 +02:00
void Box::test8()
2019-07-25 18:39:50 +02:00
{
/*
This test creates a situation, where we have more space than
2019-07-27 12:37:48 +02:00
the minimum, but not enough for preferred. For this situation
2019-07-25 18:39:50 +02:00
all layout engines use a different algorithm how to distribute
the extra space. All of them are based on the difference between
preferred and minimum.
- Skinny simply uses the ratio of the differences
- Widgets seems to do something that works exponatially
( need to check the code ).
- Graphic/Quick ( QGridLayoutEngine ) levels the impact
2019-07-27 12:37:48 +02:00
of the differences down.
2019-07-25 18:39:50 +02:00
Hard to say what a user expects to happen.
*/
insert( "PaleVioletRed", 0, 0 );
insert( "DarkSeaGreen", 1, 1 );
for ( int i = 0; i < 2; i++ )
{
setMinimumSizeAt( i, QSize( 20, 20 ) );
setPreferredSizeAt( i, ( i + 1 ) * QSize( 2000, 2000 ) );
}
}
2019-07-29 17:34:46 +02:00
void Box::test9()
2019-07-27 12:37:48 +02:00
{
/*
This one is a bit unclear about how much space from the first
element goes to column 1/2. Skinny gives 50% to both,
while QGridLayoutEngine gives 100% to column 1 ( starting
at 0 + spacing() ). The Widgets implementation seems to be
wrong as column 1 grows beyond 100%.
The situation can be clarified by using setColumnFixedWidth -
unfortunately Quick does not support this.
*/
insert( "PaleVioletRed", 0, 0, 1, 2 );
insert( "DarkSeaGreen", 1, 1 );
setFixedWidthAt( 0, 100 );
//setColumnFixedWidth( 0, 50 );
}
2019-07-29 17:34:46 +02:00
void Box::test10()
{
/*
Widgets gives space to the bounded columns 1/2 instead
of 0/3, where they would be more useful.
*/
insert( "PaleVioletRed", 0, 0 );
insert( "NavajoWhite", 0, 1, 1, 2 );
insert( "Coral", 0, 3 );
setMaximumWidthAt( 1, 70 );
}
void Box::test11()
{
/*
Here we have an expandble element, that is limited by
its maximum size and another element, that can grow only.
The expected behavior is, that if the expandable elements
do not accept the complete available space the rest goes to
the elements, that can grow only.
- Graphic/Skinny do not handle the grow flag once there is
an element with the expand flag
*/
// Quick layouts do not support GrowFlag vs. ExpandFlag
enableGrid( Quick, false );
insert( "PaleVioletRed", 0, 0 );
insert( "NavajoWhite", 1, 0 );
setSizePolicyAt( 0, Qt::Vertical, QskSizePolicy::Preferred );
setPreferredHeightAt( 0, 50 );
setSizePolicyAt( 1, Qt::Vertical, QskSizePolicy::Expanding );
setMaximumHeightAt( 1, 50 );
}
void Box::test12()
{
2020-12-05 15:09:31 +01:00
/*
We have different strategies where to put the spaces, when
there is more space than the elements are willing to accept.
QSkinny has the extraSpacingAt parameter to control this.
*/
insert( "PaleVioletRed", 0, 0 );
insert( "NavajoWhite", 1, 0 );
insert( "Coral", 2, 0 );
for ( int i = 0; i < 3; i++ )
setFixedHeightAt( i, 50 );
}
2019-07-29 17:34:46 +02:00
class MainWidget : public QWidget
{
public:
MainWidget( int id )
{
m_box = new Box( this );
m_box->showTest( id );
m_listBox = new QListWidget( this );
for ( int i = 0; i < m_box->count(); i++ )
m_listBox->addItem( QStringLiteral( "Test " ) + QString::number( i ) );
m_listBox->setCurrentRow( id );
connect( m_listBox, &QListWidget::currentRowChanged,
m_box, &Box::showTest );
}
protected:
void resizeEvent( QResizeEvent* ) override
{
/*
Not using layouts here to avoid confusion
while debugging.
2020-12-05 15:09:31 +01:00
*/
2019-07-29 17:34:46 +02:00
const auto r = contentsRect();
const int spacing = 5;
2020-03-13 13:32:22 +01:00
const int w1 = qskHorizontalAdvance( m_listBox->font(), "Test 100" ) + 20;
2019-07-29 17:34:46 +02:00
const int w2 = r.width() - w1 - spacing;
m_listBox->setGeometry( r.left(), r.top(), w1, r.height() );
m_box->setGeometry( r.right() - w2, r.top(), w2, r.height() );
m_listBox->setFocus();
}
private:
QListWidget* m_listBox;
Box* m_box;
};
int main( int argc, char** argv )
{
2021-12-17 14:44:31 +01:00
QApplication app( argc, argv );
2019-07-25 18:39:50 +02:00
int testcase = 0;
if ( argc == 2 )
testcase = atoi( argv[1] );
2019-07-29 17:34:46 +02:00
MainWidget w( testcase );
2019-07-23 18:35:51 +02:00
2019-07-29 17:34:46 +02:00
w.resize( 600, 600 );
w.show();
2021-12-17 14:44:31 +01:00
return app.exec();
}