lcikgl
lcikgl

Reputation: 779

Getting Qt Layout Direction to use right-to-left features (e.g. for Arabic) in cascading menus

I'm writing a QT5.5 application on OS X 10.11. I've implemented menu options to dynamically switch amongst languages, including setting the Qt::LayoutDirection for Right-to-Left languages. As mock-up for the right-to-left language support, I've created a test application and translation file in Arabic. Here's a screen-shot:

menus_screenshot

My complete ignorance of Arabic is not helping me here -- the translations shown come from Google Translate (I'll have the app professionally translated when it's finished). Nevertheless the behavior looks only partially correct.

These features match my expectations:

The following features, however, do not match my expectations:

My first question, therefore, is whether my expectations are wrong and the interface is in fact behaving correctly for Arabic, or alternatively what needs to be fixed?

Update: My Arabic-speaking colleagues confirm that the above screen-shot is wrong in the senses I mentioned, that instead it should look like this:

enter image description here

My second, and now main, question is how to fix whatever is wrong to make the Qt cascading menu behave properly for right-to-left languages?

I include below the full code for this standalone example as well as the Qt ".ts" file of translations I used.

#include <QApplication>
#include <QMainWindow>
#include <QtGui>
#include <QTranslator>
#include <QLabel>
#include <QMenuBar>
#include <QMenu>

int
main( int argc, char *argv[] ) {
    QApplication app( argc, argv );

    QMainWindow* mw = new QMainWindow();

    QTranslator* translator = new QTranslator();

    translator->load( "translations.qm" );

    app.installTranslator( translator );

    app.setLayoutDirection( Qt::RightToLeft );

    QLabel* aLabel = new QLabel( mw );

    mw->menuBar()->setNativeMenuBar( false );

    QMenu* fileMenu = new QMenu( QMainWindow::tr( "File" ) );
    QMenu* editMenu = new QMenu( QMainWindow::tr( "Edit" ) );
    QMenu* optionsMenu = new QMenu( QMainWindow::tr( "Options" ) );

    mw->menuBar()->addMenu( fileMenu );
    mw->menuBar()->addMenu( editMenu );
    mw->menuBar()->addMenu( optionsMenu );

    QAction* firstAction = new QAction( QMainWindow::tr( "First" ), optionsMenu );
    QAction* secondAction = new QAction( QMainWindow::tr( "Second" ), optionsMenu );
    QAction* thirdAction = new QAction( QMainWindow::tr( "Third" ), optionsMenu );

    firstAction->setCheckable( true );
    firstAction->setChecked( true );

    optionsMenu->addAction( firstAction );
    optionsMenu->addAction( secondAction );
    optionsMenu->addAction( thirdAction );

    QMenu* languageMenu = new QMenu( QMainWindow::tr( "Language" ) );
    QAction* englishAction = new QAction( QMainWindow::tr( "English" ), languageMenu );
    QAction* arabicAction = new QAction( QMainWindow::tr( "Arabic" ), languageMenu );
    languageMenu->addAction( englishAction );
    languageMenu->addAction( arabicAction );
    optionsMenu->addMenu( languageMenu );

    mw->show();

    return app.exec();
}

And the translations file:

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE TS>
<TS version="2.1" language="en_US">
<context>
    <name>QMainWindow</name>
    <message>
        <location filename="qt_rtl.cc" line="21"/>
        <source>File</source>
        <translation>Ù~EÙ~DÙ~A</translation>
    </message>
    <message>
        <location filename="qt_rtl.cc" line="22"/>
        <source>Edit</source>
        <translation>تحرÙ~Jر</translation>
    </message>
    <message>
        <location filename="qt_rtl.cc" line="23"/>
        <source>Options</source>
        <translation>Ø®Ù~Jارات</translation>
    </message>
    <message>
        <location filename="qt_rtl.cc" line="29"/>
        <source>First</source>
        <translation>اÙ~DØ£Ù~HÙ~D</translation>
    </message>
    <message>
        <location filename="qt_rtl.cc" line="30"/>
        <source>Second</source>
        <translation>ثاÙ~FÙ~Jا</translation>
    </message>
    <message>
        <location filename="qt_rtl.cc" line="31"/>
        <source>Third</source>
        <translation>Ø«Ù~DØ«</translation>
    </message>
    <message>
        <location filename="qt_rtl.cc" line="40"/>
        <source>Language</source>
        <translation>Ù~Dغة</translation>
    </message>
    <message>
        <location filename="qt_rtl.cc" line="41"/>
        <source>English</source>
        <translation>English</translation>
    </message>
    <message>
        <location filename="qt_rtl.cc" line="42"/>
        <source>Arabic</source>
        <translation>اÙ~DعربÙ~JØ©</translation>
    </message>
</context>
</TS>

I would have hoped that the app.setLayoutDirection( Qt::RightToLeft ); line would have "done the right thing" for all widgets and sub widgets but it does not appear so. Perhaps though it did? Any help would be much appreciated.

Thanks

Upvotes: 1

Views: 3067

Answers (1)

lcikgl
lcikgl

Reputation: 779

The exact same code works fine with Qt5.5 running on CentOS 6.7 Linux, i.e. with X11 platform plugin instead of Cocoa:

Cascading Arabic Qt Menus on Linux

Note that the checkmarks are on the right, all text is right-aligned, and the submenu arrow points to the left, as they all should be.

Therefore the conclusion is that the above code is correct, and there appears to be a bug in Cocoa platform support for cascading menus in right-to-left languages under Qt5.5 on OS X.

Upvotes: 2

Related Questions