| 1 |
/**************************************************************************** |
| 2 |
** |
| 3 |
** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). |
| 4 |
** All rights reserved. |
| 5 |
** Contact: Nokia Corporation (qt-info@nokia.com) |
| 6 |
** |
| 7 |
** This file is part of the test suite of the Qt Toolkit. |
| 8 |
** |
| 9 |
** $QT_BEGIN_LICENSE:LGPL$ |
| 10 |
** GNU Lesser General Public License Usage |
| 11 |
** This file may be used under the terms of the GNU Lesser General Public |
| 12 |
** License version 2.1 as published by the Free Software Foundation and |
| 13 |
** appearing in the file LICENSE.LGPL included in the packaging of this |
| 14 |
** file. Please review the following information to ensure the GNU Lesser |
| 15 |
** General Public License version 2.1 requirements will be met: |
| 16 |
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. |
| 17 |
** |
| 18 |
** In addition, as a special exception, Nokia gives you certain additional |
| 19 |
** rights. These rights are described in the Nokia Qt LGPL Exception |
| 20 |
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. |
| 21 |
** |
| 22 |
** GNU General Public License Usage |
| 23 |
** Alternatively, this file may be used under the terms of the GNU General |
| 24 |
** Public License version 3.0 as published by the Free Software Foundation |
| 25 |
** and appearing in the file LICENSE.GPL included in the packaging of this |
| 26 |
** file. Please review the following information to ensure the GNU General |
| 27 |
** Public License version 3.0 requirements will be met: |
| 28 |
** http://www.gnu.org/copyleft/gpl.html. |
| 29 |
** |
| 30 |
** Other Usage |
| 31 |
** Alternatively, this file may be used in accordance with the terms and |
| 32 |
** conditions contained in a signed written agreement between you and Nokia. |
| 33 |
** |
| 34 |
** |
| 35 |
** |
| 36 |
** |
| 37 |
** |
| 38 |
** $QT_END_LICENSE$ |
| 39 |
** |
| 40 |
****************************************************************************/ |
| 41 |
|
| 42 |
|
| 43 |
#include <QtTest/QtTest> |
| 44 |
|
| 45 |
#include <qapplication.h> |
| 46 |
#include <QtCore/QSet> |
| 47 |
#include <QtCore/QTranslator> |
| 48 |
#include <private/qthread_p.h> |
| 49 |
#include <QtGui/QInputDialog> |
| 50 |
#include <QtGui/QColorDialog> |
| 51 |
#include <QtGui/QFileDialog> |
| 52 |
#include <QtGui/QDesktopWidget> |
| 53 |
|
| 54 |
|
| 55 |
//TESTED_CLASS= |
| 56 |
//TESTED_FILES= |
| 57 |
|
| 58 |
class tst_languageChange : public QObject |
| 59 |
{ |
| 60 |
Q_OBJECT |
| 61 |
public: |
| 62 |
tst_languageChange(); |
| 63 |
|
| 64 |
public slots: |
| 65 |
void initTestCase(); |
| 66 |
void cleanupTestCase(); |
| 67 |
private slots: |
| 68 |
void retranslatability_data(); |
| 69 |
void retranslatability(); |
| 70 |
|
| 71 |
}; |
| 72 |
|
| 73 |
|
| 74 |
tst_languageChange::tst_languageChange() |
| 75 |
|
| 76 |
{ |
| 77 |
} |
| 78 |
|
| 79 |
void tst_languageChange::initTestCase() |
| 80 |
{ |
| 81 |
} |
| 82 |
|
| 83 |
void tst_languageChange::cleanupTestCase() |
| 84 |
{ |
| 85 |
} |
| 86 |
/** |
| 87 |
* Records all calls to translate() |
| 88 |
*/ |
| 89 |
class TransformTranslator : public QTranslator |
| 90 |
{ |
| 91 |
Q_OBJECT |
| 92 |
public: |
| 93 |
TransformTranslator() : QTranslator() {} |
| 94 |
TransformTranslator(QObject *parent) : QTranslator(parent) {} |
| 95 |
virtual QString translate(const char *context, const char *sourceText, const char *comment = 0) const |
| 96 |
{ |
| 97 |
QByteArray total(context); |
| 98 |
total.append("::"); |
| 99 |
total.append(sourceText); |
| 100 |
if (comment) { |
| 101 |
total.append("::"); |
| 102 |
total.append(comment); |
| 103 |
} |
| 104 |
m_translations.insert(total); |
| 105 |
QString res; |
| 106 |
for (int i = 0; i < int(qstrlen(sourceText)); ++i) { |
| 107 |
QChar ch = QLatin1Char(sourceText[i]); |
| 108 |
if (ch.isLower()) { |
| 109 |
res.append(ch.toUpper()); |
| 110 |
} else if (ch.isUpper()) { |
| 111 |
res.append(ch.toLower()); |
| 112 |
} else { |
| 113 |
res.append(ch); |
| 114 |
} |
| 115 |
} |
| 116 |
return res; |
| 117 |
} |
| 118 |
|
| 119 |
virtual bool isEmpty() const { return false; } |
| 120 |
|
| 121 |
public slots: |
| 122 |
void install() { |
| 123 |
QCoreApplication::installTranslator(this); |
| 124 |
QTest::qWait(2500); |
| 125 |
QApplication::closeAllWindows(); |
| 126 |
} |
| 127 |
public: |
| 128 |
mutable QSet<QByteArray> m_translations; |
| 129 |
}; |
| 130 |
|
| 131 |
enum DialogType { |
| 132 |
InputDialog = 1, |
| 133 |
ColorDialog, |
| 134 |
FileDialog |
| 135 |
}; |
| 136 |
|
| 137 |
typedef QSet<QByteArray> TranslationSet; |
| 138 |
Q_DECLARE_METATYPE(TranslationSet) |
| 139 |
|
| 140 |
void tst_languageChange::retranslatability_data() |
| 141 |
{ |
| 142 |
QTest::addColumn<int>("dialogType"); |
| 143 |
QTest::addColumn<TranslationSet >("expected"); |
| 144 |
|
| 145 |
//next we fill it with data |
| 146 |
QTest::newRow( "QInputDialog" ) |
| 147 |
<< int(InputDialog) << (QSet<QByteArray>() |
| 148 |
<< "QDialogButtonBox::Cancel"); |
| 149 |
|
| 150 |
QTest::newRow( "QColorDialog" ) |
| 151 |
<< int(ColorDialog) << (QSet<QByteArray>() |
| 152 |
<< "QDialogButtonBox::Cancel" |
| 153 |
<< "QColorDialog::&Sat:" |
| 154 |
<< "QColorDialog::&Add to Custom Colors" |
| 155 |
<< "QColorDialog::&Green:" |
| 156 |
<< "QColorDialog::&Red:" |
| 157 |
<< "QColorDialog::Bl&ue:" |
| 158 |
<< "QColorDialog::A&lpha channel:" |
| 159 |
<< "QColorDialog::&Basic colors" |
| 160 |
<< "QColorDialog::&Custom colors" |
| 161 |
<< "QColorDialog::&Val:" |
| 162 |
<< "QColorDialog::Hu&e:"); |
| 163 |
|
| 164 |
QTest::newRow( "QFileDialog" ) |
| 165 |
<< int(FileDialog) << (QSet<QByteArray>() |
| 166 |
<< "QFileDialog::All Files (*)" |
| 167 |
<< "QFileDialog::Back" |
| 168 |
<< "QFileDialog::Create New Folder" |
| 169 |
<< "QFileDialog::Detail View" |
| 170 |
#ifndef Q_OS_MAC |
| 171 |
<< "QFileDialog::File" |
| 172 |
#endif |
| 173 |
<< "QFileDialog::Files of type:" |
| 174 |
<< "QFileDialog::Forward" |
| 175 |
<< "QFileDialog::List View" |
| 176 |
<< "QFileDialog::Look in:" |
| 177 |
<< "QFileDialog::Open" |
| 178 |
<< "QFileDialog::Parent Directory" |
| 179 |
<< "QFileDialog::Show " |
| 180 |
<< "QFileDialog::Show &hidden files" |
| 181 |
<< "QFileDialog::&Delete" |
| 182 |
<< "QFileDialog::&New Folder" |
| 183 |
<< "QFileDialog::&Rename" |
| 184 |
<< "QFileSystemModel::Date Modified" |
| 185 |
#ifdef Q_OS_WIN |
| 186 |
<< "QFileSystemModel::My Computer" |
| 187 |
#else |
| 188 |
<< "QFileSystemModel::Computer" |
| 189 |
#endif |
| 190 |
<< "QFileSystemModel::Size" |
| 191 |
#ifdef Q_OS_MAC |
| 192 |
<< "QFileSystemModel::Kind::Match OS X Finder" |
| 193 |
#else |
| 194 |
<< "QFileSystemModel::Type::All other platforms" |
| 195 |
#endif |
| 196 |
// << "QFileSystemModel::%1 KB" |
| 197 |
<< "QDialogButtonBox::Cancel" |
| 198 |
<< "QDialogButtonBox::Open" |
| 199 |
<< "QFileDialog::File &name:"); |
| 200 |
} |
| 201 |
|
| 202 |
void tst_languageChange::retranslatability() |
| 203 |
{ |
| 204 |
QFETCH( int, dialogType); |
| 205 |
QFETCH( TranslationSet, expected); |
| 206 |
|
| 207 |
// This will always be queried for when a language changes |
| 208 |
expected.insert("QApplication::QT_LAYOUT_DIRECTION::Translate this string to the string 'LTR' in left-to-right " |
| 209 |
"languages or to 'RTL' in right-to-left languages (such as Hebrew and Arabic) to " |
| 210 |
"get proper widget layout."); |
| 211 |
TransformTranslator translator; |
| 212 |
#if defined(Q_OS_SYMBIAN) && defined(Q_CC_NOKIAX86) |
| 213 |
// Allow a little extra time or emulator startup delays cause failure |
| 214 |
QTimer::singleShot(5000, &translator, SLOT(install())); |
| 215 |
#else |
| 216 |
QTimer::singleShot(500, &translator, SLOT(install())); |
| 217 |
#endif |
| 218 |
switch (dialogType) { |
| 219 |
case InputDialog: |
| 220 |
(void)QInputDialog::getInteger(0, QLatin1String("title"), QLatin1String("label")); |
| 221 |
break; |
| 222 |
|
| 223 |
case ColorDialog: |
| 224 |
#ifdef Q_WS_MAC |
| 225 |
QSKIP("The native color dialog is used on Mac OS", SkipSingle); |
| 226 |
#else |
| 227 |
(void)QColorDialog::getColor(); |
| 228 |
#endif |
| 229 |
break; |
| 230 |
case FileDialog: { |
| 231 |
#ifdef Q_WS_MAC |
| 232 |
QSKIP("The native file dialog is used on Mac OS", SkipSingle); |
| 233 |
#endif |
| 234 |
QFileDialog dlg; |
| 235 |
dlg.setOption(QFileDialog::DontUseNativeDialog); |
| 236 |
QString tmpParentDir = QDir::tempPath() + "/languagechangetestdir"; |
| 237 |
QString tmpDir = tmpParentDir + "/finaldir"; |
| 238 |
QString fooName = tmpParentDir + "/foo"; |
| 239 |
QDir dir; |
| 240 |
QCOMPARE(dir.mkpath(tmpDir), true); |
| 241 |
#if defined(Q_OS_SYMBIAN) |
| 242 |
// Just create a new file instead of copying exe, because there is no read access to /sys/bin |
| 243 |
{ |
| 244 |
QFile fooFile(fooName); |
| 245 |
QVERIFY(fooFile.open(QIODevice::WriteOnly | QIODevice::Text)); |
| 246 |
for(int i=0; i<2048; i++) // File needs to be big enough for size to read in KB |
| 247 |
fooFile.write("@"); |
| 248 |
} |
| 249 |
#else |
| 250 |
QCOMPARE(QFile::copy(QApplication::applicationFilePath(), fooName), true); |
| 251 |
#endif |
| 252 |
|
| 253 |
dlg.setDirectory(tmpParentDir); |
| 254 |
#ifdef Q_OS_WINCE |
| 255 |
dlg.setDirectory("\\Windows"); |
| 256 |
#endif |
| 257 |
dlg.setFileMode(QFileDialog::ExistingFiles); |
| 258 |
dlg.setViewMode(QFileDialog::Detail); |
| 259 |
dlg.exec(); |
| 260 |
#if defined(Q_OS_SYMBIAN) && defined(Q_CC_NOKIAX86) |
| 261 |
// increase the wait time because of increased delay caused by emulator startup |
| 262 |
QTest::qWait(15000); |
| 263 |
#else |
| 264 |
QTest::qWait(3000); |
| 265 |
#endif |
| 266 |
QCOMPARE(QFile::remove(fooName), true); |
| 267 |
QCOMPARE(dir.rmdir(tmpDir), true); |
| 268 |
QCOMPARE(dir.rmdir(tmpParentDir), true); |
| 269 |
break; } |
| 270 |
} |
| 271 |
#if 0 |
| 272 |
QList<QByteArray> list = translator.m_translations.toList(); |
| 273 |
qSort(list); |
| 274 |
qDebug() << list; |
| 275 |
#endif |
| 276 |
// In case we use a Color dialog, we do not want to test for |
| 277 |
// strings non existing in the dialog and which do not get |
| 278 |
// translated. |
| 279 |
if ((dialogType == ColorDialog) && |
| 280 |
#ifndef Q_OS_WINCE |
| 281 |
(qApp->desktop()->width() < 480 || qApp->desktop()->height() < 350) |
| 282 |
#else |
| 283 |
true // On Qt/WinCE we always use compact mode |
| 284 |
#endif |
| 285 |
) { |
| 286 |
expected.remove("QColorDialog::&Basic colors"); |
| 287 |
expected.remove("QColorDialog::&Custom colors"); |
| 288 |
expected.remove("QColorDialog::&Define Custom Colors >>"); |
| 289 |
expected.remove("QColorDialog::&Add to Custom Colors"); |
| 290 |
} |
| 291 |
|
| 292 |
// see if all of our *expected* translations was translated. |
| 293 |
// (There might be more, but thats not that bad) |
| 294 |
QSet<QByteArray> commonTranslations = expected; |
| 295 |
commonTranslations.intersect(translator.m_translations); |
| 296 |
if (!expected.subtract(commonTranslations).isEmpty()) { |
| 297 |
qDebug() << "Missing:" << expected; |
| 298 |
if (!translator.m_translations.subtract(commonTranslations).isEmpty()) |
| 299 |
qDebug() << "Unexpected:" << translator.m_translations; |
| 300 |
} |
| 301 |
|
| 302 |
QVERIFY(expected.isEmpty()); |
| 303 |
} |
| 304 |
|
| 305 |
QTEST_MAIN(tst_languageChange) |
| 306 |
#include "tst_languagechange.moc" |