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:
commit
aadfe7d634
@ -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)
|
||||
|
||||
|
@ -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
288
dist/changes-5.6.3
vendored
Normal 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.
|
@ -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()));
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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();
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -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();
|
||||
|
@ -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;
|
||||
};
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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 |
@ -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) {
|
||||
|
@ -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:
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -42,7 +42,7 @@
|
||||
<widget class="QListWidget" name="certificateInfoView">
|
||||
<property name="font">
|
||||
<font>
|
||||
<pointsize>8</pointsize>
|
||||
<pointsize>10</pointsize>
|
||||
</font>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -1,3 +1,5 @@
|
||||
requires(qtHaveModule(network))
|
||||
|
||||
HEADERS += certificateinfo.h \
|
||||
sslclient.h
|
||||
SOURCES += certificateinfo.cpp \
|
||||
|
@ -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("<not connected>"));
|
||||
|
||||
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("<not connected>"));
|
||||
|
||||
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)
|
||||
|
@ -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
|
||||
|
@ -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><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">
|
||||
<html><head><meta name="qrichtext" content="1" /><style type="text/css">
|
||||
p, li { white-space: pre-wrap; }
|
||||
</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;">
|
||||
<p style="-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;"></p></body></html></string>
|
||||
</style></head><body style=" font-family:'.SF NS Text'; font-size:13pt; font-weight:400; font-style:normal;">
|
||||
<p style="-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;"><br /></p></body></html></string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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();
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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]
|
||||
|
@ -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();
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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]
|
||||
|
@ -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]
|
||||
|
||||
|
@ -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();
|
||||
|
@ -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]
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -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()
|
||||
|
@ -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();
|
||||
|
@ -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;
|
||||
};
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -110,7 +110,8 @@ int main(int argc, char *argv[])
|
||||
{
|
||||
QApplication app(argc, argv);
|
||||
if (!createConnection())
|
||||
return 1;
|
||||
return EXIT_FAILURE;
|
||||
|
||||
createRelationalTables();
|
||||
|
||||
QSqlRelationalTableModel model;
|
||||
|
@ -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());
|
||||
|
@ -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))
|
||||
|
@ -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;
|
||||
|
||||
|
@ -62,7 +62,7 @@ class ConnectionWidget: public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
ConnectionWidget(QWidget *parent = 0);
|
||||
ConnectionWidget(QWidget *parent = nullptr);
|
||||
virtual ~ConnectionWidget();
|
||||
|
||||
QSqlDatabase currentDatabase() const;
|
||||
|
@ -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();
|
||||
|
@ -60,7 +60,7 @@ class QSqlConnectionDialog: public QDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
QSqlConnectionDialog(QWidget *parent = 0);
|
||||
QSqlConnectionDialog(QWidget *parent = nullptr);
|
||||
~QSqlConnectionDialog();
|
||||
|
||||
QString driverName() const;
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
||||
|
@ -14,4 +14,3 @@ SUBDIRS = classwizard \
|
||||
!qtConfig(wizard) {
|
||||
SUBDIRS -= trivialwizard licensewizard classwizard
|
||||
}
|
||||
wince: SUBDIRS += sipdialog
|
||||
|
@ -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);
|
||||
|
@ -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:
|
||||
|
@ -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;
|
||||
|
@ -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): \
|
||||
|
@ -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-
|
||||
|
@ -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
|
||||
|
@ -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): \
|
||||
|
@ -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 {
|
||||
|
@ -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 \
|
||||
|
19
mkspecs/features/unix/ccache.prf
Normal file
19
mkspecs/features/unix/ccache.prf
Normal 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)
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
3
src/3rdparty/pcre2/pcre2.pro
vendored
3
src/3rdparty/pcre2/pcre2.pro
vendored
@ -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 \
|
||||
|
831
src/3rdparty/pcre2/src/pcre2_printint.c
vendored
831
src/3rdparty/pcre2/src/pcre2_printint.c
vendored
@ -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 */
|
@ -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]
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
@ -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)(); }
|
||||
|
@ -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>
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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,
|
||||
|
@ -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
|
||||
|
@ -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()
|
||||
*/
|
||||
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -296,7 +296,7 @@ static uint qt_create_qhash_seed()
|
||||
return seed;
|
||||
}
|
||||
|
||||
seed = QRandomGenerator::get32();
|
||||
seed = QRandomGenerator::generate();
|
||||
#endif // QT_BOOTSTRAPPED
|
||||
|
||||
return seed;
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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());
|
||||
}
|
||||
|
||||
//
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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>
|
||||
|
@ -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
Loading…
x
Reference in New Issue
Block a user