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]
|
-ltcg ................ Use Link Time Code Generation [no]
|
||||||
-use-gold-linker ..... Use the GNU gold linker [auto]
|
-use-gold-linker ..... Use the GNU gold linker [auto]
|
||||||
-incredibuild-xge .... Use the IncrediBuild XGE [no] (Windows only)
|
-incredibuild-xge .... Use the IncrediBuild XGE [no] (Windows only)
|
||||||
|
-ccache .............. Use the ccache compiler cache [no] (Unix only)
|
||||||
-make-tool <tool> .... Use <tool> to build qmake [nmake] (Windows only)
|
-make-tool <tool> .... Use <tool> to build qmake [nmake] (Windows only)
|
||||||
-mp .................. Use multiple processors for compilation (MSVC only)
|
-mp .................. Use multiple processors for compilation (MSVC only)
|
||||||
|
|
||||||
|
@ -61,6 +61,7 @@
|
|||||||
"avx2": "boolean",
|
"avx2": "boolean",
|
||||||
"avx512": { "type": "boolean", "name": "avx512f" },
|
"avx512": { "type": "boolean", "name": "avx512f" },
|
||||||
"c++std": "cxxstd",
|
"c++std": "cxxstd",
|
||||||
|
"ccache": { "type": "boolean", "name": "ccache" },
|
||||||
"commercial": "void",
|
"commercial": "void",
|
||||||
"compile-examples": { "type": "boolean", "name": "compile_examples" },
|
"compile-examples": { "type": "boolean", "name": "compile_examples" },
|
||||||
"confirm-license": "void",
|
"confirm-license": "void",
|
||||||
@ -635,6 +636,11 @@
|
|||||||
"label": "IncrediBuild",
|
"label": "IncrediBuild",
|
||||||
"type": "files",
|
"type": "files",
|
||||||
"files": [ "BuildConsole.exe", "xgConsole.exe" ]
|
"files": [ "BuildConsole.exe", "xgConsole.exe" ]
|
||||||
|
},
|
||||||
|
"ccache": {
|
||||||
|
"label": "ccache",
|
||||||
|
"type": "files",
|
||||||
|
"files": [ "ccache" ]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -1246,6 +1252,12 @@
|
|||||||
"condition": "tests.incredibuild_xge",
|
"condition": "tests.incredibuild_xge",
|
||||||
"output": [ "publicConfig" ]
|
"output": [ "publicConfig" ]
|
||||||
},
|
},
|
||||||
|
"ccache": {
|
||||||
|
"label": "Using ccache",
|
||||||
|
"autoDetect": false,
|
||||||
|
"condition": "config.unix && tests.ccache",
|
||||||
|
"output": [ "privateConfig" ]
|
||||||
|
},
|
||||||
"msvc_mp": {
|
"msvc_mp": {
|
||||||
"label": "Use multiple processors when compiling with MSVC",
|
"label": "Use multiple processors when compiling with MSVC",
|
||||||
"emitIf": "config.msvc",
|
"emitIf": "config.msvc",
|
||||||
@ -1353,6 +1365,11 @@ Configure with '-qreal float' to create a build that is binary-compatible with 5
|
|||||||
"type": "firstAvailableFeature",
|
"type": "firstAvailableFeature",
|
||||||
"args": "c++1z c++14 c++11"
|
"args": "c++1z c++14 c++11"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"type": "feature",
|
||||||
|
"args": "ccache",
|
||||||
|
"condition": "config.unix"
|
||||||
|
},
|
||||||
"use_gold_linker",
|
"use_gold_linker",
|
||||||
{
|
{
|
||||||
"type": "feature",
|
"type": "feature",
|
||||||
|
288
dist/changes-5.6.3
vendored
Normal file
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"
|
#include "client.h"
|
||||||
|
|
||||||
Client::Client(QWidget *parent)
|
Client::Client(QWidget *parent)
|
||||||
: QDialog(parent)
|
: QDialog(parent),
|
||||||
|
hostLineEdit(new QLineEdit("fortune")),
|
||||||
|
getFortuneButton(new QPushButton(tr("Get Fortune"))),
|
||||||
|
statusLabel(new QLabel(tr("This examples requires that you run the "
|
||||||
|
"Local Fortune Server example as well."))),
|
||||||
|
socket(new QLocalSocket(this))
|
||||||
{
|
{
|
||||||
hostLabel = new QLabel(tr("&Server name:"));
|
setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint);
|
||||||
hostLineEdit = new QLineEdit("fortune");
|
QLabel *hostLabel = new QLabel(tr("&Server name:"));
|
||||||
|
|
||||||
hostLabel->setBuddy(hostLineEdit);
|
hostLabel->setBuddy(hostLineEdit);
|
||||||
|
|
||||||
statusLabel = new QLabel(tr("This examples requires that you run the "
|
|
||||||
"Fortune Server example as well."));
|
|
||||||
statusLabel->setWordWrap(true);
|
statusLabel->setWordWrap(true);
|
||||||
|
|
||||||
getFortuneButton = new QPushButton(tr("Get Fortune"));
|
|
||||||
getFortuneButton->setDefault(true);
|
getFortuneButton->setDefault(true);
|
||||||
|
QPushButton *quitButton = new QPushButton(tr("Quit"));
|
||||||
|
|
||||||
quitButton = new QPushButton(tr("Quit"));
|
QDialogButtonBox *buttonBox = new QDialogButtonBox;
|
||||||
|
|
||||||
buttonBox = new QDialogButtonBox;
|
|
||||||
buttonBox->addButton(getFortuneButton, QDialogButtonBox::ActionRole);
|
buttonBox->addButton(getFortuneButton, QDialogButtonBox::ActionRole);
|
||||||
buttonBox->addButton(quitButton, QDialogButtonBox::RejectRole);
|
buttonBox->addButton(quitButton, QDialogButtonBox::RejectRole);
|
||||||
|
|
||||||
socket = new QLocalSocket(this);
|
in.setDevice(socket);
|
||||||
|
in.setVersion(QDataStream::Qt_5_10);
|
||||||
|
|
||||||
connect(hostLineEdit, SIGNAL(textChanged(QString)),
|
connect(hostLineEdit, &QLineEdit::textChanged,
|
||||||
this, SLOT(enableGetFortuneButton()));
|
this, &Client::enableGetFortuneButton);
|
||||||
connect(getFortuneButton, SIGNAL(clicked()),
|
connect(getFortuneButton, &QPushButton::clicked,
|
||||||
this, SLOT(requestNewFortune()));
|
this, &Client::requestNewFortune);
|
||||||
connect(quitButton, SIGNAL(clicked()), this, SLOT(close()));
|
connect(quitButton, &QPushButton::clicked, this, &Client::close);
|
||||||
connect(socket, SIGNAL(readyRead()), this, SLOT(readFortune()));
|
connect(socket, &QLocalSocket::readyRead, this, &Client::readFortune);
|
||||||
connect(socket, SIGNAL(error(QLocalSocket::LocalSocketError)),
|
connect(socket, QOverload<QLocalSocket::LocalSocketError>::of(&QLocalSocket::error),
|
||||||
this, SLOT(displayError(QLocalSocket::LocalSocketError)));
|
this, &Client::displayError);
|
||||||
|
|
||||||
QGridLayout *mainLayout = new QGridLayout;
|
QGridLayout *mainLayout = new QGridLayout(this);
|
||||||
mainLayout->addWidget(hostLabel, 0, 0);
|
mainLayout->addWidget(hostLabel, 0, 0);
|
||||||
mainLayout->addWidget(hostLineEdit, 0, 1);
|
mainLayout->addWidget(hostLineEdit, 0, 1);
|
||||||
mainLayout->addWidget(statusLabel, 2, 0, 1, 2);
|
mainLayout->addWidget(statusLabel, 2, 0, 1, 2);
|
||||||
mainLayout->addWidget(buttonBox, 3, 0, 1, 2);
|
mainLayout->addWidget(buttonBox, 3, 0, 1, 2);
|
||||||
setLayout(mainLayout);
|
|
||||||
|
|
||||||
setWindowTitle(tr("Fortune Client"));
|
setWindowTitle(QGuiApplication::applicationDisplayName());
|
||||||
hostLineEdit->setFocus();
|
hostLineEdit->setFocus();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -106,11 +106,9 @@ void Client::requestNewFortune()
|
|||||||
|
|
||||||
void Client::readFortune()
|
void Client::readFortune()
|
||||||
{
|
{
|
||||||
QDataStream in(socket);
|
|
||||||
in.setVersion(QDataStream::Qt_4_0);
|
|
||||||
|
|
||||||
if (blockSize == 0) {
|
if (blockSize == 0) {
|
||||||
// Relies on the fact that QDataStream format streams a quint32 into sizeof(quint32) bytes
|
// Relies on the fact that QDataStream serializes a quint32 into
|
||||||
|
// sizeof(quint32) bytes
|
||||||
if (socket->bytesAvailable() < (int)sizeof(quint32))
|
if (socket->bytesAvailable() < (int)sizeof(quint32))
|
||||||
return;
|
return;
|
||||||
in >> blockSize;
|
in >> blockSize;
|
||||||
@ -123,7 +121,7 @@ void Client::readFortune()
|
|||||||
in >> nextFortune;
|
in >> nextFortune;
|
||||||
|
|
||||||
if (nextFortune == currentFortune) {
|
if (nextFortune == currentFortune) {
|
||||||
QTimer::singleShot(0, this, SLOT(requestNewFortune()));
|
QTimer::singleShot(0, this, &Client::requestNewFortune);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -136,21 +134,22 @@ void Client::displayError(QLocalSocket::LocalSocketError socketError)
|
|||||||
{
|
{
|
||||||
switch (socketError) {
|
switch (socketError) {
|
||||||
case QLocalSocket::ServerNotFoundError:
|
case QLocalSocket::ServerNotFoundError:
|
||||||
QMessageBox::information(this, tr("Fortune Client"),
|
QMessageBox::information(this, tr("Local Fortune Client"),
|
||||||
tr("The host was not found. Please check the "
|
tr("The host was not found. Please make sure "
|
||||||
"host name and port settings."));
|
"that the server is running and that the "
|
||||||
|
"server name is correct."));
|
||||||
break;
|
break;
|
||||||
case QLocalSocket::ConnectionRefusedError:
|
case QLocalSocket::ConnectionRefusedError:
|
||||||
QMessageBox::information(this, tr("Fortune Client"),
|
QMessageBox::information(this, tr("Local Fortune Client"),
|
||||||
tr("The connection was refused by the peer. "
|
tr("The connection was refused by the peer. "
|
||||||
"Make sure the fortune server is running, "
|
"Make sure the fortune server is running, "
|
||||||
"and check that the host name and port "
|
"and check that the server name "
|
||||||
"settings are correct."));
|
"is correct."));
|
||||||
break;
|
break;
|
||||||
case QLocalSocket::PeerClosedError:
|
case QLocalSocket::PeerClosedError:
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
QMessageBox::information(this, tr("Fortune Client"),
|
QMessageBox::information(this, tr("Local Fortune Client"),
|
||||||
tr("The following error occurred: %1.")
|
tr("The following error occurred: %1.")
|
||||||
.arg(socket->errorString()));
|
.arg(socket->errorString()));
|
||||||
}
|
}
|
||||||
|
@ -52,11 +52,11 @@
|
|||||||
#define CLIENT_H
|
#define CLIENT_H
|
||||||
|
|
||||||
#include <QDialog>
|
#include <QDialog>
|
||||||
|
#include <QDataStream>
|
||||||
|
|
||||||
#include <qlocalsocket.h>
|
#include <qlocalsocket.h>
|
||||||
|
|
||||||
QT_BEGIN_NAMESPACE
|
QT_BEGIN_NAMESPACE
|
||||||
class QDialogButtonBox;
|
|
||||||
class QLabel;
|
class QLabel;
|
||||||
class QLineEdit;
|
class QLineEdit;
|
||||||
class QPushButton;
|
class QPushButton;
|
||||||
@ -68,7 +68,7 @@ class Client : public QDialog
|
|||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Client(QWidget *parent = 0);
|
explicit Client(QWidget *parent = nullptr);
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
void requestNewFortune();
|
void requestNewFortune();
|
||||||
@ -77,16 +77,15 @@ private slots:
|
|||||||
void enableGetFortuneButton();
|
void enableGetFortuneButton();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QLabel *hostLabel;
|
|
||||||
QLineEdit *hostLineEdit;
|
QLineEdit *hostLineEdit;
|
||||||
QLabel *statusLabel;
|
|
||||||
QPushButton *getFortuneButton;
|
QPushButton *getFortuneButton;
|
||||||
QPushButton *quitButton;
|
QLabel *statusLabel;
|
||||||
QDialogButtonBox *buttonBox;
|
|
||||||
|
|
||||||
QLocalSocket *socket;
|
QLocalSocket *socket;
|
||||||
QString currentFortune;
|
QDataStream in;
|
||||||
quint32 blockSize;
|
quint32 blockSize;
|
||||||
|
|
||||||
|
QString currentFortune;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -55,6 +55,7 @@
|
|||||||
int main(int argc, char *argv[])
|
int main(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
QApplication app(argc, argv);
|
QApplication app(argc, argv);
|
||||||
|
QGuiApplication::setApplicationDisplayName(Client::tr("Local Fortune Client"));
|
||||||
Client client;
|
Client client;
|
||||||
client.show();
|
client.show();
|
||||||
return app.exec();
|
return app.exec();
|
||||||
|
@ -58,8 +58,8 @@
|
|||||||
int main(int argc, char *argv[])
|
int main(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
QApplication app(argc, argv);
|
QApplication app(argc, argv);
|
||||||
|
QGuiApplication::setApplicationDisplayName(Server::tr("Local Fortune Server"));
|
||||||
Server server;
|
Server server;
|
||||||
server.show();
|
server.show();
|
||||||
qsrand(QTime(0,0,0).secsTo(QTime::currentTime()));
|
|
||||||
return app.exec();
|
return app.exec();
|
||||||
}
|
}
|
||||||
|
@ -60,22 +60,21 @@
|
|||||||
Server::Server(QWidget *parent)
|
Server::Server(QWidget *parent)
|
||||||
: QDialog(parent)
|
: QDialog(parent)
|
||||||
{
|
{
|
||||||
statusLabel = new QLabel;
|
setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint);
|
||||||
statusLabel->setWordWrap(true);
|
|
||||||
quitButton = new QPushButton(tr("Quit"));
|
|
||||||
quitButton->setAutoDefault(false);
|
|
||||||
|
|
||||||
server = new QLocalServer(this);
|
server = new QLocalServer(this);
|
||||||
if (!server->listen("fortune")) {
|
if (!server->listen("fortune")) {
|
||||||
QMessageBox::critical(this, tr("Fortune Server"),
|
QMessageBox::critical(this, tr("Local Fortune Server"),
|
||||||
tr("Unable to start the server: %1.")
|
tr("Unable to start the server: %1.")
|
||||||
.arg(server->errorString()));
|
.arg(server->errorString()));
|
||||||
close();
|
close();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QLabel *statusLabel = new QLabel;
|
||||||
|
statusLabel->setWordWrap(true);
|
||||||
statusLabel->setText(tr("The server is running.\n"
|
statusLabel->setText(tr("The server is running.\n"
|
||||||
"Run the Fortune Client example now."));
|
"Run the Local Fortune Client example now."));
|
||||||
|
|
||||||
fortunes << tr("You've been leading a dog's life. Stay off the furniture.")
|
fortunes << tr("You've been leading a dog's life. Stay off the furniture.")
|
||||||
<< tr("You've got to think about tomorrow.")
|
<< tr("You've got to think about tomorrow.")
|
||||||
@ -85,35 +84,36 @@ Server::Server(QWidget *parent)
|
|||||||
<< tr("You cannot kill time without injuring eternity.")
|
<< tr("You cannot kill time without injuring eternity.")
|
||||||
<< tr("Computers are not intelligent. They only think they are.");
|
<< tr("Computers are not intelligent. They only think they are.");
|
||||||
|
|
||||||
connect(quitButton, SIGNAL(clicked()), this, SLOT(close()));
|
QPushButton *quitButton = new QPushButton(tr("Quit"));
|
||||||
connect(server, SIGNAL(newConnection()), this, SLOT(sendFortune()));
|
quitButton->setAutoDefault(false);
|
||||||
|
connect(quitButton, &QPushButton::clicked, this, &Server::close);
|
||||||
|
connect(server, &QLocalServer::newConnection, this, &Server::sendFortune);
|
||||||
|
|
||||||
QHBoxLayout *buttonLayout = new QHBoxLayout;
|
QHBoxLayout *buttonLayout = new QHBoxLayout;
|
||||||
buttonLayout->addStretch(1);
|
buttonLayout->addStretch(1);
|
||||||
buttonLayout->addWidget(quitButton);
|
buttonLayout->addWidget(quitButton);
|
||||||
buttonLayout->addStretch(1);
|
buttonLayout->addStretch(1);
|
||||||
|
|
||||||
QVBoxLayout *mainLayout = new QVBoxLayout;
|
QVBoxLayout *mainLayout = new QVBoxLayout(this);
|
||||||
mainLayout->addWidget(statusLabel);
|
mainLayout->addWidget(statusLabel);
|
||||||
mainLayout->addLayout(buttonLayout);
|
mainLayout->addLayout(buttonLayout);
|
||||||
setLayout(mainLayout);
|
|
||||||
|
|
||||||
setWindowTitle(tr("Fortune Server"));
|
setWindowTitle(QGuiApplication::applicationDisplayName());
|
||||||
}
|
}
|
||||||
|
|
||||||
void Server::sendFortune()
|
void Server::sendFortune()
|
||||||
{
|
{
|
||||||
QByteArray block;
|
QByteArray block;
|
||||||
QDataStream out(&block, QIODevice::WriteOnly);
|
QDataStream out(&block, QIODevice::WriteOnly);
|
||||||
out.setVersion(QDataStream::Qt_4_0);
|
out.setVersion(QDataStream::Qt_5_10);
|
||||||
out << (quint32)0;
|
const int fortuneIndex = QRandomGenerator::bounded(0, fortunes.size());
|
||||||
out << fortunes.at(qrand() % fortunes.size());
|
const QString &message = fortunes.at(fortuneIndex);
|
||||||
out.device()->seek(0);
|
out << quint32(message.size());
|
||||||
out << (quint32)(block.size() - sizeof(quint32));
|
out << message;
|
||||||
|
|
||||||
QLocalSocket *clientConnection = server->nextPendingConnection();
|
QLocalSocket *clientConnection = server->nextPendingConnection();
|
||||||
connect(clientConnection, SIGNAL(disconnected()),
|
connect(clientConnection, &QLocalSocket::disconnected,
|
||||||
clientConnection, SLOT(deleteLater()));
|
clientConnection, &QLocalSocket::deleteLater);
|
||||||
|
|
||||||
clientConnection->write(block);
|
clientConnection->write(block);
|
||||||
clientConnection->flush();
|
clientConnection->flush();
|
||||||
|
@ -64,14 +64,12 @@ class Server : public QDialog
|
|||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Server(QWidget *parent = 0);
|
explicit Server(QWidget *parent = nullptr);
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
void sendFortune();
|
void sendFortune();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QLabel *statusLabel;
|
|
||||||
QPushButton *quitButton;
|
|
||||||
QLocalServer *server;
|
QLocalServer *server;
|
||||||
QStringList fortunes;
|
QStringList fortunes;
|
||||||
};
|
};
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
**
|
**
|
||||||
** Copyright (C) 2016 The Qt Company Ltd.
|
** Copyright (C) 2017 The Qt Company Ltd.
|
||||||
** Contact: https://www.qt.io/licensing/
|
** Contact: https://www.qt.io/licensing/
|
||||||
**
|
**
|
||||||
** This file is part of the examples of the Qt Toolkit.
|
** This file is part of the examples of the Qt Toolkit.
|
||||||
@ -50,6 +50,7 @@
|
|||||||
|
|
||||||
#include <QtWidgets>
|
#include <QtWidgets>
|
||||||
#include <QtNetwork>
|
#include <QtNetwork>
|
||||||
|
#include <QtCore>
|
||||||
|
|
||||||
#include "sender.h"
|
#include "sender.h"
|
||||||
|
|
||||||
@ -60,23 +61,21 @@ Sender::Sender(QWidget *parent)
|
|||||||
statusLabel->setWordWrap(true);
|
statusLabel->setWordWrap(true);
|
||||||
|
|
||||||
startButton = new QPushButton(tr("&Start"));
|
startButton = new QPushButton(tr("&Start"));
|
||||||
quitButton = new QPushButton(tr("&Quit"));
|
auto quitButton = new QPushButton(tr("&Quit"));
|
||||||
|
|
||||||
buttonBox = new QDialogButtonBox;
|
auto buttonBox = new QDialogButtonBox;
|
||||||
buttonBox->addButton(startButton, QDialogButtonBox::ActionRole);
|
buttonBox->addButton(startButton, QDialogButtonBox::ActionRole);
|
||||||
buttonBox->addButton(quitButton, QDialogButtonBox::RejectRole);
|
buttonBox->addButton(quitButton, QDialogButtonBox::RejectRole);
|
||||||
|
|
||||||
timer = new QTimer(this);
|
|
||||||
//! [0]
|
//! [0]
|
||||||
udpSocket = new QUdpSocket(this);
|
udpSocket = new QUdpSocket(this);
|
||||||
//! [0]
|
//! [0]
|
||||||
messageNo = 1;
|
|
||||||
|
|
||||||
connect(startButton, SIGNAL(clicked()), this, SLOT(startBroadcasting()));
|
connect(startButton, &QPushButton::clicked, this, &Sender::startBroadcasting);
|
||||||
connect(quitButton, SIGNAL(clicked()), this, SLOT(close()));
|
connect(quitButton, &QPushButton::clicked, this, &Sender::close);
|
||||||
connect(timer, SIGNAL(timeout()), this, SLOT(broadcastDatagram()));
|
connect(&timer, &QTimer::timeout, this, &Sender::broadcastDatagram);
|
||||||
|
|
||||||
QVBoxLayout *mainLayout = new QVBoxLayout;
|
auto mainLayout = new QVBoxLayout;
|
||||||
mainLayout->addWidget(statusLabel);
|
mainLayout->addWidget(statusLabel);
|
||||||
mainLayout->addWidget(buttonBox);
|
mainLayout->addWidget(buttonBox);
|
||||||
setLayout(mainLayout);
|
setLayout(mainLayout);
|
||||||
@ -87,7 +86,7 @@ Sender::Sender(QWidget *parent)
|
|||||||
void Sender::startBroadcasting()
|
void Sender::startBroadcasting()
|
||||||
{
|
{
|
||||||
startButton->setEnabled(false);
|
startButton->setEnabled(false);
|
||||||
timer->start(1000);
|
timer.start(1000);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Sender::broadcastDatagram()
|
void Sender::broadcastDatagram()
|
||||||
@ -95,8 +94,7 @@ void Sender::broadcastDatagram()
|
|||||||
statusLabel->setText(tr("Now broadcasting datagram %1").arg(messageNo));
|
statusLabel->setText(tr("Now broadcasting datagram %1").arg(messageNo));
|
||||||
//! [1]
|
//! [1]
|
||||||
QByteArray datagram = "Broadcast message " + QByteArray::number(messageNo);
|
QByteArray datagram = "Broadcast message " + QByteArray::number(messageNo);
|
||||||
udpSocket->writeDatagram(datagram.data(), datagram.size(),
|
udpSocket->writeDatagram(datagram, QHostAddress::Broadcast, 45454);
|
||||||
QHostAddress::Broadcast, 45454);
|
|
||||||
//! [1]
|
//! [1]
|
||||||
++messageNo;
|
++messageNo;
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
**
|
**
|
||||||
** Copyright (C) 2016 The Qt Company Ltd.
|
** Copyright (C) 2017 The Qt Company Ltd.
|
||||||
** Contact: https://www.qt.io/licensing/
|
** Contact: https://www.qt.io/licensing/
|
||||||
**
|
**
|
||||||
** This file is part of the examples of the Qt Toolkit.
|
** This file is part of the examples of the Qt Toolkit.
|
||||||
@ -52,12 +52,11 @@
|
|||||||
#define SENDER_H
|
#define SENDER_H
|
||||||
|
|
||||||
#include <QWidget>
|
#include <QWidget>
|
||||||
|
#include <QTimer>
|
||||||
|
|
||||||
QT_BEGIN_NAMESPACE
|
QT_BEGIN_NAMESPACE
|
||||||
class QDialogButtonBox;
|
|
||||||
class QLabel;
|
class QLabel;
|
||||||
class QPushButton;
|
class QPushButton;
|
||||||
class QTimer;
|
|
||||||
class QUdpSocket;
|
class QUdpSocket;
|
||||||
QT_END_NAMESPACE
|
QT_END_NAMESPACE
|
||||||
|
|
||||||
@ -66,20 +65,18 @@ class Sender : public QWidget
|
|||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Sender(QWidget *parent = 0);
|
explicit Sender(QWidget *parent = nullptr);
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
void startBroadcasting();
|
void startBroadcasting();
|
||||||
void broadcastDatagram();
|
void broadcastDatagram();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QLabel *statusLabel;
|
QLabel *statusLabel = nullptr;
|
||||||
QPushButton *startButton;
|
QPushButton *startButton = nullptr;
|
||||||
QPushButton *quitButton;
|
QUdpSocket *udpSocket = nullptr;
|
||||||
QDialogButtonBox *buttonBox;
|
QTimer timer;
|
||||||
QUdpSocket *udpSocket;
|
int messageNo = 1;
|
||||||
QTimer *timer;
|
|
||||||
int messageNo;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
Binary file not shown.
Before Width: | Height: | Size: 6.8 KiB After Width: | Height: | Size: 7.9 KiB |
@ -55,12 +55,12 @@
|
|||||||
#include "httpwindow.h"
|
#include "httpwindow.h"
|
||||||
#include "ui_authenticationdialog.h"
|
#include "ui_authenticationdialog.h"
|
||||||
|
|
||||||
#ifndef QT_NO_SSL
|
#if QT_CONFIG(ssl)
|
||||||
static const char defaultUrl[] = "https://www.qt.io/";
|
const char defaultUrl[] = "https://www.qt.io/";
|
||||||
#else
|
#else
|
||||||
static const char defaultUrl[] = "http://www.qt.io/";
|
const char defaultUrl[] = "http://www.qt.io/";
|
||||||
#endif
|
#endif
|
||||||
static const char defaultFileName[] = "index.html";
|
const char defaultFileName[] = "index.html";
|
||||||
|
|
||||||
ProgressDialog::ProgressDialog(const QUrl &url, QWidget *parent)
|
ProgressDialog::ProgressDialog(const QUrl &url, QWidget *parent)
|
||||||
: QProgressDialog(parent)
|
: QProgressDialog(parent)
|
||||||
@ -71,6 +71,7 @@ ProgressDialog::ProgressDialog(const QUrl &url, QWidget *parent)
|
|||||||
setMinimum(0);
|
setMinimum(0);
|
||||||
setValue(0);
|
setValue(0);
|
||||||
setMinimumDuration(0);
|
setMinimumDuration(0);
|
||||||
|
setMinimumSize(QSize(400, 75));
|
||||||
}
|
}
|
||||||
|
|
||||||
void ProgressDialog::networkReplyProgress(qint64 bytesRead, qint64 totalBytes)
|
void ProgressDialog::networkReplyProgress(qint64 bytesRead, qint64 totalBytes)
|
||||||
@ -174,15 +175,22 @@ void HttpWindow::downloadFile()
|
|||||||
if (fileName.isEmpty())
|
if (fileName.isEmpty())
|
||||||
fileName = defaultFileName;
|
fileName = defaultFileName;
|
||||||
QString downloadDirectory = QDir::cleanPath(downloadDirectoryLineEdit->text().trimmed());
|
QString downloadDirectory = QDir::cleanPath(downloadDirectoryLineEdit->text().trimmed());
|
||||||
if (!downloadDirectory.isEmpty() && QFileInfo(downloadDirectory).isDir())
|
bool useDirectory = !downloadDirectory.isEmpty() && QFileInfo(downloadDirectory).isDir();
|
||||||
|
if (useDirectory)
|
||||||
fileName.prepend(downloadDirectory + '/');
|
fileName.prepend(downloadDirectory + '/');
|
||||||
if (QFile::exists(fileName)) {
|
if (QFile::exists(fileName)) {
|
||||||
if (QMessageBox::question(this, tr("Overwrite Existing File"),
|
if (QMessageBox::question(this, tr("Overwrite Existing File"),
|
||||||
tr("There already exists a file called %1 in "
|
tr("There already exists a file called %1%2."
|
||||||
"the current directory. Overwrite?").arg(fileName),
|
" Overwrite?")
|
||||||
QMessageBox::Yes|QMessageBox::No, QMessageBox::No)
|
.arg(fileName,
|
||||||
== QMessageBox::No)
|
useDirectory
|
||||||
|
? QString()
|
||||||
|
: QStringLiteral(" in the current directory")),
|
||||||
|
QMessageBox::Yes | QMessageBox::No,
|
||||||
|
QMessageBox::No)
|
||||||
|
== QMessageBox::No) {
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
QFile::remove(fileName);
|
QFile::remove(fileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -252,7 +260,9 @@ void HttpWindow::httpFinished()
|
|||||||
if (QMessageBox::question(this, tr("Redirect"),
|
if (QMessageBox::question(this, tr("Redirect"),
|
||||||
tr("Redirect to %1 ?").arg(redirectedUrl.toString()),
|
tr("Redirect to %1 ?").arg(redirectedUrl.toString()),
|
||||||
QMessageBox::Yes | QMessageBox::No) == QMessageBox::No) {
|
QMessageBox::Yes | QMessageBox::No) == QMessageBox::No) {
|
||||||
|
QFile::remove(fi.absoluteFilePath());
|
||||||
downloadButton->setEnabled(true);
|
downloadButton->setEnabled(true);
|
||||||
|
statusLabel->setText(tr("Download failed:\nRedirect rejected."));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
file = openFileForWrite(fi.absoluteFilePath());
|
file = openFileForWrite(fi.absoluteFilePath());
|
||||||
@ -286,7 +296,7 @@ void HttpWindow::enableDownloadButton()
|
|||||||
downloadButton->setEnabled(!urlLineEdit->text().isEmpty());
|
downloadButton->setEnabled(!urlLineEdit->text().isEmpty());
|
||||||
}
|
}
|
||||||
|
|
||||||
void HttpWindow::slotAuthenticationRequired(QNetworkReply*,QAuthenticator *authenticator)
|
void HttpWindow::slotAuthenticationRequired(QNetworkReply *, QAuthenticator *authenticator)
|
||||||
{
|
{
|
||||||
QDialog authenticationDialog;
|
QDialog authenticationDialog;
|
||||||
Ui::Dialog ui;
|
Ui::Dialog ui;
|
||||||
@ -306,7 +316,7 @@ void HttpWindow::slotAuthenticationRequired(QNetworkReply*,QAuthenticator *authe
|
|||||||
}
|
}
|
||||||
|
|
||||||
#ifndef QT_NO_SSL
|
#ifndef QT_NO_SSL
|
||||||
void HttpWindow::sslErrors(QNetworkReply*,const QList<QSslError> &errors)
|
void HttpWindow::sslErrors(QNetworkReply *, const QList<QSslError> &errors)
|
||||||
{
|
{
|
||||||
QString errorString;
|
QString errorString;
|
||||||
foreach (const QSslError &error, errors) {
|
foreach (const QSslError &error, errors) {
|
||||||
|
@ -92,9 +92,9 @@ private slots:
|
|||||||
void httpFinished();
|
void httpFinished();
|
||||||
void httpReadyRead();
|
void httpReadyRead();
|
||||||
void enableDownloadButton();
|
void enableDownloadButton();
|
||||||
void slotAuthenticationRequired(QNetworkReply*,QAuthenticator *);
|
void slotAuthenticationRequired(QNetworkReply *, QAuthenticator *authenticator);
|
||||||
#ifndef QT_NO_SSL
|
#ifndef QT_NO_SSL
|
||||||
void sslErrors(QNetworkReply*,const QList<QSslError> &errors);
|
void sslErrors(QNetworkReply *, const QList<QSslError> &errors);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
**
|
**
|
||||||
** Copyright (C) 2016 The Qt Company Ltd.
|
** Copyright (C) 2017 The Qt Company Ltd.
|
||||||
** Contact: https://www.qt.io/licensing/
|
** Contact: https://www.qt.io/licensing/
|
||||||
**
|
**
|
||||||
** This file is part of the examples of the Qt Toolkit.
|
** This file is part of the examples of the Qt Toolkit.
|
||||||
@ -48,43 +48,35 @@
|
|||||||
**
|
**
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
#include <QtWidgets>
|
|
||||||
#include <QtNetwork>
|
|
||||||
|
|
||||||
#include "sender.h"
|
#include "sender.h"
|
||||||
|
|
||||||
Sender::Sender(QWidget *parent)
|
Sender::Sender(QWidget *parent)
|
||||||
: QDialog(parent)
|
: QDialog(parent),
|
||||||
|
groupAddress(QStringLiteral("239.255.43.21"))
|
||||||
{
|
{
|
||||||
groupAddress = QHostAddress("239.255.43.21");
|
|
||||||
|
|
||||||
statusLabel = new QLabel(tr("Ready to multicast datagrams to group %1 on port 45454").arg(groupAddress.toString()));
|
statusLabel = new QLabel(tr("Ready to multicast datagrams to group %1 on port 45454").arg(groupAddress.toString()));
|
||||||
|
|
||||||
ttlLabel = new QLabel(tr("TTL for multicast datagrams:"));
|
auto ttlLabel = new QLabel(tr("TTL for multicast datagrams:"));
|
||||||
ttlSpinBox = new QSpinBox;
|
auto ttlSpinBox = new QSpinBox;
|
||||||
ttlSpinBox->setRange(0, 255);
|
ttlSpinBox->setRange(0, 255);
|
||||||
|
|
||||||
QHBoxLayout *ttlLayout = new QHBoxLayout;
|
auto ttlLayout = new QHBoxLayout;
|
||||||
ttlLayout->addWidget(ttlLabel);
|
ttlLayout->addWidget(ttlLabel);
|
||||||
ttlLayout->addWidget(ttlSpinBox);
|
ttlLayout->addWidget(ttlSpinBox);
|
||||||
|
|
||||||
startButton = new QPushButton(tr("&Start"));
|
startButton = new QPushButton(tr("&Start"));
|
||||||
quitButton = new QPushButton(tr("&Quit"));
|
auto quitButton = new QPushButton(tr("&Quit"));
|
||||||
|
|
||||||
buttonBox = new QDialogButtonBox;
|
auto buttonBox = new QDialogButtonBox;
|
||||||
buttonBox->addButton(startButton, QDialogButtonBox::ActionRole);
|
buttonBox->addButton(startButton, QDialogButtonBox::ActionRole);
|
||||||
buttonBox->addButton(quitButton, QDialogButtonBox::RejectRole);
|
buttonBox->addButton(quitButton, QDialogButtonBox::RejectRole);
|
||||||
|
|
||||||
timer = new QTimer(this);
|
connect(ttlSpinBox, QOverload<int>::of(&QSpinBox::valueChanged), this, &Sender::ttlChanged);
|
||||||
udpSocket = new QUdpSocket(this);
|
connect(startButton, &QPushButton::clicked, this, &Sender::startSending);
|
||||||
messageNo = 1;
|
connect(quitButton, &QPushButton::clicked, this, &Sender::close);
|
||||||
|
connect(&timer, &QTimer::timeout, this, &Sender::sendDatagram);
|
||||||
|
|
||||||
connect(ttlSpinBox, SIGNAL(valueChanged(int)), this, SLOT(ttlChanged(int)));
|
auto mainLayout = new QVBoxLayout;
|
||||||
connect(startButton, SIGNAL(clicked()), this, SLOT(startSending()));
|
|
||||||
connect(quitButton, SIGNAL(clicked()), this, SLOT(close()));
|
|
||||||
connect(timer, SIGNAL(timeout()), this, SLOT(sendDatagram()));
|
|
||||||
|
|
||||||
QVBoxLayout *mainLayout = new QVBoxLayout;
|
|
||||||
mainLayout->addWidget(statusLabel);
|
mainLayout->addWidget(statusLabel);
|
||||||
mainLayout->addLayout(ttlLayout);
|
mainLayout->addLayout(ttlLayout);
|
||||||
mainLayout->addWidget(buttonBox);
|
mainLayout->addWidget(buttonBox);
|
||||||
@ -96,20 +88,19 @@ Sender::Sender(QWidget *parent)
|
|||||||
|
|
||||||
void Sender::ttlChanged(int newTtl)
|
void Sender::ttlChanged(int newTtl)
|
||||||
{
|
{
|
||||||
udpSocket->setSocketOption(QAbstractSocket::MulticastTtlOption, newTtl);
|
udpSocket.setSocketOption(QAbstractSocket::MulticastTtlOption, newTtl);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Sender::startSending()
|
void Sender::startSending()
|
||||||
{
|
{
|
||||||
startButton->setEnabled(false);
|
startButton->setEnabled(false);
|
||||||
timer->start(1000);
|
timer.start(1000);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Sender::sendDatagram()
|
void Sender::sendDatagram()
|
||||||
{
|
{
|
||||||
statusLabel->setText(tr("Now sending datagram %1").arg(messageNo));
|
statusLabel->setText(tr("Now sending datagram %1").arg(messageNo));
|
||||||
QByteArray datagram = "Multicast message " + QByteArray::number(messageNo);
|
QByteArray datagram = "Multicast message " + QByteArray::number(messageNo);
|
||||||
udpSocket->writeDatagram(datagram.data(), datagram.size(),
|
udpSocket.writeDatagram(datagram, groupAddress, 45454);
|
||||||
groupAddress, 45454);
|
|
||||||
++messageNo;
|
++messageNo;
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
**
|
**
|
||||||
** Copyright (C) 2016 The Qt Company Ltd.
|
** Copyright (C) 2017 The Qt Company Ltd.
|
||||||
** Contact: https://www.qt.io/licensing/
|
** Contact: https://www.qt.io/licensing/
|
||||||
**
|
**
|
||||||
** This file is part of the examples of the Qt Toolkit.
|
** This file is part of the examples of the Qt Toolkit.
|
||||||
@ -51,24 +51,16 @@
|
|||||||
#ifndef SENDER_H
|
#ifndef SENDER_H
|
||||||
#define SENDER_H
|
#define SENDER_H
|
||||||
|
|
||||||
#include <QDialog>
|
#include <QtWidgets>
|
||||||
#include <QHostAddress>
|
#include <QtNetwork>
|
||||||
|
#include <QtCore>
|
||||||
QT_BEGIN_NAMESPACE
|
|
||||||
class QDialogButtonBox;
|
|
||||||
class QLabel;
|
|
||||||
class QPushButton;
|
|
||||||
class QTimer;
|
|
||||||
class QUdpSocket;
|
|
||||||
class QSpinBox;
|
|
||||||
QT_END_NAMESPACE
|
|
||||||
|
|
||||||
class Sender : public QDialog
|
class Sender : public QDialog
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Sender(QWidget *parent = 0);
|
explicit Sender(QWidget *parent = nullptr);
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
void ttlChanged(int newTtl);
|
void ttlChanged(int newTtl);
|
||||||
@ -76,16 +68,12 @@ private slots:
|
|||||||
void sendDatagram();
|
void sendDatagram();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QLabel *statusLabel;
|
QLabel *statusLabel = nullptr;
|
||||||
QLabel *ttlLabel;
|
QPushButton *startButton = nullptr;
|
||||||
QSpinBox *ttlSpinBox;
|
QUdpSocket udpSocket;
|
||||||
QPushButton *startButton;
|
QTimer timer;
|
||||||
QPushButton *quitButton;
|
|
||||||
QDialogButtonBox *buttonBox;
|
|
||||||
QUdpSocket *udpSocket;
|
|
||||||
QTimer *timer;
|
|
||||||
QHostAddress groupAddress;
|
QHostAddress groupAddress;
|
||||||
int messageNo;
|
int messageNo = 1;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
**
|
**
|
||||||
** Copyright (C) 2016 The Qt Company Ltd.
|
** Copyright (C) 2017 The Qt Company Ltd.
|
||||||
** Contact: https://www.qt.io/licensing/
|
** Contact: https://www.qt.io/licensing/
|
||||||
**
|
**
|
||||||
** This file is part of the examples of the Qt Toolkit.
|
** This file is part of the examples of the Qt Toolkit.
|
||||||
@ -57,8 +57,8 @@ CertificateInfo::CertificateInfo(QWidget *parent)
|
|||||||
form = new Ui_CertificateInfo;
|
form = new Ui_CertificateInfo;
|
||||||
form->setupUi(this);
|
form->setupUi(this);
|
||||||
|
|
||||||
connect(form->certificationPathView, SIGNAL(currentIndexChanged(int)),
|
connect(form->certificationPathView, QOverload<int>::of(&QComboBox::currentIndexChanged),
|
||||||
this, SLOT(updateCertificateInfo(int)));
|
this, &CertificateInfo::updateCertificateInfo);
|
||||||
}
|
}
|
||||||
|
|
||||||
CertificateInfo::~CertificateInfo()
|
CertificateInfo::~CertificateInfo()
|
||||||
@ -68,25 +68,23 @@ CertificateInfo::~CertificateInfo()
|
|||||||
|
|
||||||
void CertificateInfo::setCertificateChain(const QList<QSslCertificate> &chain)
|
void CertificateInfo::setCertificateChain(const QList<QSslCertificate> &chain)
|
||||||
{
|
{
|
||||||
this->chain = chain;
|
certificateChain = chain;
|
||||||
|
|
||||||
form->certificationPathView->clear();
|
form->certificationPathView->clear();
|
||||||
|
for (int i = 0; i < certificateChain.size(); ++i) {
|
||||||
for (int i = 0; i < chain.size(); ++i) {
|
const QSslCertificate &cert = certificateChain.at(i);
|
||||||
const QSslCertificate &cert = chain.at(i);
|
|
||||||
form->certificationPathView->addItem(tr("%1%2 (%3)").arg(!i ? QString() : tr("Issued by: "))
|
form->certificationPathView->addItem(tr("%1%2 (%3)").arg(!i ? QString() : tr("Issued by: "))
|
||||||
.arg(cert.subjectInfo(QSslCertificate::Organization).join(QLatin1Char(' ')))
|
.arg(cert.subjectInfo(QSslCertificate::Organization).join(QLatin1Char(' ')))
|
||||||
.arg(cert.subjectInfo(QSslCertificate::CommonName).join(QLatin1Char(' '))));
|
.arg(cert.subjectInfo(QSslCertificate::CommonName).join(QLatin1Char(' '))));
|
||||||
}
|
}
|
||||||
|
|
||||||
form->certificationPathView->setCurrentIndex(0);
|
form->certificationPathView->setCurrentIndex(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CertificateInfo::updateCertificateInfo(int index)
|
void CertificateInfo::updateCertificateInfo(int index)
|
||||||
{
|
{
|
||||||
form->certificateInfoView->clear();
|
form->certificateInfoView->clear();
|
||||||
if (index >= 0 && index < chain.size()) {
|
if (index >= 0 && index < certificateChain.size()) {
|
||||||
const QSslCertificate &cert = chain.at(index);
|
const QSslCertificate &cert = certificateChain.at(index);
|
||||||
QStringList lines;
|
QStringList lines;
|
||||||
lines << tr("Organization: %1").arg(cert.subjectInfo(QSslCertificate::Organization).join(QLatin1Char(' ')))
|
lines << tr("Organization: %1").arg(cert.subjectInfo(QSslCertificate::Organization).join(QLatin1Char(' ')))
|
||||||
<< tr("Subunit: %1").arg(cert.subjectInfo(QSslCertificate::OrganizationalUnitName).join(QLatin1Char(' ')))
|
<< tr("Subunit: %1").arg(cert.subjectInfo(QSslCertificate::OrganizationalUnitName).join(QLatin1Char(' ')))
|
||||||
@ -101,9 +99,7 @@ void CertificateInfo::updateCertificateInfo(int index)
|
|||||||
<< tr("Issuer Locality: %1").arg(cert.issuerInfo(QSslCertificate::LocalityName).join(QLatin1Char(' ')))
|
<< tr("Issuer Locality: %1").arg(cert.issuerInfo(QSslCertificate::LocalityName).join(QLatin1Char(' ')))
|
||||||
<< tr("Issuer State/Province: %1").arg(cert.issuerInfo(QSslCertificate::StateOrProvinceName).join(QLatin1Char(' ')))
|
<< tr("Issuer State/Province: %1").arg(cert.issuerInfo(QSslCertificate::StateOrProvinceName).join(QLatin1Char(' ')))
|
||||||
<< tr("Issuer Common Name: %1").arg(cert.issuerInfo(QSslCertificate::CommonName).join(QLatin1Char(' ')));
|
<< tr("Issuer Common Name: %1").arg(cert.issuerInfo(QSslCertificate::CommonName).join(QLatin1Char(' ')));
|
||||||
foreach (QString line, lines)
|
for (const auto &line : lines)
|
||||||
form->certificateInfoView->addItem(line);
|
form->certificateInfoView->addItem(line);
|
||||||
} else {
|
|
||||||
form->certificateInfoView->clear();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
**
|
**
|
||||||
** Copyright (C) 2016 The Qt Company Ltd.
|
** Copyright (C) 2017 The Qt Company Ltd.
|
||||||
** Contact: https://www.qt.io/licensing/
|
** Contact: https://www.qt.io/licensing/
|
||||||
**
|
**
|
||||||
** This file is part of the examples of the Qt Toolkit.
|
** This file is part of the examples of the Qt Toolkit.
|
||||||
@ -51,8 +51,9 @@
|
|||||||
#ifndef CERTIFICATEINFO_H
|
#ifndef CERTIFICATEINFO_H
|
||||||
#define CERTIFICATEINFO_H
|
#define CERTIFICATEINFO_H
|
||||||
|
|
||||||
#include <QtWidgets/QDialog>
|
#include <QDialog>
|
||||||
#include <QtNetwork/QSslCertificate>
|
#include <QList>
|
||||||
|
#include <QSslCertificate>
|
||||||
|
|
||||||
QT_BEGIN_NAMESPACE
|
QT_BEGIN_NAMESPACE
|
||||||
class Ui_CertificateInfo;
|
class Ui_CertificateInfo;
|
||||||
@ -62,7 +63,7 @@ class CertificateInfo : public QDialog
|
|||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
CertificateInfo(QWidget *parent = 0);
|
explicit CertificateInfo(QWidget *parent = nullptr);
|
||||||
~CertificateInfo();
|
~CertificateInfo();
|
||||||
|
|
||||||
void setCertificateChain(const QList<QSslCertificate> &chain);
|
void setCertificateChain(const QList<QSslCertificate> &chain);
|
||||||
@ -71,8 +72,8 @@ private slots:
|
|||||||
void updateCertificateInfo(int index);
|
void updateCertificateInfo(int index);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Ui_CertificateInfo *form;
|
Ui_CertificateInfo *form = nullptr;
|
||||||
QList<QSslCertificate> chain;
|
QList<QSslCertificate> certificateChain;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -42,7 +42,7 @@
|
|||||||
<widget class="QListWidget" name="certificateInfoView">
|
<widget class="QListWidget" name="certificateInfoView">
|
||||||
<property name="font">
|
<property name="font">
|
||||||
<font>
|
<font>
|
||||||
<pointsize>8</pointsize>
|
<pointsize>10</pointsize>
|
||||||
</font>
|
</font>
|
||||||
</property>
|
</property>
|
||||||
<property name="wordWrap">
|
<property name="wordWrap">
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
**
|
**
|
||||||
** Copyright (C) 2016 The Qt Company Ltd.
|
** Copyright (C) 2017 The Qt Company Ltd.
|
||||||
** Contact: https://www.qt.io/licensing/
|
** Contact: https://www.qt.io/licensing/
|
||||||
**
|
**
|
||||||
** This file is part of the examples of the Qt Toolkit.
|
** This file is part of the examples of the Qt Toolkit.
|
||||||
@ -50,6 +50,9 @@
|
|||||||
|
|
||||||
#include <QApplication>
|
#include <QApplication>
|
||||||
#include <QMessageBox>
|
#include <QMessageBox>
|
||||||
|
#include <QtNetwork>
|
||||||
|
|
||||||
|
QT_REQUIRE_CONFIG(ssl);
|
||||||
|
|
||||||
#include "sslclient.h"
|
#include "sslclient.h"
|
||||||
|
|
||||||
@ -61,7 +64,7 @@ int main(int argc, char **argv)
|
|||||||
|
|
||||||
if (!QSslSocket::supportsSsl()) {
|
if (!QSslSocket::supportsSsl()) {
|
||||||
QMessageBox::information(0, "Secure Socket Client",
|
QMessageBox::information(0, "Secure Socket Client",
|
||||||
"This system does not support OpenSSL.");
|
"This system does not support SSL/TLS.");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
requires(qtHaveModule(network))
|
||||||
|
|
||||||
HEADERS += certificateinfo.h \
|
HEADERS += certificateinfo.h \
|
||||||
sslclient.h
|
sslclient.h
|
||||||
SOURCES += certificateinfo.cpp \
|
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/
|
** Contact: https://www.qt.io/licensing/
|
||||||
**
|
**
|
||||||
** This file is part of the examples of the Qt Toolkit.
|
** This file is part of the examples of the Qt Toolkit.
|
||||||
@ -50,29 +50,17 @@
|
|||||||
|
|
||||||
#include "certificateinfo.h"
|
#include "certificateinfo.h"
|
||||||
#include "sslclient.h"
|
#include "sslclient.h"
|
||||||
|
|
||||||
#include "ui_sslclient.h"
|
#include "ui_sslclient.h"
|
||||||
#include "ui_sslerrors.h"
|
#include "ui_sslerrors.h"
|
||||||
|
|
||||||
#include <QtWidgets/QScrollBar>
|
#include <QtCore>
|
||||||
#include <QtWidgets/QStyle>
|
|
||||||
#include <QtWidgets/QToolButton>
|
|
||||||
#include <QtWidgets/QMessageBox>
|
|
||||||
#include <QtNetwork/QSslCipher>
|
|
||||||
|
|
||||||
SslClient::SslClient(QWidget *parent)
|
SslClient::SslClient(QWidget *parent)
|
||||||
: QWidget(parent), socket(0), padLock(0), executingDialog(false)
|
: QWidget(parent)
|
||||||
{
|
{
|
||||||
form = new Ui_Form;
|
setupUi();
|
||||||
form->setupUi(this);
|
setupSecureSocket();
|
||||||
form->hostNameEdit->setSelection(0, form->hostNameEdit->text().size());
|
|
||||||
form->sessionOutput->setHtml(tr("<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()));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
SslClient::~SslClient()
|
SslClient::~SslClient()
|
||||||
@ -82,17 +70,15 @@ SslClient::~SslClient()
|
|||||||
|
|
||||||
void SslClient::updateEnabledState()
|
void SslClient::updateEnabledState()
|
||||||
{
|
{
|
||||||
bool unconnected = !socket || socket->state() == QAbstractSocket::UnconnectedState;
|
const bool unconnected = socket->state() == QAbstractSocket::UnconnectedState;
|
||||||
|
|
||||||
form->hostNameEdit->setReadOnly(!unconnected);
|
form->hostNameEdit->setReadOnly(!unconnected);
|
||||||
form->hostNameEdit->setFocusPolicy(unconnected ? Qt::StrongFocus : Qt::NoFocus);
|
form->hostNameEdit->setFocusPolicy(unconnected ? Qt::StrongFocus : Qt::NoFocus);
|
||||||
|
|
||||||
form->hostNameLabel->setEnabled(unconnected);
|
form->hostNameLabel->setEnabled(unconnected);
|
||||||
form->portBox->setEnabled(unconnected);
|
form->portBox->setEnabled(unconnected);
|
||||||
form->portLabel->setEnabled(unconnected);
|
form->portLabel->setEnabled(unconnected);
|
||||||
form->connectButton->setEnabled(unconnected && !form->hostNameEdit->text().isEmpty());
|
form->connectButton->setEnabled(unconnected && !form->hostNameEdit->text().isEmpty());
|
||||||
|
|
||||||
bool connected = socket && socket->state() == QAbstractSocket::ConnectedState;
|
const bool connected = socket->state() == QAbstractSocket::ConnectedState;
|
||||||
form->sessionOutput->setEnabled(connected);
|
form->sessionOutput->setEnabled(connected);
|
||||||
form->sessionInput->setEnabled(connected);
|
form->sessionInput->setEnabled(connected);
|
||||||
form->sessionInputLabel->setEnabled(connected);
|
form->sessionInputLabel->setEnabled(connected);
|
||||||
@ -101,20 +87,6 @@ void SslClient::updateEnabledState()
|
|||||||
|
|
||||||
void SslClient::secureConnect()
|
void SslClient::secureConnect()
|
||||||
{
|
{
|
||||||
if (!socket) {
|
|
||||||
socket = new QSslSocket(this);
|
|
||||||
connect(socket, SIGNAL(stateChanged(QAbstractSocket::SocketState)),
|
|
||||||
this, SLOT(socketStateChanged(QAbstractSocket::SocketState)));
|
|
||||||
connect(socket, SIGNAL(encrypted()),
|
|
||||||
this, SLOT(socketEncrypted()));
|
|
||||||
connect(socket, SIGNAL(error(QAbstractSocket::SocketError)),
|
|
||||||
this, SLOT(socketError(QAbstractSocket::SocketError)));
|
|
||||||
connect(socket, SIGNAL(sslErrors(QList<QSslError>)),
|
|
||||||
this, SLOT(sslErrors(QList<QSslError>)));
|
|
||||||
connect(socket, SIGNAL(readyRead()),
|
|
||||||
this, SLOT(socketReadyRead()));
|
|
||||||
}
|
|
||||||
|
|
||||||
socket->connectToHostEncrypted(form->hostNameEdit->text(), form->portBox->value());
|
socket->connectToHostEncrypted(form->hostNameEdit->text(), form->portBox->value());
|
||||||
updateEnabledState();
|
updateEnabledState();
|
||||||
}
|
}
|
||||||
@ -125,20 +97,18 @@ void SslClient::socketStateChanged(QAbstractSocket::SocketState state)
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
updateEnabledState();
|
updateEnabledState();
|
||||||
|
|
||||||
if (state == QAbstractSocket::UnconnectedState) {
|
if (state == QAbstractSocket::UnconnectedState) {
|
||||||
|
form->sessionInput->clear();
|
||||||
form->hostNameEdit->setPalette(QPalette());
|
form->hostNameEdit->setPalette(QPalette());
|
||||||
form->hostNameEdit->setFocus();
|
form->hostNameEdit->setFocus();
|
||||||
form->cipherLabel->setText(tr("<none>"));
|
form->cipherLabel->setText(tr("<none>"));
|
||||||
if (padLock)
|
padLock->hide();
|
||||||
padLock->hide();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void SslClient::socketEncrypted()
|
void SslClient::socketEncrypted()
|
||||||
{
|
{
|
||||||
if (!socket)
|
|
||||||
return; // might have disconnected already
|
|
||||||
|
|
||||||
form->sessionOutput->clear();
|
form->sessionOutput->clear();
|
||||||
form->sessionInput->setFocus();
|
form->sessionInput->setFocus();
|
||||||
|
|
||||||
@ -146,36 +116,12 @@ void SslClient::socketEncrypted()
|
|||||||
palette.setColor(QPalette::Base, QColor(255, 255, 192));
|
palette.setColor(QPalette::Base, QColor(255, 255, 192));
|
||||||
form->hostNameEdit->setPalette(palette);
|
form->hostNameEdit->setPalette(palette);
|
||||||
|
|
||||||
QSslCipher ciph = socket->sessionCipher();
|
const QSslCipher cipher = socket->sessionCipher();
|
||||||
QString cipher = QString("%1, %2 (%3/%4)").arg(ciph.authenticationMethod())
|
const QString cipherInfo = QString("%1, %2 (%3/%4)").arg(cipher.authenticationMethod())
|
||||||
.arg(ciph.name()).arg(ciph.usedBits()).arg(ciph.supportedBits());;
|
.arg(cipher.name()).arg(cipher.usedBits())
|
||||||
form->cipherLabel->setText(cipher);
|
.arg(cipher.supportedBits());;
|
||||||
|
form->cipherLabel->setText(cipherInfo);
|
||||||
if (!padLock) {
|
padLock->show();
|
||||||
padLock = new QToolButton;
|
|
||||||
padLock->setIcon(QIcon(":/encrypted.png"));
|
|
||||||
#ifndef QT_NO_CURSOR
|
|
||||||
padLock->setCursor(Qt::ArrowCursor);
|
|
||||||
#endif
|
|
||||||
padLock->setToolTip(tr("Display encryption details."));
|
|
||||||
|
|
||||||
int extent = form->hostNameEdit->height() - 2;
|
|
||||||
padLock->resize(extent, extent);
|
|
||||||
padLock->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Ignored);
|
|
||||||
|
|
||||||
QHBoxLayout *layout = new QHBoxLayout(form->hostNameEdit);
|
|
||||||
layout->setMargin(form->hostNameEdit->style()->pixelMetric(QStyle::PM_DefaultFrameWidth));
|
|
||||||
layout->setSpacing(0);
|
|
||||||
layout->addStretch();
|
|
||||||
layout->addWidget(padLock);
|
|
||||||
|
|
||||||
form->hostNameEdit->setLayout(layout);
|
|
||||||
|
|
||||||
connect(padLock, SIGNAL(clicked()),
|
|
||||||
this, SLOT(displayCertificateInfo()));
|
|
||||||
} else {
|
|
||||||
padLock->show();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void SslClient::socketReadyRead()
|
void SslClient::socketReadyRead()
|
||||||
@ -185,7 +131,7 @@ void SslClient::socketReadyRead()
|
|||||||
|
|
||||||
void SslClient::sendData()
|
void SslClient::sendData()
|
||||||
{
|
{
|
||||||
QString input = form->sessionInput->text();
|
const QString input = form->sessionInput->text();
|
||||||
appendString(input + '\n');
|
appendString(input + '\n');
|
||||||
socket->write(input.toUtf8() + "\r\n");
|
socket->write(input.toUtf8() + "\r\n");
|
||||||
form->sessionInput->clear();
|
form->sessionInput->clear();
|
||||||
@ -193,7 +139,12 @@ void SslClient::sendData()
|
|||||||
|
|
||||||
void SslClient::socketError(QAbstractSocket::SocketError)
|
void SslClient::socketError(QAbstractSocket::SocketError)
|
||||||
{
|
{
|
||||||
|
if (handlingSocketError)
|
||||||
|
return;
|
||||||
|
|
||||||
|
handlingSocketError = true;
|
||||||
QMessageBox::critical(this, tr("Connection error"), socket->errorString());
|
QMessageBox::critical(this, tr("Connection error"), socket->errorString());
|
||||||
|
handlingSocketError = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SslClient::sslErrors(const QList<QSslError> &errors)
|
void SslClient::sslErrors(const QList<QSslError> &errors)
|
||||||
@ -201,10 +152,10 @@ void SslClient::sslErrors(const QList<QSslError> &errors)
|
|||||||
QDialog errorDialog(this);
|
QDialog errorDialog(this);
|
||||||
Ui_SslErrors ui;
|
Ui_SslErrors ui;
|
||||||
ui.setupUi(&errorDialog);
|
ui.setupUi(&errorDialog);
|
||||||
connect(ui.certificateChainButton, SIGNAL(clicked()),
|
connect(ui.certificateChainButton, &QPushButton::clicked,
|
||||||
this, SLOT(displayCertificateInfo()));
|
this, &SslClient::displayCertificateInfo);
|
||||||
|
|
||||||
foreach (const QSslError &error, errors)
|
for (const auto &error : errors)
|
||||||
ui.sslErrorList->addItem(error.errorString());
|
ui.sslErrorList->addItem(error.errorString());
|
||||||
|
|
||||||
executingDialog = true;
|
executingDialog = true;
|
||||||
@ -219,10 +170,69 @@ void SslClient::sslErrors(const QList<QSslError> &errors)
|
|||||||
|
|
||||||
void SslClient::displayCertificateInfo()
|
void SslClient::displayCertificateInfo()
|
||||||
{
|
{
|
||||||
CertificateInfo *info = new CertificateInfo(this);
|
CertificateInfo info;
|
||||||
info->setCertificateChain(socket->peerCertificateChain());
|
info.setCertificateChain(socket->peerCertificateChain());
|
||||||
info->exec();
|
info.exec();
|
||||||
info->deleteLater();
|
}
|
||||||
|
|
||||||
|
void SslClient::setupUi()
|
||||||
|
{
|
||||||
|
if (form)
|
||||||
|
return;
|
||||||
|
|
||||||
|
form = new Ui_Form;
|
||||||
|
form->setupUi(this);
|
||||||
|
form->hostNameEdit->setSelection(0, form->hostNameEdit->text().size());
|
||||||
|
form->sessionOutput->setHtml(tr("<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)
|
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/
|
** Contact: https://www.qt.io/licensing/
|
||||||
**
|
**
|
||||||
** This file is part of the examples of the Qt Toolkit.
|
** This file is part of the examples of the Qt Toolkit.
|
||||||
@ -51,13 +51,13 @@
|
|||||||
#ifndef SSLCLIENT_H
|
#ifndef SSLCLIENT_H
|
||||||
#define SSLCLIENT_H
|
#define SSLCLIENT_H
|
||||||
|
|
||||||
#include <QtWidgets/QWidget>
|
#include <QtNetwork>
|
||||||
#include <QtNetwork/QAbstractSocket>
|
|
||||||
#include <QtNetwork/QSslSocket>
|
QT_REQUIRE_CONFIG(ssl);
|
||||||
|
|
||||||
|
#include <QtWidgets>
|
||||||
|
|
||||||
QT_BEGIN_NAMESPACE
|
QT_BEGIN_NAMESPACE
|
||||||
class QSslSocket;
|
|
||||||
class QToolButton;
|
|
||||||
class Ui_Form;
|
class Ui_Form;
|
||||||
QT_END_NAMESPACE
|
QT_END_NAMESPACE
|
||||||
|
|
||||||
@ -65,7 +65,7 @@ class SslClient : public QWidget
|
|||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
SslClient(QWidget *parent = 0);
|
explicit SslClient(QWidget *parent = nullptr);
|
||||||
~SslClient();
|
~SslClient();
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
@ -80,12 +80,15 @@ private slots:
|
|||||||
void displayCertificateInfo();
|
void displayCertificateInfo();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
void setupUi();
|
||||||
|
void setupSecureSocket();
|
||||||
void appendString(const QString &line);
|
void appendString(const QString &line);
|
||||||
|
|
||||||
QSslSocket *socket;
|
QSslSocket *socket = nullptr;
|
||||||
QToolButton *padLock;
|
QToolButton *padLock = nullptr;
|
||||||
Ui_Form *form;
|
Ui_Form *form = nullptr;
|
||||||
bool executingDialog;
|
bool handlingSocketError = false;
|
||||||
|
bool executingDialog = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -10,6 +10,12 @@
|
|||||||
<height>320</height>
|
<height>320</height>
|
||||||
</rect>
|
</rect>
|
||||||
</property>
|
</property>
|
||||||
|
<property name="minimumSize">
|
||||||
|
<size>
|
||||||
|
<width>343</width>
|
||||||
|
<height>320</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
<property name="windowTitle">
|
<property name="windowTitle">
|
||||||
<string>Secure Socket Client</string>
|
<string>Secure Socket Client</string>
|
||||||
</property>
|
</property>
|
||||||
@ -114,8 +120,8 @@
|
|||||||
<string><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">
|
<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">
|
<html><head><meta name="qrichtext" content="1" /><style type="text/css">
|
||||||
p, li { white-space: pre-wrap; }
|
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;">
|
</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;"></p></body></html></string>
|
<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>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
|
@ -54,6 +54,8 @@
|
|||||||
#include <QCoreApplication>
|
#include <QCoreApplication>
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
|
|
||||||
|
bool GLWidget::m_transparent = false;
|
||||||
|
|
||||||
GLWidget::GLWidget(QWidget *parent)
|
GLWidget::GLWidget(QWidget *parent)
|
||||||
: QOpenGLWidget(parent),
|
: QOpenGLWidget(parent),
|
||||||
m_xRot(0),
|
m_xRot(0),
|
||||||
@ -61,10 +63,9 @@ GLWidget::GLWidget(QWidget *parent)
|
|||||||
m_zRot(0),
|
m_zRot(0),
|
||||||
m_program(0)
|
m_program(0)
|
||||||
{
|
{
|
||||||
m_core = QCoreApplication::arguments().contains(QStringLiteral("--coreprofile"));
|
m_core = QSurfaceFormat::defaultFormat().profile() == QSurfaceFormat::CoreProfile;
|
||||||
// --transparent causes the clear color to be transparent. Therefore, on systems that
|
// --transparent causes the clear color to be transparent. Therefore, on systems that
|
||||||
// support it, the widget will become transparent apart from the logo.
|
// support it, the widget will become transparent apart from the logo.
|
||||||
m_transparent = QCoreApplication::arguments().contains(QStringLiteral("--transparent"));
|
|
||||||
if (m_transparent) {
|
if (m_transparent) {
|
||||||
QSurfaceFormat fmt = format();
|
QSurfaceFormat fmt = format();
|
||||||
fmt.setAlphaBufferSize(8);
|
fmt.setAlphaBufferSize(8);
|
||||||
@ -127,6 +128,8 @@ void GLWidget::setZRotation(int angle)
|
|||||||
|
|
||||||
void GLWidget::cleanup()
|
void GLWidget::cleanup()
|
||||||
{
|
{
|
||||||
|
if (m_program == nullptr)
|
||||||
|
return;
|
||||||
makeCurrent();
|
makeCurrent();
|
||||||
m_logoVbo.destroy();
|
m_logoVbo.destroy();
|
||||||
delete m_program;
|
delete m_program;
|
||||||
|
@ -68,6 +68,9 @@ public:
|
|||||||
GLWidget(QWidget *parent = 0);
|
GLWidget(QWidget *parent = 0);
|
||||||
~GLWidget();
|
~GLWidget();
|
||||||
|
|
||||||
|
static bool isTransparent() { return m_transparent; }
|
||||||
|
static void setTransparent(bool t) { m_transparent = t; }
|
||||||
|
|
||||||
QSize minimumSizeHint() const override;
|
QSize minimumSizeHint() const override;
|
||||||
QSize sizeHint() const override;
|
QSize sizeHint() const override;
|
||||||
|
|
||||||
@ -108,7 +111,7 @@ private:
|
|||||||
QMatrix4x4 m_proj;
|
QMatrix4x4 m_proj;
|
||||||
QMatrix4x4 m_camera;
|
QMatrix4x4 m_camera;
|
||||||
QMatrix4x4 m_world;
|
QMatrix4x4 m_world;
|
||||||
bool m_transparent;
|
static bool m_transparent;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -51,25 +51,46 @@
|
|||||||
#include <QApplication>
|
#include <QApplication>
|
||||||
#include <QDesktopWidget>
|
#include <QDesktopWidget>
|
||||||
#include <QSurfaceFormat>
|
#include <QSurfaceFormat>
|
||||||
|
#include <QCommandLineParser>
|
||||||
|
#include <QCommandLineOption>
|
||||||
|
|
||||||
|
#include "glwidget.h"
|
||||||
#include "mainwindow.h"
|
#include "mainwindow.h"
|
||||||
|
|
||||||
int main(int argc, char *argv[])
|
int main(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
QApplication app(argc, argv);
|
QApplication app(argc, argv);
|
||||||
|
|
||||||
|
QCoreApplication::setApplicationName("Qt Hello GL 2 Example");
|
||||||
|
QCoreApplication::setOrganizationName("QtProject");
|
||||||
|
QCoreApplication::setApplicationVersion(QT_VERSION_STR);
|
||||||
|
QCommandLineParser parser;
|
||||||
|
parser.setApplicationDescription(QCoreApplication::applicationName());
|
||||||
|
parser.addHelpOption();
|
||||||
|
parser.addVersionOption();
|
||||||
|
QCommandLineOption multipleSampleOption("multisample", "Multisampling");
|
||||||
|
parser.addOption(multipleSampleOption);
|
||||||
|
QCommandLineOption coreProfileOption("coreprofile", "Use core profile");
|
||||||
|
parser.addOption(coreProfileOption);
|
||||||
|
QCommandLineOption transparentOption("transparent", "Transparent window");
|
||||||
|
parser.addOption(transparentOption);
|
||||||
|
|
||||||
|
parser.process(app);
|
||||||
|
|
||||||
QSurfaceFormat fmt;
|
QSurfaceFormat fmt;
|
||||||
fmt.setDepthBufferSize(24);
|
fmt.setDepthBufferSize(24);
|
||||||
if (QCoreApplication::arguments().contains(QStringLiteral("--multisample")))
|
if (parser.isSet(multipleSampleOption))
|
||||||
fmt.setSamples(4);
|
fmt.setSamples(4);
|
||||||
if (QCoreApplication::arguments().contains(QStringLiteral("--coreprofile"))) {
|
if (parser.isSet(coreProfileOption)) {
|
||||||
fmt.setVersion(3, 2);
|
fmt.setVersion(3, 2);
|
||||||
fmt.setProfile(QSurfaceFormat::CoreProfile);
|
fmt.setProfile(QSurfaceFormat::CoreProfile);
|
||||||
}
|
}
|
||||||
QSurfaceFormat::setDefaultFormat(fmt);
|
QSurfaceFormat::setDefaultFormat(fmt);
|
||||||
|
|
||||||
MainWindow mainWindow;
|
MainWindow mainWindow;
|
||||||
if (QCoreApplication::arguments().contains(QStringLiteral("--transparent"))) {
|
|
||||||
|
GLWidget::setTransparent(parser.isSet(transparentOption));
|
||||||
|
if (GLWidget::isTransparent()) {
|
||||||
mainWindow.setAttribute(Qt::WA_TranslucentBackground);
|
mainWindow.setAttribute(Qt::WA_TranslucentBackground);
|
||||||
mainWindow.setAttribute(Qt::WA_NoSystemBackground, false);
|
mainWindow.setAttribute(Qt::WA_NoSystemBackground, false);
|
||||||
}
|
}
|
||||||
|
@ -52,6 +52,8 @@
|
|||||||
|
|
||||||
#include <qpa/qplatformintegration.h>
|
#include <qpa/qplatformintegration.h>
|
||||||
|
|
||||||
|
#include <QCommandLineParser>
|
||||||
|
#include <QCommandLineOption>
|
||||||
#include <QGuiApplication>
|
#include <QGuiApplication>
|
||||||
#include <QScreen>
|
#include <QScreen>
|
||||||
#include <QThread>
|
#include <QThread>
|
||||||
@ -60,9 +62,26 @@ int main(int argc, char *argv[])
|
|||||||
{
|
{
|
||||||
QGuiApplication app(argc, argv);
|
QGuiApplication app(argc, argv);
|
||||||
|
|
||||||
|
QCoreApplication::setApplicationName("Qt HelloWindow GL Example");
|
||||||
|
QCoreApplication::setOrganizationName("QtProject");
|
||||||
|
QCoreApplication::setApplicationVersion(QT_VERSION_STR);
|
||||||
|
QCommandLineParser parser;
|
||||||
|
parser.setApplicationDescription(QCoreApplication::applicationName());
|
||||||
|
parser.addHelpOption();
|
||||||
|
parser.addVersionOption();
|
||||||
|
QCommandLineOption multipleOption("multiple", "Create multiple windows");
|
||||||
|
parser.addOption(multipleOption);
|
||||||
|
QCommandLineOption multipleSampleOption("multisample", "Multisampling");
|
||||||
|
parser.addOption(multipleSampleOption);
|
||||||
|
QCommandLineOption multipleScreenOption("multiscreen", "Run on multiple screens");
|
||||||
|
parser.addOption(multipleScreenOption);
|
||||||
|
QCommandLineOption timeoutOption("timeout", "Close after 10s");
|
||||||
|
parser.addOption(timeoutOption);
|
||||||
|
parser.process(app);
|
||||||
|
|
||||||
// Some platforms can only have one window per screen. Therefore we need to differentiate.
|
// Some platforms can only have one window per screen. Therefore we need to differentiate.
|
||||||
const bool multipleWindows = QGuiApplication::arguments().contains(QStringLiteral("--multiple"));
|
const bool multipleWindows = parser.isSet(multipleOption);
|
||||||
const bool multipleScreens = QGuiApplication::arguments().contains(QStringLiteral("--multiscreen"));
|
const bool multipleScreens = parser.isSet(multipleScreenOption);
|
||||||
|
|
||||||
QScreen *screen = QGuiApplication::primaryScreen();
|
QScreen *screen = QGuiApplication::primaryScreen();
|
||||||
|
|
||||||
@ -70,7 +89,7 @@ int main(int argc, char *argv[])
|
|||||||
|
|
||||||
QSurfaceFormat format;
|
QSurfaceFormat format;
|
||||||
format.setDepthBufferSize(16);
|
format.setDepthBufferSize(16);
|
||||||
if (QGuiApplication::arguments().contains(QStringLiteral("--multisample")))
|
if (parser.isSet(multipleSampleOption))
|
||||||
format.setSamples(4);
|
format.setSamples(4);
|
||||||
|
|
||||||
QPoint center = QPoint(screenGeometry.center().x(), screenGeometry.top() + 80);
|
QPoint center = QPoint(screenGeometry.center().x(), screenGeometry.top() + 80);
|
||||||
@ -136,7 +155,7 @@ int main(int argc, char *argv[])
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Quit after 10 seconds. For platforms that do not have windows that are closeable.
|
// Quit after 10 seconds. For platforms that do not have windows that are closeable.
|
||||||
if (QCoreApplication::arguments().contains(QStringLiteral("--timeout")))
|
if (parser.isSet(timeoutOption))
|
||||||
QTimer::singleShot(10000, qGuiApp, &QCoreApplication::quit);
|
QTimer::singleShot(10000, qGuiApp, &QCoreApplication::quit);
|
||||||
|
|
||||||
const int exitValue = app.exec();
|
const int exitValue = app.exec();
|
||||||
|
@ -51,6 +51,8 @@
|
|||||||
#include <QApplication>
|
#include <QApplication>
|
||||||
#include <QMainWindow>
|
#include <QMainWindow>
|
||||||
#include <QSurfaceFormat>
|
#include <QSurfaceFormat>
|
||||||
|
#include <QCommandLineParser>
|
||||||
|
#include <QCommandLineOption>
|
||||||
#include "mainwindow.h"
|
#include "mainwindow.h"
|
||||||
|
|
||||||
int main( int argc, char ** argv )
|
int main( int argc, char ** argv )
|
||||||
@ -58,12 +60,25 @@ int main( int argc, char ** argv )
|
|||||||
Q_INIT_RESOURCE(texture);
|
Q_INIT_RESOURCE(texture);
|
||||||
QApplication a( argc, argv );
|
QApplication a( argc, argv );
|
||||||
|
|
||||||
|
QCoreApplication::setApplicationName("Qt QOpenGLWidget Example");
|
||||||
|
QCoreApplication::setOrganizationName("QtProject");
|
||||||
|
QCoreApplication::setApplicationVersion(QT_VERSION_STR);
|
||||||
|
QCommandLineParser parser;
|
||||||
|
parser.setApplicationDescription(QCoreApplication::applicationName());
|
||||||
|
parser.addHelpOption();
|
||||||
|
parser.addVersionOption();
|
||||||
|
QCommandLineOption multipleSampleOption("multisample", "Multisampling");
|
||||||
|
parser.addOption(multipleSampleOption);
|
||||||
|
QCommandLineOption srgbOption("srgb", "Use sRGB Color Space");
|
||||||
|
parser.addOption(srgbOption);
|
||||||
|
parser.process(a);
|
||||||
|
|
||||||
QSurfaceFormat format;
|
QSurfaceFormat format;
|
||||||
format.setDepthBufferSize(24);
|
format.setDepthBufferSize(24);
|
||||||
format.setStencilBufferSize(8);
|
format.setStencilBufferSize(8);
|
||||||
if (QCoreApplication::arguments().contains(QStringLiteral("--srgb")))
|
if (parser.isSet(srgbOption))
|
||||||
format.setColorSpace(QSurfaceFormat::sRGBColorSpace);
|
format.setColorSpace(QSurfaceFormat::sRGBColorSpace);
|
||||||
if (QCoreApplication::arguments().contains(QStringLiteral("--multisample")))
|
if (parser.isSet(multipleSampleOption))
|
||||||
format.setSamples(4);
|
format.setSamples(4);
|
||||||
QSurfaceFormat::setDefaultFormat(format);
|
QSurfaceFormat::setDefaultFormat(format);
|
||||||
|
|
||||||
|
@ -53,6 +53,8 @@
|
|||||||
#include <QDesktopWidget>
|
#include <QDesktopWidget>
|
||||||
#include <QSurfaceFormat>
|
#include <QSurfaceFormat>
|
||||||
#include <QOpenGLContext>
|
#include <QOpenGLContext>
|
||||||
|
#include <QCommandLineParser>
|
||||||
|
#include <QCommandLineOption>
|
||||||
#include "mainwindow.h"
|
#include "mainwindow.h"
|
||||||
#include "glwidget.h"
|
#include "glwidget.h"
|
||||||
|
|
||||||
@ -67,6 +69,17 @@ int main( int argc, char ** argv )
|
|||||||
{
|
{
|
||||||
QApplication a( argc, argv );
|
QApplication a( argc, argv );
|
||||||
|
|
||||||
|
QCoreApplication::setApplicationName("Qt Threaded QOpenGLWidget Example");
|
||||||
|
QCoreApplication::setOrganizationName("QtProject");
|
||||||
|
QCoreApplication::setApplicationVersion(QT_VERSION_STR);
|
||||||
|
QCommandLineParser parser;
|
||||||
|
parser.setApplicationDescription(QCoreApplication::applicationName());
|
||||||
|
parser.addHelpOption();
|
||||||
|
parser.addVersionOption();
|
||||||
|
QCommandLineOption singleOption("single", "Single thread");
|
||||||
|
parser.addOption(singleOption);
|
||||||
|
parser.process(a);
|
||||||
|
|
||||||
QSurfaceFormat format;
|
QSurfaceFormat format;
|
||||||
format.setDepthBufferSize(16);
|
format.setDepthBufferSize(16);
|
||||||
QSurfaceFormat::setDefaultFormat(format);
|
QSurfaceFormat::setDefaultFormat(format);
|
||||||
@ -93,7 +106,7 @@ int main( int argc, char ** argv )
|
|||||||
|
|
||||||
QScopedPointer<MainWindow> mw1;
|
QScopedPointer<MainWindow> mw1;
|
||||||
QScopedPointer<MainWindow> mw2;
|
QScopedPointer<MainWindow> mw2;
|
||||||
if (!QApplication::arguments().contains(QStringLiteral("--single"))) {
|
if (!parser.isSet(singleOption)) {
|
||||||
if (supportsThreading) {
|
if (supportsThreading) {
|
||||||
pos += QPoint(100, 100);
|
pos += QPoint(100, 100);
|
||||||
mw1.reset(new MainWindow);
|
mw1.reset(new MainWindow);
|
||||||
|
@ -85,9 +85,9 @@ TableEditor::TableEditor(const QString &tableName, QWidget *parent)
|
|||||||
//! [2]
|
//! [2]
|
||||||
|
|
||||||
//! [3]
|
//! [3]
|
||||||
connect(submitButton, SIGNAL(clicked()), this, SLOT(submit()));
|
connect(submitButton, &QPushButton::clicked, this, &TableEditor::submit);
|
||||||
connect(revertButton, SIGNAL(clicked()), model, SLOT(revertAll()));
|
connect(revertButton, &QPushButton::clicked, model, &QSqlTableModel::revertAll);
|
||||||
connect(quitButton, SIGNAL(clicked()), this, SLOT(close()));
|
connect(quitButton, &QPushButton::clicked, this, &TableEditor::close);
|
||||||
//! [3]
|
//! [3]
|
||||||
|
|
||||||
//! [4]
|
//! [4]
|
||||||
|
@ -65,7 +65,7 @@ class TableEditor : public QWidget
|
|||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit TableEditor(const QString &tableName, QWidget *parent = 0);
|
explicit TableEditor(const QString &tableName, QWidget *parent = nullptr);
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
void submit();
|
void submit();
|
||||||
|
@ -70,12 +70,12 @@ static bool createConnection()
|
|||||||
QSqlDatabase db = QSqlDatabase::addDatabase("QSQLITE");
|
QSqlDatabase db = QSqlDatabase::addDatabase("QSQLITE");
|
||||||
db.setDatabaseName(":memory:");
|
db.setDatabaseName(":memory:");
|
||||||
if (!db.open()) {
|
if (!db.open()) {
|
||||||
QMessageBox::critical(0, qApp->tr("Cannot open database"),
|
QMessageBox::critical(nullptr, QObject::tr("Cannot open database"),
|
||||||
qApp->tr("Unable to establish a database connection.\n"
|
QObject::tr("Unable to establish a database connection.\n"
|
||||||
"This example needs SQLite support. Please read "
|
"This example needs SQLite support. Please read "
|
||||||
"the Qt SQL driver documentation for information how "
|
"the Qt SQL driver documentation for information how "
|
||||||
"to build it.\n\n"
|
"to build it.\n\n"
|
||||||
"Click Cancel to exit."), QMessageBox::Cancel);
|
"Click Cancel to exit."), QMessageBox::Cancel);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -172,11 +172,20 @@
|
|||||||
\snippet drilldown/informationwindow.cpp 4
|
\snippet drilldown/informationwindow.cpp 4
|
||||||
|
|
||||||
Finally, we connect the "something's changed" signals in the
|
Finally, we connect the "something's changed" signals in the
|
||||||
editors to our custom \c enableButtons() slot, enabling the users
|
editors to our custom \c enableButtons slot, enabling the users
|
||||||
to either submit or revert their changes. We add all the widgets
|
to either submit or revert their changes.
|
||||||
into a layout, store the item ID and the name of the displayed
|
We need to use lambdas for connecting the \c enableButtons slot
|
||||||
image file for future reference, and set the window title and
|
because its signature does not match \c QTextEdit::textChanged
|
||||||
initial size.
|
and \c QComboBox::currentIndexChanged.
|
||||||
|
Since the latter has another overload with the signature
|
||||||
|
\c {const QString &} and the selected signal would be ambiguous,
|
||||||
|
we need to use \c QOverload<int>::of to select a specific overload
|
||||||
|
for \c currentIndexChanged.
|
||||||
|
|
||||||
|
We add all the widgets into a layout, store the item ID and the
|
||||||
|
name of the displayed image file for future reference, and set
|
||||||
|
the window title and initial size.
|
||||||
|
|
||||||
|
|
||||||
Note that we also set the Qt::Window window flag to indicate that
|
Note that we also set the Qt::Window window flag to indicate that
|
||||||
our widget is in fact a window, with a window system frame and a
|
our widget is in fact a window, with a window system frame and a
|
||||||
@ -389,19 +398,21 @@
|
|||||||
\snippet drilldown/view.cpp 6
|
\snippet drilldown/view.cpp 6
|
||||||
|
|
||||||
The \c showInformation() function is given an \c ImageItem object
|
The \c showInformation() function is given an \c ImageItem object
|
||||||
as argument, and starts off by extracting the item's item
|
as argument, and starts off by extracting the item's item ID.
|
||||||
ID. Then it determines if there already is created an information
|
|
||||||
window for this location. If it is, and the window is visible, it
|
|
||||||
ensures that the window is raised to the top of the widget stack
|
|
||||||
and activated. If the window exists but is hidden, calling its \l
|
|
||||||
{QWidget::}{show()} slot gives the same result.
|
|
||||||
|
|
||||||
|
Then it determines if there already is created an information
|
||||||
|
window for this location.
|
||||||
If no window for the given location exists, we create one by
|
If no window for the given location exists, we create one by
|
||||||
passing the item ID, a pointer to the model, and our view as a
|
passing the item ID, a pointer to the model, and our view as a
|
||||||
parent, to the \c InformationWindow constructor. Note that we
|
parent, to the \c InformationWindow constructor. Note that we
|
||||||
connect the information window's \c imageChanged() signal to \e
|
connect the information window's \c imageChanged() signal to \e
|
||||||
this widget's \c updateImage() slot, before we give it a suitable
|
this widget's \c updateImage() slot, before we give it a suitable
|
||||||
position and add it to the list of existing windows.
|
position and add it to the list of existing windows.
|
||||||
|
If there is a window for the given location, and that window is
|
||||||
|
visible, it ensures that the window is raised to the top of the
|
||||||
|
widget stack and activated. If it is hidden, calling its \l
|
||||||
|
{QWidget::}{show()} slot gives the same result.
|
||||||
|
|
||||||
|
|
||||||
\snippet drilldown/view.cpp 7
|
\snippet drilldown/view.cpp 7
|
||||||
|
|
||||||
|
@ -60,8 +60,8 @@ ImageItem::ImageItem(int id, const QPixmap &pixmap, QGraphicsItem *parent)
|
|||||||
timeLine.setDuration(150);
|
timeLine.setDuration(150);
|
||||||
timeLine.setFrameRange(0, 150);
|
timeLine.setFrameRange(0, 150);
|
||||||
|
|
||||||
connect(&timeLine, SIGNAL(frameChanged(int)), this, SLOT(setFrame(int)));
|
connect(&timeLine, &QTimeLine::frameChanged, this, &ImageItem::setFrame);
|
||||||
connect(&timeLine, SIGNAL(finished()), this, SLOT(updateItemPosition()));
|
connect(&timeLine, &QTimeLine::finished, this, &ImageItem::updateItemPosition);
|
||||||
|
|
||||||
adjust();
|
adjust();
|
||||||
}
|
}
|
||||||
@ -116,7 +116,7 @@ void ImageItem::adjust()
|
|||||||
//! [4]
|
//! [4]
|
||||||
|
|
||||||
//! [5]
|
//! [5]
|
||||||
int ImageItem::id()
|
int ImageItem::id() const
|
||||||
{
|
{
|
||||||
return recordId;
|
return recordId;
|
||||||
}
|
}
|
||||||
|
@ -60,10 +60,10 @@ class ImageItem : public QObject, public QGraphicsPixmapItem
|
|||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
ImageItem(int id, const QPixmap &pixmap, QGraphicsItem *parent = 0);
|
ImageItem(int id, const QPixmap &pixmap, QGraphicsItem *parent = nullptr);
|
||||||
|
|
||||||
void adjust();
|
void adjust();
|
||||||
int id();
|
int id() const;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void hoverEnterEvent(QGraphicsSceneHoverEvent *event) override;
|
void hoverEnterEvent(QGraphicsSceneHoverEvent *event) override;
|
||||||
|
@ -84,10 +84,12 @@ InformationWindow::InformationWindow(int id, QSqlRelationalTableModel *items,
|
|||||||
//! [3]
|
//! [3]
|
||||||
|
|
||||||
//! [4]
|
//! [4]
|
||||||
connect(descriptionEditor, SIGNAL(textChanged()),
|
connect(descriptionEditor, &QTextEdit::textChanged, [=]() {
|
||||||
this, SLOT(enableButtons()));
|
enableButtons();
|
||||||
connect(imageFileEditor, SIGNAL(currentIndexChanged(int)),
|
});
|
||||||
this, SLOT(enableButtons()));
|
connect(imageFileEditor, QOverload<int>::of(&QComboBox::currentIndexChanged), [=]() {
|
||||||
|
enableButtons();
|
||||||
|
});
|
||||||
|
|
||||||
QFormLayout *formLayout = new QFormLayout;
|
QFormLayout *formLayout = new QFormLayout;
|
||||||
formLayout->addRow(itemLabel, itemText);
|
formLayout->addRow(itemLabel, itemText);
|
||||||
@ -109,7 +111,7 @@ InformationWindow::InformationWindow(int id, QSqlRelationalTableModel *items,
|
|||||||
//! [4]
|
//! [4]
|
||||||
|
|
||||||
//! [5]
|
//! [5]
|
||||||
int InformationWindow::id()
|
int InformationWindow::id() const
|
||||||
{
|
{
|
||||||
return itemId;
|
return itemId;
|
||||||
}
|
}
|
||||||
@ -149,9 +151,9 @@ void InformationWindow::createButtons()
|
|||||||
|
|
||||||
closeButton->setDefault(true);
|
closeButton->setDefault(true);
|
||||||
|
|
||||||
connect(closeButton, SIGNAL(clicked()), this, SLOT(close()));
|
connect(closeButton, &QPushButton::clicked, this, &InformationWindow::close);
|
||||||
connect(revertButton, SIGNAL(clicked()), this, SLOT(revert()));
|
connect(revertButton, &QPushButton::clicked, this, &InformationWindow::revert);
|
||||||
connect(submitButton, SIGNAL(clicked()), this, SLOT(submit()));
|
connect(submitButton, &QPushButton::clicked, this, &InformationWindow::submit);
|
||||||
//! [8]
|
//! [8]
|
||||||
|
|
||||||
//! [9]
|
//! [9]
|
||||||
|
@ -61,9 +61,9 @@ class InformationWindow : public QDialog
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
InformationWindow(int id, QSqlRelationalTableModel *items,
|
InformationWindow(int id, QSqlRelationalTableModel *items,
|
||||||
QWidget *parent = 0);
|
QWidget *parent = nullptr);
|
||||||
|
|
||||||
int id();
|
int id() const;
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void imageChanged(int id, const QString &fileName);
|
void imageChanged(int id, const QString &fileName);
|
||||||
@ -83,16 +83,16 @@ private:
|
|||||||
int itemId;
|
int itemId;
|
||||||
QString displayedImage;
|
QString displayedImage;
|
||||||
|
|
||||||
QComboBox *imageFileEditor;
|
QComboBox *imageFileEditor = nullptr;
|
||||||
QLabel *itemText;
|
QLabel *itemText = nullptr;
|
||||||
QTextEdit *descriptionEditor;
|
QTextEdit *descriptionEditor = nullptr;
|
||||||
|
|
||||||
QPushButton *closeButton;
|
QPushButton *closeButton = nullptr;
|
||||||
QPushButton *submitButton;
|
QPushButton *submitButton = nullptr;
|
||||||
QPushButton *revertButton;
|
QPushButton *revertButton = nullptr;
|
||||||
QDialogButtonBox *buttonBox;
|
QDialogButtonBox *buttonBox = nullptr;
|
||||||
|
|
||||||
QDataWidgetMapper *mapper;
|
QDataWidgetMapper *mapper = nullptr;
|
||||||
};
|
};
|
||||||
//! [2]
|
//! [2]
|
||||||
|
|
||||||
|
@ -48,10 +48,13 @@
|
|||||||
**
|
**
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
#include <QtWidgets>
|
|
||||||
|
|
||||||
#include "../connection.h"
|
|
||||||
#include "view.h"
|
#include "view.h"
|
||||||
|
#include "../connection.h"
|
||||||
|
|
||||||
|
#include <QApplication>
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
|
||||||
int main(int argc, char *argv[])
|
int main(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
@ -60,7 +63,7 @@ int main(int argc, char *argv[])
|
|||||||
QApplication app(argc, argv);
|
QApplication app(argc, argv);
|
||||||
|
|
||||||
if (!createConnection())
|
if (!createConnection())
|
||||||
return 1;
|
return EXIT_FAILURE;
|
||||||
|
|
||||||
View view("items", "images");
|
View view("items", "images");
|
||||||
view.show();
|
view.show();
|
||||||
|
@ -89,8 +89,6 @@ void View::addItems()
|
|||||||
int topMargin = 40;
|
int topMargin = 40;
|
||||||
|
|
||||||
for (int i = 0; i < itemCount; i++) {
|
for (int i = 0; i < itemCount; i++) {
|
||||||
ImageItem *image;
|
|
||||||
QGraphicsTextItem *label;
|
|
||||||
QSqlRecord record = itemTable->record(i);
|
QSqlRecord record = itemTable->record(i);
|
||||||
|
|
||||||
int id = record.value("id").toInt();
|
int id = record.value("id").toInt();
|
||||||
@ -101,12 +99,12 @@ void View::addItems()
|
|||||||
int x = ((i % 2) * imageOffset) + leftMargin + columnOffset;
|
int x = ((i % 2) * imageOffset) + leftMargin + columnOffset;
|
||||||
int y = ((i / 2) * imageOffset) + topMargin;
|
int y = ((i / 2) * imageOffset) + topMargin;
|
||||||
|
|
||||||
image = new ImageItem(id, QPixmap(":/" + file));
|
ImageItem *image = new ImageItem(id, QPixmap(":/" + file));
|
||||||
image->setData(0, i);
|
image->setData(0, i);
|
||||||
image->setPos(x, y);
|
image->setPos(x, y);
|
||||||
scene->addItem(image);
|
scene->addItem(image);
|
||||||
|
|
||||||
label = scene->addText(item);
|
QGraphicsTextItem *label = scene->addText(item);
|
||||||
label->setDefaultTextColor(QColor("#d7d6d5"));
|
label->setDefaultTextColor(QColor("#d7d6d5"));
|
||||||
QPointF labelOffset((120 - label->boundingRect().width()) / 2, 120.0);
|
QPointF labelOffset((120 - label->boundingRect().width()) / 2, 120.0);
|
||||||
label->setPos(QPointF(x, y) + labelOffset);
|
label->setPos(QPointF(x, y) + labelOffset);
|
||||||
@ -133,22 +131,22 @@ void View::showInformation(ImageItem *image)
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
InformationWindow *window = findWindow(id);
|
InformationWindow *window = findWindow(id);
|
||||||
if (window && window->isVisible()) {
|
if (!window) {
|
||||||
window->raise();
|
|
||||||
window->activateWindow();
|
|
||||||
} else if (window && !window->isVisible()) {
|
|
||||||
window->show();
|
|
||||||
} else {
|
|
||||||
InformationWindow *window;
|
|
||||||
window = new InformationWindow(id, itemTable, this);
|
window = new InformationWindow(id, itemTable, this);
|
||||||
|
|
||||||
connect(window, SIGNAL(imageChanged(int,QString)),
|
connect(window, QOverload<int,const QString &>::of(&InformationWindow::imageChanged),
|
||||||
this, SLOT(updateImage(int,QString)));
|
this, QOverload<int,const QString &>::of(&View::updateImage));
|
||||||
|
|
||||||
window->move(pos() + QPoint(20, 40));
|
window->move(pos() + QPoint(20, 40));
|
||||||
window->show();
|
window->show();
|
||||||
informationWindows.append(window);
|
informationWindows.append(window);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (window->isVisible()) {
|
||||||
|
window->raise();
|
||||||
|
window->activateWindow();
|
||||||
|
} else
|
||||||
|
window->show();
|
||||||
}
|
}
|
||||||
//! [6]
|
//! [6]
|
||||||
|
|
||||||
@ -172,19 +170,13 @@ void View::updateImage(int id, const QString &fileName)
|
|||||||
//! [7]
|
//! [7]
|
||||||
|
|
||||||
//! [8]
|
//! [8]
|
||||||
InformationWindow* View::findWindow(int id)
|
InformationWindow *View::findWindow(int id) const
|
||||||
{
|
{
|
||||||
QList<InformationWindow*>::iterator i, beginning, end;
|
for (auto window : informationWindows) {
|
||||||
|
|
||||||
beginning = informationWindows.begin();
|
|
||||||
end = informationWindows.end();
|
|
||||||
|
|
||||||
for (i = beginning; i != end; ++i) {
|
|
||||||
InformationWindow *window = (*i);
|
|
||||||
if (window && (window->id() == id))
|
if (window && (window->id() == id))
|
||||||
return window;
|
return window;
|
||||||
}
|
}
|
||||||
return 0;
|
return nullptr;
|
||||||
}
|
}
|
||||||
//! [8]
|
//! [8]
|
||||||
|
|
||||||
|
@ -63,7 +63,7 @@ class View : public QGraphicsView
|
|||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
View(const QString &items, const QString &images, QWidget *parent = 0);
|
View(const QString &items, const QString &images, QWidget *parent = nullptr);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void mouseReleaseEvent(QMouseEvent *event) override;
|
void mouseReleaseEvent(QMouseEvent *event) override;
|
||||||
@ -77,7 +77,7 @@ private slots:
|
|||||||
//! [2]
|
//! [2]
|
||||||
private:
|
private:
|
||||||
void addItems();
|
void addItems();
|
||||||
InformationWindow* findWindow(int id);
|
InformationWindow *findWindow(int id) const;
|
||||||
void showInformation(ImageItem *image);
|
void showInformation(ImageItem *image);
|
||||||
|
|
||||||
QGraphicsScene *scene;
|
QGraphicsScene *scene;
|
||||||
|
@ -61,12 +61,12 @@ static bool createConnection()
|
|||||||
QSqlDatabase db = QSqlDatabase::addDatabase("QSQLITE");
|
QSqlDatabase db = QSqlDatabase::addDatabase("QSQLITE");
|
||||||
db.setDatabaseName(":memory:");
|
db.setDatabaseName(":memory:");
|
||||||
if (!db.open()) {
|
if (!db.open()) {
|
||||||
QMessageBox::critical(0, qApp->tr("Cannot open database"),
|
QMessageBox::critical(nullptr, QObject::tr("Cannot open database"),
|
||||||
qApp->tr("Unable to establish a database connection.\n"
|
QObject::tr("Unable to establish a database connection.\n"
|
||||||
"This example needs SQLite support. Please read "
|
"This example needs SQLite support. Please read "
|
||||||
"the Qt SQL driver documentation for information how "
|
"the Qt SQL driver documentation for information how "
|
||||||
"to build it.\n\n"
|
"to build it.\n\n"
|
||||||
"Click Cancel to exit."), QMessageBox::Cancel);
|
"Click Cancel to exit."), QMessageBox::Cancel);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -155,12 +155,12 @@ int Dialog::addNewAlbum(const QString &title, int artistId)
|
|||||||
return id;
|
return id;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Dialog::addTracks(int albumId, QStringList tracks)
|
void Dialog::addTracks(int albumId, const QStringList &tracks)
|
||||||
{
|
{
|
||||||
QDomElement albumNode = albumDetails.createElement("album");
|
QDomElement albumNode = albumDetails.createElement("album");
|
||||||
albumNode.setAttribute("id", albumId);
|
albumNode.setAttribute("id", albumId);
|
||||||
|
|
||||||
for (int i = 0; i < tracks.count(); i++) {
|
for (int i = 0; i < tracks.count(); ++i) {
|
||||||
QString trackNumber = QString::number(i);
|
QString trackNumber = QString::number(i);
|
||||||
if (i < 10)
|
if (i < 10)
|
||||||
trackNumber.prepend('0');
|
trackNumber.prepend('0');
|
||||||
@ -254,9 +254,9 @@ QDialogButtonBox *Dialog::createButtons()
|
|||||||
|
|
||||||
closeButton->setDefault(true);
|
closeButton->setDefault(true);
|
||||||
|
|
||||||
connect(closeButton, SIGNAL(clicked()), this, SLOT(close()));
|
connect(closeButton, &QPushButton::clicked, this, &Dialog::close);
|
||||||
connect(revertButton, SIGNAL(clicked()), this, SLOT(revert()));
|
connect(revertButton, &QPushButton::clicked, this, &Dialog::revert);
|
||||||
connect(submitButton, SIGNAL(clicked()), this, SLOT(submit()));
|
connect(submitButton, &QPushButton::clicked, this, &Dialog::submit);
|
||||||
|
|
||||||
QDialogButtonBox *buttonBox = new QDialogButtonBox;
|
QDialogButtonBox *buttonBox = new QDialogButtonBox;
|
||||||
buttonBox->addButton(submitButton, QDialogButtonBox::ResetRole);
|
buttonBox->addButton(submitButton, QDialogButtonBox::ResetRole);
|
||||||
@ -270,7 +270,7 @@ QModelIndex Dialog::indexOfArtist(const QString &artist)
|
|||||||
{
|
{
|
||||||
QSqlTableModel *artistModel = model->relationModel(2);
|
QSqlTableModel *artistModel = model->relationModel(2);
|
||||||
|
|
||||||
for (int i = 0; i < artistModel->rowCount(); i++) {
|
for (int i = 0; i < artistModel->rowCount(); ++i) {
|
||||||
QSqlRecord record = artistModel->record(i);
|
QSqlRecord record = artistModel->record(i);
|
||||||
if (record.value("artist") == artist)
|
if (record.value("artist") == artist)
|
||||||
return artistModel->index(i, 1);
|
return artistModel->index(i, 1);
|
||||||
|
@ -61,7 +61,7 @@ class Dialog : public QDialog
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
Dialog(QSqlRelationalTableModel *albums, QDomDocument details,
|
Dialog(QSqlRelationalTableModel *albums, QDomDocument details,
|
||||||
QFile *output, QWidget *parent = 0);
|
QFile *output, QWidget *parent = nullptr);
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
void revert();
|
void revert();
|
||||||
@ -70,12 +70,12 @@ private slots:
|
|||||||
private:
|
private:
|
||||||
int addNewAlbum(const QString &title, int artistId);
|
int addNewAlbum(const QString &title, int artistId);
|
||||||
int addNewArtist(const QString &name);
|
int addNewArtist(const QString &name);
|
||||||
void addTracks(int albumId, QStringList tracks);
|
void addTracks(int albumId, const QStringList &tracks);
|
||||||
QDialogButtonBox *createButtons();
|
QDialogButtonBox *createButtons();
|
||||||
QGroupBox *createInputWidgets();
|
QGroupBox *createInputWidgets();
|
||||||
int findArtistId(const QString &artist);
|
int findArtistId(const QString &artist);
|
||||||
int generateAlbumId();
|
static int generateAlbumId();
|
||||||
int generateArtistId();
|
static int generateArtistId();
|
||||||
void increaseAlbumCount(QModelIndex artistIndex);
|
void increaseAlbumCount(QModelIndex artistIndex);
|
||||||
QModelIndex indexOfArtist(const QString &artist);
|
QModelIndex indexOfArtist(const QString &artist);
|
||||||
|
|
||||||
|
@ -48,11 +48,14 @@
|
|||||||
**
|
**
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
#include <QtWidgets>
|
|
||||||
|
|
||||||
#include "database.h"
|
#include "database.h"
|
||||||
#include "mainwindow.h"
|
#include "mainwindow.h"
|
||||||
|
|
||||||
|
#include <QApplication>
|
||||||
|
#include <QFile>
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
int main(int argc, char *argv[])
|
int main(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
Q_INIT_RESOURCE(masterdetail);
|
Q_INIT_RESOURCE(masterdetail);
|
||||||
@ -60,10 +63,10 @@ int main(int argc, char *argv[])
|
|||||||
QApplication app(argc, argv);
|
QApplication app(argc, argv);
|
||||||
|
|
||||||
if (!createConnection())
|
if (!createConnection())
|
||||||
return 1;
|
return EXIT_FAILURE;
|
||||||
|
|
||||||
QFile *albumDetails = new QFile("albumdetails.xml");
|
QFile albumDetails("albumdetails.xml");
|
||||||
MainWindow window("artists", "albums", albumDetails);
|
MainWindow window("artists", "albums", &albumDetails);
|
||||||
window.show();
|
window.show();
|
||||||
return app.exec();
|
return app.exec();
|
||||||
}
|
}
|
||||||
|
@ -78,10 +78,10 @@ MainWindow::MainWindow(const QString &artistTable, const QString &albumTable,
|
|||||||
uniqueAlbumId = model->rowCount();
|
uniqueAlbumId = model->rowCount();
|
||||||
uniqueArtistId = artistView->count();
|
uniqueArtistId = artistView->count();
|
||||||
|
|
||||||
connect(model, SIGNAL(rowsInserted(QModelIndex,int,int)),
|
connect(model, &QSqlRelationalTableModel::rowsInserted,
|
||||||
this, SLOT(updateHeader(QModelIndex,int,int)));
|
this, &MainWindow::updateHeader);
|
||||||
connect(model, SIGNAL(rowsRemoved(QModelIndex,int,int)),
|
connect(model, &QSqlRelationalTableModel::rowsRemoved,
|
||||||
this, SLOT(updateHeader(QModelIndex,int,int)));
|
this, &MainWindow::updateHeader);
|
||||||
|
|
||||||
QGridLayout *layout = new QGridLayout;
|
QGridLayout *layout = new QGridLayout;
|
||||||
layout->addWidget(artists, 0, 0);
|
layout->addWidget(artists, 0, 0);
|
||||||
@ -145,7 +145,7 @@ void MainWindow::showAlbumDetails(QModelIndex index)
|
|||||||
titleLabel->show();
|
titleLabel->show();
|
||||||
|
|
||||||
QDomNodeList albums = albumData.elementsByTagName("album");
|
QDomNodeList albums = albumData.elementsByTagName("album");
|
||||||
for (int i = 0; i < albums.count(); i++) {
|
for (int i = 0; i < albums.count(); ++i) {
|
||||||
QDomNode album = albums.item(i);
|
QDomNode album = albums.item(i);
|
||||||
if (album.toElement().attribute("id") == albumId) {
|
if (album.toElement().attribute("id") == albumId) {
|
||||||
getTrackList(album.toElement());
|
getTrackList(album.toElement());
|
||||||
@ -164,9 +164,9 @@ void MainWindow::getTrackList(QDomNode album)
|
|||||||
QDomNode track;
|
QDomNode track;
|
||||||
QString trackNumber;
|
QString trackNumber;
|
||||||
|
|
||||||
for (int j = 0; j < tracks.count(); j++) {
|
for (int i = 0; i < tracks.count(); ++i) {
|
||||||
|
|
||||||
track = tracks.item(j);
|
track = tracks.item(i);
|
||||||
trackNumber = track.toElement().attribute("number");
|
trackNumber = track.toElement().attribute("number");
|
||||||
|
|
||||||
QListWidgetItem *item = new QListWidgetItem(trackList);
|
QListWidgetItem *item = new QListWidgetItem(trackList);
|
||||||
@ -222,7 +222,7 @@ void MainWindow::removeAlbumFromFile(int id)
|
|||||||
|
|
||||||
QDomNodeList albums = albumData.elementsByTagName("album");
|
QDomNodeList albums = albumData.elementsByTagName("album");
|
||||||
|
|
||||||
for (int i = 0; i < albums.count(); i++) {
|
for (int i = 0; i < albums.count(); ++i) {
|
||||||
QDomNode node = albums.item(i);
|
QDomNode node = albums.item(i);
|
||||||
if (node.toElement().attribute("id").toInt() == id) {
|
if (node.toElement().attribute("id").toInt() == id) {
|
||||||
albumData.elementsByTagName("archive").item(0).removeChild(node);
|
albumData.elementsByTagName("archive").item(0).removeChild(node);
|
||||||
@ -283,8 +283,8 @@ QGroupBox* MainWindow::createArtistGroupBox()
|
|||||||
artistView->setModel(model->relationModel(2));
|
artistView->setModel(model->relationModel(2));
|
||||||
artistView->setModelColumn(1);
|
artistView->setModelColumn(1);
|
||||||
|
|
||||||
connect(artistView, SIGNAL(currentIndexChanged(int)),
|
connect(artistView, QOverload<int>::of(&QComboBox::currentIndexChanged),
|
||||||
this, SLOT(changeArtist(int)));
|
this, &MainWindow::changeArtist);
|
||||||
|
|
||||||
QGroupBox *box = new QGroupBox(tr("Artist"));
|
QGroupBox *box = new QGroupBox(tr("Artist"));
|
||||||
|
|
||||||
@ -314,10 +314,10 @@ QGroupBox* MainWindow::createAlbumGroupBox()
|
|||||||
locale.setNumberOptions(QLocale::OmitGroupSeparator);
|
locale.setNumberOptions(QLocale::OmitGroupSeparator);
|
||||||
albumView->setLocale(locale);
|
albumView->setLocale(locale);
|
||||||
|
|
||||||
connect(albumView, SIGNAL(clicked(QModelIndex)),
|
connect(albumView, &QTableView::clicked,
|
||||||
this, SLOT(showAlbumDetails(QModelIndex)));
|
this, &MainWindow::showAlbumDetails);
|
||||||
connect(albumView, SIGNAL(activated(QModelIndex)),
|
connect(albumView, &QTableView::activated,
|
||||||
this, SLOT(showAlbumDetails(QModelIndex)));
|
this, &MainWindow::showAlbumDetails);
|
||||||
|
|
||||||
QVBoxLayout *layout = new QVBoxLayout;
|
QVBoxLayout *layout = new QVBoxLayout;
|
||||||
layout->addWidget(albumView, 0, 0);
|
layout->addWidget(albumView, 0, 0);
|
||||||
@ -383,11 +383,16 @@ void MainWindow::createMenuBar()
|
|||||||
helpMenu->addAction(aboutAction);
|
helpMenu->addAction(aboutAction);
|
||||||
helpMenu->addAction(aboutQtAction);
|
helpMenu->addAction(aboutQtAction);
|
||||||
|
|
||||||
connect(addAction, SIGNAL(triggered(bool)), this, SLOT(addAlbum()));
|
connect(addAction, &QAction::triggered,
|
||||||
connect(deleteAction, SIGNAL(triggered(bool)), this, SLOT(deleteAlbum()));
|
this, &MainWindow::addAlbum);
|
||||||
connect(quitAction, SIGNAL(triggered(bool)), this, SLOT(close()));
|
connect(deleteAction, &QAction::triggered,
|
||||||
connect(aboutAction, SIGNAL(triggered(bool)), this, SLOT(about()));
|
this, &MainWindow::deleteAlbum);
|
||||||
connect(aboutQtAction, SIGNAL(triggered(bool)), qApp, SLOT(aboutQt()));
|
connect(quitAction, &QAction::triggered,
|
||||||
|
this, &MainWindow::close);
|
||||||
|
connect(aboutAction, &QAction::triggered,
|
||||||
|
this, &MainWindow::about);
|
||||||
|
connect(aboutQtAction, &QAction::triggered,
|
||||||
|
qApp, &QApplication::aboutQt);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainWindow::showImageLabel()
|
void MainWindow::showImageLabel()
|
||||||
|
@ -71,7 +71,7 @@ class MainWindow : public QMainWindow
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
MainWindow(const QString &artistTable, const QString &albumTable,
|
MainWindow(const QString &artistTable, const QString &albumTable,
|
||||||
QFile *albumDetails, QWidget *parent = 0);
|
QFile *albumDetails, QWidget *parent = nullptr);
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
void about();
|
void about();
|
||||||
|
@ -59,7 +59,7 @@ class CustomSqlModel : public QSqlQueryModel
|
|||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
CustomSqlModel(QObject *parent = 0);
|
CustomSqlModel(QObject *parent = nullptr);
|
||||||
|
|
||||||
QVariant data(const QModelIndex &item, int role) const override;
|
QVariant data(const QModelIndex &item, int role) const override;
|
||||||
};
|
};
|
||||||
|
@ -58,7 +58,7 @@ class EditableSqlModel : public QSqlQueryModel
|
|||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
EditableSqlModel(QObject *parent = 0);
|
EditableSqlModel(QObject *parent = nullptr);
|
||||||
|
|
||||||
Qt::ItemFlags flags(const QModelIndex &index) const override;
|
Qt::ItemFlags flags(const QModelIndex &index) const override;
|
||||||
bool setData(const QModelIndex &index, const QVariant &value, int role) override;
|
bool setData(const QModelIndex &index, const QVariant &value, int role) override;
|
||||||
|
@ -48,12 +48,15 @@
|
|||||||
**
|
**
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
#include <QtWidgets>
|
|
||||||
|
|
||||||
#include "../connection.h"
|
#include "../connection.h"
|
||||||
#include "customsqlmodel.h"
|
#include "customsqlmodel.h"
|
||||||
#include "editablesqlmodel.h"
|
#include "editablesqlmodel.h"
|
||||||
|
|
||||||
|
#include <QApplication>
|
||||||
|
#include <QTableView>
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
void initializeModel(QSqlQueryModel *model)
|
void initializeModel(QSqlQueryModel *model)
|
||||||
{
|
{
|
||||||
model->setQuery("select * from person");
|
model->setQuery("select * from person");
|
||||||
@ -80,7 +83,7 @@ int main(int argc, char *argv[])
|
|||||||
{
|
{
|
||||||
QApplication app(argc, argv);
|
QApplication app(argc, argv);
|
||||||
if (!createConnection())
|
if (!createConnection())
|
||||||
return 1;
|
return EXIT_FAILURE;
|
||||||
|
|
||||||
QSqlQueryModel plainModel;
|
QSqlQueryModel plainModel;
|
||||||
EditableSqlModel editableModel;
|
EditableSqlModel editableModel;
|
||||||
|
@ -110,7 +110,8 @@ int main(int argc, char *argv[])
|
|||||||
{
|
{
|
||||||
QApplication app(argc, argv);
|
QApplication app(argc, argv);
|
||||||
if (!createConnection())
|
if (!createConnection())
|
||||||
return 1;
|
return EXIT_FAILURE;
|
||||||
|
|
||||||
createRelationalTables();
|
createRelationalTables();
|
||||||
|
|
||||||
QSqlRelationalTableModel model;
|
QSqlRelationalTableModel model;
|
||||||
|
@ -165,11 +165,12 @@ void Browser::showTable(const QString &t)
|
|||||||
model->select();
|
model->select();
|
||||||
if (model->lastError().type() != QSqlError::NoError)
|
if (model->lastError().type() != QSqlError::NoError)
|
||||||
emit statusMessage(model->lastError().text());
|
emit statusMessage(model->lastError().text());
|
||||||
|
|
||||||
table->setModel(model);
|
table->setModel(model);
|
||||||
table->setEditTriggers(QAbstractItemView::DoubleClicked|QAbstractItemView::EditKeyPressed);
|
table->setEditTriggers(QAbstractItemView::DoubleClicked|QAbstractItemView::EditKeyPressed);
|
||||||
|
connect(table->selectionModel(), &QItemSelectionModel::currentRowChanged,
|
||||||
|
this, &Browser::currentChanged);
|
||||||
|
|
||||||
connect(table->selectionModel(), SIGNAL(currentRowChanged(QModelIndex,QModelIndex)),
|
|
||||||
this, SLOT(currentChanged()));
|
|
||||||
updateActions();
|
updateActions();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -189,7 +190,6 @@ void Browser::showMetaData(const QString &t)
|
|||||||
model->setHeaderData(5, Qt::Horizontal, "AutoValue");
|
model->setHeaderData(5, Qt::Horizontal, "AutoValue");
|
||||||
model->setHeaderData(6, Qt::Horizontal, "DefaultValue");
|
model->setHeaderData(6, Qt::Horizontal, "DefaultValue");
|
||||||
|
|
||||||
|
|
||||||
for (int i = 0; i < rec.count(); ++i) {
|
for (int i = 0; i < rec.count(); ++i) {
|
||||||
QSqlField fld = rec.field(i);
|
QSqlField fld = rec.field(i);
|
||||||
model->setData(model->index(i, 0), fld.name());
|
model->setData(model->index(i, 0), fld.name());
|
||||||
|
@ -65,7 +65,7 @@ class Browser: public QWidget, private Ui::Browser
|
|||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
Browser(QWidget *parent = 0);
|
Browser(QWidget *parent = nullptr);
|
||||||
virtual ~Browser();
|
virtual ~Browser();
|
||||||
|
|
||||||
QSqlError addConnection(const QString &driver, const QString &dbName, const QString &host,
|
QSqlError addConnection(const QString &driver, const QString &dbName, const QString &host,
|
||||||
@ -116,7 +116,9 @@ class CustomModel: public QSqlTableModel
|
|||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
explicit CustomModel(QObject *parent = 0, QSqlDatabase db = QSqlDatabase()):QSqlTableModel(parent, db) {}
|
explicit CustomModel(QObject *parent = nullptr, QSqlDatabase db = QSqlDatabase())
|
||||||
|
: QSqlTableModel(parent, db) {}
|
||||||
|
|
||||||
QVariant data(const QModelIndex &idx, int role) const override
|
QVariant data(const QModelIndex &idx, int role) const override
|
||||||
{
|
{
|
||||||
if (role == Qt::BackgroundRole && isDirty(idx))
|
if (role == Qt::BackgroundRole && isDirty(idx))
|
||||||
|
@ -63,8 +63,8 @@ ConnectionWidget::ConnectionWidget(QWidget *parent)
|
|||||||
tree->header()->setSectionResizeMode(QHeaderView::Stretch);
|
tree->header()->setSectionResizeMode(QHeaderView::Stretch);
|
||||||
QAction *refreshAction = new QAction(tr("Refresh"), tree);
|
QAction *refreshAction = new QAction(tr("Refresh"), tree);
|
||||||
metaDataAction = new QAction(tr("Show Schema"), tree);
|
metaDataAction = new QAction(tr("Show Schema"), tree);
|
||||||
connect(refreshAction, SIGNAL(triggered()), SLOT(refresh()));
|
connect(refreshAction, &QAction::triggered, this, &ConnectionWidget::refresh);
|
||||||
connect(metaDataAction, SIGNAL(triggered()), SLOT(showMetaData()));
|
connect(metaDataAction, &QAction::triggered, this, &ConnectionWidget::showMetaData);
|
||||||
tree->addAction(refreshAction);
|
tree->addAction(refreshAction);
|
||||||
tree->addAction(metaDataAction);
|
tree->addAction(metaDataAction);
|
||||||
tree->setContextMenuPolicy(Qt::ActionsContextMenu);
|
tree->setContextMenuPolicy(Qt::ActionsContextMenu);
|
||||||
@ -146,7 +146,6 @@ void ConnectionWidget::setActive(QTreeWidgetItem *item)
|
|||||||
|
|
||||||
void ConnectionWidget::on_tree_itemActivated(QTreeWidgetItem *item, int /* column */)
|
void ConnectionWidget::on_tree_itemActivated(QTreeWidgetItem *item, int /* column */)
|
||||||
{
|
{
|
||||||
|
|
||||||
if (!item)
|
if (!item)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
@ -62,7 +62,7 @@ class ConnectionWidget: public QWidget
|
|||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
ConnectionWidget(QWidget *parent = 0);
|
ConnectionWidget(QWidget *parent = nullptr);
|
||||||
virtual ~ConnectionWidget();
|
virtual ~ConnectionWidget();
|
||||||
|
|
||||||
QSqlDatabase currentDatabase() const;
|
QSqlDatabase currentDatabase() const;
|
||||||
|
@ -80,16 +80,18 @@ int main(int argc, char *argv[])
|
|||||||
mainWin.setCentralWidget(&browser);
|
mainWin.setCentralWidget(&browser);
|
||||||
|
|
||||||
QMenu *fileMenu = mainWin.menuBar()->addMenu(QObject::tr("&File"));
|
QMenu *fileMenu = mainWin.menuBar()->addMenu(QObject::tr("&File"));
|
||||||
fileMenu->addAction(QObject::tr("Add &Connection..."), &browser, SLOT(addConnection()));
|
fileMenu->addAction(QObject::tr("Add &Connection..."),
|
||||||
|
[&]() { browser.addConnection(); });
|
||||||
fileMenu->addSeparator();
|
fileMenu->addSeparator();
|
||||||
fileMenu->addAction(QObject::tr("&Quit"), &app, SLOT(quit()));
|
fileMenu->addAction(QObject::tr("&Quit"), []() { qApp->quit(); });
|
||||||
|
|
||||||
QMenu *helpMenu = mainWin.menuBar()->addMenu(QObject::tr("&Help"));
|
QMenu *helpMenu = mainWin.menuBar()->addMenu(QObject::tr("&Help"));
|
||||||
helpMenu->addAction(QObject::tr("About"), &browser, SLOT(about()));
|
helpMenu->addAction(QObject::tr("About"), [&]() { browser.about(); });
|
||||||
helpMenu->addAction(QObject::tr("About Qt"), qApp, SLOT(aboutQt()));
|
helpMenu->addAction(QObject::tr("About Qt"), []() { qApp->aboutQt(); });
|
||||||
|
|
||||||
QObject::connect(&browser, SIGNAL(statusMessage(QString)),
|
QObject::connect(&browser, &Browser::statusMessage, [&mainWin](const QString &text) {
|
||||||
mainWin.statusBar(), SLOT(showMessage(QString)));
|
mainWin.statusBar()->showMessage(text);
|
||||||
|
});
|
||||||
|
|
||||||
addConnectionsFromCommandline(app.arguments(), &browser);
|
addConnectionsFromCommandline(app.arguments(), &browser);
|
||||||
mainWin.show();
|
mainWin.show();
|
||||||
|
@ -60,7 +60,7 @@ class QSqlConnectionDialog: public QDialog
|
|||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
QSqlConnectionDialog(QWidget *parent = 0);
|
QSqlConnectionDialog(QWidget *parent = nullptr);
|
||||||
~QSqlConnectionDialog();
|
~QSqlConnectionDialog();
|
||||||
|
|
||||||
QString driverName() const;
|
QString driverName() const;
|
||||||
|
@ -87,12 +87,12 @@ Window::Window(QWidget *parent)
|
|||||||
//! [Set up the mapper]
|
//! [Set up the mapper]
|
||||||
|
|
||||||
//! [Set up connections and layouts]
|
//! [Set up connections and layouts]
|
||||||
connect(previousButton, SIGNAL(clicked()),
|
connect(previousButton, &QPushButton::clicked,
|
||||||
mapper, SLOT(toPrevious()));
|
mapper, &QDataWidgetMapper::toPrevious);
|
||||||
connect(nextButton, SIGNAL(clicked()),
|
connect(nextButton, &QPushButton::clicked,
|
||||||
mapper, SLOT(toNext()));
|
mapper, &QDataWidgetMapper::toNext);
|
||||||
connect(mapper, SIGNAL(currentIndexChanged(int)),
|
connect(mapper, &QDataWidgetMapper::currentIndexChanged,
|
||||||
this, SLOT(updateButtons(int)));
|
this, &Window::updateButtons);
|
||||||
|
|
||||||
QGridLayout *layout = new QGridLayout();
|
QGridLayout *layout = new QGridLayout();
|
||||||
layout->addWidget(nameLabel, 0, 0, 1, 1);
|
layout->addWidget(nameLabel, 0, 0, 1, 1);
|
||||||
|
@ -72,7 +72,7 @@ class Window : public QWidget
|
|||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Window(QWidget *parent = 0);
|
Window(QWidget *parent = nullptr);
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
void updateButtons(int row);
|
void updateButtons(int row);
|
||||||
|
@ -47,12 +47,14 @@
|
|||||||
** $QT_END_LICENSE$
|
** $QT_END_LICENSE$
|
||||||
**
|
**
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
#include <QtWidgets>
|
|
||||||
#include <QtSql>
|
|
||||||
|
|
||||||
#include "../connection.h"
|
#include "../connection.h"
|
||||||
|
|
||||||
|
#include <QApplication>
|
||||||
|
#include <QSqlTableModel>
|
||||||
|
#include <QTableView>
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
void initializeModel(QSqlTableModel *model)
|
void initializeModel(QSqlTableModel *model)
|
||||||
{
|
{
|
||||||
model->setTable("person");
|
model->setTable("person");
|
||||||
@ -76,7 +78,7 @@ int main(int argc, char *argv[])
|
|||||||
{
|
{
|
||||||
QApplication app(argc, argv);
|
QApplication app(argc, argv);
|
||||||
if (!createConnection())
|
if (!createConnection())
|
||||||
return 1;
|
return EXIT_FAILURE;
|
||||||
|
|
||||||
QSqlTableModel model;
|
QSqlTableModel model;
|
||||||
|
|
||||||
|
@ -14,4 +14,3 @@ SUBDIRS = classwizard \
|
|||||||
!qtConfig(wizard) {
|
!qtConfig(wizard) {
|
||||||
SUBDIRS -= trivialwizard licensewizard classwizard
|
SUBDIRS -= trivialwizard licensewizard classwizard
|
||||||
}
|
}
|
||||||
wince: SUBDIRS += sipdialog
|
|
||||||
|
@ -51,6 +51,7 @@
|
|||||||
|
|
||||||
#include <QtWidgets/QApplication>
|
#include <QtWidgets/QApplication>
|
||||||
#include <QtWidgets/QHeaderView>
|
#include <QtWidgets/QHeaderView>
|
||||||
|
#include <QtWidgets/QShortcut>
|
||||||
#include <QtWidgets/QTreeView>
|
#include <QtWidgets/QTreeView>
|
||||||
|
|
||||||
#include "storagemodel.h"
|
#include "storagemodel.h"
|
||||||
@ -60,9 +61,16 @@ int main(int argc, char *argv[])
|
|||||||
QApplication a(argc, argv);
|
QApplication a(argc, argv);
|
||||||
|
|
||||||
QTreeView view;
|
QTreeView view;
|
||||||
view.setModel(new StorageModel(&view));
|
|
||||||
view.resize(640, 480);
|
view.resize(640, 480);
|
||||||
|
view.setWindowTitle("Storage View");
|
||||||
view.setSelectionBehavior(QAbstractItemView::SelectRows);
|
view.setSelectionBehavior(QAbstractItemView::SelectRows);
|
||||||
|
|
||||||
|
StorageModel *model = new StorageModel(&view);
|
||||||
|
model->refresh();
|
||||||
|
QShortcut *refreshShortcut = new QShortcut(Qt::CTRL + Qt::Key_R, &view);
|
||||||
|
QObject::connect(refreshShortcut, &QShortcut::activated, model, &StorageModel::refresh);
|
||||||
|
view.setModel(model);
|
||||||
|
|
||||||
int columnCount = view.model()->columnCount();
|
int columnCount = view.model()->columnCount();
|
||||||
for (int c = 0; c < columnCount; ++c)
|
for (int c = 0; c < columnCount; ++c)
|
||||||
view.resizeColumnToContents(c);
|
view.resizeColumnToContents(c);
|
||||||
|
@ -54,14 +54,27 @@
|
|||||||
#include <QDir>
|
#include <QDir>
|
||||||
#include <QLocale>
|
#include <QLocale>
|
||||||
#include <qmath.h>
|
#include <qmath.h>
|
||||||
|
#include <algorithm>
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
|
|
||||||
StorageModel::StorageModel(QObject *parent) :
|
StorageModel::StorageModel(QObject *parent) :
|
||||||
QAbstractTableModel(parent),
|
QAbstractTableModel(parent)
|
||||||
m_volumes(QStorageInfo::mountedVolumes())
|
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void StorageModel::refresh()
|
||||||
|
{
|
||||||
|
beginResetModel();
|
||||||
|
m_volumes = QStorageInfo::mountedVolumes();
|
||||||
|
std::sort(m_volumes.begin(), m_volumes.end(),
|
||||||
|
[](const QStorageInfo &st1, const QStorageInfo &st2) {
|
||||||
|
static const QString rootSortString = QStringLiteral(" ");
|
||||||
|
return (st1.isRoot() ? rootSortString : st1.rootPath())
|
||||||
|
< (st2.isRoot() ? rootSortString : st2.rootPath());
|
||||||
|
});
|
||||||
|
endResetModel();
|
||||||
|
}
|
||||||
|
|
||||||
int StorageModel::columnCount(const QModelIndex &/*parent*/) const
|
int StorageModel::columnCount(const QModelIndex &/*parent*/) const
|
||||||
{
|
{
|
||||||
return ColumnCount;
|
return ColumnCount;
|
||||||
@ -74,6 +87,22 @@ int StorageModel::rowCount(const QModelIndex &parent) const
|
|||||||
return m_volumes.count();
|
return m_volumes.count();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Qt::ItemFlags StorageModel::flags(const QModelIndex &index) const
|
||||||
|
{
|
||||||
|
Qt::ItemFlags result = QAbstractTableModel::flags(index);
|
||||||
|
switch (index.column()) {
|
||||||
|
case ColumnAvailable:
|
||||||
|
case ColumnIsReady:
|
||||||
|
case ColumnIsReadOnly:
|
||||||
|
case ColumnIsValid:
|
||||||
|
result |= Qt::ItemIsUserCheckable;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
QVariant StorageModel::data(const QModelIndex &index, int role) const
|
QVariant StorageModel::data(const QModelIndex &index, int role) const
|
||||||
{
|
{
|
||||||
if (!index.isValid())
|
if (!index.isValid())
|
||||||
@ -96,6 +125,12 @@ QVariant StorageModel::data(const QModelIndex &index, int role) const
|
|||||||
return QLocale().formattedDataSize(volume.bytesFree());
|
return QLocale().formattedDataSize(volume.bytesFree());
|
||||||
case ColumnAvailable:
|
case ColumnAvailable:
|
||||||
return QLocale().formattedDataSize(volume.bytesAvailable());
|
return QLocale().formattedDataSize(volume.bytesAvailable());
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} else if (role == Qt::CheckStateRole) {
|
||||||
|
const QStorageInfo &volume = m_volumes.at(index.row());
|
||||||
|
switch (index.column()) {
|
||||||
case ColumnIsReady:
|
case ColumnIsReady:
|
||||||
return volume.isReady();
|
return volume.isReady();
|
||||||
case ColumnIsReadOnly:
|
case ColumnIsReadOnly:
|
||||||
@ -105,6 +140,16 @@ QVariant StorageModel::data(const QModelIndex &index, int role) const
|
|||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
} else if (role == Qt::TextAlignmentRole) {
|
||||||
|
switch (index.column()) {
|
||||||
|
case ColumnTotal:
|
||||||
|
case ColumnFree:
|
||||||
|
case ColumnAvailable:
|
||||||
|
return Qt::AlignTrailing;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return Qt::AlignLeading;
|
||||||
} else if (role == Qt::ToolTipRole) {
|
} else if (role == Qt::ToolTipRole) {
|
||||||
QLocale locale;
|
QLocale locale;
|
||||||
const QStorageInfo &volume = m_volumes.at(index.row());
|
const QStorageInfo &volume = m_volumes.at(index.row());
|
||||||
@ -147,13 +192,13 @@ QVariant StorageModel::headerData(int section, Qt::Orientation orientation, int
|
|||||||
|
|
||||||
switch (section) {
|
switch (section) {
|
||||||
case ColumnRootPath:
|
case ColumnRootPath:
|
||||||
return tr("Root path");
|
return tr("Root Path");
|
||||||
case ColumnName:
|
case ColumnName:
|
||||||
return tr("Volume Name");
|
return tr("Volume Name");
|
||||||
case ColumnDevice:
|
case ColumnDevice:
|
||||||
return tr("Device");
|
return tr("Device");
|
||||||
case ColumnFileSystemName:
|
case ColumnFileSystemName:
|
||||||
return tr("File system");
|
return tr("File System");
|
||||||
case ColumnTotal:
|
case ColumnTotal:
|
||||||
return tr("Total");
|
return tr("Total");
|
||||||
case ColumnFree:
|
case ColumnFree:
|
||||||
|
@ -74,13 +74,17 @@ public:
|
|||||||
ColumnCount
|
ColumnCount
|
||||||
};
|
};
|
||||||
|
|
||||||
explicit StorageModel(QObject *parent = 0);
|
explicit StorageModel(QObject *parent = nullptr);
|
||||||
|
|
||||||
int columnCount(const QModelIndex &parent) const;
|
int columnCount(const QModelIndex &parent) const override;
|
||||||
int rowCount(const QModelIndex &parent) const;
|
int rowCount(const QModelIndex &parent) const override;
|
||||||
|
|
||||||
QVariant data(const QModelIndex &index, int role) const;
|
QVariant data(const QModelIndex &index, int role) const override;
|
||||||
QVariant headerData(int section, Qt::Orientation orientation, int role) const;
|
Qt::ItemFlags flags(const QModelIndex &index) const override;
|
||||||
|
QVariant headerData(int section, Qt::Orientation orientation, int role) const override;
|
||||||
|
|
||||||
|
public slots:
|
||||||
|
void refresh();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QList<QStorageInfo> m_volumes;
|
QList<QStorageInfo> m_volumes;
|
||||||
|
@ -9,16 +9,20 @@ include(../common/linux.conf)
|
|||||||
include(../common/gcc-base-unix.conf)
|
include(../common/gcc-base-unix.conf)
|
||||||
include(../common/android-base-head.conf)
|
include(../common/android-base-head.conf)
|
||||||
|
|
||||||
QMAKE_CC = $$NDK_TOOLCHAIN_PATH/bin/$$NDK_TOOLS_PREFIX-gcc
|
QMAKE_CC = $${CROSS_COMPILE}gcc
|
||||||
QMAKE_CXX = $$NDK_TOOLCHAIN_PATH/bin/$$NDK_TOOLS_PREFIX-g++
|
QMAKE_CXX = $${CROSS_COMPILE}g++
|
||||||
QMAKE_LINK = $$QMAKE_CXX
|
QMAKE_LINK = $$QMAKE_CXX
|
||||||
|
|
||||||
ANDROID_SOURCES_CXX_STL_LIBDIR = $$NDK_ROOT/sources/cxx-stl/gnu-libstdc++/$$NDK_TOOLCHAIN_VERSION/libs/$$ANDROID_TARGET_ARCH
|
ANDROID_SOURCES_CXX_STL_LIBDIR = $$NDK_ROOT/sources/cxx-stl/gnu-libstdc++/$$NDK_TOOLCHAIN_VERSION/libs/$$ANDROID_TARGET_ARCH
|
||||||
ANDROID_STDCPP_PATH = $$ANDROID_SOURCES_CXX_STL_LIBDIR/libgnustl_shared.so
|
ANDROID_STDCPP_PATH = $$ANDROID_SOURCES_CXX_STL_LIBDIR/libgnustl_shared.so
|
||||||
ANDROID_CXX_STL_LIBS = -lgnustl_shared -lgcc
|
ANDROID_CXX_STL_LIBS = -lgnustl_shared -lgcc
|
||||||
|
|
||||||
QMAKE_CFLAGS += --sysroot=$$ANDROID_PLATFORM_ROOT_PATH \
|
exists($$NDK_ROOT/sysroot/usr/include): \
|
||||||
-isystem $$NDK_ROOT/sources/cxx-stl/gnu-libstdc++/$$NDK_TOOLCHAIN_VERSION/include \
|
QMAKE_CFLAGS += --sysroot=$$NDK_ROOT/sysroot \
|
||||||
|
-isystem $$NDK_ROOT/sysroot/usr/include/$$NDK_TOOLS_PREFIX
|
||||||
|
else: QMAKE_CFLAGS += --sysroot=$$ANDROID_PLATFORM_ROOT_PATH
|
||||||
|
|
||||||
|
QMAKE_CFLAGS += -isystem $$NDK_ROOT/sources/cxx-stl/gnu-libstdc++/$$NDK_TOOLCHAIN_VERSION/include \
|
||||||
-isystem $$ANDROID_SOURCES_CXX_STL_LIBDIR/include
|
-isystem $$ANDROID_SOURCES_CXX_STL_LIBDIR/include
|
||||||
|
|
||||||
equals(ANDROID_TARGET_ARCH, armeabi)|equals(ANDROID_TARGET_ARCH, armeabi-v7a): \
|
equals(ANDROID_TARGET_ARCH, armeabi)|equals(ANDROID_TARGET_ARCH, armeabi-v7a): \
|
||||||
|
@ -74,3 +74,4 @@ ANDROID_PLATFORM_PATH = $$ANDROID_PLATFORM_ROOT_PATH/usr
|
|||||||
equals(ANDROID_TARGET_ARCH, x86_64)|equals(ANDROID_TARGET_ARCH, mips64): \
|
equals(ANDROID_TARGET_ARCH, x86_64)|equals(ANDROID_TARGET_ARCH, mips64): \
|
||||||
QMAKE_ANDROID_PLATFORM_LIBDIR = $${QMAKE_ANDROID_PLATFORM_LIBDIR}64
|
QMAKE_ANDROID_PLATFORM_LIBDIR = $${QMAKE_ANDROID_PLATFORM_LIBDIR}64
|
||||||
|
|
||||||
|
CROSS_COMPILE = $$NDK_TOOLCHAIN_PATH/bin/$$NDK_TOOLS_PREFIX-
|
||||||
|
@ -57,14 +57,14 @@ QMAKE_CXXFLAGS_THREAD = $$QMAKE_CFLAGS_THREAD
|
|||||||
QMAKE_CXXFLAGS_HIDESYMS = $$QMAKE_CFLAGS_HIDESYMS -fvisibility-inlines-hidden
|
QMAKE_CXXFLAGS_HIDESYMS = $$QMAKE_CFLAGS_HIDESYMS -fvisibility-inlines-hidden
|
||||||
|
|
||||||
# modifications to linux.conf
|
# modifications to linux.conf
|
||||||
QMAKE_AR = $$NDK_TOOLCHAIN_PATH/bin/$$NDK_TOOLS_PREFIX-ar cqs
|
QMAKE_AR = $${CROSS_COMPILE}ar cqs
|
||||||
QMAKE_OBJCOPY = $$NDK_TOOLCHAIN_PATH/bin/$$NDK_TOOLS_PREFIX-objcopy
|
QMAKE_OBJCOPY = $${CROSS_COMPILE}objcopy
|
||||||
QMAKE_NM = $$NDK_TOOLCHAIN_PATH/bin/$$NDK_TOOLS_PREFIX-nm -P
|
QMAKE_NM = $${CROSS_COMPILE}nm -P
|
||||||
|
|
||||||
QMAKE_STRIP =
|
QMAKE_STRIP =
|
||||||
#$$NDK_TOOLCHAIN_PATH/bin/$$NDK_TOOLS_PREFIX-strip
|
#$${CROSS_COMPILE}strip
|
||||||
|
|
||||||
QMAKE_RANLIB = $$NDK_TOOLCHAIN_PATH/bin/$$NDK_TOOLS_PREFIX-ranlib
|
QMAKE_RANLIB = $${CROSS_COMPILE}ranlib
|
||||||
|
|
||||||
QMAKE_INCDIR_POST =
|
QMAKE_INCDIR_POST =
|
||||||
QMAKE_LIBDIR_POST = $$ANDROID_SOURCES_CXX_STL_LIBDIR
|
QMAKE_LIBDIR_POST = $$ANDROID_SOURCES_CXX_STL_LIBDIR
|
||||||
|
@ -45,7 +45,7 @@ if(gcc|intel_icl|msvc):!rim_qcc:!uikit:!no_moc_predefs:if(!macos|count(QMAKE_APP
|
|||||||
|
|
||||||
defineReplace(mocCmdBase) {
|
defineReplace(mocCmdBase) {
|
||||||
!isEmpty(WIN_INCLUDETEMP) {
|
!isEmpty(WIN_INCLUDETEMP) {
|
||||||
incvar = @$$WIN_INCLUDETEMP
|
incvar = @$$shell_quote($$WIN_INCLUDETEMP)
|
||||||
} else {
|
} else {
|
||||||
incvar =
|
incvar =
|
||||||
for (inc, MOC_INCLUDEPATH): \
|
for (inc, MOC_INCLUDEPATH): \
|
||||||
|
@ -74,10 +74,10 @@ warnings_are_errors:warning_clean {
|
|||||||
# compiler.
|
# compiler.
|
||||||
clang {
|
clang {
|
||||||
# Apple clang 4.0-4.2,5.0-5.1,6.0-6.4,7.0-7.3
|
# Apple clang 4.0-4.2,5.0-5.1,6.0-6.4,7.0-7.3
|
||||||
# Regular clang 3.3-3.9, 4.0
|
# Regular clang 3.x-5.0
|
||||||
apple_ver = $${QT_APPLE_CLANG_MAJOR_VERSION}.$${QT_APPLE_CLANG_MINOR_VERSION}
|
apple_ver = $${QT_APPLE_CLANG_MAJOR_VERSION}.$${QT_APPLE_CLANG_MINOR_VERSION}
|
||||||
reg_ver = $${QT_CLANG_MAJOR_VERSION}.$${QT_CLANG_MINOR_VERSION}
|
reg_ver = $${QT_CLANG_MAJOR_VERSION}.$${QT_CLANG_MINOR_VERSION}
|
||||||
contains(apple_ver, "4\\.[012]|5\\.[01]|6\\.[01234]|7\\.[0123]")|contains(reg_ver, "3\\.[3-9]|4\\.0") {
|
contains(apple_ver, "4\\.[012]|5\\.[01]|6\\.[01234]|7\\.[0123]")|contains(reg_ver, "[34]\\.|5\\.0") {
|
||||||
QMAKE_CXXFLAGS_WARN_ON += -Werror -Wno-error=\\$${LITERAL_HASH}warnings -Wno-error=deprecated-declarations $$WERROR
|
QMAKE_CXXFLAGS_WARN_ON += -Werror -Wno-error=\\$${LITERAL_HASH}warnings -Wno-error=deprecated-declarations $$WERROR
|
||||||
}
|
}
|
||||||
} else:intel_icc:linux {
|
} else:intel_icc:linux {
|
||||||
|
@ -232,17 +232,17 @@ QMAKE_COMPILER_DEFINES += __cplusplus=$$QT_COMPILER_STDCXX
|
|||||||
QMAKE_COMPILER_DEFINES += __INTEL_COMPILER=$$QMAKE_ICC_VER __INTEL_COMPILER_UPDATE=$$QMAKE_ICC_UPDATE_VER
|
QMAKE_COMPILER_DEFINES += __INTEL_COMPILER=$$QMAKE_ICC_VER __INTEL_COMPILER_UPDATE=$$QMAKE_ICC_UPDATE_VER
|
||||||
!isEmpty(QMAKE_APPLE_CC): \
|
!isEmpty(QMAKE_APPLE_CC): \
|
||||||
QMAKE_COMPILER_DEFINES += __APPLE_CC__=$$QMAKE_APPLE_CC
|
QMAKE_COMPILER_DEFINES += __APPLE_CC__=$$QMAKE_APPLE_CC
|
||||||
!isEmpty(QT_APPLE_CLANG_MAJOR_VERSION): \
|
!isEmpty(QMAKE_APPLE_CLANG_MAJOR_VERSION): \
|
||||||
QMAKE_COMPILER_DEFINES += __clang__ \
|
QMAKE_COMPILER_DEFINES += __clang__ \
|
||||||
__clang_major__=$$QMAKE_APPLE_CLANG_MAJOR_VERSION \
|
__clang_major__=$$QMAKE_APPLE_CLANG_MAJOR_VERSION \
|
||||||
__clang_minor__=$$QMAKE_APPLE_CLANG_MINOR_VERSION \
|
__clang_minor__=$$QMAKE_APPLE_CLANG_MINOR_VERSION \
|
||||||
__clang_patchlevel__=$$QMAKE_APPLE_CLANG_PATCH_VERSION
|
__clang_patchlevel__=$$QMAKE_APPLE_CLANG_PATCH_VERSION
|
||||||
!isEmpty(QT_CLANG_MAJOR_VERSION): \
|
!isEmpty(QMAKE_CLANG_MAJOR_VERSION): \
|
||||||
QMAKE_COMPILER_DEFINES += __clang__ \
|
QMAKE_COMPILER_DEFINES += __clang__ \
|
||||||
__clang_major__=$$QMAKE_CLANG_MAJOR_VERSION \
|
__clang_major__=$$QMAKE_CLANG_MAJOR_VERSION \
|
||||||
__clang_minor__=$$QMAKE_CLANG_MINOR_VERSION \
|
__clang_minor__=$$QMAKE_CLANG_MINOR_VERSION \
|
||||||
__clang_patchlevel__=$$QMAKE_CLANG_PATCH_VERSION
|
__clang_patchlevel__=$$QMAKE_CLANG_PATCH_VERSION
|
||||||
!isEmpty(QT_GCC_MAJOR_VERSION): \
|
!isEmpty(QMAKE_GCC_MAJOR_VERSION): \
|
||||||
QMAKE_COMPILER_DEFINES += \
|
QMAKE_COMPILER_DEFINES += \
|
||||||
__GNUC__=$$QMAKE_GCC_MAJOR_VERSION \
|
__GNUC__=$$QMAKE_GCC_MAJOR_VERSION \
|
||||||
__GNUC_MINOR__=$$QMAKE_GCC_MINOR_VERSION \
|
__GNUC_MINOR__=$$QMAKE_GCC_MINOR_VERSION \
|
||||||
|
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)
|
static int installFile(const QString &source, const QString &target, bool exe = false)
|
||||||
{
|
{
|
||||||
QFile sourceFile(source);
|
QFile sourceFile(source);
|
||||||
|
QFile targetFile(target);
|
||||||
QFile::remove(target);
|
if (targetFile.exists()) {
|
||||||
QDir::root().mkpath(QFileInfo(target).absolutePath());
|
#ifdef Q_OS_WIN
|
||||||
|
targetFile.setPermissions(targetFile.permissions() | QFile::WriteUser);
|
||||||
|
#endif
|
||||||
|
QFile::remove(target);
|
||||||
|
} else {
|
||||||
|
QDir::root().mkpath(QFileInfo(target).absolutePath());
|
||||||
|
}
|
||||||
|
|
||||||
if (!sourceFile.copy(target)) {
|
if (!sourceFile.copy(target)) {
|
||||||
fprintf(stderr, "Error copying %s to %s: %s\n", source.toLatin1().constData(), qPrintable(target), qPrintable(sourceFile.errorString()));
|
fprintf(stderr, "Error copying %s to %s: %s\n", source.toLatin1().constData(), qPrintable(target), qPrintable(sourceFile.errorString()));
|
||||||
@ -255,7 +261,6 @@ static int installFile(const QString &source, const QString &target, bool exe =
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (exe) {
|
if (exe) {
|
||||||
QFile targetFile(target);
|
|
||||||
if (!targetFile.setPermissions(sourceFile.permissions() | QFileDevice::ExeOwner | QFileDevice::ExeUser |
|
if (!targetFile.setPermissions(sourceFile.permissions() | QFileDevice::ExeOwner | QFileDevice::ExeUser |
|
||||||
QFileDevice::ExeGroup | QFileDevice::ExeOther)) {
|
QFileDevice::ExeGroup | QFileDevice::ExeOther)) {
|
||||||
fprintf(stderr, "Error setting execute permissions on %s: %s\n",
|
fprintf(stderr, "Error setting execute permissions on %s: %s\n",
|
||||||
@ -266,10 +271,20 @@ static int installFile(const QString &source, const QString &target, bool exe =
|
|||||||
|
|
||||||
// Copy file times
|
// Copy file times
|
||||||
QString error;
|
QString error;
|
||||||
|
#ifdef Q_OS_WIN
|
||||||
|
const QFile::Permissions permissions = targetFile.permissions();
|
||||||
|
const bool readOnly = !(permissions & QFile::WriteUser);
|
||||||
|
if (readOnly)
|
||||||
|
targetFile.setPermissions(permissions | QFile::WriteUser);
|
||||||
|
#endif
|
||||||
if (!IoUtils::touchFile(target, sourceFile.fileName(), &error)) {
|
if (!IoUtils::touchFile(target, sourceFile.fileName(), &error)) {
|
||||||
fprintf(stderr, "%s", qPrintable(error));
|
fprintf(stderr, "%s", qPrintable(error));
|
||||||
return 3;
|
return 3;
|
||||||
}
|
}
|
||||||
|
#ifdef Q_OS_WIN
|
||||||
|
if (readOnly)
|
||||||
|
targetFile.setPermissions(permissions);
|
||||||
|
#endif
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -100,7 +100,6 @@ FILES="
|
|||||||
src/pcre2_newline.c
|
src/pcre2_newline.c
|
||||||
src/pcre2_ord2utf.c
|
src/pcre2_ord2utf.c
|
||||||
src/pcre2_pattern_info.c
|
src/pcre2_pattern_info.c
|
||||||
src/pcre2_printint.c
|
|
||||||
src/pcre2_serialize.c
|
src/pcre2_serialize.c
|
||||||
src/pcre2_string_utils.c
|
src/pcre2_string_utils.c
|
||||||
src/pcre2_study.c
|
src/pcre2_study.c
|
||||||
|
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
|
DEFINES += HAVE_CONFIG_H
|
||||||
|
|
||||||
# platform/compiler specific definitions
|
# platform/compiler specific definitions
|
||||||
ios|qnx|winrt: DEFINES += PCRE2_DISABLE_JIT
|
uikit|qnx|winrt: DEFINES += PCRE2_DISABLE_JIT
|
||||||
|
|
||||||
SOURCES += \
|
SOURCES += \
|
||||||
$$PWD/src/pcre2_auto_possess.c \
|
$$PWD/src/pcre2_auto_possess.c \
|
||||||
@ -33,7 +33,6 @@ SOURCES += \
|
|||||||
$$PWD/src/pcre2_newline.c \
|
$$PWD/src/pcre2_newline.c \
|
||||||
$$PWD/src/pcre2_ord2utf.c \
|
$$PWD/src/pcre2_ord2utf.c \
|
||||||
$$PWD/src/pcre2_pattern_info.c \
|
$$PWD/src/pcre2_pattern_info.c \
|
||||||
$$PWD/src/pcre2_printint.c \
|
|
||||||
$$PWD/src/pcre2_serialize.c \
|
$$PWD/src/pcre2_serialize.c \
|
||||||
$$PWD/src/pcre2_string_utils.c \
|
$$PWD/src/pcre2_string_utils.c \
|
||||||
$$PWD/src/pcre2_study.c \
|
$$PWD/src/pcre2_study.c \
|
||||||
|
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]
|
//! [11-qstringview]
|
||||||
int i; // current file's number
|
int i; // current file's number
|
||||||
int total; // number of files to process
|
int total; // number of files to process
|
||||||
QStringView fileName; // current file's name
|
QStringView fileName; // current file's name
|
||||||
|
|
||||||
QString status = QString("Processing file %1 of %2: %3")
|
QString status = QString("Processing file %1 of %2: %3")
|
||||||
.arg(i).arg(total).arg(fileName);
|
.arg(i).arg(total).arg(fileName);
|
||||||
//! [11]
|
//! [11-qstringview]
|
||||||
}
|
}
|
||||||
|
|
||||||
//! [12] //! [13]
|
//! [12] //! [13]
|
||||||
|
@ -43,6 +43,7 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <qversionnumber.h>
|
#include <qversionnumber.h>
|
||||||
|
#include <qdebug.h>
|
||||||
|
|
||||||
#if defined(Q_OS_ANDROID)
|
#if defined(Q_OS_ANDROID)
|
||||||
#include <private/qjni_p.h>
|
#include <private/qjni_p.h>
|
||||||
@ -154,6 +155,8 @@ QT_BEGIN_NAMESPACE
|
|||||||
\fn QOperatingSystemVersion QOperatingSystemVersion::current()
|
\fn QOperatingSystemVersion QOperatingSystemVersion::current()
|
||||||
|
|
||||||
Returns a QOperatingSystemVersion indicating the current OS and its version number.
|
Returns a QOperatingSystemVersion indicating the current OS and its version number.
|
||||||
|
|
||||||
|
\sa currentType()
|
||||||
*/
|
*/
|
||||||
#if !defined(Q_OS_DARWIN) && !defined(Q_OS_WIN)
|
#if !defined(Q_OS_DARWIN) && !defined(Q_OS_WIN)
|
||||||
QOperatingSystemVersion QOperatingSystemVersion::current()
|
QOperatingSystemVersion QOperatingSystemVersion::current()
|
||||||
@ -299,6 +302,14 @@ int QOperatingSystemVersion::compare(const QOperatingSystemVersion &v1,
|
|||||||
\sa name()
|
\sa name()
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/*!
|
||||||
|
\fn QOperatingSystemVersion::OSType QOperatingSystemVersion::currentType()
|
||||||
|
|
||||||
|
Returns the current OS type without constructing a QOperatingSystemVersion instance.
|
||||||
|
|
||||||
|
\sa current()
|
||||||
|
*/
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
\fn QString QOperatingSystemVersion::name() const
|
\fn QString QOperatingSystemVersion::name() const
|
||||||
|
|
||||||
@ -510,4 +521,16 @@ const QOperatingSystemVersion QOperatingSystemVersion::AndroidNougat_MR1 =
|
|||||||
const QOperatingSystemVersion QOperatingSystemVersion::AndroidOreo =
|
const QOperatingSystemVersion QOperatingSystemVersion::AndroidOreo =
|
||||||
QOperatingSystemVersion(QOperatingSystemVersion::Android, 8, 0);
|
QOperatingSystemVersion(QOperatingSystemVersion::Android, 8, 0);
|
||||||
|
|
||||||
|
#ifndef QT_NO_DEBUG_STREAM
|
||||||
|
QDebug operator<<(QDebug debug, const QOperatingSystemVersion &ov)
|
||||||
|
{
|
||||||
|
QDebugStateSaver saver(debug);
|
||||||
|
debug.nospace();
|
||||||
|
debug << "QOperatingSystemVersion(" << ov.name()
|
||||||
|
<< ", " << ov.majorVersion() << '.' << ov.minorVersion()
|
||||||
|
<< '.' << ov.microVersion() << ')';
|
||||||
|
return debug;
|
||||||
|
}
|
||||||
|
#endif // !QT_NO_DEBUG_STREAM
|
||||||
|
|
||||||
QT_END_NAMESPACE
|
QT_END_NAMESPACE
|
||||||
|
@ -92,6 +92,25 @@ public:
|
|||||||
|
|
||||||
static QOperatingSystemVersion current();
|
static QOperatingSystemVersion current();
|
||||||
|
|
||||||
|
static Q_DECL_CONSTEXPR OSType currentType()
|
||||||
|
{
|
||||||
|
#if defined(Q_OS_WIN)
|
||||||
|
return Windows;
|
||||||
|
#elif defined(Q_OS_MACOS)
|
||||||
|
return MacOS;
|
||||||
|
#elif defined(Q_OS_IOS)
|
||||||
|
return IOS;
|
||||||
|
#elif defined(Q_OS_TVOS)
|
||||||
|
return TvOS;
|
||||||
|
#elif defined(Q_OS_WATCHOS)
|
||||||
|
return WatchOS;
|
||||||
|
#elif defined(Q_OS_ANDROID)
|
||||||
|
return Android;
|
||||||
|
#else
|
||||||
|
return Unknown;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
Q_DECL_CONSTEXPR int majorVersion() const { return m_major; }
|
Q_DECL_CONSTEXPR int majorVersion() const { return m_major; }
|
||||||
Q_DECL_CONSTEXPR int minorVersion() const { return m_minor; }
|
Q_DECL_CONSTEXPR int minorVersion() const { return m_minor; }
|
||||||
Q_DECL_CONSTEXPR int microVersion() const { return m_micro; }
|
Q_DECL_CONSTEXPR int microVersion() const { return m_micro; }
|
||||||
@ -128,6 +147,11 @@ private:
|
|||||||
};
|
};
|
||||||
Q_DECLARE_TYPEINFO(QOperatingSystemVersion, QT_VERSION < QT_VERSION_CHECK(6, 0, 0) ? Q_RELOCATABLE_TYPE : Q_PRIMITIVE_TYPE);
|
Q_DECLARE_TYPEINFO(QOperatingSystemVersion, QT_VERSION < QT_VERSION_CHECK(6, 0, 0) ? Q_RELOCATABLE_TYPE : Q_PRIMITIVE_TYPE);
|
||||||
|
|
||||||
|
#ifndef QT_NO_DEBUG_STREAM
|
||||||
|
class QDebug;
|
||||||
|
Q_CORE_EXPORT QDebug operator<<(QDebug debug, const QOperatingSystemVersion &ov);
|
||||||
|
#endif
|
||||||
|
|
||||||
QT_END_NAMESPACE
|
QT_END_NAMESPACE
|
||||||
|
|
||||||
#endif // QOPERATINGSYSTEMVERSION_H
|
#endif // QOPERATINGSYSTEMVERSION_H
|
||||||
|
@ -63,25 +63,6 @@ QT_BEGIN_NAMESPACE
|
|||||||
OSVERSIONINFOEX qWindowsVersionInfo();
|
OSVERSIONINFOEX qWindowsVersionInfo();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static inline QOperatingSystemVersion::OSType currentType()
|
|
||||||
{
|
|
||||||
#if defined(Q_OS_WIN)
|
|
||||||
return QOperatingSystemVersion::Windows;
|
|
||||||
#elif defined(Q_OS_MACOS)
|
|
||||||
return QOperatingSystemVersion::MacOS;
|
|
||||||
#elif defined(Q_OS_IOS)
|
|
||||||
return QOperatingSystemVersion::IOS;
|
|
||||||
#elif defined(Q_OS_TVOS)
|
|
||||||
return QOperatingSystemVersion::TvOS;
|
|
||||||
#elif defined(Q_OS_WATCHOS)
|
|
||||||
return QOperatingSystemVersion::WatchOS;
|
|
||||||
#elif defined(Q_OS_ANDROID)
|
|
||||||
return QOperatingSystemVersion::Android;
|
|
||||||
#else
|
|
||||||
return QOperatingSystemVersion::Unknown;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
QT_END_NAMESPACE
|
QT_END_NAMESPACE
|
||||||
|
|
||||||
#endif // QOPERATINGSYSTEMVERSION_P_H
|
#endif // QOPERATINGSYSTEMVERSION_P_H
|
||||||
|
@ -458,14 +458,14 @@ static Q_NEVER_INLINE void fill(void *buffer, void *bufferEnd)
|
|||||||
reliable sequence, which may be needed for debugging.
|
reliable sequence, which may be needed for debugging.
|
||||||
|
|
||||||
The class can generate 32-bit or 64-bit quantities, or fill an array of
|
The class can generate 32-bit or 64-bit quantities, or fill an array of
|
||||||
those. The most common way of generating new values is to call the get32(),
|
those. The most common way of generating new values is to call the generate(),
|
||||||
get64() or fillRange() functions. One would use it as:
|
get64() or fillRange() functions. One would use it as:
|
||||||
|
|
||||||
\code
|
\code
|
||||||
quint32 value = QRandomGenerator::get32();
|
quint32 value = QRandomGenerator::generate();
|
||||||
\endcode
|
\endcode
|
||||||
|
|
||||||
Additionally, it provides a floating-point function getReal() that returns
|
Additionally, it provides a floating-point function generateDouble() that returns
|
||||||
a number in the range [0, 1) (that is, inclusive of zero and exclusive of
|
a number in the range [0, 1) (that is, inclusive of zero and exclusive of
|
||||||
1). There's also a set of convenience functions that facilitate obtaining a
|
1). There's also a set of convenience functions that facilitate obtaining a
|
||||||
random number in a bounded, integral range.
|
random number in a bounded, integral range.
|
||||||
@ -567,7 +567,7 @@ static Q_NEVER_INLINE void fill(void *buffer, void *bufferEnd)
|
|||||||
|
|
||||||
Generates a 32-bit random quantity and returns it.
|
Generates a 32-bit random quantity and returns it.
|
||||||
|
|
||||||
\sa QRandomGenerator::get32(), QRandomGenerator::get64()
|
\sa QRandomGenerator::generate(), QRandomGenerator::generate64()
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@ -611,7 +611,7 @@ static Q_NEVER_INLINE void fill(void *buffer, void *bufferEnd)
|
|||||||
and \a end. This function is equivalent to (and is implemented as):
|
and \a end. This function is equivalent to (and is implemented as):
|
||||||
|
|
||||||
\code
|
\code
|
||||||
std::generate(begin, end, []() { return get32(); });
|
std::generate(begin, end, []() { return generate(); });
|
||||||
\endcode
|
\endcode
|
||||||
|
|
||||||
This function complies with the requirements for the function
|
This function complies with the requirements for the function
|
||||||
@ -683,7 +683,7 @@ static Q_NEVER_INLINE void fill(void *buffer, void *bufferEnd)
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
\fn qreal QRandomGenerator::getReal()
|
\fn qreal QRandomGenerator::generateReal()
|
||||||
|
|
||||||
Generates one random qreal in the canonical range [0, 1) (that is,
|
Generates one random qreal in the canonical range [0, 1) (that is,
|
||||||
inclusive of zero and exclusive of 1).
|
inclusive of zero and exclusive of 1).
|
||||||
@ -698,7 +698,7 @@ static Q_NEVER_INLINE void fill(void *buffer, void *bufferEnd)
|
|||||||
\c{\l{http://en.cppreference.com/w/cpp/numeric/random/uniform_real_distribution}{std::uniform_real_distribution}}
|
\c{\l{http://en.cppreference.com/w/cpp/numeric/random/uniform_real_distribution}{std::uniform_real_distribution}}
|
||||||
with parameters 0 and 1.
|
with parameters 0 and 1.
|
||||||
|
|
||||||
\sa get32(), get64(), bounded()
|
\sa generate(), get64(), bounded()
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@ -708,10 +708,10 @@ static Q_NEVER_INLINE void fill(void *buffer, void *bufferEnd)
|
|||||||
sup (exclusive). This function is equivalent to and is implemented as:
|
sup (exclusive). This function is equivalent to and is implemented as:
|
||||||
|
|
||||||
\code
|
\code
|
||||||
return getReal() * sup;
|
return generateDouble() * sup;
|
||||||
\endcode
|
\endcode
|
||||||
|
|
||||||
\sa getReal(), bounded()
|
\sa generateDouble(), bounded()
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@ -730,13 +730,13 @@ static Q_NEVER_INLINE void fill(void *buffer, void *bufferEnd)
|
|||||||
quint32 v = QRandomGenerator::bounded(256);
|
quint32 v = QRandomGenerator::bounded(256);
|
||||||
\endcode
|
\endcode
|
||||||
|
|
||||||
Naturally, the same could also be obtained by masking the result of get32()
|
Naturally, the same could also be obtained by masking the result of generate()
|
||||||
to only the lower 8 bits. Either solution is as efficient.
|
to only the lower 8 bits. Either solution is as efficient.
|
||||||
|
|
||||||
Note that this function cannot be used to obtain values in the full 32-bit
|
Note that this function cannot be used to obtain values in the full 32-bit
|
||||||
range of quint32. Instead, use get32().
|
range of quint32. Instead, use generate().
|
||||||
|
|
||||||
\sa get32(), get64(), getReal()
|
\sa generate(), get64(), generateDouble()
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@ -747,9 +747,9 @@ static Q_NEVER_INLINE void fill(void *buffer, void *bufferEnd)
|
|||||||
\a sup (exclusive). \a sup must not be negative.
|
\a sup (exclusive). \a sup must not be negative.
|
||||||
|
|
||||||
Note that this function cannot be used to obtain values in the full 32-bit
|
Note that this function cannot be used to obtain values in the full 32-bit
|
||||||
range of int. Instead, use get32() and cast to int.
|
range of int. Instead, use generate() and cast to int.
|
||||||
|
|
||||||
\sa get32(), get64(), getReal()
|
\sa generate(), get64(), generateDouble()
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@ -771,9 +771,9 @@ static Q_NEVER_INLINE void fill(void *buffer, void *bufferEnd)
|
|||||||
|
|
||||||
|
|
||||||
Note that this function cannot be used to obtain values in the full 32-bit
|
Note that this function cannot be used to obtain values in the full 32-bit
|
||||||
range of quint32. Instead, use get32().
|
range of quint32. Instead, use generate().
|
||||||
|
|
||||||
\sa get32(), get64(), getReal()
|
\sa generate(), get64(), generateDouble()
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@ -784,9 +784,9 @@ static Q_NEVER_INLINE void fill(void *buffer, void *bufferEnd)
|
|||||||
(inclusive) and \a sup (exclusive), both of which may be negative.
|
(inclusive) and \a sup (exclusive), both of which may be negative.
|
||||||
|
|
||||||
Note that this function cannot be used to obtain values in the full 32-bit
|
Note that this function cannot be used to obtain values in the full 32-bit
|
||||||
range of int. Instead, use get32() and cast to int.
|
range of int. Instead, use generate() and cast to int.
|
||||||
|
|
||||||
\sa get32(), get64(), getReal()
|
\sa generate(), get64(), generateDouble()
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@ -798,7 +798,7 @@ static Q_NEVER_INLINE void fill(void *buffer, void *bufferEnd)
|
|||||||
from a high-quality, seed-less Random Number Generator.
|
from a high-quality, seed-less Random Number Generator.
|
||||||
|
|
||||||
QRandomGenerator64 is a simple adaptor class around QRandomGenerator, making the
|
QRandomGenerator64 is a simple adaptor class around QRandomGenerator, making the
|
||||||
QRandomGenerator::get64() function the default for operator()(), instead of the
|
QRandomGenerator::generate64() function the default for operator()(), instead of the
|
||||||
function that returns 32-bit quantities. This class is intended to be used
|
function that returns 32-bit quantities. This class is intended to be used
|
||||||
in conjunction with Standard Library algorithms that need 64-bit quantities
|
in conjunction with Standard Library algorithms that need 64-bit quantities
|
||||||
instead of 32-bit ones.
|
instead of 32-bit ones.
|
||||||
@ -823,12 +823,29 @@ static Q_NEVER_INLINE void fill(void *buffer, void *bufferEnd)
|
|||||||
\sa operator()()
|
\sa operator()()
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/*!
|
||||||
|
\fn quint64 QRandomGenerator64::generate()
|
||||||
|
|
||||||
|
Generates one 64-bit random value and returns it.
|
||||||
|
|
||||||
|
Note about casting to a signed integer: all bits returned by this function
|
||||||
|
are random, so there's a 50% chance that the most significant bit will be
|
||||||
|
set. If you wish to cast the returned value to qint64 and keep it positive,
|
||||||
|
you should mask the sign bit off:
|
||||||
|
|
||||||
|
\code
|
||||||
|
qint64 value = QRandomGenerator64::generate() & std::numeric_limits<qint64>::max();
|
||||||
|
\endcode
|
||||||
|
|
||||||
|
\sa QRandomGenerator, QRandomGenerator::generate64()
|
||||||
|
*/
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
\fn result_type QRandomGenerator64::operator()()
|
\fn result_type QRandomGenerator64::operator()()
|
||||||
|
|
||||||
Generates a 64-bit random quantity and returns it.
|
Generates a 64-bit random quantity and returns it.
|
||||||
|
|
||||||
\sa QRandomGenerator::get32(), QRandomGenerator::get64()
|
\sa QRandomGenerator::generate(), QRandomGenerator::generate64()
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@ -874,12 +891,12 @@ static Q_NEVER_INLINE void fill(void *buffer, void *bufferEnd)
|
|||||||
you should mask the sign bit off:
|
you should mask the sign bit off:
|
||||||
|
|
||||||
\code
|
\code
|
||||||
int value = QRandomGenerator::get32() & std::numeric_limits<int>::max();
|
int value = QRandomGenerator::generate() & std::numeric_limits<int>::max();
|
||||||
\endcode
|
\endcode
|
||||||
|
|
||||||
\sa get64(), getReal()
|
\sa get64(), generateDouble()
|
||||||
*/
|
*/
|
||||||
quint32 QRandomGenerator::get32()
|
quint32 QRandomGenerator::generate()
|
||||||
{
|
{
|
||||||
quint32 ret;
|
quint32 ret;
|
||||||
fill(&ret, &ret + 1);
|
fill(&ret, &ret + 1);
|
||||||
@ -895,12 +912,12 @@ quint32 QRandomGenerator::get32()
|
|||||||
you should mask the sign bit off:
|
you should mask the sign bit off:
|
||||||
|
|
||||||
\code
|
\code
|
||||||
qint64 value = QRandomGenerator::get64() & std::numeric_limits<qint64>::max();
|
qint64 value = QRandomGenerator::generate64() & std::numeric_limits<qint64>::max();
|
||||||
\endcode
|
\endcode
|
||||||
|
|
||||||
\sa get32(), getReal(), QRandomGenerator64
|
\sa generate(), generateDouble(), QRandomGenerator64
|
||||||
*/
|
*/
|
||||||
quint64 QRandomGenerator::get64()
|
quint64 QRandomGenerator::generate64()
|
||||||
{
|
{
|
||||||
quint64 ret;
|
quint64 ret;
|
||||||
fill(&ret, &ret + 1);
|
fill(&ret, &ret + 1);
|
||||||
|
@ -53,29 +53,27 @@ class QRandomGenerator
|
|||||||
public:
|
public:
|
||||||
QRandomGenerator() = default;
|
QRandomGenerator() = default;
|
||||||
|
|
||||||
static Q_CORE_EXPORT quint32 get32();
|
// ### REMOVE BEFORE 5.10
|
||||||
static Q_CORE_EXPORT quint64 get64();
|
static quint32 get32() { return generate(); }
|
||||||
static qreal getReal()
|
static quint64 get64() { return generate64(); }
|
||||||
|
static qreal getReal() { return generateDouble(); }
|
||||||
|
|
||||||
|
static Q_CORE_EXPORT quint32 generate();
|
||||||
|
static Q_CORE_EXPORT quint64 generate64();
|
||||||
|
static double generateDouble()
|
||||||
{
|
{
|
||||||
const int digits = std::numeric_limits<qreal>::digits;
|
// use get64() to get enough bits
|
||||||
if (digits < std::numeric_limits<quint32>::digits) {
|
return double(generate64()) / ((std::numeric_limits<quint64>::max)() + double(1.0));
|
||||||
// use get32()
|
|
||||||
return qreal(get32()) / ((max)() + qreal(1.0));
|
|
||||||
} else {
|
|
||||||
// use get64()
|
|
||||||
// we won't have enough bits for a __float128 though
|
|
||||||
return qreal(get64()) / ((std::numeric_limits<quint64>::max)() + qreal(1.0));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static qreal bounded(qreal sup)
|
static qreal bounded(qreal sup)
|
||||||
{
|
{
|
||||||
return getReal() * sup;
|
return generateDouble() * sup;
|
||||||
}
|
}
|
||||||
|
|
||||||
static quint32 bounded(quint32 sup)
|
static quint32 bounded(quint32 sup)
|
||||||
{
|
{
|
||||||
quint64 value = get32();
|
quint64 value = generate();
|
||||||
value *= sup;
|
value *= sup;
|
||||||
value /= (max)() + quint64(1);
|
value /= (max)() + quint64(1);
|
||||||
return quint32(value);
|
return quint32(value);
|
||||||
@ -112,7 +110,8 @@ public:
|
|||||||
template <typename ForwardIterator>
|
template <typename ForwardIterator>
|
||||||
void generate(ForwardIterator begin, ForwardIterator end)
|
void generate(ForwardIterator begin, ForwardIterator end)
|
||||||
{
|
{
|
||||||
std::generate(begin, end, &QRandomGenerator::get32);
|
auto generator = static_cast<quint32 (*)()>(&QRandomGenerator::generate);
|
||||||
|
std::generate(begin, end, generator);
|
||||||
}
|
}
|
||||||
|
|
||||||
void generate(quint32 *begin, quint32 *end)
|
void generate(quint32 *begin, quint32 *end)
|
||||||
@ -122,7 +121,7 @@ public:
|
|||||||
|
|
||||||
// API like std::random_device
|
// API like std::random_device
|
||||||
typedef quint32 result_type;
|
typedef quint32 result_type;
|
||||||
result_type operator()() { return get32(); }
|
result_type operator()() { return generate(); }
|
||||||
double entropy() const Q_DECL_NOTHROW { return 0.0; }
|
double entropy() const Q_DECL_NOTHROW { return 0.0; }
|
||||||
static Q_DECL_CONSTEXPR result_type min() { return (std::numeric_limits<result_type>::min)(); }
|
static Q_DECL_CONSTEXPR result_type min() { return (std::numeric_limits<result_type>::min)(); }
|
||||||
static Q_DECL_CONSTEXPR result_type max() { return (std::numeric_limits<result_type>::max)(); }
|
static Q_DECL_CONSTEXPR result_type max() { return (std::numeric_limits<result_type>::max)(); }
|
||||||
@ -137,9 +136,11 @@ class QRandomGenerator64
|
|||||||
public:
|
public:
|
||||||
QRandomGenerator64() = default;
|
QRandomGenerator64() = default;
|
||||||
|
|
||||||
|
static quint64 generate() { return QRandomGenerator::generate64(); }
|
||||||
|
|
||||||
// API like std::random_device
|
// API like std::random_device
|
||||||
typedef quint64 result_type;
|
typedef quint64 result_type;
|
||||||
result_type operator()() { return QRandomGenerator::get64(); }
|
result_type operator()() { return QRandomGenerator::generate64(); }
|
||||||
double entropy() const Q_DECL_NOTHROW { return 0.0; }
|
double entropy() const Q_DECL_NOTHROW { return 0.0; }
|
||||||
static Q_DECL_CONSTEXPR result_type min() { return (std::numeric_limits<result_type>::min)(); }
|
static Q_DECL_CONSTEXPR result_type min() { return (std::numeric_limits<result_type>::min)(); }
|
||||||
static Q_DECL_CONSTEXPR result_type max() { return (std::numeric_limits<result_type>::max)(); }
|
static Q_DECL_CONSTEXPR result_type max() { return (std::numeric_limits<result_type>::max)(); }
|
||||||
|
@ -47,6 +47,7 @@
|
|||||||
#include <QtCore/private/qcore_unix_p.h>
|
#include <QtCore/private/qcore_unix_p.h>
|
||||||
#include <QtCore/qvarlengtharray.h>
|
#include <QtCore/qvarlengtharray.h>
|
||||||
|
|
||||||
|
#include <pwd.h>
|
||||||
#include <stdlib.h> // for realpath()
|
#include <stdlib.h> // for realpath()
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
|
@ -440,12 +440,17 @@ QFileSystemEntry QFileSystemEngine::getLinkTarget(const QFileSystemEntry &link,
|
|||||||
if (data.missingFlags(QFileSystemMetaData::LinkType))
|
if (data.missingFlags(QFileSystemMetaData::LinkType))
|
||||||
QFileSystemEngine::fillMetaData(link, data, QFileSystemMetaData::LinkType);
|
QFileSystemEngine::fillMetaData(link, data, QFileSystemMetaData::LinkType);
|
||||||
|
|
||||||
QString ret;
|
QString target;
|
||||||
if (data.isLnkFile())
|
if (data.isLnkFile())
|
||||||
ret = readLink(link);
|
target = readLink(link);
|
||||||
else if (data.isLink())
|
else if (data.isLink())
|
||||||
ret = readSymLink(link);
|
target = readSymLink(link);
|
||||||
return QFileSystemEntry(ret);
|
QFileSystemEntry ret(target);
|
||||||
|
if (!target.isEmpty() && ret.isRelative()) {
|
||||||
|
target.prepend(absoluteName(link).path() + QLatin1Char('/'));
|
||||||
|
ret = QFileSystemEntry(QDir::cleanPath(target));
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
//static
|
//static
|
||||||
|
@ -165,7 +165,7 @@ QFileSystemEntry::NativePath QTemporaryFileName::generateNext()
|
|||||||
|
|
||||||
Char *rIter = placeholderEnd;
|
Char *rIter = placeholderEnd;
|
||||||
while (rIter != placeholderStart) {
|
while (rIter != placeholderStart) {
|
||||||
quint32 rnd = QRandomGenerator::get32();
|
quint32 rnd = QRandomGenerator::generate();
|
||||||
auto applyOne = [&]() {
|
auto applyOne = [&]() {
|
||||||
quint32 v = rnd & ((1 << BitsPerCharacter) - 1);
|
quint32 v = rnd & ((1 << BitsPerCharacter) - 1);
|
||||||
rnd >>= BitsPerCharacter;
|
rnd >>= BitsPerCharacter;
|
||||||
|
@ -79,7 +79,7 @@ public:
|
|||||||
return r < other.r
|
return r < other.r
|
||||||
|| (r == other.r && (c < other.c
|
|| (r == other.r && (c < other.c
|
||||||
|| (c == other.c && (i < other.i
|
|| (c == other.c && (i < other.i
|
||||||
|| (i == other.i && m < other.m )))));
|
|| (i == other.i && std::less<const QAbstractItemModel *>()(m, other.m))))));
|
||||||
}
|
}
|
||||||
private:
|
private:
|
||||||
inline QModelIndex(int arow, int acolumn, void *ptr, const QAbstractItemModel *amodel) Q_DECL_NOTHROW
|
inline QModelIndex(int arow, int acolumn, void *ptr, const QAbstractItemModel *amodel) Q_DECL_NOTHROW
|
||||||
|
@ -84,19 +84,83 @@ QT_FOR_EACH_MUTABLE_CORE_GRAPHICS_TYPE(QT_DECLARE_WEAK_QDEBUG_OPERATOR_FOR_CF_TY
|
|||||||
|
|
||||||
// -------------------------------------------------------------------------
|
// -------------------------------------------------------------------------
|
||||||
|
|
||||||
|
QT_END_NAMESPACE
|
||||||
|
QT_USE_NAMESPACE
|
||||||
|
@interface QT_MANGLE_NAMESPACE(QMacAutoReleasePoolTracker) : NSObject
|
||||||
|
{
|
||||||
|
NSAutoreleasePool **m_pool;
|
||||||
|
}
|
||||||
|
-(id)initWithPool:(NSAutoreleasePool**)pool;
|
||||||
|
@end
|
||||||
|
@implementation QT_MANGLE_NAMESPACE(QMacAutoReleasePoolTracker)
|
||||||
|
-(id)initWithPool:(NSAutoreleasePool**)pool
|
||||||
|
{
|
||||||
|
if (self = [super init])
|
||||||
|
m_pool = pool;
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
-(void)dealloc
|
||||||
|
{
|
||||||
|
if (*m_pool) {
|
||||||
|
// The pool is still valid, which means we're not being drained from
|
||||||
|
// the corresponding QMacAutoReleasePool (see below).
|
||||||
|
|
||||||
|
// QMacAutoReleasePool has only a single member, the NSAutoreleasePool*
|
||||||
|
// so the address of that member is also the QMacAutoReleasePool itself.
|
||||||
|
QMacAutoReleasePool *pool = reinterpret_cast<QMacAutoReleasePool *>(m_pool);
|
||||||
|
qWarning() << "Premature drain of" << pool << "This can happen if you've allocated"
|
||||||
|
<< "the pool on the heap, or as a member of a heap-allocated object. This is not a"
|
||||||
|
<< "supported use of QMacAutoReleasePool, and might result in crashes when objects"
|
||||||
|
<< "in the pool are deallocated and then used later on under the assumption they"
|
||||||
|
<< "will be valid until" << pool << "has been drained.";
|
||||||
|
|
||||||
|
// Reset the pool so that it's not drained again later on
|
||||||
|
*m_pool = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
[super dealloc];
|
||||||
|
}
|
||||||
|
@end
|
||||||
|
QT_NAMESPACE_ALIAS_OBJC_CLASS(QMacAutoReleasePoolTracker);
|
||||||
|
QT_BEGIN_NAMESPACE
|
||||||
|
|
||||||
QMacAutoReleasePool::QMacAutoReleasePool()
|
QMacAutoReleasePool::QMacAutoReleasePool()
|
||||||
: pool([[NSAutoreleasePool alloc] init])
|
: pool([[NSAutoreleasePool alloc] init])
|
||||||
{
|
{
|
||||||
|
[[[QMacAutoReleasePoolTracker alloc] initWithPool:
|
||||||
|
reinterpret_cast<NSAutoreleasePool **>(&pool)] autorelease];
|
||||||
}
|
}
|
||||||
|
|
||||||
QMacAutoReleasePool::~QMacAutoReleasePool()
|
QMacAutoReleasePool::~QMacAutoReleasePool()
|
||||||
{
|
{
|
||||||
|
if (!pool) {
|
||||||
|
qWarning() << "Prematurely drained pool" << this << "finally drained. Any objects belonging"
|
||||||
|
<< "to this pool have already been released, and have potentially been invalid since the"
|
||||||
|
<< "premature drain earlier on.";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Save and reset pool before draining, so that the pool tracker can know
|
||||||
|
// that it's being drained by its owning pool.
|
||||||
|
NSAutoreleasePool *savedPool = static_cast<NSAutoreleasePool*>(pool);
|
||||||
|
pool = nullptr;
|
||||||
|
|
||||||
// Drain behaves the same as release, with the advantage that
|
// Drain behaves the same as release, with the advantage that
|
||||||
// if we're ever used in a garbage-collected environment, the
|
// if we're ever used in a garbage-collected environment, the
|
||||||
// drain acts as a hint to the garbage collector to collect.
|
// drain acts as a hint to the garbage collector to collect.
|
||||||
[static_cast<NSAutoreleasePool*>(pool) drain];
|
[savedPool drain];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifndef QT_NO_DEBUG_STREAM
|
||||||
|
QDebug operator<<(QDebug debug, const QMacAutoReleasePool *pool)
|
||||||
|
{
|
||||||
|
QDebugStateSaver saver(debug);
|
||||||
|
debug.nospace();
|
||||||
|
debug << "QMacAutoReleasePool(" << (const void *)pool << ')';
|
||||||
|
return debug;
|
||||||
|
}
|
||||||
|
#endif // !QT_NO_DEBUG_STREAM
|
||||||
|
|
||||||
#ifdef Q_OS_MACOS
|
#ifdef Q_OS_MACOS
|
||||||
/*
|
/*
|
||||||
Ensure that Objective-C objects auto-released in main(), directly or indirectly,
|
Ensure that Objective-C objects auto-released in main(), directly or indirectly,
|
||||||
|
@ -153,6 +153,10 @@ Q_CORE_EXPORT QChar qt_mac_qtKey2CocoaKey(Qt::Key key);
|
|||||||
Q_CORE_EXPORT Qt::Key qt_mac_cocoaKey2QtKey(QChar keyCode);
|
Q_CORE_EXPORT Qt::Key qt_mac_cocoaKey2QtKey(QChar keyCode);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifndef QT_NO_DEBUG_STREAM
|
||||||
|
QDebug operator<<(QDebug debug, const QMacAutoReleasePool *pool);
|
||||||
|
#endif
|
||||||
|
|
||||||
Q_CORE_EXPORT void qt_apple_check_os_version();
|
Q_CORE_EXPORT void qt_apple_check_os_version();
|
||||||
|
|
||||||
QT_END_NAMESPACE
|
QT_END_NAMESPACE
|
||||||
|
@ -263,7 +263,7 @@ Q_GLOBAL_STATIC(QStartUpFuncList, preRList)
|
|||||||
typedef QList<QtCleanUpFunction> QVFuncList;
|
typedef QList<QtCleanUpFunction> QVFuncList;
|
||||||
Q_GLOBAL_STATIC(QVFuncList, postRList)
|
Q_GLOBAL_STATIC(QVFuncList, postRList)
|
||||||
#ifndef QT_NO_QOBJECT
|
#ifndef QT_NO_QOBJECT
|
||||||
static QBasicMutex globalPreRoutinesMutex;
|
static QBasicMutex globalRoutinesMutex;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@ -277,13 +277,15 @@ void qAddPreRoutine(QtStartUpFunction p)
|
|||||||
QStartUpFuncList *list = preRList();
|
QStartUpFuncList *list = preRList();
|
||||||
if (!list)
|
if (!list)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
if (QCoreApplication::instance())
|
||||||
|
p();
|
||||||
|
|
||||||
// Due to C++11 parallel dynamic initialization, this can be called
|
// Due to C++11 parallel dynamic initialization, this can be called
|
||||||
// from multiple threads.
|
// from multiple threads.
|
||||||
#ifndef QT_NO_THREAD
|
#ifndef QT_NO_THREAD
|
||||||
QMutexLocker locker(&globalPreRoutinesMutex);
|
QMutexLocker locker(&globalRoutinesMutex);
|
||||||
#endif
|
#endif
|
||||||
if (QCoreApplication::instance())
|
|
||||||
p();
|
|
||||||
list->prepend(p); // in case QCoreApplication is re-created, see qt_call_pre_routines
|
list->prepend(p); // in case QCoreApplication is re-created, see qt_call_pre_routines
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -292,6 +294,9 @@ void qAddPostRoutine(QtCleanUpFunction p)
|
|||||||
QVFuncList *list = postRList();
|
QVFuncList *list = postRList();
|
||||||
if (!list)
|
if (!list)
|
||||||
return;
|
return;
|
||||||
|
#ifndef QT_NO_THREAD
|
||||||
|
QMutexLocker locker(&globalRoutinesMutex);
|
||||||
|
#endif
|
||||||
list->prepend(p);
|
list->prepend(p);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -300,6 +305,9 @@ void qRemovePostRoutine(QtCleanUpFunction p)
|
|||||||
QVFuncList *list = postRList();
|
QVFuncList *list = postRList();
|
||||||
if (!list)
|
if (!list)
|
||||||
return;
|
return;
|
||||||
|
#ifndef QT_NO_THREAD
|
||||||
|
QMutexLocker locker(&globalRoutinesMutex);
|
||||||
|
#endif
|
||||||
list->removeAll(p);
|
list->removeAll(p);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -308,15 +316,18 @@ static void qt_call_pre_routines()
|
|||||||
if (!preRList.exists())
|
if (!preRList.exists())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
QVFuncList list;
|
||||||
|
{
|
||||||
#ifndef QT_NO_THREAD
|
#ifndef QT_NO_THREAD
|
||||||
QMutexLocker locker(&globalPreRoutinesMutex);
|
QMutexLocker locker(&globalRoutinesMutex);
|
||||||
#endif
|
#endif
|
||||||
QVFuncList *list = &(*preRList);
|
// Unlike qt_call_post_routines, we don't empty the list, because
|
||||||
// Unlike qt_call_post_routines, we don't empty the list, because
|
// Q_COREAPP_STARTUP_FUNCTION is a macro, so the user expects
|
||||||
// Q_COREAPP_STARTUP_FUNCTION is a macro, so the user expects
|
// the function to be executed every time QCoreApplication is created.
|
||||||
// the function to be executed every time QCoreApplication is created.
|
list = *preRList;
|
||||||
for (int i = 0; i < list->count(); ++i)
|
}
|
||||||
list->at(i)();
|
for (int i = 0; i < list.count(); ++i)
|
||||||
|
list.at(i)();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Q_CORE_EXPORT qt_call_post_routines()
|
void Q_CORE_EXPORT qt_call_post_routines()
|
||||||
@ -324,9 +335,21 @@ void Q_CORE_EXPORT qt_call_post_routines()
|
|||||||
if (!postRList.exists())
|
if (!postRList.exists())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
QVFuncList *list = &(*postRList);
|
forever {
|
||||||
while (!list->isEmpty())
|
QVFuncList list;
|
||||||
(list->takeFirst())();
|
{
|
||||||
|
// extract the current list and make the stored list empty
|
||||||
|
#ifndef QT_NO_THREAD
|
||||||
|
QMutexLocker locker(&globalRoutinesMutex);
|
||||||
|
#endif
|
||||||
|
qSwap(*postRList, list);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (list.isEmpty())
|
||||||
|
break;
|
||||||
|
for (QtCleanUpFunction f : qAsConst(list))
|
||||||
|
f();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -2864,6 +2887,7 @@ void QCoreApplication::setEventDispatcher(QAbstractEventDispatcher *eventDispatc
|
|||||||
|
|
||||||
/*!
|
/*!
|
||||||
\fn void qAddPostRoutine(QtCleanUpFunction ptr)
|
\fn void qAddPostRoutine(QtCleanUpFunction ptr)
|
||||||
|
\threadsafe
|
||||||
\relates QCoreApplication
|
\relates QCoreApplication
|
||||||
|
|
||||||
Adds a global routine that will be called from the QCoreApplication
|
Adds a global routine that will be called from the QCoreApplication
|
||||||
@ -2877,10 +2901,10 @@ void QCoreApplication::setEventDispatcher(QAbstractEventDispatcher *eventDispatc
|
|||||||
|
|
||||||
\snippet code/src_corelib_kernel_qcoreapplication.cpp 4
|
\snippet code/src_corelib_kernel_qcoreapplication.cpp 4
|
||||||
|
|
||||||
Note that for an application- or module-wide cleanup, qaddPostRoutine()
|
Note that for an application- or module-wide cleanup, qAddPostRoutine()
|
||||||
is often not suitable. For example, if the program is split into dynamically
|
is often not suitable. For example, if the program is split into dynamically
|
||||||
loaded modules, the relevant module may be unloaded long before the
|
loaded modules, the relevant module may be unloaded long before the
|
||||||
QCoreApplication destructor is called. In such cases, if using qaddPostRoutine()
|
QCoreApplication destructor is called. In such cases, if using qAddPostRoutine()
|
||||||
is still desirable, qRemovePostRoutine() can be used to prevent a routine
|
is still desirable, qRemovePostRoutine() can be used to prevent a routine
|
||||||
from being called by the QCoreApplication destructor. For example, if that
|
from being called by the QCoreApplication destructor. For example, if that
|
||||||
routine was called before the module was unloaded.
|
routine was called before the module was unloaded.
|
||||||
@ -2896,11 +2920,14 @@ void QCoreApplication::setEventDispatcher(QAbstractEventDispatcher *eventDispatc
|
|||||||
By selecting the right parent object, this can often be made to
|
By selecting the right parent object, this can often be made to
|
||||||
clean up the module's data at the right moment.
|
clean up the module's data at the right moment.
|
||||||
|
|
||||||
|
\note This function has been thread-safe since Qt 5.10.
|
||||||
|
|
||||||
\sa qRemovePostRoutine()
|
\sa qRemovePostRoutine()
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
\fn void qRemovePostRoutine(QtCleanUpFunction ptr)
|
\fn void qRemovePostRoutine(QtCleanUpFunction ptr)
|
||||||
|
\threadsafe
|
||||||
\relates QCoreApplication
|
\relates QCoreApplication
|
||||||
\since 5.3
|
\since 5.3
|
||||||
|
|
||||||
@ -2909,6 +2936,8 @@ void QCoreApplication::setEventDispatcher(QAbstractEventDispatcher *eventDispatc
|
|||||||
must have been previously added to the list by a call to
|
must have been previously added to the list by a call to
|
||||||
qAddPostRoutine(), otherwise this function has no effect.
|
qAddPostRoutine(), otherwise this function has no effect.
|
||||||
|
|
||||||
|
\note This function has been thread-safe since Qt 5.10.
|
||||||
|
|
||||||
\sa qAddPostRoutine()
|
\sa qAddPostRoutine()
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
@ -89,10 +89,6 @@ public:
|
|||||||
QString appName() const;
|
QString appName() const;
|
||||||
QString appVersion() const;
|
QString appVersion() const;
|
||||||
|
|
||||||
#ifdef Q_OS_MACOS
|
|
||||||
QMacRootLevelAutoReleasePool autoReleasePool;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef Q_OS_DARWIN
|
#ifdef Q_OS_DARWIN
|
||||||
static QString infoDictionaryStringProperty(const QString &propertyName);
|
static QString infoDictionaryStringProperty(const QString &propertyName);
|
||||||
#endif
|
#endif
|
||||||
|
@ -3173,6 +3173,9 @@ static bool canConvertMetaObject(int fromId, int toId, QObject *fromObject)
|
|||||||
*/
|
*/
|
||||||
bool QVariant::canConvert(int targetTypeId) const
|
bool QVariant::canConvert(int targetTypeId) const
|
||||||
{
|
{
|
||||||
|
if (d.type == targetTypeId)
|
||||||
|
return true;
|
||||||
|
|
||||||
if ((targetTypeId == QMetaType::QModelIndex && d.type == QMetaType::QPersistentModelIndex)
|
if ((targetTypeId == QMetaType::QModelIndex && d.type == QMetaType::QPersistentModelIndex)
|
||||||
|| (targetTypeId == QMetaType::QPersistentModelIndex && d.type == QMetaType::QModelIndex))
|
|| (targetTypeId == QMetaType::QPersistentModelIndex && d.type == QMetaType::QModelIndex))
|
||||||
return true;
|
return true;
|
||||||
@ -3639,29 +3642,36 @@ static int numericCompare(const QVariant::Private *d1, const QVariant::Private *
|
|||||||
*/
|
*/
|
||||||
bool QVariant::cmp(const QVariant &v) const
|
bool QVariant::cmp(const QVariant &v) const
|
||||||
{
|
{
|
||||||
|
auto cmp_helper = [] (const QVariant::Private &d1, const QVariant::Private &d2)
|
||||||
|
{
|
||||||
|
Q_ASSERT(d1.type == d2.type);
|
||||||
|
if (d1.type >= QMetaType::User) {
|
||||||
|
int result;
|
||||||
|
if (QMetaType::equals(QT_PREPEND_NAMESPACE(constData(d1)), QT_PREPEND_NAMESPACE(constData(d2)), d1.type, &result))
|
||||||
|
return result == 0;
|
||||||
|
}
|
||||||
|
return handlerManager[d1.type]->compare(&d1, &d2);
|
||||||
|
};
|
||||||
|
|
||||||
// try numerics first, with C++ type promotion rules (no conversion)
|
// try numerics first, with C++ type promotion rules (no conversion)
|
||||||
if (qIsNumericType(d.type) && qIsNumericType(v.d.type))
|
if (qIsNumericType(d.type) && qIsNumericType(v.d.type))
|
||||||
return numericCompare(&d, &v.d) == 0;
|
return numericCompare(&d, &v.d) == 0;
|
||||||
|
|
||||||
|
if (d.type == v.d.type)
|
||||||
|
return cmp_helper(d, v.d);
|
||||||
|
|
||||||
QVariant v1 = *this;
|
QVariant v1 = *this;
|
||||||
QVariant v2 = v;
|
QVariant v2 = v;
|
||||||
if (d.type != v2.d.type) {
|
if (v2.canConvert(v1.d.type)) {
|
||||||
if (v2.canConvert(v1.d.type)) {
|
if (!v2.convert(v1.d.type))
|
||||||
if (!v2.convert(v1.d.type))
|
return false;
|
||||||
return false;
|
} else {
|
||||||
} else {
|
// try the opposite conversion, it might work
|
||||||
// try the opposite conversion, it might work
|
qSwap(v1, v2);
|
||||||
qSwap(v1, v2);
|
if (!v2.convert(v1.d.type))
|
||||||
if (!v2.convert(v1.d.type))
|
return false;
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if (v1.d.type >= QMetaType::User) {
|
return cmp_helper(v1.d, v2.d);
|
||||||
int result;
|
|
||||||
if (QMetaType::equals(QT_PREPEND_NAMESPACE(constData(v1.d)), QT_PREPEND_NAMESPACE(constData(v2.d)), v1.d.type, &result))
|
|
||||||
return result == 0;
|
|
||||||
}
|
|
||||||
return handlerManager[v1.d.type]->compare(&v1.d, &v2.d);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@ -3677,51 +3687,53 @@ int QVariant::compare(const QVariant &v) const
|
|||||||
if (cmp(v))
|
if (cmp(v))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
QVariant v1 = *this;
|
const QVariant *v1 = this;
|
||||||
QVariant v2 = v;
|
const QVariant *v2 = &v;
|
||||||
|
QVariant converted1;
|
||||||
|
QVariant converted2;
|
||||||
|
|
||||||
if (v1.d.type != v2.d.type) {
|
if (d.type != v.d.type) {
|
||||||
// if both types differ, try to convert
|
// if both types differ, try to convert
|
||||||
if (v2.canConvert(v1.d.type)) {
|
if (v2->canConvert(v1->d.type)) {
|
||||||
QVariant temp = v2;
|
converted2 = *v2;
|
||||||
if (temp.convert(v1.d.type))
|
if (converted2.convert(v1->d.type))
|
||||||
v2 = temp;
|
v2 = &converted2;
|
||||||
}
|
}
|
||||||
if (v1.d.type != v2.d.type && v1.canConvert(v2.d.type)) {
|
if (v1->d.type != v2->d.type && v1->canConvert(v2->d.type)) {
|
||||||
QVariant temp = v1;
|
converted1 = *v1;
|
||||||
if (temp.convert(v2.d.type))
|
if (converted1.convert(v2->d.type))
|
||||||
v1 = temp;
|
v1 = &converted1;
|
||||||
}
|
}
|
||||||
if (v1.d.type != v2.d.type) {
|
if (v1->d.type != v2->d.type) {
|
||||||
// if conversion fails, default to toString
|
// if conversion fails, default to toString
|
||||||
int r = v1.toString().compare(v2.toString(), Qt::CaseInsensitive);
|
int r = v1->toString().compare(v2->toString(), Qt::CaseInsensitive);
|
||||||
if (r == 0) {
|
if (r == 0) {
|
||||||
// cmp(v) returned false, so we should try to agree with it.
|
// cmp(v) returned false, so we should try to agree with it.
|
||||||
return (v1.d.type < v2.d.type) ? -1 : 1;
|
return (v1->d.type < v2->d.type) ? -1 : 1;
|
||||||
}
|
}
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
// did we end up with two numerics? If so, restart
|
// did we end up with two numerics? If so, restart
|
||||||
if (qIsNumericType(v1.d.type) && qIsNumericType(v2.d.type))
|
if (qIsNumericType(v1->d.type) && qIsNumericType(v2->d.type))
|
||||||
return v1.compare(v2);
|
return v1->compare(*v2);
|
||||||
}
|
}
|
||||||
if (v1.d.type >= QMetaType::User) {
|
if (v1->d.type >= QMetaType::User) {
|
||||||
int result;
|
int result;
|
||||||
if (QMetaType::compare(QT_PREPEND_NAMESPACE(constData(d)), QT_PREPEND_NAMESPACE(constData(v2.d)), d.type, &result))
|
if (QMetaType::compare(QT_PREPEND_NAMESPACE(constData(d)), QT_PREPEND_NAMESPACE(constData(v2->d)), d.type, &result))
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
switch (v1.d.type) {
|
switch (v1->d.type) {
|
||||||
case QVariant::Date:
|
case QVariant::Date:
|
||||||
return v1.toDate() < v2.toDate() ? -1 : 1;
|
return v1->toDate() < v2->toDate() ? -1 : 1;
|
||||||
case QVariant::Time:
|
case QVariant::Time:
|
||||||
return v1.toTime() < v2.toTime() ? -1 : 1;
|
return v1->toTime() < v2->toTime() ? -1 : 1;
|
||||||
case QVariant::DateTime:
|
case QVariant::DateTime:
|
||||||
return v1.toDateTime() < v2.toDateTime() ? -1 : 1;
|
return v1->toDateTime() < v2->toDateTime() ? -1 : 1;
|
||||||
case QVariant::StringList:
|
case QVariant::StringList:
|
||||||
return v1.toStringList() < v2.toStringList() ? -1 : 1;
|
return v1->toStringList() < v2->toStringList() ? -1 : 1;
|
||||||
}
|
}
|
||||||
int r = v1.toString().compare(v2.toString(), Qt::CaseInsensitive);
|
int r = v1->toString().compare(v2->toString(), Qt::CaseInsensitive);
|
||||||
if (r == 0) {
|
if (r == 0) {
|
||||||
// cmp(v) returned false, so we should try to agree with it.
|
// cmp(v) returned false, so we should try to agree with it.
|
||||||
return (d.type < v.d.type) ? -1 : 1;
|
return (d.type < v.d.type) ? -1 : 1;
|
||||||
|
@ -925,6 +925,30 @@ bool QThread::isInterruptionRequested() const
|
|||||||
\sa start()
|
\sa start()
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#ifdef QTHREAD_HAS_CREATE
|
||||||
|
class QThreadCreateThread : public QThread
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
explicit QThreadCreateThread(std::future<void> &&future)
|
||||||
|
: m_future(std::move(future))
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
void run() override
|
||||||
|
{
|
||||||
|
m_future.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
std::future<void> m_future;
|
||||||
|
};
|
||||||
|
|
||||||
|
QThread *QThread::createThreadImpl(std::future<void> &&future)
|
||||||
|
{
|
||||||
|
return new QThreadCreateThread(std::move(future));
|
||||||
|
}
|
||||||
|
#endif // QTHREAD_HAS_CREATE
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
\class QDaemonThread
|
\class QDaemonThread
|
||||||
\since 5.5
|
\since 5.5
|
||||||
|
@ -119,6 +119,12 @@ public:
|
|||||||
bool event(QEvent *event) override;
|
bool event(QEvent *event) override;
|
||||||
int loopLevel() const;
|
int loopLevel() const;
|
||||||
|
|
||||||
|
#ifdef Q_QDOC
|
||||||
|
template <typename Function, typename... Args>
|
||||||
|
static QThread *create(Function &&f, Args &&... args);
|
||||||
|
template <typename Function>
|
||||||
|
static QThread *create(Function &&f);
|
||||||
|
#else
|
||||||
#ifdef QTHREAD_HAS_CREATE
|
#ifdef QTHREAD_HAS_CREATE
|
||||||
#ifdef QTHREAD_HAS_VARIADIC_CREATE
|
#ifdef QTHREAD_HAS_VARIADIC_CREATE
|
||||||
template <typename Function, typename... Args>
|
template <typename Function, typename... Args>
|
||||||
@ -128,6 +134,7 @@ public:
|
|||||||
static QThread *create(Function &&f);
|
static QThread *create(Function &&f);
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
public Q_SLOTS:
|
public Q_SLOTS:
|
||||||
void start(Priority = InheritPriority);
|
void start(Priority = InheritPriority);
|
||||||
@ -158,98 +165,81 @@ protected:
|
|||||||
private:
|
private:
|
||||||
Q_DECLARE_PRIVATE(QThread)
|
Q_DECLARE_PRIVATE(QThread)
|
||||||
|
|
||||||
|
#ifdef QTHREAD_HAS_CREATE
|
||||||
|
static QThread *createThreadImpl(std::future<void> &&future);
|
||||||
|
#endif
|
||||||
|
|
||||||
friend class QCoreApplication;
|
friend class QCoreApplication;
|
||||||
friend class QThreadData;
|
friend class QThreadData;
|
||||||
};
|
};
|
||||||
|
|
||||||
#ifdef QTHREAD_HAS_CREATE
|
#ifdef QTHREAD_HAS_CREATE
|
||||||
namespace QtPrivate {
|
|
||||||
|
|
||||||
class QThreadCreateThread : public QThread
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
#if defined(QTHREAD_HAS_VARIADIC_CREATE)
|
|
||||||
// C++17: std::thread's constructor complying call
|
|
||||||
template <typename Function, typename... Args>
|
|
||||||
explicit QThreadCreateThread(Function &&f, Args &&... args)
|
|
||||||
: m_future(std::async(std::launch::deferred,
|
|
||||||
[f = static_cast<typename std::decay<Function>::type>(std::forward<Function>(f))](auto &&... largs) mutable -> void
|
|
||||||
{
|
|
||||||
(void)std::invoke(std::move(f), std::forward<decltype(largs)>(largs)...);
|
|
||||||
}, std::forward<Args>(args)...))
|
|
||||||
{
|
|
||||||
}
|
|
||||||
#elif defined(__cpp_init_captures) && __cpp_init_captures >= 201304
|
|
||||||
// C++14: implementation for just one callable
|
|
||||||
template <typename Function>
|
|
||||||
explicit QThreadCreateThread(Function &&f)
|
|
||||||
: m_future(std::async(std::launch::deferred,
|
|
||||||
[f = static_cast<typename std::decay<Function>::type>(std::forward<Function>(f))]() mutable -> void
|
|
||||||
{
|
|
||||||
(void)f();
|
|
||||||
}))
|
|
||||||
{
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
private:
|
|
||||||
// C++11: same as C++14, but with a workaround for not having generalized lambda captures
|
|
||||||
template <typename Function>
|
|
||||||
struct Callable
|
|
||||||
{
|
|
||||||
explicit Callable(Function &&f)
|
|
||||||
: m_function(std::forward<Function>(f))
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
#if defined(Q_COMPILER_DEFAULT_MEMBERS) && defined(Q_COMPILER_DELETE_MEMBERS)
|
|
||||||
// Apply the same semantics of a lambda closure type w.r.t. the special
|
|
||||||
// member functions, if possible: delete the copy assignment operator,
|
|
||||||
// bring back all the others as per the RO5 (cf. §8.1.5.1/11 [expr.prim.lambda.closure])
|
|
||||||
~Callable() = default;
|
|
||||||
Callable(const Callable &) = default;
|
|
||||||
Callable(Callable &&) = default;
|
|
||||||
Callable &operator=(const Callable &) = delete;
|
|
||||||
Callable &operator=(Callable &&) = default;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
void operator()()
|
|
||||||
{
|
|
||||||
(void)m_function();
|
|
||||||
}
|
|
||||||
|
|
||||||
typename std::decay<Function>::type m_function;
|
|
||||||
};
|
|
||||||
|
|
||||||
public:
|
|
||||||
template <typename Function>
|
|
||||||
explicit QThreadCreateThread(Function &&f)
|
|
||||||
: m_future(std::async(std::launch::deferred, Callable<Function>(std::forward<Function>(f))))
|
|
||||||
{
|
|
||||||
}
|
|
||||||
#endif // QTHREAD_HAS_VARIADIC_CREATE
|
|
||||||
|
|
||||||
private:
|
|
||||||
void run() override
|
|
||||||
{
|
|
||||||
m_future.get();
|
|
||||||
}
|
|
||||||
|
|
||||||
std::future<void> m_future;
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace QtPrivate
|
|
||||||
|
|
||||||
#ifdef QTHREAD_HAS_VARIADIC_CREATE
|
#ifdef QTHREAD_HAS_VARIADIC_CREATE
|
||||||
|
// C++17: std::thread's constructor complying call
|
||||||
template <typename Function, typename... Args>
|
template <typename Function, typename... Args>
|
||||||
QThread *QThread::create(Function &&f, Args &&... args)
|
QThread *QThread::create(Function &&f, Args &&... args)
|
||||||
{
|
{
|
||||||
return new QtPrivate::QThreadCreateThread(std::forward<Function>(f), std::forward<Args>(args)...);
|
using DecayedFunction = typename std::decay<Function>::type;
|
||||||
|
auto threadFunction =
|
||||||
|
[f = static_cast<DecayedFunction>(std::forward<Function>(f))](auto &&... largs) mutable -> void
|
||||||
|
{
|
||||||
|
(void)std::invoke(std::move(f), std::forward<decltype(largs)>(largs)...);
|
||||||
|
};
|
||||||
|
|
||||||
|
return createThreadImpl(std::async(std::launch::deferred,
|
||||||
|
std::move(threadFunction),
|
||||||
|
std::forward<Args>(args)...));
|
||||||
}
|
}
|
||||||
#else
|
#elif defined(__cpp_init_captures) && __cpp_init_captures >= 201304
|
||||||
|
// C++14: implementation for just one callable
|
||||||
template <typename Function>
|
template <typename Function>
|
||||||
QThread *QThread::create(Function &&f)
|
QThread *QThread::create(Function &&f)
|
||||||
{
|
{
|
||||||
return new QtPrivate::QThreadCreateThread(std::forward<Function>(f));
|
using DecayedFunction = typename std::decay<Function>::type;
|
||||||
|
auto threadFunction =
|
||||||
|
[f = static_cast<DecayedFunction>(std::forward<Function>(f))]() mutable -> void
|
||||||
|
{
|
||||||
|
(void)f();
|
||||||
|
};
|
||||||
|
|
||||||
|
return createThreadImpl(std::async(std::launch::deferred, std::move(threadFunction)));
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
// C++11: same as C++14, but with a workaround for not having generalized lambda captures
|
||||||
|
namespace QtPrivate {
|
||||||
|
template <typename Function>
|
||||||
|
struct Callable
|
||||||
|
{
|
||||||
|
explicit Callable(Function &&f)
|
||||||
|
: m_function(std::forward<Function>(f))
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
#if defined(Q_COMPILER_DEFAULT_MEMBERS) && defined(Q_COMPILER_DELETE_MEMBERS)
|
||||||
|
// Apply the same semantics of a lambda closure type w.r.t. the special
|
||||||
|
// member functions, if possible: delete the copy assignment operator,
|
||||||
|
// bring back all the others as per the RO5 (cf. §8.1.5.1/11 [expr.prim.lambda.closure])
|
||||||
|
~Callable() = default;
|
||||||
|
Callable(const Callable &) = default;
|
||||||
|
Callable(Callable &&) = default;
|
||||||
|
Callable &operator=(const Callable &) = delete;
|
||||||
|
Callable &operator=(Callable &&) = default;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void operator()()
|
||||||
|
{
|
||||||
|
(void)m_function();
|
||||||
|
}
|
||||||
|
|
||||||
|
typename std::decay<Function>::type m_function;
|
||||||
|
};
|
||||||
|
} // namespace QtPrivate
|
||||||
|
|
||||||
|
template <typename Function>
|
||||||
|
QThread *QThread::create(Function &&f)
|
||||||
|
{
|
||||||
|
return createThreadImpl(std::async(std::launch::deferred, QtPrivate::Callable<Function>(std::forward<Function>(f))));
|
||||||
}
|
}
|
||||||
#endif // QTHREAD_HAS_VARIADIC_CREATE
|
#endif // QTHREAD_HAS_VARIADIC_CREATE
|
||||||
|
|
||||||
|
@ -606,17 +606,19 @@ void QThreadPool::reserveThread()
|
|||||||
++d->reservedThreads;
|
++d->reservedThreads;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*! \property QThreadPool::stacksize
|
/*! \property QThreadPool::stackSize
|
||||||
|
|
||||||
This property contains the stack size for the thread pool worker
|
This property contains the stack size for the thread pool worker
|
||||||
threads.
|
threads.
|
||||||
|
|
||||||
The value of the property is uses when the thread pool creates
|
The value of the property is only used when the thread pool creates
|
||||||
new threads only. Changing it has no effect for already created
|
new threads. Changing it has no effect for already created
|
||||||
or running threads.
|
or running threads.
|
||||||
|
|
||||||
The default value is 0, which makes QThread use the operating
|
The default value is 0, which makes QThread use the operating
|
||||||
system default stack stize.
|
system default stack size.
|
||||||
|
|
||||||
|
\since 5.10
|
||||||
*/
|
*/
|
||||||
void QThreadPool::setStackSize(uint stackSize)
|
void QThreadPool::setStackSize(uint stackSize)
|
||||||
{
|
{
|
||||||
|
@ -296,7 +296,7 @@ static uint qt_create_qhash_seed()
|
|||||||
return seed;
|
return seed;
|
||||||
}
|
}
|
||||||
|
|
||||||
seed = QRandomGenerator::get32();
|
seed = QRandomGenerator::generate();
|
||||||
#endif // QT_BOOTSTRAPPED
|
#endif // QT_BOOTSTRAPPED
|
||||||
|
|
||||||
return seed;
|
return seed;
|
||||||
|
@ -3814,8 +3814,6 @@ QString QLocale::toCurrencyString(double value, const QString &symbol, int preci
|
|||||||
1000. DataSizeIecFormat uses the new IEC standard quantifiers Ki, Mi and so
|
1000. DataSizeIecFormat uses the new IEC standard quantifiers Ki, Mi and so
|
||||||
on, whereas DataSizeSIFormat uses and DataSizeTraditionalFormat abuses the
|
on, whereas DataSizeSIFormat uses and DataSizeTraditionalFormat abuses the
|
||||||
older SI quantifiers k, M, etc.
|
older SI quantifiers k, M, etc.
|
||||||
|
|
||||||
\sa refresh(), caching()
|
|
||||||
*/
|
*/
|
||||||
QString QLocale::formattedDataSize(qint64 bytes, int precision, DataSizeFormats format)
|
QString QLocale::formattedDataSize(qint64 bytes, int precision, DataSizeFormats format)
|
||||||
{
|
{
|
||||||
|
@ -851,17 +851,20 @@ Q_INLINE_TEMPLATE typename QSharedPointer<X>::difference_type operator-(T *ptr1,
|
|||||||
template <class T, class X>
|
template <class T, class X>
|
||||||
Q_INLINE_TEMPLATE bool operator<(const QSharedPointer<T> &ptr1, const QSharedPointer<X> &ptr2)
|
Q_INLINE_TEMPLATE bool operator<(const QSharedPointer<T> &ptr1, const QSharedPointer<X> &ptr2)
|
||||||
{
|
{
|
||||||
return ptr1.data() < ptr2.data();
|
using CT = typename std::common_type<T *, X *>::type;
|
||||||
|
return std::less<CT>()(ptr1.data(), ptr2.data());
|
||||||
}
|
}
|
||||||
template <class T, class X>
|
template <class T, class X>
|
||||||
Q_INLINE_TEMPLATE bool operator<(const QSharedPointer<T> &ptr1, X *ptr2)
|
Q_INLINE_TEMPLATE bool operator<(const QSharedPointer<T> &ptr1, X *ptr2)
|
||||||
{
|
{
|
||||||
return ptr1.data() < ptr2;
|
using CT = typename std::common_type<T *, X *>::type;
|
||||||
|
return std::less<CT>()(ptr1.data(), ptr2);
|
||||||
}
|
}
|
||||||
template <class T, class X>
|
template <class T, class X>
|
||||||
Q_INLINE_TEMPLATE bool operator<(T *ptr1, const QSharedPointer<X> &ptr2)
|
Q_INLINE_TEMPLATE bool operator<(T *ptr1, const QSharedPointer<X> &ptr2)
|
||||||
{
|
{
|
||||||
return ptr1 < ptr2.data();
|
using CT = typename std::common_type<T *, X *>::type;
|
||||||
|
return std::less<CT>()(ptr1, ptr2.data());
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
|
@ -72,6 +72,7 @@
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
|
#include <wchar.h>
|
||||||
|
|
||||||
#include "qchar.cpp"
|
#include "qchar.cpp"
|
||||||
#include "qstringmatcher.cpp"
|
#include "qstringmatcher.cpp"
|
||||||
@ -159,6 +160,43 @@ static inline bool qt_ends_with(QStringView haystack, QStringView needle, Qt::Ca
|
|||||||
static inline bool qt_ends_with(QStringView haystack, QLatin1String needle, Qt::CaseSensitivity cs);
|
static inline bool qt_ends_with(QStringView haystack, QLatin1String needle, Qt::CaseSensitivity cs);
|
||||||
static inline bool qt_ends_with(QStringView haystack, QChar needle, Qt::CaseSensitivity cs);
|
static inline bool qt_ends_with(QStringView haystack, QChar needle, Qt::CaseSensitivity cs);
|
||||||
|
|
||||||
|
qssize_t qustrlen(const ushort *str) Q_DECL_NOTHROW
|
||||||
|
{
|
||||||
|
qssize_t result = 0;
|
||||||
|
|
||||||
|
#ifdef __SSE2__
|
||||||
|
// progress until we get an aligned pointer
|
||||||
|
const ushort *ptr = str;
|
||||||
|
while (*ptr && quintptr(ptr) % 16)
|
||||||
|
++ptr;
|
||||||
|
if (*ptr == 0)
|
||||||
|
return ptr - str;
|
||||||
|
|
||||||
|
// load 16 bytes and see if we have a null
|
||||||
|
// (aligned loads can never segfault)
|
||||||
|
int mask;
|
||||||
|
const __m128i zeroes = _mm_setzero_si128();
|
||||||
|
do {
|
||||||
|
__m128i data = _mm_load_si128(reinterpret_cast<const __m128i *>(ptr));
|
||||||
|
ptr += 8;
|
||||||
|
|
||||||
|
__m128i comparison = _mm_cmpeq_epi16(data, zeroes);
|
||||||
|
mask = _mm_movemask_epi8(comparison);
|
||||||
|
} while (mask == 0);
|
||||||
|
|
||||||
|
// found a null
|
||||||
|
uint idx = qCountTrailingZeroBits(quint32(mask));
|
||||||
|
return ptr - str - 8 + idx / 2;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (sizeof(wchar_t) == sizeof(ushort))
|
||||||
|
return wcslen(reinterpret_cast<const wchar_t *>(str));
|
||||||
|
|
||||||
|
while (*str++)
|
||||||
|
++result;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
#if defined(Q_COMPILER_LAMBDA) && !defined(__OPTIMIZE_SIZE__)
|
#if defined(Q_COMPILER_LAMBDA) && !defined(__OPTIMIZE_SIZE__)
|
||||||
namespace {
|
namespace {
|
||||||
template <uint MaxCount> struct UnrollTailLoop
|
template <uint MaxCount> struct UnrollTailLoop
|
||||||
|
@ -53,6 +53,8 @@ class QLatin1String;
|
|||||||
class QStringView;
|
class QStringView;
|
||||||
template <typename T> class QVector;
|
template <typename T> class QVector;
|
||||||
|
|
||||||
|
Q_REQUIRED_RESULT Q_CORE_EXPORT Q_DECL_PURE_FUNCTION qssize_t qustrlen(const ushort *str) Q_DECL_NOTHROW;
|
||||||
|
|
||||||
Q_REQUIRED_RESULT Q_CORE_EXPORT Q_DECL_PURE_FUNCTION int qCompareStrings(QStringView lhs, QStringView rhs, Qt::CaseSensitivity cs = Qt::CaseSensitive) Q_DECL_NOTHROW;
|
Q_REQUIRED_RESULT Q_CORE_EXPORT Q_DECL_PURE_FUNCTION int qCompareStrings(QStringView lhs, QStringView rhs, Qt::CaseSensitivity cs = Qt::CaseSensitive) Q_DECL_NOTHROW;
|
||||||
Q_REQUIRED_RESULT Q_CORE_EXPORT Q_DECL_PURE_FUNCTION int qCompareStrings(QStringView lhs, QLatin1String rhs, Qt::CaseSensitivity cs = Qt::CaseSensitive) Q_DECL_NOTHROW;
|
Q_REQUIRED_RESULT Q_CORE_EXPORT Q_DECL_PURE_FUNCTION int qCompareStrings(QStringView lhs, QLatin1String rhs, Qt::CaseSensitivity cs = Qt::CaseSensitive) Q_DECL_NOTHROW;
|
||||||
Q_REQUIRED_RESULT Q_CORE_EXPORT Q_DECL_PURE_FUNCTION int qCompareStrings(QLatin1String lhs, QStringView rhs, Qt::CaseSensitivity cs = Qt::CaseSensitive) Q_DECL_NOTHROW;
|
Q_REQUIRED_RESULT Q_CORE_EXPORT Q_DECL_PURE_FUNCTION int qCompareStrings(QLatin1String lhs, QStringView rhs, Qt::CaseSensitivity cs = Qt::CaseSensitive) Q_DECL_NOTHROW;
|
||||||
|
@ -143,20 +143,22 @@ private:
|
|||||||
{
|
{
|
||||||
return qssize_t(N - 1);
|
return qssize_t(N - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename Char>
|
template <typename Char>
|
||||||
static Q_DECL_RELAXED_CONSTEXPR qssize_t lengthHelperPointer(const Char *str) Q_DECL_NOTHROW
|
static qssize_t lengthHelperPointer(const Char *str) Q_DECL_NOTHROW
|
||||||
{
|
{
|
||||||
qssize_t result = 0;
|
#if defined(Q_CC_GNU) && !defined(Q_CC_CLANG) && !defined(Q_CC_INTEL)
|
||||||
while (*str++)
|
if (__builtin_constant_p(*str)) {
|
||||||
++result;
|
qssize_t result = 0;
|
||||||
return result;
|
while (*str++)
|
||||||
|
++result;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
return qustrlen(reinterpret_cast<const ushort *>(str));
|
||||||
}
|
}
|
||||||
static Q_DECL_RELAXED_CONSTEXPR qssize_t lengthHelperPointer(const QChar *str) Q_DECL_NOTHROW
|
static qssize_t lengthHelperPointer(const QChar *str) Q_DECL_NOTHROW
|
||||||
{
|
{
|
||||||
qssize_t result = 0;
|
return qustrlen(reinterpret_cast<const ushort *>(str));
|
||||||
while (!str++->isNull())
|
|
||||||
++result;
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename Char>
|
template <typename Char>
|
||||||
|
@ -2113,8 +2113,8 @@ static QImage convertWithPalette(const QImage &src, QImage::Format format,
|
|||||||
Returns a copy of the image converted to the given \a format,
|
Returns a copy of the image converted to the given \a format,
|
||||||
using the specified \a colorTable.
|
using the specified \a colorTable.
|
||||||
|
|
||||||
Conversion from 32 bit to 8 bit indexed is a slow operation and
|
Conversion from RGB formats to indexed formats is a slow operation
|
||||||
will use a straightforward nearest color approach, with no
|
and will use a straightforward nearest color approach, with no
|
||||||
dithering.
|
dithering.
|
||||||
*/
|
*/
|
||||||
QImage QImage::convertToFormat(Format format, const QVector<QRgb> &colorTable, Qt::ImageConversionFlags flags) const
|
QImage QImage::convertToFormat(Format format, const QVector<QRgb> &colorTable, Qt::ImageConversionFlags flags) const
|
||||||
@ -2122,23 +2122,12 @@ QImage QImage::convertToFormat(Format format, const QVector<QRgb> &colorTable, Q
|
|||||||
if (!d || d->format == format)
|
if (!d || d->format == format)
|
||||||
return *this;
|
return *this;
|
||||||
|
|
||||||
if (format <= QImage::Format_Indexed8 && depth() == 32) {
|
if (format == QImage::Format_Invalid)
|
||||||
return convertWithPalette(*this, format, colorTable);
|
|
||||||
}
|
|
||||||
|
|
||||||
const Image_Converter *converterPtr = &qimage_converter_map[d->format][format];
|
|
||||||
Image_Converter converter = *converterPtr;
|
|
||||||
if (!converter)
|
|
||||||
return QImage();
|
return QImage();
|
||||||
|
if (format <= QImage::Format_Indexed8)
|
||||||
|
return convertWithPalette(convertToFormat(QImage::Format_ARGB32, flags), format, colorTable);
|
||||||
|
|
||||||
QImage image(d->width, d->height, format);
|
return convertToFormat(format, flags);
|
||||||
QIMAGE_SANITYCHECK_MEMORY(image);
|
|
||||||
|
|
||||||
image.d->offset = offset();
|
|
||||||
copyMetadata(image.d, d);
|
|
||||||
|
|
||||||
converter(image.d, d, flags);
|
|
||||||
return image;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user