summaryrefslogtreecommitdiffstats
path: root/examples
diff options
context:
space:
mode:
Diffstat (limited to 'examples')
-rw-r--r--examples/corelib/serialization/cbordump/cbordump.pro14
-rw-r--r--examples/corelib/serialization/cbordump/main.cpp764
-rw-r--r--examples/corelib/serialization/cbordump/tag-transform.xslt25
-rw-r--r--examples/corelib/serialization/serialization.pro4
-rw-r--r--examples/corelib/threads/queuedcustomtype/window.cpp3
-rw-r--r--examples/gui/doc/src/rasterwindow.qdoc5
-rw-r--r--examples/gui/rasterwindow/rasterwindow.cpp4
-rw-r--r--examples/network/network-chat/client.cpp2
-rw-r--r--examples/network/network-chat/connection.cpp264
-rw-r--r--examples/network/network-chat/connection.h17
-rw-r--r--examples/network/network-chat/peermanager.cpp54
-rw-r--r--examples/network/network-chat/peermanager.h4
-rw-r--r--examples/network/network-chat/server.cpp3
-rw-r--r--examples/widgets/doc/src/customsortfiltermodel.qdoc16
-rw-r--r--examples/widgets/graphicsview/boxes/glextensions.h15
-rw-r--r--examples/widgets/graphicsview/boxes/scene.cpp16
-rw-r--r--examples/widgets/itemviews/customsortfiltermodel/mysortfilterproxymodel.cpp17
-rw-r--r--examples/widgets/mainwindows/mainwindow/mainwindow.cpp1
-rw-r--r--examples/widgets/painting/deform/pathdeform.cpp7
-rw-r--r--examples/widgets/richtext/calendar/mainwindow.cpp6
-rw-r--r--examples/widgets/richtext/textedit/example.html14
-rw-r--r--examples/widgets/richtext/textedit/textedit.cpp132
-rw-r--r--examples/widgets/tools/undo/main.cpp2
-rw-r--r--examples/widgets/widgets/tablet/tablet.pro5
24 files changed, 1130 insertions, 264 deletions
diff --git a/examples/corelib/serialization/cbordump/cbordump.pro b/examples/corelib/serialization/cbordump/cbordump.pro
new file mode 100644
index 0000000000..7fb2ef69f0
--- /dev/null
+++ b/examples/corelib/serialization/cbordump/cbordump.pro
@@ -0,0 +1,14 @@
+QT += core
+QT -= gui
+
+TARGET = cbordump
+CONFIG += console
+CONFIG -= app_bundle
+
+TEMPLATE = app
+
+# install
+target.path = $$[QT_INSTALL_EXAMPLES]/corelib/serialization/cbordump
+INSTALLS += target
+
+SOURCES += main.cpp
diff --git a/examples/corelib/serialization/cbordump/main.cpp b/examples/corelib/serialization/cbordump/main.cpp
new file mode 100644
index 0000000000..4cbd03b98d
--- /dev/null
+++ b/examples/corelib/serialization/cbordump/main.cpp
@@ -0,0 +1,764 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 Intel Corporation.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "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 Qt Company Ltd 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."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QCborStreamReader>
+#include <QCommandLineParser>
+#include <QCommandLineOption>
+#include <QCoreApplication>
+#include <QFile>
+#include <QLocale>
+#include <QStack>
+
+#include <math.h>
+#include <stdarg.h>
+#include <stdio.h>
+
+/*
+ * To regenerate:
+ * curl -O https://www.iana.org/assignments/cbor-tags/cbor-tags.xml
+ * xsltproc tag-transform.xslt cbor-tags.xml
+ */
+
+// GENERATED CODE
+struct CborTagDescription
+{
+ QCborTag tag;
+ const char *description; // with space and parentheses
+};
+
+// CBOR Tags
+static const CborTagDescription tagDescriptions[] = {
+ // from https://www.iana.org/assignments/cbor-tags/cbor-tags.xhtml
+ { QCborTag(0), " (Standard date/time string; see Section 2.4.1 [RFC7049])" },
+ { QCborTag(1), " (Epoch-based date/time; see Section 2.4.1 [RFC7049])" },
+ { QCborTag(2), " (Positive bignum; see Section 2.4.2 [RFC7049])" },
+ { QCborTag(3), " (Negative bignum; see Section 2.4.2 [RFC7049])" },
+ { QCborTag(4), " (Decimal fraction; see Section 2.4.3 [RFC7049])" },
+ { QCborTag(5), " (Bigfloat; see Section 2.4.3 [RFC7049])" },
+ { QCborTag(16), " (COSE Single Recipient Encrypted Data Object [RFC8152])" },
+ { QCborTag(17), " (COSE Mac w/o Recipients Object [RFC8152])" },
+ { QCborTag(18), " (COSE Single Signer Data Object [RFC8152])" },
+ { QCborTag(21), " (Expected conversion to base64url encoding; see Section 2.4.4.2 [RFC7049])" },
+ { QCborTag(22), " (Expected conversion to base64 encoding; see Section 2.4.4.2 [RFC7049])" },
+ { QCborTag(23), " (Expected conversion to base16 encoding; see Section 2.4.4.2 [RFC7049])" },
+ { QCborTag(24), " (Encoded CBOR data item; see Section 2.4.4.1 [RFC7049])" },
+ { QCborTag(25), " (reference the nth previously seen string)" },
+ { QCborTag(26), " (Serialised Perl object with classname and constructor arguments)" },
+ { QCborTag(27), " (Serialised language-independent object with type name and constructor arguments)" },
+ { QCborTag(28), " (mark value as (potentially) shared)" },
+ { QCborTag(29), " (reference nth marked value)" },
+ { QCborTag(30), " (Rational number)" },
+ { QCborTag(32), " (URI; see Section 2.4.4.3 [RFC7049])" },
+ { QCborTag(33), " (base64url; see Section 2.4.4.3 [RFC7049])" },
+ { QCborTag(34), " (base64; see Section 2.4.4.3 [RFC7049])" },
+ { QCborTag(35), " (Regular expression; see Section 2.4.4.3 [RFC7049])" },
+ { QCborTag(36), " (MIME message; see Section 2.4.4.3 [RFC7049])" },
+ { QCborTag(37), " (Binary UUID ( section 4.1.2))" },
+ { QCborTag(38), " (Language-tagged string)" },
+ { QCborTag(39), " (Identifier)" },
+ { QCborTag(61), " (CBOR Web Token (CWT))" },
+ { QCborTag(96), " (COSE Encrypted Data Object [RFC8152])" },
+ { QCborTag(97), " (COSE MACed Data Object [RFC8152])" },
+ { QCborTag(98), " (COSE Signed Data Object [RFC8152])" },
+ { QCborTag(256), " (mark value as having string references)" },
+ { QCborTag(257), " (Binary MIME message)" },
+ { QCborTag(258), " (Mathematical finite set)" },
+ { QCborTag(260), " (Network Address (IPv4 or IPv6 or MAC Address))" },
+ { QCborTag(264), " (Decimal fraction with arbitrary exponent)" },
+ { QCborTag(265), " (Bigfloat with arbitrary exponent)" },
+ { QCborTag(1001), " (extended time)" },
+ { QCborTag(1002), " (duration)" },
+ { QCborTag(1003), " (period)" },
+ { QCborTag(22098), " (hint that indicates an additional level of indirection)" },
+ { QCborTag(55799), " (Self-describe CBOR; see Section 2.4.5 [RFC7049])" },
+ { QCborTag(15309736), " (RAINS Message)" },
+ { QCborTag(-1), nullptr }
+};
+// END GENERATED CODE
+
+enum {
+ // See RFC 7049 section 2.
+ SmallValueBitLength = 5,
+ SmallValueMask = (1 << SmallValueBitLength) - 1, /* 0x1f */
+ Value8Bit = 24,
+ Value16Bit = 25,
+ Value32Bit = 26,
+ Value64Bit = 27
+};
+
+struct CborDumper
+{
+ enum DumpOption {
+ ShowCompact = 0x01,
+ ShowWidthIndicators = 0x02,
+ ShowAnnotated = 0x04
+ };
+ Q_DECLARE_FLAGS(DumpOptions, DumpOption)
+
+ CborDumper(QFile *f, DumpOptions opts_);
+ QCborError dump();
+
+private:
+ void dumpOne(int nestingLevel);
+ void dumpOneDetailed(int nestingLevel);
+
+ void printByteArray(const QByteArray &ba);
+ void printWidthIndicator(quint64 value, char space = '\0');
+ void printStringWidthIndicator(quint64 value);
+
+ QCborStreamReader reader;
+ QByteArray data;
+ QStack<quint8> byteArrayEncoding;
+ qint64 offset = 0;
+ DumpOptions opts;
+};
+Q_DECLARE_OPERATORS_FOR_FLAGS(CborDumper::DumpOptions)
+
+static int cborNumberSize(quint64 value)
+{
+ int normalSize = 1;
+ if (value > std::numeric_limits<quint32>::max())
+ normalSize += 8;
+ else if (value > std::numeric_limits<quint16>::max())
+ normalSize += 4;
+ else if (value > std::numeric_limits<quint8>::max())
+ normalSize += 2;
+ else if (value >= Value8Bit)
+ normalSize += 1;
+ return normalSize;
+}
+
+CborDumper::CborDumper(QFile *f, DumpOptions opts_)
+ : opts(opts_)
+{
+ // try to mmap the file, this is faster
+ char *ptr = reinterpret_cast<char *>(f->map(0, f->size(), QFile::MapPrivateOption));
+ if (ptr) {
+ // worked
+ data = QByteArray::fromRawData(ptr, f->size());
+ reader.addData(data);
+ } else if ((opts & ShowAnnotated) || f->isSequential()) {
+ // details requires full contents, so allocate memory
+ data = f->readAll();
+ reader.addData(data);
+ } else {
+ // just use the QIODevice
+ reader.setDevice(f);
+ }
+}
+
+QCborError CborDumper::dump()
+{
+ byteArrayEncoding << quint8(QCborKnownTags::ExpectedBase16);
+ if (!reader.lastError()) {
+ if (opts & ShowAnnotated)
+ dumpOneDetailed(0);
+ else
+ dumpOne(0);
+ }
+
+ QCborError err = reader.lastError();
+ offset = reader.currentOffset();
+ if (err) {
+ fflush(stdout);
+ fprintf(stderr, "cbordump: decoding failed at %lld: %s\n",
+ offset, qPrintable(err.toString()));
+ if (!data.isEmpty())
+ fprintf(stderr, " bytes at %lld: %s\n", offset,
+ data.mid(offset, 9).toHex(' ').constData());
+ } else {
+ if (!opts.testFlag(ShowAnnotated))
+ printf("\n");
+ if (offset < data.size() || (reader.device() && reader.device()->bytesAvailable()))
+ fprintf(stderr, "Warning: bytes remaining at the end of the CBOR stream\n");
+ }
+
+ return err;
+}
+
+template <typename T> static inline bool canConvertTo(double v)
+{
+ // The [conv.fpint] (7.10 Floating-integral conversions) section of the
+ // standard says only exact conversions are guaranteed. Converting
+ // integrals to floating-point with loss of precision has implementation-
+ // defined behavior whether the next higher or next lower is returned;
+ // converting FP to integral is UB if it can't be represented.;
+ Q_STATIC_ASSERT(std::numeric_limits<T>::is_integer);
+
+ double supremum = ldexp(1, std::numeric_limits<T>::digits);
+ if (v >= supremum)
+ return false;
+
+ if (v < std::numeric_limits<T>::min()) // either zero or a power of two, so it's exact
+ return false;
+
+ // we're in range
+ return v == floor(v);
+}
+
+static QString fpToString(double v, const char *suffix)
+{
+ if (qIsInf(v))
+ return v < 0 ? QStringLiteral("-inf") : QStringLiteral("inf");
+ if (qIsNaN(v))
+ return QStringLiteral("nan");
+ if (canConvertTo<qint64>(v))
+ return QString::number(qint64(v)) + ".0" + suffix;
+ if (canConvertTo<quint64>(v))
+ return QString::number(quint64(v)) + ".0" + suffix;
+
+ QString s = QString::number(v, 'g', QLocale::FloatingPointShortest);
+ if (!s.contains('.') && !s.contains('e'))
+ s += '.';
+ s += suffix;
+ return s;
+};
+
+void CborDumper::dumpOne(int nestingLevel)
+{
+ QString indent(1, QLatin1Char(' '));
+ QString indented = indent;
+ if (!opts.testFlag(ShowCompact)) {
+ indent = QLatin1Char('\n') + QString(4 * nestingLevel, QLatin1Char(' '));
+ indented = QLatin1Char('\n') + QString(4 + 4 * nestingLevel, QLatin1Char(' '));
+ }
+
+ switch (reader.type()) {
+ case QCborStreamReader::UnsignedInteger: {
+ quint64 u = reader.toUnsignedInteger();
+ printf("%llu", u);
+ reader.next();
+ printWidthIndicator(u);
+ return;
+ }
+
+ case QCborStreamReader::NegativeInteger: {
+ quint64 n = quint64(reader.toNegativeInteger());
+ if (n == 0) // -2^64 (wrapped around)
+ printf("-18446744073709551616");
+ else
+ printf("-%llu", n);
+ reader.next();
+ printWidthIndicator(n);
+ return;
+ }
+
+ case QCborStreamReader::ByteArray:
+ case QCborStreamReader::String: {
+ bool isLengthKnown = reader.isLengthKnown();
+ if (!isLengthKnown) {
+ printf("(_ ");
+ ++offset;
+ }
+
+ QString comma;
+ if (reader.isByteArray()) {
+ auto r = reader.readByteArray();
+ while (r.status == QCborStreamReader::Ok) {
+ printf("%s", qPrintable(comma));
+ printByteArray(r.data);
+ printStringWidthIndicator(r.data.size());
+
+ r = reader.readByteArray();
+ comma = QLatin1Char(',') + indented;
+ }
+ } else {
+ auto r = reader.readString();
+ while (r.status == QCborStreamReader::Ok) {
+ printf("%s\"%s\"", qPrintable(comma), qPrintable(r.data));
+ printStringWidthIndicator(r.data.toUtf8().size());
+
+ r = reader.readString();
+ comma = QLatin1Char(',') + indented;
+ }
+ }
+
+ if (!isLengthKnown && !reader.lastError())
+ printf(")");
+ break;
+ }
+
+ case QCborStreamReader::Array:
+ case QCborStreamReader::Map: {
+ const char *delimiters = (reader.isArray() ? "[]" : "{}");
+ printf("%c", delimiters[0]);
+
+ if (reader.isLengthKnown()) {
+ quint64 len = reader.length();
+ reader.enterContainer();
+ printWidthIndicator(len, ' ');
+ } else {
+ reader.enterContainer();
+ offset = reader.currentOffset();
+ printf("_ ");
+ }
+
+ const char *comma = "";
+ while (!reader.lastError() && reader.hasNext()) {
+ printf("%s%s", comma, qPrintable(indented));
+ comma = ",";
+ dumpOne(nestingLevel + 1);
+
+ if (reader.parentContainerType() != QCborStreamReader::Map)
+ continue;
+ if (reader.lastError())
+ break;
+ printf(": ");
+ dumpOne(nestingLevel + 1);
+ }
+
+ if (!reader.lastError()) {
+ reader.leaveContainer();
+ printf("%s%c", qPrintable(indent), delimiters[1]);
+ }
+ break;
+ }
+
+ case QCborStreamReader::Tag: {
+ QCborTag tag = reader.toTag();
+ printf("%llu", quint64(tag));
+
+ if (tag == QCborKnownTags::ExpectedBase16 || tag == QCborKnownTags::ExpectedBase64
+ || tag == QCborKnownTags::ExpectedBase64url)
+ byteArrayEncoding.push(quint8(tag));
+
+ if (reader.next()) {
+ printWidthIndicator(quint64(tag));
+ printf("(");
+ dumpOne(nestingLevel); // same level!
+ printf(")");
+ }
+
+ if (tag == QCborKnownTags::ExpectedBase16 || tag == QCborKnownTags::ExpectedBase64
+ || tag == QCborKnownTags::ExpectedBase64url)
+ byteArrayEncoding.pop();
+ break;
+ }
+
+ case QCborStreamReader::SimpleType:
+ switch (reader.toSimpleType()) {
+ case QCborSimpleType::False:
+ printf("false");
+ break;
+ case QCborSimpleType::True:
+ printf("true");
+ break;
+ case QCborSimpleType::Null:
+ printf("null");
+ break;
+ case QCborSimpleType::Undefined:
+ printf("undefined");
+ break;
+ default:
+ printf("simple(%u)", quint8(reader.toSimpleType()));
+ break;
+ }
+ reader.next();
+ break;
+
+ case QCborStreamReader::Float16:
+ printf("%s", qPrintable(fpToString(reader.toFloat16(), "f16")));
+ reader.next();
+ break;
+ case QCborStreamReader::Float:
+ printf("%s", qPrintable(fpToString(reader.toFloat(), "f")));
+ reader.next();
+ break;
+ case QCborStreamReader::Double:
+ printf("%s", qPrintable(fpToString(reader.toDouble(), "")));
+ reader.next();
+ break;
+ case QCborStreamReader::Invalid:
+ return;
+ }
+
+ offset = reader.currentOffset();
+}
+
+void CborDumper::dumpOneDetailed(int nestingLevel)
+{
+ auto tagDescription = [](QCborTag tag) {
+ for (auto entry : tagDescriptions) {
+ if (entry.tag == tag)
+ return entry.description;
+ if (entry.tag > tag)
+ break;
+ }
+ return "";
+ };
+ auto printOverlong = [](int actualSize, quint64 value) {
+ if (cborNumberSize(value) != actualSize)
+ printf(" (overlong)");
+ };
+ auto print = [=](const char *descr, const char *fmt, ...) {
+ qint64 prevOffset = offset;
+ offset = reader.currentOffset();
+ if (prevOffset == offset)
+ return;
+
+ QByteArray bytes = data.mid(prevOffset, offset - prevOffset);
+ QByteArray indent(nestingLevel * 2, ' ');
+ printf("%-50s # %s ", (indent + bytes.toHex(' ')).constData(), descr);
+
+ va_list va;
+ va_start(va, fmt);
+ vprintf(fmt, va);
+ va_end(va);
+
+ if (strstr(fmt, "%ll")) {
+ // Only works because all callers below that use %ll, use it as the
+ // first arg
+ va_start(va, fmt);
+ quint64 value = va_arg(va, quint64);
+ va_end(va);
+ printOverlong(bytes.size(), value);
+ }
+
+ puts("");
+ };
+
+ auto printFp = [=](const char *descr, double d) {
+ QString s = fpToString(d, "");
+ if (s.size() <= 6)
+ return print(descr, "%s", qPrintable(s));
+ return print(descr, "%a", d);
+ };
+
+ auto printString = [=](const char *descr) {
+ QByteArray indent(nestingLevel * 2, ' ');
+ const char *chunkStr = (reader.isLengthKnown() ? "" : "chunk ");
+ int width = 48 - indent.size();
+ int bytesPerLine = qMax(width / 3, 5);
+
+ qsizetype size = reader.currentStringChunkSize();
+ if (size < 0)
+ return; // error
+ if (size >= std::numeric_limits<int>::max()) {
+ fprintf(stderr, "String length too big, %lli\n", qint64(size));
+ exit(EXIT_FAILURE);
+ }
+
+ // if asking for the current string chunk changes the offset, then it
+ // was chunked
+ print(descr, "(indeterminate length)");
+
+ QByteArray bytes(size, Qt::Uninitialized);
+ auto r = reader.readStringChunk(bytes.data(), bytes.size());
+ while (r.status == QCborStreamReader::Ok) {
+ // We'll have to decode the length's width directly from CBOR...
+ const char *lenstart = data.constData() + offset;
+ const char *lenend = lenstart + 1;
+ quint8 additionalInformation = (*lenstart & SmallValueMask);
+
+ // Decode this number directly from CBOR (see RFC 7049 section 2)
+ if (additionalInformation >= Value8Bit) {
+ if (additionalInformation == Value8Bit)
+ lenend += 1;
+ else if (additionalInformation == Value16Bit)
+ lenend += 2;
+ else if (additionalInformation == Value32Bit)
+ lenend += 4;
+ else
+ lenend += 8;
+ }
+
+ {
+ QByteArray lenbytes = QByteArray::fromRawData(lenstart, lenend - lenstart);
+ printf("%-50s # %s %slength %llu",
+ (indent + lenbytes.toHex(' ')).constData(), descr, chunkStr, quint64(size));
+ printOverlong(lenbytes.size(), size);
+ puts("");
+ }
+
+ offset = reader.currentOffset();
+
+ for (int i = 0; i < r.data; i += bytesPerLine) {
+ QByteArray section = bytes.mid(i, bytesPerLine);
+ printf(" %s%s", indent.constData(), section.toHex(' ').constData());
+
+ // print the decode
+ QByteArray spaces(width > 0 ? width - section.size() * 3 + 1: 0, ' ');
+ printf("%s # \"", spaces.constData());
+ auto ptr = reinterpret_cast<const uchar *>(section.constData());
+ for (int j = 0; j < section.size(); ++j)
+ printf("%c", ptr[j] >= 0x80 || ptr[j] < 0x20 ? '.' : ptr[j]);
+
+ puts("\"");
+ }
+
+ // get the next chunk
+ size = reader.currentStringChunkSize();
+ if (size < 0)
+ return; // error
+ if (size >= std::numeric_limits<int>::max()) {
+ fprintf(stderr, "String length too big, %lli\n", qint64(size));
+ exit(EXIT_FAILURE);
+ }
+ bytes.resize(size);
+ r = reader.readStringChunk(bytes.data(), bytes.size());
+ }
+ };
+
+ if (reader.lastError())
+ return;
+
+ switch (reader.type()) {
+ case QCborStreamReader::UnsignedInteger: {
+ quint64 u = reader.toUnsignedInteger();
+ reader.next();
+ if (u < 65536 || (u % 100000) == 0)
+ print("Unsigned integer", "%llu", u);
+ else
+ print("Unsigned integer", "0x%llx", u);
+ return;
+ }
+
+ case QCborStreamReader::NegativeInteger: {
+ quint64 n = quint64(reader.toNegativeInteger());
+ reader.next();
+ print("Negative integer", n == 0 ? "-18446744073709551616" : "-%llu", n);
+ return;
+ }
+
+ case QCborStreamReader::ByteArray:
+ case QCborStreamReader::String: {
+ bool isLengthKnown = reader.isLengthKnown();
+ const char *descr = (reader.isString() ? "Text string" : "Byte string");
+ if (!isLengthKnown)
+ ++nestingLevel;
+
+ printString(descr);
+ if (reader.lastError())
+ return;
+
+ if (!isLengthKnown) {
+ --nestingLevel;
+ print("Break", "");
+ }
+ break;
+ }
+
+ case QCborStreamReader::Array:
+ case QCborStreamReader::Map: {
+ const char *descr = (reader.isArray() ? "Array" : "Map");
+ if (reader.isLengthKnown()) {
+ quint64 len = reader.length();
+ reader.enterContainer();
+ print(descr, "length %llu", len);
+ } else {
+ reader.enterContainer();
+ print(descr, "(indeterminate length)");
+ }
+
+ while (!reader.lastError() && reader.hasNext())
+ dumpOneDetailed(nestingLevel + 1);
+
+ if (!reader.lastError()) {
+ reader.leaveContainer();
+ print("Break", "");
+ }
+ break;
+ }
+
+ case QCborStreamReader::Tag: {
+ QCborTag tag = reader.toTag();
+ reader.next();
+ print("Tag", "%llu%s", quint64(tag), tagDescription(tag));
+ dumpOneDetailed(nestingLevel + 1);
+ break;
+ }
+
+ case QCborStreamReader::SimpleType: {
+ QCborSimpleType st = reader.toSimpleType();
+ reader.next();
+ switch (st) {
+ case QCborSimpleType::False:
+ print("Simple Type", "false");
+ break;
+ case QCborSimpleType::True:
+ print("Simple Type", "true");
+ break;
+ case QCborSimpleType::Null:
+ print("Simple Type", "null");
+ break;
+ case QCborSimpleType::Undefined:
+ print("Simple Type", "undefined");
+ break;
+ default:
+ print("Simple Type", "%u", quint8(st));
+ break;
+ }
+ break;
+ }
+
+ case QCborStreamReader::Float16: {
+ double d = reader.toFloat16();
+ reader.next();
+ printFp("Float16", d);
+ break;
+ }
+ case QCborStreamReader::Float: {
+ double d = reader.toFloat();
+ reader.next();
+ printFp("Float", d);
+ break;
+ }
+ case QCborStreamReader::Double: {
+ double d = reader.toDouble();
+ reader.next();
+ printFp("Double", d);
+ break;
+ }
+ case QCborStreamReader::Invalid:
+ return;
+ }
+
+ offset = reader.currentOffset();
+}
+
+void CborDumper::printByteArray(const QByteArray &ba)
+{
+ switch (byteArrayEncoding.top()) {
+ default:
+ printf("h'%s'", ba.toHex(' ').constData());
+ break;
+
+ case quint8(QCborKnownTags::ExpectedBase64):
+ printf("b64'%s'", ba.toBase64().constData());
+ break;
+
+ case quint8(QCborKnownTags::ExpectedBase64url):
+ printf("b64'%s'", ba.toBase64(QByteArray::Base64UrlEncoding | QByteArray::OmitTrailingEquals).constData());
+ break;
+ }
+}
+
+void printIndicator(quint64 value, qint64 previousOffset, qint64 offset, char space)
+{
+ int normalSize = cborNumberSize(value);
+ int actualSize = offset - previousOffset;
+
+ if (actualSize != normalSize) {
+ Q_ASSERT(actualSize > 1);
+ actualSize -= 2;
+ printf("_%d", qPopulationCount(uint(actualSize)));
+ if (space)
+ printf("%c", space);
+ }
+}
+
+void CborDumper::printWidthIndicator(quint64 value, char space)
+{
+ qint64 previousOffset = offset;
+ offset = reader.currentOffset();
+ if (opts & ShowWidthIndicators)
+ printIndicator(value, previousOffset, offset, space);
+}
+
+void CborDumper::printStringWidthIndicator(quint64 value)
+{
+ qint64 previousOffset = offset;
+ offset = reader.currentOffset();
+ if (opts & ShowWidthIndicators)
+ printIndicator(value, previousOffset, offset - uint(value), '\0');
+}
+
+int main(int argc, char *argv[])
+{
+ QCoreApplication app(argc, argv);
+ setlocale(LC_ALL, "C");
+
+ QCommandLineParser parser;
+ parser.setApplicationDescription(QStringLiteral("CBOR Dumper tool"));
+ parser.addHelpOption();
+
+ QCommandLineOption compact({QStringLiteral("c"), QStringLiteral("compact")},
+ QStringLiteral("Use compact form (no line breaks)"));
+ parser.addOption(compact);
+
+ QCommandLineOption showIndicators({QStringLiteral("i"), QStringLiteral("indicators")},
+ QStringLiteral("Show indicators for width of lengths and integrals"));
+ parser.addOption(showIndicators);
+
+ QCommandLineOption verbose({QStringLiteral("a"), QStringLiteral("annotated")},
+ QStringLiteral("Show bytes and annotated decoding"));
+ parser.addOption(verbose);
+
+ parser.addPositionalArgument(QStringLiteral("[source]"),
+ QStringLiteral("CBOR file to read from"));
+
+ parser.process(app);
+
+ CborDumper::DumpOptions opts;
+ if (parser.isSet(compact))
+ opts |= CborDumper::ShowCompact;
+ if (parser.isSet(showIndicators))
+ opts |= CborDumper::ShowWidthIndicators;
+ if (parser.isSet(verbose))
+ opts |= CborDumper::ShowAnnotated;
+
+ QStringList files = parser.positionalArguments();
+ if (files.isEmpty())
+ files << "-";
+ for (const QString &file : qAsConst(files)) {
+ QFile f(file);
+ if (file == "-" ? f.open(stdin, QIODevice::ReadOnly) : f.open(QIODevice::ReadOnly)) {
+ if (files.size() > 1)
+ printf("/ From \"%s\" /\n", qPrintable(file));
+
+ CborDumper dumper(&f, opts);
+ QCborError err = dumper.dump();
+ if (err)
+ return EXIT_FAILURE;
+ }
+ }
+
+ return EXIT_SUCCESS;
+}
diff --git a/examples/corelib/serialization/cbordump/tag-transform.xslt b/examples/corelib/serialization/cbordump/tag-transform.xslt
new file mode 100644
index 0000000000..3cc1b9b293
--- /dev/null
+++ b/examples/corelib/serialization/cbordump/tag-transform.xslt
@@ -0,0 +1,25 @@
+<?xml version="1.0"?>
+<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:a="http://www.iana.org/assignments" xmlns="http://www.iana.org/assignments" xmlns:_="http://www.iana.org/assignments" xmlns:DEFAULT="http://www.iana.org/assignments" version="1.0">
+<xsl:output omit-xml-declaration="yes" indent="no" method="text"/>
+<xsl:template match="/a:registry[@id='cbor-tags']">struct CborTagDescription
+{
+ QCborTag tag;
+ const char *description; // with space and parentheses
+};
+
+// <xsl:value-of select="a:registry/a:title"/>
+static const CborTagDescription tagDescriptions[] = {
+ // from https://www.iana.org/assignments/cbor-tags/cbor-tags.xhtml
+<xsl:for-each select="a:registry/a:record">
+ <xsl:sort select="a:value" data-type="number"/>
+ <xsl:if test="a:semantics != ''">
+ <xsl:call-template name="row"/>
+ </xsl:if>
+ </xsl:for-each> { QCborTag(-1), nullptr }
+};
+</xsl:template>
+<xsl:template name="row"> { QCborTag(<xsl:value-of select="a:value"/>), " (<xsl:value-of select="a:semantics"/> <xsl:call-template name="xref"/>)" },
+</xsl:template>
+<xsl:template name="xref"><xsl:if test="a:xref/@type = 'rfc'"> [<xsl:value-of select="translate(a:xref/@data,'rfc','RFC')"/>]</xsl:if>
+</xsl:template>
+</xsl:stylesheet>
diff --git a/examples/corelib/serialization/serialization.pro b/examples/corelib/serialization/serialization.pro
index af4d3e6f0f..34fea0c11a 100644
--- a/examples/corelib/serialization/serialization.pro
+++ b/examples/corelib/serialization/serialization.pro
@@ -1,2 +1,4 @@
TEMPLATE = subdirs
-SUBDIRS = savegame
+SUBDIRS = \
+ cbordump \
+ savegame
diff --git a/examples/corelib/threads/queuedcustomtype/window.cpp b/examples/corelib/threads/queuedcustomtype/window.cpp
index 7b9004d868..2cefba1e17 100644
--- a/examples/corelib/threads/queuedcustomtype/window.cpp
+++ b/examples/corelib/threads/queuedcustomtype/window.cpp
@@ -108,9 +108,8 @@ void Window::loadImage()
void Window::loadImage(const QImage &image)
{
- QDesktopWidget desktop;
QImage useImage;
- QRect space = desktop.availableGeometry();
+ QRect space = QGuiApplication::primaryScreen()->availableGeometry();
if (image.width() > 0.75*space.width() || image.height() > 0.75*space.height())
useImage = image.scaled(0.75*space.width(), 0.75*space.height(),
Qt::KeepAspectRatio, Qt::SmoothTransformation);
diff --git a/examples/gui/doc/src/rasterwindow.qdoc b/examples/gui/doc/src/rasterwindow.qdoc
index 36612e1707..0c52a62b8e 100644
--- a/examples/gui/doc/src/rasterwindow.qdoc
+++ b/examples/gui/doc/src/rasterwindow.qdoc
@@ -99,9 +99,8 @@
The resize event is guaranteed to be called prior to the window
being shown on screen and will also be called whenever the window
- is resized while on screen. We use this to resize the back buffer
- and call renderNow() if we are visible to immediately update the
- visual representation of the window on screen.
+ is resized while on screen. We use this to resize the back buffer,
+ and defer rendering to the corresponding/following expose event.
\snippet rasterwindow/rasterwindow.cpp 3
diff --git a/examples/gui/rasterwindow/rasterwindow.cpp b/examples/gui/rasterwindow/rasterwindow.cpp
index 3eacd20145..4dd2ac25ca 100644
--- a/examples/gui/rasterwindow/rasterwindow.cpp
+++ b/examples/gui/rasterwindow/rasterwindow.cpp
@@ -83,8 +83,6 @@ void RasterWindow::renderLater()
void RasterWindow::resizeEvent(QResizeEvent *resizeEvent)
{
m_backingStore->resize(resizeEvent->size());
- if (isExposed())
- renderNow();
}
//! [5]
@@ -109,7 +107,7 @@ void RasterWindow::renderNow()
QPaintDevice *device = m_backingStore->paintDevice();
QPainter painter(device);
- painter.fillRect(0, 0, width(), height(), Qt::white);
+ painter.fillRect(0, 0, width(), height(), QGradient::NightFade);
render(&painter);
painter.end();
diff --git a/examples/network/network-chat/client.cpp b/examples/network/network-chat/client.cpp
index c1eda52a0c..97c2c44b6b 100644
--- a/examples/network/network-chat/client.cpp
+++ b/examples/network/network-chat/client.cpp
@@ -78,7 +78,7 @@ void Client::sendMessage(const QString &message)
QString Client::nickName() const
{
- return QString(peerManager->userName()) + '@' + QHostInfo::localHostName()
+ return peerManager->userName() + '@' + QHostInfo::localHostName()
+ ':' + QString::number(server.serverPort());
}
diff --git a/examples/network/network-chat/connection.cpp b/examples/network/network-chat/connection.cpp
index 332d5dc56b..58cf67eb6d 100644
--- a/examples/network/network-chat/connection.cpp
+++ b/examples/network/network-chat/connection.cpp
@@ -1,6 +1,7 @@
/****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
+** Copyright (C) 2018 Intel Corporation.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the examples of the Qt Toolkit.
@@ -55,17 +56,29 @@
static const int TransferTimeout = 30 * 1000;
static const int PongTimeout = 60 * 1000;
static const int PingInterval = 5 * 1000;
-static const char SeparatorToken = ' ';
+
+/*
+ * Protocol is defined as follows, using the CBOR Data Definition Language:
+ *
+ * protocol = [
+ * greeting, ; must start with a greeting command
+ * * command ; zero or more regular commands after
+ * ]
+ * command = plaintext / ping / pong / greeting
+ * plaintext = { 0 => text }
+ * ping = { 1 => null }
+ * pong = { 2 => null }
+ * greeting = { 3 => text }
+ */
Connection::Connection(QObject *parent)
- : QTcpSocket(parent)
+ : QTcpSocket(parent), writer(this)
{
greetingMessage = tr("undefined");
username = tr("unknown");
state = WaitingForGreeting;
currentDataType = Undefined;
- numBytesForCurrentDataType = -1;
- transferTimerId = 0;
+ transferTimerId = -1;
isGreetingMessageSent = false;
pingTimer.setInterval(PingInterval);
@@ -76,6 +89,22 @@ Connection::Connection(QObject *parent)
this, SLOT(sendGreetingMessage()));
}
+Connection::Connection(qintptr socketDescriptor, QObject *parent)
+ : Connection(parent)
+{
+ setSocketDescriptor(socketDescriptor);
+ reader.setDevice(this);
+}
+
+Connection::~Connection()
+{
+ if (isGreetingMessageSent) {
+ // Indicate clean shutdown.
+ writer.endArray();
+ waitForBytesWritten(2000);
+ }
+}
+
QString Connection::name() const
{
return username;
@@ -91,9 +120,11 @@ bool Connection::sendMessage(const QString &message)
if (message.isEmpty())
return false;
- QByteArray msg = message.toUtf8();
- QByteArray data = "MESSAGE " + QByteArray::number(msg.size()) + ' ' + msg;
- return write(data) == data.size();
+ writer.startMap(1);
+ writer.append(PlainText);
+ writer.append(message);
+ writer.endMap();
+ return true;
}
void Connection::timerEvent(QTimerEvent *timerEvent)
@@ -101,61 +132,75 @@ void Connection::timerEvent(QTimerEvent *timerEvent)
if (timerEvent->timerId() == transferTimerId) {
abort();
killTimer(transferTimerId);
- transferTimerId = 0;
+ transferTimerId = -1;
}
}
void Connection::processReadyRead()
{
- if (state == WaitingForGreeting) {
- if (!readProtocolHeader())
- return;
- if (currentDataType != Greeting) {
- abort();
- return;
+ // we've got more data, let's parse
+ reader.reparse();
+ while (reader.lastError() == QCborError::NoError) {
+ if (state == WaitingForGreeting) {
+ if (!reader.isArray())
+ break; // protocol error
+
+ reader.enterContainer(); // we'll be in this array forever
+ state = ReadingGreeting;
+ } else if (reader.containerDepth() == 1) {
+ // Current state: no command read
+ // Next state: read command ID
+ if (!reader.hasNext()) {
+ reader.leaveContainer();
+ disconnectFromHost();
+ return;
+ }
+
+ if (!reader.isMap() || !reader.isLengthKnown() || reader.length() != 1)
+ break; // protocol error
+ reader.enterContainer();
+ } else if (currentDataType == Undefined) {
+ // Current state: read command ID
+ // Next state: read command payload
+ if (!reader.isInteger())
+ break; // protocol error
+ currentDataType = DataType(reader.toInteger());
+ reader.next();
+ } else {
+ // Current state: read command payload
+ if (reader.isString()) {
+ auto r = reader.readString();
+ buffer += r.data;
+ if (r.status != QCborStreamReader::EndOfString)
+ continue;
+ } else if (reader.isNull()) {
+ reader.next();
+ } else {
+ break; // protocol error
+ }
+
+ // Next state: no command read
+ reader.leaveContainer();
+ if (transferTimerId != -1) {
+ killTimer(transferTimerId);
+ transferTimerId = -1;
+ }
+
+ if (state == ReadingGreeting) {
+ if (currentDataType != Greeting)
+ break; // protocol error
+ processGreeting();
+ } else {
+ processData();
+ }
}
- state = ReadingGreeting;
}
- if (state == ReadingGreeting) {
- if (!hasEnoughData())
- return;
-
- buffer = read(numBytesForCurrentDataType);
- if (buffer.size() != numBytesForCurrentDataType) {
- abort();
- return;
- }
-
- username = QString(buffer) + '@' + peerAddress().toString() + ':'
- + QString::number(peerPort());
- currentDataType = Undefined;
- numBytesForCurrentDataType = 0;
- buffer.clear();
-
- if (!isValid()) {
- abort();
- return;
- }
-
- if (!isGreetingMessageSent)
- sendGreetingMessage();
-
- pingTimer.start();
- pongTime.start();
- state = ReadyForUse;
- emit readyForUse();
- }
+ if (reader.lastError() != QCborError::EndOfFile)
+ abort(); // parse error
- do {
- if (currentDataType == Undefined) {
- if (!readProtocolHeader())
- return;
- }
- if (!hasEnoughData())
- return;
- processData();
- } while (bytesAvailable() > 0);
+ if (transferTimerId != -1 && reader.containerDepth() > 1)
+ transferTimerId = startTimer(TransferTimeout);
}
void Connection::sendPing()
@@ -165,112 +210,58 @@ void Connection::sendPing()
return;
}
- write("PING 1 p");
+ writer.startMap(1);
+ writer.append(Ping);
+ writer.append(nullptr); // no payload
+ writer.endMap();
}
void Connection::sendGreetingMessage()
{
- QByteArray greeting = greetingMessage.toUtf8();
- QByteArray data = "GREETING " + QByteArray::number(greeting.size()) + ' ' + greeting;
- if (write(data) == data.size())
- isGreetingMessageSent = true;
-}
+ writer.startArray(); // this array never ends
-int Connection::readDataIntoBuffer(int maxSize)
-{
- if (maxSize > MaxBufferSize)
- return 0;
+ writer.startMap(1);
+ writer.append(Greeting);
+ writer.append(greetingMessage);
+ writer.endMap();
+ isGreetingMessageSent = true;
- int numBytesBeforeRead = buffer.size();
- if (numBytesBeforeRead == MaxBufferSize) {
- abort();
- return 0;
- }
-
- while (bytesAvailable() > 0 && buffer.size() < maxSize) {
- buffer.append(read(1));
- if (buffer.endsWith(SeparatorToken))
- break;
- }
- return buffer.size() - numBytesBeforeRead;
+ if (!reader.device())
+ reader.setDevice(this);
}
-int Connection::dataLengthForCurrentDataType()
+void Connection::processGreeting()
{
- if (bytesAvailable() <= 0 || readDataIntoBuffer() <= 0
- || !buffer.endsWith(SeparatorToken))
- return 0;
-
- buffer.chop(1);
- int number = buffer.toInt();
+ username = buffer + '@' + peerAddress().toString() + ':'
+ + QString::number(peerPort());
+ currentDataType = Undefined;
buffer.clear();
- return number;
-}
-
-bool Connection::readProtocolHeader()
-{
- if (transferTimerId) {
- killTimer(transferTimerId);
- transferTimerId = 0;
- }
-
- if (readDataIntoBuffer() <= 0) {
- transferTimerId = startTimer(TransferTimeout);
- return false;
- }
- if (buffer == "PING ") {
- currentDataType = Ping;
- } else if (buffer == "PONG ") {
- currentDataType = Pong;
- } else if (buffer == "MESSAGE ") {
- currentDataType = PlainText;
- } else if (buffer == "GREETING ") {
- currentDataType = Greeting;
- } else {
- currentDataType = Undefined;
+ if (!isValid()) {
abort();
- return false;
- }
-
- buffer.clear();
- numBytesForCurrentDataType = dataLengthForCurrentDataType();
- return true;
-}
-
-bool Connection::hasEnoughData()
-{
- if (transferTimerId) {
- QObject::killTimer(transferTimerId);
- transferTimerId = 0;
+ return;
}
- if (numBytesForCurrentDataType <= 0)
- numBytesForCurrentDataType = dataLengthForCurrentDataType();
-
- if (bytesAvailable() < numBytesForCurrentDataType
- || numBytesForCurrentDataType <= 0) {
- transferTimerId = startTimer(TransferTimeout);
- return false;
- }
+ if (!isGreetingMessageSent)
+ sendGreetingMessage();
- return true;
+ pingTimer.start();
+ pongTime.start();
+ state = ReadyForUse;
+ emit readyForUse();
}
void Connection::processData()
{
- buffer = read(numBytesForCurrentDataType);
- if (buffer.size() != numBytesForCurrentDataType) {
- abort();
- return;
- }
-
switch (currentDataType) {
case PlainText:
- emit newMessage(username, QString::fromUtf8(buffer));
+ emit newMessage(username, buffer);
break;
case Ping:
- write("PONG 1 p");
+ writer.startMap(1);
+ writer.append(Pong);
+ writer.append(nullptr); // no payload
+ writer.endMap();
break;
case Pong:
pongTime.restart();
@@ -280,6 +271,5 @@ void Connection::processData()
}
currentDataType = Undefined;
- numBytesForCurrentDataType = 0;
buffer.clear();
}
diff --git a/examples/network/network-chat/connection.h b/examples/network/network-chat/connection.h
index 67d25d4d1e..fa0671a522 100644
--- a/examples/network/network-chat/connection.h
+++ b/examples/network/network-chat/connection.h
@@ -51,10 +51,12 @@
#ifndef CONNECTION_H
#define CONNECTION_H
+#include <QCborStreamReader>
+#include <QCborStreamWriter>
+#include <QElapsedTimer>
#include <QHostAddress>
#include <QString>
#include <QTcpSocket>
-#include <QTime>
#include <QTimer>
static const int MaxBufferSize = 1024000;
@@ -78,6 +80,8 @@ public:
};
Connection(QObject *parent = 0);
+ Connection(qintptr socketDescriptor, QObject *parent = 0);
+ ~Connection();
QString name() const;
void setGreetingMessage(const QString &message);
@@ -96,20 +100,19 @@ private slots:
void sendGreetingMessage();
private:
- int readDataIntoBuffer(int maxSize = MaxBufferSize);
- int dataLengthForCurrentDataType();
- bool readProtocolHeader();
bool hasEnoughData();
+ void processGreeting();
void processData();
+ QCborStreamReader reader;
+ QCborStreamWriter writer;
QString greetingMessage;
QString username;
QTimer pingTimer;
- QTime pongTime;
- QByteArray buffer;
+ QElapsedTimer pongTime;
+ QString buffer;
ConnectionState state;
DataType currentDataType;
- int numBytesForCurrentDataType;
int transferTimerId;
bool isGreetingMessageSent;
};
diff --git a/examples/network/network-chat/peermanager.cpp b/examples/network/network-chat/peermanager.cpp
index c70cc5e56d..38fa2e8e50 100644
--- a/examples/network/network-chat/peermanager.cpp
+++ b/examples/network/network-chat/peermanager.cpp
@@ -1,6 +1,7 @@
/****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
+** Copyright (C) 2018 Intel Corporation.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the examples of the Qt Toolkit.
@@ -62,16 +63,14 @@ PeerManager::PeerManager(Client *client)
{
this->client = client;
- QStringList envVariables;
- envVariables << "USERNAME" << "USER" << "USERDOMAIN"
- << "HOSTNAME" << "DOMAINNAME";
+ static const char *envVariables[] = {
+ "USERNAME", "USER", "USERDOMAIN", "HOSTNAME", "DOMAINNAME"
+ };
- QProcessEnvironment environment = QProcessEnvironment::systemEnvironment();
- foreach (QString string, envVariables) {
- if (environment.contains(string)) {
- username = environment.value(string).toUtf8();
+ for (const char *varname : envVariables) {
+ username = qEnvironmentVariable(varname);
+ if (!username.isNull())
break;
- }
}
if (username.isEmpty())
@@ -95,7 +94,7 @@ void PeerManager::setServerPort(int port)
serverPort = port;
}
-QByteArray PeerManager::userName() const
+QString PeerManager::userName() const
{
return username;
}
@@ -108,7 +107,7 @@ void PeerManager::startBroadcasting()
bool PeerManager::isLocalHostAddress(const QHostAddress &address)
{
foreach (QHostAddress localAddress, ipAddresses) {
- if (address == localAddress)
+ if (address.isEqual(localAddress))
return true;
}
return false;
@@ -116,9 +115,14 @@ bool PeerManager::isLocalHostAddress(const QHostAddress &address)
void PeerManager::sendBroadcastDatagram()
{
- QByteArray datagram(username);
- datagram.append('@');
- datagram.append(QByteArray::number(serverPort));
+ QByteArray datagram;
+ {
+ QCborStreamWriter writer(&datagram);
+ writer.startArray(2);
+ writer.append(username);
+ writer.append(serverPort);
+ writer.endArray();
+ }
bool validBroadcastAddresses = true;
foreach (QHostAddress address, broadcastAddresses) {
@@ -142,11 +146,27 @@ void PeerManager::readBroadcastDatagram()
&senderIp, &senderPort) == -1)
continue;
- QList<QByteArray> list = datagram.split('@');
- if (list.size() != 2)
- continue;
+ int senderServerPort;
+ {
+ // decode the datagram
+ QCborStreamReader reader(datagram);
+ if (reader.lastError() != QCborError::NoError || !reader.isArray())
+ continue;
+ if (!reader.isLengthKnown() || reader.length() != 2)
+ continue;
+
+ reader.enterContainer();
+ if (reader.lastError() != QCborError::NoError || !reader.isString())
+ continue;
+ while (reader.readString().status == QCborStreamReader::Ok) {
+ // we don't actually need the username right now
+ }
+
+ if (reader.lastError() != QCborError::NoError || !reader.isUnsignedInteger())
+ continue;
+ senderServerPort = reader.toInteger();
+ }
- int senderServerPort = list.at(1).toInt();
if (isLocalHostAddress(senderIp) && senderServerPort == serverPort)
continue;
diff --git a/examples/network/network-chat/peermanager.h b/examples/network/network-chat/peermanager.h
index 0bcd67579c..b79028235b 100644
--- a/examples/network/network-chat/peermanager.h
+++ b/examples/network/network-chat/peermanager.h
@@ -68,7 +68,7 @@ public:
PeerManager(Client *client);
void setServerPort(int port);
- QByteArray userName() const;
+ QString userName() const;
void startBroadcasting();
bool isLocalHostAddress(const QHostAddress &address);
@@ -87,7 +87,7 @@ private:
QList<QHostAddress> ipAddresses;
QUdpSocket broadcastSocket;
QTimer broadcastTimer;
- QByteArray username;
+ QString username;
int serverPort;
};
diff --git a/examples/network/network-chat/server.cpp b/examples/network/network-chat/server.cpp
index cc154728d5..b3e4a07f60 100644
--- a/examples/network/network-chat/server.cpp
+++ b/examples/network/network-chat/server.cpp
@@ -61,7 +61,6 @@ Server::Server(QObject *parent)
void Server::incomingConnection(qintptr socketDescriptor)
{
- Connection *connection = new Connection(this);
- connection->setSocketDescriptor(socketDescriptor);
+ Connection *connection = new Connection(socketDescriptor, this);
emit newConnection(connection);
}
diff --git a/examples/widgets/doc/src/customsortfiltermodel.qdoc b/examples/widgets/doc/src/customsortfiltermodel.qdoc
index 6eab846e89..9f0d13dd83 100644
--- a/examples/widgets/doc/src/customsortfiltermodel.qdoc
+++ b/examples/widgets/doc/src/customsortfiltermodel.qdoc
@@ -121,14 +121,14 @@
\snippet itemviews/customsortfiltermodel/mysortfilterproxymodel.cpp 6
- We use QRegExp to define a pattern for the addresses we are looking
- for. The QRegExp::indexIn() function attempts to find a match in
- the given string and returns the position of the first match, or
- -1 if there was no match. If the given string contains the
- pattern, we use QRegExp's \l {QRegExp::cap()}{cap()} function to
- retrieve the actual address. The \l {QRegExp::cap()}{cap()}
- function returns the text captured by the \e nth
- subexpression. The entire match has index 0 and the parenthesized
+ We use QRegularExpression to define a pattern for the addresses we
+ are looking for. The \l {QRegularExpression::match()}{match()} function
+ returns a QRegularExpressionMatch object which contains the result of
+ the matching. If there is a match,
+ \l {QRegularExpressionMatch::hasMatch()}{hasMatch()} returns true. The
+ result of the match can be retrieved with QRegularExpressionMatch's
+ \l {QRegularExpressionMatch::captured()}{captured()} function.
+ The entire match has index 0 and the parenthesized
subexpressions have indexes starting from 1 (excluding
non-capturing parentheses).
diff --git a/examples/widgets/graphicsview/boxes/glextensions.h b/examples/widgets/graphicsview/boxes/glextensions.h
index ac73e61641..685700d866 100644
--- a/examples/widgets/graphicsview/boxes/glextensions.h
+++ b/examples/widgets/graphicsview/boxes/glextensions.h
@@ -78,18 +78,11 @@ glMapBuffer
glUnmapBuffer
*/
-#ifndef Q_OS_MAC
-# ifndef APIENTRYP
-# ifdef APIENTRY
-# define APIENTRYP APIENTRY *
-# else
-# define APIENTRY
-# define APIENTRYP *
-# endif
-# endif
-#else
+#ifndef APIENTRY
# define APIENTRY
-# define APIENTRYP *
+#endif
+#ifndef APIENTRYP
+# define APIENTRYP APIENTRY *
#endif
#ifndef GL_VERSION_1_2
diff --git a/examples/widgets/graphicsview/boxes/scene.cpp b/examples/widgets/graphicsview/boxes/scene.cpp
index f51cad99ac..1637c1f781 100644
--- a/examples/widgets/graphicsview/boxes/scene.cpp
+++ b/examples/widgets/graphicsview/boxes/scene.cpp
@@ -952,17 +952,17 @@ void Scene::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
return;
if (event->buttons() & Qt::LeftButton) {
- m_trackBalls[0].move(pixelPosToViewPos(event->scenePos()), m_trackBalls[2].rotation().conjugate());
+ m_trackBalls[0].move(pixelPosToViewPos(event->scenePos()), m_trackBalls[2].rotation().conjugated());
event->accept();
} else {
- m_trackBalls[0].release(pixelPosToViewPos(event->scenePos()), m_trackBalls[2].rotation().conjugate());
+ m_trackBalls[0].release(pixelPosToViewPos(event->scenePos()), m_trackBalls[2].rotation().conjugated());
}
if (event->buttons() & Qt::RightButton) {
- m_trackBalls[1].move(pixelPosToViewPos(event->scenePos()), m_trackBalls[2].rotation().conjugate());
+ m_trackBalls[1].move(pixelPosToViewPos(event->scenePos()), m_trackBalls[2].rotation().conjugated());
event->accept();
} else {
- m_trackBalls[1].release(pixelPosToViewPos(event->scenePos()), m_trackBalls[2].rotation().conjugate());
+ m_trackBalls[1].release(pixelPosToViewPos(event->scenePos()), m_trackBalls[2].rotation().conjugated());
}
if (event->buttons() & Qt::MidButton) {
@@ -980,12 +980,12 @@ void Scene::mousePressEvent(QGraphicsSceneMouseEvent *event)
return;
if (event->buttons() & Qt::LeftButton) {
- m_trackBalls[0].push(pixelPosToViewPos(event->scenePos()), m_trackBalls[2].rotation().conjugate());
+ m_trackBalls[0].push(pixelPosToViewPos(event->scenePos()), m_trackBalls[2].rotation().conjugated());
event->accept();
}
if (event->buttons() & Qt::RightButton) {
- m_trackBalls[1].push(pixelPosToViewPos(event->scenePos()), m_trackBalls[2].rotation().conjugate());
+ m_trackBalls[1].push(pixelPosToViewPos(event->scenePos()), m_trackBalls[2].rotation().conjugated());
event->accept();
}
@@ -1002,12 +1002,12 @@ void Scene::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
return;
if (event->button() == Qt::LeftButton) {
- m_trackBalls[0].release(pixelPosToViewPos(event->scenePos()), m_trackBalls[2].rotation().conjugate());
+ m_trackBalls[0].release(pixelPosToViewPos(event->scenePos()), m_trackBalls[2].rotation().conjugated());
event->accept();
}
if (event->button() == Qt::RightButton) {
- m_trackBalls[1].release(pixelPosToViewPos(event->scenePos()), m_trackBalls[2].rotation().conjugate());
+ m_trackBalls[1].release(pixelPosToViewPos(event->scenePos()), m_trackBalls[2].rotation().conjugated());
event->accept();
}
diff --git a/examples/widgets/itemviews/customsortfiltermodel/mysortfilterproxymodel.cpp b/examples/widgets/itemviews/customsortfiltermodel/mysortfilterproxymodel.cpp
index c93368b390..35426657d9 100644
--- a/examples/widgets/itemviews/customsortfiltermodel/mysortfilterproxymodel.cpp
+++ b/examples/widgets/itemviews/customsortfiltermodel/mysortfilterproxymodel.cpp
@@ -101,15 +101,20 @@ bool MySortFilterProxyModel::lessThan(const QModelIndex &left,
if (leftData.type() == QVariant::DateTime) {
return leftData.toDateTime() < rightData.toDateTime();
} else {
- static QRegExp emailPattern("[\\w\\.]*@[\\w\\.]*)");
+ static const QRegularExpression emailPattern("[\\w\\.]*@[\\w\\.]*");
QString leftString = leftData.toString();
- if(left.column() == 1 && emailPattern.indexIn(leftString) != -1)
- leftString = emailPattern.cap(1);
-
+ if (left.column() == 1) {
+ const QRegularExpressionMatch match = emailPattern.match(leftString);
+ if (match.hasMatch())
+ leftString = match.captured(0);
+ }
QString rightString = rightData.toString();
- if(right.column() == 1 && emailPattern.indexIn(rightString) != -1)
- rightString = emailPattern.cap(1);
+ if (right.column() == 1) {
+ const QRegularExpressionMatch match = emailPattern.match(rightString);
+ if (match.hasMatch())
+ rightString = match.captured(0);
+ }
return QString::localeAwareCompare(leftString, rightString) < 0;
}
diff --git a/examples/widgets/mainwindows/mainwindow/mainwindow.cpp b/examples/widgets/mainwindows/mainwindow/mainwindow.cpp
index fe31207326..4ba180f312 100644
--- a/examples/widgets/mainwindows/mainwindow/mainwindow.cpp
+++ b/examples/widgets/mainwindows/mainwindow/mainwindow.cpp
@@ -97,6 +97,7 @@ MainWindow::MainWindow(const CustomSizeHintMap &customSizeHints,
QWidget *parent, Qt::WindowFlags flags)
: QMainWindow(parent, flags)
{
+ Q_UNUSED(message);
setObjectName("MainWindow");
setWindowTitle("Qt Main Window Example");
diff --git a/examples/widgets/painting/deform/pathdeform.cpp b/examples/widgets/painting/deform/pathdeform.cpp
index 490a8508d6..cfbbdb7e8e 100644
--- a/examples/widgets/painting/deform/pathdeform.cpp
+++ b/examples/widgets/painting/deform/pathdeform.cpp
@@ -50,7 +50,8 @@
#include "pathdeform.h"
-#include <QApplication>
+#include <QGuiApplication>
+#include <QScreen>
#include <QtDebug>
#include <QMouseEvent>
#include <QTimerEvent>
@@ -247,7 +248,7 @@ void PathDeformControls::layoutForSmallScreen()
deformSlider->setValue(80);
fontSizeSlider->setValue(120);
- QRect screen_size = QApplication::desktop()->screenGeometry();
+ QRect screen_size = QGuiApplication::primaryScreen()->geometry();
radiusSlider->setValue(qMin(screen_size.width(), screen_size.height())/5);
m_renderer->setText(tr("Qt"));
@@ -277,7 +278,7 @@ PathDeformWidget::PathDeformWidget(QWidget *parent, bool smallScreen)
connect(m_renderer, SIGNAL(clicked()), this, SLOT(showControls()));
connect(m_controls, SIGNAL(okPressed()), this, SLOT(hideControls()));
- connect(m_controls, SIGNAL(quitPressed()), QApplication::instance(), SLOT(quit()));
+ connect(m_controls, SIGNAL(quitPressed()), QCoreApplication::instance(), SLOT(quit()));
}
diff --git a/examples/widgets/richtext/calendar/mainwindow.cpp b/examples/widgets/richtext/calendar/mainwindow.cpp
index 12c418e0b1..38dc0e2849 100644
--- a/examples/widgets/richtext/calendar/mainwindow.cpp
+++ b/examples/widgets/richtext/calendar/mainwindow.cpp
@@ -66,7 +66,7 @@ MainWindow::MainWindow()
QComboBox *monthCombo = new QComboBox;
for (int month = 1; month <= 12; ++month)
- monthCombo->addItem(QDate::longMonthName(month));
+ monthCombo->addItem(QLocale::system().monthName(month));
QDateTimeEdit *yearEdit = new QDateTimeEdit;
yearEdit->setDisplayFormat("yyyy");
@@ -168,7 +168,7 @@ void MainWindow::insertCalendar()
QTextTableCell cell = table->cellAt(0, weekDay-1);
//! [11] //! [12]
QTextCursor cellCursor = cell.firstCursorPosition();
- cellCursor.insertText(QString("%1").arg(QDate::longDayName(weekDay)), boldFormat);
+ cellCursor.insertText(QLocale::system().dayName(weekDay), boldFormat);
}
//! [12]
@@ -194,7 +194,7 @@ void MainWindow::insertCalendar()
cursor.endEditBlock();
//! [14]
setWindowTitle(tr("Calendar for %1 %2"
- ).arg(QDate::longMonthName(selectedDate.month())
+ ).arg(QLocale::system().monthName(selectedDate.month())
).arg(selectedDate.year()));
}
//! [14]
diff --git a/examples/widgets/richtext/textedit/example.html b/examples/widgets/richtext/textedit/example.html
index e3a56d1154..99090a697f 100644
--- a/examples/widgets/richtext/textedit/example.html
+++ b/examples/widgets/richtext/textedit/example.html
@@ -1,14 +1,14 @@
<html><head><meta name="qrichtext" content="1" /><meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /><title>QTextEdit Example</title><style type="text/css">
p, li { white-space: pre-wrap; }
</style></head><body style=" font-size:9pt; font-weight:400; font-style:normal; text-decoration:none;">
-<p align="center" style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:20pt; font-weight:600;">QTextEdit</span></p>
+<h1 align="center" style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:20pt; font-weight:600;">QTextEdit</span></h1>
<p align="justify" style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:11pt;">The QTextEdit widget is an advanced editor that supports formatted rich text. It can be used to display HTML and other rich document formats. Internally, QTextEdit uses the QTextDocument class to describe both the high-level structure of each document and the low-level formatting of paragraphs.</span></p>
<p align="justify" style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:11pt;">If you are viewing this document in the <span style=" font-style:italic;">textedit</span> example, you can edit this document to explore Qt's rich text editing features. We have included some comments in each of the following sections to encourage you to experiment. </p>
-<p style=" margin-top:16px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:18pt; font-weight:600;"><span style=" font-size:16pt;">Font and Paragraph Styles</span></p>
+<h2 style=" margin-top:16px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:18pt; font-weight:600;"><span style=" font-size:16pt;">Font and Paragraph Styles</span></h2>
<p align="justify" style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:11pt;">QTextEdit supports </span><span style=" font-size:11pt; font-weight:600;">bold</span><span style=" font-size:11pt;">, </span><span style=" font-size:11pt; font-style:italic;">italic</span><span style=" font-size:11pt;">, and </span><span style=" font-size:11pt; text-decoration: underline;">underlined</span><span style=" font-size:11pt;"> font styles, and can display </span><span style=" font-size:11pt; font-weight:600; color:#00007f;">multicolored</span><span style=" font-size:11pt;"> </span><span style=" font-size:11pt; font-weight:600; color:#aa0000;">text</span><span style=" font-size:11pt;">. Font families such as </span><span style=" font-family:'Times New Roman'; font-size:11pt; font-weight:600;">Times New Roman</span><span style=" font-size:11pt;"> and </span><span style=" font-family:'Courier'; font-size:11pt; font-weight:600;">Courier</span><span style=" font-size:11pt;"> can also be used directly. </span><span style=" font-size:11pt; font-style:italic;">If you place the cursor in a region of styled text, the controls in the tool bars will change to reflect the current style.</span></p>
<p align="justify" style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:11pt;">Paragraphs can be formatted so that the text is left-aligned, right-aligned, centered, or fully justified.</p>
<p align="center" style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:11pt;"><span style=" font-style:italic;">Try changing the alignment of some text and resize the editor to see how the text layout changes.</span> </p>
-<p align="justify" style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:16pt; font-weight:600;">Lists</span></p>
+<h2 align="justify" style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:16pt; font-weight:600;">Lists</span></h2>
<p align="justify" style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:16pt; font-weight:600;"><span style=" font-size:11pt; font-weight:400;">Different kinds of lists can be included in rich text documents. Standard bullet lists can be nested, using different symbols for each level of the list: </span></p>
<ul style="-qt-list-indent: 1;"><li style=" font-size:11pt;" style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Disc symbols are typically used for top-level list items. </li></ul>
<ul type=circle style="-qt-list-indent: 2;"><li style=" font-size:11pt;" style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Circle symbols can be used to distinguish between items in lower-level lists.</li></ul>
@@ -24,10 +24,10 @@ p, li { white-space: pre-wrap; }
<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-size:11pt;"></p>
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:11pt;">The list will automatically be renumbered if you add or remove items. <span style=" font-style:italic;">Try adding new sections to the above list or removing existing item to see the numbers change.</span> </p>
<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-size:11pt;"></p>
-<p style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:11pt;"><span style=" font-size:16pt; font-weight:600;">Images</span></p>
+<h2 style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:11pt;"><span style=" font-size:16pt; font-weight:600;">Images</span></h2>
<p style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:16pt; font-weight:600;"><span style=" font-size:11pt; font-weight:400;">Inline images are treated like ordinary ranges of characters in the text editor, so they flow with the surrounding text. Images can also be selected in the same way as text, making it easy to cut, copy, and paste them. </span></p>
<p align="justify" style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:11pt;"><img src=":/images/logo32.png" /><span style=" font-style:italic;"> Try to select this image by clicking and dragging over it with the mouse, or use the text cursor to select it by holding down Shift and using the arrow keys. You can then cut or copy it, and paste it into different parts of this document.</span></p>
-<p align="justify" style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:11pt;"><span style=" font-size:16pt; font-weight:600;">Tables</span></p>
+<h2 align="justify" style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:11pt;"><span style=" font-size:16pt; font-weight:600;">Tables</span></h2>
<p align="justify" style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:16pt; font-weight:600;"><span style=" font-size:11pt; font-weight:400;">QTextEdit can arrange and format tables, supporting features such as row and column spans, text formatting within cells, and size constraints for columns. </span></p>
<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-size:11pt;"></p>
<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-size:11pt;"></p>
@@ -72,8 +72,8 @@ p, li { white-space: pre-wrap; }
<td></td></tr></table>
<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-size:11pt;"></p>
<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:11pt; font-style:italic;">Try adding text to the cells in the table and experiment with the alignment of the paragraphs.</p>
-<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:11pt;"><span style=" font-size:16pt; font-weight:600;">Hyperlinks</span></p>
+<h2 style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:11pt;"><span style=" font-size:16pt; font-weight:600;">Hyperlinks</span></h2>
<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:11pt;">QTextEdit is designed to support hyperlinks between documents, and this feature is used extensively in </span><span style=" font-size:11pt; font-style:italic;">Qt Assistant</span><span style=" font-size:11pt;">. Hyperlinks are automatically created when an HTML file is imported into an editor. Since the rich text framework supports hyperlinks natively, they can also be created programatically.</span></p>
-<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:11pt;"><span style=" font-size:16pt; font-weight:600;">Undo and Redo</span></p>
+<h2 style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:11pt;"><span style=" font-size:16pt; font-weight:600;">Undo and Redo</span></h2>
<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:11pt;">Full support for undo and redo operations is built into QTextEdit and the underlying rich text framework. Operations on a document can be packaged together to make editing a more comfortable experience for the user.</p>
<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:11pt;"><span style=" font-style:italic;">Try making changes to this document and press Ctrl+Z to undo them. You can always recover the original contents of the document.</span> </p></body></html>
diff --git a/examples/widgets/richtext/textedit/textedit.cpp b/examples/widgets/richtext/textedit/textedit.cpp
index fe4ee4f499..0cc5204675 100644
--- a/examples/widgets/richtext/textedit/textedit.cpp
+++ b/examples/widgets/richtext/textedit/textedit.cpp
@@ -141,7 +141,9 @@ TextEdit::TextEdit(QWidget *parent)
#ifndef QT_NO_CLIPBOARD
actionCut->setEnabled(false);
+ connect(textEdit, &QTextEdit::copyAvailable, actionCut, &QAction::setEnabled);
actionCopy->setEnabled(false);
+ connect(textEdit, &QTextEdit::copyAvailable, actionCopy, &QAction::setEnabled);
connect(QApplication::clipboard(), &QClipboard::dataChanged, this, &TextEdit::clipboardDataChanged);
#endif
@@ -348,6 +350,12 @@ void TextEdit::setupTextActions()
comboStyle->addItem("Ordered List (Alpha upper)");
comboStyle->addItem("Ordered List (Roman lower)");
comboStyle->addItem("Ordered List (Roman upper)");
+ comboStyle->addItem("Heading 1");
+ comboStyle->addItem("Heading 2");
+ comboStyle->addItem("Heading 3");
+ comboStyle->addItem("Heading 4");
+ comboStyle->addItem("Heading 5");
+ comboStyle->addItem("Heading 6");
connect(comboStyle, QOverload<int>::of(&QComboBox::activated), this, &TextEdit::textStyle);
@@ -575,44 +583,56 @@ void TextEdit::textSize(const QString &p)
void TextEdit::textStyle(int styleIndex)
{
QTextCursor cursor = textEdit->textCursor();
+ QTextListFormat::Style style = QTextListFormat::ListStyleUndefined;
+
+ switch (styleIndex) {
+ case 1:
+ style = QTextListFormat::ListDisc;
+ break;
+ case 2:
+ style = QTextListFormat::ListCircle;
+ break;
+ case 3:
+ style = QTextListFormat::ListSquare;
+ break;
+ case 4:
+ style = QTextListFormat::ListDecimal;
+ break;
+ case 5:
+ style = QTextListFormat::ListLowerAlpha;
+ break;
+ case 6:
+ style = QTextListFormat::ListUpperAlpha;
+ break;
+ case 7:
+ style = QTextListFormat::ListLowerRoman;
+ break;
+ case 8:
+ style = QTextListFormat::ListUpperRoman;
+ break;
+ default:
+ break;
+ }
- if (styleIndex != 0) {
- QTextListFormat::Style style = QTextListFormat::ListDisc;
-
- switch (styleIndex) {
- default:
- case 1:
- style = QTextListFormat::ListDisc;
- break;
- case 2:
- style = QTextListFormat::ListCircle;
- break;
- case 3:
- style = QTextListFormat::ListSquare;
- break;
- case 4:
- style = QTextListFormat::ListDecimal;
- break;
- case 5:
- style = QTextListFormat::ListLowerAlpha;
- break;
- case 6:
- style = QTextListFormat::ListUpperAlpha;
- break;
- case 7:
- style = QTextListFormat::ListLowerRoman;
- break;
- case 8:
- style = QTextListFormat::ListUpperRoman;
- break;
- }
+ cursor.beginEditBlock();
- cursor.beginEditBlock();
+ QTextBlockFormat blockFmt = cursor.blockFormat();
- QTextBlockFormat blockFmt = cursor.blockFormat();
+ if (style == QTextListFormat::ListStyleUndefined) {
+ blockFmt.setObjectIndex(-1);
+ int headingLevel = styleIndex >= 9 ? styleIndex - 9 + 1 : 0; // H1 to H6, or Standard
+ blockFmt.setHeadingLevel(headingLevel);
+ cursor.setBlockFormat(blockFmt);
+ int sizeAdjustment = headingLevel ? 4 - headingLevel : 0; // H1 to H6: +3 to -2
+ QTextCharFormat fmt;
+ fmt.setFontWeight(headingLevel ? QFont::Bold : QFont::Normal);
+ fmt.setProperty(QTextFormat::FontSizeAdjustment, sizeAdjustment);
+ cursor.select(QTextCursor::LineUnderCursor);
+ cursor.mergeCharFormat(fmt);
+ textEdit->mergeCurrentCharFormat(fmt);
+ } else {
QTextListFormat listFmt;
-
if (cursor.currentList()) {
listFmt = cursor.currentList()->format();
} else {
@@ -620,18 +640,11 @@ void TextEdit::textStyle(int styleIndex)
blockFmt.setIndent(0);
cursor.setBlockFormat(blockFmt);
}
-
listFmt.setStyle(style);
-
cursor.createList(listFmt);
-
- cursor.endEditBlock();
- } else {
- // ####
- QTextBlockFormat bfmt;
- bfmt.setObjectIndex(-1);
- cursor.mergeBlockFormat(bfmt);
}
+
+ cursor.endEditBlock();
}
void TextEdit::textColor()
@@ -666,6 +679,41 @@ void TextEdit::currentCharFormatChanged(const QTextCharFormat &format)
void TextEdit::cursorPositionChanged()
{
alignmentChanged(textEdit->alignment());
+ QTextList *list = textEdit->textCursor().currentList();
+ if (list) {
+ switch (list->format().style()) {
+ case QTextListFormat::ListDisc:
+ comboStyle->setCurrentIndex(1);
+ break;
+ case QTextListFormat::ListCircle:
+ comboStyle->setCurrentIndex(2);
+ break;
+ case QTextListFormat::ListSquare:
+ comboStyle->setCurrentIndex(3);
+ break;
+ case QTextListFormat::ListDecimal:
+ comboStyle->setCurrentIndex(4);
+ break;
+ case QTextListFormat::ListLowerAlpha:
+ comboStyle->setCurrentIndex(5);
+ break;
+ case QTextListFormat::ListUpperAlpha:
+ comboStyle->setCurrentIndex(6);
+ break;
+ case QTextListFormat::ListLowerRoman:
+ comboStyle->setCurrentIndex(7);
+ break;
+ case QTextListFormat::ListUpperRoman:
+ comboStyle->setCurrentIndex(8);
+ break;
+ default:
+ comboStyle->setCurrentIndex(-1);
+ break;
+ }
+ } else {
+ int headingLevel = textEdit->textCursor().blockFormat().headingLevel();
+ comboStyle->setCurrentIndex(headingLevel ? headingLevel + 8 : 0);
+ }
}
void TextEdit::clipboardDataChanged()
diff --git a/examples/widgets/tools/undo/main.cpp b/examples/widgets/tools/undo/main.cpp
index eff44ca3e8..a5ec1b1b83 100644
--- a/examples/widgets/tools/undo/main.cpp
+++ b/examples/widgets/tools/undo/main.cpp
@@ -62,4 +62,4 @@ int main(int argc, char **argv)
win.show();
return app.exec();
-};
+}
diff --git a/examples/widgets/widgets/tablet/tablet.pro b/examples/widgets/widgets/tablet/tablet.pro
index 5772cd0385..647dc2c2f7 100644
--- a/examples/widgets/widgets/tablet/tablet.pro
+++ b/examples/widgets/widgets/tablet/tablet.pro
@@ -10,6 +10,11 @@ SOURCES = mainwindow.cpp \
tabletapplication.cpp
RESOURCES += images.qrc
+# Avoid naming the target "tablet", as it would create an executable
+# named "tablet.exe" on Windows and trigger a bug (in the Wacom drivers, apparently)
+# preventing tablet messages from being received.
+TARGET = qttablet
+
# install
target.path = $$[QT_INSTALL_EXAMPLES]/widgets/widgets/tablet
INSTALLS += target