qt5base-lts/tests/auto/other/languagechange/tst_languagechange.cpp
Friedemann Kleint 541949aed2 Add further theme hints to QPlatformTheme.
- Add hints for QDialog/QDialogButtonBox.
- Add hint for available popup-menu area.
- Add keyboard scheme hint replacing
  QGuiApplicationPrivate::currentKeyPlatform()

Reviewed-by: Samuel Rødal <samuel.rodal@nokia.com>
Reviewed-by: Morten Johan Sørvig <morten.sorvig@nokia.com>

Task-number: QTBUG-24204
Task-number: QTBUG-24315

Change-Id: I6653786b0dcb49a6fc264d3b9891dbfee502bd3e
Reviewed-by: Friedemann Kleint <Friedemann.Kleint@nokia.com>
2012-02-22 17:28:51 +01:00

339 lines
11 KiB
C++

/****************************************************************************
**
** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/
**
** This file is part of the test suite of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** GNU Lesser General Public License Usage
** This file may be used under the terms of the GNU Lesser General Public
** License version 2.1 as published by the Free Software Foundation and
** appearing in the file LICENSE.LGPL included in the packaging of this
** file. Please review the following information to ensure the GNU Lesser
** General Public License version 2.1 requirements will be met:
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU General
** Public License version 3.0 as published by the Free Software Foundation
** and appearing in the file LICENSE.GPL included in the packaging of this
** file. Please review the following information to ensure the GNU General
** Public License version 3.0 requirements will be met:
** http://www.gnu.org/copyleft/gpl.html.
**
** Other Usage
** Alternatively, this file may be used in accordance with the terms and
** conditions contained in a signed written agreement between you and Nokia.
**
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include <QtTest/QtTest>
#include <qapplication.h>
#include <private/qguiapplication_p.h>
#include <QtCore/QSet>
#include <QtCore/QFile>
#include <QtCore/QTranslator>
#include <QtCore/QTemporaryDir>
#include <private/qthread_p.h>
#include <QtGui/QPlatformTheme>
#include <QtWidgets/QInputDialog>
#include <QtWidgets/QColorDialog>
#include <QtWidgets/QDialogButtonBox>
#include <QtWidgets/QFileDialog>
#include <QtWidgets/QDesktopWidget>
class tst_languageChange : public QObject
{
Q_OBJECT
public:
tst_languageChange();
public slots:
void initTestCase();
void cleanupTestCase();
private slots:
void retranslatability_data();
void retranslatability();
private:
QDialogButtonBox::ButtonLayout m_layout;
};
tst_languageChange::tst_languageChange() :
m_layout(QDialogButtonBox::WinLayout)
{
if (const QPlatformTheme *theme = QGuiApplicationPrivate::platformTheme())
m_layout = static_cast<QDialogButtonBox::ButtonLayout>(theme->themeHint(QPlatformTheme::DialogButtonBoxLayout).toInt());
}
void tst_languageChange::initTestCase()
{
}
void tst_languageChange::cleanupTestCase()
{
}
/**
* Records all calls to translate()
*/
class TransformTranslator : public QTranslator
{
Q_OBJECT
public:
TransformTranslator() : QTranslator() {}
TransformTranslator(QObject *parent) : QTranslator(parent) {}
QString translate(const char *context, const char *sourceText,
const char *disambiguation = 0, int = -1) const
{
QByteArray total(context);
total.append("::");
total.append(sourceText);
if (disambiguation) {
total.append("::");
total.append(disambiguation);
}
m_translations.insert(total);
QString res;
for (int i = 0; i < int(qstrlen(sourceText)); ++i) {
QChar ch = QLatin1Char(sourceText[i]);
if (ch.isLower()) {
res.append(ch.toUpper());
} else if (ch.isUpper()) {
res.append(ch.toLower());
} else {
res.append(ch);
}
}
return res;
}
virtual bool isEmpty() const { return false; }
public:
mutable QSet<QByteArray> m_translations;
};
// Install the translator and close all application windows after a while to
// quit the event loop.
class LanguageTestStateMachine : public QObject
{
Q_OBJECT
public:
LanguageTestStateMachine(QTranslator *translator);
void start() { m_timer.start(); }
private slots:
void timeout();
private:
enum State { InstallTranslator, CloseDialog };
QTimer m_timer;
QTranslator *m_translator;
State m_state;
};
LanguageTestStateMachine::LanguageTestStateMachine(QTranslator *translator) :
m_translator(translator), m_state(InstallTranslator)
{
m_timer.setInterval(500);
connect(&m_timer, SIGNAL(timeout()), this, SLOT(timeout()));
}
void LanguageTestStateMachine::timeout()
{
switch (m_state) {
case InstallTranslator:
m_timer.stop();
QCoreApplication::installTranslator(m_translator);
m_timer.setInterval(2500);
m_timer.start();
m_state = CloseDialog;
break;
case CloseDialog: // Close repeatedly in case file dialog is slow.
QApplication::closeAllWindows();
break;
}
}
enum DialogType {
InputDialog = 1,
ColorDialog,
FileDialog
};
typedef QSet<QByteArray> TranslationSet;
Q_DECLARE_METATYPE(TranslationSet)
void tst_languageChange::retranslatability_data()
{
QTest::addColumn<int>("dialogType");
QTest::addColumn<TranslationSet >("expected");
//next we fill it with data
QTest::newRow( "QInputDialog" )
<< int(InputDialog) << (QSet<QByteArray>()
<< "QDialogButtonBox::Cancel");
QTest::newRow( "QColorDialog" )
<< int(ColorDialog) << (QSet<QByteArray>()
<< "QDialogButtonBox::Cancel"
<< "QColorDialog::&Sat:"
<< "QColorDialog::&Add to Custom Colors"
<< "QColorDialog::&Green:"
<< "QColorDialog::&Red:"
<< "QColorDialog::Bl&ue:"
<< "QColorDialog::A&lpha channel:"
<< "QColorDialog::&Basic colors"
<< "QColorDialog::&Custom colors"
<< "QColorDialog::&Val:"
<< "QColorDialog::Hu&e:");
QTest::newRow( "QFileDialog" )
<< int(FileDialog) << (QSet<QByteArray>()
<< "QFileDialog::All Files (*)"
<< "QFileDialog::Back"
<< "QFileDialog::Create New Folder"
<< "QFileDialog::Detail View"
#ifndef Q_OS_MAC
<< "QFileDialog::File"
#endif
<< "QFileDialog::Files of type:"
<< "QFileDialog::Forward"
<< "QFileDialog::List View"
<< "QFileDialog::Look in:"
<< "QFileDialog::Open"
<< "QFileDialog::Parent Directory"
<< "QFileDialog::Show "
<< "QFileDialog::Show &hidden files"
<< "QFileDialog::&Delete"
<< "QFileDialog::&New Folder"
<< "QFileDialog::&Rename"
<< "QFileSystemModel::Date Modified"
#ifdef Q_OS_WIN
<< "QFileSystemModel::My Computer"
#else
<< "QFileSystemModel::Computer"
#endif
<< "QFileSystemModel::Size"
#ifdef Q_OS_MAC
<< "QFileSystemModel::Kind::Match OS X Finder"
#else
<< "QFileSystemModel::Type::All other platforms"
#endif
// << "QFileSystemModel::%1 KB"
<< "QDialogButtonBox::Cancel"
<< "QDialogButtonBox::Open"
<< "QFileDialog::File &name:");
}
void tst_languageChange::retranslatability()
{
QFETCH( int, dialogType);
QFETCH( TranslationSet, expected);
if (m_layout == QDialogButtonBox::GnomeLayout)
QSKIP("The input data are not suitable for this layout (QDialogButtonBox::GnomeLayout)");
// This will always be queried for when a language changes
expected.insert("QCoreApplication::QT_LAYOUT_DIRECTION::Translate this string to the string 'LTR' in left-to-right "
"languages or to 'RTL' in right-to-left languages (such as Hebrew and Arabic) to "
"get proper widget layout.");
TransformTranslator translator;
LanguageTestStateMachine stateMachine(&translator);
switch (dialogType) {
case InputDialog:
stateMachine.start();
QInputDialog::getInteger(0, QLatin1String("title"), QLatin1String("label"));
break;
case ColorDialog:
#ifdef Q_OS_MAC
QSKIP("The native color dialog is used on Mac OS");
#else
stateMachine.start();
QColorDialog::getColor();
#endif
break;
case FileDialog: {
#ifdef Q_OS_MAC
QSKIP("The native file dialog is used on Mac OS");
#endif
QFileDialog dlg;
dlg.setOption(QFileDialog::DontUseNativeDialog);
QString tempDirPattern = QDir::tempPath();
if (!tempDirPattern.endsWith(QLatin1Char('/')))
tempDirPattern += QLatin1Char('/');
tempDirPattern += QStringLiteral("languagechangetestdirXXXXXX");
QTemporaryDir temporaryDir(tempDirPattern);
temporaryDir.setAutoRemove(true);
QVERIFY(temporaryDir.isValid());
const QString finalDir = temporaryDir.path() + QStringLiteral("/finaldir");
const QString fooName = temporaryDir.path() + QStringLiteral("/foo");
QDir dir;
QVERIFY(dir.mkpath(finalDir));
QFile fooFile(fooName);
QVERIFY(fooFile.open(QIODevice::WriteOnly|QIODevice::Text));
fooFile.write("test");
fooFile.close();
dlg.setDirectory(temporaryDir.path());
#ifdef Q_OS_WINCE
dlg.setDirectory("\\Windows");
#endif
dlg.setFileMode(QFileDialog::ExistingFiles);
dlg.setViewMode(QFileDialog::Detail);
stateMachine.start();
dlg.exec();
QTest::qWait(3000);
break; }
}
// In case we use a Color dialog, we do not want to test for
// strings non existing in the dialog and which do not get
// translated.
if ((dialogType == ColorDialog) &&
#ifndef Q_OS_WINCE
(qApp->desktop()->width() < 480 || qApp->desktop()->height() < 350)
#else
true // On Qt/WinCE we always use compact mode
#endif
) {
expected.remove("QColorDialog::&Basic colors");
expected.remove("QColorDialog::&Custom colors");
expected.remove("QColorDialog::&Define Custom Colors >>");
expected.remove("QColorDialog::&Add to Custom Colors");
}
// see if all of our *expected* translations was translated.
// (There might be more, but thats not that bad)
QSet<QByteArray> commonTranslations = expected;
commonTranslations.intersect(translator.m_translations);
if (!expected.subtract(commonTranslations).isEmpty()) {
qDebug() << "Missing:" << expected;
if (!translator.m_translations.subtract(commonTranslations).isEmpty())
qDebug() << "Unexpected:" << translator.m_translations;
}
QVERIFY(expected.isEmpty());
}
QTEST_MAIN(tst_languageChange)
#include "tst_languagechange.moc"