From f65333b027463ea40e0cd4603e48fca62d60216a Mon Sep 17 00:00:00 2001 From: Coursar Date: Mon, 2 Jun 2014 11:58:08 +0400 Subject: [PATCH 1/4] Fix Android: use fbo read back workaround with specific GPUs. Namely, the Adreno 205. We used to enable this workaround for Huawei Honor (Adreno 205). Task-number: QTBUG-33951 Change-Id: Ic92a6913664f2f0954271c700d9ef83d27c238a7 Reviewed-by: Yoann Lopes --- src/plugins/platforms/android/qandroidplatformopenglcontext.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/plugins/platforms/android/qandroidplatformopenglcontext.cpp b/src/plugins/platforms/android/qandroidplatformopenglcontext.cpp index 53047585cf9..3a3ea715620 100644 --- a/src/plugins/platforms/android/qandroidplatformopenglcontext.cpp +++ b/src/plugins/platforms/android/qandroidplatformopenglcontext.cpp @@ -74,6 +74,7 @@ bool QAndroidPlatformOpenGLContext::needsFBOReadBackWorkaroud() needsWorkaround = qstrcmp(rendererString, "Mali-400 MP") == 0 || qstrcmp(rendererString, "Adreno (TM) 200") == 0 + || qstrcmp(rendererString, "Adreno (TM) 205") == 0 || qstrcmp(rendererString, "GC1000 core") == 0; set = true; } From dbe6db192aa1a3e708b00a98a17636af37ceec27 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9rgio=20Martins?= Date: Wed, 11 Jun 2014 12:54:21 +0100 Subject: [PATCH 2/4] Windows: Fix maximizing frameless windows on secondary screens. They would either disappear or be positioned at bogus coordinates. The MINMAXINFO structure works with coords from the primary screen then uses an "interesting" algorithm to adjust to secondary screen: Say you have a primary screen with width=1000 and secondary screen with width=2000, here's what you get when you set ptMaxSize to: ptMaxSize.x | Size window gets in second screen -------------------------------------------------- 500 | 500 1000 | 2000 1001 | 2001 1100 | 2100 So basically you can't get any value between 1000 and 1999 How many people use the taskbar on a second display and maximimize a frameless window anyway ? Task-number: QTBUG-39537 Change-Id: Ic9b3120e7fb5a9a5d97828a2e44be02ae587b92e Reviewed-by: Friedemann Kleint --- src/plugins/platforms/windows/qwindowswindow.cpp | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/plugins/platforms/windows/qwindowswindow.cpp b/src/plugins/platforms/windows/qwindowswindow.cpp index c8eaded38d0..cdc0b244649 100644 --- a/src/plugins/platforms/windows/qwindowswindow.cpp +++ b/src/plugins/platforms/windows/qwindowswindow.cpp @@ -1936,7 +1936,10 @@ void QWindowsWindow::getSizeHints(MINMAXINFO *mmi) const && (m_data.flags & Qt::FramelessWindowHint)) { // This block fixes QTBUG-8361: Frameless windows shouldn't cover the // taskbar when maximized - if (const QScreen *screen = effectiveScreen(window())) { + const QScreen *screen = effectiveScreen(window()); + + // Documentation of MINMAXINFO states that it will only work for the primary screen + if (screen && screen == QGuiApplication::primaryScreen()) { mmi->ptMaxSize.y = screen->availableGeometry().height(); // Width, because you can have the taskbar on the sides too. @@ -1945,8 +1948,8 @@ void QWindowsWindow::getSizeHints(MINMAXINFO *mmi) const // If you have the taskbar on top, or on the left you don't want it at (0,0): mmi->ptMaxPosition.x = screen->availableGeometry().x(); mmi->ptMaxPosition.y = screen->availableGeometry().y(); - } else { - qWarning() << "Invalid screen"; + } else if (!screen){ + qWarning() << "effectiveScreen() returned a null screen"; } } From 81ba16cad933981f55218964a89ed1446022efba Mon Sep 17 00:00:00 2001 From: Lars Knoll Date: Mon, 24 Mar 2014 16:12:20 +0100 Subject: [PATCH 3/4] Fix case insensitive comparisons using QCollator In ICU the strength parameter decides whether a comparison is case sensitive or not. Fix mac comparison code. It can't have worked before. Added some basic automated testing for QCollator. Change-Id: I2646c464fd22ccd3a93c461fa3dba4bd1d4c7b4b Reviewed-by: Konstantin Ritt --- src/corelib/tools/qcollator_icu.cpp | 11 ++- src/corelib/tools/qcollator_macx.cpp | 9 +- .../corelib/tools/qcollator/tst_qcollator.cpp | 90 +++++++++++++++++++ 3 files changed, 105 insertions(+), 5 deletions(-) diff --git a/src/corelib/tools/qcollator_icu.cpp b/src/corelib/tools/qcollator_icu.cpp index 407a493d25d..23e88b50150 100644 --- a/src/corelib/tools/qcollator_icu.cpp +++ b/src/corelib/tools/qcollator_icu.cpp @@ -75,10 +75,17 @@ void QCollator::setCaseSensitivity(Qt::CaseSensitivity cs) { detach(); - UColAttributeValue val = (cs == Qt::CaseSensitive) ? UCOL_UPPER_FIRST : UCOL_OFF; + // The strength attribute in ICU is rather badly documented. Basically UCOL_PRIMARY + // ignores differences between base characters and accented characters as well as case. + // So A and A-umlaut would compare equal. + // UCOL_SECONDARY ignores case differences. UCOL_TERTIARY is the default in most languages + // and does case sensitive comparison. + // UCOL_QUATERNARY is used as default in a few languages such as Japanese to take care of some + // additional differences in those languages. + UColAttributeValue val = (cs == Qt::CaseSensitive) ? UCOL_DEFAULT_STRENGTH : UCOL_SECONDARY; UErrorCode status = U_ZERO_ERROR; - ucol_setAttribute(d->collator, UCOL_CASE_FIRST, val, &status); + ucol_setAttribute(d->collator, UCOL_STRENGTH, val, &status); if (U_FAILURE(status)) qWarning("ucol_setAttribute: Case First failed: %d", status); } diff --git a/src/corelib/tools/qcollator_macx.cpp b/src/corelib/tools/qcollator_macx.cpp index 8985cd4ebaf..877510489a9 100644 --- a/src/corelib/tools/qcollator_macx.cpp +++ b/src/corelib/tools/qcollator_macx.cpp @@ -128,12 +128,15 @@ bool QCollator::ignorePunctuation() const int QCollator::compare(const QChar *s1, int len1, const QChar *s2, int len2) const { SInt32 result; - return UCCompareText(d->collator.collator, + Boolean equivalent; + UCCompareText(d->collator.collator, reinterpret_cast(s1), len1, reinterpret_cast(s2), len2, - NULL, + &equivalent, &result); - return result; + if (equivalent) + return 0; + return result < 0 ? -1 : 1; } int QCollator::compare(const QString &str1, const QString &str2) const { diff --git a/tests/auto/corelib/tools/qcollator/tst_qcollator.cpp b/tests/auto/corelib/tools/qcollator/tst_qcollator.cpp index 3df8422a34f..9ed27a87426 100644 --- a/tests/auto/corelib/tools/qcollator/tst_qcollator.cpp +++ b/tests/auto/corelib/tools/qcollator/tst_qcollator.cpp @@ -52,6 +52,9 @@ class tst_QCollator : public QObject private Q_SLOTS: void moveSemantics(); + + void compare_data(); + void compare(); }; #ifdef Q_COMPILER_RVALUE_REFS @@ -87,6 +90,93 @@ void tst_QCollator::moveSemantics() #endif } + +void tst_QCollator::compare_data() +{ + QTest::addColumn("locale"); + QTest::addColumn("s1"); + QTest::addColumn("s2"); + QTest::addColumn("result"); + QTest::addColumn("caseInsensitiveResult"); + + /* + A few tests below are commented out on the mac. It's unclear why they fail, + as it looks like the collator for the locale is created correctly. + */ + + /* + It's hard to test English, because it's treated differently + on different platforms. For example, on Linux, it uses the + iso14651_t1 template file, which happens to provide good + defaults for Swedish. Mac OS X seems to do a pure bytewise + comparison of Latin-1 values, although I'm not sure. So I + just test digits to make sure that it's not totally broken. + */ + QTest::newRow("english1") << QString("en_US") << QString("5") << QString("4") << 1 << 1; + QTest::newRow("english2") << QString("en_US") << QString("4") << QString("6") << -1 << -1; + QTest::newRow("english3") << QString("en_US") << QString("5") << QString("6") << -1 << -1; + QTest::newRow("english4") << QString("en_US") << QString("a") << QString("b") << -1 << -1; + /* + In Swedish, a with ring above (E5) comes before a with + diaresis (E4), which comes before o diaresis (F6), which + all come after z. + */ + QTest::newRow("swedish1") << QString("sv_SE") << QString::fromLatin1("\xe5") << QString::fromLatin1("\xe4") << -1 << -1; + QTest::newRow("swedish2") << QString("sv_SE") << QString::fromLatin1("\xe4") << QString::fromLatin1("\xf6") << -1 << -1; + QTest::newRow("swedish3") << QString("sv_SE") << QString::fromLatin1("\xe5") << QString::fromLatin1("\xf6") << -1 << -1; +#ifndef Q_OS_MAC + QTest::newRow("swedish4") << QString("sv_SE") << QString::fromLatin1("z") << QString::fromLatin1("\xe5") << -1 << -1; +#endif + + /* + In Norwegian, ae (E6) comes before o with stroke (D8), which + comes before a with ring above (E5). + */ + QTest::newRow("norwegian1") << QString("no_NO") << QString::fromLatin1("\xe6") << QString::fromLatin1("\xd8") << -1 << -1; +#ifndef Q_OS_MAC + QTest::newRow("norwegian2") << QString("no_NO") << QString::fromLatin1("\xd8") << QString::fromLatin1("\xe5") << -1 << -1; +#endif + QTest::newRow("norwegian3") << QString("no_NO") << QString::fromLatin1("\xe6") << QString::fromLatin1("\xe5") << -1 << -1; + + /* + In German, z comes *after* a with diaresis (E4), + which comes before o diaresis (F6). + */ + QTest::newRow("german1") << QString("de_DE") << QString::fromLatin1("a") << QString::fromLatin1("\xe4") << -1 << -1; + QTest::newRow("german2") << QString("de_DE") << QString::fromLatin1("b") << QString::fromLatin1("\xe4") << 1 << 1; + QTest::newRow("german3") << QString("de_DE") << QString::fromLatin1("z") << QString::fromLatin1("\xe4") << 1 << 1; + QTest::newRow("german4") << QString("de_DE") << QString::fromLatin1("\xe4") << QString::fromLatin1("\xf6") << -1 << -1; + QTest::newRow("german5") << QString("de_DE") << QString::fromLatin1("z") << QString::fromLatin1("\xf6") << 1 << 1; + QTest::newRow("german6") << QString("de_DE") << QString::fromLatin1("\xc0") << QString::fromLatin1("\xe0") << 1 << 0; + QTest::newRow("german7") << QString("de_DE") << QString::fromLatin1("\xd6") << QString::fromLatin1("\xf6") << 1 << 0; + QTest::newRow("german8") << QString("de_DE") << QString::fromLatin1("oe") << QString::fromLatin1("\xf6") << 1 << 1; + QTest::newRow("german9") << QString("de_DE") << QString("A") << QString("a") << 1 << 0; + + /* + French sorting of e and e with accent + */ + QTest::newRow("french1") << QString("fr_FR") << QString::fromLatin1("\xe9") << QString::fromLatin1("e") << 1 << 1; + QTest::newRow("french2") << QString("fr_FR") << QString::fromLatin1("\xe9t") << QString::fromLatin1("et") << 1 << 1; + QTest::newRow("french3") << QString("fr_FR") << QString::fromLatin1("\xe9") << QString::fromLatin1("d") << 1 << 1; + QTest::newRow("french4") << QString("fr_FR") << QString::fromLatin1("\xe9") << QString::fromLatin1("f") << -1 << -1; + +} + + +void tst_QCollator::compare() +{ + QFETCH(QString, locale); + QFETCH(QString, s1); + QFETCH(QString, s2); + QFETCH(int, result); + QFETCH(int, caseInsensitiveResult); + + QCollator collator(locale); + QCOMPARE(collator.compare(s1, s2), result); + collator.setCaseSensitivity(Qt::CaseInsensitive); + QCOMPARE(collator.compare(s1, s2), caseInsensitiveResult); +} + QTEST_APPLESS_MAIN(tst_QCollator) #include "tst_qcollator.moc" From 3f39c0f76cec121181ab9d6a0cf057c1b1aeb25c Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Wed, 4 Jun 2014 12:25:56 +0200 Subject: [PATCH 4/4] Polish the image viewer example. - Open files passed on the command line. - Point the file dialog to the pictures location and use a filter string for the supported types. - Set the window title according to file name. Task-number: QTBUG-37203 Task-number: QTBUG-39287 Change-Id: I4e5e43875c3a7544c862c054181e75942939c1d5 Reviewed-by: David Faure --- examples/widgets/doc/src/imageviewer.qdoc | 21 +++--- .../widgets/imageviewer/imageviewer.cpp | 72 ++++++++++++------- .../widgets/widgets/imageviewer/imageviewer.h | 3 +- examples/widgets/widgets/imageviewer/main.cpp | 12 +++- 4 files changed, 72 insertions(+), 36 deletions(-) diff --git a/examples/widgets/doc/src/imageviewer.qdoc b/examples/widgets/doc/src/imageviewer.qdoc index 96013e844ab..6361e3f35b2 100644 --- a/examples/widgets/doc/src/imageviewer.qdoc +++ b/examples/widgets/doc/src/imageviewer.qdoc @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/legal ** ** This file is part of the documentation of the Qt Toolkit. @@ -112,15 +112,19 @@ {ImageViewer}'s appearance. \snippet widgets/imageviewer/imageviewer.cpp 1 + + In the \c open() slot, we show a file dialog to the user. We compile + a list of mime types for use as a filter by querying QImageReader + for the available mime type names. + + We show the file dialog until a valid file name is entered or + the user cancels. + + The function \c loadFile() is used to load the image. + \snippet widgets/imageviewer/imageviewer.cpp 2 - In the \c open() slot, we show a file dialog to the user. The - easiest way to create a QFileDialog is to use the static - convenience functions. QFileDialog::getOpenFileName() returns an - existing file selected by the user. If the user presses \uicontrol - Cancel, QFileDialog returns an empty string. - - Unless the file name is a empty string, we check if the file's + In the \c loadFile() function, we check if the file's format is an image format by constructing a QImage which tries to load the image from the file. If the constructor returns a null image, we use a QMessageBox to alert the user. @@ -135,7 +139,6 @@ information message with an \uicontrol OK button (the default) is sufficient, since the message is part of a normal operation. - \snippet widgets/imageviewer/imageviewer.cpp 3 \snippet widgets/imageviewer/imageviewer.cpp 4 If the format is supported, we display the image in \c imageLabel diff --git a/examples/widgets/widgets/imageviewer/imageviewer.cpp b/examples/widgets/widgets/imageviewer/imageviewer.cpp index 77ec92d57ac..eae94a2499c 100644 --- a/examples/widgets/widgets/imageviewer/imageviewer.cpp +++ b/examples/widgets/widgets/imageviewer/imageviewer.cpp @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/legal ** ** This file is part of the examples of the Qt Toolkit. @@ -61,38 +61,60 @@ ImageViewer::ImageViewer() createActions(); createMenus(); - setWindowTitle(tr("Image Viewer")); - resize(500, 400); + resize(QGuiApplication::primaryScreen()->availableSize() * 3 / 5); } + //! [0] +//! [2] + +bool ImageViewer::loadFile(const QString &fileName) +{ + QImage image(fileName); + if (image.isNull()) { + QMessageBox::information(this, QGuiApplication::applicationDisplayName(), + tr("Cannot load %1.").arg(QDir::toNativeSeparators(fileName))); + setWindowFilePath(QString()); + imageLabel->setPixmap(QPixmap()); + imageLabel->adjustSize(); + return false; + } +//! [2] //! [3] + imageLabel->setPixmap(QPixmap::fromImage(image)); +//! [3] //! [4] + scaleFactor = 1.0; + + printAct->setEnabled(true); + fitToWindowAct->setEnabled(true); + updateActions(); + + if (!fitToWindowAct->isChecked()) + imageLabel->adjustSize(); + + setWindowFilePath(fileName); + return true; +} + +//! [4] + +//! [2] //! [1] void ImageViewer::open() -//! [1] //! [2] { - QString fileName = QFileDialog::getOpenFileName(this, - tr("Open File"), QDir::currentPath()); - if (!fileName.isEmpty()) { - QImage image(fileName); - if (image.isNull()) { - QMessageBox::information(this, tr("Image Viewer"), - tr("Cannot load %1.").arg(fileName)); - return; - } -//! [2] //! [3] - imageLabel->setPixmap(QPixmap::fromImage(image)); -//! [3] //! [4] - scaleFactor = 1.0; + QStringList mimeTypeFilters; + foreach (const QByteArray &mimeTypeName, QImageReader::supportedMimeTypes()) + mimeTypeFilters.append(mimeTypeName); + mimeTypeFilters.sort(); + const QStringList picturesLocations = QStandardPaths::standardLocations(QStandardPaths::PicturesLocation); + QFileDialog dialog(this, tr("Open File"), + picturesLocations.isEmpty() ? QDir::currentPath() : picturesLocations.first()); + dialog.setAcceptMode(QFileDialog::AcceptOpen); + dialog.setMimeTypeFilters(mimeTypeFilters); + dialog.selectMimeTypeFilter("image/jpeg"); - printAct->setEnabled(true); - fitToWindowAct->setEnabled(true); - updateActions(); - - if (!fitToWindowAct->isChecked()) - imageLabel->adjustSize(); - } + while (dialog.exec() == QDialog::Accepted && !loadFile(dialog.selectedFiles().first())) {} } -//! [4] +//! [1] //! [5] void ImageViewer::print() diff --git a/examples/widgets/widgets/imageviewer/imageviewer.h b/examples/widgets/widgets/imageviewer/imageviewer.h index 7a0f0eb845f..a4fd82a696c 100644 --- a/examples/widgets/widgets/imageviewer/imageviewer.h +++ b/examples/widgets/widgets/imageviewer/imageviewer.h @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/legal ** ** This file is part of the examples of the Qt Toolkit. @@ -61,6 +61,7 @@ class ImageViewer : public QMainWindow public: ImageViewer(); + bool loadFile(const QString &); private slots: void open(); diff --git a/examples/widgets/widgets/imageviewer/main.cpp b/examples/widgets/widgets/imageviewer/main.cpp index f1697f9e3ff..ee66b29591a 100644 --- a/examples/widgets/widgets/imageviewer/main.cpp +++ b/examples/widgets/widgets/imageviewer/main.cpp @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/legal ** ** This file is part of the examples of the Qt Toolkit. @@ -39,13 +39,23 @@ ****************************************************************************/ #include +#include #include "imageviewer.h" int main(int argc, char *argv[]) { QApplication app(argc, argv); + QGuiApplication::setApplicationDisplayName(ImageViewer::tr("Image Viewer")); + QCommandLineParser commandLineParser; + commandLineParser.addHelpOption(); + commandLineParser.addPositionalArgument(ImageViewer::tr("[file]"), ImageViewer::tr("Image file to open.")); + commandLineParser.process(QCoreApplication::arguments()); ImageViewer imageViewer; + if (!commandLineParser.positionalArguments().isEmpty() + && !imageViewer.loadFile(commandLineParser.positionalArguments().front())) { + return -1; + } imageViewer.show(); return app.exec(); }