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

Conflicts:
	src/gui/kernel/qguiapplication.cpp
	src/platformsupport/input/libinput/qlibinputpointer.cpp
	src/plugins/platforminputcontexts/ibus/qibusplatforminputcontext.h
	src/plugins/platforms/cocoa/qcocoawindow.h
	src/testlib/qtestsystem.h

Change-Id: I5975ffb3261c2dd82fe02ec4e57df7c0950226c5
This commit is contained in:
Liang Qi 2017-09-26 16:08:55 +02:00
commit aadfe7d634
385 changed files with 4158 additions and 3778 deletions

View File

@ -144,6 +144,7 @@ Build options:
-ltcg ................ Use Link Time Code Generation [no] -ltcg ................ Use Link Time Code Generation [no]
-use-gold-linker ..... Use the GNU gold linker [auto] -use-gold-linker ..... Use the GNU gold linker [auto]
-incredibuild-xge .... Use the IncrediBuild XGE [no] (Windows only) -incredibuild-xge .... Use the IncrediBuild XGE [no] (Windows only)
-ccache .............. Use the ccache compiler cache [no] (Unix only)
-make-tool <tool> .... Use <tool> to build qmake [nmake] (Windows only) -make-tool <tool> .... Use <tool> to build qmake [nmake] (Windows only)
-mp .................. Use multiple processors for compilation (MSVC only) -mp .................. Use multiple processors for compilation (MSVC only)

View File

@ -61,6 +61,7 @@
"avx2": "boolean", "avx2": "boolean",
"avx512": { "type": "boolean", "name": "avx512f" }, "avx512": { "type": "boolean", "name": "avx512f" },
"c++std": "cxxstd", "c++std": "cxxstd",
"ccache": { "type": "boolean", "name": "ccache" },
"commercial": "void", "commercial": "void",
"compile-examples": { "type": "boolean", "name": "compile_examples" }, "compile-examples": { "type": "boolean", "name": "compile_examples" },
"confirm-license": "void", "confirm-license": "void",
@ -635,6 +636,11 @@
"label": "IncrediBuild", "label": "IncrediBuild",
"type": "files", "type": "files",
"files": [ "BuildConsole.exe", "xgConsole.exe" ] "files": [ "BuildConsole.exe", "xgConsole.exe" ]
},
"ccache": {
"label": "ccache",
"type": "files",
"files": [ "ccache" ]
} }
}, },
@ -1246,6 +1252,12 @@
"condition": "tests.incredibuild_xge", "condition": "tests.incredibuild_xge",
"output": [ "publicConfig" ] "output": [ "publicConfig" ]
}, },
"ccache": {
"label": "Using ccache",
"autoDetect": false,
"condition": "config.unix && tests.ccache",
"output": [ "privateConfig" ]
},
"msvc_mp": { "msvc_mp": {
"label": "Use multiple processors when compiling with MSVC", "label": "Use multiple processors when compiling with MSVC",
"emitIf": "config.msvc", "emitIf": "config.msvc",
@ -1353,6 +1365,11 @@ Configure with '-qreal float' to create a build that is binary-compatible with 5
"type": "firstAvailableFeature", "type": "firstAvailableFeature",
"args": "c++1z c++14 c++11" "args": "c++1z c++14 c++11"
}, },
{
"type": "feature",
"args": "ccache",
"condition": "config.unix"
},
"use_gold_linker", "use_gold_linker",
{ {
"type": "feature", "type": "feature",

288
dist/changes-5.6.3 vendored Normal file
View File

@ -0,0 +1,288 @@
Qt 5.6.3 is a bug-fix release. It maintains both forward and backward
compatibility (source and binary) with previous Qt 5.6.x releases.
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.6 series is binary compatible with the 5.5.x series.
Applications compiled for 5.5 will continue to run with 5.6.
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.
*****************************************************************************
* License Changes *
*****************************************************************************
- Static libraries that are linked into executables (winmain and
qopenglextensions) are now licensed under BSD _and_ commercial licenses.
******************************************************************************
* Important Behavior Changes *
******************************************************************************
- QPluginLoader:
* [QTBUG-49061] QPluginLoader no longer performs the actual unloading of
the plugin either on destruction or when unload() is called. This does
not affect QLibrary and QLibrary::unload().
******************************************************************************
* Library *
******************************************************************************
QtCore
------
- QDir:
* [QTBUG-58390] Fixed the implementation of mkpath() to not attempt to
mkdir directories that already exist, especially those in automount
filesystems (like /home).
- QHash / QMultiHash:
* [QTBUG-60395] Fixed a bug that caused operator== not to return true if
two containers had the elements with duplicate keys but in different
order.
- QLocale:
* [QTBUG-59159] Fixed the parsing of day-of-week names that start with the
name of another day.
- QObject:
* [QTBUG-59500] disconnectNotify() is now called when a connection is
disconnected using its QMetaObject::Connection handle.
* [QTBUG-52439] Fixed a bug that would cause applications compiled with the
Intel compiler to fail to connect signals and slots.
- QUrl:
* [QTBUG-60364] Fixed a bug that caused certain domain names that look
like Internationalized Domain Names to become corrupt in decoded forms
of QUrl, notably toString() and toDisplayString().
* Updated the table of valid top level domains
- QVarLengthArray:
* Fixed a bug involving appending an item already in the container to
the container again.
* [QTBUG-57277] Fixed a crash when initializing the array with an empty
std::initializer_list.
QtSql
-----
- MySql
* Fixed the build of MySql plugin with MySql 5.0
* [QTBUG-53397] Fixed the parsing of tinyint(1) when used via prepared
statements.
- PostgreSQL:
* [QTBUG-59524] Fixed datetime formats when the system locale doesn't use
arabic numerals
QtDBus
------
- QDBusServer
* [QTBUG-55087] Fixed a bug causing certain messages that arrive soon after
the client connects not to be processed.
QtNetwork
---------
- QNetworkInterface
* Fixed the reporting of virtual interfaces on Linux.
- QSslSocket
* [QTBUG-43388][QTBUG-55170] Fixed a bug that caused the read buffer's max
size not to be respected when using SecureTransport
* [QTBUG-49554] Made sure that the QSslConfiguration is up-to-date when the
QNetworkReply::encrypted() signal is emitted.
QtGui
-----
- Various fixes to our high DPI support.
- CSS parser:
* [QTBUG-53919] Fixed a crash while parsing malformed CSS.
- PDF writer:
* [QTBUG-56489] Monochrome images are now handled correctly.
- QImage:
* Fixed a crash when rendering to GrayScale8 images.
* [QTBUG-56252] Fixed an illegal memory access when rotating images.
* [QTBUG-59211] Improved rejection of corrupt images with invalid header
info.
- QMatrix4x4:
* operator*=() now calculates the correct result even if the RHS and LHS
are the same object.
- QPainter
* [QTBUG-14614] Fixed a read-after-free when using gradients.
* [QTBUG-56969] Fixed painting artifacts for certain dashed lines.
- Text:
* [QTBUG-55222] Always return a correct list of fallback fonts
* [QTBUG-55255][QTBUG-56714] Trailing whitespace are now properly taken
into account when shaping lines
* [QTBUG-53911] Fixed a crash that could happen if you were doing many
different text layouts with different fonts and superscript or
subscript alignment.
* [QTBUG-56659] Fixed a regression where raster fonts on Windows were
detected as smoothly scalable and thus rendering with said fonts in Qt
Quick would break.
* [QTBUG-51223] Fixed synthesized oblique for non-latin text on
platforms using the basic font database, such as Android.
* [QTBUG-56714] Fixed a bug where a no-break space would sometimes cause
the first character of the containing line to not be displayed.
* [QTBUG-48005] Fixed clipping errors and too small bounding rects for
some right-to-left text.
* [QTBUG-57241] Fixed a crash for very tall glyphs.
* [QTBUG-55569] Fixed Myanmar rendering with some fonts.
* [QTBUG-56659] Fixed the reporting of whether fonts are smoothly scalable
on Windows.
* [QTBUG-58364][QTBUG-42074][QTBUG-57003] Formatting characters are now
accepted as valid input.
QtWidgets
---------
- Input:
* [QTBUG-42074][QTBUG-57003] Characters in Private Use Area, as well as
zero-width joiners and zero-width non-joiners are now accepted as input
in QLineEdit and QTextEdit.
- QDockWidget:
* [QTBUG-7460][QTBUG-52354] Size of widgets no longer changed just because
they are in a floating dock.
* [QTBUG-58036] Dock widgets now have the correct parent after a drag.
* [QTBUG-58049] Fixed clearing the dock indicator when not over a floating
dock group window.
- QMainWindow:
* [QTBUG-56628] Fixed crash using takeCentralWidget when the central
widget was not set.
- QPixmapStyle:
* Now handles progress bars with minimum != 0 correctly.
- QPopup
* [QTBUG-57292] Popups blocked by modal dialogs are now properly closed.
- QTextEdit
* [QTBUG-55758] Placeholder text is no longer shown while composing text.
- QTooltip:
* [QTBUG-55523] QTooltip is now properly hidden when a close event is
received.
* [QTBUG-55523] Tooltips no longer prevent closing of the app on
lastWindowClosed()
- QWidget:
* [QTBUG-50589] Show and hide events are now properly sent to children on
minimize/restore.
* [QTBUG-53068] Fixed enter/leave events on popup menus.
- Style sheets:
* [QTBUG-55597] Now honors the font set on HeaderView section.
******************************************************************************
* Platform-specific Changes *
******************************************************************************
Android
-------
- [QTBUG-44697] Removed old work-around which was causing OpenGL shader
compilation to fail on updated Android emulators.
Darwin
------
- [QTBUG-61034] QT_NO_EXCEPTIONS is now correctly set for Objective C++
source files.
- [QTBUG-57165] Made QDir::tempPath() return the same directory as
NSTemporaryDirectory, instead of a hardcoded "/tmp".
- [QTBUG-55896] Fixed a bug that would cause QFileSystemWatcher to fail to
watch certain paths containing non-ASCII characters.
- [QTBUG-56124] Fixed a bug that would cause data corruption in QSettings
when storing QStrings containing NULs, when storing to native format.
- iOS specific:
* Starting from iOS 10, Apple requires all apps that need access to photos
to have the key 'NSPhotoLibraryUsageDescription' in the Info.plist.
Therefore, to get the same support in Qt (when, e.g., using a file
dialog), the Info.plist assigned to QMAKE_INFO_PLIST will need this key
as well.
* [QTBUG-49893] The shortcuts bar on iPad is now hidden when showing menus.
- macOS specific:
* Speech to text dictation now works for Qt text input.
* Various bug fixes to menu bar handling.
QNX
---
- Qt can now handle more than 256 file descriptors open in the same process,
up to a limit of 1000.
WinRT
-----
- Various fixes in our event and timer handling.
X11
---
- [QTBUG-55942] Qt::WindowNoState event is no longer sent when hiding
minimized windows.
- [QTBUG-49645] Fixed keyboard modifier state for drops from external apps.
- [QTBUG-48795] Fixed the keyboard state when processing key events.
******************************************************************************
* Compiler Specific Changes *
******************************************************************************
Visual Studio
-------------
- Visual Studio 2017 is now supported.
- [QTBUG-56594] PDB files are now properly generated even for static builds.
******************************************************************************
* Tools *
******************************************************************************
configure
---------
- Fixed builds that explicitly asked for -sdk iphoneos.
- [QTBUG-56388] Fixed the detection of the Microsoft compiler version when
the CL environment variable was set or when the compiler was configured to
another language (other than English).
qmake
-----
- [QTBUG-55505] Fixed an issue with iOS when the project path had a
whitespace.
- [QTBUG-56289] When cross-compiling on Windows to Unix targets, qmake no
longer generates chmod calls.
- [QTBUG-53905] Fixed qmake not to run moc twice on Objective C++ sources
listed in the OBJECTIVE_SOURCES variable.
- [QTBUG-56507] Fixed builds where a lex source refers to a file generated
by yacc.
- [QTBUG-57090][Darwin] Fixed the installation of asset catalog files.
qdbusxml2cpp
------------
- [QTBUG-21577] Fixed the generation of signals when the direction argument
was inverted from expected.

View File

@ -54,45 +54,45 @@
#include "client.h" #include "client.h"
Client::Client(QWidget *parent) Client::Client(QWidget *parent)
: QDialog(parent) : QDialog(parent),
hostLineEdit(new QLineEdit("fortune")),
getFortuneButton(new QPushButton(tr("Get Fortune"))),
statusLabel(new QLabel(tr("This examples requires that you run the "
"Local Fortune Server example as well."))),
socket(new QLocalSocket(this))
{ {
hostLabel = new QLabel(tr("&Server name:")); setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint);
hostLineEdit = new QLineEdit("fortune"); QLabel *hostLabel = new QLabel(tr("&Server name:"));
hostLabel->setBuddy(hostLineEdit); hostLabel->setBuddy(hostLineEdit);
statusLabel = new QLabel(tr("This examples requires that you run the "
"Fortune Server example as well."));
statusLabel->setWordWrap(true); statusLabel->setWordWrap(true);
getFortuneButton = new QPushButton(tr("Get Fortune"));
getFortuneButton->setDefault(true); getFortuneButton->setDefault(true);
QPushButton *quitButton = new QPushButton(tr("Quit"));
quitButton = new QPushButton(tr("Quit")); QDialogButtonBox *buttonBox = new QDialogButtonBox;
buttonBox = new QDialogButtonBox;
buttonBox->addButton(getFortuneButton, QDialogButtonBox::ActionRole); buttonBox->addButton(getFortuneButton, QDialogButtonBox::ActionRole);
buttonBox->addButton(quitButton, QDialogButtonBox::RejectRole); buttonBox->addButton(quitButton, QDialogButtonBox::RejectRole);
socket = new QLocalSocket(this); in.setDevice(socket);
in.setVersion(QDataStream::Qt_5_10);
connect(hostLineEdit, SIGNAL(textChanged(QString)), connect(hostLineEdit, &QLineEdit::textChanged,
this, SLOT(enableGetFortuneButton())); this, &Client::enableGetFortuneButton);
connect(getFortuneButton, SIGNAL(clicked()), connect(getFortuneButton, &QPushButton::clicked,
this, SLOT(requestNewFortune())); this, &Client::requestNewFortune);
connect(quitButton, SIGNAL(clicked()), this, SLOT(close())); connect(quitButton, &QPushButton::clicked, this, &Client::close);
connect(socket, SIGNAL(readyRead()), this, SLOT(readFortune())); connect(socket, &QLocalSocket::readyRead, this, &Client::readFortune);
connect(socket, SIGNAL(error(QLocalSocket::LocalSocketError)), connect(socket, QOverload<QLocalSocket::LocalSocketError>::of(&QLocalSocket::error),
this, SLOT(displayError(QLocalSocket::LocalSocketError))); this, &Client::displayError);
QGridLayout *mainLayout = new QGridLayout; QGridLayout *mainLayout = new QGridLayout(this);
mainLayout->addWidget(hostLabel, 0, 0); mainLayout->addWidget(hostLabel, 0, 0);
mainLayout->addWidget(hostLineEdit, 0, 1); mainLayout->addWidget(hostLineEdit, 0, 1);
mainLayout->addWidget(statusLabel, 2, 0, 1, 2); mainLayout->addWidget(statusLabel, 2, 0, 1, 2);
mainLayout->addWidget(buttonBox, 3, 0, 1, 2); mainLayout->addWidget(buttonBox, 3, 0, 1, 2);
setLayout(mainLayout);
setWindowTitle(tr("Fortune Client")); setWindowTitle(QGuiApplication::applicationDisplayName());
hostLineEdit->setFocus(); hostLineEdit->setFocus();
} }
@ -106,11 +106,9 @@ void Client::requestNewFortune()
void Client::readFortune() void Client::readFortune()
{ {
QDataStream in(socket);
in.setVersion(QDataStream::Qt_4_0);
if (blockSize == 0) { if (blockSize == 0) {
// Relies on the fact that QDataStream format streams a quint32 into sizeof(quint32) bytes // Relies on the fact that QDataStream serializes a quint32 into
// sizeof(quint32) bytes
if (socket->bytesAvailable() < (int)sizeof(quint32)) if (socket->bytesAvailable() < (int)sizeof(quint32))
return; return;
in >> blockSize; in >> blockSize;
@ -123,7 +121,7 @@ void Client::readFortune()
in >> nextFortune; in >> nextFortune;
if (nextFortune == currentFortune) { if (nextFortune == currentFortune) {
QTimer::singleShot(0, this, SLOT(requestNewFortune())); QTimer::singleShot(0, this, &Client::requestNewFortune);
return; return;
} }
@ -136,21 +134,22 @@ void Client::displayError(QLocalSocket::LocalSocketError socketError)
{ {
switch (socketError) { switch (socketError) {
case QLocalSocket::ServerNotFoundError: case QLocalSocket::ServerNotFoundError:
QMessageBox::information(this, tr("Fortune Client"), QMessageBox::information(this, tr("Local Fortune Client"),
tr("The host was not found. Please check the " tr("The host was not found. Please make sure "
"host name and port settings.")); "that the server is running and that the "
"server name is correct."));
break; break;
case QLocalSocket::ConnectionRefusedError: case QLocalSocket::ConnectionRefusedError:
QMessageBox::information(this, tr("Fortune Client"), QMessageBox::information(this, tr("Local Fortune Client"),
tr("The connection was refused by the peer. " tr("The connection was refused by the peer. "
"Make sure the fortune server is running, " "Make sure the fortune server is running, "
"and check that the host name and port " "and check that the server name "
"settings are correct.")); "is correct."));
break; break;
case QLocalSocket::PeerClosedError: case QLocalSocket::PeerClosedError:
break; break;
default: default:
QMessageBox::information(this, tr("Fortune Client"), QMessageBox::information(this, tr("Local Fortune Client"),
tr("The following error occurred: %1.") tr("The following error occurred: %1.")
.arg(socket->errorString())); .arg(socket->errorString()));
} }

View File

@ -52,11 +52,11 @@
#define CLIENT_H #define CLIENT_H
#include <QDialog> #include <QDialog>
#include <QDataStream>
#include <qlocalsocket.h> #include <qlocalsocket.h>
QT_BEGIN_NAMESPACE QT_BEGIN_NAMESPACE
class QDialogButtonBox;
class QLabel; class QLabel;
class QLineEdit; class QLineEdit;
class QPushButton; class QPushButton;
@ -68,7 +68,7 @@ class Client : public QDialog
Q_OBJECT Q_OBJECT
public: public:
Client(QWidget *parent = 0); explicit Client(QWidget *parent = nullptr);
private slots: private slots:
void requestNewFortune(); void requestNewFortune();
@ -77,16 +77,15 @@ private slots:
void enableGetFortuneButton(); void enableGetFortuneButton();
private: private:
QLabel *hostLabel;
QLineEdit *hostLineEdit; QLineEdit *hostLineEdit;
QLabel *statusLabel;
QPushButton *getFortuneButton; QPushButton *getFortuneButton;
QPushButton *quitButton; QLabel *statusLabel;
QDialogButtonBox *buttonBox;
QLocalSocket *socket; QLocalSocket *socket;
QString currentFortune; QDataStream in;
quint32 blockSize; quint32 blockSize;
QString currentFortune;
}; };
#endif #endif

View File

@ -55,6 +55,7 @@
int main(int argc, char *argv[]) int main(int argc, char *argv[])
{ {
QApplication app(argc, argv); QApplication app(argc, argv);
QGuiApplication::setApplicationDisplayName(Client::tr("Local Fortune Client"));
Client client; Client client;
client.show(); client.show();
return app.exec(); return app.exec();

View File

@ -58,8 +58,8 @@
int main(int argc, char *argv[]) int main(int argc, char *argv[])
{ {
QApplication app(argc, argv); QApplication app(argc, argv);
QGuiApplication::setApplicationDisplayName(Server::tr("Local Fortune Server"));
Server server; Server server;
server.show(); server.show();
qsrand(QTime(0,0,0).secsTo(QTime::currentTime()));
return app.exec(); return app.exec();
} }

View File

@ -60,22 +60,21 @@
Server::Server(QWidget *parent) Server::Server(QWidget *parent)
: QDialog(parent) : QDialog(parent)
{ {
statusLabel = new QLabel; setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint);
statusLabel->setWordWrap(true);
quitButton = new QPushButton(tr("Quit"));
quitButton->setAutoDefault(false);
server = new QLocalServer(this); server = new QLocalServer(this);
if (!server->listen("fortune")) { if (!server->listen("fortune")) {
QMessageBox::critical(this, tr("Fortune Server"), QMessageBox::critical(this, tr("Local Fortune Server"),
tr("Unable to start the server: %1.") tr("Unable to start the server: %1.")
.arg(server->errorString())); .arg(server->errorString()));
close(); close();
return; return;
} }
QLabel *statusLabel = new QLabel;
statusLabel->setWordWrap(true);
statusLabel->setText(tr("The server is running.\n" statusLabel->setText(tr("The server is running.\n"
"Run the Fortune Client example now.")); "Run the Local Fortune Client example now."));
fortunes << tr("You've been leading a dog's life. Stay off the furniture.") fortunes << tr("You've been leading a dog's life. Stay off the furniture.")
<< tr("You've got to think about tomorrow.") << tr("You've got to think about tomorrow.")
@ -85,35 +84,36 @@ Server::Server(QWidget *parent)
<< tr("You cannot kill time without injuring eternity.") << tr("You cannot kill time without injuring eternity.")
<< tr("Computers are not intelligent. They only think they are."); << tr("Computers are not intelligent. They only think they are.");
connect(quitButton, SIGNAL(clicked()), this, SLOT(close())); QPushButton *quitButton = new QPushButton(tr("Quit"));
connect(server, SIGNAL(newConnection()), this, SLOT(sendFortune())); quitButton->setAutoDefault(false);
connect(quitButton, &QPushButton::clicked, this, &Server::close);
connect(server, &QLocalServer::newConnection, this, &Server::sendFortune);
QHBoxLayout *buttonLayout = new QHBoxLayout; QHBoxLayout *buttonLayout = new QHBoxLayout;
buttonLayout->addStretch(1); buttonLayout->addStretch(1);
buttonLayout->addWidget(quitButton); buttonLayout->addWidget(quitButton);
buttonLayout->addStretch(1); buttonLayout->addStretch(1);
QVBoxLayout *mainLayout = new QVBoxLayout; QVBoxLayout *mainLayout = new QVBoxLayout(this);
mainLayout->addWidget(statusLabel); mainLayout->addWidget(statusLabel);
mainLayout->addLayout(buttonLayout); mainLayout->addLayout(buttonLayout);
setLayout(mainLayout);
setWindowTitle(tr("Fortune Server")); setWindowTitle(QGuiApplication::applicationDisplayName());
} }
void Server::sendFortune() void Server::sendFortune()
{ {
QByteArray block; QByteArray block;
QDataStream out(&block, QIODevice::WriteOnly); QDataStream out(&block, QIODevice::WriteOnly);
out.setVersion(QDataStream::Qt_4_0); out.setVersion(QDataStream::Qt_5_10);
out << (quint32)0; const int fortuneIndex = QRandomGenerator::bounded(0, fortunes.size());
out << fortunes.at(qrand() % fortunes.size()); const QString &message = fortunes.at(fortuneIndex);
out.device()->seek(0); out << quint32(message.size());
out << (quint32)(block.size() - sizeof(quint32)); out << message;
QLocalSocket *clientConnection = server->nextPendingConnection(); QLocalSocket *clientConnection = server->nextPendingConnection();
connect(clientConnection, SIGNAL(disconnected()), connect(clientConnection, &QLocalSocket::disconnected,
clientConnection, SLOT(deleteLater())); clientConnection, &QLocalSocket::deleteLater);
clientConnection->write(block); clientConnection->write(block);
clientConnection->flush(); clientConnection->flush();

View File

@ -64,14 +64,12 @@ class Server : public QDialog
Q_OBJECT Q_OBJECT
public: public:
Server(QWidget *parent = 0); explicit Server(QWidget *parent = nullptr);
private slots: private slots:
void sendFortune(); void sendFortune();
private: private:
QLabel *statusLabel;
QPushButton *quitButton;
QLocalServer *server; QLocalServer *server;
QStringList fortunes; QStringList fortunes;
}; };

View File

@ -1,6 +1,6 @@
/**************************************************************************** /****************************************************************************
** **
** Copyright (C) 2016 The Qt Company Ltd. ** Copyright (C) 2017 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/ ** Contact: https://www.qt.io/licensing/
** **
** This file is part of the examples of the Qt Toolkit. ** This file is part of the examples of the Qt Toolkit.
@ -50,6 +50,7 @@
#include <QtWidgets> #include <QtWidgets>
#include <QtNetwork> #include <QtNetwork>
#include <QtCore>
#include "sender.h" #include "sender.h"
@ -60,23 +61,21 @@ Sender::Sender(QWidget *parent)
statusLabel->setWordWrap(true); statusLabel->setWordWrap(true);
startButton = new QPushButton(tr("&Start")); startButton = new QPushButton(tr("&Start"));
quitButton = new QPushButton(tr("&Quit")); auto quitButton = new QPushButton(tr("&Quit"));
buttonBox = new QDialogButtonBox; auto buttonBox = new QDialogButtonBox;
buttonBox->addButton(startButton, QDialogButtonBox::ActionRole); buttonBox->addButton(startButton, QDialogButtonBox::ActionRole);
buttonBox->addButton(quitButton, QDialogButtonBox::RejectRole); buttonBox->addButton(quitButton, QDialogButtonBox::RejectRole);
timer = new QTimer(this);
//! [0] //! [0]
udpSocket = new QUdpSocket(this); udpSocket = new QUdpSocket(this);
//! [0] //! [0]
messageNo = 1;
connect(startButton, SIGNAL(clicked()), this, SLOT(startBroadcasting())); connect(startButton, &QPushButton::clicked, this, &Sender::startBroadcasting);
connect(quitButton, SIGNAL(clicked()), this, SLOT(close())); connect(quitButton, &QPushButton::clicked, this, &Sender::close);
connect(timer, SIGNAL(timeout()), this, SLOT(broadcastDatagram())); connect(&timer, &QTimer::timeout, this, &Sender::broadcastDatagram);
QVBoxLayout *mainLayout = new QVBoxLayout; auto mainLayout = new QVBoxLayout;
mainLayout->addWidget(statusLabel); mainLayout->addWidget(statusLabel);
mainLayout->addWidget(buttonBox); mainLayout->addWidget(buttonBox);
setLayout(mainLayout); setLayout(mainLayout);
@ -87,7 +86,7 @@ Sender::Sender(QWidget *parent)
void Sender::startBroadcasting() void Sender::startBroadcasting()
{ {
startButton->setEnabled(false); startButton->setEnabled(false);
timer->start(1000); timer.start(1000);
} }
void Sender::broadcastDatagram() void Sender::broadcastDatagram()
@ -95,8 +94,7 @@ void Sender::broadcastDatagram()
statusLabel->setText(tr("Now broadcasting datagram %1").arg(messageNo)); statusLabel->setText(tr("Now broadcasting datagram %1").arg(messageNo));
//! [1] //! [1]
QByteArray datagram = "Broadcast message " + QByteArray::number(messageNo); QByteArray datagram = "Broadcast message " + QByteArray::number(messageNo);
udpSocket->writeDatagram(datagram.data(), datagram.size(), udpSocket->writeDatagram(datagram, QHostAddress::Broadcast, 45454);
QHostAddress::Broadcast, 45454);
//! [1] //! [1]
++messageNo; ++messageNo;
} }

View File

@ -1,6 +1,6 @@
/**************************************************************************** /****************************************************************************
** **
** Copyright (C) 2016 The Qt Company Ltd. ** Copyright (C) 2017 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/ ** Contact: https://www.qt.io/licensing/
** **
** This file is part of the examples of the Qt Toolkit. ** This file is part of the examples of the Qt Toolkit.
@ -52,12 +52,11 @@
#define SENDER_H #define SENDER_H
#include <QWidget> #include <QWidget>
#include <QTimer>
QT_BEGIN_NAMESPACE QT_BEGIN_NAMESPACE
class QDialogButtonBox;
class QLabel; class QLabel;
class QPushButton; class QPushButton;
class QTimer;
class QUdpSocket; class QUdpSocket;
QT_END_NAMESPACE QT_END_NAMESPACE
@ -66,20 +65,18 @@ class Sender : public QWidget
Q_OBJECT Q_OBJECT
public: public:
Sender(QWidget *parent = 0); explicit Sender(QWidget *parent = nullptr);
private slots: private slots:
void startBroadcasting(); void startBroadcasting();
void broadcastDatagram(); void broadcastDatagram();
private: private:
QLabel *statusLabel; QLabel *statusLabel = nullptr;
QPushButton *startButton; QPushButton *startButton = nullptr;
QPushButton *quitButton; QUdpSocket *udpSocket = nullptr;
QDialogButtonBox *buttonBox; QTimer timer;
QUdpSocket *udpSocket; int messageNo = 1;
QTimer *timer;
int messageNo;
}; };
#endif #endif

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.8 KiB

After

Width:  |  Height:  |  Size: 7.9 KiB

View File

@ -55,12 +55,12 @@
#include "httpwindow.h" #include "httpwindow.h"
#include "ui_authenticationdialog.h" #include "ui_authenticationdialog.h"
#ifndef QT_NO_SSL #if QT_CONFIG(ssl)
static const char defaultUrl[] = "https://www.qt.io/"; const char defaultUrl[] = "https://www.qt.io/";
#else #else
static const char defaultUrl[] = "http://www.qt.io/"; const char defaultUrl[] = "http://www.qt.io/";
#endif #endif
static const char defaultFileName[] = "index.html"; const char defaultFileName[] = "index.html";
ProgressDialog::ProgressDialog(const QUrl &url, QWidget *parent) ProgressDialog::ProgressDialog(const QUrl &url, QWidget *parent)
: QProgressDialog(parent) : QProgressDialog(parent)
@ -71,6 +71,7 @@ ProgressDialog::ProgressDialog(const QUrl &url, QWidget *parent)
setMinimum(0); setMinimum(0);
setValue(0); setValue(0);
setMinimumDuration(0); setMinimumDuration(0);
setMinimumSize(QSize(400, 75));
} }
void ProgressDialog::networkReplyProgress(qint64 bytesRead, qint64 totalBytes) void ProgressDialog::networkReplyProgress(qint64 bytesRead, qint64 totalBytes)
@ -174,15 +175,22 @@ void HttpWindow::downloadFile()
if (fileName.isEmpty()) if (fileName.isEmpty())
fileName = defaultFileName; fileName = defaultFileName;
QString downloadDirectory = QDir::cleanPath(downloadDirectoryLineEdit->text().trimmed()); QString downloadDirectory = QDir::cleanPath(downloadDirectoryLineEdit->text().trimmed());
if (!downloadDirectory.isEmpty() && QFileInfo(downloadDirectory).isDir()) bool useDirectory = !downloadDirectory.isEmpty() && QFileInfo(downloadDirectory).isDir();
if (useDirectory)
fileName.prepend(downloadDirectory + '/'); fileName.prepend(downloadDirectory + '/');
if (QFile::exists(fileName)) { if (QFile::exists(fileName)) {
if (QMessageBox::question(this, tr("Overwrite Existing File"), if (QMessageBox::question(this, tr("Overwrite Existing File"),
tr("There already exists a file called %1 in " tr("There already exists a file called %1%2."
"the current directory. Overwrite?").arg(fileName), " Overwrite?")
QMessageBox::Yes|QMessageBox::No, QMessageBox::No) .arg(fileName,
== QMessageBox::No) useDirectory
? QString()
: QStringLiteral(" in the current directory")),
QMessageBox::Yes | QMessageBox::No,
QMessageBox::No)
== QMessageBox::No) {
return; return;
}
QFile::remove(fileName); QFile::remove(fileName);
} }
@ -252,7 +260,9 @@ void HttpWindow::httpFinished()
if (QMessageBox::question(this, tr("Redirect"), if (QMessageBox::question(this, tr("Redirect"),
tr("Redirect to %1 ?").arg(redirectedUrl.toString()), tr("Redirect to %1 ?").arg(redirectedUrl.toString()),
QMessageBox::Yes | QMessageBox::No) == QMessageBox::No) { QMessageBox::Yes | QMessageBox::No) == QMessageBox::No) {
QFile::remove(fi.absoluteFilePath());
downloadButton->setEnabled(true); downloadButton->setEnabled(true);
statusLabel->setText(tr("Download failed:\nRedirect rejected."));
return; return;
} }
file = openFileForWrite(fi.absoluteFilePath()); file = openFileForWrite(fi.absoluteFilePath());
@ -286,7 +296,7 @@ void HttpWindow::enableDownloadButton()
downloadButton->setEnabled(!urlLineEdit->text().isEmpty()); downloadButton->setEnabled(!urlLineEdit->text().isEmpty());
} }
void HttpWindow::slotAuthenticationRequired(QNetworkReply*,QAuthenticator *authenticator) void HttpWindow::slotAuthenticationRequired(QNetworkReply *, QAuthenticator *authenticator)
{ {
QDialog authenticationDialog; QDialog authenticationDialog;
Ui::Dialog ui; Ui::Dialog ui;
@ -306,7 +316,7 @@ void HttpWindow::slotAuthenticationRequired(QNetworkReply*,QAuthenticator *authe
} }
#ifndef QT_NO_SSL #ifndef QT_NO_SSL
void HttpWindow::sslErrors(QNetworkReply*,const QList<QSslError> &errors) void HttpWindow::sslErrors(QNetworkReply *, const QList<QSslError> &errors)
{ {
QString errorString; QString errorString;
foreach (const QSslError &error, errors) { foreach (const QSslError &error, errors) {

View File

@ -92,9 +92,9 @@ private slots:
void httpFinished(); void httpFinished();
void httpReadyRead(); void httpReadyRead();
void enableDownloadButton(); void enableDownloadButton();
void slotAuthenticationRequired(QNetworkReply*,QAuthenticator *); void slotAuthenticationRequired(QNetworkReply *, QAuthenticator *authenticator);
#ifndef QT_NO_SSL #ifndef QT_NO_SSL
void sslErrors(QNetworkReply*,const QList<QSslError> &errors); void sslErrors(QNetworkReply *, const QList<QSslError> &errors);
#endif #endif
private: private:

View File

@ -1,6 +1,6 @@
/**************************************************************************** /****************************************************************************
** **
** Copyright (C) 2016 The Qt Company Ltd. ** Copyright (C) 2017 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/ ** Contact: https://www.qt.io/licensing/
** **
** This file is part of the examples of the Qt Toolkit. ** This file is part of the examples of the Qt Toolkit.
@ -48,43 +48,35 @@
** **
****************************************************************************/ ****************************************************************************/
#include <QtWidgets>
#include <QtNetwork>
#include "sender.h" #include "sender.h"
Sender::Sender(QWidget *parent) Sender::Sender(QWidget *parent)
: QDialog(parent) : QDialog(parent),
groupAddress(QStringLiteral("239.255.43.21"))
{ {
groupAddress = QHostAddress("239.255.43.21");
statusLabel = new QLabel(tr("Ready to multicast datagrams to group %1 on port 45454").arg(groupAddress.toString())); statusLabel = new QLabel(tr("Ready to multicast datagrams to group %1 on port 45454").arg(groupAddress.toString()));
ttlLabel = new QLabel(tr("TTL for multicast datagrams:")); auto ttlLabel = new QLabel(tr("TTL for multicast datagrams:"));
ttlSpinBox = new QSpinBox; auto ttlSpinBox = new QSpinBox;
ttlSpinBox->setRange(0, 255); ttlSpinBox->setRange(0, 255);
QHBoxLayout *ttlLayout = new QHBoxLayout; auto ttlLayout = new QHBoxLayout;
ttlLayout->addWidget(ttlLabel); ttlLayout->addWidget(ttlLabel);
ttlLayout->addWidget(ttlSpinBox); ttlLayout->addWidget(ttlSpinBox);
startButton = new QPushButton(tr("&Start")); startButton = new QPushButton(tr("&Start"));
quitButton = new QPushButton(tr("&Quit")); auto quitButton = new QPushButton(tr("&Quit"));
buttonBox = new QDialogButtonBox; auto buttonBox = new QDialogButtonBox;
buttonBox->addButton(startButton, QDialogButtonBox::ActionRole); buttonBox->addButton(startButton, QDialogButtonBox::ActionRole);
buttonBox->addButton(quitButton, QDialogButtonBox::RejectRole); buttonBox->addButton(quitButton, QDialogButtonBox::RejectRole);
timer = new QTimer(this); connect(ttlSpinBox, QOverload<int>::of(&QSpinBox::valueChanged), this, &Sender::ttlChanged);
udpSocket = new QUdpSocket(this); connect(startButton, &QPushButton::clicked, this, &Sender::startSending);
messageNo = 1; connect(quitButton, &QPushButton::clicked, this, &Sender::close);
connect(&timer, &QTimer::timeout, this, &Sender::sendDatagram);
connect(ttlSpinBox, SIGNAL(valueChanged(int)), this, SLOT(ttlChanged(int))); auto mainLayout = new QVBoxLayout;
connect(startButton, SIGNAL(clicked()), this, SLOT(startSending()));
connect(quitButton, SIGNAL(clicked()), this, SLOT(close()));
connect(timer, SIGNAL(timeout()), this, SLOT(sendDatagram()));
QVBoxLayout *mainLayout = new QVBoxLayout;
mainLayout->addWidget(statusLabel); mainLayout->addWidget(statusLabel);
mainLayout->addLayout(ttlLayout); mainLayout->addLayout(ttlLayout);
mainLayout->addWidget(buttonBox); mainLayout->addWidget(buttonBox);
@ -96,20 +88,19 @@ Sender::Sender(QWidget *parent)
void Sender::ttlChanged(int newTtl) void Sender::ttlChanged(int newTtl)
{ {
udpSocket->setSocketOption(QAbstractSocket::MulticastTtlOption, newTtl); udpSocket.setSocketOption(QAbstractSocket::MulticastTtlOption, newTtl);
} }
void Sender::startSending() void Sender::startSending()
{ {
startButton->setEnabled(false); startButton->setEnabled(false);
timer->start(1000); timer.start(1000);
} }
void Sender::sendDatagram() void Sender::sendDatagram()
{ {
statusLabel->setText(tr("Now sending datagram %1").arg(messageNo)); statusLabel->setText(tr("Now sending datagram %1").arg(messageNo));
QByteArray datagram = "Multicast message " + QByteArray::number(messageNo); QByteArray datagram = "Multicast message " + QByteArray::number(messageNo);
udpSocket->writeDatagram(datagram.data(), datagram.size(), udpSocket.writeDatagram(datagram, groupAddress, 45454);
groupAddress, 45454);
++messageNo; ++messageNo;
} }

View File

@ -1,6 +1,6 @@
/**************************************************************************** /****************************************************************************
** **
** Copyright (C) 2016 The Qt Company Ltd. ** Copyright (C) 2017 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/ ** Contact: https://www.qt.io/licensing/
** **
** This file is part of the examples of the Qt Toolkit. ** This file is part of the examples of the Qt Toolkit.
@ -51,24 +51,16 @@
#ifndef SENDER_H #ifndef SENDER_H
#define SENDER_H #define SENDER_H
#include <QDialog> #include <QtWidgets>
#include <QHostAddress> #include <QtNetwork>
#include <QtCore>
QT_BEGIN_NAMESPACE
class QDialogButtonBox;
class QLabel;
class QPushButton;
class QTimer;
class QUdpSocket;
class QSpinBox;
QT_END_NAMESPACE
class Sender : public QDialog class Sender : public QDialog
{ {
Q_OBJECT Q_OBJECT
public: public:
Sender(QWidget *parent = 0); explicit Sender(QWidget *parent = nullptr);
private slots: private slots:
void ttlChanged(int newTtl); void ttlChanged(int newTtl);
@ -76,16 +68,12 @@ private slots:
void sendDatagram(); void sendDatagram();
private: private:
QLabel *statusLabel; QLabel *statusLabel = nullptr;
QLabel *ttlLabel; QPushButton *startButton = nullptr;
QSpinBox *ttlSpinBox; QUdpSocket udpSocket;
QPushButton *startButton; QTimer timer;
QPushButton *quitButton;
QDialogButtonBox *buttonBox;
QUdpSocket *udpSocket;
QTimer *timer;
QHostAddress groupAddress; QHostAddress groupAddress;
int messageNo; int messageNo = 1;
}; };
#endif #endif

View File

@ -1,6 +1,6 @@
/**************************************************************************** /****************************************************************************
** **
** Copyright (C) 2016 The Qt Company Ltd. ** Copyright (C) 2017 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/ ** Contact: https://www.qt.io/licensing/
** **
** This file is part of the examples of the Qt Toolkit. ** This file is part of the examples of the Qt Toolkit.
@ -57,8 +57,8 @@ CertificateInfo::CertificateInfo(QWidget *parent)
form = new Ui_CertificateInfo; form = new Ui_CertificateInfo;
form->setupUi(this); form->setupUi(this);
connect(form->certificationPathView, SIGNAL(currentIndexChanged(int)), connect(form->certificationPathView, QOverload<int>::of(&QComboBox::currentIndexChanged),
this, SLOT(updateCertificateInfo(int))); this, &CertificateInfo::updateCertificateInfo);
} }
CertificateInfo::~CertificateInfo() CertificateInfo::~CertificateInfo()
@ -68,25 +68,23 @@ CertificateInfo::~CertificateInfo()
void CertificateInfo::setCertificateChain(const QList<QSslCertificate> &chain) void CertificateInfo::setCertificateChain(const QList<QSslCertificate> &chain)
{ {
this->chain = chain; certificateChain = chain;
form->certificationPathView->clear(); form->certificationPathView->clear();
for (int i = 0; i < certificateChain.size(); ++i) {
for (int i = 0; i < chain.size(); ++i) { const QSslCertificate &cert = certificateChain.at(i);
const QSslCertificate &cert = chain.at(i);
form->certificationPathView->addItem(tr("%1%2 (%3)").arg(!i ? QString() : tr("Issued by: ")) form->certificationPathView->addItem(tr("%1%2 (%3)").arg(!i ? QString() : tr("Issued by: "))
.arg(cert.subjectInfo(QSslCertificate::Organization).join(QLatin1Char(' '))) .arg(cert.subjectInfo(QSslCertificate::Organization).join(QLatin1Char(' ')))
.arg(cert.subjectInfo(QSslCertificate::CommonName).join(QLatin1Char(' ')))); .arg(cert.subjectInfo(QSslCertificate::CommonName).join(QLatin1Char(' '))));
} }
form->certificationPathView->setCurrentIndex(0); form->certificationPathView->setCurrentIndex(0);
} }
void CertificateInfo::updateCertificateInfo(int index) void CertificateInfo::updateCertificateInfo(int index)
{ {
form->certificateInfoView->clear(); form->certificateInfoView->clear();
if (index >= 0 && index < chain.size()) { if (index >= 0 && index < certificateChain.size()) {
const QSslCertificate &cert = chain.at(index); const QSslCertificate &cert = certificateChain.at(index);
QStringList lines; QStringList lines;
lines << tr("Organization: %1").arg(cert.subjectInfo(QSslCertificate::Organization).join(QLatin1Char(' '))) lines << tr("Organization: %1").arg(cert.subjectInfo(QSslCertificate::Organization).join(QLatin1Char(' ')))
<< tr("Subunit: %1").arg(cert.subjectInfo(QSslCertificate::OrganizationalUnitName).join(QLatin1Char(' '))) << tr("Subunit: %1").arg(cert.subjectInfo(QSslCertificate::OrganizationalUnitName).join(QLatin1Char(' ')))
@ -101,9 +99,7 @@ void CertificateInfo::updateCertificateInfo(int index)
<< tr("Issuer Locality: %1").arg(cert.issuerInfo(QSslCertificate::LocalityName).join(QLatin1Char(' '))) << tr("Issuer Locality: %1").arg(cert.issuerInfo(QSslCertificate::LocalityName).join(QLatin1Char(' ')))
<< tr("Issuer State/Province: %1").arg(cert.issuerInfo(QSslCertificate::StateOrProvinceName).join(QLatin1Char(' '))) << tr("Issuer State/Province: %1").arg(cert.issuerInfo(QSslCertificate::StateOrProvinceName).join(QLatin1Char(' ')))
<< tr("Issuer Common Name: %1").arg(cert.issuerInfo(QSslCertificate::CommonName).join(QLatin1Char(' '))); << tr("Issuer Common Name: %1").arg(cert.issuerInfo(QSslCertificate::CommonName).join(QLatin1Char(' ')));
foreach (QString line, lines) for (const auto &line : lines)
form->certificateInfoView->addItem(line); form->certificateInfoView->addItem(line);
} else {
form->certificateInfoView->clear();
} }
} }

View File

@ -1,6 +1,6 @@
/**************************************************************************** /****************************************************************************
** **
** Copyright (C) 2016 The Qt Company Ltd. ** Copyright (C) 2017 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/ ** Contact: https://www.qt.io/licensing/
** **
** This file is part of the examples of the Qt Toolkit. ** This file is part of the examples of the Qt Toolkit.
@ -51,8 +51,9 @@
#ifndef CERTIFICATEINFO_H #ifndef CERTIFICATEINFO_H
#define CERTIFICATEINFO_H #define CERTIFICATEINFO_H
#include <QtWidgets/QDialog> #include <QDialog>
#include <QtNetwork/QSslCertificate> #include <QList>
#include <QSslCertificate>
QT_BEGIN_NAMESPACE QT_BEGIN_NAMESPACE
class Ui_CertificateInfo; class Ui_CertificateInfo;
@ -62,7 +63,7 @@ class CertificateInfo : public QDialog
{ {
Q_OBJECT Q_OBJECT
public: public:
CertificateInfo(QWidget *parent = 0); explicit CertificateInfo(QWidget *parent = nullptr);
~CertificateInfo(); ~CertificateInfo();
void setCertificateChain(const QList<QSslCertificate> &chain); void setCertificateChain(const QList<QSslCertificate> &chain);
@ -71,8 +72,8 @@ private slots:
void updateCertificateInfo(int index); void updateCertificateInfo(int index);
private: private:
Ui_CertificateInfo *form; Ui_CertificateInfo *form = nullptr;
QList<QSslCertificate> chain; QList<QSslCertificate> certificateChain;
}; };
#endif #endif

View File

@ -42,7 +42,7 @@
<widget class="QListWidget" name="certificateInfoView"> <widget class="QListWidget" name="certificateInfoView">
<property name="font"> <property name="font">
<font> <font>
<pointsize>8</pointsize> <pointsize>10</pointsize>
</font> </font>
</property> </property>
<property name="wordWrap"> <property name="wordWrap">

View File

@ -1,6 +1,6 @@
/**************************************************************************** /****************************************************************************
** **
** Copyright (C) 2016 The Qt Company Ltd. ** Copyright (C) 2017 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/ ** Contact: https://www.qt.io/licensing/
** **
** This file is part of the examples of the Qt Toolkit. ** This file is part of the examples of the Qt Toolkit.
@ -50,6 +50,9 @@
#include <QApplication> #include <QApplication>
#include <QMessageBox> #include <QMessageBox>
#include <QtNetwork>
QT_REQUIRE_CONFIG(ssl);
#include "sslclient.h" #include "sslclient.h"
@ -61,7 +64,7 @@ int main(int argc, char **argv)
if (!QSslSocket::supportsSsl()) { if (!QSslSocket::supportsSsl()) {
QMessageBox::information(0, "Secure Socket Client", QMessageBox::information(0, "Secure Socket Client",
"This system does not support OpenSSL."); "This system does not support SSL/TLS.");
return -1; return -1;
} }

View File

@ -1,3 +1,5 @@
requires(qtHaveModule(network))
HEADERS += certificateinfo.h \ HEADERS += certificateinfo.h \
sslclient.h sslclient.h
SOURCES += certificateinfo.cpp \ SOURCES += certificateinfo.cpp \

View File

@ -1,6 +1,6 @@
/**************************************************************************** /****************************************************************************
** **
** Copyright (C) 2016 The Qt Company Ltd. ** Copyright (C) 2017 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/ ** Contact: https://www.qt.io/licensing/
** **
** This file is part of the examples of the Qt Toolkit. ** This file is part of the examples of the Qt Toolkit.
@ -50,29 +50,17 @@
#include "certificateinfo.h" #include "certificateinfo.h"
#include "sslclient.h" #include "sslclient.h"
#include "ui_sslclient.h" #include "ui_sslclient.h"
#include "ui_sslerrors.h" #include "ui_sslerrors.h"
#include <QtWidgets/QScrollBar> #include <QtCore>
#include <QtWidgets/QStyle>
#include <QtWidgets/QToolButton>
#include <QtWidgets/QMessageBox>
#include <QtNetwork/QSslCipher>
SslClient::SslClient(QWidget *parent) SslClient::SslClient(QWidget *parent)
: QWidget(parent), socket(0), padLock(0), executingDialog(false) : QWidget(parent)
{ {
form = new Ui_Form; setupUi();
form->setupUi(this); setupSecureSocket();
form->hostNameEdit->setSelection(0, form->hostNameEdit->text().size());
form->sessionOutput->setHtml(tr("&lt;not connected&gt;"));
connect(form->hostNameEdit, SIGNAL(textChanged(QString)),
this, SLOT(updateEnabledState()));
connect(form->connectButton, SIGNAL(clicked()),
this, SLOT(secureConnect()));
connect(form->sendButton, SIGNAL(clicked()),
this, SLOT(sendData()));
} }
SslClient::~SslClient() SslClient::~SslClient()
@ -82,17 +70,15 @@ SslClient::~SslClient()
void SslClient::updateEnabledState() void SslClient::updateEnabledState()
{ {
bool unconnected = !socket || socket->state() == QAbstractSocket::UnconnectedState; const bool unconnected = socket->state() == QAbstractSocket::UnconnectedState;
form->hostNameEdit->setReadOnly(!unconnected); form->hostNameEdit->setReadOnly(!unconnected);
form->hostNameEdit->setFocusPolicy(unconnected ? Qt::StrongFocus : Qt::NoFocus); form->hostNameEdit->setFocusPolicy(unconnected ? Qt::StrongFocus : Qt::NoFocus);
form->hostNameLabel->setEnabled(unconnected); form->hostNameLabel->setEnabled(unconnected);
form->portBox->setEnabled(unconnected); form->portBox->setEnabled(unconnected);
form->portLabel->setEnabled(unconnected); form->portLabel->setEnabled(unconnected);
form->connectButton->setEnabled(unconnected && !form->hostNameEdit->text().isEmpty()); form->connectButton->setEnabled(unconnected && !form->hostNameEdit->text().isEmpty());
bool connected = socket && socket->state() == QAbstractSocket::ConnectedState; const bool connected = socket->state() == QAbstractSocket::ConnectedState;
form->sessionOutput->setEnabled(connected); form->sessionOutput->setEnabled(connected);
form->sessionInput->setEnabled(connected); form->sessionInput->setEnabled(connected);
form->sessionInputLabel->setEnabled(connected); form->sessionInputLabel->setEnabled(connected);
@ -101,20 +87,6 @@ void SslClient::updateEnabledState()
void SslClient::secureConnect() void SslClient::secureConnect()
{ {
if (!socket) {
socket = new QSslSocket(this);
connect(socket, SIGNAL(stateChanged(QAbstractSocket::SocketState)),
this, SLOT(socketStateChanged(QAbstractSocket::SocketState)));
connect(socket, SIGNAL(encrypted()),
this, SLOT(socketEncrypted()));
connect(socket, SIGNAL(error(QAbstractSocket::SocketError)),
this, SLOT(socketError(QAbstractSocket::SocketError)));
connect(socket, SIGNAL(sslErrors(QList<QSslError>)),
this, SLOT(sslErrors(QList<QSslError>)));
connect(socket, SIGNAL(readyRead()),
this, SLOT(socketReadyRead()));
}
socket->connectToHostEncrypted(form->hostNameEdit->text(), form->portBox->value()); socket->connectToHostEncrypted(form->hostNameEdit->text(), form->portBox->value());
updateEnabledState(); updateEnabledState();
} }
@ -125,20 +97,18 @@ void SslClient::socketStateChanged(QAbstractSocket::SocketState state)
return; return;
updateEnabledState(); updateEnabledState();
if (state == QAbstractSocket::UnconnectedState) { if (state == QAbstractSocket::UnconnectedState) {
form->sessionInput->clear();
form->hostNameEdit->setPalette(QPalette()); form->hostNameEdit->setPalette(QPalette());
form->hostNameEdit->setFocus(); form->hostNameEdit->setFocus();
form->cipherLabel->setText(tr("<none>")); form->cipherLabel->setText(tr("<none>"));
if (padLock) padLock->hide();
padLock->hide();
} }
} }
void SslClient::socketEncrypted() void SslClient::socketEncrypted()
{ {
if (!socket)
return; // might have disconnected already
form->sessionOutput->clear(); form->sessionOutput->clear();
form->sessionInput->setFocus(); form->sessionInput->setFocus();
@ -146,36 +116,12 @@ void SslClient::socketEncrypted()
palette.setColor(QPalette::Base, QColor(255, 255, 192)); palette.setColor(QPalette::Base, QColor(255, 255, 192));
form->hostNameEdit->setPalette(palette); form->hostNameEdit->setPalette(palette);
QSslCipher ciph = socket->sessionCipher(); const QSslCipher cipher = socket->sessionCipher();
QString cipher = QString("%1, %2 (%3/%4)").arg(ciph.authenticationMethod()) const QString cipherInfo = QString("%1, %2 (%3/%4)").arg(cipher.authenticationMethod())
.arg(ciph.name()).arg(ciph.usedBits()).arg(ciph.supportedBits());; .arg(cipher.name()).arg(cipher.usedBits())
form->cipherLabel->setText(cipher); .arg(cipher.supportedBits());;
form->cipherLabel->setText(cipherInfo);
if (!padLock) { padLock->show();
padLock = new QToolButton;
padLock->setIcon(QIcon(":/encrypted.png"));
#ifndef QT_NO_CURSOR
padLock->setCursor(Qt::ArrowCursor);
#endif
padLock->setToolTip(tr("Display encryption details."));
int extent = form->hostNameEdit->height() - 2;
padLock->resize(extent, extent);
padLock->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Ignored);
QHBoxLayout *layout = new QHBoxLayout(form->hostNameEdit);
layout->setMargin(form->hostNameEdit->style()->pixelMetric(QStyle::PM_DefaultFrameWidth));
layout->setSpacing(0);
layout->addStretch();
layout->addWidget(padLock);
form->hostNameEdit->setLayout(layout);
connect(padLock, SIGNAL(clicked()),
this, SLOT(displayCertificateInfo()));
} else {
padLock->show();
}
} }
void SslClient::socketReadyRead() void SslClient::socketReadyRead()
@ -185,7 +131,7 @@ void SslClient::socketReadyRead()
void SslClient::sendData() void SslClient::sendData()
{ {
QString input = form->sessionInput->text(); const QString input = form->sessionInput->text();
appendString(input + '\n'); appendString(input + '\n');
socket->write(input.toUtf8() + "\r\n"); socket->write(input.toUtf8() + "\r\n");
form->sessionInput->clear(); form->sessionInput->clear();
@ -193,7 +139,12 @@ void SslClient::sendData()
void SslClient::socketError(QAbstractSocket::SocketError) void SslClient::socketError(QAbstractSocket::SocketError)
{ {
if (handlingSocketError)
return;
handlingSocketError = true;
QMessageBox::critical(this, tr("Connection error"), socket->errorString()); QMessageBox::critical(this, tr("Connection error"), socket->errorString());
handlingSocketError = false;
} }
void SslClient::sslErrors(const QList<QSslError> &errors) void SslClient::sslErrors(const QList<QSslError> &errors)
@ -201,10 +152,10 @@ void SslClient::sslErrors(const QList<QSslError> &errors)
QDialog errorDialog(this); QDialog errorDialog(this);
Ui_SslErrors ui; Ui_SslErrors ui;
ui.setupUi(&errorDialog); ui.setupUi(&errorDialog);
connect(ui.certificateChainButton, SIGNAL(clicked()), connect(ui.certificateChainButton, &QPushButton::clicked,
this, SLOT(displayCertificateInfo())); this, &SslClient::displayCertificateInfo);
foreach (const QSslError &error, errors) for (const auto &error : errors)
ui.sslErrorList->addItem(error.errorString()); ui.sslErrorList->addItem(error.errorString());
executingDialog = true; executingDialog = true;
@ -219,10 +170,69 @@ void SslClient::sslErrors(const QList<QSslError> &errors)
void SslClient::displayCertificateInfo() void SslClient::displayCertificateInfo()
{ {
CertificateInfo *info = new CertificateInfo(this); CertificateInfo info;
info->setCertificateChain(socket->peerCertificateChain()); info.setCertificateChain(socket->peerCertificateChain());
info->exec(); info.exec();
info->deleteLater(); }
void SslClient::setupUi()
{
if (form)
return;
form = new Ui_Form;
form->setupUi(this);
form->hostNameEdit->setSelection(0, form->hostNameEdit->text().size());
form->sessionOutput->setHtml(tr("&lt;not connected&gt;"));
connect(form->hostNameEdit, SIGNAL(textChanged(QString)),
this, SLOT(updateEnabledState()));
connect(form->connectButton, SIGNAL(clicked()),
this, SLOT(secureConnect()));
connect(form->sendButton, SIGNAL(clicked()),
this, SLOT(sendData()));
padLock = new QToolButton;
padLock->setIcon(QIcon(":/encrypted.png"));
connect(padLock, SIGNAL(clicked()), this, SLOT(displayCertificateInfo()));
#if QT_CONFIG(cursor)
padLock->setCursor(Qt::ArrowCursor);
#endif
padLock->setToolTip(tr("Display encryption details."));
const int extent = form->hostNameEdit->height() - 2;
padLock->resize(extent, extent);
padLock->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Ignored);
QHBoxLayout *layout = new QHBoxLayout(form->hostNameEdit);
layout->setMargin(form->hostNameEdit->style()->pixelMetric(QStyle::PM_DefaultFrameWidth));
layout->setSpacing(0);
layout->addStretch();
layout->addWidget(padLock);
form->hostNameEdit->setLayout(layout);
padLock->hide();
}
void SslClient::setupSecureSocket()
{
if (socket)
return;
socket = new QSslSocket(this);
connect(socket, SIGNAL(stateChanged(QAbstractSocket::SocketState)),
this, SLOT(socketStateChanged(QAbstractSocket::SocketState)));
connect(socket, SIGNAL(encrypted()),
this, SLOT(socketEncrypted()));
connect(socket, SIGNAL(error(QAbstractSocket::SocketError)),
this, SLOT(socketError(QAbstractSocket::SocketError)));
connect(socket, SIGNAL(sslErrors(QList<QSslError>)),
this, SLOT(sslErrors(QList<QSslError>)));
connect(socket, SIGNAL(readyRead()),
this, SLOT(socketReadyRead()));
} }
void SslClient::appendString(const QString &line) void SslClient::appendString(const QString &line)

View File

@ -1,6 +1,6 @@
/**************************************************************************** /****************************************************************************
** **
** Copyright (C) 2016 The Qt Company Ltd. ** Copyright (C) 2017 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/ ** Contact: https://www.qt.io/licensing/
** **
** This file is part of the examples of the Qt Toolkit. ** This file is part of the examples of the Qt Toolkit.
@ -51,13 +51,13 @@
#ifndef SSLCLIENT_H #ifndef SSLCLIENT_H
#define SSLCLIENT_H #define SSLCLIENT_H
#include <QtWidgets/QWidget> #include <QtNetwork>
#include <QtNetwork/QAbstractSocket>
#include <QtNetwork/QSslSocket> QT_REQUIRE_CONFIG(ssl);
#include <QtWidgets>
QT_BEGIN_NAMESPACE QT_BEGIN_NAMESPACE
class QSslSocket;
class QToolButton;
class Ui_Form; class Ui_Form;
QT_END_NAMESPACE QT_END_NAMESPACE
@ -65,7 +65,7 @@ class SslClient : public QWidget
{ {
Q_OBJECT Q_OBJECT
public: public:
SslClient(QWidget *parent = 0); explicit SslClient(QWidget *parent = nullptr);
~SslClient(); ~SslClient();
private slots: private slots:
@ -80,12 +80,15 @@ private slots:
void displayCertificateInfo(); void displayCertificateInfo();
private: private:
void setupUi();
void setupSecureSocket();
void appendString(const QString &line); void appendString(const QString &line);
QSslSocket *socket; QSslSocket *socket = nullptr;
QToolButton *padLock; QToolButton *padLock = nullptr;
Ui_Form *form; Ui_Form *form = nullptr;
bool executingDialog; bool handlingSocketError = false;
bool executingDialog = false;
}; };
#endif #endif

View File

@ -10,6 +10,12 @@
<height>320</height> <height>320</height>
</rect> </rect>
</property> </property>
<property name="minimumSize">
<size>
<width>343</width>
<height>320</height>
</size>
</property>
<property name="windowTitle"> <property name="windowTitle">
<string>Secure Socket Client</string> <string>Secure Socket Client</string>
</property> </property>
@ -114,8 +120,8 @@
<string>&lt;!DOCTYPE HTML PUBLIC &quot;-//W3C//DTD HTML 4.0//EN&quot; &quot;http://www.w3.org/TR/REC-html40/strict.dtd&quot;&gt; <string>&lt;!DOCTYPE HTML PUBLIC &quot;-//W3C//DTD HTML 4.0//EN&quot; &quot;http://www.w3.org/TR/REC-html40/strict.dtd&quot;&gt;
&lt;html&gt;&lt;head&gt;&lt;meta name=&quot;qrichtext&quot; content=&quot;1&quot; /&gt;&lt;style type=&quot;text/css&quot;&gt; &lt;html&gt;&lt;head&gt;&lt;meta name=&quot;qrichtext&quot; content=&quot;1&quot; /&gt;&lt;style type=&quot;text/css&quot;&gt;
p, li { white-space: pre-wrap; } p, li { white-space: pre-wrap; }
&lt;/style&gt;&lt;/head&gt;&lt;body style=&quot; font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;&quot;&gt; &lt;/style&gt;&lt;/head&gt;&lt;body style=&quot; font-family:'.SF NS Text'; font-size:13pt; font-weight:400; font-style:normal;&quot;&gt;
&lt;p style=&quot;-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans Serif'; font-size:9pt;&quot;&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string> &lt;p style=&quot;-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans Serif'; font-size:9pt;&quot;&gt;&lt;br /&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property> </property>
</widget> </widget>
</item> </item>

View File

@ -54,6 +54,8 @@
#include <QCoreApplication> #include <QCoreApplication>
#include <math.h> #include <math.h>
bool GLWidget::m_transparent = false;
GLWidget::GLWidget(QWidget *parent) GLWidget::GLWidget(QWidget *parent)
: QOpenGLWidget(parent), : QOpenGLWidget(parent),
m_xRot(0), m_xRot(0),
@ -61,10 +63,9 @@ GLWidget::GLWidget(QWidget *parent)
m_zRot(0), m_zRot(0),
m_program(0) m_program(0)
{ {
m_core = QCoreApplication::arguments().contains(QStringLiteral("--coreprofile")); m_core = QSurfaceFormat::defaultFormat().profile() == QSurfaceFormat::CoreProfile;
// --transparent causes the clear color to be transparent. Therefore, on systems that // --transparent causes the clear color to be transparent. Therefore, on systems that
// support it, the widget will become transparent apart from the logo. // support it, the widget will become transparent apart from the logo.
m_transparent = QCoreApplication::arguments().contains(QStringLiteral("--transparent"));
if (m_transparent) { if (m_transparent) {
QSurfaceFormat fmt = format(); QSurfaceFormat fmt = format();
fmt.setAlphaBufferSize(8); fmt.setAlphaBufferSize(8);
@ -127,6 +128,8 @@ void GLWidget::setZRotation(int angle)
void GLWidget::cleanup() void GLWidget::cleanup()
{ {
if (m_program == nullptr)
return;
makeCurrent(); makeCurrent();
m_logoVbo.destroy(); m_logoVbo.destroy();
delete m_program; delete m_program;

View File

@ -68,6 +68,9 @@ public:
GLWidget(QWidget *parent = 0); GLWidget(QWidget *parent = 0);
~GLWidget(); ~GLWidget();
static bool isTransparent() { return m_transparent; }
static void setTransparent(bool t) { m_transparent = t; }
QSize minimumSizeHint() const override; QSize minimumSizeHint() const override;
QSize sizeHint() const override; QSize sizeHint() const override;
@ -108,7 +111,7 @@ private:
QMatrix4x4 m_proj; QMatrix4x4 m_proj;
QMatrix4x4 m_camera; QMatrix4x4 m_camera;
QMatrix4x4 m_world; QMatrix4x4 m_world;
bool m_transparent; static bool m_transparent;
}; };
#endif #endif

View File

@ -51,25 +51,46 @@
#include <QApplication> #include <QApplication>
#include <QDesktopWidget> #include <QDesktopWidget>
#include <QSurfaceFormat> #include <QSurfaceFormat>
#include <QCommandLineParser>
#include <QCommandLineOption>
#include "glwidget.h"
#include "mainwindow.h" #include "mainwindow.h"
int main(int argc, char *argv[]) int main(int argc, char *argv[])
{ {
QApplication app(argc, argv); QApplication app(argc, argv);
QCoreApplication::setApplicationName("Qt Hello GL 2 Example");
QCoreApplication::setOrganizationName("QtProject");
QCoreApplication::setApplicationVersion(QT_VERSION_STR);
QCommandLineParser parser;
parser.setApplicationDescription(QCoreApplication::applicationName());
parser.addHelpOption();
parser.addVersionOption();
QCommandLineOption multipleSampleOption("multisample", "Multisampling");
parser.addOption(multipleSampleOption);
QCommandLineOption coreProfileOption("coreprofile", "Use core profile");
parser.addOption(coreProfileOption);
QCommandLineOption transparentOption("transparent", "Transparent window");
parser.addOption(transparentOption);
parser.process(app);
QSurfaceFormat fmt; QSurfaceFormat fmt;
fmt.setDepthBufferSize(24); fmt.setDepthBufferSize(24);
if (QCoreApplication::arguments().contains(QStringLiteral("--multisample"))) if (parser.isSet(multipleSampleOption))
fmt.setSamples(4); fmt.setSamples(4);
if (QCoreApplication::arguments().contains(QStringLiteral("--coreprofile"))) { if (parser.isSet(coreProfileOption)) {
fmt.setVersion(3, 2); fmt.setVersion(3, 2);
fmt.setProfile(QSurfaceFormat::CoreProfile); fmt.setProfile(QSurfaceFormat::CoreProfile);
} }
QSurfaceFormat::setDefaultFormat(fmt); QSurfaceFormat::setDefaultFormat(fmt);
MainWindow mainWindow; MainWindow mainWindow;
if (QCoreApplication::arguments().contains(QStringLiteral("--transparent"))) {
GLWidget::setTransparent(parser.isSet(transparentOption));
if (GLWidget::isTransparent()) {
mainWindow.setAttribute(Qt::WA_TranslucentBackground); mainWindow.setAttribute(Qt::WA_TranslucentBackground);
mainWindow.setAttribute(Qt::WA_NoSystemBackground, false); mainWindow.setAttribute(Qt::WA_NoSystemBackground, false);
} }

View File

@ -52,6 +52,8 @@
#include <qpa/qplatformintegration.h> #include <qpa/qplatformintegration.h>
#include <QCommandLineParser>
#include <QCommandLineOption>
#include <QGuiApplication> #include <QGuiApplication>
#include <QScreen> #include <QScreen>
#include <QThread> #include <QThread>
@ -60,9 +62,26 @@ int main(int argc, char *argv[])
{ {
QGuiApplication app(argc, argv); QGuiApplication app(argc, argv);
QCoreApplication::setApplicationName("Qt HelloWindow GL Example");
QCoreApplication::setOrganizationName("QtProject");
QCoreApplication::setApplicationVersion(QT_VERSION_STR);
QCommandLineParser parser;
parser.setApplicationDescription(QCoreApplication::applicationName());
parser.addHelpOption();
parser.addVersionOption();
QCommandLineOption multipleOption("multiple", "Create multiple windows");
parser.addOption(multipleOption);
QCommandLineOption multipleSampleOption("multisample", "Multisampling");
parser.addOption(multipleSampleOption);
QCommandLineOption multipleScreenOption("multiscreen", "Run on multiple screens");
parser.addOption(multipleScreenOption);
QCommandLineOption timeoutOption("timeout", "Close after 10s");
parser.addOption(timeoutOption);
parser.process(app);
// Some platforms can only have one window per screen. Therefore we need to differentiate. // Some platforms can only have one window per screen. Therefore we need to differentiate.
const bool multipleWindows = QGuiApplication::arguments().contains(QStringLiteral("--multiple")); const bool multipleWindows = parser.isSet(multipleOption);
const bool multipleScreens = QGuiApplication::arguments().contains(QStringLiteral("--multiscreen")); const bool multipleScreens = parser.isSet(multipleScreenOption);
QScreen *screen = QGuiApplication::primaryScreen(); QScreen *screen = QGuiApplication::primaryScreen();
@ -70,7 +89,7 @@ int main(int argc, char *argv[])
QSurfaceFormat format; QSurfaceFormat format;
format.setDepthBufferSize(16); format.setDepthBufferSize(16);
if (QGuiApplication::arguments().contains(QStringLiteral("--multisample"))) if (parser.isSet(multipleSampleOption))
format.setSamples(4); format.setSamples(4);
QPoint center = QPoint(screenGeometry.center().x(), screenGeometry.top() + 80); QPoint center = QPoint(screenGeometry.center().x(), screenGeometry.top() + 80);
@ -136,7 +155,7 @@ int main(int argc, char *argv[])
} }
// Quit after 10 seconds. For platforms that do not have windows that are closeable. // Quit after 10 seconds. For platforms that do not have windows that are closeable.
if (QCoreApplication::arguments().contains(QStringLiteral("--timeout"))) if (parser.isSet(timeoutOption))
QTimer::singleShot(10000, qGuiApp, &QCoreApplication::quit); QTimer::singleShot(10000, qGuiApp, &QCoreApplication::quit);
const int exitValue = app.exec(); const int exitValue = app.exec();

View File

@ -51,6 +51,8 @@
#include <QApplication> #include <QApplication>
#include <QMainWindow> #include <QMainWindow>
#include <QSurfaceFormat> #include <QSurfaceFormat>
#include <QCommandLineParser>
#include <QCommandLineOption>
#include "mainwindow.h" #include "mainwindow.h"
int main( int argc, char ** argv ) int main( int argc, char ** argv )
@ -58,12 +60,25 @@ int main( int argc, char ** argv )
Q_INIT_RESOURCE(texture); Q_INIT_RESOURCE(texture);
QApplication a( argc, argv ); QApplication a( argc, argv );
QCoreApplication::setApplicationName("Qt QOpenGLWidget Example");
QCoreApplication::setOrganizationName("QtProject");
QCoreApplication::setApplicationVersion(QT_VERSION_STR);
QCommandLineParser parser;
parser.setApplicationDescription(QCoreApplication::applicationName());
parser.addHelpOption();
parser.addVersionOption();
QCommandLineOption multipleSampleOption("multisample", "Multisampling");
parser.addOption(multipleSampleOption);
QCommandLineOption srgbOption("srgb", "Use sRGB Color Space");
parser.addOption(srgbOption);
parser.process(a);
QSurfaceFormat format; QSurfaceFormat format;
format.setDepthBufferSize(24); format.setDepthBufferSize(24);
format.setStencilBufferSize(8); format.setStencilBufferSize(8);
if (QCoreApplication::arguments().contains(QStringLiteral("--srgb"))) if (parser.isSet(srgbOption))
format.setColorSpace(QSurfaceFormat::sRGBColorSpace); format.setColorSpace(QSurfaceFormat::sRGBColorSpace);
if (QCoreApplication::arguments().contains(QStringLiteral("--multisample"))) if (parser.isSet(multipleSampleOption))
format.setSamples(4); format.setSamples(4);
QSurfaceFormat::setDefaultFormat(format); QSurfaceFormat::setDefaultFormat(format);

View File

@ -53,6 +53,8 @@
#include <QDesktopWidget> #include <QDesktopWidget>
#include <QSurfaceFormat> #include <QSurfaceFormat>
#include <QOpenGLContext> #include <QOpenGLContext>
#include <QCommandLineParser>
#include <QCommandLineOption>
#include "mainwindow.h" #include "mainwindow.h"
#include "glwidget.h" #include "glwidget.h"
@ -67,6 +69,17 @@ int main( int argc, char ** argv )
{ {
QApplication a( argc, argv ); QApplication a( argc, argv );
QCoreApplication::setApplicationName("Qt Threaded QOpenGLWidget Example");
QCoreApplication::setOrganizationName("QtProject");
QCoreApplication::setApplicationVersion(QT_VERSION_STR);
QCommandLineParser parser;
parser.setApplicationDescription(QCoreApplication::applicationName());
parser.addHelpOption();
parser.addVersionOption();
QCommandLineOption singleOption("single", "Single thread");
parser.addOption(singleOption);
parser.process(a);
QSurfaceFormat format; QSurfaceFormat format;
format.setDepthBufferSize(16); format.setDepthBufferSize(16);
QSurfaceFormat::setDefaultFormat(format); QSurfaceFormat::setDefaultFormat(format);
@ -93,7 +106,7 @@ int main( int argc, char ** argv )
QScopedPointer<MainWindow> mw1; QScopedPointer<MainWindow> mw1;
QScopedPointer<MainWindow> mw2; QScopedPointer<MainWindow> mw2;
if (!QApplication::arguments().contains(QStringLiteral("--single"))) { if (!parser.isSet(singleOption)) {
if (supportsThreading) { if (supportsThreading) {
pos += QPoint(100, 100); pos += QPoint(100, 100);
mw1.reset(new MainWindow); mw1.reset(new MainWindow);

View File

@ -85,9 +85,9 @@ TableEditor::TableEditor(const QString &tableName, QWidget *parent)
//! [2] //! [2]
//! [3] //! [3]
connect(submitButton, SIGNAL(clicked()), this, SLOT(submit())); connect(submitButton, &QPushButton::clicked, this, &TableEditor::submit);
connect(revertButton, SIGNAL(clicked()), model, SLOT(revertAll())); connect(revertButton, &QPushButton::clicked, model, &QSqlTableModel::revertAll);
connect(quitButton, SIGNAL(clicked()), this, SLOT(close())); connect(quitButton, &QPushButton::clicked, this, &TableEditor::close);
//! [3] //! [3]
//! [4] //! [4]

View File

@ -65,7 +65,7 @@ class TableEditor : public QWidget
Q_OBJECT Q_OBJECT
public: public:
explicit TableEditor(const QString &tableName, QWidget *parent = 0); explicit TableEditor(const QString &tableName, QWidget *parent = nullptr);
private slots: private slots:
void submit(); void submit();

View File

@ -70,12 +70,12 @@ static bool createConnection()
QSqlDatabase db = QSqlDatabase::addDatabase("QSQLITE"); QSqlDatabase db = QSqlDatabase::addDatabase("QSQLITE");
db.setDatabaseName(":memory:"); db.setDatabaseName(":memory:");
if (!db.open()) { if (!db.open()) {
QMessageBox::critical(0, qApp->tr("Cannot open database"), QMessageBox::critical(nullptr, QObject::tr("Cannot open database"),
qApp->tr("Unable to establish a database connection.\n" QObject::tr("Unable to establish a database connection.\n"
"This example needs SQLite support. Please read " "This example needs SQLite support. Please read "
"the Qt SQL driver documentation for information how " "the Qt SQL driver documentation for information how "
"to build it.\n\n" "to build it.\n\n"
"Click Cancel to exit."), QMessageBox::Cancel); "Click Cancel to exit."), QMessageBox::Cancel);
return false; return false;
} }

View File

@ -172,11 +172,20 @@
\snippet drilldown/informationwindow.cpp 4 \snippet drilldown/informationwindow.cpp 4
Finally, we connect the "something's changed" signals in the Finally, we connect the "something's changed" signals in the
editors to our custom \c enableButtons() slot, enabling the users editors to our custom \c enableButtons slot, enabling the users
to either submit or revert their changes. We add all the widgets to either submit or revert their changes.
into a layout, store the item ID and the name of the displayed We need to use lambdas for connecting the \c enableButtons slot
image file for future reference, and set the window title and because its signature does not match \c QTextEdit::textChanged
initial size. and \c QComboBox::currentIndexChanged.
Since the latter has another overload with the signature
\c {const QString &} and the selected signal would be ambiguous,
we need to use \c QOverload<int>::of to select a specific overload
for \c currentIndexChanged.
We add all the widgets into a layout, store the item ID and the
name of the displayed image file for future reference, and set
the window title and initial size.
Note that we also set the Qt::Window window flag to indicate that Note that we also set the Qt::Window window flag to indicate that
our widget is in fact a window, with a window system frame and a our widget is in fact a window, with a window system frame and a
@ -389,19 +398,21 @@
\snippet drilldown/view.cpp 6 \snippet drilldown/view.cpp 6
The \c showInformation() function is given an \c ImageItem object The \c showInformation() function is given an \c ImageItem object
as argument, and starts off by extracting the item's item as argument, and starts off by extracting the item's item ID.
ID. Then it determines if there already is created an information
window for this location. If it is, and the window is visible, it
ensures that the window is raised to the top of the widget stack
and activated. If the window exists but is hidden, calling its \l
{QWidget::}{show()} slot gives the same result.
Then it determines if there already is created an information
window for this location.
If no window for the given location exists, we create one by If no window for the given location exists, we create one by
passing the item ID, a pointer to the model, and our view as a passing the item ID, a pointer to the model, and our view as a
parent, to the \c InformationWindow constructor. Note that we parent, to the \c InformationWindow constructor. Note that we
connect the information window's \c imageChanged() signal to \e connect the information window's \c imageChanged() signal to \e
this widget's \c updateImage() slot, before we give it a suitable this widget's \c updateImage() slot, before we give it a suitable
position and add it to the list of existing windows. position and add it to the list of existing windows.
If there is a window for the given location, and that window is
visible, it ensures that the window is raised to the top of the
widget stack and activated. If it is hidden, calling its \l
{QWidget::}{show()} slot gives the same result.
\snippet drilldown/view.cpp 7 \snippet drilldown/view.cpp 7

View File

@ -60,8 +60,8 @@ ImageItem::ImageItem(int id, const QPixmap &pixmap, QGraphicsItem *parent)
timeLine.setDuration(150); timeLine.setDuration(150);
timeLine.setFrameRange(0, 150); timeLine.setFrameRange(0, 150);
connect(&timeLine, SIGNAL(frameChanged(int)), this, SLOT(setFrame(int))); connect(&timeLine, &QTimeLine::frameChanged, this, &ImageItem::setFrame);
connect(&timeLine, SIGNAL(finished()), this, SLOT(updateItemPosition())); connect(&timeLine, &QTimeLine::finished, this, &ImageItem::updateItemPosition);
adjust(); adjust();
} }
@ -116,7 +116,7 @@ void ImageItem::adjust()
//! [4] //! [4]
//! [5] //! [5]
int ImageItem::id() int ImageItem::id() const
{ {
return recordId; return recordId;
} }

View File

@ -60,10 +60,10 @@ class ImageItem : public QObject, public QGraphicsPixmapItem
Q_OBJECT Q_OBJECT
public: public:
ImageItem(int id, const QPixmap &pixmap, QGraphicsItem *parent = 0); ImageItem(int id, const QPixmap &pixmap, QGraphicsItem *parent = nullptr);
void adjust(); void adjust();
int id(); int id() const;
protected: protected:
void hoverEnterEvent(QGraphicsSceneHoverEvent *event) override; void hoverEnterEvent(QGraphicsSceneHoverEvent *event) override;

View File

@ -84,10 +84,12 @@ InformationWindow::InformationWindow(int id, QSqlRelationalTableModel *items,
//! [3] //! [3]
//! [4] //! [4]
connect(descriptionEditor, SIGNAL(textChanged()), connect(descriptionEditor, &QTextEdit::textChanged, [=]() {
this, SLOT(enableButtons())); enableButtons();
connect(imageFileEditor, SIGNAL(currentIndexChanged(int)), });
this, SLOT(enableButtons())); connect(imageFileEditor, QOverload<int>::of(&QComboBox::currentIndexChanged), [=]() {
enableButtons();
});
QFormLayout *formLayout = new QFormLayout; QFormLayout *formLayout = new QFormLayout;
formLayout->addRow(itemLabel, itemText); formLayout->addRow(itemLabel, itemText);
@ -109,7 +111,7 @@ InformationWindow::InformationWindow(int id, QSqlRelationalTableModel *items,
//! [4] //! [4]
//! [5] //! [5]
int InformationWindow::id() int InformationWindow::id() const
{ {
return itemId; return itemId;
} }
@ -149,9 +151,9 @@ void InformationWindow::createButtons()
closeButton->setDefault(true); closeButton->setDefault(true);
connect(closeButton, SIGNAL(clicked()), this, SLOT(close())); connect(closeButton, &QPushButton::clicked, this, &InformationWindow::close);
connect(revertButton, SIGNAL(clicked()), this, SLOT(revert())); connect(revertButton, &QPushButton::clicked, this, &InformationWindow::revert);
connect(submitButton, SIGNAL(clicked()), this, SLOT(submit())); connect(submitButton, &QPushButton::clicked, this, &InformationWindow::submit);
//! [8] //! [8]
//! [9] //! [9]

View File

@ -61,9 +61,9 @@ class InformationWindow : public QDialog
public: public:
InformationWindow(int id, QSqlRelationalTableModel *items, InformationWindow(int id, QSqlRelationalTableModel *items,
QWidget *parent = 0); QWidget *parent = nullptr);
int id(); int id() const;
signals: signals:
void imageChanged(int id, const QString &fileName); void imageChanged(int id, const QString &fileName);
@ -83,16 +83,16 @@ private:
int itemId; int itemId;
QString displayedImage; QString displayedImage;
QComboBox *imageFileEditor; QComboBox *imageFileEditor = nullptr;
QLabel *itemText; QLabel *itemText = nullptr;
QTextEdit *descriptionEditor; QTextEdit *descriptionEditor = nullptr;
QPushButton *closeButton; QPushButton *closeButton = nullptr;
QPushButton *submitButton; QPushButton *submitButton = nullptr;
QPushButton *revertButton; QPushButton *revertButton = nullptr;
QDialogButtonBox *buttonBox; QDialogButtonBox *buttonBox = nullptr;
QDataWidgetMapper *mapper; QDataWidgetMapper *mapper = nullptr;
}; };
//! [2] //! [2]

View File

@ -48,10 +48,13 @@
** **
****************************************************************************/ ****************************************************************************/
#include <QtWidgets>
#include "../connection.h"
#include "view.h" #include "view.h"
#include "../connection.h"
#include <QApplication>
#include <stdlib.h>
int main(int argc, char *argv[]) int main(int argc, char *argv[])
{ {
@ -60,7 +63,7 @@ int main(int argc, char *argv[])
QApplication app(argc, argv); QApplication app(argc, argv);
if (!createConnection()) if (!createConnection())
return 1; return EXIT_FAILURE;
View view("items", "images"); View view("items", "images");
view.show(); view.show();

View File

@ -89,8 +89,6 @@ void View::addItems()
int topMargin = 40; int topMargin = 40;
for (int i = 0; i < itemCount; i++) { for (int i = 0; i < itemCount; i++) {
ImageItem *image;
QGraphicsTextItem *label;
QSqlRecord record = itemTable->record(i); QSqlRecord record = itemTable->record(i);
int id = record.value("id").toInt(); int id = record.value("id").toInt();
@ -101,12 +99,12 @@ void View::addItems()
int x = ((i % 2) * imageOffset) + leftMargin + columnOffset; int x = ((i % 2) * imageOffset) + leftMargin + columnOffset;
int y = ((i / 2) * imageOffset) + topMargin; int y = ((i / 2) * imageOffset) + topMargin;
image = new ImageItem(id, QPixmap(":/" + file)); ImageItem *image = new ImageItem(id, QPixmap(":/" + file));
image->setData(0, i); image->setData(0, i);
image->setPos(x, y); image->setPos(x, y);
scene->addItem(image); scene->addItem(image);
label = scene->addText(item); QGraphicsTextItem *label = scene->addText(item);
label->setDefaultTextColor(QColor("#d7d6d5")); label->setDefaultTextColor(QColor("#d7d6d5"));
QPointF labelOffset((120 - label->boundingRect().width()) / 2, 120.0); QPointF labelOffset((120 - label->boundingRect().width()) / 2, 120.0);
label->setPos(QPointF(x, y) + labelOffset); label->setPos(QPointF(x, y) + labelOffset);
@ -133,22 +131,22 @@ void View::showInformation(ImageItem *image)
return; return;
InformationWindow *window = findWindow(id); InformationWindow *window = findWindow(id);
if (window && window->isVisible()) { if (!window) {
window->raise();
window->activateWindow();
} else if (window && !window->isVisible()) {
window->show();
} else {
InformationWindow *window;
window = new InformationWindow(id, itemTable, this); window = new InformationWindow(id, itemTable, this);
connect(window, SIGNAL(imageChanged(int,QString)), connect(window, QOverload<int,const QString &>::of(&InformationWindow::imageChanged),
this, SLOT(updateImage(int,QString))); this, QOverload<int,const QString &>::of(&View::updateImage));
window->move(pos() + QPoint(20, 40)); window->move(pos() + QPoint(20, 40));
window->show(); window->show();
informationWindows.append(window); informationWindows.append(window);
} }
if (window->isVisible()) {
window->raise();
window->activateWindow();
} else
window->show();
} }
//! [6] //! [6]
@ -172,19 +170,13 @@ void View::updateImage(int id, const QString &fileName)
//! [7] //! [7]
//! [8] //! [8]
InformationWindow* View::findWindow(int id) InformationWindow *View::findWindow(int id) const
{ {
QList<InformationWindow*>::iterator i, beginning, end; for (auto window : informationWindows) {
beginning = informationWindows.begin();
end = informationWindows.end();
for (i = beginning; i != end; ++i) {
InformationWindow *window = (*i);
if (window && (window->id() == id)) if (window && (window->id() == id))
return window; return window;
} }
return 0; return nullptr;
} }
//! [8] //! [8]

View File

@ -63,7 +63,7 @@ class View : public QGraphicsView
Q_OBJECT Q_OBJECT
public: public:
View(const QString &items, const QString &images, QWidget *parent = 0); View(const QString &items, const QString &images, QWidget *parent = nullptr);
protected: protected:
void mouseReleaseEvent(QMouseEvent *event) override; void mouseReleaseEvent(QMouseEvent *event) override;
@ -77,7 +77,7 @@ private slots:
//! [2] //! [2]
private: private:
void addItems(); void addItems();
InformationWindow* findWindow(int id); InformationWindow *findWindow(int id) const;
void showInformation(ImageItem *image); void showInformation(ImageItem *image);
QGraphicsScene *scene; QGraphicsScene *scene;

View File

@ -61,12 +61,12 @@ static bool createConnection()
QSqlDatabase db = QSqlDatabase::addDatabase("QSQLITE"); QSqlDatabase db = QSqlDatabase::addDatabase("QSQLITE");
db.setDatabaseName(":memory:"); db.setDatabaseName(":memory:");
if (!db.open()) { if (!db.open()) {
QMessageBox::critical(0, qApp->tr("Cannot open database"), QMessageBox::critical(nullptr, QObject::tr("Cannot open database"),
qApp->tr("Unable to establish a database connection.\n" QObject::tr("Unable to establish a database connection.\n"
"This example needs SQLite support. Please read " "This example needs SQLite support. Please read "
"the Qt SQL driver documentation for information how " "the Qt SQL driver documentation for information how "
"to build it.\n\n" "to build it.\n\n"
"Click Cancel to exit."), QMessageBox::Cancel); "Click Cancel to exit."), QMessageBox::Cancel);
return false; return false;
} }

View File

@ -155,12 +155,12 @@ int Dialog::addNewAlbum(const QString &title, int artistId)
return id; return id;
} }
void Dialog::addTracks(int albumId, QStringList tracks) void Dialog::addTracks(int albumId, const QStringList &tracks)
{ {
QDomElement albumNode = albumDetails.createElement("album"); QDomElement albumNode = albumDetails.createElement("album");
albumNode.setAttribute("id", albumId); albumNode.setAttribute("id", albumId);
for (int i = 0; i < tracks.count(); i++) { for (int i = 0; i < tracks.count(); ++i) {
QString trackNumber = QString::number(i); QString trackNumber = QString::number(i);
if (i < 10) if (i < 10)
trackNumber.prepend('0'); trackNumber.prepend('0');
@ -254,9 +254,9 @@ QDialogButtonBox *Dialog::createButtons()
closeButton->setDefault(true); closeButton->setDefault(true);
connect(closeButton, SIGNAL(clicked()), this, SLOT(close())); connect(closeButton, &QPushButton::clicked, this, &Dialog::close);
connect(revertButton, SIGNAL(clicked()), this, SLOT(revert())); connect(revertButton, &QPushButton::clicked, this, &Dialog::revert);
connect(submitButton, SIGNAL(clicked()), this, SLOT(submit())); connect(submitButton, &QPushButton::clicked, this, &Dialog::submit);
QDialogButtonBox *buttonBox = new QDialogButtonBox; QDialogButtonBox *buttonBox = new QDialogButtonBox;
buttonBox->addButton(submitButton, QDialogButtonBox::ResetRole); buttonBox->addButton(submitButton, QDialogButtonBox::ResetRole);
@ -270,7 +270,7 @@ QModelIndex Dialog::indexOfArtist(const QString &artist)
{ {
QSqlTableModel *artistModel = model->relationModel(2); QSqlTableModel *artistModel = model->relationModel(2);
for (int i = 0; i < artistModel->rowCount(); i++) { for (int i = 0; i < artistModel->rowCount(); ++i) {
QSqlRecord record = artistModel->record(i); QSqlRecord record = artistModel->record(i);
if (record.value("artist") == artist) if (record.value("artist") == artist)
return artistModel->index(i, 1); return artistModel->index(i, 1);

View File

@ -61,7 +61,7 @@ class Dialog : public QDialog
public: public:
Dialog(QSqlRelationalTableModel *albums, QDomDocument details, Dialog(QSqlRelationalTableModel *albums, QDomDocument details,
QFile *output, QWidget *parent = 0); QFile *output, QWidget *parent = nullptr);
private slots: private slots:
void revert(); void revert();
@ -70,12 +70,12 @@ private slots:
private: private:
int addNewAlbum(const QString &title, int artistId); int addNewAlbum(const QString &title, int artistId);
int addNewArtist(const QString &name); int addNewArtist(const QString &name);
void addTracks(int albumId, QStringList tracks); void addTracks(int albumId, const QStringList &tracks);
QDialogButtonBox *createButtons(); QDialogButtonBox *createButtons();
QGroupBox *createInputWidgets(); QGroupBox *createInputWidgets();
int findArtistId(const QString &artist); int findArtistId(const QString &artist);
int generateAlbumId(); static int generateAlbumId();
int generateArtistId(); static int generateArtistId();
void increaseAlbumCount(QModelIndex artistIndex); void increaseAlbumCount(QModelIndex artistIndex);
QModelIndex indexOfArtist(const QString &artist); QModelIndex indexOfArtist(const QString &artist);

View File

@ -48,11 +48,14 @@
** **
****************************************************************************/ ****************************************************************************/
#include <QtWidgets>
#include "database.h" #include "database.h"
#include "mainwindow.h" #include "mainwindow.h"
#include <QApplication>
#include <QFile>
#include <stdlib.h>
int main(int argc, char *argv[]) int main(int argc, char *argv[])
{ {
Q_INIT_RESOURCE(masterdetail); Q_INIT_RESOURCE(masterdetail);
@ -60,10 +63,10 @@ int main(int argc, char *argv[])
QApplication app(argc, argv); QApplication app(argc, argv);
if (!createConnection()) if (!createConnection())
return 1; return EXIT_FAILURE;
QFile *albumDetails = new QFile("albumdetails.xml"); QFile albumDetails("albumdetails.xml");
MainWindow window("artists", "albums", albumDetails); MainWindow window("artists", "albums", &albumDetails);
window.show(); window.show();
return app.exec(); return app.exec();
} }

View File

@ -78,10 +78,10 @@ MainWindow::MainWindow(const QString &artistTable, const QString &albumTable,
uniqueAlbumId = model->rowCount(); uniqueAlbumId = model->rowCount();
uniqueArtistId = artistView->count(); uniqueArtistId = artistView->count();
connect(model, SIGNAL(rowsInserted(QModelIndex,int,int)), connect(model, &QSqlRelationalTableModel::rowsInserted,
this, SLOT(updateHeader(QModelIndex,int,int))); this, &MainWindow::updateHeader);
connect(model, SIGNAL(rowsRemoved(QModelIndex,int,int)), connect(model, &QSqlRelationalTableModel::rowsRemoved,
this, SLOT(updateHeader(QModelIndex,int,int))); this, &MainWindow::updateHeader);
QGridLayout *layout = new QGridLayout; QGridLayout *layout = new QGridLayout;
layout->addWidget(artists, 0, 0); layout->addWidget(artists, 0, 0);
@ -145,7 +145,7 @@ void MainWindow::showAlbumDetails(QModelIndex index)
titleLabel->show(); titleLabel->show();
QDomNodeList albums = albumData.elementsByTagName("album"); QDomNodeList albums = albumData.elementsByTagName("album");
for (int i = 0; i < albums.count(); i++) { for (int i = 0; i < albums.count(); ++i) {
QDomNode album = albums.item(i); QDomNode album = albums.item(i);
if (album.toElement().attribute("id") == albumId) { if (album.toElement().attribute("id") == albumId) {
getTrackList(album.toElement()); getTrackList(album.toElement());
@ -164,9 +164,9 @@ void MainWindow::getTrackList(QDomNode album)
QDomNode track; QDomNode track;
QString trackNumber; QString trackNumber;
for (int j = 0; j < tracks.count(); j++) { for (int i = 0; i < tracks.count(); ++i) {
track = tracks.item(j); track = tracks.item(i);
trackNumber = track.toElement().attribute("number"); trackNumber = track.toElement().attribute("number");
QListWidgetItem *item = new QListWidgetItem(trackList); QListWidgetItem *item = new QListWidgetItem(trackList);
@ -222,7 +222,7 @@ void MainWindow::removeAlbumFromFile(int id)
QDomNodeList albums = albumData.elementsByTagName("album"); QDomNodeList albums = albumData.elementsByTagName("album");
for (int i = 0; i < albums.count(); i++) { for (int i = 0; i < albums.count(); ++i) {
QDomNode node = albums.item(i); QDomNode node = albums.item(i);
if (node.toElement().attribute("id").toInt() == id) { if (node.toElement().attribute("id").toInt() == id) {
albumData.elementsByTagName("archive").item(0).removeChild(node); albumData.elementsByTagName("archive").item(0).removeChild(node);
@ -283,8 +283,8 @@ QGroupBox* MainWindow::createArtistGroupBox()
artistView->setModel(model->relationModel(2)); artistView->setModel(model->relationModel(2));
artistView->setModelColumn(1); artistView->setModelColumn(1);
connect(artistView, SIGNAL(currentIndexChanged(int)), connect(artistView, QOverload<int>::of(&QComboBox::currentIndexChanged),
this, SLOT(changeArtist(int))); this, &MainWindow::changeArtist);
QGroupBox *box = new QGroupBox(tr("Artist")); QGroupBox *box = new QGroupBox(tr("Artist"));
@ -314,10 +314,10 @@ QGroupBox* MainWindow::createAlbumGroupBox()
locale.setNumberOptions(QLocale::OmitGroupSeparator); locale.setNumberOptions(QLocale::OmitGroupSeparator);
albumView->setLocale(locale); albumView->setLocale(locale);
connect(albumView, SIGNAL(clicked(QModelIndex)), connect(albumView, &QTableView::clicked,
this, SLOT(showAlbumDetails(QModelIndex))); this, &MainWindow::showAlbumDetails);
connect(albumView, SIGNAL(activated(QModelIndex)), connect(albumView, &QTableView::activated,
this, SLOT(showAlbumDetails(QModelIndex))); this, &MainWindow::showAlbumDetails);
QVBoxLayout *layout = new QVBoxLayout; QVBoxLayout *layout = new QVBoxLayout;
layout->addWidget(albumView, 0, 0); layout->addWidget(albumView, 0, 0);
@ -383,11 +383,16 @@ void MainWindow::createMenuBar()
helpMenu->addAction(aboutAction); helpMenu->addAction(aboutAction);
helpMenu->addAction(aboutQtAction); helpMenu->addAction(aboutQtAction);
connect(addAction, SIGNAL(triggered(bool)), this, SLOT(addAlbum())); connect(addAction, &QAction::triggered,
connect(deleteAction, SIGNAL(triggered(bool)), this, SLOT(deleteAlbum())); this, &MainWindow::addAlbum);
connect(quitAction, SIGNAL(triggered(bool)), this, SLOT(close())); connect(deleteAction, &QAction::triggered,
connect(aboutAction, SIGNAL(triggered(bool)), this, SLOT(about())); this, &MainWindow::deleteAlbum);
connect(aboutQtAction, SIGNAL(triggered(bool)), qApp, SLOT(aboutQt())); connect(quitAction, &QAction::triggered,
this, &MainWindow::close);
connect(aboutAction, &QAction::triggered,
this, &MainWindow::about);
connect(aboutQtAction, &QAction::triggered,
qApp, &QApplication::aboutQt);
} }
void MainWindow::showImageLabel() void MainWindow::showImageLabel()

View File

@ -71,7 +71,7 @@ class MainWindow : public QMainWindow
public: public:
MainWindow(const QString &artistTable, const QString &albumTable, MainWindow(const QString &artistTable, const QString &albumTable,
QFile *albumDetails, QWidget *parent = 0); QFile *albumDetails, QWidget *parent = nullptr);
private slots: private slots:
void about(); void about();

View File

@ -59,7 +59,7 @@ class CustomSqlModel : public QSqlQueryModel
Q_OBJECT Q_OBJECT
public: public:
CustomSqlModel(QObject *parent = 0); CustomSqlModel(QObject *parent = nullptr);
QVariant data(const QModelIndex &item, int role) const override; QVariant data(const QModelIndex &item, int role) const override;
}; };

View File

@ -58,7 +58,7 @@ class EditableSqlModel : public QSqlQueryModel
Q_OBJECT Q_OBJECT
public: public:
EditableSqlModel(QObject *parent = 0); EditableSqlModel(QObject *parent = nullptr);
Qt::ItemFlags flags(const QModelIndex &index) const override; Qt::ItemFlags flags(const QModelIndex &index) const override;
bool setData(const QModelIndex &index, const QVariant &value, int role) override; bool setData(const QModelIndex &index, const QVariant &value, int role) override;

View File

@ -48,12 +48,15 @@
** **
****************************************************************************/ ****************************************************************************/
#include <QtWidgets>
#include "../connection.h" #include "../connection.h"
#include "customsqlmodel.h" #include "customsqlmodel.h"
#include "editablesqlmodel.h" #include "editablesqlmodel.h"
#include <QApplication>
#include <QTableView>
#include <stdlib.h>
void initializeModel(QSqlQueryModel *model) void initializeModel(QSqlQueryModel *model)
{ {
model->setQuery("select * from person"); model->setQuery("select * from person");
@ -80,7 +83,7 @@ int main(int argc, char *argv[])
{ {
QApplication app(argc, argv); QApplication app(argc, argv);
if (!createConnection()) if (!createConnection())
return 1; return EXIT_FAILURE;
QSqlQueryModel plainModel; QSqlQueryModel plainModel;
EditableSqlModel editableModel; EditableSqlModel editableModel;

View File

@ -110,7 +110,8 @@ int main(int argc, char *argv[])
{ {
QApplication app(argc, argv); QApplication app(argc, argv);
if (!createConnection()) if (!createConnection())
return 1; return EXIT_FAILURE;
createRelationalTables(); createRelationalTables();
QSqlRelationalTableModel model; QSqlRelationalTableModel model;

View File

@ -165,11 +165,12 @@ void Browser::showTable(const QString &t)
model->select(); model->select();
if (model->lastError().type() != QSqlError::NoError) if (model->lastError().type() != QSqlError::NoError)
emit statusMessage(model->lastError().text()); emit statusMessage(model->lastError().text());
table->setModel(model); table->setModel(model);
table->setEditTriggers(QAbstractItemView::DoubleClicked|QAbstractItemView::EditKeyPressed); table->setEditTriggers(QAbstractItemView::DoubleClicked|QAbstractItemView::EditKeyPressed);
connect(table->selectionModel(), &QItemSelectionModel::currentRowChanged,
this, &Browser::currentChanged);
connect(table->selectionModel(), SIGNAL(currentRowChanged(QModelIndex,QModelIndex)),
this, SLOT(currentChanged()));
updateActions(); updateActions();
} }
@ -189,7 +190,6 @@ void Browser::showMetaData(const QString &t)
model->setHeaderData(5, Qt::Horizontal, "AutoValue"); model->setHeaderData(5, Qt::Horizontal, "AutoValue");
model->setHeaderData(6, Qt::Horizontal, "DefaultValue"); model->setHeaderData(6, Qt::Horizontal, "DefaultValue");
for (int i = 0; i < rec.count(); ++i) { for (int i = 0; i < rec.count(); ++i) {
QSqlField fld = rec.field(i); QSqlField fld = rec.field(i);
model->setData(model->index(i, 0), fld.name()); model->setData(model->index(i, 0), fld.name());

View File

@ -65,7 +65,7 @@ class Browser: public QWidget, private Ui::Browser
{ {
Q_OBJECT Q_OBJECT
public: public:
Browser(QWidget *parent = 0); Browser(QWidget *parent = nullptr);
virtual ~Browser(); virtual ~Browser();
QSqlError addConnection(const QString &driver, const QString &dbName, const QString &host, QSqlError addConnection(const QString &driver, const QString &dbName, const QString &host,
@ -116,7 +116,9 @@ class CustomModel: public QSqlTableModel
{ {
Q_OBJECT Q_OBJECT
public: public:
explicit CustomModel(QObject *parent = 0, QSqlDatabase db = QSqlDatabase()):QSqlTableModel(parent, db) {} explicit CustomModel(QObject *parent = nullptr, QSqlDatabase db = QSqlDatabase())
: QSqlTableModel(parent, db) {}
QVariant data(const QModelIndex &idx, int role) const override QVariant data(const QModelIndex &idx, int role) const override
{ {
if (role == Qt::BackgroundRole && isDirty(idx)) if (role == Qt::BackgroundRole && isDirty(idx))

View File

@ -63,8 +63,8 @@ ConnectionWidget::ConnectionWidget(QWidget *parent)
tree->header()->setSectionResizeMode(QHeaderView::Stretch); tree->header()->setSectionResizeMode(QHeaderView::Stretch);
QAction *refreshAction = new QAction(tr("Refresh"), tree); QAction *refreshAction = new QAction(tr("Refresh"), tree);
metaDataAction = new QAction(tr("Show Schema"), tree); metaDataAction = new QAction(tr("Show Schema"), tree);
connect(refreshAction, SIGNAL(triggered()), SLOT(refresh())); connect(refreshAction, &QAction::triggered, this, &ConnectionWidget::refresh);
connect(metaDataAction, SIGNAL(triggered()), SLOT(showMetaData())); connect(metaDataAction, &QAction::triggered, this, &ConnectionWidget::showMetaData);
tree->addAction(refreshAction); tree->addAction(refreshAction);
tree->addAction(metaDataAction); tree->addAction(metaDataAction);
tree->setContextMenuPolicy(Qt::ActionsContextMenu); tree->setContextMenuPolicy(Qt::ActionsContextMenu);
@ -146,7 +146,6 @@ void ConnectionWidget::setActive(QTreeWidgetItem *item)
void ConnectionWidget::on_tree_itemActivated(QTreeWidgetItem *item, int /* column */) void ConnectionWidget::on_tree_itemActivated(QTreeWidgetItem *item, int /* column */)
{ {
if (!item) if (!item)
return; return;

View File

@ -62,7 +62,7 @@ class ConnectionWidget: public QWidget
{ {
Q_OBJECT Q_OBJECT
public: public:
ConnectionWidget(QWidget *parent = 0); ConnectionWidget(QWidget *parent = nullptr);
virtual ~ConnectionWidget(); virtual ~ConnectionWidget();
QSqlDatabase currentDatabase() const; QSqlDatabase currentDatabase() const;

View File

@ -80,16 +80,18 @@ int main(int argc, char *argv[])
mainWin.setCentralWidget(&browser); mainWin.setCentralWidget(&browser);
QMenu *fileMenu = mainWin.menuBar()->addMenu(QObject::tr("&File")); QMenu *fileMenu = mainWin.menuBar()->addMenu(QObject::tr("&File"));
fileMenu->addAction(QObject::tr("Add &Connection..."), &browser, SLOT(addConnection())); fileMenu->addAction(QObject::tr("Add &Connection..."),
[&]() { browser.addConnection(); });
fileMenu->addSeparator(); fileMenu->addSeparator();
fileMenu->addAction(QObject::tr("&Quit"), &app, SLOT(quit())); fileMenu->addAction(QObject::tr("&Quit"), []() { qApp->quit(); });
QMenu *helpMenu = mainWin.menuBar()->addMenu(QObject::tr("&Help")); QMenu *helpMenu = mainWin.menuBar()->addMenu(QObject::tr("&Help"));
helpMenu->addAction(QObject::tr("About"), &browser, SLOT(about())); helpMenu->addAction(QObject::tr("About"), [&]() { browser.about(); });
helpMenu->addAction(QObject::tr("About Qt"), qApp, SLOT(aboutQt())); helpMenu->addAction(QObject::tr("About Qt"), []() { qApp->aboutQt(); });
QObject::connect(&browser, SIGNAL(statusMessage(QString)), QObject::connect(&browser, &Browser::statusMessage, [&mainWin](const QString &text) {
mainWin.statusBar(), SLOT(showMessage(QString))); mainWin.statusBar()->showMessage(text);
});
addConnectionsFromCommandline(app.arguments(), &browser); addConnectionsFromCommandline(app.arguments(), &browser);
mainWin.show(); mainWin.show();

View File

@ -60,7 +60,7 @@ class QSqlConnectionDialog: public QDialog
{ {
Q_OBJECT Q_OBJECT
public: public:
QSqlConnectionDialog(QWidget *parent = 0); QSqlConnectionDialog(QWidget *parent = nullptr);
~QSqlConnectionDialog(); ~QSqlConnectionDialog();
QString driverName() const; QString driverName() const;

View File

@ -87,12 +87,12 @@ Window::Window(QWidget *parent)
//! [Set up the mapper] //! [Set up the mapper]
//! [Set up connections and layouts] //! [Set up connections and layouts]
connect(previousButton, SIGNAL(clicked()), connect(previousButton, &QPushButton::clicked,
mapper, SLOT(toPrevious())); mapper, &QDataWidgetMapper::toPrevious);
connect(nextButton, SIGNAL(clicked()), connect(nextButton, &QPushButton::clicked,
mapper, SLOT(toNext())); mapper, &QDataWidgetMapper::toNext);
connect(mapper, SIGNAL(currentIndexChanged(int)), connect(mapper, &QDataWidgetMapper::currentIndexChanged,
this, SLOT(updateButtons(int))); this, &Window::updateButtons);
QGridLayout *layout = new QGridLayout(); QGridLayout *layout = new QGridLayout();
layout->addWidget(nameLabel, 0, 0, 1, 1); layout->addWidget(nameLabel, 0, 0, 1, 1);

View File

@ -72,7 +72,7 @@ class Window : public QWidget
Q_OBJECT Q_OBJECT
public: public:
Window(QWidget *parent = 0); Window(QWidget *parent = nullptr);
private slots: private slots:
void updateButtons(int row); void updateButtons(int row);

View File

@ -47,12 +47,14 @@
** $QT_END_LICENSE$ ** $QT_END_LICENSE$
** **
****************************************************************************/ ****************************************************************************/
#include <QtWidgets>
#include <QtSql>
#include "../connection.h" #include "../connection.h"
#include <QApplication>
#include <QSqlTableModel>
#include <QTableView>
#include <stdlib.h>
void initializeModel(QSqlTableModel *model) void initializeModel(QSqlTableModel *model)
{ {
model->setTable("person"); model->setTable("person");
@ -76,7 +78,7 @@ int main(int argc, char *argv[])
{ {
QApplication app(argc, argv); QApplication app(argc, argv);
if (!createConnection()) if (!createConnection())
return 1; return EXIT_FAILURE;
QSqlTableModel model; QSqlTableModel model;

View File

@ -14,4 +14,3 @@ SUBDIRS = classwizard \
!qtConfig(wizard) { !qtConfig(wizard) {
SUBDIRS -= trivialwizard licensewizard classwizard SUBDIRS -= trivialwizard licensewizard classwizard
} }
wince: SUBDIRS += sipdialog

View File

@ -51,6 +51,7 @@
#include <QtWidgets/QApplication> #include <QtWidgets/QApplication>
#include <QtWidgets/QHeaderView> #include <QtWidgets/QHeaderView>
#include <QtWidgets/QShortcut>
#include <QtWidgets/QTreeView> #include <QtWidgets/QTreeView>
#include "storagemodel.h" #include "storagemodel.h"
@ -60,9 +61,16 @@ int main(int argc, char *argv[])
QApplication a(argc, argv); QApplication a(argc, argv);
QTreeView view; QTreeView view;
view.setModel(new StorageModel(&view));
view.resize(640, 480); view.resize(640, 480);
view.setWindowTitle("Storage View");
view.setSelectionBehavior(QAbstractItemView::SelectRows); view.setSelectionBehavior(QAbstractItemView::SelectRows);
StorageModel *model = new StorageModel(&view);
model->refresh();
QShortcut *refreshShortcut = new QShortcut(Qt::CTRL + Qt::Key_R, &view);
QObject::connect(refreshShortcut, &QShortcut::activated, model, &StorageModel::refresh);
view.setModel(model);
int columnCount = view.model()->columnCount(); int columnCount = view.model()->columnCount();
for (int c = 0; c < columnCount; ++c) for (int c = 0; c < columnCount; ++c)
view.resizeColumnToContents(c); view.resizeColumnToContents(c);

View File

@ -54,14 +54,27 @@
#include <QDir> #include <QDir>
#include <QLocale> #include <QLocale>
#include <qmath.h> #include <qmath.h>
#include <algorithm>
#include <cmath> #include <cmath>
StorageModel::StorageModel(QObject *parent) : StorageModel::StorageModel(QObject *parent) :
QAbstractTableModel(parent), QAbstractTableModel(parent)
m_volumes(QStorageInfo::mountedVolumes())
{ {
} }
void StorageModel::refresh()
{
beginResetModel();
m_volumes = QStorageInfo::mountedVolumes();
std::sort(m_volumes.begin(), m_volumes.end(),
[](const QStorageInfo &st1, const QStorageInfo &st2) {
static const QString rootSortString = QStringLiteral(" ");
return (st1.isRoot() ? rootSortString : st1.rootPath())
< (st2.isRoot() ? rootSortString : st2.rootPath());
});
endResetModel();
}
int StorageModel::columnCount(const QModelIndex &/*parent*/) const int StorageModel::columnCount(const QModelIndex &/*parent*/) const
{ {
return ColumnCount; return ColumnCount;
@ -74,6 +87,22 @@ int StorageModel::rowCount(const QModelIndex &parent) const
return m_volumes.count(); return m_volumes.count();
} }
Qt::ItemFlags StorageModel::flags(const QModelIndex &index) const
{
Qt::ItemFlags result = QAbstractTableModel::flags(index);
switch (index.column()) {
case ColumnAvailable:
case ColumnIsReady:
case ColumnIsReadOnly:
case ColumnIsValid:
result |= Qt::ItemIsUserCheckable;
break;
default:
break;
}
return result;
}
QVariant StorageModel::data(const QModelIndex &index, int role) const QVariant StorageModel::data(const QModelIndex &index, int role) const
{ {
if (!index.isValid()) if (!index.isValid())
@ -96,6 +125,12 @@ QVariant StorageModel::data(const QModelIndex &index, int role) const
return QLocale().formattedDataSize(volume.bytesFree()); return QLocale().formattedDataSize(volume.bytesFree());
case ColumnAvailable: case ColumnAvailable:
return QLocale().formattedDataSize(volume.bytesAvailable()); return QLocale().formattedDataSize(volume.bytesAvailable());
default:
break;
}
} else if (role == Qt::CheckStateRole) {
const QStorageInfo &volume = m_volumes.at(index.row());
switch (index.column()) {
case ColumnIsReady: case ColumnIsReady:
return volume.isReady(); return volume.isReady();
case ColumnIsReadOnly: case ColumnIsReadOnly:
@ -105,6 +140,16 @@ QVariant StorageModel::data(const QModelIndex &index, int role) const
default: default:
break; break;
} }
} else if (role == Qt::TextAlignmentRole) {
switch (index.column()) {
case ColumnTotal:
case ColumnFree:
case ColumnAvailable:
return Qt::AlignTrailing;
default:
break;
}
return Qt::AlignLeading;
} else if (role == Qt::ToolTipRole) { } else if (role == Qt::ToolTipRole) {
QLocale locale; QLocale locale;
const QStorageInfo &volume = m_volumes.at(index.row()); const QStorageInfo &volume = m_volumes.at(index.row());
@ -147,13 +192,13 @@ QVariant StorageModel::headerData(int section, Qt::Orientation orientation, int
switch (section) { switch (section) {
case ColumnRootPath: case ColumnRootPath:
return tr("Root path"); return tr("Root Path");
case ColumnName: case ColumnName:
return tr("Volume Name"); return tr("Volume Name");
case ColumnDevice: case ColumnDevice:
return tr("Device"); return tr("Device");
case ColumnFileSystemName: case ColumnFileSystemName:
return tr("File system"); return tr("File System");
case ColumnTotal: case ColumnTotal:
return tr("Total"); return tr("Total");
case ColumnFree: case ColumnFree:

View File

@ -74,13 +74,17 @@ public:
ColumnCount ColumnCount
}; };
explicit StorageModel(QObject *parent = 0); explicit StorageModel(QObject *parent = nullptr);
int columnCount(const QModelIndex &parent) const; int columnCount(const QModelIndex &parent) const override;
int rowCount(const QModelIndex &parent) const; int rowCount(const QModelIndex &parent) const override;
QVariant data(const QModelIndex &index, int role) const; QVariant data(const QModelIndex &index, int role) const override;
QVariant headerData(int section, Qt::Orientation orientation, int role) const; Qt::ItemFlags flags(const QModelIndex &index) const override;
QVariant headerData(int section, Qt::Orientation orientation, int role) const override;
public slots:
void refresh();
private: private:
QList<QStorageInfo> m_volumes; QList<QStorageInfo> m_volumes;

View File

@ -9,16 +9,20 @@ include(../common/linux.conf)
include(../common/gcc-base-unix.conf) include(../common/gcc-base-unix.conf)
include(../common/android-base-head.conf) include(../common/android-base-head.conf)
QMAKE_CC = $$NDK_TOOLCHAIN_PATH/bin/$$NDK_TOOLS_PREFIX-gcc QMAKE_CC = $${CROSS_COMPILE}gcc
QMAKE_CXX = $$NDK_TOOLCHAIN_PATH/bin/$$NDK_TOOLS_PREFIX-g++ QMAKE_CXX = $${CROSS_COMPILE}g++
QMAKE_LINK = $$QMAKE_CXX QMAKE_LINK = $$QMAKE_CXX
ANDROID_SOURCES_CXX_STL_LIBDIR = $$NDK_ROOT/sources/cxx-stl/gnu-libstdc++/$$NDK_TOOLCHAIN_VERSION/libs/$$ANDROID_TARGET_ARCH ANDROID_SOURCES_CXX_STL_LIBDIR = $$NDK_ROOT/sources/cxx-stl/gnu-libstdc++/$$NDK_TOOLCHAIN_VERSION/libs/$$ANDROID_TARGET_ARCH
ANDROID_STDCPP_PATH = $$ANDROID_SOURCES_CXX_STL_LIBDIR/libgnustl_shared.so ANDROID_STDCPP_PATH = $$ANDROID_SOURCES_CXX_STL_LIBDIR/libgnustl_shared.so
ANDROID_CXX_STL_LIBS = -lgnustl_shared -lgcc ANDROID_CXX_STL_LIBS = -lgnustl_shared -lgcc
QMAKE_CFLAGS += --sysroot=$$ANDROID_PLATFORM_ROOT_PATH \ exists($$NDK_ROOT/sysroot/usr/include): \
-isystem $$NDK_ROOT/sources/cxx-stl/gnu-libstdc++/$$NDK_TOOLCHAIN_VERSION/include \ QMAKE_CFLAGS += --sysroot=$$NDK_ROOT/sysroot \
-isystem $$NDK_ROOT/sysroot/usr/include/$$NDK_TOOLS_PREFIX
else: QMAKE_CFLAGS += --sysroot=$$ANDROID_PLATFORM_ROOT_PATH
QMAKE_CFLAGS += -isystem $$NDK_ROOT/sources/cxx-stl/gnu-libstdc++/$$NDK_TOOLCHAIN_VERSION/include \
-isystem $$ANDROID_SOURCES_CXX_STL_LIBDIR/include -isystem $$ANDROID_SOURCES_CXX_STL_LIBDIR/include
equals(ANDROID_TARGET_ARCH, armeabi)|equals(ANDROID_TARGET_ARCH, armeabi-v7a): \ equals(ANDROID_TARGET_ARCH, armeabi)|equals(ANDROID_TARGET_ARCH, armeabi-v7a): \

View File

@ -74,3 +74,4 @@ ANDROID_PLATFORM_PATH = $$ANDROID_PLATFORM_ROOT_PATH/usr
equals(ANDROID_TARGET_ARCH, x86_64)|equals(ANDROID_TARGET_ARCH, mips64): \ equals(ANDROID_TARGET_ARCH, x86_64)|equals(ANDROID_TARGET_ARCH, mips64): \
QMAKE_ANDROID_PLATFORM_LIBDIR = $${QMAKE_ANDROID_PLATFORM_LIBDIR}64 QMAKE_ANDROID_PLATFORM_LIBDIR = $${QMAKE_ANDROID_PLATFORM_LIBDIR}64
CROSS_COMPILE = $$NDK_TOOLCHAIN_PATH/bin/$$NDK_TOOLS_PREFIX-

View File

@ -57,14 +57,14 @@ QMAKE_CXXFLAGS_THREAD = $$QMAKE_CFLAGS_THREAD
QMAKE_CXXFLAGS_HIDESYMS = $$QMAKE_CFLAGS_HIDESYMS -fvisibility-inlines-hidden QMAKE_CXXFLAGS_HIDESYMS = $$QMAKE_CFLAGS_HIDESYMS -fvisibility-inlines-hidden
# modifications to linux.conf # modifications to linux.conf
QMAKE_AR = $$NDK_TOOLCHAIN_PATH/bin/$$NDK_TOOLS_PREFIX-ar cqs QMAKE_AR = $${CROSS_COMPILE}ar cqs
QMAKE_OBJCOPY = $$NDK_TOOLCHAIN_PATH/bin/$$NDK_TOOLS_PREFIX-objcopy QMAKE_OBJCOPY = $${CROSS_COMPILE}objcopy
QMAKE_NM = $$NDK_TOOLCHAIN_PATH/bin/$$NDK_TOOLS_PREFIX-nm -P QMAKE_NM = $${CROSS_COMPILE}nm -P
QMAKE_STRIP = QMAKE_STRIP =
#$$NDK_TOOLCHAIN_PATH/bin/$$NDK_TOOLS_PREFIX-strip #$${CROSS_COMPILE}strip
QMAKE_RANLIB = $$NDK_TOOLCHAIN_PATH/bin/$$NDK_TOOLS_PREFIX-ranlib QMAKE_RANLIB = $${CROSS_COMPILE}ranlib
QMAKE_INCDIR_POST = QMAKE_INCDIR_POST =
QMAKE_LIBDIR_POST = $$ANDROID_SOURCES_CXX_STL_LIBDIR QMAKE_LIBDIR_POST = $$ANDROID_SOURCES_CXX_STL_LIBDIR

View File

@ -45,7 +45,7 @@ if(gcc|intel_icl|msvc):!rim_qcc:!uikit:!no_moc_predefs:if(!macos|count(QMAKE_APP
defineReplace(mocCmdBase) { defineReplace(mocCmdBase) {
!isEmpty(WIN_INCLUDETEMP) { !isEmpty(WIN_INCLUDETEMP) {
incvar = @$$WIN_INCLUDETEMP incvar = @$$shell_quote($$WIN_INCLUDETEMP)
} else { } else {
incvar = incvar =
for (inc, MOC_INCLUDEPATH): \ for (inc, MOC_INCLUDEPATH): \

View File

@ -74,10 +74,10 @@ warnings_are_errors:warning_clean {
# compiler. # compiler.
clang { clang {
# Apple clang 4.0-4.2,5.0-5.1,6.0-6.4,7.0-7.3 # Apple clang 4.0-4.2,5.0-5.1,6.0-6.4,7.0-7.3
# Regular clang 3.3-3.9, 4.0 # Regular clang 3.x-5.0
apple_ver = $${QT_APPLE_CLANG_MAJOR_VERSION}.$${QT_APPLE_CLANG_MINOR_VERSION} apple_ver = $${QT_APPLE_CLANG_MAJOR_VERSION}.$${QT_APPLE_CLANG_MINOR_VERSION}
reg_ver = $${QT_CLANG_MAJOR_VERSION}.$${QT_CLANG_MINOR_VERSION} reg_ver = $${QT_CLANG_MAJOR_VERSION}.$${QT_CLANG_MINOR_VERSION}
contains(apple_ver, "4\\.[012]|5\\.[01]|6\\.[01234]|7\\.[0123]")|contains(reg_ver, "3\\.[3-9]|4\\.0") { contains(apple_ver, "4\\.[012]|5\\.[01]|6\\.[01234]|7\\.[0123]")|contains(reg_ver, "[34]\\.|5\\.0") {
QMAKE_CXXFLAGS_WARN_ON += -Werror -Wno-error=\\$${LITERAL_HASH}warnings -Wno-error=deprecated-declarations $$WERROR QMAKE_CXXFLAGS_WARN_ON += -Werror -Wno-error=\\$${LITERAL_HASH}warnings -Wno-error=deprecated-declarations $$WERROR
} }
} else:intel_icc:linux { } else:intel_icc:linux {

View File

@ -232,17 +232,17 @@ QMAKE_COMPILER_DEFINES += __cplusplus=$$QT_COMPILER_STDCXX
QMAKE_COMPILER_DEFINES += __INTEL_COMPILER=$$QMAKE_ICC_VER __INTEL_COMPILER_UPDATE=$$QMAKE_ICC_UPDATE_VER QMAKE_COMPILER_DEFINES += __INTEL_COMPILER=$$QMAKE_ICC_VER __INTEL_COMPILER_UPDATE=$$QMAKE_ICC_UPDATE_VER
!isEmpty(QMAKE_APPLE_CC): \ !isEmpty(QMAKE_APPLE_CC): \
QMAKE_COMPILER_DEFINES += __APPLE_CC__=$$QMAKE_APPLE_CC QMAKE_COMPILER_DEFINES += __APPLE_CC__=$$QMAKE_APPLE_CC
!isEmpty(QT_APPLE_CLANG_MAJOR_VERSION): \ !isEmpty(QMAKE_APPLE_CLANG_MAJOR_VERSION): \
QMAKE_COMPILER_DEFINES += __clang__ \ QMAKE_COMPILER_DEFINES += __clang__ \
__clang_major__=$$QMAKE_APPLE_CLANG_MAJOR_VERSION \ __clang_major__=$$QMAKE_APPLE_CLANG_MAJOR_VERSION \
__clang_minor__=$$QMAKE_APPLE_CLANG_MINOR_VERSION \ __clang_minor__=$$QMAKE_APPLE_CLANG_MINOR_VERSION \
__clang_patchlevel__=$$QMAKE_APPLE_CLANG_PATCH_VERSION __clang_patchlevel__=$$QMAKE_APPLE_CLANG_PATCH_VERSION
!isEmpty(QT_CLANG_MAJOR_VERSION): \ !isEmpty(QMAKE_CLANG_MAJOR_VERSION): \
QMAKE_COMPILER_DEFINES += __clang__ \ QMAKE_COMPILER_DEFINES += __clang__ \
__clang_major__=$$QMAKE_CLANG_MAJOR_VERSION \ __clang_major__=$$QMAKE_CLANG_MAJOR_VERSION \
__clang_minor__=$$QMAKE_CLANG_MINOR_VERSION \ __clang_minor__=$$QMAKE_CLANG_MINOR_VERSION \
__clang_patchlevel__=$$QMAKE_CLANG_PATCH_VERSION __clang_patchlevel__=$$QMAKE_CLANG_PATCH_VERSION
!isEmpty(QT_GCC_MAJOR_VERSION): \ !isEmpty(QMAKE_GCC_MAJOR_VERSION): \
QMAKE_COMPILER_DEFINES += \ QMAKE_COMPILER_DEFINES += \
__GNUC__=$$QMAKE_GCC_MAJOR_VERSION \ __GNUC__=$$QMAKE_GCC_MAJOR_VERSION \
__GNUC_MINOR__=$$QMAKE_GCC_MINOR_VERSION \ __GNUC_MINOR__=$$QMAKE_GCC_MINOR_VERSION \

View File

@ -0,0 +1,19 @@
macx-xcode: return()
darwin: load(sdk)
ccache_prefix = ccache
precompile_header {
CCACHE_SLOPPINESS += pch_defines time_macros
ccache_prefix = \
CCACHE_SLOPPINESS=\"$$join(CCACHE_SLOPPINESS, ',')\$${CCACHE_SLOPPINESS+,\$$CCACHE_SLOPPINESS}\" \
# Make sure we build sources directly, not from their preprocessed version,
# otherwise precompiled headers will not be used during cache misses.
CCACHE_CPP2=true \
$$ccache_prefix
}
for(tool, $$list(QMAKE_CC QMAKE_CXX QMAKE_LINK QMAKE_LINK_SHLIB QMAKE_LINK_C)): \
$$tool = $$ccache_prefix $$eval($$tool)

View File

@ -245,9 +245,15 @@ static int doLink(int argc, char **argv)
static int installFile(const QString &source, const QString &target, bool exe = false) static int installFile(const QString &source, const QString &target, bool exe = false)
{ {
QFile sourceFile(source); QFile sourceFile(source);
QFile targetFile(target);
QFile::remove(target); if (targetFile.exists()) {
QDir::root().mkpath(QFileInfo(target).absolutePath()); #ifdef Q_OS_WIN
targetFile.setPermissions(targetFile.permissions() | QFile::WriteUser);
#endif
QFile::remove(target);
} else {
QDir::root().mkpath(QFileInfo(target).absolutePath());
}
if (!sourceFile.copy(target)) { if (!sourceFile.copy(target)) {
fprintf(stderr, "Error copying %s to %s: %s\n", source.toLatin1().constData(), qPrintable(target), qPrintable(sourceFile.errorString())); fprintf(stderr, "Error copying %s to %s: %s\n", source.toLatin1().constData(), qPrintable(target), qPrintable(sourceFile.errorString()));
@ -255,7 +261,6 @@ static int installFile(const QString &source, const QString &target, bool exe =
} }
if (exe) { if (exe) {
QFile targetFile(target);
if (!targetFile.setPermissions(sourceFile.permissions() | QFileDevice::ExeOwner | QFileDevice::ExeUser | if (!targetFile.setPermissions(sourceFile.permissions() | QFileDevice::ExeOwner | QFileDevice::ExeUser |
QFileDevice::ExeGroup | QFileDevice::ExeOther)) { QFileDevice::ExeGroup | QFileDevice::ExeOther)) {
fprintf(stderr, "Error setting execute permissions on %s: %s\n", fprintf(stderr, "Error setting execute permissions on %s: %s\n",
@ -266,10 +271,20 @@ static int installFile(const QString &source, const QString &target, bool exe =
// Copy file times // Copy file times
QString error; QString error;
#ifdef Q_OS_WIN
const QFile::Permissions permissions = targetFile.permissions();
const bool readOnly = !(permissions & QFile::WriteUser);
if (readOnly)
targetFile.setPermissions(permissions | QFile::WriteUser);
#endif
if (!IoUtils::touchFile(target, sourceFile.fileName(), &error)) { if (!IoUtils::touchFile(target, sourceFile.fileName(), &error)) {
fprintf(stderr, "%s", qPrintable(error)); fprintf(stderr, "%s", qPrintable(error));
return 3; return 3;
} }
#ifdef Q_OS_WIN
if (readOnly)
targetFile.setPermissions(permissions);
#endif
return 0; return 0;
} }

View File

@ -100,7 +100,6 @@ FILES="
src/pcre2_newline.c src/pcre2_newline.c
src/pcre2_ord2utf.c src/pcre2_ord2utf.c
src/pcre2_pattern_info.c src/pcre2_pattern_info.c
src/pcre2_printint.c
src/pcre2_serialize.c src/pcre2_serialize.c
src/pcre2_string_utils.c src/pcre2_string_utils.c
src/pcre2_study.c src/pcre2_study.c

View File

@ -15,7 +15,7 @@ load(qt_helper_lib)
DEFINES += HAVE_CONFIG_H DEFINES += HAVE_CONFIG_H
# platform/compiler specific definitions # platform/compiler specific definitions
ios|qnx|winrt: DEFINES += PCRE2_DISABLE_JIT uikit|qnx|winrt: DEFINES += PCRE2_DISABLE_JIT
SOURCES += \ SOURCES += \
$$PWD/src/pcre2_auto_possess.c \ $$PWD/src/pcre2_auto_possess.c \
@ -33,7 +33,6 @@ SOURCES += \
$$PWD/src/pcre2_newline.c \ $$PWD/src/pcre2_newline.c \
$$PWD/src/pcre2_ord2utf.c \ $$PWD/src/pcre2_ord2utf.c \
$$PWD/src/pcre2_pattern_info.c \ $$PWD/src/pcre2_pattern_info.c \
$$PWD/src/pcre2_printint.c \
$$PWD/src/pcre2_serialize.c \ $$PWD/src/pcre2_serialize.c \
$$PWD/src/pcre2_string_utils.c \ $$PWD/src/pcre2_string_utils.c \
$$PWD/src/pcre2_study.c \ $$PWD/src/pcre2_study.c \

View File

@ -1,831 +0,0 @@
/*************************************************
* Perl-Compatible Regular Expressions *
*************************************************/
/* PCRE is a library of functions to support regular expressions whose syntax
and semantics are as close as possible to those of the Perl 5 language.
Written by Philip Hazel
Original API code Copyright (c) 1997-2012 University of Cambridge
New API code Copyright (c) 2016-2017 University of Cambridge
-----------------------------------------------------------------------------
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* Neither the name of the University of Cambridge nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
-----------------------------------------------------------------------------
*/
/* This module contains a PCRE private debugging function for printing out the
internal form of a compiled regular expression, along with some supporting
local functions. This source file is #included in pcre2test.c at each supported
code unit width, with PCRE2_SUFFIX set appropriately, just like the functions
that comprise the library. It can also optionally be included in
pcre2_compile.c for detailed debugging in error situations. */
/* Tables of operator names. The same 8-bit table is used for all code unit
widths, so it must be defined only once. The list itself is defined in
pcre2_internal.h, which is #included by pcre2test before this file. */
#ifndef OP_LISTS_DEFINED
static const char *OP_names[] = { OP_NAME_LIST };
#define OP_LISTS_DEFINED
#endif
/* The functions and tables herein must all have mode-dependent names. */
#define OP_lengths PCRE2_SUFFIX(OP_lengths_)
#define get_ucpname PCRE2_SUFFIX(get_ucpname_)
#define pcre2_printint PCRE2_SUFFIX(pcre2_printint_)
#define print_char PCRE2_SUFFIX(print_char_)
#define print_custring PCRE2_SUFFIX(print_custring_)
#define print_custring_bylen PCRE2_SUFFIX(print_custring_bylen_)
#define print_prop PCRE2_SUFFIX(print_prop_)
/* Table of sizes for the fixed-length opcodes. It's defined in a macro so that
the definition is next to the definition of the opcodes in pcre2_internal.h.
The contents of the table are, however, mode-dependent. */
static const uint8_t OP_lengths[] = { OP_LENGTHS };
/*************************************************
* Print one character from a string *
*************************************************/
/* In UTF mode the character may occupy more than one code unit.
Arguments:
f file to write to
ptr pointer to first code unit of the character
utf TRUE if string is UTF (will be FALSE if UTF is not supported)
Returns: number of additional code units used
*/
static unsigned int
print_char(FILE *f, PCRE2_SPTR ptr, BOOL utf)
{
uint32_t c = *ptr;
BOOL one_code_unit = !utf;
/* If UTF is supported and requested, check for a valid single code unit. */
#ifdef SUPPORT_UNICODE
if (utf)
{
#if PCRE2_CODE_UNIT_WIDTH == 8
one_code_unit = c < 0x80;
#elif PCRE2_CODE_UNIT_WIDTH == 16
one_code_unit = (c & 0xfc00) != 0xd800;
#else
one_code_unit = (c & 0xfffff800u) != 0xd800u;
#endif /* CODE_UNIT_WIDTH */
}
#endif /* SUPPORT_UNICODE */
/* Handle a valid one-code-unit character at any width. */
if (one_code_unit)
{
if (PRINTABLE(c)) fprintf(f, "%c", (char)c);
else if (c < 0x80) fprintf(f, "\\x%02x", c);
else fprintf(f, "\\x{%02x}", c);
return 0;
}
/* Code for invalid UTF code units and multi-unit UTF characters is different
for each width. If UTF is not supported, control should never get here, but we
need a return statement to keep the compiler happy. */
#ifndef SUPPORT_UNICODE
return 0;
#else
/* Malformed UTF-8 should occur only if the sanity check has been turned off.
Rather than swallow random bytes, just stop if we hit a bad one. Print it with
\X instead of \x as an indication. */
#if PCRE2_CODE_UNIT_WIDTH == 8
if ((c & 0xc0) != 0xc0)
{
fprintf(f, "\\X{%x}", c); /* Invalid starting byte */
return 0;
}
else
{
int i;
int a = PRIV(utf8_table4)[c & 0x3f]; /* Number of additional bytes */
int s = 6*a;
c = (c & PRIV(utf8_table3)[a]) << s;
for (i = 1; i <= a; i++)
{
if ((ptr[i] & 0xc0) != 0x80)
{
fprintf(f, "\\X{%x}", c); /* Invalid secondary byte */
return i - 1;
}
s -= 6;
c |= (ptr[i] & 0x3f) << s;
}
fprintf(f, "\\x{%x}", c);
return a;
}
#endif /* PCRE2_CODE_UNIT_WIDTH == 8 */
/* UTF-16: rather than swallow a low surrogate, just stop if we hit a bad one.
Print it with \X instead of \x as an indication. */
#if PCRE2_CODE_UNIT_WIDTH == 16
if ((ptr[1] & 0xfc00) != 0xdc00)
{
fprintf(f, "\\X{%x}", c);
return 0;
}
c = (((c & 0x3ff) << 10) | (ptr[1] & 0x3ff)) + 0x10000;
fprintf(f, "\\x{%x}", c);
return 1;
#endif /* PCRE2_CODE_UNIT_WIDTH == 16 */
/* For UTF-32 we get here only for a malformed code unit, which should only
occur if the sanity check has been turned off. Print it with \X instead of \x
as an indication. */
#if PCRE2_CODE_UNIT_WIDTH == 32
fprintf(f, "\\X{%x}", c);
return 0;
#endif /* PCRE2_CODE_UNIT_WIDTH == 32 */
#endif /* SUPPORT_UNICODE */
}
/*************************************************
* Print string as a list of code units *
*************************************************/
/* These take no account of UTF as they always print each individual code unit.
The string is zero-terminated for print_custring(); the length is given for
print_custring_bylen().
Arguments:
f file to write to
ptr point to the string
len length for print_custring_bylen()
Returns: nothing
*/
static void
print_custring(FILE *f, PCRE2_SPTR ptr)
{
while (*ptr != '\0')
{
uint32_t c = *ptr++;
if (PRINTABLE(c)) fprintf(f, "%c", c); else fprintf(f, "\\x{%x}", c);
}
}
static void
print_custring_bylen(FILE *f, PCRE2_SPTR ptr, PCRE2_UCHAR len)
{
for (; len > 0; len--)
{
uint32_t c = *ptr++;
if (PRINTABLE(c)) fprintf(f, "%c", c); else fprintf(f, "\\x{%x}", c);
}
}
/*************************************************
* Find Unicode property name *
*************************************************/
/* When there is no UTF/UCP support, the table of names does not exist. This
function should not be called in such configurations, because a pattern that
tries to use Unicode properties won't compile. Rather than put lots of #ifdefs
into the main code, however, we just put one into this function. */
static const char *
get_ucpname(unsigned int ptype, unsigned int pvalue)
{
#ifdef SUPPORT_UNICODE
int i;
for (i = PRIV(utt_size) - 1; i >= 0; i--)
{
if (ptype == PRIV(utt)[i].type && pvalue == PRIV(utt)[i].value) break;
}
return (i >= 0)? PRIV(utt_names) + PRIV(utt)[i].name_offset : "??";
#else /* No UTF support */
(void)ptype;
(void)pvalue;
return "??";
#endif /* SUPPORT_UNICODE */
}
/*************************************************
* Print Unicode property value *
*************************************************/
/* "Normal" properties can be printed from tables. The PT_CLIST property is a
pseudo-property that contains a pointer to a list of case-equivalent
characters.
Arguments:
f file to write to
code pointer in the compiled code
before text to print before
after text to print after
Returns: nothing
*/
static void
print_prop(FILE *f, PCRE2_SPTR code, const char *before, const char *after)
{
if (code[1] != PT_CLIST)
{
fprintf(f, "%s%s %s%s", before, OP_names[*code], get_ucpname(code[1],
code[2]), after);
}
else
{
const char *not = (*code == OP_PROP)? "" : "not ";
const uint32_t *p = PRIV(ucd_caseless_sets) + code[2];
fprintf (f, "%s%sclist", before, not);
while (*p < NOTACHAR) fprintf(f, " %04x", *p++);
fprintf(f, "%s", after);
}
}
/*************************************************
* Print compiled pattern *
*************************************************/
/* The print_lengths flag controls whether offsets and lengths of items are
printed. Lenths can be turned off from pcre2test so that automatic tests on
bytecode can be written that do not depend on the value of LINK_SIZE.
Arguments:
re a compiled pattern
f the file to write to
print_lengths show various lengths
Returns: nothing
*/
static void
pcre2_printint(pcre2_code *re, FILE *f, BOOL print_lengths)
{
PCRE2_SPTR codestart, nametable, code;
uint32_t nesize = re->name_entry_size;
BOOL utf = (re->overall_options & PCRE2_UTF) != 0;
nametable = (PCRE2_SPTR)((uint8_t *)re + sizeof(pcre2_real_code));
code = codestart = nametable + re->name_count * re->name_entry_size;
for(;;)
{
PCRE2_SPTR ccode;
uint32_t c;
int i;
const char *flag = " ";
unsigned int extra = 0;
if (print_lengths)
fprintf(f, "%3d ", (int)(code - codestart));
else
fprintf(f, " ");
switch(*code)
{
/* ========================================================================== */
/* These cases are never obeyed. This is a fudge that causes a compile-
time error if the vectors OP_names or OP_lengths, which are indexed
by opcode, are not the correct length. It seems to be the only way to do
such a check at compile time, as the sizeof() operator does not work in
the C preprocessor. */
case OP_TABLE_LENGTH:
case OP_TABLE_LENGTH +
((sizeof(OP_names)/sizeof(const char *) == OP_TABLE_LENGTH) &&
(sizeof(OP_lengths) == OP_TABLE_LENGTH)):
return;
/* ========================================================================== */
case OP_END:
fprintf(f, " %s\n", OP_names[*code]);
fprintf(f, "------------------------------------------------------------------\n");
return;
case OP_CHAR:
fprintf(f, " ");
do
{
code++;
code += 1 + print_char(f, code, utf);
}
while (*code == OP_CHAR);
fprintf(f, "\n");
continue;
case OP_CHARI:
fprintf(f, " /i ");
do
{
code++;
code += 1 + print_char(f, code, utf);
}
while (*code == OP_CHARI);
fprintf(f, "\n");
continue;
case OP_CBRA:
case OP_CBRAPOS:
case OP_SCBRA:
case OP_SCBRAPOS:
if (print_lengths) fprintf(f, "%3d ", GET(code, 1));
else fprintf(f, " ");
fprintf(f, "%s %d", OP_names[*code], GET2(code, 1+LINK_SIZE));
break;
case OP_BRA:
case OP_BRAPOS:
case OP_SBRA:
case OP_SBRAPOS:
case OP_KETRMAX:
case OP_KETRMIN:
case OP_KETRPOS:
case OP_ALT:
case OP_KET:
case OP_ASSERT:
case OP_ASSERT_NOT:
case OP_ASSERTBACK:
case OP_ASSERTBACK_NOT:
case OP_ONCE:
case OP_COND:
case OP_SCOND:
case OP_REVERSE:
if (print_lengths) fprintf(f, "%3d ", GET(code, 1));
else fprintf(f, " ");
fprintf(f, "%s", OP_names[*code]);
break;
case OP_CLOSE:
fprintf(f, " %s %d", OP_names[*code], GET2(code, 1));
break;
case OP_CREF:
fprintf(f, "%3d %s", GET2(code,1), OP_names[*code]);
break;
case OP_DNCREF:
{
PCRE2_SPTR entry = nametable + (GET2(code, 1) * nesize) + IMM2_SIZE;
fprintf(f, " %s Cond ref <", flag);
print_custring(f, entry);
fprintf(f, ">%d", GET2(code, 1 + IMM2_SIZE));
}
break;
case OP_RREF:
c = GET2(code, 1);
if (c == RREF_ANY)
fprintf(f, " Cond recurse any");
else
fprintf(f, " Cond recurse %d", c);
break;
case OP_DNRREF:
{
PCRE2_SPTR entry = nametable + (GET2(code, 1) * nesize) + IMM2_SIZE;
fprintf(f, " %s Cond recurse <", flag);
print_custring(f, entry);
fprintf(f, ">%d", GET2(code, 1 + IMM2_SIZE));
}
break;
case OP_FALSE:
fprintf(f, " Cond false");
break;
case OP_TRUE:
fprintf(f, " Cond true");
break;
case OP_STARI:
case OP_MINSTARI:
case OP_POSSTARI:
case OP_PLUSI:
case OP_MINPLUSI:
case OP_POSPLUSI:
case OP_QUERYI:
case OP_MINQUERYI:
case OP_POSQUERYI:
flag = "/i";
/* Fall through */
case OP_STAR:
case OP_MINSTAR:
case OP_POSSTAR:
case OP_PLUS:
case OP_MINPLUS:
case OP_POSPLUS:
case OP_QUERY:
case OP_MINQUERY:
case OP_POSQUERY:
case OP_TYPESTAR:
case OP_TYPEMINSTAR:
case OP_TYPEPOSSTAR:
case OP_TYPEPLUS:
case OP_TYPEMINPLUS:
case OP_TYPEPOSPLUS:
case OP_TYPEQUERY:
case OP_TYPEMINQUERY:
case OP_TYPEPOSQUERY:
fprintf(f, " %s ", flag);
if (*code >= OP_TYPESTAR)
{
if (code[1] == OP_PROP || code[1] == OP_NOTPROP)
{
print_prop(f, code + 1, "", " ");
extra = 2;
}
else fprintf(f, "%s", OP_names[code[1]]);
}
else extra = print_char(f, code+1, utf);
fprintf(f, "%s", OP_names[*code]);
break;
case OP_EXACTI:
case OP_UPTOI:
case OP_MINUPTOI:
case OP_POSUPTOI:
flag = "/i";
/* Fall through */
case OP_EXACT:
case OP_UPTO:
case OP_MINUPTO:
case OP_POSUPTO:
fprintf(f, " %s ", flag);
extra = print_char(f, code + 1 + IMM2_SIZE, utf);
fprintf(f, "{");
if (*code != OP_EXACT && *code != OP_EXACTI) fprintf(f, "0,");
fprintf(f, "%d}", GET2(code,1));
if (*code == OP_MINUPTO || *code == OP_MINUPTOI) fprintf(f, "?");
else if (*code == OP_POSUPTO || *code == OP_POSUPTOI) fprintf(f, "+");
break;
case OP_TYPEEXACT:
case OP_TYPEUPTO:
case OP_TYPEMINUPTO:
case OP_TYPEPOSUPTO:
if (code[1 + IMM2_SIZE] == OP_PROP || code[1 + IMM2_SIZE] == OP_NOTPROP)
{
print_prop(f, code + IMM2_SIZE + 1, " ", " ");
extra = 2;
}
else fprintf(f, " %s", OP_names[code[1 + IMM2_SIZE]]);
fprintf(f, "{");
if (*code != OP_TYPEEXACT) fprintf(f, "0,");
fprintf(f, "%d}", GET2(code,1));
if (*code == OP_TYPEMINUPTO) fprintf(f, "?");
else if (*code == OP_TYPEPOSUPTO) fprintf(f, "+");
break;
case OP_NOTI:
flag = "/i";
/* Fall through */
case OP_NOT:
fprintf(f, " %s [^", flag);
extra = print_char(f, code + 1, utf);
fprintf(f, "]");
break;
case OP_NOTSTARI:
case OP_NOTMINSTARI:
case OP_NOTPOSSTARI:
case OP_NOTPLUSI:
case OP_NOTMINPLUSI:
case OP_NOTPOSPLUSI:
case OP_NOTQUERYI:
case OP_NOTMINQUERYI:
case OP_NOTPOSQUERYI:
flag = "/i";
/* Fall through */
case OP_NOTSTAR:
case OP_NOTMINSTAR:
case OP_NOTPOSSTAR:
case OP_NOTPLUS:
case OP_NOTMINPLUS:
case OP_NOTPOSPLUS:
case OP_NOTQUERY:
case OP_NOTMINQUERY:
case OP_NOTPOSQUERY:
fprintf(f, " %s [^", flag);
extra = print_char(f, code + 1, utf);
fprintf(f, "]%s", OP_names[*code]);
break;
case OP_NOTEXACTI:
case OP_NOTUPTOI:
case OP_NOTMINUPTOI:
case OP_NOTPOSUPTOI:
flag = "/i";
/* Fall through */
case OP_NOTEXACT:
case OP_NOTUPTO:
case OP_NOTMINUPTO:
case OP_NOTPOSUPTO:
fprintf(f, " %s [^", flag);
extra = print_char(f, code + 1 + IMM2_SIZE, utf);
fprintf(f, "]{");
if (*code != OP_NOTEXACT && *code != OP_NOTEXACTI) fprintf(f, "0,");
fprintf(f, "%d}", GET2(code,1));
if (*code == OP_NOTMINUPTO || *code == OP_NOTMINUPTOI) fprintf(f, "?");
else
if (*code == OP_NOTPOSUPTO || *code == OP_NOTPOSUPTOI) fprintf(f, "+");
break;
case OP_RECURSE:
if (print_lengths) fprintf(f, "%3d ", GET(code, 1));
else fprintf(f, " ");
fprintf(f, "%s", OP_names[*code]);
break;
case OP_REFI:
flag = "/i";
/* Fall through */
case OP_REF:
fprintf(f, " %s \\%d", flag, GET2(code,1));
ccode = code + OP_lengths[*code];
goto CLASS_REF_REPEAT;
case OP_DNREFI:
flag = "/i";
/* Fall through */
case OP_DNREF:
{
PCRE2_SPTR entry = nametable + (GET2(code, 1) * nesize) + IMM2_SIZE;
fprintf(f, " %s \\k<", flag);
print_custring(f, entry);
fprintf(f, ">%d", GET2(code, 1 + IMM2_SIZE));
}
ccode = code + OP_lengths[*code];
goto CLASS_REF_REPEAT;
case OP_CALLOUT:
fprintf(f, " %s %d %d %d", OP_names[*code], code[1 + 2*LINK_SIZE],
GET(code, 1), GET(code, 1 + LINK_SIZE));
break;
case OP_CALLOUT_STR:
c = code[1 + 4*LINK_SIZE];
fprintf(f, " %s %c", OP_names[*code], c);
extra = GET(code, 1 + 2*LINK_SIZE);
print_custring_bylen(f, code + 2 + 4*LINK_SIZE, extra - 3 - 4*LINK_SIZE);
for (i = 0; PRIV(callout_start_delims)[i] != 0; i++)
if (c == PRIV(callout_start_delims)[i])
{
c = PRIV(callout_end_delims)[i];
break;
}
fprintf(f, "%c %d %d %d", c, GET(code, 1 + 3*LINK_SIZE), GET(code, 1),
GET(code, 1 + LINK_SIZE));
break;
case OP_PROP:
case OP_NOTPROP:
print_prop(f, code, " ", "");
break;
/* OP_XCLASS cannot occur in 8-bit, non-UTF mode. However, there's no harm
in having this code always here, and it makes it less messy without all
those #ifdefs. */
case OP_CLASS:
case OP_NCLASS:
case OP_XCLASS:
{
unsigned int min, max;
BOOL printmap;
BOOL invertmap = FALSE;
uint8_t *map;
uint8_t inverted_map[32];
fprintf(f, " [");
if (*code == OP_XCLASS)
{
extra = GET(code, 1);
ccode = code + LINK_SIZE + 1;
printmap = (*ccode & XCL_MAP) != 0;
if ((*ccode & XCL_NOT) != 0)
{
invertmap = (*ccode & XCL_HASPROP) == 0;
fprintf(f, "^");
}
ccode++;
}
else
{
printmap = TRUE;
ccode = code + 1;
}
/* Print a bit map */
if (printmap)
{
map = (uint8_t *)ccode;
if (invertmap)
{
for (i = 0; i < 32; i++) inverted_map[i] = ~map[i];
map = inverted_map;
}
for (i = 0; i < 256; i++)
{
if ((map[i/8] & (1 << (i&7))) != 0)
{
int j;
for (j = i+1; j < 256; j++)
if ((map[j/8] & (1 << (j&7))) == 0) break;
if (i == '-' || i == ']') fprintf(f, "\\");
if (PRINTABLE(i)) fprintf(f, "%c", i);
else fprintf(f, "\\x%02x", i);
if (--j > i)
{
if (j != i + 1) fprintf(f, "-");
if (j == '-' || j == ']') fprintf(f, "\\");
if (PRINTABLE(j)) fprintf(f, "%c", j);
else fprintf(f, "\\x%02x", j);
}
i = j;
}
}
ccode += 32 / sizeof(PCRE2_UCHAR);
}
/* For an XCLASS there is always some additional data */
if (*code == OP_XCLASS)
{
PCRE2_UCHAR ch;
while ((ch = *ccode++) != XCL_END)
{
BOOL not = FALSE;
const char *notch = "";
switch(ch)
{
case XCL_NOTPROP:
not = TRUE;
notch = "^";
/* Fall through */
case XCL_PROP:
{
unsigned int ptype = *ccode++;
unsigned int pvalue = *ccode++;
switch(ptype)
{
case PT_PXGRAPH:
fprintf(f, "[:%sgraph:]", notch);
break;
case PT_PXPRINT:
fprintf(f, "[:%sprint:]", notch);
break;
case PT_PXPUNCT:
fprintf(f, "[:%spunct:]", notch);
break;
default:
fprintf(f, "\\%c{%s}", (not? 'P':'p'),
get_ucpname(ptype, pvalue));
break;
}
}
break;
default:
ccode += 1 + print_char(f, ccode, utf);
if (ch == XCL_RANGE)
{
fprintf(f, "-");
ccode += 1 + print_char(f, ccode, utf);
}
break;
}
}
}
/* Indicate a non-UTF class which was created by negation */
fprintf(f, "]%s", (*code == OP_NCLASS)? " (neg)" : "");
/* Handle repeats after a class or a back reference */
CLASS_REF_REPEAT:
switch(*ccode)
{
case OP_CRSTAR:
case OP_CRMINSTAR:
case OP_CRPLUS:
case OP_CRMINPLUS:
case OP_CRQUERY:
case OP_CRMINQUERY:
case OP_CRPOSSTAR:
case OP_CRPOSPLUS:
case OP_CRPOSQUERY:
fprintf(f, "%s", OP_names[*ccode]);
extra += OP_lengths[*ccode];
break;
case OP_CRRANGE:
case OP_CRMINRANGE:
case OP_CRPOSRANGE:
min = GET2(ccode,1);
max = GET2(ccode,1 + IMM2_SIZE);
if (max == 0) fprintf(f, "{%u,}", min);
else fprintf(f, "{%u,%u}", min, max);
if (*ccode == OP_CRMINRANGE) fprintf(f, "?");
else if (*ccode == OP_CRPOSRANGE) fprintf(f, "+");
extra += OP_lengths[*ccode];
break;
/* Do nothing if it's not a repeat; this code stops picky compilers
warning about the lack of a default code path. */
default:
break;
}
}
break;
case OP_MARK:
case OP_PRUNE_ARG:
case OP_SKIP_ARG:
case OP_THEN_ARG:
fprintf(f, " %s ", OP_names[*code]);
print_custring_bylen(f, code + 2, code[1]);
extra += code[1];
break;
case OP_THEN:
fprintf(f, " %s", OP_names[*code]);
break;
case OP_CIRCM:
case OP_DOLLM:
flag = "/m";
/* Fall through */
/* Anything else is just an item with no data, but possibly a flag. */
default:
fprintf(f, " %s %s", flag, OP_names[*code]);
break;
}
code += OP_lengths[*code] + extra;
fprintf(f, "\n");
}
}
/* End of pcre2_printint.c */

View File

@ -263,14 +263,14 @@ void Widget::argFunction()
//! [11] //! [11]
{ {
//! [11] //! [11-qstringview]
int i; // current file's number int i; // current file's number
int total; // number of files to process int total; // number of files to process
QStringView fileName; // current file's name QStringView fileName; // current file's name
QString status = QString("Processing file %1 of %2: %3") QString status = QString("Processing file %1 of %2: %3")
.arg(i).arg(total).arg(fileName); .arg(i).arg(total).arg(fileName);
//! [11] //! [11-qstringview]
} }
//! [12] //! [13] //! [12] //! [13]

View File

@ -43,6 +43,7 @@
#endif #endif
#include <qversionnumber.h> #include <qversionnumber.h>
#include <qdebug.h>
#if defined(Q_OS_ANDROID) #if defined(Q_OS_ANDROID)
#include <private/qjni_p.h> #include <private/qjni_p.h>
@ -154,6 +155,8 @@ QT_BEGIN_NAMESPACE
\fn QOperatingSystemVersion QOperatingSystemVersion::current() \fn QOperatingSystemVersion QOperatingSystemVersion::current()
Returns a QOperatingSystemVersion indicating the current OS and its version number. Returns a QOperatingSystemVersion indicating the current OS and its version number.
\sa currentType()
*/ */
#if !defined(Q_OS_DARWIN) && !defined(Q_OS_WIN) #if !defined(Q_OS_DARWIN) && !defined(Q_OS_WIN)
QOperatingSystemVersion QOperatingSystemVersion::current() QOperatingSystemVersion QOperatingSystemVersion::current()
@ -299,6 +302,14 @@ int QOperatingSystemVersion::compare(const QOperatingSystemVersion &v1,
\sa name() \sa name()
*/ */
/*!
\fn QOperatingSystemVersion::OSType QOperatingSystemVersion::currentType()
Returns the current OS type without constructing a QOperatingSystemVersion instance.
\sa current()
*/
/*! /*!
\fn QString QOperatingSystemVersion::name() const \fn QString QOperatingSystemVersion::name() const
@ -510,4 +521,16 @@ const QOperatingSystemVersion QOperatingSystemVersion::AndroidNougat_MR1 =
const QOperatingSystemVersion QOperatingSystemVersion::AndroidOreo = const QOperatingSystemVersion QOperatingSystemVersion::AndroidOreo =
QOperatingSystemVersion(QOperatingSystemVersion::Android, 8, 0); QOperatingSystemVersion(QOperatingSystemVersion::Android, 8, 0);
#ifndef QT_NO_DEBUG_STREAM
QDebug operator<<(QDebug debug, const QOperatingSystemVersion &ov)
{
QDebugStateSaver saver(debug);
debug.nospace();
debug << "QOperatingSystemVersion(" << ov.name()
<< ", " << ov.majorVersion() << '.' << ov.minorVersion()
<< '.' << ov.microVersion() << ')';
return debug;
}
#endif // !QT_NO_DEBUG_STREAM
QT_END_NAMESPACE QT_END_NAMESPACE

View File

@ -92,6 +92,25 @@ public:
static QOperatingSystemVersion current(); static QOperatingSystemVersion current();
static Q_DECL_CONSTEXPR OSType currentType()
{
#if defined(Q_OS_WIN)
return Windows;
#elif defined(Q_OS_MACOS)
return MacOS;
#elif defined(Q_OS_IOS)
return IOS;
#elif defined(Q_OS_TVOS)
return TvOS;
#elif defined(Q_OS_WATCHOS)
return WatchOS;
#elif defined(Q_OS_ANDROID)
return Android;
#else
return Unknown;
#endif
}
Q_DECL_CONSTEXPR int majorVersion() const { return m_major; } Q_DECL_CONSTEXPR int majorVersion() const { return m_major; }
Q_DECL_CONSTEXPR int minorVersion() const { return m_minor; } Q_DECL_CONSTEXPR int minorVersion() const { return m_minor; }
Q_DECL_CONSTEXPR int microVersion() const { return m_micro; } Q_DECL_CONSTEXPR int microVersion() const { return m_micro; }
@ -128,6 +147,11 @@ private:
}; };
Q_DECLARE_TYPEINFO(QOperatingSystemVersion, QT_VERSION < QT_VERSION_CHECK(6, 0, 0) ? Q_RELOCATABLE_TYPE : Q_PRIMITIVE_TYPE); Q_DECLARE_TYPEINFO(QOperatingSystemVersion, QT_VERSION < QT_VERSION_CHECK(6, 0, 0) ? Q_RELOCATABLE_TYPE : Q_PRIMITIVE_TYPE);
#ifndef QT_NO_DEBUG_STREAM
class QDebug;
Q_CORE_EXPORT QDebug operator<<(QDebug debug, const QOperatingSystemVersion &ov);
#endif
QT_END_NAMESPACE QT_END_NAMESPACE
#endif // QOPERATINGSYSTEMVERSION_H #endif // QOPERATINGSYSTEMVERSION_H

View File

@ -63,25 +63,6 @@ QT_BEGIN_NAMESPACE
OSVERSIONINFOEX qWindowsVersionInfo(); OSVERSIONINFOEX qWindowsVersionInfo();
#endif #endif
static inline QOperatingSystemVersion::OSType currentType()
{
#if defined(Q_OS_WIN)
return QOperatingSystemVersion::Windows;
#elif defined(Q_OS_MACOS)
return QOperatingSystemVersion::MacOS;
#elif defined(Q_OS_IOS)
return QOperatingSystemVersion::IOS;
#elif defined(Q_OS_TVOS)
return QOperatingSystemVersion::TvOS;
#elif defined(Q_OS_WATCHOS)
return QOperatingSystemVersion::WatchOS;
#elif defined(Q_OS_ANDROID)
return QOperatingSystemVersion::Android;
#else
return QOperatingSystemVersion::Unknown;
#endif
}
QT_END_NAMESPACE QT_END_NAMESPACE
#endif // QOPERATINGSYSTEMVERSION_P_H #endif // QOPERATINGSYSTEMVERSION_P_H

View File

@ -458,14 +458,14 @@ static Q_NEVER_INLINE void fill(void *buffer, void *bufferEnd)
reliable sequence, which may be needed for debugging. reliable sequence, which may be needed for debugging.
The class can generate 32-bit or 64-bit quantities, or fill an array of The class can generate 32-bit or 64-bit quantities, or fill an array of
those. The most common way of generating new values is to call the get32(), those. The most common way of generating new values is to call the generate(),
get64() or fillRange() functions. One would use it as: get64() or fillRange() functions. One would use it as:
\code \code
quint32 value = QRandomGenerator::get32(); quint32 value = QRandomGenerator::generate();
\endcode \endcode
Additionally, it provides a floating-point function getReal() that returns Additionally, it provides a floating-point function generateDouble() that returns
a number in the range [0, 1) (that is, inclusive of zero and exclusive of a number in the range [0, 1) (that is, inclusive of zero and exclusive of
1). There's also a set of convenience functions that facilitate obtaining a 1). There's also a set of convenience functions that facilitate obtaining a
random number in a bounded, integral range. random number in a bounded, integral range.
@ -567,7 +567,7 @@ static Q_NEVER_INLINE void fill(void *buffer, void *bufferEnd)
Generates a 32-bit random quantity and returns it. Generates a 32-bit random quantity and returns it.
\sa QRandomGenerator::get32(), QRandomGenerator::get64() \sa QRandomGenerator::generate(), QRandomGenerator::generate64()
*/ */
/*! /*!
@ -611,7 +611,7 @@ static Q_NEVER_INLINE void fill(void *buffer, void *bufferEnd)
and \a end. This function is equivalent to (and is implemented as): and \a end. This function is equivalent to (and is implemented as):
\code \code
std::generate(begin, end, []() { return get32(); }); std::generate(begin, end, []() { return generate(); });
\endcode \endcode
This function complies with the requirements for the function This function complies with the requirements for the function
@ -683,7 +683,7 @@ static Q_NEVER_INLINE void fill(void *buffer, void *bufferEnd)
*/ */
/*! /*!
\fn qreal QRandomGenerator::getReal() \fn qreal QRandomGenerator::generateReal()
Generates one random qreal in the canonical range [0, 1) (that is, Generates one random qreal in the canonical range [0, 1) (that is,
inclusive of zero and exclusive of 1). inclusive of zero and exclusive of 1).
@ -698,7 +698,7 @@ static Q_NEVER_INLINE void fill(void *buffer, void *bufferEnd)
\c{\l{http://en.cppreference.com/w/cpp/numeric/random/uniform_real_distribution}{std::uniform_real_distribution}} \c{\l{http://en.cppreference.com/w/cpp/numeric/random/uniform_real_distribution}{std::uniform_real_distribution}}
with parameters 0 and 1. with parameters 0 and 1.
\sa get32(), get64(), bounded() \sa generate(), get64(), bounded()
*/ */
/*! /*!
@ -708,10 +708,10 @@ static Q_NEVER_INLINE void fill(void *buffer, void *bufferEnd)
sup (exclusive). This function is equivalent to and is implemented as: sup (exclusive). This function is equivalent to and is implemented as:
\code \code
return getReal() * sup; return generateDouble() * sup;
\endcode \endcode
\sa getReal(), bounded() \sa generateDouble(), bounded()
*/ */
/*! /*!
@ -730,13 +730,13 @@ static Q_NEVER_INLINE void fill(void *buffer, void *bufferEnd)
quint32 v = QRandomGenerator::bounded(256); quint32 v = QRandomGenerator::bounded(256);
\endcode \endcode
Naturally, the same could also be obtained by masking the result of get32() Naturally, the same could also be obtained by masking the result of generate()
to only the lower 8 bits. Either solution is as efficient. to only the lower 8 bits. Either solution is as efficient.
Note that this function cannot be used to obtain values in the full 32-bit Note that this function cannot be used to obtain values in the full 32-bit
range of quint32. Instead, use get32(). range of quint32. Instead, use generate().
\sa get32(), get64(), getReal() \sa generate(), get64(), generateDouble()
*/ */
/*! /*!
@ -747,9 +747,9 @@ static Q_NEVER_INLINE void fill(void *buffer, void *bufferEnd)
\a sup (exclusive). \a sup must not be negative. \a sup (exclusive). \a sup must not be negative.
Note that this function cannot be used to obtain values in the full 32-bit Note that this function cannot be used to obtain values in the full 32-bit
range of int. Instead, use get32() and cast to int. range of int. Instead, use generate() and cast to int.
\sa get32(), get64(), getReal() \sa generate(), get64(), generateDouble()
*/ */
/*! /*!
@ -771,9 +771,9 @@ static Q_NEVER_INLINE void fill(void *buffer, void *bufferEnd)
Note that this function cannot be used to obtain values in the full 32-bit Note that this function cannot be used to obtain values in the full 32-bit
range of quint32. Instead, use get32(). range of quint32. Instead, use generate().
\sa get32(), get64(), getReal() \sa generate(), get64(), generateDouble()
*/ */
/*! /*!
@ -784,9 +784,9 @@ static Q_NEVER_INLINE void fill(void *buffer, void *bufferEnd)
(inclusive) and \a sup (exclusive), both of which may be negative. (inclusive) and \a sup (exclusive), both of which may be negative.
Note that this function cannot be used to obtain values in the full 32-bit Note that this function cannot be used to obtain values in the full 32-bit
range of int. Instead, use get32() and cast to int. range of int. Instead, use generate() and cast to int.
\sa get32(), get64(), getReal() \sa generate(), get64(), generateDouble()
*/ */
/*! /*!
@ -798,7 +798,7 @@ static Q_NEVER_INLINE void fill(void *buffer, void *bufferEnd)
from a high-quality, seed-less Random Number Generator. from a high-quality, seed-less Random Number Generator.
QRandomGenerator64 is a simple adaptor class around QRandomGenerator, making the QRandomGenerator64 is a simple adaptor class around QRandomGenerator, making the
QRandomGenerator::get64() function the default for operator()(), instead of the QRandomGenerator::generate64() function the default for operator()(), instead of the
function that returns 32-bit quantities. This class is intended to be used function that returns 32-bit quantities. This class is intended to be used
in conjunction with Standard Library algorithms that need 64-bit quantities in conjunction with Standard Library algorithms that need 64-bit quantities
instead of 32-bit ones. instead of 32-bit ones.
@ -823,12 +823,29 @@ static Q_NEVER_INLINE void fill(void *buffer, void *bufferEnd)
\sa operator()() \sa operator()()
*/ */
/*!
\fn quint64 QRandomGenerator64::generate()
Generates one 64-bit random value and returns it.
Note about casting to a signed integer: all bits returned by this function
are random, so there's a 50% chance that the most significant bit will be
set. If you wish to cast the returned value to qint64 and keep it positive,
you should mask the sign bit off:
\code
qint64 value = QRandomGenerator64::generate() & std::numeric_limits<qint64>::max();
\endcode
\sa QRandomGenerator, QRandomGenerator::generate64()
*/
/*! /*!
\fn result_type QRandomGenerator64::operator()() \fn result_type QRandomGenerator64::operator()()
Generates a 64-bit random quantity and returns it. Generates a 64-bit random quantity and returns it.
\sa QRandomGenerator::get32(), QRandomGenerator::get64() \sa QRandomGenerator::generate(), QRandomGenerator::generate64()
*/ */
/*! /*!
@ -874,12 +891,12 @@ static Q_NEVER_INLINE void fill(void *buffer, void *bufferEnd)
you should mask the sign bit off: you should mask the sign bit off:
\code \code
int value = QRandomGenerator::get32() & std::numeric_limits<int>::max(); int value = QRandomGenerator::generate() & std::numeric_limits<int>::max();
\endcode \endcode
\sa get64(), getReal() \sa get64(), generateDouble()
*/ */
quint32 QRandomGenerator::get32() quint32 QRandomGenerator::generate()
{ {
quint32 ret; quint32 ret;
fill(&ret, &ret + 1); fill(&ret, &ret + 1);
@ -895,12 +912,12 @@ quint32 QRandomGenerator::get32()
you should mask the sign bit off: you should mask the sign bit off:
\code \code
qint64 value = QRandomGenerator::get64() & std::numeric_limits<qint64>::max(); qint64 value = QRandomGenerator::generate64() & std::numeric_limits<qint64>::max();
\endcode \endcode
\sa get32(), getReal(), QRandomGenerator64 \sa generate(), generateDouble(), QRandomGenerator64
*/ */
quint64 QRandomGenerator::get64() quint64 QRandomGenerator::generate64()
{ {
quint64 ret; quint64 ret;
fill(&ret, &ret + 1); fill(&ret, &ret + 1);

View File

@ -53,29 +53,27 @@ class QRandomGenerator
public: public:
QRandomGenerator() = default; QRandomGenerator() = default;
static Q_CORE_EXPORT quint32 get32(); // ### REMOVE BEFORE 5.10
static Q_CORE_EXPORT quint64 get64(); static quint32 get32() { return generate(); }
static qreal getReal() static quint64 get64() { return generate64(); }
static qreal getReal() { return generateDouble(); }
static Q_CORE_EXPORT quint32 generate();
static Q_CORE_EXPORT quint64 generate64();
static double generateDouble()
{ {
const int digits = std::numeric_limits<qreal>::digits; // use get64() to get enough bits
if (digits < std::numeric_limits<quint32>::digits) { return double(generate64()) / ((std::numeric_limits<quint64>::max)() + double(1.0));
// use get32()
return qreal(get32()) / ((max)() + qreal(1.0));
} else {
// use get64()
// we won't have enough bits for a __float128 though
return qreal(get64()) / ((std::numeric_limits<quint64>::max)() + qreal(1.0));
}
} }
static qreal bounded(qreal sup) static qreal bounded(qreal sup)
{ {
return getReal() * sup; return generateDouble() * sup;
} }
static quint32 bounded(quint32 sup) static quint32 bounded(quint32 sup)
{ {
quint64 value = get32(); quint64 value = generate();
value *= sup; value *= sup;
value /= (max)() + quint64(1); value /= (max)() + quint64(1);
return quint32(value); return quint32(value);
@ -112,7 +110,8 @@ public:
template <typename ForwardIterator> template <typename ForwardIterator>
void generate(ForwardIterator begin, ForwardIterator end) void generate(ForwardIterator begin, ForwardIterator end)
{ {
std::generate(begin, end, &QRandomGenerator::get32); auto generator = static_cast<quint32 (*)()>(&QRandomGenerator::generate);
std::generate(begin, end, generator);
} }
void generate(quint32 *begin, quint32 *end) void generate(quint32 *begin, quint32 *end)
@ -122,7 +121,7 @@ public:
// API like std::random_device // API like std::random_device
typedef quint32 result_type; typedef quint32 result_type;
result_type operator()() { return get32(); } result_type operator()() { return generate(); }
double entropy() const Q_DECL_NOTHROW { return 0.0; } double entropy() const Q_DECL_NOTHROW { return 0.0; }
static Q_DECL_CONSTEXPR result_type min() { return (std::numeric_limits<result_type>::min)(); } static Q_DECL_CONSTEXPR result_type min() { return (std::numeric_limits<result_type>::min)(); }
static Q_DECL_CONSTEXPR result_type max() { return (std::numeric_limits<result_type>::max)(); } static Q_DECL_CONSTEXPR result_type max() { return (std::numeric_limits<result_type>::max)(); }
@ -137,9 +136,11 @@ class QRandomGenerator64
public: public:
QRandomGenerator64() = default; QRandomGenerator64() = default;
static quint64 generate() { return QRandomGenerator::generate64(); }
// API like std::random_device // API like std::random_device
typedef quint64 result_type; typedef quint64 result_type;
result_type operator()() { return QRandomGenerator::get64(); } result_type operator()() { return QRandomGenerator::generate64(); }
double entropy() const Q_DECL_NOTHROW { return 0.0; } double entropy() const Q_DECL_NOTHROW { return 0.0; }
static Q_DECL_CONSTEXPR result_type min() { return (std::numeric_limits<result_type>::min)(); } static Q_DECL_CONSTEXPR result_type min() { return (std::numeric_limits<result_type>::min)(); }
static Q_DECL_CONSTEXPR result_type max() { return (std::numeric_limits<result_type>::max)(); } static Q_DECL_CONSTEXPR result_type max() { return (std::numeric_limits<result_type>::max)(); }

View File

@ -47,6 +47,7 @@
#include <QtCore/private/qcore_unix_p.h> #include <QtCore/private/qcore_unix_p.h>
#include <QtCore/qvarlengtharray.h> #include <QtCore/qvarlengtharray.h>
#include <pwd.h>
#include <stdlib.h> // for realpath() #include <stdlib.h> // for realpath()
#include <sys/types.h> #include <sys/types.h>
#include <sys/stat.h> #include <sys/stat.h>

View File

@ -440,12 +440,17 @@ QFileSystemEntry QFileSystemEngine::getLinkTarget(const QFileSystemEntry &link,
if (data.missingFlags(QFileSystemMetaData::LinkType)) if (data.missingFlags(QFileSystemMetaData::LinkType))
QFileSystemEngine::fillMetaData(link, data, QFileSystemMetaData::LinkType); QFileSystemEngine::fillMetaData(link, data, QFileSystemMetaData::LinkType);
QString ret; QString target;
if (data.isLnkFile()) if (data.isLnkFile())
ret = readLink(link); target = readLink(link);
else if (data.isLink()) else if (data.isLink())
ret = readSymLink(link); target = readSymLink(link);
return QFileSystemEntry(ret); QFileSystemEntry ret(target);
if (!target.isEmpty() && ret.isRelative()) {
target.prepend(absoluteName(link).path() + QLatin1Char('/'));
ret = QFileSystemEntry(QDir::cleanPath(target));
}
return ret;
} }
//static //static

View File

@ -165,7 +165,7 @@ QFileSystemEntry::NativePath QTemporaryFileName::generateNext()
Char *rIter = placeholderEnd; Char *rIter = placeholderEnd;
while (rIter != placeholderStart) { while (rIter != placeholderStart) {
quint32 rnd = QRandomGenerator::get32(); quint32 rnd = QRandomGenerator::generate();
auto applyOne = [&]() { auto applyOne = [&]() {
quint32 v = rnd & ((1 << BitsPerCharacter) - 1); quint32 v = rnd & ((1 << BitsPerCharacter) - 1);
rnd >>= BitsPerCharacter; rnd >>= BitsPerCharacter;

View File

@ -79,7 +79,7 @@ public:
return r < other.r return r < other.r
|| (r == other.r && (c < other.c || (r == other.r && (c < other.c
|| (c == other.c && (i < other.i || (c == other.c && (i < other.i
|| (i == other.i && m < other.m ))))); || (i == other.i && std::less<const QAbstractItemModel *>()(m, other.m))))));
} }
private: private:
inline QModelIndex(int arow, int acolumn, void *ptr, const QAbstractItemModel *amodel) Q_DECL_NOTHROW inline QModelIndex(int arow, int acolumn, void *ptr, const QAbstractItemModel *amodel) Q_DECL_NOTHROW

View File

@ -84,19 +84,83 @@ QT_FOR_EACH_MUTABLE_CORE_GRAPHICS_TYPE(QT_DECLARE_WEAK_QDEBUG_OPERATOR_FOR_CF_TY
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
QT_END_NAMESPACE
QT_USE_NAMESPACE
@interface QT_MANGLE_NAMESPACE(QMacAutoReleasePoolTracker) : NSObject
{
NSAutoreleasePool **m_pool;
}
-(id)initWithPool:(NSAutoreleasePool**)pool;
@end
@implementation QT_MANGLE_NAMESPACE(QMacAutoReleasePoolTracker)
-(id)initWithPool:(NSAutoreleasePool**)pool
{
if (self = [super init])
m_pool = pool;
return self;
}
-(void)dealloc
{
if (*m_pool) {
// The pool is still valid, which means we're not being drained from
// the corresponding QMacAutoReleasePool (see below).
// QMacAutoReleasePool has only a single member, the NSAutoreleasePool*
// so the address of that member is also the QMacAutoReleasePool itself.
QMacAutoReleasePool *pool = reinterpret_cast<QMacAutoReleasePool *>(m_pool);
qWarning() << "Premature drain of" << pool << "This can happen if you've allocated"
<< "the pool on the heap, or as a member of a heap-allocated object. This is not a"
<< "supported use of QMacAutoReleasePool, and might result in crashes when objects"
<< "in the pool are deallocated and then used later on under the assumption they"
<< "will be valid until" << pool << "has been drained.";
// Reset the pool so that it's not drained again later on
*m_pool = nullptr;
}
[super dealloc];
}
@end
QT_NAMESPACE_ALIAS_OBJC_CLASS(QMacAutoReleasePoolTracker);
QT_BEGIN_NAMESPACE
QMacAutoReleasePool::QMacAutoReleasePool() QMacAutoReleasePool::QMacAutoReleasePool()
: pool([[NSAutoreleasePool alloc] init]) : pool([[NSAutoreleasePool alloc] init])
{ {
[[[QMacAutoReleasePoolTracker alloc] initWithPool:
reinterpret_cast<NSAutoreleasePool **>(&pool)] autorelease];
} }
QMacAutoReleasePool::~QMacAutoReleasePool() QMacAutoReleasePool::~QMacAutoReleasePool()
{ {
if (!pool) {
qWarning() << "Prematurely drained pool" << this << "finally drained. Any objects belonging"
<< "to this pool have already been released, and have potentially been invalid since the"
<< "premature drain earlier on.";
return;
}
// Save and reset pool before draining, so that the pool tracker can know
// that it's being drained by its owning pool.
NSAutoreleasePool *savedPool = static_cast<NSAutoreleasePool*>(pool);
pool = nullptr;
// Drain behaves the same as release, with the advantage that // Drain behaves the same as release, with the advantage that
// if we're ever used in a garbage-collected environment, the // if we're ever used in a garbage-collected environment, the
// drain acts as a hint to the garbage collector to collect. // drain acts as a hint to the garbage collector to collect.
[static_cast<NSAutoreleasePool*>(pool) drain]; [savedPool drain];
} }
#ifndef QT_NO_DEBUG_STREAM
QDebug operator<<(QDebug debug, const QMacAutoReleasePool *pool)
{
QDebugStateSaver saver(debug);
debug.nospace();
debug << "QMacAutoReleasePool(" << (const void *)pool << ')';
return debug;
}
#endif // !QT_NO_DEBUG_STREAM
#ifdef Q_OS_MACOS #ifdef Q_OS_MACOS
/* /*
Ensure that Objective-C objects auto-released in main(), directly or indirectly, Ensure that Objective-C objects auto-released in main(), directly or indirectly,

View File

@ -153,6 +153,10 @@ Q_CORE_EXPORT QChar qt_mac_qtKey2CocoaKey(Qt::Key key);
Q_CORE_EXPORT Qt::Key qt_mac_cocoaKey2QtKey(QChar keyCode); Q_CORE_EXPORT Qt::Key qt_mac_cocoaKey2QtKey(QChar keyCode);
#endif #endif
#ifndef QT_NO_DEBUG_STREAM
QDebug operator<<(QDebug debug, const QMacAutoReleasePool *pool);
#endif
Q_CORE_EXPORT void qt_apple_check_os_version(); Q_CORE_EXPORT void qt_apple_check_os_version();
QT_END_NAMESPACE QT_END_NAMESPACE

View File

@ -263,7 +263,7 @@ Q_GLOBAL_STATIC(QStartUpFuncList, preRList)
typedef QList<QtCleanUpFunction> QVFuncList; typedef QList<QtCleanUpFunction> QVFuncList;
Q_GLOBAL_STATIC(QVFuncList, postRList) Q_GLOBAL_STATIC(QVFuncList, postRList)
#ifndef QT_NO_QOBJECT #ifndef QT_NO_QOBJECT
static QBasicMutex globalPreRoutinesMutex; static QBasicMutex globalRoutinesMutex;
#endif #endif
/*! /*!
@ -277,13 +277,15 @@ void qAddPreRoutine(QtStartUpFunction p)
QStartUpFuncList *list = preRList(); QStartUpFuncList *list = preRList();
if (!list) if (!list)
return; return;
if (QCoreApplication::instance())
p();
// Due to C++11 parallel dynamic initialization, this can be called // Due to C++11 parallel dynamic initialization, this can be called
// from multiple threads. // from multiple threads.
#ifndef QT_NO_THREAD #ifndef QT_NO_THREAD
QMutexLocker locker(&globalPreRoutinesMutex); QMutexLocker locker(&globalRoutinesMutex);
#endif #endif
if (QCoreApplication::instance())
p();
list->prepend(p); // in case QCoreApplication is re-created, see qt_call_pre_routines list->prepend(p); // in case QCoreApplication is re-created, see qt_call_pre_routines
} }
@ -292,6 +294,9 @@ void qAddPostRoutine(QtCleanUpFunction p)
QVFuncList *list = postRList(); QVFuncList *list = postRList();
if (!list) if (!list)
return; return;
#ifndef QT_NO_THREAD
QMutexLocker locker(&globalRoutinesMutex);
#endif
list->prepend(p); list->prepend(p);
} }
@ -300,6 +305,9 @@ void qRemovePostRoutine(QtCleanUpFunction p)
QVFuncList *list = postRList(); QVFuncList *list = postRList();
if (!list) if (!list)
return; return;
#ifndef QT_NO_THREAD
QMutexLocker locker(&globalRoutinesMutex);
#endif
list->removeAll(p); list->removeAll(p);
} }
@ -308,15 +316,18 @@ static void qt_call_pre_routines()
if (!preRList.exists()) if (!preRList.exists())
return; return;
QVFuncList list;
{
#ifndef QT_NO_THREAD #ifndef QT_NO_THREAD
QMutexLocker locker(&globalPreRoutinesMutex); QMutexLocker locker(&globalRoutinesMutex);
#endif #endif
QVFuncList *list = &(*preRList); // Unlike qt_call_post_routines, we don't empty the list, because
// Unlike qt_call_post_routines, we don't empty the list, because // Q_COREAPP_STARTUP_FUNCTION is a macro, so the user expects
// Q_COREAPP_STARTUP_FUNCTION is a macro, so the user expects // the function to be executed every time QCoreApplication is created.
// the function to be executed every time QCoreApplication is created. list = *preRList;
for (int i = 0; i < list->count(); ++i) }
list->at(i)(); for (int i = 0; i < list.count(); ++i)
list.at(i)();
} }
void Q_CORE_EXPORT qt_call_post_routines() void Q_CORE_EXPORT qt_call_post_routines()
@ -324,9 +335,21 @@ void Q_CORE_EXPORT qt_call_post_routines()
if (!postRList.exists()) if (!postRList.exists())
return; return;
QVFuncList *list = &(*postRList); forever {
while (!list->isEmpty()) QVFuncList list;
(list->takeFirst())(); {
// extract the current list and make the stored list empty
#ifndef QT_NO_THREAD
QMutexLocker locker(&globalRoutinesMutex);
#endif
qSwap(*postRList, list);
}
if (list.isEmpty())
break;
for (QtCleanUpFunction f : qAsConst(list))
f();
}
} }
@ -2864,6 +2887,7 @@ void QCoreApplication::setEventDispatcher(QAbstractEventDispatcher *eventDispatc
/*! /*!
\fn void qAddPostRoutine(QtCleanUpFunction ptr) \fn void qAddPostRoutine(QtCleanUpFunction ptr)
\threadsafe
\relates QCoreApplication \relates QCoreApplication
Adds a global routine that will be called from the QCoreApplication Adds a global routine that will be called from the QCoreApplication
@ -2877,10 +2901,10 @@ void QCoreApplication::setEventDispatcher(QAbstractEventDispatcher *eventDispatc
\snippet code/src_corelib_kernel_qcoreapplication.cpp 4 \snippet code/src_corelib_kernel_qcoreapplication.cpp 4
Note that for an application- or module-wide cleanup, qaddPostRoutine() Note that for an application- or module-wide cleanup, qAddPostRoutine()
is often not suitable. For example, if the program is split into dynamically is often not suitable. For example, if the program is split into dynamically
loaded modules, the relevant module may be unloaded long before the loaded modules, the relevant module may be unloaded long before the
QCoreApplication destructor is called. In such cases, if using qaddPostRoutine() QCoreApplication destructor is called. In such cases, if using qAddPostRoutine()
is still desirable, qRemovePostRoutine() can be used to prevent a routine is still desirable, qRemovePostRoutine() can be used to prevent a routine
from being called by the QCoreApplication destructor. For example, if that from being called by the QCoreApplication destructor. For example, if that
routine was called before the module was unloaded. routine was called before the module was unloaded.
@ -2896,11 +2920,14 @@ void QCoreApplication::setEventDispatcher(QAbstractEventDispatcher *eventDispatc
By selecting the right parent object, this can often be made to By selecting the right parent object, this can often be made to
clean up the module's data at the right moment. clean up the module's data at the right moment.
\note This function has been thread-safe since Qt 5.10.
\sa qRemovePostRoutine() \sa qRemovePostRoutine()
*/ */
/*! /*!
\fn void qRemovePostRoutine(QtCleanUpFunction ptr) \fn void qRemovePostRoutine(QtCleanUpFunction ptr)
\threadsafe
\relates QCoreApplication \relates QCoreApplication
\since 5.3 \since 5.3
@ -2909,6 +2936,8 @@ void QCoreApplication::setEventDispatcher(QAbstractEventDispatcher *eventDispatc
must have been previously added to the list by a call to must have been previously added to the list by a call to
qAddPostRoutine(), otherwise this function has no effect. qAddPostRoutine(), otherwise this function has no effect.
\note This function has been thread-safe since Qt 5.10.
\sa qAddPostRoutine() \sa qAddPostRoutine()
*/ */

View File

@ -89,10 +89,6 @@ public:
QString appName() const; QString appName() const;
QString appVersion() const; QString appVersion() const;
#ifdef Q_OS_MACOS
QMacRootLevelAutoReleasePool autoReleasePool;
#endif
#ifdef Q_OS_DARWIN #ifdef Q_OS_DARWIN
static QString infoDictionaryStringProperty(const QString &propertyName); static QString infoDictionaryStringProperty(const QString &propertyName);
#endif #endif

View File

@ -3173,6 +3173,9 @@ static bool canConvertMetaObject(int fromId, int toId, QObject *fromObject)
*/ */
bool QVariant::canConvert(int targetTypeId) const bool QVariant::canConvert(int targetTypeId) const
{ {
if (d.type == targetTypeId)
return true;
if ((targetTypeId == QMetaType::QModelIndex && d.type == QMetaType::QPersistentModelIndex) if ((targetTypeId == QMetaType::QModelIndex && d.type == QMetaType::QPersistentModelIndex)
|| (targetTypeId == QMetaType::QPersistentModelIndex && d.type == QMetaType::QModelIndex)) || (targetTypeId == QMetaType::QPersistentModelIndex && d.type == QMetaType::QModelIndex))
return true; return true;
@ -3639,29 +3642,36 @@ static int numericCompare(const QVariant::Private *d1, const QVariant::Private *
*/ */
bool QVariant::cmp(const QVariant &v) const bool QVariant::cmp(const QVariant &v) const
{ {
auto cmp_helper = [] (const QVariant::Private &d1, const QVariant::Private &d2)
{
Q_ASSERT(d1.type == d2.type);
if (d1.type >= QMetaType::User) {
int result;
if (QMetaType::equals(QT_PREPEND_NAMESPACE(constData(d1)), QT_PREPEND_NAMESPACE(constData(d2)), d1.type, &result))
return result == 0;
}
return handlerManager[d1.type]->compare(&d1, &d2);
};
// try numerics first, with C++ type promotion rules (no conversion) // try numerics first, with C++ type promotion rules (no conversion)
if (qIsNumericType(d.type) && qIsNumericType(v.d.type)) if (qIsNumericType(d.type) && qIsNumericType(v.d.type))
return numericCompare(&d, &v.d) == 0; return numericCompare(&d, &v.d) == 0;
if (d.type == v.d.type)
return cmp_helper(d, v.d);
QVariant v1 = *this; QVariant v1 = *this;
QVariant v2 = v; QVariant v2 = v;
if (d.type != v2.d.type) { if (v2.canConvert(v1.d.type)) {
if (v2.canConvert(v1.d.type)) { if (!v2.convert(v1.d.type))
if (!v2.convert(v1.d.type)) return false;
return false; } else {
} else { // try the opposite conversion, it might work
// try the opposite conversion, it might work qSwap(v1, v2);
qSwap(v1, v2); if (!v2.convert(v1.d.type))
if (!v2.convert(v1.d.type)) return false;
return false;
}
} }
if (v1.d.type >= QMetaType::User) { return cmp_helper(v1.d, v2.d);
int result;
if (QMetaType::equals(QT_PREPEND_NAMESPACE(constData(v1.d)), QT_PREPEND_NAMESPACE(constData(v2.d)), v1.d.type, &result))
return result == 0;
}
return handlerManager[v1.d.type]->compare(&v1.d, &v2.d);
} }
/*! /*!
@ -3677,51 +3687,53 @@ int QVariant::compare(const QVariant &v) const
if (cmp(v)) if (cmp(v))
return 0; return 0;
QVariant v1 = *this; const QVariant *v1 = this;
QVariant v2 = v; const QVariant *v2 = &v;
QVariant converted1;
QVariant converted2;
if (v1.d.type != v2.d.type) { if (d.type != v.d.type) {
// if both types differ, try to convert // if both types differ, try to convert
if (v2.canConvert(v1.d.type)) { if (v2->canConvert(v1->d.type)) {
QVariant temp = v2; converted2 = *v2;
if (temp.convert(v1.d.type)) if (converted2.convert(v1->d.type))
v2 = temp; v2 = &converted2;
} }
if (v1.d.type != v2.d.type && v1.canConvert(v2.d.type)) { if (v1->d.type != v2->d.type && v1->canConvert(v2->d.type)) {
QVariant temp = v1; converted1 = *v1;
if (temp.convert(v2.d.type)) if (converted1.convert(v2->d.type))
v1 = temp; v1 = &converted1;
} }
if (v1.d.type != v2.d.type) { if (v1->d.type != v2->d.type) {
// if conversion fails, default to toString // if conversion fails, default to toString
int r = v1.toString().compare(v2.toString(), Qt::CaseInsensitive); int r = v1->toString().compare(v2->toString(), Qt::CaseInsensitive);
if (r == 0) { if (r == 0) {
// cmp(v) returned false, so we should try to agree with it. // cmp(v) returned false, so we should try to agree with it.
return (v1.d.type < v2.d.type) ? -1 : 1; return (v1->d.type < v2->d.type) ? -1 : 1;
} }
return r; return r;
} }
// did we end up with two numerics? If so, restart // did we end up with two numerics? If so, restart
if (qIsNumericType(v1.d.type) && qIsNumericType(v2.d.type)) if (qIsNumericType(v1->d.type) && qIsNumericType(v2->d.type))
return v1.compare(v2); return v1->compare(*v2);
} }
if (v1.d.type >= QMetaType::User) { if (v1->d.type >= QMetaType::User) {
int result; int result;
if (QMetaType::compare(QT_PREPEND_NAMESPACE(constData(d)), QT_PREPEND_NAMESPACE(constData(v2.d)), d.type, &result)) if (QMetaType::compare(QT_PREPEND_NAMESPACE(constData(d)), QT_PREPEND_NAMESPACE(constData(v2->d)), d.type, &result))
return result; return result;
} }
switch (v1.d.type) { switch (v1->d.type) {
case QVariant::Date: case QVariant::Date:
return v1.toDate() < v2.toDate() ? -1 : 1; return v1->toDate() < v2->toDate() ? -1 : 1;
case QVariant::Time: case QVariant::Time:
return v1.toTime() < v2.toTime() ? -1 : 1; return v1->toTime() < v2->toTime() ? -1 : 1;
case QVariant::DateTime: case QVariant::DateTime:
return v1.toDateTime() < v2.toDateTime() ? -1 : 1; return v1->toDateTime() < v2->toDateTime() ? -1 : 1;
case QVariant::StringList: case QVariant::StringList:
return v1.toStringList() < v2.toStringList() ? -1 : 1; return v1->toStringList() < v2->toStringList() ? -1 : 1;
} }
int r = v1.toString().compare(v2.toString(), Qt::CaseInsensitive); int r = v1->toString().compare(v2->toString(), Qt::CaseInsensitive);
if (r == 0) { if (r == 0) {
// cmp(v) returned false, so we should try to agree with it. // cmp(v) returned false, so we should try to agree with it.
return (d.type < v.d.type) ? -1 : 1; return (d.type < v.d.type) ? -1 : 1;

View File

@ -925,6 +925,30 @@ bool QThread::isInterruptionRequested() const
\sa start() \sa start()
*/ */
#ifdef QTHREAD_HAS_CREATE
class QThreadCreateThread : public QThread
{
public:
explicit QThreadCreateThread(std::future<void> &&future)
: m_future(std::move(future))
{
}
private:
void run() override
{
m_future.get();
}
std::future<void> m_future;
};
QThread *QThread::createThreadImpl(std::future<void> &&future)
{
return new QThreadCreateThread(std::move(future));
}
#endif // QTHREAD_HAS_CREATE
/*! /*!
\class QDaemonThread \class QDaemonThread
\since 5.5 \since 5.5

View File

@ -119,6 +119,12 @@ public:
bool event(QEvent *event) override; bool event(QEvent *event) override;
int loopLevel() const; int loopLevel() const;
#ifdef Q_QDOC
template <typename Function, typename... Args>
static QThread *create(Function &&f, Args &&... args);
template <typename Function>
static QThread *create(Function &&f);
#else
#ifdef QTHREAD_HAS_CREATE #ifdef QTHREAD_HAS_CREATE
#ifdef QTHREAD_HAS_VARIADIC_CREATE #ifdef QTHREAD_HAS_VARIADIC_CREATE
template <typename Function, typename... Args> template <typename Function, typename... Args>
@ -128,6 +134,7 @@ public:
static QThread *create(Function &&f); static QThread *create(Function &&f);
#endif #endif
#endif #endif
#endif
public Q_SLOTS: public Q_SLOTS:
void start(Priority = InheritPriority); void start(Priority = InheritPriority);
@ -158,98 +165,81 @@ protected:
private: private:
Q_DECLARE_PRIVATE(QThread) Q_DECLARE_PRIVATE(QThread)
#ifdef QTHREAD_HAS_CREATE
static QThread *createThreadImpl(std::future<void> &&future);
#endif
friend class QCoreApplication; friend class QCoreApplication;
friend class QThreadData; friend class QThreadData;
}; };
#ifdef QTHREAD_HAS_CREATE #ifdef QTHREAD_HAS_CREATE
namespace QtPrivate {
class QThreadCreateThread : public QThread
{
public:
#if defined(QTHREAD_HAS_VARIADIC_CREATE)
// C++17: std::thread's constructor complying call
template <typename Function, typename... Args>
explicit QThreadCreateThread(Function &&f, Args &&... args)
: m_future(std::async(std::launch::deferred,
[f = static_cast<typename std::decay<Function>::type>(std::forward<Function>(f))](auto &&... largs) mutable -> void
{
(void)std::invoke(std::move(f), std::forward<decltype(largs)>(largs)...);
}, std::forward<Args>(args)...))
{
}
#elif defined(__cpp_init_captures) && __cpp_init_captures >= 201304
// C++14: implementation for just one callable
template <typename Function>
explicit QThreadCreateThread(Function &&f)
: m_future(std::async(std::launch::deferred,
[f = static_cast<typename std::decay<Function>::type>(std::forward<Function>(f))]() mutable -> void
{
(void)f();
}))
{
}
#else
private:
// C++11: same as C++14, but with a workaround for not having generalized lambda captures
template <typename Function>
struct Callable
{
explicit Callable(Function &&f)
: m_function(std::forward<Function>(f))
{
}
#if defined(Q_COMPILER_DEFAULT_MEMBERS) && defined(Q_COMPILER_DELETE_MEMBERS)
// Apply the same semantics of a lambda closure type w.r.t. the special
// member functions, if possible: delete the copy assignment operator,
// bring back all the others as per the RO5 (cf. §8.1.5.1/11 [expr.prim.lambda.closure])
~Callable() = default;
Callable(const Callable &) = default;
Callable(Callable &&) = default;
Callable &operator=(const Callable &) = delete;
Callable &operator=(Callable &&) = default;
#endif
void operator()()
{
(void)m_function();
}
typename std::decay<Function>::type m_function;
};
public:
template <typename Function>
explicit QThreadCreateThread(Function &&f)
: m_future(std::async(std::launch::deferred, Callable<Function>(std::forward<Function>(f))))
{
}
#endif // QTHREAD_HAS_VARIADIC_CREATE
private:
void run() override
{
m_future.get();
}
std::future<void> m_future;
};
} // namespace QtPrivate
#ifdef QTHREAD_HAS_VARIADIC_CREATE #ifdef QTHREAD_HAS_VARIADIC_CREATE
// C++17: std::thread's constructor complying call
template <typename Function, typename... Args> template <typename Function, typename... Args>
QThread *QThread::create(Function &&f, Args &&... args) QThread *QThread::create(Function &&f, Args &&... args)
{ {
return new QtPrivate::QThreadCreateThread(std::forward<Function>(f), std::forward<Args>(args)...); using DecayedFunction = typename std::decay<Function>::type;
auto threadFunction =
[f = static_cast<DecayedFunction>(std::forward<Function>(f))](auto &&... largs) mutable -> void
{
(void)std::invoke(std::move(f), std::forward<decltype(largs)>(largs)...);
};
return createThreadImpl(std::async(std::launch::deferred,
std::move(threadFunction),
std::forward<Args>(args)...));
} }
#else #elif defined(__cpp_init_captures) && __cpp_init_captures >= 201304
// C++14: implementation for just one callable
template <typename Function> template <typename Function>
QThread *QThread::create(Function &&f) QThread *QThread::create(Function &&f)
{ {
return new QtPrivate::QThreadCreateThread(std::forward<Function>(f)); using DecayedFunction = typename std::decay<Function>::type;
auto threadFunction =
[f = static_cast<DecayedFunction>(std::forward<Function>(f))]() mutable -> void
{
(void)f();
};
return createThreadImpl(std::async(std::launch::deferred, std::move(threadFunction)));
}
#else
// C++11: same as C++14, but with a workaround for not having generalized lambda captures
namespace QtPrivate {
template <typename Function>
struct Callable
{
explicit Callable(Function &&f)
: m_function(std::forward<Function>(f))
{
}
#if defined(Q_COMPILER_DEFAULT_MEMBERS) && defined(Q_COMPILER_DELETE_MEMBERS)
// Apply the same semantics of a lambda closure type w.r.t. the special
// member functions, if possible: delete the copy assignment operator,
// bring back all the others as per the RO5 (cf. §8.1.5.1/11 [expr.prim.lambda.closure])
~Callable() = default;
Callable(const Callable &) = default;
Callable(Callable &&) = default;
Callable &operator=(const Callable &) = delete;
Callable &operator=(Callable &&) = default;
#endif
void operator()()
{
(void)m_function();
}
typename std::decay<Function>::type m_function;
};
} // namespace QtPrivate
template <typename Function>
QThread *QThread::create(Function &&f)
{
return createThreadImpl(std::async(std::launch::deferred, QtPrivate::Callable<Function>(std::forward<Function>(f))));
} }
#endif // QTHREAD_HAS_VARIADIC_CREATE #endif // QTHREAD_HAS_VARIADIC_CREATE

View File

@ -606,17 +606,19 @@ void QThreadPool::reserveThread()
++d->reservedThreads; ++d->reservedThreads;
} }
/*! \property QThreadPool::stacksize /*! \property QThreadPool::stackSize
This property contains the stack size for the thread pool worker This property contains the stack size for the thread pool worker
threads. threads.
The value of the property is uses when the thread pool creates The value of the property is only used when the thread pool creates
new threads only. Changing it has no effect for already created new threads. Changing it has no effect for already created
or running threads. or running threads.
The default value is 0, which makes QThread use the operating The default value is 0, which makes QThread use the operating
system default stack stize. system default stack size.
\since 5.10
*/ */
void QThreadPool::setStackSize(uint stackSize) void QThreadPool::setStackSize(uint stackSize)
{ {

View File

@ -296,7 +296,7 @@ static uint qt_create_qhash_seed()
return seed; return seed;
} }
seed = QRandomGenerator::get32(); seed = QRandomGenerator::generate();
#endif // QT_BOOTSTRAPPED #endif // QT_BOOTSTRAPPED
return seed; return seed;

View File

@ -3814,8 +3814,6 @@ QString QLocale::toCurrencyString(double value, const QString &symbol, int preci
1000. DataSizeIecFormat uses the new IEC standard quantifiers Ki, Mi and so 1000. DataSizeIecFormat uses the new IEC standard quantifiers Ki, Mi and so
on, whereas DataSizeSIFormat uses and DataSizeTraditionalFormat abuses the on, whereas DataSizeSIFormat uses and DataSizeTraditionalFormat abuses the
older SI quantifiers k, M, etc. older SI quantifiers k, M, etc.
\sa refresh(), caching()
*/ */
QString QLocale::formattedDataSize(qint64 bytes, int precision, DataSizeFormats format) QString QLocale::formattedDataSize(qint64 bytes, int precision, DataSizeFormats format)
{ {

View File

@ -851,17 +851,20 @@ Q_INLINE_TEMPLATE typename QSharedPointer<X>::difference_type operator-(T *ptr1,
template <class T, class X> template <class T, class X>
Q_INLINE_TEMPLATE bool operator<(const QSharedPointer<T> &ptr1, const QSharedPointer<X> &ptr2) Q_INLINE_TEMPLATE bool operator<(const QSharedPointer<T> &ptr1, const QSharedPointer<X> &ptr2)
{ {
return ptr1.data() < ptr2.data(); using CT = typename std::common_type<T *, X *>::type;
return std::less<CT>()(ptr1.data(), ptr2.data());
} }
template <class T, class X> template <class T, class X>
Q_INLINE_TEMPLATE bool operator<(const QSharedPointer<T> &ptr1, X *ptr2) Q_INLINE_TEMPLATE bool operator<(const QSharedPointer<T> &ptr1, X *ptr2)
{ {
return ptr1.data() < ptr2; using CT = typename std::common_type<T *, X *>::type;
return std::less<CT>()(ptr1.data(), ptr2);
} }
template <class T, class X> template <class T, class X>
Q_INLINE_TEMPLATE bool operator<(T *ptr1, const QSharedPointer<X> &ptr2) Q_INLINE_TEMPLATE bool operator<(T *ptr1, const QSharedPointer<X> &ptr2)
{ {
return ptr1 < ptr2.data(); using CT = typename std::common_type<T *, X *>::type;
return std::less<CT>()(ptr1, ptr2.data());
} }
// //

View File

@ -72,6 +72,7 @@
#include <stdlib.h> #include <stdlib.h>
#include <stdio.h> #include <stdio.h>
#include <stdarg.h> #include <stdarg.h>
#include <wchar.h>
#include "qchar.cpp" #include "qchar.cpp"
#include "qstringmatcher.cpp" #include "qstringmatcher.cpp"
@ -159,6 +160,43 @@ static inline bool qt_ends_with(QStringView haystack, QStringView needle, Qt::Ca
static inline bool qt_ends_with(QStringView haystack, QLatin1String needle, Qt::CaseSensitivity cs); static inline bool qt_ends_with(QStringView haystack, QLatin1String needle, Qt::CaseSensitivity cs);
static inline bool qt_ends_with(QStringView haystack, QChar needle, Qt::CaseSensitivity cs); static inline bool qt_ends_with(QStringView haystack, QChar needle, Qt::CaseSensitivity cs);
qssize_t qustrlen(const ushort *str) Q_DECL_NOTHROW
{
qssize_t result = 0;
#ifdef __SSE2__
// progress until we get an aligned pointer
const ushort *ptr = str;
while (*ptr && quintptr(ptr) % 16)
++ptr;
if (*ptr == 0)
return ptr - str;
// load 16 bytes and see if we have a null
// (aligned loads can never segfault)
int mask;
const __m128i zeroes = _mm_setzero_si128();
do {
__m128i data = _mm_load_si128(reinterpret_cast<const __m128i *>(ptr));
ptr += 8;
__m128i comparison = _mm_cmpeq_epi16(data, zeroes);
mask = _mm_movemask_epi8(comparison);
} while (mask == 0);
// found a null
uint idx = qCountTrailingZeroBits(quint32(mask));
return ptr - str - 8 + idx / 2;
#endif
if (sizeof(wchar_t) == sizeof(ushort))
return wcslen(reinterpret_cast<const wchar_t *>(str));
while (*str++)
++result;
return result;
}
#if defined(Q_COMPILER_LAMBDA) && !defined(__OPTIMIZE_SIZE__) #if defined(Q_COMPILER_LAMBDA) && !defined(__OPTIMIZE_SIZE__)
namespace { namespace {
template <uint MaxCount> struct UnrollTailLoop template <uint MaxCount> struct UnrollTailLoop

View File

@ -53,6 +53,8 @@ class QLatin1String;
class QStringView; class QStringView;
template <typename T> class QVector; template <typename T> class QVector;
Q_REQUIRED_RESULT Q_CORE_EXPORT Q_DECL_PURE_FUNCTION qssize_t qustrlen(const ushort *str) Q_DECL_NOTHROW;
Q_REQUIRED_RESULT Q_CORE_EXPORT Q_DECL_PURE_FUNCTION int qCompareStrings(QStringView lhs, QStringView rhs, Qt::CaseSensitivity cs = Qt::CaseSensitive) Q_DECL_NOTHROW; Q_REQUIRED_RESULT Q_CORE_EXPORT Q_DECL_PURE_FUNCTION int qCompareStrings(QStringView lhs, QStringView rhs, Qt::CaseSensitivity cs = Qt::CaseSensitive) Q_DECL_NOTHROW;
Q_REQUIRED_RESULT Q_CORE_EXPORT Q_DECL_PURE_FUNCTION int qCompareStrings(QStringView lhs, QLatin1String rhs, Qt::CaseSensitivity cs = Qt::CaseSensitive) Q_DECL_NOTHROW; Q_REQUIRED_RESULT Q_CORE_EXPORT Q_DECL_PURE_FUNCTION int qCompareStrings(QStringView lhs, QLatin1String rhs, Qt::CaseSensitivity cs = Qt::CaseSensitive) Q_DECL_NOTHROW;
Q_REQUIRED_RESULT Q_CORE_EXPORT Q_DECL_PURE_FUNCTION int qCompareStrings(QLatin1String lhs, QStringView rhs, Qt::CaseSensitivity cs = Qt::CaseSensitive) Q_DECL_NOTHROW; Q_REQUIRED_RESULT Q_CORE_EXPORT Q_DECL_PURE_FUNCTION int qCompareStrings(QLatin1String lhs, QStringView rhs, Qt::CaseSensitivity cs = Qt::CaseSensitive) Q_DECL_NOTHROW;

View File

@ -143,20 +143,22 @@ private:
{ {
return qssize_t(N - 1); return qssize_t(N - 1);
} }
template <typename Char> template <typename Char>
static Q_DECL_RELAXED_CONSTEXPR qssize_t lengthHelperPointer(const Char *str) Q_DECL_NOTHROW static qssize_t lengthHelperPointer(const Char *str) Q_DECL_NOTHROW
{ {
qssize_t result = 0; #if defined(Q_CC_GNU) && !defined(Q_CC_CLANG) && !defined(Q_CC_INTEL)
while (*str++) if (__builtin_constant_p(*str)) {
++result; qssize_t result = 0;
return result; while (*str++)
++result;
}
#endif
return qustrlen(reinterpret_cast<const ushort *>(str));
} }
static Q_DECL_RELAXED_CONSTEXPR qssize_t lengthHelperPointer(const QChar *str) Q_DECL_NOTHROW static qssize_t lengthHelperPointer(const QChar *str) Q_DECL_NOTHROW
{ {
qssize_t result = 0; return qustrlen(reinterpret_cast<const ushort *>(str));
while (!str++->isNull())
++result;
return result;
} }
template <typename Char> template <typename Char>

View File

@ -2113,8 +2113,8 @@ static QImage convertWithPalette(const QImage &src, QImage::Format format,
Returns a copy of the image converted to the given \a format, Returns a copy of the image converted to the given \a format,
using the specified \a colorTable. using the specified \a colorTable.
Conversion from 32 bit to 8 bit indexed is a slow operation and Conversion from RGB formats to indexed formats is a slow operation
will use a straightforward nearest color approach, with no and will use a straightforward nearest color approach, with no
dithering. dithering.
*/ */
QImage QImage::convertToFormat(Format format, const QVector<QRgb> &colorTable, Qt::ImageConversionFlags flags) const QImage QImage::convertToFormat(Format format, const QVector<QRgb> &colorTable, Qt::ImageConversionFlags flags) const
@ -2122,23 +2122,12 @@ QImage QImage::convertToFormat(Format format, const QVector<QRgb> &colorTable, Q
if (!d || d->format == format) if (!d || d->format == format)
return *this; return *this;
if (format <= QImage::Format_Indexed8 && depth() == 32) { if (format == QImage::Format_Invalid)
return convertWithPalette(*this, format, colorTable);
}
const Image_Converter *converterPtr = &qimage_converter_map[d->format][format];
Image_Converter converter = *converterPtr;
if (!converter)
return QImage(); return QImage();
if (format <= QImage::Format_Indexed8)
return convertWithPalette(convertToFormat(QImage::Format_ARGB32, flags), format, colorTable);
QImage image(d->width, d->height, format); return convertToFormat(format, flags);
QIMAGE_SANITYCHECK_MEMORY(image);
image.d->offset = offset();
copyMetadata(image.d, d);
converter(image.d, d, flags);
return image;
} }
/*! /*!

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