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]
-use-gold-linker ..... Use the GNU gold linker [auto]
-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)
-mp .................. Use multiple processors for compilation (MSVC only)

View File

@ -61,6 +61,7 @@
"avx2": "boolean",
"avx512": { "type": "boolean", "name": "avx512f" },
"c++std": "cxxstd",
"ccache": { "type": "boolean", "name": "ccache" },
"commercial": "void",
"compile-examples": { "type": "boolean", "name": "compile_examples" },
"confirm-license": "void",
@ -635,6 +636,11 @@
"label": "IncrediBuild",
"type": "files",
"files": [ "BuildConsole.exe", "xgConsole.exe" ]
},
"ccache": {
"label": "ccache",
"type": "files",
"files": [ "ccache" ]
}
},
@ -1246,6 +1252,12 @@
"condition": "tests.incredibuild_xge",
"output": [ "publicConfig" ]
},
"ccache": {
"label": "Using ccache",
"autoDetect": false,
"condition": "config.unix && tests.ccache",
"output": [ "privateConfig" ]
},
"msvc_mp": {
"label": "Use multiple processors when compiling with MSVC",
"emitIf": "config.msvc",
@ -1353,6 +1365,11 @@ Configure with '-qreal float' to create a build that is binary-compatible with 5
"type": "firstAvailableFeature",
"args": "c++1z c++14 c++11"
},
{
"type": "feature",
"args": "ccache",
"condition": "config.unix"
},
"use_gold_linker",
{
"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"
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:"));
hostLineEdit = new QLineEdit("fortune");
setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint);
QLabel *hostLabel = new QLabel(tr("&Server name:"));
hostLabel->setBuddy(hostLineEdit);
statusLabel = new QLabel(tr("This examples requires that you run the "
"Fortune Server example as well."));
statusLabel->setWordWrap(true);
getFortuneButton = new QPushButton(tr("Get Fortune"));
getFortuneButton->setDefault(true);
QPushButton *quitButton = new QPushButton(tr("Quit"));
quitButton = new QPushButton(tr("Quit"));
buttonBox = new QDialogButtonBox;
QDialogButtonBox *buttonBox = new QDialogButtonBox;
buttonBox->addButton(getFortuneButton, QDialogButtonBox::ActionRole);
buttonBox->addButton(quitButton, QDialogButtonBox::RejectRole);
socket = new QLocalSocket(this);
in.setDevice(socket);
in.setVersion(QDataStream::Qt_5_10);
connect(hostLineEdit, SIGNAL(textChanged(QString)),
this, SLOT(enableGetFortuneButton()));
connect(getFortuneButton, SIGNAL(clicked()),
this, SLOT(requestNewFortune()));
connect(quitButton, SIGNAL(clicked()), this, SLOT(close()));
connect(socket, SIGNAL(readyRead()), this, SLOT(readFortune()));
connect(socket, SIGNAL(error(QLocalSocket::LocalSocketError)),
this, SLOT(displayError(QLocalSocket::LocalSocketError)));
connect(hostLineEdit, &QLineEdit::textChanged,
this, &Client::enableGetFortuneButton);
connect(getFortuneButton, &QPushButton::clicked,
this, &Client::requestNewFortune);
connect(quitButton, &QPushButton::clicked, this, &Client::close);
connect(socket, &QLocalSocket::readyRead, this, &Client::readFortune);
connect(socket, QOverload<QLocalSocket::LocalSocketError>::of(&QLocalSocket::error),
this, &Client::displayError);
QGridLayout *mainLayout = new QGridLayout;
QGridLayout *mainLayout = new QGridLayout(this);
mainLayout->addWidget(hostLabel, 0, 0);
mainLayout->addWidget(hostLineEdit, 0, 1);
mainLayout->addWidget(statusLabel, 2, 0, 1, 2);
mainLayout->addWidget(buttonBox, 3, 0, 1, 2);
setLayout(mainLayout);
setWindowTitle(tr("Fortune Client"));
setWindowTitle(QGuiApplication::applicationDisplayName());
hostLineEdit->setFocus();
}
@ -106,11 +106,9 @@ void Client::requestNewFortune()
void Client::readFortune()
{
QDataStream in(socket);
in.setVersion(QDataStream::Qt_4_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))
return;
in >> blockSize;
@ -123,7 +121,7 @@ void Client::readFortune()
in >> nextFortune;
if (nextFortune == currentFortune) {
QTimer::singleShot(0, this, SLOT(requestNewFortune()));
QTimer::singleShot(0, this, &Client::requestNewFortune);
return;
}
@ -136,21 +134,22 @@ void Client::displayError(QLocalSocket::LocalSocketError socketError)
{
switch (socketError) {
case QLocalSocket::ServerNotFoundError:
QMessageBox::information(this, tr("Fortune Client"),
tr("The host was not found. Please check the "
"host name and port settings."));
QMessageBox::information(this, tr("Local Fortune Client"),
tr("The host was not found. Please make sure "
"that the server is running and that the "
"server name is correct."));
break;
case QLocalSocket::ConnectionRefusedError:
QMessageBox::information(this, tr("Fortune Client"),
QMessageBox::information(this, tr("Local Fortune Client"),
tr("The connection was refused by the peer. "
"Make sure the fortune server is running, "
"and check that the host name and port "
"settings are correct."));
"and check that the server name "
"is correct."));
break;
case QLocalSocket::PeerClosedError:
break;
default:
QMessageBox::information(this, tr("Fortune Client"),
QMessageBox::information(this, tr("Local Fortune Client"),
tr("The following error occurred: %1.")
.arg(socket->errorString()));
}

View File

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

View File

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

View File

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

View File

@ -60,22 +60,21 @@
Server::Server(QWidget *parent)
: QDialog(parent)
{
statusLabel = new QLabel;
statusLabel->setWordWrap(true);
quitButton = new QPushButton(tr("Quit"));
quitButton->setAutoDefault(false);
setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint);
server = new QLocalServer(this);
if (!server->listen("fortune")) {
QMessageBox::critical(this, tr("Fortune Server"),
QMessageBox::critical(this, tr("Local Fortune Server"),
tr("Unable to start the server: %1.")
.arg(server->errorString()));
close();
return;
}
QLabel *statusLabel = new QLabel;
statusLabel->setWordWrap(true);
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.")
<< 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("Computers are not intelligent. They only think they are.");
connect(quitButton, SIGNAL(clicked()), this, SLOT(close()));
connect(server, SIGNAL(newConnection()), this, SLOT(sendFortune()));
QPushButton *quitButton = new QPushButton(tr("Quit"));
quitButton->setAutoDefault(false);
connect(quitButton, &QPushButton::clicked, this, &Server::close);
connect(server, &QLocalServer::newConnection, this, &Server::sendFortune);
QHBoxLayout *buttonLayout = new QHBoxLayout;
buttonLayout->addStretch(1);
buttonLayout->addWidget(quitButton);
buttonLayout->addStretch(1);
QVBoxLayout *mainLayout = new QVBoxLayout;
QVBoxLayout *mainLayout = new QVBoxLayout(this);
mainLayout->addWidget(statusLabel);
mainLayout->addLayout(buttonLayout);
setLayout(mainLayout);
setWindowTitle(tr("Fortune Server"));
setWindowTitle(QGuiApplication::applicationDisplayName());
}
void Server::sendFortune()
{
QByteArray block;
QDataStream out(&block, QIODevice::WriteOnly);
out.setVersion(QDataStream::Qt_4_0);
out << (quint32)0;
out << fortunes.at(qrand() % fortunes.size());
out.device()->seek(0);
out << (quint32)(block.size() - sizeof(quint32));
out.setVersion(QDataStream::Qt_5_10);
const int fortuneIndex = QRandomGenerator::bounded(0, fortunes.size());
const QString &message = fortunes.at(fortuneIndex);
out << quint32(message.size());
out << message;
QLocalSocket *clientConnection = server->nextPendingConnection();
connect(clientConnection, SIGNAL(disconnected()),
clientConnection, SLOT(deleteLater()));
connect(clientConnection, &QLocalSocket::disconnected,
clientConnection, &QLocalSocket::deleteLater);
clientConnection->write(block);
clientConnection->flush();

View File

@ -64,14 +64,12 @@ class Server : public QDialog
Q_OBJECT
public:
Server(QWidget *parent = 0);
explicit Server(QWidget *parent = nullptr);
private slots:
void sendFortune();
private:
QLabel *statusLabel;
QPushButton *quitButton;
QLocalServer *server;
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/
**
** This file is part of the examples of the Qt Toolkit.
@ -50,6 +50,7 @@
#include <QtWidgets>
#include <QtNetwork>
#include <QtCore>
#include "sender.h"
@ -60,23 +61,21 @@ Sender::Sender(QWidget *parent)
statusLabel->setWordWrap(true);
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(quitButton, QDialogButtonBox::RejectRole);
timer = new QTimer(this);
//! [0]
udpSocket = new QUdpSocket(this);
//! [0]
messageNo = 1;
connect(startButton, SIGNAL(clicked()), this, SLOT(startBroadcasting()));
connect(quitButton, SIGNAL(clicked()), this, SLOT(close()));
connect(timer, SIGNAL(timeout()), this, SLOT(broadcastDatagram()));
connect(startButton, &QPushButton::clicked, this, &Sender::startBroadcasting);
connect(quitButton, &QPushButton::clicked, this, &Sender::close);
connect(&timer, &QTimer::timeout, this, &Sender::broadcastDatagram);
QVBoxLayout *mainLayout = new QVBoxLayout;
auto mainLayout = new QVBoxLayout;
mainLayout->addWidget(statusLabel);
mainLayout->addWidget(buttonBox);
setLayout(mainLayout);
@ -87,7 +86,7 @@ Sender::Sender(QWidget *parent)
void Sender::startBroadcasting()
{
startButton->setEnabled(false);
timer->start(1000);
timer.start(1000);
}
void Sender::broadcastDatagram()
@ -95,8 +94,7 @@ void Sender::broadcastDatagram()
statusLabel->setText(tr("Now broadcasting datagram %1").arg(messageNo));
//! [1]
QByteArray datagram = "Broadcast message " + QByteArray::number(messageNo);
udpSocket->writeDatagram(datagram.data(), datagram.size(),
QHostAddress::Broadcast, 45454);
udpSocket->writeDatagram(datagram, QHostAddress::Broadcast, 45454);
//! [1]
++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/
**
** This file is part of the examples of the Qt Toolkit.
@ -52,12 +52,11 @@
#define SENDER_H
#include <QWidget>
#include <QTimer>
QT_BEGIN_NAMESPACE
class QDialogButtonBox;
class QLabel;
class QPushButton;
class QTimer;
class QUdpSocket;
QT_END_NAMESPACE
@ -66,20 +65,18 @@ class Sender : public QWidget
Q_OBJECT
public:
Sender(QWidget *parent = 0);
explicit Sender(QWidget *parent = nullptr);
private slots:
void startBroadcasting();
void broadcastDatagram();
private:
QLabel *statusLabel;
QPushButton *startButton;
QPushButton *quitButton;
QDialogButtonBox *buttonBox;
QUdpSocket *udpSocket;
QTimer *timer;
int messageNo;
QLabel *statusLabel = nullptr;
QPushButton *startButton = nullptr;
QUdpSocket *udpSocket = nullptr;
QTimer timer;
int messageNo = 1;
};
#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 "ui_authenticationdialog.h"
#ifndef QT_NO_SSL
static const char defaultUrl[] = "https://www.qt.io/";
#if QT_CONFIG(ssl)
const char defaultUrl[] = "https://www.qt.io/";
#else
static const char defaultUrl[] = "http://www.qt.io/";
const char defaultUrl[] = "http://www.qt.io/";
#endif
static const char defaultFileName[] = "index.html";
const char defaultFileName[] = "index.html";
ProgressDialog::ProgressDialog(const QUrl &url, QWidget *parent)
: QProgressDialog(parent)
@ -71,6 +71,7 @@ ProgressDialog::ProgressDialog(const QUrl &url, QWidget *parent)
setMinimum(0);
setValue(0);
setMinimumDuration(0);
setMinimumSize(QSize(400, 75));
}
void ProgressDialog::networkReplyProgress(qint64 bytesRead, qint64 totalBytes)
@ -174,15 +175,22 @@ void HttpWindow::downloadFile()
if (fileName.isEmpty())
fileName = defaultFileName;
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 + '/');
if (QFile::exists(fileName)) {
if (QMessageBox::question(this, tr("Overwrite Existing File"),
tr("There already exists a file called %1 in "
"the current directory. Overwrite?").arg(fileName),
QMessageBox::Yes|QMessageBox::No, QMessageBox::No)
== QMessageBox::No)
tr("There already exists a file called %1%2."
" Overwrite?")
.arg(fileName,
useDirectory
? QString()
: QStringLiteral(" in the current directory")),
QMessageBox::Yes | QMessageBox::No,
QMessageBox::No)
== QMessageBox::No) {
return;
}
QFile::remove(fileName);
}
@ -252,7 +260,9 @@ void HttpWindow::httpFinished()
if (QMessageBox::question(this, tr("Redirect"),
tr("Redirect to %1 ?").arg(redirectedUrl.toString()),
QMessageBox::Yes | QMessageBox::No) == QMessageBox::No) {
QFile::remove(fi.absoluteFilePath());
downloadButton->setEnabled(true);
statusLabel->setText(tr("Download failed:\nRedirect rejected."));
return;
}
file = openFileForWrite(fi.absoluteFilePath());
@ -286,7 +296,7 @@ void HttpWindow::enableDownloadButton()
downloadButton->setEnabled(!urlLineEdit->text().isEmpty());
}
void HttpWindow::slotAuthenticationRequired(QNetworkReply*,QAuthenticator *authenticator)
void HttpWindow::slotAuthenticationRequired(QNetworkReply *, QAuthenticator *authenticator)
{
QDialog authenticationDialog;
Ui::Dialog ui;
@ -306,7 +316,7 @@ void HttpWindow::slotAuthenticationRequired(QNetworkReply*,QAuthenticator *authe
}
#ifndef QT_NO_SSL
void HttpWindow::sslErrors(QNetworkReply*,const QList<QSslError> &errors)
void HttpWindow::sslErrors(QNetworkReply *, const QList<QSslError> &errors)
{
QString errorString;
foreach (const QSslError &error, errors) {

View File

@ -92,9 +92,9 @@ private slots:
void httpFinished();
void httpReadyRead();
void enableDownloadButton();
void slotAuthenticationRequired(QNetworkReply*,QAuthenticator *);
void slotAuthenticationRequired(QNetworkReply *, QAuthenticator *authenticator);
#ifndef QT_NO_SSL
void sslErrors(QNetworkReply*,const QList<QSslError> &errors);
void sslErrors(QNetworkReply *, const QList<QSslError> &errors);
#endif
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/
**
** This file is part of the examples of the Qt Toolkit.
@ -48,43 +48,35 @@
**
****************************************************************************/
#include <QtWidgets>
#include <QtNetwork>
#include "sender.h"
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()));
ttlLabel = new QLabel(tr("TTL for multicast datagrams:"));
ttlSpinBox = new QSpinBox;
auto ttlLabel = new QLabel(tr("TTL for multicast datagrams:"));
auto ttlSpinBox = new QSpinBox;
ttlSpinBox->setRange(0, 255);
QHBoxLayout *ttlLayout = new QHBoxLayout;
auto ttlLayout = new QHBoxLayout;
ttlLayout->addWidget(ttlLabel);
ttlLayout->addWidget(ttlSpinBox);
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(quitButton, QDialogButtonBox::RejectRole);
timer = new QTimer(this);
udpSocket = new QUdpSocket(this);
messageNo = 1;
connect(ttlSpinBox, QOverload<int>::of(&QSpinBox::valueChanged), this, &Sender::ttlChanged);
connect(startButton, &QPushButton::clicked, this, &Sender::startSending);
connect(quitButton, &QPushButton::clicked, this, &Sender::close);
connect(&timer, &QTimer::timeout, this, &Sender::sendDatagram);
connect(ttlSpinBox, SIGNAL(valueChanged(int)), this, SLOT(ttlChanged(int)));
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;
auto mainLayout = new QVBoxLayout;
mainLayout->addWidget(statusLabel);
mainLayout->addLayout(ttlLayout);
mainLayout->addWidget(buttonBox);
@ -96,20 +88,19 @@ Sender::Sender(QWidget *parent)
void Sender::ttlChanged(int newTtl)
{
udpSocket->setSocketOption(QAbstractSocket::MulticastTtlOption, newTtl);
udpSocket.setSocketOption(QAbstractSocket::MulticastTtlOption, newTtl);
}
void Sender::startSending()
{
startButton->setEnabled(false);
timer->start(1000);
timer.start(1000);
}
void Sender::sendDatagram()
{
statusLabel->setText(tr("Now sending datagram %1").arg(messageNo));
QByteArray datagram = "Multicast message " + QByteArray::number(messageNo);
udpSocket->writeDatagram(datagram.data(), datagram.size(),
groupAddress, 45454);
udpSocket.writeDatagram(datagram, groupAddress, 45454);
++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/
**
** This file is part of the examples of the Qt Toolkit.
@ -51,24 +51,16 @@
#ifndef SENDER_H
#define SENDER_H
#include <QDialog>
#include <QHostAddress>
QT_BEGIN_NAMESPACE
class QDialogButtonBox;
class QLabel;
class QPushButton;
class QTimer;
class QUdpSocket;
class QSpinBox;
QT_END_NAMESPACE
#include <QtWidgets>
#include <QtNetwork>
#include <QtCore>
class Sender : public QDialog
{
Q_OBJECT
public:
Sender(QWidget *parent = 0);
explicit Sender(QWidget *parent = nullptr);
private slots:
void ttlChanged(int newTtl);
@ -76,16 +68,12 @@ private slots:
void sendDatagram();
private:
QLabel *statusLabel;
QLabel *ttlLabel;
QSpinBox *ttlSpinBox;
QPushButton *startButton;
QPushButton *quitButton;
QDialogButtonBox *buttonBox;
QUdpSocket *udpSocket;
QTimer *timer;
QLabel *statusLabel = nullptr;
QPushButton *startButton = nullptr;
QUdpSocket udpSocket;
QTimer timer;
QHostAddress groupAddress;
int messageNo;
int messageNo = 1;
};
#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/
**
** This file is part of the examples of the Qt Toolkit.
@ -57,8 +57,8 @@ CertificateInfo::CertificateInfo(QWidget *parent)
form = new Ui_CertificateInfo;
form->setupUi(this);
connect(form->certificationPathView, SIGNAL(currentIndexChanged(int)),
this, SLOT(updateCertificateInfo(int)));
connect(form->certificationPathView, QOverload<int>::of(&QComboBox::currentIndexChanged),
this, &CertificateInfo::updateCertificateInfo);
}
CertificateInfo::~CertificateInfo()
@ -68,25 +68,23 @@ CertificateInfo::~CertificateInfo()
void CertificateInfo::setCertificateChain(const QList<QSslCertificate> &chain)
{
this->chain = chain;
certificateChain = chain;
form->certificationPathView->clear();
for (int i = 0; i < chain.size(); ++i) {
const QSslCertificate &cert = chain.at(i);
for (int i = 0; i < certificateChain.size(); ++i) {
const QSslCertificate &cert = certificateChain.at(i);
form->certificationPathView->addItem(tr("%1%2 (%3)").arg(!i ? QString() : tr("Issued by: "))
.arg(cert.subjectInfo(QSslCertificate::Organization).join(QLatin1Char(' ')))
.arg(cert.subjectInfo(QSslCertificate::CommonName).join(QLatin1Char(' '))));
}
form->certificationPathView->setCurrentIndex(0);
}
void CertificateInfo::updateCertificateInfo(int index)
{
form->certificateInfoView->clear();
if (index >= 0 && index < chain.size()) {
const QSslCertificate &cert = chain.at(index);
if (index >= 0 && index < certificateChain.size()) {
const QSslCertificate &cert = certificateChain.at(index);
QStringList lines;
lines << tr("Organization: %1").arg(cert.subjectInfo(QSslCertificate::Organization).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 State/Province: %1").arg(cert.issuerInfo(QSslCertificate::StateOrProvinceName).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);
} 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/
**
** This file is part of the examples of the Qt Toolkit.
@ -51,8 +51,9 @@
#ifndef CERTIFICATEINFO_H
#define CERTIFICATEINFO_H
#include <QtWidgets/QDialog>
#include <QtNetwork/QSslCertificate>
#include <QDialog>
#include <QList>
#include <QSslCertificate>
QT_BEGIN_NAMESPACE
class Ui_CertificateInfo;
@ -62,7 +63,7 @@ class CertificateInfo : public QDialog
{
Q_OBJECT
public:
CertificateInfo(QWidget *parent = 0);
explicit CertificateInfo(QWidget *parent = nullptr);
~CertificateInfo();
void setCertificateChain(const QList<QSslCertificate> &chain);
@ -71,8 +72,8 @@ private slots:
void updateCertificateInfo(int index);
private:
Ui_CertificateInfo *form;
QList<QSslCertificate> chain;
Ui_CertificateInfo *form = nullptr;
QList<QSslCertificate> certificateChain;
};
#endif

View File

@ -42,7 +42,7 @@
<widget class="QListWidget" name="certificateInfoView">
<property name="font">
<font>
<pointsize>8</pointsize>
<pointsize>10</pointsize>
</font>
</property>
<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/
**
** This file is part of the examples of the Qt Toolkit.
@ -50,6 +50,9 @@
#include <QApplication>
#include <QMessageBox>
#include <QtNetwork>
QT_REQUIRE_CONFIG(ssl);
#include "sslclient.h"
@ -61,7 +64,7 @@ int main(int argc, char **argv)
if (!QSslSocket::supportsSsl()) {
QMessageBox::information(0, "Secure Socket Client",
"This system does not support OpenSSL.");
"This system does not support SSL/TLS.");
return -1;
}

View File

@ -1,3 +1,5 @@
requires(qtHaveModule(network))
HEADERS += certificateinfo.h \
sslclient.h
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/
**
** This file is part of the examples of the Qt Toolkit.
@ -50,29 +50,17 @@
#include "certificateinfo.h"
#include "sslclient.h"
#include "ui_sslclient.h"
#include "ui_sslerrors.h"
#include <QtWidgets/QScrollBar>
#include <QtWidgets/QStyle>
#include <QtWidgets/QToolButton>
#include <QtWidgets/QMessageBox>
#include <QtNetwork/QSslCipher>
#include <QtCore>
SslClient::SslClient(QWidget *parent)
: QWidget(parent), socket(0), padLock(0), executingDialog(false)
: QWidget(parent)
{
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()));
setupUi();
setupSecureSocket();
}
SslClient::~SslClient()
@ -82,17 +70,15 @@ SslClient::~SslClient()
void SslClient::updateEnabledState()
{
bool unconnected = !socket || socket->state() == QAbstractSocket::UnconnectedState;
const bool unconnected = socket->state() == QAbstractSocket::UnconnectedState;
form->hostNameEdit->setReadOnly(!unconnected);
form->hostNameEdit->setFocusPolicy(unconnected ? Qt::StrongFocus : Qt::NoFocus);
form->hostNameLabel->setEnabled(unconnected);
form->portBox->setEnabled(unconnected);
form->portLabel->setEnabled(unconnected);
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->sessionInput->setEnabled(connected);
form->sessionInputLabel->setEnabled(connected);
@ -101,20 +87,6 @@ void SslClient::updateEnabledState()
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());
updateEnabledState();
}
@ -125,20 +97,18 @@ void SslClient::socketStateChanged(QAbstractSocket::SocketState state)
return;
updateEnabledState();
if (state == QAbstractSocket::UnconnectedState) {
form->sessionInput->clear();
form->hostNameEdit->setPalette(QPalette());
form->hostNameEdit->setFocus();
form->cipherLabel->setText(tr("<none>"));
if (padLock)
padLock->hide();
padLock->hide();
}
}
void SslClient::socketEncrypted()
{
if (!socket)
return; // might have disconnected already
form->sessionOutput->clear();
form->sessionInput->setFocus();
@ -146,36 +116,12 @@ void SslClient::socketEncrypted()
palette.setColor(QPalette::Base, QColor(255, 255, 192));
form->hostNameEdit->setPalette(palette);
QSslCipher ciph = socket->sessionCipher();
QString cipher = QString("%1, %2 (%3/%4)").arg(ciph.authenticationMethod())
.arg(ciph.name()).arg(ciph.usedBits()).arg(ciph.supportedBits());;
form->cipherLabel->setText(cipher);
if (!padLock) {
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();
}
const QSslCipher cipher = socket->sessionCipher();
const QString cipherInfo = QString("%1, %2 (%3/%4)").arg(cipher.authenticationMethod())
.arg(cipher.name()).arg(cipher.usedBits())
.arg(cipher.supportedBits());;
form->cipherLabel->setText(cipherInfo);
padLock->show();
}
void SslClient::socketReadyRead()
@ -185,7 +131,7 @@ void SslClient::socketReadyRead()
void SslClient::sendData()
{
QString input = form->sessionInput->text();
const QString input = form->sessionInput->text();
appendString(input + '\n');
socket->write(input.toUtf8() + "\r\n");
form->sessionInput->clear();
@ -193,7 +139,12 @@ void SslClient::sendData()
void SslClient::socketError(QAbstractSocket::SocketError)
{
if (handlingSocketError)
return;
handlingSocketError = true;
QMessageBox::critical(this, tr("Connection error"), socket->errorString());
handlingSocketError = false;
}
void SslClient::sslErrors(const QList<QSslError> &errors)
@ -201,10 +152,10 @@ void SslClient::sslErrors(const QList<QSslError> &errors)
QDialog errorDialog(this);
Ui_SslErrors ui;
ui.setupUi(&errorDialog);
connect(ui.certificateChainButton, SIGNAL(clicked()),
this, SLOT(displayCertificateInfo()));
connect(ui.certificateChainButton, &QPushButton::clicked,
this, &SslClient::displayCertificateInfo);
foreach (const QSslError &error, errors)
for (const auto &error : errors)
ui.sslErrorList->addItem(error.errorString());
executingDialog = true;
@ -219,10 +170,69 @@ void SslClient::sslErrors(const QList<QSslError> &errors)
void SslClient::displayCertificateInfo()
{
CertificateInfo *info = new CertificateInfo(this);
info->setCertificateChain(socket->peerCertificateChain());
info->exec();
info->deleteLater();
CertificateInfo info;
info.setCertificateChain(socket->peerCertificateChain());
info.exec();
}
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)

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

View File

@ -10,6 +10,12 @@
<height>320</height>
</rect>
</property>
<property name="minimumSize">
<size>
<width>343</width>
<height>320</height>
</size>
</property>
<property name="windowTitle">
<string>Secure Socket Client</string>
</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;
&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; }
&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;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;/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;br /&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
</widget>
</item>

View File

@ -54,6 +54,8 @@
#include <QCoreApplication>
#include <math.h>
bool GLWidget::m_transparent = false;
GLWidget::GLWidget(QWidget *parent)
: QOpenGLWidget(parent),
m_xRot(0),
@ -61,10 +63,9 @@ GLWidget::GLWidget(QWidget *parent)
m_zRot(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
// support it, the widget will become transparent apart from the logo.
m_transparent = QCoreApplication::arguments().contains(QStringLiteral("--transparent"));
if (m_transparent) {
QSurfaceFormat fmt = format();
fmt.setAlphaBufferSize(8);
@ -127,6 +128,8 @@ void GLWidget::setZRotation(int angle)
void GLWidget::cleanup()
{
if (m_program == nullptr)
return;
makeCurrent();
m_logoVbo.destroy();
delete m_program;

View File

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

View File

@ -51,25 +51,46 @@
#include <QApplication>
#include <QDesktopWidget>
#include <QSurfaceFormat>
#include <QCommandLineParser>
#include <QCommandLineOption>
#include "glwidget.h"
#include "mainwindow.h"
int main(int argc, char *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;
fmt.setDepthBufferSize(24);
if (QCoreApplication::arguments().contains(QStringLiteral("--multisample")))
if (parser.isSet(multipleSampleOption))
fmt.setSamples(4);
if (QCoreApplication::arguments().contains(QStringLiteral("--coreprofile"))) {
if (parser.isSet(coreProfileOption)) {
fmt.setVersion(3, 2);
fmt.setProfile(QSurfaceFormat::CoreProfile);
}
QSurfaceFormat::setDefaultFormat(fmt);
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_NoSystemBackground, false);
}

View File

@ -52,6 +52,8 @@
#include <qpa/qplatformintegration.h>
#include <QCommandLineParser>
#include <QCommandLineOption>
#include <QGuiApplication>
#include <QScreen>
#include <QThread>
@ -60,9 +62,26 @@ int main(int argc, char *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.
const bool multipleWindows = QGuiApplication::arguments().contains(QStringLiteral("--multiple"));
const bool multipleScreens = QGuiApplication::arguments().contains(QStringLiteral("--multiscreen"));
const bool multipleWindows = parser.isSet(multipleOption);
const bool multipleScreens = parser.isSet(multipleScreenOption);
QScreen *screen = QGuiApplication::primaryScreen();
@ -70,7 +89,7 @@ int main(int argc, char *argv[])
QSurfaceFormat format;
format.setDepthBufferSize(16);
if (QGuiApplication::arguments().contains(QStringLiteral("--multisample")))
if (parser.isSet(multipleSampleOption))
format.setSamples(4);
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.
if (QCoreApplication::arguments().contains(QStringLiteral("--timeout")))
if (parser.isSet(timeoutOption))
QTimer::singleShot(10000, qGuiApp, &QCoreApplication::quit);
const int exitValue = app.exec();

View File

@ -51,6 +51,8 @@
#include <QApplication>
#include <QMainWindow>
#include <QSurfaceFormat>
#include <QCommandLineParser>
#include <QCommandLineOption>
#include "mainwindow.h"
int main( int argc, char ** argv )
@ -58,12 +60,25 @@ int main( int argc, char ** argv )
Q_INIT_RESOURCE(texture);
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;
format.setDepthBufferSize(24);
format.setStencilBufferSize(8);
if (QCoreApplication::arguments().contains(QStringLiteral("--srgb")))
if (parser.isSet(srgbOption))
format.setColorSpace(QSurfaceFormat::sRGBColorSpace);
if (QCoreApplication::arguments().contains(QStringLiteral("--multisample")))
if (parser.isSet(multipleSampleOption))
format.setSamples(4);
QSurfaceFormat::setDefaultFormat(format);

View File

@ -53,6 +53,8 @@
#include <QDesktopWidget>
#include <QSurfaceFormat>
#include <QOpenGLContext>
#include <QCommandLineParser>
#include <QCommandLineOption>
#include "mainwindow.h"
#include "glwidget.h"
@ -67,6 +69,17 @@ int main( int argc, char ** 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;
format.setDepthBufferSize(16);
QSurfaceFormat::setDefaultFormat(format);
@ -93,7 +106,7 @@ int main( int argc, char ** argv )
QScopedPointer<MainWindow> mw1;
QScopedPointer<MainWindow> mw2;
if (!QApplication::arguments().contains(QStringLiteral("--single"))) {
if (!parser.isSet(singleOption)) {
if (supportsThreading) {
pos += QPoint(100, 100);
mw1.reset(new MainWindow);

View File

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

View File

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

View File

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

View File

@ -172,11 +172,20 @@
\snippet drilldown/informationwindow.cpp 4
Finally, we connect the "something's changed" signals in the
editors to our custom \c enableButtons() slot, enabling the users
to either submit or revert their changes. 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.
editors to our custom \c enableButtons slot, enabling the users
to either submit or revert their changes.
We need to use lambdas for connecting the \c enableButtons slot
because its signature does not match \c QTextEdit::textChanged
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
our widget is in fact a window, with a window system frame and a
@ -389,19 +398,21 @@
\snippet drilldown/view.cpp 6
The \c showInformation() function is given an \c ImageItem object
as argument, and starts off by extracting the item's item
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.
as argument, and starts off by extracting the item's item ID.
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
passing the item ID, a pointer to the model, and our view as a
parent, to the \c InformationWindow constructor. Note that we
connect the information window's \c imageChanged() signal to \e
this widget's \c updateImage() slot, before we give it a suitable
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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -165,11 +165,12 @@ void Browser::showTable(const QString &t)
model->select();
if (model->lastError().type() != QSqlError::NoError)
emit statusMessage(model->lastError().text());
table->setModel(model);
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();
}
@ -189,7 +190,6 @@ void Browser::showMetaData(const QString &t)
model->setHeaderData(5, Qt::Horizontal, "AutoValue");
model->setHeaderData(6, Qt::Horizontal, "DefaultValue");
for (int i = 0; i < rec.count(); ++i) {
QSqlField fld = rec.field(i);
model->setData(model->index(i, 0), fld.name());

View File

@ -65,7 +65,7 @@ class Browser: public QWidget, private Ui::Browser
{
Q_OBJECT
public:
Browser(QWidget *parent = 0);
Browser(QWidget *parent = nullptr);
virtual ~Browser();
QSqlError addConnection(const QString &driver, const QString &dbName, const QString &host,
@ -116,7 +116,9 @@ class CustomModel: public QSqlTableModel
{
Q_OBJECT
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
{
if (role == Qt::BackgroundRole && isDirty(idx))

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -51,6 +51,7 @@
#include <QtWidgets/QApplication>
#include <QtWidgets/QHeaderView>
#include <QtWidgets/QShortcut>
#include <QtWidgets/QTreeView>
#include "storagemodel.h"
@ -60,9 +61,16 @@ int main(int argc, char *argv[])
QApplication a(argc, argv);
QTreeView view;
view.setModel(new StorageModel(&view));
view.resize(640, 480);
view.setWindowTitle("Storage View");
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();
for (int c = 0; c < columnCount; ++c)
view.resizeColumnToContents(c);

View File

@ -54,14 +54,27 @@
#include <QDir>
#include <QLocale>
#include <qmath.h>
#include <algorithm>
#include <cmath>
StorageModel::StorageModel(QObject *parent) :
QAbstractTableModel(parent),
m_volumes(QStorageInfo::mountedVolumes())
QAbstractTableModel(parent)
{
}
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
{
return ColumnCount;
@ -74,6 +87,22 @@ int StorageModel::rowCount(const QModelIndex &parent) const
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
{
if (!index.isValid())
@ -96,6 +125,12 @@ QVariant StorageModel::data(const QModelIndex &index, int role) const
return QLocale().formattedDataSize(volume.bytesFree());
case ColumnAvailable:
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:
return volume.isReady();
case ColumnIsReadOnly:
@ -105,6 +140,16 @@ QVariant StorageModel::data(const QModelIndex &index, int role) const
default:
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) {
QLocale locale;
const QStorageInfo &volume = m_volumes.at(index.row());
@ -147,13 +192,13 @@ QVariant StorageModel::headerData(int section, Qt::Orientation orientation, int
switch (section) {
case ColumnRootPath:
return tr("Root path");
return tr("Root Path");
case ColumnName:
return tr("Volume Name");
case ColumnDevice:
return tr("Device");
case ColumnFileSystemName:
return tr("File system");
return tr("File System");
case ColumnTotal:
return tr("Total");
case ColumnFree:

View File

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

View File

@ -9,16 +9,20 @@ include(../common/linux.conf)
include(../common/gcc-base-unix.conf)
include(../common/android-base-head.conf)
QMAKE_CC = $$NDK_TOOLCHAIN_PATH/bin/$$NDK_TOOLS_PREFIX-gcc
QMAKE_CXX = $$NDK_TOOLCHAIN_PATH/bin/$$NDK_TOOLS_PREFIX-g++
QMAKE_CC = $${CROSS_COMPILE}gcc
QMAKE_CXX = $${CROSS_COMPILE}g++
QMAKE_LINK = $$QMAKE_CXX
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_CXX_STL_LIBS = -lgnustl_shared -lgcc
QMAKE_CFLAGS += --sysroot=$$ANDROID_PLATFORM_ROOT_PATH \
-isystem $$NDK_ROOT/sources/cxx-stl/gnu-libstdc++/$$NDK_TOOLCHAIN_VERSION/include \
exists($$NDK_ROOT/sysroot/usr/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
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): \
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
# modifications to linux.conf
QMAKE_AR = $$NDK_TOOLCHAIN_PATH/bin/$$NDK_TOOLS_PREFIX-ar cqs
QMAKE_OBJCOPY = $$NDK_TOOLCHAIN_PATH/bin/$$NDK_TOOLS_PREFIX-objcopy
QMAKE_NM = $$NDK_TOOLCHAIN_PATH/bin/$$NDK_TOOLS_PREFIX-nm -P
QMAKE_AR = $${CROSS_COMPILE}ar cqs
QMAKE_OBJCOPY = $${CROSS_COMPILE}objcopy
QMAKE_NM = $${CROSS_COMPILE}nm -P
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_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) {
!isEmpty(WIN_INCLUDETEMP) {
incvar = @$$WIN_INCLUDETEMP
incvar = @$$shell_quote($$WIN_INCLUDETEMP)
} else {
incvar =
for (inc, MOC_INCLUDEPATH): \

View File

@ -74,10 +74,10 @@ warnings_are_errors:warning_clean {
# compiler.
clang {
# 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}
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
}
} 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
!isEmpty(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__ \
__clang_major__=$$QMAKE_APPLE_CLANG_MAJOR_VERSION \
__clang_minor__=$$QMAKE_APPLE_CLANG_MINOR_VERSION \
__clang_patchlevel__=$$QMAKE_APPLE_CLANG_PATCH_VERSION
!isEmpty(QT_CLANG_MAJOR_VERSION): \
!isEmpty(QMAKE_CLANG_MAJOR_VERSION): \
QMAKE_COMPILER_DEFINES += __clang__ \
__clang_major__=$$QMAKE_CLANG_MAJOR_VERSION \
__clang_minor__=$$QMAKE_CLANG_MINOR_VERSION \
__clang_patchlevel__=$$QMAKE_CLANG_PATCH_VERSION
!isEmpty(QT_GCC_MAJOR_VERSION): \
!isEmpty(QMAKE_GCC_MAJOR_VERSION): \
QMAKE_COMPILER_DEFINES += \
__GNUC__=$$QMAKE_GCC_MAJOR_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)
{
QFile sourceFile(source);
QFile::remove(target);
QDir::root().mkpath(QFileInfo(target).absolutePath());
QFile targetFile(target);
if (targetFile.exists()) {
#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)) {
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) {
QFile targetFile(target);
if (!targetFile.setPermissions(sourceFile.permissions() | QFileDevice::ExeOwner | QFileDevice::ExeUser |
QFileDevice::ExeGroup | QFileDevice::ExeOther)) {
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
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)) {
fprintf(stderr, "%s", qPrintable(error));
return 3;
}
#ifdef Q_OS_WIN
if (readOnly)
targetFile.setPermissions(permissions);
#endif
return 0;
}

View File

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

View File

@ -15,7 +15,7 @@ load(qt_helper_lib)
DEFINES += HAVE_CONFIG_H
# platform/compiler specific definitions
ios|qnx|winrt: DEFINES += PCRE2_DISABLE_JIT
uikit|qnx|winrt: DEFINES += PCRE2_DISABLE_JIT
SOURCES += \
$$PWD/src/pcre2_auto_possess.c \
@ -33,7 +33,6 @@ SOURCES += \
$$PWD/src/pcre2_newline.c \
$$PWD/src/pcre2_ord2utf.c \
$$PWD/src/pcre2_pattern_info.c \
$$PWD/src/pcre2_printint.c \
$$PWD/src/pcre2_serialize.c \
$$PWD/src/pcre2_string_utils.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-qstringview]
int i; // current file's number
int total; // number of files to process
QStringView fileName; // current file's name
QString status = QString("Processing file %1 of %2: %3")
.arg(i).arg(total).arg(fileName);
//! [11]
//! [11-qstringview]
}
//! [12] //! [13]

View File

@ -43,6 +43,7 @@
#endif
#include <qversionnumber.h>
#include <qdebug.h>
#if defined(Q_OS_ANDROID)
#include <private/qjni_p.h>
@ -154,6 +155,8 @@ QT_BEGIN_NAMESPACE
\fn QOperatingSystemVersion QOperatingSystemVersion::current()
Returns a QOperatingSystemVersion indicating the current OS and its version number.
\sa currentType()
*/
#if !defined(Q_OS_DARWIN) && !defined(Q_OS_WIN)
QOperatingSystemVersion QOperatingSystemVersion::current()
@ -299,6 +302,14 @@ int QOperatingSystemVersion::compare(const QOperatingSystemVersion &v1,
\sa name()
*/
/*!
\fn QOperatingSystemVersion::OSType QOperatingSystemVersion::currentType()
Returns the current OS type without constructing a QOperatingSystemVersion instance.
\sa current()
*/
/*!
\fn QString QOperatingSystemVersion::name() const
@ -510,4 +521,16 @@ const QOperatingSystemVersion QOperatingSystemVersion::AndroidNougat_MR1 =
const QOperatingSystemVersion QOperatingSystemVersion::AndroidOreo =
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

View File

@ -92,6 +92,25 @@ public:
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 minorVersion() const { return m_minor; }
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);
#ifndef QT_NO_DEBUG_STREAM
class QDebug;
Q_CORE_EXPORT QDebug operator<<(QDebug debug, const QOperatingSystemVersion &ov);
#endif
QT_END_NAMESPACE
#endif // QOPERATINGSYSTEMVERSION_H

View File

@ -63,25 +63,6 @@ QT_BEGIN_NAMESPACE
OSVERSIONINFOEX qWindowsVersionInfo();
#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
#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.
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:
\code
quint32 value = QRandomGenerator::get32();
quint32 value = QRandomGenerator::generate();
\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
1). There's also a set of convenience functions that facilitate obtaining a
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.
\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):
\code
std::generate(begin, end, []() { return get32(); });
std::generate(begin, end, []() { return generate(); });
\endcode
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,
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}}
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:
\code
return getReal() * sup;
return generateDouble() * sup;
\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);
\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.
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.
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
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.
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.
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
in conjunction with Standard Library algorithms that need 64-bit quantities
instead of 32-bit ones.
@ -823,12 +823,29 @@ static Q_NEVER_INLINE void fill(void *buffer, void *bufferEnd)
\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()()
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:
\code
int value = QRandomGenerator::get32() & std::numeric_limits<int>::max();
int value = QRandomGenerator::generate() & std::numeric_limits<int>::max();
\endcode
\sa get64(), getReal()
\sa get64(), generateDouble()
*/
quint32 QRandomGenerator::get32()
quint32 QRandomGenerator::generate()
{
quint32 ret;
fill(&ret, &ret + 1);
@ -895,12 +912,12 @@ quint32 QRandomGenerator::get32()
you should mask the sign bit off:
\code
qint64 value = QRandomGenerator::get64() & std::numeric_limits<qint64>::max();
qint64 value = QRandomGenerator::generate64() & std::numeric_limits<qint64>::max();
\endcode
\sa get32(), getReal(), QRandomGenerator64
\sa generate(), generateDouble(), QRandomGenerator64
*/
quint64 QRandomGenerator::get64()
quint64 QRandomGenerator::generate64()
{
quint64 ret;
fill(&ret, &ret + 1);

View File

@ -53,29 +53,27 @@ class QRandomGenerator
public:
QRandomGenerator() = default;
static Q_CORE_EXPORT quint32 get32();
static Q_CORE_EXPORT quint64 get64();
static qreal getReal()
// ### REMOVE BEFORE 5.10
static quint32 get32() { return generate(); }
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;
if (digits < std::numeric_limits<quint32>::digits) {
// 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));
}
// use get64() to get enough bits
return double(generate64()) / ((std::numeric_limits<quint64>::max)() + double(1.0));
}
static qreal bounded(qreal sup)
{
return getReal() * sup;
return generateDouble() * sup;
}
static quint32 bounded(quint32 sup)
{
quint64 value = get32();
quint64 value = generate();
value *= sup;
value /= (max)() + quint64(1);
return quint32(value);
@ -112,7 +110,8 @@ public:
template <typename ForwardIterator>
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)
@ -122,7 +121,7 @@ public:
// API like std::random_device
typedef quint32 result_type;
result_type operator()() { return get32(); }
result_type operator()() { return generate(); }
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 max() { return (std::numeric_limits<result_type>::max)(); }
@ -137,9 +136,11 @@ class QRandomGenerator64
public:
QRandomGenerator64() = default;
static quint64 generate() { return QRandomGenerator::generate64(); }
// API like std::random_device
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; }
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)(); }

View File

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

View File

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

View File

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

View File

@ -79,7 +79,7 @@ public:
return r < other.r
|| (r == other.r && (c < other.c
|| (c == other.c && (i < other.i
|| (i == other.i && m < other.m )))));
|| (i == other.i && std::less<const QAbstractItemModel *>()(m, other.m))))));
}
private:
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()
: pool([[NSAutoreleasePool alloc] init])
{
[[[QMacAutoReleasePoolTracker alloc] initWithPool:
reinterpret_cast<NSAutoreleasePool **>(&pool)] autorelease];
}
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
// if we're ever used in a garbage-collected environment, the
// 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
/*
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);
#endif
#ifndef QT_NO_DEBUG_STREAM
QDebug operator<<(QDebug debug, const QMacAutoReleasePool *pool);
#endif
Q_CORE_EXPORT void qt_apple_check_os_version();
QT_END_NAMESPACE

View File

@ -263,7 +263,7 @@ Q_GLOBAL_STATIC(QStartUpFuncList, preRList)
typedef QList<QtCleanUpFunction> QVFuncList;
Q_GLOBAL_STATIC(QVFuncList, postRList)
#ifndef QT_NO_QOBJECT
static QBasicMutex globalPreRoutinesMutex;
static QBasicMutex globalRoutinesMutex;
#endif
/*!
@ -277,13 +277,15 @@ void qAddPreRoutine(QtStartUpFunction p)
QStartUpFuncList *list = preRList();
if (!list)
return;
if (QCoreApplication::instance())
p();
// Due to C++11 parallel dynamic initialization, this can be called
// from multiple threads.
#ifndef QT_NO_THREAD
QMutexLocker locker(&globalPreRoutinesMutex);
QMutexLocker locker(&globalRoutinesMutex);
#endif
if (QCoreApplication::instance())
p();
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();
if (!list)
return;
#ifndef QT_NO_THREAD
QMutexLocker locker(&globalRoutinesMutex);
#endif
list->prepend(p);
}
@ -300,6 +305,9 @@ void qRemovePostRoutine(QtCleanUpFunction p)
QVFuncList *list = postRList();
if (!list)
return;
#ifndef QT_NO_THREAD
QMutexLocker locker(&globalRoutinesMutex);
#endif
list->removeAll(p);
}
@ -308,15 +316,18 @@ static void qt_call_pre_routines()
if (!preRList.exists())
return;
QVFuncList list;
{
#ifndef QT_NO_THREAD
QMutexLocker locker(&globalPreRoutinesMutex);
QMutexLocker locker(&globalRoutinesMutex);
#endif
QVFuncList *list = &(*preRList);
// Unlike qt_call_post_routines, we don't empty the list, because
// Q_COREAPP_STARTUP_FUNCTION is a macro, so the user expects
// the function to be executed every time QCoreApplication is created.
for (int i = 0; i < list->count(); ++i)
list->at(i)();
// Unlike qt_call_post_routines, we don't empty the list, because
// Q_COREAPP_STARTUP_FUNCTION is a macro, so the user expects
// the function to be executed every time QCoreApplication is created.
list = *preRList;
}
for (int i = 0; i < list.count(); ++i)
list.at(i)();
}
void Q_CORE_EXPORT qt_call_post_routines()
@ -324,9 +335,21 @@ void Q_CORE_EXPORT qt_call_post_routines()
if (!postRList.exists())
return;
QVFuncList *list = &(*postRList);
while (!list->isEmpty())
(list->takeFirst())();
forever {
QVFuncList list;
{
// 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)
\threadsafe
\relates 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
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
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
from being called by the QCoreApplication destructor. For example, if that
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
clean up the module's data at the right moment.
\note This function has been thread-safe since Qt 5.10.
\sa qRemovePostRoutine()
*/
/*!
\fn void qRemovePostRoutine(QtCleanUpFunction ptr)
\threadsafe
\relates QCoreApplication
\since 5.3
@ -2909,6 +2936,8 @@ void QCoreApplication::setEventDispatcher(QAbstractEventDispatcher *eventDispatc
must have been previously added to the list by a call to
qAddPostRoutine(), otherwise this function has no effect.
\note This function has been thread-safe since Qt 5.10.
\sa qAddPostRoutine()
*/

View File

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

View File

@ -3173,6 +3173,9 @@ static bool canConvertMetaObject(int fromId, int toId, QObject *fromObject)
*/
bool QVariant::canConvert(int targetTypeId) const
{
if (d.type == targetTypeId)
return true;
if ((targetTypeId == QMetaType::QModelIndex && d.type == QMetaType::QPersistentModelIndex)
|| (targetTypeId == QMetaType::QPersistentModelIndex && d.type == QMetaType::QModelIndex))
return true;
@ -3639,29 +3642,36 @@ static int numericCompare(const QVariant::Private *d1, const QVariant::Private *
*/
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)
if (qIsNumericType(d.type) && qIsNumericType(v.d.type))
return numericCompare(&d, &v.d) == 0;
if (d.type == v.d.type)
return cmp_helper(d, v.d);
QVariant v1 = *this;
QVariant v2 = v;
if (d.type != v2.d.type) {
if (v2.canConvert(v1.d.type)) {
if (!v2.convert(v1.d.type))
return false;
} else {
// try the opposite conversion, it might work
qSwap(v1, v2);
if (!v2.convert(v1.d.type))
return false;
}
if (v2.canConvert(v1.d.type)) {
if (!v2.convert(v1.d.type))
return false;
} else {
// try the opposite conversion, it might work
qSwap(v1, v2);
if (!v2.convert(v1.d.type))
return false;
}
if (v1.d.type >= QMetaType::User) {
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);
return cmp_helper(v1.d, v2.d);
}
/*!
@ -3677,51 +3687,53 @@ int QVariant::compare(const QVariant &v) const
if (cmp(v))
return 0;
QVariant v1 = *this;
QVariant v2 = v;
const QVariant *v1 = this;
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 (v2.canConvert(v1.d.type)) {
QVariant temp = v2;
if (temp.convert(v1.d.type))
v2 = temp;
if (v2->canConvert(v1->d.type)) {
converted2 = *v2;
if (converted2.convert(v1->d.type))
v2 = &converted2;
}
if (v1.d.type != v2.d.type && v1.canConvert(v2.d.type)) {
QVariant temp = v1;
if (temp.convert(v2.d.type))
v1 = temp;
if (v1->d.type != v2->d.type && v1->canConvert(v2->d.type)) {
converted1 = *v1;
if (converted1.convert(v2->d.type))
v1 = &converted1;
}
if (v1.d.type != v2.d.type) {
if (v1->d.type != v2->d.type) {
// 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) {
// 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;
}
// did we end up with two numerics? If so, restart
if (qIsNumericType(v1.d.type) && qIsNumericType(v2.d.type))
return v1.compare(v2);
if (qIsNumericType(v1->d.type) && qIsNumericType(v2->d.type))
return v1->compare(*v2);
}
if (v1.d.type >= QMetaType::User) {
if (v1->d.type >= QMetaType::User) {
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;
}
switch (v1.d.type) {
switch (v1->d.type) {
case QVariant::Date:
return v1.toDate() < v2.toDate() ? -1 : 1;
return v1->toDate() < v2->toDate() ? -1 : 1;
case QVariant::Time:
return v1.toTime() < v2.toTime() ? -1 : 1;
return v1->toTime() < v2->toTime() ? -1 : 1;
case QVariant::DateTime:
return v1.toDateTime() < v2.toDateTime() ? -1 : 1;
return v1->toDateTime() < v2->toDateTime() ? -1 : 1;
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) {
// cmp(v) returned false, so we should try to agree with it.
return (d.type < v.d.type) ? -1 : 1;

View File

@ -925,6 +925,30 @@ bool QThread::isInterruptionRequested() const
\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
\since 5.5

View File

@ -119,6 +119,12 @@ public:
bool event(QEvent *event) override;
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_VARIADIC_CREATE
template <typename Function, typename... Args>
@ -128,6 +134,7 @@ public:
static QThread *create(Function &&f);
#endif
#endif
#endif
public Q_SLOTS:
void start(Priority = InheritPriority);
@ -158,98 +165,81 @@ protected:
private:
Q_DECLARE_PRIVATE(QThread)
#ifdef QTHREAD_HAS_CREATE
static QThread *createThreadImpl(std::future<void> &&future);
#endif
friend class QCoreApplication;
friend class QThreadData;
};
#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
// C++17: std::thread's constructor complying call
template <typename Function, typename... 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>
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

View File

@ -606,17 +606,19 @@ void QThreadPool::reserveThread()
++d->reservedThreads;
}
/*! \property QThreadPool::stacksize
/*! \property QThreadPool::stackSize
This property contains the stack size for the thread pool worker
threads.
The value of the property is uses when the thread pool creates
new threads only. Changing it has no effect for already created
The value of the property is only used when the thread pool creates
new threads. Changing it has no effect for already created
or running threads.
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)
{

View File

@ -296,7 +296,7 @@ static uint qt_create_qhash_seed()
return seed;
}
seed = QRandomGenerator::get32();
seed = QRandomGenerator::generate();
#endif // QT_BOOTSTRAPPED
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
on, whereas DataSizeSIFormat uses and DataSizeTraditionalFormat abuses the
older SI quantifiers k, M, etc.
\sa refresh(), caching()
*/
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>
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>
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>
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 <stdio.h>
#include <stdarg.h>
#include <wchar.h>
#include "qchar.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, 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__)
namespace {
template <uint MaxCount> struct UnrollTailLoop

View File

@ -53,6 +53,8 @@ class QLatin1String;
class QStringView;
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, 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;

View File

@ -143,20 +143,22 @@ private:
{
return qssize_t(N - 1);
}
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;
while (*str++)
++result;
return result;
#if defined(Q_CC_GNU) && !defined(Q_CC_CLANG) && !defined(Q_CC_INTEL)
if (__builtin_constant_p(*str)) {
qssize_t result = 0;
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;
while (!str++->isNull())
++result;
return result;
return qustrlen(reinterpret_cast<const ushort *>(str));
}
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,
using the specified \a colorTable.
Conversion from 32 bit to 8 bit indexed is a slow operation and
will use a straightforward nearest color approach, with no
Conversion from RGB formats to indexed formats is a slow operation
and will use a straightforward nearest color approach, with no
dithering.
*/
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)
return *this;
if (format <= QImage::Format_Indexed8 && depth() == 32) {
return convertWithPalette(*this, format, colorTable);
}
const Image_Converter *converterPtr = &qimage_converter_map[d->format][format];
Image_Converter converter = *converterPtr;
if (!converter)
if (format == QImage::Format_Invalid)
return QImage();
if (format <= QImage::Format_Indexed8)
return convertWithPalette(convertToFormat(QImage::Format_ARGB32, flags), format, colorTable);
QImage image(d->width, d->height, format);
QIMAGE_SANITYCHECK_MEMORY(image);
image.d->offset = offset();
copyMetadata(image.d, d);
converter(image.d, d, flags);
return image;
return convertToFormat(format, flags);
}
/*!

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