]> cloud.milkyroute.net Git - dolphin.git/commitdiff
Better support for RTL
authorEugene Popov <popov895@ukr.net>
Wed, 27 Mar 2024 10:28:15 +0000 (10:28 +0000)
committerMéven Car <meven.car@kdemail.net>
Wed, 27 Mar 2024 10:28:15 +0000 (10:28 +0000)
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

src/kitemviews/kitemlistcontainer.cpp
src/kitemviews/kitemlistcontroller.cpp
src/kitemviews/kitemlistview.cpp
src/kitemviews/kstandarditemlistwidget.cpp
src/kitemviews/private/kitemlistviewlayouter.cpp
src/tests/kitemlistcontrollertest.cpp

index 1cac8f7a602bbe71e29c045f919e5dcbe1ff5db2..2f9f5d401b78de2df8b5472e9107c603672421dc 100644 (file)
@@ -399,6 +399,11 @@ void KItemListContainer::updateSmoothScrollers(Qt::Orientation orientation)
         m_horizontalSmoothScroller->setPropertyName("scrollOffset");
         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()
index 3c1b088bec6796a33a97901b0dbf73d3d03f0693..71c37a7aff00057a91d9db4815bee17b8399c451 100644 (file)
@@ -241,6 +241,8 @@ bool KItemListController::keyPressEvent(QKeyEvent *event)
     int key = event->key();
     const bool shiftPressed = event->modifiers() & Qt::ShiftModifier;
 
+    const bool horizontalScrolling = m_view->scrollOrientation() == Qt::Horizontal;
+
     // Handle the expanding/collapsing of items
     // expand / collapse all selected directories
     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
     // the arrow keys to simplify the event handling.
-    if (m_view->scrollOrientation() == Qt::Horizontal) {
+    if (horizontalScrolling) {
         switch (key) {
         case Qt::Key_Up:
             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) {
-        switch (key) {
-        case Qt::Key_Left:
-            key = Qt::Key_Right;
-            break;
-        case Qt::Key_Right:
-            key = Qt::Key_Left;
-            break;
-        default:
-            break;
+        if (horizontalScrolling) {
+            // swap up and down arrow keys
+            switch (key) {
+            case Qt::Key_Up:
+                key = Qt::Key_Down;
+                break;
+            case Qt::Key_Down:
+                key = Qt::Key_Up;
+                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;
 
     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.
             int newIndex = qMax(index - 1, 0);
             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;
 
     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.
             int newIndex = qMin(index + 1, m_model->count() - 1);
             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;
     }
 
-    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
     int lastColumnIndex = index;
-    while ((leftToRight && keyboardAnchorPos(lastColumnIndex + 1) > keyboardAnchorPos(lastColumnIndex))
-           || (!leftToRight && keyboardAnchorPos(lastColumnIndex + 1) < keyboardAnchorPos(lastColumnIndex))) {
+    while ((!reversed && keyboardAnchorPos(lastColumnIndex + 1) > keyboardAnchorPos(lastColumnIndex))
+           || (reversed && keyboardAnchorPos(lastColumnIndex + 1) < keyboardAnchorPos(lastColumnIndex))) {
         ++lastColumnIndex;
         if (lastColumnIndex >= maxIndex) {
             return index;
@@ -1504,8 +1520,8 @@ int KItemListController::nextRowIndex(int index) const
     int searchIndex = nextRowIndex;
     qreal minDiff = qAbs(m_keyboardAnchorPos - keyboardAnchorPos(nextRowIndex));
     while (searchIndex < maxIndex
-           && ((leftToRight && keyboardAnchorPos(searchIndex + 1) > keyboardAnchorPos(searchIndex))
-               || (!leftToRight && keyboardAnchorPos(searchIndex + 1) < keyboardAnchorPos(searchIndex)))) {
+           && ((!reversed && keyboardAnchorPos(searchIndex + 1) > keyboardAnchorPos(searchIndex))
+               || (reversed && keyboardAnchorPos(searchIndex + 1) < keyboardAnchorPos(searchIndex)))) {
         ++searchIndex;
         const qreal searchDiff = qAbs(m_keyboardAnchorPos - keyboardAnchorPos(searchIndex));
         if (searchDiff < minDiff) {
@@ -1523,12 +1539,12 @@ int KItemListController::previousRowIndex(int index) const
         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
     int firstColumnIndex = index;
-    while ((leftToRight && keyboardAnchorPos(firstColumnIndex - 1) < keyboardAnchorPos(firstColumnIndex))
-           || (!leftToRight && keyboardAnchorPos(firstColumnIndex - 1) > keyboardAnchorPos(firstColumnIndex))) {
+    while ((!reversed && keyboardAnchorPos(firstColumnIndex - 1) < keyboardAnchorPos(firstColumnIndex))
+           || (reversed && keyboardAnchorPos(firstColumnIndex - 1) > keyboardAnchorPos(firstColumnIndex))) {
         --firstColumnIndex;
         if (firstColumnIndex <= 0) {
             return index;
@@ -1541,8 +1557,8 @@ int KItemListController::previousRowIndex(int index) const
     int searchIndex = previousRowIndex;
     qreal minDiff = qAbs(m_keyboardAnchorPos - keyboardAnchorPos(previousRowIndex));
     while (searchIndex > 0
-           && ((leftToRight && keyboardAnchorPos(searchIndex - 1) < keyboardAnchorPos(searchIndex))
-               || (!leftToRight && keyboardAnchorPos(searchIndex - 1) > keyboardAnchorPos(searchIndex)))) {
+           && ((!reversed && keyboardAnchorPos(searchIndex - 1) < keyboardAnchorPos(searchIndex))
+               || (reversed && keyboardAnchorPos(searchIndex - 1) > keyboardAnchorPos(searchIndex)))) {
         --searchIndex;
         const qreal searchDiff = qAbs(m_keyboardAnchorPos - keyboardAnchorPos(searchIndex));
         if (searchDiff < minDiff) {
index f906b7a13d7057ffb434bd71a2e332e5f3faec08..e291ee5ecd5122af06c15087a3a6d32f29c6a4e5 100644 (file)
@@ -550,6 +550,10 @@ void KItemListView::scrollToItem(int index, ViewItemPosition viewItemPosition)
     }
     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
     currentRect.adjust(-m_styleOption.horizontalMargin, -m_styleOption.verticalMargin, m_styleOption.horizontalMargin, m_styleOption.verticalMargin);
 
index 2ac8f4f693ab766bc4a926d2e585127be425b277..0d3cfed1a596eacf888e3a230a8a58a2f890ed9f 100644 (file)
@@ -1132,7 +1132,11 @@ void KStandardItemListWidget::updatePixmapCache()
     } else {
         // Center horizontally and vertically within the icon-area
         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
         // 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);
         break;
     case CompactLayout:
+        textOption.setAlignment(QApplication::isRightToLeft() ? Qt::AlignRight : Qt::AlignLeft);
+        textOption.setWrapMode(QTextOption::NoWrap);
+        break;
     case DetailsLayout:
         textOption.setAlignment(Qt::AlignLeft);
         textOption.setWrapMode(QTextOption::NoWrap);
@@ -1404,9 +1411,9 @@ void KStandardItemListWidget::updateCompactLayoutTextCache()
     const qreal textLinesHeight = qMax(visibleRoles().count(), 1) * lineSpacing;
 
     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);
-    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)) {
         const QString text = escapeString(roleText(role, values));
         TextInfo *textInfo = m_textInfo.value(role);
index 5b0df0bd0200959c91019f2cb40772d1d1b2d51d..a2d92f0deb6a4e101f4d643a40e79541600e3535 100644 (file)
@@ -226,8 +226,12 @@ QRectF KItemListViewLayouter::itemRect(int index) const
         // Rotate the logical direction which is always vertical by 90°
         // to get the physical horizontal direction
         QPointF pos(y, x);
-        pos.rx() -= m_scrollOffset;
         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);
     }
 
@@ -361,7 +365,7 @@ void KItemListViewLayouter::doLayout()
 
     const bool grouped = createGroupHeaders();
 
-    const bool horizontalScrolling = (m_scrollOrientation == Qt::Horizontal);
+    const bool horizontalScrolling = m_scrollOrientation == Qt::Horizontal;
     if (horizontalScrolling) {
         // Flip everything so that the layout logically can work like having
         // a vertical scrolling
@@ -377,8 +381,9 @@ void KItemListViewLayouter::doLayout()
         }
     }
 
+    const bool isRightToLeft = QGuiApplication::isRightToLeft();
     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_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.
     m_columnOffsets.resize(m_columnCount);
-    qreal currentOffset = QGuiApplication::isRightToLeft() ? widthForColumns : m_xPosInc;
+    qreal currentOffset = isRightToLeft ? widthForColumns : m_xPosInc;
 
     if (grouped && horizontalScrolling) {
         // All group headers will always be aligned on the top and not
@@ -405,16 +410,21 @@ void KItemListViewLayouter::doLayout()
         currentOffset += m_groupHeaderHeight;
     }
 
-    if (QGuiApplication::isLeftToRight())
+    if (isRightToLeft) {
         for (int column = 0; column < m_columnCount; ++column) {
-            m_columnOffsets[column] = currentOffset;
-            currentOffset += m_columnWidth;
+            if (horizontalScrolling) {
+                m_columnOffsets[column] = column * m_columnWidth;
+            } else {
+                currentOffset -= m_columnWidth;
+                m_columnOffsets[column] = currentOffset;
+            }
         }
-    else
+    } else {
         for (int column = 0; column < m_columnCount; ++column) {
-            m_columnOffsets[column] = currentOffset - m_columnWidth;
-            currentOffset -= m_columnWidth;
+            m_columnOffsets[column] = currentOffset;
+            currentOffset += m_columnWidth;
         }
+    }
 
     // Prepare the QVector which stores the y-coordinate for each new row.
     int numberOfRows = (itemCount + m_columnCount - 1) / m_columnCount;
index 56d383958929147ef9bf487810f80368217fd2e7..40b2cecaad8fad5cc27ef7810e14976ff5cc90cf 100644 (file)
@@ -309,7 +309,7 @@ void KItemListControllerTest::testKeyboardNavigation_data()
                     std::swap(nextItemKey, previousItemKey);
                     break;
                 case KFileItemListView::CompactLayout:
-                    std::swap(nextItemKey, previousItemKey);
+                    std::swap(nextRowKey, previousRowKey);
                     break;
                 default:
                     break;