diff options
182 files changed, 3875 insertions, 2906 deletions
diff --git a/.qmake.conf b/.qmake.conf index 6d42bbdd344..5153f8139ff 100644 --- a/.qmake.conf +++ b/.qmake.conf @@ -4,4 +4,4 @@ CONFIG += warning_clean QT_SOURCE_TREE = $$PWD QT_BUILD_TREE = $$shadowed($$PWD) -MODULE_VERSION = 5.9.0 +MODULE_VERSION = 5.10.0 diff --git a/config.tests/common/aesni/aesni.cpp b/config.tests/common/aesni/aesni.cpp new file mode 100644 index 00000000000..a177183c724 --- /dev/null +++ b/config.tests/common/aesni/aesni.cpp @@ -0,0 +1,49 @@ +/**************************************************************************** +** +** Copyright (C) 2017 Intel Corporation. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the config.tests of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include <wmmintrin.h> + +int main(int, char**) +{ + __m128i a = _mm_setzero_si128(); + __m128i b = _mm_aesenc_si128(a, a); + __m128i c = _mm_aesdec_si128(a, b); + (void)c; + return 0; +} diff --git a/config.tests/common/aesni/aesni.pro b/config.tests/common/aesni/aesni.pro new file mode 100644 index 00000000000..49cb132ef78 --- /dev/null +++ b/config.tests/common/aesni/aesni.pro @@ -0,0 +1,3 @@ +SOURCES = aesni.cpp +!defined(QMAKE_CFLAGS_AESNI, "var"): error("This compiler does not support AES New Instructions") +else: QMAKE_CXXFLAGS += $$QMAKE_CFLAGS_AESNI diff --git a/config.tests/common/shani/shani.cpp b/config.tests/common/shani/shani.cpp new file mode 100644 index 00000000000..0fe6e87dd84 --- /dev/null +++ b/config.tests/common/shani/shani.cpp @@ -0,0 +1,50 @@ +/**************************************************************************** +** +** Copyright (C) 2017 Intel Corporation. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the config.tests of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include <immintrin.h> + +int main(int, char**) +{ + __m128i a = _mm_setzero_si128(); + __m128i b = _mm_sha1rnds4_epu32(a, a, 0); + __m128i c = _mm_sha1msg1_epu32(a, b); + __m128i d = _mm_sha256msg2_epu32(b, c); + (void)d; + return 0; +} diff --git a/config.tests/common/shani/shani.pro b/config.tests/common/shani/shani.pro new file mode 100644 index 00000000000..278f49ef90a --- /dev/null +++ b/config.tests/common/shani/shani.pro @@ -0,0 +1,3 @@ +SOURCES = shani.cpp +!defined(QMAKE_CFLAGS_SHANI, "var"): error("This compiler does not support Secure Hash Algorithm extensions") +else: QMAKE_CXXFLAGS += $$QMAKE_CFLAGS_SHANI diff --git a/configure.json b/configure.json index c5be88856de..69019afa808 100644 --- a/configure.json +++ b/configure.json @@ -315,11 +315,21 @@ "type": "compile", "test": "common/sse4_2" }, + "aesni": { + "label": "AES new instructions", + "type": "compile", + "test": "common/aesni" + }, "f16c": { "label": "F16C instructions", "type": "compile", "test": "common/f16c" }, + "shani": { + "label": "SHA new instructions", + "type": "compile", + "test": "common/shani" + }, "avx": { "label": "AVX instructions", "type": "compile", @@ -869,6 +879,22 @@ { "type": "define", "name": "QT_COMPILER_SUPPORTS_AVX512VBMI", "value": 1 } ] }, + "aesni": { + "label": "aesni", + "condition": "features.sse2 && tests.aesni", + "output": [ + "privateConfig", + { "type": "define", "name": "QT_COMPILER_SUPPORTS_AES", "value": 1 } + ] + }, + "shani": { + "label": "shani", + "condition": "features.sse2 && tests.shani", + "output": [ + "privateConfig", + { "type": "define", "name": "QT_COMPILER_SUPPORTS_SHA", "value": 1 } + ] + }, "mips_dsp": { "label": "DSP", "condition": "arch.mips && tests.mips_dsp", diff --git a/doc/global/config.qdocconf b/doc/global/config.qdocconf index 0c22d70529e..a18396876dc 100644 --- a/doc/global/config.qdocconf +++ b/doc/global/config.qdocconf @@ -13,3 +13,7 @@ navigation.homepage = "Qt $QT_VER" sourcedirs += includes $$BUILDDIR url = http://doc.qt.io/qt-5 + +# Uncomment the following two lines to generate documentation marked as \internal +# alias.internal = disable +# macro.internal.HTML = "<span style="color:red">[internal]</span>" diff --git a/examples/opengl/qopenglwidget/glwidget.cpp b/examples/opengl/qopenglwidget/glwidget.cpp index 21d922d713a..bb7c952a269 100644 --- a/examples/opengl/qopenglwidget/glwidget.cpp +++ b/examples/opengl/qopenglwidget/glwidget.cpp @@ -61,6 +61,10 @@ const int bubbleNum = 8; +#ifndef GL_SRGB8_ALPHA8 +#define GL_SRGB8_ALPHA8 0x8C43 +#endif + GLWidget::GLWidget(MainWindow *mw, bool button, const QColor &background) : m_mainWindow(mw), m_showBubbles(true), @@ -75,6 +79,8 @@ GLWidget::GLWidget(MainWindow *mw, bool button, const QColor &background) m_background(background) { setMinimumSize(300, 250); + if (QCoreApplication::arguments().contains(QStringLiteral("--srgb"))) + setTextureFormat(GL_SRGB8_ALPHA8); } GLWidget::~GLWidget() diff --git a/examples/opengl/qopenglwidget/main.cpp b/examples/opengl/qopenglwidget/main.cpp index d7aa791142b..f9b5731b8f8 100644 --- a/examples/opengl/qopenglwidget/main.cpp +++ b/examples/opengl/qopenglwidget/main.cpp @@ -61,6 +61,8 @@ int main( int argc, char ** argv ) QSurfaceFormat format; format.setDepthBufferSize(24); format.setStencilBufferSize(8); + if (QCoreApplication::arguments().contains(QStringLiteral("--srgb"))) + format.setColorSpace(QSurfaceFormat::sRGBColorSpace); if (QCoreApplication::arguments().contains(QStringLiteral("--multisample"))) format.setSamples(4); QSurfaceFormat::setDefaultFormat(format); diff --git a/examples/touch/pinchzoom/mouse.cpp b/examples/touch/pinchzoom/mouse.cpp index f063e966542..3b8e6b56908 100644 --- a/examples/touch/pinchzoom/mouse.cpp +++ b/examples/touch/pinchzoom/mouse.cpp @@ -54,7 +54,7 @@ #include <QPainter> #include <QStyleOption> -#include <math.h> +#include <cmath> static const double Pi = 3.14159265358979323846264338327950288419717; static double TwoPi = 2.0 * Pi; @@ -139,9 +139,7 @@ void Mouse::timerEvent(QTimerEvent *) //! [5] QLineF lineToCenter(QPointF(0, 0), mapFromScene(0, 0)); if (lineToCenter.length() > 150) { - qreal angleToCenter = ::acos(lineToCenter.dx() / lineToCenter.length()); - if (lineToCenter.dy() < 0) - angleToCenter = TwoPi - angleToCenter; + qreal angleToCenter = std::atan2(lineToCenter.dy(), lineToCenter.dx()); angleToCenter = normalizeAngle((Pi - angleToCenter) + Pi / 2); if (angleToCenter < Pi && angleToCenter > Pi / 4) { @@ -170,9 +168,7 @@ void Mouse::timerEvent(QTimerEvent *) continue; QLineF lineToMouse(QPointF(0, 0), mapFromItem(item, 0, 0)); - qreal angleToMouse = ::acos(lineToMouse.dx() / lineToMouse.length()); - if (lineToMouse.dy() < 0) - angleToMouse = TwoPi - angleToMouse; + qreal angleToMouse = std::atan2(lineToMouse.dy(), lineToMouse.dx()); angleToMouse = normalizeAngle((Pi - angleToMouse) + Pi / 2); if (angleToMouse >= 0 && angleToMouse < Pi / 2) { diff --git a/examples/widgets/graphicsview/collidingmice/mouse.cpp b/examples/widgets/graphicsview/collidingmice/mouse.cpp index b94c650c185..cc1a15cd825 100644 --- a/examples/widgets/graphicsview/collidingmice/mouse.cpp +++ b/examples/widgets/graphicsview/collidingmice/mouse.cpp @@ -54,7 +54,7 @@ #include <QPainter> #include <QStyleOption> -#include <math.h> +#include <cmath> static const double Pi = 3.14159265358979323846264338327950288419717; static double TwoPi = 2.0 * Pi; @@ -140,9 +140,7 @@ void Mouse::advance(int step) //! [5] QLineF lineToCenter(QPointF(0, 0), mapFromScene(0, 0)); if (lineToCenter.length() > 150) { - qreal angleToCenter = ::acos(lineToCenter.dx() / lineToCenter.length()); - if (lineToCenter.dy() < 0) - angleToCenter = TwoPi - angleToCenter; + qreal angleToCenter = std::atan2(lineToCenter.dy(), lineToCenter.dx()); angleToCenter = normalizeAngle((Pi - angleToCenter) + Pi / 2); if (angleToCenter < Pi && angleToCenter > Pi / 4) { @@ -171,9 +169,7 @@ void Mouse::advance(int step) continue; QLineF lineToMouse(QPointF(0, 0), mapFromItem(item, 0, 0)); - qreal angleToMouse = ::acos(lineToMouse.dx() / lineToMouse.length()); - if (lineToMouse.dy() < 0) - angleToMouse = TwoPi - angleToMouse; + qreal angleToMouse = std::atan2(lineToMouse.dy(), lineToMouse.dx()); angleToMouse = normalizeAngle((Pi - angleToMouse) + Pi / 2); if (angleToMouse >= 0 && angleToMouse < Pi / 2) { diff --git a/examples/widgets/graphicsview/diagramscene/arrow.cpp b/examples/widgets/graphicsview/diagramscene/arrow.cpp index 012b9ea2ed3..ae7fa7af904 100644 --- a/examples/widgets/graphicsview/diagramscene/arrow.cpp +++ b/examples/widgets/graphicsview/diagramscene/arrow.cpp @@ -51,7 +51,7 @@ #include "arrow.h" -#include <math.h> +#include <cmath> #include <QPen> #include <QPainter> @@ -132,9 +132,7 @@ void Arrow::paint(QPainter *painter, const QStyleOptionGraphicsItem *, setLine(QLineF(intersectPoint, myStartItem->pos())); //! [5] //! [6] - double angle = ::acos(line().dx() / line().length()); - if (line().dy() >= 0) - angle = (Pi * 2) - angle; + double angle = std::atan2(-line().dy(), line().dx()); QPointF arrowP1 = line().p1() + QPointF(sin(angle + Pi / 3) * arrowSize, cos(angle + Pi / 3) * arrowSize); diff --git a/examples/widgets/graphicsview/elasticnodes/edge.cpp b/examples/widgets/graphicsview/elasticnodes/edge.cpp index e794e803cf5..d9e4c62e347 100644 --- a/examples/widgets/graphicsview/elasticnodes/edge.cpp +++ b/examples/widgets/graphicsview/elasticnodes/edge.cpp @@ -51,12 +51,11 @@ #include "edge.h" #include "node.h" -#include <math.h> +#include <cmath> #include <QPainter> static const double Pi = 3.14159265358979323846264338327950288419717; -static double TwoPi = 2.0 * Pi; //! [0] Edge::Edge(Node *sourceNode, Node *destNode) @@ -139,9 +138,7 @@ void Edge::paint(QPainter *painter, const QStyleOptionGraphicsItem *, QWidget *) //! [6] // Draw the arrows - double angle = ::acos(line.dx() / line.length()); - if (line.dy() >= 0) - angle = TwoPi - angle; + double angle = std::atan2(-line.dy(), line.dx()); QPointF sourceArrowP1 = sourcePoint + QPointF(sin(angle + Pi / 3) * arrowSize, cos(angle + Pi / 3) * arrowSize); diff --git a/examples/widgets/itemviews/chart/pieview.cpp b/examples/widgets/itemviews/chart/pieview.cpp index fb439fae67a..942bbe5ca57 100644 --- a/examples/widgets/itemviews/chart/pieview.cpp +++ b/examples/widgets/itemviews/chart/pieview.cpp @@ -125,9 +125,9 @@ QModelIndex PieView::indexAt(const QPoint &point) const return QModelIndex(); // Determine the angle of the point. - double angle = (180 / M_PI) * std::acos(cx / d); - if (cy < 0) - angle = 360 - angle; + double angle = (180 / M_PI) * std::atan2(cy, cx); + if (angle < 0) + angle = 360 + angle; // Find the relevant slice of the pie. double startAngle = 0.0; diff --git a/examples/xml/dombookmarks/mainwindow.cpp b/examples/xml/dombookmarks/mainwindow.cpp index e0f208d3369..fade2dfc960 100644 --- a/examples/xml/dombookmarks/mainwindow.cpp +++ b/examples/xml/dombookmarks/mainwindow.cpp @@ -58,13 +58,13 @@ MainWindow::MainWindow() xbelTree = new XbelTree; setCentralWidget(xbelTree); - createActions(); createMenus(); statusBar()->showMessage(tr("Ready")); setWindowTitle(tr("DOM Bookmarks")); - resize(480, 320); + const QSize availableSize = QApplication::desktop()->availableGeometry(this).size(); + resize(availableSize.width() / 2, availableSize.height() / 3); } void MainWindow::open() @@ -80,8 +80,8 @@ void MainWindow::open() if (!file.open(QFile::ReadOnly | QFile::Text)) { QMessageBox::warning(this, tr("SAX Bookmarks"), tr("Cannot read file %1:\n%2.") - .arg(fileName) - .arg(file.errorString())); + .arg(QDir::toNativeSeparators(fileName), + file.errorString())); return; } @@ -102,8 +102,8 @@ void MainWindow::saveAs() if (!file.open(QFile::WriteOnly | QFile::Text)) { QMessageBox::warning(this, tr("SAX Bookmarks"), tr("Cannot write file %1:\n%2.") - .arg(fileName) - .arg(file.errorString())); + .arg(QDir::toNativeSeparators(fileName), + file.errorString())); return; } @@ -119,37 +119,21 @@ void MainWindow::about() "documents.")); } -void MainWindow::createActions() +void MainWindow::createMenus() { - openAct = new QAction(tr("&Open..."), this); + QMenu *fileMenu = menuBar()->addMenu(tr("&File")); + QAction *openAct = fileMenu->addAction(tr("&Open..."), this, &MainWindow::open); openAct->setShortcuts(QKeySequence::Open); - connect(openAct, SIGNAL(triggered()), this, SLOT(open())); - saveAsAct = new QAction(tr("&Save As..."), this); + QAction *saveAsAct = fileMenu->addAction(tr("&Save As..."), this, &MainWindow::saveAs); saveAsAct->setShortcuts(QKeySequence::SaveAs); - connect(saveAsAct, SIGNAL(triggered()), this, SLOT(saveAs())); - exitAct = new QAction(tr("E&xit"), this); + QAction *exitAct = fileMenu->addAction(tr("E&xit"), this, &QWidget::close); exitAct->setShortcuts(QKeySequence::Quit); - connect(exitAct, SIGNAL(triggered()), this, SLOT(close())); - - aboutAct = new QAction(tr("&About"), this); - connect(aboutAct, SIGNAL(triggered()), this, SLOT(about())); - - aboutQtAct = new QAction(tr("About &Qt"), this); - connect(aboutQtAct, SIGNAL(triggered()), qApp, SLOT(aboutQt())); -} - -void MainWindow::createMenus() -{ - fileMenu = menuBar()->addMenu(tr("&File")); - fileMenu->addAction(openAct); - fileMenu->addAction(saveAsAct); - fileMenu->addAction(exitAct); menuBar()->addSeparator(); - helpMenu = menuBar()->addMenu(tr("&Help")); - helpMenu->addAction(aboutAct); - helpMenu->addAction(aboutQtAct); + QMenu *helpMenu = menuBar()->addMenu(tr("&Help")); + helpMenu->addAction(tr("&About"), this, &MainWindow::about); + helpMenu->addAction(tr("About &Qt"), qApp, &QCoreApplication::quit); } diff --git a/examples/xml/dombookmarks/mainwindow.h b/examples/xml/dombookmarks/mainwindow.h index 6d490caf647..0a8c7bdd82b 100644 --- a/examples/xml/dombookmarks/mainwindow.h +++ b/examples/xml/dombookmarks/mainwindow.h @@ -68,18 +68,9 @@ public slots: void about(); private: - void createActions(); void createMenus(); XbelTree *xbelTree; - - QMenu *fileMenu; - QMenu *helpMenu; - QAction *openAct; - QAction *saveAsAct; - QAction *exitAct; - QAction *aboutAct; - QAction *aboutQtAct; }; #endif diff --git a/examples/xml/dombookmarks/xbeltree.cpp b/examples/xml/dombookmarks/xbeltree.cpp index 82afc48bd9d..f7ff1de6382 100644 --- a/examples/xml/dombookmarks/xbeltree.cpp +++ b/examples/xml/dombookmarks/xbeltree.cpp @@ -52,6 +52,18 @@ #include "xbeltree.h" +enum { DomElementRole = Qt::UserRole + 1 }; + +Q_DECLARE_METATYPE(QDomElement) + +static inline QString titleElement() { return QStringLiteral("title"); } +static inline QString folderElement() { return QStringLiteral("folder"); } +static inline QString bookmarkElement() { return QStringLiteral("bookmark"); } + +static inline QString versionAttribute() { return QStringLiteral("version"); } +static inline QString hrefAttribute() { return QStringLiteral("href"); } +static inline QString foldedAttribute() { return QStringLiteral("folded"); } + XbelTree::XbelTree(QWidget *parent) : QTreeWidget(parent) { @@ -68,6 +80,24 @@ XbelTree::XbelTree(QWidget *parent) bookmarkIcon.addPixmap(style()->standardPixmap(QStyle::SP_FileIcon)); } +#if !defined(QT_NO_CONTEXTMENU) && !defined(QT_NO_CLIPBOARD) +void XbelTree::contextMenuEvent(QContextMenuEvent *event) +{ + const QTreeWidgetItem *item = itemAt(event->pos()); + if (!item) + return; + const QString url = item->text(1); + QMenu contextMenu; + QAction *copyAction = contextMenu.addAction(tr("Copy Link to Clipboard")); + QAction *openAction = contextMenu.addAction(tr("Open")); + QAction *action = contextMenu.exec(event->globalPos()); + if (action == copyAction) + QGuiApplication::clipboard()->setText(url); + else if (action == openAction) + QDesktopServices::openUrl(QUrl(url)); +} +#endif // !QT_NO_CONTEXTMENU && !QT_NO_CLIPBOARD + bool XbelTree::read(QIODevice *device) { QString errorStr; @@ -89,8 +119,8 @@ bool XbelTree::read(QIODevice *device) QMessageBox::information(window(), tr("DOM Bookmarks"), tr("The file is not an XBEL file.")); return false; - } else if (root.hasAttribute("version") - && root.attribute("version") != "1.0") { + } else if (root.hasAttribute(versionAttribute()) + && root.attribute(versionAttribute()) != QLatin1String("1.0")) { QMessageBox::information(window(), tr("DOM Bookmarks"), tr("The file is not an XBEL version 1.0 " "file.")); @@ -99,22 +129,20 @@ bool XbelTree::read(QIODevice *device) clear(); - disconnect(this, SIGNAL(itemChanged(QTreeWidgetItem*,int)), - this, SLOT(updateDomElement(QTreeWidgetItem*,int))); + disconnect(this, &QTreeWidget::itemChanged, this, &XbelTree::updateDomElement); - QDomElement child = root.firstChildElement("folder"); + QDomElement child = root.firstChildElement(folderElement()); while (!child.isNull()) { parseFolderElement(child); - child = child.nextSiblingElement("folder"); + child = child.nextSiblingElement(folderElement()); } - connect(this, SIGNAL(itemChanged(QTreeWidgetItem*,int)), - this, SLOT(updateDomElement(QTreeWidgetItem*,int))); + connect(this, &QTreeWidget::itemChanged, this, &XbelTree::updateDomElement); return true; } -bool XbelTree::write(QIODevice *device) +bool XbelTree::write(QIODevice *device) const { const int IndentSize = 4; @@ -123,21 +151,21 @@ bool XbelTree::write(QIODevice *device) return true; } -void XbelTree::updateDomElement(QTreeWidgetItem *item, int column) +void XbelTree::updateDomElement(const QTreeWidgetItem *item, int column) { - QDomElement element = domElementForItem.value(item); + QDomElement element = item->data(0, DomElementRole).value<QDomElement>(); if (!element.isNull()) { if (column == 0) { - QDomElement oldTitleElement = element.firstChildElement("title"); - QDomElement newTitleElement = domDocument.createElement("title"); + QDomElement oldTitleElement = element.firstChildElement(titleElement()); + QDomElement newTitleElement = domDocument.createElement(titleElement()); QDomText newTitleText = domDocument.createTextNode(item->text(0)); newTitleElement.appendChild(newTitleText); element.replaceChild(newTitleElement, oldTitleElement); } else { - if (element.tagName() == "bookmark") - element.setAttribute("href", item->text(1)); + if (element.tagName() == bookmarkElement()) + element.setAttribute(hrefAttribute(), item->text(1)); } } } @@ -147,7 +175,7 @@ void XbelTree::parseFolderElement(const QDomElement &element, { QTreeWidgetItem *item = createItem(element, parentItem); - QString title = element.firstChildElement("title").text(); + QString title = element.firstChildElement(titleElement()).text(); if (title.isEmpty()) title = QObject::tr("Folder"); @@ -155,25 +183,25 @@ void XbelTree::parseFolderElement(const QDomElement &element, item->setIcon(0, folderIcon); item->setText(0, title); - bool folded = (element.attribute("folded") != "no"); + bool folded = (element.attribute(foldedAttribute()) != QLatin1String("no")); setItemExpanded(item, !folded); QDomElement child = element.firstChildElement(); while (!child.isNull()) { - if (child.tagName() == "folder") { + if (child.tagName() == folderElement()) { parseFolderElement(child, item); - } else if (child.tagName() == "bookmark") { + } else if (child.tagName() == bookmarkElement()) { QTreeWidgetItem *childItem = createItem(child, item); - QString title = child.firstChildElement("title").text(); + QString title = child.firstChildElement(titleElement()).text(); if (title.isEmpty()) title = QObject::tr("Folder"); childItem->setFlags(item->flags() | Qt::ItemIsEditable); childItem->setIcon(0, bookmarkIcon); childItem->setText(0, title); - childItem->setText(1, child.attribute("href")); - } else if (child.tagName() == "separator") { + childItem->setText(1, child.attribute(hrefAttribute())); + } else if (child.tagName() == QLatin1String("separator")) { QTreeWidgetItem *childItem = createItem(child, item); childItem->setFlags(item->flags() & ~(Qt::ItemIsSelectable | Qt::ItemIsEditable)); childItem->setText(0, QString(30, 0xB7)); @@ -191,6 +219,6 @@ QTreeWidgetItem *XbelTree::createItem(const QDomElement &element, } else { item = new QTreeWidgetItem(this); } - domElementForItem.insert(item, element); + item->setData(0, DomElementRole, QVariant::fromValue(element)); return item; } diff --git a/examples/xml/dombookmarks/xbeltree.h b/examples/xml/dombookmarks/xbeltree.h index bf4b55ea74b..f6c7ef8bfeb 100644 --- a/examples/xml/dombookmarks/xbeltree.h +++ b/examples/xml/dombookmarks/xbeltree.h @@ -52,7 +52,6 @@ #define XBELTREE_H #include <QDomDocument> -#include <QHash> #include <QIcon> #include <QTreeWidget> @@ -64,10 +63,15 @@ public: XbelTree(QWidget *parent = 0); bool read(QIODevice *device); - bool write(QIODevice *device); + bool write(QIODevice *device) const; + +protected: +#if !defined(QT_NO_CONTEXTMENU) && !defined(QT_NO_CLIPBOARD) + void contextMenuEvent(QContextMenuEvent *event) Q_DECL_OVERRIDE; +#endif private slots: - void updateDomElement(QTreeWidgetItem *item, int column); + void updateDomElement(const QTreeWidgetItem *item, int column); private: void parseFolderElement(const QDomElement &element, @@ -76,7 +80,6 @@ private: QTreeWidgetItem *parentItem = 0); QDomDocument domDocument; - QHash<QTreeWidgetItem *, QDomElement> domElementForItem; QIcon folderIcon; QIcon bookmarkIcon; }; diff --git a/examples/xml/saxbookmarks/mainwindow.cpp b/examples/xml/saxbookmarks/mainwindow.cpp index 2ce2b9a508e..0583cd82cf0 100644 --- a/examples/xml/saxbookmarks/mainwindow.cpp +++ b/examples/xml/saxbookmarks/mainwindow.cpp @@ -62,17 +62,40 @@ MainWindow::MainWindow() treeWidget = new QTreeWidget; treeWidget->header()->setSectionResizeMode(QHeaderView::Stretch); treeWidget->setHeaderLabels(labels); +#if !defined(QT_NO_CONTEXTMENU) && !defined(QT_NO_CLIPBOARD) + treeWidget->setContextMenuPolicy(Qt::CustomContextMenu); + connect(treeWidget, &QWidget::customContextMenuRequested, + this, &MainWindow::onCustomContextMenuRequested); +#endif setCentralWidget(treeWidget); - createActions(); createMenus(); statusBar()->showMessage(tr("Ready")); setWindowTitle(tr("SAX Bookmarks")); - resize(480, 320); + const QSize availableSize = QApplication::desktop()->availableGeometry(this).size(); + resize(availableSize.width() / 2, availableSize.height() / 3); } +#if !defined(QT_NO_CONTEXTMENU) && !defined(QT_NO_CLIPBOARD) +void MainWindow::onCustomContextMenuRequested(const QPoint &pos) +{ + const QTreeWidgetItem *item = treeWidget->itemAt(pos); + if (!item) + return; + const QString url = item->text(1); + QMenu contextMenu; + QAction *copyAction = contextMenu.addAction(tr("Copy Link to Clipboard")); + QAction *openAction = contextMenu.addAction(tr("Open")); + QAction *action = contextMenu.exec(treeWidget->viewport()->mapToGlobal(pos)); + if (action == copyAction) + QGuiApplication::clipboard()->setText(url); + else if (action == openAction) + QDesktopServices::openUrl(QUrl(url)); +} +#endif // !QT_NO_CONTEXTMENU && !QT_NO_CLIPBOARD + void MainWindow::open() { QString fileName = @@ -93,8 +116,8 @@ void MainWindow::open() if (!file.open(QFile::ReadOnly | QFile::Text)) { QMessageBox::warning(this, tr("SAX Bookmarks"), tr("Cannot read file %1:\n%2.") - .arg(fileName) - .arg(file.errorString())); + .arg(QDir::toNativeSeparators(fileName), + file.errorString())); return; } @@ -116,8 +139,8 @@ void MainWindow::saveAs() if (!file.open(QFile::WriteOnly | QFile::Text)) { QMessageBox::warning(this, tr("SAX Bookmarks"), tr("Cannot write file %1:\n%2.") - .arg(fileName) - .arg(file.errorString())); + .arg(QDir::toNativeSeparators(fileName), + file.errorString())); return; } @@ -134,37 +157,21 @@ void MainWindow::about() "hand.")); } -void MainWindow::createActions() +void MainWindow::createMenus() { - openAct = new QAction(tr("&Open..."), this); + QMenu *fileMenu = menuBar()->addMenu(tr("&File")); + QAction *openAct = fileMenu->addAction(tr("&Open..."), this, &MainWindow::open); openAct->setShortcuts(QKeySequence::Open); - connect(openAct, SIGNAL(triggered()), this, SLOT(open())); - saveAsAct = new QAction(tr("&Save As..."), this); + QAction *saveAsAct = fileMenu->addAction(tr("&Save As..."), this, &MainWindow::saveAs); saveAsAct->setShortcuts(QKeySequence::SaveAs); - connect(saveAsAct, SIGNAL(triggered()), this, SLOT(saveAs())); - exitAct = new QAction(tr("E&xit"), this); + QAction *exitAct = fileMenu->addAction(tr("E&xit"), this, &QWidget::close); exitAct->setShortcuts(QKeySequence::Quit); - connect(exitAct, SIGNAL(triggered()), this, SLOT(close())); - - aboutAct = new QAction(tr("&About"), this); - connect(aboutAct, SIGNAL(triggered()), this, SLOT(about())); - - aboutQtAct = new QAction(tr("About &Qt"), this); - connect(aboutQtAct, SIGNAL(triggered()), qApp, SLOT(aboutQt())); -} - -void MainWindow::createMenus() -{ - fileMenu = menuBar()->addMenu(tr("&File")); - fileMenu->addAction(openAct); - fileMenu->addAction(saveAsAct); - fileMenu->addAction(exitAct); menuBar()->addSeparator(); - helpMenu = menuBar()->addMenu(tr("&Help")); - helpMenu->addAction(aboutAct); - helpMenu->addAction(aboutQtAct); + QMenu *helpMenu = menuBar()->addMenu(tr("&Help")); + helpMenu->addAction(tr("&About"), this, &MainWindow::about); + helpMenu->addAction(tr("About &Qt"), qApp, &QCoreApplication::quit); } diff --git a/examples/xml/saxbookmarks/mainwindow.h b/examples/xml/saxbookmarks/mainwindow.h index 828a0ed14e7..20a11bb2029 100644 --- a/examples/xml/saxbookmarks/mainwindow.h +++ b/examples/xml/saxbookmarks/mainwindow.h @@ -68,20 +68,13 @@ public slots: void open(); void saveAs(); void about(); - +#if !defined(QT_NO_CONTEXTMENU) && !defined(QT_NO_CLIPBOARD) + void onCustomContextMenuRequested(const QPoint &pos); +#endif private: - void createActions(); void createMenus(); QTreeWidget *treeWidget; - - QMenu *fileMenu; - QMenu *helpMenu; - QAction *openAct; - QAction *saveAsAct; - QAction *exitAct; - QAction *aboutAct; - QAction *aboutQtAct; }; #endif diff --git a/examples/xml/saxbookmarks/xbelgenerator.cpp b/examples/xml/saxbookmarks/xbelgenerator.cpp index 30ce1428e6c..ee6f113f9c7 100644 --- a/examples/xml/saxbookmarks/xbelgenerator.cpp +++ b/examples/xml/saxbookmarks/xbelgenerator.cpp @@ -52,7 +52,7 @@ #include "xbelgenerator.h" -XbelGenerator::XbelGenerator(QTreeWidget *treeWidget) +XbelGenerator::XbelGenerator(const QTreeWidget *treeWidget) : treeWidget(treeWidget) { } @@ -81,25 +81,25 @@ QString XbelGenerator::indent(int depth) QString XbelGenerator::escapedText(const QString &str) { QString result = str; - result.replace("&", "&"); - result.replace("<", "<"); - result.replace(">", ">"); + result.replace('&', "&"); + result.replace('<', "<"); + result.replace('>', ">"); return result; } QString XbelGenerator::escapedAttribute(const QString &str) { QString result = escapedText(str); - result.replace("\"", """); + result.replace(QLatin1Char('"'), """); result.prepend(QLatin1Char('"')); result.append(QLatin1Char('"')); return result; } -void XbelGenerator::generateItem(QTreeWidgetItem *item, int depth) +void XbelGenerator::generateItem(const QTreeWidgetItem *item, int depth) { QString tagName = item->data(0, Qt::UserRole).toString(); - if (tagName == "folder") { + if (tagName == QLatin1String("folder")) { bool folded = !treeWidget->isItemExpanded(item); out << indent(depth) << "<folder folded=\"" << (folded ? "yes" : "no") << "\">\n" @@ -110,7 +110,7 @@ void XbelGenerator::generateItem(QTreeWidgetItem *item, int depth) generateItem(item->child(i), depth + 1); out << indent(depth) << "</folder>\n"; - } else if (tagName == "bookmark") { + } else if (tagName == QLatin1String("bookmark")) { out << indent(depth) << "<bookmark"; if (!item->text(1).isEmpty()) out << " href=" << escapedAttribute(item->text(1)); @@ -118,7 +118,7 @@ void XbelGenerator::generateItem(QTreeWidgetItem *item, int depth) << indent(depth + 1) << "<title>" << escapedText(item->text(0)) << "</title>\n" << indent(depth) << "</bookmark>\n"; - } else if (tagName == "separator") { + } else if (tagName == QLatin1String("separator")) { out << indent(depth) << "<separator/>\n"; } } diff --git a/examples/xml/saxbookmarks/xbelgenerator.h b/examples/xml/saxbookmarks/xbelgenerator.h index 44069599e2f..abfabfd75c0 100644 --- a/examples/xml/saxbookmarks/xbelgenerator.h +++ b/examples/xml/saxbookmarks/xbelgenerator.h @@ -61,7 +61,7 @@ QT_END_NAMESPACE class XbelGenerator { public: - XbelGenerator(QTreeWidget *treeWidget); + explicit XbelGenerator(const QTreeWidget *treeWidget); bool write(QIODevice *device); @@ -69,9 +69,9 @@ private: static QString indent(int indentLevel); static QString escapedText(const QString &str); static QString escapedAttribute(const QString &str); - void generateItem(QTreeWidgetItem *item, int depth); + void generateItem(const QTreeWidgetItem *item, int depth); - QTreeWidget *treeWidget; + const QTreeWidget *treeWidget; QTextStream out; }; diff --git a/examples/xml/saxbookmarks/xbelhandler.cpp b/examples/xml/saxbookmarks/xbelhandler.cpp index 03b16c81f1f..7e2a9db3c21 100644 --- a/examples/xml/saxbookmarks/xbelhandler.cpp +++ b/examples/xml/saxbookmarks/xbelhandler.cpp @@ -52,6 +52,10 @@ #include "xbelhandler.h" +static inline QString versionAttribute() { return QStringLiteral("version"); } +static inline QString hrefAttribute() { return QStringLiteral("href"); } +static inline QString foldedAttribute() { return QStringLiteral("folded"); } + XbelHandler::XbelHandler(QTreeWidget *treeWidget) : treeWidget(treeWidget) { @@ -72,32 +76,32 @@ bool XbelHandler::startElement(const QString & /* namespaceURI */, const QString &qName, const QXmlAttributes &attributes) { - if (!metXbelTag && qName != "xbel") { + if (!metXbelTag && qName != QLatin1String("xbel")) { errorStr = QObject::tr("The file is not an XBEL file."); return false; } - if (qName == "xbel") { - QString version = attributes.value("version"); - if (!version.isEmpty() && version != "1.0") { + if (qName == QLatin1String("xbel")) { + QString version = attributes.value(versionAttribute()); + if (!version.isEmpty() && version != QLatin1String("1.0")) { errorStr = QObject::tr("The file is not an XBEL version 1.0 file."); return false; } metXbelTag = true; - } else if (qName == "folder") { + } else if (qName == QLatin1String("folder")) { item = createChildItem(qName); item->setFlags(item->flags() | Qt::ItemIsEditable); item->setIcon(0, folderIcon); item->setText(0, QObject::tr("Folder")); - bool folded = (attributes.value("folded") != "no"); + bool folded = (attributes.value(foldedAttribute()) != QLatin1String("no")); treeWidget->setItemExpanded(item, !folded); - } else if (qName == "bookmark") { + } else if (qName == QLatin1String("bookmark")) { item = createChildItem(qName); item->setFlags(item->flags() | Qt::ItemIsEditable); item->setIcon(0, bookmarkIcon); item->setText(0, QObject::tr("Unknown title")); - item->setText(1, attributes.value("href")); - } else if (qName == "separator") { + item->setText(1, attributes.value(hrefAttribute())); + } else if (qName == QLatin1String("separator")) { item = createChildItem(qName); item->setFlags(item->flags() & ~Qt::ItemIsSelectable); item->setText(0, QString(30, 0xB7)); @@ -111,11 +115,11 @@ bool XbelHandler::endElement(const QString & /* namespaceURI */, const QString & /* localName */, const QString &qName) { - if (qName == "title") { + if (qName == QLatin1String("title")) { if (item) item->setText(0, currentText); - } else if (qName == "folder" || qName == "bookmark" - || qName == "separator") { + } else if (qName == QLatin1String("folder") || qName == QLatin1String("bookmark") + || qName == QLatin1String("separator")) { item = item->parent(); } return true; diff --git a/examples/xml/streambookmarks/doc/src/qxmlstreambookmarks.qdoc b/examples/xml/streambookmarks/doc/src/qxmlstreambookmarks.qdoc index 0720e3eadd7..ad093c2098f 100644 --- a/examples/xml/streambookmarks/doc/src/qxmlstreambookmarks.qdoc +++ b/examples/xml/streambookmarks/doc/src/qxmlstreambookmarks.qdoc @@ -167,7 +167,7 @@ add them to the \c fileMenu and \c helpMenu. The connections are as shown below: - \snippet streambookmarks/mainwindow.cpp 4 + \snippet streambookmarks/mainwindow.cpp 5 The \c createMenus() function creates the \c fileMenu and \c helpMenu and adds the QAction objects to them in order to create the menu shown diff --git a/examples/xml/streambookmarks/mainwindow.cpp b/examples/xml/streambookmarks/mainwindow.cpp index 7c0fd8720df..c9a18fa3c47 100644 --- a/examples/xml/streambookmarks/mainwindow.cpp +++ b/examples/xml/streambookmarks/mainwindow.cpp @@ -63,18 +63,41 @@ MainWindow::MainWindow() treeWidget = new QTreeWidget; treeWidget->header()->setSectionResizeMode(QHeaderView::Stretch); treeWidget->setHeaderLabels(labels); +#if !defined(QT_NO_CONTEXTMENU) && !defined(QT_NO_CLIPBOARD) + treeWidget->setContextMenuPolicy(Qt::CustomContextMenu); + connect(treeWidget, &QWidget::customContextMenuRequested, + this, &MainWindow::onCustomContextMenuRequested); +#endif setCentralWidget(treeWidget); - createActions(); createMenus(); statusBar()->showMessage(tr("Ready")); setWindowTitle(tr("QXmlStream Bookmarks")); - resize(480, 320); + const QSize availableSize = QApplication::desktop()->availableGeometry(this).size(); + resize(availableSize.width() / 2, availableSize.height() / 3); } //! [0] +#if !defined(QT_NO_CONTEXTMENU) && !defined(QT_NO_CLIPBOARD) +void MainWindow::onCustomContextMenuRequested(const QPoint &pos) +{ + const QTreeWidgetItem *item = treeWidget->itemAt(pos); + if (!item) + return; + const QString url = item->text(1); + QMenu contextMenu; + QAction *copyAction = contextMenu.addAction(tr("Copy Link to Clipboard")); + QAction *openAction = contextMenu.addAction(tr("Open")); + QAction *action = contextMenu.exec(treeWidget->viewport()->mapToGlobal(pos)); + if (action == copyAction) + QGuiApplication::clipboard()->setText(url); + else if (action == openAction) + QDesktopServices::openUrl(QUrl(url)); +} +#endif // !QT_NO_CONTEXTMENU && !QT_NO_CLIPBOARD + //! [1] void MainWindow::open() { @@ -92,8 +115,8 @@ void MainWindow::open() if (!file.open(QFile::ReadOnly | QFile::Text)) { QMessageBox::warning(this, tr("QXmlStream Bookmarks"), tr("Cannot read file %1:\n%2.") - .arg(fileName) - .arg(file.errorString())); + .arg(QDir::toNativeSeparators(fileName), + file.errorString())); return; } @@ -101,8 +124,8 @@ void MainWindow::open() if (!reader.read(&file)) { QMessageBox::warning(this, tr("QXmlStream Bookmarks"), tr("Parse error in file %1:\n\n%2") - .arg(fileName) - .arg(reader.errorString())); + .arg(QDir::toNativeSeparators(fileName), + reader.errorString())); } else { statusBar()->showMessage(tr("File loaded"), 2000); } @@ -124,8 +147,8 @@ void MainWindow::saveAs() if (!file.open(QFile::WriteOnly | QFile::Text)) { QMessageBox::warning(this, tr("QXmlStream Bookmarks"), tr("Cannot write file %1:\n%2.") - .arg(fileName) - .arg(file.errorString())); + .arg(QDir::toNativeSeparators(fileName), + file.errorString())); return; } @@ -144,41 +167,23 @@ void MainWindow::about() } //! [3] -//! [4] -void MainWindow::createActions() +//! [5] +void MainWindow::createMenus() { - openAct = new QAction(tr("&Open..."), this); + QMenu *fileMenu = menuBar()->addMenu(tr("&File")); + QAction *openAct = fileMenu->addAction(tr("&Open..."), this, &MainWindow::open); openAct->setShortcuts(QKeySequence::Open); - connect(openAct, SIGNAL(triggered()), this, SLOT(open())); - saveAsAct = new QAction(tr("&Save As..."), this); + QAction *saveAsAct = fileMenu->addAction(tr("&Save As..."), this, &MainWindow::saveAs); saveAsAct->setShortcuts(QKeySequence::SaveAs); - connect(saveAsAct, SIGNAL(triggered()), this, SLOT(saveAs())); - exitAct = new QAction(tr("E&xit"), this); + QAction *exitAct = fileMenu->addAction(tr("E&xit"), this, &QWidget::close); exitAct->setShortcuts(QKeySequence::Quit); - connect(exitAct, SIGNAL(triggered()), this, SLOT(close())); - - aboutAct = new QAction(tr("&About"), this); - connect(aboutAct, SIGNAL(triggered()), this, SLOT(about())); - - aboutQtAct = new QAction(tr("About &Qt"), this); - connect(aboutQtAct, SIGNAL(triggered()), qApp, SLOT(aboutQt())); -} -//! [4] - -//! [5] -void MainWindow::createMenus() -{ - fileMenu = menuBar()->addMenu(tr("&File")); - fileMenu->addAction(openAct); - fileMenu->addAction(saveAsAct); - fileMenu->addAction(exitAct); menuBar()->addSeparator(); - helpMenu = menuBar()->addMenu(tr("&Help")); - helpMenu->addAction(aboutAct); - helpMenu->addAction(aboutQtAct); + QMenu *helpMenu = menuBar()->addMenu(tr("&Help")); + helpMenu->addAction(tr("&About"), this, &MainWindow::about); + helpMenu->addAction(tr("About &Qt"), qApp, &QCoreApplication::quit); } //! [5] diff --git a/examples/xml/streambookmarks/mainwindow.h b/examples/xml/streambookmarks/mainwindow.h index 2b6feeb26f4..fbdc1e0c62e 100644 --- a/examples/xml/streambookmarks/mainwindow.h +++ b/examples/xml/streambookmarks/mainwindow.h @@ -69,20 +69,13 @@ public slots: void open(); void saveAs(); void about(); - +#if !defined(QT_NO_CONTEXTMENU) && !defined(QT_NO_CLIPBOARD) + void onCustomContextMenuRequested(const QPoint &pos); +#endif private: - void createActions(); void createMenus(); QTreeWidget *treeWidget; - - QMenu *fileMenu; - QMenu *helpMenu; - QAction *openAct; - QAction *saveAsAct; - QAction *exitAct; - QAction *aboutAct; - QAction *aboutQtAct; }; //! [0] diff --git a/examples/xml/streambookmarks/xbelreader.cpp b/examples/xml/streambookmarks/xbelreader.cpp index 53d6b94ba0a..099985d91eb 100644 --- a/examples/xml/streambookmarks/xbelreader.cpp +++ b/examples/xml/streambookmarks/xbelreader.cpp @@ -72,10 +72,12 @@ bool XbelReader::read(QIODevice *device) xml.setDevice(device); if (xml.readNextStartElement()) { - if (xml.name() == "xbel" && xml.attributes().value("version") == "1.0") + if (xml.name() == QLatin1String("xbel") + && xml.attributes().value(versionAttribute()) == QLatin1String("1.0")) { readXBEL(); - else + } else { xml.raiseError(QObject::tr("The file is not an XBEL version 1.0 file.")); + } } return !xml.error(); @@ -95,14 +97,14 @@ QString XbelReader::errorString() const //! [3] void XbelReader::readXBEL() { - Q_ASSERT(xml.isStartElement() && xml.name() == "xbel"); + Q_ASSERT(xml.isStartElement() && xml.name() == QLatin1String("xbel")); while (xml.readNextStartElement()) { - if (xml.name() == "folder") + if (xml.name() == QLatin1String("folder")) readFolder(0); - else if (xml.name() == "bookmark") + else if (xml.name() == QLatin1String("bookmark")) readBookmark(0); - else if (xml.name() == "separator") + else if (xml.name() == QLatin1String("separator")) readSeparator(0); else xml.skipCurrentElement(); @@ -113,7 +115,7 @@ void XbelReader::readXBEL() //! [4] void XbelReader::readTitle(QTreeWidgetItem *item) { - Q_ASSERT(xml.isStartElement() && xml.name() == "title"); + Q_ASSERT(xml.isStartElement() && xml.name() == QLatin1String("title")); QString title = xml.readElementText(); item->setText(0, title); @@ -123,7 +125,7 @@ void XbelReader::readTitle(QTreeWidgetItem *item) //! [5] void XbelReader::readSeparator(QTreeWidgetItem *item) { - Q_ASSERT(xml.isStartElement() && xml.name() == "separator"); + Q_ASSERT(xml.isStartElement() && xml.name() == QLatin1String("separator")); QTreeWidgetItem *separator = createChildItem(item); separator->setFlags(item->flags() & ~Qt::ItemIsSelectable); @@ -134,20 +136,20 @@ void XbelReader::readSeparator(QTreeWidgetItem *item) void XbelReader::readFolder(QTreeWidgetItem *item) { - Q_ASSERT(xml.isStartElement() && xml.name() == "folder"); + Q_ASSERT(xml.isStartElement() && xml.name() == QLatin1String("folder")); QTreeWidgetItem *folder = createChildItem(item); - bool folded = (xml.attributes().value("folded") != "no"); + bool folded = (xml.attributes().value(foldedAttribute()) != QLatin1String("no")); treeWidget->setItemExpanded(folder, !folded); while (xml.readNextStartElement()) { - if (xml.name() == "title") + if (xml.name() == QLatin1String("title")) readTitle(folder); - else if (xml.name() == "folder") + else if (xml.name() == QLatin1String("folder")) readFolder(folder); - else if (xml.name() == "bookmark") + else if (xml.name() == QLatin1String("bookmark")) readBookmark(folder); - else if (xml.name() == "separator") + else if (xml.name() == QLatin1String("separator")) readSeparator(folder); else xml.skipCurrentElement(); @@ -156,16 +158,16 @@ void XbelReader::readFolder(QTreeWidgetItem *item) void XbelReader::readBookmark(QTreeWidgetItem *item) { - Q_ASSERT(xml.isStartElement() && xml.name() == "bookmark"); + Q_ASSERT(xml.isStartElement() && xml.name() == QLatin1String("bookmark")); QTreeWidgetItem *bookmark = createChildItem(item); bookmark->setFlags(bookmark->flags() | Qt::ItemIsEditable); bookmark->setIcon(0, bookmarkIcon); bookmark->setText(0, QObject::tr("Unknown title")); - bookmark->setText(1, xml.attributes().value("href").toString()); + bookmark->setText(1, xml.attributes().value(hrefAttribute()).toString()); while (xml.readNextStartElement()) { - if (xml.name() == "title") + if (xml.name() == QLatin1String("title")) readTitle(bookmark); else xml.skipCurrentElement(); diff --git a/examples/xml/streambookmarks/xbelreader.h b/examples/xml/streambookmarks/xbelreader.h index 3175441ddd2..fd486a430f9 100644 --- a/examples/xml/streambookmarks/xbelreader.h +++ b/examples/xml/streambookmarks/xbelreader.h @@ -71,6 +71,10 @@ public: QString errorString() const; + static inline QString versionAttribute() { return QStringLiteral("version"); } + static inline QString hrefAttribute() { return QStringLiteral("href"); } + static inline QString foldedAttribute() { return QStringLiteral("folded"); } + private: //! [2] void readXBEL(); diff --git a/examples/xml/streambookmarks/xbelwriter.cpp b/examples/xml/streambookmarks/xbelwriter.cpp index fdf2e1095ef..2959680678d 100644 --- a/examples/xml/streambookmarks/xbelwriter.cpp +++ b/examples/xml/streambookmarks/xbelwriter.cpp @@ -51,9 +51,14 @@ #include <QtWidgets> #include "xbelwriter.h" +#include "xbelreader.h" + +static inline QString yesValue() { return QStringLiteral("yes"); } +static inline QString noValue() { return QStringLiteral("no"); } +static inline QString titleElement() { return QStringLiteral("title"); } //! [0] -XbelWriter::XbelWriter(QTreeWidget *treeWidget) +XbelWriter::XbelWriter(const QTreeWidget *treeWidget) : treeWidget(treeWidget) { xml.setAutoFormatting(true); @@ -66,9 +71,9 @@ bool XbelWriter::writeFile(QIODevice *device) xml.setDevice(device); xml.writeStartDocument(); - xml.writeDTD("<!DOCTYPE xbel>"); - xml.writeStartElement("xbel"); - xml.writeAttribute("version", "1.0"); + xml.writeDTD(QStringLiteral("<!DOCTYPE xbel>")); + xml.writeStartElement(QStringLiteral("xbel")); + xml.writeAttribute(XbelReader::versionAttribute(), QStringLiteral("1.0")); for (int i = 0; i < treeWidget->topLevelItemCount(); ++i) writeItem(treeWidget->topLevelItem(i)); @@ -78,24 +83,24 @@ bool XbelWriter::writeFile(QIODevice *device) //! [1] //! [2] -void XbelWriter::writeItem(QTreeWidgetItem *item) +void XbelWriter::writeItem(const QTreeWidgetItem *item) { QString tagName = item->data(0, Qt::UserRole).toString(); - if (tagName == "folder") { + if (tagName == QLatin1String("folder")) { bool folded = !treeWidget->isItemExpanded(item); xml.writeStartElement(tagName); - xml.writeAttribute("folded", folded ? "yes" : "no"); - xml.writeTextElement("title", item->text(0)); + xml.writeAttribute(XbelReader::foldedAttribute(), folded ? yesValue() : noValue()); + xml.writeTextElement(titleElement(), item->text(0)); for (int i = 0; i < item->childCount(); ++i) writeItem(item->child(i)); xml.writeEndElement(); - } else if (tagName == "bookmark") { + } else if (tagName == QLatin1String("bookmark")) { xml.writeStartElement(tagName); if (!item->text(1).isEmpty()) - xml.writeAttribute("href", item->text(1)); - xml.writeTextElement("title", item->text(0)); + xml.writeAttribute(XbelReader::hrefAttribute(), item->text(1)); + xml.writeTextElement(titleElement(), item->text(0)); xml.writeEndElement(); - } else if (tagName == "separator") { + } else if (tagName == QLatin1String("separator")) { xml.writeEmptyElement(tagName); } } diff --git a/examples/xml/streambookmarks/xbelwriter.h b/examples/xml/streambookmarks/xbelwriter.h index b15bf60e313..465d8f0dc42 100644 --- a/examples/xml/streambookmarks/xbelwriter.h +++ b/examples/xml/streambookmarks/xbelwriter.h @@ -62,13 +62,13 @@ QT_END_NAMESPACE class XbelWriter { public: - XbelWriter(QTreeWidget *treeWidget); + explicit XbelWriter(const QTreeWidget *treeWidget); bool writeFile(QIODevice *device); private: - void writeItem(QTreeWidgetItem *item); + void writeItem(const QTreeWidgetItem *item); QXmlStreamWriter xml; - QTreeWidget *treeWidget; + const QTreeWidget *treeWidget; }; //! [0] diff --git a/mkspecs/common/gcc-base.conf b/mkspecs/common/gcc-base.conf index 9ddebae506b..ca5697dd90b 100644 --- a/mkspecs/common/gcc-base.conf +++ b/mkspecs/common/gcc-base.conf @@ -97,6 +97,8 @@ QMAKE_CFLAGS_AVX512BW += -mavx512bw QMAKE_CFLAGS_AVX512VL += -mavx512vl QMAKE_CFLAGS_AVX512IFMA += -mavx512ifma QMAKE_CFLAGS_AVX512VBMI += -mavx512vbmi +QMAKE_CFLAGS_AESNI += -maes +QMAKE_CFLAGS_SHANI += -msha QMAKE_CFLAGS_NEON += -mfpu=neon QMAKE_CFLAGS_MIPS_DSP += -mdsp QMAKE_CFLAGS_MIPS_DSPR2 += -mdspr2 diff --git a/mkspecs/common/msvc-desktop.conf b/mkspecs/common/msvc-desktop.conf index 02b8441547b..0ca27fe4ec8 100644 --- a/mkspecs/common/msvc-desktop.conf +++ b/mkspecs/common/msvc-desktop.conf @@ -44,6 +44,8 @@ QMAKE_CFLAGS_SSE3 = $$QMAKE_CFLAGS_SSE2 QMAKE_CFLAGS_SSSE3 = $$QMAKE_CFLAGS_SSE2 QMAKE_CFLAGS_SSE4_1 = $$QMAKE_CFLAGS_SSE2 QMAKE_CFLAGS_SSE4_2 = $$QMAKE_CFLAGS_SSE2 +QMAKE_CFLAGS_AESNI = $$QMAKE_CFLAGS_SSE2 +QMAKE_CFLAGS_SHANI = $$QMAKE_CFLAGS_SSE2 QMAKE_CXX = $$QMAKE_CC QMAKE_CXXFLAGS = $$QMAKE_CFLAGS diff --git a/mkspecs/common/qcc-base.conf b/mkspecs/common/qcc-base.conf index 4ef03d8587b..77e0476777c 100644 --- a/mkspecs/common/qcc-base.conf +++ b/mkspecs/common/qcc-base.conf @@ -33,6 +33,8 @@ QMAKE_CFLAGS_SSE4_1 += -msse4.1 QMAKE_CFLAGS_SSE4_2 += -msse4.2 QMAKE_CFLAGS_AVX += -mavx QMAKE_CFLAGS_AVX2 += -mavx2 +QMAKE_CFLAGS_AESNI += -maes +QMAKE_CFLAGS_SHANI += -msha QMAKE_CXXFLAGS += $$QMAKE_CFLAGS -lang-c++ QMAKE_CXXFLAGS_DEPS += $$QMAKE_CFLAGS_DEPS diff --git a/mkspecs/common/winrt_winphone/qmake.conf b/mkspecs/common/winrt_winphone/qmake.conf index 818264c46b9..1b9bf4d20f1 100644 --- a/mkspecs/common/winrt_winphone/qmake.conf +++ b/mkspecs/common/winrt_winphone/qmake.conf @@ -34,6 +34,8 @@ QMAKE_CFLAGS_SSE4_1 = -arch:SSE2 QMAKE_CFLAGS_SSE4_2 = -arch:SSE2 QMAKE_CFLAGS_AVX = -arch:AVX QMAKE_CFLAGS_AVX2 = -arch:AVX +QMAKE_CFLAGS_AESNI = -arch:SSE2 +QMAKE_CFLAGS_SHANI = -arch:SSE2 QMAKE_CXX = $$QMAKE_CC QMAKE_CXXFLAGS = $$QMAKE_CFLAGS diff --git a/mkspecs/features/simd.prf b/mkspecs/features/simd.prf index 953fc52c65a..aca9ae62430 100644 --- a/mkspecs/features/simd.prf +++ b/mkspecs/features/simd.prf @@ -93,6 +93,8 @@ addSimdCompiler(sse3) addSimdCompiler(ssse3) addSimdCompiler(sse4_1) addSimdCompiler(sse4_2) +addSimdCompiler(aesni) +addSimdCompiler(shani) addSimdCompiler(avx) addSimdCompiler(avx2) addSimdCompiler(avx512f) diff --git a/mkspecs/linux-icc-k1om/qmake.conf b/mkspecs/linux-icc-k1om/qmake.conf new file mode 100644 index 00000000000..86cd921e892 --- /dev/null +++ b/mkspecs/linux-icc-k1om/qmake.conf @@ -0,0 +1,21 @@ +# +# qmake configuration for linux-icc-k1om +# +# Written for Intel C++ Compiler +# +# This mkspec is intended for use on x100 Co-processors +# + +# Use the linux-icc as the base for our configuration +include(../linux-icc/qmake.conf) + +QMAKE_CC = icc -mmic +QMAKE_CFLAGS_WARN_ON += -wd10364,1786 + +QMAKE_CXX = icpc -mmic +QMAKE_CXXFLAGS_WARN_ON = $$QMAKE_CFLAGS_WARN_ON + +QMAKE_LFLAGS += -mmic +QMAKE_LFLAGS_APP = +QMAKE_AR = xiar crs + diff --git a/mkspecs/linux-icc-k1om/qplatformdefs.h b/mkspecs/linux-icc-k1om/qplatformdefs.h new file mode 100644 index 00000000000..33a3bf0e1c6 --- /dev/null +++ b/mkspecs/linux-icc-k1om/qplatformdefs.h @@ -0,0 +1,40 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the qmake spec of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "../linux-icc/qplatformdefs.h" diff --git a/mkspecs/linux-icc/qmake.conf b/mkspecs/linux-icc/qmake.conf index 196e33432c9..801a8acf6a5 100644 --- a/mkspecs/linux-icc/qmake.conf +++ b/mkspecs/linux-icc/qmake.conf @@ -42,6 +42,8 @@ QMAKE_CFLAGS_AVX512PF += -xMIC-AVX512 QMAKE_CFLAGS_AVX512DQ += -xCORE-AVX512 QMAKE_CFLAGS_AVX512BW += -xCORE-AVX512 QMAKE_CFLAGS_AVX512VL += -xCORE-AVX512 +QMAKE_CFLAGS_AESNI += -maes +QMAKE_CFLAGS_SHANI += -msha QMAKE_CXX = icpc QMAKE_CXXFLAGS = $$QMAKE_CFLAGS diff --git a/mkspecs/macx-icc/qmake.conf b/mkspecs/macx-icc/qmake.conf index bb454377eff..bb9a495f6f9 100644 --- a/mkspecs/macx-icc/qmake.conf +++ b/mkspecs/macx-icc/qmake.conf @@ -40,6 +40,8 @@ QMAKE_CFLAGS_AVX512PF += -xMIC-AVX512 QMAKE_CFLAGS_AVX512DQ += -xCORE-AVX512 QMAKE_CFLAGS_AVX512BW += -xCORE-AVX512 QMAKE_CFLAGS_AVX512VL += -xCORE-AVX512 +QMAKE_CFLAGS_AESNI += -maes +QMAKE_CFLAGS_SHANI += -msha QMAKE_CXX = icpc QMAKE_CXXFLAGS = $$QMAKE_CFLAGS diff --git a/mkspecs/win32-g++/qmake.conf b/mkspecs/win32-g++/qmake.conf index d6b08f53238..5f98bd1d036 100644 --- a/mkspecs/win32-g++/qmake.conf +++ b/mkspecs/win32-g++/qmake.conf @@ -28,6 +28,8 @@ QMAKE_YACCFLAGS = -d QMAKE_CFLAGS += -fno-keep-inline-dllexport QMAKE_CFLAGS_WARN_ON += -Wextra QMAKE_CFLAGS_SSE2 += -mstackrealign +QMAKE_CFLAGS_AESNI = -maes +QMAKE_CFLAGS_SHANI = -msha QMAKE_CXX = $${CROSS_COMPILE}g++ QMAKE_CXXFLAGS_THREAD = $$QMAKE_CFLAGS_THREAD diff --git a/mkspecs/win32-icc-k1om/qmake.conf b/mkspecs/win32-icc-k1om/qmake.conf new file mode 100644 index 00000000000..498b47cf2d1 --- /dev/null +++ b/mkspecs/win32-icc-k1om/qmake.conf @@ -0,0 +1,15 @@ +# +# qmake configuration for win32-icc-k1om +# +# Written for Intel C++ +# +# Use the win32-icc as the base for our configuration +include(../win32-icc/qmake.conf) + +# rework k1om + +QMAKE_CC = icl /Qmic +QMAKE_CXX = icl /Qmic +QMAKE_LINK = xild +QMAKE_LINK_SHLIB = xild +QMAKE_LFLAGS = -limf -lsvml -lirng -lintlc diff --git a/mkspecs/win32-icc-k1om/qplatformdefs.h b/mkspecs/win32-icc-k1om/qplatformdefs.h new file mode 100644 index 00000000000..8a3afa7630d --- /dev/null +++ b/mkspecs/win32-icc-k1om/qplatformdefs.h @@ -0,0 +1,40 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the qmake spec of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "../win32-msvc/qplatformdefs.h" diff --git a/mkspecs/win32-icc/qmake.conf b/mkspecs/win32-icc/qmake.conf index 6e2589b4c49..9a86407043b 100644 --- a/mkspecs/win32-icc/qmake.conf +++ b/mkspecs/win32-icc/qmake.conf @@ -33,6 +33,8 @@ QMAKE_CFLAGS_AVX512PF += -QxMIC-AVX512 QMAKE_CFLAGS_AVX512DQ += -QxCORE-AVX512 QMAKE_CFLAGS_AVX512BW += -QxCORE-AVX512 QMAKE_CFLAGS_AVX512VL += -QxCORE-AVX512 +QMAKE_CFLAGS_AESNI = -QxSSE2 +QMAKE_CFLAGS_SHANI = -QxSSE4.2 QMAKE_CXX = $$QMAKE_CC QMAKE_CXXFLAGS = $$QMAKE_CFLAGS /Zc:forScope diff --git a/qmake/Makefile.unix b/qmake/Makefile.unix index ed1668d54e8..4df0ff281fa 100644 --- a/qmake/Makefile.unix +++ b/qmake/Makefile.unix @@ -2,107 +2,142 @@ QMKSRC = $(SOURCE_PATH)/qmake QMKLIBSRC = $(QMKSRC)/library QMKGENSRC = $(QMKSRC)/generators -#qmake code -OBJS=project.o option.o property.o main.o ioutils.o proitems.o \ - qmakevfs.o qmakeglobals.o qmakeparser.o qmakeevaluator.o qmakebuiltins.o \ - makefile.o unixmake2.o unixmake.o \ - mingw_make.o winmakefile.o projectgenerator.o \ - meta.o makefiledeps.o metamakefile.o xmloutput.o pbuilder_pbx.o \ - msvc_vcproj.o msvc_vcxproj.o msvc_nmake.o msvc_objectmodel.o msbuild_objectmodel.o - -#qt code -QOBJS=qtextcodec.o qutfcodec.o qstring.o qstring_compat.o qstringbuilder.o qtextstream.o qiodevice.o \ - qringbuffer.o qdebug.o qmalloc.o qglobal.o \ - qarraydata.o qbytearray.o qbytearraymatcher.o qdatastream.o qbuffer.o qlist.o qfiledevice.o qfile.o \ - qfilesystementry.o qfilesystemengine.o qfsfileengine.o qfsfileengine_iterator.o qregexp.o \ - qbitarray.o qdir.o qdiriterator.o quuid.o qhash.o qfileinfo.o qdatetime.o qstringlist.o \ - qabstractfileengine.o qtemporaryfile.o qmap.o qmetatype.o qsettings.o qsystemerror.o \ - qvariant.o qvsnprintf.o qlocale.o qlocale_tools.o qlinkedlist.o qnumeric.o \ - qcryptographichash.o qxmlstream.o qxmlutils.o qlogging.o qoperatingsystemversion.o \ - qjson.o qjsondocument.o qjsonparser.o qjsonarray.o qjsonobject.o qjsonvalue.o \ - $(QTOBJS) $(QTOBJS2) - - -#all sources, used for the depend target +#qmake code (please keep in order matching DEPEND_SRC) +OBJS = \ + main.o meta.o option.o project.o property.o \ + ioutils.o proitems.o qmakebuiltins.o qmakeevaluator.o \ + qmakeglobals.o qmakeparser.o qmakevfs.o \ + pbuilder_pbx.o \ + makefile.o makefiledeps.o metamakefile.o projectgenerator.o \ + unixmake2.o unixmake.o \ + mingw_make.o msbuild_objectmodel.o \ + msvc_nmake.o msvc_objectmodel.o msvc_vcproj.o msvc_vcxproj.o \ + winmakefile.o \ + xmloutput.o + +#qt code (please keep in order matching DEPEND_SRC) +QOBJS = \ + qtextcodec.o qutfcodec.o \ + qglobal.o qlogging.o qmalloc.o qnumeric.o qoperatingsystemversion.o \ + qabstractfileengine.o qbuffer.o qdatastream.o qdebug.o \ + qdir.o qdiriterator.o \ + qfile.o qfiledevice.o qfileinfo.o qfilesystemengine.o \ + qfilesystementry.o qfsfileengine.o qfsfileengine_iterator.o \ + qiodevice.o qsettings.o qtemporaryfile.o qtextstream.o \ + qjsonarray.o qjson.o qjsondocument.o qjsonobject.o qjsonparser.o qjsonvalue.o \ + qmetatype.o qsystemerror.o qvariant.o \ + quuid.o \ + qarraydata.o qbitarray.o qbytearray.o qbytearraymatcher.o \ + qcryptographichash.o qdatetime.o qhash.o qlinkedlist.o qlist.o \ + qlocale.o qlocale_tools.o qmap.o qregexp.o qringbuffer.o \ + qstringbuilder.o qstring_compat.o qstring.o qstringlist.o qvsnprintf.o \ + qxmlstream.o qxmlutils.o \ + $(QTOBJS) $(QTOBJS2) +# QTOBJS and QTOBJS2 are populated by Makefile.unix.* as for QTSRC (see below). +# Note: qlibraryinfo.o omitted deliberately - see below. +# Note: qcore_mac_objc.o is in SOURCES (see qmake.pri) but not QOBJS. + +#all sources, used for the depend target (please keep alphabetic in each block) DEPEND_SRC = \ - $(QMKSRC)/main.cpp $(QMKSRC)/project.cpp $(QMKSRC)/option.cpp $(QMKSRC)/property.cpp \ + $(QMKSRC)/main.cpp \ $(QMKSRC)/meta.cpp \ - $(QMKLIBSRC)/ioutils.cpp $(QMKLIBSRC)/proitems.cpp $(QMKLIBSRC)/qmakeglobals.cpp \ - $(QMKLIBSRC)/qmakeparser.cpp $(QMKLIBSRC)/qmakeevaluator.cpp $(QMKLIBSRC)/qmakebuiltins.cpp \ - $(QMKGENSRC)/makefiledeps.cpp $(QMKGENSRC)/metamakefile.cpp \ - $(QMKGENSRC)/projectgenerator.cpp $(QMKGENSRC)/makefile.cpp \ - $(QMKGENSRC)/unix/unixmake.cpp $(QMKGENSRC)/unix/unixmake2.cpp \ + $(QMKSRC)/option.cpp \ + $(QMKSRC)/project.cpp \ + $(QMKSRC)/property.cpp \ + $(QMKLIBSRC)/ioutils.cpp \ + $(QMKLIBSRC)/proitems.cpp \ + $(QMKLIBSRC)/qmakebuiltins.cpp \ + $(QMKLIBSRC)/qmakeevaluator.cpp \ + $(QMKLIBSRC)/qmakeglobals.cpp \ + $(QMKLIBSRC)/qmakeparser.cpp \ + $(QMKLIBSRC)/qmakevfs.cpp \ $(QMKGENSRC)/mac/pbuilder_pbx.cpp \ - $(QMKGENSRC)/win32/registry.cpp \ + $(QMKGENSRC)/makefile.cpp \ + $(QMKGENSRC)/makefiledeps.cpp \ + $(QMKGENSRC)/metamakefile.cpp \ + $(QMKGENSRC)/projectgenerator.cpp \ + $(QMKGENSRC)/unix/unixmake2.cpp \ + $(QMKGENSRC)/unix/unixmake.cpp \ + $(QMKGENSRC)/win32/mingw_make.cpp \ + $(QMKGENSRC)/win32/msbuild_objectmodel.cpp \ + $(QMKGENSRC)/win32/msvc_nmake.cpp \ + $(QMKGENSRC)/win32/msvc_objectmodel.cpp \ + $(QMKGENSRC)/win32/msvc_vcproj.cpp \ + $(QMKGENSRC)/win32/msvc_vcxproj.cpp \ $(QMKGENSRC)/win32/winmakefile.cpp \ - $(QMKGENSRC)/win32/mingw_make.cpp $(QMKGENSRC)/win32/msvc_nmake.cpp \ - $(QMKGENSRC)/mac/xmloutput.cpp \ - $(QMKGENSRC)/win32/msvc_vcproj.cpp $(QMKGENSRC)/win32/msvc_vcxproj.cpp \ - $(QMKGENSRC)/win32/msvc_objectmodel.cpp $(QMKGENSRC)/win32/msbuild_objectmodel.cpp \ - $(SOURCE_PATH)/src/corelib/codecs/qtextcodec.cpp $(SOURCE_PATH)/src/corelib/codecs/qutfcodec.cpp \ - $(SOURCE_PATH)/src/corelib/tools/qstring.cpp $(SOURCE_PATH)/src/corelib/io/qfile.cpp \ - $(SOURCE_PATH)/src/corelib/tools/qstring_compat.cpp \ - $(SOURCE_PATH)/src/corelib/io/qfiledevice.cpp \ - $(SOURCE_PATH)/src/corelib/io/qtextstream.cpp $(SOURCE_PATH)/src/corelib/io/qiodevice.cpp \ - $(SOURCE_PATH)/src/corelib/tools/qringbuffer.cpp \ - $(SOURCE_PATH)/src/corelib/io/qdebug.cpp \ + $(QMKGENSRC)/xmloutput.cpp \ + $(SOURCE_PATH)/src/corelib/codecs/qtextcodec.cpp \ + $(SOURCE_PATH)/src/corelib/codecs/qutfcodec.cpp \ + $(SOURCE_PATH)/src/corelib/global/qglobal.cpp \ + $(SOURCE_PATH)/src/corelib/global/qlibraryinfo.cpp \ + $(SOURCE_PATH)/src/corelib/global/qlogging.cpp \ $(SOURCE_PATH)/src/corelib/global/qmalloc.cpp \ - $(SOURCE_PATH)/src/corelib/global/qglobal.cpp $(SOURCE_PATH)/src/corelib/tools/qregexp.cpp \ - $(SOURCE_PATH)/src/corelib/tools/qarraydata.cpp $(SOURCE_PATH)/src/corelib/tools/qbytearray.cpp\ - $(SOURCE_PATH)/src/corelib/tools/qbytearraymatcher.cpp \ - $(SOURCE_PATH)/src/corelib/io/qdatastream.cpp $(SOURCE_PATH)/src/corelib/io/qbuffer.cpp \ - $(SOURCE_PATH)/src/corelib/io/qfilesystementry.cpp \ - $(SOURCE_PATH)/src/corelib/io/qfilesystemengine_unix.cpp \ - $(SOURCE_PATH)/src/corelib/io/qfilesystemengine_win.cpp \ - $(SOURCE_PATH)/src/corelib/io/qfilesystemengine.cpp \ - $(SOURCE_PATH)/src/corelib/io/qfilesystemiterator_unix.cpp \ - $(SOURCE_PATH)/src/corelib/io/qfilesystemiterator_win.cpp \ - $(SOURCE_PATH)/src/corelib/io/qfsfileengine_unix.cpp \ - $(SOURCE_PATH)/src/corelib/io/qfsfileengine_win.cpp \ + $(SOURCE_PATH)/src/corelib/global/qnumeric.cpp \ + $(SOURCE_PATH)/src/corelib/global/qoperatingsystemversion.cpp \ $(SOURCE_PATH)/src/corelib/io/qabstractfileengine.cpp \ + $(SOURCE_PATH)/src/corelib/io/qbuffer.cpp \ + $(SOURCE_PATH)/src/corelib/io/qdatastream.cpp \ + $(SOURCE_PATH)/src/corelib/io/qdebug.cpp \ + $(SOURCE_PATH)/src/corelib/io/qdir.cpp \ + $(SOURCE_PATH)/src/corelib/io/qdiriterator.cpp \ + $(SOURCE_PATH)/src/corelib/io/qfile.cpp \ + $(SOURCE_PATH)/src/corelib/io/qfiledevice.cpp \ + $(SOURCE_PATH)/src/corelib/io/qfileinfo.cpp \ + $(SOURCE_PATH)/src/corelib/io/qfilesystemengine.cpp \ + $(SOURCE_PATH)/src/corelib/io/qfilesystementry.cpp \ + $(SOURCE_PATH)/src/corelib/io/qfsfileengine.cpp \ $(SOURCE_PATH)/src/corelib/io/qfsfileengine_iterator.cpp \ - $(SOURCE_PATH)/src/corelib/io/qfsfileengine.cpp $(SOURCE_PATH)/src/corelib/tools/qlist.cpp \ + $(SOURCE_PATH)/src/corelib/io/qiodevice.cpp \ + $(SOURCE_PATH)/src/corelib/io/qsettings.cpp \ + $(SOURCE_PATH)/src/corelib/io/qtemporaryfile.cpp \ + $(SOURCE_PATH)/src/corelib/io/qtextstream.cpp \ + $(SOURCE_PATH)/src/corelib/json/qjsonarray.cpp \ + $(SOURCE_PATH)/src/corelib/json/qjson.cpp \ + $(SOURCE_PATH)/src/corelib/json/qjsondocument.cpp \ + $(SOURCE_PATH)/src/corelib/json/qjsonobject.cpp \ + $(SOURCE_PATH)/src/corelib/json/qjsonparser.cpp \ + $(SOURCE_PATH)/src/corelib/json/qjsonvalue.cpp \ + $(SOURCE_PATH)/src/corelib/kernel/qcore_mac_objc.mm \ + $(SOURCE_PATH)/src/corelib/kernel/qmetatype.cpp \ + $(SOURCE_PATH)/src/corelib/kernel/qsystemerror.cpp \ + $(SOURCE_PATH)/src/corelib/kernel/qvariant.cpp \ + $(SOURCE_PATH)/src/corelib/plugin/quuid.cpp \ + $(SOURCE_PATH)/src/corelib/tools/qarraydata.cpp \ $(SOURCE_PATH)/src/corelib/tools/qbitarray.cpp \ - $(SOURCE_PATH)/src/corelib/io/qdiriterator.cpp \ - $(SOURCE_PATH)/src/corelib/io/qdir.cpp $(SOURCE_PATH)/src/corelib/plugin/quuid.cpp \ - $(SOURCE_PATH)/src/corelib/io/qfileinfo.cpp $(SOURCE_PATH)/src/corelib/tools/qdatetime.cpp \ - $(SOURCE_PATH)/src/corelib/tools/qstringlist.cpp $(SOURCE_PATH)/src/corelib/tools/qmap.cpp \ - $(SOURCE_PATH)/src/corelib/tools/qstringbuilder.cpp \ + $(SOURCE_PATH)/src/corelib/tools/qbytearray.cpp\ + $(SOURCE_PATH)/src/corelib/tools/qbytearraymatcher.cpp \ + $(SOURCE_PATH)/src/corelib/tools/qcryptographichash.cpp \ + $(SOURCE_PATH)/src/corelib/tools/qdatetime.cpp \ + $(SOURCE_PATH)/src/corelib/tools/qhash.cpp \ + $(SOURCE_PATH)/src/corelib/tools/qlinkedlist.cpp \ + $(SOURCE_PATH)/src/corelib/tools/qlist.cpp \ $(SOURCE_PATH)/src/corelib/tools/qlocale.cpp \ $(SOURCE_PATH)/src/corelib/tools/qlocale_tools.cpp \ - $(SOURCE_PATH)/src/corelib/tools/qlocale_unix.cpp \ - $(SOURCE_PATH)/src/corelib/tools/qlocale_win.cpp \ - $(SOURCE_PATH)/src/corelib/tools/qlinkedlist.cpp \ - $(SOURCE_PATH)/src/corelib/tools/qhash.cpp $(SOURCE_PATH)/src/corelib/kernel/qcore_mac.cpp \ - $(SOURCE_PATH)/src/corelib/kernel/qcore_mac_objc.mm \ - $(SOURCE_PATH)/src/corelib/kernel/qcore_foundation.mm \ - $(SOURCE_PATH)/src/corelib/io/qtemporaryfile.cpp $(SOURCE_PATH)/src/corelib/kernel/qmetatype.cpp \ - $(SOURCE_PATH)/src/corelib/io/qsettings.cpp $(SOURCE_PATH)/src/corelib/kernel/qvariant.cpp \ - $(SOURCE_PATH)/src/corelib/global/qlibraryinfo.cpp $(SOURCE_PATH)/src/corelib/tools/qcryptographichash.cpp \ - $(SOURCE_PATH)/src/corelib/tools/qvsnprintf.cpp $(SOURCE_PATH)/src/corelib/global/qnumeric.cpp \ + $(SOURCE_PATH)/src/corelib/tools/qmap.cpp \ + $(SOURCE_PATH)/src/corelib/tools/qregexp.cpp \ + $(SOURCE_PATH)/src/corelib/tools/qringbuffer.cpp \ + $(SOURCE_PATH)/src/corelib/tools/qstringbuilder.cpp \ + $(SOURCE_PATH)/src/corelib/tools/qstring_compat.cpp \ + $(SOURCE_PATH)/src/corelib/tools/qstring.cpp \ + $(SOURCE_PATH)/src/corelib/tools/qstringlist.cpp \ + $(SOURCE_PATH)/src/corelib/tools/qvsnprintf.cpp \ $(SOURCE_PATH)/src/corelib/xml/qxmlstream.cpp \ $(SOURCE_PATH)/src/corelib/xml/qxmlutils.cpp \ - $(SOURCE_PATH)/src/corelib/kernel/qsystemerror.cpp \ - $(SOURCE_PATH)/src/corelib/global/qlogging.cpp \ - $(SOURCE_PATH)/src/corelib/plugin/qsystemlibrary.cpp \ - $(SOURCE_PATH)/src/corelib/json/qjson.cpp \ - $(SOURCE_PATH)/src/corelib/json/qjsondocument.cpp \ - $(SOURCE_PATH)/src/corelib/json/qjsonparser.cpp \ - $(SOURCE_PATH)/src/corelib/json/qjsonarray.cpp \ - $(SOURCE_PATH)/src/corelib/json/qjsonobject.cpp \ - $(SOURCE_PATH)/src/corelib/json/qjsonvalue.cpp \ $(QTSRCS) $(QTSRCS2) +# QTSRCS and QTSRCS2 come from Makefile.unix.* (concatenated with this +# by configure); QTSRCS2 may include *.mm entries on macOS. +# See below for special handling of qlibraryinfo.cpp CPPFLAGS = -g $(EXTRA_CPPFLAGS) \ - -I$(QMKSRC) -I$(QMKLIBSRC) -I$(QMKSRC)/generators -I$(QMKSRC)/generators/unix -I$(QMKSRC)/generators/win32 \ - -I$(QMKSRC)/generators/mac \ + -I$(QMKSRC) -I$(QMKLIBSRC) -I$(QMKGENSRC) \ + -I$(QMKGENSRC)/unix -I$(QMKGENSRC)/win32 -I$(QMKGENSRC)/mac \ -I$(INC_PATH) -I$(INC_PATH)/QtCore \ -I$(INC_PATH)/QtCore/$(QT_VERSION) -I$(INC_PATH)/QtCore/$(QT_VERSION)/QtCore \ -I$(BUILD_PATH)/src/corelib/global \ -I$(QMAKESPEC) \ -DQT_VERSION_STR=\"$(QT_VERSION)\" -DQT_VERSION_MAJOR=$(QT_MAJOR_VERSION) -DQT_VERSION_MINOR=$(QT_MINOR_VERSION) -DQT_VERSION_PATCH=$(QT_PATCH_VERSION) \ - -DQT_BUILD_QMAKE -DQT_BOOTSTRAPPED -DPROEVALUATOR_FULL \ - -DQT_NO_FOREACH + -DQT_BUILD_QMAKE -DQT_BOOTSTRAPPED -DPROEVALUATOR_FULL \ + -DQT_NO_FOREACH CXXFLAGS = $(EXTRA_CXXFLAGS) $(CONFIG_CXXFLAGS) $(CPPFLAGS) LFLAGS = $(EXTRA_LFLAGS) $(CONFIG_LFLAGS) @@ -220,222 +255,222 @@ projectgenerator.o: $(QMKSRC)/generators/projectgenerator.cpp qtextstream.o: $(SOURCE_PATH)/src/corelib/io/qtextstream.cpp - $(CXX) -c -o $@ $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/io/qtextstream.cpp + $(CXX) -c -o $@ $(CXXFLAGS) $< qvariant.o: $(SOURCE_PATH)/src/corelib/kernel/qvariant.cpp - $(CXX) -c -o $@ $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/kernel/qvariant.cpp + $(CXX) -c -o $@ $(CXXFLAGS) $< qsettings.o: $(SOURCE_PATH)/src/corelib/io/qsettings.cpp - $(CXX) -c -o $@ $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/io/qsettings.cpp + $(CXX) -c -o $@ $(CXXFLAGS) $< qsystemerror.o: $(SOURCE_PATH)/src/corelib/kernel/qsystemerror.cpp - $(CXX) -c -o $@ $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/kernel/qsystemerror.cpp + $(CXX) -c -o $@ $(CXXFLAGS) $< qlibraryinfo.o: $(SOURCE_PATH)/src/corelib/global/qlibraryinfo.cpp - $(CXX) -c -o $@ $(CXXFLAGS) -DQT_BUILD_QMAKE_BOOTSTRAP $(SOURCE_PATH)/src/corelib/global/qlibraryinfo.cpp + $(CXX) -c -o $@ $(CXXFLAGS) -DQT_BUILD_QMAKE_BOOTSTRAP $< qlibraryinfo_final.o: $(SOURCE_PATH)/src/corelib/global/qlibraryinfo.cpp $(BUILD_PATH)/src/corelib/global/qconfig.cpp - $(CXX) -c -o $@ $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/global/qlibraryinfo.cpp + $(CXX) -c -o $@ $(CXXFLAGS) $< qnumeric.o: $(SOURCE_PATH)/src/corelib/global/qnumeric.cpp - $(CXX) -c -o $@ $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/global/qnumeric.cpp + $(CXX) -c -o $@ $(CXXFLAGS) $< qsettings_mac.o: $(SOURCE_PATH)/src/corelib/io/qsettings_mac.cpp - $(CXX) -c -o $@ $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/io/qsettings_mac.cpp + $(CXX) -c -o $@ $(CXXFLAGS) $< qsettings_win.o: $(SOURCE_PATH)/src/corelib/io/qsettings_win.cpp - $(CXX) -c -o $@ $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/io/qsettings_win.cpp + $(CXX) -c -o $@ $(CXXFLAGS) $< qiodevice.o: $(SOURCE_PATH)/src/corelib/io/qiodevice.cpp - $(CXX) -c -o $@ $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/io/qiodevice.cpp + $(CXX) -c -o $@ $(CXXFLAGS) $< qringbuffer.o: $(SOURCE_PATH)/src/corelib/tools/qringbuffer.cpp - $(CXX) -c -o $@ $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/tools/qringbuffer.cpp + $(CXX) -c -o $@ $(CXXFLAGS) $< qdebug.o: $(SOURCE_PATH)/src/corelib/io/qdebug.cpp - $(CXX) -c -o $@ $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/io/qdebug.cpp + $(CXX) -c -o $@ $(CXXFLAGS) $< qmalloc.o: $(SOURCE_PATH)/src/corelib/global/qmalloc.cpp - $(CXX) -c -o $@ $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/global/qmalloc.cpp + $(CXX) -c -o $@ $(CXXFLAGS) $< qglobal.o: $(SOURCE_PATH)/src/corelib/global/qglobal.cpp - $(CXX) -c -o $@ $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/global/qglobal.cpp + $(CXX) -c -o $@ $(CXXFLAGS) $< qarraydata.o: $(SOURCE_PATH)/src/corelib/tools/qarraydata.cpp - $(CXX) -c -o $@ $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/tools/qarraydata.cpp + $(CXX) -c -o $@ $(CXXFLAGS) $< qbytearray.o: $(SOURCE_PATH)/src/corelib/tools/qbytearray.cpp - $(CXX) -c -o $@ $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/tools/qbytearray.cpp + $(CXX) -c -o $@ $(CXXFLAGS) $< qvsnprintf.o: $(SOURCE_PATH)/src/corelib/tools/qvsnprintf.cpp - $(CXX) -c -o $@ $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/tools/qvsnprintf.cpp + $(CXX) -c -o $@ $(CXXFLAGS) $< qbytearraymatcher.o: $(SOURCE_PATH)/src/corelib/tools/qbytearraymatcher.cpp - $(CXX) -c -o $@ $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/tools/qbytearraymatcher.cpp + $(CXX) -c -o $@ $(CXXFLAGS) $< qmetatype.o: $(SOURCE_PATH)/src/corelib/kernel/qmetatype.cpp - $(CXX) -c -o $@ $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/kernel/qmetatype.cpp + $(CXX) -c -o $@ $(CXXFLAGS) $< qcore_mac.o: $(SOURCE_PATH)/src/corelib/kernel/qcore_mac.cpp - $(CXX) -c -o $@ $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/kernel/qcore_mac.cpp + $(CXX) -c -o $@ $(CXXFLAGS) $< qoperatingsystemversion.o: $(SOURCE_PATH)/src/corelib/global/qoperatingsystemversion.cpp - $(CXX) -c -o $@ $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/global/qoperatingsystemversion.cpp + $(CXX) -c -o $@ $(CXXFLAGS) $< qoperatingsystemversion_win.o: $(SOURCE_PATH)/src/corelib/global/qoperatingsystemversion_win.cpp - $(CXX) -c -o $@ $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/global/qoperatingsystemversion_win.cpp + $(CXX) -c -o $@ $(CXXFLAGS) $< qoperatingsystemversion_darwin.o: $(SOURCE_PATH)/src/corelib/global/qoperatingsystemversion_darwin.mm - $(CXX) -c -o $@ $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/global/qoperatingsystemversion_darwin.mm + $(CXX) -c -o $@ $(CXXFLAGS) $< qcore_mac_objc.o: $(SOURCE_PATH)/src/corelib/kernel/qcore_mac_objc.mm - $(CXX) -c -o $@ $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/kernel/qcore_mac_objc.mm + $(CXX) -c -o $@ $(CXXFLAGS) $< qcore_foundation.o: $(SOURCE_PATH)/src/corelib/kernel/qcore_foundation.mm - $(CXX) -c -o $@ $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/kernel/qcore_foundation.mm + $(CXX) -c -o $@ $(CXXFLAGS) $< qutfcodec.o: $(SOURCE_PATH)/src/corelib/codecs/qutfcodec.cpp - $(CXX) -c -o $@ $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/codecs/qutfcodec.cpp + $(CXX) -c -o $@ $(CXXFLAGS) $< qtextcodec.o: $(SOURCE_PATH)/src/corelib/codecs/qtextcodec.cpp - $(CXX) -c -o $@ $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/codecs/qtextcodec.cpp + $(CXX) -c -o $@ $(CXXFLAGS) $< qstring.o: $(SOURCE_PATH)/src/corelib/tools/qstring.cpp - $(CXX) -c -o $@ $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/tools/qstring.cpp + $(CXX) -c -o $@ $(CXXFLAGS) $< qstring_compat.o: $(SOURCE_PATH)/src/corelib/tools/qstring_compat.cpp - $(CXX) -c -o $@ $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/tools/qstring_compat.cpp + $(CXX) -c -o $@ $(CXXFLAGS) $< qstringbuilder.o: $(SOURCE_PATH)/src/corelib/tools/qstringbuilder.cpp - $(CXX) -c -o $@ $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/tools/qstringbuilder.cpp + $(CXX) -c -o $@ $(CXXFLAGS) $< qlocale.o: $(SOURCE_PATH)/src/corelib/tools/qlocale.cpp - $(CXX) -c -o $@ $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/tools/qlocale.cpp + $(CXX) -c -o $@ $(CXXFLAGS) $< qlocale_tools.o: $(SOURCE_PATH)/src/corelib/tools/qlocale_tools.cpp - $(CXX) -c -o $@ $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/tools/qlocale_tools.cpp + $(CXX) -c -o $@ $(CXXFLAGS) $< qlocale_unix.o: $(SOURCE_PATH)/src/corelib/tools/qlocale_unix.cpp - $(CXX) -c -o $@ $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/tools/qlocale_unix.cpp + $(CXX) -c -o $@ $(CXXFLAGS) $< qlocale_win.o: $(SOURCE_PATH)/src/corelib/tools/qlocale_win.cpp - $(CXX) -c -o $@ $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/tools/qlocale_win.cpp + $(CXX) -c -o $@ $(CXXFLAGS) $< qdatastream.o: $(SOURCE_PATH)/src/corelib/io/qdatastream.cpp - $(CXX) -c -o $@ $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/io/qdatastream.cpp + $(CXX) -c -o $@ $(CXXFLAGS) $< qbuffer.o: $(SOURCE_PATH)/src/corelib/io/qbuffer.cpp - $(CXX) -c -o $@ $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/io/qbuffer.cpp + $(CXX) -c -o $@ $(CXXFLAGS) $< qlist.o: $(SOURCE_PATH)/src/corelib/tools/qlist.cpp - $(CXX) -c -o $@ $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/tools/qlist.cpp + $(CXX) -c -o $@ $(CXXFLAGS) $< qfile.o: $(SOURCE_PATH)/src/corelib/io/qfile.cpp - $(CXX) -c -o $@ $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/io/qfile.cpp + $(CXX) -c -o $@ $(CXXFLAGS) $< qfiledevice.o: $(SOURCE_PATH)/src/corelib/io/qfiledevice.cpp - $(CXX) -c -o $@ $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/io/qfiledevice.cpp + $(CXX) -c -o $@ $(CXXFLAGS) $< qfilesystementry.o: $(SOURCE_PATH)/src/corelib/io/qfilesystementry.cpp - $(CXX) -c -o $@ $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/io/qfilesystementry.cpp + $(CXX) -c -o $@ $(CXXFLAGS) $< qfilesystemengine.o: $(SOURCE_PATH)/src/corelib/io/qfilesystemengine.cpp - $(CXX) -c -o $@ $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/io/qfilesystemengine.cpp + $(CXX) -c -o $@ $(CXXFLAGS) $< qfilesystemengine_unix.o: $(SOURCE_PATH)/src/corelib/io/qfilesystemengine_unix.cpp - $(CXX) -c -o $@ $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/io/qfilesystemengine_unix.cpp + $(CXX) -c -o $@ $(CXXFLAGS) $< qfilesystemengine_win.o: $(SOURCE_PATH)/src/corelib/io/qfilesystemengine_win.cpp - $(CXX) -c -o $@ $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/io/qfilesystemengine_win.cpp + $(CXX) -c -o $@ $(CXXFLAGS) $< qfilesystemiterator_unix.o: $(SOURCE_PATH)/src/corelib/io/qfilesystemiterator_unix.cpp - $(CXX) -c -o $@ $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/io/qfilesystemiterator_unix.cpp + $(CXX) -c -o $@ $(CXXFLAGS) $< qfilesystemiterator_win.o: $(SOURCE_PATH)/src/corelib/io/qfilesystemiterator_win.cpp - $(CXX) -c -o $@ $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/io/qfilesystemiterator_win.cpp + $(CXX) -c -o $@ $(CXXFLAGS) $< qfsfileengine.o: $(SOURCE_PATH)/src/corelib/io/qfsfileengine.cpp - $(CXX) -c -o $@ $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/io/qfsfileengine.cpp + $(CXX) -c -o $@ $(CXXFLAGS) $< qfsfileengine_iterator.o: $(SOURCE_PATH)/src/corelib/io/qfsfileengine_iterator.cpp - $(CXX) -c -o $@ $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/io/qfsfileengine_iterator.cpp + $(CXX) -c -o $@ $(CXXFLAGS) $< qfsfileengine_unix.o: $(SOURCE_PATH)/src/corelib/io/qfsfileengine_unix.cpp - $(CXX) -c -o $@ $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/io/qfsfileengine_unix.cpp + $(CXX) -c -o $@ $(CXXFLAGS) $< qfsfileengine_win.o: $(SOURCE_PATH)/src/corelib/io/qfsfileengine_win.cpp - $(CXX) -c -o $@ $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/io/qfsfileengine_win.cpp + $(CXX) -c -o $@ $(CXXFLAGS) $< qabstractfileengine.o: $(SOURCE_PATH)/src/corelib/io/qabstractfileengine.cpp - $(CXX) -c -o $@ $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/io/qabstractfileengine.cpp + $(CXX) -c -o $@ $(CXXFLAGS) $< qtemporaryfile.o: $(SOURCE_PATH)/src/corelib/io/qtemporaryfile.cpp - $(CXX) -c -o $@ $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/io/qtemporaryfile.cpp + $(CXX) -c -o $@ $(CXXFLAGS) $< qregexp.o: $(SOURCE_PATH)/src/corelib/tools/qregexp.cpp - $(CXX) -c -o $@ $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/tools/qregexp.cpp + $(CXX) -c -o $@ $(CXXFLAGS) $< qbitarray.o: $(SOURCE_PATH)/src/corelib/tools/qbitarray.cpp - $(CXX) -c -o $@ $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/tools/qbitarray.cpp + $(CXX) -c -o $@ $(CXXFLAGS) $< qdir.o: $(SOURCE_PATH)/src/corelib/io/qdir.cpp - $(CXX) -c -o $@ $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/io/qdir.cpp + $(CXX) -c -o $@ $(CXXFLAGS) $< qdiriterator.o: $(SOURCE_PATH)/src/corelib/io/qdiriterator.cpp - $(CXX) -c -o $@ $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/io/qdiriterator.cpp + $(CXX) -c -o $@ $(CXXFLAGS) $< quuid.o: $(SOURCE_PATH)/src/corelib/plugin/quuid.cpp - $(CXX) -c -o $@ $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/plugin/quuid.cpp + $(CXX) -c -o $@ $(CXXFLAGS) $< qfileinfo.o: $(SOURCE_PATH)/src/corelib/io/qfileinfo.cpp - $(CXX) -c -o $@ $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/io/qfileinfo.cpp + $(CXX) -c -o $@ $(CXXFLAGS) $< qdatetime.o: $(SOURCE_PATH)/src/corelib/tools/qdatetime.cpp - $(CXX) -c -o $@ $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/tools/qdatetime.cpp + $(CXX) -c -o $@ $(CXXFLAGS) $< qstringlist.o: $(SOURCE_PATH)/src/corelib/tools/qstringlist.cpp - $(CXX) -c -o $@ $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/tools/qstringlist.cpp + $(CXX) -c -o $@ $(CXXFLAGS) $< qmap.o: $(SOURCE_PATH)/src/corelib/tools/qmap.cpp - $(CXX) -c -o $@ $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/tools/qmap.cpp + $(CXX) -c -o $@ $(CXXFLAGS) $< qhash.o: $(SOURCE_PATH)/src/corelib/tools/qhash.cpp - $(CXX) -c -o $@ $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/tools/qhash.cpp + $(CXX) -c -o $@ $(CXXFLAGS) $< qlinkedlist.o: $(SOURCE_PATH)/src/corelib/tools/qlinkedlist.cpp - $(CXX) -c -o $@ $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/tools/qlinkedlist.cpp + $(CXX) -c -o $@ $(CXXFLAGS) $< -qcryptographichash.o: $(SOURCE_PATH)/src/corelib/tools/qcryptographichash.cpp - $(CXX) -c -o $@ $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/tools/qcryptographichash.cpp +qcryptographichash.o: $(SOURCE_PATH)/src/corelib/tools/qcryptographichash.cpp + $(CXX) -c -o $@ $(CXXFLAGS) $< qxmlstream.o: $(SOURCE_PATH)/src/corelib/xml/qxmlstream.cpp - $(CXX) -c -o $@ $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/xml/qxmlstream.cpp + $(CXX) -c -o $@ $(CXXFLAGS) $< qxmlutils.o: $(SOURCE_PATH)/src/corelib/xml/qxmlutils.cpp - $(CXX) -c -o $@ $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/xml/qxmlutils.cpp + $(CXX) -c -o $@ $(CXXFLAGS) $< qlogging.o: $(SOURCE_PATH)/src/corelib/global/qlogging.cpp - $(CXX) -c -o $@ $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/global/qlogging.cpp + $(CXX) -c -o $@ $(CXXFLAGS) $< qsystemlibrary.o: $(SOURCE_PATH)/src/corelib/plugin/qsystemlibrary.cpp - $(CXX) -c -o $@ $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/plugin/qsystemlibrary.cpp + $(CXX) -c -o $@ $(CXXFLAGS) $< qjson.o: $(SOURCE_PATH)/src/corelib/json/qjson.cpp - $(CXX) -c -o $@ $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/json/qjson.cpp + $(CXX) -c -o $@ $(CXXFLAGS) $< qjsondocument.o: $(SOURCE_PATH)/src/corelib/json/qjsondocument.cpp - $(CXX) -c -o $@ $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/json/qjsondocument.cpp + $(CXX) -c -o $@ $(CXXFLAGS) $< qjsonparser.o: $(SOURCE_PATH)/src/corelib/json/qjsonparser.cpp - $(CXX) -c -o $@ $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/json/qjsonparser.cpp + $(CXX) -c -o $@ $(CXXFLAGS) $< qjsonarray.o: $(SOURCE_PATH)/src/corelib/json/qjsonarray.cpp - $(CXX) -c -o $@ $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/json/qjsonarray.cpp + $(CXX) -c -o $@ $(CXXFLAGS) $< qjsonobject.o: $(SOURCE_PATH)/src/corelib/json/qjsonobject.cpp - $(CXX) -c -o $@ $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/json/qjsonobject.cpp + $(CXX) -c -o $@ $(CXXFLAGS) $< qjsonvalue.o: $(SOURCE_PATH)/src/corelib/json/qjsonvalue.cpp - $(CXX) -c -o $@ $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/json/qjsonvalue.cpp + $(CXX) -c -o $@ $(CXXFLAGS) $< # DO NOT DELETE THIS LINE -- make depend depends on it diff --git a/qmake/qmake.pri b/qmake/qmake.pri index c0f7250bcf3..b9ed9ce96a5 100644 --- a/qmake/qmake.pri +++ b/qmake/qmake.pri @@ -132,8 +132,7 @@ bootstrap { #Qt code unix { SOURCES += qfilesystemengine_unix.cpp qfilesystemiterator_unix.cpp qfsfileengine_unix.cpp mac { - SOURCES += qcore_mac.cpp qsettings_mac.cpp - OBJECTIVE_SOURCES += qcore_mac_objc.mm qlocale_mac.mm + SOURCES += qcore_mac.cpp qsettings_mac.cpp qcore_mac_objc.mm qlocale_mac.mm LIBS += -framework ApplicationServices -framework CoreServices -framework Foundation } else { SOURCES += qlocale_unix.cpp diff --git a/src/android/jar/src/org/qtproject/qt5/android/QtActivityDelegate.java b/src/android/jar/src/org/qtproject/qt5/android/QtActivityDelegate.java index e0878f078fc..7c11b5d136a 100644 --- a/src/android/jar/src/org/qtproject/qt5/android/QtActivityDelegate.java +++ b/src/android/jar/src/org/qtproject/qt5/android/QtActivityDelegate.java @@ -62,6 +62,9 @@ import android.util.Base64; import android.util.DisplayMetrics; import android.util.Log; import android.util.TypedValue; +import android.view.animation.AccelerateInterpolator; +import android.view.animation.AlphaAnimation; +import android.view.animation.Animation; import android.view.ContextMenu; import android.view.ContextMenu.ContextMenuInfo; import android.view.KeyCharacterMap; @@ -1020,10 +1023,36 @@ public class QtActivityDelegate public void hideSplashScreen() { + hideSplashScreen(0); + } + + public void hideSplashScreen(final int duration) + { if (m_splashScreen == null) return; - m_layout.removeView(m_splashScreen); - m_splashScreen = null; + + if (duration <= 0) { + m_layout.removeView(m_splashScreen); + m_splashScreen = null; + return; + } + + final Animation fadeOut = new AlphaAnimation(1, 0); + fadeOut.setInterpolator(new AccelerateInterpolator()); + fadeOut.setDuration(duration); + + fadeOut.setAnimationListener(new Animation.AnimationListener() { + @Override + public void onAnimationEnd(Animation animation) { hideSplashScreen(0); } + + @Override + public void onAnimationRepeat(Animation animation) {} + + @Override + public void onAnimationStart(Animation animation) {} + }); + + m_splashScreen.startAnimation(fadeOut); } diff --git a/src/android/jar/src/org/qtproject/qt5/android/QtNative.java b/src/android/jar/src/org/qtproject/qt5/android/QtNative.java index b6dbd825970..94a23635943 100644 --- a/src/android/jar/src/org/qtproject/qt5/android/QtNative.java +++ b/src/android/jar/src/org/qtproject/qt5/android/QtNative.java @@ -764,13 +764,13 @@ public class QtNative }); } - private static void hideSplashScreen() + private static void hideSplashScreen(final int duration) { runAction(new Runnable() { @Override public void run() { if (m_activityDelegate != null) - m_activityDelegate.hideSplashScreen(); + m_activityDelegate.hideSplashScreen(duration); } }); } diff --git a/src/corelib/global/qglobal.h b/src/corelib/global/qglobal.h index 9ac29acd160..0e374931820 100644 --- a/src/corelib/global/qglobal.h +++ b/src/corelib/global/qglobal.h @@ -612,6 +612,18 @@ private: void *pool; }; +#else + +#define QT_DARWIN_PLATFORM_SDK_EQUAL_OR_ABOVE(macos, ios, tvos, watchos) (0) +#define QT_MACOS_IOS_PLATFORM_SDK_EQUAL_OR_ABOVE(macos, ios) (0) +#define QT_MACOS_PLATFORM_SDK_EQUAL_OR_ABOVE(macos) (0) +#define QT_IOS_PLATFORM_SDK_EQUAL_OR_ABOVE(ios) (0) +#define QT_TVOS_PLATFORM_SDK_EQUAL_OR_ABOVE(tvos) (0) +#define QT_WATCHOS_PLATFORM_SDK_EQUAL_OR_ABOVE(watchos) (0) + +#define QT_MAC_PLATFORM_SDK_EQUAL_OR_ABOVE(osx, ios) (0) +#define QT_OSX_PLATFORM_SDK_EQUAL_OR_ABOVE(osx) (0) + #endif // Q_OS_DARWIN /* diff --git a/src/corelib/global/qtypeinfo.h b/src/corelib/global/qtypeinfo.h index 7031021e166..4f79c48c514 100644 --- a/src/corelib/global/qtypeinfo.h +++ b/src/corelib/global/qtypeinfo.h @@ -311,14 +311,11 @@ Q_DECLARE_TYPEINFO(qint64, Q_PRIMITIVE_TYPE); Q_DECLARE_TYPEINFO(quint64, Q_PRIMITIVE_TYPE); Q_DECLARE_TYPEINFO(float, Q_PRIMITIVE_TYPE); Q_DECLARE_TYPEINFO(double, Q_PRIMITIVE_TYPE); -#ifndef Q_OS_DARWIN -Q_DECLARE_TYPEINFO(long double, Q_PRIMITIVE_TYPE); -#endif - #if QT_VERSION >= QT_VERSION_CHECK(6,0,0) // ### Qt 6: remove the other branch // This was required so that QList<T> for these types allocates out of the array storage +Q_DECLARE_TYPEINFO(long double, Q_PRIMITIVE_TYPE); # ifdef Q_COMPILER_UNICODE_STRINGS Q_DECLARE_TYPEINFO(char16_t, Q_PRIMITIVE_TYPE); Q_DECLARE_TYPEINFO(char32_t, Q_PRIMITIVE_TYPE); @@ -327,6 +324,11 @@ Q_DECLARE_TYPEINFO(char32_t, Q_PRIMITIVE_TYPE); Q_DECLARE_TYPEINFO(wchar_t, Q_PRIMITIVE_TYPE); # endif #else +# ifndef Q_OS_DARWIN +Q_DECLARE_TYPEINFO(long double, Q_PRIMITIVE_TYPE); +# else +Q_DECLARE_TYPEINFO(long double, Q_RELOCATABLE_TYPE); +# endif # ifdef Q_COMPILER_UNICODE_STRINGS Q_DECLARE_TYPEINFO(char16_t, Q_RELOCATABLE_TYPE); Q_DECLARE_TYPEINFO(char32_t, Q_RELOCATABLE_TYPE); diff --git a/src/corelib/io/qabstractfileengine.cpp b/src/corelib/io/qabstractfileengine.cpp index 9606ec68e9c..5f1f7e381e0 100644 --- a/src/corelib/io/qabstractfileengine.cpp +++ b/src/corelib/io/qabstractfileengine.cpp @@ -832,6 +832,19 @@ bool QAbstractFileEngine::unmap(uchar *address) } /*! + \since 5.10 + + Copies the contents from the file specified by \a sourceHandle to this file + by cloning it. + Returns \c true on success; otherwise, \c false is returned. + */ +bool QAbstractFileEngine::clone(int sourceHandle) +{ + Q_UNUSED(sourceHandle); + return false; +} + +/*! \since 4.3 \class QAbstractFileEngineIterator \inmodule QtCore diff --git a/src/corelib/io/qabstractfileengine_p.h b/src/corelib/io/qabstractfileengine_p.h index 48b3dec3249..dbf0d77b154 100644 --- a/src/corelib/io/qabstractfileengine_p.h +++ b/src/corelib/io/qabstractfileengine_p.h @@ -147,6 +147,7 @@ public: virtual QDateTime fileTime(FileTime time) const; virtual void setFileName(const QString &file); virtual int handle() const; + virtual bool clone(int sourceHandle); bool atEnd() const; uchar *map(qint64 offset, qint64 size, QFile::MemoryMapFlags flags); bool unmap(uchar *ptr); diff --git a/src/corelib/io/qdatastream.cpp b/src/corelib/io/qdatastream.cpp index 2369fe47265..58e25000573 100644 --- a/src/corelib/io/qdatastream.cpp +++ b/src/corelib/io/qdatastream.cpp @@ -562,6 +562,7 @@ void QDataStream::setByteOrder(ByteOrder bo) \value Qt_5_7 Same as Qt_5_6 \value Qt_5_8 Same as Qt_5_6 \value Qt_5_9 Same as Qt_5_6 + \value Qt_5_10 Same as Qt_5_6 \omitvalue Qt_DefaultCompiledVersion \sa setVersion(), version() diff --git a/src/corelib/io/qdatastream.h b/src/corelib/io/qdatastream.h index db1bbfbd63b..993a20fcd32 100644 --- a/src/corelib/io/qdatastream.h +++ b/src/corelib/io/qdatastream.h @@ -96,10 +96,11 @@ public: Qt_5_7 = Qt_5_6, Qt_5_8 = Qt_5_7, Qt_5_9 = Qt_5_8, -#if QT_VERSION >= 0x050a00 + Qt_5_10 = Qt_5_9, +#if QT_VERSION >= 0x050b00 #error Add the datastream version for this Qt version and update Qt_DefaultCompiledVersion #endif - Qt_DefaultCompiledVersion = Qt_5_9 + Qt_DefaultCompiledVersion = Qt_5_10 }; enum ByteOrder { diff --git a/src/corelib/io/qfile.cpp b/src/corelib/io/qfile.cpp index 41fae69bb23..6249d54f7de 100644 --- a/src/corelib/io/qfile.cpp +++ b/src/corelib/io/qfile.cpp @@ -42,6 +42,7 @@ #include "qfile.h" #include "qfsfileengine_p.h" #include "qtemporaryfile.h" +#include "qtemporaryfile_p.h" #include "qlist.h" #include "qfileinfo.h" #include "private/qiodevice_p.h" @@ -790,25 +791,27 @@ QFile::copy(const QString &newName) close(); d->setError(QFile::CopyError, tr("Cannot open for output")); } else { - char block[4096]; - qint64 totalRead = 0; - while(!atEnd()) { - qint64 in = read(block, sizeof(block)); - if (in <= 0) - break; - totalRead += in; - if(in != out.write(block, in)) { - close(); - d->setError(QFile::CopyError, tr("Failure to write block")); - error = true; - break; + if (!out.d_func()->engine()->clone(d->engine()->handle())) { + char block[4096]; + qint64 totalRead = 0; + while (!atEnd()) { + qint64 in = read(block, sizeof(block)); + if (in <= 0) + break; + totalRead += in; + if (in != out.write(block, in)) { + close(); + d->setError(QFile::CopyError, tr("Failure to write block")); + error = true; + break; + } } - } - if (totalRead != size()) { - // Unable to read from the source. The error string is - // already set from read(). - error = true; + if (totalRead != size()) { + // Unable to read from the source. The error string is + // already set from read(). + error = true; + } } if (!error && !out.rename(newName)) { error = true; diff --git a/src/corelib/io/qfilesystemengine_unix.cpp b/src/corelib/io/qfilesystemengine_unix.cpp index 3cb412e47c8..b8dca93f61b 100644 --- a/src/corelib/io/qfilesystemengine_unix.cpp +++ b/src/corelib/io/qfilesystemengine_unix.cpp @@ -42,6 +42,7 @@ #include "qfilesystemengine_p.h" #include "qfile.h" +#include <QtCore/qoperatingsystemversion.h> #include <QtCore/qvarlengtharray.h> #include <stdlib.h> // for realpath() @@ -66,6 +67,9 @@ #endif #if defined(Q_OS_DARWIN) +# if QT_DARWIN_PLATFORM_SDK_EQUAL_OR_ABOVE(101200, 100000, 100000, 30000) +# include <sys/clonefile.h> +# endif // We cannot include <Foundation/Foundation.h> (it's an Objective-C header), but // we need these declarations: Q_FORWARD_DECLARE_OBJC_CLASS(NSString); @@ -659,8 +663,22 @@ bool QFileSystemEngine::createLink(const QFileSystemEntry &source, const QFileSy //static bool QFileSystemEngine::copyFile(const QFileSystemEntry &source, const QFileSystemEntry &target, QSystemError &error) { +#if QT_DARWIN_PLATFORM_SDK_EQUAL_OR_ABOVE(101200, 100000, 100000, 30000) + const auto current = QOperatingSystemVersion::current(); + if (current >= QOperatingSystemVersion::MacOSSierra || + current >= QOperatingSystemVersion(QOperatingSystemVersion::IOS, 10) || + current >= QOperatingSystemVersion(QOperatingSystemVersion::TvOS, 10) || + current >= QOperatingSystemVersion(QOperatingSystemVersion::WatchOS, 3)) { + if (::clonefile(source.nativeFilePath().constData(), + target.nativeFilePath().constData(), 0) == 0) + return true; + error = QSystemError(errno, QSystemError::StandardLibraryError); + return false; + } +#else Q_UNUSED(source); Q_UNUSED(target); +#endif error = QSystemError(ENOSYS, QSystemError::StandardLibraryError); //Function not implemented return false; } diff --git a/src/corelib/io/qfsfileengine.cpp b/src/corelib/io/qfsfileengine.cpp index 0b9cd0557f9..de921c0be6e 100644 --- a/src/corelib/io/qfsfileengine.cpp +++ b/src/corelib/io/qfsfileengine.cpp @@ -860,9 +860,9 @@ bool QFSFileEngine::supportsExtension(Extension extension) const /*! \fn bool QFSFileEngine::copy(const QString ©Name) - For windows, copy the file to file \a copyName. + For Windows or Apple platforms, copy the file to file \a copyName. - Not implemented for Unix. + Not implemented for other Unix platforms. */ /*! \fn QString QFSFileEngine::currentPath(const QString &fileName) diff --git a/src/corelib/io/qfsfileengine_p.h b/src/corelib/io/qfsfileengine_p.h index 593ecc26871..742cebad872 100644 --- a/src/corelib/io/qfsfileengine_p.h +++ b/src/corelib/io/qfsfileengine_p.h @@ -108,6 +108,7 @@ public: qint64 read(char *data, qint64 maxlen) Q_DECL_OVERRIDE; qint64 readLine(char *data, qint64 maxlen) Q_DECL_OVERRIDE; qint64 write(const char *data, qint64 len) Q_DECL_OVERRIDE; + bool clone(int sourceHandle) override; bool extension(Extension extension, const ExtensionOption *option = 0, ExtensionReturn *output = 0) Q_DECL_OVERRIDE; bool supportsExtension(Extension extension) const Q_DECL_OVERRIDE; diff --git a/src/corelib/io/qfsfileengine_unix.cpp b/src/corelib/io/qfsfileengine_unix.cpp index ca5af924e9a..ff77278dc14 100644 --- a/src/corelib/io/qfsfileengine_unix.cpp +++ b/src/corelib/io/qfsfileengine_unix.cpp @@ -780,6 +780,23 @@ bool QFSFileEnginePrivate::unmap(uchar *ptr) #endif } +/*! + \reimp +*/ +bool QFSFileEngine::clone(int sourceHandle) +{ +#if defined(Q_OS_LINUX) + Q_D(QFSFileEngine); +# if !defined FICLONE +# define FICLONE _IOW (0x94, 9, int) +# endif + return ::ioctl(d->fd, FICLONE, sourceHandle) == 0; +#else + Q_UNUSED(sourceHandle); + return false; +#endif +} + QT_END_NAMESPACE #endif // QT_NO_FSFILEENGINE diff --git a/src/corelib/io/qfsfileengine_win.cpp b/src/corelib/io/qfsfileengine_win.cpp index a7fd50df83a..2ebc98e0de1 100644 --- a/src/corelib/io/qfsfileengine_win.cpp +++ b/src/corelib/io/qfsfileengine_win.cpp @@ -984,4 +984,13 @@ bool QFSFileEnginePrivate::unmap(uchar *ptr) return true; } +/*! + \reimp +*/ +bool QFSFileEngine::clone(int sourceHandle) +{ + Q_UNUSED(sourceHandle); + return false; +} + QT_END_NAMESPACE diff --git a/src/corelib/io/qsettings.cpp b/src/corelib/io/qsettings.cpp index 16dab38a60e..24fa00c4d96 100644 --- a/src/corelib/io/qsettings.cpp +++ b/src/corelib/io/qsettings.cpp @@ -1802,6 +1802,8 @@ struct QSettingsIniSection inline QSettingsIniSection() : position(-1) {} }; +Q_DECLARE_TYPEINFO(QSettingsIniSection, Q_MOVABLE_TYPE); + typedef QMap<QString, QSettingsIniSection> IniMap; /* diff --git a/src/corelib/io/qsettings_p.h b/src/corelib/io/qsettings_p.h index 639605d8c46..d8e91e48ce5 100644 --- a/src/corelib/io/qsettings_p.h +++ b/src/corelib/io/qsettings_p.h @@ -109,6 +109,8 @@ private: }; #endif +Q_DECLARE_TYPEINFO(QSettingsKey, Q_MOVABLE_TYPE); + typedef QMap<QSettingsKey, QByteArray> UnparsedSettingsMap; typedef QMap<QSettingsKey, QVariant> ParsedSettingsMap; diff --git a/src/corelib/io/qtemporaryfile_p.h b/src/corelib/io/qtemporaryfile_p.h index 7f365f0e8a1..bf40e1627a1 100644 --- a/src/corelib/io/qtemporaryfile_p.h +++ b/src/corelib/io/qtemporaryfile_p.h @@ -65,7 +65,7 @@ class QTemporaryFilePrivate : public QFilePrivate { Q_DECLARE_PUBLIC(QTemporaryFile) -protected: +public: QTemporaryFilePrivate(); explicit QTemporaryFilePrivate(const QString &templateNameIn); ~QTemporaryFilePrivate(); diff --git a/src/corelib/itemmodels/qstringlistmodel.cpp b/src/corelib/itemmodels/qstringlistmodel.cpp index 0f7472aa5ae..da232cc1423 100644 --- a/src/corelib/itemmodels/qstringlistmodel.cpp +++ b/src/corelib/itemmodels/qstringlistmodel.cpp @@ -131,7 +131,7 @@ int QStringListModel::rowCount(const QModelIndex &parent) const */ QModelIndex QStringListModel::sibling(int row, int column, const QModelIndex &idx) const { - if (!idx.isValid() || column != 0 || row >= lst.count()) + if (!idx.isValid() || column != 0 || row >= lst.count() || row < 0) return QModelIndex(); return createIndex(row, 0); diff --git a/src/corelib/kernel/qabstracteventdispatcher.h b/src/corelib/kernel/qabstracteventdispatcher.h index 68d9bf180f2..961148d9ecf 100644 --- a/src/corelib/kernel/qabstracteventdispatcher.h +++ b/src/corelib/kernel/qabstracteventdispatcher.h @@ -124,6 +124,8 @@ protected: QObject *parent); }; +Q_DECLARE_TYPEINFO(QAbstractEventDispatcher::TimerInfo, (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) ? Q_PRIMITIVE_TYPE : Q_RELOCATABLE_TYPE)); + QT_END_NAMESPACE #endif // QABSTRACTEVENTDISPATCHER_H diff --git a/src/corelib/kernel/qcore_unix_p.h b/src/corelib/kernel/qcore_unix_p.h index 80058d91155..63b45d7f891 100644 --- a/src/corelib/kernel/qcore_unix_p.h +++ b/src/corelib/kernel/qcore_unix_p.h @@ -103,6 +103,8 @@ struct sockaddr; QT_BEGIN_NAMESPACE +Q_DECLARE_TYPEINFO(pollfd, Q_PRIMITIVE_TYPE); + // Internal operator functions for timespecs inline timespec &normalizedTimespec(timespec &t) { diff --git a/src/corelib/kernel/qjnihelpers.cpp b/src/corelib/kernel/qjnihelpers.cpp index 93bc477e7db..306c0845efe 100644 --- a/src/corelib/kernel/qjnihelpers.cpp +++ b/src/corelib/kernel/qjnihelpers.cpp @@ -406,7 +406,7 @@ jint QtAndroidPrivate::initJNI(JavaVM *vm, JNIEnv *env) g_runPendingCppRunnablesMethodID = env->GetStaticMethodID(jQtNative, "runPendingCppRunnablesOnAndroidThread", "()V"); - g_hideSplashScreenMethodID = env->GetStaticMethodID(jQtNative, "hideSplashScreen", "()V"); + g_hideSplashScreenMethodID = env->GetStaticMethodID(jQtNative, "hideSplashScreen", "(I)V"); g_jNativeClass = static_cast<jclass>(env->NewGlobalRef(jQtNative)); env->DeleteLocalRef(jQtNative); @@ -566,9 +566,9 @@ void QtAndroidPrivate::unregisterKeyEventListener(QtAndroidPrivate::KeyEventList g_keyEventListeners()->listeners.removeOne(listener); } -void QtAndroidPrivate::hideSplashScreen(JNIEnv *env) +void QtAndroidPrivate::hideSplashScreen(JNIEnv *env, int duration) { - env->CallStaticVoidMethod(g_jNativeClass, g_hideSplashScreenMethodID); + env->CallStaticVoidMethod(g_jNativeClass, g_hideSplashScreenMethodID, duration); } QT_END_NAMESPACE diff --git a/src/corelib/kernel/qjnihelpers_p.h b/src/corelib/kernel/qjnihelpers_p.h index 62f9358513f..9fa47d5302d 100644 --- a/src/corelib/kernel/qjnihelpers_p.h +++ b/src/corelib/kernel/qjnihelpers_p.h @@ -140,7 +140,7 @@ namespace QtAndroidPrivate Q_CORE_EXPORT void registerKeyEventListener(KeyEventListener *listener); Q_CORE_EXPORT void unregisterKeyEventListener(KeyEventListener *listener); - Q_CORE_EXPORT void hideSplashScreen(JNIEnv *env); + Q_CORE_EXPORT void hideSplashScreen(JNIEnv *env, int duration = 0); } QT_END_NAMESPACE diff --git a/src/corelib/kernel/qmetatype.h b/src/corelib/kernel/qmetatype.h index 3674ebc1a15..5e2e746bbc8 100644 --- a/src/corelib/kernel/qmetatype.h +++ b/src/corelib/kernel/qmetatype.h @@ -462,7 +462,8 @@ public: WeakPointerToQObject = 0x40, TrackingPointerToQObject = 0x80, WasDeclaredAsMetaType = 0x100, - IsGadget = 0x200 + IsGadget = 0x200, + PointerToGadget = 0x400 }; Q_DECLARE_FLAGS(TypeFlags, TypeFlag) @@ -1388,6 +1389,19 @@ namespace QtPrivate enum { Value = sizeof(checkType(&T::qt_check_for_QGADGET_macro)) == sizeof(void *) }; }; + template<typename T, typename Enable = void> + struct IsPointerToGadgetHelper { enum { Value = false }; }; + + template<typename T> + struct IsPointerToGadgetHelper<T*, typename T::QtGadgetHelper> + { + using BaseType = T; + template <typename X> + static char checkType(void (X::*)()); + static void *checkType(void (T::*)()); + enum { Value = sizeof(checkType(&T::qt_check_for_QGADGET_macro)) == sizeof(void *) }; + }; + template<typename T> char qt_getEnumMetaObject(const T&); @@ -1423,6 +1437,11 @@ namespace QtPrivate static inline const QMetaObject *value() { return &T::staticMetaObject; } }; template<typename T> + struct MetaObjectForType<T, typename QEnableIf<IsPointerToGadgetHelper<T>::Value>::Type> + { + static inline const QMetaObject *value() { return &IsPointerToGadgetHelper<T>::BaseType::staticMetaObject; } + }; + template<typename T> struct MetaObjectForType<T, typename std::enable_if<IsQEnumHelper<T>::Value>::type > { static inline const QMetaObject *value() { return qt_getEnumMetaObject(T()); } @@ -1578,6 +1597,7 @@ namespace QtPrivate template <typename T, int = QtPrivate::IsPointerToTypeDerivedFromQObject<T>::Value ? QMetaType::PointerToQObject : QtPrivate::IsGadgetHelper<T>::Value ? QMetaType::IsGadget : + QtPrivate::IsPointerToGadgetHelper<T>::Value ? QMetaType::PointerToGadget : QtPrivate::IsQEnumHelper<T>::Value ? QMetaType::IsEnumeration : 0> struct QMetaTypeIdQObject { @@ -1631,6 +1651,7 @@ namespace QtPrivate { | (IsTrackingPointerToTypeDerivedFromQObject<T>::Value ? QMetaType::TrackingPointerToQObject : 0) | (std::is_enum<T>::value ? QMetaType::IsEnumeration : 0) | (IsGadgetHelper<T>::Value ? QMetaType::IsGadget : 0) + | (IsPointerToGadgetHelper<T>::Value ? QMetaType::PointerToGadget : 0) }; }; @@ -1798,6 +1819,30 @@ struct QMetaTypeIdQObject<T, QMetaType::IsGadget> }; template <typename T> +struct QMetaTypeIdQObject<T*, QMetaType::PointerToGadget> +{ + enum { + Defined = 1 + }; + + static int qt_metatype_id() + { + static QBasicAtomicInt metatype_id = Q_BASIC_ATOMIC_INITIALIZER(0); + if (const int id = metatype_id.loadAcquire()) + return id; + const char * const cName = T::staticMetaObject.className(); + QByteArray typeName; + typeName.reserve(int(strlen(cName)) + 1); + typeName.append(cName).append('*'); + const int newId = qRegisterNormalizedMetaType<T*>( + typeName, + reinterpret_cast<T**>(quintptr(-1))); + metatype_id.storeRelease(newId); + return newId; + } +}; + +template <typename T> struct QMetaTypeIdQObject<T, QMetaType::IsEnumeration> { enum { diff --git a/src/corelib/kernel/qobject_p.h b/src/corelib/kernel/qobject_p.h index a7d7ef08897..2bdaffb4659 100644 --- a/src/corelib/kernel/qobject_p.h +++ b/src/corelib/kernel/qobject_p.h @@ -243,6 +243,7 @@ public: QAtomicPointer<QtSharedPointer::ExternalRefCountData> sharedRefcount; }; +Q_DECLARE_TYPEINFO(QObjectPrivate::ConnectionList, Q_MOVABLE_TYPE); /*! \internal diff --git a/src/corelib/mimetypes/qmimetypeparser.cpp b/src/corelib/mimetypes/qmimetypeparser.cpp index 20b4461b039..5ecd339908d 100644 --- a/src/corelib/mimetypes/qmimetypeparser.cpp +++ b/src/corelib/mimetypes/qmimetypeparser.cpp @@ -49,7 +49,6 @@ #include <QtCore/QCoreApplication> #include <QtCore/QDebug> #include <QtCore/QDir> -#include <QtCore/QPair> #include <QtCore/QXmlStreamReader> #include <QtCore/QXmlStreamWriter> #include <QtCore/QStack> diff --git a/src/corelib/thread/qresultstore.h b/src/corelib/thread/qresultstore.h index 56cfcb6ed66..fa6907dde2e 100644 --- a/src/corelib/thread/qresultstore.h +++ b/src/corelib/thread/qresultstore.h @@ -228,6 +228,8 @@ public: } // namespace QtPrivate +Q_DECLARE_TYPEINFO(QtPrivate::ResultItem, Q_PRIMITIVE_TYPE); + #endif //Q_QDOC QT_END_NAMESPACE diff --git a/src/corelib/thread/qsemaphore.cpp b/src/corelib/thread/qsemaphore.cpp index 8427b0e696b..397d6203aa4 100644 --- a/src/corelib/thread/qsemaphore.cpp +++ b/src/corelib/thread/qsemaphore.cpp @@ -94,7 +94,7 @@ QT_BEGIN_NAMESPACE seated (taking the available seats to 5, making the party of 10 people wait longer). - \sa QMutex, QWaitCondition, QThread, {Semaphores Example} + \sa QSemaphoreReleaser, QMutex, QWaitCondition, QThread, {Semaphores Example} */ class QSemaphorePrivate { @@ -152,7 +152,10 @@ void QSemaphore::acquire(int n) \snippet code/src_corelib_thread_qsemaphore.cpp 1 - \sa acquire(), available() + QSemaphoreReleaser is a \l{http://en.cppreference.com/w/cpp/language/raii}{RAII} + wrapper around this function. + + \sa acquire(), available(), QSemaphoreReleaser */ void QSemaphore::release(int n) { @@ -234,6 +237,152 @@ bool QSemaphore::tryAcquire(int n, int timeout) } +/*! + \class QSemaphoreReleaser + \brief The QSemaphoreReleaser class provides exception-safe deferral of a QSemaphore::release() call + \since 5.10 + \ingroup thread + \inmodule QtCore + + \reentrant + + QSemaphoreReleaser can be used wherever you would otherwise use + QSemaphore::release(). Constructing a QSemaphoreReleaser defers the + release() call on the semaphore until the QSemaphoreReleaser is + destroyed (see + \l{http://en.cppreference.com/w/cpp/language/raii}{RAII pattern}). + + You can use this to reliably release a semaphore to avoid dead-lock + in the face of exceptions or early returns: + + \code + // ... do something that may throw or return early + sem.release(); + \endcode + + If an early return is taken or an exception is thrown before the + \c{sem.release()} call is reached, the semaphore is not released, + possibly preventing the thread waiting in the corresponding + \c{sem.acquire()} call from ever continuing execution. + + When using RAII instead: + + \code + const QSemaphoreReleaser releaser(sem); + // ... do something that may throw or early return + // implicitly calls sem.release() here and at every other return in between + \endcode + + this can no longer happen, because the compiler will make sure that + the QSemaphoreReleaser destructor is always called, and therefore + the semaphore is always released. + + QSemaphoreReleaser is move-enabled and can therefore be returned + from functions to transfer responsibility for releasing a semaphore + out of a function or a scope: + + \code + { // some scope + QSemaphoreReleaser releaser; // does nothing + // ... + if (someCondition) { + releaser = QSemaphoreReleaser(sem); + // ... + } + // ... + } // conditionally calls sem.release(), depending on someCondition + \endcode + + A QSemaphoreReleaser can be canceled by a call to cancel(). A canceled + semaphore releaser will no longer call QSemaphore::release() in its + destructor. + + \sa QMutexLocker +*/ + +/*! + \fn QSemaphoreReleaser::QSemaphoreReleaser() + + Default constructor. Creates a QSemaphoreReleaser that does nothing. +*/ + +/*! + \fn QSemaphoreReleaser::QSemaphoreReleaser(QSemaphore &sem, int n) + + Constructor. Stores the arguments and calls \a{sem}.release(\a{n}) + in the destructor. +*/ + +/*! + \fn QSemaphoreReleaser::QSemaphoreReleaser(QSemaphore *sem, int n) + + Constructor. Stores the arguments and calls \a{sem}->release(\a{n}) + in the destructor. +*/ + +/*! + \fn QSemaphoreReleaser::QSemaphoreReleaser(QSemaphoreReleaser &&other) + + Move constructor. Takes over responsibility to call QSemaphore::release() + from \a other, which in turn is canceled. + + \sa cancel() +*/ + +/*! + \fn QSemaphoreReleaser::operator=(QSemaphoreReleaser &&other) + + Move assignment operator. Takes over responsibility to call QSemaphore::release() + from \a other, which in turn is canceled. + + If this semaphore releaser had the responsibility to call some QSemaphore::release() + itself, it performs the call before taking over from \a other. + + \sa cancel() +*/ + +/*! + \fn QSemaphoreReleaser::~QSemaphoreReleaser() + + Unless canceled, calls QSemaphore::release() with the arguments provided + to the constructor, or by the last move assignment. +*/ + +/*! + \fn QSemaphoreReleaser::swap(QSemaphoreReleaser &other) + + Exchanges the responsibilites of \c{*this} and \a other. + + Unlike move assignment, neither of the two objects ever releases its + semaphore, if any, as a consequence of swapping. + + Therefore this function is very fast and never fails. +*/ + +/*! + \fn QSemaphoreReleaser::semaphore() const + + Returns a pointer to the QSemaphore object provided to the constructor, + or by the last move assignment, if any. Otherwise, returns \c nullptr. +*/ + +/*! + \fn QSemaphoreReleaser::cancel() + + Cancels this QSemaphoreReleaser such that the destructor will no longer + call \c{semaphore()->release()}. Returns the value of semaphore() + before this call. After this call, semaphore() will return \c nullptr. + + To enable again, assign a new QSemaphoreReleaser: + + \code + releaser.cancel(); // avoid releasing old semaphore() + releaser = QSemaphoreReleaser(sem, 42); + // now will call sem.release(42) when 'releaser' is destroyed + \endcode +*/ + + QT_END_NAMESPACE #endif // QT_NO_THREAD diff --git a/src/corelib/thread/qsemaphore.h b/src/corelib/thread/qsemaphore.h index adb9d73e509..a92740c8cea 100644 --- a/src/corelib/thread/qsemaphore.h +++ b/src/corelib/thread/qsemaphore.h @@ -69,6 +69,45 @@ private: QSemaphorePrivate *d; }; +class QSemaphoreReleaser +{ + QSemaphore *m_sem = nullptr; + int m_n; +public: + QSemaphoreReleaser() = default; + explicit QSemaphoreReleaser(QSemaphore &sem, int n = 1) Q_DECL_NOTHROW + : m_sem(&sem), m_n(n) {} + explicit QSemaphoreReleaser(QSemaphore *sem, int n = 1) Q_DECL_NOTHROW + : m_sem(sem), m_n(n) {} + QSemaphoreReleaser(QSemaphoreReleaser &&other) Q_DECL_NOTHROW + : m_sem(other.m_sem), m_n(other.m_n) + { other.m_sem = nullptr; } + QSemaphoreReleaser &operator=(QSemaphoreReleaser &&other) Q_DECL_NOTHROW + { QSemaphoreReleaser moved(std::move(other)); swap(moved); return *this; } + + ~QSemaphoreReleaser() + { + if (m_sem) + m_sem->release(m_n); + } + + void swap(QSemaphoreReleaser &other) Q_DECL_NOTHROW + { + qSwap(m_sem, other.m_sem); + qSwap(m_n, other.m_n); + } + + QSemaphore *semaphore() const Q_DECL_NOTHROW + { return m_sem; } + + QSemaphore *cancel() Q_DECL_NOTHROW + { + QSemaphore *old = m_sem; + m_sem = nullptr; + return old; + } +}; + #endif // QT_NO_THREAD QT_END_NAMESPACE diff --git a/src/corelib/tools/qringbuffer_p.h b/src/corelib/tools/qringbuffer_p.h index 325b71f2670..558a456515e 100644 --- a/src/corelib/tools/qringbuffer_p.h +++ b/src/corelib/tools/qringbuffer_p.h @@ -159,6 +159,8 @@ private: qint64 bufferSize; }; +Q_DECLARE_TYPEINFO(QRingBuffer, Q_MOVABLE_TYPE); + QT_END_NAMESPACE #endif // QRINGBUFFER_P_H diff --git a/src/corelib/tools/qsimd_p.h b/src/corelib/tools/qsimd_p.h index f6164e22970..59a8dd9d0c3 100644 --- a/src/corelib/tools/qsimd_p.h +++ b/src/corelib/tools/qsimd_p.h @@ -261,7 +261,7 @@ # endif #endif -#if defined(__AES__) || defined(__PCLMUL__) +#if defined(__AES__) || defined(__PCLMUL__) || (defined(QT_COMPILER_SUPPORTS_AES) && defined(QT_COMPILER_SUPPORTS_SIMD_ALWAYS)) # include <wmmintrin.h> #endif diff --git a/src/corelib/tools/qstring.cpp b/src/corelib/tools/qstring.cpp index d76eb110732..8e7f0e50d32 100644 --- a/src/corelib/tools/qstring.cpp +++ b/src/corelib/tools/qstring.cpp @@ -8368,6 +8368,24 @@ QString &QString::setRawData(const QChar *unicode, int size) Returns the size of the Latin-1 string stored in this object. */ +/*! \fn bool QLatin1String::isNull() const + \since 5.10 + + Returns whether the Latin-1 string stored in this object is null + (\c{data() == nullptr}) or not. + + \sa isEmpty(), data() +*/ + +/*! \fn bool QLatin1String::isEmpty() const + \since 5.10 + + Returns whether the Latin-1 string stored in this object is empty + (\c{size() == 0}) or not. + + \sa isNull(), size() +*/ + /*! \fn QLatin1Char QLatin1String::at(int pos) const \since 5.8 diff --git a/src/corelib/tools/qstring.h b/src/corelib/tools/qstring.h index e06927d4340..36edcc72428 100644 --- a/src/corelib/tools/qstring.h +++ b/src/corelib/tools/qstring.h @@ -97,6 +97,9 @@ public: Q_DECL_CONSTEXPR int size() const Q_DECL_NOTHROW { return m_size; } Q_DECL_CONSTEXPR const char *data() const Q_DECL_NOTHROW { return m_data; } + Q_DECL_CONSTEXPR bool isNull() const Q_DECL_NOTHROW { return !data(); } + Q_DECL_CONSTEXPR bool isEmpty() const Q_DECL_NOTHROW { return !size(); } + Q_DECL_CONSTEXPR QLatin1Char at(int i) const { return QLatin1Char(m_data[i]); } Q_DECL_CONSTEXPR QLatin1Char operator[](int i) const { return at(i); } diff --git a/src/gui/image/qiconloader.cpp b/src/gui/image/qiconloader.cpp index d72c05a3c5d..1d700446a93 100644 --- a/src/gui/image/qiconloader.cpp +++ b/src/gui/image/qiconloader.cpp @@ -609,18 +609,18 @@ static int directorySizeDistance(const QIconDirInfo &dir, int iconsize, int icon return INT_MAX; } -QIconLoaderEngineEntry *QIconLoaderEngine::entryForSize(const QSize &size, int scale) +QIconLoaderEngineEntry *QIconLoaderEngine::entryForSize(const QThemeIconInfo &info, const QSize &size, int scale) { int iconsize = qMin(size.width(), size.height()); // Note that m_info.entries are sorted so that png-files // come first - const int numEntries = m_info.entries.size(); + const int numEntries = info.entries.size(); // Search for exact matches first for (int i = 0; i < numEntries; ++i) { - QIconLoaderEngineEntry *entry = m_info.entries.at(i); + QIconLoaderEngineEntry *entry = info.entries.at(i); if (directoryMatchesSize(entry->dir, iconsize, scale)) { return entry; } @@ -630,7 +630,7 @@ QIconLoaderEngineEntry *QIconLoaderEngine::entryForSize(const QSize &size, int s int minimalSize = INT_MAX; QIconLoaderEngineEntry *closestMatch = 0; for (int i = 0; i < numEntries; ++i) { - QIconLoaderEngineEntry *entry = m_info.entries.at(i); + QIconLoaderEngineEntry *entry = info.entries.at(i); int distance = directorySizeDistance(entry->dir, iconsize, scale); if (distance < minimalSize) { minimalSize = distance; @@ -651,7 +651,7 @@ QSize QIconLoaderEngine::actualSize(const QSize &size, QIcon::Mode mode, { ensureLoaded(); - QIconLoaderEngineEntry *entry = entryForSize(size); + QIconLoaderEngineEntry *entry = entryForSize(m_info, size); if (entry) { const QIconDirInfo &dir = entry->dir; if (dir.type == QIconDirInfo::Scalable) @@ -715,7 +715,7 @@ QPixmap QIconLoaderEngine::pixmap(const QSize &size, QIcon::Mode mode, { ensureLoaded(); - QIconLoaderEngineEntry *entry = entryForSize(size); + QIconLoaderEngineEntry *entry = entryForSize(m_info, size); if (entry) return entry->pixmap(size, mode, state); @@ -764,7 +764,7 @@ void QIconLoaderEngine::virtual_hook(int id, void *data) QIconEngine::ScaledPixmapArgument &arg = *reinterpret_cast<QIconEngine::ScaledPixmapArgument*>(data); // QIcon::pixmap() multiplies size by the device pixel ratio. const int integerScale = qCeil(arg.scale); - QIconLoaderEngineEntry *entry = entryForSize(arg.size / integerScale, integerScale); + QIconLoaderEngineEntry *entry = entryForSize(m_info, arg.size / integerScale, integerScale); arg.pixmap = entry ? entry->pixmap(arg.size, arg.mode, arg.state) : QPixmap(); } break; diff --git a/src/gui/image/qiconloader_p.h b/src/gui/image/qiconloader_p.h index 5f3a3ef948d..9398bca5855 100644 --- a/src/gui/image/qiconloader_p.h +++ b/src/gui/image/qiconloader_p.h @@ -132,12 +132,13 @@ public: bool read(QDataStream &in) Q_DECL_OVERRIDE; bool write(QDataStream &out) const Q_DECL_OVERRIDE; + Q_GUI_EXPORT static QIconLoaderEngineEntry *entryForSize(const QThemeIconInfo &info, const QSize &size, int scale = 1); + private: QString key() const Q_DECL_OVERRIDE; bool hasIcon() const; void ensureLoaded(); void virtual_hook(int id, void *data) Q_DECL_OVERRIDE; - QIconLoaderEngineEntry *entryForSize(const QSize &size, int scale = 1); QIconLoaderEngine(const QIconLoaderEngine &other); QThemeIconInfo m_info; diff --git a/src/gui/image/qimagewriter.cpp b/src/gui/image/qimagewriter.cpp index ab15d8ee290..a39d2046779 100644 --- a/src/gui/image/qimagewriter.cpp +++ b/src/gui/image/qimagewriter.cpp @@ -87,6 +87,9 @@ \value UnsupportedFormatError Qt does not support the requested image format. + \value InvalidImageError An attempt was made to write an invalid QImage. An + example of an invalid image would be a null QImage. + \value UnknownError An unknown error occurred. If you get this value after calling write(), it is most likely caused by a bug in QImageWriter. @@ -736,6 +739,13 @@ extern void qt_imageTransform(QImage &src, QImageIOHandler::Transformations orie */ bool QImageWriter::write(const QImage &image) { + // Do this before canWrite, so it doesn't create a file if this fails. + if (Q_UNLIKELY(image.isNull())) { + d->imageWriterError = QImageWriter::InvalidImageError; + d->errorString = QImageWriter::tr("Image is empty"); + return false; + } + if (!canWrite()) return false; diff --git a/src/gui/image/qimagewriter.h b/src/gui/image/qimagewriter.h index 58f8c514724..fd1fdd07e80 100644 --- a/src/gui/image/qimagewriter.h +++ b/src/gui/image/qimagewriter.h @@ -60,7 +60,8 @@ public: enum ImageWriterError { UnknownError, DeviceError, - UnsupportedFormatError + UnsupportedFormatError, + InvalidImageError }; QImageWriter(); diff --git a/src/gui/kernel/qplatformintegration.cpp b/src/gui/kernel/qplatformintegration.cpp index fe1861e08b1..0af32954306 100644 --- a/src/gui/kernel/qplatformintegration.cpp +++ b/src/gui/kernel/qplatformintegration.cpp @@ -237,6 +237,10 @@ QPlatformServices *QPlatformIntegration::services() const is required to have this capability. \value ApplicationIcon The platform supports setting the application icon. (since 5.5) + + \value TopStackedNativeChildWindows The platform supports native child windows via + QWindowContainer without having to punch a transparent hole in the + backingstore. (since 5.10) */ /*! @@ -260,7 +264,8 @@ QPlatformServices *QPlatformIntegration::services() const bool QPlatformIntegration::hasCapability(Capability cap) const { - return cap == NonFullScreenWindows || cap == NativeWidgets || cap == WindowManagement; + return cap == NonFullScreenWindows || cap == NativeWidgets || cap == WindowManagement + || cap == TopStackedNativeChildWindows; } QPlatformPixmap *QPlatformIntegration::createPlatformPixmap(QPlatformPixmap::PixelType type) const diff --git a/src/gui/kernel/qplatformintegration.h b/src/gui/kernel/qplatformintegration.h index 0449e0b4c84..54904ef60de 100644 --- a/src/gui/kernel/qplatformintegration.h +++ b/src/gui/kernel/qplatformintegration.h @@ -99,7 +99,8 @@ public: RasterGLSurface, AllGLFunctionsQueryable, ApplicationIcon, - SwitchableWidgetComposition + SwitchableWidgetComposition, + TopStackedNativeChildWindows }; virtual ~QPlatformIntegration() { } diff --git a/src/gui/kernel/qsurfaceformat.cpp b/src/gui/kernel/qsurfaceformat.cpp index 000d727380a..574310f5548 100644 --- a/src/gui/kernel/qsurfaceformat.cpp +++ b/src/gui/kernel/qsurfaceformat.cpp @@ -73,6 +73,7 @@ public: , major(2) , minor(0) , swapInterval(1) // default to vsync + , colorSpace(QSurfaceFormat::DefaultColorSpace) { } @@ -91,7 +92,8 @@ public: profile(other->profile), major(other->major), minor(other->minor), - swapInterval(other->swapInterval) + swapInterval(other->swapInterval), + colorSpace(other->colorSpace) { } @@ -110,6 +112,7 @@ public: int major; int minor; int swapInterval; + QSurfaceFormat::ColorSpace colorSpace; }; /*! @@ -124,6 +127,12 @@ public: contains surface configuration parameters such as OpenGL profile and version for rendering, whether or not to enable stereo buffers, and swap behaviour. + + \note When troubleshooting context or window format issues, it can be + helpful to enable the logging category \c{qt.qpa.gl}. Depending on the + platform, this may print useful debug information when it comes to OpenGL + initialization and the native visual or framebuffer configurations which + QSurfaceFormat gets mapped to. */ /*! @@ -199,6 +208,22 @@ public: */ /*! + \enum QSurfaceFormat::ColorSpace + + This enum is used to specify the preferred color space, controlling if the + window's associated default framebuffer is able to do updates and blending + in a given encoding instead of the standard linear operations. + + \value DefaultColorSpace The default, unspecified color space. + + \value sRGBColorSpace When \c{GL_ARB_framebuffer_sRGB} or + \c{GL_EXT_framebuffer_sRGB} is supported by the platform and this value is + set, the window will be created with an sRGB-capable default + framebuffer. Note that some platforms may return windows with a sRGB-capable + default framebuffer even when not requested explicitly. + */ + +/*! Constructs a default initialized QSurfaceFormat. \note By default OpenGL 2.0 is requested since this provides the highest @@ -736,6 +761,47 @@ int QSurfaceFormat::swapInterval() const return d->swapInterval; } +/*! + Sets the preferred \a colorSpace. + + For example, this allows requesting windows with default framebuffers that + are sRGB-capable on platforms that support it. + + \note When the requested color space is not supported by the platform, the + request is ignored. Query the QSurfaceFormat after window creation to verify + if the color space request could be honored or not. + + \note This setting controls if the default framebuffer of the window is + capable of updates and blending in a given color space. It does not change + applications' output by itself. The applications' rendering code will still + have to opt in via the appropriate OpenGL calls to enable updates and + blending to be performed in the given color space instead of using the + standard linear operations. + + \since 5.10 + + \sa colorSpace() + */ +void QSurfaceFormat::setColorSpace(ColorSpace colorSpace) +{ + if (d->colorSpace != colorSpace) { + detach(); + d->colorSpace = colorSpace; + } +} + +/*! + \return the color space. + + \since 5.10 + + \sa setColorSpace() +*/ +QSurfaceFormat::ColorSpace QSurfaceFormat::colorSpace() const +{ + return d->colorSpace; +} + Q_GLOBAL_STATIC(QSurfaceFormat, qt_default_surface_format) /*! @@ -841,6 +907,7 @@ QDebug operator<<(QDebug dbg, const QSurfaceFormat &f) << ", samples " << d->numSamples << ", swapBehavior " << d->swapBehavior << ", swapInterval " << d->swapInterval + << ", colorSpace " << d->colorSpace << ", profile " << d->profile << ')'; diff --git a/src/gui/kernel/qsurfaceformat.h b/src/gui/kernel/qsurfaceformat.h index 246163609ef..ed63eb8bbf0 100644 --- a/src/gui/kernel/qsurfaceformat.h +++ b/src/gui/kernel/qsurfaceformat.h @@ -85,6 +85,12 @@ public: }; Q_ENUM(OpenGLContextProfile) + enum ColorSpace { + DefaultColorSpace, + sRGBColorSpace + }; + Q_ENUM(ColorSpace) + QSurfaceFormat(); /*implicit*/ QSurfaceFormat(FormatOptions options); QSurfaceFormat(const QSurfaceFormat &other); @@ -145,6 +151,9 @@ public: int swapInterval() const; void setSwapInterval(int interval); + ColorSpace colorSpace() const; + void setColorSpace(ColorSpace colorSpace); + static void setDefaultFormat(const QSurfaceFormat &format); static QSurfaceFormat defaultFormat(); diff --git a/src/gui/painting/qgrayraster.c b/src/gui/painting/qgrayraster.c index db3453898f4..49e53973b01 100644 --- a/src/gui/painting/qgrayraster.c +++ b/src/gui/painting/qgrayraster.c @@ -43,7 +43,7 @@ /* */ /* A new `perfect' anti-aliasing renderer (body). */ /* */ -/* Copyright 2000-2001, 2002, 2003 by */ +/* Copyright 2000-2016 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -119,10 +119,6 @@ /* */ /*************************************************************************/ -/* experimental support for gamma correction within the rasterizer */ -#define xxxGRAYS_USE_GAMMA - - /*************************************************************************/ /* */ /* The macro QT_FT_COMPONENT is used in trace mode. It is an implicit */ @@ -133,6 +129,28 @@ #define QT_FT_COMPONENT trace_smooth +/* Auxiliary macros for token concatenation. */ +#define QT_FT_ERR_XCAT( x, y ) x ## y +#define QT_FT_ERR_CAT( x, y ) QT_FT_ERR_XCAT( x, y ) + +#define QT_FT_BEGIN_STMNT do { +#define QT_FT_END_STMNT } while ( 0 ) + +#define QT_FT_MAX( a, b ) ( (a) > (b) ? (a) : (b) ) +#define QT_FT_ABS( a ) ( (a) < 0 ? -(a) : (a) ) + + +/* + * Approximate sqrt(x*x+y*y) using the `alpha max plus beta min' + * algorithm. We use alpha = 1, beta = 3/8, giving us results with a + * largest error less than 7% compared to the exact value. + */ +#define QT_FT_HYPOT( x, y ) \ + ( x = QT_FT_ABS( x ), \ + y = QT_FT_ABS( y ), \ + x > y ? x + ( 3 * y >> 3 ) \ + : y + ( 3 * x >> 3 ) ) + #define ErrRaster_MemoryOverflow -4 #if defined(VXWORKS) @@ -150,6 +168,9 @@ #define qt_ft_longjmp longjmp #define qt_ft_jmp_buf jmp_buf +#include <stddef.h> +typedef ptrdiff_t QT_FT_PtrDist; + #define ErrRaster_Invalid_Mode -2 #define ErrRaster_Invalid_Outline -1 #define ErrRaster_Invalid_Argument -3 @@ -171,15 +192,10 @@ /* ANSI compilers (e.g. LCC). */ #define QT_FT_UNUSED( x ) (x) = (x) - /* Disable the tracing mechanism for simplicity -- developers can */ - /* activate it easily by redefining these two macros. */ -#ifndef QT_FT_ERROR -#define QT_FT_ERROR( x ) do ; while ( 0 ) /* nothing */ -#endif - -#ifndef QT_FT_TRACE -#define QT_FT_TRACE( x ) do ; while ( 0 ) /* nothing */ -#endif +#define QT_FT_TRACE5( x ) do { } while ( 0 ) /* nothing */ +#define QT_FT_TRACE7( x ) do { } while ( 0 ) /* nothing */ +#define QT_FT_ERROR( x ) do { } while ( 0 ) /* nothing */ +#define QT_FT_THROW( e ) QT_FT_ERR_CAT( ErrRaster_, e ) #ifndef QT_FT_MEM_SET #define QT_FT_MEM_SET( d, s, c ) qt_ft_memset( d, s, c ) @@ -189,9 +205,6 @@ #define QT_FT_MEM_ZERO( dest, count ) QT_FT_MEM_SET( dest, 0, count ) #endif - /* define this to dump debugging information */ -#define xxxDEBUG_GRAYS - #define RAS_ARG PWorker worker #define RAS_ARG_ PWorker worker, @@ -201,26 +214,47 @@ #define ras (*worker) - /* must be at least 6 bits! */ #define PIXEL_BITS 8 #define ONE_PIXEL ( 1L << PIXEL_BITS ) -#define PIXEL_MASK ( -1L << PIXEL_BITS ) #define TRUNC( x ) ( (TCoord)( (x) >> PIXEL_BITS ) ) -#define SUBPIXELS( x ) ( (TPos)(x) * ( 1 << PIXEL_BITS ) ) +#define SUBPIXELS( x ) ( (TPos)(x) * ONE_PIXEL ) #define FLOOR( x ) ( (x) & -ONE_PIXEL ) #define CEILING( x ) ( ( (x) + ONE_PIXEL - 1 ) & -ONE_PIXEL ) #define ROUND( x ) ( ( (x) + ONE_PIXEL / 2 ) & -ONE_PIXEL ) #if PIXEL_BITS >= 6 -#define UPSCALE( x ) ( (x) * ( 1 << ( PIXEL_BITS - 6 ) ) ) +#define UPSCALE( x ) ( (x) * ( ONE_PIXEL >> 6 ) ) #define DOWNSCALE( x ) ( (x) >> ( PIXEL_BITS - 6 ) ) #else #define UPSCALE( x ) ( (x) >> ( 6 - PIXEL_BITS ) ) -#define DOWNSCALE( x ) ( (x) << ( 6 - PIXEL_BITS ) ) +#define DOWNSCALE( x ) ( (x) * ( 64 >> PIXEL_BITS ) ) #endif +/* Compute `dividend / divisor' and return both its quotient and */ +/* remainder, cast to a specific type. This macro also ensures that */ +/* the remainder is always positive. */ +#define QT_FT_DIV_MOD( type, dividend, divisor, quotient, remainder ) \ +QT_FT_BEGIN_STMNT \ + (quotient) = (type)( (dividend) / (divisor) ); \ + (remainder) = (type)( (dividend) % (divisor) ); \ + if ( (remainder) < 0 ) \ + { \ + (quotient)--; \ + (remainder) += (type)(divisor); \ + } \ +QT_FT_END_STMNT + + /* These macros speed up repetitive divisions by replacing them */ + /* with multiplications and right shifts. */ +#define QT_FT_UDIVPREP( b ) \ + long b ## _r = (long)( ULONG_MAX >> PIXEL_BITS ) / ( b ) +#define QT_FT_UDIV( a, b ) \ + ( ( (unsigned long)( a ) * (unsigned long)( b ## _r ) ) >> \ + ( sizeof( long ) * CHAR_BIT - PIXEL_BITS ) ) + + /*************************************************************************/ /* */ /* TYPE DEFINITIONS */ @@ -230,28 +264,9 @@ /* need to define them to "float" or "double" when experimenting with */ /* new algorithms */ - typedef int TCoord; /* integer scanline/pixel coordinate */ - typedef int TPos; /* sub-pixel coordinate */ - - /* determine the type used to store cell areas. This normally takes at */ - /* least PIXEL_BITS*2 + 1 bits. On 16-bit systems, we need to use */ - /* `long' instead of `int', otherwise bad things happen */ - -#if PIXEL_BITS <= 7 - - typedef int TArea; - -#else /* PIXEL_BITS >= 8 */ - - /* approximately determine the size of integers using an ANSI-C header */ -#if QT_FT_UINT_MAX == 0xFFFFU - typedef long TArea; -#else - typedef int TArea; -#endif - -#endif /* PIXEL_BITS >= 8 */ - + typedef long TCoord; /* integer scanline/pixel coordinate */ + typedef long TPos; /* sub-pixel coordinate */ + typedef long TArea ; /* cell areas, coordinate products */ /* maximal number of gray spans in a call to the span callback */ #define QT_FT_MAX_GRAY_SPANS 256 @@ -281,17 +296,11 @@ int invalid; PCell cells; - int max_cells; - int num_cells; + QT_FT_PtrDist max_cells; + QT_FT_PtrDist num_cells; - TCoord cx, cy; TPos x, y; - TPos last_ey; - - QT_FT_Vector bez_stack[32 * 3 + 1]; - int lev_stack[32]; - QT_FT_Outline outline; QT_FT_Bitmap target; QT_FT_BBox clip_box; @@ -304,8 +313,6 @@ int band_size; int band_shoot; - int conic_level; - int cubic_level; qt_ft_jmp_buf jump_buffer; @@ -313,7 +320,7 @@ long buffer_size; PCell* ycells; - int ycount; + TPos ycount; int skip_spans; } TWorker, *PWorker; @@ -343,7 +350,7 @@ /* */ static void gray_init_cells( RAS_ARG_ void* buffer, - long byte_size ) + long byte_size ) { ras.buffer = buffer; ras.buffer_size = byte_size; @@ -406,31 +413,25 @@ /* */ /* Record the current cell in the table. */ /* */ - static void - gray_record_cell( RAS_ARG ) + static PCell + gray_find_cell( RAS_ARG ) { PCell *pcell, cell; - int x = ras.ex; + TPos x = ras.ex; - if ( ras.invalid || !( ras.area | ras.cover ) ) - return; - if ( x > ras.max_ex ) - x = ras.max_ex; + if ( x > ras.count_ex ) + x = ras.count_ex; pcell = &ras.ycells[ras.ey]; - for (;;) { cell = *pcell; if ( cell == NULL || cell->x > x ) break; - if ( cell->x == x ) { - cell->area += ras.area; - cell->cover += ras.cover; - return; - } + if ( cell->x == x ) + goto Exit; pcell = &cell->next; } @@ -440,11 +441,28 @@ cell = ras.cells + ras.num_cells++; cell->x = x; - cell->area = ras.area; - cell->cover = ras.cover; + cell->area = 0; + cell->cover = 0; cell->next = *pcell; *pcell = cell; + + Exit: + return cell; + } + + + static void + gray_record_cell( RAS_ARG ) + { + if ( ras.area | ras.cover ) + { + PCell cell = gray_find_cell( RAS_VAR ); + + + cell->area += ras.area; + cell->cover += ras.cover; + } } @@ -490,8 +508,8 @@ ras.ey = ey; } - ras.invalid = ( (unsigned)ey >= (unsigned)ras.count_ey || - ex >= ras.count_ex ); + ras.invalid = ( (unsigned int)ey >= (unsigned int)ras.count_ey || + ex >= ras.count_ex ); } @@ -513,12 +531,13 @@ ras.cover = 0; ras.ex = ex - ras.min_ex; ras.ey = ey - ras.min_ey; - ras.last_ey = SUBPIXELS( ey ); ras.invalid = 0; gray_set_cell( RAS_VAR_ ex, ey ); } +// The new render-line implementation is not yet used +#if 1 /*************************************************************************/ /* */ @@ -531,9 +550,9 @@ TPos x2, TCoord y2 ) { - TCoord ex1, ex2, fx1, fx2, delta; + TCoord ex1, ex2, fx1, fx2, delta, mod; int p, first, dx; - int incr, lift, mod, rem; + int incr; dx = x2 - x1; @@ -575,13 +594,7 @@ dx = -dx; } - delta = (TCoord)( p / dx ); - mod = (TCoord)( p % dx ); - if ( mod < 0 ) - { - delta--; - mod += (TCoord)dx; - } + QT_FT_DIV_MOD( TCoord, p, dx, delta, mod ); ras.area += (TArea)( fx1 + first ) * delta; ras.cover += delta; @@ -592,14 +605,11 @@ if ( ex1 != ex2 ) { - p = ONE_PIXEL * ( y2 - y1 + delta ); - lift = (TCoord)( p / dx ); - rem = (TCoord)( p % dx ); - if ( rem < 0 ) - { - lift--; - rem += (TCoord)dx; - } + TCoord lift, rem; + + + p = ONE_PIXEL * ( y2 - y1 + delta ); + QT_FT_DIV_MOD( TCoord, p, dx, lift, rem ); mod -= (int)dx; @@ -635,38 +645,24 @@ gray_render_line( RAS_ARG_ TPos to_x, TPos to_y ) { - TCoord ey1, ey2, fy1, fy2; + TCoord ey1, ey2, fy1, fy2, mod; TPos dx, dy, x, x2; int p, first; - int delta, rem, mod, lift, incr; + int delta, rem, lift, incr; - ey1 = TRUNC( ras.last_ey ); + ey1 = TRUNC( ras.y ); ey2 = TRUNC( to_y ); /* if (ey2 >= ras.max_ey) ey2 = ras.max_ey-1; */ - fy1 = (TCoord)( ras.y - ras.last_ey ); + fy1 = (TCoord)( ras.y - SUBPIXELS( ey1 ) ); fy2 = (TCoord)( to_y - SUBPIXELS( ey2 ) ); dx = to_x - ras.x; dy = to_y - ras.y; - /* XXX: we should do something about the trivial case where dx == 0, */ - /* as it happens very often! */ - /* perform vertical clipping */ - { - TCoord min, max; - - - min = ey1; - max = ey2; - if ( ey1 > ey2 ) - { - min = ey2; - max = ey1; - } - if ( min >= ras.max_ey || max < ras.min_ey ) - goto End; - } + if ( ( ey1 >= ras.max_ey && ey2 >= ras.max_ey ) || + ( ey1 < ras.min_ey && ey2 < ras.min_ey ) ) + goto End; /* everything is on a single scanline */ if ( ey1 == ey2 ) @@ -773,13 +769,7 @@ if ( ey1 != ey2 ) { p = ONE_PIXEL * dx; - lift = (int)( p / dy ); - rem = (int)( p % dy ); - if ( rem < 0 ) - { - lift--; - rem += (int)dy; - } + QT_FT_DIV_MOD( int, p, dy, lift, rem ); mod -= (int)dy; while ( ey1 != ey2 ) @@ -810,10 +800,147 @@ End: ras.x = to_x; ras.y = to_y; - ras.last_ey = SUBPIXELS( ey2 ); } +#else + + /*************************************************************************/ + /* */ + /* Render a straight line across multiple cells in any direction. */ + /* */ + static void + gray_render_line( RAS_ARG_ TPos to_x, + TPos to_y ) + { + TPos dx, dy, fx1, fy1, fx2, fy2; + TCoord ex1, ex2, ey1, ey2; + + + ex1 = TRUNC( ras.x ); + ex2 = TRUNC( to_x ); + ey1 = TRUNC( ras.y ); + ey2 = TRUNC( to_y ); + + /* perform vertical clipping */ + if ( ( ey1 >= ras.max_ey && ey2 >= ras.max_ey ) || + ( ey1 < ras.min_ey && ey2 < ras.min_ey ) ) + goto End; + + dx = to_x - ras.x; + dy = to_y - ras.y; + + fx1 = ras.x - SUBPIXELS( ex1 ); + fy1 = ras.y - SUBPIXELS( ey1 ); + + if ( ex1 == ex2 && ey1 == ey2 ) /* inside one cell */ + ; + else if ( dy == 0 ) /* ex1 != ex2 */ /* any horizontal line */ + { + ex1 = ex2; + gray_set_cell( RAS_VAR_ ex1, ey1 ); + } + else if ( dx == 0 ) + { + if ( dy > 0 ) /* vertical line up */ + do + { + fy2 = ONE_PIXEL; + ras.cover += ( fy2 - fy1 ); + ras.area += ( fy2 - fy1 ) * fx1 * 2; + fy1 = 0; + ey1++; + gray_set_cell( RAS_VAR_ ex1, ey1 ); + } while ( ey1 != ey2 ); + else /* vertical line down */ + do + { + fy2 = 0; + ras.cover += ( fy2 - fy1 ); + ras.area += ( fy2 - fy1 ) * fx1 * 2; + fy1 = ONE_PIXEL; + ey1--; + gray_set_cell( RAS_VAR_ ex1, ey1 ); + } while ( ey1 != ey2 ); + } + else /* any other line */ + { + TArea prod = dx * fy1 - dy * fx1; + QT_FT_UDIVPREP( dx ); + QT_FT_UDIVPREP( dy ); + + + /* The fundamental value `prod' determines which side and the */ + /* exact coordinate where the line exits current cell. It is */ + /* also easily updated when moving from one cell to the next. */ + do + { + if ( prod <= 0 && + prod - dx * ONE_PIXEL > 0 ) /* left */ + { + fx2 = 0; + fy2 = (TPos)QT_FT_UDIV( -prod, -dx ); + prod -= dy * ONE_PIXEL; + ras.cover += ( fy2 - fy1 ); + ras.area += ( fy2 - fy1 ) * ( fx1 + fx2 ); + fx1 = ONE_PIXEL; + fy1 = fy2; + ex1--; + } + else if ( prod - dx * ONE_PIXEL <= 0 && + prod - dx * ONE_PIXEL + dy * ONE_PIXEL > 0 ) /* up */ + { + prod -= dx * ONE_PIXEL; + fx2 = (TPos)QT_FT_UDIV( -prod, dy ); + fy2 = ONE_PIXEL; + ras.cover += ( fy2 - fy1 ); + ras.area += ( fy2 - fy1 ) * ( fx1 + fx2 ); + fx1 = fx2; + fy1 = 0; + ey1++; + } + else if ( prod - dx * ONE_PIXEL + dy * ONE_PIXEL <= 0 && + prod + dy * ONE_PIXEL >= 0 ) /* right */ + { + prod += dy * ONE_PIXEL; + fx2 = ONE_PIXEL; + fy2 = (TPos)QT_FT_UDIV( prod, dx ); + ras.cover += ( fy2 - fy1 ); + ras.area += ( fy2 - fy1 ) * ( fx1 + fx2 ); + fx1 = 0; + fy1 = fy2; + ex1++; + } + else /* ( prod + dy * ONE_PIXEL < 0 && + prod > 0 ) down */ + { + fx2 = (TPos)QT_FT_UDIV( prod, -dy ); + fy2 = 0; + prod += dx * ONE_PIXEL; + ras.cover += ( fy2 - fy1 ); + ras.area += ( fy2 - fy1 ) * ( fx1 + fx2 ); + fx1 = fx2; + fy1 = ONE_PIXEL; + ey1--; + } + + gray_set_cell( RAS_VAR_ ex1, ey1 ); + } while ( ex1 != ex2 || ey1 != ey2 ); + } + + fx2 = to_x - SUBPIXELS( ex2 ); + fy2 = to_y - SUBPIXELS( ey2 ); + + ras.cover += ( fy2 - fy1 ); + ras.area += ( fy2 - fy1 ) * ( fx1 + fx2 ); + + End: + ras.x = to_x; + ras.y = to_y; + } + +#endif + static void gray_split_conic( QT_FT_Vector* base ) { @@ -838,52 +965,11 @@ gray_render_conic( RAS_ARG_ const QT_FT_Vector* control, const QT_FT_Vector* to ) { + QT_FT_Vector bez_stack[16 * 2 + 1]; /* enough to accommodate bisections */ + QT_FT_Vector* arc = bez_stack; TPos dx, dy; - int top, level; - int* levels; - QT_FT_Vector* arc; - - - dx = DOWNSCALE( ras.x ) + to->x - ( control->x << 1 ); - if ( dx < 0 ) - dx = -dx; - dy = DOWNSCALE( ras.y ) + to->y - ( control->y << 1 ); - if ( dy < 0 ) - dy = -dy; - if ( dx < dy ) - dx = dy; - - level = 1; - dx = dx / ras.conic_level; - while ( dx > 0 ) - { - dx >>= 2; - level++; - } + int draw, split; - /* a shortcut to speed things up */ - if ( level <= 1 ) - { - /* we compute the mid-point directly in order to avoid */ - /* calling gray_split_conic() */ - TPos to_x, to_y, mid_x, mid_y; - - - to_x = UPSCALE( to->x ); - to_y = UPSCALE( to->y ); - mid_x = ( ras.x + to_x + 2 * UPSCALE( control->x ) ) / 4; - mid_y = ( ras.y + to_y + 2 * UPSCALE( control->y ) ) / 4; - - gray_render_line( RAS_VAR_ mid_x, mid_y ); - gray_render_line( RAS_VAR_ to_x, to_y ); - - return; - } - - arc = ras.bez_stack; - levels = ras.lev_stack; - top = 0; - levels[0] = level; arc[0].x = UPSCALE( to->x ); arc[0].y = UPSCALE( to->y ); @@ -892,54 +978,51 @@ arc[2].x = ras.x; arc[2].y = ras.y; - while ( top >= 0 ) + /* short-cut the arc that crosses the current band */ + if ( ( TRUNC( arc[0].y ) >= ras.max_ey && + TRUNC( arc[1].y ) >= ras.max_ey && + TRUNC( arc[2].y ) >= ras.max_ey ) || + ( TRUNC( arc[0].y ) < ras.min_ey && + TRUNC( arc[1].y ) < ras.min_ey && + TRUNC( arc[2].y ) < ras.min_ey ) ) { - level = levels[top]; - if ( level > 1 ) - { - /* check that the arc crosses the current band */ - TPos min, max, y; - - - min = max = arc[0].y; - - y = arc[1].y; - if ( y < min ) min = y; - if ( y > max ) max = y; + ras.x = arc[0].x; + ras.y = arc[0].y; + return; + } - y = arc[2].y; - if ( y < min ) min = y; - if ( y > max ) max = y; + dx = QT_FT_ABS( arc[2].x + arc[0].x - 2 * arc[1].x ); + dy = QT_FT_ABS( arc[2].y + arc[0].y - 2 * arc[1].y ); + if ( dx < dy ) + dx = dy; - if ( TRUNC( min ) >= ras.max_ey || TRUNC( max ) < ras.min_ey ) - goto Draw; + /* We can calculate the number of necessary bisections because */ + /* each bisection predictably reduces deviation exactly 4-fold. */ + /* Even 32-bit deviation would vanish after 16 bisections. */ + draw = 1; + while ( dx > ONE_PIXEL / 4 ) + { + dx >>= 2; + draw <<= 1; + } + /* We use decrement counter to count the total number of segments */ + /* to draw starting from 2^level. Before each draw we split as */ + /* many times as there are trailing zeros in the counter. */ + do + { + split = 1; + while ( ( draw & split ) == 0 ) + { gray_split_conic( arc ); arc += 2; - top++; - levels[top] = levels[top - 1] = level - 1; - continue; + split <<= 1; } - Draw: - { - TPos to_x, to_y, mid_x, mid_y; - - - to_x = arc[0].x; - to_y = arc[0].y; - mid_x = ( ras.x + to_x + 2 * arc[1].x ) / 4; - mid_y = ( ras.y + to_y + 2 * arc[1].y ) / 4; - - gray_render_line( RAS_VAR_ mid_x, mid_y ); - gray_render_line( RAS_VAR_ to_x, to_y ); - - top--; - arc -= 2; - } - } + gray_render_line( RAS_VAR_ arc[0].x, arc[0].y ); + arc -= 2; - return; + } while ( --draw ); } @@ -976,60 +1059,13 @@ const QT_FT_Vector* control2, const QT_FT_Vector* to ) { - TPos dx, dy, da, db; - int top, level; - int* levels; - QT_FT_Vector* arc; + QT_FT_Vector bez_stack[16 * 3 + 1]; /* enough to accommodate bisections */ + QT_FT_Vector* arc = bez_stack; + TPos dx, dy, dx_, dy_; + TPos dx1, dy1, dx2, dy2; + TPos L, s, s_limit; - dx = DOWNSCALE( ras.x ) + to->x - ( control1->x << 1 ); - if ( dx < 0 ) - dx = -dx; - dy = DOWNSCALE( ras.y ) + to->y - ( control1->y << 1 ); - if ( dy < 0 ) - dy = -dy; - if ( dx < dy ) - dx = dy; - da = dx; - - dx = DOWNSCALE( ras.x ) + to->x - 3 * ( control1->x + control2->x ); - if ( dx < 0 ) - dx = -dx; - dy = DOWNSCALE( ras.y ) + to->y - 3 * ( control1->y + control2->y ); - if ( dy < 0 ) - dy = -dy; - if ( dx < dy ) - dx = dy; - db = dx; - - level = 1; - da = da / ras.cubic_level; - db = db / ras.conic_level; - while ( da > 0 || db > 0 ) - { - da >>= 2; - db >>= 3; - level++; - } - - if ( level <= 1 ) - { - TPos to_x, to_y, mid_x, mid_y; - - - to_x = UPSCALE( to->x ); - to_y = UPSCALE( to->y ); - mid_x = ( ras.x + to_x + - 3 * UPSCALE( control1->x + control2->x ) ) / 8; - mid_y = ( ras.y + to_y + - 3 * UPSCALE( control1->y + control2->y ) ) / 8; - - gray_render_line( RAS_VAR_ mid_x, mid_y ); - gray_render_line( RAS_VAR_ to_x, to_y ); - return; - } - - arc = ras.bez_stack; arc[0].x = UPSCALE( to->x ); arc[0].y = UPSCALE( to->y ); arc[1].x = UPSCALE( control2->x ); @@ -1039,56 +1075,77 @@ arc[3].x = ras.x; arc[3].y = ras.y; - levels = ras.lev_stack; - top = 0; - levels[0] = level; + /* short-cut the arc that crosses the current band */ + if ( ( TRUNC( arc[0].y ) >= ras.max_ey && + TRUNC( arc[1].y ) >= ras.max_ey && + TRUNC( arc[2].y ) >= ras.max_ey && + TRUNC( arc[3].y ) >= ras.max_ey ) || + ( TRUNC( arc[0].y ) < ras.min_ey && + TRUNC( arc[1].y ) < ras.min_ey && + TRUNC( arc[2].y ) < ras.min_ey && + TRUNC( arc[3].y ) < ras.min_ey ) ) + { + ras.x = arc[0].x; + ras.y = arc[0].y; + return; + } - while ( top >= 0 ) + for (;;) { - level = levels[top]; - if ( level > 1 ) - { - /* check that the arc crosses the current band */ - TPos min, max, y; - - - min = max = arc[0].y; - y = arc[1].y; - if ( y < min ) min = y; - if ( y > max ) max = y; - y = arc[2].y; - if ( y < min ) min = y; - if ( y > max ) max = y; - y = arc[3].y; - if ( y < min ) min = y; - if ( y > max ) max = y; - if ( TRUNC( min ) >= ras.max_ey || TRUNC( max ) < 0 ) - goto Draw; - gray_split_cubic( arc ); - arc += 3; - top ++; - levels[top] = levels[top - 1] = level - 1; - continue; - } + /* Decide whether to split or draw. See `Rapid Termination */ + /* Evaluation for Recursive Subdivision of Bezier Curves' by Thomas */ + /* F. Hain, at */ + /* http://www.cis.southalabama.edu/~hain/general/Publications/Bezier/Camera-ready%20CISST02%202.pdf */ - Draw: - { - TPos to_x, to_y, mid_x, mid_y; + /* dx and dy are x and y components of the P0-P3 chord vector. */ + dx = dx_ = arc[3].x - arc[0].x; + dy = dy_ = arc[3].y - arc[0].y; - to_x = arc[0].x; - to_y = arc[0].y; - mid_x = ( ras.x + to_x + 3 * ( arc[1].x + arc[2].x ) ) / 8; - mid_y = ( ras.y + to_y + 3 * ( arc[1].y + arc[2].y ) ) / 8; + L = QT_FT_HYPOT( dx_, dy_ ); - gray_render_line( RAS_VAR_ mid_x, mid_y ); - gray_render_line( RAS_VAR_ to_x, to_y ); - top --; - arc -= 3; - } - } + /* Avoid possible arithmetic overflow below by splitting. */ + if ( L > 32767 ) + goto Split; + + /* Max deviation may be as much as (s/L) * 3/4 (if Hain's v = 1). */ + s_limit = L * (TPos)( ONE_PIXEL / 6 ); + + /* s is L * the perpendicular distance from P1 to the line P0-P3. */ + dx1 = arc[1].x - arc[0].x; + dy1 = arc[1].y - arc[0].y; + s = QT_FT_ABS( dy * dx1 - dx * dy1 ); + + if ( s > s_limit ) + goto Split; + + /* s is L * the perpendicular distance from P2 to the line P0-P3. */ + dx2 = arc[2].x - arc[0].x; + dy2 = arc[2].y - arc[0].y; + s = QT_FT_ABS( dy * dx2 - dx * dy2 ); + + if ( s > s_limit ) + goto Split; + + /* Split super curvy segments where the off points are so far + from the chord that the angles P0-P1-P3 or P0-P2-P3 become + acute as detected by appropriate dot products. */ + if ( dx1 * ( dx1 - dx ) + dy1 * ( dy1 - dy ) > 0 || + dx2 * ( dx2 - dx ) + dy2 * ( dy2 - dy ) > 0 ) + goto Split; - return; + gray_render_line( RAS_VAR_ arc[0].x, arc[0].y ); + + if ( arc == bez_stack ) + return; + + arc -= 3; + continue; + + Split: + gray_split_cubic( arc ); + arc += 3; + } } @@ -1101,7 +1158,8 @@ /* record current cell, if any */ - gray_record_cell( worker ); + if ( !ras.invalid ) + gray_record_cell( worker ); /* start to a new position */ x = UPSCALE( to->x ); @@ -1109,15 +1167,15 @@ gray_start_cell( worker, TRUNC( x ), TRUNC( y ) ); - worker->x = x; - worker->y = y; + ras.x = x; + ras.y = y; return 0; } static void - gray_render_span( int count, + gray_render_span( int count, const QT_FT_Span* spans, - PWorker worker ) + PWorker worker ) { unsigned char* p; QT_FT_Bitmap* map = &worker->target; @@ -1129,34 +1187,30 @@ /* first of all, compute the scanline offset */ p = (unsigned char*)map->buffer - spans->y * map->pitch; if ( map->pitch >= 0 ) - p += ( map->rows - 1 ) * map->pitch; + p += ( map->rows - 1 ) * (unsigned int)map->pitch; if ( coverage ) { + unsigned char* q = p + spans->x; + + /* For small-spans it is faster to do it by ourselves than * calling `memset'. This is mainly due to the cost of the * function call. */ - if ( spans->len >= 8 ) - QT_FT_MEM_SET( p + spans->x, (unsigned char)coverage, spans->len ); - else + switch ( spans->len ) { - unsigned char* q = p + spans->x; - - - switch ( spans->len ) - { - case 7: *q++ = (unsigned char)coverage; - case 6: *q++ = (unsigned char)coverage; - case 5: *q++ = (unsigned char)coverage; - case 4: *q++ = (unsigned char)coverage; - case 3: *q++ = (unsigned char)coverage; - case 2: *q++ = (unsigned char)coverage; - case 1: *q = (unsigned char)coverage; - default: - ; - } + case 7: *q++ = coverage; + case 6: *q++ = coverage; + case 5: *q++ = coverage; + case 4: *q++ = coverage; + case 3: *q++ = coverage; + case 2: *q++ = coverage; + case 1: *q = coverage; + case 0: break; + default: + QT_FT_MEM_SET( q, coverage, spans->len ); } } } @@ -1169,9 +1223,7 @@ TPos area, int acount ) { - QT_FT_Span* span; - int coverage; - int skip; + int coverage; /* compute the coverage line's coverage, depending on the */ @@ -1204,14 +1256,24 @@ x += (TCoord)ras.min_ex; /* QT_FT_Span.x is a 16-bit short, so limit our coordinates appropriately */ - if ( x >= 32768 ) + if ( x >= 32767 ) x = 32767; + /* QT_FT_Span.y is a 16-bit short, so limit our coordinates appropriately */ + if ( y >= 32767 ) + y = 32767; + if ( coverage ) { + QT_FT_Span* span; + int count; + int skip; + + /* see whether we can add this span to the current list */ - span = ras.gray_spans + ras.num_gray_spans - 1; - if ( ras.num_gray_spans > 0 && + count = ras.num_gray_spans; + span = ras.gray_spans + count - 1; + if ( count > 0 && span->y == y && (int)span->x + span->len == (int)x && span->coverage == coverage ) @@ -1220,9 +1282,9 @@ return; } - if ( ras.num_gray_spans >= QT_FT_MAX_GRAY_SPANS ) + if ( count >= QT_FT_MAX_GRAY_SPANS ) { - if ( ras.render_span && ras.num_gray_spans > ras.skip_spans ) + if ( ras.render_span && count > ras.skip_spans ) { skip = ras.skip_spans > 0 ? ras.skip_spans : 0; ras.render_span( ras.num_gray_spans - skip, @@ -1304,6 +1366,8 @@ if ( ras.num_cells == 0 ) return; + QT_FT_TRACE7(( "gray_sweep: start\n" )); + for ( yindex = 0; yindex < ras.ycount; yindex++ ) { PCell cell = ras.ycells[yindex]; @@ -1333,6 +1397,8 @@ gray_hline( RAS_VAR_ x, yindex, cover * ( ONE_PIXEL * 2 ), ras.count_ex - x ); } + + QT_FT_TRACE7(( "gray_sweep: end\n" )); } /*************************************************************************/ @@ -1366,7 +1432,7 @@ /* */ static int QT_FT_Outline_Decompose( const QT_FT_Outline* outline, - void* user ) + void* user ) { #undef SCALED #define SCALED( x ) (x) @@ -1384,6 +1450,9 @@ int error; char tag; /* current point's state */ + if ( !outline ) + return ErrRaster_Invalid_Outline; + first = 0; for ( n = 0; n < outline->n_contours; n++ ) @@ -1392,16 +1461,17 @@ last = outline->contours[n]; + if ( last < 0 ) + goto Invalid_Outline; limit = outline->points + last; - v_start = outline->points[first]; - v_last = outline->points[last]; - + v_start = outline->points[first]; v_start.x = SCALED( v_start.x ); v_start.y = SCALED( v_start.y ); - v_last.x = SCALED( v_last.x ); - v_last.y = SCALED( v_last.y ); + v_last = outline->points[last]; + v_last.x = SCALED( v_last.x ); + v_last.y = SCALED( v_last.y ); v_control = v_start; @@ -1437,6 +1507,8 @@ tags--; } + QT_FT_TRACE5(( " move to (%.2f, %.2f)\n", + v_start.x / 64.0, v_start.y / 64.0 )); error = gray_move_to( &v_start, user ); if ( error ) goto Exit; @@ -1457,6 +1529,8 @@ vec.x = SCALED( point->x ); vec.y = SCALED( point->y ); + QT_FT_TRACE5(( " line to (%.2f, %.2f)\n", + vec.x / 64.0, vec.y / 64.0 )); gray_render_line(user, UPSCALE(vec.x), UPSCALE(vec.y)); continue; } @@ -1482,6 +1556,10 @@ if ( tag == QT_FT_CURVE_TAG_ON ) { + QT_FT_TRACE5(( " conic to (%.2f, %.2f)" + " with control (%.2f, %.2f)\n", + vec.x / 64.0, vec.y / 64.0, + v_control.x / 64.0, v_control.y / 64.0 )); gray_render_conic(user, &v_control, &vec); continue; } @@ -1492,11 +1570,20 @@ v_middle.x = ( v_control.x + vec.x ) / 2; v_middle.y = ( v_control.y + vec.y ) / 2; + QT_FT_TRACE5(( " conic to (%.2f, %.2f)" + " with control (%.2f, %.2f)\n", + v_middle.x / 64.0, v_middle.y / 64.0, + v_control.x / 64.0, v_control.y / 64.0 )); gray_render_conic(user, &v_control, &v_middle); + v_control = vec; goto Do_Conic; } + QT_FT_TRACE5(( " conic to (%.2f, %.2f)" + " with control (%.2f, %.2f)\n", + v_start.x / 64.0, v_start.y / 64.0, + v_control.x / 64.0, v_control.y / 64.0 )); gray_render_conic(user, &v_control, &v_start); goto Close; } @@ -1527,10 +1614,20 @@ vec.x = SCALED( point->x ); vec.y = SCALED( point->y ); + QT_FT_TRACE5(( " cubic to (%.2f, %.2f)" + " with controls (%.2f, %.2f) and (%.2f, %.2f)\n", + vec.x / 64.0, vec.y / 64.0, + vec1.x / 64.0, vec1.y / 64.0, + vec2.x / 64.0, vec2.y / 64.0 )); gray_render_cubic(user, &vec1, &vec2, &vec); continue; } + QT_FT_TRACE5(( " cubic to (%.2f, %.2f)" + " with controls (%.2f, %.2f) and (%.2f, %.2f)\n", + v_start.x / 64.0, v_start.y / 64.0, + vec1.x / 64.0, vec1.y / 64.0, + vec2.x / 64.0, vec2.y / 64.0 )); gray_render_cubic(user, &vec1, &vec2, &v_start); goto Close; } @@ -1538,15 +1635,19 @@ } /* close the contour with a line segment */ + QT_FT_TRACE5(( " line to (%.2f, %.2f)\n", + v_start.x / 64.0, v_start.y / 64.0 )); gray_render_line(user, UPSCALE(v_start.x), UPSCALE(v_start.y)); Close: first = last + 1; } + QT_FT_TRACE5(( "FT_Outline_Decompose: Done\n", n )); return 0; Exit: + QT_FT_TRACE5(( "FT_Outline_Decompose: Error %d\n", error )); return error; Invalid_Outline: @@ -1559,7 +1660,6 @@ } TBand; - static int gray_convert_glyph_inner( RAS_ARG ) { @@ -1568,7 +1668,8 @@ if ( qt_ft_setjmp( ras.jump_buffer ) == 0 ) { error = QT_FT_Outline_Decompose( &ras.outline, &ras ); - gray_record_cell( RAS_VAR ); + if ( !ras.invalid ) + gray_record_cell( RAS_VAR ); } else { @@ -1610,29 +1711,12 @@ ras.count_ex = ras.max_ex - ras.min_ex; ras.count_ey = ras.max_ey - ras.min_ey; - /* simple heuristic used to speed-up the bezier decomposition -- see */ - /* the code in gray_render_conic() and gray_render_cubic() for more */ - /* details */ - ras.conic_level = 32; - ras.cubic_level = 16; - - { - int level = 0; - - - if ( ras.count_ex > 24 || ras.count_ey > 24 ) - level++; - if ( ras.count_ex > 120 || ras.count_ey > 120 ) - level++; - - ras.conic_level <<= level; - ras.cubic_level <<= level; - } - - /* setup vertical bands */ + /* set up vertical bands */ num_bands = (int)( ( ras.max_ey - ras.min_ey ) / ras.band_size ); - if ( num_bands == 0 ) num_bands = 1; - if ( num_bands >= 39 ) num_bands = 39; + if ( num_bands == 0 ) + num_bands = 1; + if ( num_bands >= 39 ) + num_bands = 39; ras.band_shoot = 0; @@ -1766,11 +1850,14 @@ if (raster->buffer_allocated_size < MINIMUM_POOL_SIZE ) return ErrRaster_OutOfMemory; + if ( !outline ) + return ErrRaster_Invalid_Outline; + /* return immediately if the outline is empty */ if ( outline->n_points == 0 || outline->n_contours <= 0 ) return 0; - if ( !outline || !outline->contours || !outline->points ) + if ( !outline->contours || !outline->points ) return ErrRaster_Invalid_Outline; if ( outline->n_points != diff --git a/src/gui/painting/qpdf.cpp b/src/gui/painting/qpdf.cpp index 7b8bae16421..bac97408924 100644 --- a/src/gui/painting/qpdf.cpp +++ b/src/gui/painting/qpdf.cpp @@ -1465,6 +1465,7 @@ void QPdfEnginePrivate::writeHeader() addXrefEntry(0,false); xprintf("%%PDF-1.4\n"); + xprintf("%%\303\242\303\243\n"); writeInfo(); @@ -1597,7 +1598,7 @@ void QPdfEnginePrivate::embedFont(QFontSubset *font) "/CapHeight " << properties.capHeight.toReal()*scale << "\n" "/StemV " << properties.lineWidth.toReal()*scale << "\n" "/FontFile2 " << fontstream << "0 R\n" - ">> endobj\n"; + ">>\nendobj\n"; write(descriptor); } { @@ -1615,7 +1616,7 @@ void QPdfEnginePrivate::embedFont(QFontSubset *font) "stream\n"; write(header); int len = writeCompressed(fontData); - write("endstream\n" + write("\nendstream\n" "endobj\n"); addXrefEntry(length_object); xprintf("%d\n" @@ -1642,7 +1643,7 @@ void QPdfEnginePrivate::embedFont(QFontSubset *font) xprintf("<< /Length %d >>\n" "stream\n", touc.length()); write(touc); - write("endstream\n" + write("\nendstream\n" "endobj\n"); } { @@ -1748,7 +1749,7 @@ void QPdfEnginePrivate::writePage() xprintf("stream\n"); QIODevice *content = currentPage->stream(); int len = writeCompressed(content); - xprintf("endstream\n" + xprintf("\nendstream\n" "endobj\n"); addXrefEntry(pageStreamLength); @@ -1794,7 +1795,13 @@ int QPdfEnginePrivate::addXrefEntry(int object, bool printostr) return object; } -void QPdfEnginePrivate::printString(const QString &string) { +void QPdfEnginePrivate::printString(const QString &string) +{ + if (string.isEmpty()) { + write("()"); + return; + } + // The 'text string' type in PDF is encoded either as PDFDocEncoding, or // Unicode UTF-16 with a Unicode byte order mark as the first character // (0xfeff), with the high-order byte first. diff --git a/src/gui/painting/qplatformbackingstore.cpp b/src/gui/painting/qplatformbackingstore.cpp index b8bbdefa374..e006fad437b 100644 --- a/src/gui/painting/qplatformbackingstore.cpp +++ b/src/gui/painting/qplatformbackingstore.cpp @@ -70,6 +70,13 @@ #define GL_UNSIGNED_INT_2_10_10_10_REV 0x8368 #endif +#ifndef GL_FRAMEBUFFER_SRB +#define GL_FRAMEBUFFER_SRGB 0x8DB9 +#endif +#ifndef GL_FRAMEBUFFER_SRGB_CAPABLE +#define GL_FRAMEBUFFER_SRGB_CAPABLE 0x8DBA +#endif + QT_BEGIN_NAMESPACE class QPlatformBackingStorePrivate @@ -269,7 +276,7 @@ static inline QRect toBottomLeftRect(const QRect &topLeftRect, int windowHeight) } static void blitTextureForWidget(const QPlatformTextureList *textures, int idx, QWindow *window, const QRect &deviceWindowRect, - QOpenGLTextureBlitter *blitter, const QPoint &offset) + QOpenGLTextureBlitter *blitter, const QPoint &offset, bool canUseSrgb) { const QRect clipRect = textures->clipRect(idx); if (clipRect.isEmpty()) @@ -289,7 +296,15 @@ static void blitTextureForWidget(const QPlatformTextureList *textures, int idx, deviceRect(rectInWindow, window).size(), QOpenGLTextureBlitter::OriginBottomLeft); + QOpenGLFunctions *funcs = QOpenGLContext::currentContext()->functions(); + const bool srgb = textures->flags(idx).testFlag(QPlatformTextureList::TextureIsSrgb); + if (srgb && canUseSrgb) + funcs->glEnable(GL_FRAMEBUFFER_SRGB); + blitter->blit(textures->textureId(idx), target, source); + + if (srgb && canUseSrgb) + funcs->glDisable(GL_FRAMEBUFFER_SRGB); } /*! @@ -334,10 +349,23 @@ void QPlatformBackingStore::composeAndFlush(QWindow *window, const QRegion ®i const QRect deviceWindowRect = deviceRect(QRect(QPoint(), window->size()), window); + bool canUseSrgb = false; + // If there are any sRGB textures in the list, check if the destination + // framebuffer is sRGB capable. + for (int i = 0; i < textures->count(); ++i) { + if (textures->flags(i).testFlag(QPlatformTextureList::TextureIsSrgb)) { + GLint cap = 0; + funcs->glGetIntegerv(GL_FRAMEBUFFER_SRGB_CAPABLE, &cap); + if (cap) + canUseSrgb = true; + break; + } + } + // Textures for renderToTexture widgets. for (int i = 0; i < textures->count(); ++i) { if (!textures->flags(i).testFlag(QPlatformTextureList::StacksOnTop)) - blitTextureForWidget(textures, i, window, deviceWindowRect, d_ptr->blitter, offset); + blitTextureForWidget(textures, i, window, deviceWindowRect, d_ptr->blitter, offset, canUseSrgb); } // Backingstore texture with the normal widgets. @@ -406,7 +434,7 @@ void QPlatformBackingStore::composeAndFlush(QWindow *window, const QRegion ®i // Textures for renderToTexture widgets that have WA_AlwaysStackOnTop set. for (int i = 0; i < textures->count(); ++i) { if (textures->flags(i).testFlag(QPlatformTextureList::StacksOnTop)) - blitTextureForWidget(textures, i, window, deviceWindowRect, d_ptr->blitter, offset); + blitTextureForWidget(textures, i, window, deviceWindowRect, d_ptr->blitter, offset, canUseSrgb); } funcs->glDisable(GL_BLEND); diff --git a/src/gui/painting/qplatformbackingstore.h b/src/gui/painting/qplatformbackingstore.h index ec56aaa002f..d1ce67a65da 100644 --- a/src/gui/painting/qplatformbackingstore.h +++ b/src/gui/painting/qplatformbackingstore.h @@ -78,7 +78,8 @@ class Q_GUI_EXPORT QPlatformTextureList : public QObject Q_DECLARE_PRIVATE(QPlatformTextureList) public: enum Flag { - StacksOnTop = 0x01 + StacksOnTop = 0x01, + TextureIsSrgb = 0x02 }; Q_DECLARE_FLAGS(Flags, Flag) diff --git a/src/gui/text/qdistancefield.cpp b/src/gui/text/qdistancefield.cpp index 933dd1bf540..0a2ea8fdb25 100644 --- a/src/gui/text/qdistancefield.cpp +++ b/src/gui/text/qdistancefield.cpp @@ -437,7 +437,7 @@ static void drawPolygons(qint32 *bits, int width, int height, const QPoint *vert { Q_ASSERT(indexCount != 0); Q_ASSERT(height <= 128); - QVarLengthArray<quint8, 16> scans[128]; + QVarLengthArray<quint16, 16> scans[128]; int first = 0; for (int i = 1; i < indexCount; ++i) { quint32 idx1 = indices[i - 1]; @@ -461,16 +461,16 @@ static void drawPolygons(qint32 *bits, int width, int height, const QPoint *vert for (int y = fromY; y < toY; ++y) { quint32 c = quint32(x >> 8); if (c < quint32(width)) - scans[y].append(quint8(c)); + scans[y].append(quint16(c)); x += dx; } } for (int i = 0; i < height; ++i) { - quint8 *scanline = scans[i].data(); + quint16 *scanline = scans[i].data(); int size = scans[i].size(); for (int j = 1; j < size; ++j) { int k = j; - quint8 value = scanline[k]; + quint16 value = scanline[k]; for (; k != 0 && value < scanline[k - 1]; --k) scanline[k] = scanline[k - 1]; scanline[k] = value; @@ -478,7 +478,7 @@ static void drawPolygons(qint32 *bits, int width, int height, const QPoint *vert qint32 *line = bits + i * width; int j = 0; for (; j + 1 < size; j += 2) { - for (quint8 x = scanline[j]; x < scanline[j + 1]; ++x) + for (quint16 x = scanline[j]; x < scanline[j + 1]; ++x) line[x] = value; } if (j < size) { diff --git a/src/gui/text/qfontsubset.cpp b/src/gui/text/qfontsubset.cpp index 92eeaf79190..f5fc562e136 100644 --- a/src/gui/text/qfontsubset.cpp +++ b/src/gui/text/qfontsubset.cpp @@ -136,7 +136,7 @@ QByteArray QFontSubset::widthArray() const QByteArray width; QPdf::ByteStream s(&width); - QFixed scale = QFixed(1000)/emSquare; + const qreal scale = 1000.0/emSquare.toInt(); QFixed defWidth = widths[0]; //qDebug("defWidth=%d, scale=%f", defWidth.toInt(), scale.toReal()); @@ -145,7 +145,7 @@ QByteArray QFontSubset::widthArray() const defWidth = 0; } if (defWidth > 0) { - s << "/DW " << (defWidth*scale).toInt(); + s << "/DW " << qRound(defWidth.toInt() * scale); } else { s << "/W ["; for (int g = 0; g < nGlyphs();) { @@ -174,11 +174,11 @@ QByteArray QFontSubset::widthArray() const if (endnonlinear > start) { s << start << '['; for (int i = start; i < endnonlinear; ++i) - s << (widths[i]*scale).toInt(); + s << qRound(widths[i].toInt() * scale); s << "]\n"; } if (startLinear) - s << startLinear << g - 1 << (widths[startLinear]*scale).toInt() << '\n'; + s << startLinear << g - 1 << qRound(widths[startLinear].toInt() * scale) << '\n'; } s << "]\n"; } diff --git a/src/network/access/qhttpthreaddelegate.cpp b/src/network/access/qhttpthreaddelegate.cpp index 6e5e29d7bf2..e9b3760ce53 100644 --- a/src/network/access/qhttpthreaddelegate.cpp +++ b/src/network/access/qhttpthreaddelegate.cpp @@ -44,6 +44,7 @@ #include <QTimer> #include <QAuthenticator> #include <QEventLoop> +#include <QCryptographicHash> #include "private/qhttpnetworkreply_p.h" #include "private/qnetworkaccesscache_p.h" @@ -158,7 +159,10 @@ static QByteArray makeCacheKey(QUrl &url, QNetworkProxy *proxy) } if (!key.scheme().isEmpty()) { + const QByteArray obfuscatedPassword = QCryptographicHash::hash(proxy->password().toUtf8(), + QCryptographicHash::Sha1).toHex(); key.setUserName(proxy->user()); + key.setPassword(QString::fromUtf8(obfuscatedPassword)); key.setHost(proxy->hostName()); key.setPort(proxy->port()); key.setQuery(result); diff --git a/src/network/socket/qnativesocketengine_unix.cpp b/src/network/socket/qnativesocketengine_unix.cpp index e140b33ce9e..1e69aebb54d 100644 --- a/src/network/socket/qnativesocketengine_unix.cpp +++ b/src/network/socket/qnativesocketengine_unix.cpp @@ -668,8 +668,7 @@ static bool multicastMembershipHelper(QNativeSocketEnginePrivate *d, Q_IPV6ADDR ip6 = groupAddress.toIPv6Address(); memcpy(&mreq6.ipv6mr_multiaddr, &ip6, sizeof(ip6)); mreq6.ipv6mr_interface = interface.index(); - } else - if (groupAddress.protocol() == QAbstractSocket::IPv4Protocol) { + } else if (groupAddress.protocol() == QAbstractSocket::IPv4Protocol) { level = IPPROTO_IP; sockOpt = how4; sockArg = &mreq4; diff --git a/src/network/socket/qnativesocketengine_win.cpp b/src/network/socket/qnativesocketengine_win.cpp index 28aea6be3d9..2088d3927e3 100644 --- a/src/network/socket/qnativesocketengine_win.cpp +++ b/src/network/socket/qnativesocketengine_win.cpp @@ -943,9 +943,7 @@ static bool multicastMembershipHelper(QNativeSocketEnginePrivate *d, Q_IPV6ADDR ip6 = groupAddress.toIPv6Address(); memcpy(&mreq6.ipv6mr_multiaddr, &ip6, sizeof(ip6)); mreq6.ipv6mr_interface = iface.index(); - } else - - if (groupAddress.protocol() == QAbstractSocket::IPv4Protocol) { + } else if (groupAddress.protocol() == QAbstractSocket::IPv4Protocol) { level = IPPROTO_IP; sockOpt = how4; sockArg = reinterpret_cast<char *>(&mreq4); diff --git a/src/network/ssl/qsslsocket.cpp b/src/network/ssl/qsslsocket.cpp index bb0d949684e..b4109cadb58 100644 --- a/src/network/ssl/qsslsocket.cpp +++ b/src/network/ssl/qsslsocket.cpp @@ -971,6 +971,13 @@ QList<QSslCertificate> QSslSocket::localCertificateChain() const sockets, but are also rarely used by client sockets if the server requires the client to authenticate. + \note Secure Transport SSL backend on macOS may update the default keychain + (the default is probably your login keychain) by importing your local certificates + and keys. This can also result in system dialogs showing up and asking for + permission when your application is using these private keys. If such behavior + is undesired, set the QT_SSL_USE_TEMPORARY_KEYCHAIN environment variable to a + non-zero value; this will prompt QSslSocket to use its own temporary keychain. + \sa localCertificate(), setPrivateKey() */ void QSslSocket::setLocalCertificate(const QSslCertificate &certificate) diff --git a/src/network/ssl/qsslsocket_mac.cpp b/src/network/ssl/qsslsocket_mac.cpp index 752640bd467..07de954ceff 100644 --- a/src/network/ssl/qsslsocket_mac.cpp +++ b/src/network/ssl/qsslsocket_mac.cpp @@ -53,9 +53,12 @@ #include <QtCore/qvector.h> #include <QtCore/qmutex.h> #include <QtCore/qdebug.h> +#include <QtCore/quuid.h> +#include <QtCore/qdir.h> #include <algorithm> #include <cstddef> +#include <vector> #include <QtCore/private/qcore_mac_p.h> @@ -65,6 +68,102 @@ QT_BEGIN_NAMESPACE +namespace +{ +#ifdef Q_OS_MACOS +/* + +Our own temporarykeychain is needed only on macOS where SecPKCS12Import changes +the default keychain and where we see annoying pop-ups asking about accessing a +private key. + +*/ + +struct EphemeralSecKeychain +{ + EphemeralSecKeychain(); + ~EphemeralSecKeychain(); + + SecKeychainRef keychain = nullptr; + Q_DISABLE_COPY(EphemeralSecKeychain) +}; + +EphemeralSecKeychain::EphemeralSecKeychain() +{ + const auto uuid = QUuid::createUuid(); + if (uuid.isNull()) { + qCWarning(lcSsl) << "Failed to create an unique keychain name"; + return; + } + + QString uuidAsString(uuid.toString()); + Q_ASSERT(uuidAsString.size() > 2); + Q_ASSERT(uuidAsString.startsWith(QLatin1Char('{')) + && uuidAsString.endsWith(QLatin1Char('}'))); + uuidAsString = uuidAsString.mid(1, uuidAsString.size() - 2); + + QString keychainName(QDir::tempPath()); + keychainName.append(QDir::separator()); + keychainName += uuidAsString; + keychainName += QLatin1String(".keychain"); + // SecKeychainCreate, pathName parameter: + // + // "A constant character string representing the POSIX path indicating where + // to store the keychain." + // + // Internally they seem to use std::string, but this does not really help. + // Fortunately, CFString has a convenient API. + QCFType<CFStringRef> cfName = keychainName.toCFString(); + std::vector<char> posixPath; + // "Extracts the contents of a string as a NULL-terminated 8-bit string + // appropriate for passing to POSIX APIs." + posixPath.resize(CFStringGetMaximumSizeOfFileSystemRepresentation(cfName)); + const auto ok = CFStringGetFileSystemRepresentation(cfName, &posixPath[0], + CFIndex(posixPath.size())); + if (!ok) { + qCWarning(lcSsl) << "Failed to create a unique keychain name from" + << "QDir::tempPath()"; + return; + } + + std::vector<uint8_t> passUtf8(256); + if (SecRandomCopyBytes(kSecRandomDefault, passUtf8.size(), &passUtf8[0])) { + qCWarning(lcSsl) << "SecRandomCopyBytes: failed to create a key"; + return; + } + + const OSStatus status = SecKeychainCreate(&posixPath[0], passUtf8.size(), + &passUtf8[0], FALSE, nullptr, + &keychain); + if (status != errSecSuccess || !keychain) { + qCWarning(lcSsl) << "SecKeychainCreate: failed to create a custom keychain"; + if (keychain) { + SecKeychainDelete(keychain); + CFRelease(keychain); + keychain = nullptr; + } + } + +#ifdef QSSLSOCKET_DEBUG + if (keychain) { + qCDebug(lcSsl) << "Custom keychain with name" << keychainName << "was created" + << "successfully"; + } +#endif +} + +EphemeralSecKeychain::~EphemeralSecKeychain() +{ + if (keychain) { + // clear file off disk + SecKeychainDelete(keychain); + CFRelease(keychain); + } +} + +#endif // Q_OS_MACOS +} + static SSLContextRef qt_createSecureTransportContext(QSslSocket::SslMode mode) { const bool isServer = mode == QSslSocket::SslServerMode; @@ -794,11 +893,24 @@ bool QSslSocketBackendPrivate::setSessionCertificate(QString &errorDescription, QCFType<CFDataRef> pkcs12 = _q_makePkcs12(configuration.localCertificateChain, configuration.privateKey, passPhrase).toCFData(); QCFType<CFStringRef> password = passPhrase.toCFString(); - const void *keys[] = { kSecImportExportPassphrase }; - const void *values[] = { password }; - QCFType<CFDictionaryRef> options(CFDictionaryCreate(Q_NULLPTR, keys, values, 1, - Q_NULLPTR, Q_NULLPTR)); - CFArrayRef items = Q_NULLPTR; + const void *keys[2] = { kSecImportExportPassphrase }; + const void *values[2] = { password }; + CFIndex nKeys = 1; +#ifdef Q_OS_MACOS + bool envOk = false; + const int env = qEnvironmentVariableIntValue("QT_SSL_USE_TEMPORARY_KEYCHAIN", &envOk); + if (envOk && env) { + static const EphemeralSecKeychain temporaryKeychain; + if (temporaryKeychain.keychain) { + nKeys = 2; + keys[1] = kSecImportExportKeychain; + values[1] = temporaryKeychain.keychain; + } + } +#endif + QCFType<CFDictionaryRef> options = CFDictionaryCreate(nullptr, keys, values, nKeys, + nullptr, nullptr); + CFArrayRef items = nullptr; OSStatus err = SecPKCS12Import(pkcs12, options, &items); if (err != noErr) { #ifdef QSSLSOCKET_DEBUG @@ -830,7 +942,7 @@ bool QSslSocketBackendPrivate::setSessionCertificate(QString &errorDescription, return false; } - QCFType<CFMutableArrayRef> certs = CFArrayCreateMutable(Q_NULLPTR, 0, &kCFTypeArrayCallBacks); + QCFType<CFMutableArrayRef> certs = CFArrayCreateMutable(nullptr, 0, &kCFTypeArrayCallBacks); if (!certs) { errorCode = QAbstractSocket::SslInternalError; errorDescription = QStringLiteral("Failed to allocate certificates array"); @@ -975,6 +1087,12 @@ bool QSslSocketBackendPrivate::verifySessionProtocol() const protocolOk = (sessionProtocol() >= QSsl::SslV3); else if (configuration.protocol == QSsl::SecureProtocols) protocolOk = (sessionProtocol() >= QSsl::TlsV1_0); + else if (configuration.protocol == QSsl::TlsV1_0OrLater) + protocolOk = (sessionProtocol() >= QSsl::TlsV1_0); + else if (configuration.protocol == QSsl::TlsV1_1OrLater) + protocolOk = (sessionProtocol() >= QSsl::TlsV1_1); + else if (configuration.protocol == QSsl::TlsV1_2OrLater) + protocolOk = (sessionProtocol() >= QSsl::TlsV1_2); else protocolOk = (sessionProtocol() == configuration.protocol); diff --git a/src/network/ssl/qsslsocket_openssl.cpp b/src/network/ssl/qsslsocket_openssl.cpp index aca7507d13f..28576f11678 100644 --- a/src/network/ssl/qsslsocket_openssl.cpp +++ b/src/network/ssl/qsslsocket_openssl.cpp @@ -213,6 +213,48 @@ static unsigned int q_ssl_psk_server_callback(SSL *ssl, #endif } // extern "C" +static void q_OpenSSL_add_all_algorithms_safe() +{ +#ifdef Q_OS_WIN + // Prior to version 1.0.1m an attempt to call OpenSSL_add_all_algorithms on + // Windows could result in 'exit' call from OPENSSL_config (QTBUG-43843). + // We can predict this and avoid OPENSSL_add_all_algorithms call. + // From OpenSSL docs: + // "An application does not need to add algorithms to use them explicitly, + // for example by EVP_sha1(). It just needs to add them if it (or any of + // the functions it calls) needs to lookup algorithms. + // The cipher and digest lookup functions are used in many parts of the + // library. If the table is not initialized several functions will + // misbehave and complain they cannot find algorithms. This includes the + // PEM, PKCS#12, SSL and S/MIME libraries. This is a common query in + // the OpenSSL mailing lists." + // + // Anyway, as a result, we chose not to call this function if it would exit. + + if (q_SSLeay() < 0x100010DFL) + { + // Now, before we try to call it, check if an attempt to open config file + // will result in exit: + if (char *confFileName = q_CONF_get1_default_config_file()) { + BIO *confFile = q_BIO_new_file(confFileName, "r"); + const auto lastError = q_ERR_peek_last_error(); + q_OPENSSL_free(confFileName); + if (confFile) { + q_BIO_free(confFile); + } else { + q_ERR_clear_error(); + if (ERR_GET_REASON(lastError) == ERR_R_SYS_LIB) { + qCWarning(lcSsl, "failed to open openssl.conf file"); + return; + } + } + } + } +#endif // Q_OS_WIN + + q_OpenSSL_add_all_algorithms(); +} + QSslSocketBackendPrivate::QSslSocketBackendPrivate() : ssl(0), readBio(0), @@ -504,7 +546,7 @@ bool QSslSocketPrivate::ensureLibraryLoaded() if (q_SSL_library_init() != 1) return false; q_SSL_load_error_strings(); - q_OpenSSL_add_all_algorithms(); + q_OpenSSL_add_all_algorithms_safe(); #if OPENSSL_VERSION_NUMBER >= 0x10001000L if (q_SSLeay() >= 0x10001000L) diff --git a/src/network/ssl/qsslsocket_openssl_symbols.cpp b/src/network/ssl/qsslsocket_openssl_symbols.cpp index 2a0d746fde7..02364b194bb 100644 --- a/src/network/ssl/qsslsocket_openssl_symbols.cpp +++ b/src/network/ssl/qsslsocket_openssl_symbols.cpp @@ -144,6 +144,9 @@ DEFINEFUNC(unsigned char *, ASN1_STRING_data, ASN1_STRING *a, a, return 0, retur DEFINEFUNC(int, ASN1_STRING_length, ASN1_STRING *a, a, return 0, return) DEFINEFUNC2(int, ASN1_STRING_to_UTF8, unsigned char **a, a, ASN1_STRING *b, b, return 0, return); DEFINEFUNC4(long, BIO_ctrl, BIO *a, a, int b, b, long c, c, void *d, d, return -1, return) +DEFINEFUNC2(BIO *, BIO_new_file, const char *filename, filename, const char *mode, mode, return 0, return) +DEFINEFUNC(void, ERR_clear_error, DUMMYARG, DUMMYARG, return, DUMMYARG) +DEFINEFUNC(void, OPENSSL_free, void *ptr, ptr, return, DUMMYARG) DEFINEFUNC(int, BIO_free, BIO *a, a, return 0, return) DEFINEFUNC(BIO *, BIO_new, BIO_METHOD *a, a, return 0, return) DEFINEFUNC2(BIO *, BIO_new_mem_buf, void *a, a, int b, b, return 0, return) @@ -168,6 +171,7 @@ DEFINEFUNC(void, DSA_free, DSA *a, a, return, DUMMYARG) DEFINEFUNC3(X509 *, d2i_X509, X509 **a, a, const unsigned char **b, b, long c, c, return 0, return) DEFINEFUNC2(char *, ERR_error_string, unsigned long a, a, char *b, b, return 0, return) DEFINEFUNC(unsigned long, ERR_get_error, DUMMYARG, DUMMYARG, return 0, return) +DEFINEFUNC(unsigned long, ERR_peek_last_error, DUMMYARG, DUMMYARG, return 0, return) DEFINEFUNC(void, ERR_free_strings, void, DUMMYARG, return, DUMMYARG) DEFINEFUNC(void, EVP_CIPHER_CTX_cleanup, EVP_CIPHER_CTX *a, a, return, DUMMYARG) DEFINEFUNC(void, EVP_CIPHER_CTX_init, EVP_CIPHER_CTX *a, a, return, DUMMYARG) @@ -407,6 +411,7 @@ DEFINEFUNC3(DSA *, d2i_DSAPrivateKey, DSA **a, a, unsigned char **b, b, long c, DEFINEFUNC3(EC_KEY *, d2i_ECPrivateKey, EC_KEY **a, a, unsigned char **b, b, long c, c, return 0, return) #endif #endif +DEFINEFUNC(char *, CONF_get1_default_config_file, DUMMYARG, DUMMYARG, return 0, return) DEFINEFUNC(void, OPENSSL_add_all_algorithms_noconf, void, DUMMYARG, return, DUMMYARG) DEFINEFUNC(void, OPENSSL_add_all_algorithms_conf, void, DUMMYARG, return, DUMMYARG) DEFINEFUNC3(int, SSL_CTX_load_verify_locations, SSL_CTX *ctx, ctx, const char *CAfile, CAfile, const char *CApath, CApath, return 0, return) @@ -780,6 +785,9 @@ bool q_resolveOpenSslSymbols() RESOLVEFUNC(ASN1_STRING_length) RESOLVEFUNC(ASN1_STRING_to_UTF8) RESOLVEFUNC(BIO_ctrl) + RESOLVEFUNC(BIO_new_file) + RESOLVEFUNC(ERR_clear_error) + RESOLVEFUNC(OPENSSL_free) RESOLVEFUNC(BIO_free) RESOLVEFUNC(BIO_new) RESOLVEFUNC(BIO_new_mem_buf) @@ -803,6 +811,7 @@ bool q_resolveOpenSslSymbols() RESOLVEFUNC(DSA_free) RESOLVEFUNC(ERR_error_string) RESOLVEFUNC(ERR_get_error) + RESOLVEFUNC(ERR_peek_last_error) RESOLVEFUNC(ERR_free_strings) RESOLVEFUNC(EVP_CIPHER_CTX_cleanup) RESOLVEFUNC(EVP_CIPHER_CTX_init) @@ -992,6 +1001,7 @@ bool q_resolveOpenSslSymbols() RESOLVEFUNC(d2i_DSAPrivateKey) RESOLVEFUNC(d2i_RSAPrivateKey) #endif + RESOLVEFUNC(CONF_get1_default_config_file) RESOLVEFUNC(OPENSSL_add_all_algorithms_noconf) RESOLVEFUNC(OPENSSL_add_all_algorithms_conf) RESOLVEFUNC(SSL_CTX_load_verify_locations) diff --git a/src/network/ssl/qsslsocket_openssl_symbols_p.h b/src/network/ssl/qsslsocket_openssl_symbols_p.h index b35a895d381..68dc6da8112 100644 --- a/src/network/ssl/qsslsocket_openssl_symbols_p.h +++ b/src/network/ssl/qsslsocket_openssl_symbols_p.h @@ -221,6 +221,9 @@ unsigned char * q_ASN1_STRING_data(ASN1_STRING *a); int q_ASN1_STRING_length(ASN1_STRING *a); int q_ASN1_STRING_to_UTF8(unsigned char **a, ASN1_STRING *b); long q_BIO_ctrl(BIO *a, int b, long c, void *d); +BIO *q_BIO_new_file(const char *filename, const char *mode); +void q_ERR_clear_error(); +void q_OPENSSL_free(void *ptr); Q_AUTOTEST_EXPORT int q_BIO_free(BIO *a); Q_AUTOTEST_EXPORT BIO *q_BIO_new(BIO_METHOD *a); BIO *q_BIO_new_mem_buf(void *a, int b); @@ -256,6 +259,7 @@ void q_DSA_free(DSA *a); X509 *q_d2i_X509(X509 **a, const unsigned char **b, long c); char *q_ERR_error_string(unsigned long a, char *b); unsigned long q_ERR_get_error(); +unsigned long q_ERR_peek_last_error(); void q_ERR_free_strings(); void q_EVP_CIPHER_CTX_cleanup(EVP_CIPHER_CTX *a); void q_EVP_CIPHER_CTX_init(EVP_CIPHER_CTX *a); @@ -565,6 +569,7 @@ DSA *q_d2i_DSAPrivateKey(DSA **a, unsigned char **pp, long length); #define q_EVP_PKEY_assign_DSA(pkey,dsa) q_EVP_PKEY_assign((pkey),EVP_PKEY_DSA,\ (char *)(dsa)) #define q_OpenSSL_add_all_algorithms() q_OPENSSL_add_all_algorithms_conf() +char *q_CONF_get1_default_config_file(); void q_OPENSSL_add_all_algorithms_noconf(); void q_OPENSSL_add_all_algorithms_conf(); int q_SSL_CTX_load_verify_locations(SSL_CTX *ctx, const char *CAfile, const char *CApath); diff --git a/src/platformsupport/glxconvenience/qglxconvenience.cpp b/src/platformsupport/glxconvenience/qglxconvenience.cpp index 4225bebf37d..c7b5470b390 100644 --- a/src/platformsupport/glxconvenience/qglxconvenience.cpp +++ b/src/platformsupport/glxconvenience/qglxconvenience.cpp @@ -76,7 +76,11 @@ enum { #undef FontChange #endif -QVector<int> qglx_buildSpec(const QSurfaceFormat &format, int drawableBit) +#ifndef GLX_FRAMEBUFFER_SRGB_CAPABLE_ARB +#define GLX_FRAMEBUFFER_SRGB_CAPABLE_ARB 0x20B2 +#endif + +QVector<int> qglx_buildSpec(const QSurfaceFormat &format, int drawableBit, int flags) { QVector<int> spec; @@ -120,6 +124,10 @@ QVector<int> qglx_buildSpec(const QSurfaceFormat &format, int drawableBit) << GLX_SAMPLES_ARB << format.samples(); + if ((flags & QGLX_SUPPORTS_SRGB) && format.colorSpace() == QSurfaceFormat::sRGBColorSpace) + spec << GLX_FRAMEBUFFER_SRGB_CAPABLE_ARB + << True; + spec << GLX_DRAWABLE_TYPE << drawableBit @@ -179,14 +187,14 @@ template <class T> using QXlibArrayPointer = QScopedArrayPointer<T, QXlibScopedPointerDeleter<T>>; } -GLXFBConfig qglx_findConfig(Display *display, int screen , QSurfaceFormat format, bool highestPixelFormat, int drawableBit) +GLXFBConfig qglx_findConfig(Display *display, int screen , QSurfaceFormat format, bool highestPixelFormat, int drawableBit, int flags) { QXcbSoftwareOpenGLEnforcer softwareOpenGLEnforcer; GLXFBConfig config = 0; do { - const QVector<int> spec = qglx_buildSpec(format, drawableBit); + const QVector<int> spec = qglx_buildSpec(format, drawableBit, flags); int confcount = 0; QXlibArrayPointer<GLXFBConfig> configs(glXChooseFBConfig(display, screen, spec.constData(), &confcount)); @@ -205,6 +213,13 @@ GLXFBConfig qglx_findConfig(Display *display, int screen , QSurfaceFormat format for (int i = 0; i < confcount; i++) { GLXFBConfig candidate = configs[i]; + if ((flags & QGLX_SUPPORTS_SRGB) && format.colorSpace() == QSurfaceFormat::sRGBColorSpace) { + int srgbCapable = 0; + glXGetFBConfigAttrib(display, candidate, GLX_FRAMEBUFFER_SRGB_CAPABLE_ARB, &srgbCapable); + if (!srgbCapable) + continue; + } + QXlibPointer<XVisualInfo> visual(glXGetVisualFromFBConfig(display, candidate)); const int actualRed = qPopulationCount(visual->red_mask); @@ -228,28 +243,28 @@ GLXFBConfig qglx_findConfig(Display *display, int screen , QSurfaceFormat format return config; } -XVisualInfo *qglx_findVisualInfo(Display *display, int screen, QSurfaceFormat *format, int drawableBit) +XVisualInfo *qglx_findVisualInfo(Display *display, int screen, QSurfaceFormat *format, int drawableBit, int flags) { Q_ASSERT(format); XVisualInfo *visualInfo = 0; - GLXFBConfig config = qglx_findConfig(display, screen, *format, false, drawableBit); + GLXFBConfig config = qglx_findConfig(display, screen, *format, false, drawableBit, flags); if (config) visualInfo = glXGetVisualFromFBConfig(display, config); if (visualInfo) { - qglx_surfaceFormatFromGLXFBConfig(format, display, config); + qglx_surfaceFormatFromGLXFBConfig(format, display, config, flags); return visualInfo; } // attempt to fall back to glXChooseVisual do { - QVector<int> attribs = qglx_buildSpec(*format, drawableBit); + QVector<int> attribs = qglx_buildSpec(*format, drawableBit, flags); visualInfo = glXChooseVisual(display, screen, attribs.data()); if (visualInfo) { - qglx_surfaceFormatFromVisualInfo(format, display, visualInfo); + qglx_surfaceFormatFromVisualInfo(format, display, visualInfo, flags); return visualInfo; } } while (qglx_reduceFormat(format)); @@ -257,7 +272,7 @@ XVisualInfo *qglx_findVisualInfo(Display *display, int screen, QSurfaceFormat *f return visualInfo; } -void qglx_surfaceFormatFromGLXFBConfig(QSurfaceFormat *format, Display *display, GLXFBConfig config) +void qglx_surfaceFormatFromGLXFBConfig(QSurfaceFormat *format, Display *display, GLXFBConfig config, int flags) { int redSize = 0; int greenSize = 0; @@ -268,6 +283,7 @@ void qglx_surfaceFormatFromGLXFBConfig(QSurfaceFormat *format, Display *display, int sampleBuffers = 0; int sampleCount = 0; int stereo = 0; + int srgbCapable = 0; glXGetFBConfigAttrib(display, config, GLX_RED_SIZE, &redSize); glXGetFBConfigAttrib(display, config, GLX_GREEN_SIZE, &greenSize); @@ -277,6 +293,8 @@ void qglx_surfaceFormatFromGLXFBConfig(QSurfaceFormat *format, Display *display, glXGetFBConfigAttrib(display, config, GLX_STENCIL_SIZE, &stencilSize); glXGetFBConfigAttrib(display, config, GLX_SAMPLES_ARB, &sampleBuffers); glXGetFBConfigAttrib(display, config, GLX_STEREO, &stereo); + if (flags & QGLX_SUPPORTS_SRGB) + glXGetFBConfigAttrib(display, config, GLX_FRAMEBUFFER_SRGB_CAPABLE_ARB, &srgbCapable); format->setRedBufferSize(redSize); format->setGreenBufferSize(greenSize); @@ -288,11 +306,12 @@ void qglx_surfaceFormatFromGLXFBConfig(QSurfaceFormat *format, Display *display, glXGetFBConfigAttrib(display, config, GLX_SAMPLES_ARB, &sampleCount); format->setSamples(sampleCount); } + format->setColorSpace(srgbCapable ? QSurfaceFormat::sRGBColorSpace : QSurfaceFormat::DefaultColorSpace); format->setStereo(stereo); } -void qglx_surfaceFormatFromVisualInfo(QSurfaceFormat *format, Display *display, XVisualInfo *visualInfo) +void qglx_surfaceFormatFromVisualInfo(QSurfaceFormat *format, Display *display, XVisualInfo *visualInfo, int flags) { int redSize = 0; int greenSize = 0; @@ -303,6 +322,7 @@ void qglx_surfaceFormatFromVisualInfo(QSurfaceFormat *format, Display *display, int sampleBuffers = 0; int sampleCount = 0; int stereo = 0; + int srgbCapable = 0; glXGetConfig(display, visualInfo, GLX_RED_SIZE, &redSize); glXGetConfig(display, visualInfo, GLX_GREEN_SIZE, &greenSize); @@ -312,6 +332,8 @@ void qglx_surfaceFormatFromVisualInfo(QSurfaceFormat *format, Display *display, glXGetConfig(display, visualInfo, GLX_STENCIL_SIZE, &stencilSize); glXGetConfig(display, visualInfo, GLX_SAMPLES_ARB, &sampleBuffers); glXGetConfig(display, visualInfo, GLX_STEREO, &stereo); + if (flags & QGLX_SUPPORTS_SRGB) + glXGetConfig(display, visualInfo, GLX_FRAMEBUFFER_SRGB_CAPABLE_ARB, &srgbCapable); format->setRedBufferSize(redSize); format->setGreenBufferSize(greenSize); @@ -323,6 +345,7 @@ void qglx_surfaceFormatFromVisualInfo(QSurfaceFormat *format, Display *display, glXGetConfig(display, visualInfo, GLX_SAMPLES_ARB, &sampleCount); format->setSamples(sampleCount); } + format->setColorSpace(srgbCapable ? QSurfaceFormat::sRGBColorSpace : QSurfaceFormat::DefaultColorSpace); format->setStereo(stereo); } @@ -391,5 +414,10 @@ bool qglx_reduceFormat(QSurfaceFormat *format) return true; } + if (format->colorSpace() == QSurfaceFormat::sRGBColorSpace) { + format->setColorSpace(QSurfaceFormat::DefaultColorSpace); + return true; + } + return false; } diff --git a/src/platformsupport/glxconvenience/qglxconvenience_p.h b/src/platformsupport/glxconvenience/qglxconvenience_p.h index d4226685846..f9647bfd9af 100644 --- a/src/platformsupport/glxconvenience/qglxconvenience_p.h +++ b/src/platformsupport/glxconvenience/qglxconvenience_p.h @@ -57,11 +57,16 @@ #include <X11/Xlib.h> #include <GL/glx.h> -QVector<int> qglx_buildSpec(const QSurfaceFormat &format, int drawableBit = GLX_WINDOW_BIT); -XVisualInfo *qglx_findVisualInfo(Display *display, int screen, QSurfaceFormat *format, int drawableBit = GLX_WINDOW_BIT); -GLXFBConfig qglx_findConfig(Display *display, int screen, QSurfaceFormat format, bool highestPixelFormat = false, int drawableBit = GLX_WINDOW_BIT); -void qglx_surfaceFormatFromGLXFBConfig(QSurfaceFormat *format, Display *display, GLXFBConfig config); -void qglx_surfaceFormatFromVisualInfo(QSurfaceFormat *format, Display *display, XVisualInfo *visualInfo); +enum QGlxFlags +{ + QGLX_SUPPORTS_SRGB = 0x01 +}; + +QVector<int> qglx_buildSpec(const QSurfaceFormat &format, int drawableBit = GLX_WINDOW_BIT, int flags = 0); +XVisualInfo *qglx_findVisualInfo(Display *display, int screen, QSurfaceFormat *format, int drawableBit = GLX_WINDOW_BIT, int flags = 0); +GLXFBConfig qglx_findConfig(Display *display, int screen, QSurfaceFormat format, bool highestPixelFormat = false, int drawableBit = GLX_WINDOW_BIT, int flags = 0); +void qglx_surfaceFormatFromGLXFBConfig(QSurfaceFormat *format, Display *display, GLXFBConfig config, int flags = 0); +void qglx_surfaceFormatFromVisualInfo(QSurfaceFormat *format, Display *display, XVisualInfo *visualInfo, int flags = 0); bool qglx_reduceFormat(QSurfaceFormat *format); #endif // QGLXCONVENIENCE_H diff --git a/src/platformsupport/kmsconvenience/qkmsdevice.cpp b/src/platformsupport/kmsconvenience/qkmsdevice.cpp index 669abab3318..fcc068c2026 100644 --- a/src/platformsupport/kmsconvenience/qkmsdevice.cpp +++ b/src/platformsupport/kmsconvenience/qkmsdevice.cpp @@ -330,6 +330,7 @@ QPlatformScreen *QKmsDevice::createScreenForConnector(drmModeResPtr resources, crtc_id, physSize, selected_mode, + selected_mode, false, drmModeGetCrtc(m_dri_fd, crtc_id), modes, diff --git a/src/platformsupport/kmsconvenience/qkmsdevice_p.h b/src/platformsupport/kmsconvenience/qkmsdevice_p.h index 35a51c18b12..55b572f0dd6 100644 --- a/src/platformsupport/kmsconvenience/qkmsdevice_p.h +++ b/src/platformsupport/kmsconvenience/qkmsdevice_p.h @@ -100,6 +100,7 @@ struct QKmsOutput uint32_t connector_id; uint32_t crtc_id; QSizeF physical_size; + int preferred_mode; // index of preferred mode in list below int mode; // index of selected mode in list below bool mode_set; drmModeCrtcPtr saved_crtc; diff --git a/src/plugins/platforms/android/qandroidplatformintegration.cpp b/src/plugins/platforms/android/qandroidplatformintegration.cpp index 73aa9d0e8ab..13f9dc5a681 100644 --- a/src/plugins/platforms/android/qandroidplatformintegration.cpp +++ b/src/plugins/platforms/android/qandroidplatformintegration.cpp @@ -233,6 +233,7 @@ bool QAndroidPlatformIntegration::hasCapability(Capability cap) const case ForeignWindows: return QtAndroid::activity(); case ThreadedOpenGL: return !needsBasicRenderloopWorkaround() && QtAndroid::activity(); case RasterGLSurface: return QtAndroid::activity(); + case TopStackedNativeChildWindows: return false; default: return QPlatformIntegration::hasCapability(cap); } diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_support/qeglfskmsscreen.cpp b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_support/qeglfskmsscreen.cpp index 3951f46a82d..6920a81e94f 100644 --- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_support/qeglfskmsscreen.cpp +++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_support/qeglfskmsscreen.cpp @@ -173,6 +173,28 @@ qreal QEglFSKmsScreen::refreshRate() const return refresh > 0 ? refresh : 60; } +QVector<QPlatformScreen::Mode> QEglFSKmsScreen::modes() const +{ + QVector<QPlatformScreen::Mode> list; + list.reserve(m_output.modes.size()); + + for (const drmModeModeInfo &info : qAsConst(m_output.modes)) + list.append({QSize(info.hdisplay, info.vdisplay), + qreal(info.vrefresh > 0 ? info.vrefresh : 60)}); + + return list; +} + +int QEglFSKmsScreen::currentMode() const +{ + return m_output.mode; +} + +int QEglFSKmsScreen::preferredMode() const +{ + return m_output.preferred_mode; +} + QPlatformScreen::SubpixelAntialiasingType QEglFSKmsScreen::subpixelAntialiasingTypeHint() const { return m_output.subpixelAntialiasingTypeHint(); diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_support/qeglfskmsscreen.h b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_support/qeglfskmsscreen.h index 80bbb0c7f13..c90e917f0a1 100644 --- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_support/qeglfskmsscreen.h +++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_support/qeglfskmsscreen.h @@ -77,6 +77,11 @@ public: QList<QPlatformScreen *> virtualSiblings() const override { return m_siblings; } void setVirtualSiblings(QList<QPlatformScreen *> sl) { m_siblings = sl; } + QVector<QPlatformScreen::Mode> modes() const override; + + int currentMode() const override; + int preferredMode() const override; + QKmsDevice *device() const { return m_device; } void destroySurface(); diff --git a/src/plugins/platforms/windows/accessible/iaccessible2.cpp b/src/plugins/platforms/windows/accessible/iaccessible2.cpp index d5cd9ac6db3..d9c3d6ac140 100644 --- a/src/plugins/platforms/windows/accessible/iaccessible2.cpp +++ b/src/plugins/platforms/windows/accessible/iaccessible2.cpp @@ -61,40 +61,7 @@ static inline T *coTaskMemAllocArray(int size) /**************************************************************\ * AccessibleApplication * **************************************************************/ -// IUnknown -HRESULT STDMETHODCALLTYPE AccessibleApplication::QueryInterface(REFIID id, LPVOID *iface) -{ - *iface = 0; - if (id == IID_IUnknown) { - qCDebug(lcQpaAccessibility) << "AccessibleApplication::QI(): IID_IUnknown"; - *iface = static_cast<IUnknown *>(this); - } else if (id == IID_IAccessibleApplication) { - qCDebug(lcQpaAccessibility) << "AccessibleApplication::QI(): IID_IAccessibleApplication"; - *iface = static_cast<IAccessibleApplication*>(this); - } - - if (*iface) { - AddRef(); - return S_OK; - } - return E_NOINTERFACE; -} - -ULONG STDMETHODCALLTYPE AccessibleApplication::AddRef() -{ - return ++m_ref; -} -ULONG STDMETHODCALLTYPE AccessibleApplication::Release() -{ - if (!--m_ref) { - delete this; - return 0; - } - return m_ref; -} - -/* IAccessibleApplication */ HRESULT STDMETHODCALLTYPE AccessibleApplication::get_appName(/* [retval][out] */ BSTR *name) { const QString appName = QGuiApplication::applicationName(); @@ -127,40 +94,11 @@ HRESULT STDMETHODCALLTYPE AccessibleApplication::get_toolkitVersion(/* [retval][ **************************************************************/ AccessibleRelation::AccessibleRelation(const QList<QAccessibleInterface *> &targets, QAccessible::Relation relation) - : m_targets(targets), m_relation(relation), m_ref(1) + : m_targets(targets), m_relation(relation) { Q_ASSERT(m_targets.count()); } -/* IUnknown */ -HRESULT STDMETHODCALLTYPE AccessibleRelation::QueryInterface(REFIID id, LPVOID *iface) -{ - *iface = 0; - if (id == IID_IUnknown || id == IID_IAccessibleRelation) - *iface = static_cast<IUnknown *>(this); - - if (*iface) { - AddRef(); - return S_OK; - } - - return E_NOINTERFACE; -} - -ULONG STDMETHODCALLTYPE AccessibleRelation::AddRef() -{ - return ++m_ref; -} - -ULONG STDMETHODCALLTYPE AccessibleRelation::Release() -{ - if (!--m_ref) { - delete this; - return 0; - } - return m_ref; -} - /* IAccessibleRelation */ HRESULT STDMETHODCALLTYPE AccessibleRelation::get_relationType( /* [retval][out] */ BSTR *relationType) @@ -237,56 +175,53 @@ HRESULT STDMETHODCALLTYPE AccessibleRelation::get_targets( **************************************************************/ HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::QueryInterface(REFIID id, LPVOID *iface) { + *iface = nullptr; QAccessibleInterface *accessible = accessibleInterface(); if (!accessible) return E_NOINTERFACE; - HRESULT hr = QWindowsMsaaAccessible::QueryInterface(id, iface); - if (!SUCCEEDED(hr)) { - if (id == IID_IServiceProvider) { - *iface = static_cast<IServiceProvider *>(this); - } else if (id == IID_IAccessible2) { - *iface = static_cast<IAccessible2 *>(this); - } else if (id == IID_IAccessibleAction) { - if (accessible->actionInterface()) - *iface = static_cast<IAccessibleAction *>(this); - } else if (id == IID_IAccessibleComponent) { - *iface = static_cast<IAccessibleComponent *>(this); - } else if (id == IID_IAccessibleEditableText) { - if (accessible->editableTextInterface() || - accessible->role() == QAccessible::EditableText) - { - *iface = static_cast<IAccessibleEditableText *>(this); - } - } else if (id == IID_IAccessibleHyperlink) { - //*iface = static_cast<IAccessibleHyperlink *>(this); - } else if (id == IID_IAccessibleHypertext) { - //*iface = static_cast<IAccessibleHypertext *>(this); - } else if (id == IID_IAccessibleImage) { - //*iface = static_cast<IAccessibleImage *>(this); - } else if (id == IID_IAccessibleTable) { - //*iface = static_cast<IAccessibleTable *>(this); // not supported - } else if (id == IID_IAccessibleTable2) { - if (accessible->tableInterface()) - *iface = static_cast<IAccessibleTable2 *>(this); - } else if (id == IID_IAccessibleTableCell) { - if (accessible->tableCellInterface()) - *iface = static_cast<IAccessibleTableCell *>(this); - } else if (id == IID_IAccessibleText) { - if (accessible->textInterface()) - *iface = static_cast<IAccessibleText *>(this); - } else if (id == IID_IAccessibleValue) { - if (accessible->valueInterface()) - *iface = static_cast<IAccessibleValue *>(this); - } - if (*iface) { - AddRef(); - hr = S_OK; - } else { - hr = E_NOINTERFACE; + if (SUCCEEDED(QWindowsMsaaAccessible::QueryInterface(id, iface)) + || qWindowsComQueryInterface<IServiceProvider>(this, id, iface) + || qWindowsComQueryInterface<IAccessible2>(this, id, iface) + || qWindowsComQueryInterface<IAccessibleComponent>(this, id, iface)) { + return S_OK; + } + + if (id == IID_IAccessibleAction) { + if (accessible->actionInterface()) + *iface = static_cast<IAccessibleAction *>(this); + } else if (id == IID_IAccessibleEditableText) { + if (accessible->editableTextInterface() || + accessible->role() == QAccessible::EditableText) + { + *iface = static_cast<IAccessibleEditableText *>(this); } + } else if (id == IID_IAccessibleHyperlink) { + //*iface = static_cast<IAccessibleHyperlink *>(this); + } else if (id == IID_IAccessibleHypertext) { + //*iface = static_cast<IAccessibleHypertext *>(this); + } else if (id == IID_IAccessibleImage) { + //*iface = static_cast<IAccessibleImage *>(this); + } else if (id == IID_IAccessibleTable) { + //*iface = static_cast<IAccessibleTable *>(this); // not supported + } else if (id == IID_IAccessibleTable2) { + if (accessible->tableInterface()) + *iface = static_cast<IAccessibleTable2 *>(this); + } else if (id == IID_IAccessibleTableCell) { + if (accessible->tableCellInterface()) + *iface = static_cast<IAccessibleTableCell *>(this); + } else if (id == IID_IAccessibleText) { + if (accessible->textInterface()) + *iface = static_cast<IAccessibleText *>(this); + } else if (id == IID_IAccessibleValue) { + if (accessible->valueInterface()) + *iface = static_cast<IAccessibleValue *>(this); } - return hr; + if (*iface) { + AddRef(); + return S_OK; + } + return E_NOINTERFACE; } @@ -1593,7 +1528,7 @@ HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::QueryService(REFGUID guidServic return E_POINTER; Q_UNUSED(guidService); *iface = 0; - qCDebug(lcQpaAccessibility) << "QWindowsIA2Accessible::QS(): " << IIDToString(riid); + qCDebug(lcQpaAccessibility) << "QWindowsIA2Accessible::QS(): " << QWindowsAccessibleGuid(riid); if (guidService == IID_IAccessible) { @@ -1692,45 +1627,6 @@ HRESULT QWindowsIA2Accessible::wrapListOfCells(const QList<QAccessibleInterface* return count > 0 ? S_OK : S_FALSE; } -#define IF_EQUAL_RETURN_IIDSTRING(id, iid) if (id == iid) return QByteArray(#iid) - -QByteArray QWindowsIA2Accessible::IIDToString(REFIID id) -{ - QByteArray strGuid = QWindowsMsaaAccessible::IIDToString(id); - if (!strGuid.isEmpty()) - return strGuid; - - IF_EQUAL_RETURN_IIDSTRING(id, IID_IUnknown); - IF_EQUAL_RETURN_IIDSTRING(id, IID_IDispatch); - IF_EQUAL_RETURN_IIDSTRING(id, IID_IAccessible); - IF_EQUAL_RETURN_IIDSTRING(id, IID_IOleWindow); - IF_EQUAL_RETURN_IIDSTRING(id, IID_IServiceProvider); - IF_EQUAL_RETURN_IIDSTRING(id, IID_IAccessible2); - IF_EQUAL_RETURN_IIDSTRING(id, IID_IAccessibleAction); - IF_EQUAL_RETURN_IIDSTRING(id, IID_IAccessibleApplication); - IF_EQUAL_RETURN_IIDSTRING(id, IID_IAccessibleComponent); - IF_EQUAL_RETURN_IIDSTRING(id, IID_IAccessibleEditableText); - IF_EQUAL_RETURN_IIDSTRING(id, IID_IAccessibleHyperlink); - IF_EQUAL_RETURN_IIDSTRING(id, IID_IAccessibleHypertext); - IF_EQUAL_RETURN_IIDSTRING(id, IID_IAccessibleImage); - IF_EQUAL_RETURN_IIDSTRING(id, IID_IAccessibleRelation); - IF_EQUAL_RETURN_IIDSTRING(id, IID_IAccessibleTable); - IF_EQUAL_RETURN_IIDSTRING(id, IID_IAccessibleTable2); - IF_EQUAL_RETURN_IIDSTRING(id, IID_IAccessibleTableCell); - IF_EQUAL_RETURN_IIDSTRING(id, IID_IAccessibleText); - IF_EQUAL_RETURN_IIDSTRING(id, IID_IAccessibleValue); - - // else... -#if 0 // Can be useful for debugging, but normally we'd like to reduce the noise a bit... - OLECHAR szGuid[39]={0}; - ::StringFromGUID2(id, szGuid, 39); - strGuid.reserve(40); - ::WideCharToMultiByte(CP_UTF8, 0, szGuid, 39, strGuid.data(), 39, NULL, NULL); - strGuid[38] = '\0'; -#endif - return strGuid; -} - // Q_STATIC_ASSERT(IA2_ROLE_CANVAS == QAccessible::Canvas); // ### Qt 6: make them the same Q_STATIC_ASSERT(IA2_ROLE_COLOR_CHOOSER == static_cast<IA2Role>(QAccessible::ColorChooser)); Q_STATIC_ASSERT(IA2_ROLE_FOOTER == static_cast<IA2Role>(QAccessible::Footer)); diff --git a/src/plugins/platforms/windows/accessible/iaccessible2.h b/src/plugins/platforms/windows/accessible/iaccessible2.h index bc5f5be60fb..d5c67f8b513 100644 --- a/src/plugins/platforms/windows/accessible/iaccessible2.h +++ b/src/plugins/platforms/windows/accessible/iaccessible2.h @@ -42,6 +42,7 @@ #include <QtCore/QtConfig> #ifndef QT_NO_ACCESSIBILITY +#include "qwindowscombase.h" #include "qwindowsmsaaaccessible.h" #include "comutils.h" @@ -249,7 +250,6 @@ private: HRESULT getRelationsHelper(IAccessibleRelation **relations, int startIndex, long maxRelations, long *nRelations = 0); HRESULT wrapListOfCells(const QList<QAccessibleInterface*> &inputCells, IUnknown ***outputAccessibles, long *nCellCount); - QByteArray IIDToString(REFIID id); QString textForRange(int startOffset, int endOffset) const; void replaceTextFallback(long startOffset, long endOffset, const QString &txt); @@ -258,28 +258,18 @@ private: /**************************************************************\ * AccessibleApplication * **************************************************************/ -class AccessibleApplication : public IAccessibleApplication +class AccessibleApplication : public QWindowsComBase<IAccessibleApplication> { public: - AccessibleApplication() : m_ref(1) - { - - } + AccessibleApplication() {} virtual ~AccessibleApplication() {} - /* IUnknown */ - HRESULT STDMETHODCALLTYPE QueryInterface(REFIID, LPVOID *); - ULONG STDMETHODCALLTYPE AddRef(); - ULONG STDMETHODCALLTYPE Release(); - /* IAccessibleApplication */ HRESULT STDMETHODCALLTYPE get_appName(/* [retval][out] */ BSTR *name); HRESULT STDMETHODCALLTYPE get_appVersion(/* [retval][out] */ BSTR *version); HRESULT STDMETHODCALLTYPE get_toolkitName(/* [retval][out] */ BSTR *name); HRESULT STDMETHODCALLTYPE get_toolkitVersion(/* [retval][out] */ BSTR *version); -private: - ULONG m_ref; }; @@ -287,7 +277,7 @@ private: /**************************************************************\ * AccessibleRelation * **************************************************************/ -class AccessibleRelation : public IAccessibleRelation +class AccessibleRelation : public QWindowsComBase<IAccessibleRelation> { public: AccessibleRelation(const QList<QAccessibleInterface *> &targets, @@ -295,11 +285,6 @@ public: virtual ~AccessibleRelation() {} - /* IUnknown */ - HRESULT STDMETHODCALLTYPE QueryInterface(REFIID id, LPVOID *iface); - ULONG STDMETHODCALLTYPE AddRef(); - ULONG STDMETHODCALLTYPE Release(); - /* IAccessibleRelation */ HRESULT STDMETHODCALLTYPE get_relationType(BSTR *relationType); HRESULT STDMETHODCALLTYPE get_localizedRelationType(BSTR *localizedRelationType); @@ -341,7 +326,6 @@ private: QList<QAccessibleInterface *> m_targets; QAccessible::Relation m_relation; - ULONG m_ref; }; QT_END_NAMESPACE diff --git a/src/plugins/platforms/windows/accessible/qwindowsmsaaaccessible.cpp b/src/plugins/platforms/windows/accessible/qwindowsmsaaaccessible.cpp index 25b15777729..308ff59c49c 100644 --- a/src/plugins/platforms/windows/accessible/qwindowsmsaaaccessible.cpp +++ b/src/plugins/platforms/windows/accessible/qwindowsmsaaaccessible.cpp @@ -42,6 +42,7 @@ #include "qwindowsmsaaaccessible.h" #include "qwindowsaccessibility.h" +#include "qwindowscombase.h" #include <oleacc.h> #include <servprov.h> #include <winuser.h> @@ -71,61 +72,22 @@ QT_BEGIN_NAMESPACE -class QWindowsEnumerate : public IEnumVARIANT +class QWindowsEnumerate : public QWindowsComBase<IEnumVARIANT> { public: - QWindowsEnumerate(const QVector<int> &a) - : ref(0), current(0),array(a) - { - } - + QWindowsEnumerate(const QVector<int> &a) : QWindowsComBase<IEnumVARIANT>(0), current(0),array(a) {} virtual ~QWindowsEnumerate() {} - HRESULT STDMETHODCALLTYPE QueryInterface(REFIID, LPVOID *); - ULONG STDMETHODCALLTYPE AddRef(); - ULONG STDMETHODCALLTYPE Release(); - HRESULT STDMETHODCALLTYPE Clone(IEnumVARIANT **ppEnum); HRESULT STDMETHODCALLTYPE Next(unsigned long celt, VARIANT FAR* rgVar, unsigned long FAR* pCeltFetched); HRESULT STDMETHODCALLTYPE Reset(); HRESULT STDMETHODCALLTYPE Skip(unsigned long celt); private: - ULONG ref; ULONG current; QVector<int> array; }; -HRESULT STDMETHODCALLTYPE QWindowsEnumerate::QueryInterface(REFIID id, LPVOID *iface) -{ - *iface = 0; - if (id == IID_IUnknown) - *iface = static_cast<IUnknown *>(this); - else if (id == IID_IEnumVARIANT) - *iface = static_cast<IEnumVARIANT *>(this); - - if (*iface) { - AddRef(); - return S_OK; - } - - return E_NOINTERFACE; -} - -ULONG STDMETHODCALLTYPE QWindowsEnumerate::AddRef() -{ - return ++ref; -} - -ULONG STDMETHODCALLTYPE QWindowsEnumerate::Release() -{ - if (!--ref) { - delete this; - return 0; - } - return ref; -} - HRESULT STDMETHODCALLTYPE QWindowsEnumerate::Clone(IEnumVARIANT **ppEnum) { QWindowsEnumerate *penum = 0; @@ -193,29 +155,17 @@ void accessibleDebugClientCalls_helper(const char* funcName, const QAccessibleIn **************************************************************/ HRESULT STDMETHODCALLTYPE QWindowsMsaaAccessible::QueryInterface(REFIID id, LPVOID *iface) { - *iface = 0; - - QByteArray strIID = IIDToString(id); - if (!strIID.isEmpty()) { - qCDebug(lcQpaAccessibility) << "QWindowsIA2Accessible::QI() - IID:" - << strIID << ", iface:" << accessibleInterface(); + *iface = nullptr; + const bool result = qWindowsComQueryUnknownInterfaceMulti<AccessibleBase>(this, id, iface) + || qWindowsComQueryInterface<IDispatch>(this, id, iface) + || qWindowsComQueryInterface<IAccessible>(this, id, iface) + || qWindowsComQueryInterface<IOleWindow>(this, id, iface); + + if (result) { + qCDebug(lcQpaAccessibility) << "QWindowsIA2Accessible::QI() - " + << QWindowsAccessibleGuid(id) << ", iface:" << accessibleInterface(); } - if (id == IID_IUnknown) { - *iface = static_cast<IUnknown *>(static_cast<IDispatch *>(this)); - } else if (id == IID_IDispatch) { - *iface = static_cast<IDispatch *>(this); - } else if (id == IID_IAccessible) { - *iface = static_cast<IAccessible *>(this); - } else if (id == IID_IOleWindow) { - *iface = static_cast<IOleWindow *>(this); - } - - if (*iface) { - AddRef(); - return S_OK; - } - - return E_NOINTERFACE; + return result ? S_OK : E_NOINTERFACE; } ULONG STDMETHODCALLTYPE QWindowsMsaaAccessible::AddRef() @@ -1209,16 +1159,66 @@ HRESULT STDMETHODCALLTYPE QWindowsMsaaAccessible::ContextSensitiveHelp(BOOL) return S_OK; } -#define IF_EQUAL_RETURN_IIDSTRING(id, iid) if (id == iid) return QByteArray(#iid) -QByteArray QWindowsMsaaAccessible::IIDToString(REFIID id) +const char *QWindowsAccessibleGuid::iidToString(const GUID &id) { - IF_EQUAL_RETURN_IIDSTRING(id, IID_IUnknown); - IF_EQUAL_RETURN_IIDSTRING(id, IID_IDispatch); - IF_EQUAL_RETURN_IIDSTRING(id, IID_IAccessible); - IF_EQUAL_RETURN_IIDSTRING(id, IID_IOleWindow); + const char *result = nullptr; + if (id == IID_IUnknown) + result = "IID_IUnknown"; + else if (id == IID_IDispatch) + result = "IID_IDispatch"; + else if (id == IID_IAccessible) + result = "IID_IAccessible"; + else if (id == IID_IOleWindow) + result = "IID_IOleWindow"; + else if (id == IID_IServiceProvider) + result = "IID_IServiceProvider"; +#ifndef Q_CC_MINGW + else if (id == IID_IAccessible2) + result = "IID_IAccessible2"; + else if (id == IID_IAccessibleAction) + result = "IID_IAccessibleAction"; + else if (id == IID_IAccessibleApplication) + result = "IID_IAccessibleApplication"; + else if (id == IID_IAccessibleComponent) + result = "IID_IAccessibleComponent"; + else if (id == IID_IAccessibleEditableText) + result = "IID_IAccessibleEditableText"; + else if (id == IID_IAccessibleHyperlink) + result = "IID_IAccessibleHyperlink"; + else if (id == IID_IAccessibleHypertext) + result = "IID_IAccessibleHypertext"; + else if (id == IID_IAccessibleImage) + result = "IID_IAccessibleImage"; + else if (id == IID_IAccessibleRelation) + result = "IID_IAccessibleRelation"; + else if (id == IID_IAccessibleTable) + result = "IID_IAccessibleTable"; + else if (id == IID_IAccessibleTable2) + result = "IID_IAccessibleTable2"; + else if (id == IID_IAccessibleTableCell) + result = "IID_IAccessibleTableCell"; + else if (id == IID_IAccessibleText) + result = "IID_IAccessibleText"; + else if (id == IID_IAccessibleValue) + result = "IID_IAccessibleValue"; +#endif // !Q_CC_MINGW + return result; +} + +#ifndef QT_NO_DEBUG_STREAM +QDebug operator<<(QDebug, const GUID &); - return QByteArray(); +QDebug operator<<(QDebug d, const QWindowsAccessibleGuid &aguid) +{ + QDebugStateSaver saver(d); + d.nospace(); + if (const char *ids = QWindowsAccessibleGuid::iidToString(aguid.guid())) + d << ids; + else + d << aguid.guid(); + return d; } +#endif // !QT_NO_DEBUG_STREAM QT_END_NAMESPACE diff --git a/src/plugins/platforms/windows/accessible/qwindowsmsaaaccessible.h b/src/plugins/platforms/windows/accessible/qwindowsmsaaaccessible.h index fd00f8ac8bd..07f10da99a4 100644 --- a/src/plugins/platforms/windows/accessible/qwindowsmsaaaccessible.h +++ b/src/plugins/platforms/windows/accessible/qwindowsmsaaaccessible.h @@ -69,16 +69,32 @@ void accessibleDebugClientCalls_helper(const char* funcName, const QAccessibleIn QWindow *window_helper(const QAccessibleInterface *iface); +class QWindowsAccessibleGuid // Helper for QDebug, outputs known ids by name. +{ +public: + explicit QWindowsAccessibleGuid(const GUID &g) : m_guid(g) {} + GUID guid () const { return m_guid; } + static const char *iidToString(const GUID &id); + +private: + GUID m_guid; +}; + +#ifndef QT_NO_DEBUG_STREAM +QDebug operator<<(QDebug d, const QWindowsAccessibleGuid &aguid); +#endif + /**************************************************************\ * QWindowsAccessible * **************************************************************/ -class QWindowsMsaaAccessible : public -#ifdef Q_CC_MINGW - IAccessible + +#ifndef Q_CC_MINGW +typedef IAccessible2 AccessibleBase; #else - IAccessible2 +typedef IAccessible AccessibleBase; #endif - , public IOleWindow + +class QWindowsMsaaAccessible : public AccessibleBase, public IOleWindow { public: QWindowsMsaaAccessible(QAccessibleInterface *a) @@ -132,8 +148,6 @@ public: HRESULT STDMETHODCALLTYPE ContextSensitiveHelp(BOOL fEnterMode); protected: - virtual QByteArray IIDToString(REFIID id); - QAccessible::Id id; QAccessibleInterface *accessibleInterface() const diff --git a/src/plugins/platforms/windows/qwindowscombase.h b/src/plugins/platforms/windows/qwindowscombase.h new file mode 100644 index 00000000000..f8afcc81cf9 --- /dev/null +++ b/src/plugins/platforms/windows/qwindowscombase.h @@ -0,0 +1,106 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QWINDOWSCOMBASE_H +#define QWINDOWSCOMBASE_H + +#include <QtCore/QtGlobal> + +#include <unknwn.h> + +QT_BEGIN_NAMESPACE + +// Helper for implementing IUnknown::QueryInterface. +template <class DesiredInterface, class Derived> +bool qWindowsComQueryInterface(Derived *d, REFIID id, LPVOID *iface) +{ + if (id == __uuidof(DesiredInterface)) { + *iface = static_cast<DesiredInterface *>(d); + d->AddRef(); + return true; + } + return false; +} + +// Helper for implementing IUnknown::QueryInterface for IUnknown +// in the case of multiple inheritance via the first inherited class. +template <class FirstInheritedInterface, class Derived> +bool qWindowsComQueryUnknownInterfaceMulti(Derived *d, REFIID id, LPVOID *iface) +{ + if (id == __uuidof(IUnknown)) { + *iface = static_cast<FirstInheritedInterface *>(d); + d->AddRef(); + return true; + } + return false; +} + +// Helper base class to provide IUnknown methods for COM classes (single inheritance) +template <class ComInterface> class QWindowsComBase : public ComInterface +{ + Q_DISABLE_COPY(QWindowsComBase) +public: + explicit QWindowsComBase(ULONG initialRefCount = 1) : m_ref(initialRefCount) {} + virtual ~QWindowsComBase() {} + + HRESULT STDMETHODCALLTYPE QueryInterface(REFIID id, LPVOID *iface) + { + *iface = nullptr; + return qWindowsComQueryInterface<IUnknown>(this, id, iface) || qWindowsComQueryInterface<ComInterface>(this, id, iface) + ? S_OK : E_NOINTERFACE; + } + + ULONG STDMETHODCALLTYPE AddRef() { return ++m_ref; } + + ULONG STDMETHODCALLTYPE Release() + { + if (!--m_ref) { + delete this; + return 0; + } + return m_ref; + } + +private: + ULONG m_ref; +}; + +QT_END_NAMESPACE + +#endif // QWINDOWSCOMBASE_H diff --git a/src/plugins/platforms/windows/qwindowsdialoghelpers.cpp b/src/plugins/platforms/windows/qwindowsdialoghelpers.cpp index f4527bcc600..59e2aacee90 100644 --- a/src/plugins/platforms/windows/qwindowsdialoghelpers.cpp +++ b/src/plugins/platforms/windows/qwindowsdialoghelpers.cpp @@ -41,6 +41,7 @@ #define _WIN32_WINNT 0x0600 +#include "qwindowscombase.h" #include "qwindowsdialoghelpers.h" #include "qwindowscontext.h" @@ -504,33 +505,11 @@ inline void QWindowsFileDialogSharedData::fromOptions(const QSharedPointer<QFile class QWindowsNativeFileDialogBase; -class QWindowsNativeFileDialogEventHandler : public IFileDialogEvents +class QWindowsNativeFileDialogEventHandler : public QWindowsComBase<IFileDialogEvents> { public: static IFileDialogEvents *create(QWindowsNativeFileDialogBase *nativeFileDialog); - // IUnknown methods - IFACEMETHODIMP QueryInterface(REFIID riid, void** ppv) - { - if (riid != IID_IUnknown && riid != IID_IFileDialogEvents) { - *ppv = NULL; - return ResultFromScode(E_NOINTERFACE); - } - *ppv = this; - AddRef(); - return NOERROR; - } - - IFACEMETHODIMP_(ULONG) AddRef() { return InterlockedIncrement(&m_ref); } - - IFACEMETHODIMP_(ULONG) Release() - { - const long ref = InterlockedDecrement(&m_ref); - if (!ref) - delete this; - return ref; - } - // IFileDialogEvents methods IFACEMETHODIMP OnFileOk(IFileDialog *); IFACEMETHODIMP OnFolderChange(IFileDialog *) { return S_OK; } @@ -546,7 +525,6 @@ public: virtual ~QWindowsNativeFileDialogEventHandler() {} private: - long m_ref = 1; QWindowsNativeFileDialogBase *m_nativeFileDialog; }; diff --git a/src/plugins/platforms/windows/qwindowsdrag.cpp b/src/plugins/platforms/windows/qwindowsdrag.cpp index 550415e8891..92759584564 100644 --- a/src/plugins/platforms/windows/qwindowsdrag.cpp +++ b/src/plugins/platforms/windows/qwindowsdrag.cpp @@ -215,7 +215,7 @@ static inline Qt::MouseButtons toQtMouseButtons(DWORD keyState) \ingroup qt-lighthouse-win */ -class QWindowsOleDropSource : public IDropSource +class QWindowsOleDropSource : public QWindowsComBase<IDropSource> { public: enum Mode { @@ -228,11 +228,6 @@ public: void createCursors(); - // IUnknown methods - STDMETHOD(QueryInterface)(REFIID riid, void ** ppvObj); - STDMETHOD_(ULONG,AddRef)(void); - STDMETHOD_(ULONG,Release)(void); - // IDropSource methods STDMETHOD(QueryContinueDrag)(BOOL fEscapePressed, DWORD grfKeyState); STDMETHOD(GiveFeedback)(DWORD dwEffect); @@ -257,7 +252,6 @@ private: ActionCursorMap m_cursors; QWindowsDragCursorWindow *m_touchDragWindow; - ULONG m_refs; #ifndef QT_NO_DEBUG_STREAM friend QDebug operator<<(QDebug, const QWindowsOleDropSource::CursorEntry &); #endif @@ -268,7 +262,6 @@ QWindowsOleDropSource::QWindowsOleDropSource(QWindowsDrag *drag) , m_drag(drag) , m_currentButtons(Qt::NoButton) , m_touchDragWindow(0) - , m_refs(1) { qCDebug(lcQpaMime) << __FUNCTION__ << m_mode; } @@ -373,38 +366,6 @@ void QWindowsOleDropSource::createCursors() #endif // !QT_NO_DEBUG_OUTPUT } -//--------------------------------------------------------------------- -// IUnknown Methods -//--------------------------------------------------------------------- - -STDMETHODIMP -QWindowsOleDropSource::QueryInterface(REFIID iid, void FAR* FAR* ppv) -{ - if (iid == IID_IUnknown || iid == IID_IDropSource) { - *ppv = this; - ++m_refs; - return NOERROR; - } - *ppv = NULL; - return ResultFromScode(E_NOINTERFACE); -} - -STDMETHODIMP_(ULONG) -QWindowsOleDropSource::AddRef(void) -{ - return ++m_refs; -} - -STDMETHODIMP_(ULONG) -QWindowsOleDropSource::Release(void) -{ - if (--m_refs == 0) { - delete this; - return 0; - } - return m_refs; -} - /*! \brief Check for cancel. */ @@ -504,34 +465,6 @@ QWindowsOleDropTarget::~QWindowsOleDropTarget() qCDebug(lcQpaMime) << __FUNCTION__ << this; } -STDMETHODIMP -QWindowsOleDropTarget::QueryInterface(REFIID iid, void FAR* FAR* ppv) -{ - if (iid == IID_IUnknown || iid == IID_IDropTarget) { - *ppv = this; - AddRef(); - return NOERROR; - } - *ppv = NULL; - return ResultFromScode(E_NOINTERFACE); -} - -STDMETHODIMP_(ULONG) -QWindowsOleDropTarget::AddRef(void) -{ - return ++m_refs; -} - -STDMETHODIMP_(ULONG) -QWindowsOleDropTarget::Release(void) -{ - if (--m_refs == 0) { - delete this; - return 0; - } - return m_refs; -} - void QWindowsOleDropTarget::handleDrag(QWindow *window, DWORD grfKeyState, const QPoint &point, LPDWORD pdwEffect) { diff --git a/src/plugins/platforms/windows/qwindowsdrag.h b/src/plugins/platforms/windows/qwindowsdrag.h index 983f3a67b4f..069f58cf021 100644 --- a/src/plugins/platforms/windows/qwindowsdrag.h +++ b/src/plugins/platforms/windows/qwindowsdrag.h @@ -40,6 +40,7 @@ #ifndef QWINDOWSDRAG_H #define QWINDOWSDRAG_H +#include "qwindowscombase.h" #include "qwindowsinternalmimedata.h" #include <qpa/qplatformdrag.h> @@ -57,17 +58,12 @@ public: IDataObject *retrieveDataObject() const override; }; -class QWindowsOleDropTarget : public IDropTarget +class QWindowsOleDropTarget : public QWindowsComBase<IDropTarget> { public: explicit QWindowsOleDropTarget(QWindow *w); virtual ~QWindowsOleDropTarget(); - // IUnknown methods - STDMETHOD(QueryInterface)(REFIID riid, void FAR* FAR* ppvObj); - STDMETHOD_(ULONG, AddRef)(void); - STDMETHOD_(ULONG, Release)(void); - // IDropTarget methods STDMETHOD(DragEnter)(LPDATAOBJECT pDataObj, DWORD grfKeyState, POINTL pt, LPDWORD pdwEffect); STDMETHOD(DragOver)(DWORD grfKeyState, POINTL pt, LPDWORD pdwEffect); @@ -77,7 +73,6 @@ public: private: void handleDrag(QWindow *window, DWORD grfKeyState, const QPoint &, LPDWORD pdwEffect); - ULONG m_refs = 1; QWindow *const m_window; QRect m_answerRect; QPoint m_lastPoint; diff --git a/src/plugins/platforms/windows/qwindowsglcontext.cpp b/src/plugins/platforms/windows/qwindowsglcontext.cpp index 751807e897c..78368d87de4 100644 --- a/src/plugins/platforms/windows/qwindowsglcontext.cpp +++ b/src/plugins/platforms/windows/qwindowsglcontext.cpp @@ -145,6 +145,10 @@ #define RESET_NOTIFICATION_STRATEGY_ARB 0x8256 #define LOSE_CONTEXT_ON_RESET_ARB 0x8252 +#ifndef WGL_FRAMEBUFFER_SRGB_CAPABLE_EXT +#define WGL_FRAMEBUFFER_SRGB_CAPABLE_EXT 0x20A9 +#endif + QT_BEGIN_NAMESPACE QWindowsOpengl32DLL QOpenGLStaticContext::opengl32; @@ -489,7 +493,7 @@ static int choosePixelFormat(HDC hdc, const QWindowsOpenGLAdditionalFormat &additional, PIXELFORMATDESCRIPTOR *obtainedPfd) { - enum { attribSize =40 }; + enum { attribSize = 42 }; if ((additional.formatFlags & QWindowsGLRenderToPixmap) || !staticContext.hasExtensions()) return 0; @@ -570,7 +574,15 @@ static int choosePixelFormat(HDC hdc, iAttributes[i++] = WGL_SAMPLE_BUFFERS_ARB; iAttributes[i++] = FALSE; } - // If sample buffer request cannot be satisfied, reduce request. + // must be the last + bool srgbRequested = format.colorSpace() == QSurfaceFormat::sRGBColorSpace; + int srgbValuePosition = 0; + if (srgbRequested) { + srgbValuePosition = i; + iAttributes[i++] = WGL_FRAMEBUFFER_SRGB_CAPABLE_EXT; + iAttributes[i++] = TRUE; + } + // If sample or sRGB request cannot be satisfied, reduce request. int pixelFormat = 0; uint numFormats = 0; while (true) { @@ -578,20 +590,25 @@ static int choosePixelFormat(HDC hdc, staticContext.wglChoosePixelFormatARB(hdc, iAttributes, 0, 1, &pixelFormat, &numFormats) && numFormats >= 1; - if (valid || !sampleBuffersRequested) - break; - if (iAttributes[samplesValuePosition] > 1) { - iAttributes[samplesValuePosition] /= 2; - } else if (iAttributes[samplesValuePosition] == 1) { - // Fallback in case it is unable to initialize with any - // samples to avoid falling back to the GDI path - // NB: The sample attributes needs to be at the end for this - // to work correctly - iAttributes[samplesValuePosition - 1] = FALSE; - iAttributes[samplesValuePosition] = 0; - iAttributes[samplesValuePosition + 1] = 0; - } else { + if (valid || (!sampleBuffersRequested && !srgbRequested)) break; + if (srgbRequested) { + iAttributes[srgbValuePosition] = 0; + srgbRequested = false; + } else if (sampleBuffersRequested) { + if (iAttributes[samplesValuePosition] > 1) { + iAttributes[samplesValuePosition] /= 2; + } else if (iAttributes[samplesValuePosition] == 1) { + // Fallback in case it is unable to initialize with any + // samples to avoid falling back to the GDI path + // NB: The sample attributes needs to be at the end for this + // to work correctly + iAttributes[samplesValuePosition - 1] = FALSE; + iAttributes[samplesValuePosition] = 0; + iAttributes[samplesValuePosition + 1] = 0; + } else { + break; + } } } // Verify if format is acceptable. Note that the returned @@ -628,7 +645,7 @@ static QSurfaceFormat HDC hdc, int pixelFormat, QWindowsOpenGLAdditionalFormat *additionalIn = 0) { - enum { attribSize =40 }; + enum { attribSize = 42 }; QSurfaceFormat result; result.setRenderableType(QSurfaceFormat::OpenGL); @@ -641,6 +658,7 @@ static QSurfaceFormat int i = 0; const bool hasSampleBuffers = testFlag(staticContext.extensions, QOpenGLStaticContext::SampleBuffers); + const bool hasSrgbSupport = testFlag(staticContext.extensions, QOpenGLStaticContext::sRGBCapableFramebuffer); iAttributes[i++] = WGL_DOUBLE_BUFFER_ARB; // 0 iAttributes[i++] = WGL_DEPTH_BITS_ARB; // 1 @@ -658,6 +676,9 @@ static QSurfaceFormat iAttributes[i++] = WGL_SAMPLE_BUFFERS_ARB; // 12 iAttributes[i++] = WGL_SAMPLES_ARB; // 13 } + if (hasSrgbSupport) + iAttributes[i++] = WGL_FRAMEBUFFER_SRGB_CAPABLE_EXT; // 12 or 14 + if (!staticContext.wglGetPixelFormatAttribIVARB(hdc, pixelFormat, 0, i, iAttributes, iValues)) { qErrnoWarning("%s: wglGetPixelFormatAttribIVARB() failed for basic parameters.", __FUNCTION__); @@ -673,8 +694,14 @@ static QSurfaceFormat if (iValues[9]) result.setOption(QSurfaceFormat::StereoBuffers); - if (hasSampleBuffers) + if (hasSampleBuffers) { result.setSamples(iValues[13]); + if (hasSrgbSupport && iValues[14]) + result.setColorSpace(QSurfaceFormat::sRGBColorSpace); + } else { + if (hasSrgbSupport && iValues[12]) + result.setColorSpace(QSurfaceFormat::sRGBColorSpace); + } if (additionalIn) { if (iValues[7]) additionalIn->formatFlags |= QWindowsGLAccumBuffer; @@ -947,7 +974,8 @@ QOpenGLStaticContext::QOpenGLStaticContext() : wglChoosePixelFormatARB((WglChoosePixelFormatARB)QOpenGLStaticContext::opengl32.wglGetProcAddress("wglChoosePixelFormatARB")), wglCreateContextAttribsARB((WglCreateContextAttribsARB)QOpenGLStaticContext::opengl32.wglGetProcAddress("wglCreateContextAttribsARB")), wglSwapInternalExt((WglSwapInternalExt)QOpenGLStaticContext::opengl32.wglGetProcAddress("wglSwapIntervalEXT")), - wglGetSwapInternalExt((WglGetSwapInternalExt)QOpenGLStaticContext::opengl32.wglGetProcAddress("wglGetSwapIntervalEXT")) + wglGetSwapInternalExt((WglGetSwapInternalExt)QOpenGLStaticContext::opengl32.wglGetProcAddress("wglGetSwapIntervalEXT")), + wglGetExtensionsStringARB((WglGetExtensionsStringARB)QOpenGLStaticContext::opengl32.wglGetProcAddress("wglGetExtensionsStringARB")) { if (extensionNames.startsWith(SAMPLE_BUFFER_EXTENSION " ") || extensionNames.indexOf(" " SAMPLE_BUFFER_EXTENSION " ") != -1) @@ -1091,6 +1119,14 @@ QWindowsGLContext::QWindowsGLContext(QOpenGLStaticContext *staticContext, && !(QWindowsIntegration::instance()->options() & QWindowsIntegration::DisableArb); QWindowsOpenGLAdditionalFormat obtainedAdditional; if (tryExtensions) { + if (m_staticContext->wglGetExtensionsStringARB) { + const char *exts = m_staticContext->wglGetExtensionsStringARB(hdc); + if (exts) { + qCDebug(lcQpaGl) << __FUNCTION__ << "WGL extensions:" << exts; + if (strstr(exts, "WGL_EXT_framebuffer_sRGB")) + m_staticContext->extensions |= QOpenGLStaticContext::sRGBCapableFramebuffer; + } + } m_pixelFormat = ARB::choosePixelFormat(hdc, *m_staticContext, format, requestedAdditional, &m_obtainedPixelFormatDescriptor); diff --git a/src/plugins/platforms/windows/qwindowsglcontext.h b/src/plugins/platforms/windows/qwindowsglcontext.h index dfaa4285205..2d5b94af0e4 100644 --- a/src/plugins/platforms/windows/qwindowsglcontext.h +++ b/src/plugins/platforms/windows/qwindowsglcontext.h @@ -139,7 +139,8 @@ class QOpenGLStaticContext : public QWindowsStaticOpenGLContext public: enum Extensions { - SampleBuffers = 0x1 + SampleBuffers = 0x1, + sRGBCapableFramebuffer = 0x2 }; typedef bool @@ -160,6 +161,9 @@ public: typedef int (APIENTRY *WglGetSwapInternalExt)(void); + typedef const char * + (APIENTRY *WglGetExtensionsStringARB)(HDC); + bool hasExtensions() const { return wglGetPixelFormatAttribIVARB && wglChoosePixelFormatARB && wglCreateContextAttribsARB; } @@ -185,6 +189,7 @@ public: WglCreateContextAttribsARB wglCreateContextAttribsARB; WglSwapInternalExt wglSwapInternalExt; WglGetSwapInternalExt wglGetSwapInternalExt; + WglGetExtensionsStringARB wglGetExtensionsStringARB; static QWindowsOpengl32DLL opengl32; }; diff --git a/src/plugins/platforms/windows/qwindowsole.cpp b/src/plugins/platforms/windows/qwindowsole.cpp index 9b71061aa5c..0ceb0d82fa3 100644 --- a/src/plugins/platforms/windows/qwindowsole.cpp +++ b/src/plugins/platforms/windows/qwindowsole.cpp @@ -99,39 +99,6 @@ DWORD QWindowsOleDataObject::reportedPerformedEffect() const return performedEffect; } -//--------------------------------------------------------------------- -// IUnknown Methods -//--------------------------------------------------------------------- - -STDMETHODIMP -QWindowsOleDataObject::QueryInterface(REFIID iid, void FAR* FAR* ppv) -{ - if (iid == IID_IUnknown || iid == IID_IDataObject) { - *ppv = this; - AddRef(); - return NOERROR; - } - *ppv = NULL; - return ResultFromScode(E_NOINTERFACE); -} - -STDMETHODIMP_(ULONG) -QWindowsOleDataObject::AddRef(void) -{ - return ++m_refs; -} - -STDMETHODIMP_(ULONG) -QWindowsOleDataObject::Release(void) -{ - if (--m_refs == 0) { - releaseQt(); - delete this; - return 0; - } - return m_refs; -} - STDMETHODIMP QWindowsOleDataObject::GetData(LPFORMATETC pformatetc, LPSTGMEDIUM pmedium) { @@ -323,35 +290,6 @@ bool QWindowsOleEnumFmtEtc::isNull() const return m_isNull; } -// IUnknown methods -STDMETHODIMP -QWindowsOleEnumFmtEtc::QueryInterface(REFIID riid, void FAR* FAR* ppvObj) -{ - if (riid == IID_IUnknown || riid == IID_IEnumFORMATETC) { - *ppvObj = this; - AddRef(); - return NOERROR; - } - *ppvObj = NULL; - return ResultFromScode(E_NOINTERFACE); -} - -STDMETHODIMP_(ULONG) -QWindowsOleEnumFmtEtc::AddRef(void) -{ - return ++m_dwRefs; -} - -STDMETHODIMP_(ULONG) -QWindowsOleEnumFmtEtc::Release(void) -{ - if (--m_dwRefs == 0) { - delete this; - return 0; - } - return m_dwRefs; -} - // IEnumFORMATETC methods STDMETHODIMP QWindowsOleEnumFmtEtc::Next(ULONG celt, LPFORMATETC rgelt, ULONG FAR* pceltFetched) diff --git a/src/plugins/platforms/windows/qwindowsole.h b/src/plugins/platforms/windows/qwindowsole.h index 643011272b5..fc58858f2c1 100644 --- a/src/plugins/platforms/windows/qwindowsole.h +++ b/src/plugins/platforms/windows/qwindowsole.h @@ -40,6 +40,7 @@ #ifndef QWINDOWSOLE_H #define QWINDOWSOLE_H +#include "qwindowscombase.h" #include <QtCore/qt_windows.h> #include <QtCore/QMap> @@ -53,7 +54,7 @@ QT_BEGIN_NAMESPACE class QMimeData; class QWindow; -class QWindowsOleDataObject : public IDataObject +class QWindowsOleDataObject : public QWindowsComBase<IDataObject> { public: explicit QWindowsOleDataObject(QMimeData *mimeData); @@ -63,11 +64,6 @@ public: QMimeData *mimeData() const; DWORD reportedPerformedEffect() const; - // IUnknown methods - STDMETHOD(QueryInterface)(REFIID riid, void FAR* FAR* ppvObj); - STDMETHOD_(ULONG,AddRef)(void); - STDMETHOD_(ULONG,Release)(void); - // IDataObject methods STDMETHOD(GetData)(LPFORMATETC pformatetcIn, LPSTGMEDIUM pmedium); STDMETHOD(GetDataHere)(LPFORMATETC pformatetc, LPSTGMEDIUM pmedium); @@ -82,13 +78,12 @@ public: STDMETHOD(EnumDAdvise)(LPENUMSTATDATA FAR* ppenumAdvise); private: - ULONG m_refs = 1; QPointer<QMimeData> data; const int CF_PERFORMEDDROPEFFECT; DWORD performedEffect = DROPEFFECT_NONE; }; -class QWindowsOleEnumFmtEtc : public IEnumFORMATETC +class QWindowsOleEnumFmtEtc : public QWindowsComBase<IEnumFORMATETC> { public: explicit QWindowsOleEnumFmtEtc(const QVector<FORMATETC> &fmtetcs); @@ -97,11 +92,6 @@ public: bool isNull() const; - // IUnknown methods - STDMETHOD(QueryInterface)(REFIID riid, void FAR* FAR* ppvObj); - STDMETHOD_(ULONG,AddRef)(void); - STDMETHOD_(ULONG,Release)(void); - // IEnumFORMATETC methods STDMETHOD(Next)(ULONG celt, LPFORMATETC rgelt, ULONG FAR* pceltFetched); STDMETHOD(Skip)(ULONG celt); @@ -111,7 +101,6 @@ public: private: bool copyFormatEtc(LPFORMATETC dest, const FORMATETC *src) const; - ULONG m_dwRefs = 1; ULONG m_nIndex = 0; QVector<LPFORMATETC> m_lpfmtetcs; bool m_isNull = false; diff --git a/src/plugins/platforms/windows/qwindowswindow.cpp b/src/plugins/platforms/windows/qwindowswindow.cpp index 0028ad1bd0c..121fdaeabde 100644 --- a/src/plugins/platforms/windows/qwindowswindow.cpp +++ b/src/plugins/platforms/windows/qwindowswindow.cpp @@ -224,6 +224,23 @@ QDebug operator<<(QDebug d, const WINDOWPLACEMENT &wp) << ", rcNormalPosition=" << wp.rcNormalPosition; return d; } + +QDebug operator<<(QDebug d, const GUID &guid) +{ + QDebugStateSaver saver(d); + d.nospace(); + d << '{' << hex << uppercasedigits << qSetPadChar(QLatin1Char('0')) + << qSetFieldWidth(8) << guid.Data1 + << qSetFieldWidth(0) << '-' << qSetFieldWidth(4) + << guid.Data2 << qSetFieldWidth(0) << '-' << qSetFieldWidth(4) + << guid.Data3 << qSetFieldWidth(0) << '-' << qSetFieldWidth(4) + << qSetFieldWidth(2) << guid.Data4[0] << guid.Data4[1] + << qSetFieldWidth(0) << '-' << qSetFieldWidth(2); + for (int i = 2; i < 8; ++i) + d << guid.Data4[i]; + d << qSetFieldWidth(0) << '}'; + return d; +} #endif // !QT_NO_DEBUG_STREAM // QTBUG-43872, for windows that do not have WS_EX_TOOLWINDOW set, WINDOWPLACEMENT diff --git a/src/plugins/platforms/windows/qwindowswindow.h b/src/plugins/platforms/windows/qwindowswindow.h index e541b110a66..5664539058d 100644 --- a/src/plugins/platforms/windows/qwindowswindow.h +++ b/src/plugins/platforms/windows/qwindowswindow.h @@ -359,6 +359,7 @@ QDebug operator<<(QDebug d, const MINMAXINFO &i); QDebug operator<<(QDebug d, const NCCALCSIZE_PARAMS &p); QDebug operator<<(QDebug d, const WINDOWPLACEMENT &); QDebug operator<<(QDebug d, const WINDOWPOS &); +QDebug operator<<(QDebug d, const GUID &guid); #endif // !QT_NO_DEBUG_STREAM // ---------- QWindowsGeometryHint inline functions. diff --git a/src/plugins/platforms/windows/windows.pri b/src/plugins/platforms/windows/windows.pri index 7d3ecc8aa20..1a80526aaba 100644 --- a/src/plugins/platforms/windows/windows.pri +++ b/src/plugins/platforms/windows/windows.pri @@ -29,6 +29,7 @@ SOURCES += \ $$PWD/qwin10helpers.cpp HEADERS += \ + $$PWD/qwindowscombase.h \ $$PWD/qwindowswindow.h \ $$PWD/qwindowsintegration.h \ $$PWD/qwindowscontext.h \ diff --git a/src/plugins/platforms/xcb/gl_integrations/xcb_glx/qglxintegration.cpp b/src/plugins/platforms/xcb/gl_integrations/xcb_glx/qglxintegration.cpp index 1f36a1ad2a5..492fbf7e10d 100644 --- a/src/plugins/platforms/xcb/gl_integrations/xcb_glx/qglxintegration.cpp +++ b/src/plugins/platforms/xcb/gl_integrations/xcb_glx/qglxintegration.cpp @@ -711,8 +711,7 @@ void QGLXContext::queryDummyContext() bool QGLXContext::supportsThreading() { - if (!m_queriedDummyContext) - queryDummyContext(); + queryDummyContext(); return m_supportsThreading; } diff --git a/src/plugins/platforms/xcb/gl_integrations/xcb_glx/qxcbglxintegration.cpp b/src/plugins/platforms/xcb/gl_integrations/xcb_glx/qxcbglxintegration.cpp index 77cbdd5fbad..0d02062421b 100644 --- a/src/plugins/platforms/xcb/gl_integrations/xcb_glx/qxcbglxintegration.cpp +++ b/src/plugins/platforms/xcb/gl_integrations/xcb_glx/qxcbglxintegration.cpp @@ -111,18 +111,13 @@ bool QXcbGlxIntegration::initialize(QXcbConnection *connection) m_glx_first_event = reply->first_event; - xcb_generic_error_t *error = 0; - xcb_glx_query_version_cookie_t xglx_query_cookie = xcb_glx_query_version(m_connection->xcb_connection(), - XCB_GLX_MAJOR_VERSION, - XCB_GLX_MINOR_VERSION); - xcb_glx_query_version_reply_t *xglx_query = xcb_glx_query_version_reply(m_connection->xcb_connection(), - xglx_query_cookie, &error); - if (!xglx_query || error) { + auto xglx_query = Q_XCB_REPLY(xcb_glx_query_version, m_connection->xcb_connection(), + XCB_GLX_MAJOR_VERSION, + XCB_GLX_MINOR_VERSION); + if (!xglx_query) { qCWarning(lcQpaGl) << "QXcbConnection: Failed to initialize GLX"; - free(error); return false; } - free(xglx_query); #endif m_native_interface_handler.reset(new QXcbGlxNativeInterfaceHandler(connection->nativeInterface())); diff --git a/src/plugins/platforms/xcb/gl_integrations/xcb_glx/qxcbglxwindow.cpp b/src/plugins/platforms/xcb/gl_integrations/xcb_glx/qxcbglxwindow.cpp index 8df8b28f72f..61fed6f5e36 100644 --- a/src/plugins/platforms/xcb/gl_integrations/xcb_glx/qxcbglxwindow.cpp +++ b/src/plugins/platforms/xcb/gl_integrations/xcb_glx/qxcbglxwindow.cpp @@ -41,6 +41,7 @@ #include "qxcbscreen.h" #include <QtGlxSupport/private/qglxconvenience_p.h> +#include <QDebug> QT_BEGIN_NAMESPACE @@ -58,13 +59,27 @@ const xcb_visualtype_t *QXcbGlxWindow::createVisual() QXcbScreen *scr = xcbScreen(); if (!scr) return Q_NULLPTR; - XVisualInfo *visualInfo = qglx_findVisualInfo(DISPLAY_FROM_XCB(scr), scr->screenNumber(), &m_format); + + qDebug(lcQpaGl) << "Requested format before FBConfig/Visual selection:" << m_format; + + const char *glxExts = glXQueryExtensionsString(DISPLAY_FROM_XCB(scr), scr->screenNumber()); + int flags = 0; + if (glxExts) { + qCDebug(lcQpaGl, "Available GLX extensions: %s", glxExts); + if (strstr(glxExts, "GLX_EXT_framebuffer_sRGB") || strstr(glxExts, "GLX_ARB_framebuffer_sRGB")) + flags |= QGLX_SUPPORTS_SRGB; + } + + XVisualInfo *visualInfo = qglx_findVisualInfo(DISPLAY_FROM_XCB(scr), scr->screenNumber(), &m_format, GLX_WINDOW_BIT, flags); if (!visualInfo) { qWarning() << "No XVisualInfo for format" << m_format; return Q_NULLPTR; } const xcb_visualtype_t *xcb_visualtype = scr->visualForId(visualInfo->visualid); XFree(visualInfo); + + qDebug(lcQpaGl) << "Got format:" << m_format; + return xcb_visualtype; } diff --git a/src/plugins/platforms/xcb/qxcbclipboard.cpp b/src/plugins/platforms/xcb/qxcbclipboard.cpp index 6a5d40267a6..a164ed0ef2b 100644 --- a/src/plugins/platforms/xcb/qxcbclipboard.cpp +++ b/src/plugins/platforms/xcb/qxcbclipboard.cpp @@ -305,8 +305,7 @@ QXcbClipboard::~QXcbClipboard() m_timestamp[QClipboard::Selection] != XCB_CURRENT_TIME) { // First we check if there is a clipboard manager. - xcb_get_selection_owner_cookie_t cookie = xcb_get_selection_owner(xcb_connection(), atom(QXcbAtom::CLIPBOARD_MANAGER)); - xcb_get_selection_owner_reply_t *reply = xcb_get_selection_owner_reply(xcb_connection(), cookie, 0); + auto reply = Q_XCB_REPLY(xcb_get_selection_owner, xcb_connection(), atom(QXcbAtom::CLIPBOARD_MANAGER)); if (reply && reply->owner != XCB_NONE) { // we delete the property so the manager saves all TARGETS. xcb_delete_property(xcb_connection(), m_owner, atom(QXcbAtom::_QT_SELECTION)); @@ -320,7 +319,6 @@ QXcbClipboard::~QXcbClipboard() "clipboard manager in a reasonable time"); } } - free(reply); } if (m_clientClipboard[QClipboard::Clipboard] != m_clientClipboard[QClipboard::Selection]) @@ -759,17 +757,14 @@ bool QXcbClipboard::clipboardReadProperty(xcb_window_t win, xcb_atom_t property, format = &dummy_format; // Don't read anything, just get the size of the property data - xcb_get_property_cookie_t cookie = Q_XCB_CALL(xcb_get_property(xcb_connection(), false, win, property, XCB_GET_PROPERTY_TYPE_ANY, 0, 0)); - xcb_get_property_reply_t *reply = xcb_get_property_reply(xcb_connection(), cookie, 0); + auto reply = Q_XCB_REPLY(xcb_get_property, xcb_connection(), false, win, property, XCB_GET_PROPERTY_TYPE_ANY, 0, 0); if (!reply || reply->type == XCB_NONE) { - free(reply); buffer->resize(0); return false; } *type = reply->type; *format = reply->format; bytes_left = reply->bytes_after; - free(reply); int offset = 0, buffer_offset = 0; @@ -784,17 +779,15 @@ bool QXcbClipboard::clipboardReadProperty(xcb_window_t win, xcb_atom_t property, while (bytes_left) { // more to read... - xcb_get_property_cookie_t cookie = Q_XCB_CALL(xcb_get_property(xcb_connection(), false, win, property, XCB_GET_PROPERTY_TYPE_ANY, offset, maxsize/4)); - reply = xcb_get_property_reply(xcb_connection(), cookie, 0); - if (!reply || reply->type == XCB_NONE) { - free(reply); + reply = Q_XCB_REPLY(xcb_get_property, xcb_connection(), false, win, property, XCB_GET_PROPERTY_TYPE_ANY, offset, maxsize/4); + if (!reply || reply->type == XCB_NONE) break; - } + *type = reply->type; *format = reply->format; bytes_left = reply->bytes_after; - char *data = (char *)xcb_get_property_value(reply); - int length = xcb_get_property_value_length(reply); + char *data = (char *)xcb_get_property_value(reply.get()); + int length = xcb_get_property_value_length(reply.get()); // Here we check if we get a buffer overflow and tries to // recover -- this shouldn't normally happen, but it doesn't @@ -814,7 +807,6 @@ bool QXcbClipboard::clipboardReadProperty(xcb_window_t win, xcb_atom_t property, // offset is specified in 32-bit multiples offset += length / 4; } - free(reply); } } @@ -891,13 +883,9 @@ xcb_generic_event_t *QXcbClipboard::waitForClipboardEvent(xcb_window_t win, int return e; if (checkManager) { - xcb_get_selection_owner_cookie_t cookie = xcb_get_selection_owner(xcb_connection(), atom(QXcbAtom::CLIPBOARD_MANAGER)); - xcb_get_selection_owner_reply_t *reply = xcb_get_selection_owner_reply(xcb_connection(), cookie, 0); - if (!reply || reply->owner == XCB_NONE) { - free(reply); + auto reply = Q_XCB_REPLY(xcb_get_selection_owner, xcb_connection(), atom(QXcbAtom::CLIPBOARD_MANAGER)); + if (!reply || reply->owner == XCB_NONE) return 0; - } - free(reply); } // process other clipboard events, since someone is probably requesting data from us diff --git a/src/plugins/platforms/xcb/qxcbconnection.cpp b/src/plugins/platforms/xcb/qxcbconnection.cpp index 8c5f8cae08b..c69adab357a 100644 --- a/src/plugins/platforms/xcb/qxcbconnection.cpp +++ b/src/plugins/platforms/xcb/qxcbconnection.cpp @@ -243,11 +243,8 @@ void QXcbConnection::updateScreens(const xcb_randr_notify_event_t *event) } else if (!screen && output.connection == XCB_RANDR_CONNECTION_CONNECTED) { // New XRandR output is available and it's enabled if (output.crtc != XCB_NONE && output.mode != XCB_NONE) { - xcb_randr_get_output_info_cookie_t outputInfoCookie = - xcb_randr_get_output_info(xcb_connection(), output.output, output.config_timestamp); - QScopedPointer<xcb_randr_get_output_info_reply_t, QScopedPointerPodDeleter> outputInfo( - xcb_randr_get_output_info_reply(xcb_connection(), outputInfoCookie, NULL)); - + auto outputInfo = Q_XCB_REPLY(xcb_randr_get_output_info, xcb_connection(), + output.output, output.config_timestamp); // Find a fake screen const auto scrs = virtualDesktop->screens(); for (QPlatformScreen *scr : scrs) { @@ -261,12 +258,12 @@ void QXcbConnection::updateScreens(const xcb_randr_notify_event_t *event) if (screen) { QString nameWas = screen->name(); // Transform the fake screen into a physical screen - screen->setOutput(output.output, outputInfo.data()); + screen->setOutput(output.output, outputInfo.get()); updateScreen(screen, output); qCDebug(lcQpaScreen) << "output" << screen->name() << "is connected and enabled; was fake:" << nameWas; } else { - screen = createScreen(virtualDesktop, output, outputInfo.data()); + screen = createScreen(virtualDesktop, output, outputInfo.get()); qCDebug(lcQpaScreen) << "output" << screen->name() << "is connected and enabled"; } QHighDpiScaling::updateHighDpiScaling(); @@ -274,10 +271,8 @@ void QXcbConnection::updateScreens(const xcb_randr_notify_event_t *event) } else if (screen) { if (output.crtc == XCB_NONE && output.mode == XCB_NONE) { // Screen has been disabled - xcb_randr_get_output_info_cookie_t outputInfoCookie = - xcb_randr_get_output_info(xcb_connection(), output.output, output.config_timestamp); - QScopedPointer<xcb_randr_get_output_info_reply_t, QScopedPointerPodDeleter> outputInfo( - xcb_randr_get_output_info_reply(xcb_connection(), outputInfoCookie, NULL)); + auto outputInfo = Q_XCB_REPLY(xcb_randr_get_output_info, xcb_connection(), + output.output, output.config_timestamp); if (outputInfo->crtc == XCB_NONE) { qCDebug(lcQpaScreen) << "output" << screen->name() << "has been disabled"; destroyScreen(screen); @@ -299,16 +294,10 @@ void QXcbConnection::updateScreens(const xcb_randr_notify_event_t *event) bool QXcbConnection::checkOutputIsPrimary(xcb_window_t rootWindow, xcb_randr_output_t output) { - xcb_generic_error_t *error = 0; - xcb_randr_get_output_primary_cookie_t primaryCookie = - xcb_randr_get_output_primary(xcb_connection(), rootWindow); - QScopedPointer<xcb_randr_get_output_primary_reply_t, QScopedPointerPodDeleter> primary ( - xcb_randr_get_output_primary_reply(xcb_connection(), primaryCookie, &error)); - if (!primary || error) { + auto primary = Q_XCB_REPLY(xcb_randr_get_output_primary, xcb_connection(), rootWindow); + if (!primary) qWarning("failed to get the primary output of the screen"); - free(error); - error = NULL; - } + const bool isPrimary = primary ? (primary->output == output) : false; return isPrimary; @@ -404,72 +393,59 @@ void QXcbConnection::initializeScreens() m_virtualDesktops.append(virtualDesktop); QList<QPlatformScreen *> siblings; if (has_randr_extension) { - xcb_generic_error_t *error = NULL; // RRGetScreenResourcesCurrent is fast but it may return nothing if the // configuration is not initialized wrt to the hardware. We should call // RRGetScreenResources in this case. - QScopedPointer<xcb_randr_get_screen_resources_reply_t, QScopedPointerPodDeleter> resources; - xcb_randr_get_screen_resources_current_cookie_t resourcesCookie = - xcb_randr_get_screen_resources_current(xcb_connection(), xcbScreen->root); - QScopedPointer<xcb_randr_get_screen_resources_current_reply_t, QScopedPointerPodDeleter> resources_current( - xcb_randr_get_screen_resources_current_reply(xcb_connection(), resourcesCookie, &error)); - if (!resources_current || error) { + auto resources_current = Q_XCB_REPLY(xcb_randr_get_screen_resources_current, + xcb_connection(), xcbScreen->root); + if (!resources_current) { qWarning("failed to get the current screen resources"); - free(error); } else { xcb_timestamp_t timestamp = 0; xcb_randr_output_t *outputs = Q_NULLPTR; - int outputCount = xcb_randr_get_screen_resources_current_outputs_length(resources_current.data()); + int outputCount = xcb_randr_get_screen_resources_current_outputs_length(resources_current.get()); if (outputCount) { timestamp = resources_current->config_timestamp; - outputs = xcb_randr_get_screen_resources_current_outputs(resources_current.data()); + outputs = xcb_randr_get_screen_resources_current_outputs(resources_current.get()); } else { - xcb_randr_get_screen_resources_cookie_t resourcesCookie = - xcb_randr_get_screen_resources(xcb_connection(), xcbScreen->root); - resources.reset(xcb_randr_get_screen_resources_reply(xcb_connection(), resourcesCookie, &error)); - if (!resources || error) { + auto resources = Q_XCB_REPLY(xcb_randr_get_screen_resources, + xcb_connection(), xcbScreen->root); + if (!resources) { qWarning("failed to get the screen resources"); - free(error); } else { timestamp = resources->config_timestamp; - outputCount = xcb_randr_get_screen_resources_outputs_length(resources.data()); - outputs = xcb_randr_get_screen_resources_outputs(resources.data()); + outputCount = xcb_randr_get_screen_resources_outputs_length(resources.get()); + outputs = xcb_randr_get_screen_resources_outputs(resources.get()); } } if (outputCount) { - xcb_randr_get_output_primary_cookie_t primaryCookie = - xcb_randr_get_output_primary(xcb_connection(), xcbScreen->root); - QScopedPointer<xcb_randr_get_output_primary_reply_t, QScopedPointerPodDeleter> primary( - xcb_randr_get_output_primary_reply(xcb_connection(), primaryCookie, &error)); - if (!primary || error) { + auto primary = Q_XCB_REPLY(xcb_randr_get_output_primary, xcb_connection(), xcbScreen->root); + if (!primary) { qWarning("failed to get the primary output of the screen"); - free(error); } else { for (int i = 0; i < outputCount; i++) { - QScopedPointer<xcb_randr_get_output_info_reply_t, QScopedPointerPodDeleter> output( - xcb_randr_get_output_info_reply(xcb_connection(), - xcb_randr_get_output_info_unchecked(xcb_connection(), outputs[i], timestamp), NULL)); - + auto output = Q_XCB_REPLY_UNCHECKED(xcb_randr_get_output_info, + xcb_connection(), outputs[i], timestamp); // Invalid, disconnected or disabled output - if (output == NULL) + if (!output) continue; if (output->connection != XCB_RANDR_CONNECTION_CONNECTED) { qCDebug(lcQpaScreen, "Output %s is not connected", qPrintable( - QString::fromUtf8((const char*)xcb_randr_get_output_info_name(output.data()), - xcb_randr_get_output_info_name_length(output.data())))); + QString::fromUtf8((const char*)xcb_randr_get_output_info_name(output.get()), + xcb_randr_get_output_info_name_length(output.get())))); continue; } if (output->crtc == XCB_NONE) { qCDebug(lcQpaScreen, "Output %s is not enabled", qPrintable( - QString::fromUtf8((const char*)xcb_randr_get_output_info_name(output.data()), - xcb_randr_get_output_info_name_length(output.data())))); + QString::fromUtf8((const char*)xcb_randr_get_output_info_name(output.get()), + xcb_randr_get_output_info_name_length(output.get())))); continue; } - QXcbScreen *screen = new QXcbScreen(this, virtualDesktop, outputs[i], output.data()); + QXcbScreen *screen = new QXcbScreen(this, virtualDesktop, outputs[i], output.get()); siblings << screen; m_screens << screen; @@ -492,12 +468,9 @@ void QXcbConnection::initializeScreens() } } else if (has_xinerama_extension) { // Xinerama is available - xcb_xinerama_query_screens_cookie_t cookie = xcb_xinerama_query_screens(m_connection); - xcb_xinerama_query_screens_reply_t *screens = xcb_xinerama_query_screens_reply(m_connection, - cookie, - Q_NULLPTR); + auto screens = Q_XCB_REPLY(xcb_xinerama_query_screens, m_connection); if (screens) { - xcb_xinerama_screen_info_iterator_t it = xcb_xinerama_query_screens_screen_info_iterator(screens); + xcb_xinerama_screen_info_iterator_t it = xcb_xinerama_query_screens_screen_info_iterator(screens.get()); while (it.rem) { xcb_xinerama_screen_info_t *screen_info = it.data; QXcbScreen *screen = new QXcbScreen(this, virtualDesktop, @@ -507,7 +480,6 @@ void QXcbConnection::initializeScreens() m_screens << screen; xcb_xinerama_screen_info_next(&it); } - free(screens); } } if (siblings.isEmpty()) { @@ -1461,13 +1433,7 @@ xcb_timestamp_t QXcbConnection::getTimestamp() xcb_window_t QXcbConnection::getSelectionOwner(xcb_atom_t atom) const { - xcb_connection_t *c = xcb_connection(); - xcb_get_selection_owner_cookie_t cookie = xcb_get_selection_owner(c, atom); - xcb_get_selection_owner_reply_t *reply; - reply = xcb_get_selection_owner_reply(c, cookie, 0); - xcb_window_t win = reply->owner; - free(reply); - return win; + return Q_XCB_REPLY(xcb_get_selection_owner, xcb_connection(), atom)->owner; } xcb_window_t QXcbConnection::getQtSelectionOwner() @@ -1993,11 +1959,7 @@ xcb_atom_t QXcbConnection::internAtom(const char *name) if (!name || *name == 0) return XCB_NONE; - xcb_intern_atom_cookie_t cookie = xcb_intern_atom(xcb_connection(), false, strlen(name), name); - xcb_intern_atom_reply_t *reply = xcb_intern_atom_reply(xcb_connection(), cookie, 0); - int atom = reply->atom; - free(reply); - return atom; + return Q_XCB_REPLY(xcb_intern_atom, xcb_connection(), false, strlen(name), name)->atom; } QByteArray QXcbConnection::atomName(xcb_atom_t atom) @@ -2005,18 +1967,12 @@ QByteArray QXcbConnection::atomName(xcb_atom_t atom) if (!atom) return QByteArray(); - xcb_generic_error_t *error = 0; - xcb_get_atom_name_cookie_t cookie = Q_XCB_CALL(xcb_get_atom_name(xcb_connection(), atom)); - xcb_get_atom_name_reply_t *reply = xcb_get_atom_name_reply(xcb_connection(), cookie, &error); - if (error) { + auto reply = Q_XCB_REPLY(xcb_get_atom_name, xcb_connection(), atom); + if (!reply) qWarning() << "QXcbConnection::atomName: bad Atom" << atom; - free(error); - } - if (reply) { - QByteArray result(xcb_get_atom_name_name(reply), xcb_get_atom_name_name_length(reply)); - free(reply); - return result; - } + else + return QByteArray(xcb_get_atom_name_name(reply.get()), xcb_get_atom_name_name_length(reply.get())); + return QByteArray(); } @@ -2044,23 +2000,18 @@ void QXcbConnection::sync() void QXcbConnection::initializeXFixes() { - xcb_generic_error_t *error = 0; const xcb_query_extension_reply_t *reply = xcb_get_extension_data(m_connection, &xcb_xfixes_id); if (!reply || !reply->present) return; xfixes_first_event = reply->first_event; - xcb_xfixes_query_version_cookie_t xfixes_query_cookie = xcb_xfixes_query_version(m_connection, - XCB_XFIXES_MAJOR_VERSION, - XCB_XFIXES_MINOR_VERSION); - xcb_xfixes_query_version_reply_t *xfixes_query = xcb_xfixes_query_version_reply (m_connection, - xfixes_query_cookie, &error); - if (!xfixes_query || error || xfixes_query->major_version < 2) { + auto xfixes_query = Q_XCB_REPLY(xcb_xfixes_query_version, m_connection, + XCB_XFIXES_MAJOR_VERSION, + XCB_XFIXES_MINOR_VERSION); + if (!xfixes_query || xfixes_query->major_version < 2) { qWarning("QXcbConnection: Failed to initialize XFixes"); - free(error); xfixes_first_event = 0; } - free(xfixes_query); } void QXcbConnection::initializeXRender() @@ -2070,17 +2021,11 @@ void QXcbConnection::initializeXRender() if (!reply || !reply->present) return; - xcb_generic_error_t *error = 0; - xcb_render_query_version_cookie_t xrender_query_cookie = xcb_render_query_version(m_connection, - XCB_RENDER_MAJOR_VERSION, - XCB_RENDER_MINOR_VERSION); - xcb_render_query_version_reply_t *xrender_query = xcb_render_query_version_reply(m_connection, - xrender_query_cookie, &error); - if (!xrender_query || error || (xrender_query->major_version == 0 && xrender_query->minor_version < 5)) { + auto xrender_query = Q_XCB_REPLY(xcb_render_query_version, m_connection, + XCB_RENDER_MAJOR_VERSION, + XCB_RENDER_MINOR_VERSION); + if (!xrender_query || (xrender_query->major_version == 0 && xrender_query->minor_version < 5)) qWarning("QXcbConnection: Failed to initialize XRender"); - free(error); - } - free(xrender_query); #endif } @@ -2092,21 +2037,16 @@ void QXcbConnection::initializeXRandr() xrandr_first_event = reply->first_event; - xcb_generic_error_t *error = 0; - xcb_randr_query_version_cookie_t xrandr_query_cookie = xcb_randr_query_version(m_connection, - XCB_RANDR_MAJOR_VERSION, - XCB_RANDR_MINOR_VERSION); + auto xrandr_query = Q_XCB_REPLY(xcb_randr_query_version, m_connection, + XCB_RANDR_MAJOR_VERSION, + XCB_RANDR_MINOR_VERSION); has_randr_extension = true; - xcb_randr_query_version_reply_t *xrandr_query = xcb_randr_query_version_reply(m_connection, - xrandr_query_cookie, &error); - if (!xrandr_query || error || (xrandr_query->major_version < 1 || (xrandr_query->major_version == 1 && xrandr_query->minor_version < 2))) { + if (!xrandr_query || (xrandr_query->major_version < 1 || (xrandr_query->major_version == 1 && xrandr_query->minor_version < 2))) { qWarning("QXcbConnection: Failed to initialize XRandr"); - free(error); has_randr_extension = false; } - free(xrandr_query); xcb_screen_iterator_t rootIter = xcb_setup_roots_iterator(m_setup); for (; rootIter.rem; xcb_screen_next(&rootIter)) { @@ -2126,14 +2066,8 @@ void QXcbConnection::initializeXinerama() if (!reply || !reply->present) return; - xcb_generic_error_t *error = Q_NULLPTR; - xcb_xinerama_is_active_cookie_t xinerama_query_cookie = xcb_xinerama_is_active(m_connection); - xcb_xinerama_is_active_reply_t *xinerama_is_active = xcb_xinerama_is_active_reply(m_connection, - xinerama_query_cookie, - &error); - has_xinerama_extension = xinerama_is_active && !error && xinerama_is_active->state; - free(error); - free(xinerama_is_active); + auto xinerama_is_active = Q_XCB_REPLY(xcb_xinerama_is_active, m_connection); + has_xinerama_extension = xinerama_is_active && xinerama_is_active->state; } void QXcbConnection::initializeXShape() @@ -2143,16 +2077,13 @@ void QXcbConnection::initializeXShape() return; has_shape_extension = true; - xcb_shape_query_version_cookie_t cookie = xcb_shape_query_version(m_connection); - xcb_shape_query_version_reply_t *shape_query = xcb_shape_query_version_reply(m_connection, - cookie, NULL); + auto shape_query = Q_XCB_REPLY(xcb_shape_query_version, m_connection); if (!shape_query) { qWarning("QXcbConnection: Failed to initialize SHAPE extension"); } else if (shape_query->major_version > 1 || (shape_query->major_version == 1 && shape_query->minor_version >= 1)) { // The input shape is the only thing added in SHAPE 1.1 has_input_shape = true; } - free(shape_query); } void QXcbConnection::initializeXKB() @@ -2167,11 +2098,10 @@ void QXcbConnection::initializeXKB() xkb_first_event = reply->first_event; xcb_connection_t *c = connection()->xcb_connection(); - xcb_xkb_use_extension_cookie_t xkb_query_cookie; - xcb_xkb_use_extension_reply_t *xkb_query; - xkb_query_cookie = xcb_xkb_use_extension(c, XKB_X11_MIN_MAJOR_XKB_VERSION, XKB_X11_MIN_MINOR_XKB_VERSION); - xkb_query = xcb_xkb_use_extension_reply(c, xkb_query_cookie, 0); + auto xkb_query = Q_XCB_REPLY(xcb_xkb_use_extension, c, + XKB_X11_MIN_MAJOR_XKB_VERSION, + XKB_X11_MIN_MINOR_XKB_VERSION); if (!xkb_query) { qWarning("Qt: Failed to initialize XKB extension"); @@ -2180,12 +2110,10 @@ void QXcbConnection::initializeXKB() qWarning("Qt: Unsupported XKB version (We want %d %d, but X server has %d %d)", XCB_XKB_MAJOR_VERSION, XCB_XKB_MINOR_VERSION, xkb_query->serverMajor, xkb_query->serverMinor); - free(xkb_query); return; } has_xkb = true; - free(xkb_query); const uint16_t required_map_parts = (XCB_XKB_MAP_PART_KEY_TYPES | XCB_XKB_MAP_PART_KEY_SYMS | @@ -2230,52 +2158,6 @@ bool QXcbConnection::xi2MouseEvents() const } #endif -#if defined(XCB_USE_XINPUT2) -static int xi2ValuatorOffset(const unsigned char *maskPtr, int maskLen, int number) -{ - int offset = 0; - for (int i = 0; i < maskLen; i++) { - if (number < 8) { - if ((maskPtr[i] & (1 << number)) == 0) - return -1; - } - for (int j = 0; j < 8; j++) { - if (j == number) - return offset; - if (maskPtr[i] & (1 << j)) - offset++; - } - number -= 8; - } - return -1; -} - -bool QXcbConnection::xi2GetValuatorValueIfSet(const void *event, int valuatorNum, double *value) -{ - const xXIDeviceEvent *xideviceevent = static_cast<const xXIDeviceEvent *>(event); - const unsigned char *buttonsMaskAddr = (const unsigned char*)&xideviceevent[1]; - const unsigned char *valuatorsMaskAddr = buttonsMaskAddr + xideviceevent->buttons_len * 4; - FP3232 *valuatorsValuesAddr = (FP3232*)(valuatorsMaskAddr + xideviceevent->valuators_len * 4); - - int valuatorOffset = xi2ValuatorOffset(valuatorsMaskAddr, xideviceevent->valuators_len, valuatorNum); - if (valuatorOffset < 0) - return false; - - *value = valuatorsValuesAddr[valuatorOffset].integral; - *value += ((double)valuatorsValuesAddr[valuatorOffset].frac / (1 << 16) / (1 << 16)); - return true; -} - -void QXcbConnection::xi2PrepareXIGenericDeviceEvent(xcb_ge_event_t *event) -{ - // xcb event structs contain stuff that wasn't on the wire, the full_sequence field - // adds an extra 4 bytes and generic events cookie data is on the wire right after the standard 32 bytes. - // Move this data back to have the same layout in memory as it was on the wire - // and allow casting, overwriting the full_sequence field. - memmove((char*) event + 32, (char*) event + 36, event->length * 4); -} -#endif // defined(XCB_USE_XINPUT2) - QXcbSystemTrayTracker *QXcbConnection::systemTrayTracker() const { if (!m_systemTrayTracker) { diff --git a/src/plugins/platforms/xcb/qxcbconnection.h b/src/plugins/platforms/xcb/qxcbconnection.h index 7f0d5cf2ccb..c298c08322b 100644 --- a/src/plugins/platforms/xcb/qxcbconnection.h +++ b/src/plugins/platforms/xcb/qxcbconnection.h @@ -56,6 +56,8 @@ #include <QtCore/QLoggingCategory> #include <QtCore/private/qglobal_p.h> +#include <memory> + // This is needed to make Qt compile together with XKB. xkb.h is using a variable // which is called 'explicit', this is a reserved keyword in c++ #if QT_CONFIG(xkb) @@ -731,6 +733,20 @@ private: QXcbConnection *m_connection; }; +#define Q_XCB_REPLY_CONNECTION_ARG(connection, ...) connection + +#define Q_XCB_REPLY(call, ...) \ + std::unique_ptr<call##_reply_t, decltype(std::free) *>( \ + call##_reply(Q_XCB_REPLY_CONNECTION_ARG(__VA_ARGS__), call(__VA_ARGS__), nullptr), \ + std::free \ + ) + +#define Q_XCB_REPLY_UNCHECKED(call, ...) \ + std::unique_ptr<call##_reply_t, decltype(std::free) *>( \ + call##_reply(Q_XCB_REPLY_CONNECTION_ARG(__VA_ARGS__), call##_unchecked(__VA_ARGS__), nullptr), \ + std::free \ + ) + #ifdef Q_XCB_DEBUG template <typename cookie_t> cookie_t q_xcb_call_template(const cookie_t &cookie, QXcbConnection *connection, const char *file, diff --git a/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp b/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp index 7c842ae1ba2..4f976986bb6 100644 --- a/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp +++ b/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp @@ -1008,6 +1008,50 @@ void QXcbConnection::xi2HandleScrollEvent(void *event, ScrollingDevice &scrollin #endif // XCB_USE_XINPUT21 } +static int xi2ValuatorOffset(const unsigned char *maskPtr, int maskLen, int number) +{ + int offset = 0; + for (int i = 0; i < maskLen; i++) { + if (number < 8) { + if ((maskPtr[i] & (1 << number)) == 0) + return -1; + } + for (int j = 0; j < 8; j++) { + if (j == number) + return offset; + if (maskPtr[i] & (1 << j)) + offset++; + } + number -= 8; + } + return -1; +} + +bool QXcbConnection::xi2GetValuatorValueIfSet(const void *event, int valuatorNum, double *value) +{ + const xXIDeviceEvent *xideviceevent = static_cast<const xXIDeviceEvent *>(event); + const unsigned char *buttonsMaskAddr = (const unsigned char*)&xideviceevent[1]; + const unsigned char *valuatorsMaskAddr = buttonsMaskAddr + xideviceevent->buttons_len * 4; + FP3232 *valuatorsValuesAddr = (FP3232*)(valuatorsMaskAddr + xideviceevent->valuators_len * 4); + + int valuatorOffset = xi2ValuatorOffset(valuatorsMaskAddr, xideviceevent->valuators_len, valuatorNum); + if (valuatorOffset < 0) + return false; + + *value = valuatorsValuesAddr[valuatorOffset].integral; + *value += ((double)valuatorsValuesAddr[valuatorOffset].frac / (1 << 16) / (1 << 16)); + return true; +} + +void QXcbConnection::xi2PrepareXIGenericDeviceEvent(xcb_ge_event_t *event) +{ + // xcb event structs contain stuff that wasn't on the wire, the full_sequence field + // adds an extra 4 bytes and generic events cookie data is on the wire right after the standard 32 bytes. + // Move this data back to have the same layout in memory as it was on the wire + // and allow casting, overwriting the full_sequence field. + memmove((char*) event + 32, (char*) event + 36, event->length * 4); +} + Qt::MouseButton QXcbConnection::xiToQtMouseButton(uint32_t b) { switch (b) { diff --git a/src/plugins/platforms/xcb/qxcbcursor.cpp b/src/plugins/platforms/xcb/qxcbcursor.cpp index 80fe5a21993..7f8c7af2ae1 100644 --- a/src/plugins/platforms/xcb/qxcbcursor.cpp +++ b/src/plugins/platforms/xcb/qxcbcursor.cpp @@ -629,10 +629,9 @@ void QXcbCursor::queryPointer(QXcbConnection *c, QXcbVirtualDesktop **virtualDes *pos = QPoint(); xcb_window_t root = c->primaryVirtualDesktop()->root(); - xcb_query_pointer_cookie_t cookie = xcb_query_pointer(c->xcb_connection(), root); - xcb_generic_error_t *err = 0; - xcb_query_pointer_reply_t *reply = xcb_query_pointer_reply(c->xcb_connection(), cookie, &err); - if (!err && reply) { + + auto reply = Q_XCB_REPLY(xcb_query_pointer, c->xcb_connection(), root); + if (reply) { if (virtualDesktop) { const auto virtualDesktops = c->virtualDesktops(); for (QXcbVirtualDesktop *vd : virtualDesktops) { @@ -646,11 +645,8 @@ void QXcbCursor::queryPointer(QXcbConnection *c, QXcbVirtualDesktop **virtualDes *pos = QPoint(reply->root_x, reply->root_y); if (keybMask) *keybMask = reply->mask; - free(reply); return; } - free(err); - free(reply); } QPoint QXcbCursor::pos() const diff --git a/src/plugins/platforms/xcb/qxcbdrag.cpp b/src/plugins/platforms/xcb/qxcbdrag.cpp index 58fb1f39181..4dc132c667f 100644 --- a/src/plugins/platforms/xcb/qxcbdrag.cpp +++ b/src/plugins/platforms/xcb/qxcbdrag.cpp @@ -94,32 +94,27 @@ static xcb_window_t xdndProxy(QXcbConnection *c, xcb_window_t w) { xcb_window_t proxy = XCB_NONE; - xcb_get_property_cookie_t cookie = Q_XCB_CALL2(xcb_get_property(c->xcb_connection(), false, w, c->atom(QXcbAtom::XdndProxy), - XCB_ATOM_WINDOW, 0, 1), c); - xcb_get_property_reply_t *reply = xcb_get_property_reply(c->xcb_connection(), cookie, 0); + auto reply = Q_XCB_REPLY(xcb_get_property, c->xcb_connection(), + false, w, c->atom(QXcbAtom::XdndProxy), XCB_ATOM_WINDOW, 0, 1); if (reply && reply->type == XCB_ATOM_WINDOW) - proxy = *((xcb_window_t *)xcb_get_property_value(reply)); - free(reply); + proxy = *((xcb_window_t *)xcb_get_property_value(reply.get())); if (proxy == XCB_NONE) return proxy; // exists and is real? - cookie = Q_XCB_CALL2(xcb_get_property(c->xcb_connection(), false, proxy, c->atom(QXcbAtom::XdndProxy), - XCB_ATOM_WINDOW, 0, 1), c); - reply = xcb_get_property_reply(c->xcb_connection(), cookie, 0); + reply = Q_XCB_REPLY(xcb_get_property, c->xcb_connection(), + false, proxy, c->atom(QXcbAtom::XdndProxy), XCB_ATOM_WINDOW, 0, 1); if (reply && reply->type == XCB_ATOM_WINDOW) { - xcb_window_t p = *((xcb_window_t *)xcb_get_property_value(reply)); + xcb_window_t p = *((xcb_window_t *)xcb_get_property_value(reply.get())); if (proxy != p) proxy = 0; } else { proxy = 0; } - free(reply); - return proxy; } @@ -228,28 +223,19 @@ void QXcbDrag::endDrag() initiatorWindow.clear(); } -static xcb_translate_coordinates_reply_t * -translateCoordinates(QXcbConnection *c, xcb_window_t from, xcb_window_t to, int x, int y) -{ - xcb_translate_coordinates_cookie_t cookie = - xcb_translate_coordinates(c->xcb_connection(), from, to, x, y); - return xcb_translate_coordinates_reply(c->xcb_connection(), cookie, 0); -} - static bool windowInteractsWithPosition(xcb_connection_t *connection, const QPoint & pos, xcb_window_t w, xcb_shape_sk_t shapeType) { bool interacts = false; - xcb_shape_get_rectangles_reply_t *reply = xcb_shape_get_rectangles_reply(connection, xcb_shape_get_rectangles(connection, w, shapeType), NULL); + auto reply = Q_XCB_REPLY(xcb_shape_get_rectangles, connection, w, shapeType); if (reply) { - xcb_rectangle_t *rectangles = xcb_shape_get_rectangles_rectangles(reply); + xcb_rectangle_t *rectangles = xcb_shape_get_rectangles_rectangles(reply.get()); if (rectangles) { - const int nRectangles = xcb_shape_get_rectangles_rectangles_length(reply); + const int nRectangles = xcb_shape_get_rectangles_rectangles_length(reply.get()); for (int i = 0; !interacts && i < nRectangles; ++i) { interacts = QRect(rectangles[i].x, rectangles[i].y, rectangles[i].width, rectangles[i].height).contains(pos); } } - free(reply); } return interacts; @@ -261,33 +247,25 @@ xcb_window_t QXcbDrag::findRealWindow(const QPoint & pos, xcb_window_t w, int md return 0; if (md) { - xcb_get_window_attributes_cookie_t cookie = xcb_get_window_attributes(xcb_connection(), w); - xcb_get_window_attributes_reply_t *reply = xcb_get_window_attributes_reply(xcb_connection(), cookie, 0); + auto reply = Q_XCB_REPLY(xcb_get_window_attributes, xcb_connection(), w); if (!reply) return 0; if (reply->map_state != XCB_MAP_STATE_VIEWABLE) return 0; - free(reply); - - xcb_get_geometry_cookie_t gcookie = xcb_get_geometry(xcb_connection(), w); - xcb_get_geometry_reply_t *greply = xcb_get_geometry_reply(xcb_connection(), gcookie, 0); + auto greply = Q_XCB_REPLY(xcb_get_geometry, xcb_connection(), w); if (!greply) return 0; QRect windowRect(greply->x, greply->y, greply->width, greply->height); - free(greply); if (windowRect.contains(pos)) { bool windowContainsMouse = !ignoreNonXdndAwareWindows; { - xcb_get_property_cookie_t cookie = - Q_XCB_CALL(xcb_get_property(xcb_connection(), false, w, connection()->atom(QXcbAtom::XdndAware), - XCB_GET_PROPERTY_TYPE_ANY, 0, 0)); - xcb_get_property_reply_t *reply = xcb_get_property_reply(xcb_connection(), cookie, 0); - + auto reply = Q_XCB_REPLY(xcb_get_property, xcb_connection(), + false, w, connection()->atom(QXcbAtom::XdndAware), + XCB_GET_PROPERTY_TYPE_ANY, 0, 0); bool isAware = reply && reply->type != XCB_NONE; - free(reply); if (isAware) { const QPoint relPos = pos - windowRect.topLeft(); // When ShapeInput and ShapeBounding are not set they return a single rectangle with the geometry of the window, this is why we @@ -303,19 +281,16 @@ xcb_window_t QXcbDrag::findRealWindow(const QPoint & pos, xcb_window_t w, int md } } - xcb_query_tree_cookie_t cookie = xcb_query_tree (xcb_connection(), w); - xcb_query_tree_reply_t *reply = xcb_query_tree_reply(xcb_connection(), cookie, 0); - + auto reply = Q_XCB_REPLY(xcb_query_tree, xcb_connection(), w); if (!reply) return 0; - int nc = xcb_query_tree_children_length(reply); - xcb_window_t *c = xcb_query_tree_children(reply); + int nc = xcb_query_tree_children_length(reply.get()); + xcb_window_t *c = xcb_query_tree_children(reply.get()); xcb_window_t r = 0; for (uint i = nc; !r && i--;) r = findRealWindow(pos - windowRect.topLeft(), c[i], md-1, ignoreNonXdndAwareWindows); - free(reply); if (r) return r; @@ -356,15 +331,14 @@ void QXcbDrag::move(const QPoint &globalPos) } xcb_window_t rootwin = current_virtual_desktop->root(); - xcb_translate_coordinates_reply_t *translate = - ::translateCoordinates(connection(), rootwin, rootwin, globalPos.x(), globalPos.y()); + auto translate = Q_XCB_REPLY(xcb_translate_coordinates, connection()->xcb_connection(), + rootwin, rootwin, globalPos.x(), globalPos.y()); if (!translate) return; xcb_window_t target = translate->child; int lx = translate->dst_x; int ly = translate->dst_y; - free (translate); if (target && target != rootwin) { xcb_window_t src = rootwin; @@ -372,7 +346,8 @@ void QXcbDrag::move(const QPoint &globalPos) DNDDEBUG << "checking target for XdndAware" << target << lx << ly; // translate coordinates - translate = ::translateCoordinates(connection(), src, target, lx, ly); + auto translate = Q_XCB_REPLY(xcb_translate_coordinates, connection()->xcb_connection(), + src, target, lx, ly); if (!translate) { target = 0; break; @@ -381,14 +356,11 @@ void QXcbDrag::move(const QPoint &globalPos) ly = translate->dst_y; src = target; xcb_window_t child = translate->child; - free(translate); // check if it has XdndAware - xcb_get_property_cookie_t cookie = Q_XCB_CALL(xcb_get_property(xcb_connection(), false, target, - atom(QXcbAtom::XdndAware), XCB_GET_PROPERTY_TYPE_ANY, 0, 0)); - xcb_get_property_reply_t *reply = xcb_get_property_reply(xcb_connection(), cookie, 0); + auto reply = Q_XCB_REPLY(xcb_get_property, xcb_connection(), false, target, + atom(QXcbAtom::XdndAware), XCB_GET_PROPERTY_TYPE_ANY, 0, 0); bool aware = reply && reply->type != XCB_NONE; - free(reply); if (aware) { DNDDEBUG << "Found XdndAware on " << target; break; @@ -422,16 +394,14 @@ void QXcbDrag::move(const QPoint &globalPos) int target_version = 1; if (proxy_target) { - xcb_get_property_cookie_t cookie = xcb_get_property(xcb_connection(), false, proxy_target, - atom(QXcbAtom::XdndAware), XCB_GET_PROPERTY_TYPE_ANY, 0, 1); - xcb_get_property_reply_t *reply = xcb_get_property_reply(xcb_connection(), cookie, 0); + auto reply = Q_XCB_REPLY(xcb_get_property, xcb_connection(), + false, proxy_target, + atom(QXcbAtom::XdndAware), XCB_GET_PROPERTY_TYPE_ANY, 0, 1); if (!reply || reply->type == XCB_NONE) target = 0; - target_version = *(uint32_t *)xcb_get_property_value(reply); + target_version = *(uint32_t *)xcb_get_property_value(reply.get()); target_version = qMin(xdnd_version, target_version ? target_version : 1); - - free(reply); } if (target != current_target) { @@ -714,21 +684,19 @@ void QXcbDrag::handleEnter(QPlatformWindow *window, const xcb_client_message_eve if (event->data.data32[1] & 1) { // get the types from XdndTypeList - xcb_get_property_cookie_t cookie = xcb_get_property(xcb_connection(), false, xdnd_dragsource, - atom(QXcbAtom::XdndTypelist), XCB_ATOM_ATOM, - 0, xdnd_max_type); - xcb_get_property_reply_t *reply = xcb_get_property_reply(xcb_connection(), cookie, 0); + auto reply = Q_XCB_REPLY(xcb_get_property, xcb_connection(), false, xdnd_dragsource, + atom(QXcbAtom::XdndTypelist), XCB_ATOM_ATOM, + 0, xdnd_max_type); if (reply && reply->type != XCB_NONE && reply->format == 32) { - int length = xcb_get_property_value_length(reply) / 4; + int length = xcb_get_property_value_length(reply.get()) / 4; if (length > xdnd_max_type) length = xdnd_max_type; - xcb_atom_t *atoms = (xcb_atom_t *)xcb_get_property_value(reply); + xcb_atom_t *atoms = (xcb_atom_t *)xcb_get_property_value(reply.get()); xdnd_types.reserve(length); for (int i = 0; i < length; ++i) xdnd_types.append(atoms[i]); } - free(reply); } else { // get the types from the message for(int i = 2; i < 5; i++) { @@ -1132,28 +1100,20 @@ static xcb_window_t findXdndAwareParent(QXcbConnection *c, xcb_window_t window) xcb_window_t target = 0; forever { // check if window has XdndAware - xcb_get_property_cookie_t gpCookie = Q_XCB_CALL( - xcb_get_property(c->xcb_connection(), false, window, - c->atom(QXcbAtom::XdndAware), XCB_GET_PROPERTY_TYPE_ANY, 0, 0)); - xcb_get_property_reply_t *gpReply = xcb_get_property_reply( - c->xcb_connection(), gpCookie, 0); + auto gpReply = Q_XCB_REPLY(xcb_get_property, c->xcb_connection(), false, window, + c->atom(QXcbAtom::XdndAware), XCB_GET_PROPERTY_TYPE_ANY, 0, 0); bool aware = gpReply && gpReply->type != XCB_NONE; - free(gpReply); if (aware) { target = window; break; } // try window's parent - xcb_query_tree_cookie_t qtCookie = Q_XCB_CALL( - xcb_query_tree_unchecked(c->xcb_connection(), window)); - xcb_query_tree_reply_t *qtReply = xcb_query_tree_reply( - c->xcb_connection(), qtCookie, NULL); + auto qtReply = Q_XCB_REPLY_UNCHECKED(xcb_query_tree, c->xcb_connection(), window); if (!qtReply) break; xcb_window_t root = qtReply->root; xcb_window_t parent = qtReply->parent; - free(qtReply); if (window == root) break; window = parent; diff --git a/src/plugins/platforms/xcb/qxcbimage.cpp b/src/plugins/platforms/xcb/qxcbimage.cpp index d4bdb6c7711..67a959d8a4d 100644 --- a/src/plugins/platforms/xcb/qxcbimage.cpp +++ b/src/plugins/platforms/xcb/qxcbimage.cpp @@ -91,19 +91,14 @@ QPixmap qt_xcb_pixmapFromXPixmap(QXcbConnection *connection, xcb_pixmap_t pixmap { xcb_connection_t *conn = connection->xcb_connection(); - xcb_get_image_cookie_t get_image_cookie = - xcb_get_image_unchecked(conn, XCB_IMAGE_FORMAT_Z_PIXMAP, pixmap, - 0, 0, width, height, 0xffffffff); - - xcb_get_image_reply_t *image_reply = - xcb_get_image_reply(conn, get_image_cookie, NULL); - + auto image_reply = Q_XCB_REPLY_UNCHECKED(xcb_get_image, conn, XCB_IMAGE_FORMAT_Z_PIXMAP, pixmap, + 0, 0, width, height, 0xffffffff); if (!image_reply) { return QPixmap(); } - uint8_t *data = xcb_get_image_data(image_reply); - uint32_t length = xcb_get_image_data_length(image_reply); + uint8_t *data = xcb_get_image_data(image_reply.get()); + uint32_t length = xcb_get_image_data_length(image_reply.get()); QPixmap result; @@ -165,7 +160,6 @@ QPixmap qt_xcb_pixmapFromXPixmap(QXcbConnection *connection, xcb_pixmap_t pixmap result = QPixmap::fromImage(image.copy()); } - free(image_reply); return result; } @@ -203,22 +197,15 @@ xcb_cursor_t qt_xcb_createCursorXRender(QXcbScreen *screen, const QImage &image, xcb_connection_t *conn = screen->xcb_connection(); const int w = image.width(); const int h = image.height(); - xcb_generic_error_t *error = 0; - xcb_render_query_pict_formats_cookie_t formatsCookie = xcb_render_query_pict_formats(conn); - xcb_render_query_pict_formats_reply_t *formatsReply = xcb_render_query_pict_formats_reply(conn, - formatsCookie, - &error); - if (!formatsReply || error) { + auto formats = Q_XCB_REPLY(xcb_render_query_pict_formats, conn); + if (!formats) { qWarning("qt_xcb_createCursorXRender: query_pict_formats failed"); - free(formatsReply); - free(error); return XCB_NONE; } - xcb_render_pictforminfo_t *fmt = xcb_render_util_find_standard_format(formatsReply, + xcb_render_pictforminfo_t *fmt = xcb_render_util_find_standard_format(formats.get(), XCB_PICT_STANDARD_ARGB_32); if (!fmt) { qWarning("qt_xcb_createCursorXRender: Failed to find format PICT_STANDARD_ARGB_32"); - free(formatsReply); return XCB_NONE; } @@ -230,14 +217,12 @@ xcb_cursor_t qt_xcb_createCursorXRender(QXcbScreen *screen, const QImage &image, 0, 0, 0); if (!xi) { qWarning("qt_xcb_createCursorXRender: xcb_image_create failed"); - free(formatsReply); return XCB_NONE; } xi->data = (uint8_t *) malloc(xi->stride * h); if (!xi->data) { qWarning("qt_xcb_createCursorXRender: Failed to malloc() image data"); xcb_image_destroy(xi); - free(formatsReply); return XCB_NONE; } memcpy(xi->data, img.constBits(), img.byteCount()); @@ -260,7 +245,6 @@ xcb_cursor_t qt_xcb_createCursorXRender(QXcbScreen *screen, const QImage &image, xcb_image_destroy(xi); xcb_render_free_picture(conn, pic); xcb_free_pixmap(conn, pix); - free(formatsReply); return cursor; #else diff --git a/src/plugins/platforms/xcb/qxcbkeyboard.cpp b/src/plugins/platforms/xcb/qxcbkeyboard.cpp index 2e29c208c73..e71e77695c6 100644 --- a/src/plugins/platforms/xcb/qxcbkeyboard.cpp +++ b/src/plugins/platforms/xcb/qxcbkeyboard.cpp @@ -612,23 +612,18 @@ Qt::KeyboardModifiers QXcbKeyboard::translateModifiers(int s) const void QXcbKeyboard::readXKBConfig() { clearXKBConfig(); - xcb_generic_error_t *error; - xcb_get_property_cookie_t cookie; - xcb_get_property_reply_t *config_reply; xcb_connection_t *c = xcb_connection(); xcb_window_t rootWindow = connection()->rootWindow(); - cookie = xcb_get_property(c, 0, rootWindow, - atom(QXcbAtom::_XKB_RULES_NAMES), XCB_ATOM_STRING, 0, 1024); - - config_reply = xcb_get_property_reply(c, cookie, &error); + auto config_reply = Q_XCB_REPLY(xcb_get_property, c, 0, rootWindow, + atom(QXcbAtom::_XKB_RULES_NAMES), XCB_ATOM_STRING, 0, 1024); if (!config_reply) { qWarning("Qt: Couldn't interpret the _XKB_RULES_NAMES property"); return; } - char *xkb_config = (char *)xcb_get_property_value(config_reply); - int length = xcb_get_property_value_length(config_reply); + char *xkb_config = (char *)xcb_get_property_value(config_reply.get()); + int length = xcb_get_property_value_length(config_reply.get()); // on old X servers xkb_config can be 0 even if config_reply indicates a succesfull read if (!xkb_config || length == 0) @@ -653,8 +648,6 @@ void QXcbKeyboard::readXKBConfig() xkb_names.layout = qstrdup(names[2]); xkb_names.variant = qstrdup(names[3]); xkb_names.options = qstrdup(names[4]); - - free(config_reply); } void QXcbKeyboard::clearXKBConfig() @@ -1172,23 +1165,19 @@ QXcbKeyboard::~QXcbKeyboard() void QXcbKeyboard::updateVModMapping() { #if QT_CONFIG(xkb) - xcb_xkb_get_names_cookie_t names_cookie; - xcb_xkb_get_names_reply_t *name_reply; xcb_xkb_get_names_value_list_t names_list; memset(&vmod_masks, 0, sizeof(vmod_masks)); - names_cookie = xcb_xkb_get_names(xcb_connection(), - XCB_XKB_ID_USE_CORE_KBD, - XCB_XKB_NAME_DETAIL_VIRTUAL_MOD_NAMES); - - name_reply = xcb_xkb_get_names_reply(xcb_connection(), names_cookie, 0); + auto name_reply = Q_XCB_REPLY(xcb_xkb_get_names, xcb_connection(), + XCB_XKB_ID_USE_CORE_KBD, + XCB_XKB_NAME_DETAIL_VIRTUAL_MOD_NAMES); if (!name_reply) { qWarning("Qt: failed to retrieve the virtual modifier names from XKB"); return; } - const void *buffer = xcb_xkb_get_names_value_list(name_reply); + const void *buffer = xcb_xkb_get_names_value_list(name_reply.get()); xcb_xkb_get_names_value_list_unpack(buffer, name_reply->nTypes, name_reply->indicators, @@ -1233,32 +1222,27 @@ void QXcbKeyboard::updateVModMapping() else if (qstrcmp(vmod_name, "Hyper") == 0) vmod_masks.hyper = bit; } - - free(name_reply); #endif } void QXcbKeyboard::updateVModToRModMapping() { #if QT_CONFIG(xkb) - xcb_xkb_get_map_cookie_t map_cookie; - xcb_xkb_get_map_reply_t *map_reply; xcb_xkb_get_map_map_t map; memset(&rmod_masks, 0, sizeof(rmod_masks)); - map_cookie = xcb_xkb_get_map(xcb_connection(), - XCB_XKB_ID_USE_CORE_KBD, - XCB_XKB_MAP_PART_VIRTUAL_MODS, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); - - map_reply = xcb_xkb_get_map_reply(xcb_connection(), map_cookie, 0); + auto map_reply = Q_XCB_REPLY(xcb_xkb_get_map, + xcb_connection(), + XCB_XKB_ID_USE_CORE_KBD, + XCB_XKB_MAP_PART_VIRTUAL_MODS, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); if (!map_reply) { qWarning("Qt: failed to retrieve the virtual modifier map from XKB"); return; } - const void *buffer = xcb_xkb_get_map_map(map_reply); + const void *buffer = xcb_xkb_get_map_map(map_reply.get()); xcb_xkb_get_map_map_unpack(buffer, map_reply->nTypes, map_reply->nKeySyms, @@ -1301,7 +1285,6 @@ void QXcbKeyboard::updateVModToRModMapping() rmod_masks.hyper = modmap; } - free(map_reply); resolveMaskConflicts(); #endif } @@ -1315,14 +1298,10 @@ void QXcbKeyboard::updateModifiers() // process for all modifiers whenever any part of the modifier mapping is changed. memset(&rmod_masks, 0, sizeof(rmod_masks)); - xcb_generic_error_t *error = 0; xcb_connection_t *conn = xcb_connection(); - xcb_get_modifier_mapping_cookie_t modMapCookie = xcb_get_modifier_mapping(conn); - xcb_get_modifier_mapping_reply_t *modMapReply = - xcb_get_modifier_mapping_reply(conn, modMapCookie, &error); - if (error) { + auto modMapReply = Q_XCB_REPLY(xcb_get_modifier_mapping, conn); + if (!modMapReply) { qWarning("Qt: failed to get modifier mapping"); - free(error); return; } @@ -1338,7 +1317,7 @@ void QXcbKeyboard::updateModifiers() for (size_t i = 0; i < numSymbols; ++i) modKeyCodes[i] = xcb_key_symbols_get_keycode(m_key_symbols, symbols[i]); - xcb_keycode_t *modMap = xcb_get_modifier_mapping_keycodes(modMapReply); + xcb_keycode_t *modMap = xcb_get_modifier_mapping_keycodes(modMapReply.get()); const int w = modMapReply->keycodes_per_modifier; for (size_t i = 0; i < numSymbols; ++i) { for (int bit = 0; bit < 8; ++bit) { @@ -1366,7 +1345,6 @@ void QXcbKeyboard::updateModifiers() for (size_t i = 0; i < numSymbols; ++i) free(modKeyCodes[i]); - free(modMapReply); resolveMaskConflicts(); } diff --git a/src/plugins/platforms/xcb/qxcbnativeinterface.cpp b/src/plugins/platforms/xcb/qxcbnativeinterface.cpp index 725288633a2..cc056715806 100644 --- a/src/plugins/platforms/xcb/qxcbnativeinterface.cpp +++ b/src/plugins/platforms/xcb/qxcbnativeinterface.cpp @@ -121,28 +121,19 @@ xcb_window_t QXcbNativeInterface::locateSystemTray(xcb_connection_t *conn, const { if (m_sysTraySelectionAtom == XCB_ATOM_NONE) { const QByteArray net_sys_tray = QString::fromLatin1("_NET_SYSTEM_TRAY_S%1").arg(screen->screenNumber()).toLatin1(); - xcb_intern_atom_cookie_t intern_c = - xcb_intern_atom_unchecked(conn, true, net_sys_tray.length(), net_sys_tray); - - xcb_intern_atom_reply_t *intern_r = xcb_intern_atom_reply(conn, intern_c, 0); - + auto intern_r = Q_XCB_REPLY_UNCHECKED(xcb_intern_atom, conn, + true, net_sys_tray.length(), net_sys_tray); if (!intern_r) return XCB_WINDOW_NONE; m_sysTraySelectionAtom = intern_r->atom; - free(intern_r); } - xcb_get_selection_owner_cookie_t sel_owner_c = xcb_get_selection_owner_unchecked(conn, m_sysTraySelectionAtom); - xcb_get_selection_owner_reply_t *sel_owner_r = xcb_get_selection_owner_reply(conn, sel_owner_c, 0); - + auto sel_owner_r = Q_XCB_REPLY_UNCHECKED(xcb_get_selection_owner, conn, m_sysTraySelectionAtom); if (!sel_owner_r) return XCB_WINDOW_NONE; - xcb_window_t selection_window = sel_owner_r->owner; - free(sel_owner_r); - - return selection_window; + return sel_owner_r->owner; } bool QXcbNativeInterface::systrayVisualHasAlphaChannel() @@ -457,21 +448,13 @@ void *QXcbNativeInterface::atspiBus() QXcbConnection *defaultConnection = integration->defaultConnection(); if (defaultConnection) { xcb_atom_t atspiBusAtom = defaultConnection->internAtom("AT_SPI_BUS"); - xcb_get_property_cookie_t cookie = Q_XCB_CALL2(xcb_get_property( - defaultConnection->xcb_connection(), - false, defaultConnection->rootWindow(), - atspiBusAtom, XCB_ATOM_STRING, 0, 128), - defaultConnection); - xcb_get_property_reply_t *reply = Q_XCB_CALL2(xcb_get_property_reply( - defaultConnection->xcb_connection(), - cookie, 0), - defaultConnection); + auto reply = Q_XCB_REPLY(xcb_get_property, defaultConnection->xcb_connection(), + false, defaultConnection->rootWindow(), + atspiBusAtom, XCB_ATOM_STRING, 0, 128); Q_ASSERT(!reply->bytes_after); - char *data = (char *)xcb_get_property_value(reply); - int length = xcb_get_property_value_length(reply); - QByteArray *busAddress = new QByteArray(data, length); - free(reply); - return busAddress; + char *data = (char *)xcb_get_property_value(reply.get()); + int length = xcb_get_property_value_length(reply.get()); + return new QByteArray(data, length); } return 0; } diff --git a/src/plugins/platforms/xcb/qxcbscreen.cpp b/src/plugins/platforms/xcb/qxcbscreen.cpp index 5e136b5d7e5..b1bd0a54538 100644 --- a/src/plugins/platforms/xcb/qxcbscreen.cpp +++ b/src/plugins/platforms/xcb/qxcbscreen.cpp @@ -130,11 +130,9 @@ void QXcbVirtualDesktop::subscribeToXFixesSelectionNotify() QRect QXcbVirtualDesktop::getWorkArea() const { QRect r; - xcb_get_property_reply_t * workArea = - xcb_get_property_reply(xcb_connection(), - xcb_get_property_unchecked(xcb_connection(), false, screen()->root, - atom(QXcbAtom::_NET_WORKAREA), - XCB_ATOM_CARDINAL, 0, 1024), NULL); + auto workArea = Q_XCB_REPLY_UNCHECKED(xcb_get_property, xcb_connection(), false, screen()->root, + atom(QXcbAtom::_NET_WORKAREA), + XCB_ATOM_CARDINAL, 0, 1024); if (workArea && workArea->type == XCB_ATOM_CARDINAL && workArea->format == 32 && workArea->value_len >= 4) { // If workArea->value_len > 4, the remaining ones seem to be for WM's virtual desktops // (don't mess with QXcbVirtualDesktop which represents an X screen). @@ -142,12 +140,11 @@ QRect QXcbVirtualDesktop::getWorkArea() const // "docked" panel (with _NET_WM_STRUT_PARTIAL atom set) on just one desktop. // But for now just assume the first 4 values give us the geometry of the // "work area", AKA "available geometry" - uint32_t *geom = (uint32_t*)xcb_get_property_value(workArea); + uint32_t *geom = (uint32_t*)xcb_get_property_value(workArea.get()); r = QRect(geom[0], geom[1], geom[2], geom[3]); } else { r = QRect(QPoint(), size()); } - free(workArea); return r; } @@ -181,14 +178,11 @@ QXcbScreen::QXcbScreen(QXcbConnection *connection, QXcbVirtualDesktop *virtualDe { if (connection->hasXRandr()) { xcb_randr_select_input(xcb_connection(), screen()->root, true); - xcb_randr_get_crtc_info_cookie_t crtcCookie = - xcb_randr_get_crtc_info_unchecked(xcb_connection(), m_crtc, output ? output->timestamp : 0); - xcb_randr_get_crtc_info_reply_t *crtc = - xcb_randr_get_crtc_info_reply(xcb_connection(), crtcCookie, NULL); + auto crtc = Q_XCB_REPLY_UNCHECKED(xcb_randr_get_crtc_info, xcb_connection(), + m_crtc, output ? output->timestamp : 0); if (crtc) { updateGeometry(QRect(crtc->x, crtc->y, crtc->width, crtc->height), crtc->rotation); updateRefreshRate(crtc->mode); - free(crtc); } } else if (xineramaScreenInfo) { m_geometry = QRect(xineramaScreenInfo->x_org, xineramaScreenInfo->y_org, @@ -210,10 +204,9 @@ QXcbScreen::QXcbScreen(QXcbConnection *connection, QXcbVirtualDesktop *virtualDe readXResources(); - QScopedPointer<xcb_get_window_attributes_reply_t, QScopedPointerPodDeleter> rootAttribs( - xcb_get_window_attributes_reply(xcb_connection(), - xcb_get_window_attributes_unchecked(xcb_connection(), screen()->root), NULL)); - const quint32 existingEventMask = rootAttribs.isNull() ? 0 : rootAttribs->your_event_mask; + auto rootAttribs = Q_XCB_REPLY_UNCHECKED(xcb_get_window_attributes, xcb_connection(), + screen()->root); + const quint32 existingEventMask = !rootAttribs ? 0 : rootAttribs->your_event_mask; const quint32 mask = XCB_CW_EVENT_MASK; const quint32 values[] = { @@ -227,29 +220,24 @@ QXcbScreen::QXcbScreen(QXcbConnection *connection, QXcbVirtualDesktop *virtualDe xcb_change_window_attributes(xcb_connection(), screen()->root, mask, values); - xcb_get_property_reply_t *reply = - xcb_get_property_reply(xcb_connection(), - xcb_get_property_unchecked(xcb_connection(), false, screen()->root, - atom(QXcbAtom::_NET_SUPPORTING_WM_CHECK), - XCB_ATOM_WINDOW, 0, 1024), NULL); - + auto reply = Q_XCB_REPLY_UNCHECKED(xcb_get_property, xcb_connection(), + false, screen()->root, + atom(QXcbAtom::_NET_SUPPORTING_WM_CHECK), + XCB_ATOM_WINDOW, 0, 1024); if (reply && reply->format == 32 && reply->type == XCB_ATOM_WINDOW) { - xcb_window_t windowManager = *((xcb_window_t *)xcb_get_property_value(reply)); + xcb_window_t windowManager = *((xcb_window_t *)xcb_get_property_value(reply.get())); if (windowManager != XCB_WINDOW_NONE) { - xcb_get_property_reply_t *windowManagerReply = - xcb_get_property_reply(xcb_connection(), - xcb_get_property_unchecked(xcb_connection(), false, windowManager, - atom(QXcbAtom::_NET_WM_NAME), - atom(QXcbAtom::UTF8_STRING), 0, 1024), NULL); + auto windowManagerReply = Q_XCB_REPLY_UNCHECKED(xcb_get_property, xcb_connection(), + false, windowManager, + atom(QXcbAtom::_NET_WM_NAME), + atom(QXcbAtom::UTF8_STRING), 0, 1024); if (windowManagerReply && windowManagerReply->format == 8 && windowManagerReply->type == atom(QXcbAtom::UTF8_STRING)) { - m_windowManagerName = QString::fromUtf8((const char *)xcb_get_property_value(windowManagerReply), xcb_get_property_value_length(windowManagerReply)); + m_windowManagerName = QString::fromUtf8((const char *)xcb_get_property_value(windowManagerReply.get()), + xcb_get_property_value_length(windowManagerReply.get())); } - - free(windowManagerReply); } } - free(reply); const xcb_query_extension_reply_t *sync_reply = xcb_get_extension_data(xcb_connection(), &xcb_sync_id); if (!sync_reply || !sync_reply->present) @@ -311,12 +299,7 @@ QWindow *QXcbScreen::topLevelAt(const QPoint &p) const xcb_window_t child = root; do { - xcb_translate_coordinates_cookie_t translate_cookie = - xcb_translate_coordinates_unchecked(xcb_connection(), parent, child, x, y); - - xcb_translate_coordinates_reply_t *translate_reply = - xcb_translate_coordinates_reply(xcb_connection(), translate_cookie, NULL); - + auto translate_reply = Q_XCB_REPLY_UNCHECKED(xcb_translate_coordinates, xcb_connection(), parent, child, x, y); if (!translate_reply) { return 0; } @@ -326,8 +309,6 @@ QWindow *QXcbScreen::topLevelAt(const QPoint &p) const x = translate_reply->dst_x; y = translate_reply->dst_y; - free(translate_reply); - if (!child || child == root) return 0; @@ -581,14 +562,10 @@ void QXcbScreen::updateGeometry(xcb_timestamp_t timestamp) if (!connection()->hasXRandr()) return; - xcb_randr_get_crtc_info_cookie_t crtcCookie = - xcb_randr_get_crtc_info_unchecked(xcb_connection(), m_crtc, timestamp); - xcb_randr_get_crtc_info_reply_t *crtc = - xcb_randr_get_crtc_info_reply(xcb_connection(), crtcCookie, NULL); - if (crtc) { + auto crtc = Q_XCB_REPLY_UNCHECKED(xcb_randr_get_crtc_info, xcb_connection(), + m_crtc, timestamp); + if (crtc) updateGeometry(QRect(crtc->x, crtc->y, crtc->width, crtc->height), crtc->rotation); - free(crtc); - } } void QXcbScreen::updateGeometry(const QRect &geom, uint8_t rotation) @@ -645,13 +622,11 @@ void QXcbScreen::updateRefreshRate(xcb_randr_mode_t mode) // we can safely use get_screen_resources_current here, because in order to // get here, we must have called get_screen_resources before - xcb_randr_get_screen_resources_current_cookie_t resourcesCookie = - xcb_randr_get_screen_resources_current_unchecked(xcb_connection(), screen()->root); - xcb_randr_get_screen_resources_current_reply_t *resources = - xcb_randr_get_screen_resources_current_reply(xcb_connection(), resourcesCookie, NULL); + auto resources = Q_XCB_REPLY_UNCHECKED(xcb_randr_get_screen_resources_current, + xcb_connection(), screen()->root); if (resources) { xcb_randr_mode_info_iterator_t modesIter = - xcb_randr_get_screen_resources_current_modes_iterator(resources); + xcb_randr_get_screen_resources_current_modes_iterator(resources.get()); for (; modesIter.rem; xcb_randr_mode_info_next(&modesIter)) { xcb_randr_mode_info_t *modeInfo = modesIter.data; if (modeInfo->id == mode) { @@ -662,29 +637,19 @@ void QXcbScreen::updateRefreshRate(xcb_randr_mode_t mode) } } - free(resources); QWindowSystemInterface::handleScreenRefreshRateChange(QPlatformScreen::screen(), m_refreshRate); } } -static xcb_get_geometry_reply_t *getGeometryUnchecked(xcb_connection_t *connection, xcb_window_t window) -{ - const xcb_get_geometry_cookie_t geometry_cookie = xcb_get_geometry_unchecked(connection, window); - return xcb_get_geometry_reply(connection, geometry_cookie, NULL); -} - static inline bool translate(xcb_connection_t *connection, xcb_window_t child, xcb_window_t parent, int *x, int *y) { - const xcb_translate_coordinates_cookie_t translate_cookie = - xcb_translate_coordinates_unchecked(connection, child, parent, *x, *y); - xcb_translate_coordinates_reply_t *translate_reply = - xcb_translate_coordinates_reply(connection, translate_cookie, NULL); + auto translate_reply = Q_XCB_REPLY_UNCHECKED(xcb_translate_coordinates, + connection, child, parent, *x, *y); if (!translate_reply) return false; *x = translate_reply->dst_x; *y = translate_reply->dst_y; - free(translate_reply); return true; } @@ -698,22 +663,20 @@ QPixmap QXcbScreen::grabWindow(WId window, int xIn, int yIn, int width, int heig QXcbScreen *screen = const_cast<QXcbScreen *>(this); xcb_window_t root = screen->root(); - xcb_get_geometry_reply_t *rootReply = getGeometryUnchecked(xcb_connection(), root); + auto rootReply = Q_XCB_REPLY_UNCHECKED(xcb_get_geometry, xcb_connection(), root); if (!rootReply) return QPixmap(); const quint8 rootDepth = rootReply->depth; - free(rootReply); QSize windowSize; quint8 effectiveDepth = 0; if (window) { - xcb_get_geometry_reply_t *windowReply = getGeometryUnchecked(xcb_connection(), window); + auto windowReply = Q_XCB_REPLY_UNCHECKED(xcb_get_geometry, xcb_connection(), window); if (!windowReply) return QPixmap(); windowSize = QSize(windowReply->width, windowReply->height); effectiveDepth = windowReply->depth; - free(windowReply); if (effectiveDepth == rootDepth) { // if the depth of the specified window and the root window are the // same, grab pixels from the root window (so that we get the any @@ -738,14 +701,12 @@ QPixmap QXcbScreen::grabWindow(WId window, int xIn, int yIn, int width, int heig if (height < 0) height = windowSize.height() - yIn; - xcb_get_window_attributes_reply_t *attributes_reply = - xcb_get_window_attributes_reply(xcb_connection(), xcb_get_window_attributes_unchecked(xcb_connection(), window), NULL); + auto attributes_reply = Q_XCB_REPLY_UNCHECKED(xcb_get_window_attributes, xcb_connection(), window); if (!attributes_reply) return QPixmap(); const xcb_visualtype_t *visual = screen->visualForId(attributes_reply->visual); - free(attributes_reply); xcb_pixmap_t pixmap = xcb_generate_id(xcb_connection()); xcb_create_pixmap(xcb_connection(), effectiveDepth, pixmap, window, width, height); @@ -819,21 +780,17 @@ void QXcbScreen::readXResources() int offset = 0; QByteArray resources; while(1) { - xcb_get_property_reply_t *reply = - xcb_get_property_reply(xcb_connection(), - xcb_get_property_unchecked(xcb_connection(), false, screen()->root, - XCB_ATOM_RESOURCE_MANAGER, - XCB_ATOM_STRING, offset/4, 8192), NULL); + auto reply = Q_XCB_REPLY_UNCHECKED(xcb_get_property, xcb_connection(), + false, screen()->root, + XCB_ATOM_RESOURCE_MANAGER, + XCB_ATOM_STRING, offset/4, 8192); bool more = false; if (reply && reply->format == 8 && reply->type == XCB_ATOM_STRING) { - resources += QByteArray((const char *)xcb_get_property_value(reply), xcb_get_property_value_length(reply)); - offset += xcb_get_property_value_length(reply); + resources += QByteArray((const char *)xcb_get_property_value(reply.get()), xcb_get_property_value_length(reply.get())); + offset += xcb_get_property_value_length(reply.get()); more = reply->bytes_after != 0; } - if (reply) - free(reply); - if (!more) break; } diff --git a/src/plugins/platforms/xcb/qxcbsystemtraytracker.cpp b/src/plugins/platforms/xcb/qxcbsystemtraytracker.cpp index fb0a4a39392..3939fc90054 100644 --- a/src/plugins/platforms/xcb/qxcbsystemtraytracker.cpp +++ b/src/plugins/platforms/xcb/qxcbsystemtraytracker.cpp @@ -85,13 +85,10 @@ QXcbSystemTrayTracker::QXcbSystemTrayTracker(QXcbConnection *connection, xcb_window_t QXcbSystemTrayTracker::locateTrayWindow(const QXcbConnection *connection, xcb_atom_t selection) { - xcb_get_selection_owner_cookie_t cookie = xcb_get_selection_owner(connection->xcb_connection(), selection); - xcb_get_selection_owner_reply_t *reply = xcb_get_selection_owner_reply(connection->xcb_connection(), cookie, 0); + auto reply = Q_XCB_REPLY(xcb_get_selection_owner, connection->xcb_connection(), selection); if (!reply) return 0; - const xcb_window_t result = reply->owner; - free(reply); - return result; + return reply->owner; } // API for QPlatformNativeInterface/QPlatformSystemTrayIcon: Request a window @@ -130,23 +127,16 @@ xcb_window_t QXcbSystemTrayTracker::trayWindow() // does not work for the QWindow parented on the tray. QRect QXcbSystemTrayTracker::systemTrayWindowGlobalGeometry(xcb_window_t window) const { - xcb_connection_t *conn = m_connection->xcb_connection(); - xcb_get_geometry_reply_t *geomReply = - xcb_get_geometry_reply(conn, xcb_get_geometry(conn, window), 0); + auto geomReply = Q_XCB_REPLY(xcb_get_geometry, conn, window); if (!geomReply) return QRect(); - xcb_translate_coordinates_reply_t *translateReply = - xcb_translate_coordinates_reply(conn, xcb_translate_coordinates(conn, window, m_connection->rootWindow(), 0, 0), 0); - if (!translateReply) { - free(geomReply); + auto translateReply = Q_XCB_REPLY(xcb_translate_coordinates, conn, window, m_connection->rootWindow(), 0, 0); + if (!translateReply) return QRect(); - } - const QRect result(QPoint(translateReply->dst_x, translateReply->dst_y), QSize(geomReply->width, geomReply->height)); - free(translateReply); - return result; + return QRect(QPoint(translateReply->dst_x, translateReply->dst_y), QSize(geomReply->width, geomReply->height)); } inline void QXcbSystemTrayTracker::emitSystemTrayWindowChanged() @@ -180,24 +170,18 @@ bool QXcbSystemTrayTracker::visualHasAlphaChannel() xcb_atom_t tray_atom = m_connection->atom(QXcbAtom::_NET_SYSTEM_TRAY_VISUAL); // Get the xcb property for the _NET_SYSTEM_TRAY_VISUAL atom - xcb_get_property_cookie_t systray_atom_cookie; - xcb_get_property_reply_t *systray_atom_reply; - - systray_atom_cookie = xcb_get_property_unchecked(m_connection->xcb_connection(), false, m_trayWindow, + auto systray_atom_reply = Q_XCB_REPLY_UNCHECKED(xcb_get_property, m_connection->xcb_connection(), + false, m_trayWindow, tray_atom, XCB_ATOM_VISUALID, 0, 1); - systray_atom_reply = xcb_get_property_reply(m_connection->xcb_connection(), systray_atom_cookie, 0); - if (!systray_atom_reply) return false; xcb_visualid_t systrayVisualId = XCB_NONE; - if (systray_atom_reply->value_len > 0 && xcb_get_property_value_length(systray_atom_reply) > 0) { - xcb_visualid_t * vids = (uint32_t *)xcb_get_property_value(systray_atom_reply); + if (systray_atom_reply->value_len > 0 && xcb_get_property_value_length(systray_atom_reply.get()) > 0) { + xcb_visualid_t * vids = (uint32_t *)xcb_get_property_value(systray_atom_reply.get()); systrayVisualId = vids[0]; } - free(systray_atom_reply); - if (systrayVisualId != XCB_NONE) { quint8 depth = m_connection->primaryScreen()->depthOfVisual(systrayVisualId); return depth == 32; diff --git a/src/plugins/platforms/xcb/qxcbwindow.cpp b/src/plugins/platforms/xcb/qxcbwindow.cpp index f7c36ec3867..abd41bb9424 100644 --- a/src/plugins/platforms/xcb/qxcbwindow.cpp +++ b/src/plugins/platforms/xcb/qxcbwindow.cpp @@ -669,12 +669,10 @@ QMargins QXcbWindow::frameMargins() const { if (m_dirtyFrameMargins) { if (connection()->wmSupport()->isSupportedByWM(atom(QXcbAtom::_NET_FRAME_EXTENTS))) { - xcb_get_property_cookie_t cookie = xcb_get_property(xcb_connection(), false, m_window, - atom(QXcbAtom::_NET_FRAME_EXTENTS), XCB_ATOM_CARDINAL, 0, 4); - QScopedPointer<xcb_get_property_reply_t, QScopedPointerPodDeleter> reply( - xcb_get_property_reply(xcb_connection(), cookie, NULL)); + auto reply = Q_XCB_REPLY(xcb_get_property, xcb_connection(), false, m_window, + atom(QXcbAtom::_NET_FRAME_EXTENTS), XCB_ATOM_CARDINAL, 0, 4); if (reply && reply->type == XCB_ATOM_CARDINAL && reply->format == 32 && reply->value_len == 4) { - quint32 *data = (quint32 *)xcb_get_property_value(reply.data()); + quint32 *data = (quint32 *)xcb_get_property_value(reply.get()); // _NET_FRAME_EXTENTS format is left, right, top, bottom m_frameMargins = QMargins(data[0], data[2], data[1], data[3]); m_dirtyFrameMargins = false; @@ -693,9 +691,7 @@ QMargins QXcbWindow::frameMargins() const connection()->wmSupport()->virtualRoots(); while (!foundRoot) { - xcb_query_tree_cookie_t cookie = xcb_query_tree_unchecked(xcb_connection(), parent); - - xcb_query_tree_reply_t *reply = xcb_query_tree_reply(xcb_connection(), cookie, NULL); + auto reply = Q_XCB_REPLY_UNCHECKED(xcb_query_tree, xcb_connection(), parent); if (reply) { if (reply->root == reply->parent || virtualRoots.indexOf(reply->parent) != -1 || reply->parent == XCB_WINDOW_NONE) { foundRoot = true; @@ -703,8 +699,6 @@ QMargins QXcbWindow::frameMargins() const window = parent; parent = reply->parent; } - - free(reply); } else { m_dirtyFrameMargins = false; m_frameMargins = QMargins(); @@ -714,23 +708,12 @@ QMargins QXcbWindow::frameMargins() const QPoint offset; - xcb_translate_coordinates_reply_t *reply = - xcb_translate_coordinates_reply( - xcb_connection(), - xcb_translate_coordinates(xcb_connection(), window, parent, 0, 0), - NULL); - + auto reply = Q_XCB_REPLY(xcb_translate_coordinates, xcb_connection(), window, parent, 0, 0); if (reply) { offset = QPoint(reply->dst_x, reply->dst_y); - free(reply); } - xcb_get_geometry_reply_t *geom = - xcb_get_geometry_reply( - xcb_connection(), - xcb_get_geometry(xcb_connection(), parent), - NULL); - + auto geom = Q_XCB_REPLY(xcb_get_geometry, xcb_connection(), parent); if (geom) { // -- // add the border_width for the window managers frame... some window managers @@ -747,8 +730,6 @@ QMargins QXcbWindow::frameMargins() const int bottom = geom->height + geom->border_width - geometry().height() - offset.y(); m_frameMargins = QMargins(left, top, right, bottom); - - free(geom); } m_dirtyFrameMargins = false; @@ -775,6 +756,7 @@ static inline bool testShowWithoutActivating(const QWindow *window) void QXcbWindow::show() { if (window()->isTopLevel()) { + xcb_get_property_cookie_t cookie = xcb_get_wm_hints_unchecked(xcb_connection(), m_window); xcb_wm_hints_t hints; @@ -1002,15 +984,11 @@ static QtMotifWmHints getMotifWmHints(QXcbConnection *c, xcb_window_t window) { QtMotifWmHints hints; - xcb_get_property_cookie_t get_cookie = - xcb_get_property_unchecked(c->xcb_connection(), 0, window, c->atom(QXcbAtom::_MOTIF_WM_HINTS), - c->atom(QXcbAtom::_MOTIF_WM_HINTS), 0, 20); - - xcb_get_property_reply_t *reply = - xcb_get_property_reply(c->xcb_connection(), get_cookie, NULL); + auto reply = Q_XCB_REPLY_UNCHECKED(xcb_get_property, c->xcb_connection(), 0, window, + c->atom(QXcbAtom::_MOTIF_WM_HINTS), c->atom(QXcbAtom::_MOTIF_WM_HINTS), 0, 20); if (reply && reply->format == 32 && reply->type == c->atom(QXcbAtom::_MOTIF_WM_HINTS)) { - hints = *((QtMotifWmHints *)xcb_get_property_value(reply)); + hints = *((QtMotifWmHints *)xcb_get_property_value(reply.get())); } else { hints.flags = 0L; hints.functions = MWM_FUNC_ALL; @@ -1019,8 +997,6 @@ static QtMotifWmHints getMotifWmHints(QXcbConnection *c, xcb_window_t window) hints.status = 0L; } - free(reply); - return hints; } @@ -1044,15 +1020,12 @@ QXcbWindow::NetWmStates QXcbWindow::netWmStates() { NetWmStates result(0); - xcb_get_property_cookie_t get_cookie = - xcb_get_property_unchecked(xcb_connection(), 0, m_window, atom(QXcbAtom::_NET_WM_STATE), - XCB_ATOM_ATOM, 0, 1024); - - xcb_get_property_reply_t *reply = - xcb_get_property_reply(xcb_connection(), get_cookie, NULL); + auto reply = Q_XCB_REPLY_UNCHECKED(xcb_get_property, xcb_connection(), + 0, m_window, atom(QXcbAtom::_NET_WM_STATE), + XCB_ATOM_ATOM, 0, 1024); if (reply && reply->format == 32 && reply->type == XCB_ATOM_ATOM) { - const xcb_atom_t *states = static_cast<const xcb_atom_t *>(xcb_get_property_value(reply)); + const xcb_atom_t *states = static_cast<const xcb_atom_t *>(xcb_get_property_value(reply.get())); const xcb_atom_t *statesEnd = states + reply->length; if (statesEnd != std::find(states, statesEnd, atom(QXcbAtom::_NET_WM_STATE_ABOVE))) result |= NetWmStateAbove; @@ -1070,7 +1043,6 @@ QXcbWindow::NetWmStates QXcbWindow::netWmStates() result |= NetWmStateStaysOnTop; if (statesEnd != std::find(states, statesEnd, atom(QXcbAtom::_NET_WM_STATE_DEMANDS_ATTENTION))) result |= NetWmStateDemandsAttention; - free(reply); } else { #ifdef NET_WM_STATE_DEBUG printf("getting net wm state (%x), empty\n", m_window); @@ -1084,21 +1056,15 @@ void QXcbWindow::setNetWmStates(NetWmStates states) { QVector<xcb_atom_t> atoms; - xcb_get_property_cookie_t get_cookie = - xcb_get_property_unchecked(xcb_connection(), 0, m_window, atom(QXcbAtom::_NET_WM_STATE), - XCB_ATOM_ATOM, 0, 1024); - - xcb_get_property_reply_t *reply = - xcb_get_property_reply(xcb_connection(), get_cookie, NULL); - + auto reply = Q_XCB_REPLY_UNCHECKED(xcb_get_property, xcb_connection(), + 0, m_window, atom(QXcbAtom::_NET_WM_STATE), + XCB_ATOM_ATOM, 0, 1024); if (reply && reply->format == 32 && reply->type == XCB_ATOM_ATOM && reply->value_len > 0) { - const xcb_atom_t *data = static_cast<const xcb_atom_t *>(xcb_get_property_value(reply)); + const xcb_atom_t *data = static_cast<const xcb_atom_t *>(xcb_get_property_value(reply.get())); atoms.resize(reply->value_len); memcpy((void *)&atoms.first(), (void *)data, reply->value_len * sizeof(xcb_atom_t)); } - free(reply); - if (states & NetWmStateAbove && !atoms.contains(atom(QXcbAtom::_NET_WM_STATE_ABOVE))) atoms.push_back(atom(QXcbAtom::_NET_WM_STATE_ABOVE)); if (states & NetWmStateBelow && !atoms.contains(atom(QXcbAtom::_NET_WM_STATE_BELOW))) @@ -1739,15 +1705,11 @@ QXcbWindowFunctions::WmWindowTypes QXcbWindow::wmWindowTypes() const { QXcbWindowFunctions::WmWindowTypes result(0); - xcb_get_property_cookie_t get_cookie = - xcb_get_property_unchecked(xcb_connection(), 0, m_window, atom(QXcbAtom::_NET_WM_WINDOW_TYPE), - XCB_ATOM_ATOM, 0, 1024); - - xcb_get_property_reply_t *reply = - xcb_get_property_reply(xcb_connection(), get_cookie, NULL); - + auto reply = Q_XCB_REPLY_UNCHECKED(xcb_get_property, xcb_connection(), + 0, m_window, atom(QXcbAtom::_NET_WM_WINDOW_TYPE), + XCB_ATOM_ATOM, 0, 1024); if (reply && reply->format == 32 && reply->type == XCB_ATOM_ATOM) { - const xcb_atom_t *types = static_cast<const xcb_atom_t *>(xcb_get_property_value(reply)); + const xcb_atom_t *types = static_cast<const xcb_atom_t *>(xcb_get_property_value(reply.get())); const xcb_atom_t *types_end = types + reply->length; for (; types != types_end; types++) { QXcbAtom::Atom type = connection()->qatom(*types); @@ -1801,7 +1763,6 @@ QXcbWindowFunctions::WmWindowTypes QXcbWindow::wmWindowTypes() const break; } } - free(reply); } return result; } @@ -2087,13 +2048,11 @@ void QXcbWindow::handleConfigureNotifyEvent(const xcb_configure_notify_event_t * QPoint pos(event->x, event->y); if (!parent() && !fromSendEvent) { // Do not trust the position, query it instead. - xcb_translate_coordinates_cookie_t cookie = xcb_translate_coordinates(xcb_connection(), xcb_window(), - xcbScreen()->root(), 0, 0); - xcb_translate_coordinates_reply_t *reply = xcb_translate_coordinates_reply(xcb_connection(), cookie, NULL); + auto reply = Q_XCB_REPLY(xcb_translate_coordinates, xcb_connection(), + xcb_window(), xcbScreen()->root(), 0, 0); if (reply) { pos.setX(reply->dst_x); pos.setY(reply->dst_y); - free(reply); } } @@ -2148,15 +2107,12 @@ QPoint QXcbWindow::mapToGlobal(const QPoint &pos) const return pos; QPoint ret; - xcb_translate_coordinates_cookie_t cookie = - xcb_translate_coordinates(xcb_connection(), xcb_window(), xcbScreen()->root(), - pos.x(), pos.y()); - xcb_translate_coordinates_reply_t *reply = - xcb_translate_coordinates_reply(xcb_connection(), cookie, NULL); + auto reply = Q_XCB_REPLY(xcb_translate_coordinates, xcb_connection(), + xcb_window(), xcbScreen()->root(), + pos.x(), pos.y()); if (reply) { ret.setX(reply->dst_x); ret.setY(reply->dst_y); - free(reply); } return ret; @@ -2168,15 +2124,12 @@ QPoint QXcbWindow::mapFromGlobal(const QPoint &pos) const return pos; QPoint ret; - xcb_translate_coordinates_cookie_t cookie = - xcb_translate_coordinates(xcb_connection(), xcbScreen()->root(), xcb_window(), - pos.x(), pos.y()); - xcb_translate_coordinates_reply_t *reply = - xcb_translate_coordinates_reply(xcb_connection(), cookie, NULL); + auto reply = Q_XCB_REPLY(xcb_translate_coordinates, xcb_connection(), + xcbScreen()->root(), xcb_window(), + pos.x(), pos.y()); if (reply) { ret.setX(reply->dst_x); ret.setY(reply->dst_y); - free(reply); } return ret; @@ -2529,15 +2482,11 @@ void QXcbWindow::handlePropertyNotifyEvent(const xcb_property_notify_event_t *ev Qt::WindowState newState = Qt::WindowNoState; if (event->atom == atom(QXcbAtom::WM_STATE)) { // WM_STATE: Quick check for 'Minimize'. - const xcb_get_property_cookie_t get_cookie = - xcb_get_property(xcb_connection(), 0, m_window, atom(QXcbAtom::WM_STATE), - XCB_ATOM_ANY, 0, 1024); - - xcb_get_property_reply_t *reply = - xcb_get_property_reply(xcb_connection(), get_cookie, NULL); - + auto reply = Q_XCB_REPLY(xcb_get_property, xcb_connection(), + 0, m_window, atom(QXcbAtom::WM_STATE), + XCB_ATOM_ANY, 0, 1024); if (reply && reply->format == 32 && reply->type == atom(QXcbAtom::WM_STATE)) { - const quint32 *data = (const quint32 *)xcb_get_property_value(reply); + const quint32 *data = (const quint32 *)xcb_get_property_value(reply.get()); if (reply->length != 0) { if (data[0] == XCB_WM_STATE_ICONIC || (data[0] == XCB_WM_STATE_WITHDRAWN @@ -2546,7 +2495,6 @@ void QXcbWindow::handlePropertyNotifyEvent(const xcb_property_notify_event_t *ev } } } - free(reply); } else { // _NET_WM_STATE can't change minimized state if (m_lastWindowStateEvent == Qt::WindowMinimized) newState = Qt::WindowMinimized; @@ -2623,13 +2571,11 @@ bool QXcbWindow::setKeyboardGrabEnabled(bool grab) xcb_ungrab_keyboard(xcb_connection(), XCB_TIME_CURRENT_TIME); return true; } - xcb_grab_keyboard_cookie_t cookie = xcb_grab_keyboard(xcb_connection(), false, - m_window, XCB_TIME_CURRENT_TIME, - XCB_GRAB_MODE_ASYNC, XCB_GRAB_MODE_ASYNC); - xcb_grab_keyboard_reply_t *reply = xcb_grab_keyboard_reply(xcb_connection(), cookie, NULL); - bool result = !(!reply || reply->status != XCB_GRAB_STATUS_SUCCESS); - free(reply); - return result; + + auto reply = Q_XCB_REPLY(xcb_grab_keyboard, xcb_connection(), false, + m_window, XCB_TIME_CURRENT_TIME, + XCB_GRAB_MODE_ASYNC, XCB_GRAB_MODE_ASYNC); + return reply && reply->status == XCB_GRAB_STATUS_SUCCESS; } bool QXcbWindow::setMouseGrabEnabled(bool grab) @@ -2651,16 +2597,16 @@ bool QXcbWindow::setMouseGrabEnabled(bool grab) xcb_ungrab_pointer(xcb_connection(), XCB_TIME_CURRENT_TIME); return true; } - xcb_grab_pointer_cookie_t cookie = xcb_grab_pointer(xcb_connection(), false, m_window, - (XCB_EVENT_MASK_BUTTON_PRESS | XCB_EVENT_MASK_BUTTON_RELEASE - | XCB_EVENT_MASK_BUTTON_MOTION | XCB_EVENT_MASK_ENTER_WINDOW - | XCB_EVENT_MASK_LEAVE_WINDOW | XCB_EVENT_MASK_POINTER_MOTION), - XCB_GRAB_MODE_ASYNC, XCB_GRAB_MODE_ASYNC, - XCB_WINDOW_NONE, XCB_CURSOR_NONE, - XCB_TIME_CURRENT_TIME); - xcb_grab_pointer_reply_t *reply = xcb_grab_pointer_reply(xcb_connection(), cookie, NULL); - bool result = !(!reply || reply->status != XCB_GRAB_STATUS_SUCCESS); - free(reply); + + auto reply = Q_XCB_REPLY(xcb_grab_pointer, xcb_connection(), + false, m_window, + (XCB_EVENT_MASK_BUTTON_PRESS | XCB_EVENT_MASK_BUTTON_RELEASE + | XCB_EVENT_MASK_BUTTON_MOTION | XCB_EVENT_MASK_ENTER_WINDOW + | XCB_EVENT_MASK_LEAVE_WINDOW | XCB_EVENT_MASK_POINTER_MOTION), + XCB_GRAB_MODE_ASYNC, XCB_GRAB_MODE_ASYNC, + XCB_WINDOW_NONE, XCB_CURSOR_NONE, + XCB_TIME_CURRENT_TIME); + bool result = reply && reply->status == XCB_GRAB_STATUS_SUCCESS; if (result) connection()->setMouseGrabber(this); return result; diff --git a/src/plugins/platforms/xcb/qxcbwmsupport.cpp b/src/plugins/platforms/xcb/qxcbwmsupport.cpp index 470f021314a..05cf4c6c1aa 100644 --- a/src/plugins/platforms/xcb/qxcbwmsupport.cpp +++ b/src/plugins/platforms/xcb/qxcbwmsupport.cpp @@ -66,16 +66,15 @@ void QXcbWMSupport::updateNetWMAtoms() int offset = 0; int remaining = 0; do { - xcb_get_property_cookie_t cookie = xcb_get_property(xcb_connection(), false, root, atom(QXcbAtom::_NET_SUPPORTED), XCB_ATOM_ATOM, offset, 1024); - xcb_get_property_reply_t *reply = xcb_get_property_reply(xcb_connection(), cookie, NULL); + auto reply = Q_XCB_REPLY(xcb_get_property, xcb_connection(), false, root, atom(QXcbAtom::_NET_SUPPORTED), XCB_ATOM_ATOM, offset, 1024); if (!reply) break; remaining = 0; if (reply->type == XCB_ATOM_ATOM && reply->format == 32) { - int len = xcb_get_property_value_length(reply)/sizeof(xcb_atom_t); - xcb_atom_t *atoms = (xcb_atom_t *)xcb_get_property_value(reply); + int len = xcb_get_property_value_length(reply.get())/sizeof(xcb_atom_t); + xcb_atom_t *atoms = (xcb_atom_t *)xcb_get_property_value(reply.get()); int s = net_wm_atoms.size(); net_wm_atoms.resize(s + len); memcpy(net_wm_atoms.data() + s, atoms, len*sizeof(xcb_atom_t)); @@ -83,8 +82,6 @@ void QXcbWMSupport::updateNetWMAtoms() remaining = reply->bytes_after; offset += len; } - - free(reply); } while (remaining > 0); } @@ -100,16 +97,16 @@ void QXcbWMSupport::updateVirtualRoots() int offset = 0; int remaining = 0; do { - xcb_get_property_cookie_t cookie = xcb_get_property(xcb_connection(), false, root, atom(QXcbAtom::_NET_VIRTUAL_ROOTS), XCB_ATOM_WINDOW, offset, 1024); - xcb_get_property_reply_t *reply = xcb_get_property_reply(xcb_connection(), cookie, NULL); + auto reply = Q_XCB_REPLY(xcb_get_property, xcb_connection(), + false, root, atom(QXcbAtom::_NET_VIRTUAL_ROOTS), XCB_ATOM_WINDOW, offset, 1024); if (!reply) break; remaining = 0; if (reply->type == XCB_ATOM_WINDOW && reply->format == 32) { - int len = xcb_get_property_value_length(reply)/sizeof(xcb_window_t); - xcb_window_t *roots = (xcb_window_t *)xcb_get_property_value(reply); + int len = xcb_get_property_value_length(reply.get())/sizeof(xcb_window_t); + xcb_window_t *roots = (xcb_window_t *)xcb_get_property_value(reply.get()); int s = net_virtual_roots.size(); net_virtual_roots.resize(s + len); memcpy(net_virtual_roots.data() + s, roots, len*sizeof(xcb_window_t)); @@ -118,7 +115,6 @@ void QXcbWMSupport::updateVirtualRoots() offset += len; } - free(reply); } while (remaining > 0); #ifdef Q_XCB_DEBUG diff --git a/src/plugins/platforms/xcb/qxcbxsettings.cpp b/src/plugins/platforms/xcb/qxcbxsettings.cpp index 401eb8043c7..bd398ea049e 100644 --- a/src/plugins/platforms/xcb/qxcbxsettings.cpp +++ b/src/plugins/platforms/xcb/qxcbxsettings.cpp @@ -45,10 +45,6 @@ #include <vector> #include <algorithm> -#ifdef XCB_USE_XLIB -#include <X11/extensions/XIproto.h> -#endif //XCB_USE_XLIB - QT_BEGIN_NAMESPACE /* Implementation of http://standards.freedesktop.org/xsettings-spec/xsettings-0.5.html */ @@ -110,26 +106,23 @@ public: QByteArray settings; xcb_atom_t _xsettings_atom = screen->connection()->atom(QXcbAtom::_XSETTINGS_SETTINGS); while (1) { - xcb_get_property_cookie_t get_prop_cookie = - xcb_get_property_unchecked(screen->xcb_connection(), + auto reply = Q_XCB_REPLY_UNCHECKED(xcb_get_property, + screen->xcb_connection(), false, x_settings_window, _xsettings_atom, _xsettings_atom, offset/4, 8192); - xcb_get_property_reply_t *reply = xcb_get_property_reply(screen->xcb_connection(), get_prop_cookie, NULL); bool more = false; if (!reply) return settings; - const auto property_value_length = xcb_get_property_value_length(reply); - settings.append(static_cast<const char *>(xcb_get_property_value(reply)), property_value_length); + const auto property_value_length = xcb_get_property_value_length(reply.get()); + settings.append(static_cast<const char *>(xcb_get_property_value(reply.get())), property_value_length); offset += property_value_length; more = reply->bytes_after != 0; - free(reply); - if (!more) break; } @@ -145,19 +138,18 @@ public: return value + 4 - remainder; } -#ifdef XCB_USE_XLIB void populateSettings(const QByteArray &xSettings) { if (xSettings.length() < 12) return; char byteOrder = xSettings.at(0); - if (byteOrder != LSBFirst && byteOrder != MSBFirst) { + if (byteOrder != XCB_IMAGE_ORDER_LSB_FIRST && byteOrder != XCB_IMAGE_ORDER_MSB_FIRST) { qWarning("ByteOrder byte %d not 0 or 1", byteOrder); return; } #define ADJUST_BO(b, t, x) \ - ((b == LSBFirst) ? \ + ((b == XCB_IMAGE_ORDER_LSB_FIRST) ? \ qFromLittleEndian<t>(x) : \ qFromBigEndian<t>(x)) #define VALIDATE_LENGTH(x) \ @@ -220,7 +212,6 @@ public: } } -#endif //XCB_USE_XLIB QXcbVirtualDesktop *screen; xcb_window_t x_settings_window; @@ -234,43 +225,31 @@ QXcbXSettings::QXcbXSettings(QXcbVirtualDesktop *screen) { QByteArray settings_atom_for_screen("_XSETTINGS_S"); settings_atom_for_screen.append(QByteArray::number(screen->number())); - xcb_intern_atom_cookie_t atom_cookie = xcb_intern_atom(screen->xcb_connection(), - true, - settings_atom_for_screen.length(), - settings_atom_for_screen.constData()); - xcb_generic_error_t *error = 0; - xcb_intern_atom_reply_t *atom_reply = xcb_intern_atom_reply(screen->xcb_connection(),atom_cookie,&error); - if (error) { - free(error); + auto atom_reply = Q_XCB_REPLY(xcb_intern_atom, + screen->xcb_connection(), + true, + settings_atom_for_screen.length(), + settings_atom_for_screen.constData()); + if (!atom_reply) return; - } - xcb_atom_t selection_owner_atom = atom_reply->atom; - free(atom_reply); - xcb_get_selection_owner_cookie_t selection_cookie = - xcb_get_selection_owner(screen->xcb_connection(), selection_owner_atom); + xcb_atom_t selection_owner_atom = atom_reply->atom; - xcb_get_selection_owner_reply_t *selection_result = - xcb_get_selection_owner_reply(screen->xcb_connection(), selection_cookie, &error); - if (error) { - free(error); + auto selection_result = Q_XCB_REPLY(xcb_get_selection_owner, + screen->xcb_connection(), selection_owner_atom); + if (!selection_result) return; - } d_ptr->x_settings_window = selection_result->owner; - free(selection_result); - if (!d_ptr->x_settings_window) { + if (!d_ptr->x_settings_window) return; - } const uint32_t event = XCB_CW_EVENT_MASK; const uint32_t event_mask[] = { XCB_EVENT_MASK_STRUCTURE_NOTIFY|XCB_EVENT_MASK_PROPERTY_CHANGE }; xcb_change_window_attributes(screen->xcb_connection(),d_ptr->x_settings_window,event,event_mask); -#ifdef XCB_USE_XLIB d_ptr->populateSettings(d_ptr->getSettings()); d_ptr->initialized = true; -#endif //XCB_USE_XLIB } QXcbXSettings::~QXcbXSettings() @@ -290,9 +269,8 @@ void QXcbXSettings::handlePropertyNotifyEvent(const xcb_property_notify_event_t Q_D(QXcbXSettings); if (event->window != d->x_settings_window) return; -#ifdef XCB_USE_XLIB + d->populateSettings(d->getSettings()); -#endif //XCB_USE_XLIB } void QXcbXSettings::registerCallbackForProperty(const QByteArray &property, QXcbXSettings::PropertyChangeFunc func, void *handle) diff --git a/src/plugins/sqldrivers/sqlite/qsql_sqlite.cpp b/src/plugins/sqldrivers/sqlite/qsql_sqlite.cpp index 1cb0f10494a..56eceeecbd4 100644 --- a/src/plugins/sqldrivers/sqlite/qsql_sqlite.cpp +++ b/src/plugins/sqldrivers/sqlite/qsql_sqlite.cpp @@ -51,6 +51,10 @@ #include <qstringlist.h> #include <qvector.h> #include <qdebug.h> +#ifndef QT_NO_REGULAREXPRESSION +#include <qcache.h> +#include <qregularexpression.h> +#endif #if defined Q_OS_WIN # include <qt_windows.h> @@ -556,6 +560,37 @@ QVariant QSQLiteResult::handle() const ///////////////////////////////////////////////////////// +#ifndef QT_NO_REGULAREXPRESSION +static void _q_regexp(sqlite3_context* context, int argc, sqlite3_value** argv) +{ + if (Q_UNLIKELY(argc != 2)) { + sqlite3_result_int(context, 0); + return; + } + + const QString pattern = QString::fromUtf8( + reinterpret_cast<const char*>(sqlite3_value_text(argv[0]))); + const QString subject = QString::fromUtf8( + reinterpret_cast<const char*>(sqlite3_value_text(argv[1]))); + + auto cache = static_cast<QCache<QString, QRegularExpression>*>(sqlite3_user_data(context)); + QRegularExpression *regexp = cache->object(pattern); + if (!regexp) { + regexp = new QRegularExpression(pattern, QRegularExpression::DontCaptureOption + | QRegularExpression::OptimizeOnFirstUsageOption); + cache->insert(pattern, regexp); + } + const bool found = subject.contains(*regexp); + + sqlite3_result_int(context, int(found)); +} + +static void _q_regexp_cleanup(void *cache) +{ + delete static_cast<QCache<QString, QRegularExpression>*>(cache); +} +#endif + QSQLiteDriver::QSQLiteDriver(QObject * parent) : QSqlDriver(*new QSQLiteDriverPrivate, parent) { @@ -615,6 +650,11 @@ bool QSQLiteDriver::open(const QString & db, const QString &, const QString &, c bool sharedCache = false; bool openReadOnlyOption = false; bool openUriOption = false; +#ifndef QT_NO_REGULAREXPRESSION + static const QLatin1String regexpConnectOption = QLatin1String("QSQLITE_ENABLE_REGEXP"); + bool defineRegexp = false; + int regexpCacheSize = 25; +#endif const auto opts = conOpts.splitRef(QLatin1Char(';')); for (auto option : opts) { @@ -634,6 +674,22 @@ bool QSQLiteDriver::open(const QString & db, const QString &, const QString &, c } else if (option == QLatin1String("QSQLITE_ENABLE_SHARED_CACHE")) { sharedCache = true; } +#ifndef QT_NO_REGULAREXPRESSION + else if (option.startsWith(regexpConnectOption)) { + option = option.mid(regexpConnectOption.size()).trimmed(); + if (option.isEmpty()) { + defineRegexp = true; + } else if (option.startsWith(QLatin1Char('='))) { + bool ok = false; + const int cacheSize = option.mid(1).trimmed().toInt(&ok); + if (ok) { + defineRegexp = true; + if (cacheSize > 0) + regexpCacheSize = cacheSize; + } + } + } +#endif } int openMode = (openReadOnlyOption ? SQLITE_OPEN_READONLY : (SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE)); @@ -646,6 +702,13 @@ bool QSQLiteDriver::open(const QString & db, const QString &, const QString &, c sqlite3_busy_timeout(d->access, timeOut); setOpen(true); setOpenError(false); +#ifndef QT_NO_REGULAREXPRESSION + if (defineRegexp) { + auto cache = new QCache<QString, QRegularExpression>(regexpCacheSize); + sqlite3_create_function_v2(d->access, "regexp", 2, SQLITE_UTF8, cache, &_q_regexp, NULL, + NULL, &_q_regexp_cleanup); + } +#endif return true; } else { if (d->access) { diff --git a/src/sql/doc/snippets/code/doc_src_sql-driver.cpp b/src/sql/doc/snippets/code/doc_src_sql-driver.cpp index f25ad4f2b05..7983386642b 100644 --- a/src/sql/doc/snippets/code/doc_src_sql-driver.cpp +++ b/src/sql/doc/snippets/code/doc_src_sql-driver.cpp @@ -90,3 +90,8 @@ qDebug() << q.value(0); // outputs the first RETURN/OUT value QSqlDatabase: QMYSQL driver not loaded QSqlDatabase: available drivers: QMYSQL //! [31] + + +//! [34] +column.contains(QRegularExpression("pattern")); +//! [34] diff --git a/src/sql/doc/src/sql-driver.qdoc b/src/sql/doc/src/sql-driver.qdoc index 364d733e924..57a53006c4b 100644 --- a/src/sql/doc/src/sql-driver.qdoc +++ b/src/sql/doc/src/sql-driver.qdoc @@ -568,6 +568,22 @@ \snippet code/doc_src_sql-driver.qdoc 23 + \section3 Enable REGEXP operator + + SQLite comes with a REGEXP operation. However the needed implementation must + be provided by the user. For convenience a default implementation can be + enabled by \l{QSqlDatabase::setConnectOptions()} {setting the connect + option} \c{QSQLITE_ENABLE_REGEXP} before \l{QSqlDatabase::open()} {the + database connection is opened}. Then a SQL statement like "column REGEXP + 'pattern'" basically expands to the Qt code + + \snippet code/doc_src_sql-driver.cpp 34 + + For better performance the regular expressions are cached internally. By + default the cache size is 25, but it can be changed through the option's + value. For example passing "\c{QSQLITE_ENABLE_REGEXP=10}" reduces the + cache size to 10. + \section3 QSQLITE File Format Compatibility SQLite minor releases sometimes break file format forward compatibility. diff --git a/src/sql/kernel/qsqldatabase.cpp b/src/sql/kernel/qsqldatabase.cpp index 0416215870e..eb3a3c444dc 100644 --- a/src/sql/kernel/qsqldatabase.cpp +++ b/src/sql/kernel/qsqldatabase.cpp @@ -1175,6 +1175,7 @@ QSqlRecord QSqlDatabase::record(const QString& tablename) const \li QSQLITE_OPEN_READONLY \li QSQLITE_OPEN_URI \li QSQLITE_ENABLE_SHARED_CACHE + \li QSQLITE_ENABLE_REGEXP \endlist \li diff --git a/src/widgets/dialogs/qprogressdialog.cpp b/src/widgets/dialogs/qprogressdialog.cpp index 26a8fcc92df..0a6253ea271 100644 --- a/src/widgets/dialogs/qprogressdialog.cpp +++ b/src/widgets/dialogs/qprogressdialog.cpp @@ -244,7 +244,7 @@ void QProgressDialogPrivate::_q_disconnectOnClose() A modeless progress dialog is suitable for operations that take place in the background, where the user is able to interact with the application. Such operations are typically based on QTimer (or - QObject::timerEvent()), QSocketNotifier, or QUrlOperator; or performed + QObject::timerEvent()) or QSocketNotifier; or performed in a separate thread. A QProgressBar in the status bar of your main window is often an alternative to a modeless progress dialog. diff --git a/src/widgets/graphicsview/qgraphicswidget_p.cpp b/src/widgets/graphicsview/qgraphicswidget_p.cpp index 660620a5d94..f3c568fa015 100644 --- a/src/widgets/graphicsview/qgraphicswidget_p.cpp +++ b/src/widgets/graphicsview/qgraphicswidget_p.cpp @@ -52,9 +52,6 @@ #include <QtWidgets/qstyleoption.h> #include <QtWidgets/QStyleOptionTitleBar> #include <QtWidgets/QGraphicsSceneMouseEvent> -#if 0 /* Used to be included in Qt4 for Q_WS_MAC */ && QT_CONFIG(style_mac) -# include <private/qmacstyle_mac_p.h> -#endif QT_BEGIN_NAMESPACE diff --git a/src/widgets/kernel/qopenglwidget.cpp b/src/widgets/kernel/qopenglwidget.cpp index 147e0774e7a..4d457821706 100644 --- a/src/widgets/kernel/qopenglwidget.cpp +++ b/src/widgets/kernel/qopenglwidget.cpp @@ -566,7 +566,8 @@ public: paintDevice(0), updateBehavior(QOpenGLWidget::NoPartialUpdate), requestedSamples(0), - inPaintGL(false) + inPaintGL(false), + textureFormat(0) { requestedFormat = QSurfaceFormat::defaultFormat(); } @@ -580,6 +581,7 @@ public: void recreateFbo(); GLuint textureId() const Q_DECL_OVERRIDE; + QPlatformTextureList::Flags textureListFlags() Q_DECL_OVERRIDE; void initialize(); void invokeUserPaint(); @@ -610,6 +612,7 @@ public: QOpenGLWidget::UpdateBehavior updateBehavior; int requestedSamples; bool inPaintGL; + GLenum textureFormat; }; void QOpenGLWidgetPaintDevicePrivate::beginPaint() @@ -654,6 +657,35 @@ GLuint QOpenGLWidgetPrivate::textureId() const return resolvedFbo ? resolvedFbo->texture() : (fbo ? fbo->texture() : 0); } +#ifndef GL_SRGB +#define GL_SRGB 0x8C40 +#endif +#ifndef GL_SRGB8 +#define GL_SRGB8 0x8C41 +#endif +#ifndef GL_SRGB_ALPHA +#define GL_SRGB_ALPHA 0x8C42 +#endif +#ifndef GL_SRGB8_ALPHA8 +#define GL_SRGB8_ALPHA8 0x8C43 +#endif + +QPlatformTextureList::Flags QOpenGLWidgetPrivate::textureListFlags() +{ + QPlatformTextureList::Flags flags = QWidgetPrivate::textureListFlags(); + switch (textureFormat) { + case GL_SRGB: + case GL_SRGB8: + case GL_SRGB_ALPHA: + case GL_SRGB8_ALPHA8: + flags |= QPlatformTextureList::TextureIsSrgb; + break; + default: + break; + } + return flags; +} + void QOpenGLWidgetPrivate::reset() { Q_Q(QOpenGLWidget); @@ -703,12 +735,16 @@ void QOpenGLWidgetPrivate::recreateFbo() QOpenGLFramebufferObjectFormat format; format.setAttachment(QOpenGLFramebufferObject::CombinedDepthStencil); format.setSamples(samples); + if (textureFormat) + format.setInternalTextureFormat(textureFormat); const QSize deviceSize = q->size() * q->devicePixelRatioF(); fbo = new QOpenGLFramebufferObject(deviceSize, format); if (samples > 0) resolvedFbo = new QOpenGLFramebufferObject(deviceSize); + textureFormat = fbo->format().internalTextureFormat(); + fbo->bind(); context->functions()->glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); @@ -767,7 +803,9 @@ void QOpenGLWidgetPrivate::initialize() return; } - // Propagate settings that make sense only for the tlw. + // Propagate settings that make sense only for the tlw. Note that this only + // makes sense for properties that get picked up even after the native + // window is created. QSurfaceFormat tlwFormat = tlw->windowHandle()->format(); if (requestedFormat.swapInterval() != tlwFormat.swapInterval()) { // Most platforms will pick up the changed swap interval on the next @@ -990,7 +1028,6 @@ QOpenGLWidget::UpdateBehavior QOpenGLWidget::updateBehavior() const */ void QOpenGLWidget::setFormat(const QSurfaceFormat &format) { - Q_UNUSED(format); Q_D(QOpenGLWidget); if (Q_UNLIKELY(d->initialized)) { qWarning("QOpenGLWidget: Already initialized, setting the format has no effect"); @@ -1023,6 +1060,47 @@ QSurfaceFormat QOpenGLWidget::format() const } /*! + Sets a custom internal texture format. + + When working with sRGB framebuffers, it will be necessary to specify a + format like \c{GL_SRGB8_ALPHA8}. This can be achieved by calling this + function. + + \note This function has no effect if called after the widget has already + been shown and thus it performed initialization. + + \note This function will typically have to be used in combination with a + QSurfaceFormat::setDefaultFormat() call that sets the color space to + QSurfaceFormat::sRGBColorSpace. + + \since 5.10 + */ +void QOpenGLWidget::setTextureFormat(GLenum texFormat) +{ + Q_D(QOpenGLWidget); + if (Q_UNLIKELY(d->initialized)) { + qWarning("QOpenGLWidget: Already initialized, setting the internal texture format has no effect"); + return; + } + + d->textureFormat = texFormat; +} + +/*! + \return the active internal texture format if the widget has already + initialized, the requested format if one was set but the widget has not yet + been made visible, or 0 if setTextureFormat() was not called and the widget + has not yet been made visible. + + \since 5.10 + */ +GLenum QOpenGLWidget::textureFormat() const +{ + Q_D(const QOpenGLWidget); + return d->textureFormat; +} + +/*! \return \e true if the widget and OpenGL resources, like the context, have been successfully initialized. Note that the return value is always false until the widget is shown. diff --git a/src/widgets/kernel/qopenglwidget.h b/src/widgets/kernel/qopenglwidget.h index b60d79bedb5..c0a6e415222 100644 --- a/src/widgets/kernel/qopenglwidget.h +++ b/src/widgets/kernel/qopenglwidget.h @@ -72,6 +72,9 @@ public: void setFormat(const QSurfaceFormat &format); QSurfaceFormat format() const; + GLenum textureFormat() const; + void setTextureFormat(GLenum texFormat); + bool isValid() const; void makeCurrent(); diff --git a/src/widgets/kernel/qwidget.cpp b/src/widgets/kernel/qwidget.cpp index 70bc407587b..8a642940cd5 100644 --- a/src/widgets/kernel/qwidget.cpp +++ b/src/widgets/kernel/qwidget.cpp @@ -67,7 +67,6 @@ # include <private/qmainwindowlayout_p.h> #endif #include <qpa/qplatformwindow.h> -#include <qpa/qplatformbackingstore.h> #include "private/qwidgetwindow_p.h" #include "qpainter.h" #include "qtooltip.h" diff --git a/src/widgets/kernel/qwidget_p.h b/src/widgets/kernel/qwidget_p.h index 68e063c25a2..858328e6187 100644 --- a/src/widgets/kernel/qwidget_p.h +++ b/src/widgets/kernel/qwidget_p.h @@ -69,6 +69,7 @@ #include "QtWidgets/qgraphicsscene.h" #include "QtWidgets/qgraphicsview.h" #include <private/qgesture_p.h> +#include <qpa/qplatformbackingstore.h> QT_BEGIN_NAMESPACE @@ -81,7 +82,6 @@ class QWidgetBackingStore; class QGraphicsProxyWidget; class QWidgetItemV2; class QOpenGLContext; -class QPlatformTextureList; class QStyle; @@ -630,6 +630,12 @@ public: #ifndef QT_NO_OPENGL virtual GLuint textureId() const { return 0; } + virtual QPlatformTextureList::Flags textureListFlags() { + Q_Q(QWidget); + return q->testAttribute(Qt::WA_AlwaysStackOnTop) + ? QPlatformTextureList::StacksOnTop + : QPlatformTextureList::Flags(0); + } virtual QImage grabFramebuffer() { return QImage(); } virtual void beginBackingStorePainting() { } virtual void endBackingStorePainting() { } diff --git a/src/widgets/kernel/qwidgetbackingstore.cpp b/src/widgets/kernel/qwidgetbackingstore.cpp index 781ad9600d7..4421218d1d9 100644 --- a/src/widgets/kernel/qwidgetbackingstore.cpp +++ b/src/widgets/kernel/qwidgetbackingstore.cpp @@ -945,9 +945,7 @@ static void findTextureWidgetsRecursively(QWidget *tlw, QWidget *widget, QPlatfo { QWidgetPrivate *wd = QWidgetPrivate::get(widget); if (wd->renderToTexture) { - QPlatformTextureList::Flags flags = 0; - if (widget->testAttribute(Qt::WA_AlwaysStackOnTop)) - flags |= QPlatformTextureList::StacksOnTop; + QPlatformTextureList::Flags flags = wd->textureListFlags(); const QRect rect(widget->mapTo(tlw, QPoint()), widget->size()); widgetTextures->appendTexture(widget, wd->textureId(), rect, wd->clipRect(), flags); } diff --git a/src/widgets/kernel/qwindowcontainer.cpp b/src/widgets/kernel/qwindowcontainer.cpp index 7ae63e54b3a..a17c69c5cee 100644 --- a/src/widgets/kernel/qwindowcontainer.cpp +++ b/src/widgets/kernel/qwindowcontainer.cpp @@ -337,6 +337,19 @@ bool QWindowContainer::event(QEvent *e) e->accept(); return true; #endif + + case QEvent::Paint: + { + static bool needsPunch = !QGuiApplicationPrivate::platformIntegration()->hasCapability( + QPlatformIntegration::TopStackedNativeChildWindows); + if (needsPunch) { + QPainter p(this); + p.setCompositionMode(QPainter::CompositionMode_Source); + p.fillRect(rect(), Qt::transparent); + } + break; + } + default: break; } diff --git a/src/widgets/widgets/qcombobox.cpp b/src/widgets/widgets/qcombobox.cpp index f4e08dc670f..37d0e5c51e8 100644 --- a/src/widgets/widgets/qcombobox.cpp +++ b/src/widgets/widgets/qcombobox.cpp @@ -67,11 +67,6 @@ #include <private/qabstractscrollarea_p.h> #include <private/qlineedit_p.h> #include <qdebug.h> -#if 0 /* Used to be included in Qt4 for Q_WS_MAC */ && !defined(QT_NO_EFFECTS) && QT_CONFIG(style_mac) -#include <private/qcore_mac_p.h> -#include <private/qmacstyle_mac_p.h> -#include <private/qt_cocoa_helpers_mac_p.h> -#endif #ifndef QT_NO_EFFECTS # include <private/qeffects_p.h> #endif diff --git a/src/widgets/widgets/qdockarealayout.cpp b/src/widgets/widgets/qdockarealayout.cpp index 8d9280ebb5c..e730eddd574 100644 --- a/src/widgets/widgets/qdockarealayout.cpp +++ b/src/widgets/widgets/qdockarealayout.cpp @@ -1044,33 +1044,6 @@ QLayoutItem *QDockAreaLayoutInfo::plug(const QList<int> &path) Q_ASSERT(item.widgetItem != 0); Q_ASSERT(item.flags & QDockAreaLayoutItem::GapItem); item.flags &= ~QDockAreaLayoutItem::GapItem; - - QRect result; - -#ifndef QT_NO_TABBAR - if (tabbed) { - } else -#endif - { - int prev = this->prev(index); - int next = this->next(index); - - if (prev != -1 && !(item_list.at(prev).flags & QDockAreaLayoutItem::GapItem)) { - item.pos += *sep; - item.size -= *sep; - } - if (next != -1 && !(item_list.at(next).flags & QDockAreaLayoutItem::GapItem)) - item.size -= *sep; - - QPoint pos; - rpick(o, pos) = item.pos; - rperp(o, pos) = perp(o, rect.topLeft()); - QSize s; - rpick(o, s) = item.size; - rperp(o, s) = perp(o, rect.size()); - result = QRect(pos, s); - } - return item.widgetItem; } diff --git a/src/widgets/widgets/qdockwidget.cpp b/src/widgets/widgets/qdockwidget.cpp index 307a261a43f..2928d51d20a 100644 --- a/src/widgets/widgets/qdockwidget.cpp +++ b/src/widgets/widgets/qdockwidget.cpp @@ -58,11 +58,6 @@ #include "qdockwidget_p.h" #include "qmainwindowlayout_p.h" -#if 0 // Used to be included in Qt4 for Q_WS_MAC -#include <private/qapplication_p.h> -#include <private/qt_mac_p.h> -#include <private/qmacstyle_mac_p.h> -#endif QT_BEGIN_NAMESPACE diff --git a/src/widgets/widgets/qmainwindow.cpp b/src/widgets/widgets/qmainwindow.cpp index c9349ac72d0..8eb5669f1c6 100644 --- a/src/widgets/widgets/qmainwindow.cpp +++ b/src/widgets/widgets/qmainwindow.cpp @@ -61,13 +61,6 @@ #ifdef Q_OS_OSX #include <qpa/qplatformnativeinterface.h> #endif -#if 0 // Used to be included in Qt4 for Q_WS_MAC -#include <private/qt_mac_p.h> -#include <private/qt_cocoa_helpers_mac_p.h> -QT_BEGIN_NAMESPACE -extern OSWindowRef qt_mac_window_for(const QWidget *); // qwidget_mac.cpp -QT_END_NAMESPACE -#endif QT_BEGIN_NAMESPACE @@ -80,10 +73,6 @@ public: #ifdef Q_OS_OSX , useUnifiedToolBar(false) #endif -#if 0 // Used to be included in Qt4 for Q_WS_MAC - , useHIToolBar(false) - , activateUnifiedToolbarAfterFullScreen(false) -#endif #if !defined(QT_NO_DOCKWIDGET) && !defined(QT_NO_CURSOR) , hasOldCursor(false) , cursorAdjusted(false) #endif @@ -95,10 +84,6 @@ public: #ifdef Q_OS_OSX bool useUnifiedToolBar; #endif -#if 0 // Used to be included in Qt4 for Q_WS_MAC - bool useHIToolBar; - bool activateUnifiedToolbarAfterFullScreen; -#endif void init(); QList<int> hoverSeparator; QPoint hoverPos; @@ -805,11 +790,7 @@ void QMainWindow::addToolBar(Qt::ToolBarArea area, QToolBar *toolbar) #endif } - if (!d->layout->usesHIToolBar(toolbar)) { - d->layout->removeWidget(toolbar); - } else { - d->layout->removeToolBar(toolbar); - } + d->layout->removeToolBar(toolbar); toolbar->d_func()->_q_updateIconSize(d->iconSize); toolbar->d_func()->_q_updateToolButtonStyle(d->toolButtonStyle); @@ -1111,21 +1092,6 @@ void QMainWindow::addDockWidget(Qt::DockWidgetArea area, QDockWidget *dockwidget } d_func()->layout->removeWidget(dockwidget); // in case it was already in here addDockWidget(area, dockwidget, orientation); - -#if 0 // Used to be included in Qt4 for Q_WS_MAC //drawer support - QMacAutoReleasePool pool; - extern bool qt_mac_is_macdrawer(const QWidget *); //qwidget_mac.cpp - if (qt_mac_is_macdrawer(dockwidget)) { - extern bool qt_mac_set_drawer_preferred_edge(QWidget *, Qt::DockWidgetArea); //qwidget_mac.cpp - window()->createWinId(); - dockwidget->window()->createWinId(); - qt_mac_set_drawer_preferred_edge(dockwidget, area); - if (dockwidget->isVisible()) { - dockwidget->hide(); - dockwidget->show(); - } - } -#endif } /*! @@ -1516,26 +1482,6 @@ bool QMainWindow::event(QEvent *event) if (!d->explicitIconSize) setIconSize(QSize()); break; -#if 0 // Used to be included in Qt4 for Q_WS_MAC - case QEvent::Show: - if (unifiedTitleAndToolBarOnMac()) - d->layout->syncUnifiedToolbarVisibility(); - d->layout->blockVisiblityCheck = false; - break; - case QEvent::WindowStateChange: - { - if (isHidden()) { - // We are coming out of a minimize, leave things as is. - d->layout->blockVisiblityCheck = true; - } - // We need to update the HIToolbar status when we go out of or into fullscreen. - QWindowStateChangeEvent *wce = static_cast<QWindowStateChangeEvent *>(event); - if ((windowState() & Qt::WindowFullScreen) || (wce->oldState() & Qt::WindowFullScreen)) { - d->layout->updateHIToolBarStatus(); - } - } - break; -#endif #if !defined(QT_NO_DOCKWIDGET) && !defined(QT_NO_CURSOR) case QEvent::CursorChange: // CursorChange events are triggered as mouse moves to new widgets even @@ -1589,33 +1535,6 @@ void QMainWindow::setUnifiedTitleAndToolBarOnMac(bool set) (reinterpret_cast<SetContentBorderEnabledFunction>(function))(window()->windowHandle(), set); update(); } -#endif - -#if 0 // Used to be included in Qt4 for Q_WS_MAC - Q_D(QMainWindow); - if (!isWindow() || d->useHIToolBar == set || QSysInfo::MacintoshVersion < QSysInfo::MV_10_3) - return; - - d->useHIToolBar = set; - createWinId(); // We need the hiview for down below. - - // Activate the unified toolbar with the raster engine. - if (windowSurface() && set) { - d->layout->unifiedSurface = new QUnifiedToolbarSurface(this); - } - - d->layout->updateHIToolBarStatus(); - - // Deactivate the unified toolbar with the raster engine. - if (windowSurface() && !set) { - if (d->layout->unifiedSurface) { - delete d->layout->unifiedSurface; - d->layout->unifiedSurface = 0; - } - } - - // Enabling the unified toolbar clears the opaque size grip setting, update it. - d->macUpdateOpaqueSizeGrip(); #else Q_UNUSED(set) #endif @@ -1626,9 +1545,6 @@ bool QMainWindow::unifiedTitleAndToolBarOnMac() const #ifdef Q_OS_OSX return d_func()->useUnifiedToolBar; #endif -#if 0 // Used to be included in Qt4 for Q_WS_MAC - return d_func()->useHIToolBar && !testAttribute(Qt::WA_MacBrushedMetal) && !(windowFlags() & Qt::FramelessWindowHint); -#endif return false; } diff --git a/src/widgets/widgets/qmainwindowlayout.cpp b/src/widgets/widgets/qmainwindowlayout.cpp index 640154063eb..63b6bcfaefb 100644 --- a/src/widgets/widgets/qmainwindowlayout.cpp +++ b/src/widgets/widgets/qmainwindowlayout.cpp @@ -70,10 +70,6 @@ #include <private/qapplication_p.h> #include <private/qlayoutengine_p.h> #include <private/qwidgetresizehandler_p.h> -#if 0 // Used to be included in Qt4 for Q_WS_MAC -# include <private/qcore_mac_p.h> -# include <private/qt_cocoa_helpers_mac_p.h> -#endif QT_BEGIN_NAMESPACE @@ -1183,14 +1179,7 @@ void QMainWindowLayout::removeToolBar(QToolBar *toolbar) QObject::disconnect(parentWidget(), SIGNAL(toolButtonStyleChanged(Qt::ToolButtonStyle)), toolbar, SLOT(_q_updateToolButtonStyle(Qt::ToolButtonStyle))); -#if 0 // Used to be included in Qt4 for Q_WS_MAC - if (usesHIToolBar(toolbar)) { - removeFromMacToolbar(toolbar); - } else -#endif - { - removeWidget(toolbar); - } + removeWidget(toolbar); } } @@ -1202,25 +1191,17 @@ void QMainWindowLayout::addToolBar(Qt::ToolBarArea area, bool) { validateToolBarArea(area); -#if 0 // Used to be included in Qt4 for Q_WS_MAC - if ((area == Qt::TopToolBarArea) - && layoutState.mainWindow->unifiedTitleAndToolBarOnMac()) { - insertIntoMacToolbar(0, toolbar); - } else -#endif - { - //let's add the toolbar to the layout - addChildWidget(toolbar); - QLayoutItem * item = layoutState.toolBarAreaLayout.addToolBar(toDockPos(area), toolbar); - if (savedState.isValid() && item) { - // copy the toolbar also in the saved state - savedState.toolBarAreaLayout.insertItem(toDockPos(area), item); - } - invalidate(); - - //this ensures that the toolbar has the right window flags (not floating any more) - toolbar->d_func()->updateWindowFlags(false /*floating*/); + // let's add the toolbar to the layout + addChildWidget(toolbar); + QLayoutItem *item = layoutState.toolBarAreaLayout.addToolBar(toDockPos(area), toolbar); + if (savedState.isValid() && item) { + // copy the toolbar also in the saved state + savedState.toolBarAreaLayout.insertItem(toDockPos(area), item); } + invalidate(); + + // this ensures that the toolbar has the right window flags (not floating any more) + toolbar->d_func()->updateWindowFlags(false /*floating*/); } /*! @@ -1228,27 +1209,20 @@ void QMainWindowLayout::addToolBar(Qt::ToolBarArea area, */ void QMainWindowLayout::insertToolBar(QToolBar *before, QToolBar *toolbar) { -#if 0 // Used to be included in Qt4 for Q_WS_MAC - if (usesHIToolBar(before)) { - insertIntoMacToolbar(before, toolbar); - } else -#endif - { - addChildWidget(toolbar); - QLayoutItem * item = layoutState.toolBarAreaLayout.insertToolBar(before, toolbar); - if (savedState.isValid() && item) { - // copy the toolbar also in the saved state - savedState.toolBarAreaLayout.insertItem(before, item); - } - if (!currentGapPos.isEmpty() && currentGapPos.constFirst() == 0) { - currentGapPos = layoutState.toolBarAreaLayout.currentGapIndex(); - if (!currentGapPos.isEmpty()) { - currentGapPos.prepend(0); - currentGapRect = layoutState.itemRect(currentGapPos); - } + addChildWidget(toolbar); + QLayoutItem *item = layoutState.toolBarAreaLayout.insertToolBar(before, toolbar); + if (savedState.isValid() && item) { + // copy the toolbar also in the saved state + savedState.toolBarAreaLayout.insertItem(before, item); + } + if (!currentGapPos.isEmpty() && currentGapPos.constFirst() == 0) { + currentGapPos = layoutState.toolBarAreaLayout.currentGapIndex(); + if (!currentGapPos.isEmpty()) { + currentGapPos.prepend(0); + currentGapRect = layoutState.itemRect(currentGapPos); } - invalidate(); } + invalidate(); } Qt::ToolBarArea QMainWindowLayout::toolBarArea(QToolBar *toolbar) const @@ -1261,12 +1235,6 @@ Qt::ToolBarArea QMainWindowLayout::toolBarArea(QToolBar *toolbar) const case QInternal::BottomDock: return Qt::BottomToolBarArea; default: break; } -#if 0 // Used to be included in Qt4 for Q_WS_MAC - if (pos == QInternal::DockCount) { - if (qtoolbarsInUnifiedToolbarList.contains(toolbar)) - return Qt::TopToolBarArea; - } -#endif return Qt::NoToolBarArea; } @@ -1283,70 +1251,15 @@ void QMainWindowLayout::getStyleOptionInfo(QStyleOptionToolBar *option, QToolBar void QMainWindowLayout::toggleToolBarsVisible() { - bool updateNonUnifiedParts = true; -#if 0 // Used to be included in Qt4 for Q_WS_MAC - if (layoutState.mainWindow->unifiedTitleAndToolBarOnMac()) { - // If we hit this case, someone has pressed the "toolbar button" which will - // toggle the unified toolbar visibility, because that's what the user wants. - // We might be in a situation where someone has hidden all the toolbars - // beforehand (maybe in construction), but now they've hit this button and - // and are expecting the items to show. What do we do? - // 1) Check the visibility of all the toolbars, if one is visible, do nothing, this - // preserves what people would expect (these toolbars were visible when I clicked last time). - // 2) If NONE are visible, then show them all. Again, this preserves the user expectation - // of, "I want to see the toolbars." The user may get more toolbars than expected, but this - // is better seeing nothing. - // Don't worry about any of this if we are going invisible. This does mean we may get - // into issues when switching into and out of fullscreen mode, but this is probably minor. - // If we ever need to do hiding, that would have to be taken care of after the unified toolbar - // has finished hiding. - // People can of course handle the QEvent::ToolBarChange event themselves and do - // WHATEVER they want if they don't like what we are doing (though the unified toolbar - // will fire regardless). - - // Check if we REALLY need to update the geometry below. If we only have items in the - // unified toolbar, all the docks will be empty, so there's very little point - // in doing the geometry as Apple will do it (we also avoid flicker in Cocoa as well). - // FWIW, layoutState.toolBarAreaLayout.visible and the state of the unified toolbar - // visibility can get out of sync. I really don't think it's a big issue. It is kept - // to a minimum because we only change the visibility if we absolutely must. - // update the "non unified parts." - updateNonUnifiedParts = !layoutState.toolBarAreaLayout.isEmpty(); - - // We get this function before the unified toolbar does its thing. - // So, the value will be opposite of what we expect. - bool goingVisible = !macWindowToolbarIsVisible(qt_mac_window_for(layoutState.mainWindow)); - if (goingVisible) { - const int ToolBarCount = qtoolbarsInUnifiedToolbarList.size(); - bool needAllVisible = true; - for (int i = 0; i < ToolBarCount; ++i) { - if (!qtoolbarsInUnifiedToolbarList.at(i)->isHidden()) { - needAllVisible = false; - break; - } - } - if (needAllVisible) { - QBoolBlocker blocker(blockVisiblityCheck); // Disable the visibilty check because - // the toggle has already happened. - for (int i = 0; i < ToolBarCount; ++i) - qtoolbarsInUnifiedToolbarList.at(i)->setVisible(true); - } - } - if (!updateNonUnifiedParts) - layoutState.toolBarAreaLayout.visible = goingVisible; - } -#endif - if (updateNonUnifiedParts) { - layoutState.toolBarAreaLayout.visible = !layoutState.toolBarAreaLayout.visible; - if (!layoutState.mainWindow->isMaximized()) { - QPoint topLeft = parentWidget()->geometry().topLeft(); - QRect r = parentWidget()->geometry(); - r = layoutState.toolBarAreaLayout.rectHint(r); - r.moveTo(topLeft); - parentWidget()->setGeometry(r); - } else { - update(); - } + layoutState.toolBarAreaLayout.visible = !layoutState.toolBarAreaLayout.visible; + if (!layoutState.mainWindow->isMaximized()) { + QPoint topLeft = parentWidget()->geometry().topLeft(); + QRect r = parentWidget()->geometry(); + r = layoutState.toolBarAreaLayout.rectHint(r); + r.moveTo(topLeft); + parentWidget()->setGeometry(r); + } else { + update(); } } @@ -1933,14 +1846,6 @@ QSize QMainWindowLayout::minimumSize() const const QSize sbMin = statusbar ? statusbar->minimumSize() : QSize(0, 0); minSize = QSize(qMax(sbMin.width(), minSize.width()), sbMin.height() + minSize.height()); -#if 0 // Used to be included in Qt4 for Q_WS_MAC - const QSize storedSize = minSize; - int minWidth = 0; - foreach (QToolBar *toolbar, qtoolbarsInUnifiedToolbarList) { - minWidth += toolbar->sizeHint().width() + 20; - } - minSize = QSize(qMax(minWidth, storedSize.width()), storedSize.height()); -#endif } return minSize; } @@ -2272,9 +2177,6 @@ QMainWindowLayout::QMainWindowLayout(QMainWindow *mainwindow, QLayout *parentLay #endif // QT_NO_DOCKWIDGET , widgetAnimator(this) , pluggingWidget(0) -#if 0 // Used to be included in Qt4 for Q_WS_MAC - , blockVisiblityCheck(false) -#endif { if (parentLayout) setParent(parentLayout); @@ -2299,10 +2201,6 @@ QMainWindowLayout::~QMainWindowLayout() layoutState.deleteAllLayoutItems(); layoutState.deleteCentralWidgetItem(); -#if 0 // Used to be included in Qt4 for Q_WS_MAC - cleanUpMacToolbarItems(); -#endif - delete statusbar; } @@ -2674,22 +2572,6 @@ bool QMainWindowLayout::restoreState(QDataStream &stream) return true; } - -// Returns if this toolbar *should* be using HIToolbar. Won't work for all in between cases -// for example, you have a toolbar in the top area and then you suddenly turn on -// HIToolbar. -bool QMainWindowLayout::usesHIToolBar(QToolBar *toolbar) const -{ -#if 1 // Used to be excluded in Qt4 for Q_WS_MAC - Q_UNUSED(toolbar); - return false; -#else - return qtoolbarsInUnifiedToolbarList.contains(toolbar) - || ((toolBarArea(toolbar) == Qt::TopToolBarArea) - && layoutState.mainWindow->unifiedTitleAndToolBarOnMac()); -#endif -} - void QMainWindowLayout::timerEvent(QTimerEvent *e) { #ifndef QT_NO_DOCKWIDGET diff --git a/src/widgets/widgets/qmainwindowlayout_p.h b/src/widgets/widgets/qmainwindowlayout_p.h index ed8da61bc34..507759fe962 100644 --- a/src/widgets/widgets/qmainwindowlayout_p.h +++ b/src/widgets/widgets/qmainwindowlayout_p.h @@ -180,7 +180,6 @@ public: QMainWindow::DockOptions dockOptions; void setDockOptions(QMainWindow::DockOptions opts); - bool usesHIToolBar(QToolBar *toolbar) const; void timerEvent(QTimerEvent *e) Q_DECL_OVERRIDE; @@ -316,7 +315,6 @@ public: void paintDropIndicator(QPainter *p, QWidget *widget, const QRegion &clip); void applyState(QMainWindowLayoutState &newState, bool animate = true); void restore(bool keepSavedState = false); - void updateHIToolBarStatus(); void animationFinished(QWidget *widget); private Q_SLOTS: @@ -331,40 +329,6 @@ private: #ifndef QT_NO_TABBAR void updateTabBarShapes(); #endif -#if 0 // Used to be included in Qt4 for Q_WS_MAC - static OSStatus qtmacToolbarDelegate(EventHandlerCallRef, EventRef , void *); - static OSStatus qtoolbarInHIToolbarHandler(EventHandlerCallRef inCallRef, EventRef event, - void *data); - static void qtMacHIToolbarRegisterQToolBarInHIToolborItemClass(); - static HIToolbarItemRef CreateToolbarItemForIdentifier(CFStringRef identifier, CFTypeRef data); - static HIToolbarItemRef createQToolBarInHIToolbarItem(QToolBar *toolbar, - QMainWindowLayout *layout); -public: - struct ToolBarSaveState { - ToolBarSaveState() : movable(false) { } - ToolBarSaveState(bool newMovable, const QSize &newMax) - : movable(newMovable), maximumSize(newMax) { } - bool movable; - QSize maximumSize; - }; - QList<QToolBar *> qtoolbarsInUnifiedToolbarList; - QList<void *> toolbarItemsCopy; - QHash<void *, QToolBar *> unifiedToolbarHash; - QHash<QToolBar *, ToolBarSaveState> toolbarSaveState; - QHash<QString, QToolBar *> cocoaItemIDToToolbarHash; - void insertIntoMacToolbar(QToolBar *before, QToolBar *after); - void removeFromMacToolbar(QToolBar *toolbar); - void cleanUpMacToolbarItems(); - void fixSizeInUnifiedToolbar(QToolBar *tb) const; - bool useHIToolBar; - bool activateUnifiedToolbarAfterFullScreen; - void syncUnifiedToolbarVisibility(); - bool blockVisiblityCheck; - - QUnifiedToolbarSurface *unifiedSurface; - void updateUnifiedToolbarOffset(); - -#endif }; #if !defined(QT_NO_DOCKWIDGET) && !defined(QT_NO_DEBUG_STREAM) diff --git a/src/widgets/widgets/qmdiarea.cpp b/src/widgets/widgets/qmdiarea.cpp index 18cb8237029..0dc45ddbc39 100644 --- a/src/widgets/widgets/qmdiarea.cpp +++ b/src/widgets/widgets/qmdiarea.cpp @@ -160,9 +160,6 @@ #include <QApplication> #include <QStyle> -#if 0 /* Used to be included in Qt4 for Q_WS_MAC */ && QT_CONFIG(style_mac) -#include <private/qmacstyle_mac_p.h> -#endif #include <QChildEvent> #include <QResizeEvent> #include <QScrollBar> diff --git a/src/widgets/widgets/qmdisubwindow.cpp b/src/widgets/widgets/qmdisubwindow.cpp index a627c86871e..34b64145e35 100644 --- a/src/widgets/widgets/qmdisubwindow.cpp +++ b/src/widgets/widgets/qmdisubwindow.cpp @@ -194,6 +194,11 @@ static const Qt::WindowFlags CustomizeWindowFlags = static const int BoundaryMargin = 5; +static inline bool isMacStyle(QStyle *style) +{ + return style->inherits("QMacStyle"); +} + static inline int getMoveDeltaComponent(uint cflags, uint moveFlag, uint resizeFlag, int delta, int maxDelta, int minDelta) { @@ -1077,7 +1082,7 @@ void QMdiSubWindowPrivate::updateCursor() #ifndef QT_NO_CURSOR Q_Q(QMdiSubWindow); #if QT_CONFIG(style_mac) - if (qobject_cast<QMacStyle *>(q->style())) + if (isMacStyle(q->style())) return; #endif @@ -1505,7 +1510,7 @@ void QMdiSubWindowPrivate::processClickedSubControl() break; case QStyle::SC_TitleBarMinButton: #if QT_CONFIG(style_mac) - if (qobject_cast<QMacStyle *>(q->style())) { + if (isMacStyle(q->style())) { if (q->isMinimized()) q->showNormal(); else @@ -1522,7 +1527,7 @@ void QMdiSubWindowPrivate::processClickedSubControl() break; case QStyle::SC_TitleBarMaxButton: #if QT_CONFIG(style_mac) - if (qobject_cast<QMacStyle *>(q->style())) { + if (isMacStyle(q->style())) { if (q->isMaximized()) q->showNormal(); else @@ -1569,7 +1574,7 @@ QRegion QMdiSubWindowPrivate::getRegion(Operation operation) const QRegion region; #if QT_CONFIG(style_mac) - if (qobject_cast<QMacStyle *>(q->style())) + if (isMacStyle(q->style())) return region; #endif @@ -2192,7 +2197,7 @@ void QMdiSubWindowPrivate::setSizeGrip(QSizeGrip *newSizeGrip) newSizeGrip->setFixedSize(newSizeGrip->sizeHint()); bool putSizeGripInLayout = layout ? true : false; #if QT_CONFIG(style_mac) - if (qobject_cast<QMacStyle *>(q->style())) + if (isMacStyle(q->style())) putSizeGripInLayout = false; #endif if (putSizeGripInLayout) { @@ -2844,7 +2849,7 @@ bool QMdiSubWindow::event(QEvent *event) d->isWidgetHiddenByUs = false; if (!parent()) { #if !defined(QT_NO_SIZEGRIP) && QT_CONFIG(style_mac) - if (qobject_cast<QMacStyle *>(style())) + if (isMacStyle(style())) delete d->sizeGrip; #endif setOption(RubberBandResize, false); @@ -2939,7 +2944,7 @@ void QMdiSubWindow::showEvent(QShowEvent *showEvent) } #if !defined(QT_NO_SIZEGRIP) && QT_CONFIG(style_mac) - if (qobject_cast<QMacStyle *>(style()) && !d->sizeGrip + if (isMacStyle(style()) && !d->sizeGrip && !(windowFlags() & Qt::FramelessWindowHint)) { d->setSizeGrip(new QSizeGrip(this)); Q_ASSERT(d->sizeGrip); @@ -3334,7 +3339,7 @@ void QMdiSubWindow::mouseMoveEvent(QMouseEvent *mouseEvent) d->hoveredSubControl, this); } #if QT_CONFIG(style_mac) - if (qobject_cast<QMacStyle *>(style()) && !hoverRegion.isEmpty()) + if (isMacStyle(style()) && !hoverRegion.isEmpty()) hoverRegion += QRegion(0, 0, width(), d->titleBarHeight(options)); #endif if (!hoverRegion.isEmpty()) @@ -3544,7 +3549,7 @@ QSize QMdiSubWindow::minimumSizeHint() const if (d->sizeGrip && d->sizeGrip->isVisibleTo(const_cast<QMdiSubWindow *>(this))) sizeGripHeight = d->sizeGrip->height(); #if QT_CONFIG(style_mac) - else if (parent() && qobject_cast<QMacStyle *>(style()) && !d->sizeGrip) + else if (parent() && isMacStyle(style()) && !d->sizeGrip) sizeGripHeight = style()->pixelMetric(QStyle::PM_SizeGripSize, 0, this); #endif minHeight = qMax(minHeight, decorationHeight + sizeGripHeight); diff --git a/src/widgets/widgets/qpushbutton.cpp b/src/widgets/widgets/qpushbutton.cpp index d8eae724ee6..cae1f9d1692 100644 --- a/src/widgets/widgets/qpushbutton.cpp +++ b/src/widgets/widgets/qpushbutton.cpp @@ -56,10 +56,6 @@ #include "qdebug.h" #include "qlayoutitem.h" #include "qdialogbuttonbox.h" -#if 0 // Used to be included in Qt4 for Q_WS_MAC -#include "private/qmacstyle_mac_p.h" -#include "private/qmacstyle_mac_p_p.h" -#endif #ifndef QT_NO_ACCESSIBILITY #include "qaccessible.h" diff --git a/tests/auto/corelib/io/qurl/tst_qurl.cpp b/tests/auto/corelib/io/qurl/tst_qurl.cpp index ee18151e4a4..e1a999abfb7 100644 --- a/tests/auto/corelib/io/qurl/tst_qurl.cpp +++ b/tests/auto/corelib/io/qurl/tst_qurl.cpp @@ -1384,18 +1384,6 @@ void tst_QUrl::compat_constructor_01_data() void tst_QUrl::compat_constructor_01() { - /* The following should work as expected: - * - * QUrlOperator op; - * op.copy( QString( "Makefile" ), - * QString("ftp://rms:grmpf12@nibbler/home/rms/tmp"), - * false ); - * - * as well as the following: - * - * QUrlOperator op; - * op.copy(QString("ftp://ftp.qt-project.org/qt/INSTALL"), "."); - */ QFETCH( QString, urlStr ); { @@ -1425,11 +1413,6 @@ void tst_QUrl::compat_constructor_02_data() void tst_QUrl::compat_constructor_02() { - /* The following should work as expected: - * - * QUrlOperator op( "ftp://ftp.qt-project.org/qt" ); - * op.copy(QString("INSTALL"), "."); - */ QFETCH( QString, urlStr ); QFETCH( QString, fileName ); diff --git a/tests/auto/corelib/itemmodels/qsortfilterproxymodel/tst_qsortfilterproxymodel.cpp b/tests/auto/corelib/itemmodels/qsortfilterproxymodel/tst_qsortfilterproxymodel.cpp index 7b6c470dc4d..6444b76a3ae 100644 --- a/tests/auto/corelib/itemmodels/qsortfilterproxymodel/tst_qsortfilterproxymodel.cpp +++ b/tests/auto/corelib/itemmodels/qsortfilterproxymodel/tst_qsortfilterproxymodel.cpp @@ -3994,14 +3994,14 @@ class DropOnOddRows : public QAbstractListModel public: DropOnOddRows(QObject *parent = 0) : QAbstractListModel(parent) {} - QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const + QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override { if (role == Qt::DisplayRole) return (index.row() % 2 == 0) ? "A" : "B"; return QVariant(); } - int rowCount(const QModelIndex &parent = QModelIndex()) const + int rowCount(const QModelIndex &parent = QModelIndex()) const override { Q_UNUSED(parent); return 10; @@ -4026,7 +4026,7 @@ public: } - QModelIndex mapToSource(const QModelIndex &proxyIndex) const + QModelIndex mapToSource(const QModelIndex &proxyIndex) const override { Q_ASSERT(sourceModel()); return QSortFilterProxyModel::mapToSource(proxyIndex); diff --git a/tests/auto/corelib/kernel/qmetatype/tst_qmetatype.cpp b/tests/auto/corelib/kernel/qmetatype/tst_qmetatype.cpp index e3c810984cb..d57c4629cc2 100644 --- a/tests/auto/corelib/kernel/qmetatype/tst_qmetatype.cpp +++ b/tests/auto/corelib/kernel/qmetatype/tst_qmetatype.cpp @@ -155,7 +155,9 @@ void tst_QMetaType::defined() QCOMPARE(int(QMetaTypeId2<int*>::Defined), 0); QCOMPARE(int(QMetaTypeId2<CustomQObject::CustomQEnum>::Defined), 1); QCOMPARE(int(QMetaTypeId2<CustomGadget>::Defined), 1); + QCOMPARE(int(QMetaTypeId2<CustomGadget*>::Defined), 1); QVERIFY(!QMetaTypeId2<GadgetDerived>::Defined); + QVERIFY(!QMetaTypeId2<GadgetDerived*>::Defined); QVERIFY(int(QMetaTypeId2<CustomQObject*>::Defined)); QVERIFY(!QMetaTypeId2<CustomQObject>::Defined); QVERIFY(!QMetaTypeId2<CustomNonQObject>::Defined); @@ -395,6 +397,7 @@ void tst_QMetaType::typeName_data() QTest::newRow("CustomQObject*") << ::qMetaTypeId<CustomQObject*>() << QString::fromLatin1("CustomQObject*"); QTest::newRow("CustomGadget") << ::qMetaTypeId<CustomGadget>() << QString::fromLatin1("CustomGadget"); + QTest::newRow("CustomGadget*") << ::qMetaTypeId<CustomGadget*>() << QString::fromLatin1("CustomGadget*"); QTest::newRow("CustomQObject::CustomQEnum") << ::qMetaTypeId<CustomQObject::CustomQEnum>() << QString::fromLatin1("CustomQObject::CustomQEnum"); QTest::newRow("Qt::ArrowType") << ::qMetaTypeId<Qt::ArrowType>() << QString::fromLatin1("Qt::ArrowType"); } @@ -1675,6 +1678,7 @@ public: }; Q_DECLARE_METATYPE(MyGadget); +Q_DECLARE_METATYPE(MyGadget*); Q_DECLARE_METATYPE(const QMetaObject *); Q_DECLARE_METATYPE(Qt::ScrollBarPolicy); Q_DECLARE_METATYPE(MyGadget::MyEnum); @@ -1684,16 +1688,18 @@ void tst_QMetaType::metaObject_data() QTest::addColumn<int>("type"); QTest::addColumn<const QMetaObject*>("result"); QTest::addColumn<bool>("isGadget"); + QTest::addColumn<bool>("isGadgetPtr"); QTest::addColumn<bool>("isQObjectPtr"); - QTest::newRow("QObject") << int(QMetaType::QObjectStar) << &QObject::staticMetaObject << false << true; - QTest::newRow("QFile*") << ::qMetaTypeId<QFile*>() << &QFile::staticMetaObject << false << true; - QTest::newRow("MyObject*") << ::qMetaTypeId<MyObject*>() << &MyObject::staticMetaObject << false << true; - QTest::newRow("int") << int(QMetaType::Int) << static_cast<const QMetaObject *>(0) << false << false; - QTest::newRow("QEasingCurve") << ::qMetaTypeId<QEasingCurve>() << &QEasingCurve::staticMetaObject << true << false; - QTest::newRow("MyGadget") << ::qMetaTypeId<MyGadget>() << &MyGadget::staticMetaObject << true << false; - QTest::newRow("MyEnum") << ::qMetaTypeId<MyGadget::MyEnum>() << &MyGadget::staticMetaObject << false << false; - QTest::newRow("Qt::ScrollBarPolicy") << ::qMetaTypeId<Qt::ScrollBarPolicy>() << &QObject::staticQtMetaObject << false << false; + QTest::newRow("QObject") << int(QMetaType::QObjectStar) << &QObject::staticMetaObject << false << false << true; + QTest::newRow("QFile*") << ::qMetaTypeId<QFile*>() << &QFile::staticMetaObject << false << false << true; + QTest::newRow("MyObject*") << ::qMetaTypeId<MyObject*>() << &MyObject::staticMetaObject << false << false << true; + QTest::newRow("int") << int(QMetaType::Int) << static_cast<const QMetaObject *>(0) << false << false << false; + QTest::newRow("QEasingCurve") << ::qMetaTypeId<QEasingCurve>() << &QEasingCurve::staticMetaObject << true << false << false; + QTest::newRow("MyGadget") << ::qMetaTypeId<MyGadget>() << &MyGadget::staticMetaObject << true << false << false; + QTest::newRow("MyGadget*") << ::qMetaTypeId<MyGadget*>() << &MyGadget::staticMetaObject << false << true << false; + QTest::newRow("MyEnum") << ::qMetaTypeId<MyGadget::MyEnum>() << &MyGadget::staticMetaObject << false << false << false; + QTest::newRow("Qt::ScrollBarPolicy") << ::qMetaTypeId<Qt::ScrollBarPolicy>() << &QObject::staticQtMetaObject << false << false << false; } @@ -1702,12 +1708,14 @@ void tst_QMetaType::metaObject() QFETCH(int, type); QFETCH(const QMetaObject *, result); QFETCH(bool, isGadget); + QFETCH(bool, isGadgetPtr); QFETCH(bool, isQObjectPtr); QCOMPARE(QMetaType::metaObjectForType(type), result); QMetaType mt(type); QCOMPARE(mt.metaObject(), result); QCOMPARE(!!(mt.flags() & QMetaType::IsGadget), isGadget); + QCOMPARE(!!(mt.flags() & QMetaType::PointerToGadget), isGadgetPtr); QCOMPARE(!!(mt.flags() & QMetaType::PointerToQObject), isQObjectPtr); } diff --git a/tests/auto/corelib/thread/qfuture/tst_qfuture.cpp b/tests/auto/corelib/thread/qfuture/tst_qfuture.cpp index b8841bb6a34..5f67ffedd1b 100644 --- a/tests/auto/corelib/thread/qfuture/tst_qfuture.cpp +++ b/tests/auto/corelib/thread/qfuture/tst_qfuture.cpp @@ -1200,8 +1200,6 @@ void tst_QFuture::pause() Interface.reportFinished(); } -const int resultCount = 1000; - class ResultObject : public QObject { Q_OBJECT diff --git a/tests/auto/corelib/thread/qsemaphore/tst_qsemaphore.cpp b/tests/auto/corelib/thread/qsemaphore/tst_qsemaphore.cpp index 2970b2e118d..ba470a77c9b 100644 --- a/tests/auto/corelib/thread/qsemaphore/tst_qsemaphore.cpp +++ b/tests/auto/corelib/thread/qsemaphore/tst_qsemaphore.cpp @@ -42,6 +42,7 @@ private slots: void tryAcquireWithTimeout(); void tryAcquireWithTimeoutStarvation(); void producerConsumer(); + void raii(); }; static QSemaphore *semaphore = 0; @@ -417,5 +418,54 @@ void tst_QSemaphore::producerConsumer() consumer.wait(); } +void tst_QSemaphore::raii() +{ + QSemaphore sem; + + QCOMPARE(sem.available(), 0); + + // basic operation: + { + QSemaphoreReleaser r0; + const QSemaphoreReleaser r1(sem); + const QSemaphoreReleaser r2(sem, 2); + + QCOMPARE(r0.semaphore(), nullptr); + QCOMPARE(r1.semaphore(), &sem); + QCOMPARE(r2.semaphore(), &sem); + } + + QCOMPARE(sem.available(), 3); + + // cancel: + { + const QSemaphoreReleaser r1(sem); + QSemaphoreReleaser r2(sem, 2); + + QCOMPARE(r2.cancel(), &sem); + QCOMPARE(r2.semaphore(), nullptr); + } + + QCOMPARE(sem.available(), 4); + + // move-assignment: + { + const QSemaphoreReleaser r1(sem); + QSemaphoreReleaser r2(sem, 2); + + QCOMPARE(sem.available(), 4); + + r2 = QSemaphoreReleaser(); + + QCOMPARE(sem.available(), 6); + + r2 = QSemaphoreReleaser(sem, 42); + + QCOMPARE(sem.available(), 6); + } + + QCOMPARE(sem.available(), 49); +} + QTEST_MAIN(tst_QSemaphore) #include "tst_qsemaphore.moc" diff --git a/tests/auto/corelib/tools/qstring/tst_qstring.cpp b/tests/auto/corelib/tools/qstring/tst_qstring.cpp index 48e856f4069..dfa8cceccc9 100644 --- a/tests/auto/corelib/tools/qstring/tst_qstring.cpp +++ b/tests/auto/corelib/tools/qstring/tst_qstring.cpp @@ -6067,14 +6067,6 @@ void tst_QString::compare_data() lower += QChar(QChar::lowSurrogate(0x10428)); QTest::newRow("data8") << upper << lower << -1 << 0; - QTest::newRow("vectorized-boundaries-7") << QString("1234567") << QString("abcdefg") << -1 << -1; - QTest::newRow("vectorized-boundaries-8") << QString("12345678") << QString("abcdefgh") << -1 << -1; - QTest::newRow("vectorized-boundaries-9") << QString("123456789") << QString("abcdefghi") << -1 << -1; - - QTest::newRow("vectorized-boundaries-15") << QString("123456789012345") << QString("abcdefghiklmnop") << -1 << -1; - QTest::newRow("vectorized-boundaries-16") << QString("1234567890123456") << QString("abcdefghiklmnopq") << -1 << -1; - QTest::newRow("vectorized-boundaries-17") << QString("12345678901234567") << QString("abcdefghiklmnopqr") << -1 << -1; - // embedded nulls // These don't work as of now. It's OK that these don't work since \0 is not a valid unicode /*QTest::newRow("data10") << QString(QByteArray("\0", 1)) << QString(QByteArray("\0", 1)) << 0 << 0; @@ -6083,6 +6075,44 @@ void tst_QString::compare_data() QTest::newRow("data13") << QString("ab\0c") << QString(QByteArray("ab\0c", 4)) << 0 << 0; QTest::newRow("data14") << QString(QByteArray("ab\0c", 4)) << QString("abc") << -1 << -1; QTest::newRow("data15") << QString("abc") << QString(QByteArray("ab\0c", 4)) << 1 << 1;*/ + + // All tests below (generated by the 3 for-loops) are meant to excercise the vectorized versions + // of ucstrncmp. + + QString in1, in2; + for (int i = 0; i < 70; ++i) { + in1 += QString::number(i % 10); + in2 += QString::number((70 - i + 1) % 10); + } + Q_ASSERT(in1.length() == in2.length()); + Q_ASSERT(in1 != in2); + Q_ASSERT(in1.at(0) < in2.at(0)); + for (int i = 0; i < in1.length(); ++i) { + Q_ASSERT(in1.at(i) != in2.at(i)); + } + + for (int i = 1; i <= 65; ++i) { + QString inp1 = in1.left(i); + QString inp2 = in2.left(i); + QTest::addRow("all-different-%d", i) << inp1 << inp2 << -1 << -1; + } + + for (int i = 1; i <= 65; ++i) { + QString start(i - 1, 'a'); + + QString in = start + QLatin1Char('a'); + QTest::addRow("all-same-%d", i) << in << in << 0 << 0; + + QString in2 = start + QLatin1Char('b'); + QTest::addRow("last-different-%d", i) << in << in2 << -1 << -1; + } + + for (int i = 0; i < 16; ++i) { + QString in1(16, 'a'); + QString in2 = in1; + in2[i] = 'b'; + QTest::addRow("all-same-except-char-%d", i) << in1 << in2 << -1 << -1; + } } static bool isLatin(const QString &s) diff --git a/tests/auto/corelib/tools/qstringapisymmetry/tst_qstringapisymmetry.cpp b/tests/auto/corelib/tools/qstringapisymmetry/tst_qstringapisymmetry.cpp index 9d9b47b61e2..36f479ca012 100644 --- a/tests/auto/corelib/tools/qstringapisymmetry/tst_qstringapisymmetry.cpp +++ b/tests/auto/corelib/tools/qstringapisymmetry/tst_qstringapisymmetry.cpp @@ -160,6 +160,45 @@ private Q_SLOTS: //void compare_const_char_star_const_char_star_data() { compare_data(); } //void compare_const_char_star_const_char_star() { compare_impl<const char *, const char *>(); } +private: + void mid_data(); + template <typename String> void mid_impl(); + + void left_data(); + template <typename String> void left_impl(); + + void right_data(); + template <typename String> void right_impl(); + +private Q_SLOTS: + + void mid_QString_data() { mid_data(); } + void mid_QString() { mid_impl<QString>(); } + void mid_QStringRef_data() { mid_data(); } + void mid_QStringRef() { mid_impl<QStringRef>(); } + void mid_QLatin1String_data() { mid_data(); } + void mid_QLatin1String() { mid_impl<QLatin1String>(); } + void mid_QByteArray_data() { mid_data(); } + void mid_QByteArray() { mid_impl<QByteArray>(); } + + void left_QString_data() { left_data(); } + void left_QString() { left_impl<QString>(); } + void left_QStringRef_data() { left_data(); } + void left_QStringRef() { left_impl<QStringRef>(); } + void left_QLatin1String_data() { left_data(); } + void left_QLatin1String() { left_impl<QLatin1String>(); } + void left_QByteArray_data() { left_data(); } + void left_QByteArray() { left_impl<QByteArray>(); } + + void right_QString_data() { right_data(); } + void right_QString() { right_impl<QString>(); } + void right_QStringRef_data() { right_data(); } + void right_QStringRef() { right_impl<QStringRef>(); } + void right_QLatin1String_data() { right_data(); } + void right_QLatin1String() { right_impl<QLatin1String>(); } + void right_QByteArray_data() { right_data(); } + void right_QByteArray() { right_impl<QByteArray>(); } + // // UTF-16-only checks: // @@ -300,6 +339,178 @@ void tst_QStringApiSymmetry::compare_impl() const #undef CHECK } +static QString empty = QLatin1String(""); +// the tests below rely on the fact that these objects' names match their contents: +static QString a = QStringLiteral("a"); +static QString b = QStringLiteral("b"); +static QString c = QStringLiteral("c"); +static QString ab = QStringLiteral("ab"); +static QString bc = QStringLiteral("bc"); +static QString abc = QStringLiteral("abc"); + +void tst_QStringApiSymmetry::mid_data() +{ + QTest::addColumn<QStringRef>("unicode"); + QTest::addColumn<QLatin1String>("latin1"); + QTest::addColumn<int>("pos"); + QTest::addColumn<int>("n"); + QTest::addColumn<QStringRef>("result"); + QTest::addColumn<QStringRef>("result2"); + + QTest::addRow("null") << QStringRef() << QLatin1String() << 0 << 0 << QStringRef() << QStringRef(); + QTest::addRow("empty") << QStringRef(&empty) << QLatin1String("") << 0 << 0 << QStringRef(&empty) << QStringRef(&empty); + + // Some classes' mid() implementations have a wide contract, others a narrow one + // so only test valid arguents here: +#define ROW(base, p, n, r1, r2) \ + QTest::addRow("%s%d%d", #base, p, n) << QStringRef(&base) << QLatin1String(#base) << p << n << QStringRef(&r1) << QStringRef(&r2) + + ROW(a, 0, 0, a, empty); + ROW(a, 0, 1, a, a); + ROW(a, 1, 0, empty, empty); + + ROW(ab, 0, 0, ab, empty); + ROW(ab, 0, 1, ab, a); + ROW(ab, 0, 2, ab, ab); + ROW(ab, 1, 0, b, empty); + ROW(ab, 1, 1, b, b); + ROW(ab, 2, 0, empty, empty); + + ROW(abc, 0, 0, abc, empty); + ROW(abc, 0, 1, abc, a); + ROW(abc, 0, 2, abc, ab); + ROW(abc, 0, 3, abc, abc); + ROW(abc, 1, 0, bc, empty); + ROW(abc, 1, 1, bc, b); + ROW(abc, 1, 2, bc, bc); + ROW(abc, 2, 0, c, empty); + ROW(abc, 2, 1, c, c); + ROW(abc, 3, 0, empty, empty); +#undef ROW +} + +template <typename String> +void tst_QStringApiSymmetry::mid_impl() +{ + QFETCH(const QStringRef, unicode); + QFETCH(const QLatin1String, latin1); + QFETCH(const int, pos); + QFETCH(const int, n); + QFETCH(const QStringRef, result); + QFETCH(const QStringRef, result2); + + const auto utf8 = unicode.toUtf8(); + + const auto s = make<String>(unicode, latin1, utf8); + + const auto mid = s.mid(pos); + const auto mid2 = s.mid(pos, n); + + QVERIFY(mid == result); + QCOMPARE(mid.isNull(), result.isNull()); + QCOMPARE(mid.isEmpty(), result.isEmpty()); + + QVERIFY(mid2 == result2); + QCOMPARE(mid2.isNull(), result2.isNull()); + QCOMPARE(mid2.isEmpty(), result2.isEmpty()); +} + +void tst_QStringApiSymmetry::left_data() +{ + QTest::addColumn<QStringRef>("unicode"); + QTest::addColumn<QLatin1String>("latin1"); + QTest::addColumn<int>("n"); + QTest::addColumn<QStringRef>("result"); + + QTest::addRow("null") << QStringRef() << QLatin1String() << 0 << QStringRef(); + QTest::addRow("empty") << QStringRef(&empty) << QLatin1String("") << 0 << QStringRef(&empty); + + // Some classes' left() implementations have a wide contract, others a narrow one + // so only test valid arguents here: +#define ROW(base, n, res) \ + QTest::addRow("%s%d", #base, n) << QStringRef(&base) << QLatin1String(#base) << n << QStringRef(&res); + + ROW(a, 0, empty); + ROW(a, 1, a); + + ROW(ab, 0, empty); + ROW(ab, 1, a); + ROW(ab, 2, ab); + + ROW(abc, 0, empty); + ROW(abc, 1, a); + ROW(abc, 2, ab); + ROW(abc, 3, abc); +#undef ROW +} + +template <typename String> +void tst_QStringApiSymmetry::left_impl() +{ + QFETCH(const QStringRef, unicode); + QFETCH(const QLatin1String, latin1); + QFETCH(const int, n); + QFETCH(const QStringRef, result); + + const auto utf8 = unicode.toUtf8(); + + const auto s = make<String>(unicode, latin1, utf8); + + const auto left = s.left(n); + + QVERIFY(left == result); + QCOMPARE(left.isNull(), result.isNull()); + QCOMPARE(left.isEmpty(), result.isEmpty()); +} + +void tst_QStringApiSymmetry::right_data() +{ + QTest::addColumn<QStringRef>("unicode"); + QTest::addColumn<QLatin1String>("latin1"); + QTest::addColumn<int>("n"); + QTest::addColumn<QStringRef>("result"); + + QTest::addRow("null") << QStringRef() << QLatin1String() << 0 << QStringRef(); + QTest::addRow("empty") << QStringRef(&empty) << QLatin1String("") << 0 << QStringRef(&empty); + + // Some classes' right() implementations have a wide contract, others a narrow one + // so only test valid arguents here: +#define ROW(base, n, res) \ + QTest::addRow("%s%d", #base, n) << QStringRef(&base) << QLatin1String(#base) << n << QStringRef(&res); + + ROW(a, 0, empty); + ROW(a, 1, a); + + ROW(ab, 0, empty); + ROW(ab, 1, b); + ROW(ab, 2, ab); + + ROW(abc, 0, empty); + ROW(abc, 1, c); + ROW(abc, 2, bc); + ROW(abc, 3, abc); +#undef ROW +} + +template <typename String> +void tst_QStringApiSymmetry::right_impl() +{ + QFETCH(const QStringRef, unicode); + QFETCH(const QLatin1String, latin1); + QFETCH(const int, n); + QFETCH(const QStringRef, result); + + const auto utf8 = unicode.toUtf8(); + + const auto s = make<String>(unicode, latin1, utf8); + + const auto right = s.right(n); + + QVERIFY(right == result); + QCOMPARE(right.isNull(), result.isNull()); + QCOMPARE(right.isEmpty(), result.isEmpty()); +} + // // // UTF-16-only checks: diff --git a/tests/auto/corelib/tools/qvarlengtharray/tst_qvarlengtharray.cpp b/tests/auto/corelib/tools/qvarlengtharray/tst_qvarlengtharray.cpp index 0806ad13185..3971353cbb5 100644 --- a/tests/auto/corelib/tools/qvarlengtharray/tst_qvarlengtharray.cpp +++ b/tests/auto/corelib/tools/qvarlengtharray/tst_qvarlengtharray.cpp @@ -30,8 +30,6 @@ #include <qvarlengtharray.h> #include <qvariant.h> -const int N = 1; - class tst_QVarLengthArray : public QObject { Q_OBJECT diff --git a/tests/auto/gui/image/qicon/tst_qicon.cpp b/tests/auto/gui/image/qicon/tst_qicon.cpp index 4218d0751f0..01f3eabb177 100644 --- a/tests/auto/gui/image/qicon/tst_qicon.cpp +++ b/tests/auto/gui/image/qicon/tst_qicon.cpp @@ -530,16 +530,6 @@ void tst_QIcon::streamAvailableSizes() } } - -static inline bool operator<(const QSize &lhs, const QSize &rhs) -{ - if (lhs.width() < rhs.width()) - return true; - else if (lhs.width() == lhs.width()) - return lhs.height() < lhs.height(); - return false; -} - #ifndef QT_NO_WIDGETS void tst_QIcon::task184901_badCache() { diff --git a/tests/auto/gui/image/qimagewriter/tst_qimagewriter.cpp b/tests/auto/gui/image/qimagewriter/tst_qimagewriter.cpp index d5c624833c2..2381fd92465 100644 --- a/tests/auto/gui/image/qimagewriter/tst_qimagewriter.cpp +++ b/tests/auto/gui/image/qimagewriter/tst_qimagewriter.cpp @@ -77,6 +77,9 @@ private slots: void saveWithNoFormat(); void saveToTemporaryFile(); + + void writeEmpty(); + private: QTemporaryDir m_temporaryDir; QString prefix; @@ -529,5 +532,18 @@ void tst_QImageWriter::saveToTemporaryFile() } } +void tst_QImageWriter::writeEmpty() +{ + // check writing a null QImage errors gracefully + QTemporaryDir dir; + QVERIFY2(dir.isValid(), qPrintable(dir.errorString())); + QString fileName(dir.path() + QLatin1String("/testimage.bmp")); + QVERIFY(!QFileInfo(fileName).exists()); + QImageWriter writer(fileName); + QVERIFY(!writer.write(QImage())); + QCOMPARE(writer.error(), QImageWriter::InvalidImageError); + QVERIFY(!QFileInfo(fileName).exists()); +} + QTEST_MAIN(tst_QImageWriter) #include "tst_qimagewriter.moc" diff --git a/tests/auto/gui/painting/qpainter/tst_qpainter.cpp b/tests/auto/gui/painting/qpainter/tst_qpainter.cpp index 3562bc63f48..7f72fb04f2d 100644 --- a/tests/auto/gui/painting/qpainter/tst_qpainter.cpp +++ b/tests/auto/gui/painting/qpainter/tst_qpainter.cpp @@ -397,51 +397,6 @@ void tst_QPainter::cleanupTestCase() QFile::remove(QLatin1String("foo.png")); } -static const char* const maskSource_data[] = { -"16 13 6 1", -". c None", -"d c #000000", -"# c #999999", -"c c #cccccc", -"b c #ffff00", -"a c #ffffff", -"...#####........", -"..#aaaaa#.......", -".#abcbcba######.", -".#acbcbcaaaaaa#d", -".#abcbcbcbcbcb#d", -"#############b#d", -"#aaaaaaaaaa##c#d", -"#abcbcbcbcbbd##d", -".#abcbcbcbcbcd#d", -".#acbcbcbcbcbd#d", -"..#acbcbcbcbb#dd", -"..#############d", -"...ddddddddddddd"}; - -static const char* const maskResult_data[] = { -"16 13 6 1", -". c #ff0000", -"d c #000000", -"# c #999999", -"c c #cccccc", -"b c #ffff00", -"a c #ffffff", -"...#####........", -"..#aaaaa#.......", -".#abcbcba######.", -".#acbcbcaaaaaa#d", -".#abcbcbcbcbcb#d", -"#############b#d", -"#aaaaaaaaaa##c#d", -"#abcbcbcbcbbd##d", -".#abcbcbcbcbcd#d", -".#acbcbcbcbcbd#d", -"..#acbcbcbcbb#dd", -"..#############d", -"...ddddddddddddd"}; - - #ifndef QT_NO_WIDGETS void tst_QPainter::drawPixmap_comp_data() { diff --git a/tests/auto/gui/painting/qwmatrix/tst_qwmatrix.cpp b/tests/auto/gui/painting/qwmatrix/tst_qwmatrix.cpp index a79526c4341..46420b49c57 100644 --- a/tests/auto/gui/painting/qwmatrix/tst_qwmatrix.cpp +++ b/tests/auto/gui/painting/qwmatrix/tst_qwmatrix.cpp @@ -118,127 +118,96 @@ void tst_QWMatrix::mapping_data() #define M_PI 3.14159265897932384626433832795f #endif + const auto rotate = [](qreal degrees) { + const qreal rad = M_PI * degrees / 180.; + return QMatrix(std::cos(rad), -std::sin(rad), + std::sin(rad), std::cos(rad), 0, 0); + }; + // rotations - float deg = 0.; - QTest::newRow( "rot 0 a" ) << QMatrix( std::cos( M_PI*deg/180. ), -std::sin( M_PI*deg/180. ), - std::sin( M_PI*deg/180. ), std::cos( M_PI*deg/180. ), 0, 0 ) + QTest::newRow( "rot 0 a" ) << rotate(0.) << QRect( 0, 0, 30, 40 ) << QPolygon ( QRect( 0, 0, 30, 40 ) ); - deg = 0.00001f; - QTest::newRow( "rot 0 b" ) << QMatrix( std::cos( M_PI*deg/180. ), -std::sin( M_PI*deg/180. ), - std::sin( M_PI*deg/180. ), std::cos( M_PI*deg/180. ), 0, 0 ) + QTest::newRow( "rot 0 b" ) << rotate(0.00001f) << QRect( 0, 0, 30, 40 ) << QPolygon ( QRect( 0, 0, 30, 40 ) ); - deg = 0.; - QTest::newRow( "rot 0 c" ) << QMatrix( std::cos( M_PI*deg/180. ), -std::sin( M_PI*deg/180. ), - std::sin( M_PI*deg/180. ), std::cos( M_PI*deg/180. ), 0, 0 ) + QTest::newRow( "rot 0 c" ) << rotate(0.) << QRect( 10, 20, 30, 40 ) << QPolygon ( QRect( 10, 20, 30, 40 ) ); - deg = 0.00001f; - QTest::newRow( "rot 0 d" ) << QMatrix( std::cos( M_PI*deg/180. ), -std::sin( M_PI*deg/180. ), - std::sin( M_PI*deg/180. ), std::cos( M_PI*deg/180. ), 0, 0 ) + QTest::newRow( "rot 0 d" ) << rotate(0.00001f) << QRect( 10, 20, 30, 40 ) << QPolygon ( QRect( 10, 20, 30, 40 ) ); #if 0 - // rotations - deg = 90.; - QTest::newRow( "rotscale 90 a" ) << QMatrix( 10*std::cos( M_PI*deg/180. ), -10*std::sin( M_PI*deg/180. ), - 10*std::sin( M_PI*deg/180. ), 10*std::cos( M_PI*deg/180. ), 0, 0 ) + const auto rotScale = [](qreal degrees, qreal scale) { + const qreal rad = M_PI * degrees / 180.; + return QMatrix(scale * std::cos(rad), -scale * std::sin(rad), + scale * std::sin(rad), scale * std::cos(rad), 0, 0); + }; + // rotations with scaling + QTest::newRow( "rotscale 90 a" ) << rotScale(90., 10) << QRect( 0, 0, 30, 40 ) << QPolygon( QRect( 0, -299, 400, 300 ) ); - deg = 90.00001; - QTest::newRow( "rotscale 90 b" ) << QMatrix( 10*std::cos( M_PI*deg/180. ), -10*std::sin( M_PI*deg/180. ), - 10*std::sin( M_PI*deg/180. ), 10*std::cos( M_PI*deg/180. ), 0, 0 ) + QTest::newRow( "rotscale 90 b" ) << rotScale(90.00001, 10) << QRect( 0, 0, 30, 40 ) << QPolygon( QRect( 0, -299, 400, 300 ) ); - deg = 90.; - QTest::newRow( "rotscale 90 c" ) << QMatrix( 10*std::cos( M_PI*deg/180. ), -10*std::sin( M_PI*deg/180. ), - 10*std::sin( M_PI*deg/180. ), 10*std::cos( M_PI*deg/180. ), 0, 0 ) + QTest::newRow( "rotscale 90 c" ) << rotScale(90., 10) << QRect( 10, 20, 30, 40 ) << QPolygon( QRect( 200, -399, 400, 300 ) ); - deg = 90.00001; - QTest::newRow( "rotscale 90 d" ) << QMatrix( 10*std::cos( M_PI*deg/180. ), -10*std::sin( M_PI*deg/180. ), - 10*std::sin( M_PI*deg/180. ), 10*std::cos( M_PI*deg/180. ), 0, 0 ) + QTest::newRow( "rotscale 90 d" ) << rotScale(90.00001, 10) << QRect( 10, 20, 30, 40 ) << QPolygon( QRect( 200, -399, 400, 300 ) ); - deg = 180.; - QTest::newRow( "rotscale 180 a" ) << QMatrix( 10*std::cos( M_PI*deg/180. ), -10*std::sin( M_PI*deg/180. ), - 10*std::sin( M_PI*deg/180. ), 10*std::cos( M_PI*deg/180. ), 0, 0 ) + QTest::newRow( "rotscale 180 a" ) << rotScale(180., 10) << QRect( 0, 0, 30, 40 ) << QPolygon( QRect( -299, -399, 300, 400 ) ); - deg = 180.000001; - QTest::newRow( "rotscale 180 b" ) << QMatrix( 10*std::cos( M_PI*deg/180. ), -10*std::sin( M_PI*deg/180. ), - 10*std::sin( M_PI*deg/180. ), 10*std::cos( M_PI*deg/180. ), 0, 0 ) + QTest::newRow( "rotscale 180 b" ) << rotScale(180.000001, 10) << QRect( 0, 0, 30, 40 ) << QPolygon( QRect( -299, -399, 300, 400 ) ); - deg = 180.; - QTest::newRow( "rotscale 180 c" ) << QMatrix( 10*std::cos( M_PI*deg/180. ), -10*std::sin( M_PI*deg/180. ), - 10*std::sin( M_PI*deg/180. ), 10*std::cos( M_PI*deg/180. ), 0, 0 ) + QTest::newRow( "rotscale 180 c" ) << rotScale(180., 10) << QRect( 10, 20, 30, 40 ) << QPolygon( QRect( -399, -599, 300, 400 ) ); - deg = 180.000001; - QTest::newRow( "rotscale 180 d" ) << QMatrix( 10*std::cos( M_PI*deg/180. ), -10*std::sin( M_PI*deg/180. ), - 10*std::sin( M_PI*deg/180. ), 10*std::cos( M_PI*deg/180. ), 0, 0 ) + QTest::newRow( "rotscale 180 d" ) << rotScale(180.000001, 10) << QRect( 10, 20, 30, 40 ) << QPolygon( QRect( -399, -599, 300, 400 ) ); - deg = 270.; - QTest::newRow( "rotscale 270 a" ) << QMatrix( 10*std::cos( M_PI*deg/180. ), -10*std::sin( M_PI*deg/180. ), - 10*std::sin( M_PI*deg/180. ), 10*std::cos( M_PI*deg/180. ), 0, 0 ) + QTest::newRow( "rotscale 270 a" ) << rotScale(270., 10) << QRect( 0, 0, 30, 40 ) << QPolygon( QRect( -399, 00, 400, 300 ) ); - deg = 270.0000001; - QTest::newRow( "rotscale 270 b" ) << QMatrix( 10*std::cos( M_PI*deg/180. ), -10*std::sin( M_PI*deg/180. ), - 10*std::sin( M_PI*deg/180. ), 10*std::cos( M_PI*deg/180. ), 0, 0 ) + QTest::newRow( "rotscale 270 b" ) << rotScale(270.0000001, 10) << QRect( 0, 0, 30, 40 ) << QPolygon( QRect( -399, 00, 400, 300 ) ); - deg = 270.; - QTest::newRow( "rotscale 270 c" ) << QMatrix( 10*std::cos( M_PI*deg/180. ), -10*std::sin( M_PI*deg/180. ), - 10*std::sin( M_PI*deg/180. ), 10*std::cos( M_PI*deg/180. ), 0, 0 ) + QTest::newRow( "rotscale 270 c" ) << rotScale(270., 10) << QRect( 10, 20, 30, 40 ) << QPolygon( QRect( -599, 100, 400, 300 ) ); - deg = 270.000001; - QTest::newRow( "rotscale 270 d" ) << QMatrix( 10*std::cos( M_PI*deg/180. ), -10*std::sin( M_PI*deg/180. ), - 10*std::sin( M_PI*deg/180. ), 10*std::cos( M_PI*deg/180. ), 0, 0 ) + QTest::newRow( "rotscale 270 d" ) << rotScale(270.000001, 10) << QRect( 10, 20, 30, 40 ) << QPolygon( QRect( -599, 100, 400, 300 ) ); // rotations that are not multiples of 90 degrees. mapRect returns the bounding rect here. - deg = 45; - QTest::newRow( "rot 45 a" ) << QMatrix( std::cos( M_PI*deg/180. ), -std::sin( M_PI*deg/180. ), - std::sin( M_PI*deg/180. ), std::cos( M_PI*deg/180. ), 0, 0 ) + QTest::newRow( "rot 45 a" ) << rotate(45) << QRect( 0, 0, 10, 10 ) << QPolygon( QRect( 0, -7, 14, 14 ) ); - QTest::newRow( "rot 45 b" ) << QMatrix( std::cos( M_PI*deg/180. ), -std::sin( M_PI*deg/180. ), - std::sin( M_PI*deg/180. ), std::cos( M_PI*deg/180. ), 0, 0 ) + QTest::newRow( "rot 45 b" ) << rotate(45) << QRect( 10, 20, 30, 40 ) << QPolygon( QRect( 21, -14, 49, 49 ) ); - QTest::newRow( "rot 45 c" ) << QMatrix( 10*std::cos( M_PI*deg/180. ), -10*std::sin( M_PI*deg/180. ), - 10*std::sin( M_PI*deg/180. ), 10*std::cos( M_PI*deg/180. ), 0, 0 ) + QTest::newRow( "rot 45 c" ) << rotScale(45, 10) << QRect( 0, 0, 10, 10 ) << QPolygon( QRect( 0, -70, 141, 141 ) ); - QTest::newRow( "rot 45 d" ) << QMatrix( 10*std::cos( M_PI*deg/180. ), -10*std::sin( M_PI*deg/180. ), - 10*std::sin( M_PI*deg/180. ), 10*std::cos( M_PI*deg/180. ), 0, 0 ) + QTest::newRow( "rot 45 d" ) << rotScale(45, 10) << QRect( 10, 20, 30, 40 ) << QPolygon( QRect( 212, -141, 495, 495 ) ); - deg = -45; - QTest::newRow( "rot -45 a" ) << QMatrix( std::cos( M_PI*deg/180. ), -std::sin( M_PI*deg/180. ), - std::sin( M_PI*deg/180. ), std::cos( M_PI*deg/180. ), 0, 0 ) + QTest::newRow( "rot -45 a" ) << rotate(-45) << QRect( 0, 0, 10, 10 ) << QPolygon( QRect( -7, 0, 14, 14 ) ); - QTest::newRow( "rot -45 b" ) << QMatrix( std::cos( M_PI*deg/180. ), -std::sin( M_PI*deg/180. ), - std::sin( M_PI*deg/180. ), std::cos( M_PI*deg/180. ), 0, 0 ) + QTest::newRow( "rot -45 b" ) << rotate(-45) << QRect( 10, 20, 30, 40 ) << QPolygon( QRect( -35, 21, 49, 49 ) ); - QTest::newRow( "rot -45 c" ) << QMatrix( 10*std::cos( M_PI*deg/180. ), -10*std::sin( M_PI*deg/180. ), - 10*std::sin( M_PI*deg/180. ), 10*std::cos( M_PI*deg/180. ), 0, 0 ) + QTest::newRow( "rot -45 c" ) << rotScale(-45, 10) << QRect( 0, 0, 10, 10 ) << QPolygon( QRect( -70, 0, 141, 141 ) ); - QTest::newRow( "rot -45 d" ) << QMatrix( 10*std::cos( M_PI*deg/180. ), -10*std::sin( M_PI*deg/180. ), - 10*std::sin( M_PI*deg/180. ), 10*std::cos( M_PI*deg/180. ), 0, 0 ) + QTest::newRow( "rot -45 d" ) << rotScale(-45, 10) << QRect( 10, 20, 30, 40 ) << QPolygon( QRect( -353, 212, 495, 495 ) ); #endif diff --git a/tests/auto/network/ssl/qsslsocket/tst_qsslsocket.cpp b/tests/auto/network/ssl/qsslsocket/tst_qsslsocket.cpp index 4eb26d17fec..ba02af1d476 100644 --- a/tests/auto/network/ssl/qsslsocket/tst_qsslsocket.cpp +++ b/tests/auto/network/ssl/qsslsocket/tst_qsslsocket.cpp @@ -1096,6 +1096,9 @@ public: QString m_interFile; QString ciphers; +signals: + void socketError(QAbstractSocket::SocketError); + protected: void incomingConnection(qintptr socketDescriptor) { @@ -1105,6 +1108,7 @@ protected: socket->setProtocol(protocol); if (ignoreSslErrors) connect(socket, SIGNAL(sslErrors(QList<QSslError>)), this, SLOT(ignoreErrorSlot())); + connect(socket, SIGNAL(error(QAbstractSocket::SocketError)), this, SIGNAL(socketError(QAbstractSocket::SocketError))); QFile file(m_keyFile); QVERIFY(file.open(QIODevice::ReadOnly)); @@ -1240,6 +1244,37 @@ void tst_QSslSocket::protocolServerSide_data() #if !defined(OPENSSL_NO_SSL3) QTest::newRow("any-ssl3") << QSsl::AnyProtocol << QSsl::SslV3 << true; #endif + +#if !defined(OPENSSL_NO_SSL2) && !defined(QT_SECURETRANSPORT) + QTest::newRow("tls1.0orlater-ssl2") << QSsl::TlsV1_0OrLater << QSsl::SslV2 << false; +#endif +#if !defined(OPENSSL_NO_SSL3) + QTest::newRow("tls1.0orlater-ssl3") << QSsl::TlsV1_0OrLater << QSsl::SslV3 << false; +#endif + QTest::newRow("tls1.0orlater-tls1.0") << QSsl::TlsV1_0OrLater << QSsl::TlsV1_0 << true; + QTest::newRow("tls1.0orlater-tls1.1") << QSsl::TlsV1_0OrLater << QSsl::TlsV1_1 << true; + QTest::newRow("tls1.0orlater-tls1.2") << QSsl::TlsV1_0OrLater << QSsl::TlsV1_2 << true; + +#if !defined(OPENSSL_NO_SSL2) && !defined(QT_SECURETRANSPORT) + QTest::newRow("tls1.1orlater-ssl2") << QSsl::TlsV1_1OrLater << QSsl::SslV2 << false; +#endif +#if !defined(OPENSSL_NO_SSL3) + QTest::newRow("tls1.1orlater-ssl3") << QSsl::TlsV1_1OrLater << QSsl::SslV3 << false; +#endif + QTest::newRow("tls1.1orlater-tls1.0") << QSsl::TlsV1_1OrLater << QSsl::TlsV1_0 << false; + QTest::newRow("tls1.1orlater-tls1.1") << QSsl::TlsV1_1OrLater << QSsl::TlsV1_1 << true; + QTest::newRow("tls1.1orlater-tls1.2") << QSsl::TlsV1_1OrLater << QSsl::TlsV1_2 << true; + +#if !defined(OPENSSL_NO_SSL2) && !defined(QT_SECURETRANSPORT) + QTest::newRow("tls1.2orlater-ssl2") << QSsl::TlsV1_2OrLater << QSsl::SslV2 << false; +#endif +#if !defined(OPENSSL_NO_SSL3) + QTest::newRow("tls1.2orlater-ssl3") << QSsl::TlsV1_2OrLater << QSsl::SslV3 << false; +#endif + QTest::newRow("tls1.2orlater-tls1.0") << QSsl::TlsV1_2OrLater << QSsl::TlsV1_0 << false; + QTest::newRow("tls1.2orlater-tls1.1") << QSsl::TlsV1_2OrLater << QSsl::TlsV1_1 << false; + QTest::newRow("tls1.2orlater-tls1.2") << QSsl::TlsV1_2OrLater << QSsl::TlsV1_2 << true; + QTest::newRow("any-tls1.0") << QSsl::AnyProtocol << QSsl::TlsV1_0 << true; QTest::newRow("any-tls1ssl3") << QSsl::AnyProtocol << QSsl::TlsV1SslV3 << true; QTest::newRow("any-secure") << QSsl::AnyProtocol << QSsl::SecureProtocols << true; @@ -1262,6 +1297,7 @@ void tst_QSslSocket::protocolServerSide() QVERIFY(server.listen()); QEventLoop loop; + connect(&server, SIGNAL(socketError(QAbstractSocket::SocketError)), &loop, SLOT(quit())); QTimer::singleShot(5000, &loop, SLOT(quit())); QSslSocket client; @@ -1279,7 +1315,15 @@ void tst_QSslSocket::protocolServerSide() QFETCH(bool, works); QAbstractSocket::SocketState expectedState = (works) ? QAbstractSocket::ConnectedState : QAbstractSocket::UnconnectedState; - QCOMPARE(int(client.state()), int(expectedState)); + // Determine whether the client or the server caused the event loop + // to quit due to a socket error, and investigate the culprit. + if (server.socket->error() != QAbstractSocket::UnknownSocketError) { + QVERIFY(client.error() == QAbstractSocket::UnknownSocketError); + QCOMPARE(int(server.socket->state()), int(expectedState)); + } else if (client.error() != QAbstractSocket::UnknownSocketError) { + QVERIFY(server.socket->error() == QAbstractSocket::UnknownSocketError); + QCOMPARE(int(client.state()), int(expectedState)); + } QCOMPARE(client.isEncrypted(), works); } diff --git a/tests/auto/other/modeltest/dynamictreemodel.cpp b/tests/auto/other/modeltest/dynamictreemodel.cpp index 1f6463db8af..fc979bce2df 100644 --- a/tests/auto/other/modeltest/dynamictreemodel.cpp +++ b/tests/auto/other/modeltest/dynamictreemodel.cpp @@ -33,9 +33,8 @@ #include <QtCore/QTimer> #include <QtCore/QDebug> - -DynamicTreeModel::DynamicTreeModel(QObject *parent) - : QAbstractItemModel(parent), +DynamicTreeModel::DynamicTreeModel(QObject *parent) : + QAbstractItemModel(parent), nextId(1) { } @@ -45,186 +44,172 @@ QModelIndex DynamicTreeModel::index(int row, int column, const QModelIndex &pare // if (column != 0) // return QModelIndex(); + if (column < 0 || row < 0) + return QModelIndex(); - if ( column < 0 || row < 0 ) - return QModelIndex(); - - QList<QList<qint64> > childIdColumns = m_childItems.value(parent.internalId()); + QList<QList<qint64> > childIdColumns = m_childItems.value(parent.internalId()); - const qint64 grandParent = findParentId(parent.internalId()); - if (grandParent >= 0) { - QList<QList<qint64> > parentTable = m_childItems.value(grandParent); - if (parent.column() >= parentTable.size()) - qFatal("%s: parent.column() must be less than parentTable.size()", Q_FUNC_INFO); - QList<qint64> parentSiblings = parentTable.at(parent.column()); - if (parent.row() >= parentSiblings.size()) - qFatal("%s: parent.row() must be less than parentSiblings.size()", Q_FUNC_INFO); - } - - if (childIdColumns.size() == 0) - return QModelIndex(); + const qint64 grandParent = findParentId(parent.internalId()); + if (grandParent >= 0) { + QList<QList<qint64> > parentTable = m_childItems.value(grandParent); + if (parent.column() >= parentTable.size()) + qFatal("%s: parent.column() must be less than parentTable.size()", Q_FUNC_INFO); + QList<qint64> parentSiblings = parentTable.at(parent.column()); + if (parent.row() >= parentSiblings.size()) + qFatal("%s: parent.row() must be less than parentSiblings.size()", Q_FUNC_INFO); + } - if (column >= childIdColumns.size()) - return QModelIndex(); + if (childIdColumns.size() == 0) + return QModelIndex(); - QList<qint64> rowIds = childIdColumns.at(column); + if (column >= childIdColumns.size()) + return QModelIndex(); - if ( row >= rowIds.size()) - return QModelIndex(); + QList<qint64> rowIds = childIdColumns.at(column); - qint64 id = rowIds.at(row); + if (row >= rowIds.size()) + return QModelIndex(); - return createIndex(row, column, reinterpret_cast<void *>(id)); + qint64 id = rowIds.at(row); + return createIndex(row, column, reinterpret_cast<void *>(id)); } qint64 DynamicTreeModel::findParentId(qint64 searchId) const { - if (searchId <= 0) - return -1; - - QHashIterator<qint64, QList<QList<qint64> > > i(m_childItems); - while (i.hasNext()) - { - i.next(); - QListIterator<QList<qint64> > j(i.value()); - while (j.hasNext()) - { - QList<qint64> l = j.next(); - if (l.contains(searchId)) - { - return i.key(); - } + if (searchId <= 0) + return -1; + + QHashIterator<qint64, QList<QList<qint64> > > i(m_childItems); + while (i.hasNext()) { + i.next(); + QListIterator<QList<qint64> > j(i.value()); + while (j.hasNext()) { + QList<qint64> l = j.next(); + if (l.contains(searchId)) + return i.key(); + } } - } - return -1; + return -1; } QModelIndex DynamicTreeModel::parent(const QModelIndex &index) const { - if (!index.isValid()) - return QModelIndex(); + if (!index.isValid()) + return QModelIndex(); - qint64 searchId = index.internalId(); - qint64 parentId = findParentId(searchId); - // Will never happen for valid index, but what the hey... - if (parentId <= 0) - return QModelIndex(); + qint64 searchId = index.internalId(); + qint64 parentId = findParentId(searchId); + // Will never happen for valid index, but what the hey... + if (parentId <= 0) + return QModelIndex(); - qint64 grandParentId = findParentId(parentId); - if (grandParentId < 0) - grandParentId = 0; + qint64 grandParentId = findParentId(parentId); + if (grandParentId < 0) + grandParentId = 0; - int column = 0; - QList<qint64> childList = m_childItems.value(grandParentId).at(column); + int column = 0; + QList<qint64> childList = m_childItems.value(grandParentId).at(column); - int row = childList.indexOf(parentId); - - return createIndex(row, column, reinterpret_cast<void *>(parentId)); + int row = childList.indexOf(parentId); + return createIndex(row, column, reinterpret_cast<void *>(parentId)); } -int DynamicTreeModel::rowCount(const QModelIndex &index ) const +int DynamicTreeModel::rowCount(const QModelIndex &index) const { - QList<QList<qint64> > cols = m_childItems.value(index.internalId()); + QList<QList<qint64> > cols = m_childItems.value(index.internalId()); - if (cols.size() == 0 ) - return 0; + if (cols.size() == 0) + return 0; - if (index.column() > 0) - return 0; + if (index.column() > 0) + return 0; - return cols.at(0).size(); + return cols.at(0).size(); } -int DynamicTreeModel::columnCount(const QModelIndex &index ) const +int DynamicTreeModel::columnCount(const QModelIndex &index) const { // Q_UNUSED(index); - return m_childItems.value(index.internalId()).size(); + return m_childItems.value(index.internalId()).size(); } QVariant DynamicTreeModel::data(const QModelIndex &index, int role) const { - if (!index.isValid()) - return QVariant(); + if (!index.isValid()) + return QVariant(); - if (Qt::DisplayRole == role) - { - return m_items.value(index.internalId()); - } - return QVariant(); + if (Qt::DisplayRole == role) + return m_items.value(index.internalId()); + return QVariant(); } void DynamicTreeModel::clear() { - beginResetModel(); - m_items.clear(); - m_childItems.clear(); - nextId = 1; - endResetModel(); + beginResetModel(); + m_items.clear(); + m_childItems.clear(); + nextId = 1; + endResetModel(); } - -ModelChangeCommand::ModelChangeCommand( DynamicTreeModel *model, QObject *parent ) - : QObject(parent), m_model(model), m_numCols(1), m_startRow(-1), m_endRow(-1) +ModelChangeCommand::ModelChangeCommand(DynamicTreeModel *model, QObject *parent) : + QObject(parent), + m_model(model), + m_numCols(1), + m_startRow(-1), + m_endRow(-1) { - } QModelIndex ModelChangeCommand::findIndex(QList<int> rows) { - const int col = 0; - QModelIndex parent = QModelIndex(); - QListIterator<int> i(rows); - while (i.hasNext()) - { - parent = m_model->index(i.next(), col, parent); - if (!parent.isValid()) - qFatal("%s: parent must be valid", Q_FUNC_INFO); - } - return parent; + const int col = 0; + QModelIndex parent = QModelIndex(); + QListIterator<int> i(rows); + while (i.hasNext()) { + parent = m_model->index(i.next(), col, parent); + if (!parent.isValid()) + qFatal("%s: parent must be valid", Q_FUNC_INFO); + } + return parent; } -ModelInsertCommand::ModelInsertCommand(DynamicTreeModel *model, QObject *parent ) - : ModelChangeCommand(model, parent) +ModelInsertCommand::ModelInsertCommand(DynamicTreeModel *model, QObject *parent) : + ModelChangeCommand(model, parent) { - } void ModelInsertCommand::doCommand() { - QModelIndex parent = findIndex(m_rowNumbers); - m_model->beginInsertRows(parent, m_startRow, m_endRow); - qint64 parentId = parent.internalId(); - for (int row = m_startRow; row <= m_endRow; row++) - { - for(int col = 0; col < m_numCols; col++ ) - { - if (m_model->m_childItems[parentId].size() <= col) - { - m_model->m_childItems[parentId].append(QList<qint64>()); - } + QModelIndex parent = findIndex(m_rowNumbers); + m_model->beginInsertRows(parent, m_startRow, m_endRow); + qint64 parentId = parent.internalId(); + for (int row = m_startRow; row <= m_endRow; row++) { + for (int col = 0; col < m_numCols; col++) { + if (m_model->m_childItems[parentId].size() <= col) + m_model->m_childItems[parentId].append(QList<qint64>()); // QString name = QUuid::createUuid().toString(); - qint64 id = m_model->newId(); - QString name = QString::number(id); - - m_model->m_items.insert(id, name); - m_model->m_childItems[parentId][col].insert(row, id); + qint64 id = m_model->newId(); + QString name = QString::number(id); + m_model->m_items.insert(id, name); + m_model->m_childItems[parentId][col].insert(row, id); + } } - } - m_model->endInsertRows(); + m_model->endInsertRows(); } - -ModelMoveCommand::ModelMoveCommand(DynamicTreeModel *model, QObject *parent) - : ModelChangeCommand(model, parent) +ModelMoveCommand::ModelMoveCommand(DynamicTreeModel *model, QObject *parent) : + ModelChangeCommand(model, parent) { - } -bool ModelMoveCommand::emitPreSignal(const QModelIndex &srcParent, int srcStart, int srcEnd, const QModelIndex &destParent, int destRow) + +bool ModelMoveCommand::emitPreSignal(const QModelIndex &srcParent, int srcStart, int srcEnd, + const QModelIndex &destParent, int destRow) { - return m_model->beginMoveRows(srcParent, srcStart, srcEnd, destParent, destRow); + return m_model->beginMoveRows(srcParent, srcStart, srcEnd, destParent, destRow); } void ModelMoveCommand::doCommand() @@ -233,33 +218,26 @@ void ModelMoveCommand::doCommand() QModelIndex destParent = findIndex(m_destRowNumbers); if (!emitPreSignal(srcParent, m_startRow, m_endRow, destParent, m_destRow)) - { return; - } - for (int column = 0; column < m_numCols; ++column) - { - QList<qint64> l = m_model->m_childItems.value(srcParent.internalId())[column].mid(m_startRow, m_endRow - m_startRow + 1 ); + for (int column = 0; column < m_numCols; ++column) { + QList<qint64> l = m_model->m_childItems.value(srcParent.internalId())[column].mid( + m_startRow, m_endRow - m_startRow + 1); - for (int i = m_startRow; i <= m_endRow ; i++) - { + for (int i = m_startRow; i <= m_endRow; i++) m_model->m_childItems[srcParent.internalId()][column].removeAt(m_startRow); - } int d; - if (m_destRow < m_startRow) + if (m_destRow < m_startRow) { d = m_destRow; - else - { + } else { if (srcParent == destParent) d = m_destRow - (m_endRow - m_startRow + 1); else d = m_destRow - (m_endRow - m_startRow) + 1; } - foreach(const qint64 id, l) - { + foreach (const qint64 id, l) m_model->m_childItems[destParent.internalId()][column].insert(d++, id); - } } emitPostSignal(); @@ -270,18 +248,17 @@ void ModelMoveCommand::emitPostSignal() m_model->endMoveRows(); } -ModelResetCommand::ModelResetCommand(DynamicTreeModel* model, QObject* parent) - : ModelMoveCommand(model, parent) +ModelResetCommand::ModelResetCommand(DynamicTreeModel *model, QObject *parent) : + ModelMoveCommand(model, parent) { - } ModelResetCommand::~ModelResetCommand() { - } -bool ModelResetCommand::emitPreSignal(const QModelIndex &srcParent, int srcStart, int srcEnd, const QModelIndex &destParent, int destRow) +bool ModelResetCommand::emitPreSignal(const QModelIndex &srcParent, int srcStart, int srcEnd, + const QModelIndex &destParent, int destRow) { Q_UNUSED(srcParent); Q_UNUSED(srcStart); @@ -298,18 +275,17 @@ void ModelResetCommand::emitPostSignal() m_model->endResetModel(); } -ModelResetCommandFixed::ModelResetCommandFixed(DynamicTreeModel* model, QObject* parent) - : ModelMoveCommand(model, parent) +ModelResetCommandFixed::ModelResetCommandFixed(DynamicTreeModel *model, QObject *parent) : + ModelMoveCommand(model, parent) { - } ModelResetCommandFixed::~ModelResetCommandFixed() { - } -bool ModelResetCommandFixed::emitPreSignal(const QModelIndex &srcParent, int srcStart, int srcEnd, const QModelIndex &destParent, int destRow) +bool ModelResetCommandFixed::emitPreSignal(const QModelIndex &srcParent, int srcStart, int srcEnd, + const QModelIndex &destParent, int destRow) { Q_UNUSED(srcParent); Q_UNUSED(srcStart); @@ -326,10 +302,10 @@ void ModelResetCommandFixed::emitPostSignal() m_model->endResetModel(); } -ModelChangeChildrenLayoutsCommand::ModelChangeChildrenLayoutsCommand(DynamicTreeModel* model, QObject* parent) - : ModelChangeCommand(model, parent) +ModelChangeChildrenLayoutsCommand::ModelChangeChildrenLayoutsCommand(DynamicTreeModel *model, + QObject *parent) : + ModelChangeCommand(model, parent) { - } void ModelChangeChildrenLayoutsCommand::doCommand() @@ -346,17 +322,16 @@ void ModelChangeChildrenLayoutsCommand::doCommand() int rowSize1 = -1; int rowSize2 = -1; - for (int column = 0; column < m_numCols; ++column) - { + for (int column = 0; column < m_numCols; ++column) { { - QList<qint64> &l = m_model->m_childItems[parent1.internalId()][column]; - rowSize1 = l.size(); - l.prepend(l.takeLast()); + QList<qint64> &l = m_model->m_childItems[parent1.internalId()][column]; + rowSize1 = l.size(); + l.prepend(l.takeLast()); } { - QList<qint64> &l = m_model->m_childItems[parent2.internalId()][column]; - rowSize2 = l.size(); - l.append(l.takeFirst()); + QList<qint64> &l = m_model->m_childItems[parent2.internalId()][column]; + rowSize2 = l.size(); + l.append(l.takeFirst()); } } @@ -373,15 +348,23 @@ void ModelChangeChildrenLayoutsCommand::doCommand() foreach (const QModelIndex &idx, persistent) { if (idx.parent() == parent1) { if (idx.row() == rowSize1 - 1) { - m_model->changePersistentIndex(idx, m_model->createIndex(0, idx.column(), idx.internalPointer())); + m_model->changePersistentIndex(idx, + m_model->createIndex(0, idx.column(), + idx.internalPointer())); } else { - m_model->changePersistentIndex(idx, m_model->createIndex(idx.row() + 1, idx.column(), idx.internalPointer())); + m_model->changePersistentIndex(idx, + m_model->createIndex(idx.row() + 1, idx.column(), + idx.internalPointer())); } } else if (idx.parent() == parent2) { if (idx.row() == 0) { - m_model->changePersistentIndex(idx, m_model->createIndex(rowSize2 - 1, idx.column(), idx.internalPointer())); + m_model->changePersistentIndex(idx, + m_model->createIndex(rowSize2 - 1, idx.column(), + idx.internalPointer())); } else { - m_model->changePersistentIndex(idx, m_model->createIndex(idx.row() - 1, idx.column(), idx.internalPointer())); + m_model->changePersistentIndex(idx, + m_model->createIndex(idx.row() - 1, idx.column(), + idx.internalPointer())); } } } diff --git a/tests/auto/other/modeltest/dynamictreemodel.h b/tests/auto/other/modeltest/dynamictreemodel.h index e31c4569fda..709751dd27a 100644 --- a/tests/auto/other/modeltest/dynamictreemodel.h +++ b/tests/auto/other/modeltest/dynamictreemodel.h @@ -34,119 +34,142 @@ #include <QtCore/QHash> #include <QtCore/QList> - class DynamicTreeModel : public QAbstractItemModel { - Q_OBJECT + Q_OBJECT public: - DynamicTreeModel(QObject *parent = 0); + DynamicTreeModel(QObject *parent = 0); - QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const; - QModelIndex parent(const QModelIndex &index) const; - int rowCount(const QModelIndex &index = QModelIndex()) const; - int columnCount(const QModelIndex &index = QModelIndex()) const; + QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const; + QModelIndex parent(const QModelIndex &index) const; + int rowCount(const QModelIndex &index = QModelIndex()) const; + int columnCount(const QModelIndex &index = QModelIndex()) const; - QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const; + QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const; - void clear(); + void clear(); protected slots: - /** - Finds the parent id of the string with id @p searchId. + /** + Finds the parent id of the string with id @p searchId. - Returns -1 if not found. - */ - qint64 findParentId(qint64 searchId) const; + Returns -1 if not found. + */ + qint64 findParentId(qint64 searchId) const; private: - QHash<qint64, QString> m_items; - QHash<qint64, QList<QList<qint64> > > m_childItems; - qint64 nextId; - qint64 newId() { return nextId++; }; - - QModelIndex m_nextParentIndex; - int m_nextRow; - - int m_depth; - int maxDepth; - - friend class ModelInsertCommand; - friend class ModelMoveCommand; - friend class ModelResetCommand; - friend class ModelResetCommandFixed; - friend class ModelChangeChildrenLayoutsCommand; - + QHash<qint64, QString> m_items; + QHash<qint64, QList<QList<qint64> > > m_childItems; + qint64 nextId; + qint64 newId() + { + return nextId++; + } + + QModelIndex m_nextParentIndex; + int m_nextRow; + + int m_depth; + int maxDepth; + + friend class ModelInsertCommand; + friend class ModelMoveCommand; + friend class ModelResetCommand; + friend class ModelResetCommandFixed; + friend class ModelChangeChildrenLayoutsCommand; }; - class ModelChangeCommand : public QObject { - Q_OBJECT + Q_OBJECT public: - ModelChangeCommand( DynamicTreeModel *model, QObject *parent = 0 ); + ModelChangeCommand(DynamicTreeModel *model, QObject *parent = 0); - virtual ~ModelChangeCommand() {} + virtual ~ModelChangeCommand() + { + } - void setAncestorRowNumbers(QList<int> rowNumbers) { m_rowNumbers = rowNumbers; } + void setAncestorRowNumbers(QList<int> rowNumbers) + { + m_rowNumbers = rowNumbers; + } - QModelIndex findIndex(QList<int> rows); + QModelIndex findIndex(QList<int> rows); - void setStartRow(int row) { m_startRow = row; } + void setStartRow(int row) + { + m_startRow = row; + } - void setEndRow(int row) { m_endRow = row; } + void setEndRow(int row) + { + m_endRow = row; + } - void setNumCols(int cols) { m_numCols = cols; } + void setNumCols(int cols) + { + m_numCols = cols; + } - virtual void doCommand() = 0; + virtual void doCommand() = 0; protected: - DynamicTreeModel* m_model; - QList<int> m_rowNumbers; - int m_numCols; - int m_startRow; - int m_endRow; - + DynamicTreeModel *m_model; + QList<int> m_rowNumbers; + int m_numCols; + int m_startRow; + int m_endRow; }; -typedef QList<ModelChangeCommand*> ModelChangeCommandList; +typedef QList<ModelChangeCommand *> ModelChangeCommandList; class ModelInsertCommand : public ModelChangeCommand { - Q_OBJECT + Q_OBJECT public: - ModelInsertCommand(DynamicTreeModel *model, QObject *parent = 0 ); - virtual ~ModelInsertCommand() {} + ModelInsertCommand(DynamicTreeModel *model, QObject *parent = 0); + virtual ~ModelInsertCommand() + { + } - virtual void doCommand(); + virtual void doCommand(); }; - class ModelMoveCommand : public ModelChangeCommand { - Q_OBJECT + Q_OBJECT public: - ModelMoveCommand(DynamicTreeModel *model, QObject *parent); + ModelMoveCommand(DynamicTreeModel *model, QObject *parent); - virtual ~ModelMoveCommand() {} + virtual ~ModelMoveCommand() + { + } - virtual bool emitPreSignal(const QModelIndex &srcParent, int srcStart, int srcEnd, const QModelIndex &destParent, int destRow); + virtual bool emitPreSignal(const QModelIndex &srcParent, int srcStart, int srcEnd, + const QModelIndex &destParent, int destRow); - virtual void doCommand(); + virtual void doCommand(); - virtual void emitPostSignal(); + virtual void emitPostSignal(); - void setDestAncestors( QList<int> rows ) { m_destRowNumbers = rows; } + void setDestAncestors(QList<int> rows) + { + m_destRowNumbers = rows; + } - void setDestRow(int row) { m_destRow = row; } + void setDestRow(int row) + { + m_destRow = row; + } protected: - QList<int> m_destRowNumbers; - int m_destRow; + QList<int> m_destRowNumbers; + int m_destRow; }; /** @@ -154,15 +177,15 @@ protected: */ class ModelResetCommand : public ModelMoveCommand { - Q_OBJECT + Q_OBJECT public: - ModelResetCommand(DynamicTreeModel* model, QObject* parent = 0); + ModelResetCommand(DynamicTreeModel *model, QObject *parent = 0); - virtual ~ModelResetCommand(); - - virtual bool emitPreSignal(const QModelIndex &srcParent, int srcStart, int srcEnd, const QModelIndex &destParent, int destRow); - virtual void emitPostSignal(); + virtual ~ModelResetCommand(); + virtual bool emitPreSignal(const QModelIndex &srcParent, int srcStart, int srcEnd, + const QModelIndex &destParent, int destRow); + virtual void emitPostSignal(); }; /** @@ -170,32 +193,37 @@ public: */ class ModelResetCommandFixed : public ModelMoveCommand { - Q_OBJECT + Q_OBJECT public: - ModelResetCommandFixed(DynamicTreeModel* model, QObject* parent = 0); - - virtual ~ModelResetCommandFixed(); + ModelResetCommandFixed(DynamicTreeModel *model, QObject *parent = 0); - virtual bool emitPreSignal(const QModelIndex &srcParent, int srcStart, int srcEnd, const QModelIndex &destParent, int destRow); - virtual void emitPostSignal(); + virtual ~ModelResetCommandFixed(); + virtual bool emitPreSignal(const QModelIndex &srcParent, int srcStart, int srcEnd, + const QModelIndex &destParent, int destRow); + virtual void emitPostSignal(); }; class ModelChangeChildrenLayoutsCommand : public ModelChangeCommand { - Q_OBJECT + Q_OBJECT public: - ModelChangeChildrenLayoutsCommand(DynamicTreeModel *model, QObject *parent); + ModelChangeChildrenLayoutsCommand(DynamicTreeModel *model, QObject *parent); - virtual ~ModelChangeChildrenLayoutsCommand() {} + virtual ~ModelChangeChildrenLayoutsCommand() + { + } - virtual void doCommand(); + virtual void doCommand(); - void setSecondAncestorRowNumbers( QList<int> rows ) { m_secondRowNumbers = rows; } + void setSecondAncestorRowNumbers(QList<int> rows) + { + m_secondRowNumbers = rows; + } protected: - QList<int> m_secondRowNumbers; - int m_destRow; + QList<int> m_secondRowNumbers; + int m_destRow; }; #endif diff --git a/tests/auto/other/modeltest/modeltest.cpp b/tests/auto/other/modeltest/modeltest.cpp index 4da00bda4d8..611f9e904b3 100644 --- a/tests/auto/other/modeltest/modeltest.cpp +++ b/tests/auto/other/modeltest/modeltest.cpp @@ -34,60 +34,62 @@ /*! Connect to all of the models signals. Whenever anything happens recheck everything. */ -ModelTest::ModelTest ( QAbstractItemModel *_model, QObject *parent ) : QObject ( parent ), model ( _model ), fetchingMore ( false ) +ModelTest::ModelTest(QAbstractItemModel *_model, QObject *parent) : QObject(parent), + model(_model), + fetchingMore(false) { if (!model) qFatal("%s: model must not be null", Q_FUNC_INFO); connect(model, SIGNAL(columnsAboutToBeInserted(QModelIndex,int,int)), - this, SLOT(runAllTests()) ); + this, SLOT(runAllTests())); connect(model, SIGNAL(columnsAboutToBeRemoved(QModelIndex,int,int)), - this, SLOT(runAllTests()) ); + this, SLOT(runAllTests())); connect(model, SIGNAL(columnsInserted(QModelIndex,int,int)), - this, SLOT(runAllTests()) ); + this, SLOT(runAllTests())); connect(model, SIGNAL(columnsRemoved(QModelIndex,int,int)), - this, SLOT(runAllTests()) ); + this, SLOT(runAllTests())); connect(model, SIGNAL(dataChanged(QModelIndex,QModelIndex)), - this, SLOT(runAllTests()) ); + this, SLOT(runAllTests())); connect(model, SIGNAL(headerDataChanged(Qt::Orientation,int,int)), - this, SLOT(runAllTests()) ); - connect(model, SIGNAL(layoutAboutToBeChanged()), this, SLOT(runAllTests()) ); - connect(model, SIGNAL(layoutChanged()), this, SLOT(runAllTests()) ); - connect(model, SIGNAL(modelReset()), this, SLOT(runAllTests()) ); + this, SLOT(runAllTests())); + connect(model, SIGNAL(layoutAboutToBeChanged()), this, SLOT(runAllTests())); + connect(model, SIGNAL(layoutChanged()), this, SLOT(runAllTests())); + connect(model, SIGNAL(modelReset()), this, SLOT(runAllTests())); connect(model, SIGNAL(rowsAboutToBeInserted(QModelIndex,int,int)), - this, SLOT(runAllTests()) ); + this, SLOT(runAllTests())); connect(model, SIGNAL(rowsAboutToBeRemoved(QModelIndex,int,int)), - this, SLOT(runAllTests()) ); + this, SLOT(runAllTests())); connect(model, SIGNAL(rowsInserted(QModelIndex,int,int)), - this, SLOT(runAllTests()) ); + this, SLOT(runAllTests())); connect(model, SIGNAL(rowsRemoved(QModelIndex,int,int)), - this, SLOT(runAllTests()) ); + this, SLOT(runAllTests())); // Special checks for changes connect(model, SIGNAL(layoutAboutToBeChanged()), - this, SLOT(layoutAboutToBeChanged()) ); + this, SLOT(layoutAboutToBeChanged())); connect(model, SIGNAL(layoutChanged()), - this, SLOT(layoutChanged()) ); + this, SLOT(layoutChanged())); connect(model, SIGNAL(rowsAboutToBeInserted(QModelIndex,int,int)), - this, SLOT(rowsAboutToBeInserted(QModelIndex,int,int)) ); + this, SLOT(rowsAboutToBeInserted(QModelIndex,int,int))); connect(model, SIGNAL(rowsAboutToBeRemoved(QModelIndex,int,int)), - this, SLOT(rowsAboutToBeRemoved(QModelIndex,int,int)) ); + this, SLOT(rowsAboutToBeRemoved(QModelIndex,int,int))); connect(model, SIGNAL(rowsInserted(QModelIndex,int,int)), - this, SLOT(rowsInserted(QModelIndex,int,int)) ); + this, SLOT(rowsInserted(QModelIndex,int,int))); connect(model, SIGNAL(rowsRemoved(QModelIndex,int,int)), - this, SLOT(rowsRemoved(QModelIndex,int,int)) ); + this, SLOT(rowsRemoved(QModelIndex,int,int))); connect(model, SIGNAL(dataChanged(QModelIndex,QModelIndex)), - this, SLOT(dataChanged(QModelIndex,QModelIndex)) ); + this, SLOT(dataChanged(QModelIndex,QModelIndex))); connect(model, SIGNAL(headerDataChanged(Qt::Orientation,int,int)), - this, SLOT(headerDataChanged(Qt::Orientation,int,int)) ); + this, SLOT(headerDataChanged(Qt::Orientation,int,int))); runAllTests(); } void ModelTest::runAllTests() { - if ( fetchingMore ) + if (fetchingMore) return; nonDestructiveBasicTest(); rowCount(); @@ -105,31 +107,31 @@ void ModelTest::runAllTests() void ModelTest::nonDestructiveBasicTest() { QVERIFY(!model->buddy(QModelIndex()).isValid()); - model->canFetchMore ( QModelIndex() ); - QVERIFY( model->columnCount ( QModelIndex() ) >= 0 ); + model->canFetchMore(QModelIndex()); + QVERIFY(model->columnCount(QModelIndex()) >= 0); QCOMPARE(model->data(QModelIndex()), QVariant()); fetchingMore = true; - model->fetchMore ( QModelIndex() ); + model->fetchMore(QModelIndex()); fetchingMore = false; - Qt::ItemFlags flags = model->flags ( QModelIndex() ); - QVERIFY( flags == Qt::ItemIsDropEnabled || flags == 0 ); - model->hasChildren ( QModelIndex() ); - model->hasIndex ( 0, 0 ); - model->headerData ( 0, Qt::Horizontal ); - model->index ( 0, 0 ); - model->itemData ( QModelIndex() ); + Qt::ItemFlags flags = model->flags(QModelIndex()); + QVERIFY(flags == Qt::ItemIsDropEnabled || flags == 0); + model->hasChildren(QModelIndex()); + model->hasIndex(0, 0); + model->headerData(0, Qt::Horizontal); + model->index(0, 0); + model->itemData(QModelIndex()); QVariant cache; - model->match ( QModelIndex(), -1, cache ); + model->match(QModelIndex(), -1, cache); model->mimeTypes(); QVERIFY(!model->parent(QModelIndex()).isValid()); - QVERIFY( model->rowCount() >= 0 ); + QVERIFY(model->rowCount() >= 0); QVariant variant; - model->setData ( QModelIndex(), variant, -1 ); - model->setHeaderData ( -1, Qt::Horizontal, QVariant() ); - model->setHeaderData ( 999999, Qt::Horizontal, QVariant() ); + model->setData(QModelIndex(), variant, -1); + model->setHeaderData(-1, Qt::Horizontal, QVariant()); + model->setHeaderData(999999, Qt::Horizontal, QVariant()); QMap<int, QVariant> roles; - model->sibling ( 0, 0, QModelIndex() ); - model->span ( QModelIndex() ); + model->sibling(0, 0, QModelIndex()); + model->span(QModelIndex()); model->supportedDropActions(); } @@ -142,19 +144,19 @@ void ModelTest::rowCount() { // qDebug() << "rc"; // check top row - QModelIndex topIndex = model->index ( 0, 0, QModelIndex() ); - int rows = model->rowCount ( topIndex ); - QVERIFY( rows >= 0 ); - if ( rows > 0 ) - QVERIFY( model->hasChildren ( topIndex ) ); - - QModelIndex secondLevelIndex = model->index ( 0, 0, topIndex ); - if ( secondLevelIndex.isValid() ) { // not the top level + QModelIndex topIndex = model->index(0, 0, QModelIndex()); + int rows = model->rowCount(topIndex); + QVERIFY(rows >= 0); + if (rows > 0) + QVERIFY(model->hasChildren(topIndex)); + + QModelIndex secondLevelIndex = model->index(0, 0, topIndex); + if (secondLevelIndex.isValid()) { // not the top level // check a row count where parent is valid - rows = model->rowCount ( secondLevelIndex ); - QVERIFY( rows >= 0 ); - if ( rows > 0 ) - QVERIFY( model->hasChildren ( secondLevelIndex ) ); + rows = model->rowCount(secondLevelIndex); + QVERIFY(rows >= 0); + if (rows > 0) + QVERIFY(model->hasChildren(secondLevelIndex)); } // The models rowCount() is tested more extensively in checkChildren(), @@ -167,13 +169,13 @@ void ModelTest::rowCount() void ModelTest::columnCount() { // check top row - QModelIndex topIndex = model->index ( 0, 0, QModelIndex() ); - QVERIFY( model->columnCount ( topIndex ) >= 0 ); + QModelIndex topIndex = model->index(0, 0, QModelIndex()); + QVERIFY(model->columnCount(topIndex) >= 0); // check a column count where parent is valid - QModelIndex childIndex = model->index ( 0, 0, topIndex ); - if ( childIndex.isValid() ) - QVERIFY( model->columnCount ( childIndex ) >= 0 ); + QModelIndex childIndex = model->index(0, 0, topIndex); + if (childIndex.isValid()) + QVERIFY(model->columnCount(childIndex) >= 0); // columnCount() is tested more extensively in checkChildren(), // but this catches the big mistakes @@ -186,19 +188,19 @@ void ModelTest::hasIndex() { // qDebug() << "hi"; // Make sure that invalid values returns an invalid index - QVERIFY( !model->hasIndex ( -2, -2 ) ); - QVERIFY( !model->hasIndex ( -2, 0 ) ); - QVERIFY( !model->hasIndex ( 0, -2 ) ); + QVERIFY(!model->hasIndex(-2, -2)); + QVERIFY(!model->hasIndex(-2, 0)); + QVERIFY(!model->hasIndex(0, -2)); int rows = model->rowCount(); int columns = model->columnCount(); // check out of bounds - QVERIFY( !model->hasIndex ( rows, columns ) ); - QVERIFY( !model->hasIndex ( rows + 1, columns + 1 ) ); + QVERIFY(!model->hasIndex(rows, columns)); + QVERIFY(!model->hasIndex(rows + 1, columns + 1)); - if ( rows > 0 ) - QVERIFY( model->hasIndex ( 0, 0 ) ); + if (rows > 0) + QVERIFY(model->hasIndex(0, 0)); // hasIndex() is tested more extensively in checkChildren(), // but this catches the big mistakes @@ -218,7 +220,7 @@ void ModelTest::index() int rows = model->rowCount(); int columns = model->columnCount(); - if ( rows == 0 ) + if (rows == 0) return; // Catch off by one errors @@ -226,8 +228,8 @@ void ModelTest::index() QVERIFY(model->index(0, 0).isValid()); // Make sure that the same index is *always* returned - QModelIndex a = model->index ( 0, 0 ); - QModelIndex b = model->index ( 0, 0 ); + QModelIndex a = model->index(0, 0); + QModelIndex b = model->index(0, 0); QCOMPARE(a, b); // index() is tested more extensively in checkChildren(), @@ -244,7 +246,7 @@ void ModelTest::parent() // when asked for the parent of an invalid index. QVERIFY(!model->parent(QModelIndex()).isValid()); - if ( model->rowCount() == 0 ) + if (model->rowCount() == 0) return; // Column 0 | Column 1 | @@ -254,29 +256,29 @@ void ModelTest::parent() // Common error test #1, make sure that a top level index has a parent // that is a invalid QModelIndex. - QModelIndex topIndex = model->index ( 0, 0, QModelIndex() ); + QModelIndex topIndex = model->index(0, 0, QModelIndex()); QVERIFY(!model->parent(topIndex).isValid()); // Common error test #2, make sure that a second level index has a parent // that is the first level index. - if ( model->rowCount ( topIndex ) > 0 ) { - QModelIndex childIndex = model->index ( 0, 0, topIndex ); + if (model->rowCount(topIndex) > 0) { + QModelIndex childIndex = model->index(0, 0, topIndex); QCOMPARE(model->parent(childIndex), topIndex); } // Common error test #3, the second column should NOT have the same children // as the first column in a row. // Usually the second column shouldn't have children. - QModelIndex topIndex1 = model->index ( 0, 1, QModelIndex() ); - if ( model->rowCount ( topIndex1 ) > 0 ) { - QModelIndex childIndex = model->index ( 0, 0, topIndex ); - QModelIndex childIndex1 = model->index ( 0, 0, topIndex1 ); - QVERIFY( childIndex != childIndex1 ); + QModelIndex topIndex1 = model->index(0, 1, QModelIndex()); + if (model->rowCount(topIndex1) > 0) { + QModelIndex childIndex = model->index(0, 0, topIndex); + QModelIndex childIndex1 = model->index(0, 0, topIndex1); + QVERIFY(childIndex != childIndex1); } // Full test, walk n levels deep through the model making sure that all // parent's children correctly specify their parent. - checkChildren ( QModelIndex() ); + checkChildren(QModelIndex()); } /*! @@ -293,73 +295,75 @@ void ModelTest::parent() found the basic bugs because it is easier to figure out the problem in those tests then this one. */ -void ModelTest::checkChildren ( const QModelIndex &parent, int currentDepth ) +void ModelTest::checkChildren(const QModelIndex &parent, int currentDepth) { // First just try walking back up the tree. QModelIndex p = parent; - while ( p.isValid() ) + while (p.isValid()) p = p.parent(); // For models that are dynamically populated - if ( model->canFetchMore ( parent ) ) { + if (model->canFetchMore(parent)) { fetchingMore = true; - model->fetchMore ( parent ); + model->fetchMore(parent); fetchingMore = false; } - int rows = model->rowCount ( parent ); - int columns = model->columnCount ( parent ); + int rows = model->rowCount(parent); + int columns = model->columnCount(parent); - if ( rows > 0 ) - QVERIFY( model->hasChildren ( parent ) ); + if (rows > 0) + QVERIFY(model->hasChildren(parent)); // Some further testing against rows(), columns(), and hasChildren() - QVERIFY( rows >= 0 ); - QVERIFY( columns >= 0 ); - if ( rows > 0 ) - QVERIFY( model->hasChildren ( parent ) ); + QVERIFY(rows >= 0); + QVERIFY(columns >= 0); + if (rows > 0) + QVERIFY(model->hasChildren(parent)); //qDebug() << "parent:" << model->data(parent).toString() << "rows:" << rows // << "columns:" << columns << "parent column:" << parent.column(); - const QModelIndex topLeftChild = model->index( 0, 0, parent ); + const QModelIndex topLeftChild = model->index(0, 0, parent); - QVERIFY( !model->hasIndex ( rows + 1, 0, parent ) ); - for ( int r = 0; r < rows; ++r ) { - if ( model->canFetchMore ( parent ) ) { + QVERIFY(!model->hasIndex(rows + 1, 0, parent)); + for (int r = 0; r < rows; ++r) { + if (model->canFetchMore(parent)) { fetchingMore = true; - model->fetchMore ( parent ); + model->fetchMore(parent); fetchingMore = false; } - QVERIFY( !model->hasIndex ( r, columns + 1, parent ) ); - for ( int c = 0; c < columns; ++c ) { - QVERIFY( model->hasIndex ( r, c, parent ) ); - QModelIndex index = model->index ( r, c, parent ); + QVERIFY(!model->hasIndex(r, columns + 1, parent)); + for (int c = 0; c < columns; ++c) { + QVERIFY(model->hasIndex(r, c, parent)); + QModelIndex index = model->index(r, c, parent); // rowCount() and columnCount() said that it existed... + if (!index.isValid()) + qWarning() << "Got invalid index at row=" << r << "col=" << c << "parent=" << parent; QVERIFY(index.isValid()); // index() should always return the same index when called twice in a row - QModelIndex modifiedIndex = model->index ( r, c, parent ); + QModelIndex modifiedIndex = model->index(r, c, parent); QCOMPARE(index, modifiedIndex); // Make sure we get the same index if we request it twice in a row - QModelIndex a = model->index ( r, c, parent ); - QModelIndex b = model->index ( r, c, parent ); + QModelIndex a = model->index(r, c, parent); + QModelIndex b = model->index(r, c, parent); QCOMPARE(a, b); { - const QModelIndex sibling = model->sibling( r, c, topLeftChild ); + const QModelIndex sibling = model->sibling(r, c, topLeftChild); QCOMPARE(index, sibling); } { - const QModelIndex sibling = topLeftChild.sibling( r, c ); + const QModelIndex sibling = topLeftChild.sibling(r, c); QCOMPARE(index, sibling); } // Some basic checking on the index that is returned QCOMPARE(index.model(), model); - QCOMPARE( index.row(), r ); - QCOMPARE( index.column(), c ); + QCOMPARE(index.row(), r); + QCOMPARE(index.column(), c); // While you can technically return a QVariant usually this is a sign // of a bug in data(). Disable if this really is ok in your model. // QVERIFY( model->data ( index, Qt::DisplayRole ).isValid() ); @@ -377,16 +381,16 @@ void ModelTest::checkChildren ( const QModelIndex &parent, int currentDepth ) } // Check that we can get back our real parent. - QCOMPARE( model->parent ( index ), parent ); + QCOMPARE(model->parent(index), parent); // recursively go down the children - if ( model->hasChildren ( index ) && currentDepth < 10 ) { + if (model->hasChildren(index) && currentDepth < 10) { //qDebug() << r << c << "has children" << model->rowCount(index); - checkChildren ( index, ++currentDepth ); + checkChildren(index, ++currentDepth); }/* else { if (currentDepth >= 10) qDebug() << "checked 10 deep"; };*/ // make sure that after testing the children that the index doesn't change. - QModelIndex newerIndex = model->index ( r, c, parent ); + QModelIndex newerIndex = model->index(r, c, parent); QCOMPARE(index, newerIndex); } } @@ -398,68 +402,61 @@ void ModelTest::checkChildren ( const QModelIndex &parent, int currentDepth ) void ModelTest::data() { // Invalid index should return an invalid qvariant - QVERIFY( !model->data ( QModelIndex() ).isValid() ); + QVERIFY(!model->data(QModelIndex()).isValid()); - if ( model->rowCount() == 0 ) + if (model->rowCount() == 0) return; // A valid index should have a valid QVariant data - QVERIFY( model->index ( 0, 0 ).isValid() ); + QVERIFY(model->index(0, 0).isValid()); // shouldn't be able to set data on an invalid index - QVERIFY( !model->setData ( QModelIndex(), QLatin1String ( "foo" ), Qt::DisplayRole ) ); + QVERIFY(!model->setData(QModelIndex(), QLatin1String("foo"), Qt::DisplayRole)); // General Purpose roles that should return a QString - QVariant variant = model->data ( model->index ( 0, 0 ), Qt::ToolTipRole ); - if ( variant.isValid() ) { - QVERIFY( variant.canConvert<QString>() ); - } - variant = model->data ( model->index ( 0, 0 ), Qt::StatusTipRole ); - if ( variant.isValid() ) { - QVERIFY( variant.canConvert<QString>() ); - } - variant = model->data ( model->index ( 0, 0 ), Qt::WhatsThisRole ); - if ( variant.isValid() ) { - QVERIFY( variant.canConvert<QString>() ); - } + QVariant variant = model->data(model->index(0, 0), Qt::ToolTipRole); + if (variant.isValid()) + QVERIFY(variant.canConvert<QString>()); + variant = model->data(model->index(0, 0), Qt::StatusTipRole); + if (variant.isValid()) + QVERIFY(variant.canConvert<QString>()); + variant = model->data(model->index(0, 0), Qt::WhatsThisRole); + if (variant.isValid()) + QVERIFY(variant.canConvert<QString>()); // General Purpose roles that should return a QSize - variant = model->data ( model->index ( 0, 0 ), Qt::SizeHintRole ); - if ( variant.isValid() ) { - QVERIFY( variant.canConvert<QSize>() ); - } + variant = model->data(model->index(0, 0), Qt::SizeHintRole); + if (variant.isValid()) + QVERIFY(variant.canConvert<QSize>()); // General Purpose roles that should return a QFont - QVariant fontVariant = model->data ( model->index ( 0, 0 ), Qt::FontRole ); - if ( fontVariant.isValid() ) { - QVERIFY( fontVariant.canConvert<QFont>() ); - } + QVariant fontVariant = model->data(model->index(0, 0), Qt::FontRole); + if (fontVariant.isValid()) + QVERIFY(fontVariant.canConvert<QFont>()); // Check that the alignment is one we know about - QVariant textAlignmentVariant = model->data ( model->index ( 0, 0 ), Qt::TextAlignmentRole ); - if ( textAlignmentVariant.isValid() ) { + QVariant textAlignmentVariant = model->data(model->index(0, 0), Qt::TextAlignmentRole); + if (textAlignmentVariant.isValid()) { Qt::Alignment alignment = textAlignmentVariant.value<Qt::Alignment>(); - QCOMPARE( alignment, ( alignment & ( Qt::AlignHorizontal_Mask | Qt::AlignVertical_Mask ) ) ); + QCOMPARE(alignment, (alignment & (Qt::AlignHorizontal_Mask | Qt::AlignVertical_Mask))); } // General Purpose roles that should return a QColor - QVariant colorVariant = model->data ( model->index ( 0, 0 ), Qt::BackgroundColorRole ); - if ( colorVariant.isValid() ) { - QVERIFY( colorVariant.canConvert<QColor>() ); - } + QVariant colorVariant = model->data(model->index(0, 0), Qt::BackgroundColorRole); + if (colorVariant.isValid()) + QVERIFY(colorVariant.canConvert<QColor>()); - colorVariant = model->data ( model->index ( 0, 0 ), Qt::TextColorRole ); - if ( colorVariant.isValid() ) { - QVERIFY( colorVariant.canConvert<QColor>() ); - } + colorVariant = model->data(model->index(0, 0), Qt::TextColorRole); + if (colorVariant.isValid()) + QVERIFY(colorVariant.canConvert<QColor>()); // Check that the "check state" is one we know about. - QVariant checkStateVariant = model->data ( model->index ( 0, 0 ), Qt::CheckStateRole ); - if ( checkStateVariant.isValid() ) { + QVariant checkStateVariant = model->data(model->index(0, 0), Qt::CheckStateRole); + if (checkStateVariant.isValid()) { int state = checkStateVariant.toInt(); - QVERIFY( state == Qt::Unchecked || - state == Qt::PartiallyChecked || - state == Qt::Checked ); + QVERIFY(state == Qt::Unchecked + || state == Qt::PartiallyChecked + || state == Qt::Checked); } } @@ -468,7 +465,7 @@ void ModelTest::data() \sa rowsInserted() */ -void ModelTest::rowsAboutToBeInserted ( const QModelIndex &parent, int start, int /* end */) +void ModelTest::rowsAboutToBeInserted(const QModelIndex &parent, int start, int /* end */) { // Q_UNUSED(end); // qDebug() << "rowsAboutToBeInserted" << "start=" << start << "end=" << end << "parent=" << model->data ( parent ).toString() @@ -476,10 +473,10 @@ void ModelTest::rowsAboutToBeInserted ( const QModelIndex &parent, int start, in // qDebug() << model->index(start-1, 0, parent) << model->data( model->index(start-1, 0, parent) ); Changing c; c.parent = parent; - c.oldSize = model->rowCount ( parent ); - c.last = model->data ( model->index ( start - 1, 0, parent ) ); - c.next = model->data ( model->index ( start, 0, parent ) ); - insert.push ( c ); + c.oldSize = model->rowCount(parent); + c.last = model->data(model->index(start - 1, 0, parent)); + c.next = model->data(model->index(start, 0, parent)); + insert.push(c); } /*! @@ -487,10 +484,10 @@ void ModelTest::rowsAboutToBeInserted ( const QModelIndex &parent, int start, in \sa rowsAboutToBeInserted() */ -void ModelTest::rowsInserted ( const QModelIndex & parent, int start, int end ) +void ModelTest::rowsInserted(const QModelIndex &parent, int start, int end) { Changing c = insert.pop(); - QCOMPARE(c.parent, parent); + QCOMPARE(parent, c.parent); // qDebug() << "rowsInserted" << "start=" << start << "end=" << end << "oldsize=" << c.oldSize // << "parent=" << model->data ( parent ).toString() << "current rowcount of parent=" << model->rowCount ( parent ); @@ -500,30 +497,30 @@ void ModelTest::rowsInserted ( const QModelIndex & parent, int start, int end ) // } // qDebug(); - QCOMPARE(c.oldSize + (end - start + 1), model->rowCount(parent)); - QCOMPARE(c.last, model->data(model->index(start - 1, 0, c.parent))); + QCOMPARE(model->rowCount(parent), c.oldSize + (end - start + 1)); + QCOMPARE(model->data(model->index(start - 1, 0, c.parent)), c.last); if (c.next != model->data(model->index(end + 1, 0, c.parent))) { qDebug() << start << end; - for (int i=0; i < model->rowCount(); ++i) + for (int i = 0; i < model->rowCount(); ++i) qDebug() << model->index(i, 0).data().toString(); qDebug() << c.next << model->data(model->index(end + 1, 0, c.parent)); } - QCOMPARE(c.next, model->data(model->index(end + 1, 0, c.parent))); + QCOMPARE(model->data(model->index(end + 1, 0, c.parent)), c.next); } void ModelTest::layoutAboutToBeChanged() { - for ( int i = 0; i < qBound ( 0, model->rowCount(), 100 ); ++i ) - changing.append ( QPersistentModelIndex ( model->index ( i, 0 ) ) ); + for (int i = 0; i < qBound(0, model->rowCount(), 100); ++i) + changing.append(QPersistentModelIndex(model->index(i, 0))); } void ModelTest::layoutChanged() { - for ( int i = 0; i < changing.count(); ++i ) { + for (int i = 0; i < changing.count(); ++i) { QPersistentModelIndex p = changing[i]; - QCOMPARE(QModelIndex(p), model->index(p.row(), p.column(), p.parent())); + QCOMPARE(model->index(p.row(), p.column(), p.parent()), QModelIndex(p)); } changing.clear(); } @@ -533,15 +530,15 @@ void ModelTest::layoutChanged() \sa rowsRemoved() */ -void ModelTest::rowsAboutToBeRemoved ( const QModelIndex &parent, int start, int end ) +void ModelTest::rowsAboutToBeRemoved(const QModelIndex &parent, int start, int end) { -qDebug() << "ratbr" << parent << start << end; + qDebug() << "ratbr" << parent << start << end; Changing c; c.parent = parent; - c.oldSize = model->rowCount ( parent ); - c.last = model->data ( model->index ( start - 1, 0, parent ) ); - c.next = model->data ( model->index ( end + 1, 0, parent ) ); - remove.push ( c ); + c.oldSize = model->rowCount(parent); + c.last = model->data(model->index(start - 1, 0, parent)); + c.next = model->data(model->index(end + 1, 0, parent)); + remove.push(c); } /*! @@ -549,14 +546,14 @@ qDebug() << "ratbr" << parent << start << end; \sa rowsAboutToBeRemoved() */ -void ModelTest::rowsRemoved ( const QModelIndex & parent, int start, int end ) +void ModelTest::rowsRemoved(const QModelIndex &parent, int start, int end) { - qDebug() << "rr" << parent << start << end; + qDebug() << "rr" << parent << start << end; Changing c = remove.pop(); - QCOMPARE(c.parent, parent); - QCOMPARE(c.oldSize - (end - start + 1), model->rowCount(parent)); - QCOMPARE(c.last, model->data(model->index(start - 1, 0, c.parent))); - QCOMPARE(c.next, model->data(model->index(start, 0, c.parent))); + QCOMPARE(parent, c.parent); + QCOMPARE(model->rowCount(parent), c.oldSize - (end - start + 1)); + QCOMPARE(model->data(model->index(start - 1, 0, c.parent)), c.last); + QCOMPARE(model->data(model->index(start, 0, c.parent)), c.next); } void ModelTest::dataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight) @@ -582,4 +579,3 @@ void ModelTest::headerDataChanged(Qt::Orientation orientation, int start, int en QVERIFY(start < itemCount); QVERIFY(end < itemCount); } - diff --git a/tests/auto/other/modeltest/modeltest.h b/tests/auto/other/modeltest/modeltest.h index 735a422729b..4676bf44346 100644 --- a/tests/auto/other/modeltest/modeltest.h +++ b/tests/auto/other/modeltest/modeltest.h @@ -26,7 +26,6 @@ ** ****************************************************************************/ - #ifndef MODELTEST_H #define MODELTEST_H @@ -36,48 +35,48 @@ class ModelTest : public QObject { - Q_OBJECT + Q_OBJECT public: - ModelTest( QAbstractItemModel *model, QObject *parent = 0 ); + ModelTest(QAbstractItemModel *model, QObject *parent = 0); private Q_SLOTS: - void nonDestructiveBasicTest(); - void rowCount(); - void columnCount(); - void hasIndex(); - void index(); - void parent(); - void data(); + void nonDestructiveBasicTest(); + void rowCount(); + void columnCount(); + void hasIndex(); + void index(); + void parent(); + void data(); protected Q_SLOTS: - void runAllTests(); - void layoutAboutToBeChanged(); - void layoutChanged(); - void rowsAboutToBeInserted( const QModelIndex &parent, int start, int end ); - void rowsInserted( const QModelIndex & parent, int start, int end ); - void rowsAboutToBeRemoved( const QModelIndex &parent, int start, int end ); - void rowsRemoved( const QModelIndex & parent, int start, int end ); - void dataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight); - void headerDataChanged(Qt::Orientation orientation, int start, int end); + void runAllTests(); + void layoutAboutToBeChanged(); + void layoutChanged(); + void rowsAboutToBeInserted(const QModelIndex &parent, int start, int end); + void rowsInserted(const QModelIndex &parent, int start, int end); + void rowsAboutToBeRemoved(const QModelIndex &parent, int start, int end); + void rowsRemoved(const QModelIndex &parent, int start, int end); + void dataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight); + void headerDataChanged(Qt::Orientation orientation, int start, int end); private: - void checkChildren( const QModelIndex &parent, int currentDepth = 0 ); + void checkChildren(const QModelIndex &parent, int currentDepth = 0); - QAbstractItemModel *model; + QAbstractItemModel *model; - struct Changing { - QModelIndex parent; - int oldSize; - QVariant last; - QVariant next; - }; - QStack<Changing> insert; - QStack<Changing> remove; + struct Changing { + QModelIndex parent; + int oldSize; + QVariant last; + QVariant next; + }; + QStack<Changing> insert; + QStack<Changing> remove; - bool fetchingMore; + bool fetchingMore; - QList<QPersistentModelIndex> changing; + QList<QPersistentModelIndex> changing; }; #endif diff --git a/tests/auto/other/modeltest/tst_modeltest.cpp b/tests/auto/other/modeltest/tst_modeltest.cpp index f81fefe9d10..e2d002844be 100644 --- a/tests/auto/other/modeltest/tst_modeltest.cpp +++ b/tests/auto/other/modeltest/tst_modeltest.cpp @@ -26,7 +26,6 @@ ** ****************************************************************************/ - #include <QtTest/QtTest> #include <QtGui/QtGui> #include <QtWidgets/QtWidgets> @@ -34,7 +33,6 @@ #include "modeltest.h" #include "dynamictreemodel.h" - class tst_ModelTest : public QObject { Q_OBJECT @@ -63,7 +61,7 @@ void tst_ModelTest::stringListModel() proxy.setSourceModel(&model); model.setStringList(QStringList() << "2" << "3" << "1"); - model.setStringList(QStringList() << "a" << "e" << "plop" << "b" << "c" ); + model.setStringList(QStringList() << "a" << "e" << "plop" << "b" << "c"); proxy.setDynamicSortFilter(true); proxy.setFilterRegExp(QRegExp("[^b]")); @@ -76,9 +74,8 @@ void tst_ModelTest::treeWidgetModel() ModelTest t1(widget.model()); QTreeWidgetItem *root = new QTreeWidgetItem(&widget, QStringList("root")); - for (int i = 0; i < 20; ++i) { + for (int i = 0; i < 20; ++i) new QTreeWidgetItem(root, QStringList(QString::number(i))); - } QTreeWidgetItem *remove = root->child(2); root->removeChild(remove); QTreeWidgetItem *parent = new QTreeWidgetItem(&widget, QStringList("parent")); @@ -90,10 +87,9 @@ void tst_ModelTest::treeWidgetModel() void tst_ModelTest::standardItemModel() { - QStandardItemModel model(10,10); + QStandardItemModel model(10, 10); QSortFilterProxyModel proxy; - ModelTest t1(&model); ModelTest t2(&proxy); @@ -105,8 +101,8 @@ void tst_ModelTest::standardItemModel() model.insertColumns(2, 5); model.removeColumns(4, 5); - model.insertRows(0,5, model.index(1,1)); - model.insertColumns(0,5, model.index(1,3)); + model.insertRows(0, 5, model.index(1, 1)); + model.insertColumns(0, 5, model.index(1, 3)); } void tst_ModelTest::testInsertThroughProxy() @@ -148,7 +144,9 @@ class AccessibleProxyModel : public QSortFilterProxyModel { Q_OBJECT public: - AccessibleProxyModel(QObject *parent = 0) : QSortFilterProxyModel(parent) {} + AccessibleProxyModel(QObject *parent = 0) : QSortFilterProxyModel(parent) + { + } QModelIndexList persistent() { @@ -160,14 +158,16 @@ class ObservingObject : public QObject { Q_OBJECT public: - ObservingObject(AccessibleProxyModel *proxy, QObject *parent = 0) - : QObject(parent) - , m_proxy(proxy) - , storePersistentFailureCount(0) - , checkPersistentFailureCount(0) + ObservingObject(AccessibleProxyModel *proxy, QObject *parent = 0) : + QObject(parent), + m_proxy(proxy), + storePersistentFailureCount(0), + checkPersistentFailureCount(0) { - connect(m_proxy, SIGNAL(rowsAboutToBeMoved(QModelIndex,int,int,QModelIndex,int)), SLOT(storePersistent())); - connect(m_proxy, SIGNAL(rowsMoved(QModelIndex,int,int,QModelIndex,int)), SLOT(checkPersistent())); + connect(m_proxy, SIGNAL(rowsAboutToBeMoved(QModelIndex,int,int,QModelIndex,int)), + SLOT(storePersistent())); + connect(m_proxy, SIGNAL(rowsMoved(QModelIndex,int,int,QModelIndex,int)), + SLOT(checkPersistent())); } public slots: @@ -195,7 +195,7 @@ public slots: void storePersistent() { // This method is called from rowsAboutToBeMoved. Persistent indexes should be valid - foreach(const QModelIndex &idx, m_persistentProxyIndexes) + foreach (const QModelIndex &idx, m_persistentProxyIndexes) if (!idx.isValid()) { qWarning("%s: persistentProxyIndexes contains invalid index", Q_FUNC_INFO); ++storePersistentFailureCount; @@ -233,7 +233,7 @@ public slots: } private: - AccessibleProxyModel *m_proxy; + AccessibleProxyModel *m_proxy; QList<QPersistentModelIndex> m_persistentSourceIndexes; QList<QPersistentModelIndex> m_persistentProxyIndexes; public: @@ -296,6 +296,5 @@ void tst_ModelTest::testResetThroughProxy() QCOMPARE(observer.checkPersistentFailureCount, 0); } - QTEST_MAIN(tst_ModelTest) #include "tst_modeltest.moc" diff --git a/tests/auto/other/qaccessibility/accessiblewidgets.h b/tests/auto/other/qaccessibility/accessiblewidgets.h index 35b1ec890ba..62aa38ff6c5 100644 --- a/tests/auto/other/qaccessibility/accessiblewidgets.h +++ b/tests/auto/other/qaccessibility/accessiblewidgets.h @@ -98,7 +98,7 @@ public: return 0; } CustomTextWidgetIface(CustomTextWidget *w): QAccessibleWidget(w) {} - void *interface_cast(QAccessible::InterfaceType t) { + void *interface_cast(QAccessible::InterfaceType t) override { if (t == QAccessible::TextInterface) return static_cast<QAccessibleTextInterface*>(this); return 0; @@ -112,19 +112,19 @@ public: return QAccessibleWidget::text(t); } - QString textBeforeOffset(int offset, QAccessible::TextBoundaryType boundaryType, int *startOffset, int *endOffset) const + QString textBeforeOffset(int offset, QAccessible::TextBoundaryType boundaryType, int *startOffset, int *endOffset) const override { if (offset == -2) offset = textWidget()->cursorPosition; return QAccessibleTextInterface::textBeforeOffset(offset, boundaryType, startOffset, endOffset); } - QString textAtOffset(int offset, QAccessible::TextBoundaryType boundaryType, int *startOffset, int *endOffset) const + QString textAtOffset(int offset, QAccessible::TextBoundaryType boundaryType, int *startOffset, int *endOffset) const override { if (offset == -2) offset = textWidget()->cursorPosition; return QAccessibleTextInterface::textAtOffset(offset, boundaryType, startOffset, endOffset); } - QString textAfterOffset(int offset, QAccessible::TextBoundaryType boundaryType, int *startOffset, int *endOffset) const + QString textAfterOffset(int offset, QAccessible::TextBoundaryType boundaryType, int *startOffset, int *endOffset) const override { if (offset == -2) offset = textWidget()->cursorPosition; diff --git a/tests/auto/sql/kernel/qsqldatabase/tst_qsqldatabase.cpp b/tests/auto/sql/kernel/qsqldatabase/tst_qsqldatabase.cpp index 8126e72ad25..a2e9140cc8d 100644 --- a/tests/auto/sql/kernel/qsqldatabase/tst_qsqldatabase.cpp +++ b/tests/auto/sql/kernel/qsqldatabase/tst_qsqldatabase.cpp @@ -188,6 +188,9 @@ private slots: void sqlite_enable_cache_mode_data() { generic_data("QSQLITE"); } void sqlite_enable_cache_mode(); + void sqlite_enableRegexp_data() { generic_data("QSQLITE"); } + void sqlite_enableRegexp(); + private: void createTestTables(QSqlDatabase db); void dropTestTables(QSqlDatabase db); @@ -2259,5 +2262,33 @@ void tst_QSqlDatabase::sqlite_enable_cache_mode() db2.close(); } +void tst_QSqlDatabase::sqlite_enableRegexp() +{ + QFETCH(QString, dbName); + QSqlDatabase db = QSqlDatabase::database(dbName); + CHECK_DATABASE(db); + if (db.driverName().startsWith("QSQLITE2")) + QSKIP("SQLite3 specific test"); + + db.close(); + db.setConnectOptions("QSQLITE_ENABLE_REGEXP"); + QVERIFY_SQL(db, open()); + + QSqlQuery q(db); + const QString tableName(qTableName("uint_test", __FILE__, db)); + QVERIFY_SQL(q, exec(QString("CREATE TABLE %1(text TEXT)").arg(tableName))); + QVERIFY_SQL(q, prepare(QString("INSERT INTO %1 VALUES(?)").arg(tableName))); + q.addBindValue("a0"); + QVERIFY_SQL(q, exec()); + q.addBindValue("a1"); + QVERIFY_SQL(q, exec()); + + QVERIFY_SQL(q, exec(QString("SELECT text FROM %1 WHERE text REGEXP 'a[^0]' " + "ORDER BY text").arg(tableName))); + QVERIFY_SQL(q, next()); + QCOMPARE(q.value(0).toString(), QString("a1")); + QFAIL_SQL(q, next()); +} + QTEST_MAIN(tst_QSqlDatabase) #include "tst_qsqldatabase.moc" diff --git a/tests/auto/tools/uic/tst_uic.cpp b/tests/auto/tools/uic/tst_uic.cpp index cf43cb02d38..85668c96d43 100644 --- a/tests/auto/tools/uic/tst_uic.cpp +++ b/tests/auto/tools/uic/tst_uic.cpp @@ -34,6 +34,7 @@ #include <QtCore/QByteArray> #include <QtCore/QLibraryInfo> #include <QtCore/QTemporaryDir> +#include <QtCore/QRegularExpression> #include <QtCore/QStandardPaths> class tst_uic : public QObject @@ -63,12 +64,12 @@ private: const QString m_command; QString m_baseline; QTemporaryDir m_generated; - QRegExp m_versionRegexp; + QRegularExpression m_versionRegexp; }; tst_uic::tst_uic() : m_command(QLibraryInfo::location(QLibraryInfo::BinariesPath) + QLatin1String("/uic")) - , m_versionRegexp(QLatin1String("Created by: Qt User Interface Compiler version [.\\d]{5,5}")) + , m_versionRegexp(QLatin1String("\\*\\* Created by: Qt User Interface Compiler version \\d{1,2}\\.\\d{1,2}\\.\\d{1,2}")) { } diff --git a/tests/auto/widgets/widgets/qopenglwidget/tst_qopenglwidget.cpp b/tests/auto/widgets/widgets/qopenglwidget/tst_qopenglwidget.cpp index e3e26d612f0..a1b585d0d33 100644 --- a/tests/auto/widgets/widgets/qopenglwidget/tst_qopenglwidget.cpp +++ b/tests/auto/widgets/widgets/qopenglwidget/tst_qopenglwidget.cpp @@ -64,6 +64,7 @@ void tst_QOpenGLWidget::create() { QScopedPointer<QOpenGLWidget> w(new QOpenGLWidget); QVERIFY(!w->isValid()); + QVERIFY(w->textureFormat() == 0); QSignalSpy frameSwappedSpy(w.data(), SIGNAL(frameSwapped())); w->show(); QTest::qWaitForWindowExposed(w.data()); @@ -73,6 +74,7 @@ void tst_QOpenGLWidget::create() QVERIFY(w->context()); QCOMPARE(w->context()->format(), w->format()); QVERIFY(w->defaultFramebufferObject() != 0); + QVERIFY(w->textureFormat() != 0); } class ClearWidget : public QOpenGLWidget, protected QOpenGLFunctions diff --git a/tests/auto/widgets/widgets/qprogressbar/tst_qprogressbar.cpp b/tests/auto/widgets/widgets/qprogressbar/tst_qprogressbar.cpp index 205ef349586..9f64335930d 100644 --- a/tests/auto/widgets/widgets/qprogressbar/tst_qprogressbar.cpp +++ b/tests/auto/widgets/widgets/qprogressbar/tst_qprogressbar.cpp @@ -45,6 +45,7 @@ private slots: void destroyIndeterminate(); void text(); void format(); + void setValueRepaint_data(); void setValueRepaint(); #ifndef Q_OS_MAC void setMinMaxRepaint(); @@ -191,21 +192,49 @@ void tst_QProgressBar::format() QCOMPARE(bar.text(), QString()); } +void tst_QProgressBar::setValueRepaint_data() +{ + QTest::addColumn<int>("min"); + QTest::addColumn<int>("max"); + QTest::addColumn<int>("increment"); + + auto add = [](int min, int max, int increment) { + QTest::addRow("%d-%d@%d", min, max, increment) << min << max << increment; + }; + + add(0, 10, 1); + + auto add_set = [=](int min, int max, int increment) { + // check corner cases, and adjacent values (to circumvent explicit checks for corner cases) + add(min, max, increment); + add(min + 1, max, increment); + add(min, max - 1, increment); + add(min + 1, max - 1, increment); + }; + + add_set(INT_MIN, INT_MAX, INT_MAX / 50 + 1); + add_set(0, INT_MAX, INT_MAX / 100 + 1); + add_set(INT_MIN, 0, INT_MAX / 100 + 1); +} + void tst_QProgressBar::setValueRepaint() { + QFETCH(int, min); + QFETCH(int, max); + QFETCH(int, increment); + ProgressBar pbar; - pbar.setMinimum(0); - pbar.setMaximum(10); + pbar.setMinimum(min); + pbar.setMaximum(max); pbar.setFormat("%v"); pbar.move(300, 300); pbar.show(); QVERIFY(QTest::qWaitForWindowExposed(&pbar)); QApplication::processEvents(); - for (int i = pbar.minimum(); i < pbar.maximum(); ++i) { + for (qint64 i = min; i < max; i += increment) { pbar.repainted = false; - pbar.setValue(i); - QTest::qWait(50); + pbar.setValue(int(i)); QTRY_VERIFY(pbar.repainted); } } |