Skip to content
GitLab
Projects
Groups
Snippets
/
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
Open sidebar
System
Dolphin
Commits
b81d3fbb
Commit
b81d3fbb
authored
Dec 27, 2021
by
Jan Blackquill
🌈
Committed by
Jan Blackquill
Jan 19, 2022
Browse files
KItemListViewLayouter: handle grid view layouts in RtL properly
parent
f8f97f05
Pipeline
#125997
passed with stage
in 3 minutes and 49 seconds
Changes
1
Pipelines
3
Hide whitespace changes
Inline
Side-by-side
src/kitemviews/private/kitemlistviewlayouter.cpp
View file @
b81d3fbb
...
...
@@ -9,6 +9,9 @@
#include
"kitemlistsizehintresolver.h"
#include
"kitemviews/kitemmodelbase.h"
#include
<QGuiApplication>
#include
<QScopeGuard>
// #define KITEMLISTVIEWLAYOUTER_DEBUG
KItemListViewLayouter
::
KItemListViewLayouter
(
KItemListSizeHintResolver
*
sizeHintResolver
,
QObject
*
parent
)
:
...
...
@@ -343,170 +346,177 @@ void KItemListViewLayouter::markAsDirty()
void
KItemListViewLayouter
::
doLayout
()
{
if
(
m_dirty
)
{
// we always want to update visible indexes after performing a layout
auto
qsg
=
qScopeGuard
([
this
]
{
updateVisibleIndexes
();
});
if
(
!
m_dirty
)
{
return
;
}
#ifdef KITEMLISTVIEWLAYOUTER_DEBUG
QElapsedTimer
timer
;
timer
.
start
();
QElapsedTimer
timer
;
timer
.
start
();
#endif
m_visibleIndexesDirty
=
true
;
QSizeF
itemSize
=
m_itemSize
;
QSizeF
itemMargin
=
m_itemMargin
;
QSizeF
size
=
m_size
;
const
bool
grouped
=
createGroupHeaders
();
const
bool
horizontalScrolling
=
(
m_scrollOrientation
==
Qt
::
Horizontal
);
if
(
horizontalScrolling
)
{
// Flip everything so that the layout logically can work like having
// a vertical scrolling
itemSize
.
transpose
();
itemMargin
.
transpose
();
size
.
transpose
();
if
(
grouped
)
{
// In the horizontal scrolling case all groups are aligned
// at the top, which decreases the available height. For the
// flipped data this means that the width must be decreased.
size
.
rwidth
()
-=
m_groupHeaderHeight
;
}
m_visibleIndexesDirty
=
true
;
QSizeF
itemSize
=
m_itemSize
;
QSizeF
itemMargin
=
m_itemMargin
;
QSizeF
size
=
m_size
;
const
bool
grouped
=
createGroupHeaders
();
const
bool
horizontalScrolling
=
(
m_scrollOrientation
==
Qt
::
Horizontal
);
if
(
horizontalScrolling
)
{
// Flip everything so that the layout logically can work like having
// a vertical scrolling
itemSize
.
transpose
();
itemMargin
.
transpose
();
size
.
transpose
();
if
(
grouped
)
{
// In the horizontal scrolling case all groups are aligned
// at the top, which decreases the available height. For the
// flipped data this means that the width must be decreased.
size
.
rwidth
()
-=
m_groupHeaderHeight
;
}
}
m_columnWidth
=
itemSize
.
width
()
+
itemMargin
.
width
();
const
qreal
widthForColumns
=
size
.
width
()
-
itemMargin
.
width
();
m_columnCount
=
qMax
(
1
,
int
(
widthForColumns
/
m_columnWidth
));
m_xPosInc
=
itemMargin
.
width
();
const
int
itemCount
=
m_model
->
count
();
if
(
itemCount
>
m_columnCount
&&
m_columnWidth
>=
32
)
{
// Apply the unused width equally to each column
const
qreal
unusedWidth
=
widthForColumns
-
m_columnCount
*
m_columnWidth
;
if
(
unusedWidth
>
0
)
{
const
qreal
columnInc
=
unusedWidth
/
(
m_columnCount
+
1
);
m_columnWidth
+=
columnInc
;
m_xPosInc
+=
columnInc
;
}
m_columnWidth
=
itemSize
.
width
()
+
itemMargin
.
width
();
const
qreal
widthForColumns
=
size
.
width
()
-
itemMargin
.
width
();
m_columnCount
=
qMax
(
1
,
int
(
widthForColumns
/
m_columnWidth
));
m_xPosInc
=
itemMargin
.
width
();
const
int
itemCount
=
m_model
->
count
();
if
(
itemCount
>
m_columnCount
&&
m_columnWidth
>=
32
)
{
// Apply the unused width equally to each column
const
qreal
unusedWidth
=
widthForColumns
-
m_columnCount
*
m_columnWidth
;
if
(
unusedWidth
>
0
)
{
const
qreal
columnInc
=
unusedWidth
/
(
m_columnCount
+
1
);
m_columnWidth
+=
columnInc
;
m_xPosInc
+=
columnInc
;
}
}
m_itemInfos
.
resize
(
itemCount
);
m_itemInfos
.
resize
(
itemCount
);
// Calculate the offset of each column, i.e., the x-coordinate where the column starts.
m_columnOffsets
.
resize
(
m_columnCount
);
qreal
currentOffset
=
m_xPosInc
;
// Calculate the offset of each column, i.e., the x-coordinate where the column starts.
m_columnOffsets
.
resize
(
m_columnCount
);
qreal
currentOffset
=
QGuiApplication
::
isRightToLeft
()
?
widthForColumns
:
m_xPosInc
;
if
(
grouped
&&
horizontalScrolling
)
{
// All group headers will always be aligned on the top and not
// flipped like the other properties.
currentOffset
+=
m_groupHeaderHeight
;
}
if
(
grouped
&&
horizontalScrolling
)
{
// All group headers will always be aligned on the top and not
// flipped like the other properties.
currentOffset
+=
m_groupHeaderHeight
;
}
for
(
int
column
=
0
;
column
<
m_columnCount
;
++
column
)
{
m_columnOffsets
[
column
]
=
currentOffset
;
currentOffset
+=
m_columnWidth
;
}
if
(
QGuiApplication
::
isLeftToRight
())
for
(
int
column
=
0
;
column
<
m_columnCount
;
++
column
)
{
m_columnOffsets
[
column
]
=
currentOffset
;
currentOffset
+=
m_columnWidth
;
}
else
for
(
int
column
=
0
;
column
<
m_columnCount
;
++
column
)
{
m_columnOffsets
[
column
]
=
currentOffset
-
m_columnWidth
;
currentOffset
-=
m_columnWidth
;
}
// Prepare the QVector which stores the y-coordinate for each new row.
int
numberOfRows
=
(
itemCount
+
m_columnCount
-
1
)
/
m_columnCount
;
if
(
grouped
&&
m_columnCount
>
1
)
{
// In the worst case, a new row will be started for every group.
// We could calculate the exact number of rows now to prevent that we reserve
// too much memory, but the code required to do that might need much more
// memory than it would save in the average case.
numberOfRows
+=
m_groupItemIndexes
.
count
();
}
m_rowOffsets
.
resize
(
numberOfRows
);
qreal
y
=
m_headerHeight
+
itemMargin
.
height
();
int
row
=
0
;
int
index
=
0
;
while
(
index
<
itemCount
)
{
qreal
maxItemHeight
=
itemSize
.
height
();
if
(
grouped
)
{
if
(
m_groupItemIndexes
.
contains
(
index
))
{
// The item is the first item of a group.
// Increase the y-position to provide space
// for the group header.
if
(
index
>
0
)
{
// Only add a margin if there has been added another
// group already before
y
+=
m_groupHeaderMargin
;
}
else
if
(
!
horizontalScrolling
)
{
// The first group header should be aligned on top
y
-=
itemMargin
.
height
();
}
if
(
!
horizontalScrolling
)
{
y
+=
m_groupHeaderHeight
;
}
// Prepare the QVector which stores the y-coordinate for each new row.
int
numberOfRows
=
(
itemCount
+
m_columnCount
-
1
)
/
m_columnCount
;
if
(
grouped
&&
m_columnCount
>
1
)
{
// In the worst case, a new row will be started for every group.
// We could calculate the exact number of rows now to prevent that we reserve
// too much memory, but the code required to do that might need much more
// memory than it would save in the average case.
numberOfRows
+=
m_groupItemIndexes
.
count
();
}
m_rowOffsets
.
resize
(
numberOfRows
);
qreal
y
=
m_headerHeight
+
itemMargin
.
height
();
int
row
=
0
;
int
index
=
0
;
while
(
index
<
itemCount
)
{
qreal
maxItemHeight
=
itemSize
.
height
();
if
(
grouped
)
{
if
(
m_groupItemIndexes
.
contains
(
index
))
{
// The item is the first item of a group.
// Increase the y-position to provide space
// for the group header.
if
(
index
>
0
)
{
// Only add a margin if there has been added another
// group already before
y
+=
m_groupHeaderMargin
;
}
else
if
(
!
horizontalScrolling
)
{
// The first group header should be aligned on top
y
-=
itemMargin
.
height
();
}
}
m_rowOffsets
[
row
]
=
y
;
int
column
=
0
;
while
(
index
<
itemCount
&&
column
<
m_columnCount
)
{
qreal
requiredItemHeight
=
itemSize
.
height
();
const
QSizeF
sizeHint
=
m_sizeHintResolver
->
sizeHint
(
index
);
const
qreal
sizeHintHeight
=
sizeHint
.
height
();
if
(
sizeHintHeight
>
requiredItemHeight
)
{
requiredItemHeight
=
sizeHintHeight
;
if
(
!
horizontalScrolling
)
{
y
+=
m_groupHeaderHeight
;
}
}
}
ItemInfo
&
itemInfo
=
m_itemInfos
[
index
];
itemInfo
.
column
=
column
;
itemInfo
.
row
=
row
;
if
(
grouped
&&
horizontalScrolling
)
{
// When grouping is enabled in the horizontal mode, the header alignment
// looks like this:
// Header-1 Header-2 Header-3
// Item 1 Item 4 Item 7
// Item 2 Item 5 Item 8
// Item 3 Item 6 Item 9
// In this case 'requiredItemHeight' represents the column-width. We don't
// check the content of the header in the layouter to determine the required
// width, hence assure that at least a minimal width of 15 characters is given
// (in average a character requires the halve width of the font height).
//
// TODO: Let the group headers provide a minimum width and respect this width here
const
qreal
headerWidth
=
minimumGroupHeaderWidth
();
if
(
requiredItemHeight
<
headerWidth
)
{
requiredItemHeight
=
headerWidth
;
}
}
m_rowOffsets
[
row
]
=
y
;
maxItemHeight
=
qMax
(
maxItemHeight
,
requiredItemHeight
);
++
index
;
++
column
;
int
column
=
0
;
while
(
index
<
itemCount
&&
column
<
m_columnCount
)
{
qreal
requiredItemHeight
=
itemSize
.
height
();
const
QSizeF
sizeHint
=
m_sizeHintResolver
->
sizeHint
(
index
);
const
qreal
sizeHintHeight
=
sizeHint
.
height
();
if
(
sizeHintHeight
>
requiredItemHeight
)
{
requiredItemHeight
=
sizeHintHeight
;
}
if
(
grouped
&&
m_groupItemIndexes
.
contains
(
index
))
{
// The item represents the first index of a group
// and must aligned in the first column
break
;
ItemInfo
&
itemInfo
=
m_itemInfos
[
index
];
itemInfo
.
column
=
column
;
itemInfo
.
row
=
row
;
if
(
grouped
&&
horizontalScrolling
)
{
// When grouping is enabled in the horizontal mode, the header alignment
// looks like this:
// Header-1 Header-2 Header-3
// Item 1 Item 4 Item 7
// Item 2 Item 5 Item 8
// Item 3 Item 6 Item 9
// In this case 'requiredItemHeight' represents the column-width. We don't
// check the content of the header in the layouter to determine the required
// width, hence assure that at least a minimal width of 15 characters is given
// (in average a character requires the halve width of the font height).
//
// TODO: Let the group headers provide a minimum width and respect this width here
const
qreal
headerWidth
=
minimumGroupHeaderWidth
();
if
(
requiredItemHeight
<
headerWidth
)
{
requiredItemHeight
=
headerWidth
;
}
}
y
+=
maxItemHeight
+
itemMargin
.
h
eight
(
);
++
row
;
}
maxItemHeight
=
qMax
(
maxItemHeight
,
requiredItemH
eight
);
++
index
;
++
column
;
if
(
itemCount
>
0
)
{
m_maximumScrollOffset
=
y
;
m_maximumItemOffset
=
m_columnCount
*
m_columnWidth
;
}
else
{
m_maximumScrollOffset
=
0
;
m_maximumItemOffset
=
0
;
if
(
grouped
&&
m_groupItemIndexes
.
contains
(
index
))
{
// The item represents the first index of a group
// and must aligned in the first column
break
;
}
}
#ifdef KITEMLISTVIEWLAYOUTER_DEBUG
qCDebug
(
DolphinDebug
)
<<
"[TIME] doLayout() for "
<<
m_model
->
count
()
<<
"items:"
<<
timer
.
elapsed
();
#endif
m_dirty
=
false
;
y
+=
maxItemHeight
+
itemMargin
.
height
();
++
row
;
}
updateVisibleIndexes
();
if
(
itemCount
>
0
)
{
m_maximumScrollOffset
=
y
;
m_maximumItemOffset
=
m_columnCount
*
m_columnWidth
;
}
else
{
m_maximumScrollOffset
=
0
;
m_maximumItemOffset
=
0
;
}
#ifdef KITEMLISTVIEWLAYOUTER_DEBUG
qCDebug
(
DolphinDebug
)
<<
"[TIME] doLayout() for "
<<
m_model
->
count
()
<<
"items:"
<<
timer
.
elapsed
();
#endif
m_dirty
=
false
;
}
void
KItemListViewLayouter
::
updateVisibleIndexes
()
...
...
Write
Preview
Supports
Markdown
0%
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment