Solved Opt out of layout mirroring in right to left languages
-
Hello everyone,
I've written a small program for quizing my kid (code at https://github.com/Shachar/Quizer). It works fine on my machine (Ubuntu 18.04 with KDE, language set to English).
When I transfer it to my kid's machine, however (Ubuntu 18.04 with KDE, language set to Hebrew), the entire layout of the program reverses. This varies from mildly annoying for the dictation part to downright incorrect when the program asks for algebra exercises, where "12-3" becomes "3-12".
I could not find the setting that causes it to happen. It is not anything to do with environment variables (I tried setting LANG and LANGUAGE to
en
). I'm guessing this is some configuration in KDE.The thing is, however, that I just don't want it. I don't want the environment to try and automatically transform my layout. It does nothing to help my program.
I think it is a bad idea regardless of context, but at least for a program I write, I would like to opt-out of this automatic layout mirroring.
Is there a way to do that?
-
Hi and welcome to devnet,
You can use qApp->setLayoutDirection to set the direction you want.
-
Hi and welcome to devnet,
You can use qApp->setLayoutDirection to set the direction you want.
-
Thank you for your answer. Setting the app level direction indeed solved the problem.
What I don't understand is why it was necessary to get to that point. All of the widgets in the project had the layout show up as "LeftToRight". I expected that to define the layout direction.
Please note that I am no translation newbie. I am a native Hebrew speaker, I've done extensive work on both I18n and L10n for Android and Wine, with specific focus on translations to right-to-left languages, specifically Hebrew. I've even written articles about how to do such translations. I cannot describe the current QT behavior as anything other than "completely broken".
I expected widgets marked with a layout of "auto" to mirror, while widgets marked with a layout of "left to right" to be, well, left to right. I don't see how a global setting leaves me the freedom to translate a layout so it ends up looking the way I would need it to look.
I'll give an example from the quizer I wrote. This is a segment of the layout in "AlgebraWidget.ui":
<layout class="QHBoxLayout" name="horizontalLayout_2"> <item> <widget class="QLabel" name="number1"> <property name="text"> <string>a</string> </property> </widget> </item> <item> <widget class="QLabel" name="operation"> <property name="text"> <string>+</string> </property> </widget> </item> <item> <widget class="QLabel" name="number2"> <property name="text"> <string>b</string> </property> </widget> </item> <item> <widget class="QLabel" name="equals"> <property name="text"> <string>=</string> </property> </widget> </item> <item> <widget class="QLineEdit" name="answer"/> </item> </layout>
It has three labels for number1, number2 and operation. Since math is universally written from left to right, that is the order those labels need to be in at the layout. Mirroring it turns the exercise "10-3", which my 10 y.o can solve, into "3-10", which she cannot.
Even if I want the rest of the layout to mirror, I don't want that particular part of it to. To me, setting the rest of the layout to "auto", and this part to "left-to-right", would do it.
But it seems that QT does not support that.
-
I understand your issue and it indeed looks like there's something off.
What version of Qt are you using ?
Can you provide a minimal compilable example that shows your issue ?
-
So, the good news is that it does not seem to be a problem with QT after all. The following code seems to work fine:
#include <QApplication> #include <QHBoxLayout> #include <QPushButton> #include <QMainWindow> int main(int argc, char *argv[]) { QApplication a(argc, argv); QWidget *window = new QWidget; window->setLayoutDirection( Qt::LeftToRight ); // The important line QPushButton *button1 = new QPushButton("One"); QPushButton *button2 = new QPushButton("Two"); QPushButton *button3 = new QPushButton("Three"); QPushButton *button4 = new QPushButton("Four"); QPushButton *button5 = new QPushButton("Five"); QHBoxLayout *layout = new QHBoxLayout; layout->addWidget(button1); layout->addWidget(button2); layout->addWidget(button3); layout->addWidget(button4); layout->addWidget(button5); window->setLayout(layout); window->show(); return a.exec(); }
As written, this program does not mirror. Removing the important line does, indeed, mirror. This means that the default for QT widgets is
LayoutDirectionAuto
, and setting it explicitly toLeftToRight
does the right thing.I will point out that I think that
LayoutDirectionAuto
has its problems as default, at least for top level windows such asQMainWindow
, but at least it is consistent.Which means we can focus the problem on two places:
- The documentation states that
LeftToRight
is the default. Clearly this is a mistake. - QT Creator displays in the UI that a widget's layout is
LeftToRight
, while actually meaning "I'm leaving it as default". It should showLayoutDirectionAuto
instead.
- The documentation states that
-
I've reported it:
https://bugreports.qt.io/browse/QTBUG-85839