diff options
93 files changed, 1155 insertions, 954 deletions
diff --git a/.gitignore b/.gitignore index f98f90d292..f133a2124e 100644 --- a/.gitignore +++ b/.gitignore @@ -245,6 +245,7 @@ tags *.gcda *.gcno *.lib +!Info.plist.lib *.o *.obj *.orig diff --git a/config_help.txt b/config_help.txt index 3d2ab79fa0..ae0bb24520 100644 --- a/config_help.txt +++ b/config_help.txt @@ -82,7 +82,7 @@ Build options: -debug-and-release ... Build two versions of Qt, with and without debugging turned on [yes] (Apple and Windows only) -optimize-debug ...... Enable debug-friendly optimizations in debug builds - [auto] (Not supported with MSVC) + [auto] (Not supported with MSVC or Clang toolchains) -optimize-size ....... Optimize release builds for size instead of speed [no] -optimized-tools ..... Build optimized host tools even in debug build [no] -force-debug-info .... Create symbol files for release builds [no] diff --git a/configure.json b/configure.json index 1268fc87a2..a0b9765d18 100644 --- a/configure.json +++ b/configure.json @@ -585,7 +585,7 @@ }, "optimize_debug": { "label": "Optimize debug build", - "condition": "!config.msvc && (features.debug || features.debug_and_release) && tests.optimize_debug", + "condition": "!config.msvc && !config.clang && (features.debug || features.debug_and_release) && tests.optimize_debug", "output": [ "privateConfig" ] }, "optimize_size": { @@ -1234,7 +1234,7 @@ Configure with '-qreal float' to create a build that is binary-compatible with 5 { "type": "feature", "args": "optimize_debug", - "condition": "!config.msvc && (features.debug || features.debug_and_release)" + "condition": "!config.msvc && !config.clang && (features.debug || features.debug_and_release)" }, { "type": "feature", diff --git a/dist/changes-5.9.3 b/dist/changes-5.9.3 new file mode 100644 index 0000000000..521833dba0 --- /dev/null +++ b/dist/changes-5.9.3 @@ -0,0 +1,144 @@ +Qt 5.9.3 is a bug-fix release. It maintains both forward and backward +compatibility (source and binary) with Qt 5.9.0 through 5.9.2. + +For more details, refer to the online documentation included in this +distribution. The documentation is also available online: + +http://doc.qt.io/qt-5/index.html + +The Qt version 5.9 series is binary compatible with the 5.8.x series. +Applications compiled for 5.8 will continue to run with 5.9. + +Some of the changes listed in this file include issue tracking numbers +corresponding to tasks in the Qt Bug Tracker: + +https://bugreports.qt.io/ + +Each of these identifiers can be entered in the bug tracker to obtain more +information about a particular change. + +**************************************************************************** +* Qt 5.9.3 Changes * +**************************************************************************** + +QtCore +------ + + - QFileSystemWatcher: + * [QTBUG-64171] Fixed a bug that would cause the application to crash if + QFileSystemWatcher was created in an auxiliary thread on Windows. + + - QStorageInfo: + * [QTBUG-61420] Fixed decoding of volume labels containing certain + uncommon characters on Linux. + + - QThreadPool: + * Improved performance with large amount of QRunnable items. + +QtGui +------ + + - [QTBUG-64239] Fixed memory corruption on scaled emojis. + - [QTBUG-63846] Fixed dragging inside a modal window when a + QShapedPixmapWindow is used. + - [QTBUG-61777] Fixed painting of zero-length lines with scaling. + - [QTBUG-61244] Fixed centering of some items in layouts. + - [QTBUG-63168] Fixed a crash when reparenting QWindowContainer. + + +QtNetwork +--------- + + - QHostAddress: + * [QTBUG-63764] Fixed a problem in QHostAddress not detaching in its + setters and thus spoiling shared data. + + - QNetworkAccessManager: + * [QTBUG-63075] Added support for HTTP status 308. + * [QTBUG-61300] Fixed a problem with mixing headers from different + responses. + * [QTBUG-63471] Fixed redirects support in HTTP/2 protocol handler. + * [QTBUG-63313] Fixed cookies received during a redirect not being + applied in the redirect. + * [QTBUG-63142] Fixed HTTP method always being changed to GET when + redirected with 307 and 308. + + - QNetworkCookieJar: + * Fixed cookies with a root path ("/") not matching an empty path (""). + +QtSql +------ + + - PostgreSQL: + * Fixed handling of binary data for PostgreSQL 9.x and later + * Fixed detection of PostgreSQL 9.x and later + + - OCI: + * [QTBUG-57765] Fixed a bug that would see some cached results returned + when issuing a forward only query + +QtWidgets +--------- + + - QAction: + * [QTBUG-62006] Ensured setData() does not emit changed() if no change + happened. + + - QDockWidget: + * [QTBUG-63526] Fixed an issue in QDockWidgets where the widget would + not resize despite showing a resize cursor. + + - QHeaderView: + * [QTBUG-54601] Fixed resizing when hidden sections were involved. + * [QTBUG-64036] Ensured maximumSectionSize property is honored during + resizeSections(). + + - QListView: + * [QTBUG-45427] Fixed the laying out of a QListView in a grid layout + after the dataChanged() signal is emitted. + + - QMenuBar + * [QTBUG-34160] Fixed a problem with adding the same QAction to more than + one menu. + + - QWidget + * [QTBUG-56860] Fixed widget losing focus after showing menu second time. + + - QWizard: + * [QTBUG-46894] Fixed the shortcut for the Next button on Windows. + + +Platform-specific changes +------------------------- + + - Cocoa: + * optimize backingstore flush on 10-bit displays + * [QTBUG-57076] [QTBUG-63712] Attach menu items when updating the menubar + * [QTBUG-63444] Toggle titlebar transparency to support unified toolbar + + - iOS: + * [QTBUG-57428][QTBUG-63660] add support for adding mimetypes other than text + on the clipboard + + - Windows: + * [QTBUG-63654] Windows font database: Remove clamping of default font size + + - X11: + * [QTBUG-48034] Don't misdetect certain trackballs as tablets + * [QTBUG-62840] Fix crash on X servers with BGR888 display + +Third-Party Code +---------------- + + - Improved documentation about Freetype 2 licenses. + - Updated Sqlite to fix CVE-2017-10989. + - Updated bundled libpng to version 1.6.34. + +Tools +----- + + * qmake: + - [QTBUG-63409] Fixed a build error with MSVC when concrt.h was included + while exceptions are disabled. + - [QTBUG-62985] Fixed a bug that caused the accidental creation of files + called "NUL" when using MinGW. diff --git a/doc/src/images/appchooser-example.png b/doc/src/images/appchooser-example.png Binary files differdeleted file mode 100644 index 885476e8b9..0000000000 --- a/doc/src/images/appchooser-example.png +++ /dev/null diff --git a/doc/src/images/customsortfiltermodel-example.png b/doc/src/images/customsortfiltermodel-example.png Binary files differindex d7ee8bd7e7..7c0750eb57 100644 --- a/doc/src/images/customsortfiltermodel-example.png +++ b/doc/src/images/customsortfiltermodel-example.png diff --git a/doc/src/images/lightingeffect-example.png b/doc/src/images/lightingeffect-example.png Binary files differdeleted file mode 100644 index d9dc990481..0000000000 --- a/doc/src/images/lightingeffect-example.png +++ /dev/null diff --git a/doc/src/images/validators.png b/doc/src/images/validators.png Binary files differnew file mode 100644 index 0000000000..1940c6da3f --- /dev/null +++ b/doc/src/images/validators.png diff --git a/examples/widgets/animation/animation.pro b/examples/widgets/animation/animation.pro index a13f8bb65a..19b79caf15 100644 --- a/examples/widgets/animation/animation.pro +++ b/examples/widgets/animation/animation.pro @@ -2,7 +2,6 @@ TEMPLATE = \ subdirs SUBDIRS += \ animatedtiles \ - appchooser \ easing \ moveblocks \ states \ diff --git a/examples/widgets/animation/appchooser/accessories-dictionary.png b/examples/widgets/animation/appchooser/accessories-dictionary.png Binary files differdeleted file mode 100644 index e9bd55d918..0000000000 --- a/examples/widgets/animation/appchooser/accessories-dictionary.png +++ /dev/null diff --git a/examples/widgets/animation/appchooser/akregator.png b/examples/widgets/animation/appchooser/akregator.png Binary files differdeleted file mode 100644 index a086f45ab6..0000000000 --- a/examples/widgets/animation/appchooser/akregator.png +++ /dev/null diff --git a/examples/widgets/animation/appchooser/appchooser.pro b/examples/widgets/animation/appchooser/appchooser.pro deleted file mode 100644 index 674e623b2d..0000000000 --- a/examples/widgets/animation/appchooser/appchooser.pro +++ /dev/null @@ -1,8 +0,0 @@ -QT += widgets - -SOURCES = main.cpp -RESOURCES = appchooser.qrc - -# install -target.path = $$[QT_INSTALL_EXAMPLES]/widgets/animation/appchooser -INSTALLS += target diff --git a/examples/widgets/animation/appchooser/appchooser.qrc b/examples/widgets/animation/appchooser/appchooser.qrc deleted file mode 100644 index 28a3e1c4c1..0000000000 --- a/examples/widgets/animation/appchooser/appchooser.qrc +++ /dev/null @@ -1,8 +0,0 @@ -<!DOCTYPE RCC><RCC version="1.0"> -<qresource> - <file>accessories-dictionary.png</file> - <file>akregator.png</file> - <file>digikam.png</file> - <file>k3b.png</file> -</qresource> -</RCC> diff --git a/examples/widgets/animation/appchooser/digikam.png b/examples/widgets/animation/appchooser/digikam.png Binary files differdeleted file mode 100644 index 9de9fb2f80..0000000000 --- a/examples/widgets/animation/appchooser/digikam.png +++ /dev/null diff --git a/examples/widgets/animation/appchooser/k3b.png b/examples/widgets/animation/appchooser/k3b.png Binary files differdeleted file mode 100644 index bbcafcfba1..0000000000 --- a/examples/widgets/animation/appchooser/k3b.png +++ /dev/null diff --git a/examples/widgets/animation/appchooser/main.cpp b/examples/widgets/animation/appchooser/main.cpp deleted file mode 100644 index 71c869f6a2..0000000000 --- a/examples/widgets/animation/appchooser/main.cpp +++ /dev/null @@ -1,183 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the QtCore module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:BSD$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** BSD License Usage -** Alternatively, you may use this file under the terms of the BSD license -** as follows: -** -** "Redistribution and use in source and binary forms, with or without -** modification, are permitted provided that the following conditions are -** met: -** * Redistributions of source code must retain the above copyright -** notice, this list of conditions and the following disclaimer. -** * Redistributions in binary form must reproduce the above copyright -** notice, this list of conditions and the following disclaimer in -** the documentation and/or other materials provided with the -** distribution. -** * Neither the name of The Qt Company Ltd nor the names of its -** contributors may be used to endorse or promote products derived -** from this software without specific prior written permission. -** -** -** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include <QtCore> -#include <QtWidgets> - - -class Pixmap : public QGraphicsWidget -{ - Q_OBJECT - -public: - Pixmap(const QPixmap &pix, QGraphicsItem *parent = 0) - : QGraphicsWidget(parent), orig(pix), p(pix) - { - } - - void paint(QPainter *painter, const QStyleOptionGraphicsItem *, QWidget *) override - { - painter->drawPixmap(QPointF(), p); - } - - void mousePressEvent(QGraphicsSceneMouseEvent *) override - { - emit clicked(); - } - - void setGeometry(const QRectF &rect) override - { - QGraphicsWidget::setGeometry(rect); - - if (rect.size().width() > orig.size().width()) - p = orig.scaled(rect.size().toSize()); - else - p = orig; - } - -Q_SIGNALS: - void clicked(); - -private: - QPixmap orig; - QPixmap p; -}; - -class GraphicsView : public QGraphicsView -{ - Q_OBJECT -public: - GraphicsView(QGraphicsScene *scene, QWidget *parent = 0) : QGraphicsView(scene, parent) - { - } - - void resizeEvent(QResizeEvent *) override - { - fitInView(sceneRect(), Qt::KeepAspectRatio); - } -}; - - -void createStates(const QObjectList &objects, - const QRect &selectedRect, QState *parent) -{ - for (int i = 0; i < objects.size(); ++i) { - QState *state = new QState(parent); - state->assignProperty(objects.at(i), "geometry", selectedRect); - parent->addTransition(objects.at(i), SIGNAL(clicked()), state); - } -} - -void createAnimations(const QObjectList &objects, QStateMachine *machine) -{ - for (int i=0; i<objects.size(); ++i) - machine->addDefaultAnimation(new QPropertyAnimation(objects.at(i), "geometry")); -} - -int main(int argc, char **argv) -{ - Q_INIT_RESOURCE(appchooser); - - QApplication app(argc, argv); - - Pixmap *p1 = new Pixmap(QPixmap(":/digikam.png")); - Pixmap *p2 = new Pixmap(QPixmap(":/akregator.png")); - Pixmap *p3 = new Pixmap(QPixmap(":/accessories-dictionary.png")); - Pixmap *p4 = new Pixmap(QPixmap(":/k3b.png")); - - p1->setObjectName("p1"); - p2->setObjectName("p2"); - p3->setObjectName("p3"); - p4->setObjectName("p4"); - - p1->setGeometry(QRectF( 0.0, 0.0, 64.0, 64.0)); - p2->setGeometry(QRectF(236.0, 0.0, 64.0, 64.0)); - p3->setGeometry(QRectF(236.0, 236.0, 64.0, 64.0)); - p4->setGeometry(QRectF( 0.0, 236.0, 64.0, 64.0)); - - QGraphicsScene scene(0, 0, 300, 300); - scene.setBackgroundBrush(Qt::white); - scene.addItem(p1); - scene.addItem(p2); - scene.addItem(p3); - scene.addItem(p4); - - GraphicsView window(&scene); - window.setFrameStyle(0); - window.setAlignment(Qt::AlignLeft | Qt::AlignTop); - window.setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); - window.setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff); - - QStateMachine machine; - machine.setGlobalRestorePolicy(QState::RestoreProperties); - - QState *group = new QState(&machine); - group->setObjectName("group"); - - QRect selectedRect(86, 86, 128, 128); - - QState *idleState = new QState(group); - group->setInitialState(idleState); - - QObjectList objects; - objects << p1 << p2 << p3 << p4; - createStates(objects, selectedRect, group); - createAnimations(objects, &machine); - - machine.setInitialState(group); - machine.start(); - - window.resize(300, 300); - window.show(); - - return app.exec(); -} - -#include "main.moc" diff --git a/examples/widgets/doc/images/addressbook-editdialog.png b/examples/widgets/doc/images/addressbook-editdialog.png Binary files differindex fd41ee63f7..7434aa44ef 100644 --- a/examples/widgets/doc/images/addressbook-editdialog.png +++ b/examples/widgets/doc/images/addressbook-editdialog.png diff --git a/examples/widgets/doc/images/addressbook-example.png b/examples/widgets/doc/images/addressbook-example.png Binary files differindex b743c166da..eebe97a718 100644 --- a/examples/widgets/doc/images/addressbook-example.png +++ b/examples/widgets/doc/images/addressbook-example.png diff --git a/examples/widgets/doc/images/addressbook-newaddresstab.png b/examples/widgets/doc/images/addressbook-newaddresstab.png Binary files differindex ff215a4b20..6b60ee08e9 100644 --- a/examples/widgets/doc/images/addressbook-newaddresstab.png +++ b/examples/widgets/doc/images/addressbook-newaddresstab.png diff --git a/examples/widgets/doc/src/appchooser.qdoc b/examples/widgets/doc/src/appchooser.qdoc deleted file mode 100644 index e74860214a..0000000000 --- a/examples/widgets/doc/src/appchooser.qdoc +++ /dev/null @@ -1,38 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the documentation of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:FDL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Free Documentation License Usage -** Alternatively, this file may be used under the terms of the GNU Free -** Documentation License version 1.3 as published by the Free Software -** Foundation and appearing in the file included in the packaging of -** this file. Please review the following information to ensure -** the GNU Free Documentation License version 1.3 requirements -** will be met: https://www.gnu.org/licenses/fdl-1.3.html. -** $QT_END_LICENSE$ -** -****************************************************************************/ - -/*! - \example animation/appchooser - \title Application Chooser Example - - \brief The Application Chooser example shows how to use the Qt state - machine and the animation framework to select between - applications. - - \image appchooser-example.png - -*/ diff --git a/examples/widgets/doc/src/customsortfiltermodel.qdoc b/examples/widgets/doc/src/customsortfiltermodel.qdoc index 0eb6560e10..6eab846e89 100644 --- a/examples/widgets/doc/src/customsortfiltermodel.qdoc +++ b/examples/widgets/doc/src/customsortfiltermodel.qdoc @@ -75,7 +75,7 @@ QSortFilterProxyModel's default implementations of functions are written so that they call the equivalent functions in the relevant source model. This simple proxying mechanism may need to be - overridden for source models with more complex behavior; in this + overridden for source models with more complex behavior. In this example we derive from the QSortFilterProxyModel class to ensure that our filter can recognize a valid range of dates, and to control the sorting behavior. @@ -170,7 +170,7 @@ We implement two private slots, \c textFilterChanged() and \c dateFilterChanged(), to respond to the user changing the filter - pattern, case sensitivity or any of the dates. In addition, we + pattern, case sensitivity, or any of the dates. In addition, we implement a public \c setSourceModel() convenience function to set up the model/ view relation. @@ -197,7 +197,7 @@ \snippet itemviews/customsortfiltermodel/window.cpp 1 The QTreeView class provides a default model/view implementation - of a tree view; our view implements a tree representation of items + of a tree view. Our view implements a tree representation of items in the application's source model. \snippet itemviews/customsortfiltermodel/window.cpp 2 diff --git a/examples/widgets/doc/src/lighting.qdoc b/examples/widgets/doc/src/lighting.qdoc deleted file mode 100644 index 994172cf5d..0000000000 --- a/examples/widgets/doc/src/lighting.qdoc +++ /dev/null @@ -1,35 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the documentation of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:FDL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Free Documentation License Usage -** Alternatively, this file may be used under the terms of the GNU Free -** Documentation License version 1.3 as published by the Free Software -** Foundation and appearing in the file included in the packaging of -** this file. Please review the following information to ensure -** the GNU Free Documentation License version 1.3 requirements -** will be met: https://www.gnu.org/licenses/fdl-1.3.html. -** $QT_END_LICENSE$ -** -****************************************************************************/ - -/*! - \example effects/lighting - \title Lighting Effect Example - \ingroup examples-graphicsview-graphicseffects - \brief Demonstrates how to apply effects on items in the view - - \image lightingeffect-example.png -*/ diff --git a/examples/widgets/doc/src/stardelegate.qdoc b/examples/widgets/doc/src/stardelegate.qdoc index dcc7080456..44d17662ca 100644 --- a/examples/widgets/doc/src/stardelegate.qdoc +++ b/examples/widgets/doc/src/stardelegate.qdoc @@ -37,7 +37,7 @@ When displaying data in a QListView, QTableView, or QTreeView, the individual items are drawn by a \l{Delegate Classes}{delegate}. Also, when the user starts - editing an item (e.g., by double-clicking the item), the delegate + editing an item (for example, by double-clicking the item), the delegate provides an editor widget that is placed on top of the item while editing takes place. @@ -96,9 +96,9 @@ QItemDelegate paint it for us. This ensures that the \c StarDelegate can handle the most common data types. - In the case where the item is a \c StarRating, we draw the - background if the item is selected, and we draw the item using \c - StarRating::paint(), which we will review later. + If the item is a \c StarRating, we draw the background if the + item is selected, and we draw the item using \c StarRating::paint(), + which we will review later. \c{StartRating}s can be stored in a QVariant thanks to the Q_DECLARE_METATYPE() macro appearing in \c starrating.h. More on @@ -133,8 +133,8 @@ We simply call \c setStarRating() on the editor. The \l{QAbstractItemDelegate::}{setModelData()} function is - called when editing is finished, to commit data from the editor - to the model: + called to commit data from the editor to the model when editing + is finished: \snippet itemviews/stardelegate/stardelegate.cpp 4 @@ -210,7 +210,7 @@ current rating, and \c myMaxStarCount stores the highest possible rating (typically 5). - The Q_DECLARE_METATYPE() macro makes the type \c StarRating known + The \c Q_DECLARE_METATYPE() macro makes the type \c StarRating known to QVariant, making it possible to store \c StarRating values in QVariant. @@ -283,7 +283,7 @@ \list \li It is possible to open editors programmatically by calling QAbstractItemView::edit(), instead of relying on edit - triggers. This could be use to support other edit triggers + triggers. This could be used to support other edit triggers than those offered by the QAbstractItemView::EditTrigger enum. For example, in the Star Delegate example, hovering over an item with the mouse might make sense as a way to pop up an diff --git a/examples/widgets/doc/src/stylesheet.qdoc b/examples/widgets/doc/src/stylesheet.qdoc index 0016836f0d..a86b697059 100644 --- a/examples/widgets/doc/src/stylesheet.qdoc +++ b/examples/widgets/doc/src/stylesheet.qdoc @@ -33,5 +33,56 @@ \borderedimage stylesheet-pagefold.png \caption Screen Shot of the Pagefold style sheet + + The Style Sheet example shows how widgets can be styled using Qt Style Sheets. + You can open the style editor by selecting \uicontrol File > \uicontrol Edit Style Sheet, + to select an existing style sheet or design your own style and load it. + + The Style Sheet example consists of 2 classes: + \list + \li \c MainWindow + \li \c StyleSheetEditor + \endlist + + + \section1 MainWindow Class + + \c MainWindow inherits QWidget, and is the application's main window defined in + \c mainwindow.ui. The style of \c MainWindow can be modified with \l StyleSheetEditor. + + + \section1 StyleSheetEditor Class + + \c StyleSheetEditor enables you to open an editor where you can load an existing style sheet. + It is also possible to define a new stylesheet and load it. Its layout is defined in + \c stylesheeteditor.ui. + + \quotefromfile widgets/stylesheet/stylesheeteditor.cpp + \skipto on_styleCombo_activated + \printline on_styleCombo_activated + + Sets the specified \a styleName and grays the \c applyButton. + + \skipto on_styleSheetCombo_activated + \printline on_styleSheetCombo_activated + + Loads the stylesheet from \c styleSheetName. + + \skipto on_styleTextEdit_textChanged() + \printline on_styleTextEdit_textChanged() + + Enables the \c applyButton when the text in the buffer has changed. + + \skipto on_applyButton_clicked() + \printline on_applyButton_clicked() + + Sets the stylesheet properties in \l qApp and disables the \c applyButton. + + \skipto loadStyleSheet(const QString &sheetName) + \printline loadStyleSheet(const QString &sheetName) + + Loads the specified \a sheetName, and sets its properties in + \l qApp. + */ diff --git a/examples/widgets/doc/src/validators.qdoc b/examples/widgets/doc/src/validators.qdoc index f3f4dc5e63..bbb2e5f7b6 100644 --- a/examples/widgets/doc/src/validators.qdoc +++ b/examples/widgets/doc/src/validators.qdoc @@ -31,4 +31,6 @@ \ingroup examples-widgets \brief The Validators example shows the signal emission behavior of input validators. + + \borderedimage validators.png */ diff --git a/examples/widgets/effects/effects.pro b/examples/widgets/effects/effects.pro index 795e0508ac..05911979b9 100644 --- a/examples/widgets/effects/effects.pro +++ b/examples/widgets/effects/effects.pro @@ -2,5 +2,4 @@ TEMPLATE = \ subdirs SUBDIRS = \ blurpicker \ - lighting \ fademessage diff --git a/examples/widgets/effects/lighting/lighting.cpp b/examples/widgets/effects/lighting/lighting.cpp deleted file mode 100644 index 1ba7dd9ce7..0000000000 --- a/examples/widgets/effects/lighting/lighting.cpp +++ /dev/null @@ -1,145 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the examples of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:BSD$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** BSD License Usage -** Alternatively, you may use this file under the terms of the BSD license -** as follows: -** -** "Redistribution and use in source and binary forms, with or without -** modification, are permitted provided that the following conditions are -** met: -** * Redistributions of source code must retain the above copyright -** notice, this list of conditions and the following disclaimer. -** * Redistributions in binary form must reproduce the above copyright -** notice, this list of conditions and the following disclaimer in -** the documentation and/or other materials provided with the -** distribution. -** * Neither the name of The Qt Company Ltd nor the names of its -** contributors may be used to endorse or promote products derived -** from this software without specific prior written permission. -** -** -** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "lighting.h" -#include <QtWidgets> -#include <QtCore/qmath.h> - -Lighting::Lighting(QWidget *parent): QGraphicsView(parent), angle(0.0) -{ - setScene(&m_scene); - - setupScene(); - - QTimer *timer = new QTimer(this); - connect(timer, SIGNAL(timeout()), SLOT(animate())); - timer->setInterval(30); - timer->start(); - - setRenderHint(QPainter::Antialiasing, true); - setFrameStyle(QFrame::NoFrame); -} - -void Lighting::setupScene() -{ - m_scene.setSceneRect(-300, -200, 600, 460); - - QLinearGradient linearGrad(QPointF(-100, -100), QPointF(100, 100)); - linearGrad.setColorAt(0, QColor(255, 255, 255)); - linearGrad.setColorAt(1, QColor(192, 192, 255)); - setBackgroundBrush(linearGrad); - - QRadialGradient radialGrad(30, 30, 30); - radialGrad.setColorAt(0, Qt::yellow); - radialGrad.setColorAt(0.2, Qt::yellow); - radialGrad.setColorAt(1, Qt::transparent); - QPixmap pixmap(60, 60); - pixmap.fill(Qt::transparent); - QPainter painter(&pixmap); - painter.setPen(Qt::NoPen); - painter.setBrush(radialGrad); - painter.drawEllipse(0, 0, 60, 60); - painter.end(); - - m_lightSource = m_scene.addPixmap(pixmap); - m_lightSource->setZValue(2); - - for (int i = -2; i < 3; ++i) - for (int j = -2; j < 3; ++j) { - QAbstractGraphicsShapeItem *item; - if ((i + j) & 1) - item = new QGraphicsEllipseItem(0, 0, 50, 50); - else - item = new QGraphicsRectItem(0, 0, 50, 50); - - item->setPen(QPen(Qt::black, 1)); - item->setBrush(QBrush(Qt::white)); - QGraphicsDropShadowEffect *effect = new QGraphicsDropShadowEffect; - effect->setBlurRadius(8); - item->setGraphicsEffect(effect); - item->setZValue(1); - item->setPos(i * 80, j * 80); - m_scene.addItem(item); - m_items << item; - } - - -} - -void Lighting::animate() -{ - angle += qDegreesToRadians(qreal(6)); - qreal xs = 200 * qSin(angle) - 40 + 25; - qreal ys = 200 * qCos(angle) - 40 + 25; - m_lightSource->setPos(xs, ys); - - for (int i = 0; i < m_items.size(); ++i) { - QGraphicsItem *item = m_items.at(i); - Q_ASSERT(item); - QGraphicsDropShadowEffect *effect = static_cast<QGraphicsDropShadowEffect *>(item->graphicsEffect()); - Q_ASSERT(effect); - - QPointF delta(item->x() - xs, item->y() - ys); - effect->setOffset(delta.toPoint() / 30); - - qreal dx = delta.x(); - qreal dy = delta.y(); - qreal dd = qSqrt(dx * dx + dy * dy); - QColor color = effect->color(); - color.setAlphaF(qBound(0.4, 1 - dd / 200.0, 0.7)); - effect->setColor(color); - } - - m_scene.update(); -} - -void Lighting::resizeEvent(QResizeEvent * /* event */) -{ -} diff --git a/examples/widgets/effects/lighting/lighting.h b/examples/widgets/effects/lighting/lighting.h deleted file mode 100644 index 615824d46f..0000000000 --- a/examples/widgets/effects/lighting/lighting.h +++ /dev/null @@ -1,80 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the examples of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:BSD$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** BSD License Usage -** Alternatively, you may use this file under the terms of the BSD license -** as follows: -** -** "Redistribution and use in source and binary forms, with or without -** modification, are permitted provided that the following conditions are -** met: -** * Redistributions of source code must retain the above copyright -** notice, this list of conditions and the following disclaimer. -** * Redistributions in binary form must reproduce the above copyright -** notice, this list of conditions and the following disclaimer in -** the documentation and/or other materials provided with the -** distribution. -** * Neither the name of The Qt Company Ltd nor the names of its -** contributors may be used to endorse or promote products derived -** from this software without specific prior written permission. -** -** -** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef LIGHTING_H -#define LIGHTING_H - -#include <QGraphicsEffect> -#include <QGraphicsView> - -class Lighting: public QGraphicsView -{ - Q_OBJECT - -public: - Lighting(QWidget *parent = 0); - -private slots: - void animate(); - -private: - void setupScene(); - -protected: - void resizeEvent(QResizeEvent *event) override; - -private: - qreal angle; - QGraphicsScene m_scene; - QGraphicsItem *m_lightSource; - QList<QGraphicsItem*> m_items; -}; - -#endif // LIGHTING_H diff --git a/examples/widgets/effects/lighting/lighting.pro b/examples/widgets/effects/lighting/lighting.pro deleted file mode 100644 index 0a3b397de5..0000000000 --- a/examples/widgets/effects/lighting/lighting.pro +++ /dev/null @@ -1,8 +0,0 @@ -QT += widgets - -SOURCES += main.cpp lighting.cpp -HEADERS += lighting.h - -# install -target.path = $$[QT_INSTALL_EXAMPLES]/widgets/effects/lighting -INSTALLS += target diff --git a/examples/widgets/effects/lighting/main.cpp b/examples/widgets/effects/lighting/main.cpp deleted file mode 100644 index 22e55c0985..0000000000 --- a/examples/widgets/effects/lighting/main.cpp +++ /dev/null @@ -1,65 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the examples of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:BSD$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** BSD License Usage -** Alternatively, you may use this file under the terms of the BSD license -** as follows: -** -** "Redistribution and use in source and binary forms, with or without -** modification, are permitted provided that the following conditions are -** met: -** * Redistributions of source code must retain the above copyright -** notice, this list of conditions and the following disclaimer. -** * Redistributions in binary form must reproduce the above copyright -** notice, this list of conditions and the following disclaimer in -** the documentation and/or other materials provided with the -** distribution. -** * Neither the name of The Qt Company Ltd nor the names of its -** contributors may be used to endorse or promote products derived -** from this software without specific prior written permission. -** -** -** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "lighting.h" -#include <QApplication> - -int main(int argc, char **argv) -{ - QApplication app(argc, argv); - - Lighting lighting; - lighting.setWindowTitle(QT_TRANSLATE_NOOP(QGraphicsView, "Lighting and Shadows")); - - lighting.resize(640, 480); - lighting.show(); - - return app.exec(); -} diff --git a/examples/widgets/painting/affine/xform.cpp b/examples/widgets/painting/affine/xform.cpp index e47bc9d251..20f6eb3c6d 100644 --- a/examples/widgets/painting/affine/xform.cpp +++ b/examples/widgets/painting/affine/xform.cpp @@ -77,8 +77,8 @@ XFormView::XFormView(QWidget *parent) pts->setBoundingRect(QRectF(0, 0, 500, 500)); ctrlPoints << QPointF(250, 250) << QPointF(350, 250); pts->setPoints(ctrlPoints); - connect(pts, SIGNAL(pointsChanged(QPolygonF)), - this, SLOT(updateCtrlPoints(QPolygonF))); + connect(pts, &HoverPoints::pointsChanged, + this,&XFormView::updateCtrlPoints); setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); } @@ -876,29 +876,29 @@ XFormWidget::XFormWidget(QWidget *parent) #endif mainGroupLayout->addWidget(whatsThisButton); - connect(rotateSlider, SIGNAL(valueChanged(int)), view, SLOT(changeRotation(int))); - connect(shearSlider, SIGNAL(valueChanged(int)), view, SLOT(changeShear(int))); - connect(scaleSlider, SIGNAL(valueChanged(int)), view, SLOT(changeScale(int))); - - connect(vectorType, SIGNAL(clicked()), view, SLOT(setVectorType())); - connect(pixmapType, SIGNAL(clicked()), view, SLOT(setPixmapType())); - connect(textType, SIGNAL(clicked()), view, SLOT(setTextType())); - connect(textType, SIGNAL(toggled(bool)), textEditor, SLOT(setEnabled(bool))); - connect(textEditor, SIGNAL(textChanged(QString)), view, SLOT(setText(QString))); - - connect(view, SIGNAL(rotationChanged(int)), rotateSlider, SLOT(setValue(int))); - connect(view, SIGNAL(scaleChanged(int)), scaleSlider, SLOT(setValue(int))); - connect(view, SIGNAL(shearChanged(int)), shearSlider, SLOT(setValue(int))); - - connect(resetButton, SIGNAL(clicked()), view, SLOT(reset())); - connect(animateButton, SIGNAL(clicked(bool)), view, SLOT(setAnimation(bool))); - connect(whatsThisButton, SIGNAL(clicked(bool)), view, SLOT(setDescriptionEnabled(bool))); - connect(whatsThisButton, SIGNAL(clicked(bool)), view->hoverPoints(), SLOT(setDisabled(bool))); - connect(view, SIGNAL(descriptionEnabledChanged(bool)), view->hoverPoints(), SLOT(setDisabled(bool))); - connect(view, SIGNAL(descriptionEnabledChanged(bool)), whatsThisButton, SLOT(setChecked(bool))); - connect(showSourceButton, SIGNAL(clicked()), view, SLOT(showSource())); + connect(rotateSlider, &QSlider::valueChanged, view, &XFormView::changeRotation); + connect(shearSlider, &QSlider::valueChanged, view, &XFormView::changeShear); + connect(scaleSlider, &QSlider::valueChanged, view, &XFormView::changeScale); + + connect(vectorType, &QRadioButton::clicked, view, &XFormView::setVectorType); + connect(pixmapType, &QRadioButton::clicked, view, &XFormView::setPixmapType); + connect(textType, &QRadioButton::clicked, view, &XFormView::setTextType); + connect(textType, &QRadioButton::toggled, textEditor, &XFormView::setEnabled); + connect(textEditor, &QLineEdit::textChanged, view, &XFormView::setText); + + connect(view, &XFormView::rotationChanged, rotateSlider, &QSlider::setValue); + connect(view, &XFormView::scaleChanged, scaleSlider, &QAbstractSlider::setValue); + connect(view, &XFormView::shearChanged, shearSlider, &QAbstractSlider::setValue); + + connect(resetButton, &QPushButton::clicked, view, &XFormView::reset); + connect(animateButton, &QPushButton::clicked, view, &XFormView::setAnimation); + connect(whatsThisButton, &QPushButton::clicked, view, &ArthurFrame::setDescriptionEnabled); + connect(whatsThisButton, &QPushButton::clicked, view->hoverPoints(), &HoverPoints::setDisabled); + connect(view, &XFormView::descriptionEnabledChanged, view->hoverPoints(), &HoverPoints::setDisabled); + connect(view, &XFormView::descriptionEnabledChanged, whatsThisButton, &QPushButton::setChecked); + connect(showSourceButton, &QPushButton::clicked, view, &XFormView::showSource); #ifdef QT_OPENGL_SUPPORT - connect(enableOpenGLButton, SIGNAL(clicked(bool)), view, SLOT(enableOpenGL(bool))); + connect(enableOpenGLButton, &QPushButton::clicked, view, &XFormView::enableOpenGL); #endif view->loadSourceFile(":res/affine/xform.cpp"); view->loadDescription(":res/affine/xform.html"); diff --git a/examples/widgets/widgets/tablet/mainwindow.cpp b/examples/widgets/widgets/tablet/mainwindow.cpp index c02e02f0a4..994666d4de 100644 --- a/examples/widgets/widgets/tablet/mainwindow.cpp +++ b/examples/widgets/widgets/tablet/mainwindow.cpp @@ -60,6 +60,7 @@ MainWindow::MainWindow(TabletCanvas *canvas) createMenus(); setWindowTitle(tr("Tablet Example")); setCentralWidget(m_canvas); + QCoreApplication::setAttribute(Qt::AA_CompressHighFrequencyEvents); } //! [0] @@ -97,6 +98,11 @@ void MainWindow::setSaturationValuator(QAction *action) } //! [4] +void MainWindow::setEventCompression(bool compress) +{ + QCoreApplication::setAttribute(Qt::AA_CompressTabletEvents, compress); +} + //! [5] void MainWindow::save() { @@ -220,6 +226,10 @@ void MainWindow::createMenus() connect(colorSaturationGroup, &QActionGroup::triggered, this, &MainWindow::setSaturationValuator); + QAction *compressAction = tabletMenu->addAction(tr("Co&mpress events")); + compressAction->setCheckable(true); + connect(compressAction, &QAction::toggled, this, &MainWindow::setEventCompression); + QMenu *helpMenu = menuBar()->addMenu("&Help"); helpMenu->addAction(tr("A&bout"), this, &MainWindow::about); helpMenu->addAction(tr("About &Qt"), qApp, &QApplication::aboutQt); diff --git a/examples/widgets/widgets/tablet/mainwindow.h b/examples/widgets/widgets/tablet/mainwindow.h index 68af1f1687..4b99324f04 100644 --- a/examples/widgets/widgets/tablet/mainwindow.h +++ b/examples/widgets/widgets/tablet/mainwindow.h @@ -71,6 +71,7 @@ private slots: void setAlphaValuator(QAction *action); void setLineWidthValuator(QAction *action); void setSaturationValuator(QAction *action); + void setEventCompression(bool compress); void save(); void load(); void about(); diff --git a/src/android/jar/src/org/qtproject/qt5/android/QtActivityDelegate.java b/src/android/jar/src/org/qtproject/qt5/android/QtActivityDelegate.java index 720a35902b..84d5adf856 100644 --- a/src/android/jar/src/org/qtproject/qt5/android/QtActivityDelegate.java +++ b/src/android/jar/src/org/qtproject/qt5/android/QtActivityDelegate.java @@ -723,184 +723,189 @@ public class QtActivityDelegate Bundle extras = m_activity.getIntent().getExtras(); if (extras != null) { - if ( /*(ai.flags&ApplicationInfo.FLAG_DEBUGGABLE) != 0 - &&*/ extras.containsKey("debug_ping") - && extras.getString("debug_ping").equals("true")) { - try { - final String dc = "--Added-by-androiddeployqt--/debugger.command"; - String debuggerCommand = - new BufferedReader(new InputStreamReader(m_activity.getAssets().open(dc))).readLine(); - String packagePath = - m_activity.getPackageManager().getApplicationInfo(m_activity.getPackageName(), - PackageManager.GET_CONFIGURATIONS).dataDir + "/"; - - debugLog("extra parameters: " + extras); - String packageName = m_activity.getPackageName(); - String pingFile = extras.getString("ping_file"); - String pongFile = extras.getString("pong_file"); - String gdbserverSocket = extras.getString("gdbserver_socket"); - String gdbserverCommand = packagePath + debuggerCommand + gdbserverSocket; - String pingSocket = extras.getString("ping_socket"); - boolean usePing = pingFile != null; - boolean usePong = pongFile != null; - boolean useSocket = gdbserverSocket != null; - boolean usePingSocket = pingSocket != null; - int napTime = 200; // milliseconds between file accesses - int timeOut = 30000; // ms until we give up on ping and pong - int maxAttempts = timeOut / napTime; - - if (gdbserverSocket != null) { - debugLog("removing gdb socket " + gdbserverSocket); - new File(gdbserverSocket).delete(); - } - - if (usePing) { - debugLog("removing ping file " + pingFile); - File ping = new File(pingFile); - if (ping.exists()) { - if (!ping.delete()) - debugLog("ping file cannot be deleted"); + try { + final String dc = "--Added-by-androiddeployqt--/debugger.command"; + String debuggerCommand = + new BufferedReader(new InputStreamReader(m_activity.getAssets().open(dc))).readLine(); + if ( /*(ai.flags&ApplicationInfo.FLAG_DEBUGGABLE) != 0 + &&*/ extras.containsKey("debug_ping") + && extras.getString("debug_ping").equals("true")) { + try { + String packagePath = + m_activity.getPackageManager().getApplicationInfo(m_activity.getPackageName(), + PackageManager.GET_CONFIGURATIONS).dataDir + "/"; + + debugLog("extra parameters: " + extras); + String packageName = m_activity.getPackageName(); + String pingFile = extras.getString("ping_file"); + String pongFile = extras.getString("pong_file"); + String gdbserverSocket = extras.getString("gdbserver_socket"); + String gdbserverCommand = packagePath + debuggerCommand + gdbserverSocket; + String pingSocket = extras.getString("ping_socket"); + boolean usePing = pingFile != null; + boolean usePong = pongFile != null; + boolean useSocket = gdbserverSocket != null; + boolean usePingSocket = pingSocket != null; + int napTime = 200; // milliseconds between file accesses + int timeOut = 30000; // ms until we give up on ping and pong + int maxAttempts = timeOut / napTime; + + if (gdbserverSocket != null) { + debugLog("removing gdb socket " + gdbserverSocket); + new File(gdbserverSocket).delete(); } - } - if (usePong) { - debugLog("removing pong file " + pongFile); - File pong = new File(pongFile); - if (pong.exists()) { - if (!pong.delete()) - debugLog("pong file cannot be deleted"); + if (usePing) { + debugLog("removing ping file " + pingFile); + File ping = new File(pingFile); + if (ping.exists()) { + if (!ping.delete()) + debugLog("ping file cannot be deleted"); + } } - } - debugLog("starting " + gdbserverCommand); - m_debuggerProcess = Runtime.getRuntime().exec(gdbserverCommand); - debugLog("gdbserver started"); - - if (useSocket) { - int i; - for (i = 0; i < maxAttempts; ++i) { - debugLog("waiting for socket at " + gdbserverSocket + ", attempt " + i); - File file = new File(gdbserverSocket); - if (file.exists()) { - file.setReadable(true, false); - file.setWritable(true, false); - file.setExecutable(true, false); - break; + if (usePong) { + debugLog("removing pong file " + pongFile); + File pong = new File(pongFile); + if (pong.exists()) { + if (!pong.delete()) + debugLog("pong file cannot be deleted"); } - Thread.sleep(napTime); } - if (i == maxAttempts) { - debugLog("time out when waiting for debug socket"); - return false; + debugLog("starting " + gdbserverCommand); + m_debuggerProcess = Runtime.getRuntime().exec(gdbserverCommand); + debugLog("gdbserver started"); + + if (useSocket) { + int i; + for (i = 0; i < maxAttempts; ++i) { + debugLog("waiting for socket at " + gdbserverSocket + ", attempt " + i); + File file = new File(gdbserverSocket); + if (file.exists()) { + file.setReadable(true, false); + file.setWritable(true, false); + file.setExecutable(true, false); + break; + } + Thread.sleep(napTime); + } + + if (i == maxAttempts) { + debugLog("time out when waiting for debug socket"); + return false; + } + + debugLog("socket ok"); + } else { + debugLog("socket not used"); } - debugLog("socket ok"); - } else { - debugLog("socket not used"); - } + if (usePingSocket) { + DebugWaitRunnable runnable = new DebugWaitRunnable(pingSocket); + Thread waitThread = new Thread(runnable); + waitThread.start(); - if (usePingSocket) { - DebugWaitRunnable runnable = new DebugWaitRunnable(pingSocket); - Thread waitThread = new Thread(runnable); - waitThread.start(); + int i; + for (i = 0; i < maxAttempts && waitThread.isAlive(); ++i) { + debugLog("Waiting for debug socket connect"); + debugLog("go to sleep"); + Thread.sleep(napTime); + } - int i; - for (i = 0; i < maxAttempts && waitThread.isAlive(); ++i) { - debugLog("Waiting for debug socket connect"); - debugLog("go to sleep"); - Thread.sleep(napTime); - } + if (i == maxAttempts) { + debugLog("time out when waiting for ping socket"); + runnable.shutdown(); + return false; + } - if (i == maxAttempts) { - debugLog("time out when waiting for ping socket"); - runnable.shutdown(); - return false; + if (runnable.wasFailure) { + debugLog("Could not connect to debug client"); + return false; + } else { + debugLog("Got pid acknowledgment"); + } } - if (runnable.wasFailure) { - debugLog("Could not connect to debug client"); - return false; + if (usePing) { + // Tell we are ready. + debugLog("writing ping at " + pingFile); + FileWriter writer = new FileWriter(pingFile); + writer.write("" + android.os.Process.myPid()); + writer.close(); + File file = new File(pingFile); + file.setReadable(true, false); + file.setWritable(true, false); + file.setExecutable(true, false); + debugLog("wrote ping"); } else { - debugLog("Got pid acknowledgment"); + debugLog("ping not requested"); } - } - if (usePing) { - // Tell we are ready. - debugLog("writing ping at " + pingFile); - FileWriter writer = new FileWriter(pingFile); - writer.write("" + android.os.Process.myPid()); - writer.close(); - File file = new File(pingFile); - file.setReadable(true, false); - file.setWritable(true, false); - file.setExecutable(true, false); - debugLog("wrote ping"); - } else { - debugLog("ping not requested"); - } + // Wait until other side is ready. + if (usePong) { + int i; + for (i = 0; i < maxAttempts; ++i) { + debugLog("waiting for pong at " + pongFile + ", attempt " + i); + File file = new File(pongFile); + if (file.exists()) { + file.delete(); + break; + } + debugLog("go to sleep"); + Thread.sleep(napTime); + } + debugLog("Removing pingFile " + pingFile); + new File(pingFile).delete(); - // Wait until other side is ready. - if (usePong) { - int i; - for (i = 0; i < maxAttempts; ++i) { - debugLog("waiting for pong at " + pongFile + ", attempt " + i); - File file = new File(pongFile); - if (file.exists()) { - file.delete(); - break; + if (i == maxAttempts) { + debugLog("time out when waiting for pong file"); + return false; } - debugLog("go to sleep"); - Thread.sleep(napTime); - } - debugLog("Removing pingFile " + pingFile); - new File(pingFile).delete(); - if (i == maxAttempts) { - debugLog("time out when waiting for pong file"); - return false; + debugLog("got pong " + pongFile); + } else { + debugLog("pong not requested"); } - debugLog("got pong " + pongFile); - } else { - debugLog("pong not requested"); + } catch (IOException ioe) { + ioe.printStackTrace(); + } catch (SecurityException se) { + se.printStackTrace(); } - - } catch (IOException ioe) { - ioe.printStackTrace(); - } catch (SecurityException se) { - se.printStackTrace(); } - } - if (/*(ai.flags&ApplicationInfo.FLAG_DEBUGGABLE) != 0 - &&*/ extras.containsKey("qml_debug") - && extras.getString("qml_debug").equals("true")) { - String qmljsdebugger; - if (extras.containsKey("qmljsdebugger")) { - qmljsdebugger = extras.getString("qmljsdebugger"); - qmljsdebugger.replaceAll("\\s", ""); // remove whitespace for security - } else { - qmljsdebugger = "port:3768"; + if (/*(ai.flags&ApplicationInfo.FLAG_DEBUGGABLE) != 0 + &&*/ extras.containsKey("qml_debug") + && extras.getString("qml_debug").equals("true")) { + String qmljsdebugger; + if (extras.containsKey("qmljsdebugger")) { + qmljsdebugger = extras.getString("qmljsdebugger"); + qmljsdebugger.replaceAll("\\s", ""); // remove whitespace for security + } else { + qmljsdebugger = "port:3768"; + } + m_applicationParameters += "\t-qmljsdebugger=" + qmljsdebugger; } - m_applicationParameters += "\t-qmljsdebugger=" + qmljsdebugger; - } - if (extras.containsKey("extraenvvars")) { - try { - m_environmentVariables += "\t" + new String(Base64.decode(extras.getString("extraenvvars"), Base64.DEFAULT), "UTF-8"); - } catch (Exception e) { - e.printStackTrace(); + if (extras.containsKey("extraenvvars")) { + try { + m_environmentVariables += "\t" + new String(Base64.decode(extras.getString("extraenvvars"), Base64.DEFAULT), "UTF-8"); + } catch (Exception e) { + e.printStackTrace(); + } } - } - if (extras.containsKey("extraappparams")) { - try { - m_applicationParameters += "\t" + new String(Base64.decode(extras.getString("extraappparams"), Base64.DEFAULT), "UTF-8"); - } catch (Exception e) { - e.printStackTrace(); + if (extras.containsKey("extraappparams")) { + try { + m_applicationParameters += "\t" + new String(Base64.decode(extras.getString("extraappparams"), Base64.DEFAULT), "UTF-8"); + } catch (Exception e) { + e.printStackTrace(); + } } + } catch (Exception e) { + // This is not an error, so keep it silent + // e.printStackTrace(); } } // extras != null diff --git a/src/corelib/Qt5CoreMacros.cmake b/src/corelib/Qt5CoreMacros.cmake index 489bc75511..8b65db95cb 100644 --- a/src/corelib/Qt5CoreMacros.cmake +++ b/src/corelib/Qt5CoreMacros.cmake @@ -137,6 +137,9 @@ function(QT5_CREATE_MOC_COMMAND infile outfile moc_flags moc_options moc_target DEPENDS ${infile} ${moc_depends} ${_moc_working_dir} VERBATIM) + set_source_files_properties(${infile} PROPERTIES SKIP_AUTOMOC ON) + set_source_files_properties(${outfile} PROPERTIES SKIP_AUTOMOC ON) + set_source_files_properties(${outfile} PROPERTIES SKIP_AUTOUIC ON) endfunction() @@ -155,7 +158,6 @@ function(QT5_GENERATE_MOC infile outfile ) set(moc_target ${ARGV3}) endif() qt5_create_moc_command(${abs_infile} ${_outfile} "${moc_flags}" "" "${moc_target}" "") - set_source_files_properties(${outfile} PROPERTIES SKIP_AUTOMOC TRUE) # dont run automoc on this file endfunction() @@ -246,6 +248,7 @@ function(QT5_ADD_BINARY_RESOURCES target ) get_filename_component(infile ${it} ABSOLUTE) _QT5_PARSE_QRC_FILE(${infile} _out_depends _rc_depends) + set_source_files_properties(${infile} PROPERTIES SKIP_AUTORCC ON) set(infiles ${infiles} ${infile}) set(out_depends ${out_depends} ${_out_depends}) set(rc_depends ${rc_depends} ${_rc_depends}) @@ -255,7 +258,6 @@ function(QT5_ADD_BINARY_RESOURCES target ) COMMAND ${Qt5Core_RCC_EXECUTABLE} ARGS ${rcc_options} --binary --name ${target} --output ${rcc_destination} ${infiles} DEPENDS ${rc_depends} ${out_depends} VERBATIM) - add_custom_target(${target} ALL DEPENDS ${rcc_destination}) endfunction() @@ -283,12 +285,15 @@ function(QT5_ADD_RESOURCES outfiles ) set(outfile ${CMAKE_CURRENT_BINARY_DIR}/qrc_${outfilename}.cpp) _QT5_PARSE_QRC_FILE(${infile} _out_depends _rc_depends) + set_source_files_properties(${infile} PROPERTIES SKIP_AUTORCC ON) add_custom_command(OUTPUT ${outfile} COMMAND ${Qt5Core_RCC_EXECUTABLE} ARGS ${rcc_options} --name ${outfilename} --output ${outfile} ${infile} MAIN_DEPENDENCY ${infile} DEPENDS ${_rc_depends} "${out_depends}" VERBATIM) + set_source_files_properties(${outfile} PROPERTIES SKIP_AUTOMOC ON) + set_source_files_properties(${outfile} PROPERTIES SKIP_AUTOUIC ON) list(APPEND ${outfiles} ${outfile}) endforeach() set(${outfiles} ${${outfiles}} PARENT_SCOPE) diff --git a/src/corelib/global/qflags.h b/src/corelib/global/qflags.h index 4806f6cd74..c22c22d10a 100644 --- a/src/corelib/global/qflags.h +++ b/src/corelib/global/qflags.h @@ -150,7 +150,7 @@ public: Q_DECL_CONSTEXPR inline bool testFlag(Enum f) const Q_DECL_NOTHROW { return (i & Int(f)) == Int(f) && (Int(f) != 0 || i == Int(f) ); } Q_DECL_RELAXED_CONSTEXPR inline QFlags &setFlag(Enum f, bool on = true) Q_DECL_NOTHROW { - return on ? (*this |= f) : (*this &= ~f); + return on ? (*this |= f) : (*this &= ~Int(f)); } private: diff --git a/src/corelib/global/qfloat16.h b/src/corelib/global/qfloat16.h index 6b5c550b53..bf223bee0c 100644 --- a/src/corelib/global/qfloat16.h +++ b/src/corelib/global/qfloat16.h @@ -44,7 +44,16 @@ #include <QtCore/qmetatype.h> #include <string.h> -#if defined __F16C__ +#if defined(QT_COMPILER_SUPPORTS_F16C) && defined(__AVX2__) && !defined(__F16C__) +// All processors that support AVX2 do support F16C too. That doesn't mean +// we're allowed to use the intrinsics directly, so we'll do it only for +// the Intel and Microsoft's compilers. +# if defined(Q_CC_INTEL) || defined(Q_CC_MSVC) +# define __F16C__ 1 +# endif +#endif + +#if defined(QT_COMPILER_SUPPORTS_F16C) && defined(__F16C__) #include <immintrin.h> #endif @@ -119,7 +128,7 @@ QT_WARNING_DISABLE_CLANG("-Wc99-extensions") QT_WARNING_DISABLE_GCC("-Wold-style-cast") inline qfloat16::qfloat16(float f) Q_DECL_NOTHROW { -#if defined(QT_COMPILER_SUPPORTS_F16C) && (defined(__F16C__) || defined(__AVX2__)) +#if defined(QT_COMPILER_SUPPORTS_F16C) && defined(__F16C__) __m128 packsingle = _mm_set_ss(f); __m128i packhalf = _mm_cvtps_ph(packsingle, 0); b16 = _mm_extract_epi16(packhalf, 0); @@ -137,7 +146,7 @@ QT_WARNING_POP inline qfloat16::operator float() const Q_DECL_NOTHROW { -#if defined(QT_COMPILER_SUPPORTS_F16C) && (defined(__F16C__) || defined(__AVX2__)) +#if defined(QT_COMPILER_SUPPORTS_F16C) && defined(__F16C__) __m128i packhalf = _mm_cvtsi32_si128(b16); __m128 packsingle = _mm_cvtph_ps(packhalf); return _mm_cvtss_f32(packsingle); diff --git a/src/corelib/io/qiodevice.cpp b/src/corelib/io/qiodevice.cpp index 0a3e83206b..7d46898911 100644 --- a/src/corelib/io/qiodevice.cpp +++ b/src/corelib/io/qiodevice.cpp @@ -1879,7 +1879,7 @@ QByteArray QIODevice::peek(qint64 maxSize) } /*! - \since 5.11 + \since 5.10 Skips up to \a maxSize bytes from the device. Returns the number of bytes actually skipped, or -1 on error. diff --git a/src/corelib/io/qloggingregistry.cpp b/src/corelib/io/qloggingregistry.cpp index 0e7eaeea76..1bf61017f6 100644 --- a/src/corelib/io/qloggingregistry.cpp +++ b/src/corelib/io/qloggingregistry.cpp @@ -255,6 +255,7 @@ void QLoggingSettingsParser::parseNextLine(QStringRef line) QLoggingRegistry::QLoggingRegistry() : categoryFilter(defaultCategoryFilter) { + initalizeRules(); // Init on first use } static bool qtLoggingDebug() @@ -283,7 +284,7 @@ static QVector<QLoggingRule> loadRulesFromFile(const QString &filePath) Initializes the rules database by loading $QT_LOGGING_CONF, $QT_LOGGING_RULES, and .config/QtProject/qtlogging.ini. */ -void QLoggingRegistry::init() +void QLoggingRegistry::initalizeRules() { QVector<QLoggingRule> er, qr, cr; // get rules from environment diff --git a/src/corelib/io/qloggingregistry_p.h b/src/corelib/io/qloggingregistry_p.h index a68b993cca..a3857d3588 100644 --- a/src/corelib/io/qloggingregistry_p.h +++ b/src/corelib/io/qloggingregistry_p.h @@ -113,7 +113,7 @@ class Q_AUTOTEST_EXPORT QLoggingRegistry public: QLoggingRegistry(); - void init(); + void initalizeRules(); void registerCategory(QLoggingCategory *category, QtMsgType enableForLevel); void unregisterCategory(QLoggingCategory *category); diff --git a/src/corelib/io/qstandardpaths_win.cpp b/src/corelib/io/qstandardpaths_win.cpp index 41fd31df8b..eeb02419c3 100644 --- a/src/corelib/io/qstandardpaths_win.cpp +++ b/src/corelib/io/qstandardpaths_win.cpp @@ -201,6 +201,10 @@ QString QStandardPaths::writableLocation(StandardLocation type) return result; } +#ifndef QT_BOOTSTRAPPED +extern QString qAppFileName(); +#endif + QStringList QStandardPaths::standardLocations(StandardLocation type) { QStringList dirs; @@ -217,8 +221,13 @@ QStringList QStandardPaths::standardLocations(StandardLocation type) dirs.append(programData); } #ifndef QT_BOOTSTRAPPED - dirs.append(QCoreApplication::applicationDirPath()); - const QString dataDir = QCoreApplication::applicationDirPath() + QLatin1String("/data"); + // Note: QCoreApplication::applicationDirPath(), while static, requires + // an application instance. But we might need to resolve the standard + // locations earlier than that, so we fall back to qAppFileName(). + QString applicationDirPath = qApp ? QCoreApplication::applicationDirPath() + : QFileInfo(qAppFileName()).path(); + dirs.append(applicationDirPath); + const QString dataDir = applicationDirPath + QLatin1String("/data"); dirs.append(dataDir); if (!isGenericConfigLocation(type)) { diff --git a/src/corelib/kernel/qcoreapplication.cpp b/src/corelib/kernel/qcoreapplication.cpp index d1640bdc49..a3342ecd5f 100644 --- a/src/corelib/kernel/qcoreapplication.cpp +++ b/src/corelib/kernel/qcoreapplication.cpp @@ -802,8 +802,6 @@ void QCoreApplicationPrivate::init() if (!coreappdata()->applicationVersionSet) coreappdata()->applicationVersion = appVersion(); - QLoggingRegistry::instance()->init(); - #if QT_CONFIG(library) // Reset the lib paths, so that they will be recomputed, taking the availability of argv[0] // into account. If necessary, recompute right away and replay the manual changes on top of the diff --git a/src/corelib/thread/qsemaphore.cpp b/src/corelib/thread/qsemaphore.cpp index 21acc533a1..012628ef63 100644 --- a/src/corelib/thread/qsemaphore.cpp +++ b/src/corelib/thread/qsemaphore.cpp @@ -414,13 +414,18 @@ bool QSemaphore::tryAcquire(int n) bool QSemaphore::tryAcquire(int n, int timeout) { Q_ASSERT_X(n >= 0, "QSemaphore::tryAcquire", "parameter 'n' must be non-negative"); + + // We're documented to accept any negative value as "forever" + // but QDeadlineTimer only accepts -1. + timeout = qMax(timeout, -1); + if (futexAvailable()) - return futexSemaphoreTryAcquire<true>(u, n, timeout < 0 ? -1 : timeout); + return futexSemaphoreTryAcquire<true>(u, n, timeout); QDeadlineTimer timer(timeout); QMutexLocker locker(&d->mutex); qint64 remainingTime = timer.remainingTime(); - while (n > d->avail && remainingTime > 0) { + while (n > d->avail && remainingTime != 0) { if (!d->cond.wait(locker.mutex(), remainingTime)) return false; remainingTime = timer.remainingTime(); diff --git a/src/corelib/tools/qlocale.cpp b/src/corelib/tools/qlocale.cpp index c85dcb4358..179784c7ba 100644 --- a/src/corelib/tools/qlocale.cpp +++ b/src/corelib/tools/qlocale.cpp @@ -3809,17 +3809,18 @@ QString QLocale::toCurrencyString(double value, const QString &symbol, int preci /*! \since 5.10 - Converts a size in bytes to a human-readable localized string, expressed in - a unit for which the numeric portion is at least 1 but as low as - possible. For example if \a bytes is 16384, \a precision is 2, and \a format - is \c DataSizeIecFormat (the default), this function returns "16.00 KiB"; - for 1330409069609 bytes it returns "1.21 GiB"; and so on. If \a format is \c - DataSizeIecFormat or \c DataSizeTraditionalFormat, the given number of bytes - is divided by a power of 1024, with result less than 1024; for \c - DataSizeSIFormat, it is divided by a power of 1000, with result less than - 1000. DataSizeIecFormat uses the new IEC standard quantifiers Ki, Mi and so - on, whereas DataSizeSIFormat uses and DataSizeTraditionalFormat abuses the - older SI quantifiers k, M, etc. + Converts a size in bytes to a human-readable localized string, comprising a + number and a quantified unit. The quantifier is chosen such that the number + is at least one, and as small as possible. For example if \a bytes is + 16384, \a precision is 2, and \a format is \l DataSizeIecFormat (the + default), this function returns "16.00 KiB"; for 1330409069609 bytes it + returns "1.21 GiB"; and so on. If \a format is \l DataSizeIecFormat or + \l DataSizeTraditionalFormat, the given number of bytes is divided by a + power of 1024, with result less than 1024; for \l DataSizeSIFormat, it is + divided by a power of 1000, with result less than 1000. + \c DataSizeIecFormat uses the new IEC standard quantifiers Ki, Mi and so on, + whereas \c DataSizeSIFormat uses the older SI quantifiers k, M, etc., and + \c DataSizeTraditionalFormat abuses them. */ QString QLocale::formattedDataSize(qint64 bytes, int precision, DataSizeFormats format) { diff --git a/src/corelib/tools/qsimd.cpp b/src/corelib/tools/qsimd.cpp index 4c6f08c774..25340f2d02 100644 --- a/src/corelib/tools/qsimd.cpp +++ b/src/corelib/tools/qsimd.cpp @@ -652,32 +652,6 @@ Q_CORE_EXPORT QBasicAtomicInteger<unsigned> qt_cpu_features[2] = { Q_BASIC_ATOMI void qDetectCpuFeatures() { -#if defined(Q_CC_GNU) && !defined(Q_CC_CLANG) && !defined(Q_CC_INTEL) -# if Q_CC_GNU < 403 - // GCC 4.2 (at least the one that comes with Apple's XCode, on Mac) is - // known to be broken beyond repair in dealing with the inline assembly - // above. It will generate bad code that could corrupt important registers - // like the PIC register. The behaviour of code after this function would - // be totally unpredictable. - // - // For that reason, simply forego the CPUID check at all and return the set - // of features that we found at compile time, through the #defines from the - // compiler. This should at least allow code to execute, even if none of - // the specialized code found in Qt GUI and elsewhere will ever be enabled - // (it's the user's fault for using a broken compiler). - // - // This also disables the runtime checking that the processor actually - // contains all the features that the code required. Qt 4 ran for years - // like that, so it shouldn't be a problem. - - qt_cpu_features[0].store(minFeature | quint32(QSimdInitialized)); -#ifndef Q_ATOMIC_INT64_IS_SUPPORTED - qt_cpu_features[1].store(minFeature >> 32); -#endif - - return; -# endif -#endif quint64 f = detectProcessorFeatures(); QByteArray disable = qgetenv("QT_NO_CPU_FEATURE"); if (!disable.isEmpty()) { diff --git a/src/corelib/tools/qtimezoneprivate_tz.cpp b/src/corelib/tools/qtimezoneprivate_tz.cpp index bcc1285472..6a5df6272a 100644 --- a/src/corelib/tools/qtimezoneprivate_tz.cpp +++ b/src/corelib/tools/qtimezoneprivate_tz.cpp @@ -1050,7 +1050,18 @@ QByteArray QTzTimeZonePrivate::systemTimeZoneId() const if (ianaId == "/etc/localtime") ianaId.clear(); - // On Debian Etch and later /etc/localtime is real file with name held in /etc/timezone + // On most distros /etc/localtime is a symlink to a real file so extract name from the path + if (ianaId.isEmpty()) { + const QString path = QFile::symLinkTarget(QStringLiteral("/etc/localtime")); + if (!path.isEmpty()) { + // /etc/localtime is a symlink to the current TZ file, so extract from path + int index = path.indexOf(QLatin1String("/zoneinfo/")); + if (index != -1) + ianaId = path.mid(index + 10).toUtf8(); + } + } + + // On Debian Etch up to Jessie, /etc/localtime is a regular file while the actual name is in /etc/timezone if (ianaId.isEmpty()) { QFile tzif(QStringLiteral("/etc/timezone")); if (tzif.open(QIODevice::ReadOnly)) { @@ -1061,16 +1072,6 @@ QByteArray QTzTimeZonePrivate::systemTimeZoneId() const } } - // On other distros /etc/localtime is symlink to real file so can extract name from the path - if (ianaId.isEmpty()) { - const QString path = QFile::symLinkTarget(QStringLiteral("/etc/localtime")); - if (!path.isEmpty()) { - // /etc/localtime is a symlink to the current TZ file, so extract from path - int index = path.indexOf(QLatin1String("/zoneinfo/")) + 10; - ianaId = path.mid(index).toUtf8(); - } - } - // On some Red Hat distros /etc/localtime is real file with name held in /etc/sysconfig/clock // in a line like ZONE="Europe/Oslo" or TIMEZONE="Europe/Oslo" if (ianaId.isEmpty()) { diff --git a/src/gui/image/qimage.h b/src/gui/image/qimage.h index 11ad9b7510..5f2965042f 100644 --- a/src/gui/image/qimage.h +++ b/src/gui/image/qimage.h @@ -215,7 +215,7 @@ public: const uchar *constBits() const; #if QT_DEPRECATED_SINCE(5, 10) - QT_DEPRECATED int byteCount() const; + QT_DEPRECATED_X("Use sizeInBytes") int byteCount() const; #endif qssize_t sizeInBytes() const; diff --git a/src/gui/image/qplatformpixmap.cpp b/src/gui/image/qplatformpixmap.cpp index b123afb4db..2209c3de4d 100644 --- a/src/gui/image/qplatformpixmap.cpp +++ b/src/gui/image/qplatformpixmap.cpp @@ -58,6 +58,9 @@ QT_BEGIN_NAMESPACE */ QPlatformPixmap *QPlatformPixmap::create(int w, int h, PixelType type) { + if (Q_UNLIKELY(!QGuiApplicationPrivate::platformIntegration())) + qFatal("QPlatformPixmap: QGuiApplication required"); + QPlatformPixmap *data = QGuiApplicationPrivate::platformIntegration()->createPlatformPixmap(static_cast<QPlatformPixmap::PixelType>(type)); data->resize(w, h); return data; diff --git a/src/gui/kernel/qwindowsysteminterface.cpp b/src/gui/kernel/qwindowsysteminterface.cpp index a065e254df..a47bac8f39 100644 --- a/src/gui/kernel/qwindowsysteminterface.cpp +++ b/src/gui/kernel/qwindowsysteminterface.cpp @@ -265,12 +265,12 @@ void QWindowSystemInterface::handleWindowScreenChanged(QWindow *window, QScreen QWindowSystemInterfacePrivate::handleWindowSystemEvent(e); } -void QWindowSystemInterface::handleApplicationStateChanged(Qt::ApplicationState newState, bool forcePropagate) +QT_DEFINE_QPA_EVENT_HANDLER(void, handleApplicationStateChanged, Qt::ApplicationState newState, bool forcePropagate) { Q_ASSERT(QGuiApplicationPrivate::platformIntegration()->hasCapability(QPlatformIntegration::ApplicationState)); QWindowSystemInterfacePrivate::ApplicationStateChangedEvent *e = new QWindowSystemInterfacePrivate::ApplicationStateChangedEvent(newState, forcePropagate); - QWindowSystemInterfacePrivate::handleWindowSystemEvent(e); + QWindowSystemInterfacePrivate::handleWindowSystemEvent<Delivery>(e); } QWindowSystemInterfacePrivate::GeometryChangeEvent::GeometryChangeEvent(QWindow *window, const QRect &newGeometry) diff --git a/src/gui/kernel/qwindowsysteminterface.h b/src/gui/kernel/qwindowsysteminterface.h index e027157fac..960f79b5ba 100644 --- a/src/gui/kernel/qwindowsysteminterface.h +++ b/src/gui/kernel/qwindowsysteminterface.h @@ -207,6 +207,7 @@ public: static void handleWindowStateChanged(QWindow *window, Qt::WindowStates newState, int oldState = -1); static void handleWindowScreenChanged(QWindow *window, QScreen *newScreen); + template<typename Delivery = QWindowSystemInterface::DefaultDelivery> static void handleApplicationStateChanged(Qt::ApplicationState newState, bool forcePropagate = false); #ifndef QT_NO_DRAGANDDROP diff --git a/src/network/access/qhttpnetworkconnection.cpp b/src/network/access/qhttpnetworkconnection.cpp index 842a73a2f9..d24927b922 100644 --- a/src/network/access/qhttpnetworkconnection.cpp +++ b/src/network/access/qhttpnetworkconnection.cpp @@ -1231,20 +1231,20 @@ void QHttpNetworkConnectionPrivate::_q_hostLookupFinished(const QHostInfo &info) if (dequeueRequest(channels[0].socket)) { emitReplyError(channels[0].socket, channels[0].reply, QNetworkReply::HostNotFoundError); networkLayerState = QHttpNetworkConnectionPrivate::Unknown; - } -#ifndef QT_NO_SSL - else if (connectionType == QHttpNetworkConnection::ConnectionTypeSPDY) { + } else if (connectionType == QHttpNetworkConnection::ConnectionTypeSPDY + || connectionType == QHttpNetworkConnection::ConnectionTypeHTTP2) { for (const HttpMessagePair &spdyPair : qAsConst(channels[0].spdyRequestsToSend)) { // emit error for all replies QHttpNetworkReply *currentReply = spdyPair.second; Q_ASSERT(currentReply); emitReplyError(channels[0].socket, currentReply, QNetworkReply::HostNotFoundError); } - } -#endif // QT_NO_SSL - else { - // Should not happen - qWarning("QHttpNetworkConnectionPrivate::_q_hostLookupFinished could not de-queue request"); + } else { + // Should not happen: we start a host lookup before sending a request, + // so it's natural to have requests either in SPDY/HTTP/2 queue, + // or in low/high priority queues. + qWarning("QHttpNetworkConnectionPrivate::_q_hostLookupFinished" + " could not de-queue request, failed to report HostNotFoundError"); networkLayerState = QHttpNetworkConnectionPrivate::Unknown; } } diff --git a/src/network/access/qnetworkaccessmanager.cpp b/src/network/access/qnetworkaccessmanager.cpp index 248b4ccd3b..6dabe13228 100644 --- a/src/network/access/qnetworkaccessmanager.cpp +++ b/src/network/access/qnetworkaccessmanager.cpp @@ -1031,8 +1031,7 @@ QNetworkConfiguration QNetworkAccessManager::configuration() const if (session) { return session->configuration(); } else { - QNetworkConfigurationManager manager; - return manager.defaultConfiguration(); + return d->networkConfigurationManager.defaultConfiguration(); } } @@ -1056,12 +1055,11 @@ QNetworkConfiguration QNetworkAccessManager::activeConfiguration() const Q_D(const QNetworkAccessManager); QSharedPointer<QNetworkSession> networkSession(d->getNetworkSession()); - QNetworkConfigurationManager manager; if (networkSession) { - return manager.configurationFromIdentifier( + return d->networkConfigurationManager.configurationFromIdentifier( networkSession->sessionProperty(QLatin1String("ActiveConfiguration")).toString()); } else { - return manager.defaultConfiguration(); + return d->networkConfigurationManager.defaultConfiguration(); } } @@ -1390,17 +1388,16 @@ QNetworkReply *QNetworkAccessManager::createRequest(QNetworkAccessManager::Opera } if (!d->networkSessionStrongRef && (d->initializeSession || !d->networkConfiguration.identifier().isEmpty())) { - QNetworkConfigurationManager manager; if (!d->networkConfiguration.identifier().isEmpty()) { if ((d->networkConfiguration.state() & QNetworkConfiguration::Defined) - && d->networkConfiguration != manager.defaultConfiguration()) - d->createSession(manager.defaultConfiguration()); + && d->networkConfiguration != d->networkConfigurationManager.defaultConfiguration()) + d->createSession(d->networkConfigurationManager.defaultConfiguration()); else d->createSession(d->networkConfiguration); } else { - if (manager.capabilities() & QNetworkConfigurationManager::NetworkSessionRequired) - d->createSession(manager.defaultConfiguration()); + if (d->networkSessionRequired) + d->createSession(d->networkConfigurationManager.defaultConfiguration()); else d->initializeSession = false; } @@ -1932,8 +1929,8 @@ void QNetworkAccessManagerPrivate::_q_onlineStateChanged(bool isOnline) online = (networkConfiguration.state() & QNetworkConfiguration::Active); } else { if (online != isOnline) { - _q_networkSessionClosed(); - createSession(q->configuration()); + _q_networkSessionClosed(); + createSession(q->configuration()); online = isOnline; } } @@ -1957,13 +1954,13 @@ void QNetworkAccessManagerPrivate::_q_configurationChanged(const QNetworkConfigu const QString id = configuration.identifier(); if (configuration.state().testFlag(QNetworkConfiguration::Active)) { if (!onlineConfigurations.contains(id)) { - QSharedPointer<QNetworkSession> session(getNetworkSession()); if (session) { if (online && session->configuration().identifier() != networkConfigurationManager.defaultConfiguration().identifier()) { onlineConfigurations.insert(id); + // CHECK: If it's having Active flag - why would it be disconnected ??? //this one disconnected but another one is online, // close and create new session _q_networkSessionClosed(); @@ -1974,6 +1971,7 @@ void QNetworkAccessManagerPrivate::_q_configurationChanged(const QNetworkConfigu } else if (onlineConfigurations.contains(id)) { //this one is disconnecting + // CHECK: If it disconnected while we create a session over a down configuration ??? onlineConfigurations.remove(id); if (!onlineConfigurations.isEmpty()) { _q_networkSessionClosed(); diff --git a/src/network/socket/qnativesocketengine_win.cpp b/src/network/socket/qnativesocketengine_win.cpp index afdc4cf319..e8ab8de469 100644 --- a/src/network/socket/qnativesocketengine_win.cpp +++ b/src/network/socket/qnativesocketengine_win.cpp @@ -1215,10 +1215,8 @@ qint64 QNativeSocketEnginePrivate::nativeReceiveDatagram(char *data, qint64 maxL msg.dwBufferCount = 1; msg.name = reinterpret_cast<LPSOCKADDR>(&aa); msg.namelen = sizeof(aa); - if (options & (QAbstractSocketEngine::WantDatagramHopLimit | QAbstractSocketEngine::WantDatagramDestination)) { - msg.Control.buf = cbuf; - msg.Control.len = sizeof(cbuf); - } + msg.Control.buf = cbuf; + msg.Control.len = sizeof(cbuf); DWORD flags = 0; DWORD bytesRead = 0; diff --git a/src/platformsupport/themes/genericunix/qgenericunixthemes.cpp b/src/platformsupport/themes/genericunix/qgenericunixthemes.cpp index eeb03eb958..5eac0a3584 100644 --- a/src/platformsupport/themes/genericunix/qgenericunixthemes.cpp +++ b/src/platformsupport/themes/genericunix/qgenericunixthemes.cpp @@ -112,9 +112,11 @@ static bool isDBusTrayAvailable() { #ifndef QT_NO_DBUS static bool checkDBusGlobalMenuAvailable() { - QDBusConnection connection = QDBusConnection::sessionBus(); - QString registrarService = QStringLiteral("com.canonical.AppMenu.Registrar"); - return connection.interface()->isServiceRegistered(registrarService); + const QDBusConnection connection = QDBusConnection::sessionBus(); + static const QString registrarService = QStringLiteral("com.canonical.AppMenu.Registrar"); + if (const auto iface = connection.interface()) + return iface->isServiceRegistered(registrarService); + return false; } static bool isDBusGlobalMenuAvailable() diff --git a/src/plugins/platforms/android/androidjniclipboard.cpp b/src/plugins/platforms/android/androidjniclipboard.cpp index 833996403c..d169035339 100644 --- a/src/plugins/platforms/android/androidjniclipboard.cpp +++ b/src/plugins/platforms/android/androidjniclipboard.cpp @@ -47,7 +47,6 @@ namespace QtAndroidClipboard { QAndroidPlatformClipboard *m_manager = nullptr; - static char const *const QtNativeClassName = "org/qtproject/qt5/android/QtNative"; static JNINativeMethod methods[] = { {"onClipboardDataChanged", "()V", (void *)onClipboardDataChanged} }; diff --git a/src/plugins/platforms/cocoa/qnsview.mm b/src/plugins/platforms/cocoa/qnsview.mm index 90a6f936e2..33f9527213 100644 --- a/src/plugins/platforms/cocoa/qnsview.mm +++ b/src/plugins/platforms/cocoa/qnsview.mm @@ -354,6 +354,12 @@ Q_LOGGING_CATEGORY(lcQpaTablet, "qt.qpa.input.tablet") m_platformWindow->handleExposeEvent(QRectF::fromCGRect(self.bounds).toRect()); } +- (void)viewDidChangeBackingProperties +{ + if (self.layer) + self.layer.contentsScale = self.window.backingScaleFactor; +} + - (BOOL)isFlipped { return YES; diff --git a/src/plugins/platforms/ios/qiosapplicationstate.mm b/src/plugins/platforms/ios/qiosapplicationstate.mm index 7b923e4692..13e7e1150f 100644 --- a/src/plugins/platforms/ios/qiosapplicationstate.mm +++ b/src/plugins/platforms/ios/qiosapplicationstate.mm @@ -39,6 +39,8 @@ #include "qiosapplicationstate.h" +#include "qiosglobal.h" + #include <qpa/qwindowsysteminterface.h> #include <QtCore/qcoreapplication.h> @@ -72,8 +74,8 @@ static Qt::ApplicationState qtApplicationState(UIApplicationState uiApplicationS static void handleApplicationStateChanged(UIApplicationState uiApplicationState) { Qt::ApplicationState state = qtApplicationState(uiApplicationState); - QWindowSystemInterface::handleApplicationStateChanged(state); - QWindowSystemInterface::flushWindowSystemEvents(); + qCDebug(lcQpaApplication) << "moved to" << state; + QWindowSystemInterface::handleApplicationStateChanged<QWindowSystemInterface::SynchronousDelivery>(state); } QT_BEGIN_NAMESPACE diff --git a/src/plugins/platforms/ios/qioscontext.mm b/src/plugins/platforms/ios/qioscontext.mm index 2d5286e971..6a6cbb4324 100644 --- a/src/plugins/platforms/ios/qioscontext.mm +++ b/src/plugins/platforms/ios/qioscontext.mm @@ -165,8 +165,6 @@ bool QIOSContext::makeCurrent(QPlatformSurface *surface) glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, framebufferObject.depthRenderbuffer); } - - connect(static_cast<QIOSWindow *>(surface), SIGNAL(destroyed(QObject*)), this, SLOT(windowDestroyed(QObject*))); } else { glBindFramebuffer(GL_FRAMEBUFFER, framebufferObject.handle); } @@ -249,8 +247,13 @@ QIOSContext::FramebufferObject &QIOSContext::backingFramebufferObjectFor(QPlatfo // should probably use QOpenGLMultiGroupSharedResource to track the shared default-FBOs. if (m_sharedContext) return m_sharedContext->backingFramebufferObjectFor(surface); - else - return m_framebufferObjects[surface]; + + if (!m_framebufferObjects.contains(surface)) { + // We're about to create a new FBO, make sure it's cleaned up as well + connect(static_cast<QIOSWindow *>(surface), SIGNAL(destroyed(QObject*)), this, SLOT(windowDestroyed(QObject*))); + } + + return m_framebufferObjects[surface]; } GLuint QIOSContext::defaultFramebufferObject(QPlatformSurface *surface) const diff --git a/src/plugins/platforms/ios/qiosglobal.h b/src/plugins/platforms/ios/qiosglobal.h index f74e3004cc..8b39aded06 100644 --- a/src/plugins/platforms/ios/qiosglobal.h +++ b/src/plugins/platforms/ios/qiosglobal.h @@ -47,7 +47,9 @@ QT_BEGIN_NAMESPACE +Q_DECLARE_LOGGING_CATEGORY(lcQpaApplication); Q_DECLARE_LOGGING_CATEGORY(lcQpaInputMethods); +Q_DECLARE_LOGGING_CATEGORY(lcQpaWindow); #if !defined(QT_NO_DEBUG) #define qImDebug \ diff --git a/src/plugins/platforms/ios/qiosglobal.mm b/src/plugins/platforms/ios/qiosglobal.mm index 1482ffc7af..f27b2242df 100644 --- a/src/plugins/platforms/ios/qiosglobal.mm +++ b/src/plugins/platforms/ios/qiosglobal.mm @@ -44,7 +44,9 @@ QT_BEGIN_NAMESPACE +Q_LOGGING_CATEGORY(lcQpaApplication, "qt.qpa.application"); Q_LOGGING_CATEGORY(lcQpaInputMethods, "qt.qpa.input.methods"); +Q_LOGGING_CATEGORY(lcQpaWindow, "qt.qpa.window"); bool isQtApplication() { diff --git a/src/plugins/platforms/ios/qiosintegration.h b/src/plugins/platforms/ios/qiosintegration.h index 19fe93da30..20eb210cd5 100644 --- a/src/plugins/platforms/ios/qiosintegration.h +++ b/src/plugins/platforms/ios/qiosintegration.h @@ -58,8 +58,6 @@ class QIOSServices; class QIOSIntegration : public QPlatformNativeInterface, public QPlatformIntegration { Q_OBJECT - Q_PROPERTY(bool debugWindowManagement READ debugWindowManagement WRITE setDebugWindowManagement); - public: QIOSIntegration(); ~QIOSIntegration(); @@ -104,9 +102,6 @@ public: void *nativeResourceForWindow(const QByteArray &resource, QWindow *window) override; - void setDebugWindowManagement(bool); - bool debugWindowManagement() const; - QFactoryLoader *optionalPlugins() { return m_optionalPlugins; } private: @@ -123,8 +118,6 @@ private: #ifndef Q_OS_TVOS QIOSTextInputOverlay m_textInputOverlay; #endif - - bool m_debugWindowManagement; }; QT_END_NAMESPACE diff --git a/src/plugins/platforms/ios/qiosintegration.mm b/src/plugins/platforms/ios/qiosintegration.mm index 0e4bc62227..92c1e39d72 100644 --- a/src/plugins/platforms/ios/qiosintegration.mm +++ b/src/plugins/platforms/ios/qiosintegration.mm @@ -85,7 +85,6 @@ QIOSIntegration::QIOSIntegration() , m_platformServices(new QIOSServices) , m_accessibility(0) , m_optionalPlugins(new QFactoryLoader(QIosOptionalPluginInterface_iid, QLatin1String("/platforms/darwin"))) - , m_debugWindowManagement(false) { if (Q_UNLIKELY(![UIApplication sharedApplication])) { qFatal("Error: You are creating QApplication before calling UIApplicationMain.\n" \ @@ -94,10 +93,6 @@ QIOSIntegration::QIOSIntegration() "'applicationDidFinishLaunching' inside your UIApplication delegate.\n"); } - // The backingstore needs a global share context in order to support composition in - // QPlatformBackingStore. - qApp->setAttribute(Qt::AA_ShareOpenGLContexts, true); - // Set current directory to app bundle folder QDir::setCurrent(QString::fromUtf8([[[NSBundle mainBundle] bundlePath] UTF8String])); @@ -325,16 +320,6 @@ void *QIOSIntegration::nativeResourceForWindow(const QByteArray &resource, QWind return 0; } -void QIOSIntegration::setDebugWindowManagement(bool enabled) -{ - m_debugWindowManagement = enabled; -} - -bool QIOSIntegration::debugWindowManagement() const -{ - return m_debugWindowManagement; -} - // --------------------------------------------------------- #include "moc_qiosintegration.cpp" diff --git a/src/plugins/platforms/ios/qiosviewcontroller.mm b/src/plugins/platforms/ios/qiosviewcontroller.mm index a4c151ed8b..a7f1254064 100644 --- a/src/plugins/platforms/ios/qiosviewcontroller.mm +++ b/src/plugins/platforms/ios/qiosviewcontroller.mm @@ -77,8 +77,7 @@ if (!(self = [super init])) return nil; - QIOSIntegration *iosIntegration = QIOSIntegration::instance(); - if (iosIntegration && iosIntegration->debugWindowManagement()) { + if (qEnvironmentVariableIntValue("QT_IOS_DEBUG_WINDOW_MANAGEMENT")) { static UIImage *gridPattern = nil; static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ diff --git a/src/plugins/platforms/ios/qioswindow.mm b/src/plugins/platforms/ios/qioswindow.mm index 4e6d48423d..bcec9899f7 100644 --- a/src/plugins/platforms/ios/qioswindow.mm +++ b/src/plugins/platforms/ios/qioswindow.mm @@ -239,15 +239,28 @@ void QIOSWindow::setWindowState(Qt::WindowStates state) if (window()->isTopLevel() && window()->isVisible() && window()->isActive()) [m_view.qtViewController updateProperties]; - if (state & Qt::WindowMinimized) + if (state & Qt::WindowMinimized) { applyGeometry(QRect()); - else if (state & Qt::WindowFullScreen) - applyGeometry(screen()->geometry()); - else if (state & Qt::WindowMaximized) - applyGeometry(window()->flags() & Qt::MaximizeUsingFullscreenGeometryHint ? - screen()->geometry() : screen()->availableGeometry()); - else + } else if (state & (Qt::WindowFullScreen | Qt::WindowMaximized)) { + // When an application is in split-view mode, the UIScreen still has the + // same geometry, but the UIWindow is resized to the area reserved for the + // application. We use this to constrain the geometry used when applying the + // fullscreen or maximized window states. Note that we do not do this + // in applyGeometry(), as we don't want to artificially limit window + // placement "outside" of the screen bounds if that's what the user wants. + + QRect uiWindowBounds = QRectF::fromCGRect(m_view.window.bounds).toRect(); + QRect fullscreenGeometry = screen()->geometry().intersected(uiWindowBounds); + QRect maximizedGeometry = window()->flags() & Qt::MaximizeUsingFullscreenGeometryHint ? + fullscreenGeometry : screen()->availableGeometry().intersected(uiWindowBounds); + + if (state & Qt::WindowFullScreen) + applyGeometry(fullscreenGeometry); + else + applyGeometry(maximizedGeometry); + } else { applyGeometry(m_normalGeometry); + } } void QIOSWindow::setParent(const QPlatformWindow *parentWindow) diff --git a/src/plugins/platforms/ios/quiview.mm b/src/plugins/platforms/ios/quiview.mm index ddfd2c46fd..406bfcf5b3 100644 --- a/src/plugins/platforms/ios/quiview.mm +++ b/src/plugins/platforms/ios/quiview.mm @@ -88,7 +88,7 @@ Q_LOGGING_CATEGORY(lcQpaTablet, "qt.qpa.input.tablet") self.multipleTouchEnabled = YES; #endif - if (QIOSIntegration::instance()->debugWindowManagement()) { + if (qEnvironmentVariableIntValue("QT_IOS_DEBUG_WINDOW_MANAGEMENT")) { static CGFloat hue = 0.0; CGFloat lastHue = hue; for (CGFloat diff = 0; diff < 0.1 || diff > 0.9; diff = fabs(hue - lastHue)) @@ -97,7 +97,6 @@ Q_LOGGING_CATEGORY(lcQpaTablet, "qt.qpa.input.tablet") #define colorWithBrightness(br) \ [UIColor colorWithHue:hue saturation:0.5 brightness:br alpha:1.0].CGColor - self.layer.backgroundColor = colorWithBrightness(0.5); self.layer.borderColor = colorWithBrightness(1.0); self.layer.borderWidth = 1.0; } @@ -163,6 +162,7 @@ Q_LOGGING_CATEGORY(lcQpaTablet, "qt.qpa.input.tablet") QWindow *window = m_qioswindow->window(); QRect lastReportedGeometry = qt_window_private(window)->geometry; QRect currentGeometry = QRectF::fromCGRect(self.frame).toRect(); + qCDebug(lcQpaWindow) << m_qioswindow->window() << "new geometry is" << currentGeometry; QWindowSystemInterface::handleGeometryChange<QWindowSystemInterface::SynchronousDelivery>(window, currentGeometry); if (currentGeometry.size() != lastReportedGeometry.size()) { @@ -195,6 +195,7 @@ Q_LOGGING_CATEGORY(lcQpaTablet, "qt.qpa.input.tablet") region = QRect(QPoint(), bounds); } + qCDebug(lcQpaWindow) << m_qioswindow->window() << region << "isExposed" << m_qioswindow->isExposed(); QWindowSystemInterface::handleExposeEvent<QWindowSystemInterface::SynchronousDelivery>(m_qioswindow->window(), region); } diff --git a/src/widgets/Qt5WidgetsMacros.cmake b/src/widgets/Qt5WidgetsMacros.cmake index f5e7b7f050..737371a5ad 100644 --- a/src/widgets/Qt5WidgetsMacros.cmake +++ b/src/widgets/Qt5WidgetsMacros.cmake @@ -59,6 +59,9 @@ function(QT5_WRAP_UI outfiles ) COMMAND ${Qt5Widgets_UIC_EXECUTABLE} ARGS ${ui_options} -o ${outfile} ${infile} MAIN_DEPENDENCY ${infile} VERBATIM) + set_source_files_properties(${infile} PROPERTIES SKIP_AUTOUIC ON) + set_source_files_properties(${outfile} PROPERTIES SKIP_AUTOMOC ON) + set_source_files_properties(${outfile} PROPERTIES SKIP_AUTOUIC ON) list(APPEND ${outfiles} ${outfile}) endforeach() set(${outfiles} ${${outfiles}} PARENT_SCOPE) diff --git a/src/widgets/doc/images/stardelegate.png b/src/widgets/doc/images/stardelegate.png Binary files differindex 24fa9fb0d7..66f55c5fc7 100644 --- a/src/widgets/doc/images/stardelegate.png +++ b/src/widgets/doc/images/stardelegate.png diff --git a/src/widgets/itemviews/qheaderview.cpp b/src/widgets/itemviews/qheaderview.cpp index 463ed7e58c..c7966f624f 100644 --- a/src/widgets/itemviews/qheaderview.cpp +++ b/src/widgets/itemviews/qheaderview.cpp @@ -2086,40 +2086,26 @@ void QHeaderViewPrivate::_q_layoutChanged() { Q_Q(QHeaderView); viewport->update(); - if (persistentHiddenSections.isEmpty() || modelIsEmpty()) { - if (modelSectionCount() != sectionCount()) - q->initializeSections(); - persistentHiddenSections.clear(); + + const auto hiddenSections = persistentHiddenSections; + persistentHiddenSections.clear(); + + clear(); + q->initializeSections(); + invalidateCachedSizeHint(); + + if (modelIsEmpty()) { return; } - QBitArray oldSectionHidden = sectionsHiddenToBitVector(); - oldSectionHidden.resize(sectionItems.size()); - bool sectionCountChanged = false; - - for (int i = 0; i < persistentHiddenSections.count(); ++i) { - QModelIndex index = persistentHiddenSections.at(i); + for (const auto &index : hiddenSections) { if (index.isValid()) { const int logical = (orientation == Qt::Horizontal ? index.column() : index.row()); q->setSectionHidden(logical, true); - oldSectionHidden.setBit(logical, false); - } else if (!sectionCountChanged && (modelSectionCount() != sectionCount())) { - sectionCountChanged = true; - break; } } - persistentHiddenSections.clear(); - - for (int i = 0; i < oldSectionHidden.count(); ++i) { - if (oldSectionHidden.testBit(i)) - q->setSectionHidden(i, false); - } - - // the number of sections changed; we need to reread the state of the model - if (sectionCountChanged) - q->initializeSections(); } /*! diff --git a/src/widgets/itemviews/qtableview.cpp b/src/widgets/itemviews/qtableview.cpp index d42ed0ad19..fd3bdfd065 100644 --- a/src/widgets/itemviews/qtableview.cpp +++ b/src/widgets/itemviews/qtableview.cpp @@ -1397,6 +1397,9 @@ void QTableView::paintEvent(QPaintEvent *event) } else { dirtyArea.setRight(qMin(dirtyArea.right(), int(x))); } + // dirtyArea may be invalid when the horizontal header is not stretched + if (!dirtyArea.isValid()) + continue; // get the horizontal start and end visual sections int left = horizontalHeader->visualIndexAt(dirtyArea.left()); diff --git a/src/widgets/itemviews/qtreeview.cpp b/src/widgets/itemviews/qtreeview.cpp index d504263bd1..6ea180dcf2 100644 --- a/src/widgets/itemviews/qtreeview.cpp +++ b/src/widgets/itemviews/qtreeview.cpp @@ -736,7 +736,10 @@ void QTreeView::dataChanged(const QModelIndex &topLeft, const QModelIndex &botto void QTreeView::hideColumn(int column) { Q_D(QTreeView); + if (d->header->isSectionHidden(column)) + return; d->header->hideSection(column); + doItemsLayout(); } /*! @@ -747,7 +750,10 @@ void QTreeView::hideColumn(int column) void QTreeView::showColumn(int column) { Q_D(QTreeView); + if (!d->header->isSectionHidden(column)) + return; d->header->showSection(column); + doItemsLayout(); } /*! @@ -1008,11 +1014,16 @@ void QTreeView::keyboardSearch(const QString &search) if (!d->model->rowCount(d->root) || !d->model->columnCount(d->root)) return; + // Do a relayout nows, so that we can utilize viewItems + d->executePostedLayout(); + if (d->viewItems.isEmpty()) + return; + QModelIndex start; if (currentIndex().isValid()) start = currentIndex(); else - start = d->model->index(0, 0, d->root); + start = d->viewItems.at(0).index; bool skipRow = false; bool keyboardTimeWasValid = d->keyboardInputTime.isValid(); @@ -1040,13 +1051,16 @@ void QTreeView::keyboardSearch(const QString &search) // skip if we are searching for the same key or a new search started if (skipRow) { - if (indexBelow(start).isValid()) + if (indexBelow(start).isValid()) { start = indexBelow(start); - else - start = d->model->index(0, start.column(), d->root); + } else { + const int origCol = start.column(); + start = d->viewItems.at(0).index; + if (origCol != start.column()) + start = start.sibling(start.row(), origCol); + } } - d->executePostedLayout(); int startIndex = d->viewIndex(start); if (startIndex <= -1) return; diff --git a/src/widgets/styles/qfusionstyle.cpp b/src/widgets/styles/qfusionstyle.cpp index 074aa3ecec..e002b49d25 100644 --- a/src/widgets/styles/qfusionstyle.cpp +++ b/src/widgets/styles/qfusionstyle.cpp @@ -476,8 +476,10 @@ void QFusionStyle::drawPrimitive(PrimitiveElement elem, break; if (option->state & State_Open) drawPrimitive(PE_IndicatorArrowDown, option, painter, widget); - else - drawPrimitive(PE_IndicatorArrowRight, option, painter, widget); + else { + const bool reverse = (option->direction == Qt::RightToLeft); + drawPrimitive(reverse ? PE_IndicatorArrowLeft : PE_IndicatorArrowRight, option, painter, widget); + } break; } #if QT_CONFIG(tabbar) diff --git a/src/widgets/widgets/qtoolbar.cpp b/src/widgets/widgets/qtoolbar.cpp index 1c6d41ee2f..a00557c34e 100644 --- a/src/widgets/widgets/qtoolbar.cpp +++ b/src/widgets/widgets/qtoolbar.cpp @@ -1119,6 +1119,8 @@ static bool waitForPopup(QToolBar *tb, QWidget *popup) static void enableMacToolBar(QToolBar *toolbar, bool enable) { QPlatformNativeInterface *nativeInterface = QApplication::platformNativeInterface(); + if (!nativeInterface) + return; QPlatformNativeInterface::NativeResourceForIntegrationFunction function = nativeInterface->nativeResourceFunctionForIntegration("setContentBorderAreaEnabled"); if (!function) diff --git a/tests/auto/cmake/CMakeLists.txt b/tests/auto/cmake/CMakeLists.txt index 0e6da23c09..40c86132e9 100644 --- a/tests/auto/cmake/CMakeLists.txt +++ b/tests/auto/cmake/CMakeLists.txt @@ -157,7 +157,13 @@ if (NOT CMAKE_VERSION VERSION_LESS 2.8.11 AND NOT NO_WIDGETS) expect_pass(test_interface) endif() -if (NOT CMAKE_VERSION VERSION_LESS 2.8.12) - expect_pass(test_interface_link_libraries) - expect_pass(test_moc_macro_target) +expect_pass(test_interface_link_libraries) +expect_pass(test_moc_macro_target) + +if (NOT CMAKE_VERSION VERSION_LESS 3.8) + # With earlier CMake versions, this test would simply run moc multiple times and lead to: + # /usr/bin/ld: error: CMakeFiles/mywidget.dir/mywidget_automoc.cpp.o: multiple definition of 'MyWidget::qt_static_metacall(QObject*, QMetaObject::Call, int, void**)' + # /usr/bin/ld: CMakeFiles/mywidget.dir/moc_mywidget.cpp.o: previous definition here + # Reason: SKIP_* properties were added in CMake 3.8 only + expect_pass(test_QTBUG-63422) endif() diff --git a/tests/auto/cmake/test_QTBUG-63422/CMakeLists.txt b/tests/auto/cmake/test_QTBUG-63422/CMakeLists.txt new file mode 100644 index 0000000000..a0b82caee4 --- /dev/null +++ b/tests/auto/cmake/test_QTBUG-63422/CMakeLists.txt @@ -0,0 +1,30 @@ +cmake_minimum_required(VERSION 2.8) +project(test_dependent_modules) + +find_package(Qt5Widgets REQUIRED) + +set(CMAKE_AUTOMOC ON) +set(CMAKE_AUTOUIC ON) +set(CMAKE_AUTORCC ON) +set(CMAKE_INCLUDE_CURRENT_DIR ON) + +# make sure CMP0071 warnings cause a test failure +set(CMAKE_SUPPRESS_DEVELOPER_ERRORS FALSE CACHE INTERNAL "" FORCE) + +qt5_wrap_cpp(moc_files mywidget.h) +qt5_wrap_ui(ui_files mywidget.ui) +qt5_add_resources(qrc_files res.qrc) + +add_executable(mywidget + # source files + mywidget.cpp + mywidget.h + mywidget.ui + res.qrc + + # generated files + ${moc_files} + ${ui_files} + ${qrc_files} +) +target_link_libraries(mywidget ${Qt5Widgets_LIBRARIES}) diff --git a/tests/auto/cmake/test_QTBUG-63422/mywidget.cpp b/tests/auto/cmake/test_QTBUG-63422/mywidget.cpp new file mode 100644 index 0000000000..7bc42537d5 --- /dev/null +++ b/tests/auto/cmake/test_QTBUG-63422/mywidget.cpp @@ -0,0 +1,43 @@ +/**************************************************************************** +** +** Copyright (C) 2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Kevin Funk <kevin.funk@kdab.com> +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "mywidget.h" +#include "ui_mywidget.h" + +MyWidget::MyWidget(QWidget *parent) + : QWidget(parent) +{ + emit someSignal(); +} + +int main(int argc, char **argv) +{ + QApplication app(argc, argv); + MyWidget myWidget; + return 0; +} diff --git a/tests/auto/cmake/test_QTBUG-63422/mywidget.h b/tests/auto/cmake/test_QTBUG-63422/mywidget.h new file mode 100644 index 0000000000..d0c79c0538 --- /dev/null +++ b/tests/auto/cmake/test_QTBUG-63422/mywidget.h @@ -0,0 +1,52 @@ +/**************************************************************************** +** +** Copyright (C) 2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Kevin Funk <kevin.funk@kdab.com> +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef MYWIDGET_H +#define MYWIDGET_H + +#include <QWidget> + +namespace Ui +{ +class MyWidget; +} + +class MyWidget : public QWidget +{ + Q_OBJECT +public: + MyWidget(QWidget *parent = nullptr); + +signals: + void someSignal(); + +private: + Ui::MyWidget *ui = nullptr; +}; + +#endif diff --git a/tests/auto/cmake/test_QTBUG-63422/mywidget.ui b/tests/auto/cmake/test_QTBUG-63422/mywidget.ui new file mode 100644 index 0000000000..ac42ac4dc2 --- /dev/null +++ b/tests/auto/cmake/test_QTBUG-63422/mywidget.ui @@ -0,0 +1,34 @@ +<?xml version="1.0" encoding="UTF-8"?> +<ui version="4.0"> + <class>Form</class> + <widget class="QWidget" name="Form"> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>400</width> + <height>300</height> + </rect> + </property> + <property name="windowTitle"> + <string>Form</string> + </property> + <layout class="QVBoxLayout" name="verticalLayout"> + <item> + <widget class="QPushButton" name="pushButton"> + <property name="text"> + <string>PushButton</string> + </property> + </widget> + </item> + <item> + <widget class="QLineEdit" name="lineEdit"/> + </item> + <item> + <widget class="QTextEdit" name="textEdit"/> + </item> + </layout> + </widget> + <resources/> + <connections/> +</ui> diff --git a/tests/auto/cmake/test_QTBUG-63422/res.qrc b/tests/auto/cmake/test_QTBUG-63422/res.qrc new file mode 100644 index 0000000000..4ca9cd5837 --- /dev/null +++ b/tests/auto/cmake/test_QTBUG-63422/res.qrc @@ -0,0 +1,4 @@ +<!DOCTYPE RCC><RCC version="1.0"> +<qresource> +</qresource> +</RCC> diff --git a/tests/auto/corelib/global/qflags/tst_qflags.cpp b/tests/auto/corelib/global/qflags/tst_qflags.cpp index 7dd1a1be01..2f1b56629a 100644 --- a/tests/auto/corelib/global/qflags/tst_qflags.cpp +++ b/tests/auto/corelib/global/qflags/tst_qflags.cpp @@ -290,6 +290,18 @@ void tst_QFlags::testSetFlags() btn.setFlag(Qt::LeftButton, false); QVERIFY(!btn.testFlag(Qt::LeftButton)); QVERIFY(!btn.testFlag(Qt::MidButton)); + + MyStrictFlags flags; + flags.setFlag(MyStrictEnum::StrictOne); + flags.setFlag(MyStrictEnum::StrictTwo, true); + QVERIFY(flags.testFlag(MyStrictEnum::StrictOne)); + QVERIFY(flags.testFlag(MyStrictEnum::StrictTwo)); + QVERIFY(!flags.testFlag(MyStrictEnum::StrictFour)); + + flags.setFlag(MyStrictEnum::StrictTwo, false); + QVERIFY(flags.testFlag(MyStrictEnum::StrictOne)); + QVERIFY(!flags.testFlag(MyStrictEnum::StrictTwo)); + QVERIFY(!flags.testFlag(MyStrictEnum::StrictFour)); } // (statically) check QTypeInfo for QFlags instantiations: diff --git a/tests/auto/corelib/io/qloggingregistry/tst_qloggingregistry.cpp b/tests/auto/corelib/io/qloggingregistry/tst_qloggingregistry.cpp index 1643eed3d2..15c63d4acd 100644 --- a/tests/auto/corelib/io/qloggingregistry/tst_qloggingregistry.cpp +++ b/tests/auto/corelib/io/qloggingregistry/tst_qloggingregistry.cpp @@ -197,10 +197,22 @@ private slots: // Check whether QT_LOGGING_CONF is picked up from environment // - qputenv("QT_LOGGING_CONF", QFINDTESTDATA("qtlogging.ini").toLocal8Bit()); + Q_ASSERT(!qApp); // Rules should not require an app to resolve - QLoggingRegistry registry; - registry.init(); + qputenv("QT_LOGGING_RULES", "qt.foo.bar=true"); + QLoggingCategory qtEnabledByLoggingRule("qt.foo.bar"); + QCOMPARE(qtEnabledByLoggingRule.isDebugEnabled(), true); + QLoggingCategory qtDisabledByDefault("qt.foo.baz"); + QCOMPARE(qtDisabledByDefault.isDebugEnabled(), false); + + QLoggingRegistry ®istry = *QLoggingRegistry::instance(); + QCOMPARE(registry.ruleSets[QLoggingRegistry::ApiRules].size(), 0); + QCOMPARE(registry.ruleSets[QLoggingRegistry::ConfigRules].size(), 0); + QCOMPARE(registry.ruleSets[QLoggingRegistry::EnvironmentRules].size(), 1); + + qunsetenv("QT_LOGGING_RULES"); + qputenv("QT_LOGGING_CONF", QFINDTESTDATA("qtlogging.ini").toLocal8Bit()); + registry.initalizeRules(); QCOMPARE(registry.ruleSets[QLoggingRegistry::ApiRules].size(), 0); QCOMPARE(registry.ruleSets[QLoggingRegistry::ConfigRules].size(), 0); @@ -208,7 +220,7 @@ private slots: // check that QT_LOGGING_RULES take precedence qputenv("QT_LOGGING_RULES", "Digia.*=true"); - registry.init(); + registry.initalizeRules(); QCOMPARE(registry.ruleSets[QLoggingRegistry::EnvironmentRules].size(), 2); QCOMPARE(registry.ruleSets[QLoggingRegistry::EnvironmentRules].at(1).enabled, true); } @@ -234,7 +246,7 @@ private slots: file.close(); QLoggingRegistry registry; - registry.init(); + registry.initalizeRules(); QCOMPARE(registry.ruleSets[QLoggingRegistry::ConfigRules].size(), 1); // remove file again @@ -300,6 +312,6 @@ private slots: } }; -QTEST_MAIN(tst_QLoggingRegistry) +QTEST_APPLESS_MAIN(tst_QLoggingRegistry) #include "tst_qloggingregistry.moc" diff --git a/tests/auto/corelib/thread/qsemaphore/tst_qsemaphore.cpp b/tests/auto/corelib/thread/qsemaphore/tst_qsemaphore.cpp index ba470a77c9..a67ecc2471 100644 --- a/tests/auto/corelib/thread/qsemaphore/tst_qsemaphore.cpp +++ b/tests/auto/corelib/thread/qsemaphore/tst_qsemaphore.cpp @@ -41,6 +41,8 @@ private slots: void tryAcquireWithTimeout_data(); void tryAcquireWithTimeout(); void tryAcquireWithTimeoutStarvation(); + void tryAcquireWithTimeoutForever_data(); + void tryAcquireWithTimeoutForever(); void producerConsumer(); void raii(); }; @@ -156,21 +158,25 @@ void tst_QSemaphore::tryAcquire() semaphore.release(); QCOMPARE(semaphore.available(), 1); QVERIFY(!semaphore.tryAcquire(2)); + QVERIFY(!semaphore.tryAcquire(2, 0)); QCOMPARE(semaphore.available(), 1); semaphore.release(); QCOMPARE(semaphore.available(), 2); QVERIFY(!semaphore.tryAcquire(3)); + QVERIFY(!semaphore.tryAcquire(3, 0)); QCOMPARE(semaphore.available(), 2); semaphore.release(10); QCOMPARE(semaphore.available(), 12); QVERIFY(!semaphore.tryAcquire(100)); + QVERIFY(!semaphore.tryAcquire(100, 0)); QCOMPARE(semaphore.available(), 12); semaphore.release(10); QCOMPARE(semaphore.available(), 22); QVERIFY(!semaphore.tryAcquire(100)); + QVERIFY(!semaphore.tryAcquire(100, 0)); QCOMPARE(semaphore.available(), 22); QVERIFY(semaphore.tryAcquire()); @@ -179,23 +185,38 @@ void tst_QSemaphore::tryAcquire() QVERIFY(semaphore.tryAcquire()); QCOMPARE(semaphore.available(), 20); + semaphore.release(2); + QVERIFY(semaphore.tryAcquire(1, 0)); + QCOMPARE(semaphore.available(), 21); + + QVERIFY(semaphore.tryAcquire(1, 0)); + QCOMPARE(semaphore.available(), 20); + QVERIFY(semaphore.tryAcquire(10)); QCOMPARE(semaphore.available(), 10); + semaphore.release(10); + QVERIFY(semaphore.tryAcquire(10, 0)); + QCOMPARE(semaphore.available(), 10); + QVERIFY(semaphore.tryAcquire(10)); QCOMPARE(semaphore.available(), 0); // should not be able to acquire more QVERIFY(!semaphore.tryAcquire()); + QVERIFY(!semaphore.tryAcquire(1, 0)); QCOMPARE(semaphore.available(), 0); QVERIFY(!semaphore.tryAcquire()); + QVERIFY(!semaphore.tryAcquire(1, 0)); QCOMPARE(semaphore.available(), 0); QVERIFY(!semaphore.tryAcquire(10)); + QVERIFY(!semaphore.tryAcquire(10, 0)); QCOMPARE(semaphore.available(), 0); QVERIFY(!semaphore.tryAcquire(10)); + QVERIFY(!semaphore.tryAcquire(10, 0)); QCOMPARE(semaphore.available(), 0); } @@ -345,6 +366,48 @@ void tst_QSemaphore::tryAcquireWithTimeoutStarvation() QVERIFY(consumer.wait()); } +void tst_QSemaphore::tryAcquireWithTimeoutForever_data() +{ + QTest::addColumn<int>("timeout"); + QTest::newRow("-1") << -1; + + // tryAcquire is documented to take any negative value as "forever" + QTest::newRow("INT_MIN") << INT_MIN; +} + +void tst_QSemaphore::tryAcquireWithTimeoutForever() +{ + enum { WaitTime = 1000 }; + struct Thread : public QThread { + QSemaphore sem; + + void run() override + { + QTest::qWait(WaitTime); + sem.release(2); + } + }; + + QFETCH(int, timeout); + Thread t; + + // sanity check it works if we can immediately acquire + t.sem.release(11); + QVERIFY(t.sem.tryAcquire(1, timeout)); + QVERIFY(t.sem.tryAcquire(10, timeout)); + + // verify that we do wait for at least WaitTime if we can't acquire immediately + QElapsedTimer timer; + timer.start(); + t.start(); + QVERIFY(t.sem.tryAcquire(1, timeout)); + QVERIFY(timer.elapsed() >= WaitTime); + + QVERIFY(t.wait()); + + QCOMPARE(t.sem.available(), 1); +} + const char alphabet[] = "ACGTH"; const int AlphabetSize = sizeof(alphabet) - 1; diff --git a/tests/auto/corelib/thread/qthreadpool/tst_qthreadpool.cpp b/tests/auto/corelib/thread/qthreadpool/tst_qthreadpool.cpp index 094c6ed0a5..1092216fb7 100644 --- a/tests/auto/corelib/thread/qthreadpool/tst_qthreadpool.cpp +++ b/tests/auto/corelib/thread/qthreadpool/tst_qthreadpool.cpp @@ -95,6 +95,7 @@ private slots: void stackSize(); void stressTest(); void takeAllAndIncreaseMaxThreadCount(); + void waitForDoneAfterTake(); private: QMutex m_functionTestMutex; @@ -1267,5 +1268,72 @@ void tst_QThreadPool::takeAllAndIncreaseMaxThreadCount() { delete task3; } +void tst_QThreadPool::waitForDoneAfterTake() +{ + class Task : public QRunnable + { + public: + Task(QSemaphore *mainBarrier, QSemaphore *threadBarrier) + : m_mainBarrier(mainBarrier) + , m_threadBarrier(threadBarrier) + {} + + void run() + { + m_mainBarrier->release(); + m_threadBarrier->acquire(); + } + + private: + QSemaphore *m_mainBarrier = nullptr; + QSemaphore *m_threadBarrier = nullptr; + }; + + int threadCount = 4; + + // Blocks the main thread from releasing the threadBarrier before all run() functions have started + QSemaphore mainBarrier; + // Blocks the tasks from completing their run function + QSemaphore threadBarrier; + + QThreadPool manager; + manager.setMaxThreadCount(threadCount); + + // Fill all the threads with runnables that wait for the threadBarrier + for (int i = 0; i < threadCount; i++) { + auto *task = new Task(&mainBarrier, &threadBarrier); + manager.start(task); + } + + QVERIFY(manager.activeThreadCount() == manager.maxThreadCount()); + + // Add runnables that are immediately removed from the pool queue. + // This sets the queue elements to nullptr in QThreadPool and we want to test that + // the threads keep going through the queue after encountering a nullptr. + for (int i = 0; i < threadCount; i++) { + QRunnable *runnable = createTask(emptyFunct); + manager.start(runnable); + QVERIFY(manager.tryTake(runnable)); + } + + // Add another runnable that will not be removed + manager.start(createTask(emptyFunct)); + + // Wait for the first runnables to start + mainBarrier.acquire(threadCount); + + QVERIFY(mainBarrier.available() == 0); + QVERIFY(threadBarrier.available() == 0); + + // Release runnables that are waiting and expect all runnables to complete + threadBarrier.release(threadCount); + + // Using qFatal instead of QVERIFY to force exit if threads are still running after timeout. + // Otherwise, QCoreApplication will still wait for the stale threads and never exit the test. + if (!manager.waitForDone(5 * 60 * 1000)) + qFatal("waitForDone returned false. Aborting to stop background threads."); + +} + QTEST_MAIN(tst_QThreadPool); #include "tst_qthreadpool.moc" diff --git a/tests/auto/network/access/qnetworkreply/tst_qnetworkreply.cpp b/tests/auto/network/access/qnetworkreply/tst_qnetworkreply.cpp index df68d4fcd5..69bd78a4f0 100644 --- a/tests/auto/network/access/qnetworkreply/tst_qnetworkreply.cpp +++ b/tests/auto/network/access/qnetworkreply/tst_qnetworkreply.cpp @@ -630,7 +630,7 @@ protected: Q_ASSERT(!client.isNull()); // we need to emulate the bytesWrittenSlot call if the data is empty. if (dataToTransmit.size() == 0) { - QMetaObject::invokeMethod(this, "bytesWrittenSlot", Qt::QueuedConnection); + emit client->bytesWritten(0); } else { client->write(dataToTransmit); // FIXME: For SSL connections, if we don't flush the socket, the @@ -667,23 +667,26 @@ private slots: #ifndef QT_NO_SSL void slotSslErrors(const QList<QSslError>& errors) { - Q_ASSERT(!client.isNull()); - qDebug() << "slotSslErrors" << client->errorString() << errors; + QTcpSocket *currentClient = qobject_cast<QTcpSocket *>(sender()); + Q_ASSERT(currentClient); + qDebug() << "slotSslErrors" << currentClient->errorString() << errors; } #endif void slotError(QAbstractSocket::SocketError err) { - if (client.isNull()) - qDebug() << "slotError" << err; - else - qDebug() << "slotError" << err << client->errorString(); + QTcpSocket *currentClient = qobject_cast<QTcpSocket *>(sender()); + Q_ASSERT(currentClient); + qDebug() << "slotError" << err << currentClient->errorString(); } public slots: void readyReadSlot() { - Q_ASSERT(!client.isNull()); + QTcpSocket *currentClient = qobject_cast<QTcpSocket *>(sender()); + Q_ASSERT(currentClient); + if (currentClient != client) + client = currentClient; receivedData += client->readAll(); const int doubleEndlPos = receivedData.indexOf("\r\n\r\n"); @@ -8307,11 +8310,23 @@ void tst_QNetworkReply::ioHttpRedirectErrors() QNetworkReplyPtr reply(manager.get(request)); if (localhost.scheme() == "https") reply.data()->ignoreSslErrors(); - QSignalSpy spy(reply.data(), SIGNAL(error(QNetworkReply::NetworkError))); - QCOMPARE(waitForFinish(reply), int(Failure)); + QEventLoop eventLoop; + QTimer watchDog; + watchDog.setSingleShot(true); - QCOMPARE(spy.count(), 1); + reply->connect(reply.data(), QOverload<QNetworkReply::NetworkError>().of(&QNetworkReply::error), + [&eventLoop](QNetworkReply::NetworkError){ + eventLoop.exit(Failure); + }); + + watchDog.connect(&watchDog, &QTimer::timeout, [&eventLoop](){ + eventLoop.exit(Timeout); + }); + + watchDog.start(5000); + + QCOMPARE(eventLoop.exec(), int(Failure)); QCOMPARE(reply->error(), error); } diff --git a/tests/auto/network/kernel/qdnslookup_appless/tst_qdnslookup_appless.cpp b/tests/auto/network/kernel/qdnslookup_appless/tst_qdnslookup_appless.cpp index 7874221da9..e302fe8c74 100644 --- a/tests/auto/network/kernel/qdnslookup_appless/tst_qdnslookup_appless.cpp +++ b/tests/auto/network/kernel/qdnslookup_appless/tst_qdnslookup_appless.cpp @@ -43,7 +43,7 @@ private slots: void tst_QDnsLookup_Appless::noApplication() { QTest::ignoreMessage(QtWarningMsg, "QDnsLookup requires a QCoreApplication"); - QDnsLookup dns(QDnsLookup::A, "a-single.test.macieira.org"); + QDnsLookup dns(QDnsLookup::A, "a-single.test.qt-project.org"); dns.lookup(); } @@ -53,7 +53,7 @@ void tst_QDnsLookup_Appless::recreateApplication() char **argv = 0; for (int i = 0; i < 10; ++i) { QCoreApplication app(argc, argv); - QDnsLookup dns(QDnsLookup::A, "a-single.test.macieira.org"); + QDnsLookup dns(QDnsLookup::A, "a-single.test.qt-project.org"); dns.lookup(); if (!dns.isFinished()) { QObject::connect(&dns, SIGNAL(finished()), diff --git a/tests/auto/network/kernel/qhostinfo/tst_qhostinfo.cpp b/tests/auto/network/kernel/qhostinfo/tst_qhostinfo.cpp index f5f5146eb5..82825f608c 100644 --- a/tests/auto/network/kernel/qhostinfo/tst_qhostinfo.cpp +++ b/tests/auto/network/kernel/qhostinfo/tst_qhostinfo.cpp @@ -72,7 +72,7 @@ #include "../../../network-settings.h" -#define TEST_DOMAIN ".test.macieira.org" +#define TEST_DOMAIN ".test.qt-project.org" class tst_QHostInfo : public QObject diff --git a/tests/auto/network/socket/qtcpsocket/BLACKLIST b/tests/auto/network/socket/qtcpsocket/BLACKLIST index 5fc2589323..96e59e5678 100644 --- a/tests/auto/network/socket/qtcpsocket/BLACKLIST +++ b/tests/auto/network/socket/qtcpsocket/BLACKLIST @@ -6,8 +6,6 @@ windows windows [invalidProxy:socks5-on-http] windows -[disconnectWhileLookingUp] -windows [timeoutConnect:ip] windows ] diff --git a/tests/auto/network/socket/qtcpsocket/tst_qtcpsocket.cpp b/tests/auto/network/socket/qtcpsocket/tst_qtcpsocket.cpp index 396ce62536..fc92ed6cbc 100644 --- a/tests/auto/network/socket/qtcpsocket/tst_qtcpsocket.cpp +++ b/tests/auto/network/socket/qtcpsocket/tst_qtcpsocket.cpp @@ -1445,8 +1445,15 @@ void tst_QTcpSocket::disconnectWhileLookingUp() } // let anything queued happen + QEventLoop loop; - QTimer::singleShot(50, &loop, SLOT(quit())); + // If 'doClose' is false then we called '::waitForDisconnected' earlier, meaning + // we are already 'Unconnected'. So we don't need to wait for any potentially slow host lookups. + QTimer::singleShot(doClose ? 4000 : 50, &loop, SLOT(quit())); + connect(socket, &QTcpSocket::stateChanged, [&loop](QAbstractSocket::SocketState state) { + if (state == QAbstractSocket::UnconnectedState) + loop.exit(); // we don't need to wait for the timer to expire; we're done. + }); loop.exec(); // recheck diff --git a/tests/auto/network/ssl/qsslsocket/BLACKLIST b/tests/auto/network/ssl/qsslsocket/BLACKLIST index 52c023b78f..a9ecc69f50 100644 --- a/tests/auto/network/ssl/qsslsocket/BLACKLIST +++ b/tests/auto/network/ssl/qsslsocket/BLACKLIST @@ -1,6 +1,4 @@ windows -[waitForConnectedEncryptedReadyRead:WithSocks5ProxyAuth] -* [protocolServerSide:ssl3-any] rhel-7.2 [protocolServerSide:tls1.0-any] diff --git a/tests/auto/network/ssl/qsslsocket/tst_qsslsocket.cpp b/tests/auto/network/ssl/qsslsocket/tst_qsslsocket.cpp index 5488553760..4e12a16696 100644 --- a/tests/auto/network/ssl/qsslsocket/tst_qsslsocket.cpp +++ b/tests/auto/network/ssl/qsslsocket/tst_qsslsocket.cpp @@ -1613,7 +1613,12 @@ void tst_QSslSocket::waitForConnectedEncryptedReadyRead() QFETCH_GLOBAL(bool, setProxy); if (setProxy && !socket->waitForEncrypted(10000)) QSKIP("Skipping flaky test - See QTBUG-29941"); - QVERIFY(socket->waitForReadyRead(10000)); + + // We only do this if we have no bytes available to read already because readyRead will + // not be emitted again. + if (socket->bytesAvailable() == 0) + QVERIFY(socket->waitForReadyRead(10000)); + QVERIFY(!socket->peerCertificate().isNull()); QVERIFY(!socket->peerCertificateChain().isEmpty()); } diff --git a/tests/auto/widgets/itemviews/qheaderview/tst_qheaderview.cpp b/tests/auto/widgets/itemviews/qheaderview/tst_qheaderview.cpp index f2279ea4d4..273e90e110 100644 --- a/tests/auto/widgets/itemviews/qheaderview/tst_qheaderview.cpp +++ b/tests/auto/widgets/itemviews/qheaderview/tst_qheaderview.cpp @@ -210,6 +210,7 @@ private slots: void QTBUG12268_hiddenMovedSectionSorting(); void QTBUG14242_hideSectionAutoSize(); void QTBUG50171_visualRegionForSwappedItems(); + void QTBUG53221_assertShiftHiddenRow(); void ensureNoIndexAtLength(); void offsetConsistent(); @@ -2384,6 +2385,54 @@ void tst_QHeaderView::QTBUG50171_visualRegionForSwappedItems() headerView.testVisualRegionForSelection(); } +class QTBUG53221_Model : public QAbstractItemModel +{ +public: + void insertRowAtBeginning() + { + Q_EMIT layoutAboutToBeChanged(); + m_displayNames.insert(0, QStringLiteral("Item %1").arg(m_displayNames.count())); + // Rows are always inserted at the beginning, so move all others. + foreach (const QModelIndex &persIndex, persistentIndexList()) + { + // The vertical header view will have a persistent index stored here on the second call to insertRowAtBeginning. + changePersistentIndex(persIndex, index(persIndex.row() + 1, persIndex.column(), persIndex.parent())); + } + Q_EMIT layoutChanged(); + } + + QVariant data(const QModelIndex &index, int role) const override + { + return (role == Qt::DisplayRole) ? m_displayNames.at(index.row()) : QVariant(); + } + + QModelIndex index(int row, int column, const QModelIndex &) const override { return createIndex(row, column); } + QModelIndex parent(const QModelIndex &) const override { return QModelIndex(); } + int rowCount(const QModelIndex &) const override { return m_displayNames.count(); } + int columnCount(const QModelIndex &) const override { return 1; } + +private: + QStringList m_displayNames; +}; + +void tst_QHeaderView::QTBUG53221_assertShiftHiddenRow() +{ + QTableView tableView; + QTBUG53221_Model modelTableView; + tableView.setModel(&modelTableView); + + modelTableView.insertRowAtBeginning(); + tableView.setRowHidden(0, true); + QCOMPARE(tableView.verticalHeader()->isSectionHidden(0), true); + modelTableView.insertRowAtBeginning(); + QCOMPARE(tableView.verticalHeader()->isSectionHidden(0), false); + QCOMPARE(tableView.verticalHeader()->isSectionHidden(1), true); + modelTableView.insertRowAtBeginning(); + QCOMPARE(tableView.verticalHeader()->isSectionHidden(0), false); + QCOMPARE(tableView.verticalHeader()->isSectionHidden(1), false); + QCOMPARE(tableView.verticalHeader()->isSectionHidden(2), true); +} + void protected_QHeaderView::testVisualRegionForSelection() { QRegion r = visualRegionForSelection(QItemSelection(model()->index(1, 0), model()->index(1, 2))); diff --git a/tests/auto/widgets/itemviews/qtreeview/tst_qtreeview.cpp b/tests/auto/widgets/itemviews/qtreeview/tst_qtreeview.cpp index 1d82081bec..f870605d7d 100644 --- a/tests/auto/widgets/itemviews/qtreeview/tst_qtreeview.cpp +++ b/tests/auto/widgets/itemviews/qtreeview/tst_qtreeview.cpp @@ -197,6 +197,7 @@ private slots: void taskQTBUG_37813_crash(); void taskQTBUG_45697_crash(); void taskQTBUG_7232_AllowUserToControlSingleStep(); + void taskQTBUG_8376(); void testInitialFocus(); }; @@ -1087,6 +1088,103 @@ void tst_QTreeView::keyboardSearch() // The item that starts with B is selected. view.keyboardSearch(QLatin1String("B")); QVERIFY(view.selectionModel()->isSelected(model.index(1, 0))); + + // Test that it wraps round + model.appendRow(new QStandardItem("Andy")); + QTest::qWait(QApplication::keyboardInputInterval() * 2); + view.keyboardSearch(QLatin1String("A")); + QVERIFY(view.selectionModel()->isSelected(model.index(3, 0))); + QTest::qWait(QApplication::keyboardInputInterval() * 2); + view.keyboardSearch(QLatin1String("A")); + QVERIFY(view.selectionModel()->isSelected(model.index(0, 0))); + QTest::qWait(QApplication::keyboardInputInterval() * 2); + view.keyboardSearch(QLatin1String("A")); + QVERIFY(view.selectionModel()->isSelected(model.index(3, 0))); + + // Test that it handles the case where the first item is hidden correctly + model.insertRow(0, new QStandardItem("Hidden item")); + view.setRowHidden(0, QModelIndex(), true); + + QTest::qWait(QApplication::keyboardInputInterval() * 2); + view.keyboardSearch(QLatin1String("A")); + QVERIFY(view.selectionModel()->isSelected(model.index(1, 0))); + QTest::qWait(QApplication::keyboardInputInterval() * 2); + view.keyboardSearch(QLatin1String("A")); + QVERIFY(view.selectionModel()->isSelected(model.index(4, 0))); + QTest::qWait(QApplication::keyboardInputInterval() * 2); + view.keyboardSearch(QLatin1String("A")); + QVERIFY(view.selectionModel()->isSelected(model.index(1, 0))); + + QTest::qWait(QApplication::keyboardInputInterval() * 2); + model.clear(); + view.setCurrentIndex(QModelIndex()); + QList<QStandardItem *> items = { new QStandardItem("Andreas"), new QStandardItem("Alicia") }; + model.appendRow(items); + items = { new QStandardItem("Baldrian"), new QStandardItem("Belinda") }; + model.appendRow(items); + items = { new QStandardItem("Cecilie"), new QStandardItem("Claire") }; + model.appendRow(items); + QVERIFY(!view.selectionModel()->hasSelection()); + QVERIFY(!view.selectionModel()->isSelected(model.index(0, 0))); + + // We want to search on the 2nd column so we have to force it to have + // an index in that column as a starting point + view.setCurrentIndex(QModelIndex(model.index(0, 1))); + // Second item in first row is selected + view.keyboardSearch(QLatin1String("A")); + QTRY_VERIFY(view.selectionModel()->isSelected(model.index(0, 1))); + QVERIFY(view.currentIndex() == model.index(0, 1)); + + // Second item in first row is still selected + view.keyboardSearch(QLatin1String("l")); + QVERIFY(view.selectionModel()->isSelected(model.index(0, 1))); + QCOMPARE(view.currentIndex(), model.index(0, 1)); + + // No "AnB" item - keep the same selection. + view.keyboardSearch(QLatin1String("B")); + QVERIFY(view.selectionModel()->isSelected(model.index(0, 1))); + QCOMPARE(view.currentIndex(), model.index(0, 1)); + + // Wait a bit. + QTest::qWait(QApplication::keyboardInputInterval() * 2); + + // The item that starts with B is selected. + view.keyboardSearch(QLatin1String("B")); + QVERIFY(view.selectionModel()->isSelected(model.index(1, 1))); + QCOMPARE(view.currentIndex(), model.index(1, 1)); + + // Test that it wraps round + items = { new QStandardItem("Andy"), new QStandardItem("Adele") }; + model.appendRow(items); + QTest::qWait(QApplication::keyboardInputInterval() * 2); + view.keyboardSearch(QLatin1String("A")); + QVERIFY(view.selectionModel()->isSelected(model.index(3, 1))); + QCOMPARE(view.currentIndex(), model.index(3, 1)); + QTest::qWait(QApplication::keyboardInputInterval() * 2); + view.keyboardSearch(QLatin1String("A")); + QVERIFY(view.selectionModel()->isSelected(model.index(0, 1))); + QCOMPARE(view.currentIndex(), model.index(0, 1)); + QTest::qWait(QApplication::keyboardInputInterval() * 2); + view.keyboardSearch(QLatin1String("A")); + QVERIFY(view.selectionModel()->isSelected(model.index(3, 1))); + QCOMPARE(view.currentIndex(), model.index(3, 1)); + + // Test that it handles the case where the first item is hidden correctly + model.insertRow(0, new QStandardItem("Hidden item")); + view.setRowHidden(0, QModelIndex(), true); + + QTest::qWait(QApplication::keyboardInputInterval() * 2); + view.keyboardSearch(QLatin1String("A")); + QVERIFY(view.selectionModel()->isSelected(model.index(1, 1))); + QCOMPARE(view.currentIndex(), model.index(1, 1)); + QTest::qWait(QApplication::keyboardInputInterval() * 2); + view.keyboardSearch(QLatin1String("A")); + QVERIFY(view.selectionModel()->isSelected(model.index(4, 1))); + QCOMPARE(view.currentIndex(), model.index(4, 1)); + QTest::qWait(QApplication::keyboardInputInterval() * 2); + view.keyboardSearch(QLatin1String("A")); + QVERIFY(view.selectionModel()->isSelected(model.index(1, 1))); + QCOMPARE(view.currentIndex(), model.index(1, 1)); } void tst_QTreeView::keyboardSearchMultiColumn() @@ -4511,5 +4609,50 @@ void tst_QTreeView::fetchMoreOnScroll() QCOMPARE(im.item(19)->rowCount(), 20); } +static void fillModeltaskQTBUG_8376(QAbstractItemModel &model) +{ + model.insertRow(0); + model.insertColumn(0); + model.insertColumn(1); + QModelIndex index = model.index(0, 0); + model.setData(index, "Level0"); + { + model.insertRow(0, index); + model.insertRow(1, index); + model.insertColumn(0, index); + model.insertColumn(1, index); + + QModelIndex idx; + idx = model.index(0, 0, index); + model.setData(idx, "Level1"); + + idx = model.index(0, 1, index); + model.setData(idx, "very\nvery\nhigh\ncell"); + } +} + +void tst_QTreeView::taskQTBUG_8376() +{ + QTreeView tv; + QStandardItemModel model; + fillModeltaskQTBUG_8376(model); + tv.setModel(&model); + tv.expandAll(); // init layout + + QModelIndex idxLvl0 = model.index(0, 0); + QModelIndex idxLvl1 = model.index(0, 1, idxLvl0); + const int rowHeightLvl0 = tv.rowHeight(idxLvl0); + const int rowHeightLvl1Visible = tv.rowHeight(idxLvl1); + QVERIFY(rowHeightLvl0 < rowHeightLvl1Visible); + + tv.hideColumn(1); + const int rowHeightLvl1Hidden = tv.rowHeight(idxLvl1); + QCOMPARE(rowHeightLvl0, rowHeightLvl1Hidden); + + tv.showColumn(1); + const int rowHeightLvl1Visible2 = tv.rowHeight(idxLvl1); + QCOMPARE(rowHeightLvl1Visible, rowHeightLvl1Visible2); +} + QTEST_MAIN(tst_QTreeView) #include "tst_qtreeview.moc" diff --git a/tests/manual/cocoa/menurama/menuramaapplication.cpp b/tests/manual/cocoa/menurama/menuramaapplication.cpp index 5fb2041ae4..1506fe7d19 100644 --- a/tests/manual/cocoa/menurama/menuramaapplication.cpp +++ b/tests/manual/cocoa/menurama/menuramaapplication.cpp @@ -28,7 +28,7 @@ #include "menuramaapplication.h" -MenuramaApplication::MenuramaApplication(int argc, char **argv) +MenuramaApplication::MenuramaApplication(int &argc, char **argv) : QApplication (argc, argv) { #if 0 diff --git a/tests/manual/cocoa/menurama/menuramaapplication.h b/tests/manual/cocoa/menurama/menuramaapplication.h index 1a5a55e0ff..2d836832fa 100644 --- a/tests/manual/cocoa/menurama/menuramaapplication.h +++ b/tests/manual/cocoa/menurama/menuramaapplication.h @@ -36,7 +36,7 @@ class MenuramaApplication : public QApplication { public: - MenuramaApplication(int argc, char **argv); + MenuramaApplication(int &argc, char **argv); void addDynMenu(QLatin1String title, QMenu *parentMenu); QAction *findAction(QLatin1String title, QMenu *parentMenu); |