diff --git a/doc/global/manifest-meta.qdocconf b/doc/global/manifest-meta.qdocconf index 3db67a3131..f5e5dbf8db 100644 --- a/doc/global/manifest-meta.qdocconf +++ b/doc/global/manifest-meta.qdocconf @@ -32,84 +32,103 @@ manifestmeta.filters = highlighted android thumbnail ios manifestmeta.highlighted.attributes = isHighlighted:true -manifestmeta.android.names = "QtQuick/Qt Quick Demo - Calqlatr" \ - "QtWidgets/Application Chooser Example" \ - "QtWidgets/Stickman Example" \ - "QtWidgets/Move Blocks Example" \ - "QtWidgets/Border Layout Example" \ - "QtWidgets/Flow Layout Example" \ - "QtWidgets/Dock Widgets Example" \ - "QtWidgets/Recent Files Example" \ - "QtWidgets/Concentric Circles Example" \ - "QtWidgets/Gradients" \ - "QtWidgets/Font Sampler Example" \ - "QtWidgets/Path Stroking" \ - "QtWidgets/Transformations Example" \ - "QtWidgets/Syntax Highlighter Example" \ - "QtWidgets/Calendar Example" \ - "QtWidgets/Analog Clock Example" \ - "QtWidgets/Calculator Example" \ - "QtWidgets/Mouse Button Tester" \ - "QtWidgets/Character Map Example" \ - "QtWidgets/Digital Clock Example" \ - "QtWidgets/Elided Label Example" \ - "QtWidgets/Sliders Example" \ - "QtWidgets/Tetrix Example" \ - "QtWidgets/Group Box Example" \ - "QtWidgets/Undo Framework" \ - "QtWidgets/Colliding Mice Example" \ - "QtWidgets/Diagram Scene Example" \ - "QtWidgets/Elastic Nodes Example" \ - "QtWidgets/Weather Anchor Layout Example" \ - "QtNetwork/Torrent Example" \ - "QtNetwork/Network Chat Example" \ - "QtSQL/Master Detail Example" \ - "QtLinguist/Arrow Pad Example" \ - "QtGui/Raster Window Example" \ - "QtGui/Analog Clock Window Example" \ - "QtAndroidExtras/Qt Notifier" \ - "QtMultimedia/QML Video Shader Effects Example" \ - "QtMultimedia/QML Video Example" \ - "QtMultimedia/QML Camera Example" \ - "QtSVG/Text Object Example" \ - "QtQML/Qt Quick Examples - XMLHttpRequest" \ - "QtQuick/Qt Quick Particles Examples - *" \ - "QtQuick/Qt Quick Examples - Touch Interaction" \ - "QtQuick/Scene Graph - Custom Geometry" \ - "QtQuick/Scene Graph - Graph" \ - "QtQuick/Scene Graph - OpenGL Under QML" \ - "QtQuick/Scene Graph - Painted Item" \ - "QtQuick/Scene Graph - Rendering FBOs" \ - "QtQuick/Scene Graph - Simple Material" \ - "QtQuick/Qt Quick Examples - Image Elements" \ - "QtQuick/Qt Quick Examples - Key Interaction" \ - "QtQuick/Qt Quick Examples - Text" \ - "QtQuick/Qt Quick Examples - Animation" \ - "QtQuick/Qt Quick Examples - Shader Effects" \ - "QtQuick/Qt Quick Examples - Canvas" \ - "QtQuick/Qt Quick Examples - MouseArea" \ - "QtQuick/Qt Quick Examples - Positioners" \ - "QtQuick/Qt Quick Examples - Right to Left" \ - "QtWidgets/Interview" \ - "QtWidgets/Spreadsheet" \ - "QtWidgets/Pixelator Example" \ - "QtWidgets/Animated Tiles Example" \ - "QtWidgets/Affine Transformations" \ - "QtWidgets/Image Composition Example" \ - "QtWidgets/Basic Drawing Example" \ - "QtWidgets/Vector Deformation" \ - "QtWidgets/Painter Paths Example" \ - "QtWidgets/Style Sheet Example" \ - "QtWidgets/Code Editor Example" \ - "QtWidgets/Scribble Example" \ - "QtWidgets/Line Edits Example" \ - "QtWidgets/Calendar Widget Example" \ - "QtWidgets/Completer Example" \ - "QtWidgets/I18N Example" \ - "QtQML/Extending QML - Grouped Properties Example" \ - "QtQML/Extending QML - Methods Example" \ - "QtQML/Extending QML - Signal Support Example" \ - "QtQML/Extending QML - Attached Properties Example" +manifestmeta.android.names = "Qt3D/Qt 3D: Basic Shapes C++ Example" \ + "Qt3D/Qt 3D: Planets QML Example" \ + "Qt3D/Qt 3D: Simple Custom Material QML Example" \ + "QtAndroidExtras/Qt Notifier" \ + "QtBluetooth/Bluetooth Low Energy Scanner Example" \ + "QtBluetooth/Bluetooth Scanner Example" \ + "QtBluetooth/QML Bluetooth Scanner Example" \ + "QtCharts/*" \ + "QtConcurrent/QtConcurrent Progress Dialog Example" \ + "QtDataVisualization/Audiolevels Example" \ + "QtDataVisualization/Qt Quick 2 Scatter Example" \ + "QtDataVisualization/Qt Quick 2 Surface Multiseries Example" \ + "QtGui/Analog Clock Window Example" \ + "QtGui/OpenGL Window Example" \ + "QtGui/Raster Window Example" \ + "QtLinguist/Arrow Pad Example" \ + "QtLinguistManual/Hello tr() Example" \ + "QtLocation/Map Viewer (QML)" \ + "QtLocation/Places Map (QML)" \ + "QtLocation/Plane Spotter (QML)" \ + "QtMultimedia/AudioEngine Example" \ + "QtMultimedia/Camera Example" \ + "QtMultimedia/QML Camera Example" \ + "QtMultimedia/QML Video Example" \ + "QtMultimedia/QML Video Shader Effects Example" \ + "QtNFC/Annotated URL Example" \ + "QtNFC/QML Poster Example" \ + "QtOpenGL/2D Painting Example" \ + "QtOpenGL/Hello GLES3 Example" \ + "QtOpenGL/Textures Example" \ + "QtPositioning/SatelliteInfo (C++/QML)" \ + "QtPositioning/Weather Info (C++/QML)" \ + "QtPurchasing/Qt Purchasing Examples - QtHangman" \ + "QtQML/Extending QML - Attached Properties Example" \ + "QtQML/Extending QML - Grouped Properties Example" \ + "QtQML/Extending QML - Methods Example" \ + "QtQML/Extending QML - Signal Support Example" \ + "QtQML/Qt Quick Examples - XMLHttpRequest" \ + "QtQml/Qt Quick Examples - XMLHttpRequest" \ + "QtQuick/*" \ + "QtQuickControls/*" \ + "QtQuickControls1/Qt Quick Controls 1 - Calendar Example" \ + "QtQuickControls1/Qt Quick Controls 1 - Gallery" \ + "QtQuickControls1/Qt Quick Controls 1 - Styles Example" \ + "QtQuickControls1/Qt Quick Controls 1 - Table View Example" \ + "QtQuickControls1/Qt Quick Controls 1 - Touch Gallery" \ + "QtQuickDialogs/*" \ + "QtQuickExtras/*" \ + "QtSCXML/Qt SCXML Calculator QML Example" \ + "QtSCXML/Qt SCXML Sudoku Example" \ + "QtSCXML/Qt SCXML Traffic Light Example (Dynamic)" \ + "QtSCXML/Qt SCXML Traffic Light QML Example (Dynamic)" \ + "QtSQL/Master Detail Example" \ + "QtSVG/Text Object Example" \ + "QtUiTools/Text Finder Example" \ + "QtWebView/Qt WebView Examples - Minibrowser" \ + "QtWidgets/Address Book Example" \ + "QtWidgets/Affine Transformations" \ + "QtWidgets/Analog Clock Example" \ + "QtWidgets/Animated Tiles Example" \ + "QtWidgets/Application Chooser Example" \ + "QtWidgets/Basic Layouts Example" \ + "QtWidgets/Border Layout Example" \ + "QtWidgets/Code Editor Example" \ + "QtWidgets/Colliding Mice Example" \ + "QtWidgets/Concentric Circles Example" \ + "QtWidgets/Digital Clock Example" \ + "QtWidgets/Dynamic Layouts Example" \ + "QtWidgets/Easing Curves Example" \ + "QtWidgets/Editable Tree Model Example" \ + "QtWidgets/Elided Label Example" \ + "QtWidgets/Event Transitions Example" \ + "QtWidgets/Fade Message Effect Example" \ + "QtWidgets/Flow Layout Example" \ + "QtWidgets/Font Sampler Example" \ + "QtWidgets/Frozen Column Example" \ + "QtWidgets/Gradients" \ + "QtWidgets/Group Box Example" \ + "QtWidgets/Image Composition Example" \ + "QtWidgets/Line Edits Example" \ + "QtWidgets/Mouse Button Tester" \ + "QtWidgets/Move Blocks Example" \ + "QtWidgets/Painter Paths Example" \ + "QtWidgets/Painter Paths Example" \ + "QtWidgets/Path Stroking" \ + "QtWidgets/Pixelator Example" \ + "QtWidgets/Recent Files Example" \ + "QtWidgets/SDI Example" \ + "QtWidgets/Scribble Example" \ + "QtWidgets/Simple Tree Model Example" \ + "QtWidgets/Sliders Example" \ + "QtWidgets/Spreadsheet" \ + "QtWidgets/Touch Dials Example" \ + "QtWidgets/Transformations Example" \ + "QtWidgets/Undo Framework" \ + "QtWidgets/Vector Deformation" \ + "QtWidgets/Wiggly Example" manifestmeta.android.tags = android diff --git a/examples/network/http/main.cpp b/examples/network/http/main.cpp index 1339f2f693..6c86933fd6 100644 --- a/examples/network/http/main.cpp +++ b/examples/network/http/main.cpp @@ -81,7 +81,11 @@ int main(int argc, char *argv[]) const QRect availableSize = httpWin.screen()->availableGeometry(); httpWin.resize(availableSize.width() / 5, availableSize.height() / 5); httpWin.move((availableSize.width() - httpWin.width()) / 2, (availableSize.height() - httpWin.height()) / 2); - +#ifdef Q_OS_ANDROID + httpWin.showMaximized(); +#else httpWin.show(); +#endif + return app.exec(); } diff --git a/examples/widgets/graphicsview/collidingmice/main.cpp b/examples/widgets/graphicsview/collidingmice/main.cpp index ef6d6cca64..c9ad90260f 100644 --- a/examples/widgets/graphicsview/collidingmice/main.cpp +++ b/examples/widgets/graphicsview/collidingmice/main.cpp @@ -58,6 +58,9 @@ static constexpr int MouseCount = 7; //! [0] int main(int argc, char **argv) { +#ifdef Q_OS_ANDROID + QApplication::setAttribute(Qt::AA_EnableHighDpiScaling); +#endif QApplication app(argc, argv); //! [0] diff --git a/examples/widgets/graphicsview/diagramscene/main.cpp b/examples/widgets/graphicsview/diagramscene/main.cpp index eefaa86554..3e321259c5 100644 --- a/examples/widgets/graphicsview/diagramscene/main.cpp +++ b/examples/widgets/graphicsview/diagramscene/main.cpp @@ -55,6 +55,9 @@ int main(int argv, char *args[]) { Q_INIT_RESOURCE(diagramscene); +#ifdef Q_OS_ANDROID + QApplication::setAttribute(Qt::AA_EnableHighDpiScaling); +#endif QApplication app(argv, args); MainWindow mainWindow; diff --git a/examples/widgets/itemviews/addressbook/main.cpp b/examples/widgets/itemviews/addressbook/main.cpp index 0731287cdd..86a11c5850 100644 --- a/examples/widgets/itemviews/addressbook/main.cpp +++ b/examples/widgets/itemviews/addressbook/main.cpp @@ -55,6 +55,9 @@ //! [0] int main(int argc, char *argv[]) { +#ifdef Q_OS_ANDROID + QApplication::setAttribute(Qt::AA_EnableHighDpiScaling); +#endif QApplication app(argc, argv); MainWindow mw; mw.show(); diff --git a/examples/widgets/itemviews/spreadsheet/main.cpp b/examples/widgets/itemviews/spreadsheet/main.cpp index 548dc8d604..968312d097 100644 --- a/examples/widgets/itemviews/spreadsheet/main.cpp +++ b/examples/widgets/itemviews/spreadsheet/main.cpp @@ -56,6 +56,10 @@ int main(int argc, char **argv) { Q_INIT_RESOURCE(spreadsheet); +#ifdef Q_OS_ANDROID + QApplication::setAttribute(Qt::AA_EnableHighDpiScaling); +#endif + QApplication app(argc, argv); SpreadSheet sheet(10, 6); sheet.setWindowIcon(QPixmap(":/images/interview.png")); diff --git a/examples/widgets/layouts/basiclayouts/main.cpp b/examples/widgets/layouts/basiclayouts/main.cpp index f59de1d385..cf0ff0a535 100644 --- a/examples/widgets/layouts/basiclayouts/main.cpp +++ b/examples/widgets/layouts/basiclayouts/main.cpp @@ -56,7 +56,11 @@ int main(int argc, char *argv[]) { QApplication app(argc, argv); Dialog dialog; +#ifdef Q_OS_ANDROID + dialog.showMaximized(); +#else dialog.show(); +#endif return app.exec(); } diff --git a/examples/widgets/layouts/dynamiclayouts/main.cpp b/examples/widgets/layouts/dynamiclayouts/main.cpp index 9959c472f4..cf0ff0a535 100644 --- a/examples/widgets/layouts/dynamiclayouts/main.cpp +++ b/examples/widgets/layouts/dynamiclayouts/main.cpp @@ -56,6 +56,11 @@ int main(int argc, char *argv[]) { QApplication app(argc, argv); Dialog dialog; +#ifdef Q_OS_ANDROID + dialog.showMaximized(); +#else dialog.show(); +#endif + return app.exec(); } diff --git a/examples/widgets/mainwindows/application/main.cpp b/examples/widgets/mainwindows/application/main.cpp index 78db7134a3..b46e1116dc 100644 --- a/examples/widgets/mainwindows/application/main.cpp +++ b/examples/widgets/mainwindows/application/main.cpp @@ -58,6 +58,9 @@ int main(int argc, char *argv[]) { Q_INIT_RESOURCE(application); +#ifdef Q_OS_ANDROID + QApplication::setAttribute(Qt::AA_EnableHighDpiScaling); +#endif QApplication app(argc, argv); QCoreApplication::setOrganizationName("QtProject"); diff --git a/examples/widgets/mainwindows/dockwidgets/main.cpp b/examples/widgets/mainwindows/dockwidgets/main.cpp index ff3ba506a8..bf3ad9bcf7 100644 --- a/examples/widgets/mainwindows/dockwidgets/main.cpp +++ b/examples/widgets/mainwindows/dockwidgets/main.cpp @@ -54,6 +54,9 @@ int main(int argc, char *argv[]) { +#ifdef Q_OS_ANDROID + QApplication::setAttribute(Qt::AA_EnableHighDpiScaling); +#endif QApplication app(argc, argv); Q_INIT_RESOURCE(dockwidgets); MainWindow mainWin; diff --git a/examples/widgets/painting/affine/main.cpp b/examples/widgets/painting/affine/main.cpp index 6ce8efe482..641fc5c204 100644 --- a/examples/widgets/painting/affine/main.cpp +++ b/examples/widgets/painting/affine/main.cpp @@ -55,7 +55,9 @@ int main(int argc, char **argv) { Q_INIT_RESOURCE(affine); - +#ifdef Q_OS_ANDROID + qputenv("QT_SCALE_FACTOR", "2"); +#endif QApplication app(argc, argv); XFormWidget xformWidget(nullptr); diff --git a/examples/widgets/painting/affine/xform.cpp b/examples/widgets/painting/affine/xform.cpp index 4e7cb91ce1..d7ed2125d2 100644 --- a/examples/widgets/painting/affine/xform.cpp +++ b/examples/widgets/painting/affine/xform.cpp @@ -787,8 +787,8 @@ XFormWidget::XFormWidget(QWidget *parent) view = new XFormView(this); view->setMinimumSize(200, 200); - QGroupBox *mainGroup = new QGroupBox(this); - mainGroup->setFixedWidth(180); + QWidget *mainContentWidget = new QWidget(); + QGroupBox *mainGroup = new QGroupBox(mainContentWidget); mainGroup->setTitle(tr("Affine Transformations")); QGroupBox *rotateGroup = new QGroupBox(mainGroup); @@ -837,10 +837,6 @@ XFormWidget::XFormWidget(QWidget *parent) whatsThisButton->setText(tr("What's This?")); whatsThisButton->setCheckable(true); - QHBoxLayout *viewLayout = new QHBoxLayout(this); - viewLayout->addWidget(view); - viewLayout->addWidget(mainGroup); - QVBoxLayout *rotateGroupLayout = new QVBoxLayout(rotateGroup); rotateGroupLayout->addWidget(rotateSlider); @@ -871,6 +867,20 @@ XFormWidget::XFormWidget(QWidget *parent) #endif mainGroupLayout->addWidget(whatsThisButton); + mainGroup->setLayout(mainGroupLayout); + + QVBoxLayout *mainContentLayout = new QVBoxLayout(); + mainContentLayout->addWidget(mainGroup); + mainContentWidget->setLayout(mainContentLayout); + + QScrollArea *mainScrollArea = new QScrollArea(); + mainScrollArea->setWidget(mainContentWidget); + mainScrollArea->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Preferred); + + QHBoxLayout *viewLayout = new QHBoxLayout(this); + viewLayout->addWidget(view); + viewLayout->addWidget(mainScrollArea); + connect(rotateSlider, &QSlider::valueChanged, view, &XFormView::changeRotation); connect(shearSlider, &QSlider::valueChanged, view, &XFormView::changeShear); connect(scaleSlider, &QSlider::valueChanged, view, &XFormView::changeScale); diff --git a/examples/widgets/painting/concentriccircles/main.cpp b/examples/widgets/painting/concentriccircles/main.cpp index d9fa2879c4..00456195d9 100644 --- a/examples/widgets/painting/concentriccircles/main.cpp +++ b/examples/widgets/painting/concentriccircles/main.cpp @@ -54,6 +54,9 @@ int main(int argc, char *argv[]) { +#ifdef Q_OS_ANDROID + QApplication::setAttribute(Qt::AA_EnableHighDpiScaling); +#endif QApplication app(argc, argv); Window window; window.show(); diff --git a/examples/widgets/painting/fontsampler/main.cpp b/examples/widgets/painting/fontsampler/main.cpp index 1bf46b226f..cec6929827 100644 --- a/examples/widgets/painting/fontsampler/main.cpp +++ b/examples/widgets/painting/fontsampler/main.cpp @@ -54,6 +54,9 @@ int main(int argc, char *argv[]) { +#ifdef Q_OS_ANDROID + QApplication::setAttribute(Qt::AA_EnableHighDpiScaling); +#endif QApplication app(argc, argv); MainWindow window; window.show(); diff --git a/examples/widgets/painting/gradients/gradients.cpp b/examples/widgets/painting/gradients/gradients.cpp index d62ae93a15..cb1a0177e9 100644 --- a/examples/widgets/painting/gradients/gradients.cpp +++ b/examples/widgets/painting/gradients/gradients.cpp @@ -282,7 +282,8 @@ GradientWidget::GradientWidget(QWidget *parent) m_renderer = new GradientRenderer(this); - QGroupBox *mainGroup = new QGroupBox(this); + QWidget *mainContentWidget = new QWidget(); + QGroupBox *mainGroup = new QGroupBox(mainContentWidget); mainGroup->setTitle(tr("Gradients")); QGroupBox *editorGroup = new QGroupBox(mainGroup); @@ -327,11 +328,6 @@ GradientWidget::GradientWidget(QWidget *parent) whatsThisButton->setText(tr("What's This?")); whatsThisButton->setCheckable(true); - // Layouts - QHBoxLayout *mainLayout = new QHBoxLayout(this); - mainLayout->addWidget(m_renderer); - mainLayout->addWidget(mainGroup); - mainGroup->setFixedWidth(200); QVBoxLayout *mainGroupLayout = new QVBoxLayout(mainGroup); mainGroupLayout->addWidget(editorGroup); @@ -370,6 +366,21 @@ GradientWidget::GradientWidget(QWidget *parent) defaultsGroupLayout->addWidget(default3Button); editorGroupLayout->addWidget(default4Button); + mainGroup->setLayout(mainGroupLayout); + + QVBoxLayout *mainContentLayout = new QVBoxLayout(); + mainContentLayout->addWidget(mainGroup); + mainContentWidget->setLayout(mainContentLayout); + + QScrollArea *mainScrollArea = new QScrollArea(); + mainScrollArea->setWidget(mainContentWidget); + mainScrollArea->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Preferred); + + // Layouts + QHBoxLayout *mainLayout = new QHBoxLayout(this); + mainLayout->addWidget(m_renderer); + mainLayout->addWidget(mainScrollArea); + connect(m_editor, &GradientEditor::gradientStopsChanged, m_renderer, &GradientRenderer::setGradientStops); connect(m_linearButton, &QRadioButton::clicked, diff --git a/examples/widgets/painting/gradients/main.cpp b/examples/widgets/painting/gradients/main.cpp index 0ddf7a4579..7ffb0326e9 100644 --- a/examples/widgets/painting/gradients/main.cpp +++ b/examples/widgets/painting/gradients/main.cpp @@ -55,6 +55,9 @@ int main(int argc, char *argv[]) { Q_INIT_RESOURCE(gradients); +#ifdef Q_OS_ANDROID + qputenv("QT_SCALE_FACTOR", "2"); +#endif QApplication app(argc, argv); diff --git a/examples/widgets/painting/pathstroke/main.cpp b/examples/widgets/painting/pathstroke/main.cpp index 57c85d73a3..35317480a3 100644 --- a/examples/widgets/painting/pathstroke/main.cpp +++ b/examples/widgets/painting/pathstroke/main.cpp @@ -55,6 +55,9 @@ int main(int argc, char **argv) { Q_INIT_RESOURCE(pathstroke); +#ifdef Q_OS_ANDROID + qputenv("QT_SCALE_FACTOR", "2"); +#endif QApplication app(argc, argv); diff --git a/examples/widgets/tools/undo/main.cpp b/examples/widgets/tools/undo/main.cpp index a5ec1b1b83..1a6dcf8c48 100644 --- a/examples/widgets/tools/undo/main.cpp +++ b/examples/widgets/tools/undo/main.cpp @@ -54,6 +54,9 @@ int main(int argc, char **argv) { Q_INIT_RESOURCE(undo); +#ifdef Q_OS_ANDROID + QApplication::setAttribute(Qt::AA_EnableHighDpiScaling); +#endif QApplication app(argc, argv); diff --git a/examples/widgets/widgets/calculator/main.cpp b/examples/widgets/widgets/calculator/main.cpp index a034bb262e..5f59d00ca6 100644 --- a/examples/widgets/widgets/calculator/main.cpp +++ b/examples/widgets/widgets/calculator/main.cpp @@ -54,6 +54,9 @@ int main(int argc, char *argv[]) { +#ifdef Q_OS_ANDROID + QApplication::setAttribute(Qt::AA_EnableHighDpiScaling); +#endif QApplication app(argc, argv); Calculator calc; calc.show(); diff --git a/examples/widgets/widgets/elidedlabel/main.cpp b/examples/widgets/widgets/elidedlabel/main.cpp index 1c620c1d41..58507766e7 100644 --- a/examples/widgets/widgets/elidedlabel/main.cpp +++ b/examples/widgets/widgets/elidedlabel/main.cpp @@ -55,6 +55,9 @@ //! [0] int main( int argc, char *argv[] ) { +#ifdef Q_OS_ANDROID + QApplication::setAttribute(Qt::AA_EnableHighDpiScaling); +#endif QApplication application( argc, argv ); TestWidget w; w.showFullScreen(); diff --git a/examples/widgets/widgets/scribble/main.cpp b/examples/widgets/widgets/scribble/main.cpp index 1bf46b226f..cec6929827 100644 --- a/examples/widgets/widgets/scribble/main.cpp +++ b/examples/widgets/widgets/scribble/main.cpp @@ -54,6 +54,9 @@ int main(int argc, char *argv[]) { +#ifdef Q_OS_ANDROID + QApplication::setAttribute(Qt::AA_EnableHighDpiScaling); +#endif QApplication app(argc, argv); MainWindow window; window.show(); diff --git a/examples/widgets/widgets/sliders/main.cpp b/examples/widgets/widgets/sliders/main.cpp index 99725195e5..9bf18cb6d4 100644 --- a/examples/widgets/widgets/sliders/main.cpp +++ b/examples/widgets/widgets/sliders/main.cpp @@ -54,6 +54,9 @@ int main(int argc, char *argv[]) { +#ifdef Q_OS_ANDROID + QApplication::setAttribute(Qt::AA_EnableHighDpiScaling); +#endif QApplication app(argc, argv); Window window; window.show(); diff --git a/examples/xml/rsslisting/rsslisting.cpp b/examples/xml/rsslisting/rsslisting.cpp index d1b4373531..143ad6dcba 100644 --- a/examples/xml/rsslisting/rsslisting.cpp +++ b/examples/xml/rsslisting/rsslisting.cpp @@ -131,7 +131,7 @@ void RSSListing::get(const QUrl &url) currentReply = manager.get(request); connect(currentReply, SIGNAL(readyRead()), this, SLOT(readyRead())); connect(currentReply, SIGNAL(metaDataChanged()), this, SLOT(metaDataChanged())); - connect(currentReply, SIGNAL(error(QNetworkReply::NetworkError)), this, SLOT(error(QNetworkReply::NetworkError))); + connect(currentReply, SIGNAL(errorOccurred(QNetworkReply::NetworkError)), this, SLOT(error(QNetworkReply::NetworkError))); } /* diff --git a/mkspecs/features/qt_common.prf b/mkspecs/features/qt_common.prf index 02460a2e0c..ac24b03b6b 100644 --- a/mkspecs/features/qt_common.prf +++ b/mkspecs/features/qt_common.prf @@ -20,11 +20,11 @@ qtConfig(c++1z): CONFIG += c++1z qtConfig(c++2a): CONFIG += c++2a qtConfig(c99): CONFIG += c99 qtConfig(c11): CONFIG += c11 +qtConfig(separate_debug_info): CONFIG += separate_debug_info qtConfig(stack-protector-strong): CONFIG += stack_protector_strong contains(TEMPLATE, .*lib) { # module and plugins unix:qtConfig(reduce_relocations): CONFIG += bsymbolic_functions - qtConfig(separate_debug_info): CONFIG += separate_debug_info !isEmpty(_QMAKE_SUPER_CACHE_): \ rplbase = $$dirname(_QMAKE_SUPER_CACHE_)/[^/][^/]* diff --git a/src/corelib/global/qfloat16.cpp b/src/corelib/global/qfloat16.cpp index 80a851e4e4..3d82bbe95a 100644 --- a/src/corelib/global/qfloat16.cpp +++ b/src/corelib/global/qfloat16.cpp @@ -147,7 +147,7 @@ QT_BEGIN_NAMESPACE /*! \since 5.15 - \fn qfloat16::copySign(qfloat16 sign) const noexcept + \fn qfloat16 qfloat16::copySign(qfloat16 sign) const noexcept Returns a qfloat16 with the sign of \a sign but the rest of its value taken from this qfloat16. Serves as qfloat16's equivalent of std::copysign(). diff --git a/src/corelib/kernel/qeventdispatcher_win.cpp b/src/corelib/kernel/qeventdispatcher_win.cpp index 8616631603..f2216d4113 100644 --- a/src/corelib/kernel/qeventdispatcher_win.cpp +++ b/src/corelib/kernel/qeventdispatcher_win.cpp @@ -884,7 +884,11 @@ void QEventDispatcherWin32::unregisterEventNotifier(QWinEventNotifier *notifier) return; } #endif + doUnregisterEventNotifier(notifier); +} +void QEventDispatcherWin32::doUnregisterEventNotifier(QWinEventNotifier *notifier) +{ Q_D(QEventDispatcherWin32); int i = d->winEventNotifierList.indexOf(notifier); @@ -996,6 +1000,10 @@ void QEventDispatcherWin32::closingDown() doUnregisterSocketNotifier((*(d->sn_except.begin()))->obj); Q_ASSERT(d->active_fd.isEmpty()); + // clean up any eventnotifiers + while (!d->winEventNotifierList.isEmpty()) + doUnregisterEventNotifier(d->winEventNotifierList.first()); + // clean up any timers for (int i = 0; i < d->timerVec.count(); ++i) d->unregisterTimer(d->timerVec.at(i)); diff --git a/src/corelib/kernel/qeventdispatcher_win_p.h b/src/corelib/kernel/qeventdispatcher_win_p.h index e6620178d8..a482c8b7db 100644 --- a/src/corelib/kernel/qeventdispatcher_win_p.h +++ b/src/corelib/kernel/qeventdispatcher_win_p.h @@ -110,6 +110,7 @@ protected: QEventDispatcherWin32(QEventDispatcherWin32Private &dd, QObject *parent = 0); virtual void sendPostedEvents(); void doUnregisterSocketNotifier(QSocketNotifier *notifier); + void doUnregisterEventNotifier(QWinEventNotifier *notifier); private: friend LRESULT QT_WIN_CALLBACK qt_internal_proc(HWND hwnd, UINT message, WPARAM wp, LPARAM lp); diff --git a/src/corelib/kernel/qwineventnotifier.cpp b/src/corelib/kernel/qwineventnotifier.cpp index db5d44b276..0c574e9a4b 100644 --- a/src/corelib/kernel/qwineventnotifier.cpp +++ b/src/corelib/kernel/qwineventnotifier.cpp @@ -198,11 +198,8 @@ void QWinEventNotifier::setEnabled(bool enable) d->enabled = enable; QAbstractEventDispatcher *eventDispatcher = d->threadData.loadRelaxed()->eventDispatcher.loadRelaxed(); - if (!eventDispatcher) { // perhaps application is shutting down - if (!enable && d->waitHandle != nullptr) - d->unregisterWaitObject(); + if (!eventDispatcher) // perhaps application is shutting down return; - } if (Q_UNLIKELY(thread() != QThread::currentThread())) { qWarning("QWinEventNotifier: Event notifiers cannot be enabled or disabled from another thread"); return; diff --git a/src/corelib/mimetypes/qmimeprovider.cpp b/src/corelib/mimetypes/qmimeprovider.cpp index 4aee772366..9dba72923a 100644 --- a/src/corelib/mimetypes/qmimeprovider.cpp +++ b/src/corelib/mimetypes/qmimeprovider.cpp @@ -664,7 +664,15 @@ QMimeXMLProvider::QMimeXMLProvider(QMimeDatabasePrivate *db, InternalDatabaseEnu load(data, size); } -#endif +#else // !QT_CONFIG(mimetype_database) +// never called in release mode, but some debug builds may need +// this to be defined. +QMimeXMLProvider::QMimeXMLProvider(QMimeDatabasePrivate *db, InternalDatabaseEnum) + : QMimeProviderBase(db, QString()) +{ + Q_UNREACHABLE(); +} +#endif // QT_CONFIG(mimetype_database) QMimeXMLProvider::QMimeXMLProvider(QMimeDatabasePrivate *db, const QString &directory) : QMimeProviderBase(db, directory) diff --git a/src/corelib/mimetypes/qmimeprovider_p.h b/src/corelib/mimetypes/qmimeprovider_p.h index c4e712b318..9c91903684 100644 --- a/src/corelib/mimetypes/qmimeprovider_p.h +++ b/src/corelib/mimetypes/qmimeprovider_p.h @@ -135,13 +135,10 @@ public: enum InternalDatabaseEnum { InternalDatabase }; #if QT_CONFIG(mimetype_database) enum : bool { InternalDatabaseAvailable = true }; - QMimeXMLProvider(QMimeDatabasePrivate *db, InternalDatabaseEnum); #else enum : bool { InternalDatabaseAvailable = false }; - QMimeXMLProvider(QMimeDatabasePrivate *db, InternalDatabaseEnum) - : QMimeProviderBase(db, QString()) - { Q_UNREACHABLE(); }; #endif + QMimeXMLProvider(QMimeDatabasePrivate *db, InternalDatabaseEnum); QMimeXMLProvider(QMimeDatabasePrivate *db, const QString &directory); ~QMimeXMLProvider(); diff --git a/src/corelib/text/qstring.cpp b/src/corelib/text/qstring.cpp index da2c44bef6..757f248e8a 100644 --- a/src/corelib/text/qstring.cpp +++ b/src/corelib/text/qstring.cpp @@ -7626,7 +7626,10 @@ static ResultList splitString(const StringSource &source, const QChar *sep, #if QT_DEPRECATED_SINCE(5, 15) Qt::SplitBehavior mapSplitBehavior(QString::SplitBehavior sb) { +QT_WARNING_PUSH +QT_WARNING_DISABLE_DEPRECATED return sb & QString::SkipEmptyParts ? Qt::SkipEmptyParts : Qt::KeepEmptyParts; +QT_WARNING_POP } #endif diff --git a/src/corelib/time/qdatetime.cpp b/src/corelib/time/qdatetime.cpp index e9fe34110a..47539141bd 100644 --- a/src/corelib/time/qdatetime.cpp +++ b/src/corelib/time/qdatetime.cpp @@ -1383,6 +1383,10 @@ QT_WARNING_POP If the datetime is invalid, an empty string will be returned. + \note If localized month and day names are desired, please switch to using + QLocale::system().toString() as QDate methods shall change to use English (C + locale) names at Qt 6. + \sa fromString(), QDateTime::toString(), QTime::toString(), QLocale::toString() */ @@ -1884,6 +1888,10 @@ QT_WARNING_POP \snippet code/src_corelib_tools_qdatetime.cpp 3 + \note If localized month and day names are used, please switch to using + QLocale::system().toDate() as QDate methods shall change to only recognize + English (C locale) names at Qt 6. + \sa toString(), QDateTime::fromString(), QTime::fromString(), QLocale::toDate() */ @@ -2244,6 +2252,10 @@ QT_WARNING_POP If the time is invalid, an empty string will be returned. If \a format is empty, the default format "hh:mm:ss" is used. + \note If localized forms of am or pm (the AP, ap, A or a formats) are + desired, please switch to using QLocale::system().toString() as QTime + methods shall change to use English (C locale) at Qt 6. + \sa fromString(), QDate::toString(), QDateTime::toString(), QLocale::toString() */ QString QTime::toString(QStringView format) const @@ -2641,6 +2653,10 @@ QT_WARNING_POP \snippet code/src_corelib_tools_qdatetime.cpp 8 + \note If localized forms of am or pm (the AP, ap, A or a formats) are used, + please switch to using QLocale::system().toTime() as QTime methods shall + change to only recognize English (C locale) at Qt 6. + \sa toString(), QDateTime::fromString(), QDate::fromString(), QLocale::toTime() */ @@ -4541,6 +4557,10 @@ QT_WARNING_POP If the datetime is invalid, an empty string will be returned. + \note If localized month and day names are desired, please switch to using + QLocale::system().toString() as QDateTime methods shall change to use + English (C locale) names at Qt 6. + \sa fromString(), QDate::toString(), QTime::toString(), QLocale::toString() */ QString QDateTime::toString(QStringView format) const @@ -5580,6 +5600,10 @@ QT_WARNING_POP \snippet code/src_corelib_tools_qdatetime.cpp 14 + \note If localized month and day names are used, please switch to using + QLocale::system().toDateTime() as QDateTime methods shall change to only + recognize English (C locale) names at Qt 6. + \sa toString(), QDate::fromString(), QTime::fromString(), QLocale::toDateTime() */ diff --git a/src/corelib/tools/qhash.cpp b/src/corelib/tools/qhash.cpp index 15f731a603..7ebc374d9f 100644 --- a/src/corelib/tools/qhash.cpp +++ b/src/corelib/tools/qhash.cpp @@ -1574,7 +1574,6 @@ uint qHash(long double key, uint seed) noexcept */ /*! \fn template int QHash::count(const Key &key) const - \obsolete Returns the number of items associated with the \a key. @@ -2693,13 +2692,6 @@ uint qHash(long double key, uint seed) noexcept \sa QHash::remove() */ -/*! \fn template int QMultiHash::count(const Key &key) const - - Returns the number of items associated with the \a key. - - \sa contains(), insert() -*/ - /*! \fn template int QMultiHash::count(const Key &key, const T &value) const \since 4.3 diff --git a/src/corelib/tools/qhash.h b/src/corelib/tools/qhash.h index 59883e3968..c87cf56988 100644 --- a/src/corelib/tools/qhash.h +++ b/src/corelib/tools/qhash.h @@ -309,10 +309,10 @@ public: QList keys(const T &value) const; QList values() const; #if QT_DEPRECATED_SINCE(5, 15) - QT_DEPRECATED_X("Use QMultiHash for hashes storing multiple values with the same key.") QList uniqueKeys() const; - QT_DEPRECATED_X("Use QMultiHash for hashes storing multiple values with the same key.") QList values(const Key &key) const; - QT_DEPRECATED_X("Use QMultiHash for hashes storing multiple values with the same key.") int count(const Key &key) const; + QT_DEPRECATED_VERSION_X_5_15("Use QMultiHash for hashes storing multiple values with the same key.") QList uniqueKeys() const; + QT_DEPRECATED_VERSION_X_5_15("Use QMultiHash for hashes storing multiple values with the same key.") QList values(const Key &key) const; #endif + int count(const Key &key) const; class const_iterator; @@ -512,8 +512,8 @@ public: iterator insert(const Key &key, const T &value); void insert(const QHash &hash); #if QT_DEPRECATED_SINCE(5, 15) - QT_DEPRECATED_X("Use QMultiHash for hashes storing multiple values with the same key.") iterator insertMulti(const Key &key, const T &value); - QT_DEPRECATED_X("Use QMultiHash for hashes storing multiple values with the same key.") QHash &unite(const QHash &other); + QT_DEPRECATED_VERSION_X_5_15("Use QMultiHash for hashes storing multiple values with the same key.") iterator insertMulti(const Key &key, const T &value); + QT_DEPRECATED_VERSION_X_5_15("Use QMultiHash for hashes storing multiple values with the same key.") QHash &unite(const QHash &other); #endif // STL compatibility @@ -710,6 +710,19 @@ Q_OUTOFLINE_TEMPLATE QList QHash::values() const return res; } +template +Q_OUTOFLINE_TEMPLATE int QHash::count(const Key &akey) const +{ + int cnt = 0; + Node *node = *findNode(akey); + if (node != e) { + do { + ++cnt; + } while ((node = node->next) != e && node->key == akey); + } + return cnt; +} + template Q_INLINE_TEMPLATE const T QHash::operator[](const Key &akey) const { @@ -1053,7 +1066,6 @@ public: int remove(const Key &key, const T &value); - int count(const Key &key) const; int count(const Key &key, const T &value) const; QList uniqueKeys() const; @@ -1206,12 +1218,6 @@ Q_OUTOFLINE_TEMPLATE QList QHash::values(const Key &akey) const return static_cast *>(this)->values(akey); } -template -Q_OUTOFLINE_TEMPLATE int QHash::count(const Key &akey) const -{ - return static_cast *>(this)->count(akey); -} - template Q_OUTOFLINE_TEMPLATE QList QHash::uniqueKeys() const { @@ -1232,19 +1238,6 @@ Q_OUTOFLINE_TEMPLATE QList QMultiHash::values(const Key &akey) const return res; } -template -Q_OUTOFLINE_TEMPLATE int QMultiHash::count(const Key &akey) const -{ - int cnt = 0; - Node *node = *findNode(akey); - if (node != this->e) { - do { - ++cnt; - } while ((node = node->next) != this->e && node->key == akey); - } - return cnt; -} - #if !defined(QT_NO_JAVA_STYLE_ITERATORS) template class QHashIterator diff --git a/src/corelib/tools/qiterator.h b/src/corelib/tools/qiterator.h index 84a0e116ca..c4665c7c87 100644 --- a/src/corelib/tools/qiterator.h +++ b/src/corelib/tools/qiterator.h @@ -195,7 +195,6 @@ public: typedef typename Iterator::iterator_category iterator_category; typedef typename Iterator::difference_type difference_type; typedef std::pair value_type; - typedef const value_type *pointer; typedef const value_type &reference; QKeyValueIterator() = default; @@ -206,6 +205,31 @@ public: return std::pair(i.key(), i.value()); } + struct pointer { + pointer(value_type&& r_) + : r(std::move(r_)) + {} + + pointer() = default; + pointer(const pointer &other) = default; + pointer(pointer &&other) = default; + pointer& operator=(const pointer &other) = default; + pointer& operator=(pointer &&other) = default; + + value_type& operator*() const { + return r; + } + + value_type r; + const value_type *operator->() const { + return &r; + } + }; + + pointer operator->() const { + return pointer(std::pair(i.key(), i.value())); + } + friend bool operator==(QKeyValueIterator lhs, QKeyValueIterator rhs) noexcept { return lhs.i == rhs.i; } friend bool operator!=(QKeyValueIterator lhs, QKeyValueIterator rhs) noexcept { return lhs.i != rhs.i; } diff --git a/src/corelib/tools/qiterator.qdoc b/src/corelib/tools/qiterator.qdoc index 69f9d52ce5..8cfa665ffd 100644 --- a/src/corelib/tools/qiterator.qdoc +++ b/src/corelib/tools/qiterator.qdoc @@ -57,7 +57,7 @@ \internal */ -/*! \typedef QKeyValueIterator::pointer +/*! \struct QKeyValueIterator::pointer \internal */ @@ -75,11 +75,20 @@ Constructs a QKeyValueIterator on top of \a o. */ -/*! \fn template const T &QKeyValueIterator::operator*() const +/*! \fn template std::pair QKeyValueIterator::operator*() const Returns the current entry as a pair. */ +/*! \fn template pointer QKeyValueIterator::operator->() const + + Returns the current entry as a pointer-like object to the pair. + + \since 5.15 + + \sa operator*() +*/ + /*! \fn template bool operator==(QKeyValueIterator lhs, QKeyValueIterator rhs) \relates QKeyValueIterator diff --git a/src/corelib/tools/qmap.cpp b/src/corelib/tools/qmap.cpp index 6d2b8f7a3e..25ea5f25d7 100644 --- a/src/corelib/tools/qmap.cpp +++ b/src/corelib/tools/qmap.cpp @@ -814,11 +814,10 @@ void QMapDataBase::freeData(QMapDataBase *d) */ /*! \fn template int QMap::count(const Key &key) const - \obsolete Returns the number of items associated with key \a key. - \sa QMultiMap::count() + \sa contains(), QMultiMap::count() */ /*! \fn template int QMap::count() const @@ -2115,11 +2114,6 @@ void QMapDataBase::freeData(QMapDataBase *d) inserted one. */ -/*! \fn template int QMultiMap::count(const Key &key) const - - Returns the number of items associated with key \a key. -*/ - /*! \fn template QList QMultiMap::uniqueKeys() const \since 4.2 diff --git a/src/corelib/tools/qmap.h b/src/corelib/tools/qmap.h index a971919e54..6081019294 100644 --- a/src/corelib/tools/qmap.h +++ b/src/corelib/tools/qmap.h @@ -373,10 +373,10 @@ public: QList keys(const T &value) const; QList values() const; #if QT_DEPRECATED_SINCE(5, 15) - QT_DEPRECATED_X("Use QMultiMap for maps storing multiple values with the same key.") QList uniqueKeys() const; - QT_DEPRECATED_X("Use QMultiMap for maps storing multiple values with the same key.") QList values(const Key &key) const; - QT_DEPRECATED_X("Use QMultiMap for maps storing multiple values with the same key.") int count(const Key &key) const; + QT_DEPRECATED_VERSION_X_5_15("Use QMultiMap for maps storing multiple values with the same key.") QList uniqueKeys() const; + QT_DEPRECATED_VERSION_X_5_15("Use QMultiMap for maps storing multiple values with the same key.") QList values(const Key &key) const; #endif + int count(const Key &key) const; inline const Key &firstKey() const { Q_ASSERT(!isEmpty()); return constBegin().key(); } @@ -559,9 +559,9 @@ public: iterator insert(const_iterator pos, const Key &key, const T &value); void insert(const QMap &map); #if QT_DEPRECATED_SINCE(5, 15) - QT_DEPRECATED_X("Use QMultiMap for maps storing multiple values with the same key.") iterator insertMulti(const Key &key, const T &value); - QT_DEPRECATED_X("Use QMultiMap for maps storing multiple values with the same key.") iterator insertMulti(const_iterator pos, const Key &akey, const T &avalue); - QT_DEPRECATED_X("Use QMultiMap for maps storing multiple values with the same key.") QMap &unite(const QMap &other); + QT_DEPRECATED_VERSION_X_5_15("Use QMultiMap for maps storing multiple values with the same key.") iterator insertMulti(const Key &key, const T &value); + QT_DEPRECATED_VERSION_X_5_15("Use QMultiMap for maps storing multiple values with the same key.") iterator insertMulti(const_iterator pos, const Key &akey, const T &avalue); + QT_DEPRECATED_VERSION_X_5_15("Use QMultiMap for maps storing multiple values with the same key.") QMap &unite(const QMap &other); #endif // STL compatibility @@ -654,6 +654,23 @@ Q_INLINE_TEMPLATE T &QMap::operator[](const Key &akey) return n->value; } +template +Q_INLINE_TEMPLATE int QMap::count(const Key &akey) const +{ + Node *firstNode; + Node *lastNode; + d->nodeRange(akey, &firstNode, &lastNode); + + const_iterator ci_first(firstNode); + const const_iterator ci_last(lastNode); + int cnt = 0; + while (ci_first != ci_last) { + ++cnt; + ++ci_first; + } + return cnt; +} + template Q_INLINE_TEMPLATE bool QMap::contains(const Key &akey) const { @@ -1116,7 +1133,6 @@ public: int remove(const Key &key, const T &value); - int count(const Key &key) const; int count(const Key &key, const T &value) const; typename QMap::iterator find(const Key &key, const T &value) { @@ -1289,23 +1305,6 @@ Q_INLINE_TEMPLATE int QMultiMap::remove(const Key &key, const T &value) return n; } -template -Q_INLINE_TEMPLATE int QMultiMap::count(const Key &akey) const -{ - QMultiMap::Node *firstNode; - QMultiMap::Node *lastNode; - this->d->nodeRange(akey, &firstNode, &lastNode); - - typename QMap::const_iterator ci_first(firstNode); - const typename QMap::const_iterator ci_last(lastNode); - int cnt = 0; - while (ci_first != ci_last) { - ++cnt; - ++ci_first; - } - return cnt; -} - template Q_INLINE_TEMPLATE int QMultiMap::count(const Key &key, const T &value) const { @@ -1333,12 +1332,6 @@ QList QMap::values(const Key &key) const return static_cast *>(this)->values(key); } -template -int QMap::count(const Key &key) const -{ - return static_cast *>(this)->count(key); -} - template typename QMap::iterator QMap::insertMulti(const Key &key, const T &value) { diff --git a/src/gui/image/qbmphandler.cpp b/src/gui/image/qbmphandler.cpp index d447faaceb..d559913161 100644 --- a/src/gui/image/qbmphandler.cpp +++ b/src/gui/image/qbmphandler.cpp @@ -870,13 +870,6 @@ void QBmpHandler::setOption(ImageOption option, const QVariant &value) Q_UNUSED(value); } -#if QT_DEPRECATED_SINCE(5, 13) -QByteArray QBmpHandler::name() const -{ - return formatName(); -} -#endif - QT_END_NAMESPACE #endif // QT_NO_IMAGEFORMAT_BMP diff --git a/src/gui/image/qbmphandler_p.h b/src/gui/image/qbmphandler_p.h index 33b5b9c501..fd044fc442 100644 --- a/src/gui/image/qbmphandler_p.h +++ b/src/gui/image/qbmphandler_p.h @@ -113,9 +113,6 @@ public: bool read(QImage *image) override; bool write(const QImage &image) override; -#if QT_DEPRECATED_SINCE(5, 13) - QByteArray name() const override; -#endif static bool canRead(QIODevice *device); QVariant option(ImageOption option) const override; diff --git a/src/gui/image/qpnghandler.cpp b/src/gui/image/qpnghandler.cpp index e6a3604ad4..5738148718 100644 --- a/src/gui/image/qpnghandler.cpp +++ b/src/gui/image/qpnghandler.cpp @@ -1296,13 +1296,6 @@ void QPngHandler::setOption(ImageOption option, const QVariant &value) d->scaledSize = value.toSize(); } -#if QT_DEPRECATED_SINCE(5, 13) -QByteArray QPngHandler::name() const -{ - return "png"; -} -#endif - QT_END_NAMESPACE #endif // QT_NO_IMAGEFORMAT_PNG diff --git a/src/gui/image/qpnghandler_p.h b/src/gui/image/qpnghandler_p.h index 5d4da97395..9e12d2d081 100644 --- a/src/gui/image/qpnghandler_p.h +++ b/src/gui/image/qpnghandler_p.h @@ -69,10 +69,6 @@ public: bool read(QImage *image) override; bool write(const QImage &image) override; -#if QT_DEPRECATED_SINCE(5, 13) - QByteArray name() const override; -#endif - QVariant option(ImageOption option) const override; void setOption(ImageOption option, const QVariant &value) override; bool supportsOption(ImageOption option) const override; diff --git a/src/gui/image/qppmhandler.cpp b/src/gui/image/qppmhandler.cpp index 195e58d283..16136e6be3 100644 --- a/src/gui/image/qppmhandler.cpp +++ b/src/gui/image/qppmhandler.cpp @@ -576,13 +576,6 @@ void QPpmHandler::setOption(ImageOption option, const QVariant &value) subType = value.toByteArray().toLower(); } -#if QT_DEPRECATED_SINCE(5, 13) -QByteArray QPpmHandler::name() const -{ - return subType.isEmpty() ? QByteArray("ppm") : subType; -} -#endif - QT_END_NAMESPACE #endif // QT_NO_IMAGEFORMAT_PPM diff --git a/src/gui/image/qppmhandler_p.h b/src/gui/image/qppmhandler_p.h index 2f3811b759..f2faf93984 100644 --- a/src/gui/image/qppmhandler_p.h +++ b/src/gui/image/qppmhandler_p.h @@ -67,10 +67,6 @@ public: bool read(QImage *image) override; bool write(const QImage &image) override; -#if QT_DEPRECATED_SINCE(5, 13) - QByteArray name() const override; -#endif - static bool canRead(QIODevice *device, QByteArray *subType = nullptr); QVariant option(ImageOption option) const override; diff --git a/src/gui/image/qxbmhandler.cpp b/src/gui/image/qxbmhandler.cpp index 3cd15b3e4d..f06561690c 100644 --- a/src/gui/image/qxbmhandler.cpp +++ b/src/gui/image/qxbmhandler.cpp @@ -357,13 +357,6 @@ void QXbmHandler::setOption(ImageOption option, const QVariant &value) fileName = value.toString(); } -#if QT_DEPRECATED_SINCE(5, 13) -QByteArray QXbmHandler::name() const -{ - return "xbm"; -} -#endif - QT_END_NAMESPACE #endif // QT_NO_IMAGEFORMAT_XBM diff --git a/src/gui/image/qxbmhandler_p.h b/src/gui/image/qxbmhandler_p.h index ae590a1944..db5f352d46 100644 --- a/src/gui/image/qxbmhandler_p.h +++ b/src/gui/image/qxbmhandler_p.h @@ -66,10 +66,6 @@ public: bool read(QImage *image) override; bool write(const QImage &image) override; -#if QT_DEPRECATED_SINCE(5, 13) - QByteArray name() const override; -#endif - static bool canRead(QIODevice *device); QVariant option(ImageOption option) const override; diff --git a/src/gui/image/qxpmhandler.cpp b/src/gui/image/qxpmhandler.cpp index f9424b62bb..07fec929bf 100644 --- a/src/gui/image/qxpmhandler.cpp +++ b/src/gui/image/qxpmhandler.cpp @@ -1280,13 +1280,6 @@ void QXpmHandler::setOption(ImageOption option, const QVariant &value) fileName = value.toString(); } -#if QT_DEPRECATED_SINCE(5, 13) -QByteArray QXpmHandler::name() const -{ - return "xpm"; -} -#endif - QT_END_NAMESPACE #endif // QT_NO_IMAGEFORMAT_XPM diff --git a/src/gui/image/qxpmhandler_p.h b/src/gui/image/qxpmhandler_p.h index a4dd88cd17..646e8df69e 100644 --- a/src/gui/image/qxpmhandler_p.h +++ b/src/gui/image/qxpmhandler_p.h @@ -68,10 +68,6 @@ public: static bool canRead(QIODevice *device); -#if QT_DEPRECATED_SINCE(5, 13) - QByteArray name() const override; -#endif - QVariant option(ImageOption option) const override; void setOption(ImageOption option, const QVariant &value) override; bool supportsOption(ImageOption option) const override; diff --git a/src/gui/kernel/qwindow.cpp b/src/gui/kernel/qwindow.cpp index c099ec9692..702c055fbb 100644 --- a/src/gui/kernel/qwindow.cpp +++ b/src/gui/kernel/qwindow.cpp @@ -1731,7 +1731,7 @@ void QWindow::setGeometry(const QRect &rect) if (newScreen && isTopLevel()) nativeRect = QHighDpi::toNativePixels(rect, newScreen); else - nativeRect = QHighDpi::toNativePixels(rect, this); + nativeRect = QHighDpi::toNativeLocalPosition(rect, newScreen); d->platformWindow->setGeometry(nativeRect); } else { d->geometry = rect; @@ -1782,8 +1782,12 @@ QScreen *QWindowPrivate::screenForGeometry(const QRect &newGeometry) const QRect QWindow::geometry() const { Q_D(const QWindow); - if (d->platformWindow) - return QHighDpi::fromNativePixels(d->platformWindow->geometry(), this); + if (d->platformWindow) { + const auto nativeGeometry = d->platformWindow->geometry(); + return isTopLevel() + ? QHighDpi::fromNativePixels(nativeGeometry, this) + : QHighDpi::fromNativeLocalPosition(nativeGeometry, this); + } return d->geometry; } diff --git a/src/gui/kernel/qwindowsysteminterface.cpp b/src/gui/kernel/qwindowsysteminterface.cpp index 2de0131640..6ecd908296 100644 --- a/src/gui/kernel/qwindowsysteminterface.cpp +++ b/src/gui/kernel/qwindowsysteminterface.cpp @@ -298,14 +298,21 @@ QWindowSystemInterfacePrivate::GeometryChangeEvent::GeometryChangeEvent(QWindow , window(window) , newGeometry(newGeometry) { - if (const QPlatformWindow *pw = window->handle()) - requestedGeometry = QHighDpi::fromNativePixels(pw->QPlatformWindow::geometry(), window); + if (const QPlatformWindow *pw = window->handle()) { + const auto nativeGeometry = pw->QPlatformWindow::geometry(); + requestedGeometry = window->isTopLevel() + ? QHighDpi::fromNativePixels(nativeGeometry, window) + : QHighDpi::fromNativeLocalPosition(nativeGeometry, window); + } } QT_DEFINE_QPA_EVENT_HANDLER(void, handleGeometryChange, QWindow *window, const QRect &newRect) { Q_ASSERT(window); - QWindowSystemInterfacePrivate::GeometryChangeEvent *e = new QWindowSystemInterfacePrivate::GeometryChangeEvent(window, QHighDpi::fromNativePixels(newRect, window)); + const auto newRectDi = window->isTopLevel() + ? QHighDpi::fromNativePixels(newRect, window) + : QHighDpi::fromNativeLocalPosition(newRect, window); + auto e = new QWindowSystemInterfacePrivate::GeometryChangeEvent(window, newRectDi); if (window->handle()) { // Persist the new geometry so that QWindow::geometry() can be queried in the resize event window->handle()->QPlatformWindow::setGeometry(newRect); diff --git a/src/gui/rhi/qrhi.cpp b/src/gui/rhi/qrhi.cpp index 7a0d53e1e4..c805e23ad0 100644 --- a/src/gui/rhi/qrhi.cpp +++ b/src/gui/rhi/qrhi.cpp @@ -2048,11 +2048,9 @@ QRhiResource::Type QRhiBuffer::resourceType() const UniformBuffer may not even be backed by a native buffer object at all if uniform buffers are not used or supported by a given backend and graphics API. There are also differences to how data is written to the buffer and - the type of backing memory used, and, if host visible memory is involved, - when memory writes become available and visible. Therefore, in general it - is recommended to limit native buffer object access to vertex and index - buffers with types Static or Immutable, because these operate in a - relatively uniform manner with all backends. + the type of backing memory used. For buffers backed by host visible memory, + calling this function guarantees that pending host writes are executed for + all the returned native buffers. \sa QRhi::currentFrameSlot(), QRhi::FramesInFlight */ @@ -2341,6 +2339,31 @@ bool QRhiTexture::buildFrom(QRhiTexture::NativeTexture src) return false; } +/*! + With some graphics APIs, such as Vulkan, integrating custom rendering code + that uses the graphics API directly needs special care when it comes to + image layouts. This function allows communicating the expected layout the + image backing the QRhiTexture is in after the native rendering commands. + + For example, consider rendering into a QRhiTexture's VkImage directly with + Vulkan in a code block enclosed by QRhiCommandBuffer::beginExternal() and + QRhiCommandBuffer::endExternal(), followed by using the image for texture + sampling in a QRhi-based render pass. To avoid potentially incorrect image + layout transitions, this function can be used to indicate what the image + layout will be once the commands recorded in said code block complete. + + Calling this function makes sense only after + QRhiCommandBuffer::endExternal() and before a subsequent + QRhiCommandBuffer::beginPass(). + + This function has no effect with QRhi backends where the underlying + graphics API does not expose a concept of image layouts. + */ +void QRhiTexture::setNativeLayout(int layout) +{ + Q_UNUSED(layout); +} + /*! \class QRhiSampler \internal diff --git a/src/gui/rhi/qrhi_p.h b/src/gui/rhi/qrhi_p.h index 8f53808d34..17c911a5ff 100644 --- a/src/gui/rhi/qrhi_p.h +++ b/src/gui/rhi/qrhi_p.h @@ -791,6 +791,7 @@ public: virtual bool build() = 0; virtual NativeTexture nativeTexture(); virtual bool buildFrom(NativeTexture src); + virtual void setNativeLayout(int layout); protected: QRhiTexture(QRhiImplementation *rhi, Format format_, const QSize &pixelSize_, diff --git a/src/gui/rhi/qrhid3d11.cpp b/src/gui/rhi/qrhid3d11.cpp index f7c7f4a9f2..7b583e6fd2 100644 --- a/src/gui/rhi/qrhid3d11.cpp +++ b/src/gui/rhi/qrhid3d11.cpp @@ -580,6 +580,11 @@ void QRhiD3D11::setGraphicsPipeline(QRhiCommandBuffer *cb, QRhiGraphicsPipeline } } +static const int RBM_SUPPORTED_STAGES = 3; +static const int RBM_VERTEX = 0; +static const int RBM_FRAGMENT = 1; +static const int RBM_COMPUTE = 2; + void QRhiD3D11::setShaderResources(QRhiCommandBuffer *cb, QRhiShaderResourceBindings *srb, int dynamicOffsetCount, const QRhiCommandBuffer::DynamicOffset *dynamicOffsets) @@ -608,7 +613,7 @@ void QRhiD3D11::setShaderResources(QRhiCommandBuffer *cb, QRhiShaderResourceBind { QD3D11Buffer *bufD = QRHI_RES(QD3D11Buffer, b->u.ubuf.buf); if (bufD->m_type == QRhiBuffer::Dynamic) - executeBufferHostWritesForCurrentFrame(bufD); + executeBufferHostWrites(bufD); if (bufD->generation != bd.ubuf.generation || bufD->m_id != bd.ubuf.id) { srbUpdate = true; @@ -667,8 +672,17 @@ void QRhiD3D11::setShaderResources(QRhiCommandBuffer *cb, QRhiShaderResourceBind } } - if (srbUpdate) - updateShaderResourceBindings(srbD); + if (srbUpdate) { + const QShader::NativeResourceBindingMap *resBindMaps[RBM_SUPPORTED_STAGES]; + memset(resBindMaps, 0, sizeof(resBindMaps)); + if (gfxPsD) { + resBindMaps[RBM_VERTEX] = &gfxPsD->vs.nativeResourceBindingMap; + resBindMaps[RBM_FRAGMENT] = &gfxPsD->fs.nativeResourceBindingMap; + } else { + resBindMaps[RBM_COMPUTE] = &compPsD->cs.nativeResourceBindingMap; + } + updateShaderResourceBindings(srbD, resBindMaps); + } const bool srbChanged = gfxPsD ? (cbD->currentGraphicsSrb != srb) : (cbD->currentComputeSrb != srb); const bool srbRebuilt = cbD->currentSrbGeneration != srbD->generation; @@ -725,7 +739,7 @@ void QRhiD3D11::setVertexInput(QRhiCommandBuffer *cb, QD3D11Buffer *bufD = QRHI_RES(QD3D11Buffer, bindings[i].first); Q_ASSERT(bufD->m_usage.testFlag(QRhiBuffer::VertexBuffer)); if (bufD->m_type == QRhiBuffer::Dynamic) - executeBufferHostWritesForCurrentFrame(bufD); + executeBufferHostWrites(bufD); if (cbD->currentVertexBuffers[inputSlot] != bufD->buffer || cbD->currentVertexOffsets[inputSlot] != bindings[i].second) @@ -757,7 +771,7 @@ void QRhiD3D11::setVertexInput(QRhiCommandBuffer *cb, QD3D11Buffer *ibufD = QRHI_RES(QD3D11Buffer, indexBuf); Q_ASSERT(ibufD->m_usage.testFlag(QRhiBuffer::IndexBuffer)); if (ibufD->m_type == QRhiBuffer::Dynamic) - executeBufferHostWritesForCurrentFrame(ibufD); + executeBufferHostWrites(ibufD); const DXGI_FORMAT dxgiFormat = indexFormat == QRhiCommandBuffer::IndexUInt16 ? DXGI_FORMAT_R16_UINT : DXGI_FORMAT_R32_UINT; @@ -1774,7 +1788,26 @@ void QRhiD3D11::dispatch(QRhiCommandBuffer *cb, int x, int y, int z) cbD->commands.append(cmd); } -void QRhiD3D11::updateShaderResourceBindings(QD3D11ShaderResourceBindings *srbD) +static inline QPair mapBinding(int binding, + int stageIndex, + const QShader::NativeResourceBindingMap *nativeResourceBindingMaps[]) +{ + const QShader::NativeResourceBindingMap *map = nativeResourceBindingMaps[stageIndex]; + if (!map || map->isEmpty()) + return { binding, binding }; // old QShader versions do not have this map, assume 1:1 mapping then + + auto it = map->constFind(binding); + if (it != map->cend()) + return *it; + + // Hitting this path is normal too. It is not given that the resource is + // present in the shaders for all the stages specified by the visibility + // mask in the QRhiShaderResourceBinding. + return { -1, -1 }; +} + +void QRhiD3D11::updateShaderResourceBindings(QD3D11ShaderResourceBindings *srbD, + const QShader::NativeResourceBindingMap *nativeResourceBindingMaps[]) { srbD->vsubufs.clear(); srbD->vsubufoffsets.clear(); @@ -1799,6 +1832,31 @@ void QRhiD3D11::updateShaderResourceBindings(QD3D11ShaderResourceBindings *srbD) srbD->csUAVs.clear(); + struct Stage { + struct Buffer { + int breg; // b0, b1, ... + ID3D11Buffer *buffer; + uint offsetInConstants; + uint sizeInConstants; + }; + struct Texture { + int treg; // t0, t1, ... + ID3D11ShaderResourceView *srv; + }; + struct Sampler { + int sreg; // s0, s1, ... + ID3D11SamplerState *sampler; + }; + struct Uav { + int ureg; + ID3D11UnorderedAccessView *uav; + }; + QVarLengthArray buffers; + QVarLengthArray textures; + QVarLengthArray samplers; + QVarLengthArray uavs; + } res[RBM_SUPPORTED_STAGES]; + for (int i = 0, ie = srbD->sortedBindings.count(); i != ie; ++i) { const QRhiShaderResourceBinding::Data *b = srbD->sortedBindings.at(i).data(); QD3D11ShaderResourceBindings::BoundResourceData &bd(srbD->boundResourceData[i]); @@ -1818,26 +1876,24 @@ void QRhiD3D11::updateShaderResourceBindings(QD3D11ShaderResourceBindings *srbD) // (ByteWidth) is always a multiple of 256. const uint sizeInConstants = uint(aligned(b->u.ubuf.maybeSize ? b->u.ubuf.maybeSize : bufD->m_size, 256) / 16); if (b->stage.testFlag(QRhiShaderResourceBinding::VertexStage)) { - srbD->vsubufs.feed(b->binding, bufD->buffer); - srbD->vsubufoffsets.feed(b->binding, offsetInConstants); - srbD->vsubufsizes.feed(b->binding, sizeInConstants); + QPair nativeBinding = mapBinding(b->binding, RBM_VERTEX, nativeResourceBindingMaps); + if (nativeBinding.first >= 0) + res[RBM_VERTEX].buffers.append({ nativeBinding.first, bufD->buffer, offsetInConstants, sizeInConstants }); } if (b->stage.testFlag(QRhiShaderResourceBinding::FragmentStage)) { - srbD->fsubufs.feed(b->binding, bufD->buffer); - srbD->fsubufoffsets.feed(b->binding, offsetInConstants); - srbD->fsubufsizes.feed(b->binding, sizeInConstants); + QPair nativeBinding = mapBinding(b->binding, RBM_FRAGMENT, nativeResourceBindingMaps); + if (nativeBinding.first >= 0) + res[RBM_FRAGMENT].buffers.append({ nativeBinding.first, bufD->buffer, offsetInConstants, sizeInConstants }); } if (b->stage.testFlag(QRhiShaderResourceBinding::ComputeStage)) { - srbD->csubufs.feed(b->binding, bufD->buffer); - srbD->csubufoffsets.feed(b->binding, offsetInConstants); - srbD->csubufsizes.feed(b->binding, sizeInConstants); + QPair nativeBinding = mapBinding(b->binding, RBM_COMPUTE, nativeResourceBindingMaps); + if (nativeBinding.first >= 0) + res[RBM_COMPUTE].buffers.append({ nativeBinding.first, bufD->buffer, offsetInConstants, sizeInConstants }); } } break; case QRhiShaderResourceBinding::SampledTexture: { - // A sampler with binding N is mapped to a HLSL sampler and texture - // with registers sN and tN by SPIRV-Cross. QD3D11Texture *texD = QRHI_RES(QD3D11Texture, b->u.stex.tex); QD3D11Sampler *samplerD = QRHI_RES(QD3D11Sampler, b->u.stex.sampler); bd.stex.texId = texD->m_id; @@ -1845,16 +1901,25 @@ void QRhiD3D11::updateShaderResourceBindings(QD3D11ShaderResourceBindings *srbD) bd.stex.samplerId = samplerD->m_id; bd.stex.samplerGeneration = samplerD->generation; if (b->stage.testFlag(QRhiShaderResourceBinding::VertexStage)) { - srbD->vssamplers.feed(b->binding, samplerD->samplerState); - srbD->vsshaderresources.feed(b->binding, texD->srv); + QPair nativeBinding = mapBinding(b->binding, RBM_VERTEX, nativeResourceBindingMaps); + if (nativeBinding.first >= 0 && nativeBinding.second >= 0) { + res[RBM_VERTEX].textures.append({ nativeBinding.first, texD->srv }); + res[RBM_VERTEX].samplers.append({ nativeBinding.second, samplerD->samplerState }); + } } if (b->stage.testFlag(QRhiShaderResourceBinding::FragmentStage)) { - srbD->fssamplers.feed(b->binding, samplerD->samplerState); - srbD->fsshaderresources.feed(b->binding, texD->srv); + QPair nativeBinding = mapBinding(b->binding, RBM_FRAGMENT, nativeResourceBindingMaps); + if (nativeBinding.first >= 0 && nativeBinding.second >= 0) { + res[RBM_FRAGMENT].textures.append({ nativeBinding.first, texD->srv }); + res[RBM_FRAGMENT].samplers.append({ nativeBinding.second, samplerD->samplerState }); + } } if (b->stage.testFlag(QRhiShaderResourceBinding::ComputeStage)) { - srbD->cssamplers.feed(b->binding, samplerD->samplerState); - srbD->csshaderresources.feed(b->binding, texD->srv); + QPair nativeBinding = mapBinding(b->binding, RBM_COMPUTE, nativeResourceBindingMaps); + if (nativeBinding.first >= 0 && nativeBinding.second >= 0) { + res[RBM_COMPUTE].textures.append({ nativeBinding.first, texD->srv }); + res[RBM_COMPUTE].samplers.append({ nativeBinding.second, samplerD->samplerState }); + } } } break; @@ -1866,9 +1931,12 @@ void QRhiD3D11::updateShaderResourceBindings(QD3D11ShaderResourceBindings *srbD) bd.simage.id = texD->m_id; bd.simage.generation = texD->generation; if (b->stage.testFlag(QRhiShaderResourceBinding::ComputeStage)) { - ID3D11UnorderedAccessView *uav = texD->unorderedAccessViewForLevel(b->u.simage.level); - if (uav) - srbD->csUAVs.feed(b->binding, uav); + QPair nativeBinding = mapBinding(b->binding, RBM_COMPUTE, nativeResourceBindingMaps); + if (nativeBinding.first >= 0) { + ID3D11UnorderedAccessView *uav = texD->unorderedAccessViewForLevel(b->u.simage.level); + if (uav) + res[RBM_COMPUTE].uavs.append({ nativeBinding.first, uav }); + } } else { qWarning("Unordered access only supported at compute stage"); } @@ -1882,9 +1950,12 @@ void QRhiD3D11::updateShaderResourceBindings(QD3D11ShaderResourceBindings *srbD) bd.sbuf.id = bufD->m_id; bd.sbuf.generation = bufD->generation; if (b->stage.testFlag(QRhiShaderResourceBinding::ComputeStage)) { - ID3D11UnorderedAccessView *uav = bufD->unorderedAccessView(); - if (uav) - srbD->csUAVs.feed(b->binding, uav); + QPair nativeBinding = mapBinding(b->binding, RBM_COMPUTE, nativeResourceBindingMaps); + if (nativeBinding.first >= 0) { + ID3D11UnorderedAccessView *uav = bufD->unorderedAccessView(); + if (uav) + res[RBM_COMPUTE].uavs.append({ nativeBinding.first, uav }); + } } else { qWarning("Unordered access only supported at compute stage"); } @@ -1896,31 +1967,79 @@ void QRhiD3D11::updateShaderResourceBindings(QD3D11ShaderResourceBindings *srbD) } } + // QRhiBatchedBindings works with the native bindings and expects + // sorted input. The pre-sorted QRhiShaderResourceBinding list (based + // on the QRhi (SPIR-V) binding) is not helpful in this regard, so we + // have to sort here every time. + for (int stage = 0; stage < RBM_SUPPORTED_STAGES; ++stage) { + std::sort(res[stage].buffers.begin(), res[stage].buffers.end(), [](const Stage::Buffer &a, const Stage::Buffer &b) { + return a.breg < b.breg; + }); + std::sort(res[stage].textures.begin(), res[stage].textures.end(), [](const Stage::Texture &a, const Stage::Texture &b) { + return a.treg < b.treg; + }); + std::sort(res[stage].samplers.begin(), res[stage].samplers.end(), [](const Stage::Sampler &a, const Stage::Sampler &b) { + return a.sreg < b.sreg; + }); + std::sort(res[stage].uavs.begin(), res[stage].uavs.end(), [](const Stage::Uav &a, const Stage::Uav &b) { + return a.ureg < b.ureg; + }); + } + + for (const Stage::Buffer &buf : qAsConst(res[RBM_VERTEX].buffers)) { + srbD->vsubufs.feed(buf.breg, buf.buffer); + srbD->vsubufoffsets.feed(buf.breg, buf.offsetInConstants); + srbD->vsubufsizes.feed(buf.breg, buf.sizeInConstants); + } srbD->vsubufs.finish(); srbD->vsubufoffsets.finish(); srbD->vsubufsizes.finish(); + for (const Stage::Buffer &buf : qAsConst(res[RBM_FRAGMENT].buffers)) { + srbD->fsubufs.feed(buf.breg, buf.buffer); + srbD->fsubufoffsets.feed(buf.breg, buf.offsetInConstants); + srbD->fsubufsizes.feed(buf.breg, buf.sizeInConstants); + } srbD->fsubufs.finish(); srbD->fsubufoffsets.finish(); srbD->fsubufsizes.finish(); + for (const Stage::Buffer &buf : qAsConst(res[RBM_COMPUTE].buffers)) { + srbD->csubufs.feed(buf.breg, buf.buffer); + srbD->csubufoffsets.feed(buf.breg, buf.offsetInConstants); + srbD->csubufsizes.feed(buf.breg, buf.sizeInConstants); + } srbD->csubufs.finish(); srbD->csubufoffsets.finish(); srbD->csubufsizes.finish(); + for (const Stage::Texture &t : qAsConst(res[RBM_VERTEX].textures)) + srbD->vsshaderresources.feed(t.treg, t.srv); + for (const Stage::Sampler &s : qAsConst(res[RBM_VERTEX].samplers)) + srbD->vssamplers.feed(s.sreg, s.sampler); srbD->vssamplers.finish(); srbD->vsshaderresources.finish(); + for (const Stage::Texture &t : qAsConst(res[RBM_FRAGMENT].textures)) + srbD->fsshaderresources.feed(t.treg, t.srv); + for (const Stage::Sampler &s : qAsConst(res[RBM_FRAGMENT].samplers)) + srbD->fssamplers.feed(s.sreg, s.sampler); srbD->fssamplers.finish(); srbD->fsshaderresources.finish(); + for (const Stage::Texture &t : qAsConst(res[RBM_COMPUTE].textures)) + srbD->csshaderresources.feed(t.treg, t.srv); + for (const Stage::Sampler &s : qAsConst(res[RBM_COMPUTE].samplers)) + srbD->cssamplers.feed(s.sreg, s.sampler); srbD->cssamplers.finish(); srbD->csshaderresources.finish(); + for (const Stage::Uav &u : qAsConst(res[RBM_COMPUTE].uavs)) + srbD->csUAVs.feed(u.ureg, u.uav); srbD->csUAVs.finish(); } -void QRhiD3D11::executeBufferHostWritesForCurrentFrame(QD3D11Buffer *bufD) +void QRhiD3D11::executeBufferHostWrites(QD3D11Buffer *bufD) { if (!bufD->hasPendingDynamicUpdates) return; @@ -2205,8 +2324,8 @@ void QRhiD3D11::executeCommandBuffer(QD3D11CommandBuffer *cbD, QD3D11SwapChain * case QD3D11CommandBuffer::Command::BindGraphicsPipeline: { QD3D11GraphicsPipeline *psD = cmd.args.bindGraphicsPipeline.ps; - context->VSSetShader(psD->vs, nullptr, 0); - context->PSSetShader(psD->fs, nullptr, 0); + context->VSSetShader(psD->vs.shader, nullptr, 0); + context->PSSetShader(psD->fs.shader, nullptr, 0); context->IASetPrimitiveTopology(psD->d3dTopology); context->IASetInputLayout(psD->inputLayout); context->OMSetDepthStencilState(psD->dsState, stencilRef); @@ -2281,7 +2400,7 @@ void QRhiD3D11::executeCommandBuffer(QD3D11CommandBuffer *cbD, QD3D11SwapChain * annotations->SetMarker(reinterpret_cast(QString::fromLatin1(cmd.args.debugMark.s).utf16())); break; case QD3D11CommandBuffer::Command::BindComputePipeline: - context->CSSetShader(cmd.args.bindComputePipeline.ps->cs, nullptr, 0); + context->CSSetShader(cmd.args.bindComputePipeline.ps->cs.shader, nullptr, 0); break; case QD3D11CommandBuffer::Command::Dispatch: context->Dispatch(cmd.args.dispatch.x, cmd.args.dispatch.y, cmd.args.dispatch.z); @@ -2388,6 +2507,10 @@ bool QD3D11Buffer::build() QRhiBuffer::NativeBuffer QD3D11Buffer::nativeBuffer() { + if (m_type == Dynamic) { + QRHI_RES_RHI(QRhiD3D11); + rhiD->executeBufferHostWrites(this); + } return { { &buffer }, 1 }; } @@ -3133,6 +3256,7 @@ QD3D11ShaderResourceBindings::~QD3D11ShaderResourceBindings() void QD3D11ShaderResourceBindings::release() { sortedBindings.clear(); + boundResourceData.clear(); } bool QD3D11ShaderResourceBindings::build() @@ -3149,8 +3273,8 @@ bool QD3D11ShaderResourceBindings::build() boundResourceData.resize(sortedBindings.count()); - QRHI_RES_RHI(QRhiD3D11); - rhiD->updateShaderResourceBindings(this); + for (BoundResourceData &bd : boundResourceData) + memset(&bd, 0, sizeof(BoundResourceData)); generation += 1; return true; @@ -3191,15 +3315,17 @@ void QD3D11GraphicsPipeline::release() rastState = nullptr; } - if (vs) { - vs->Release(); - vs = nullptr; + if (vs.shader) { + vs.shader->Release(); + vs.shader = nullptr; } + vs.nativeResourceBindingMap.clear(); - if (fs) { - fs->Release(); - fs = nullptr; + if (fs.shader) { + fs.shader->Release(); + fs.shader = nullptr; } + fs.nativeResourceBindingMap.clear(); rhiD->unregisterResource(this); } @@ -3401,13 +3527,14 @@ static pD3DCompile resolveD3DCompile() return nullptr; } -static QByteArray compileHlslShaderSource(const QShader &shader, QShader::Variant shaderVariant, QString *error) +static QByteArray compileHlslShaderSource(const QShader &shader, QShader::Variant shaderVariant, QString *error, QShaderKey *usedShaderKey) { QShaderCode dxbc = shader.shader({ QShader::DxbcShader, 50, shaderVariant }); if (!dxbc.shader().isEmpty()) return dxbc.shader(); - QShaderCode hlslSource = shader.shader({ QShader::HlslShader, 50, shaderVariant }); + const QShaderKey key = { QShader::HlslShader, 50, shaderVariant }; + QShaderCode hlslSource = shader.shader(key); if (hlslSource.shader().isEmpty()) { qWarning() << "No HLSL (shader model 5.0) code found in baked shader" << shader; return QByteArray(); @@ -3459,6 +3586,9 @@ static QByteArray compileHlslShaderSource(const QShader &shader, QShader::Varian return QByteArray(); } + if (usedShaderKey) + *usedShaderKey = key; + QByteArray result; result.resize(int(bytecode->GetBufferSize())); memcpy(result.data(), bytecode->GetBufferPointer(), size_t(result.size())); @@ -3550,20 +3680,23 @@ bool QD3D11GraphicsPipeline::build() if (cacheIt != rhiD->m_shaderCache.constEnd()) { switch (shaderStage.type()) { case QRhiShaderStage::Vertex: - vs = static_cast(cacheIt->s); - vs->AddRef(); + vs.shader = static_cast(cacheIt->s); + vs.shader->AddRef(); vsByteCode = cacheIt->bytecode; + vs.nativeResourceBindingMap = cacheIt->nativeResourceBindingMap; break; case QRhiShaderStage::Fragment: - fs = static_cast(cacheIt->s); - fs->AddRef(); + fs.shader = static_cast(cacheIt->s); + fs.shader->AddRef(); + fs.nativeResourceBindingMap = cacheIt->nativeResourceBindingMap; break; default: break; } } else { QString error; - const QByteArray bytecode = compileHlslShaderSource(shaderStage.shader(), shaderStage.shaderVariant(), &error); + QShaderKey shaderKey; + const QByteArray bytecode = compileHlslShaderSource(shaderStage.shader(), shaderStage.shaderVariant(), &error, &shaderKey); if (bytecode.isEmpty()) { qWarning("HLSL shader compilation failed: %s", qPrintable(error)); return false; @@ -3576,23 +3709,27 @@ bool QD3D11GraphicsPipeline::build() switch (shaderStage.type()) { case QRhiShaderStage::Vertex: - hr = rhiD->dev->CreateVertexShader(bytecode.constData(), SIZE_T(bytecode.size()), nullptr, &vs); + hr = rhiD->dev->CreateVertexShader(bytecode.constData(), SIZE_T(bytecode.size()), nullptr, &vs.shader); if (FAILED(hr)) { qWarning("Failed to create vertex shader: %s", qPrintable(comErrorMessage(hr))); return false; } vsByteCode = bytecode; - rhiD->m_shaderCache.insert(shaderStage, QRhiD3D11::Shader(vs, bytecode)); - vs->AddRef(); + if (const QShader::NativeResourceBindingMap *map = shaderStage.shader().nativeResourceBindingMap(shaderKey)) + vs.nativeResourceBindingMap = *map; + rhiD->m_shaderCache.insert(shaderStage, QRhiD3D11::Shader(vs.shader, bytecode, vs.nativeResourceBindingMap)); + vs.shader->AddRef(); break; case QRhiShaderStage::Fragment: - hr = rhiD->dev->CreatePixelShader(bytecode.constData(), SIZE_T(bytecode.size()), nullptr, &fs); + hr = rhiD->dev->CreatePixelShader(bytecode.constData(), SIZE_T(bytecode.size()), nullptr, &fs.shader); if (FAILED(hr)) { qWarning("Failed to create pixel shader: %s", qPrintable(comErrorMessage(hr))); return false; } - rhiD->m_shaderCache.insert(shaderStage, QRhiD3D11::Shader(fs, bytecode)); - fs->AddRef(); + if (const QShader::NativeResourceBindingMap *map = shaderStage.shader().nativeResourceBindingMap(shaderKey)) + fs.nativeResourceBindingMap = *map; + rhiD->m_shaderCache.insert(shaderStage, QRhiD3D11::Shader(fs.shader, bytecode, fs.nativeResourceBindingMap)); + fs.shader->AddRef(); break; default: break; @@ -3651,46 +3788,52 @@ void QD3D11ComputePipeline::release() { QRHI_RES_RHI(QRhiD3D11); - if (!cs) + if (!cs.shader) return; - cs->Release(); - cs = nullptr; + cs.shader->Release(); + cs.shader = nullptr; + cs.nativeResourceBindingMap.clear(); rhiD->unregisterResource(this); } bool QD3D11ComputePipeline::build() { - if (cs) + if (cs.shader) release(); QRHI_RES_RHI(QRhiD3D11); auto cacheIt = rhiD->m_shaderCache.constFind(m_shaderStage); if (cacheIt != rhiD->m_shaderCache.constEnd()) { - cs = static_cast(cacheIt->s); + cs.shader = static_cast(cacheIt->s); + cs.nativeResourceBindingMap = cacheIt->nativeResourceBindingMap; } else { QString error; - const QByteArray bytecode = compileHlslShaderSource(m_shaderStage.shader(), m_shaderStage.shaderVariant(), &error); + QShaderKey shaderKey; + const QByteArray bytecode = compileHlslShaderSource(m_shaderStage.shader(), m_shaderStage.shaderVariant(), &error, &shaderKey); if (bytecode.isEmpty()) { qWarning("HLSL compute shader compilation failed: %s", qPrintable(error)); return false; } - HRESULT hr = rhiD->dev->CreateComputeShader(bytecode.constData(), SIZE_T(bytecode.size()), nullptr, &cs); + HRESULT hr = rhiD->dev->CreateComputeShader(bytecode.constData(), SIZE_T(bytecode.size()), nullptr, &cs.shader); if (FAILED(hr)) { qWarning("Failed to create compute shader: %s", qPrintable(comErrorMessage(hr))); return false; } + if (const QShader::NativeResourceBindingMap *map = m_shaderStage.shader().nativeResourceBindingMap(shaderKey)) + cs.nativeResourceBindingMap = *map; + if (rhiD->m_shaderCache.count() >= QRhiD3D11::MAX_SHADER_CACHE_ENTRIES) rhiD->clearShaderCache(); - rhiD->m_shaderCache.insert(m_shaderStage, QRhiD3D11::Shader(cs, bytecode)); + rhiD->m_shaderCache.insert(m_shaderStage, QRhiD3D11::Shader(cs.shader, bytecode, cs.nativeResourceBindingMap)); } - cs->AddRef(); + cs.shader->AddRef(); generation += 1; rhiD->registerResource(this); diff --git a/src/gui/rhi/qrhid3d11_p_p.h b/src/gui/rhi/qrhid3d11_p_p.h index 04751397f7..f749b612b5 100644 --- a/src/gui/rhi/qrhid3d11_p_p.h +++ b/src/gui/rhi/qrhid3d11_p_p.h @@ -270,8 +270,14 @@ struct QD3D11GraphicsPipeline : public QRhiGraphicsPipeline ID3D11DepthStencilState *dsState = nullptr; ID3D11BlendState *blendState = nullptr; - ID3D11VertexShader *vs = nullptr; - ID3D11PixelShader *fs = nullptr; + struct { + ID3D11VertexShader *shader = nullptr; + QShader::NativeResourceBindingMap nativeResourceBindingMap; + } vs; + struct { + ID3D11PixelShader *shader = nullptr; + QShader::NativeResourceBindingMap nativeResourceBindingMap; + } fs; ID3D11InputLayout *inputLayout = nullptr; D3D11_PRIMITIVE_TOPOLOGY d3dTopology = D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST; ID3D11RasterizerState *rastState = nullptr; @@ -286,7 +292,10 @@ struct QD3D11ComputePipeline : public QRhiComputePipeline void release() override; bool build() override; - ID3D11ComputeShader *cs = nullptr; + struct { + ID3D11ComputeShader *shader = nullptr; + QShader::NativeResourceBindingMap nativeResourceBindingMap; + } cs; uint generation = 0; friend class QRhiD3D11; }; @@ -642,8 +651,9 @@ public: void enqueueSubresUpload(QD3D11Texture *texD, QD3D11CommandBuffer *cbD, int layer, int level, const QRhiTextureSubresourceUploadDescription &subresDesc); void enqueueResourceUpdates(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch *resourceUpdates); - void updateShaderResourceBindings(QD3D11ShaderResourceBindings *srbD); - void executeBufferHostWritesForCurrentFrame(QD3D11Buffer *bufD); + void updateShaderResourceBindings(QD3D11ShaderResourceBindings *srbD, + const QShader::NativeResourceBindingMap *nativeResourceBindingMaps[]); + void executeBufferHostWrites(QD3D11Buffer *bufD); void bindShaderResources(QD3D11ShaderResourceBindings *srbD, const uint *dynOfsPairs, int dynOfsPairCount, bool offsetOnlyChange); @@ -701,9 +711,11 @@ public: struct Shader { Shader() = default; - Shader(IUnknown *s, const QByteArray &bytecode) : s(s), bytecode(bytecode) { } + Shader(IUnknown *s, const QByteArray &bytecode, const QShader::NativeResourceBindingMap &rbm) + : s(s), bytecode(bytecode), nativeResourceBindingMap(rbm) { } IUnknown *s; QByteArray bytecode; + QShader::NativeResourceBindingMap nativeResourceBindingMap; }; QHash m_shaderCache; diff --git a/src/gui/rhi/qrhimetal.mm b/src/gui/rhi/qrhimetal.mm index 48a562ef1d..314c58b0b7 100644 --- a/src/gui/rhi/qrhimetal.mm +++ b/src/gui/rhi/qrhimetal.mm @@ -1827,16 +1827,15 @@ void QRhiMetal::enqueueResourceUpdates(QRhiCommandBuffer *cb, QRhiResourceUpdate } // this handles all types of buffers, not just Dynamic -void QRhiMetal::executeBufferHostWritesForCurrentFrame(QMetalBuffer *bufD) +void QRhiMetal::executeBufferHostWritesForSlot(QMetalBuffer *bufD, int slot) { - const int idx = bufD->d->slotted ? currentFrameSlot : 0; - if (bufD->d->pendingUpdates[idx].isEmpty()) + if (bufD->d->pendingUpdates[slot].isEmpty()) return; - void *p = [bufD->d->buf[idx] contents]; + void *p = [bufD->d->buf[slot] contents]; int changeBegin = -1; int changeEnd = -1; - for (const QRhiResourceUpdateBatchPrivate::BufferOp &u : qAsConst(bufD->d->pendingUpdates[idx])) { + for (const QRhiResourceUpdateBatchPrivate::BufferOp &u : qAsConst(bufD->d->pendingUpdates[slot])) { Q_ASSERT(bufD == QRHI_RES(QMetalBuffer, u.buf)); memcpy(static_cast(p) + u.offset, u.data.constData(), size_t(u.data.size())); if (changeBegin == -1 || u.offset < changeBegin) @@ -1846,10 +1845,15 @@ void QRhiMetal::executeBufferHostWritesForCurrentFrame(QMetalBuffer *bufD) } #ifdef Q_OS_MACOS if (changeBegin >= 0 && bufD->d->managed) - [bufD->d->buf[idx] didModifyRange: NSMakeRange(NSUInteger(changeBegin), NSUInteger(changeEnd - changeBegin))]; + [bufD->d->buf[slot] didModifyRange: NSMakeRange(NSUInteger(changeBegin), NSUInteger(changeEnd - changeBegin))]; #endif - bufD->d->pendingUpdates[idx].clear(); + bufD->d->pendingUpdates[slot].clear(); +} + +void QRhiMetal::executeBufferHostWritesForCurrentFrame(QMetalBuffer *bufD) +{ + executeBufferHostWritesForSlot(bufD, bufD->d->slotted ? currentFrameSlot : 0); } void QRhiMetal::resourceUpdate(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch *resourceUpdates) @@ -2205,8 +2209,11 @@ QRhiBuffer::NativeBuffer QMetalBuffer::nativeBuffer() if (d->slotted) { NativeBuffer b; Q_ASSERT(sizeof(b.objects) / sizeof(b.objects[0]) >= size_t(QMTL_FRAMES_IN_FLIGHT)); - for (int i = 0; i < QMTL_FRAMES_IN_FLIGHT; ++i) + for (int i = 0; i < QMTL_FRAMES_IN_FLIGHT; ++i) { + QRHI_RES_RHI(QRhiMetal); + rhiD->executeBufferHostWritesForSlot(this, i); b.objects[i] = &d->buf[i]; + } b.slotCount = QMTL_FRAMES_IN_FLIGHT; return b; } diff --git a/src/gui/rhi/qrhimetal_p_p.h b/src/gui/rhi/qrhimetal_p_p.h index 212b731b71..a5af5611a6 100644 --- a/src/gui/rhi/qrhimetal_p_p.h +++ b/src/gui/rhi/qrhimetal_p_p.h @@ -437,6 +437,7 @@ public: int layer, int level, const QRhiTextureSubresourceUploadDescription &subresDesc, qsizetype *curOfs); void enqueueResourceUpdates(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch *resourceUpdates); + void executeBufferHostWritesForSlot(QMetalBuffer *bufD, int slot); void executeBufferHostWritesForCurrentFrame(QMetalBuffer *bufD); static const int SUPPORTED_STAGES = 3; void enqueueShaderResourceBindings(QMetalShaderResourceBindings *srbD, diff --git a/src/gui/rhi/qrhivulkan.cpp b/src/gui/rhi/qrhivulkan.cpp index d378e2a4ad..a92c3e14e9 100644 --- a/src/gui/rhi/qrhivulkan.cpp +++ b/src/gui/rhi/qrhivulkan.cpp @@ -149,6 +149,10 @@ QT_BEGIN_NAMESPACE for other windows as well, as long as they all have their QWindow::surfaceType() set to QSurface::VulkanSurface. + To request additional extensions to be enabled on the Vulkan device, list them + in deviceExtensions. This can be relevant when integrating with native Vulkan + rendering code. + \section2 Working with existing Vulkan devices When interoperating with another graphics engine, it may be necessary to @@ -299,6 +303,7 @@ QRhiVulkan::QRhiVulkan(QRhiVulkanInitParams *params, QRhiVulkanNativeHandles *im { inst = params->inst; maybeWindow = params->window; // may be null + requestedDeviceExtensions = params->deviceExtensions; importedDevice = importDevice != nullptr; if (importedDevice) { @@ -463,40 +468,59 @@ bool QRhiVulkan::create(QRhi::Flags flags) if (inst->layers().contains("VK_LAYER_LUNARG_standard_validation")) devLayers.append("VK_LAYER_LUNARG_standard_validation"); + QVulkanInfoVector devExts; uint32_t devExtCount = 0; f->vkEnumerateDeviceExtensionProperties(physDev, nullptr, &devExtCount, nullptr); - QVector devExts(devExtCount); - f->vkEnumerateDeviceExtensionProperties(physDev, nullptr, &devExtCount, devExts.data()); + if (devExtCount) { + QVector extProps(devExtCount); + f->vkEnumerateDeviceExtensionProperties(physDev, nullptr, &devExtCount, extProps.data()); + for (const VkExtensionProperties &p : qAsConst(extProps)) + devExts.append({ p.extensionName, p.specVersion }); + } qCDebug(QRHI_LOG_INFO, "%d device extensions available", devExts.count()); QVector requestedDevExts; requestedDevExts.append("VK_KHR_swapchain"); debugMarkersAvailable = false; + if (devExts.contains(VK_EXT_DEBUG_MARKER_EXTENSION_NAME)) { + requestedDevExts.append(VK_EXT_DEBUG_MARKER_EXTENSION_NAME); + debugMarkersAvailable = true; + } + vertexAttribDivisorAvailable = false; - for (const VkExtensionProperties &ext : devExts) { - if (!strcmp(ext.extensionName, VK_EXT_DEBUG_MARKER_EXTENSION_NAME)) { - requestedDevExts.append(VK_EXT_DEBUG_MARKER_EXTENSION_NAME); - debugMarkersAvailable = true; - } else if (!strcmp(ext.extensionName, VK_EXT_VERTEX_ATTRIBUTE_DIVISOR_EXTENSION_NAME)) { - if (inst->extensions().contains(QByteArrayLiteral("VK_KHR_get_physical_device_properties2"))) { - requestedDevExts.append(VK_EXT_VERTEX_ATTRIBUTE_DIVISOR_EXTENSION_NAME); - vertexAttribDivisorAvailable = true; - } + if (devExts.contains(VK_EXT_VERTEX_ATTRIBUTE_DIVISOR_EXTENSION_NAME)) { + if (inst->extensions().contains(QByteArrayLiteral("VK_KHR_get_physical_device_properties2"))) { + requestedDevExts.append(VK_EXT_VERTEX_ATTRIBUTE_DIVISOR_EXTENSION_NAME); + vertexAttribDivisorAvailable = true; } } - QByteArrayList envExtList; - if (qEnvironmentVariableIsSet("QT_VULKAN_DEVICE_EXTENSIONS")) { - envExtList = qgetenv("QT_VULKAN_DEVICE_EXTENSIONS").split(';'); - for (auto ext : requestedDevExts) - envExtList.removeAll(ext); - for (const QByteArray &ext : envExtList) { - if (!ext.isEmpty()) + for (const QByteArray &ext : requestedDeviceExtensions) { + if (!ext.isEmpty()) { + if (devExts.contains(ext)) requestedDevExts.append(ext.constData()); + else + qWarning("Device extension %s is not supported", ext.constData()); } } + QByteArrayList envExtList = qgetenv("QT_VULKAN_DEVICE_EXTENSIONS").split(';'); + for (const QByteArray &ext : envExtList) { + if (!ext.isEmpty() && !requestedDevExts.contains(ext)) { + if (devExts.contains(ext)) + requestedDevExts.append(ext.constData()); + else + qWarning("Device extension %s is not supported", ext.constData()); + } + } + + if (QRHI_LOG_INFO().isEnabled(QtDebugMsg)) { + qCDebug(QRHI_LOG_INFO, "Enabling device extensions:"); + for (const char *ext : requestedDevExts) + qCDebug(QRHI_LOG_INFO, " %s", ext); + } + VkDeviceCreateInfo devInfo; memset(&devInfo, 0, sizeof(devInfo)); devInfo.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO; @@ -2903,7 +2927,7 @@ void QRhiVulkan::enqueueResourceUpdates(QVkCommandBuffer *cbD, QRhiResourceUpdat } else if (u.type == QRhiResourceUpdateBatchPrivate::BufferOp::Read) { QVkBuffer *bufD = QRHI_RES(QVkBuffer, u.buf); if (bufD->m_type == QRhiBuffer::Dynamic) { - executeBufferHostWritesForCurrentFrame(bufD); + executeBufferHostWritesForSlot(bufD, currentFrameSlot); void *p = nullptr; VmaAllocation a = toVmaAllocation(bufD->allocations[currentFrameSlot]); VkResult err = vmaMapMemory(toVmaAllocator(allocator), a, &p); @@ -3300,14 +3324,14 @@ void QRhiVulkan::enqueueResourceUpdates(QVkCommandBuffer *cbD, QRhiResourceUpdat ud->free(); } -void QRhiVulkan::executeBufferHostWritesForCurrentFrame(QVkBuffer *bufD) +void QRhiVulkan::executeBufferHostWritesForSlot(QVkBuffer *bufD, int slot) { - if (bufD->pendingDynamicUpdates[currentFrameSlot].isEmpty()) + if (bufD->pendingDynamicUpdates[slot].isEmpty()) return; Q_ASSERT(bufD->m_type == QRhiBuffer::Dynamic); void *p = nullptr; - VmaAllocation a = toVmaAllocation(bufD->allocations[currentFrameSlot]); + VmaAllocation a = toVmaAllocation(bufD->allocations[slot]); // The vmaMap/Unmap are basically a no-op when persistently mapped since it // refcounts; this is great because we don't need to care if the allocation // was created as persistently mapped or not. @@ -3318,7 +3342,7 @@ void QRhiVulkan::executeBufferHostWritesForCurrentFrame(QVkBuffer *bufD) } int changeBegin = -1; int changeEnd = -1; - for (const QRhiResourceUpdateBatchPrivate::BufferOp &u : qAsConst(bufD->pendingDynamicUpdates[currentFrameSlot])) { + for (const QRhiResourceUpdateBatchPrivate::BufferOp &u : qAsConst(bufD->pendingDynamicUpdates[slot])) { Q_ASSERT(bufD == QRHI_RES(QVkBuffer, u.buf)); memcpy(static_cast(p) + u.offset, u.data.constData(), size_t(u.data.size())); if (changeBegin == -1 || u.offset < changeBegin) @@ -3330,7 +3354,7 @@ void QRhiVulkan::executeBufferHostWritesForCurrentFrame(QVkBuffer *bufD) if (changeBegin >= 0) vmaFlushAllocation(toVmaAllocator(allocator), a, VkDeviceSize(changeBegin), VkDeviceSize(changeEnd - changeBegin)); - bufD->pendingDynamicUpdates[currentFrameSlot].clear(); + bufD->pendingDynamicUpdates[slot].clear(); } static void qrhivk_releaseBuffer(const QRhiVulkan::DeferredReleaseEntry &e, void *allocator) @@ -4166,7 +4190,7 @@ void QRhiVulkan::setShaderResources(QRhiCommandBuffer *cb, QRhiShaderResourceBin Q_ASSERT(bufD->m_usage.testFlag(QRhiBuffer::UniformBuffer)); if (bufD->m_type == QRhiBuffer::Dynamic) - executeBufferHostWritesForCurrentFrame(bufD); + executeBufferHostWritesForSlot(bufD, currentFrameSlot); bufD->lastActiveFrameSlot = currentFrameSlot; trackedRegisterBuffer(&passResTracker, bufD, bufD->m_type == QRhiBuffer::Dynamic ? currentFrameSlot : 0, @@ -4240,7 +4264,7 @@ void QRhiVulkan::setShaderResources(QRhiCommandBuffer *cb, QRhiShaderResourceBin Q_ASSERT(bufD->m_usage.testFlag(QRhiBuffer::StorageBuffer)); if (bufD->m_type == QRhiBuffer::Dynamic) - executeBufferHostWritesForCurrentFrame(bufD); + executeBufferHostWritesForSlot(bufD, currentFrameSlot); bufD->lastActiveFrameSlot = currentFrameSlot; QRhiPassResourceTracker::BufferAccess access; @@ -4349,7 +4373,7 @@ void QRhiVulkan::setVertexInput(QRhiCommandBuffer *cb, Q_ASSERT(bufD->m_usage.testFlag(QRhiBuffer::VertexBuffer)); bufD->lastActiveFrameSlot = currentFrameSlot; if (bufD->m_type == QRhiBuffer::Dynamic) - executeBufferHostWritesForCurrentFrame(bufD); + executeBufferHostWritesForSlot(bufD, currentFrameSlot); const VkBuffer vkvertexbuf = bufD->buffers[bufD->m_type == QRhiBuffer::Dynamic ? currentFrameSlot : 0]; if (cbD->currentVertexBuffers[inputSlot] != vkvertexbuf @@ -4395,7 +4419,7 @@ void QRhiVulkan::setVertexInput(QRhiCommandBuffer *cb, Q_ASSERT(ibufD->m_usage.testFlag(QRhiBuffer::IndexBuffer)); ibufD->lastActiveFrameSlot = currentFrameSlot; if (ibufD->m_type == QRhiBuffer::Dynamic) - executeBufferHostWritesForCurrentFrame(ibufD); + executeBufferHostWritesForSlot(ibufD, currentFrameSlot); const int slot = ibufD->m_type == QRhiBuffer::Dynamic ? currentFrameSlot : 0; const VkBuffer vkindexbuf = ibufD->buffers[slot]; @@ -5188,10 +5212,13 @@ bool QVkBuffer::build() QRhiBuffer::NativeBuffer QVkBuffer::nativeBuffer() { if (m_type == Dynamic) { + QRHI_RES_RHI(QRhiVulkan); NativeBuffer b; Q_ASSERT(sizeof(b.objects) / sizeof(b.objects[0]) >= size_t(QVK_FRAMES_IN_FLIGHT)); - for (int i = 0; i < QVK_FRAMES_IN_FLIGHT; ++i) + for (int i = 0; i < QVK_FRAMES_IN_FLIGHT; ++i) { + rhiD->executeBufferHostWritesForSlot(this, i); b.objects[i] = &buffers[i]; + } b.slotCount = QVK_FRAMES_IN_FLIGHT; return b; } @@ -5536,6 +5563,11 @@ QRhiTexture::NativeTexture QVkTexture::nativeTexture() return {&image, usageState.layout}; } +void QVkTexture::setNativeLayout(int layout) +{ + usageState.layout = VkImageLayout(layout); +} + VkImageView QVkTexture::imageViewForLevel(int level) { Q_ASSERT(level >= 0 && level < int(mipLevelCount)); diff --git a/src/gui/rhi/qrhivulkan_p.h b/src/gui/rhi/qrhivulkan_p.h index d495919671..f8870dcd77 100644 --- a/src/gui/rhi/qrhivulkan_p.h +++ b/src/gui/rhi/qrhivulkan_p.h @@ -57,6 +57,7 @@ struct Q_GUI_EXPORT QRhiVulkanInitParams : public QRhiInitParams { QVulkanInstance *inst = nullptr; QWindow *window = nullptr; + QByteArrayList deviceExtensions; }; struct Q_GUI_EXPORT QRhiVulkanNativeHandles : public QRhiNativeHandles diff --git a/src/gui/rhi/qrhivulkan_p_p.h b/src/gui/rhi/qrhivulkan_p_p.h index 6322882569..fd65417e75 100644 --- a/src/gui/rhi/qrhivulkan_p_p.h +++ b/src/gui/rhi/qrhivulkan_p_p.h @@ -123,6 +123,7 @@ struct QVkTexture : public QRhiTexture bool build() override; bool buildFrom(NativeTexture src) override; NativeTexture nativeTexture() override; + void setNativeLayout(int layout) override; bool prepareBuild(QSize *adjustedSize = nullptr); bool finishBuild(); @@ -778,7 +779,7 @@ public: size_t *curOfs, void *mp, BufferImageCopyList *copyInfos); void enqueueResourceUpdates(QVkCommandBuffer *cbD, QRhiResourceUpdateBatch *resourceUpdates); - void executeBufferHostWritesForCurrentFrame(QVkBuffer *bufD); + void executeBufferHostWritesForSlot(QVkBuffer *bufD, int slot); void enqueueTransitionPassResources(QVkCommandBuffer *cbD); void recordPrimaryCommandBuffer(QVkCommandBuffer *cbD); void trackedRegisterBuffer(QRhiPassResourceTracker *passResTracker, @@ -810,6 +811,7 @@ public: QVulkanInstance *inst = nullptr; QWindow *maybeWindow = nullptr; + QByteArrayList requestedDeviceExtensions; bool importedDevice = false; VkPhysicalDevice physDev = VK_NULL_HANDLE; VkDevice dev = VK_NULL_HANDLE; diff --git a/src/gui/rhi/qshader.cpp b/src/gui/rhi/qshader.cpp index 69f4a68215..945f4820c2 100644 --- a/src/gui/rhi/qshader.cpp +++ b/src/gui/rhi/qshader.cpp @@ -428,6 +428,7 @@ QShader QShader::fromSerialized(const QByteArray &data) ds >> intVal; d->qsbVersion = intVal; if (d->qsbVersion != QShaderPrivate::QSB_VERSION + && d->qsbVersion != QShaderPrivate::QSB_VERSION_WITHOUT_VAR_ARRAYDIMS && d->qsbVersion != QShaderPrivate::QSB_VERSION_WITH_CBOR && d->qsbVersion != QShaderPrivate::QSB_VERSION_WITH_BINARY_JSON && d->qsbVersion != QShaderPrivate::QSB_VERSION_WITHOUT_BINDINGS) @@ -439,7 +440,7 @@ QShader QShader::fromSerialized(const QByteArray &data) ds >> intVal; d->stage = Stage(intVal); if (d->qsbVersion > QShaderPrivate::QSB_VERSION_WITH_CBOR) { - d->desc = QShaderDescription::deserialize(&ds); + d->desc = QShaderDescription::deserialize(&ds, d->qsbVersion); } else if (d->qsbVersion > QShaderPrivate::QSB_VERSION_WITH_BINARY_JSON) { QByteArray descBin; ds >> descBin; diff --git a/src/gui/rhi/qshader_p_p.h b/src/gui/rhi/qshader_p_p.h index 66ef18f391..ec9d25971f 100644 --- a/src/gui/rhi/qshader_p_p.h +++ b/src/gui/rhi/qshader_p_p.h @@ -57,7 +57,8 @@ QT_BEGIN_NAMESPACE struct Q_GUI_EXPORT QShaderPrivate { - static const int QSB_VERSION = 4; + static const int QSB_VERSION = 5; + static const int QSB_VERSION_WITHOUT_VAR_ARRAYDIMS = 4; static const int QSB_VERSION_WITH_CBOR = 3; static const int QSB_VERSION_WITH_BINARY_JSON = 2; static const int QSB_VERSION_WITHOUT_BINDINGS = 1; diff --git a/src/gui/rhi/qshaderdescription.cpp b/src/gui/rhi/qshaderdescription.cpp index 96c8d082fc..f3ef5edd12 100644 --- a/src/gui/rhi/qshaderdescription.cpp +++ b/src/gui/rhi/qshaderdescription.cpp @@ -35,6 +35,7 @@ ****************************************************************************/ #include "qshaderdescription_p_p.h" +#include "qshader_p_p.h" #include #include #include @@ -402,10 +403,10 @@ QShaderDescription QShaderDescription::fromCbor(const QByteArray &data) return desc; } -QShaderDescription QShaderDescription::deserialize(QDataStream *stream) +QShaderDescription QShaderDescription::deserialize(QDataStream *stream, int version) { QShaderDescription desc; - QShaderDescriptionPrivate::get(&desc)->loadFromStream(stream); + QShaderDescriptionPrivate::get(&desc)->loadFromStream(stream, version); return desc; } @@ -783,6 +784,8 @@ QDebug operator<<(QDebug dbg, const QShaderDescription::InOutVariable &var) dbg.nospace() << " imageFormat=" << imageFormatStr(var.imageFormat); if (var.imageFlags) dbg.nospace() << " imageFlags=" << var.imageFlags; + if (!var.arrayDims.isEmpty()) + dbg.nospace() << " array=" << var.arrayDims; dbg.nospace() << ')'; return dbg; } @@ -878,6 +881,12 @@ static void addDeco(QJsonObject *obj, const QShaderDescription::InOutVariable &v (*obj)[imageFormatKey] = imageFormatStr(v.imageFormat); if (v.imageFlags) (*obj)[imageFlagsKey] = int(v.imageFlags); + if (!v.arrayDims.isEmpty()) { + QJsonArray dimArr; + for (int dim : v.arrayDims) + dimArr.append(dim); + (*obj)[arrayDimsKey] = dimArr; + } } static void serializeDecorations(QDataStream *stream, const QShaderDescription::InOutVariable &v) @@ -887,6 +896,9 @@ static void serializeDecorations(QDataStream *stream, const QShaderDescription:: (*stream) << v.descriptorSet; (*stream) << int(v.imageFormat); (*stream) << int(v.imageFlags); + (*stream) << v.arrayDims.count(); + for (int dim : v.arrayDims) + (*stream) << dim; } static QJsonObject inOutObject(const QShaderDescription::InOutVariable &v) @@ -1124,10 +1136,15 @@ static QShaderDescription::InOutVariable inOutVar(const QJsonObject &obj) var.imageFormat = mapImageFormat(obj[imageFormatKey].toString()); if (obj.contains(imageFlagsKey)) var.imageFlags = QShaderDescription::ImageFlags(obj[imageFlagsKey].toInt()); + if (obj.contains(arrayDimsKey)) { + QJsonArray dimArr = obj[arrayDimsKey].toArray(); + for (int i = 0; i < dimArr.count(); ++i) + var.arrayDims.append(dimArr.at(i).toInt()); + } return var; } -static void deserializeDecorations(QDataStream *stream, QShaderDescription::InOutVariable *v) +static void deserializeDecorations(QDataStream *stream, int version, QShaderDescription::InOutVariable *v) { (*stream) >> v->location; (*stream) >> v->binding; @@ -1137,16 +1154,23 @@ static void deserializeDecorations(QDataStream *stream, QShaderDescription::InOu v->imageFormat = QShaderDescription::ImageFormat(f); (*stream) >> f; v->imageFlags = QShaderDescription::ImageFlags(f); + + if (version > QShaderPrivate::QSB_VERSION_WITHOUT_VAR_ARRAYDIMS) { + (*stream) >> f; + v->arrayDims.resize(f); + for (int i = 0; i < f; ++i) + (*stream) >> v->arrayDims[i]; + } } -static QShaderDescription::InOutVariable deserializeInOutVar(QDataStream *stream) +static QShaderDescription::InOutVariable deserializeInOutVar(QDataStream *stream, int version) { QShaderDescription::InOutVariable var; (*stream) >> var.name; int t; (*stream) >> t; var.type = QShaderDescription::VariableType(t); - deserializeDecorations(stream, &var); + deserializeDecorations(stream, version, &var); return var; } @@ -1176,7 +1200,7 @@ static QShaderDescription::BlockVariable blockVar(const QJsonObject &obj) return var; } -static QShaderDescription::BlockVariable deserializeBlockMemberVar(QDataStream *stream) +static QShaderDescription::BlockVariable deserializeBlockMemberVar(QDataStream *stream, int version) { QShaderDescription::BlockVariable var; (*stream) >> var.name; @@ -1196,7 +1220,7 @@ static QShaderDescription::BlockVariable deserializeBlockMemberVar(QDataStream * (*stream) >> count; var.structMembers.resize(count); for (int i = 0; i < count; ++i) - var.structMembers[i] = deserializeBlockMemberVar(stream); + var.structMembers[i] = deserializeBlockMemberVar(stream, version); return var; } @@ -1304,7 +1328,7 @@ void QShaderDescriptionPrivate::loadDoc(const QJsonDocument &doc) } } -void QShaderDescriptionPrivate::loadFromStream(QDataStream *stream) +void QShaderDescriptionPrivate::loadFromStream(QDataStream *stream, int version) { Q_ASSERT(ref.loadRelaxed() == 1); // must be detached @@ -1312,12 +1336,12 @@ void QShaderDescriptionPrivate::loadFromStream(QDataStream *stream) (*stream) >> count; inVars.resize(count); for (int i = 0; i < count; ++i) - inVars[i] = deserializeInOutVar(stream); + inVars[i] = deserializeInOutVar(stream, version); (*stream) >> count; outVars.resize(count); for (int i = 0; i < count; ++i) - outVars[i] = deserializeInOutVar(stream); + outVars[i] = deserializeInOutVar(stream, version); (*stream) >> count; uniformBlocks.resize(count); @@ -1331,7 +1355,7 @@ void QShaderDescriptionPrivate::loadFromStream(QDataStream *stream) (*stream) >> memberCount; uniformBlocks[i].members.resize(memberCount); for (int memberIdx = 0; memberIdx < memberCount; ++memberIdx) - uniformBlocks[i].members[memberIdx] = deserializeBlockMemberVar(stream); + uniformBlocks[i].members[memberIdx] = deserializeBlockMemberVar(stream, version); } (*stream) >> count; @@ -1343,7 +1367,7 @@ void QShaderDescriptionPrivate::loadFromStream(QDataStream *stream) (*stream) >> memberCount; pushConstantBlocks[i].members.resize(memberCount); for (int memberIdx = 0; memberIdx < memberCount; ++memberIdx) - pushConstantBlocks[i].members[memberIdx] = deserializeBlockMemberVar(stream); + pushConstantBlocks[i].members[memberIdx] = deserializeBlockMemberVar(stream, version); } (*stream) >> count; @@ -1358,7 +1382,7 @@ void QShaderDescriptionPrivate::loadFromStream(QDataStream *stream) (*stream) >> memberCount; storageBlocks[i].members.resize(memberCount); for (int memberIdx = 0; memberIdx < memberCount; ++memberIdx) - storageBlocks[i].members[memberIdx] = deserializeBlockMemberVar(stream); + storageBlocks[i].members[memberIdx] = deserializeBlockMemberVar(stream, version); } (*stream) >> count; @@ -1368,7 +1392,7 @@ void QShaderDescriptionPrivate::loadFromStream(QDataStream *stream) int t; (*stream) >> t; combinedImageSamplers[i].type = QShaderDescription::VariableType(t); - deserializeDecorations(stream, &combinedImageSamplers[i]); + deserializeDecorations(stream, version, &combinedImageSamplers[i]); } (*stream) >> count; @@ -1378,7 +1402,7 @@ void QShaderDescriptionPrivate::loadFromStream(QDataStream *stream) int t; (*stream) >> t; storageImages[i].type = QShaderDescription::VariableType(t); - deserializeDecorations(stream, &storageImages[i]); + deserializeDecorations(stream, version, &storageImages[i]); } for (size_t i = 0; i < 3; ++i) @@ -1420,7 +1444,8 @@ bool operator==(const QShaderDescription::InOutVariable &lhs, const QShaderDescr && lhs.binding == rhs.binding && lhs.descriptorSet == rhs.descriptorSet && lhs.imageFormat == rhs.imageFormat - && lhs.imageFlags == rhs.imageFlags; + && lhs.imageFlags == rhs.imageFlags + && lhs.arrayDims == rhs.arrayDims; } /*! diff --git a/src/gui/rhi/qshaderdescription_p.h b/src/gui/rhi/qshaderdescription_p.h index 108fc32a56..e5650ed921 100644 --- a/src/gui/rhi/qshaderdescription_p.h +++ b/src/gui/rhi/qshaderdescription_p.h @@ -78,7 +78,7 @@ public: static QShaderDescription fromBinaryJson(const QByteArray &data); #endif static QShaderDescription fromCbor(const QByteArray &data); - static QShaderDescription deserialize(QDataStream *stream); + static QShaderDescription deserialize(QDataStream *stream, int version); enum VariableType { Unknown = 0, @@ -216,6 +216,7 @@ public: int descriptorSet = -1; ImageFormat imageFormat = ImageFormatUnknown; ImageFlags imageFlags; + QVector arrayDims; }; struct BlockVariable { diff --git a/src/gui/rhi/qshaderdescription_p_p.h b/src/gui/rhi/qshaderdescription_p_p.h index 69b6e811a1..ec2b0b6b4c 100644 --- a/src/gui/rhi/qshaderdescription_p_p.h +++ b/src/gui/rhi/qshaderdescription_p_p.h @@ -82,7 +82,7 @@ struct Q_GUI_EXPORT QShaderDescriptionPrivate QJsonDocument makeDoc(); void writeToStream(QDataStream *stream); void loadDoc(const QJsonDocument &doc); - void loadFromStream(QDataStream *stream); + void loadFromStream(QDataStream *stream, int version); QAtomicInt ref; QVector inVars; diff --git a/src/gui/text/qtextmarkdownimporter.cpp b/src/gui/text/qtextmarkdownimporter.cpp index 7e18a10895..5e75e7816b 100644 --- a/src/gui/text/qtextmarkdownimporter.cpp +++ b/src/gui/text/qtextmarkdownimporter.cpp @@ -577,7 +577,10 @@ void QTextMarkdownImporter::insertBlock() QTextBlockFormat blockFormat; if (!m_listStack.isEmpty() && !m_needsInsertList && m_listItem) { QTextList *list = m_listStack.top(); - blockFormat = list->item(list->count() - 1).blockFormat(); + if (list) + blockFormat = list->item(list->count() - 1).blockFormat(); + else + qWarning() << "attempted to insert into a list that no longer exists"; } if (m_blockQuoteDepth) { blockFormat.setProperty(QTextFormat::BlockQuoteLevel, m_blockQuoteDepth); @@ -607,7 +610,7 @@ void QTextMarkdownImporter::insertBlock() } if (m_needsInsertList) { m_listStack.push(m_cursor->createList(m_listFormat)); - } else if (!m_listStack.isEmpty() && m_listItem) { + } else if (!m_listStack.isEmpty() && m_listItem && m_listStack.top()) { m_listStack.top()->add(m_cursor->block()); } m_needsInsertList = false; diff --git a/src/gui/text/qtextmarkdownimporter_p.h b/src/gui/text/qtextmarkdownimporter_p.h index f450da5eb3..f12b725d8e 100644 --- a/src/gui/text/qtextmarkdownimporter_p.h +++ b/src/gui/text/qtextmarkdownimporter_p.h @@ -56,6 +56,7 @@ #include #include #include +#include #include QT_BEGIN_NAMESPACE @@ -113,7 +114,7 @@ private: #endif QString m_blockCodeLanguage; QVector m_nonEmptyTableCells; // in the current row - QStack m_listStack; + QStack> m_listStack; QStack m_spanFormatStack; QFont m_monoFont; QPalette m_palette; diff --git a/src/gui/vulkan/qvulkaninstance.cpp b/src/gui/vulkan/qvulkaninstance.cpp index 4b961a6f20..555dee3a9c 100644 --- a/src/gui/vulkan/qvulkaninstance.cpp +++ b/src/gui/vulkan/qvulkaninstance.cpp @@ -781,6 +781,8 @@ bool QVulkanInstance::supportsPresent(VkPhysicalDevice physicalDevice, uint32_t system dependent synchronization. For example, on Wayland this will add send a wl_surface.frame request in order to prevent the driver from blocking for minimized windows. + + \since 5.15 */ void QVulkanInstance::presentAboutToBeQueued(QWindow *window) { diff --git a/src/gui/vulkan/qvulkanwindow.cpp b/src/gui/vulkan/qvulkanwindow.cpp index e211863f21..ee49cf0999 100644 --- a/src/gui/vulkan/qvulkanwindow.cpp +++ b/src/gui/vulkan/qvulkanwindow.cpp @@ -1595,19 +1595,6 @@ bool QVulkanWindow::event(QEvent *e) \sa setQueueCreateInfoModifier() */ -/*! - Return a previously set queue create info modification function. - - \sa setQueueCreateInfoModifier() - - \since 5.15 - */ -QVulkanWindow::QueueCreateInfoModifier QVulkanWindow::queueCreateInfoModifier() const -{ - Q_D(const QVulkanWindow); - return d->queueCreateInfoModifier; -} - /*! Set a queue create info modification function. diff --git a/src/gui/vulkan/qvulkanwindow.h b/src/gui/vulkan/qvulkanwindow.h index 530b6c0744..511b9501bd 100644 --- a/src/gui/vulkan/qvulkanwindow.h +++ b/src/gui/vulkan/qvulkanwindow.h @@ -106,7 +106,6 @@ public: typedef std::function &)> QueueCreateInfoModifier; - QueueCreateInfoModifier queueCreateInfoModifier() const; void setQueueCreateInfoModifier(QueueCreateInfoModifier modifier); bool isValid() const; diff --git a/src/network/access/qnetworkreply.cpp b/src/network/access/qnetworkreply.cpp index fb30bfd4f1..22c522756c 100644 --- a/src/network/access/qnetworkreply.cpp +++ b/src/network/access/qnetworkreply.cpp @@ -91,7 +91,7 @@ QNetworkReplyPrivate::QNetworkReplyPrivate() content. \note Do not delete the object in the slot connected to the - error() or finished() signal. Use deleteLater(). + errorOccurred() or finished() signal. Use deleteLater(). \sa QNetworkRequest, QNetworkAccessManager */ @@ -219,6 +219,7 @@ QNetworkReplyPrivate::QNetworkReplyPrivate() the server response was detected \sa error() + \sa errorOccurred() */ /*! @@ -362,6 +363,14 @@ QNetworkReplyPrivate::QNetworkReplyPrivate() /*! \fn void QNetworkReply::error(QNetworkReply::NetworkError code) + \obsolete + + Use errorOccurred() instead. +*/ + +/*! + \fn void QNetworkReply::errorOccurred(QNetworkReply::NetworkError code) + \since 5.15 This signal is emitted when the reply detects an error in processing. The finished() signal will probably follow, indicating @@ -442,7 +451,7 @@ QNetworkReplyPrivate::QNetworkReplyPrivate() QNetworkAccessManager functions to do that. */ QNetworkReply::QNetworkReply(QObject *parent) - : QIODevice(*new QNetworkReplyPrivate, parent) + : QNetworkReply(*new QNetworkReplyPrivate, parent) { } @@ -452,6 +461,8 @@ QNetworkReply::QNetworkReply(QObject *parent) QNetworkReply::QNetworkReply(QNetworkReplyPrivate &dd, QObject *parent) : QIODevice(dd, parent) { + // Support the deprecated error() signal: + connect(this, &QNetworkReply::errorOccurred, this, QOverload::of(&QNetworkReply::error)); } /*! diff --git a/src/network/access/qnetworkreply.h b/src/network/access/qnetworkreply.h index 4a402daa91..82349f9e2a 100644 --- a/src/network/access/qnetworkreply.h +++ b/src/network/access/qnetworkreply.h @@ -156,7 +156,11 @@ public Q_SLOTS: Q_SIGNALS: void metaDataChanged(); void finished(); +#if QT_DEPRECATED_SINCE(5,15) + QT_DEPRECATED_X("Use QNetworkReply::errorOccurred(QNetworkReply::NetworkError) instead") void error(QNetworkReply::NetworkError); +#endif + void errorOccurred(QNetworkReply::NetworkError); #if QT_CONFIG(ssl) void encrypted(); void sslErrors(const QList &errors); diff --git a/src/network/access/qnetworkreplydataimpl.cpp b/src/network/access/qnetworkreplydataimpl.cpp index 924c905b1a..2f75020446 100644 --- a/src/network/access/qnetworkreplydataimpl.cpp +++ b/src/network/access/qnetworkreplydataimpl.cpp @@ -88,7 +88,7 @@ QNetworkReplyDataImpl::QNetworkReplyDataImpl(QObject *parent, const QNetworkRequ const QString msg = QCoreApplication::translate("QNetworkAccessDataBackend", "Invalid URI: %1").arg(url.toString()); setError(QNetworkReply::ProtocolFailure, msg); - QMetaObject::invokeMethod(this, "error", Qt::QueuedConnection, + QMetaObject::invokeMethod(this, "errorOccurred", Qt::QueuedConnection, Q_ARG(QNetworkReply::NetworkError, QNetworkReply::ProtocolFailure)); QMetaObject::invokeMethod(this, "finished", Qt::QueuedConnection); } diff --git a/src/network/access/qnetworkreplyhttpimpl.cpp b/src/network/access/qnetworkreplyhttpimpl.cpp index c7d22be8f5..bb65660ba8 100644 --- a/src/network/access/qnetworkreplyhttpimpl.cpp +++ b/src/network/access/qnetworkreplyhttpimpl.cpp @@ -2253,7 +2253,7 @@ void QNetworkReplyHttpImplPrivate::error(QNetworkReplyImpl::NetworkError code, c // note: might not be a good idea, since users could decide to delete us // which would delete the backend too... // maybe we should protect the backend - emit q->error(code); + emit q->errorOccurred(code); } void QNetworkReplyHttpImplPrivate::_q_metaDataChanged() diff --git a/src/network/access/qnetworkreplyimpl.cpp b/src/network/access/qnetworkreplyimpl.cpp index 51bb386186..a0b4ace470 100644 --- a/src/network/access/qnetworkreplyimpl.cpp +++ b/src/network/access/qnetworkreplyimpl.cpp @@ -855,7 +855,7 @@ void QNetworkReplyImplPrivate::error(QNetworkReplyImpl::NetworkError code, const // note: might not be a good idea, since users could decide to delete us // which would delete the backend too... // maybe we should protect the backend - emit q->error(code); + emit q->errorOccurred(code); } void QNetworkReplyImplPrivate::metaDataChanged() @@ -1128,7 +1128,7 @@ QDisabledNetworkReply::QDisabledNetworkReply(QObject *parent, "Network access is disabled."); setError(UnknownNetworkError, msg); - QMetaObject::invokeMethod(this, "error", Qt::QueuedConnection, + QMetaObject::invokeMethod(this, "errorOccurred", Qt::QueuedConnection, Q_ARG(QNetworkReply::NetworkError, UnknownNetworkError)); QMetaObject::invokeMethod(this, "finished", Qt::QueuedConnection); } diff --git a/src/plugins/imageformats/gif/qgifhandler.cpp b/src/plugins/imageformats/gif/qgifhandler.cpp index a672e92006..d45ebfb314 100644 --- a/src/plugins/imageformats/gif/qgifhandler.cpp +++ b/src/plugins/imageformats/gif/qgifhandler.cpp @@ -1215,11 +1215,4 @@ int QGifHandler::currentImageNumber() const return frameNumber; } -#if QT_DEPRECATED_SINCE(5, 13) -QByteArray QGifHandler::name() const -{ - return "gif"; -} -#endif - QT_END_NAMESPACE diff --git a/src/plugins/imageformats/gif/qgifhandler_p.h b/src/plugins/imageformats/gif/qgifhandler_p.h index c6592043ce..f19777fa18 100644 --- a/src/plugins/imageformats/gif/qgifhandler_p.h +++ b/src/plugins/imageformats/gif/qgifhandler_p.h @@ -73,10 +73,6 @@ public: bool read(QImage *image) override; bool write(const QImage &image) override; -#if QT_DEPRECATED_SINCE(5, 13) - QByteArray name() const override; -#endif - static bool canRead(QIODevice *device); QVariant option(ImageOption option) const override; diff --git a/src/plugins/imageformats/ico/qicohandler.cpp b/src/plugins/imageformats/ico/qicohandler.cpp index 1982e05344..4c8ff7d489 100644 --- a/src/plugins/imageformats/ico/qicohandler.cpp +++ b/src/plugins/imageformats/ico/qicohandler.cpp @@ -809,17 +809,6 @@ bool QtIcoHandler::write(const QImage &image) return ICOReader::write(device, imgs); } -#if QT_DEPRECATED_SINCE(5, 13) -/*! - * Return the common identifier of the format. - * For ICO format this will return "ico". - */ -QByteArray QtIcoHandler::name() const -{ - return "ico"; -} -#endif - /*! \reimp */ diff --git a/src/plugins/imageformats/ico/qicohandler.h b/src/plugins/imageformats/ico/qicohandler.h index 328dfce47e..0d44a67dfc 100644 --- a/src/plugins/imageformats/ico/qicohandler.h +++ b/src/plugins/imageformats/ico/qicohandler.h @@ -54,10 +54,6 @@ public: bool read(QImage *image) override; bool write(const QImage &image) override; -#if QT_DEPRECATED_SINCE(5, 13) - QByteArray name() const override; -#endif - int imageCount() const override; bool jumpToImage(int imageNumber) override; bool jumpToNextImage() override; diff --git a/src/plugins/imageformats/jpeg/qjpeghandler.cpp b/src/plugins/imageformats/jpeg/qjpeghandler.cpp index c31e2db3c5..fed585a82e 100644 --- a/src/plugins/imageformats/jpeg/qjpeghandler.cpp +++ b/src/plugins/imageformats/jpeg/qjpeghandler.cpp @@ -1184,11 +1184,4 @@ void QJpegHandler::setOption(ImageOption option, const QVariant &value) } } -#if QT_DEPRECATED_SINCE(5, 13) -QByteArray QJpegHandler::name() const -{ - return "jpeg"; -} -#endif - QT_END_NAMESPACE diff --git a/src/plugins/imageformats/jpeg/qjpeghandler_p.h b/src/plugins/imageformats/jpeg/qjpeghandler_p.h index fafa930c11..43ca17317a 100644 --- a/src/plugins/imageformats/jpeg/qjpeghandler_p.h +++ b/src/plugins/imageformats/jpeg/qjpeghandler_p.h @@ -68,10 +68,6 @@ public: bool read(QImage *image) override; bool write(const QImage &image) override; -#if QT_DEPRECATED_SINCE(5, 13) - QByteArray name() const override; -#endif - static bool canRead(QIODevice *device); QVariant option(ImageOption option) const override; diff --git a/src/plugins/platforms/android/qandroidassetsfileenginehandler.cpp b/src/plugins/platforms/android/qandroidassetsfileenginehandler.cpp index ca16efe34f..07776a4a76 100644 --- a/src/plugins/platforms/android/qandroidassetsfileenginehandler.cpp +++ b/src/plugins/platforms/android/qandroidassetsfileenginehandler.cpp @@ -202,9 +202,7 @@ public: const QString &path) : QAbstractFileEngineIterator(filters, nameFilters) { - m_stack.push_back(FolderIterator::fromCache(cleanedAssetPath(path), true)); - if (m_stack.last()->empty()) - m_stack.pop_back(); + m_currentIterator = FolderIterator::fromCache(cleanedAssetPath(path), true); } QFileInfo currentFileInfo() const override @@ -228,36 +226,23 @@ public: bool hasNext() const override { - if (m_stack.empty()) + if (!m_currentIterator) return false; - if (!m_stack.last()->hasNext()) { - m_stack.pop_back(); - return hasNext(); - } - return true; + return m_currentIterator->hasNext(); } QString next() override { - if (m_stack.empty()) { - m_currentIterator.reset(); + if (!m_currentIterator) return {}; - } - m_currentIterator = m_stack.last(); auto res = m_currentIterator->next(); if (!res) return {}; - if (res->second.type == AssetItem::Type::Folder) { - m_stack.push_back(FolderIterator::fromCache(cleanedAssetPath(currentFilePath()), true)); - if (m_stack.last()->empty()) - m_stack.pop_back(); - } return res->first; } private: - mutable QSharedPointer m_currentIterator; - mutable QVector> m_stack; + QSharedPointer m_currentIterator; }; class AndroidAbstractFileEngine: public QAbstractFileEngine diff --git a/src/plugins/platforms/cocoa/qcocoafiledialoghelper.mm b/src/plugins/platforms/cocoa/qcocoafiledialoghelper.mm index 6aa21d78d1..8b76e45616 100644 --- a/src/plugins/platforms/cocoa/qcocoafiledialoghelper.mm +++ b/src/plugins/platforms/cocoa/qcocoafiledialoghelper.mm @@ -419,8 +419,7 @@ static QString strippedText(QString s) [mPopUpButton setHidden:chooseDirsOnly]; // TODO hide the whole sunken pane instead? if (mOptions->acceptMode() == QFileDialogOptions::AcceptSave) { - const QStringList ext = [self acceptableExtensionsForSave]; - [mSavePanel setAllowedFileTypes:ext.isEmpty() ? nil : qt_mac_QStringListToNSMutableArray(ext)]; + [self recomputeAcceptableExtensionsForSave]; } else { [mOpenPanel setAllowedFileTypes:nil]; // delegate panel:shouldEnableURL: does the file filtering for NSOpenPanel } @@ -457,25 +456,49 @@ static QString strippedText(QString s) } /* - Returns a list of extensions (e.g. "png", "jpg", "gif") - for the current name filter. If a filter do not conform - to the format *.xyz or * or *.*, an empty list - is returned meaning accept everything. + Computes a list of extensions (e.g. "png", "jpg", "gif") + for the current name filter, and updates the save panel. + + If a filter do not conform to the format *.xyz or * or *.*, + all files types are allowed. + + Extensions with more than one part (e.g. "tar.gz") are + reduced to their final part, as NSSavePanel does not deal + well with multi-part extensions. */ -- (QStringList)acceptableExtensionsForSave +- (void)recomputeAcceptableExtensionsForSave { - QStringList result; - for (int i=0; icount(); ++i) { - const QString &filter = mSelectedNameFilter->at(i); - if (filter.startsWith(QLatin1String("*.")) - && !filter.contains(QLatin1Char('?')) - && filter.count(QLatin1Char('*')) == 1) { - result += filter.mid(2); - } else { - return QStringList(); // Accept everything - } + QStringList fileTypes; + for (const QString &filter : *mSelectedNameFilter) { + if (!filter.startsWith(QLatin1String("*."))) + continue; + + if (filter.contains(QLatin1Char('?'))) + continue; + + if (filter.count(QLatin1Char('*')) != 1) + continue; + + auto extensions = filter.split('.', Qt::SkipEmptyParts); + fileTypes += extensions.last(); + + // Explicitly show extensions if we detect a filter + // that has a multi-part extension. This prevents + // confusing situations where the user clicks e.g. + // 'foo.tar.gz' and 'foo.tar' is populated in the + // file name box, but when then clicking save macOS + // will warn that the file needs to end in .gz, + // due to thinking the user tried to save the file + // as a 'tar' file instead. Unfortunately this + // property can only be set before the panel is + // shown, so it will not have any effect when + // swithcing filters in an already opened dialog. + if (extensions.size() > 2) + mSavePanel.extensionHidden = NO; } - return result; + + mSavePanel.allowedFileTypes = fileTypes.isEmpty() ? nil + : qt_mac_QStringListToNSMutableArray(fileTypes); } - (QString)removeExtensions:(const QString &)filter diff --git a/src/plugins/platforms/cocoa/qcocoanativeinterface.mm b/src/plugins/platforms/cocoa/qcocoanativeinterface.mm index d0e69bdca5..450329f569 100644 --- a/src/plugins/platforms/cocoa/qcocoanativeinterface.mm +++ b/src/plugins/platforms/cocoa/qcocoanativeinterface.mm @@ -107,7 +107,7 @@ void *QCocoaNativeInterface::nativeResourceForWindow(const QByteArray &resourceS #if QT_CONFIG(vulkan) } else if (resourceString == "vkSurface") { if (QVulkanInstance *instance = window->vulkanInstance()) - return static_cast(instance->handle())->createSurface(window); + return static_cast(instance->handle())->surface(window); #endif } return nullptr; diff --git a/src/plugins/platforms/cocoa/qcocoavulkaninstance.h b/src/plugins/platforms/cocoa/qcocoavulkaninstance.h index 5fe6a612af..2a8d04757e 100644 --- a/src/plugins/platforms/cocoa/qcocoavulkaninstance.h +++ b/src/plugins/platforms/cocoa/qcocoavulkaninstance.h @@ -61,9 +61,11 @@ public: void createOrAdoptInstance() override; - VkSurfaceKHR *createSurface(QWindow *window); - VkSurfaceKHR createSurface(NSView *view); + VkSurfaceKHR *surface(QWindow *window); + private: + VkSurfaceKHR createSurface(NSView *view); + QVulkanInstance *m_instance = nullptr; QLibrary m_lib; VkSurfaceKHR m_nullSurface = nullptr; diff --git a/src/plugins/platforms/cocoa/qcocoavulkaninstance.mm b/src/plugins/platforms/cocoa/qcocoavulkaninstance.mm index 7ce78ee738..9e714859f2 100644 --- a/src/plugins/platforms/cocoa/qcocoavulkaninstance.mm +++ b/src/plugins/platforms/cocoa/qcocoavulkaninstance.mm @@ -57,12 +57,11 @@ void QCocoaVulkanInstance::createOrAdoptInstance() initInstance(m_instance, QByteArrayList() << QByteArrayLiteral("VK_MVK_macos_surface")); } -VkSurfaceKHR *QCocoaVulkanInstance::createSurface(QWindow *window) +VkSurfaceKHR *QCocoaVulkanInstance::surface(QWindow *window) { QCocoaWindow *cocoaWindow = static_cast(window->handle()); - if (cocoaWindow->m_vulkanSurface) - destroySurface(cocoaWindow->m_vulkanSurface); - cocoaWindow->m_vulkanSurface = createSurface(cocoaWindow->m_view); + if (!cocoaWindow->m_vulkanSurface) + cocoaWindow->m_vulkanSurface = createSurface(cocoaWindow->m_view); return &cocoaWindow->m_vulkanSurface; } @@ -81,7 +80,7 @@ VkSurfaceKHR QCocoaVulkanInstance::createSurface(NSView *view) surfaceInfo.sType = VK_STRUCTURE_TYPE_MACOS_SURFACE_CREATE_INFO_MVK; surfaceInfo.pNext = nullptr; surfaceInfo.flags = 0; - surfaceInfo.pView = view; + surfaceInfo.pView = view.layer; VkSurfaceKHR surface = nullptr; VkResult err = m_createSurface(m_vkInst, &surfaceInfo, nullptr, &surface); diff --git a/src/plugins/platforms/cocoa/qpaintengine_mac.mm b/src/plugins/platforms/cocoa/qpaintengine_mac.mm index cadb76d2e4..429c47dc3b 100644 --- a/src/plugins/platforms/cocoa/qpaintengine_mac.mm +++ b/src/plugins/platforms/cocoa/qpaintengine_mac.mm @@ -394,16 +394,19 @@ QCoreGraphicsPaintEngine::begin(QPaintDevice *pdev) d->cosmeticPenSize = 1; d->current.clipEnabled = false; d->pixelSize = QPoint(1,1); - QMacCGContext ctx(pdev); - d->hd = CGContextRetain(ctx); - if (d->hd) { - d->saveGraphicsState(); - d->orig_xform = CGContextGetCTM(d->hd); - if (d->shading) { - CGShadingRelease(d->shading); - d->shading = nullptr; + + if (pdev->devType() != QInternal::Printer) { + QMacCGContext ctx(pdev); + d->hd = CGContextRetain(ctx); + if (d->hd) { + d->saveGraphicsState(); + d->orig_xform = CGContextGetCTM(d->hd); + if (d->shading) { + CGShadingRelease(d->shading); + d->shading = nullptr; + } + d->setClip(nullptr); //clear the context's clipping } - d->setClip(nullptr); //clear the context's clipping } setActive(true); diff --git a/src/plugins/platforms/windows/qwindowsintegration.cpp b/src/plugins/platforms/windows/qwindowsintegration.cpp index 77340387d8..8963f2ad17 100644 --- a/src/plugins/platforms/windows/qwindowsintegration.cpp +++ b/src/plugins/platforms/windows/qwindowsintegration.cpp @@ -343,7 +343,9 @@ QPlatformWindow *QWindowsIntegration::createPlatformWindow(QWindow *window) cons QWindowsWindowData requested; requested.flags = window->flags(); - requested.geometry = QHighDpi::toNativePixels(window->geometry(), window); + requested.geometry = window->isTopLevel() + ? QHighDpi::toNativePixels(window->geometry(), window) + : QHighDpi::toNativeLocalPosition(window->geometry(), window); // Apply custom margins (see QWindowsWindow::setCustomMargins())). const QVariant customMarginsV = window->property("_q_windowsCustomMargins"); if (customMarginsV.isValid()) diff --git a/src/plugins/platforms/windows/qwindowssystemtrayicon.cpp b/src/plugins/platforms/windows/qwindowssystemtrayicon.cpp index 53562c87dd..d6a5b29a71 100644 --- a/src/plugins/platforms/windows/qwindowssystemtrayicon.cpp +++ b/src/plugins/platforms/windows/qwindowssystemtrayicon.cpp @@ -424,8 +424,12 @@ bool QWindowsSystemTrayIcon::winEvent(const MSG &message, long *result) if (screen) { emit contextMenuRequested(globalPos, screen); emit activated(Context); - if (m_menu) + if (m_menu) { + // Set the foreground window to the controlling window so that clicking outside + // of the menu or window will cause the menu to close + SetForegroundWindow(m_hwnd); m_menu->trackPopupMenu(message.hwnd, globalPos.x(), globalPos.y()); + } } } break; diff --git a/src/plugins/platforms/windows/qwindowswindow.cpp b/src/plugins/platforms/windows/qwindowswindow.cpp index e635463951..3dfffa6de6 100644 --- a/src/plugins/platforms/windows/qwindowswindow.cpp +++ b/src/plugins/platforms/windows/qwindowswindow.cpp @@ -1954,10 +1954,8 @@ void QWindowsWindow::checkForScreenChanged(ScreenChangeMode mode) qCDebug(lcQpaWindows).noquote().nospace() << __FUNCTION__ << ' ' << window() << " \"" << (currentScreen ? currentScreen->name() : QString()) << "\"->\"" << newScreen->name() << '"'; - if (mode == FromGeometryChange) - setFlag(SynchronousGeometryChangeEvent); updateFullFrameMargins(); - QWindowSystemInterface::handleWindowScreenChanged(window(), newScreen->screen()); + QWindowSystemInterface::handleWindowScreenChanged(window(), newScreen->screen()); } void QWindowsWindow::handleGeometryChange() diff --git a/src/plugins/platforms/xcb/qxcbwindow.cpp b/src/plugins/platforms/xcb/qxcbwindow.cpp index 71ec47b053..5be04a984a 100644 --- a/src/plugins/platforms/xcb/qxcbwindow.cpp +++ b/src/plugins/platforms/xcb/qxcbwindow.cpp @@ -274,7 +274,9 @@ void QXcbWindow::create() QXcbScreen *currentScreen = xcbScreen(); QXcbScreen *platformScreen = parent() ? parentScreen() : initialScreen(); - QRect rect = QHighDpi::toNativePixels(window()->geometry(), platformScreen); + QRect rect = parent() + ? QHighDpi::toNativeLocalPosition(window()->geometry(), platformScreen) + : QHighDpi::toNativePixels(window()->geometry(), platformScreen); if (type == Qt::Desktop) { m_window = platformScreen->root(); diff --git a/src/tools/uic/python/pythonwriteimports.cpp b/src/tools/uic/python/pythonwriteimports.cpp index d33b4c6210..95e039e6f0 100644 --- a/src/tools/uic/python/pythonwriteimports.cpp +++ b/src/tools/uic/python/pythonwriteimports.cpp @@ -131,6 +131,8 @@ void WriteImports::acceptCustomWidget(DomCustomWidget *node) output << "import " << className << '\n'; } else { // When we do have elementHeader, we know it's a relative import. QString modulePath = node->elementHeader()->text(); + // Replace the '/' by '.' + modulePath.replace(QLatin1Char('/'), QLatin1Char('.')); // '.h' is added by default on headers for if (modulePath.endsWith(QLatin1String(".h"))) modulePath.chop(2); diff --git a/src/widgets/widgets/qmenu.cpp b/src/widgets/widgets/qmenu.cpp index cae776159d..23292062cb 100644 --- a/src/widgets/widgets/qmenu.cpp +++ b/src/widgets/widgets/qmenu.cpp @@ -1473,6 +1473,9 @@ void QMenuPrivate::_q_actionTriggered() } } activateCausedStack(list, action, QAction::Trigger, false); + // if a widget action fires, we need to hide the menu explicitly + if (qobject_cast(action)) + hideUpToMenuBar(); } } } @@ -1640,10 +1643,8 @@ void QMenu::initStyleOption(QStyleOptionMenuItem *option, const QAction *action) Widgets can be inserted into menus with the QWidgetAction class. Instances of this class are used to hold widgets, and are inserted - into menus with the addAction() overload that takes a QAction. - - Conversely, actions can be added to widgets with the addAction(), - addActions() and insertAction() functions. + into menus with the addAction() overload that takes a QAction. If the + QWidgetAction fires the triggered() signal, the menu will close. \warning To make QMenu visible on the screen, exec() or popup() should be used instead of show(). diff --git a/tests/auto/corelib/kernel/qdeadlinetimer/tst_qdeadlinetimer.cpp b/tests/auto/corelib/kernel/qdeadlinetimer/tst_qdeadlinetimer.cpp index 35c5e7cb75..db53c3f20c 100644 --- a/tests/auto/corelib/kernel/qdeadlinetimer/tst_qdeadlinetimer.cpp +++ b/tests/auto/corelib/kernel/qdeadlinetimer/tst_qdeadlinetimer.cpp @@ -573,12 +573,32 @@ void tst_QDeadlineTimer::stdchrono() QCOMPARE(deadline.remainingTimeAsDuration(), nanoseconds::zero()); + /* + Call QTest::qSleep, and return true if the time actually slept is + within \a deviationPercent percent of the requested sleep time. + Otherwise, return false, in which case the test should to abort. + */ + auto sleepHelper = [](int ms, int deviationPercent = 10) -> bool { + auto before = steady_clock::now(); + QTest::qSleep(ms); + auto after = steady_clock::now(); + auto diff = duration_cast(after - before).count(); + bool inRange = qAbs(diff - ms) < ms * deviationPercent/100.0; + if (!inRange) + qWarning() << "sleeping" << diff << "instead of" << ms << inRange; + return inRange; + }; + auto steady_before = steady_clock::now(); auto system_before = system_clock::now(); - QTest::qSleep(minResolution); + if (!sleepHelper(minResolution)) + QSKIP("Slept too long"); auto now = QDeadlineTimer::current(timerType); - QTest::qSleep(minResolution); + auto steady_reference = steady_clock::now(); + auto system_reference = system_clock::now(); + if (!sleepHelper(minResolution)) + QSKIP("Slept too long"); auto sampling_start = steady_clock::now(); auto steady_deadline = now.deadline(); @@ -599,35 +619,33 @@ void tst_QDeadlineTimer::stdchrono() } { - auto diff = duration_cast(steady_after - steady_deadline); - QVERIFY2(diff.count() > minResolution/2, QByteArray::number(qint64(diff.count()))); - QVERIFY2(diff.count() < 3*minResolution/2, QByteArray::number(qint64(diff.count()))); + auto reference = duration_cast(steady_after - steady_reference).count(); + auto diff = duration_cast(steady_after - steady_deadline).count(); + QVERIFY2(diff > reference * 0.9 && diff < reference*1.1, QByteArray::number(qint64(diff))); QDeadlineTimer dt_after(steady_after, timerType); QVERIFY2(now < dt_after, ("now = " + QLocale().toString(now.deadlineNSecs()) + "; after = " + QLocale().toString(dt_after.deadlineNSecs())).toLatin1()); - diff = duration_cast(steady_deadline - steady_before); - QVERIFY2(diff.count() > minResolution/2, QByteArray::number(qint64(diff.count()))); - QVERIFY2(diff.count() < 3*minResolution/2, QByteArray::number(qint64(diff.count()))); + reference = duration_cast(steady_reference - steady_before).count(); + diff = duration_cast(steady_deadline - steady_before).count(); + QVERIFY2(diff > reference * 0.9 && diff < reference*1.1, QByteArray::number(qint64(diff))); QDeadlineTimer dt_before(steady_before, timerType); QVERIFY2(now > dt_before, ("now = " + QLocale().toString(now.deadlineNSecs()) + "; before = " + QLocale().toString(dt_before.deadlineNSecs())).toLatin1()); } { - auto diff = duration_cast(system_after - system_deadline); - QVERIFY2(diff.count() > minResolution/2, QByteArray::number(qint64(diff.count()))); - QVERIFY2(diff.count() < 3*minResolution/2, QByteArray::number(qint64(diff.count()))); - QDeadlineTimer dt_after(system_after, timerType); + auto reference = duration_cast(system_after - system_reference).count(); + auto diff = duration_cast(system_after - system_deadline).count(); + QVERIFY2(diff > reference * 0.9 && diff < reference*1.1, QByteArray::number(qint64(diff))); QDeadlineTimer dt_after(system_after, timerType); QVERIFY2(now < dt_after, ("now = " + QLocale().toString(now.deadlineNSecs()) + "; after = " + QLocale().toString(dt_after.deadlineNSecs())).toLatin1()); - diff = duration_cast(system_deadline - system_before); - QVERIFY2(diff.count() > minResolution/2, QByteArray::number(qint64(diff.count()))); - QVERIFY2(diff.count() < 3*minResolution/2, QByteArray::number(qint64(diff.count()))); - QDeadlineTimer dt_before(system_before, timerType); + reference = duration_cast(system_reference - system_before).count(); + diff = duration_cast(steady_deadline - steady_before).count(); + QVERIFY2(diff > reference * 0.9 && diff < reference*1.1, QByteArray::number(qint64(diff))); QDeadlineTimer dt_before(system_before, timerType); QVERIFY2(now > dt_before, ("now = " + QLocale().toString(now.deadlineNSecs()) + "; before = " + QLocale().toString(dt_before.deadlineNSecs())).toLatin1()); diff --git a/tests/auto/corelib/kernel/qelapsedtimer/tst_qelapsedtimer.cpp b/tests/auto/corelib/kernel/qelapsedtimer/tst_qelapsedtimer.cpp index 4ee3ca361f..bfc4f2ca36 100644 --- a/tests/auto/corelib/kernel/qelapsedtimer/tst_qelapsedtimer.cpp +++ b/tests/auto/corelib/kernel/qelapsedtimer/tst_qelapsedtimer.cpp @@ -48,6 +48,7 @@ private Q_SLOTS: void validity(); void basics(); void elapsed(); + void msecsTo(); }; void tst_QElapsedTimer::statics() @@ -108,30 +109,42 @@ void tst_QElapsedTimer::elapsed() t1.start(); QTest::qSleep(2*minResolution); + + auto nsecs = t1.nsecsElapsed(); + auto msecs = t1.elapsed(); + QVERIFY(nsecs > 0); + QVERIFY(msecs > 0); + // the number of elapsed nanoseconds and milliseconds should match + QVERIFY(nsecs - msecs * 1000000 < 1000000); + + if (msecs > 8 * minResolution) + QSKIP("Sampling timer took too long, aborting test"); + + QVERIFY(t1.hasExpired(minResolution)); + QVERIFY(!t1.hasExpired(8*minResolution)); + QVERIFY(!t1.hasExpired(-1)); + + qint64 elapsed = t1.restart(); + QVERIFY(elapsed >= msecs); + QVERIFY(elapsed < msecs + 3*minResolution); +} + +void tst_QElapsedTimer::msecsTo() +{ + QElapsedTimer t1; + t1.start(); + QTest::qSleep(minResolution); QElapsedTimer t2; t2.start(); QVERIFY(t1 != t2); QVERIFY(!(t1 == t2)); QVERIFY(t1 < t2); - QVERIFY(t1.msecsTo(t2) > 0); - QVERIFY(t1.nsecsElapsed() > 0); - QVERIFY(t1.elapsed() > 0); - // the number of elapsed nanoseconds and milliseconds should match - QVERIFY(t1.nsecsElapsed() - t1.elapsed() * 1000000 < 1000000); - QVERIFY(t1.hasExpired(minResolution)); - QVERIFY(!t1.hasExpired(8*minResolution)); - QVERIFY(!t2.hasExpired(minResolution)); - - QVERIFY(!t1.hasExpired(-1)); - QVERIFY(!t2.hasExpired(-1)); - - qint64 elapsed = t1.restart(); - QVERIFY(elapsed > minResolution); - QVERIFY(elapsed < 3*minResolution); - qint64 diff = t2.msecsTo(t1); - QVERIFY(diff < minResolution); + auto diff = t1.msecsTo(t2); + QVERIFY2(diff > 0, QString("difference t1 and t2 is %1").arg(diff).toLatin1()); + diff = t2.msecsTo(t1); + QVERIFY2(diff < 0, QString("difference t2 and t1 is %1").arg(diff).toLatin1()); } QTEST_MAIN(tst_QElapsedTimer); diff --git a/tests/auto/corelib/text/qstring/tst_qstring.cpp b/tests/auto/corelib/text/qstring/tst_qstring.cpp index 2c02fb2264..65f88c0e4d 100644 --- a/tests/auto/corelib/text/qstring/tst_qstring.cpp +++ b/tests/auto/corelib/text/qstring/tst_qstring.cpp @@ -5803,6 +5803,8 @@ void tst_QString::split(const QString &string, const QString &sep, QStringList r QVERIFY(list == result); } +QT_WARNING_PUSH +QT_WARNING_DISABLE_DEPRECATED list = str.split(sep, QString::KeepEmptyParts); QVERIFY(list == result); list = str.split(rx, QString::KeepEmptyParts); @@ -5825,6 +5827,7 @@ void tst_QString::split(const QString &string, const QString &sep, QStringList r list = str.split(sep.at(0), QString::SkipEmptyParts); QVERIFY(list == result); } +QT_WARNING_POP } void tst_QString::split() diff --git a/tests/auto/corelib/tools/qhash/tst_qhash.cpp b/tests/auto/corelib/tools/qhash/tst_qhash.cpp index 4052eff0ae..2a18f8d3e6 100644 --- a/tests/auto/corelib/tools/qhash/tst_qhash.cpp +++ b/tests/auto/corelib/tools/qhash/tst_qhash.cpp @@ -1115,6 +1115,12 @@ void tst_QHash::keyValueIterator() entry_type pair(it.key(), it.value()); QCOMPARE(*key_value_it, pair); + QCOMPARE(key_value_it->first, pair.first); + QCOMPARE(key_value_it->second, pair.second); + QCOMPARE(&(*key_value_it).first, &it.key()); + QCOMPARE(&key_value_it->first, &it.key()); + QCOMPARE(&(*key_value_it).second, &it.value()); + QCOMPARE(&key_value_it->second, &it.value()); ++key_value_it; ++it; } diff --git a/tests/auto/corelib/tools/qmap/tst_qmap.cpp b/tests/auto/corelib/tools/qmap/tst_qmap.cpp index 1638ebc992..9f0524c9e0 100644 --- a/tests/auto/corelib/tools/qmap/tst_qmap.cpp +++ b/tests/auto/corelib/tools/qmap/tst_qmap.cpp @@ -881,6 +881,12 @@ void tst_QMap::keyValueIterator() entry_type pair(it.key(), it.value()); QCOMPARE(*key_value_it, pair); + QCOMPARE(key_value_it->first, pair.first); + QCOMPARE(key_value_it->second, pair.second); + QCOMPARE(&(*key_value_it).first, &it.key()); + QCOMPARE(&key_value_it->first, &it.key()); + QCOMPARE(&(*key_value_it).second, &it.value()); + QCOMPARE(&key_value_it->second, &it.value()); ++key_value_it; ++it; } diff --git a/tests/auto/gui/rhi/qshader/tst_qshader.cpp b/tests/auto/gui/rhi/qshader/tst_qshader.cpp index ab7115b74a..378d1e85e7 100644 --- a/tests/auto/gui/rhi/qshader/tst_qshader.cpp +++ b/tests/auto/gui/rhi/qshader/tst_qshader.cpp @@ -368,7 +368,7 @@ void tst_QShader::serializeShaderDesc() QBuffer buf(&data); QDataStream ds(&buf); QVERIFY(buf.open(QIODevice::ReadOnly)); - QShaderDescription desc2 = QShaderDescription::deserialize(&ds); + QShaderDescription desc2 = QShaderDescription::deserialize(&ds, QShaderPrivate::QSB_VERSION); QVERIFY(!desc2.isValid()); } } @@ -400,7 +400,7 @@ void tst_QShader::serializeShaderDesc() QBuffer buf(&data); QDataStream ds(&buf); QVERIFY(buf.open(QIODevice::ReadOnly)); - QShaderDescription desc2 = QShaderDescription::deserialize(&ds); + QShaderDescription desc2 = QShaderDescription::deserialize(&ds, QShaderPrivate::QSB_VERSION); QVERIFY(desc2.isValid()); QCOMPARE(desc, desc2); } diff --git a/tests/auto/gui/text/qtextmarkdownimporter/data/fuzz20450.md b/tests/auto/gui/text/qtextmarkdownimporter/data/fuzz20450.md new file mode 100644 index 0000000000..d7005cb01e --- /dev/null +++ b/tests/auto/gui/text/qtextmarkdownimporter/data/fuzz20450.md @@ -0,0 +1,5 @@ +ÿ +* ÿ + + ÿ +* ÿ \ No newline at end of file diff --git a/tests/auto/gui/text/qtextmarkdownimporter/data/fuzz20580.md b/tests/auto/gui/text/qtextmarkdownimporter/data/fuzz20580.md new file mode 100644 index 0000000000..22006f5876 --- /dev/null +++ b/tests/auto/gui/text/qtextmarkdownimporter/data/fuzz20580.md @@ -0,0 +1 @@ +| --:| ("warning"); + QTest::newRow("fuzz20450") << "attempted to insert into a list that no longer exists"; + QTest::newRow("fuzz20580") << ""; +} + +void tst_QTextMarkdownImporter::pathological() // avoid crashing on crazy input +{ + QFETCH(QString, warning); + QString filename = QLatin1String("data/") + QTest::currentDataTag() + QLatin1String(".md"); + QFile f(QFINDTESTDATA(filename)); + QVERIFY(f.open(QFile::ReadOnly)); +#ifdef QT_NO_DEBUG + Q_UNUSED(warning) +#else + if (!warning.isEmpty()) + QTest::ignoreMessage(QtWarningMsg, warning.toLatin1()); +#endif + QTextDocument().setMarkdown(f.readAll()); +} + QTEST_MAIN(tst_QTextMarkdownImporter) #include "tst_qtextmarkdownimporter.moc" diff --git a/tests/auto/network/access/http2/tst_http2.cpp b/tests/auto/network/access/http2/tst_http2.cpp index 904cfd52b0..1ca60655a6 100644 --- a/tests/auto/network/access/http2/tst_http2.cpp +++ b/tests/auto/network/access/http2/tst_http2.cpp @@ -513,7 +513,7 @@ void tst_Http2::goaway() replies[i] = manager->get(request); QCOMPARE(replies[i]->error(), QNetworkReply::NoError); void (QNetworkReply::*errorSignal)(QNetworkReply::NetworkError) = - &QNetworkReply::error; + &QNetworkReply::errorOccurred; connect(replies[i], errorSignal, this, &tst_Http2::replyFinishedWithError); // Since we're using self-signed certificates, ignore SSL errors: replies[i]->ignoreSslErrors(); diff --git a/tests/auto/network/access/qhttpnetworkconnection/tst_qhttpnetworkconnection.cpp b/tests/auto/network/access/qhttpnetworkconnection/tst_qhttpnetworkconnection.cpp index 57fa5a613c..e8d4c773f0 100644 --- a/tests/auto/network/access/qhttpnetworkconnection/tst_qhttpnetworkconnection.cpp +++ b/tests/auto/network/access/qhttpnetworkconnection/tst_qhttpnetworkconnection.cpp @@ -1005,10 +1005,8 @@ void tst_QHttpNetworkConnection::overlappingCloseAndWrite() for (int i = 0; i < 10; ++i) { QNetworkRequest request(url); QNetworkReply *reply = accessManager.get(request); - // Not using Qt5 connection syntax here because of overly baroque syntax to discern between - // different error() methods. - QObject::connect(reply, SIGNAL(error(QNetworkReply::NetworkError)), - &server, SLOT(onReply(QNetworkReply::NetworkError))); + QObject::connect(reply, &QNetworkReply::errorOccurred, + &server, &TestTcpServer::onReply); } QTRY_COMPARE(server.errorCodeReports, 10); diff --git a/tests/auto/network/access/qnetworkaccessmanager/tst_qnetworkaccessmanager.cpp b/tests/auto/network/access/qnetworkaccessmanager/tst_qnetworkaccessmanager.cpp index 752655ee94..b5ded86d58 100644 --- a/tests/auto/network/access/qnetworkaccessmanager/tst_qnetworkaccessmanager.cpp +++ b/tests/auto/network/access/qnetworkaccessmanager/tst_qnetworkaccessmanager.cpp @@ -87,7 +87,7 @@ void tst_QNetworkAccessManager::networkAccessible() // When network is not accessible, all requests fail QNetworkReply *reply = manager.get(QNetworkRequest(QUrl("http://www.example.org"))); QSignalSpy finishedSpy(reply, &QNetworkReply::finished); - QSignalSpy errorSpy(reply, QOverload::of(&QNetworkReply::error)); + QSignalSpy errorSpy(reply, &QNetworkReply::errorOccurred); QVERIFY(finishedSpy.wait()); QCOMPARE(reply->isFinished(), true); QCOMPARE(reply->errorString(), QStringLiteral("Network access is disabled.")); diff --git a/tests/auto/network/access/qnetworkreply/tst_qnetworkreply.cpp b/tests/auto/network/access/qnetworkreply/tst_qnetworkreply.cpp index 5d46002a7c..430f9b7575 100644 --- a/tests/auto/network/access/qnetworkreply/tst_qnetworkreply.cpp +++ b/tests/auto/network/access/qnetworkreply/tst_qnetworkreply.cpp @@ -1381,7 +1381,7 @@ QString tst_QNetworkReply::runMultipartRequest(const QNetworkRequest &request, // the code below is copied from tst_QNetworkReply::runSimpleRequest, see below reply->setParent(this); connect(reply, SIGNAL(finished()), SLOT(finished())); - connect(reply, SIGNAL(error(QNetworkReply::NetworkError)), SLOT(gotError())); + connect(reply, SIGNAL(errorOccurred(QNetworkReply::NetworkError)), SLOT(gotError())); multiPart->setParent(reply.data()); returnCode = Timeout; @@ -1441,7 +1441,7 @@ QString tst_QNetworkReply::runSimpleRequest(QNetworkAccessManager::Operation op, code = Failure; } else { connect(reply, SIGNAL(finished()), SLOT(finished())); - connect(reply, SIGNAL(error(QNetworkReply::NetworkError)), SLOT(gotError())); + connect(reply, SIGNAL(errorOccurred(QNetworkReply::NetworkError)), SLOT(gotError())); int count = 0; loop = new QEventLoop; @@ -1476,7 +1476,7 @@ QString tst_QNetworkReply::runCustomRequest(const QNetworkRequest &request, reply.reset(manager.sendCustomRequest(request, verb, data)); reply->setParent(this); connect(reply, SIGNAL(finished()), SLOT(finished())); - connect(reply, SIGNAL(error(QNetworkReply::NetworkError)), SLOT(gotError())); + connect(reply, SIGNAL(errorOccurred(QNetworkReply::NetworkError)), SLOT(gotError())); returnCode = Timeout; loop = new QEventLoop; @@ -1513,7 +1513,7 @@ int tst_QNetworkReply::waitForFinish(QNetworkReplyPtr &reply) int count = 0; connect(reply, SIGNAL(finished()), SLOT(finished())); - connect(reply, SIGNAL(error(QNetworkReply::NetworkError)), SLOT(gotError())); + connect(reply, SIGNAL(errorOccurred(QNetworkReply::NetworkError)), SLOT(gotError())); returnCode = Success; loop = new QEventLoop; QSignalSpy spy(reply.data(), SIGNAL(downloadProgress(qint64,qint64))); @@ -1901,7 +1901,7 @@ void tst_QNetworkReply::getFromFtpAfterError() QNetworkRequest invalidRequest(QUrl("ftp://" + QtNetworkSettings::ftpServerName() + "/qtest/invalid.txt")); QNetworkReplyPtr invalidReply; invalidReply.reset(manager.get(invalidRequest)); - QSignalSpy spy(invalidReply.data(), SIGNAL(error(QNetworkReply::NetworkError))); + QSignalSpy spy(invalidReply.data(), SIGNAL(errorOccurred(QNetworkReply::NetworkError))); QVERIFY(spy.wait()); QCOMPARE(invalidReply->error(), QNetworkReply::ContentNotFoundError); @@ -3927,7 +3927,7 @@ void tst_QNetworkReply::ioGetFromHttpBrokenServer() QNetworkRequest request(QUrl("http://localhost:" + QString::number(server.serverPort()))); QNetworkReplyPtr reply(manager.get(request)); - QSignalSpy spy(reply.data(), SIGNAL(error(QNetworkReply::NetworkError))); + QSignalSpy spy(reply.data(), SIGNAL(errorOccurred(QNetworkReply::NetworkError))); QCOMPARE(waitForFinish(reply), int(Failure)); @@ -5475,7 +5475,7 @@ void tst_QNetworkReply::rateControl() QNetworkRequest request("debugpipe://localhost:" + QString::number(sender.serverPort())); QNetworkReplyPtr reply(manager.get(request)); reply->setReadBufferSize(32768); - QSignalSpy errorSpy(reply.data(), SIGNAL(error(QNetworkReply::NetworkError))); + QSignalSpy errorSpy(reply.data(), SIGNAL(errorOccurred(QNetworkReply::NetworkError))); RateControlledReader reader(sender, reply.data(), rate, 20); @@ -5889,7 +5889,7 @@ void tst_QNetworkReply::nestedEventLoops() QNetworkReplyPtr reply(manager.get(request)); QSignalSpy finishedspy(reply.data(), SIGNAL(finished())); - QSignalSpy errorspy(reply.data(), SIGNAL(error(QNetworkReply::NetworkError))); + QSignalSpy errorspy(reply.data(), SIGNAL(errorOccurred(QNetworkReply::NetworkError))); connect(reply, SIGNAL(finished()), SLOT(nestedEventLoops_slot())); QTestEventLoop::instance().enterLoop(20); @@ -6122,7 +6122,7 @@ void tst_QNetworkReply::authorizationError() QCOMPARE(reply->error(), QNetworkReply::NoError); - QSignalSpy errorSpy(reply.data(), SIGNAL(error(QNetworkReply::NetworkError))); + QSignalSpy errorSpy(reply.data(), SIGNAL(errorOccurred(QNetworkReply::NetworkError))); QSignalSpy finishedSpy(reply.data(), SIGNAL(finished())); // now run the request: QCOMPARE(waitForFinish(reply), int(Failure)); @@ -7078,7 +7078,7 @@ void tst_QNetworkReply::qtbug4121unknownAuthentication() QSignalSpy authSpy(&manager, SIGNAL(authenticationRequired(QNetworkReply*,QAuthenticator*))); QSignalSpy finishedSpy(&manager, SIGNAL(finished(QNetworkReply*))); - QSignalSpy errorSpy(reply.data(), SIGNAL(error(QNetworkReply::NetworkError))); + QSignalSpy errorSpy(reply.data(), SIGNAL(errorOccurred(QNetworkReply::NetworkError))); connect(reply, SIGNAL(finished()), &QTestEventLoop::instance(), SLOT(exitLoop()), Qt::QueuedConnection); QTestEventLoop::instance().enterLoop(10); @@ -7399,7 +7399,7 @@ void tst_QNetworkReply::httpWithNoCredentialUsage() request.setAttribute(QNetworkRequest::AuthenticationReuseAttribute, QNetworkRequest::Manual); QNetworkReplyPtr reply(manager.get(request)); - QSignalSpy errorSpy(reply.data(), SIGNAL(error(QNetworkReply::NetworkError))); + QSignalSpy errorSpy(reply.data(), SIGNAL(errorOccurred(QNetworkReply::NetworkError))); connect(reply, SIGNAL(finished()), &QTestEventLoop::instance(), SLOT(exitLoop()), Qt::QueuedConnection); QTestEventLoop::instance().enterLoop(10); @@ -8115,7 +8115,7 @@ void tst_QNetworkReply::emitErrorForAllReplies() // QTBUG-36890 QNetworkRequest request(urls.at(a)); QNetworkReply *reply = manager.get(request); replies.append(reply); - QSignalSpy *errorSpy = new QSignalSpy(reply, SIGNAL(error(QNetworkReply::NetworkError))); + QSignalSpy *errorSpy = new QSignalSpy(reply, SIGNAL(errorOccurred(QNetworkReply::NetworkError))); errorSpies.append(errorSpy); QSignalSpy *finishedSpy = new QSignalSpy(reply, SIGNAL(finished())); finishedSpies.append(finishedSpy); @@ -8517,7 +8517,7 @@ void tst_QNetworkReply::ioHttpChangeMaxRedirects() QNetworkReplyPtr reply(manager.get(request)); QSignalSpy redSpy(reply.data(), SIGNAL(redirected(QUrl))); - QSignalSpy spy(reply.data(), SIGNAL(error(QNetworkReply::NetworkError))); + QSignalSpy spy(reply.data(), SIGNAL(errorOccurred(QNetworkReply::NetworkError))); QCOMPARE(waitForFinish(reply), int(Failure)); @@ -8581,7 +8581,7 @@ void tst_QNetworkReply::ioHttpRedirectErrors() QTimer watchDog; watchDog.setSingleShot(true); - reply->connect(reply.data(), QOverload().of(&QNetworkReply::error), + reply->connect(reply.data(), &QNetworkReply::errorOccurred, [&eventLoop](QNetworkReply::NetworkError){ eventLoop.exit(Failure); }); @@ -8747,7 +8747,7 @@ void tst_QNetworkReply::ioHttpRedirectPolicyErrors() if (ssl) reply->ignoreSslErrors(); - QSignalSpy spy(reply.data(), SIGNAL(error(QNetworkReply::NetworkError))); + QSignalSpy spy(reply.data(), SIGNAL(errorOccurred(QNetworkReply::NetworkError))); QCOMPARE(waitForFinish(reply), int(Failure)); QCOMPARE(spy.count(), 1); @@ -9397,7 +9397,7 @@ void tst_QNetworkReply::getWithTimeout() QNetworkRequest request(QUrl("http://localhost:" + QString::number(server.serverPort()))); QNetworkReplyPtr reply(manager.get(request)); - QSignalSpy spy(reply.data(), SIGNAL(error(QNetworkReply::NetworkError))); + QSignalSpy spy(reply.data(), SIGNAL(errorOccurred(QNetworkReply::NetworkError))); QCOMPARE(waitForFinish(reply), int(Success)); @@ -9408,7 +9408,7 @@ void tst_QNetworkReply::getWithTimeout() server.stopTransfer = true; QNetworkReplyPtr reply2(manager.get(request)); - QSignalSpy spy2(reply2.data(), SIGNAL(error(QNetworkReply::NetworkError))); + QSignalSpy spy2(reply2.data(), SIGNAL(errorOccurred(QNetworkReply::NetworkError))); QCOMPARE(waitForFinish(reply2), int(Failure)); @@ -9419,7 +9419,7 @@ void tst_QNetworkReply::getWithTimeout() manager.setTransferTimeout(1000); QNetworkReplyPtr reply3(manager.get(request)); - QSignalSpy spy3(reply3.data(), SIGNAL(error(QNetworkReply::NetworkError))); + QSignalSpy spy3(reply3.data(), SIGNAL(errorOccurred(QNetworkReply::NetworkError))); QCOMPARE(waitForFinish(reply3), int(Failure)); @@ -9437,7 +9437,7 @@ void tst_QNetworkReply::postWithTimeout() request.setRawHeader("Content-Type", "application/octet-stream"); QByteArray postData("Just some nonsense"); QNetworkReplyPtr reply(manager.post(request, postData)); - QSignalSpy spy(reply.data(), SIGNAL(error(QNetworkReply::NetworkError))); + QSignalSpy spy(reply.data(), SIGNAL(errorOccurred(QNetworkReply::NetworkError))); QCOMPARE(waitForFinish(reply), int(Success)); @@ -9448,7 +9448,7 @@ void tst_QNetworkReply::postWithTimeout() server.stopTransfer = true; QNetworkReplyPtr reply2(manager.post(request, postData)); - QSignalSpy spy2(reply2.data(), SIGNAL(error(QNetworkReply::NetworkError))); + QSignalSpy spy2(reply2.data(), SIGNAL(errorOccurred(QNetworkReply::NetworkError))); QCOMPARE(waitForFinish(reply2), int(Failure)); @@ -9459,7 +9459,7 @@ void tst_QNetworkReply::postWithTimeout() manager.setTransferTimeout(1000); QNetworkReplyPtr reply3(manager.post(request, postData)); - QSignalSpy spy3(reply3.data(), SIGNAL(error(QNetworkReply::NetworkError))); + QSignalSpy spy3(reply3.data(), SIGNAL(errorOccurred(QNetworkReply::NetworkError))); QCOMPARE(waitForFinish(reply3), int(Failure)); diff --git a/tests/auto/widgets/graphicsview/qgraphicsview/tst_qgraphicsview.cpp b/tests/auto/widgets/graphicsview/qgraphicsview/tst_qgraphicsview.cpp index 769836ff62..157c07f922 100644 --- a/tests/auto/widgets/graphicsview/qgraphicsview/tst_qgraphicsview.cpp +++ b/tests/auto/widgets/graphicsview/qgraphicsview/tst_qgraphicsview.cpp @@ -4568,7 +4568,9 @@ void tst_QGraphicsView::task255529_transformationAnchorMouseAndViewportMargins() view.show(); qApp->setActiveWindow(&view); QVERIFY(QTest::qWaitForWindowExposed(&view)); - QVERIFY(QTest::qWaitForWindowActive(&view)); + const bool isActiveWindow = QTest::qWaitForWindowActive(&view); + if (!isActiveWindow) + QSKIP("Window activation failed, skipping test", Abort); // This is highly unstable (observed to pass on Windows and some Linux configurations). #ifndef Q_OS_MAC for (int i = 0; i < 4; ++i) { diff --git a/tests/auto/widgets/widgets/qmenu/tst_qmenu.cpp b/tests/auto/widgets/widgets/qmenu/tst_qmenu.cpp index 8ad4324c9e..a89b3231ad 100644 --- a/tests/auto/widgets/widgets/qmenu/tst_qmenu.cpp +++ b/tests/auto/widgets/widgets/qmenu/tst_qmenu.cpp @@ -116,6 +116,7 @@ private slots: void QTBUG20403_nested_popup_on_shortcut_trigger(); void QTBUG47515_widgetActionEnterLeave(); void QTBUG8122_widgetActionCrashOnClose(); + void widgetActionTriggerClosesMenu(); void QTBUG_10735_crashWithDialog(); #ifdef Q_OS_MAC @@ -1407,6 +1408,84 @@ void tst_QMenu::QTBUG8122_widgetActionCrashOnClose() QTRY_VERIFY(menu->isHidden()); } +/*! + Test that a QWidgetAction that fires closes the menus that it is in. +*/ +void tst_QMenu::widgetActionTriggerClosesMenu() +{ + class ButtonAction : public QWidgetAction + { + public: + ButtonAction() + : QWidgetAction(nullptr) + {} + + void click() + { + if (pushButton) + pushButton->click(); + } + + protected: + QWidget *createWidget(QWidget *parent) + { + QPushButton *button = new QPushButton(QLatin1String("Button"), parent); + connect(button, &QPushButton::clicked, this, &QAction::trigger); + + if (!pushButton) + pushButton = button; + return button; + } + + private: + QPointer pushButton; + }; + + QMenu menu; + QMenu submenu; + + int menuTriggeredCount = 0; + int menuAboutToHideCount = 0; + QAction *actionTriggered = nullptr; + + connect(&menu, &QMenu::triggered, this, [&](QAction *action){ + ++menuTriggeredCount; + actionTriggered = action; + }); + connect (&menu, &QMenu::aboutToHide, this, [&](){ + ++menuAboutToHideCount; + }); + + QAction regularAction(QLatin1String("Action")); + ButtonAction widgetAction; + + submenu.addAction(®ularAction); + submenu.addAction(&widgetAction); + + menu.addMenu(&submenu); + menu.addAction(®ularAction); + menu.addAction(&widgetAction); + + menu.popup(QPoint(200,200)); + submenu.popup(QPoint(250,250)); + if (!QTest::qWaitForWindowExposed(&menu) || !QTest::qWaitForWindowExposed(&submenu)) + QSKIP("Failed to show menus, aborting test"); + + regularAction.trigger(); + QVERIFY(menu.isVisible()); + QVERIFY(submenu.isVisible()); + QCOMPARE(menuTriggeredCount, 1); + QCOMPARE(actionTriggered, ®ularAction); + menuTriggeredCount = 0; + actionTriggered = nullptr; + + widgetAction.click(); + QVERIFY(!menu.isVisible()); + QVERIFY(!submenu.isVisible()); + QCOMPARE(menuTriggeredCount, 1); + QCOMPARE(menuAboutToHideCount, 1); + QCOMPARE(actionTriggered, &widgetAction); +} class MyMenu : public QMenu { diff --git a/util/locale_database/cldr2qlocalexml.py b/util/locale_database/cldr2qlocalexml.py index fdb0a34037..7f98e29d47 100755 --- a/util/locale_database/cldr2qlocalexml.py +++ b/util/locale_database/cldr2qlocalexml.py @@ -61,7 +61,7 @@ import enumdata import xpathlite from xpathlite import DraftResolution, findAlias, findEntry, findTagsInFile from dateconverter import convert_date -from localexml import Locale +from qlocalexml import Locale # TODO: make calendars a command-line option calendars = ['gregorian', 'persian', 'islamic'] # 'hebrew' @@ -335,8 +335,8 @@ def _generateLocaleInfo(path, language_code, script_code, country_code, variant_ endonym = findEntryDef(path, "localeDisplayNames/languages/language[type=%s_%s]" % (language_code, country_code)) if not endonym: endonym = findEntryDef(path, "localeDisplayNames/languages/language[type=%s]" % (language_code)) - result['language_endonym'] = endonym - result['country_endonym'] = findEntryDef(path, "localeDisplayNames/territories/territory[type=%s]" % (country_code)) + result['languageEndonym'] = endonym + result['countryEndonym'] = findEntryDef(path, "localeDisplayNames/territories/territory[type=%s]" % (country_code)) currency_format = get_number_in_system(path, "numbers/currencyFormats/currencyFormatLength/currencyFormat/pattern", numbering_system) currency_format = parse_number_format(currency_format, result) diff --git a/util/locale_database/localexml.py b/util/locale_database/qlocalexml.py similarity index 97% rename from util/locale_database/localexml.py rename to util/locale_database/qlocalexml.py index 85ecb2d6ca..b4fbe86be5 100644 --- a/util/locale_database/localexml.py +++ b/util/locale_database/qlocalexml.py @@ -169,7 +169,7 @@ class Locale: for key in ('decimal', 'group', 'zero', 'list', 'percent', 'minus', 'plus', 'exp'): print inner + "<%s>" % key + get(key) + "" % key - for key in ('language_endonym', 'country_endonym', + for key in ('languageEndonym', 'countryEndonym', 'quotationStart', 'quotationEnd', 'alternateQuotationStart', 'alternateQuotationEnd', 'listPatternPartStart', 'listPatternPartMiddle', @@ -187,8 +187,7 @@ class Locale: '_'.join((k, cal)) for k in self.propsMonthDay('months') for cal in calendars): - ent = camelCase(key.split('_')) if key.endswith('_endonym') else key - print inner + "<%s>%s" % (ent, escape(get(key)).encode('utf-8'), ent) + print inner + "<%s>%s" % (key, escape(get(key)).encode('utf-8'), key) for key in ('currencyDigits', 'currencyRounding'): print inner + "<%s>%d" % (key, get(key), key) @@ -262,9 +261,9 @@ class Locale: quantifiers=('k', 'M', 'G', 'T', 'P', 'E')): """Returns an object representing the C locale.""" return cls(dict(cls.__monthNames(calendars)), - language='C', language_code='0', language_endonym='', + language='C', language_code='0', languageEndonym='', script='AnyScript', script_code='0', - country='AnyCountry', country_code='0', country_endonym='', + country='AnyCountry', country_code='0', countryEndonym='', decimal='.', group=',', list=';', percent='%', zero='0', minus='-', plus='+', exp='e', quotationStart='"', quotationEnd='"', diff --git a/util/locale_database/qlocalexml2cpp.py b/util/locale_database/qlocalexml2cpp.py index bb9f138c18..3dde298f47 100755 --- a/util/locale_database/qlocalexml2cpp.py +++ b/util/locale_database/qlocalexml2cpp.py @@ -40,7 +40,7 @@ import datetime import xml.dom.minidom from enumdata import language_aliases, country_aliases, script_aliases -from localexml import Locale +from qlocalexml import Locale # TODO: Make calendars a command-line parameter # map { CLDR name: Qt file name } @@ -373,7 +373,7 @@ def main(): if len(sys.argv) != 3: usage() - localexml = sys.argv[1] + qlocalexml = sys.argv[1] qtsrcdir = sys.argv[2] if not (os.path.isdir(qtsrcdir) @@ -390,7 +390,7 @@ def main(): s = qlocaledata_file.readline() data_temp_file.write(GENERATED_BLOCK_START) - doc = xml.dom.minidom.parse(localexml) + doc = xml.dom.minidom.parse(qlocalexml) language_map = loadMap(doc, 'language') script_map = loadMap(doc, 'script') country_map = loadMap(doc, 'country')