QGuiApplication: use translation-based layout direction unless explicitly set
The stored layout direction used to get changed during initialization to what was auto-detected based on the translation. Changing the translation then overwrote that stored value, even if an explicit call to setLayoutDirection was made by the application. Calling QGuiApplication::setLayoutDirection(Auto) has so far been a no-op. Change this logic so that the stored layout direction continues to be LayoutDirectionAuto also if it's set based on auto-detection, and only overwrite it when explicitly called with a non-Auto value. This way, applications can set a layout direction that stays unchanged even when translators are installed. Add test coverage that uses a QTranslator. In practice, this is not a change of behavior, unless applications called setLayoutDirection(Auto) (which is no longer a no-op), or called setLayoutDirection() and then installed a translator and expected the translator's layout direction to come into effect in spite of the explicit setting. [ChangeLog][Gui][QGuiApplication] Calling setLayoutDirection with a non- auto value now disables the auto-detection based on installed translators. Applications that explicitly set a layout direction and also want translators installed afterwards to take effect should reset the layout direction to Auto, which is now no longer a no-op. Fixes: QTBUG-100632 Pick-to: 6.3 Change-Id: I1fdcebd43a9b1b468ff95bf15f53f441bb214e08 Reviewed-by: Ulf Hermann <ulf.hermann@qt.io>bb10
parent
32b596b7b1
commit
4cca8ee527
|
|
@ -191,6 +191,7 @@ static int touchDoubleTapDistance = 0;
|
|||
QWindow *QGuiApplicationPrivate::currentMousePressWindow = nullptr;
|
||||
|
||||
static Qt::LayoutDirection layout_direction = Qt::LayoutDirectionAuto;
|
||||
static Qt::LayoutDirection effective_layout_direction = Qt::LeftToRight;
|
||||
static bool force_reverse = false;
|
||||
|
||||
QGuiApplicationPrivate *QGuiApplicationPrivate::self = nullptr;
|
||||
|
|
@ -1672,8 +1673,8 @@ void QGuiApplicationPrivate::init()
|
|||
Q_UNUSED(loadTestability);
|
||||
#endif // QT_CONFIG(library)
|
||||
|
||||
if (layout_direction == Qt::LayoutDirectionAuto || force_reverse)
|
||||
QGuiApplication::setLayoutDirection(qt_detectRTLLanguage() ? Qt::RightToLeft : Qt::LeftToRight);
|
||||
// trigger changed signal and event delivery
|
||||
QGuiApplication::setLayoutDirection(layout_direction);
|
||||
|
||||
if (!QGuiApplicationPrivate::displayName)
|
||||
QObject::connect(q, &QGuiApplication::applicationNameChanged,
|
||||
|
|
@ -1699,7 +1700,7 @@ QGuiApplicationPrivate::~QGuiApplicationPrivate()
|
|||
QCursorData::cleanup();
|
||||
#endif
|
||||
|
||||
layout_direction = Qt::LeftToRight;
|
||||
layout_direction = Qt::LayoutDirectionAuto;
|
||||
|
||||
cleanupThreadData();
|
||||
|
||||
|
|
@ -1943,7 +1944,9 @@ bool QGuiApplication::notify(QObject *object, QEvent *event)
|
|||
bool QGuiApplication::event(QEvent *e)
|
||||
{
|
||||
if (e->type() == QEvent::LanguageChange) {
|
||||
setLayoutDirection(qt_detectRTLLanguage()?Qt::RightToLeft:Qt::LeftToRight);
|
||||
// if the layout direction was set explicitly, then don't override it here
|
||||
if (layout_direction == Qt::LayoutDirectionAuto)
|
||||
setLayoutDirection(layout_direction);
|
||||
for (auto *topLevelWindow : QGuiApplication::topLevelWindows()) {
|
||||
if (topLevelWindow->flags() != Qt::Desktop)
|
||||
postEvent(topLevelWindow, new QEvent(QEvent::LanguageChange));
|
||||
|
|
@ -3881,7 +3884,8 @@ void QGuiApplication::sync()
|
|||
\property QGuiApplication::layoutDirection
|
||||
\brief the default layout direction for this application
|
||||
|
||||
On system start-up, the default layout direction depends on the
|
||||
On system start-up, or when the direction is explicitly set to
|
||||
Qt::LayoutDirectionAuto, the default layout direction depends on the
|
||||
application's language.
|
||||
|
||||
The notifier signal was introduced in Qt 5.4.
|
||||
|
|
@ -3891,11 +3895,15 @@ void QGuiApplication::sync()
|
|||
|
||||
void QGuiApplication::setLayoutDirection(Qt::LayoutDirection direction)
|
||||
{
|
||||
if (layout_direction == direction || direction == Qt::LayoutDirectionAuto)
|
||||
layout_direction = direction;
|
||||
if (direction == Qt::LayoutDirectionAuto)
|
||||
direction = qt_detectRTLLanguage() ? Qt::RightToLeft : Qt::LeftToRight;
|
||||
|
||||
// no change to the explicitly set or auto-detected layout direction
|
||||
if (direction == effective_layout_direction)
|
||||
return;
|
||||
|
||||
layout_direction = direction;
|
||||
|
||||
effective_layout_direction = direction;
|
||||
if (qGuiApp) {
|
||||
emit qGuiApp->layoutDirectionChanged(direction);
|
||||
QGuiApplicationPrivate::self->notifyLayoutDirectionChange();
|
||||
|
|
@ -3904,10 +3912,15 @@ void QGuiApplication::setLayoutDirection(Qt::LayoutDirection direction)
|
|||
|
||||
Qt::LayoutDirection QGuiApplication::layoutDirection()
|
||||
{
|
||||
// layout_direction is only ever Qt::LayoutDirectionAuto if setLayoutDirection
|
||||
// was never called, or called with Qt::LayoutDirectionAuto (which is a no-op).
|
||||
// In that case we return the default LeftToRight.
|
||||
return layout_direction == Qt::LayoutDirectionAuto ? Qt::LeftToRight : layout_direction;
|
||||
/*
|
||||
effective_layout_direction defaults to Qt::LeftToRight, and is updated with what is
|
||||
auto-detected by a call to setLayoutDirection(Qt::LayoutDirectionAuto). This happens in
|
||||
QGuiApplicationPrivate::init and when the language changes (or before if the application
|
||||
calls the static function, but then no translators are installed so the auto-detection
|
||||
always yields Qt::LeftToRight).
|
||||
So we can be certain that it's always the right value.
|
||||
*/
|
||||
return effective_layout_direction;
|
||||
}
|
||||
|
||||
/*!
|
||||
|
|
|
|||
|
|
@ -1158,8 +1158,8 @@ void tst_QGuiApplication::layoutDirection()
|
|||
{
|
||||
qRegisterMetaType<Qt::LayoutDirection>();
|
||||
|
||||
Qt::LayoutDirection oldDirection = QGuiApplication::layoutDirection();
|
||||
Qt::LayoutDirection newDirection = oldDirection == Qt::LeftToRight ? Qt::RightToLeft : Qt::LeftToRight;
|
||||
const Qt::LayoutDirection oldDirection = QGuiApplication::layoutDirection();
|
||||
const Qt::LayoutDirection newDirection = oldDirection == Qt::LeftToRight ? Qt::RightToLeft : Qt::LeftToRight;
|
||||
|
||||
QGuiApplication::setLayoutDirection(newDirection);
|
||||
QCOMPARE(QGuiApplication::layoutDirection(), newDirection);
|
||||
|
|
@ -1177,8 +1177,64 @@ void tst_QGuiApplication::layoutDirection()
|
|||
QGuiApplication::setLayoutDirection(oldDirection);
|
||||
QCOMPARE(QGuiApplication::layoutDirection(), oldDirection);
|
||||
QCOMPARE(signalSpy.count(), 1);
|
||||
|
||||
// with QGuiApplication instantiated, install a translator that gives us control
|
||||
class LayoutDirectionTranslator : public QTranslator
|
||||
{
|
||||
public:
|
||||
LayoutDirectionTranslator(Qt::LayoutDirection direction)
|
||||
: direction(direction)
|
||||
{}
|
||||
|
||||
bool isEmpty() const override { return false; }
|
||||
QString translate(const char *context, const char *sourceText, const char *disambiguation, int n) const override
|
||||
{
|
||||
if (QByteArrayView(sourceText) == "QT_LAYOUT_DIRECTION")
|
||||
return direction == Qt::LeftToRight ? QLatin1String("LTR") : QLatin1String("RTL");
|
||||
return QTranslator::translate(context, sourceText, disambiguation, n);
|
||||
}
|
||||
|
||||
const Qt::LayoutDirection direction;
|
||||
};
|
||||
|
||||
int layoutDirectionChangedCount = 0;
|
||||
// reset to auto-detection, should be back to oldDirection now
|
||||
QGuiApplication::setLayoutDirection(Qt::LayoutDirectionAuto);
|
||||
QCOMPARE(QGuiApplication::layoutDirection(), oldDirection);
|
||||
signalSpy.clear();
|
||||
{
|
||||
// this translator doesn't change the direction
|
||||
LayoutDirectionTranslator translator(oldDirection);
|
||||
QGuiApplication::installTranslator(&translator);
|
||||
QCOMPARE(QGuiApplication::layoutDirection(), translator.direction);
|
||||
QCOMPARE(signalSpy.count(), layoutDirectionChangedCount);
|
||||
}
|
||||
QCOMPARE(signalSpy.count(), layoutDirectionChangedCount); // ltrTranslator removed, no change
|
||||
|
||||
// install a new translator that changes the direction
|
||||
{
|
||||
LayoutDirectionTranslator translator(newDirection);
|
||||
QGuiApplication::installTranslator(&translator);
|
||||
QCOMPARE(QGuiApplication::layoutDirection(), translator.direction);
|
||||
QCOMPARE(signalSpy.count(), ++layoutDirectionChangedCount);
|
||||
}
|
||||
// rtlTranslator removed
|
||||
QCOMPARE(signalSpy.count(), ++layoutDirectionChangedCount);
|
||||
|
||||
// override translation
|
||||
QGuiApplication::setLayoutDirection(newDirection);
|
||||
QCOMPARE(signalSpy.count(), ++layoutDirectionChangedCount);
|
||||
{
|
||||
// this translator will be ignored
|
||||
LayoutDirectionTranslator translator(oldDirection);
|
||||
QGuiApplication::installTranslator(&translator);
|
||||
QCOMPARE(QGuiApplication::layoutDirection(), newDirection);
|
||||
QCOMPARE(signalSpy.count(), layoutDirectionChangedCount);
|
||||
}
|
||||
QCOMPARE(signalSpy.count(), layoutDirectionChangedCount);
|
||||
}
|
||||
|
||||
|
||||
void tst_QGuiApplication::globalShareContext()
|
||||
{
|
||||
#ifndef QT_NO_OPENGL
|
||||
|
|
|
|||
Loading…
Reference in New Issue