mirror of
https://invent.kde.org/system/dolphin
synced 2024-10-03 23:29:06 +00:00
Better support for RTL
This MR fixes some issues related to RTL scripts: - wrong layout in Compact View mode - broken horizontal scrolling in Icon View and Details View modes - broken navigation with left and right arrow keys in Details View mode BUG: 484012 BUG: 449493
This commit is contained in:
parent
7a7cab61b6
commit
240d33ce17
|
@ -399,6 +399,11 @@ void KItemListContainer::updateSmoothScrollers(Qt::Orientation orientation)
|
||||||
m_horizontalSmoothScroller->setPropertyName("scrollOffset");
|
m_horizontalSmoothScroller->setPropertyName("scrollOffset");
|
||||||
m_verticalSmoothScroller->setPropertyName("itemOffset");
|
m_verticalSmoothScroller->setPropertyName("itemOffset");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const bool isRightToLeft = m_controller->view()->layoutDirection() == Qt::RightToLeft;
|
||||||
|
QScrollBar *hScrollBar = horizontalScrollBar();
|
||||||
|
hScrollBar->setInvertedAppearance(isRightToLeft && orientation == Qt::Vertical);
|
||||||
|
hScrollBar->setInvertedControls(!isRightToLeft || orientation == Qt::Vertical);
|
||||||
}
|
}
|
||||||
|
|
||||||
void KItemListContainer::updateScrollOffsetScrollBarPolicy()
|
void KItemListContainer::updateScrollOffsetScrollBarPolicy()
|
||||||
|
|
|
@ -241,6 +241,8 @@ bool KItemListController::keyPressEvent(QKeyEvent *event)
|
||||||
int key = event->key();
|
int key = event->key();
|
||||||
const bool shiftPressed = event->modifiers() & Qt::ShiftModifier;
|
const bool shiftPressed = event->modifiers() & Qt::ShiftModifier;
|
||||||
|
|
||||||
|
const bool horizontalScrolling = m_view->scrollOrientation() == Qt::Horizontal;
|
||||||
|
|
||||||
// Handle the expanding/collapsing of items
|
// Handle the expanding/collapsing of items
|
||||||
// expand / collapse all selected directories
|
// expand / collapse all selected directories
|
||||||
if (m_view->supportsItemExpanding() && m_model->isExpandable(index) && (key == Qt::Key_Right || key == Qt::Key_Left)) {
|
if (m_view->supportsItemExpanding() && m_model->isExpandable(index) && (key == Qt::Key_Right || key == Qt::Key_Left)) {
|
||||||
|
@ -276,7 +278,7 @@ bool KItemListController::keyPressEvent(QKeyEvent *event)
|
||||||
|
|
||||||
// For horizontal scroll orientation, transform
|
// For horizontal scroll orientation, transform
|
||||||
// the arrow keys to simplify the event handling.
|
// the arrow keys to simplify the event handling.
|
||||||
if (m_view->scrollOrientation() == Qt::Horizontal) {
|
if (horizontalScrolling) {
|
||||||
switch (key) {
|
switch (key) {
|
||||||
case Qt::Key_Up:
|
case Qt::Key_Up:
|
||||||
key = Qt::Key_Left;
|
key = Qt::Key_Left;
|
||||||
|
@ -295,17 +297,31 @@ bool KItemListController::keyPressEvent(QKeyEvent *event)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// For right to left languages, exchange right and left arrow keys.
|
|
||||||
if (m_view->layoutDirection() == Qt::RightToLeft) {
|
if (m_view->layoutDirection() == Qt::RightToLeft) {
|
||||||
switch (key) {
|
if (horizontalScrolling) {
|
||||||
case Qt::Key_Left:
|
// swap up and down arrow keys
|
||||||
key = Qt::Key_Right;
|
switch (key) {
|
||||||
break;
|
case Qt::Key_Up:
|
||||||
case Qt::Key_Right:
|
key = Qt::Key_Down;
|
||||||
key = Qt::Key_Left;
|
break;
|
||||||
break;
|
case Qt::Key_Down:
|
||||||
default:
|
key = Qt::Key_Up;
|
||||||
break;
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} else if (!m_view->supportsItemExpanding()) {
|
||||||
|
// swap left and right arrow keys
|
||||||
|
switch (key) {
|
||||||
|
case Qt::Key_Left:
|
||||||
|
key = Qt::Key_Right;
|
||||||
|
break;
|
||||||
|
case Qt::Key_Right:
|
||||||
|
key = Qt::Key_Left;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -371,7 +387,7 @@ bool KItemListController::keyPressEvent(QKeyEvent *event)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case Qt::Key_PageUp:
|
case Qt::Key_PageUp:
|
||||||
if (m_view->scrollOrientation() == Qt::Horizontal) {
|
if (horizontalScrolling) {
|
||||||
// The new current index should correspond to the first item in the current column.
|
// The new current index should correspond to the first item in the current column.
|
||||||
int newIndex = qMax(index - 1, 0);
|
int newIndex = qMax(index - 1, 0);
|
||||||
while (newIndex != index && m_view->itemRect(newIndex).topLeft().y() < m_view->itemRect(index).topLeft().y()) {
|
while (newIndex != index && m_view->itemRect(newIndex).topLeft().y() < m_view->itemRect(index).topLeft().y()) {
|
||||||
|
@ -399,7 +415,7 @@ bool KItemListController::keyPressEvent(QKeyEvent *event)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case Qt::Key_PageDown:
|
case Qt::Key_PageDown:
|
||||||
if (m_view->scrollOrientation() == Qt::Horizontal) {
|
if (horizontalScrolling) {
|
||||||
// The new current index should correspond to the last item in the current column.
|
// The new current index should correspond to the last item in the current column.
|
||||||
int newIndex = qMin(index + 1, m_model->count() - 1);
|
int newIndex = qMin(index + 1, m_model->count() - 1);
|
||||||
while (newIndex != index && m_view->itemRect(newIndex).topLeft().y() > m_view->itemRect(index).topLeft().y()) {
|
while (newIndex != index && m_view->itemRect(newIndex).topLeft().y() > m_view->itemRect(index).topLeft().y()) {
|
||||||
|
@ -1486,12 +1502,12 @@ int KItemListController::nextRowIndex(int index) const
|
||||||
return index;
|
return index;
|
||||||
}
|
}
|
||||||
|
|
||||||
const bool leftToRight = m_view->layoutDirection() != Qt::RightToLeft;
|
const bool reversed = m_view->layoutDirection() == Qt::RightToLeft && m_view->scrollOrientation() == Qt::Vertical;
|
||||||
|
|
||||||
// Calculate the index of the last column inside the row of the current index
|
// Calculate the index of the last column inside the row of the current index
|
||||||
int lastColumnIndex = index;
|
int lastColumnIndex = index;
|
||||||
while ((leftToRight && keyboardAnchorPos(lastColumnIndex + 1) > keyboardAnchorPos(lastColumnIndex))
|
while ((!reversed && keyboardAnchorPos(lastColumnIndex + 1) > keyboardAnchorPos(lastColumnIndex))
|
||||||
|| (!leftToRight && keyboardAnchorPos(lastColumnIndex + 1) < keyboardAnchorPos(lastColumnIndex))) {
|
|| (reversed && keyboardAnchorPos(lastColumnIndex + 1) < keyboardAnchorPos(lastColumnIndex))) {
|
||||||
++lastColumnIndex;
|
++lastColumnIndex;
|
||||||
if (lastColumnIndex >= maxIndex) {
|
if (lastColumnIndex >= maxIndex) {
|
||||||
return index;
|
return index;
|
||||||
|
@ -1504,8 +1520,8 @@ int KItemListController::nextRowIndex(int index) const
|
||||||
int searchIndex = nextRowIndex;
|
int searchIndex = nextRowIndex;
|
||||||
qreal minDiff = qAbs(m_keyboardAnchorPos - keyboardAnchorPos(nextRowIndex));
|
qreal minDiff = qAbs(m_keyboardAnchorPos - keyboardAnchorPos(nextRowIndex));
|
||||||
while (searchIndex < maxIndex
|
while (searchIndex < maxIndex
|
||||||
&& ((leftToRight && keyboardAnchorPos(searchIndex + 1) > keyboardAnchorPos(searchIndex))
|
&& ((!reversed && keyboardAnchorPos(searchIndex + 1) > keyboardAnchorPos(searchIndex))
|
||||||
|| (!leftToRight && keyboardAnchorPos(searchIndex + 1) < keyboardAnchorPos(searchIndex)))) {
|
|| (reversed && keyboardAnchorPos(searchIndex + 1) < keyboardAnchorPos(searchIndex)))) {
|
||||||
++searchIndex;
|
++searchIndex;
|
||||||
const qreal searchDiff = qAbs(m_keyboardAnchorPos - keyboardAnchorPos(searchIndex));
|
const qreal searchDiff = qAbs(m_keyboardAnchorPos - keyboardAnchorPos(searchIndex));
|
||||||
if (searchDiff < minDiff) {
|
if (searchDiff < minDiff) {
|
||||||
|
@ -1523,12 +1539,12 @@ int KItemListController::previousRowIndex(int index) const
|
||||||
return index;
|
return index;
|
||||||
}
|
}
|
||||||
|
|
||||||
const bool leftToRight = m_view->layoutDirection() != Qt::RightToLeft;
|
const bool reversed = m_view->layoutDirection() == Qt::RightToLeft && m_view->scrollOrientation() == Qt::Vertical;
|
||||||
|
|
||||||
// Calculate the index of the first column inside the row of the current index
|
// Calculate the index of the first column inside the row of the current index
|
||||||
int firstColumnIndex = index;
|
int firstColumnIndex = index;
|
||||||
while ((leftToRight && keyboardAnchorPos(firstColumnIndex - 1) < keyboardAnchorPos(firstColumnIndex))
|
while ((!reversed && keyboardAnchorPos(firstColumnIndex - 1) < keyboardAnchorPos(firstColumnIndex))
|
||||||
|| (!leftToRight && keyboardAnchorPos(firstColumnIndex - 1) > keyboardAnchorPos(firstColumnIndex))) {
|
|| (reversed && keyboardAnchorPos(firstColumnIndex - 1) > keyboardAnchorPos(firstColumnIndex))) {
|
||||||
--firstColumnIndex;
|
--firstColumnIndex;
|
||||||
if (firstColumnIndex <= 0) {
|
if (firstColumnIndex <= 0) {
|
||||||
return index;
|
return index;
|
||||||
|
@ -1541,8 +1557,8 @@ int KItemListController::previousRowIndex(int index) const
|
||||||
int searchIndex = previousRowIndex;
|
int searchIndex = previousRowIndex;
|
||||||
qreal minDiff = qAbs(m_keyboardAnchorPos - keyboardAnchorPos(previousRowIndex));
|
qreal minDiff = qAbs(m_keyboardAnchorPos - keyboardAnchorPos(previousRowIndex));
|
||||||
while (searchIndex > 0
|
while (searchIndex > 0
|
||||||
&& ((leftToRight && keyboardAnchorPos(searchIndex - 1) < keyboardAnchorPos(searchIndex))
|
&& ((!reversed && keyboardAnchorPos(searchIndex - 1) < keyboardAnchorPos(searchIndex))
|
||||||
|| (!leftToRight && keyboardAnchorPos(searchIndex - 1) > keyboardAnchorPos(searchIndex)))) {
|
|| (reversed && keyboardAnchorPos(searchIndex - 1) > keyboardAnchorPos(searchIndex)))) {
|
||||||
--searchIndex;
|
--searchIndex;
|
||||||
const qreal searchDiff = qAbs(m_keyboardAnchorPos - keyboardAnchorPos(searchIndex));
|
const qreal searchDiff = qAbs(m_keyboardAnchorPos - keyboardAnchorPos(searchIndex));
|
||||||
if (searchDiff < minDiff) {
|
if (searchDiff < minDiff) {
|
||||||
|
|
|
@ -550,6 +550,10 @@ void KItemListView::scrollToItem(int index, ViewItemPosition viewItemPosition)
|
||||||
}
|
}
|
||||||
QRectF currentRect = itemRect(index);
|
QRectF currentRect = itemRect(index);
|
||||||
|
|
||||||
|
if (layoutDirection() == Qt::RightToLeft && scrollOrientation() == Qt::Horizontal) {
|
||||||
|
currentRect.moveTo(m_layouter->size().width() - currentRect.right(), 0);
|
||||||
|
}
|
||||||
|
|
||||||
// Fix for Bug 311099 - View the underscore when using Ctrl + PageDown
|
// Fix for Bug 311099 - View the underscore when using Ctrl + PageDown
|
||||||
currentRect.adjust(-m_styleOption.horizontalMargin, -m_styleOption.verticalMargin, m_styleOption.horizontalMargin, m_styleOption.verticalMargin);
|
currentRect.adjust(-m_styleOption.horizontalMargin, -m_styleOption.verticalMargin, m_styleOption.horizontalMargin, m_styleOption.verticalMargin);
|
||||||
|
|
||||||
|
|
|
@ -1132,7 +1132,11 @@ void KStandardItemListWidget::updatePixmapCache()
|
||||||
} else {
|
} else {
|
||||||
// Center horizontally and vertically within the icon-area
|
// Center horizontally and vertically within the icon-area
|
||||||
const TextInfo *textInfo = m_textInfo.value("text");
|
const TextInfo *textInfo = m_textInfo.value("text");
|
||||||
m_pixmapPos.setX(textInfo->pos.x() - 2.0 * padding - (scaledIconSize + m_scaledPixmapSize.width()) / 2.0);
|
if (QApplication::isRightToLeft() && m_layout == CompactLayout) {
|
||||||
|
m_pixmapPos.setX(size().width() - padding - (scaledIconSize + m_scaledPixmapSize.width()) / 2.0);
|
||||||
|
} else {
|
||||||
|
m_pixmapPos.setX(textInfo->pos.x() - 2.0 * padding - (scaledIconSize + m_scaledPixmapSize.width()) / 2.0);
|
||||||
|
}
|
||||||
|
|
||||||
// Derive icon's vertical center from the center of the text frame, including
|
// Derive icon's vertical center from the center of the text frame, including
|
||||||
// any necessary adjustment if the font's midline is offset from the frame center
|
// any necessary adjustment if the font's midline is offset from the frame center
|
||||||
|
@ -1175,6 +1179,9 @@ void KStandardItemListWidget::updateTextsCache()
|
||||||
textOption.setAlignment(Qt::AlignHCenter);
|
textOption.setAlignment(Qt::AlignHCenter);
|
||||||
break;
|
break;
|
||||||
case CompactLayout:
|
case CompactLayout:
|
||||||
|
textOption.setAlignment(QApplication::isRightToLeft() ? Qt::AlignRight : Qt::AlignLeft);
|
||||||
|
textOption.setWrapMode(QTextOption::NoWrap);
|
||||||
|
break;
|
||||||
case DetailsLayout:
|
case DetailsLayout:
|
||||||
textOption.setAlignment(Qt::AlignLeft);
|
textOption.setAlignment(Qt::AlignLeft);
|
||||||
textOption.setWrapMode(QTextOption::NoWrap);
|
textOption.setWrapMode(QTextOption::NoWrap);
|
||||||
|
@ -1404,9 +1411,9 @@ void KStandardItemListWidget::updateCompactLayoutTextCache()
|
||||||
const qreal textLinesHeight = qMax(visibleRoles().count(), 1) * lineSpacing;
|
const qreal textLinesHeight = qMax(visibleRoles().count(), 1) * lineSpacing;
|
||||||
|
|
||||||
qreal maximumRequiredTextWidth = 0;
|
qreal maximumRequiredTextWidth = 0;
|
||||||
const qreal x = option.padding * 3 + iconSize();
|
const qreal x = QApplication::isRightToLeft() ? option.padding : option.padding * 3 + iconSize();
|
||||||
qreal y = qRound((widgetHeight - textLinesHeight) / 2);
|
qreal y = qRound((widgetHeight - textLinesHeight) / 2);
|
||||||
const qreal maxWidth = size().width() - x - option.padding;
|
const qreal maxWidth = size().width() - iconSize() - 4 * option.padding;
|
||||||
for (const QByteArray &role : std::as_const(m_sortedVisibleRoles)) {
|
for (const QByteArray &role : std::as_const(m_sortedVisibleRoles)) {
|
||||||
const QString text = escapeString(roleText(role, values));
|
const QString text = escapeString(roleText(role, values));
|
||||||
TextInfo *textInfo = m_textInfo.value(role);
|
TextInfo *textInfo = m_textInfo.value(role);
|
||||||
|
|
|
@ -226,8 +226,12 @@ QRectF KItemListViewLayouter::itemRect(int index) const
|
||||||
// Rotate the logical direction which is always vertical by 90°
|
// Rotate the logical direction which is always vertical by 90°
|
||||||
// to get the physical horizontal direction
|
// to get the physical horizontal direction
|
||||||
QPointF pos(y, x);
|
QPointF pos(y, x);
|
||||||
pos.rx() -= m_scrollOffset;
|
|
||||||
sizeHint.transpose();
|
sizeHint.transpose();
|
||||||
|
if (QGuiApplication::isRightToLeft()) {
|
||||||
|
pos.rx() = m_size.width() + m_scrollOffset - pos.x() - sizeHint.width();
|
||||||
|
} else {
|
||||||
|
pos.rx() -= m_scrollOffset;
|
||||||
|
}
|
||||||
return QRectF(pos, sizeHint);
|
return QRectF(pos, sizeHint);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -361,7 +365,7 @@ void KItemListViewLayouter::doLayout()
|
||||||
|
|
||||||
const bool grouped = createGroupHeaders();
|
const bool grouped = createGroupHeaders();
|
||||||
|
|
||||||
const bool horizontalScrolling = (m_scrollOrientation == Qt::Horizontal);
|
const bool horizontalScrolling = m_scrollOrientation == Qt::Horizontal;
|
||||||
if (horizontalScrolling) {
|
if (horizontalScrolling) {
|
||||||
// Flip everything so that the layout logically can work like having
|
// Flip everything so that the layout logically can work like having
|
||||||
// a vertical scrolling
|
// a vertical scrolling
|
||||||
|
@ -377,8 +381,9 @@ void KItemListViewLayouter::doLayout()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const bool isRightToLeft = QGuiApplication::isRightToLeft();
|
||||||
m_columnWidth = itemSize.width() + itemMargin.width();
|
m_columnWidth = itemSize.width() + itemMargin.width();
|
||||||
const qreal widthForColumns = size.width() - itemMargin.width();
|
const qreal widthForColumns = std::max(size.width() - itemMargin.width(), m_columnWidth);
|
||||||
m_columnCount = qMax(1, int(widthForColumns / m_columnWidth));
|
m_columnCount = qMax(1, int(widthForColumns / m_columnWidth));
|
||||||
m_xPosInc = itemMargin.width();
|
m_xPosInc = itemMargin.width();
|
||||||
|
|
||||||
|
@ -397,7 +402,7 @@ void KItemListViewLayouter::doLayout()
|
||||||
|
|
||||||
// Calculate the offset of each column, i.e., the x-coordinate where the column starts.
|
// Calculate the offset of each column, i.e., the x-coordinate where the column starts.
|
||||||
m_columnOffsets.resize(m_columnCount);
|
m_columnOffsets.resize(m_columnCount);
|
||||||
qreal currentOffset = QGuiApplication::isRightToLeft() ? widthForColumns : m_xPosInc;
|
qreal currentOffset = isRightToLeft ? widthForColumns : m_xPosInc;
|
||||||
|
|
||||||
if (grouped && horizontalScrolling) {
|
if (grouped && horizontalScrolling) {
|
||||||
// All group headers will always be aligned on the top and not
|
// All group headers will always be aligned on the top and not
|
||||||
|
@ -405,16 +410,21 @@ void KItemListViewLayouter::doLayout()
|
||||||
currentOffset += m_groupHeaderHeight;
|
currentOffset += m_groupHeaderHeight;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (QGuiApplication::isLeftToRight())
|
if (isRightToLeft) {
|
||||||
|
for (int column = 0; column < m_columnCount; ++column) {
|
||||||
|
if (horizontalScrolling) {
|
||||||
|
m_columnOffsets[column] = column * m_columnWidth;
|
||||||
|
} else {
|
||||||
|
currentOffset -= m_columnWidth;
|
||||||
|
m_columnOffsets[column] = currentOffset;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
for (int column = 0; column < m_columnCount; ++column) {
|
for (int column = 0; column < m_columnCount; ++column) {
|
||||||
m_columnOffsets[column] = currentOffset;
|
m_columnOffsets[column] = currentOffset;
|
||||||
currentOffset += m_columnWidth;
|
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.
|
// Prepare the QVector which stores the y-coordinate for each new row.
|
||||||
int numberOfRows = (itemCount + m_columnCount - 1) / m_columnCount;
|
int numberOfRows = (itemCount + m_columnCount - 1) / m_columnCount;
|
||||||
|
|
|
@ -309,7 +309,7 @@ void KItemListControllerTest::testKeyboardNavigation_data()
|
||||||
std::swap(nextItemKey, previousItemKey);
|
std::swap(nextItemKey, previousItemKey);
|
||||||
break;
|
break;
|
||||||
case KFileItemListView::CompactLayout:
|
case KFileItemListView::CompactLayout:
|
||||||
std::swap(nextItemKey, previousItemKey);
|
std::swap(nextRowKey, previousRowKey);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
|
|
Loading…
Reference in a new issue