Merge remote-tracking branch 'origin/5.10' into dev

Conflicts:
	src/plugins/platforms/windows/qwindowsmousehandler.cpp
	src/plugins/platforms/xcb/qxcbimage.cpp
	tests/auto/network/access/qnetworkreply/tst_qnetworkreply.cpp
	tests/manual/qtabletevent/regular_widgets/main.cpp

Done-with: Friedemann Kleint<Friedemann.Kleint@qt.io>
Done-with: Mårten Nordheim<marten.nordheim@qt.io>
Change-Id: I5b2499513a92c590ed0756f7d2e93c35a64b7f30
This commit is contained in:
Allan Sandfeld Jensen 2017-10-24 10:37:17 +02:00 committed by Liang Qi
commit fa9d12f4a2
141 changed files with 1586 additions and 891 deletions

1
.gitignore vendored
View File

@ -28,6 +28,7 @@
/src/corelib/global/qconfig_p.h
/bin/qt.conf
/bin/qmake
/bin/qvkgen
/qmake/qmake
qt*-config.h
qt*-config_p.h

259
dist/changes-5.9.2 vendored Normal file
View File

@ -0,0 +1,259 @@
Qt 5.9.2 is a bug-fix release. It maintains both forward and backward
compatibility (source and binary) with Qt 5.9.0.
For more details, refer to the online documentation included in this
distribution. The documentation is also available online:
http://doc.qt.io/qt-5/index.html
The Qt version 5.9 series is binary compatible with the 5.8.x series.
Applications compiled for 5.8 will continue to run with 5.9.
Some of the changes listed in this file include issue tracking numbers
corresponding to tasks in the Qt Bug Tracker:
https://bugreports.qt.io/
Each of these identifiers can be entered in the bug tracker to obtain more
information about a particular change.
****************************************************************************
* Important Behavior Changes *
****************************************************************************
- Building examples inside the Qt source tree while not building Qt itself
is rejected now, because this can cause hard to debug configuration
issues. If building isolated examples is needed, you may still use shadow
builds.
- This version of Qt restores compatibility with pre-5.9.0 calculation of
QCryptographicHash algorithms that were labelled "Sha3_nnn": that is,
applications compiled with old versions of Qt will continue using the
Keccak algorithm. Applications recompiled with this version will use
SHA-3, unless QT_SHA3_KECCAK_COMPAT is #define'd prior to #include
<QCryptographicHash>.
****************************************************************************
* General Notes *
****************************************************************************
Binary Compatibility Note
-------------------------
- The variable QOperatingSystemVersion::AndroidOreo was added in this
release. Code that uses this variable will not run under Qt 5.9.1. If
backwards compatibility is desired, use instead
QOperatingSystemVersion(QOperatingSystemVersion::Android, 8)
[This is similar to QOperatingSystemVersion::MacOSHighSierra added in
5.9.1]
- This version of Qt changes the values assigned to enumerations
QCryptographicHash::Sha3_nnn. Applications compiled with this version and
using those enumerations will not work with Qt 5.9.0 and 5.9.1, unless
QT_SHA3_KECCAK_COMPAT is defined.
Deprecation Notice
------------------
- Starting with Qt 5.10, IPv6 support will be mandatory for all platforms.
Systems without proper IPv6 support, such as the getaddrinfo() function
or the proper socket address structures, will not be able to build
QtNetwork anymore.
Third-Party Code
----------------
- [QTBUG-31020] zlib was updated to version 1.2.11.
- libpng was updated to version 1.6.32
****************************************************************************
* Library *
****************************************************************************
QtCore
------
- [QTBUG-61350] Fixed the conversion from string to double of the strings
"0E+1" and "0E-1" (with capital E), which QString::toDouble(),
QByteArray::toDouble() and similar functions reported as invalid.
- QFile:
* [QTBUG-57023] Reverted an incorrect change from Qt 5.9.0 that forbade
the creation and access to Alternate Data Streams on NTFS on Windows.
This means that file names containing a colon (':') are allowed again,
but note that they are not regular files.
- QFileInfo:
* [QTBUG-62802] Relative symbolic links on Windows are now resolved to
their absolute path by symLinkTarget().
- QFileSystemWatcher:
* [QTBUG-62242] Fixed a crash on Windows if this class was instantiated
before QCoreApplication was created.
* [QTBUG-61792] Fixed an issue on Windows that would cause this class not
to monitor files properly if the directory containing the monitored
files was added to the list of watched paths after the files.
- QLocale:
* [QTBUG-53565] Fixed the conversion of QTime to string form and parsing
from string form to always treat the value as the decimal fraction of
the seconds component. That is, the string format ".z" produces/parses
".2" for 200 milliseconds and ".002" for 2 milliseconds. Use of "z" or
"zzz" is discouraged outside decimal fractions to avoid surprises.
* [QTBUG-61949] Fixed bcp57Name() to return "en" for the QLocale::c()
locale. Previously, it returned "C", which is not a valid BCP47
language tag.
- QProcess:
* [QTBUG-61634] Added a workaround for a rare race-condition bug in
some C libraries that caused the child process started by QProcess to
hang after trying to launch a non-existent executable or change to a
non-existent directory.
* [QTBUG-62584] Fixed a race-condition bug that could cause
waitForXxx() functions to hang forever if a slot triggered by that
function futher started a nested event loop.
- QTimeZone:
* [QTBUG-63205] Fixed a bug that would cause QTimeZone to mis-parse
timezone files on Unix systems if they contained leap second
information.
- QVariant:
* [QTBUG-61471] Fixed QVariant to actually perform the conversions
between QVariantHash and QVariantMap in the respective .toHash() and
.toMap() functions. QVariant already reported true in .canConvert()
between those two types.
QtDBus
------
- [QTBUG-62284] Fixed a race condition in QDBusAbstractInterface that
could cause the class to never see the notification that the remote
service became available and cause isValid() to change to true.
QtGui
-----
- Text:
* [QTBUG-61520] Fixed matching of non-regular font weights for
application fonts on macOS.
QtNetwork
---------
- [QTBUG-61692] Fixed the handling of application-wide proxy settings (set
with QNetworkProxy): previously, QTcpSocket would directly fall back to
the system settings if the object-specific setting was
QNetworkProxy::DefaultProxy.
- QLocalSocket:
* [QTBUG-61643] Fixed an issue with Qt pipe-handling code that could
cause deadlocks on Windows, most often if the QLocalSocket object tried
to wait for more data during application shutdown.
QtTest
------
- Added flowId to messages when logging in TeamCity format. FlowId is used
to distinguish logging from multiple processes running in parallel.
QtWidgets
---------
- Android:
* [QTBUG-48639] Fixed label duplication for buttons when using style
sheets with the Android style.
- QLineEdit:
* [QTBUG-60319] Fixed behavior of the ImSurroundingText query.
Previously, it returned a masked text whose length may be less than
the cursor position. Now it returns unmasked text, so the text length
is always greater than or equal to the cursor position.
- QMenu:
* [QTBUG-59794] Fixed menu size issue when using high DPI on
multi-screen system.
****************************************************************************
* Compiler-specific Changes *
****************************************************************************
clang
-----
- [QTBUG-61840][QTBUG-62085] Fixed an issue that caused recent Clang
versions to print a warning about [[nodiscard].
Visual Studio
-------------
- [QTBUG-61902] Changed Qt uses of certain C++ Standard Library functions
that Visual Studio warns about. Now Qt public headers call
Microsoft-specific versions that do not produce warnings.
****************************************************************************
* Platform-specific Changes *
****************************************************************************
macOS
-----
- [QTBUG-59222] Switching focus objects inside a top level window while
composing text using dead keys or input method events would leave the
application in an inconsistent state. The composition now automatically
cancels when the focus object changes.
Windows
-------
- [QTBUG-57916] Fixed build with ANGLE and newer MinGW versions.
- [QTBUG-62083] Fixed Qt trying to steal certain events from user windows if
the event ID was WM_USER.
****************************************************************************
* Tools *
****************************************************************************
configure & build system
------------------------
- [QTBUG-35928][QTBUG-41908][Apple] Qt can now be built using just the
Xcode Command Line Tools, without needing to install the full Xcode IDE.
- [QTBUG-55755][Windows] All Qt .exe files now include meta information,
like .dll files already did.
- [QTBUG-58012] (Re-)added a way to specify alternative ICU libraries.
- [QTBUG-62150] Fixed detection of ICU in static builds.
- [QTBUG-53537][X11] Added missing detection of Xinerama.
- [QTBUG-61731][X11] Fixed detection of AT-SPI, allowing accessibility
support to be built again.
- [X11] Fixed detection of x11-xcb with pkg-config.
- [CMake] All Qt module defines are now propagated to the config files.
qmake
-----
- [QTBUG-31034] Added qmake feature and configure option to use ccache.
- [QTBUG-48342] Fixed generation of extraneous slashes in -project mode.
- [QTBUG-55633] Fixed misparsing of some string literal concatenations
as C++11 raw strings. This affects dependency scanning.
- [QTBUG-59301][Xcode] Fixed duplicate references in project files.
- [QTBUG-59827][nmake] The 'clean' target now deletes backup files of
MSVC manifests.
- [QTBUG-60455][Android] libc++ is now used instead of libstdc++ when
building with the android-clang mkspec.
- [QTBUG-60430][iOS] Fixed handling of the deprecated variable
QMAKE_IOS_TARGETED_DEVICE_FAMILY.
- [QTBUG-60899][WinRT] Fixed capability handling for Win10 targets.
- [WinRT] Added support for new Win10 capabilities.
- [QTBUG-61335][MinGW] Worked around LTO+MRI linker issue when cross-
building from Linux.
- [QTBUG-61411][Windows] _UNICODE is now defined, consistently with VS.
- [QTBUG-61688][MSVC] Fixed compilation of precompiled headers with
CONFIG+=silent. Done by removing redundant progress messages.
- [QTBUG-61690][QTBUG-61735] Fixed detection of compiler default search
paths for various compilers and platforms.
- [QTBUG-63197][Windows] Fixed moc'ing in a build directory with spaces
when INCLUDEPATH contains 40+ entries.
- [Android] Fixed building with ndkr16+ by using unified headers.
- [Windows] Fixed repeated installation of read-only files.
- [VS] Fixed deployment rules in created solution files.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.7 KiB

After

Width:  |  Height:  |  Size: 30 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 19 KiB

After

Width:  |  Height:  |  Size: 39 KiB

View File

@ -60,8 +60,8 @@
the address book.
\c TableModel is a subclass of QAbstractTableModel that provides
the standard model/view API to access data. It also holds a
QList of \l{QPair}s corresponding to the contacts added.
the standard model/view API to access data. It holds a list of
added contacts.
However, this data is not all visible in a single tab. Instead,
QTableView is used to provide 9 different views of the same
data, according to the alphabet groups.
@ -80,7 +80,7 @@
\section1 TableModel Class Definition
The \c TableModel class provides standard API to access data in
its QList of \l{QPair}s by subclassing QAbstractTableModel. The
its list of contacts by subclassing QAbstractTableModel. The
basic functions that must be implemented in order to do so are:
\c rowCount(), \c columnCount(), \c data(), \c headerData().
For TableModel to be editable, it has to provide implementations
@ -90,15 +90,14 @@
\snippet itemviews/addressbook/tablemodel.h 0
Two constructors are used, a default constructor which uses
\c TableModel's own \c {QList<QPair<QString, QString>>} and one
that takes \c {QList<QPair<QString, QString>} as an argument,
for convenience.
\c TableModel's own \c {QList<Contact>} and one that takes
\c {QList<Contact>} as an argument, for convenience.
\section1 TableModel Class Implementation
We implement the two constructors as defined in the header file.
The second constructor initializes the list of pairs in the
The second constructor initializes the list of contacts in the
model, with the parameter value.
\snippet itemviews/addressbook/tablemodel.cpp 0
@ -117,7 +116,7 @@
The \c data() function returns either a \b Name or
\b {Address}, based on the contents of the model index
supplied. The row number stored in the model index is used to
reference an item in the list of pairs. Selection is handled
reference an item in the list of contacts. Selection is handled
by the QItemSelectionModel, which will be explained with
\c AddressWidget.
@ -164,12 +163,11 @@
use the editing features of the QTableView object, we enable
them here so that we can reuse the model in other programs.
The last function in \c {TableModel}, \c getList() returns the
QList<QPair<QString, QString>> object that holds all the
contacts in the address book. We use this function later to
obtain the list of contacts to check for existing entries, write
the contacts to a file and read them back. Further explanation is
given with \c AddressWidget.
The last function in \c {TableModel}, \c getContacts() returns the
QList<Contact> object that holds all the contacts in the address
book. We use this function later to obtain the list of contacts to
check for existing entries, write the contacts to a file and read
them back. Further explanation is given with \c AddressWidget.
\snippet itemviews/addressbook/tablemodel.cpp 8
@ -222,11 +220,12 @@
The QItemSelectionModel class provides a
\l{QItemSelectionModel::selectionChanged()}{selectionChanged}
signal that is connected to \c{AddressWidget}'s
\c selectionChanged() signal. This signal to signal connection
is necessary to enable the \uicontrol{Edit Entry...} and
\uicontrol{Remove Entry} actions in \c MainWindow's Tools menu. This
connection is further explained in \c MainWindow's
implementation.
\c selectionChanged() signal. We also connect
QTabWidget::currentChanged() signal to the lambda expression which
emits \c{AddressWidget}'s \c selectionChanged() as well. These
connections are necessary to enable the \uicontrol{Edit Entry...} and
\uicontrol{Remove Entry} actions in \c MainWindow's Tools menu.
It is further explained in \c MainWindow's implementation.
Each table view in the address book is added as a tab to the
QTabWidget with the relevant label, obtained from the QStringList
@ -250,7 +249,7 @@
Basic validation is done in the second \c addEntry() function to
prevent duplicate entries in the address book. As mentioned with
\c TableModel, this is part of the reason why we require the
getter method \c getList().
getter method \c getContacts().
\snippet itemviews/addressbook/addresswidget.cpp 3
@ -292,7 +291,7 @@
The \c writeToFile() function is used to save a file containing
all the contacts in the address book. The file is saved in a
custom \c{.dat} format. The contents of the QList of \l{QPair}s
custom \c{.dat} format. The contents of the list of contacts
are written to \c file using QDataStream. If the file cannot be
opened, a QMessageBox is displayed with the related error message.
@ -301,7 +300,7 @@
The \c readFromFile() function loads a file containing all the
contacts in the address book, previously saved using
\c writeToFile(). QDataStream is used to read the contents of a
\c{.dat} file into a list of pairs and each of these is added
\c{.dat} file into a list of contacts and each of these is added
using \c addEntry().
\snippet itemviews/addressbook/addresswidget.cpp 7

View File

@ -62,7 +62,7 @@ QT_END_NAMESPACE
class DragWidget : public QFrame
{
public:
DragWidget(QWidget *parent = 0);
explicit DragWidget(QWidget *parent = nullptr);
protected:
void dragEnterEvent(QDragEnterEvent *event) override;

View File

@ -123,7 +123,7 @@ void DragWidget::dropEvent(QDropEvent *event)
hotSpot.setY(hotSpotPos.last().toInt());
}
foreach (const QString &piece, pieces) {
for (const QString &piece : pieces) {
QLabel *newLabel = createDragLabel(piece, this);
newLabel->move(position - hotSpot);
newLabel->show();
@ -141,7 +141,7 @@ void DragWidget::dropEvent(QDropEvent *event)
} else {
event->ignore();
}
foreach (QWidget *widget, findChildren<QWidget *>()) {
for (QWidget *widget : findChildren<QWidget *>()) {
if (!widget->isVisible())
widget->deleteLater();
}

View File

@ -61,7 +61,7 @@ QT_END_NAMESPACE
class DragWidget : public QWidget
{
public:
DragWidget(QWidget *parent = 0);
explicit DragWidget(QWidget *parent = nullptr);
protected:
void dragEnterEvent(QDragEnterEvent *event) override;

View File

@ -63,13 +63,13 @@ class DropArea : public QLabel
Q_OBJECT
public:
DropArea(QWidget *parent = 0);
explicit DropArea(QWidget *parent = nullptr);
public slots:
void clear();
signals:
void changed(const QMimeData *mimeData = 0);
void changed(const QMimeData *mimeData = nullptr);
//! [DropArea header part1]
//! [DropArea header part2]

View File

@ -88,8 +88,8 @@ DropSiteWindow::DropSiteWindow()
buttonBox->addButton(clearButton, QDialogButtonBox::ActionRole);
buttonBox->addButton(quitButton, QDialogButtonBox::RejectRole);
connect(quitButton, &QAbstractButton::pressed, this, &QWidget::close);
connect(clearButton, &QAbstractButton::pressed, dropArea, &DropArea::clear);
connect(quitButton, &QAbstractButton::clicked, this, &QWidget::close);
connect(clearButton, &QAbstractButton::clicked, dropArea, &DropArea::clear);
//! [constructor part4]
//! [constructor part5]
@ -113,7 +113,7 @@ void DropSiteWindow::updateFormatsTable(const QMimeData *mimeData)
//! [updateFormatsTable() part1]
//! [updateFormatsTable() part2]
foreach (QString format, mimeData->formats()) {
for (const QString &format : mimeData->formats()) {
QTableWidgetItem *formatItem = new QTableWidgetItem(format);
formatItem->setFlags(Qt::ItemIsEnabled);
formatItem->setTextAlignment(Qt::AlignTop | Qt::AlignLeft);

View File

@ -167,7 +167,7 @@ void DragWidget::dropEvent(QDropEvent *event)
QString::SkipEmptyParts);
QPoint position = event->pos();
foreach (const QString &piece, pieces) {
for (const QString &piece : pieces) {
DragLabel *newLabel = new DragLabel(piece, this);
newLabel->move(position);
newLabel->show();

View File

@ -62,7 +62,7 @@ QT_END_NAMESPACE
class DragWidget : public QWidget
{
public:
DragWidget(QWidget *parent = 0);
explicit DragWidget(QWidget *parent = nullptr);
protected:
void dragEnterEvent(QDragEnterEvent *event) override;

View File

@ -48,10 +48,10 @@
**
****************************************************************************/
#include <QApplication>
#include "mainwindow.h"
#include <QApplication>
int main(int argc, char *argv[])
{
Q_INIT_RESOURCE(puzzle);

View File

@ -67,12 +67,19 @@ MainWindow::MainWindow(QWidget *parent)
void MainWindow::openImage()
{
const QString fileName =
QFileDialog::getOpenFileName(this, tr("Open Image"), QString(),
tr("Image Files (*.png *.jpg *.bmp)"));
if (!fileName.isEmpty())
loadImage(fileName);
const QString directory =
QStandardPaths::standardLocations(QStandardPaths::PicturesLocation).value(0, QDir::homePath());
QFileDialog dialog(this, tr("Open Image"), directory);
dialog.setAcceptMode(QFileDialog::AcceptOpen);
dialog.setFileMode(QFileDialog::ExistingFile);
QStringList mimeTypeFilters;
for (const QByteArray &mimeTypeName : QImageReader::supportedMimeTypes())
mimeTypeFilters.append(mimeTypeName);
mimeTypeFilters.sort();
dialog.setMimeTypeFilters(mimeTypeFilters);
dialog.selectMimeTypeFilter("image/jpeg");
if (dialog.exec() == QDialog::Accepted)
loadImage(dialog.selectedFiles().constFirst());
}
void MainWindow::loadImage(const QString &fileName)
@ -101,8 +108,8 @@ void MainWindow::setCompleted()
void MainWindow::setupPuzzle()
{
int size = qMin(puzzleImage.width(), puzzleImage.height());
puzzleImage = puzzleImage.copy((puzzleImage.width() - size)/2,
(puzzleImage.height() - size)/2, size, size).scaled(puzzleWidget->width(),
puzzleImage = puzzleImage.copy((puzzleImage.width() - size) / 2,
(puzzleImage.height() - size) / 2, size, size).scaled(puzzleWidget->width(),
puzzleWidget->height(), Qt::IgnoreAspectRatio, Qt::SmoothTransformation);
piecesList->clear();

View File

@ -51,8 +51,8 @@
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QPixmap>
#include <QMainWindow>
#include <QPixmap>
class PiecesList;
class PuzzleWidget;
@ -65,7 +65,7 @@ class MainWindow : public QMainWindow
Q_OBJECT
public:
MainWindow(QWidget *parent = 0);
explicit MainWindow(QWidget *parent = nullptr);
void loadImage(const QString &path);
public slots:

View File

@ -101,7 +101,7 @@ void PiecesList::dropEvent(QDropEvent *event)
}
}
void PiecesList::addPiece(QPixmap pixmap, QPoint location)
void PiecesList::addPiece(const QPixmap &pixmap, const QPoint &location)
{
QListWidgetItem *pieceItem = new QListWidgetItem(this);
pieceItem->setIcon(QIcon(pixmap));

View File

@ -58,8 +58,8 @@ class PiecesList : public QListWidget
Q_OBJECT
public:
explicit PiecesList(int pieceSize, QWidget *parent = 0);
void addPiece(QPixmap pixmap, QPoint location);
explicit PiecesList(int pieceSize, QWidget *parent = nullptr);
void addPiece(const QPixmap &pixmap, const QPoint &location);
static QString puzzleMimeType() { return QStringLiteral("image/x-puzzle-piece"); }

View File

@ -66,9 +66,7 @@ PuzzleWidget::PuzzleWidget(int imageSize, QWidget *parent)
void PuzzleWidget::clear()
{
pieceLocations.clear();
piecePixmaps.clear();
pieceRects.clear();
pieces.clear();
highlightedRect = QRect();
inPlace = 0;
update();
@ -95,7 +93,7 @@ void PuzzleWidget::dragMoveEvent(QDragMoveEvent *event)
QRect updateRect = highlightedRect.united(targetSquare(event->pos()));
if (event->mimeData()->hasFormat(PiecesList::puzzleMimeType())
&& pieceRects.indexOf(targetSquare(event->pos())) == -1) {
&& findPiece(targetSquare(event->pos())) == -1) {
highlightedRect = targetSquare(event->pos());
event->setDropAction(Qt::MoveAction);
@ -111,26 +109,23 @@ void PuzzleWidget::dragMoveEvent(QDragMoveEvent *event)
void PuzzleWidget::dropEvent(QDropEvent *event)
{
if (event->mimeData()->hasFormat(PiecesList::puzzleMimeType())
&& pieceRects.indexOf(targetSquare(event->pos())) == -1) {
&& findPiece(targetSquare(event->pos())) == -1) {
QByteArray pieceData = event->mimeData()->data(PiecesList::puzzleMimeType());
QDataStream dataStream(&pieceData, QIODevice::ReadOnly);
QRect square = targetSquare(event->pos());
QPixmap pixmap;
QPoint location;
dataStream >> pixmap >> location;
Piece piece;
piece.rect = targetSquare(event->pos());
dataStream >> piece.pixmap >> piece.location;
pieceLocations.append(location);
piecePixmaps.append(pixmap);
pieceRects.append(square);
pieces.append(piece);
highlightedRect = QRect();
update(square);
update(piece.rect);
event->setDropAction(Qt::MoveAction);
event->accept();
if (location == QPoint(square.x()/pieceSize(), square.y()/pieceSize())) {
if (piece.location == piece.rect.topLeft() / pieceSize()) {
inPlace++;
if (inPlace == 25)
emit puzzleCompleted();
@ -141,21 +136,26 @@ void PuzzleWidget::dropEvent(QDropEvent *event)
}
}
int PuzzleWidget::findPiece(const QRect &pieceRect) const
{
for (int i = 0, size = pieces.size(); i < size; ++i) {
if (pieces.at(i).rect == pieceRect)
return i;
}
return -1;
}
void PuzzleWidget::mousePressEvent(QMouseEvent *event)
{
QRect square = targetSquare(event->pos());
int found = pieceRects.indexOf(square);
const int found = findPiece(square);
if (found == -1)
return;
QPoint location = pieceLocations[found];
QPixmap pixmap = piecePixmaps[found];
pieceLocations.removeAt(found);
piecePixmaps.removeAt(found);
pieceRects.removeAt(found);
Piece piece = pieces.takeAt(found);
if (location == QPoint(square.x()/pieceSize(), square.y()/pieceSize()))
if (piece.location == square.topLeft() / pieceSize())
inPlace--;
update(square);
@ -163,7 +163,7 @@ void PuzzleWidget::mousePressEvent(QMouseEvent *event)
QByteArray itemData;
QDataStream dataStream(&itemData, QIODevice::WriteOnly);
dataStream << pixmap << location;
dataStream << piece.pixmap << piece.location;
QMimeData *mimeData = new QMimeData;
mimeData->setData(PiecesList::puzzleMimeType(), itemData);
@ -171,23 +171,20 @@ void PuzzleWidget::mousePressEvent(QMouseEvent *event)
QDrag *drag = new QDrag(this);
drag->setMimeData(mimeData);
drag->setHotSpot(event->pos() - square.topLeft());
drag->setPixmap(pixmap);
drag->setPixmap(piece.pixmap);
if (!(drag->exec(Qt::MoveAction) == Qt::MoveAction)) {
pieceLocations.insert(found, location);
piecePixmaps.insert(found, pixmap);
pieceRects.insert(found, square);
if (drag->exec(Qt::MoveAction) != Qt::MoveAction) {
pieces.insert(found, piece);
update(targetSquare(event->pos()));
if (location == QPoint(square.x()/pieceSize(), square.y()/pieceSize()))
if (piece.location == square.topLeft() / pieceSize())
inPlace++;
}
}
void PuzzleWidget::paintEvent(QPaintEvent *event)
{
QPainter painter;
painter.begin(this);
QPainter painter(this);
painter.fillRect(event->rect(), Qt::white);
if (highlightedRect.isValid()) {
@ -196,14 +193,14 @@ void PuzzleWidget::paintEvent(QPaintEvent *event)
painter.drawRect(highlightedRect.adjusted(0, 0, -1, -1));
}
for (int i = 0; i < pieceRects.size(); ++i)
painter.drawPixmap(pieceRects[i], piecePixmaps[i]);
painter.end();
for (const Piece &piece : pieces)
painter.drawPixmap(piece.rect, piece.pixmap);
}
const QRect PuzzleWidget::targetSquare(const QPoint &position) const
{
return QRect(position.x()/pieceSize() * pieceSize(), position.y()/pieceSize() * pieceSize(), pieceSize(), pieceSize());
return QRect(position / pieceSize() * pieceSize(),
QSize(pieceSize(), pieceSize()));
}
int PuzzleWidget::pieceSize() const

View File

@ -51,9 +51,9 @@
#ifndef PUZZLEWIDGET_H
#define PUZZLEWIDGET_H
#include <QList>
#include <QPoint>
#include <QPixmap>
#include <QVector>
#include <QWidget>
QT_BEGIN_NAMESPACE
@ -67,7 +67,7 @@ class PuzzleWidget : public QWidget
Q_OBJECT
public:
explicit PuzzleWidget(int imageSize, QWidget *parent = 0);
explicit PuzzleWidget(int imageSize, QWidget *parent = nullptr);
void clear();
int pieceSize() const;
@ -85,11 +85,16 @@ protected:
void paintEvent(QPaintEvent *event) override;
private:
struct Piece {
QPixmap pixmap;
QRect rect;
QPoint location;
};
int findPiece(const QRect &pieceRect) const;
const QRect targetSquare(const QPoint &position) const;
QList<QPixmap> piecePixmaps;
QList<QRect> pieceRects;
QList<QPoint> pieceLocations;
QVector<Piece> pieces;
QRect highlightedRect;
int inPlace;
int m_ImageSize;

View File

@ -85,10 +85,7 @@ void AddressWidget::showAddEntryDialog()
//! [3]
void AddressWidget::addEntry(QString name, QString address)
{
QList<QPair<QString, QString> >list = table->getList();
QPair<QString, QString> pair(name, address);
if (!list.contains(pair)) {
if (!table->getContacts().contains({ name, address })) {
table->insertRows(0, 1, QModelIndex());
QModelIndex index = table->index(0, 0, QModelIndex());
@ -195,6 +192,12 @@ void AddressWidget::setupTabs()
&QItemSelectionModel::selectionChanged,
this, &AddressWidget::selectionChanged);
connect(this, &QTabWidget::currentChanged, this, [this](int tabIndex) {
auto *tableView = qobject_cast<QTableView *>(widget(tabIndex));
if (tableView)
emit selectionChanged(tableView->selectionModel()->selection());
});
addTab(tableView, str);
}
}
@ -211,18 +214,16 @@ void AddressWidget::readFromFile(const QString &fileName)
return;
}
QList<QPair<QString, QString> > pairs = table->getList();
QList<Contact> contacts;
QDataStream in(&file);
in >> pairs;
in >> contacts;
if (pairs.isEmpty()) {
if (contacts.isEmpty()) {
QMessageBox::information(this, tr("No contacts in file"),
tr("The file you are attempting to open contains no contacts."));
} else {
for (int i=0; i<pairs.size(); ++i) {
QPair<QString, QString> p = pairs.at(i);
addEntry(p.first, p.second);
}
for (const auto &contact: qAsConst(contacts))
addEntry(contact.name, contact.address);
}
}
//! [7]
@ -237,8 +238,7 @@ void AddressWidget::writeToFile(const QString &fileName)
return;
}
QList<QPair<QString, QString> > pairs = table->getList();
QDataStream out(&file);
out << pairs;
out << table->getContacts();
}
//! [6]

View File

@ -56,10 +56,10 @@ TableModel::TableModel(QObject *parent)
{
}
TableModel::TableModel(QList<QPair<QString, QString> > pairs, QObject *parent)
TableModel::TableModel(QList<Contact> contacts, QObject *parent)
: QAbstractTableModel(parent)
, contacts(contacts)
{
listOfPairs = pairs;
}
//! [0]
@ -67,7 +67,7 @@ TableModel::TableModel(QList<QPair<QString, QString> > pairs, QObject *parent)
int TableModel::rowCount(const QModelIndex &parent) const
{
Q_UNUSED(parent);
return listOfPairs.size();
return contacts.size();
}
int TableModel::columnCount(const QModelIndex &parent) const
@ -83,16 +83,16 @@ QVariant TableModel::data(const QModelIndex &index, int role) const
if (!index.isValid())
return QVariant();
if (index.row() >= listOfPairs.size() || index.row() < 0)
if (index.row() >= contacts.size() || index.row() < 0)
return QVariant();
if (role == Qt::DisplayRole) {
QPair<QString, QString> pair = listOfPairs.at(index.row());
const auto &contact = contacts.at(index.row());
if (index.column() == 0)
return pair.first;
return contact.name;
else if (index.column() == 1)
return pair.second;
return contact.address;
}
return QVariant();
}
@ -126,10 +126,8 @@ bool TableModel::insertRows(int position, int rows, const QModelIndex &index)
Q_UNUSED(index);
beginInsertRows(QModelIndex(), position, position + rows - 1);
for (int row = 0; row < rows; ++row) {
QPair<QString, QString> pair(" ", " ");
listOfPairs.insert(position, pair);
}
for (int row = 0; row < rows; ++row)
contacts.insert(position, { QString(), QString() });
endInsertRows();
return true;
@ -142,9 +140,8 @@ bool TableModel::removeRows(int position, int rows, const QModelIndex &index)
Q_UNUSED(index);
beginRemoveRows(QModelIndex(), position, position + rows - 1);
for (int row = 0; row < rows; ++row) {
listOfPairs.removeAt(position);
}
for (int row = 0; row < rows; ++row)
contacts.removeAt(position);
endRemoveRows();
return true;
@ -157,16 +154,16 @@ bool TableModel::setData(const QModelIndex &index, const QVariant &value, int ro
if (index.isValid() && role == Qt::EditRole) {
int row = index.row();
QPair<QString, QString> p = listOfPairs.value(row);
auto contact = contacts.value(row);
if (index.column() == 0)
p.first = value.toString();
contact.name = value.toString();
else if (index.column() == 1)
p.second = value.toString();
contact.address = value.toString();
else
return false;
listOfPairs.replace(row, p);
contacts.replace(row, contact);
emit(dataChanged(index, index));
return true;
@ -187,8 +184,8 @@ Qt::ItemFlags TableModel::flags(const QModelIndex &index) const
//! [7]
//! [8]
QList< QPair<QString, QString> > TableModel::getList()
QList<Contact> TableModel::getContacts() const
{
return listOfPairs;
return contacts;
}
//! [8]

View File

@ -53,16 +53,37 @@
#include <QAbstractTableModel>
#include <QList>
#include <QPair>
//! [0]
struct Contact
{
QString name;
QString address;
bool operator==(const Contact &other) const
{
return name == other.name && address == other.address;
}
};
inline QDataStream &operator<<(QDataStream &stream, const Contact &contact)
{
return stream << contact.name << contact.address;
}
inline QDataStream &operator>>(QDataStream &stream, Contact &contact)
{
return stream >> contact.name >> contact.address;
}
class TableModel : public QAbstractTableModel
{
Q_OBJECT
public:
TableModel(QObject *parent = 0);
TableModel(QList<QPair<QString, QString> > listofPairs, QObject *parent = 0);
TableModel(QList<Contact> contacts, QObject *parent = 0);
int rowCount(const QModelIndex &parent) const override;
int columnCount(const QModelIndex &parent) const override;
@ -72,10 +93,10 @@ public:
bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole) override;
bool insertRows(int position, int rows, const QModelIndex &index = QModelIndex()) override;
bool removeRows(int position, int rows, const QModelIndex &index = QModelIndex()) override;
QList<QPair<QString, QString> > getList();
QList<Contact> getContacts() const;
private:
QList<QPair<QString, QString> > listOfPairs;
QList<Contact> contacts;
};
//! [0]

View File

@ -58,7 +58,7 @@ int main(int argc, char *argv[])
QApplication app(argc, argv);
MainWindow window;
window.loadImage(":/images/example.jpg");
window.loadImage(QStringLiteral(":/images/example.jpg"));
window.show();
return app.exec();
}

View File

@ -69,12 +69,19 @@ MainWindow::MainWindow(QWidget *parent)
void MainWindow::openImage()
{
const QString fileName =
QFileDialog::getOpenFileName(this,
tr("Open Image"), QString(),
tr("Image Files (*.png *.jpg *.bmp)"));
if (!fileName.isEmpty())
loadImage(fileName);
const QString directory =
QStandardPaths::standardLocations(QStandardPaths::PicturesLocation).value(0, QDir::homePath());
QFileDialog dialog(this, tr("Open Image"), directory);
dialog.setAcceptMode(QFileDialog::AcceptOpen);
dialog.setFileMode(QFileDialog::ExistingFile);
QStringList mimeTypeFilters;
for (const QByteArray &mimeTypeName : QImageReader::supportedMimeTypes())
mimeTypeFilters.append(mimeTypeName);
mimeTypeFilters.sort();
dialog.setMimeTypeFilters(mimeTypeFilters);
dialog.selectMimeTypeFilter("image/jpeg");
if (dialog.exec() == QDialog::Accepted)
loadImage(dialog.selectedFiles().constFirst());
}
void MainWindow::loadImage(const QString &fileName)
@ -83,7 +90,7 @@ void MainWindow::loadImage(const QString &fileName)
if (!newImage.load(fileName)) {
QMessageBox::warning(this, tr("Open Image"),
tr("The image file could not be loaded."),
QMessageBox::Cancel);
QMessageBox::Close);
return;
}
puzzleImage = newImage;
@ -117,19 +124,15 @@ void MainWindow::setupMenus()
{
QMenu *fileMenu = menuBar()->addMenu(tr("&File"));
QAction *openAction = fileMenu->addAction(tr("&Open..."));
QAction *openAction = fileMenu->addAction(tr("&Open..."), this, &MainWindow::openImage);
openAction->setShortcuts(QKeySequence::Open);
QAction *exitAction = fileMenu->addAction(tr("E&xit"));
QAction *exitAction = fileMenu->addAction(tr("E&xit"), qApp, &QCoreApplication::quit);
exitAction->setShortcuts(QKeySequence::Quit);
QMenu *gameMenu = menuBar()->addMenu(tr("&Game"));
QAction *restartAction = gameMenu->addAction(tr("&Restart"));
connect(openAction, &QAction::triggered, this, &MainWindow::openImage);
connect(exitAction, &QAction::triggered, qApp, &QCoreApplication::quit);
connect(restartAction, &QAction::triggered, this, &MainWindow::setupPuzzle);
gameMenu->addAction(tr("&Restart"), this, &MainWindow::setupPuzzle);
}
void MainWindow::setupWidgets()

View File

@ -65,7 +65,7 @@ class MainWindow : public QMainWindow
Q_OBJECT
public:
MainWindow(QWidget *parent = 0);
explicit MainWindow(QWidget *parent = nullptr);
public slots:
void openImage();

View File

@ -62,9 +62,7 @@ PuzzleWidget::PuzzleWidget(int imageSize, QWidget *parent)
void PuzzleWidget::clear()
{
pieceLocations.clear();
piecePixmaps.clear();
pieceRects.clear();
pieces.clear();
highlightedRect = QRect();
inPlace = 0;
update();
@ -110,23 +108,20 @@ void PuzzleWidget::dropEvent(QDropEvent *event)
&& findPiece(targetSquare(event->pos())) == -1) {
QByteArray pieceData = event->mimeData()->data("image/x-puzzle-piece");
QDataStream stream(&pieceData, QIODevice::ReadOnly);
QRect square = targetSquare(event->pos());
QPixmap pixmap;
QPoint location;
stream >> pixmap >> location;
QDataStream dataStream(&pieceData, QIODevice::ReadOnly);
Piece piece;
piece.rect = targetSquare(event->pos());
dataStream >> piece.pixmap >> piece.location;
pieceLocations.append(location);
piecePixmaps.append(pixmap);
pieceRects.append(square);
pieces.append(piece);
highlightedRect = QRect();
update(square);
update(piece.rect);
event->setDropAction(Qt::MoveAction);
event->accept();
if (location == QPoint(square.x()/pieceSize(), square.y()/pieceSize())) {
if (piece.location == piece.rect.topLeft() / pieceSize()) {
inPlace++;
if (inPlace == 25)
emit puzzleCompleted();
@ -139,8 +134,8 @@ void PuzzleWidget::dropEvent(QDropEvent *event)
int PuzzleWidget::findPiece(const QRect &pieceRect) const
{
for (int i = 0; i < pieceRects.size(); ++i) {
if (pieceRect == pieceRects[i])
for (int i = 0, size = pieces.size(); i < size; ++i) {
if (pieces.at(i).rect == pieceRect)
return i;
}
return -1;
@ -154,13 +149,9 @@ void PuzzleWidget::mousePressEvent(QMouseEvent *event)
if (found == -1)
return;
QPoint location = pieceLocations[found];
QPixmap pixmap = piecePixmaps[found];
pieceLocations.removeAt(found);
piecePixmaps.removeAt(found);
pieceRects.removeAt(found);
Piece piece = pieces.takeAt(found);
if (location == QPoint(square.x()/pieceSize(), square.y()/pieceSize()))
if (piece.location == square.topLeft() / pieceSize())
inPlace--;
update(square);
@ -168,7 +159,7 @@ void PuzzleWidget::mousePressEvent(QMouseEvent *event)
QByteArray itemData;
QDataStream dataStream(&itemData, QIODevice::WriteOnly);
dataStream << pixmap << location;
dataStream << piece.pixmap << piece.location;
QMimeData *mimeData = new QMimeData;
mimeData->setData("image/x-puzzle-piece", itemData);
@ -176,23 +167,20 @@ void PuzzleWidget::mousePressEvent(QMouseEvent *event)
QDrag *drag = new QDrag(this);
drag->setMimeData(mimeData);
drag->setHotSpot(event->pos() - square.topLeft());
drag->setPixmap(pixmap);
drag->setPixmap(piece.pixmap);
if (drag->start(Qt::MoveAction) == 0) {
pieceLocations.insert(found, location);
piecePixmaps.insert(found, pixmap);
pieceRects.insert(found, square);
if (drag->start(Qt::MoveAction) == Qt::IgnoreAction) {
pieces.insert(found, piece);
update(targetSquare(event->pos()));
if (location == QPoint(square.x()/pieceSize(), square.y()/pieceSize()))
if (piece.location == QPoint(square.x() / pieceSize(), square.y() / pieceSize()))
inPlace++;
}
}
void PuzzleWidget::paintEvent(QPaintEvent *event)
{
QPainter painter;
painter.begin(this);
QPainter painter(this);
painter.fillRect(event->rect(), Qt::white);
if (highlightedRect.isValid()) {
@ -201,15 +189,14 @@ void PuzzleWidget::paintEvent(QPaintEvent *event)
painter.drawRect(highlightedRect.adjusted(0, 0, -1, -1));
}
for (int i = 0; i < pieceRects.size(); ++i) {
painter.drawPixmap(pieceRects[i], piecePixmaps[i]);
}
painter.end();
for (const Piece &piece : pieces)
painter.drawPixmap(piece.rect, piece.pixmap);
}
const QRect PuzzleWidget::targetSquare(const QPoint &position) const
{
return QRect(position.x()/pieceSize() * pieceSize(), position.y()/pieceSize() * pieceSize(), pieceSize(), pieceSize());
return QRect(position / pieceSize() * pieceSize(),
QSize(pieceSize(), pieceSize()));
}
int PuzzleWidget::pieceSize() const

View File

@ -51,9 +51,9 @@
#ifndef PUZZLEWIDGET_H
#define PUZZLEWIDGET_H
#include <QList>
#include <QPixmap>
#include <QPoint>
#include <QPixmap>
#include <QVector>
#include <QWidget>
QT_BEGIN_NAMESPACE
@ -67,7 +67,7 @@ class PuzzleWidget : public QWidget
Q_OBJECT
public:
explicit PuzzleWidget(int imageSize, QWidget *parent = 0);
explicit PuzzleWidget(int imageSize, QWidget *parent = nullptr);
void clear();
int pieceSize() const;
@ -85,12 +85,16 @@ protected:
void paintEvent(QPaintEvent *event) override;
private:
struct Piece {
QPixmap pixmap;
QRect rect;
QPoint location;
};
int findPiece(const QRect &pieceRect) const;
const QRect targetSquare(const QPoint &position) const;
QList<QPixmap> piecePixmaps;
QList<QRect> pieceRects;
QList<QPoint> pieceLocations;
QVector<Piece> pieces;
QRect highlightedRect;
int inPlace;
int m_ImageSize;

View File

@ -129,6 +129,10 @@ PatternLineEdit::PatternLineEdit(QWidget *parent) :
connect(escapeSelectionAction, &QAction::triggered, this, &PatternLineEdit::escapeSelection);
connect(copyToCodeAction, &QAction::triggered, this, &PatternLineEdit::copyToCode);
connect(pasteFromCodeAction, &QAction::triggered, this, &PatternLineEdit::pasteFromCode);
#if !QT_CONFIG(clipboard)
copyToCodeAction->setEnabled(false);
pasteFromCodeAction->setEnabled(false);
#endif
}
void PatternLineEdit::escapeSelection()
@ -144,12 +148,16 @@ void PatternLineEdit::escapeSelection()
void PatternLineEdit::copyToCode()
{
#if QT_CONFIG(clipboard)
QGuiApplication::clipboard()->setText(patternToCode(text()));
#endif
}
void PatternLineEdit::pasteFromCode()
{
#if QT_CONFIG(clipboard)
setText(codeToPattern(QGuiApplication::clipboard()->text()));
#endif
}
void PatternLineEdit::contextMenuEvent(QContextMenuEvent *event)
@ -316,7 +324,7 @@ void RegularExpressionDialog::refresh()
void RegularExpressionDialog::copyEscapedPatternToClipboard()
{
#ifndef QT_NO_CLIPBOARD
#if QT_CONFIG(clipboard)
QClipboard *clipboard = QGuiApplication::clipboard();
if (clipboard)
clipboard->setText(escapedPatternLineEdit->text());
@ -361,7 +369,7 @@ QWidget *RegularExpressionDialog::setupLeftUi()
palette.setBrush(QPalette::Base, palette.brush(QPalette::Disabled, QPalette::Base));
escapedPatternLineEdit->setPalette(palette);
#ifndef QT_NO_CLIPBOARD
#if QT_CONFIG(clipboard)
QAction *copyEscapedPatternAction = new QAction(this);
copyEscapedPatternAction->setText(tr("Copy to clipboard"));
copyEscapedPatternAction->setIcon(QIcon(QStringLiteral(":/images/copy.png")));

View File

@ -1,10 +1,5 @@
win32 {
cmake_version_output = $$system(cmake --version 2>NUL, lines)
} else {
cmake_version_output = $$system(cmake --version 2>/dev/null, lines)
}
cmake_version_output = $$system(cmake --version 2>$$QMAKE_SYSTEM_NULL_DEVICE, lines)
# First line
cmake_version_output = $$first(cmake_version_output)
# Format is "cmake version X.Y.Z"
@ -19,12 +14,7 @@ isEmpty(CMAKE_VERSION) {
return()
}
win32 {
CTEST_VERSION = $$system(ctest --version 2>NUL)
} else {
CTEST_VERSION = $$system(ctest --version 2>/dev/null)
}
CTEST_VERSION = $$system(ctest --version 2>$$QMAKE_SYSTEM_NULL_DEVICE)
isEmpty(CTEST_VERSION) {
message("ctest executable not found. Not running CMake unit tests")
return()

View File

@ -13,5 +13,6 @@
}
$$add_plist: \
QMAKE_LFLAGS += -Wl,-sectcreate,__TEXT,__info_plist,$$shell_quote($$QMAKE_INFO_PLIST)
QMAKE_LFLAGS += -Wl,-sectcreate,__TEXT,__info_plist,$$shell_quote( \
$$relative_path($$absolute_path($$QMAKE_INFO_PLIST, $$_PRO_FILE_PWD_), $$OUT_PWD))
}

View File

@ -100,6 +100,9 @@ unix: CONFIG += explicitlib
# By default we want tests on macOS to be built as standalone executables
macos: CONFIG += testcase_no_bundle
# Override MinGW's definition in _mingw.h
mingw: DEFINES += WINVER=0x0601 _WIN32_WINNT=0x0601
defineTest(qtBuildPart) {
bp = $$eval($$upper($$section(_QMAKE_CONF_, /, -2, -2))_BUILD_PARTS)
isEmpty(bp): bp = $$QT_BUILD_PARTS

View File

@ -291,10 +291,7 @@ defineReplace(pkgConfigExecutable) {
}
}
equals(QMAKE_HOST.os, Windows): \
PKG_CONFIG += 2> NUL
else: \
PKG_CONFIG += 2> /dev/null
PKG_CONFIG += 2> $$QMAKE_SYSTEM_NULL_DEVICE
return($$PKG_CONFIG)
}

View File

@ -82,6 +82,7 @@ equals(MAKEFILE_GENERATOR, MSBUILD) \
QMAKE_MKDIR = mkdir # legacy
QMAKE_MKDIR_CMD = if not exist %1 mkdir %1 & if not exist %1 exit 1
QMAKE_STREAM_EDITOR = $(QMAKE) -install sed
QMAKE_SHELL_NULL_DEVICE = NUL
QMAKE_INSTALL_FILE = copy /y
QMAKE_INSTALL_PROGRAM = copy /y
} else {
@ -101,6 +102,7 @@ equals(MAKEFILE_GENERATOR, MSBUILD) \
QMAKE_MKDIR = mkdir -p # legacy
QMAKE_MKDIR_CMD = test -d %1 || mkdir -p %1
QMAKE_STREAM_EDITOR = sed
QMAKE_SHELL_NULL_DEVICE = /dev/null
equals(QMAKE_HOST.os, Windows) {
MINGW_IN_SHELL = 1 # legacy
@ -118,9 +120,11 @@ equals(MAKEFILE_GENERATOR, MSBUILD) \
}
QMAKE_INSTALL_DIR = $$QMAKE_COPY_DIR
equals(QMAKE_HOST.os, Windows) {
QMAKE_SYMBOLIC_LINK = $(QMAKE) -install ln -f -s
QMAKE_LN_SHLIB = $(QMAKE) -install ln -s
QMAKE_SYMBOLIC_LINK = $(QMAKE) -install ln -f -s
QMAKE_LN_SHLIB = $(QMAKE) -install ln -s
QMAKE_SYSTEM_NULL_DEVICE = NUL
} else {
QMAKE_SYMBOLIC_LINK = ln -f -s
QMAKE_LN_SHLIB = ln -s
QMAKE_SYMBOLIC_LINK = ln -f -s
QMAKE_LN_SHLIB = ln -s
QMAKE_SYSTEM_NULL_DEVICE = /dev/null
}

View File

@ -32,15 +32,11 @@ isEmpty($${target_prefix}.INCDIRS) {
# Get default include and library paths from compiler
#
gcc {
!equals(QMAKE_HOST.os, Windows) {
cmd_prefix = "LC_ALL=C"
cmd_suffix = "</dev/null >/dev/null"
null_file = /dev/null
} else {
cmd_suffix = "<$$QMAKE_SYSTEM_NULL_DEVICE >$$QMAKE_SYSTEM_NULL_DEVICE"
equals(QMAKE_HOST.os, Windows): \
cmd_prefix = "set LC_ALL=C&"
cmd_suffix = "<NUL >NUL"
null_file = NUL
}
else: \
cmd_prefix = "LC_ALL=C"
cxx_flags = $$QMAKE_CXXFLAGS
@ -59,7 +55,7 @@ isEmpty($${target_prefix}.INCDIRS) {
rim_qcc: \
# Need the cc1plus and ld command lines to pick up the paths
cxx_flags += $$QMAKE_LFLAGS_SHLIB -o $$null_file -v
cxx_flags += $$QMAKE_LFLAGS_SHLIB -o $$QMAKE_SYSTEM_NULL_DEVICE -v
else: darwin:clang: \
# Need to link to pick up library paths
cxx_flags += $$QMAKE_LFLAGS_SHLIB -o /dev/null -v -Wl,-v
@ -175,9 +171,8 @@ defineReplace(qtVariablesFromMSVC) {
}
defineReplace(qtVariablesFromGCC) {
null_device = /dev/null
equals(QMAKE_HOST.os, Windows): null_device = NUL
ret = $$system("$$1 -E $$system_quote($$PWD/data/macros.cpp) <$$null_device 2>$$null_device", lines, ec)
ret = $$system("$$1 -E $$system_quote($$PWD/data/macros.cpp) \
<$$QMAKE_SYSTEM_NULL_DEVICE 2>$$QMAKE_SYSTEM_NULL_DEVICE", lines, ec)
!equals(ec, 0): qtCompilerErrror($$1)
return($$ret)
}

View File

@ -36,12 +36,6 @@
#include <stdlib.h>
#include <time.h>
#ifdef Q_OS_WIN
#define NULL_DEVICE "NUL"
#else
#define NULL_DEVICE "/dev/null"
#endif
QT_BEGIN_NAMESPACE
MingwMakefileGenerator::MingwMakefileGenerator() : Win32MakefileGenerator()
@ -329,7 +323,7 @@ void MingwMakefileGenerator::writeBuildRulesPart(QTextStream &t)
if(!project->isEmpty("QMAKE_PRE_LINK"))
t << "\n\t" <<var("QMAKE_PRE_LINK");
if(project->isActiveConfig("staticlib") && project->first("TEMPLATE") == "lib") {
t << "\n\t-$(DEL_FILE) $(DESTDIR_TARGET) 2>" NULL_DEVICE;
t << "\n\t-$(DEL_FILE) $(DESTDIR_TARGET) 2>" << var("QMAKE_SHELL_NULL_DEVICE");
if (project->values("OBJECTS").count() < var("QMAKE_LINK_OBJECT_MAX").toInt()) {
t << "\n\t$(LIB) $(DESTDIR_TARGET) " << objectsLinkLine << " " ;
} else {

View File

@ -1,32 +1,32 @@
// Copyright (C) 2002-2013 The ANGLE Project Authors.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
//
// Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
//
// Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following
// disclaimer in the documentation and/or other materials provided
// with the distribution.
//
// Neither the name of TransGaming Inc., Google Inc., 3DLabs Inc.
// Ltd., nor the names of their contributors may be used to endorse
// or promote products derived from this software without specific
// prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
// COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
Copyright (C) 2002-2013 The ANGLE Project Authors.
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the following
disclaimer in the documentation and/or other materials provided
with the distribution.
Neither the name of TransGaming Inc., Google Inc., 3DLabs Inc.
Ltd., nor the names of their contributors may be used to endorse
or promote products derived from this software without specific
prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.

View File

@ -0,0 +1,15 @@
diff --git a/src/3rdparty/sqlite/sqlite3.c b/src/3rdparty/sqlite/sqlite3.c
index 7f5e75921f..f5c6180a03 100644
--- a/src/3rdparty/sqlite/sqlite3.c
+++ b/src/3rdparty/sqlite/sqlite3.c
@@ -165733,6 +165733,10 @@ static int getNodeSize(
rc = getIntFromStmt(db, zSql, &pRtree->iNodeSize);
if( rc!=SQLITE_OK ){
*pzErr = sqlite3_mprintf("%s", sqlite3_errmsg(db));
+ }else if( pRtree->iNodeSize<(512-64) ){
+ rc = SQLITE_CORRUPT;
+ *pzErr = sqlite3_mprintf("undersize RTree blobs in \"%q_node\"",
+ pRtree->zName);
}
}

View File

@ -165733,6 +165733,10 @@ static int getNodeSize(
rc = getIntFromStmt(db, zSql, &pRtree->iNodeSize);
if( rc!=SQLITE_OK ){
*pzErr = sqlite3_mprintf("%s", sqlite3_errmsg(db));
}else if( pRtree->iNodeSize<(512-64) ){
rc = SQLITE_CORRUPT;
*pzErr = sqlite3_mprintf("undersize RTree blobs in \"%q_node\"",
pRtree->zName);
}
}

View File

@ -585,7 +585,7 @@ angle_d3d11: SHADERS = VS_Passthrough2D \
for (SHADER, SHADERS) {
INPUT = $$eval($${SHADER}.input)
OUT_DIR = $$OUT_PWD/libANGLE/$$relative_path($$dirname($$INPUT), $$ANGLE_DIR/src/libANGLE)/compiled
fxc_$${SHADER}.commands = $$FXC /nologo /E $${SHADER} /T $$eval($${SHADER}.type) /Fh ${QMAKE_FILE_OUT} ${QMAKE_FILE_NAME}
fxc_$${SHADER}.commands = $$FXC -nologo -E $${SHADER} -T $$eval($${SHADER}.type) -Fh ${QMAKE_FILE_OUT} ${QMAKE_FILE_NAME}
fxc_$${SHADER}.output = $$OUT_DIR/$$eval($${SHADER}.output)
fxc_$${SHADER}.input = $$INPUT
fxc_$${SHADER}.dependency_type = TYPE_C

View File

@ -48,8 +48,6 @@ win32 {
mingw {
# otherwise mingw headers do not declare common functions like putenv
CONFIG -= strict_c++
# Override MinGW's definition in _mingw.h
DEFINES += WINVER=0x600 _WIN32_WINNT=0x0600
}
LIBS_PRIVATE += -lws2_32
!winrt {

View File

@ -99,16 +99,13 @@ gcc:ltcg {
SOURCES += $$VERSIONTAGGING_SOURCES
}
# On AARCH64 the fp16 extension is mandatory, so we don't need the conversion tables.
!contains(QT_ARCH, "arm64") {
QMAKE_QFLOAT16_TABLES_GENERATE = global/qfloat16.h
QMAKE_QFLOAT16_TABLES_GENERATE = global/qfloat16.h
qtPrepareTool(QMAKE_QFLOAT16_TABLES, qfloat16-tables)
qtPrepareTool(QMAKE_QFLOAT16_TABLES, qfloat16-tables)
qfloat16_tables.commands = $$QMAKE_QFLOAT16_TABLES ${QMAKE_FILE_OUT}
qfloat16_tables.output = global/qfloat16tables.cpp
qfloat16_tables.depends = $$QMAKE_QFLOAT16_TABLES
qfloat16_tables.input = QMAKE_QFLOAT16_TABLES_GENERATE
qfloat16_tables.variable_out = SOURCES
QMAKE_EXTRA_COMPILERS += qfloat16_tables
}
qfloat16_tables.commands = $$QMAKE_QFLOAT16_TABLES ${QMAKE_FILE_OUT}
qfloat16_tables.output = global/qfloat16tables.cpp
qfloat16_tables.depends = $$QMAKE_QFLOAT16_TABLES
qfloat16_tables.input = QMAKE_QFLOAT16_TABLES_GENERATE
qfloat16_tables.variable_out = SOURCES
QMAKE_EXTRA_COMPILERS += qfloat16_tables

View File

@ -4296,6 +4296,7 @@ bool QInternal::activateCallbacks(Callback cb, void **parameters)
/*!
\macro qDebug(const char *message, ...)
\relates <QtGlobal>
\threadsafe
Calls the message handler with the debug message \a message. If no
message handler has been installed, the message is printed to
@ -4332,6 +4333,7 @@ bool QInternal::activateCallbacks(Callback cb, void **parameters)
/*!
\macro qInfo(const char *message, ...)
\relates <QtGlobal>
\threadsafe
\since 5.5
Calls the message handler with the informational message \a message. If no
@ -4369,6 +4371,7 @@ bool QInternal::activateCallbacks(Callback cb, void **parameters)
/*!
\macro qWarning(const char *message, ...)
\relates <QtGlobal>
\threadsafe
Calls the message handler with the warning message \a message. If no
message handler has been installed, the message is printed to
@ -4406,6 +4409,7 @@ bool QInternal::activateCallbacks(Callback cb, void **parameters)
/*!
\macro qCritical(const char *message, ...)
\relates <QtGlobal>
\threadsafe
Calls the message handler with the critical message \a message. If no
message handler has been installed, the message is printed to

View File

@ -154,15 +154,19 @@ class SystemRandom
{
static QBasicAtomicInt s_fdp1; // "file descriptor plus 1"
static int openDevice();
#ifdef Q_CC_GNU
// If it's not GCC or GCC-like, then we'll leak the file descriptor
__attribute__((destructor))
#endif
static void closeDevice();
SystemRandom() {}
~SystemRandom();
public:
enum { EfficientBufferFill = true };
static qssize_t fillBuffer(void *buffer, qssize_t count);
};
QBasicAtomicInt SystemRandom::s_fdp1 = Q_BASIC_ATOMIC_INITIALIZER(0);
SystemRandom::~SystemRandom()
void SystemRandom::closeDevice()
{
int fd = s_fdp1.loadAcquire() - 1;
if (fd >= 0)

View File

@ -62,8 +62,16 @@ public:
static Q_CORE_EXPORT quint64 generate64();
static double generateDouble()
{
// use get64() to get enough bits
return double(generate64()) / ((std::numeric_limits<quint64>::max)() + double(1.0));
// IEEE 754 double precision has:
// 1 bit sign
// 10 bits exponent
// 53 bits mantissa
// In order for our result to be normalized in the range [0, 1), we
// need exactly 53 bits of random data. Use generate64() to get enough.
quint64 x = generate64();
quint64 limit = Q_UINT64_C(1) << std::numeric_limits<double>::digits;
x >>= std::numeric_limits<quint64>::digits - std::numeric_limits<double>::digits;
return double(x) / double(limit);
}
static qreal bounded(qreal sup)

View File

@ -48,10 +48,10 @@
#if defined(Q_CC_MINGW)
// mingw's windows.h does not set _WIN32_WINNT, resulting breaking compilation
# ifndef WINVER
# define WINVER 0x600
# define WINVER 0x601
# endif
# ifndef _WIN32_WINNT
# define _WIN32_WINNT 0x600
# define _WIN32_WINNT 0x601
# endif
# ifndef NTDDI_VERSION
# define NTDDI_VERSION 0x06000000

View File

@ -595,6 +595,9 @@ QByteArray QFileSystemEngine::id(const QFileSystemEntry &entry)
params.dwSize = sizeof(params);
params.dwFileAttributes = FILE_ATTRIBUTE_NORMAL;
params.dwFileFlags = FILE_FLAG_BACKUP_SEMANTICS;
params.dwSecurityQosFlags = SECURITY_ANONYMOUS;
params.lpSecurityAttributes = NULL;
params.hTemplateFile = NULL;
const HANDLE handle =
CreateFile2((const wchar_t*)entry.nativeFilePath().utf16(), 0,
FILE_SHARE_READ, OPEN_EXISTING, &params);

View File

@ -445,6 +445,7 @@ void QLoggingCategory::setFilterRules(const QString &rules)
/*!
\macro qCDebug(category)
\relates QLoggingCategory
\threadsafe
\since 5.2
Returns an output stream for debug messages in the logging category
@ -469,6 +470,7 @@ void QLoggingCategory::setFilterRules(const QString &rules)
/*!
\macro qCDebug(category, const char *message, ...)
\relates QLoggingCategory
\threadsafe
\since 5.3
Logs a debug message \a message in the logging category \a category.
@ -490,6 +492,7 @@ void QLoggingCategory::setFilterRules(const QString &rules)
/*!
\macro qCInfo(category)
\relates QLoggingCategory
\threadsafe
\since 5.5
Returns an output stream for informational messages in the logging category
@ -514,6 +517,7 @@ void QLoggingCategory::setFilterRules(const QString &rules)
/*!
\macro qCInfo(category, const char *message, ...)
\relates QLoggingCategory
\threadsafe
\since 5.5
Logs an informational message \a message in the logging category \a category.
@ -535,6 +539,7 @@ void QLoggingCategory::setFilterRules(const QString &rules)
/*!
\macro qCWarning(category)
\relates QLoggingCategory
\threadsafe
\since 5.2
Returns an output stream for warning messages in the logging category
@ -559,6 +564,7 @@ void QLoggingCategory::setFilterRules(const QString &rules)
/*!
\macro qCWarning(category, const char *message, ...)
\relates QLoggingCategory
\threadsafe
\since 5.3
Logs a warning message \a message in the logging category \a category.
@ -580,6 +586,7 @@ void QLoggingCategory::setFilterRules(const QString &rules)
/*!
\macro qCCritical(category)
\relates QLoggingCategory
\threadsafe
\since 5.2
Returns an output stream for critical messages in the logging category
@ -604,6 +611,7 @@ void QLoggingCategory::setFilterRules(const QString &rules)
/*!
\macro qCCritical(category, const char *message, ...)
\relates QLoggingCategory
\threadsafe
\since 5.3
Logs a critical message \a message in the logging category \a category.

View File

@ -499,9 +499,10 @@ public:
InvalidFragmentError = Fragment << 8,
// the following two cases are only possible in combination
// with presence/absence of the authority and scheme. See validityError().
// the following three cases are only possible in combination with
// presence/absence of the path, authority and scheme. See validityError().
AuthorityPresentAndPathIsRelative = Authority << 8 | Path << 8 | 0x10000,
AuthorityAbsentAndPathIsDoubleSlash,
RelativeUrlPathContainsColonBeforeSlash = Scheme << 8 | Authority << 8 | Path << 8 | 0x10000,
NoError = 0
@ -1627,19 +1628,32 @@ inline QUrlPrivate::ErrorCode QUrlPrivate::validityError(QString *source, int *p
return error->code;
}
// There are two more cases of invalid URLs that QUrl recognizes and they
// There are three more cases of invalid URLs that QUrl recognizes and they
// are only possible with constructed URLs (setXXX methods), not with
// parsing. Therefore, they are tested here.
//
// The two cases are a non-empty path that doesn't start with a slash and:
// Two cases are a non-empty path that doesn't start with a slash and:
// - with an authority
// - without an authority, without scheme but the path with a colon before
// the first slash
// The third case is an empty authority and a non-empty path that starts
// with "//".
// Those cases are considered invalid because toString() would produce a URL
// that wouldn't be parsed back to the same QUrl.
if (path.isEmpty() || path.at(0) == QLatin1Char('/'))
if (path.isEmpty())
return NoError;
if (path.at(0) == QLatin1Char('/')) {
if (sectionIsPresent & QUrlPrivate::Authority || port != -1 ||
path.length() == 1 || path.at(1) != QLatin1Char('/'))
return NoError;
if (source) {
*source = path;
*position = 0;
}
return AuthorityAbsentAndPathIsDoubleSlash;
}
if (sectionIsPresent & QUrlPrivate::Host) {
if (source) {
*source = path;
@ -2514,10 +2528,7 @@ void QUrl::setPath(const QString &path, ParsingMode mode)
mode = TolerantMode;
}
int from = 0;
while (from < data.length() - 2 && data.midRef(from, 2) == QLatin1String("//"))
++from;
d->setPath(data, from, data.length());
d->setPath(data, 0, data.length());
// optimized out, since there is no path delimiter
// if (path.isNull())
@ -3989,6 +4000,8 @@ static QString errorMessage(QUrlPrivate::ErrorCode errorCode, const QString &err
case QUrlPrivate::AuthorityPresentAndPathIsRelative:
return QStringLiteral("Path component is relative and authority is present");
case QUrlPrivate::AuthorityAbsentAndPathIsDoubleSlash:
return QStringLiteral("Path component starts with '//' and authority is absent");
case QUrlPrivate::RelativeUrlPathContainsColonBeforeSlash:
return QStringLiteral("Relative URL's path component contains ':' before any '/'");
}

View File

@ -170,10 +170,10 @@ QT_BEGIN_NAMESPACE
\value LeaveEditFocus An editor widget loses focus for editing. QT_KEYPAD_NAVIGATION must be defined.
\value LeaveWhatsThisMode Send to toplevel widgets when the application leaves "What's This?" mode.
\value LocaleChange The system locale has changed.
\value NonClientAreaMouseButtonDblClick A mouse double click occurred outside the client area.
\value NonClientAreaMouseButtonPress A mouse button press occurred outside the client area.
\value NonClientAreaMouseButtonRelease A mouse button release occurred outside the client area.
\value NonClientAreaMouseMove A mouse move occurred outside the client area.
\value NonClientAreaMouseButtonDblClick A mouse double click occurred outside the client area (QMouseEvent).
\value NonClientAreaMouseButtonPress A mouse button press occurred outside the client area (QMouseEvent).
\value NonClientAreaMouseButtonRelease A mouse button release occurred outside the client area (QMouseEvent).
\value NonClientAreaMouseMove A mouse move occurred outside the client area (QMouseEvent).
\value MacSizeChange The user changed his widget sizes (\macos only).
\value MetaCall An asynchronous method invocation via QMetaObject::invokeMethod().
\value ModifiedChange Widgets modification state has been changed.

View File

@ -251,7 +251,7 @@ class Q_CORE_EXPORT QMutex
public:
enum RecursionMode { NonRecursive, Recursive };
inline explicit QMutex(RecursionMode mode = NonRecursive) Q_DECL_NOTHROW { Q_UNUSED(mode); }
inline Q_DECL_CONSTEXPR explicit QMutex(RecursionMode = NonRecursive) Q_DECL_NOTHROW { }
inline void lock() Q_DECL_NOTHROW {}
inline bool tryLock(int timeout = 0) Q_DECL_NOTHROW { Q_UNUSED(timeout); return true; }

View File

@ -73,7 +73,7 @@ public:
\internal
*/
QThreadPoolThread::QThreadPoolThread(QThreadPoolPrivate *manager)
:manager(manager), runnable(0)
:manager(manager), runnable(nullptr)
{
setStackSize(manager->stackSize);
}
@ -86,7 +86,7 @@ void QThreadPoolThread::run()
QMutexLocker locker(&manager->mutex);
for(;;) {
QRunnable *r = runnable;
runnable = 0;
runnable = nullptr;
do {
if (r) {
@ -118,8 +118,19 @@ void QThreadPoolThread::run()
if (manager->tooManyThreadsActive())
break;
r = !manager->queue.isEmpty() ? manager->queue.takeFirst().first : 0;
} while (r != 0);
if (manager->queue.isEmpty()) {
r = nullptr;
break;
}
QueuePage *page = manager->queue.first();
r = page->pop();
if (page->isFinished()) {
manager->queue.removeFirst();
delete page;
}
} while (true);
if (manager->isExiting) {
registerThreadInactive();
@ -160,6 +171,7 @@ QThreadPoolPrivate:: QThreadPoolPrivate()
bool QThreadPoolPrivate::tryStart(QRunnable *task)
{
Q_ASSERT(task != nullptr);
if (allThreads.isEmpty()) {
// always create at least one thread
startThread(task);
@ -180,7 +192,7 @@ bool QThreadPoolPrivate::tryStart(QRunnable *task)
if (!expiredThreads.isEmpty()) {
// restart an expired thread
QThreadPoolThread *thread = expiredThreads.dequeue();
Q_ASSERT(thread->runnable == 0);
Q_ASSERT(thread->runnable == nullptr);
++activeThreads;
@ -196,22 +208,25 @@ bool QThreadPoolPrivate::tryStart(QRunnable *task)
return true;
}
inline bool operator<(int priority, const QPair<QRunnable *, int> &p)
{ return p.second < priority; }
inline bool operator<(const QPair<QRunnable *, int> &p, int priority)
{ return priority < p.second; }
inline bool comparePriority(int priority, const QueuePage *p)
{
return p->priority() < priority;
}
void QThreadPoolPrivate::enqueueTask(QRunnable *runnable, int priority)
{
Q_ASSERT(runnable != nullptr);
if (runnable->autoDelete())
++runnable->ref;
// put it on the queue
QVector<QPair<QRunnable *, int> >::const_iterator begin = queue.constBegin();
QVector<QPair<QRunnable *, int> >::const_iterator it = queue.constEnd();
if (it != begin && priority > (*(it - 1)).second)
it = std::upper_bound(begin, --it, priority);
queue.insert(it - begin, qMakePair(runnable, priority));
for (QueuePage *page : qAsConst(queue)) {
if (page->priority() == priority && !page->isFull()) {
page->push(runnable);
return;
}
}
auto it = std::upper_bound(queue.constBegin(), queue.constEnd(), priority, comparePriority);
queue.insert(std::distance(queue.constBegin(), it), new QueuePage(runnable, priority));
}
int QThreadPoolPrivate::activeThreadCount() const
@ -225,8 +240,18 @@ int QThreadPoolPrivate::activeThreadCount() const
void QThreadPoolPrivate::tryToStartMoreThreads()
{
// try to push tasks on the queue to any available threads
while (!queue.isEmpty() && tryStart(queue.constFirst().first))
queue.removeFirst();
while (!queue.isEmpty()) {
QueuePage *page = queue.first();
if (!tryStart(page->first()))
break;
page->pop();
if (page->isFinished()) {
queue.removeFirst();
delete page;
}
}
}
bool QThreadPoolPrivate::tooManyThreadsActive() const
@ -240,6 +265,7 @@ bool QThreadPoolPrivate::tooManyThreadsActive() const
*/
void QThreadPoolPrivate::startThread(QRunnable *runnable)
{
Q_ASSERT(runnable != nullptr);
QScopedPointer <QThreadPoolThread> thread(new QThreadPoolThread(this));
thread->setObjectName(QLatin1String("Thread (pooled)"));
Q_ASSERT(!allThreads.contains(thread.data())); // if this assert hits, we have an ABA problem (deleted threads don't get removed here)
@ -303,12 +329,14 @@ bool QThreadPoolPrivate::waitForDone(int msecs)
void QThreadPoolPrivate::clear()
{
QMutexLocker locker(&mutex);
for (QVector<QPair<QRunnable *, int> >::const_iterator it = queue.constBegin();
it != queue.constEnd(); ++it) {
QRunnable* r = it->first;
if (r->autoDelete() && !--r->ref)
delete r;
for (QueuePage *page : qAsConst(queue)) {
while (!page->isFinished()) {
QRunnable *r = page->pop();
if (r && r->autoDelete() && !--r->ref)
delete r;
}
}
qDeleteAll(queue);
queue.clear();
}
@ -333,22 +361,21 @@ bool QThreadPool::tryTake(QRunnable *runnable)
{
Q_D(QThreadPool);
if (runnable == 0)
if (runnable == nullptr)
return false;
{
QMutexLocker locker(&d->mutex);
auto it = d->queue.begin();
auto end = d->queue.end();
while (it != end) {
if (it->first == runnable) {
d->queue.erase(it);
for (QueuePage *page : qAsConst(d->queue)) {
if (page->tryTake(runnable)) {
if (page->isFinished()) {
d->queue.removeOne(page);
delete page;
}
if (runnable->autoDelete())
--runnable->ref; // undo ++ref in start()
return true;
}
++it;
}
}

View File

@ -63,6 +63,87 @@
QT_BEGIN_NAMESPACE
class QueuePage {
public:
enum {
MaxPageSize = 256
};
QueuePage(QRunnable *runnable, int pri)
: m_priority(pri)
{
push(runnable);
}
bool isFull() {
return m_lastIndex >= MaxPageSize - 1;
}
bool isFinished() {
return m_firstIndex > m_lastIndex;
}
void push(QRunnable *runnable) {
Q_ASSERT(runnable != nullptr);
Q_ASSERT(!isFull());
m_lastIndex += 1;
m_entries[m_lastIndex] = runnable;
}
void skipToNextOrEnd() {
while (!isFinished() && m_entries[m_firstIndex] == nullptr) {
m_firstIndex += 1;
}
}
QRunnable *first() {
Q_ASSERT(!isFinished());
QRunnable *runnable = m_entries[m_firstIndex];
Q_ASSERT(runnable);
return runnable;
}
QRunnable *pop() {
Q_ASSERT(!isFinished());
QRunnable *runnable = first();
Q_ASSERT(runnable);
// clear the entry although this should not be necessary
m_entries[m_firstIndex] = nullptr;
m_firstIndex += 1;
// make sure the next runnable returned by first() is not a nullptr
skipToNextOrEnd();
return runnable;
}
bool tryTake(QRunnable *runnable) {
Q_ASSERT(!isFinished());
for (int i = m_firstIndex; i <= m_lastIndex; i++) {
if (m_entries[i] == runnable) {
m_entries[i] = nullptr;
if (i == m_firstIndex) {
// make sure first() does not return a nullptr
skipToNextOrEnd();
}
return true;
}
}
return false;
}
int priority() const {
return m_priority;
}
private:
int m_priority = 0;
int m_firstIndex = 0;
int m_lastIndex = -1;
QRunnable *m_entries[MaxPageSize];
};
class QThreadPoolThread;
class Q_CORE_EXPORT QThreadPoolPrivate : public QObjectPrivate
{
@ -84,12 +165,13 @@ public:
bool waitForDone(int msecs);
void clear();
void stealAndRunRunnable(QRunnable *runnable);
void deletePageIfFinished(QueuePage *page);
mutable QMutex mutex;
QList<QThreadPoolThread *> allThreads;
QQueue<QThreadPoolThread *> waitingThreads;
QQueue<QThreadPoolThread *> expiredThreads;
QVector<QPair<QRunnable *, int> > queue;
QVector<QueuePage*> queue;
QWaitCondition noActiveThreads;
int expiryTimeout = 30000;

View File

@ -195,7 +195,7 @@ QT_BEGIN_NAMESPACE
\inmodule QtDBus
\brief Information about one interface on the bus.
Each interface on D-Bus has an unique \a name, identifying where that interface was defined.
Each interface on D-Bus has a unique \a name, identifying where that interface was defined.
Interfaces may have annotations, methods, signals and properties, but none are mandatory.
*/

View File

@ -228,7 +228,6 @@ Q_GLOBAL_STATIC(QReadWriteLock, customTypesLock)
void QDBusMetaType::registerMarshallOperators(int id, MarshallFunction mf,
DemarshallFunction df)
{
QByteArray var;
QVector<QDBusCustomTypeInfo> *ct = customTypes();
if (id < 0 || !mf || !df || !ct)
return; // error!

View File

@ -1124,7 +1124,7 @@ QWheelEvent::QWheelEvent(const QPointF &pos, const QPointF& globalPos,
The event is propagated up the parent widget chain until a widget
accepts it or an event filter consumes it.
The QWidget::setEnable() function can be used to enable or disable
The QWidget::setEnabled() function can be used to enable or disable
mouse and keyboard events for a widget.
The event handlers QWidget::keyPressEvent(), QWidget::keyReleaseEvent(),
@ -2335,6 +2335,13 @@ QVariant QInputMethodQueryEvent::value(Qt::InputMethodQuery query) const
cursor and touchpad. Qt recognizes these by their names. Otherwise, if the
tablet is configured to use the evdev driver, there will be only one device
and applications may not be able to distinguish the stylus from the eraser.
\section1 Notes for Windows Users
Tablet support currently requires the WACOM windows driver providing the DLL
\c{wintab32.dll} to be installed. It is contained in older packages,
for example \c{pentablet_5.3.5-3.exe}.
*/
/*!
@ -2783,13 +2790,13 @@ Q_GLOBAL_STATIC(NativeGestureEventDataHash, g_nativeGestureEventDataHash)
\a realValue is the \macos event parameter, \a sequenceId and \a intValue are the Windows event parameters.
\since 5.10
*/
QNativeGestureEvent::QNativeGestureEvent(Qt::NativeGestureType type, const QTouchDevice *dev, const QPointF &localPos, const QPointF &windowPos,
QNativeGestureEvent::QNativeGestureEvent(Qt::NativeGestureType type, const QTouchDevice *device, const QPointF &localPos, const QPointF &windowPos,
const QPointF &screenPos, qreal realValue, ulong sequenceId, quint64 intValue)
: QInputEvent(QEvent::NativeGesture), mGestureType(type),
mLocalPos(localPos), mWindowPos(windowPos), mScreenPos(screenPos), mRealValue(realValue),
mSequenceId(sequenceId), mIntValue(intValue)
{
g_nativeGestureEventDataHash->insert(this, dev);
g_nativeGestureEventDataHash->insert(this, device);
}
QNativeGestureEvent::~QNativeGestureEvent()

View File

@ -531,7 +531,7 @@ QVariant QPlatformTheme::defaultThemeHint(ThemeHint hint)
case UiEffects:
return QVariant(int(0));
case SpellCheckUnderlineStyle:
return QVariant(int(QTextCharFormat::SpellCheckUnderline));
return QVariant(int(QTextCharFormat::WaveUnderline));
case TabFocusBehavior:
return QVariant(int(Qt::TabFocusAllControls));
case IconPixmapSizes:

View File

@ -5572,6 +5572,8 @@ static void qt_alphamapblit_generic(QRasterBuffer *rasterBuffer,
int start = qMax<int>(x, clip.x);
int end = qMin<int>(x + mapWidth, clip.x + clip.len);
if (end <= start)
continue;
Q_ASSERT(end - start <= buffer_size);
QRgba64 *dest = destFetch64((QRgba64*)buffer, rasterBuffer, start, clip.y, end - start);
@ -5845,6 +5847,8 @@ static void qt_alphargbblit_generic(QRasterBuffer *rasterBuffer,
int start = qMax<int>(x, clip.x);
int end = qMin<int>(x + mapWidth, clip.x + clip.len);
if (end <= start)
continue;
Q_ASSERT(end - start <= buffer_size);
QRgba64 *dest = destFetch64((QRgba64*)buffer, rasterBuffer, start, clip.y, end - start);

View File

@ -1638,7 +1638,7 @@ void QRasterPaintEngine::stroke(const QVectorPath &path, const QPen &pen)
QPointF p = lines[i].p1();
QLineF line = s->matrix.map(QLineF(QPointF(p.x() - width*0.5, p.y()),
QPointF(p.x() + width*0.5, p.y())));
d->rasterizer->rasterizeLine(line.p1(), line.p2(), 1);
d->rasterizer->rasterizeLine(line.p1(), line.p2(), width / line.length());
}
continue;
}

View File

@ -6261,6 +6261,8 @@ static void drawTextItemDecoration(QPainter *painter, const QPointF &pos, const
QPlatformTheme *theme = QGuiApplicationPrivate::platformTheme();
if (theme)
underlineStyle = QTextCharFormat::UnderlineStyle(theme->themeHint(QPlatformTheme::SpellCheckUnderlineStyle).toInt());
if (underlineStyle == QTextCharFormat::SpellCheckUnderline) // still not resolved
underlineStyle = QTextCharFormat::WaveUnderline;
}
if (underlineStyle == QTextCharFormat::WaveUnderline) {

View File

@ -1147,8 +1147,6 @@ void QDashStroker::processCurrentSubpath()
QLineF cline;
QPainterPath dashPath;
QSubpathFlatIterator it(&m_elements, m_dashThreshold);
qfixed2d prev = it.next();

View File

@ -1333,9 +1333,9 @@ bool QTextFormat::operator==(const QTextFormat &rhs) const
\value DashDotLine Dashs and dots are drawn using Qt::DashDotLine.
\value DashDotDotLine Underlines draw drawn using Qt::DashDotDotLine.
\value WaveUnderline The text is underlined using a wave shaped line.
\value SpellCheckUnderline The underline is drawn depending on the QStyle::SH_SpellCeckUnderlineStyle
style hint of the QApplication style. By default this is mapped to
WaveUnderline, on \macos it is mapped to DashDotLine.
\value SpellCheckUnderline The underline is drawn depending on the SpellCheckUnderlineStyle
theme hint of QPlatformTheme. By default this is mapped to
WaveUnderline, on \macos it is mapped to DotLine.
\sa Qt::PenStyle
*/

View File

@ -381,7 +381,6 @@ void QTextOdfWriter::writeInlineCharacter(QXmlStreamWriter &writer, const QTextF
}
if (image.isNull()) {
QString context;
if (image.isNull()) { // try direct loading
name = imageFormat.name(); // remove qrc:/ prefix again
image.load(name);

View File

@ -1051,10 +1051,12 @@ void QGridLayoutEngine::setGeometries(const QRectF &contentsGeometry, const QAbs
if (m_snapToPixelGrid) {
// x and y should already be rounded, but the call to geometryWithin() above might
// result in a geom with x,y at half-pixels (due to centering within the cell)
geom.setX(qround(geom.x()));
// QRectF may change the width as it wants to maintain the right edge. In this
// case the width need to be preserved.
geom.moveLeft(qround(geom.x()));
// Do not snap baseline aligned items, since that might cause the baselines to not be aligned.
if (align != Qt::AlignBaseline)
geom.setY(qround(geom.y()));
geom.moveTop(qround(geom.y()));
}
visualRect(&geom, visualDirection(), contentsGeometry);
item->setGeometry(geom);

View File

@ -59,7 +59,7 @@
QT_BEGIN_NAMESPACE
// internal helper. Converts an integer value to an unique string token
// internal helper. Converts an integer value to a unique string token
template <typename T>
struct HexString
{

View File

@ -114,7 +114,7 @@ void QHstsStore::synchronize()
if (observedPolicies.size()) {
beginHstsGroups();
for (const QHstsPolicy &policy : observedPolicies) {
for (const QHstsPolicy &policy : qAsConst(observedPolicies)) {
const QString key(host_name_to_settings_key(policy.host()));
// If we fail to write a new, updated policy, we also remove the old one.
if (policy.isExpired() || !serializePolicy(key, policy))

View File

@ -476,6 +476,8 @@ bool QHttpMultiPartIODevice::isSequential() const
bool QHttpMultiPartIODevice::reset()
{
// Reset QIODevice's data
QIODevice::reset();
for (int a = 0; a < multiPart->parts.count(); a++)
if (!multiPart->parts[a].d->reset())
return false;

View File

@ -604,14 +604,21 @@ void QHttpNetworkConnectionChannel::handleStatus()
case 302:
case 303:
case 305:
case 307: {
case 307:
case 308: {
// Parse the response headers and get the "location" url
QUrl redirectUrl = connection->d_func()->parseRedirectResponse(socket, reply);
if (redirectUrl.isValid())
reply->setRedirectUrl(redirectUrl);
if (qobject_cast<QHttpNetworkConnection *>(connection))
if ((statusCode == 307 || statusCode == 308) && !resetUploadData()) {
// Couldn't reset the upload data, which means it will be unable to POST the data -
// this would lead to a long wait until it eventually failed and then retried.
// Instead of doing that we fail here instead, resetUploadData will already have emitted
// a ContentReSendError, so we're done.
} else if (qobject_cast<QHttpNetworkConnection *>(connection)) {
QMetaObject::invokeMethod(connection, "_q_startNextRequest", Qt::QueuedConnection);
}
break;
}
case 401: // auth required

View File

@ -96,7 +96,7 @@ void QHttpNetworkReply::setRedirectUrl(const QUrl &url)
bool QHttpNetworkReply::isHttpRedirect(int statusCode)
{
return (statusCode == 301 || statusCode == 302 || statusCode == 303
|| statusCode == 305 || statusCode == 307);
|| statusCode == 305 || statusCode == 307 || statusCode == 308);
}
qint64 QHttpNetworkReply::contentLength() const

View File

@ -140,7 +140,7 @@ void QNetworkCookieJar::setAllCookies(const QList<QNetworkCookie> &cookieList)
static inline bool isParentPath(const QString &path, const QString &reference)
{
if (path.startsWith(reference)) {
if ((path.isEmpty() && reference == QLatin1String("/")) || path.startsWith(reference)) {
//The cookie-path and the request-path are identical.
if (path.length() == reference.length())
return true;

View File

@ -297,7 +297,7 @@ QNetworkReplyPrivate::QNetworkReplyPrivate()
This signal is emitted if the QNetworkRequest::FollowRedirectsAttribute was
set in the request and the server responded with a 3xx status (specifically
301, 302, 303, 305 or 307 status code) with a valid url in the location
301, 302, 303, 305, 307 or 308 status code) with a valid url in the location
header, indicating a HTTP redirect. The \a url parameter contains the new
redirect url as returned by the server in the location header.

View File

@ -165,6 +165,16 @@ static QHash<QByteArray, QByteArray> parseHttpOptionHeader(const QByteArray &hea
}
}
#if QT_CONFIG(bearermanagement)
static bool isSessionNeeded(const QUrl &url)
{
// Connections to the local machine does not require a session
QString host = url.host().toLower();
return !QHostAddress(host).isLoopback() && host != QLatin1String("localhost")
&& host != QSysInfo::machineHostName().toLower();
}
#endif // bearer management
QNetworkReplyHttpImpl::QNetworkReplyHttpImpl(QNetworkAccessManager* const manager,
const QNetworkRequest& request,
QNetworkAccessManager::Operation& operation,
@ -1115,10 +1125,15 @@ QNetworkAccessManager::Operation QNetworkReplyHttpImplPrivate::getRedirectOperat
switch (currentOp) {
case QNetworkAccessManager::HeadOperation:
return QNetworkAccessManager::HeadOperation;
case QNetworkAccessManager::PostOperation:
// We MUST keep using POST when being redirected with 307 or 308.
if (statusCode == 307 || statusCode == 308)
return QNetworkAccessManager::PostOperation;
break;
default:
break;
}
// For now, we're always returning GET for anything other than HEAD
// Use GET for everything else.
return QNetworkAccessManager::GetOperation;
}
@ -1193,11 +1208,30 @@ void QNetworkReplyHttpImplPrivate::followRedirect()
{
Q_Q(QNetworkReplyHttpImpl);
rawHeaders.clear();
cookedHeaders.clear();
if (managerPrivate->thread)
managerPrivate->thread->disconnect();
#if QT_CONFIG(bearermanagement)
// If the original request didn't need a session (i.e. it was to localhost)
// then we might not have a session open, to which to redirect, if the
// new URL is remote. When this happens, we need to open the session now:
if (managerPrivate && isSessionNeeded(url)) {
if (auto session = managerPrivate->getNetworkSession()) {
if (session->state() != QNetworkSession::State::Connected || !session->isOpen()) {
startWaitForSession(session);
// Need to set 'request' to the redirectRequest so that when QNAM restarts
// the request after the session starts it will not repeat the previous request.
request = redirectRequest;
// Return now, QNAM will start the request when the session has started.
return;
}
}
}
#endif // bearer management
QMetaObject::invokeMethod(q, "start", Qt::QueuedConnection,
Q_ARG(QNetworkRequest, redirectRequest));
}
@ -1210,6 +1244,7 @@ void QNetworkReplyHttpImplPrivate::checkForRedirect(const int statusCode)
case 302: // Found
case 303: // See Other
case 307: // Temporary Redirect
case 308: // Permanent Redirect
// What do we do about the caching of the HTML note?
// The response to a 303 MUST NOT be cached, while the response to
// all of the others is cacheable if the headers indicate it to be
@ -1783,10 +1818,8 @@ bool QNetworkReplyHttpImplPrivate::start(const QNetworkRequest &newHttpRequest)
}
// This is not ideal.
const QString host = url.host();
if (host == QLatin1String("localhost") ||
QHostAddress(host).isLoopback()) {
// Don't need an open session for localhost access.
if (!isSessionNeeded(url)) {
// Don't need to check for an open session if we don't need one.
postRequest(newHttpRequest);
return true;
}
@ -1810,6 +1843,34 @@ bool QNetworkReplyHttpImplPrivate::start(const QNetworkRequest &newHttpRequest)
#endif
}
#if QT_CONFIG(bearermanagement)
bool QNetworkReplyHttpImplPrivate::startWaitForSession(QSharedPointer<QNetworkSession> &session)
{
Q_Q(QNetworkReplyHttpImpl);
state = WaitingForSession;
if (session) {
QObject::connect(session.data(), SIGNAL(error(QNetworkSession::SessionError)),
q, SLOT(_q_networkSessionFailed()), Qt::QueuedConnection);
if (!session->isOpen()) {
QVariant isBackground = request.attribute(QNetworkRequest::BackgroundRequestAttribute,
QVariant::fromValue(false));
session->setSessionProperty(QStringLiteral("ConnectInBackground"), isBackground);
session->open();
}
return true;
}
const Qt::ConnectionType connection = synchronous ? Qt::DirectConnection : Qt::QueuedConnection;
qWarning("Backend is waiting for QNetworkSession to connect, but there is none!");
QMetaObject::invokeMethod(q, "_q_error", connection,
Q_ARG(QNetworkReply::NetworkError, QNetworkReply::NetworkSessionFailedError),
Q_ARG(QString, QCoreApplication::translate("QNetworkReply", "Network session error.")));
QMetaObject::invokeMethod(q, "_q_finished", connection);
return false;
}
#endif // QT_CONFIG(bearermanagement)
void QNetworkReplyHttpImplPrivate::_q_startOperation()
{
Q_Q(QNetworkReplyHttpImpl);
@ -1837,24 +1898,8 @@ void QNetworkReplyHttpImplPrivate::_q_startOperation()
// backend failed to start because the session state is not Connected.
// QNetworkAccessManager will call reply->backend->start() again for us when the session
// state changes.
state = WaitingForSession;
if (session) {
QObject::connect(session.data(), SIGNAL(error(QNetworkSession::SessionError)),
q, SLOT(_q_networkSessionFailed()), Qt::QueuedConnection);
if (!session->isOpen()) {
session->setSessionProperty(QStringLiteral("ConnectInBackground"), isBackground);
session->open();
}
} else {
qWarning("Backend is waiting for QNetworkSession to connect, but there is none!");
QMetaObject::invokeMethod(q, "_q_error", synchronous ? Qt::DirectConnection : Qt::QueuedConnection,
Q_ARG(QNetworkReply::NetworkError, QNetworkReply::NetworkSessionFailedError),
Q_ARG(QString, QCoreApplication::translate("QNetworkReply", "Network session error.")));
QMetaObject::invokeMethod(q, "_q_finished", synchronous ? Qt::DirectConnection : Qt::QueuedConnection);
if (!startWaitForSession(session))
return;
}
} else if (session) {
QObject::connect(session.data(), SIGNAL(stateChanged(QNetworkSession::State)),
q, SLOT(_q_networkSessionStateChanged(QNetworkSession::State)),

View File

@ -161,6 +161,10 @@ signals:
class QNetworkReplyHttpImplPrivate: public QNetworkReplyPrivate
{
#if QT_CONFIG(bearermanagement)
bool startWaitForSession(QSharedPointer<QNetworkSession> &session);
#endif
public:
static QHttpNetworkRequest::Priority convert(const QNetworkRequest::Priority& prio);

View File

@ -89,31 +89,6 @@
},
"tests": {
"getaddrinfo": {
"label": "getaddrinfo()",
"type": "compile",
"test": {
"head": [
"#include <stdio.h>",
"#include <stdlib.h>",
"#ifdef __MINGW32__",
"# include <winsock2.h>",
"# include <ws2tcpip.h>",
"#else",
"# include <sys/types.h>",
"# include <sys/socket.h>",
"# include <netdb.h>",
"#endif"
],
"main": [
"addrinfo *res = 0;",
"(void) getaddrinfo(\"foo\", 0, 0, &res);",
"freeaddrinfo(res);",
"gai_strerror(0);"
]
},
"use": "network"
},
"getifaddrs": {
"label": "getifaddrs()",
"type": "compile",
@ -170,11 +145,6 @@
"emitIf": "config.darwin",
"output": [ "feature", "privateFeature" ]
},
"getaddrinfo": {
"label": "getaddrinfo()",
"condition": "tests.getaddrinfo",
"output": [ "feature" ]
},
"getifaddrs": {
"label": "getifaddrs()",
"condition": "tests.getifaddrs",
@ -337,7 +307,7 @@ For example:
"args": "corewlan",
"condition": "config.darwin"
},
"getaddrinfo", "getifaddrs", "ipv6ifname", "libproxy",
"getifaddrs", "ipv6ifname", "libproxy",
{
"type": "feature",
"args": "securetransport",

View File

@ -49,8 +49,6 @@ win32: {
SOURCES += kernel/qdnslookup_win.cpp \
kernel/qnetworkinterface_win.cpp
LIBS_PRIVATE += -ldnsapi -liphlpapi
DEFINES += WINVER=0x0600 _WIN32_WINNT=0x0600
} else {
SOURCES += kernel/qdnslookup_winrt.cpp \
kernel/qnetworkinterface_winrt.cpp

View File

@ -533,49 +533,6 @@ QHostAddress::QHostAddress(SpecialAddress address)
setAddress(address);
}
/*!
\overload
\since 5.8
Sets the special address specified by \a address.
*/
void QHostAddress::setAddress(SpecialAddress address)
{
d->clear();
Q_IPV6ADDR ip6;
memset(&ip6, 0, sizeof ip6);
quint32 ip4 = INADDR_ANY;
switch (address) {
case Null:
return;
case Broadcast:
ip4 = INADDR_BROADCAST;
break;
case LocalHost:
ip4 = INADDR_LOOPBACK;
break;
case AnyIPv4:
break;
case LocalHostIPv6:
ip6[15] = 1;
Q_FALLTHROUGH();
case AnyIPv6:
d->setAddress(ip6);
return;
case Any:
d->protocol = QAbstractSocket::AnyIPProtocol;
return;
}
// common IPv4 part
d->setAddress(ip4);
}
/*!
Destroys the host address object.
*/
@ -739,6 +696,49 @@ void QHostAddress::setAddress(const struct sockaddr *sockaddr)
#endif
}
/*!
\overload
\since 5.8
Sets the special address specified by \a address.
*/
void QHostAddress::setAddress(SpecialAddress address)
{
clear();
Q_IPV6ADDR ip6;
memset(&ip6, 0, sizeof ip6);
quint32 ip4 = INADDR_ANY;
switch (address) {
case Null:
return;
case Broadcast:
ip4 = INADDR_BROADCAST;
break;
case LocalHost:
ip4 = INADDR_LOOPBACK;
break;
case AnyIPv4:
break;
case LocalHostIPv6:
ip6[15] = 1;
Q_FALLTHROUGH();
case AnyIPv6:
d->setAddress(ip6);
return;
case Any:
d->protocol = QAbstractSocket::AnyIPProtocol;
return;
}
// common IPv4 part
d->setAddress(ip4);
}
/*!
Returns the IPv4 address as a number.

View File

@ -66,10 +66,6 @@
# include <gnu/lib-names.h>
#endif
#if defined (QT_NO_GETADDRINFO)
static QBasicMutex getHostByNameMutex;
#endif
QT_BEGIN_NAMESPACE
// Almost always the same. If not, specify in qplatformdefs.h.
@ -188,7 +184,6 @@ QHostInfo QHostInfoAgent::fromName(const QString &hostName)
QHostAddress address;
if (address.setAddress(hostName)) {
// Reverse lookup
#if !defined (QT_NO_GETADDRINFO)
sockaddr_in sa4;
sockaddr_in6 sa6;
sockaddr *sa = 0;
@ -211,12 +206,6 @@ QHostInfo QHostInfoAgent::fromName(const QString &hostName)
char hbuf[NI_MAXHOST];
if (sa && getnameinfo(sa, saSize, hbuf, sizeof(hbuf), 0, 0, 0) == 0)
results.setHostName(QString::fromLatin1(hbuf));
#else
in_addr_t inetaddr = qt_safe_inet_addr(hostName.toLatin1().constData());
struct hostent *ent = gethostbyaddr((const char *)&inetaddr, sizeof(inetaddr), AF_INET);
if (ent)
results.setHostName(QString::fromLatin1(ent->h_name));
#endif
if (results.hostName().isEmpty())
results.setHostName(address.toString());
@ -235,7 +224,6 @@ QHostInfo QHostInfoAgent::fromName(const QString &hostName)
return results;
}
#if !defined (QT_NO_GETADDRINFO)
// Call getaddrinfo, and place all IPv4 addresses at the start and
// the IPv6 addresses at the end of the address list in results.
addrinfo *res = 0;
@ -302,39 +290,6 @@ QHostInfo QHostInfoAgent::fromName(const QString &hostName)
results.setErrorString(QString::fromLocal8Bit(gai_strerror(result)));
}
#else
// Fall back to gethostbyname for platforms that don't define
// getaddrinfo. gethostbyname does not support IPv6, and it's not
// reentrant on all platforms. For now this is okay since we only
// use one QHostInfoAgent, but if more agents are introduced, locking
// must be provided.
QMutexLocker locker(&getHostByNameMutex);
hostent *result = gethostbyname(aceHostname.constData());
if (result) {
if (result->h_addrtype == AF_INET) {
QList<QHostAddress> addresses;
for (char **p = result->h_addr_list; *p != 0; p++) {
QHostAddress addr;
addr.setAddress(ntohl(*((quint32 *)*p)));
if (!addresses.contains(addr))
addresses.prepend(addr);
}
results.setAddresses(addresses);
} else {
results.setError(QHostInfo::UnknownError);
results.setErrorString(tr("Unknown address type"));
}
#if !defined(Q_OS_VXWORKS)
} else if (h_errno == HOST_NOT_FOUND || h_errno == NO_DATA
|| h_errno == NO_ADDRESS) {
results.setError(QHostInfo::HostNotFound);
results.setErrorString(tr("Host not found"));
#endif
} else {
results.setError(QHostInfo::UnknownError);
results.setErrorString(tr("Unknown error"));
}
#endif // !defined (QT_NO_GETADDRINFO)
#if defined(QHOSTINFO_DEBUG)
if (results.error() != QHostInfo::NoError) {
@ -377,11 +332,6 @@ QString QHostInfo::localDomainName()
if (local_res_init && local_res) {
// using thread-unsafe version
#if defined(QT_NO_GETADDRINFO)
// We have to call res_init to be sure that _res was initialized
// So, for systems without getaddrinfo (which is thread-safe), we lock the mutex too
QMutexLocker locker(&getHostByNameMutex);
#endif
local_res_init();
QString domainName = QUrl::fromAce(local_res->defdname);
if (domainName.isEmpty())

View File

@ -50,50 +50,12 @@ QT_BEGIN_NAMESPACE
//#define QHOSTINFO_DEBUG
// Older SDKs do not include the addrinfo struct declaration, so we
// include a copy of it here.
struct qt_addrinfo
{
int ai_flags;
int ai_family;
int ai_socktype;
int ai_protocol;
size_t ai_addrlen;
char *ai_canonname;
sockaddr *ai_addr;
qt_addrinfo *ai_next;
};
//###
#define QT_SOCKLEN_T int
#ifndef NI_MAXHOST // already defined to 1025 in ws2tcpip.h?
#define NI_MAXHOST 1024
#endif
typedef int (__stdcall *getnameinfoProto)(const sockaddr *, QT_SOCKLEN_T, const char *, DWORD, const char *, DWORD, int);
typedef int (__stdcall *getaddrinfoProto)(const char *, const char *, const qt_addrinfo *, qt_addrinfo **);
typedef int (__stdcall *freeaddrinfoProto)(qt_addrinfo *);
static getnameinfoProto local_getnameinfo = 0;
static getaddrinfoProto local_getaddrinfo = 0;
static freeaddrinfoProto local_freeaddrinfo = 0;
static bool resolveLibraryInternal()
{
// Attempt to resolve getaddrinfo(); without it we'll have to fall
// back to gethostbyname(), which has no IPv6 support.
#if defined (Q_OS_WINRT)
local_getaddrinfo = (getaddrinfoProto) &getaddrinfo;
local_freeaddrinfo = (freeaddrinfoProto) &freeaddrinfo;
local_getnameinfo = (getnameinfoProto) getnameinfo;
#else
local_getaddrinfo = (getaddrinfoProto) QSystemLibrary::resolve(QLatin1String("ws2_32"), "getaddrinfo");
local_freeaddrinfo = (freeaddrinfoProto) QSystemLibrary::resolve(QLatin1String("ws2_32"), "freeaddrinfo");
local_getnameinfo = (getnameinfoProto) QSystemLibrary::resolve(QLatin1String("ws2_32"), "getnameinfo");
#endif
return true;
}
Q_GLOBAL_STATIC_WITH_ARGS(bool, resolveLibrary, (resolveLibraryInternal()))
static void translateWSAError(int error, QHostInfo *results)
{
switch (error) {
@ -114,49 +76,39 @@ QHostInfo QHostInfoAgent::fromName(const QString &hostName)
{
QSysInfo::machineHostName(); // this initializes ws2_32.dll
// Load res_init on demand.
resolveLibrary();
QHostInfo results;
#if defined(QHOSTINFO_DEBUG)
qDebug("QHostInfoAgent::fromName(): looking up \"%s\" (IPv6 support is %s)",
hostName.toLatin1().constData(),
(local_getaddrinfo && local_freeaddrinfo) ? "enabled" : "disabled");
(getaddrinfo && freeaddrinfo) ? "enabled" : "disabled");
#endif
QHostAddress address;
if (address.setAddress(hostName)) {
// Reverse lookup
if (local_getnameinfo) {
sockaddr_in sa4;
sockaddr_in6 sa6;
sockaddr *sa;
QT_SOCKLEN_T saSize;
if (address.protocol() == QAbstractSocket::IPv4Protocol) {
sa = (sockaddr *)&sa4;
saSize = sizeof(sa4);
memset(&sa4, 0, sizeof(sa4));
sa4.sin_family = AF_INET;
sa4.sin_addr.s_addr = htonl(address.toIPv4Address());
} else {
sa = (sockaddr *)&sa6;
saSize = sizeof(sa6);
memset(&sa6, 0, sizeof(sa6));
sa6.sin6_family = AF_INET6;
memcpy(&sa6.sin6_addr, address.toIPv6Address().c, sizeof(sa6.sin6_addr));
}
char hbuf[NI_MAXHOST];
if (local_getnameinfo(sa, saSize, hbuf, sizeof(hbuf), 0, 0, 0) == 0)
results.setHostName(QString::fromLatin1(hbuf));
sockaddr_in sa4;
sockaddr_in6 sa6;
sockaddr *sa;
QT_SOCKLEN_T saSize;
if (address.protocol() == QAbstractSocket::IPv4Protocol) {
sa = (sockaddr *)&sa4;
saSize = sizeof(sa4);
memset(&sa4, 0, sizeof(sa4));
sa4.sin_family = AF_INET;
sa4.sin_addr.s_addr = htonl(address.toIPv4Address());
} else {
unsigned long addr = inet_addr(hostName.toLatin1().constData());
struct hostent *ent = gethostbyaddr((const char*)&addr, sizeof(addr), AF_INET);
if (ent)
results.setHostName(QString::fromLatin1(ent->h_name));
sa = (sockaddr *)&sa6;
saSize = sizeof(sa6);
memset(&sa6, 0, sizeof(sa6));
sa6.sin6_family = AF_INET6;
memcpy(&sa6.sin6_addr, address.toIPv6Address().c, sizeof(sa6.sin6_addr));
}
char hbuf[NI_MAXHOST];
if (getnameinfo(sa, saSize, hbuf, sizeof(hbuf), 0, 0, 0) == 0)
results.setHostName(QString::fromLatin1(hbuf));
if (results.hostName().isEmpty())
results.setHostName(address.toString());
results.setAddresses(QList<QHostAddress>() << address);
@ -172,64 +124,35 @@ QHostInfo QHostInfoAgent::fromName(const QString &hostName)
return results;
}
if (local_getaddrinfo && local_freeaddrinfo) {
// Call getaddrinfo, and place all IPv4 addresses at the start
// and the IPv6 addresses at the end of the address list in
// results.
qt_addrinfo *res;
int err = local_getaddrinfo(aceHostname.constData(), 0, 0, &res);
if (err == 0) {
QList<QHostAddress> addresses;
for (qt_addrinfo *p = res; p != 0; p = p->ai_next) {
switch (p->ai_family) {
case AF_INET: {
QHostAddress addr;
addr.setAddress(ntohl(((sockaddr_in *) p->ai_addr)->sin_addr.s_addr));
if (!addresses.contains(addr))
addresses.append(addr);
}
break;
case AF_INET6: {
QHostAddress addr;
addr.setAddress(((sockaddr_in6 *) p->ai_addr)->sin6_addr.s6_addr);
if (!addresses.contains(addr))
addresses.append(addr);
}
break;
default:
results.setError(QHostInfo::UnknownError);
results.setErrorString(tr("Unknown address type"));
}
addrinfo *res;
int err = getaddrinfo(aceHostname.constData(), 0, 0, &res);
if (err == 0) {
QList<QHostAddress> addresses;
for (addrinfo *p = res; p != 0; p = p->ai_next) {
switch (p->ai_family) {
case AF_INET: {
QHostAddress addr;
addr.setAddress(ntohl(((sockaddr_in *) p->ai_addr)->sin_addr.s_addr));
if (!addresses.contains(addr))
addresses.append(addr);
}
break;
case AF_INET6: {
QHostAddress addr;
addr.setAddress(((sockaddr_in6 *) p->ai_addr)->sin6_addr.s6_addr);
if (!addresses.contains(addr))
addresses.append(addr);
}
results.setAddresses(addresses);
local_freeaddrinfo(res);
} else {
translateWSAError(WSAGetLastError(), &results);
}
} else {
// Fall back to gethostbyname, which only supports IPv4.
hostent *ent = gethostbyname(aceHostname.constData());
if (ent) {
char **p;
QList<QHostAddress> addresses;
switch (ent->h_addrtype) {
case AF_INET:
for (p = ent->h_addr_list; *p != 0; p++) {
long *ip4Addr = (long *) *p;
QHostAddress temp;
temp.setAddress(ntohl(*ip4Addr));
addresses << temp;
}
break;
default:
results.setError(QHostInfo::UnknownError);
results.setErrorString(tr("Unknown address type"));
break;
}
results.setAddresses(addresses);
} else {
translateWSAError(WSAGetLastError(), &results);
}
results.setAddresses(addresses);
freeaddrinfo(res);
} else {
translateWSAError(WSAGetLastError(), &results);
}
#if defined(QHOSTINFO_DEBUG)

View File

@ -124,9 +124,7 @@ QT_BEGIN_NAMESPACE
\row \li Linux \li Supported \li Supported \li Supported
\row \li OS X \li Supported \li Supported \li Only for IPv6
\row \li Other Unix supporting RFC 3542 \li Only for IPv6 \li Only for IPv6 \li Only for IPv6
\row \li Windows XP and older \li Not supported \li Not supported \li Not supported
\row \li Windows Vista & up \li Supported \li Supported \li Supported
\row \li Windows CE \li Not supported \li Not supported \li Not supported
\row \li Windows (desktop) \li Supported \li Supported \li Supported
\row \li Windows RT \li Not supported \li Not supported \li Not supported
\endtable

View File

@ -56,6 +56,7 @@
// (http://sourceforge.net/p/mingw-w64/mailman/message/32935366/)
#include <winsock2.h>
#include <ws2ipdef.h>
#include <wincrypt.h>
#include <iphlpapi.h>
#include <ws2tcpip.h>

View File

@ -174,16 +174,6 @@ static inline int qt_safe_ioctl(int sockfd, unsigned long request, T arg)
#endif
}
// VxWorks' headers do not specify any const modifiers
static inline in_addr_t qt_safe_inet_addr(const char *cp)
{
#ifdef Q_OS_VXWORKS
return ::inet_addr((char *) cp);
#else
return ::inet_addr(cp);
#endif
}
static inline int qt_safe_sendmsg(int sockfd, const struct msghdr *msg, int flags)
{
#ifdef MSG_NOSIGNAL

View File

@ -454,10 +454,12 @@ QNetworkDatagram QUdpSocket::receiveDatagram(qint64 maxSize)
QAbstractSocketEngine::WantAll);
d->hasPendingData = false;
d->socketEngine->setReadNotificationEnabled(true);
if (readBytes < 0)
if (readBytes < 0) {
d->setErrorAndEmit(d->socketEngine->error(), d->socketEngine->errorString());
else if (readBytes != result.d->data.size())
result.d->data.truncate(readBytes);
readBytes = 0;
}
result.d->data.truncate(readBytes);
return result;
}

View File

@ -92,7 +92,7 @@ EphemeralSecKeychain::EphemeralSecKeychain()
{
const auto uuid = QUuid::createUuid();
if (uuid.isNull()) {
qCWarning(lcSsl) << "Failed to create an unique keychain name";
qCWarning(lcSsl) << "Failed to create a unique keychain name";
return;
}

View File

@ -666,7 +666,7 @@ static CTFontUIFontType fontTypeFromTheme(QPlatformTheme::Font f)
return kCTFontUIFontSystem;
case QPlatformTheme::TipLabelFont:
return kCTFontToolTipFontType;
return kCTFontUIFontToolTip;
case QPlatformTheme::StatusBarFont:
return kCTFontUIFontSystem;

View File

@ -1980,12 +1980,6 @@ QFont QWindowsFontDatabase::systemDefaultFont()
// long deprecated; the message font of the NONCLIENTMETRICS structure obtained by
// SystemParametersInfo(SPI_GETNONCLIENTMETRICS) should be used instead (see
// QWindowsTheme::refreshFonts(), typically "Segoe UI, 9pt"), which is larger.
// In single monitor setups, the point sizes revolve around 8 (depending on UI
// scale factor, but not proportional to it). However, in multi monitor setups,
// where the DPI of the primary monitor are smaller than those of the secondary,
// large bogus values are returned. Limit to 8.25 in that case.
if (GetSystemMetrics(SM_CMONITORS) > 1 && systemFont.pointSizeF() > 8.25)
systemFont.setPointSizeF(8.25);
#endif // Qt 5
qCDebug(lcQpaFonts) << __FUNCTION__ << systemFont;
return systemFont;

View File

@ -55,10 +55,10 @@
#if defined(Q_OS_WIN32)
// PMIB_TCPTABLE2 is only available since Vista
#if _WIN32_WINNT < 0x0600
#if _WIN32_WINNT < 0x0601
# undef _WIN32_WINNT
# define _WIN32_WINNT 0x0600
#endif // _WIN32_WINNT < 0x0600
# define _WIN32_WINNT 0x0601
#endif // _WIN32_WINNT < 0x0601
#include "../platformdefs_win.h"
#include <iphlpapi.h>
#endif

View File

@ -45,6 +45,7 @@
#include <winsock2.h>
#include <mswsock.h>
#undef interface
#include <wincrypt.h>
#include <winioctl.h>
QT_BEGIN_NAMESPACE

View File

@ -520,7 +520,7 @@ static inline int fromBase8(const char *s, const char *end)
{
int result = 0;
while (*s && s != end) {
if (*s <= '0' || *s >= '7')
if (*s < '0' || *s > '7')
return 0;
result *= 8;
result += *s - '0';

View File

@ -104,11 +104,11 @@ namespace QtAndroidAccessibility
static jintArray childIdListForAccessibleObject(JNIEnv *env, jobject /*thiz*/, jint objectId)
{
QAccessibleInterface *iface = interfaceFromId(objectId);
if (iface) {
if (iface && iface->isValid()) {
jintArray jArray = env->NewIntArray(jsize(iface->childCount()));
for (int i = 0; i < iface->childCount(); ++i) {
QAccessibleInterface *child = iface->child(i);
if (child) {
if (child && child->isValid()) {
QAccessible::Id ifaceId = QAccessible::uniqueId(child);
jint jid = ifaceId;
env->SetIntArrayRegion(jArray, i, 1, &jid);
@ -123,9 +123,9 @@ namespace QtAndroidAccessibility
static jint parentId(JNIEnv */*env*/, jobject /*thiz*/, jint objectId)
{
QAccessibleInterface *iface = interfaceFromId(objectId);
if (iface) {
if (iface && iface->isValid()) {
QAccessibleInterface *parent = iface->parent();
if (parent) {
if (parent && parent->isValid()) {
if (parent->role() == QAccessible::Application)
return -1;
return QAccessible::uniqueId(parent);
@ -151,7 +151,7 @@ namespace QtAndroidAccessibility
static jint hitTest(JNIEnv */*env*/, jobject /*thiz*/, jfloat x, jfloat y)
{
QAccessibleInterface *root = interfaceFromId(-1);
if (root) {
if (root && root->isValid()) {
QPoint pos = QHighDpi::fromNativePixels(QPoint(int(x), int(y)), root->window());
QAccessibleInterface *child = root->childAt(pos.x(), pos.y());
@ -170,7 +170,7 @@ namespace QtAndroidAccessibility
{
// qDebug() << "A11Y: CLICK: " << objectId;
QAccessibleInterface *iface = interfaceFromId(objectId);
if (iface && iface->actionInterface()) {
if (iface && iface->isValid() && iface->actionInterface()) {
if (iface->actionInterface()->actionNames().contains(QAccessibleActionInterface::pressAction()))
iface->actionInterface()->doAction(QAccessibleActionInterface::pressAction());
else
@ -182,13 +182,17 @@ namespace QtAndroidAccessibility
static jboolean scrollForward(JNIEnv */*env*/, jobject /*thiz*/, jint objectId)
{
QAccessibleInterface *iface = interfaceFromId(objectId);
return QAccessibleBridgeUtils::performEffectiveAction(iface, QAccessibleActionInterface::increaseAction());
if (iface && iface->isValid())
return QAccessibleBridgeUtils::performEffectiveAction(iface, QAccessibleActionInterface::increaseAction());
return false;
}
static jboolean scrollBackward(JNIEnv */*env*/, jobject /*thiz*/, jint objectId)
{
QAccessibleInterface *iface = interfaceFromId(objectId);
return QAccessibleBridgeUtils::performEffectiveAction(iface, QAccessibleActionInterface::decreaseAction());
if (iface && iface->isValid())
return QAccessibleBridgeUtils::performEffectiveAction(iface, QAccessibleActionInterface::decreaseAction());
return false;
}

View File

@ -450,6 +450,17 @@ static jboolean startQtAndroidPlugin(JNIEnv* /*env*/, jobject /*object*//*, jobj
static void *startMainMethod(void */*data*/)
{
{
JNIEnv* env = nullptr;
JavaVMAttachArgs args;
args.version = JNI_VERSION_1_6;
args.name = "QtMainThread";
args.group = NULL;
JavaVM *vm = QtAndroidPrivate::javaVM();
if (vm != 0)
vm->AttachCurrentThread(&env, &args);
}
QVarLengthArray<const char *> params(m_applicationParams.size());
for (int i = 0; i < m_applicationParams.size(); i++)
params[i] = static_cast<const char *>(m_applicationParams[i].constData());

View File

@ -1,6 +1,6 @@
TARGET = qcocoa
OBJECTIVE_SOURCES += main.mm \
SOURCES += main.mm \
qcocoaintegration.mm \
qcocoascreen.mm \
qcocoatheme.mm \
@ -32,9 +32,8 @@ OBJECTIVE_SOURCES += main.mm \
qcocoasystemtrayicon.mm \
qcocoaintrospection.mm \
qcocoakeymapper.mm \
qcocoamimetypes.mm
SOURCES += messages.cpp
qcocoamimetypes.mm \
messages.cpp
HEADERS += qcocoaintegration.h \
qcocoascreen.h \
@ -70,7 +69,7 @@ HEADERS += qcocoaintegration.h \
qcocoamimetypes.h
qtConfig(opengl.*) {
OBJECTIVE_SOURCES += qcocoaglcontext.mm
SOURCES += qcocoaglcontext.mm
HEADERS += qcocoaglcontext.h
}
@ -89,7 +88,7 @@ CONFIG += no_app_extension_api_only
qtHaveModule(widgets) {
QT_FOR_CONFIG += widgets
OBJECTIVE_SOURCES += \
SOURCES += \
qpaintengine_mac.mm \
qprintengine_mac.mm \
qcocoaprintersupport.mm \

View File

@ -92,7 +92,6 @@
QT_USE_NAMESPACE
@class QT_MANGLE_NAMESPACE(QNSMenu);
@class QT_MANGLE_NAMESPACE(QNSImageView);
@interface QT_MANGLE_NAMESPACE(QNSStatusItem) : NSObject <NSUserNotificationCenterDelegate>
@ -123,16 +122,8 @@ QT_USE_NAMESPACE
-(void)mousePressed:(NSEvent *)mouseEvent button:(Qt::MouseButton)mouseButton;
@end
@interface QT_MANGLE_NAMESPACE(QNSMenu) : NSMenu <NSMenuDelegate> {
QPlatformMenu *qmenu;
}
-(QPlatformMenu*)menu;
-(id)initWithQMenu:(QPlatformMenu*)qmenu;
@end
QT_NAMESPACE_ALIAS_OBJC_CLASS(QNSStatusItem);
QT_NAMESPACE_ALIAS_OBJC_CLASS(QNSImageView);
QT_NAMESPACE_ALIAS_OBJC_CLASS(QNSMenu);
QT_BEGIN_NAMESPACE
class QSystemTrayIconSys
@ -447,26 +438,4 @@ QT_END_NAMESPACE
@end
class QSystemTrayIconQMenu : public QPlatformMenu
{
public:
void doAboutToShow() { emit aboutToShow(); }
private:
QSystemTrayIconQMenu();
};
@implementation QNSMenu
-(id)initWithQMenu:(QPlatformMenu*)qm {
self = [super init];
if (self) {
self->qmenu = qm;
[self setDelegate:self];
}
return self;
}
-(QPlatformMenu*)menu {
return qmenu;
}
@end
#endif // QT_NO_SYSTEMTRAYICON

View File

@ -55,6 +55,7 @@
#include <QtGui/private/qguiapplication_p.h>
#include <QtGui/private/qcoregraphics_p.h>
#include <QtGui/qpainter.h>
#include <QtGui/qtextformat.h>
#include <QtFontDatabaseSupport/private/qcoretextfontdatabase_p.h>
#include <QtThemeSupport/private/qabstractfileiconengine_p.h>
#include <qpa/qplatformdialoghelper.h>
@ -344,6 +345,8 @@ QVariant QCocoaTheme::themeHint(ThemeHint hint) const
return QVariant(QChar(0x2022));
case QPlatformTheme::UiEffects:
return QVariant(int(HoverEffect));
case QPlatformTheme::SpellCheckUnderlineStyle:
return QVariant(int(QTextCharFormat::DotLine));
default:
break;
}

View File

@ -262,7 +262,7 @@ public: // for QNSView
bool m_hasModalSession;
bool m_frameStrutEventsEnabled;
bool m_isExposed;
QRect m_exposedRect;
int m_registerTouchCount;
bool m_resizableTransientParent;

View File

@ -150,7 +150,6 @@ QCocoaWindow::QCocoaWindow(QWindow *win, WId nativeHandle)
, m_needsInvalidateShadow(false)
, m_hasModalSession(false)
, m_frameStrutEventsEnabled(false)
, m_isExposed(false)
, m_registerTouchCount(0)
, m_resizableTransientParent(false)
, m_alertRequest(NoAlertRequest)
@ -692,7 +691,7 @@ void QCocoaWindow::lower()
bool QCocoaWindow::isExposed() const
{
return m_isExposed;
return !m_exposedRect.isEmpty();
}
bool QCocoaWindow::isOpaque() const
@ -1120,7 +1119,7 @@ void QCocoaWindow::handleGeometryChange()
void QCocoaWindow::handleExposeEvent(const QRegion &region)
{
const bool wasExposed = isExposed();
const QRect previouslyExposedRect = m_exposedRect;
// Ideally we'd implement isExposed() in terms of these properties,
// plus the occlusionState of the NSWindow, and let the expose event
@ -1133,27 +1132,29 @@ void QCocoaWindow::handleExposeEvent(const QRegion &region)
// a window being obscured is an empty region, and in the case of
// a drawRect call is a non-null region, even if occlusionState
// is still hidden. This ensures the window is prepared for display.
m_isExposed = m_view.window.visible
&& m_view.window.screen
&& !geometry().size().isEmpty()
&& !region.isEmpty()
&& !m_view.hiddenOrHasHiddenAncestor;
if (m_view.window.visible && m_view.window.screen
&& !geometry().size().isEmpty() && !region.isEmpty()
&& !m_view.hiddenOrHasHiddenAncestor) {
m_exposedRect = region.boundingRect();
} else {
m_exposedRect = QRect();
}
QWindowPrivate *windowPrivate = qt_window_private(window());
if (windowPrivate->updateRequestPending) {
// We can only deliver update request events when the window is exposed,
// and we also have to make sure we deliver the first expose event after
// becoming exposed as a real expose event, otherwise the exposed state
// of the QWindow is never updated.
// FIXME: Should this logic live in QGuiApplication?
if (wasExposed && m_isExposed) {
// and we also have to make sure we deliver any change to the exposed
// rect as a real expose event (including going from non-exposed to
// exposed). FIXME: Should this logic live in QGuiApplication?
if (isExposed() && m_exposedRect == previouslyExposedRect) {
qCDebug(lcQpaCocoaWindow) << "QCocoaWindow::handleExposeEvent" << window() << region << "as update request";
windowPrivate->deliverUpdateRequest();
return;
} else {
// Since updateRequestPending is still set, we will issue a deferred setNeedsDisplay
// from drawRect and get back into this code on the next display cycle, delivering
// the pending update request.
}
// FIXME: Should we re-trigger setNeedsDisplay in case of !wasExposed && m_isExposed?
// Or possibly send the expose event first, and then the update request?
}
qCDebug(lcQpaCocoaWindow) << "QCocoaWindow::handleExposeEvent" << window() << region << "isExposed" << isExposed();
@ -1669,6 +1670,7 @@ void QCocoaWindow::applyContentBorderThickness(NSWindow *window)
if (!m_drawContentBorderGradient) {
window.styleMask = window.styleMask & ~NSTexturedBackgroundWindowMask;
[window.contentView.superview setNeedsDisplay:YES];
window.titlebarAppearsTransparent = NO;
return;
}
@ -1693,6 +1695,7 @@ void QCocoaWindow::applyContentBorderThickness(NSWindow *window)
int effectiveBottomContentBorderThickness = m_bottomContentBorderThickness;
[window setStyleMask:[window styleMask] | NSTexturedBackgroundWindowMask];
window.titlebarAppearsTransparent = YES;
[window setContentBorderThickness:effectiveTopContentBorderThickness forEdge:NSMaxYEdge];
[window setAutorecalculatesContentBorderThickness:NO forEdge:NSMaxYEdge];

View File

@ -324,12 +324,13 @@ Q_LOGGING_CATEGORY(lcQpaTablet, "qt.qpa.input.tablet")
m_platformWindow->handleExposeEvent(exposedRegion);
// A call to QWindow::requestUpdate was issued during the expose event, but
// AppKit will reset the needsDisplay state of the view after completing the
// current display cycle, so we need to defer the request to redisplay.
// FIXME: Perhaps this should be a trigger to enable CADisplayLink?
if (qt_window_private(m_platformWindow->window())->updateRequestPending) {
qCDebug(lcQpaCocoaWindow) << "[QNSView drawRect:] deferring setNeedsDisplay";
// A call to QWindow::requestUpdate was issued during the expose event, or we
// had to deliver a real expose event and still need to deliver the update.
// But AppKit will reset the needsDisplay state of the view after completing
// the current display cycle, so we need to defer the request to redisplay.
// FIXME: Perhaps this should be a trigger to enable CADisplayLink?
qCDebug(lcQpaCocoaWindow) << "[QNSView drawRect:] issuing deferred setNeedsDisplay due to pending update request";
dispatch_async(dispatch_get_main_queue (), ^{
[self setNeedsDisplay:YES];
});

View File

@ -2,9 +2,10 @@ TARGET = qdirect2d
QT += \
core-private gui-private \
eventdispatcher_support-private accessibility_support-private \
eventdispatcher_support-private \
fontdatabase_support-private theme_support-private
qtConfig(accessibility): QT += accessibility_support-private
qtConfig(vulkan): QT += vulkan_support-private
LIBS += -ldwmapi -ld2d1 -ld3d11 -ldwrite -lVersion -lgdi32

View File

@ -47,7 +47,9 @@
#include "qwindowsmenu.h"
#include "qwindowsmime.h"
#include "qwindowsinputcontext.h"
#include "qwindowstabletsupport.h"
#if QT_CONFIG(tabletevent)
# include "qwindowstabletsupport.h"
#endif
#include "qwindowstheme.h"
#include <private/qguiapplication_p.h>
#ifndef QT_NO_ACCESSIBILITY

View File

@ -39,7 +39,9 @@
#define QT_NO_URL_CAST_FROM_STRING 1
#define _WIN32_WINNT 0x0600
#ifndef _WIN32_WINNT
#define _WIN32_WINNT 0x0601
#endif
#include "qwindowscombase.h"
#include "qwindowsdialoghelpers.h"

View File

@ -37,13 +37,6 @@
**
****************************************************************************/
#if defined(WINVER) && WINVER < 0x0601
# undef WINVER
#endif
#if !defined(WINVER)
# define WINVER 0x0601 // Enable touch functions for MinGW
#endif
#include "qwindowsmousehandler.h"
#include "qwindowskeymapper.h"
#include "qwindowscontext.h"

View File

@ -352,16 +352,26 @@ bool QWindowsTabletSupport::translateTabletProximityEvent(WPARAM /* wParam */, L
{
PACKET proximityBuffer[1]; // we are only interested in the first packet in this case
const int totalPacks = QWindowsTabletSupport::m_winTab32DLL.wTPacketsGet(m_context, 1, proximityBuffer);
if (!totalPacks)
return false;
if (!LOWORD(lParam)) {
qCDebug(lcQpaTablet) << "leave proximity for device #" << m_currentDevice;
QWindowSystemInterface::handleTabletLeaveProximityEvent(proximityBuffer[0].pkTime,
m_devices.at(m_currentDevice).currentDevice,
m_devices.at(m_currentDevice).currentPointerType,
m_devices.at(m_currentDevice).uniqueId);
if (totalPacks > 0) {
QWindowSystemInterface::handleTabletLeaveProximityEvent(proximityBuffer[0].pkTime,
m_devices.at(m_currentDevice).currentDevice,
m_devices.at(m_currentDevice).currentPointerType,
m_devices.at(m_currentDevice).uniqueId);
} else {
QWindowSystemInterface::handleTabletLeaveProximityEvent(m_devices.at(m_currentDevice).currentDevice,
m_devices.at(m_currentDevice).currentPointerType,
m_devices.at(m_currentDevice).uniqueId);
}
return true;
}
if (!totalPacks)
return false;
const UINT currentCursor = proximityBuffer[0].pkCursor;
UINT physicalCursorId;
QWindowsTabletSupport::m_winTab32DLL.wTInfo(WTI_CURSORS + currentCursor, CSR_PHYSID, &physicalCursorId);

Some files were not shown because too many files have changed in this diff Show More