summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/3rdparty/pcre2/qt_attribution.json2
-rw-r--r--src/corelib/CMakeLists.txt5
-rw-r--r--src/corelib/configure.cmake2
-rw-r--r--src/corelib/doc/images/javaiterators1.svg59
-rw-r--r--src/corelib/doc/images/javaiterators2.svg63
-rw-r--r--src/corelib/doc/src/java-style-iterators.qdoc4
-rw-r--r--src/corelib/itemmodels/qrangemodel.cpp12
-rw-r--r--src/corelib/itemmodels/qrangemodel_impl.h70
-rw-r--r--src/corelib/kernel/qvariant.cpp152
-rw-r--r--src/corelib/kernel/qvariant.h132
-rw-r--r--src/corelib/platform/windows/quniquehandle_types_windows.cpp17
-rw-r--r--src/corelib/platform/windows/quniquehandle_types_windows_p.h65
-rw-r--r--src/corelib/text/qstring.cpp95
-rw-r--r--src/corelib/time/qgregoriancalendar.cpp1
-rw-r--r--src/corelib/time/qjalalicalendar.cpp1
-rw-r--r--src/corelib/time/qjuliancalendar.cpp1
-rw-r--r--src/corelib/time/qmilankoviccalendar.cpp1
-rw-r--r--src/corelib/time/qromancalendar.cpp1
-rw-r--r--src/corelib/time/qtimezone.cpp7
-rw-r--r--src/corelib/time/qtimezonelocale.cpp64
-rw-r--r--src/corelib/time/qtimezoneprivate.cpp12
-rw-r--r--src/corelib/time/qtimezoneprivate_p.h18
-rw-r--r--src/corelib/tools/qiterator.qdoc20
-rw-r--r--src/corelib/tools/quniquehandle_p.h103
-rw-r--r--src/gui/kernel/qevent.cpp75
-rw-r--r--src/gui/kernel/qinputdevice.cpp5
-rw-r--r--src/gui/kernel/qpointingdevice.cpp23
-rw-r--r--src/gui/rhi/qrhi.cpp20
-rw-r--r--src/gui/rhi/qrhi.h4
-rw-r--r--src/gui/rhi/qrhid3d11.cpp2
-rw-r--r--src/gui/rhi/qrhid3d12.cpp2
-rw-r--r--src/gui/rhi/qrhigles2.cpp22
-rw-r--r--src/gui/rhi/qrhigles2_p.h3
-rw-r--r--src/gui/rhi/qrhimetal.mm8
-rw-r--r--src/gui/rhi/qrhimetal_p.h1
-rw-r--r--src/gui/rhi/qrhivulkan.cpp4
-rw-r--r--src/gui/rhi/qrhivulkan_p.h1
-rw-r--r--src/gui/text/qfontvariableaxis.cpp38
-rw-r--r--src/network/access/qhttp2protocolhandler.cpp14
-rw-r--r--src/network/access/qnetworkreplyhttpimpl.cpp14
-rw-r--r--src/network/access/qnetworkreplyhttpimpl_p.h1
-rw-r--r--src/plugins/platforms/cocoa/qcocoafiledialoghelper.mm2
-rw-r--r--src/plugins/platforms/cocoa/qcocoamessagedialog.mm5
-rw-r--r--src/plugins/platforms/wasm/qwasmaccessibility.cpp142
-rw-r--r--src/plugins/platforms/wasm/qwasmaccessibility.h9
-rw-r--r--src/plugins/platforms/wayland/global/qwaylandclientextension.cpp5
-rw-r--r--src/plugins/platforms/wayland/qwaylandinputcontext.cpp10
-rw-r--r--src/plugins/platforms/windows/qwindowscontext.cpp3
-rw-r--r--src/plugins/platforms/windows/qwindowsiconengine.cpp6
-rw-r--r--src/plugins/platforms/windows/qwindowswindow.cpp23
-rw-r--r--src/plugins/styles/modernwindows/qwindows11style.cpp102
-rw-r--r--src/plugins/styles/modernwindows/qwindows11style_p.h1
-rw-r--r--src/plugins/styles/modernwindows/qwindowsvistastyle.cpp3
-rw-r--r--src/plugins/styles/modernwindows/qwindowsvistastyle_p_p.h4
-rw-r--r--src/testlib/qtestcase.cpp13
-rw-r--r--src/widgets/accessible/itemviews.cpp4
-rw-r--r--src/widgets/accessible/itemviews_p.h4
-rw-r--r--src/widgets/accessible/rangecontrols.cpp10
-rw-r--r--src/widgets/accessible/rangecontrols_p.h1
-rw-r--r--src/widgets/dialogs/qfontdialog.cpp2
-rw-r--r--src/widgets/kernel/qlayout.cpp11
61 files changed, 1181 insertions, 323 deletions
diff --git a/src/3rdparty/pcre2/qt_attribution.json b/src/3rdparty/pcre2/qt_attribution.json
index ef29ad7d951..0468bca1b3e 100644
--- a/src/3rdparty/pcre2/qt_attribution.json
+++ b/src/3rdparty/pcre2/qt_attribution.json
@@ -30,7 +30,7 @@
"Homepage": "http://www.pcre.org/",
"Version": "10.47",
"DownloadLocation": "https://github.com/PCRE2Project/pcre2/releases/download/pcre2-10.47/pcre2-10.47.tar.bz2",
- "PURL": "pkg:github/PCRE2Project/pcre2@$<VERSION>",
+ "PURL": "pkg:github/PCRE2Project/pcre2@pcre2-$<VERSION>",
"CPE": "cpe:2.3:a:pcre:pcre2:$<VERSION>:*:*:*:*:*:*:*",
"License": "BSD 2-clause \"Simplified\" License",
"LicenseId": "BSD-2-Clause",
diff --git a/src/corelib/CMakeLists.txt b/src/corelib/CMakeLists.txt
index 1147205b79f..380b571c3cf 100644
--- a/src/corelib/CMakeLists.txt
+++ b/src/corelib/CMakeLists.txt
@@ -638,6 +638,7 @@ qt_internal_extend_target(Core CONDITION WIN32
platform/windows/qcomptr_p.h
platform/windows/qbstr_p.h
platform/windows/qcomvariant_p.h
+ platform/windows/quniquehandle_types_windows.cpp platform/windows/quniquehandle_types_windows_p.h
LIBRARIES
advapi32
authz
@@ -1028,7 +1029,7 @@ qt_internal_extend_target(Core
qt_internal_extend_target(Core
CONDITION
- QT_FEATURE_timezone AND UNIX
+ QT_FEATURE_timezone AND UNIX AND NOT VXWORKS
AND NOT ANDROID AND NOT APPLE AND NOT QT_FEATURE_timezone_tzdb
SOURCES
time/qtimezoneprivate_tz.cpp
@@ -1037,7 +1038,7 @@ qt_internal_extend_target(Core
qt_internal_extend_target(Core
CONDITION
QT_FEATURE_icu AND QT_FEATURE_timezone
- AND NOT UNIX AND NOT QT_FEATURE_timezone_tzdb
+ AND (VXWORKS OR NOT UNIX) AND NOT QT_FEATURE_timezone_tzdb
SOURCES
time/qtimezoneprivate_icu.cpp
)
diff --git a/src/corelib/configure.cmake b/src/corelib/configure.cmake
index d951b85c147..edcfba0f6ce 100644
--- a/src/corelib/configure.cmake
+++ b/src/corelib/configure.cmake
@@ -1150,7 +1150,7 @@ qt_feature("timezone" PUBLIC
SECTION "Utilities"
LABEL "QTimeZone"
PURPOSE "Provides support for time-zone handling."
- CONDITION NOT WASM AND NOT VXWORKS
+ CONDITION NOT WASM
)
qt_feature("timezone_locale" PRIVATE
SECTION "Utilities"
diff --git a/src/corelib/doc/images/javaiterators1.svg b/src/corelib/doc/images/javaiterators1.svg
new file mode 100644
index 00000000000..468dbe5371c
--- /dev/null
+++ b/src/corelib/doc/images/javaiterators1.svg
@@ -0,0 +1,59 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg
+ version="1.1"
+ width="340"
+ height="110"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:svg="http://www.w3.org/2000/svg">
+
+<style>
+ svg .box-style { stroke: black; fill: white }
+ svg .line-style { stroke: red; fill: none }
+ svg .text-style { font: 20px arial; fill: black }
+ svg .fill-style { stroke: none; fill: red }
+
+ [data-theme="dark"] svg .box-style { stroke: #f2f2f2; fill: black }
+ [data-theme="dark"] svg .line-style { stroke: red; fill: none }
+ [data-theme="dark"] svg .text-style { font: 20px arial; fill: #f2f2f2 }
+ [data-theme="dark"] svg .fill-style { stroke: none; fill: red }
+
+ [data-theme="light"] svg .box-style { stroke: black; fill: white }
+ [data-theme="light"] svg .line-style { stroke: red; fill: none }
+ [data-theme="light"] svg .text-style { font: 20px arial; fill: black }
+ [data-theme="light"] svg .fill-style { stroke: none; fill: red }
+</style>
+
+<g transform="translate(10.5, 10.5)">
+<path d="m 0,0 h 80 v 60 h -80 z" class="box-style" />
+<text x="35" y="36" class="text-style">A</text>
+<path d="M 0,60 v 30" class="line-style" />
+<path d="M 0,60 l -5,10 l 10,0 z" class="fill-style" />
+</g>
+
+<g transform="translate(90.5, 10.5)">
+<path d="m 0,0 h 80 v 60 h -80 z" class="box-style" />
+<text x="35" y="36" class="text-style">B</text>
+<path d="M 0,60 v 30" class="line-style" />
+<path d="M 0,60 l -5,10 l 10,0 z" class="fill-style" />
+</g>
+
+<g transform="translate(170.5, 10.5)">
+<path d="m 0,0 h 80 v 60 h -80 z" class="box-style" />
+<text x="35" y="36" class="text-style">C</text>
+<path d="M 0,60 v 30" class="line-style" />
+<path d="M 0,60 l -5,10 l 10,0 z" class="fill-style" />
+</g>
+
+<g transform="translate(250.5, 10.5)">
+<path d="m 0,0 h 80 v 60 h -80 z" class="box-style" />
+<text x="35" y="36" class="text-style">D</text>
+<path d="M 0,60 v 30" class="line-style" />
+<path d="M 0,60 l -5,10 l 10,0 z" class="fill-style" />
+</g>
+
+<g transform="translate(330.5, 10.5)">
+<path d="M 0,60 v 30" class="line-style" />
+<path d="M 0,60 l -5,10 l 10,0 z" class="fill-style" />
+</g>
+
+</svg>
diff --git a/src/corelib/doc/images/javaiterators2.svg b/src/corelib/doc/images/javaiterators2.svg
new file mode 100644
index 00000000000..df4c6b352a6
--- /dev/null
+++ b/src/corelib/doc/images/javaiterators2.svg
@@ -0,0 +1,63 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg
+ version="1.1"
+ width="340"
+ height="130"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:svg="http://www.w3.org/2000/svg">
+
+<style>
+ svg .box-style { stroke: black; fill: white }
+ svg .line-style { stroke: red; fill: none }
+ svg .fill-style { stroke: none; fill: red }
+ svg .np-line-style { stroke: blue; fill: none }
+ svg .np-fill-style { stroke: none; fill: blue }
+ svg .text-style { font: 20px arial; fill: black }
+ svg .small-text-style { font: 12px monospace; fill: black }
+
+ [data-theme="dark"] svg .box-style { stroke: #f2f2f2; fill: black }
+ [data-theme="dark"] svg .line-style { stroke: red; fill: none }
+ [data-theme="dark"] svg .fill-style { stroke: none; fill: red }
+ [data-theme="dark"] svg .np-line-style { stroke: #4080ff; fill: none; stroke-width: 1.5 }
+ [data-theme="dark"] svg .np-fill-style { stroke: none; fill: #4080ff }
+ [data-theme="dark"] svg .text-style { font: 20px arial; fill: #f2f2f2 }
+ [data-theme="dark"] svg .small-text-style { font: 12px monospace; fill: #f2f2f2 }
+
+ [data-theme="light"] svg .box-style { stroke: black; fill: white }
+ [data-theme="light"] svg .line-style { stroke: red; fill: none }
+ [data-theme="light"] svg .fill-style { stroke: none; fill: red }
+ [data-theme="light"] svg .np-line-style { stroke: blue; fill: none }
+ [data-theme="light"] svg .np-fill-style { stroke: none; fill: blue }
+ [data-theme="light"] svg .text-style { font: 20px arial; fill: black }
+ [data-theme="light"] svg .small-text-style { font: 12px monospace; fill: black }
+</style>
+
+<g transform="translate(10.5, 10.5)">
+<path d="m 0,0 h 80 v 60 h -80 z" class="box-style" />
+<text x="35" y="36" class="text-style">A</text>
+</g>
+
+<g transform="translate(90.5, 10.5)">
+<path d="m 0,0 h 80 v 60 h -80 z" class="box-style" />
+<text x="35" y="36" class="text-style">B</text>
+<path d="M 0,60 c 0,30 50,40 80,30" class="np-line-style" />
+<path d="M 0,60 l -2,14 l 11,-4 z" class="np-fill-style" />
+<text x="-15" y="110" class="small-text-style">previous()</text>
+</g>
+
+<g transform="translate(170.5, 10.5)">
+<path d="m 0,0 h 80 v 60 h -80 z" class="box-style" />
+<text x="35" y="36" class="text-style">C</text>
+<path d="M 0,60 v 50" class="line-style" />
+<path d="M 0,60 l -5,10 l 10,0 z" class="fill-style" />
+<text x="30" y="110" class="small-text-style">next()</text>
+</g>
+
+<g transform="translate(250.5, 10.5)">
+<path d="m 0,0 h 80 v 60 h -80 z" class="box-style" />
+<text x="35" y="36" class="text-style">D</text>
+<path d="M 0,60 c 0,30 -50,40 -80,30" class="np-line-style" />
+<path d="M 0,60 l 2,14 l -11,-4 z" class="np-fill-style" />
+</g>
+
+</svg>
diff --git a/src/corelib/doc/src/java-style-iterators.qdoc b/src/corelib/doc/src/java-style-iterators.qdoc
index 856005cb66c..a0e5c53d633 100644
--- a/src/corelib/doc/src/java-style-iterators.qdoc
+++ b/src/corelib/doc/src/java-style-iterators.qdoc
@@ -42,7 +42,7 @@
diagram below shows the valid iterator positions as red arrows for a list
containing four items:
- \image javaiterators1.png
+ \image javaiterators1.svg Java-style iterators point between items
Here's a typical loop for iterating through all the elements of a
QList<QString> in order:
@@ -70,7 +70,7 @@
\l{QListIterator::next()}{next()} and
\l{QListIterator::previous()}{previous()} on an iterator:
- \image javaiterators2.png
+ \image javaiterators2.png Iterating to the next and previous items
The following table summarizes the QListIterator API:
diff --git a/src/corelib/itemmodels/qrangemodel.cpp b/src/corelib/itemmodels/qrangemodel.cpp
index 05e3a39e589..b0c6c46b125 100644
--- a/src/corelib/itemmodels/qrangemodel.cpp
+++ b/src/corelib/itemmodels/qrangemodel.cpp
@@ -20,6 +20,8 @@ public:
private:
std::unique_ptr<QRangeModelImplBase, QRangeModelImplBase::Deleter> impl;
+ friend class QRangeModelImplBase;
+
mutable QHash<int, QByteArray> m_roleNames;
};
@@ -28,6 +30,16 @@ QRangeModel::QRangeModel(QRangeModelImplBase *impl, QObject *parent)
{
}
+QRangeModelImplBase *QRangeModelImplBase::getImplementation(QRangeModel *model)
+{
+ return model->d_func()->impl.get();
+}
+
+const QRangeModelImplBase *QRangeModelImplBase::getImplementation(const QRangeModel *model)
+{
+ return model->d_func()->impl.get();
+}
+
/*!
\class QRangeModel
\inmodule QtCore
diff --git a/src/corelib/itemmodels/qrangemodel_impl.h b/src/corelib/itemmodels/qrangemodel_impl.h
index f38dc88c0d9..c2f473542d7 100644
--- a/src/corelib/itemmodels/qrangemodel_impl.h
+++ b/src/corelib/itemmodels/qrangemodel_impl.h
@@ -842,6 +842,11 @@ namespace QRangeModelDetails
{
using protocol = wrapped_t<Protocol>;
using row = typename range_traits<wrapped_t<Range>>::value_type;
+ static constexpr bool is_tree = std::conjunction_v<protocol_parentRow<protocol, row>,
+ protocol_childRows<protocol, row>>;
+ static constexpr bool is_list = static_size_v<row> == 0
+ && (!has_metaobject_v<row> || row_category<row>::isMultiRole);
+ static constexpr bool is_table = !is_list && !is_tree;
static constexpr bool has_newRow = protocol_newRow<protocol>();
static constexpr bool has_deleteRow = protocol_deleteRow<protocol, row>();
@@ -1046,6 +1051,9 @@ public:
typename C::MultiData
>;
+ static Q_CORE_EXPORT QRangeModelImplBase *getImplementation(QRangeModel *model);
+ static Q_CORE_EXPORT const QRangeModelImplBase *getImplementation(const QRangeModel *model);
+
private:
friend class QRangeModelPrivate;
QRangeModel *m_rangeModel;
@@ -1147,13 +1155,6 @@ protected:
}
}
- static constexpr bool isMutable()
- {
- return range_features::is_mutable && row_features::is_mutable
- && std::is_reference_v<row_reference>
- && Structure::is_mutable_impl;
- }
-
static constexpr int static_row_count = QRangeModelDetails::static_size_v<range_type>;
static constexpr bool rows_are_raw_pointers = std::is_pointer_v<row_type>;
static constexpr bool rows_are_owning_or_raw_pointers =
@@ -1161,9 +1162,6 @@ protected:
static constexpr int static_column_count = QRangeModelDetails::static_size_v<row_type>;
static constexpr bool one_dimensional_range = static_column_count == 0;
- static constexpr bool dynamicRows() { return isMutable() && static_row_count < 0; }
- static constexpr bool dynamicColumns() { return static_column_count < 0; }
-
// A row might be a value (or range of values), or a pointer.
// row_ptr is always a pointer, and const_row_ptr is a pointer to const.
using row_ptr = wrapped_row_type *;
@@ -1205,6 +1203,15 @@ protected:
"The range holding a move-only row-type must support insert(pos, start, end)");
public:
+ static constexpr bool isMutable()
+ {
+ return range_features::is_mutable && row_features::is_mutable
+ && std::is_reference_v<row_reference>
+ && Structure::is_mutable_impl;
+ }
+ static constexpr bool dynamicRows() { return isMutable() && static_row_count < 0; }
+ static constexpr bool dynamicColumns() { return static_column_count < 0; }
+
explicit QRangeModelImpl(Range &&model, Protocol&& protocol, QRangeModel *itemModel)
: Ancestor(itemModel)
, ProtocolStorage{std::forward<Protocol>(protocol)}
@@ -1236,7 +1243,7 @@ public:
if (row == index.row() && column == index.column())
return index;
- if (column < 0 || column >= this->itemModel().columnCount())
+ if (column < 0 || column >= this->columnCount({}))
return {};
if (row == index.row())
@@ -1974,8 +1981,8 @@ public:
}
if (sourceRow == destRow || sourceRow == destRow - 1 || count <= 0
- || sourceRow < 0 || sourceRow + count - 1 >= this->itemModel().rowCount(sourceParent)
- || destRow < 0 || destRow > this->itemModel().rowCount(destParent)) {
+ || sourceRow < 0 || sourceRow + count - 1 >= this->rowCount(sourceParent)
+ || destRow < 0 || destRow > this->rowCount(destParent)) {
return false;
}
@@ -1995,11 +2002,14 @@ public:
}
}
- QModelIndex parent(const QModelIndex &child) const { return that().parent(child); }
+ const protocol_type& protocol() const { return QRangeModelDetails::refTo(ProtocolStorage::object()); }
+ protocol_type& protocol() { return QRangeModelDetails::refTo(ProtocolStorage::object()); }
+
+ QModelIndex parent(const QModelIndex &child) const { return that().parentImpl(child); }
- int rowCount(const QModelIndex &parent) const { return that().rowCount(parent); }
+ int rowCount(const QModelIndex &parent) const { return that().rowCountImpl(parent); }
- int columnCount(const QModelIndex &parent) const { return that().columnCount(parent); }
+ int columnCount(const QModelIndex &parent) const { return that().columnCountImpl(parent); }
void destroy() { delete std::addressof(that()); }
@@ -2035,6 +2045,11 @@ public:
protected:
~QRangeModelImpl()
{
+ deleteOwnedRows();
+ }
+
+ void deleteOwnedRows()
+ {
// We delete row objects if we are not operating on a reference or pointer
// to a range, as in that case, the owner of the referenced/pointed to
// range also owns the row entries.
@@ -2335,9 +2350,6 @@ protected:
}
- const protocol_type& protocol() const { return QRangeModelDetails::refTo(ProtocolStorage::object()); }
- protocol_type& protocol() { return QRangeModelDetails::refTo(ProtocolStorage::object()); }
-
ModelData m_data;
};
@@ -2385,7 +2397,7 @@ protected:
return this->createIndex(row, column, QRangeModelDetails::pointerTo(*it));
}
- QModelIndex parent(const QModelIndex &child) const
+ QModelIndex parentImpl(const QModelIndex &child) const
{
if (!child.isValid())
return {};
@@ -2410,12 +2422,12 @@ protected:
return {};
}
- int rowCount(const QModelIndex &parent) const
+ int rowCountImpl(const QModelIndex &parent) const
{
return Base::size(this->childRange(parent));
}
- int columnCount(const QModelIndex &) const
+ int columnCountImpl(const QModelIndex &) const
{
// all levels of a tree have to have the same, static, column count
if constexpr (Base::one_dimensional_range)
@@ -2662,6 +2674,9 @@ class QGenericTableItemModelImpl
using Base = QRangeModelImpl<QGenericTableItemModelImpl<Range>, Range>;
friend class QRangeModelImpl<QGenericTableItemModelImpl<Range>, Range>;
+ static constexpr bool is_mutable_impl = true;
+
+public:
using range_type = typename Base::range_type;
using range_features = typename Base::range_features;
using row_type = typename Base::row_type;
@@ -2669,9 +2684,6 @@ class QGenericTableItemModelImpl
using row_traits = typename Base::row_traits;
using row_features = typename Base::row_features;
- static constexpr bool is_mutable_impl = true;
-
-public:
explicit QGenericTableItemModelImpl(Range &&model, QRangeModel *itemModel)
: Base(std::forward<Range>(model), {}, itemModel)
{}
@@ -2692,19 +2704,19 @@ protected:
}
}
- QModelIndex parent(const QModelIndex &) const
+ QModelIndex parentImpl(const QModelIndex &) const
{
return {};
}
- int rowCount(const QModelIndex &parent) const
+ int rowCountImpl(const QModelIndex &parent) const
{
if (parent.isValid())
return 0;
return int(Base::size(*this->m_data.model()));
}
- int columnCount(const QModelIndex &parent) const
+ int columnCountImpl(const QModelIndex &parent) const
{
if (parent.isValid())
return 0;
@@ -2760,7 +2772,7 @@ protected:
// dynamically sized rows all have to have the same column count
if constexpr (Base::dynamicColumns() && row_features::has_resize) {
if (QRangeModelDetails::isValid(empty_row))
- QRangeModelDetails::refTo(empty_row).resize(this->itemModel().columnCount());
+ QRangeModelDetails::refTo(empty_row).resize(this->columnCount({}));
}
return empty_row;
diff --git a/src/corelib/kernel/qvariant.cpp b/src/corelib/kernel/qvariant.cpp
index 8366787ea66..57089f164b2 100644
--- a/src/corelib/kernel/qvariant.cpp
+++ b/src/corelib/kernel/qvariant.cpp
@@ -2974,4 +2974,156 @@ const QVariant *QVariantConstPointer::operator->() const
implement operator->().
*/
+/*!
+ \class QVariant::ConstReference
+ \since 6.11
+ \inmodule QtCore
+ \brief The QVariant::ConstReference acts as a const reference to a QVariant.
+
+ As the generic iterators don't actually instantiate a QVariant on each
+ step, they cannot return a reference to one from operator*().
+ QVariant::ConstReference provides the same functionality as an actual
+ reference to a QVariant would, but is backed a referred-to value given as
+ template parameter. The template is implemented for
+ QMetaSequence::ConstIterator, QMetaSequence::Iterator,
+ QMetaAssociation::ConstIterator, and QMetaAssociation::Iterator.
+*/
+
+/*!
+ \fn template<typename Referred> QVariant::ConstReference<Referred>::ConstReference(const Referred &referred)
+
+ Creates a QVariant::ConstReference from a \a referred.
+ */
+
+/*!
+ \fn template<typename Referred> QVariant::ConstReference<Referred>::ConstReference(Referred &&referred)
+
+ Creates a QVariant::ConstReference from a \a referred.
+ */
+
+/*!
+ \fn template<typename Referred> QVariant::ConstReference<Referred>::operator QVariant() const
+
+ Dereferences the reference to a QVariant.
+ This method needs to be specialized for each Referred type. It is
+ pre-defined for QMetaSequence::ConstIterator, QMetaSequence::Iterator,
+ QMetaAssociation::ConstIterator, and QMetaAssociation::Iterator.
+ */
+
+
+/*!
+ \class QVariant::Reference
+ \since 6.11
+ \inmodule QtCore
+ \brief The QVariant::Reference acts as a non-const reference to a QVariant.
+
+ As the generic iterators don't actually instantiate a QVariant on each
+ step, they cannot return a reference to one from operator*().
+ QVariant::Reference provides the same functionality as an actual reference
+ to a QVariant would, but is backed a referred-to value given as template
+ parameter. The template is implemented for QMetaSequence::Iterator and
+ QMetaAssociation::Iterator.
+*/
+
+/*!
+ \fn template<typename Referred> QVariant::Reference<Referred>::Reference(const Referred &referred)
+
+ Creates a QVariant::Reference from a \a referred.
+ */
+
+/*!
+ \fn template<typename Referred> QVariant::Reference<Referred>::Reference(Referred &&referred)
+
+ Creates a QVariant::Reference from a \a referred.
+ */
+
+/*!
+ \fn template<typename Referred> QVariant::Reference<Referred> &QVariant::Reference<Referred>::operator=(const Reference<Referred> &value)
+
+ Assigns a new \a value to the value referred to by this QVariant::Reference.
+ */
+
+/*!
+ \fn template<typename Referred> QVariant::Reference<Referred> &QVariant::Reference<Referred>::operator=(Reference<Referred> &&value)
+
+ Assigns a new \a value to the value referred to by this QVariant::Reference.
+*/
+
+/*!
+ \fn template<typename Referred> QVariant::Reference<Referred> &QVariant::Reference<Referred>::operator=(const QVariant &value)
+
+ Assigns a new \a value to the value referred to by this QVariant::Reference.
+ This method needs to be specialized for each Referred type. It is
+ pre-defined for QMetaSequence::Iterator and QMetaAssociation::Iterator.
+ */
+
+/*!
+ \fn template<typename Referred> QVariant::Reference<Referred>::operator QVariant() const
+
+ Dereferences the reference to a QVariant. By default this instantiates a
+ temporary QVariant::ConstReference and calls dereferences that. In cases
+ where instantiating a temporary ConstReference is expensive, this method
+ should be specialized.
+ */
+
+/*!
+ \class QVariant::ConstPointer
+ \since 6.11
+ \inmodule QtCore
+ \brief QVariant::ConstPointer is a template class that emulates a const pointer to QVariant.
+
+ QVariant::ConstPointer wraps pointed-to value and returns a
+ QVariant::ConstReference to it from its operator*(). This makes it suitable
+ as replacement for an actual pointer. We cannot return an actual pointer
+ from generic iterators as the iterators don't hold an actual QVariant.
+*/
+
+/*!
+ \fn template<typename Pointed> QVariant::ConstPointer<Pointed>::ConstPointer(const Pointed &pointed)
+
+ Constructs a QVariant::ConstPointer from the value \a pointed to.
+ */
+
+/*!
+ \fn template<typename Pointed> QVariant::ConstPointer<Pointed>::ConstPointer(Pointed &&pointed)
+
+ Constructs a QVariant::ConstPointer from the value \a pointed to.
+ */
+
+/*!
+ \fn template<typename Pointed> QVariant::ConstReference<Pointer> QVariant::ConstPointer<Pointed>::operator*() const
+
+ Dereferences the QVariant::ConstPointer to a QVariant::ConstReference.
+ */
+
+/*!
+ \class QVariant::Pointer
+ \since 6.11
+ \inmodule QtCore
+ \brief QVariant::Pointer is a template class that emulates a non-const pointer to QVariant.
+
+ QVariant::Pointer wraps pointed-to value and returns a QVariant::Reference
+ to it from its operator*(). This makes it suitable as replacement for an
+ actual pointer. We cannot return an actual pointer from generic iterators as
+ the iterators don't hold an actual QVariant.
+*/
+
+/*!
+ \fn template<typename Pointed> QVariant::Pointer<Pointed>::Pointer(const Pointed &pointed)
+
+ Constructs a QVariant::Pointer from the value \a pointed to.
+ */
+
+/*!
+ \fn template<typename Pointed> QVariant::Pointer<Pointed>::Pointer(Pointed &&pointed)
+
+ Constructs a QVariant::Pointer from the value \a pointed to.
+ */
+
+/*!
+ \fn template<typename Pointed> QVariant::Reference<Pointer> QVariant::Pointer<Pointed>::operator*() const
+
+ Dereferences the QVariant::Pointer to a QVariant::Reference.
+ */
+
QT_END_NAMESPACE
diff --git a/src/corelib/kernel/qvariant.h b/src/corelib/kernel/qvariant.h
index 542b1d9b709..9b219d089b5 100644
--- a/src/corelib/kernel/qvariant.h
+++ b/src/corelib/kernel/qvariant.h
@@ -61,7 +61,20 @@ inline T qvariant_cast(const QVariant &);
namespace QtPrivate {
template<> constexpr inline bool qIsRelocatable<QVariant> = true;
-}
+
+template<typename Referred>
+class ConstReference;
+
+template<typename Referred>
+class Reference;
+
+template<typename Pointed>
+class ConstPointer;
+
+template<typename Pointed>
+class Pointer;
+} // namespace QtPrivate
+
class Q_CORE_EXPORT QVariant
{
template <typename T, typename... Args>
@@ -228,6 +241,123 @@ private:
>;
public:
+ template<typename Referred>
+ class ConstReference
+ {
+ private:
+ const Referred m_referred;
+
+ public:
+ // You can initialize a const reference from another one, but you can't assign to it.
+
+ explicit ConstReference(const Referred &referred)
+ noexcept(std::is_nothrow_copy_constructible_v<Referred>)
+ : m_referred(referred) {}
+ explicit ConstReference(Referred &&referred)
+ noexcept(std::is_nothrow_move_constructible_v<Referred>)
+ : m_referred(std::move(referred)) {}
+ ConstReference(const ConstReference &) = default;
+ ConstReference(ConstReference &&) = default;
+ ~ConstReference() = default;
+ ConstReference &operator=(const ConstReference &value) = delete;
+ ConstReference &operator=(ConstReference &&value) = delete;
+
+ // To be specialized for each Referred
+ operator QVariant() const noexcept(Referred::canNoexceptConvertToQVariant);
+ };
+
+ template<typename Referred>
+ class Reference
+ {
+ private:
+ Referred m_referred;
+
+ friend void swap(Reference a, Reference b) { return a.swap(std::move(b)); }
+
+ public:
+ // Assigning and initializing are different operations for references.
+
+ explicit Reference(const Referred &referred)
+ noexcept(std::is_nothrow_copy_constructible_v<Referred>)
+ : m_referred(referred) {}
+ explicit Reference(Referred &&referred)
+ noexcept(std::is_nothrow_move_constructible_v<Referred>)
+ : m_referred(std::move(referred)) {}
+ Reference(const Reference &) = default;
+ Reference(Reference &&) = default;
+ ~Reference() = default;
+
+ Reference &operator=(const Reference &value)
+ noexcept(Referred::canNoexceptAssignQVariant)
+ {
+ return operator=(QVariant(value));
+ }
+
+ Reference &operator=(Reference &&value)
+ noexcept(Referred::canNoexceptAssignQVariant)
+ {
+ return operator=(QVariant(value));
+ }
+
+ operator QVariant() const noexcept(Referred::canNoexceptConvertToQVariant)
+ {
+ return ConstReference(m_referred);
+ }
+
+ void swap(Reference b)
+ {
+ // swapping a reference is not swapping the referred item, but swapping its contents.
+ QVariant tmp = *this;
+ *this = std::move(b);
+ b = std::move(tmp);
+ }
+
+ // To be specialized for each Referred
+ Reference &operator=(const QVariant &value) noexcept(Referred::canNoexceptAssignQVariant);
+ };
+
+ template<typename Pointed>
+ class ConstPointer
+ {
+ private:
+ Pointed m_pointed;
+
+ public:
+ explicit ConstPointer(const Pointed &pointed)
+ noexcept(std::is_nothrow_copy_constructible_v<Pointed>)
+ : m_pointed(pointed) {}
+ explicit ConstPointer(Pointed &&pointed)
+ noexcept(std::is_nothrow_move_constructible_v<Pointed>)
+ : m_pointed(std::move(pointed)) {}
+
+ ConstReference<Pointed> operator*()
+ const noexcept(std::is_nothrow_copy_constructible_v<Pointed>)
+ {
+ return ConstReference<Pointed>(m_pointed);
+ }
+ };
+
+ template<typename Pointed>
+ class Pointer
+ {
+ private:
+ Pointed m_pointed;
+
+ public:
+ explicit Pointer(const Pointed &pointed)
+ noexcept(std::is_nothrow_copy_constructible_v<Pointed>)
+ : m_pointed(pointed) {}
+ explicit Pointer(Pointed &&pointed)
+ noexcept(std::is_nothrow_move_constructible_v<Pointed>)
+ : m_pointed(std::move(pointed)) {}
+
+ Reference<Pointed> operator*()
+ const noexcept(std::is_nothrow_copy_constructible_v<Pointed>)
+ {
+ return Reference<Pointed>(m_pointed);
+ }
+ };
+
template <typename T, typename... Args,
if_constructible<T, Args...> = true>
explicit QVariant(std::in_place_type_t<T>, Args&&... args)
diff --git a/src/corelib/platform/windows/quniquehandle_types_windows.cpp b/src/corelib/platform/windows/quniquehandle_types_windows.cpp
new file mode 100644
index 00000000000..801c9ab13d6
--- /dev/null
+++ b/src/corelib/platform/windows/quniquehandle_types_windows.cpp
@@ -0,0 +1,17 @@
+// Copyright (C) 2025 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#include "quniquehandle_types_windows_p.h"
+
+QT_BEGIN_NAMESPACE
+
+namespace QtUniqueHandleTraits {
+
+bool HDCTraits::close(Type handle, HWND hwnd) noexcept
+{
+ return ::ReleaseDC(hwnd, handle);
+}
+
+} // namespace QtUniqueHandleTraits
+
+QT_END_NAMESPACE
diff --git a/src/corelib/platform/windows/quniquehandle_types_windows_p.h b/src/corelib/platform/windows/quniquehandle_types_windows_p.h
new file mode 100644
index 00000000000..0b832d2b9d1
--- /dev/null
+++ b/src/corelib/platform/windows/quniquehandle_types_windows_p.h
@@ -0,0 +1,65 @@
+// Copyright (C) 2025 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#ifndef QUNIQUEHANDLE_TYPES_WINDOWS_P_H
+#define QUNIQUEHANDLE_TYPES_WINDOWS_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#if defined(Q_OS_WIN) || defined(Q_QDOC)
+
+#include <QtCore/qnamespace.h>
+#include <QtCore/qt_windows.h>
+#include <QtCore/private/quniquehandle_p.h>
+
+QT_BEGIN_NAMESPACE
+
+namespace QtUniqueHandleTraits {
+
+struct HDCTraits
+{
+ using Type = HDC;
+ static Type invalidValue() noexcept { return nullptr; }
+ Q_CORE_EXPORT static bool close(Type handle, HWND hwnd) noexcept;
+};
+
+struct HDCDeleter
+{
+ using Type = HDCTraits::Type;
+
+ constexpr HDCDeleter() noexcept = default;
+ explicit constexpr HDCDeleter(HWND hwnd) noexcept
+ : hwnd(hwnd)
+ {}
+
+ void operator()(Type handle) const noexcept
+ {
+ if (handle != HDCTraits::invalidValue()) {
+ const bool success = HDCTraits::close(handle, hwnd);
+ Q_ASSERT(success);
+ }
+ }
+
+ HWND hwnd{ nullptr };
+};
+
+} // namespace QtUniqueHandleTraits
+using QUniqueHDCHandle = QUniqueHandle<
+ QtUniqueHandleTraits::HDCTraits,
+ QtUniqueHandleTraits::HDCDeleter
+>;
+
+QT_END_NAMESPACE
+
+#endif // Q_OS_WIN
+
+#endif // QUNIQUEHANDLE_TYPES_WINDOWS_P_H
diff --git a/src/corelib/text/qstring.cpp b/src/corelib/text/qstring.cpp
index 711b70ebf8f..c01c1a9999d 100644
--- a/src/corelib/text/qstring.cpp
+++ b/src/corelib/text/qstring.cpp
@@ -3681,95 +3681,24 @@ QString &QString::remove(QChar ch, Qt::CaseSensitivity cs)
\sa remove()
*/
-
-/*! \internal
- Instead of detaching, or reallocating if "before" is shorter than "after"
- and there isn't enough capacity, create a new string, copy characters to it
- as needed, then swap it with "str".
-*/
-static void replace_with_copy(QString &str, QSpan<size_t> indices, qsizetype blen,
- QStringView after)
-{
- const qsizetype alen = after.size();
- const char16_t *after_b = after.utf16();
-
- const QString::DataPointer &str_d = str.data_ptr();
- auto src_start = str_d.begin();
- const qsizetype newSize = str_d.size + indices.size() * (alen - blen);
- QString copy{ newSize, Qt::Uninitialized };
- QString::DataPointer &copy_d = copy.data_ptr();
- auto dst = copy_d.begin();
- for (size_t index : indices) {
- auto hit = str_d.begin() + index;
- dst = std::copy(src_start, hit, dst);
- dst = std::copy_n(after_b, alen, dst);
- src_start = hit + blen;
- }
- dst = std::copy(src_start, str_d.end(), dst);
- str.swap(copy);
-}
-
-// No detaching or reallocation is needed
-static void replace_in_place(QString &str, QSpan<size_t> indices,
- qsizetype blen, QStringView after)
-{
- const qsizetype alen = after.size();
- const char16_t *after_b = after.utf16();
- const char16_t *after_e = after.utf16() + after.size();
-
- if (blen == alen) { // Replace in place
- for (size_t index : indices)
- std::copy_n(after_b, alen, str.data_ptr().begin() + index);
- } else if (blen > alen) { // Replace from front
- char16_t *begin = str.data_ptr().begin();
- char16_t *hit = begin + indices.front();
- char16_t *to = hit;
- to = std::copy_n(after_b, alen, to);
- char16_t *movestart = hit + blen;
- for (size_t index : indices.sliced(1)) {
- hit = begin + index;
- to = std::move(movestart, hit, to);
- to = std::copy_n(after_b, alen, to);
- movestart = hit + blen;
- }
- to = std::move(movestart, str.data_ptr().end(), to);
- str.resize(std::distance(begin, to));
- } else { // blen < alen, Replace from back
- const qsizetype oldSize = str.data_ptr().size;
- const qsizetype adjust = indices.size() * (alen - blen);
- const qsizetype newSize = oldSize + adjust;
-
- str.resize(newSize);
- char16_t *begin = str.data_ptr().begin();
- char16_t *moveend = begin + oldSize;
- char16_t *to = str.data_ptr().end();
-
- for (auto it = indices.rbegin(), end = indices.rend(); it != end; ++it) {
- char16_t *hit = begin + *it;
- char16_t *movestart = hit + blen;
- to = std::move_backward(movestart, moveend, to);
- to = std::copy_backward(after_b, after_e, to);
- moveend = hit;
- }
- }
-}
-
-static void replace_helper(QString &str, QSpan<size_t> indices, qsizetype blen, QStringView after)
+static void replace_helper(QString &str, QSpan<qsizetype> indices, qsizetype blen, QStringView after)
{
const qsizetype oldSize = str.data_ptr().size;
const qsizetype adjust = indices.size() * (after.size() - blen);
const qsizetype newSize = oldSize + adjust;
+ using A = QStringAlgorithms<QString>;
if (str.data_ptr().needsDetach() || needsReallocate(str, newSize)) {
- replace_with_copy(str, indices, blen, after);
+ A::replace_helper(str, blen, after, indices);
return;
}
- if (QtPrivate::q_points_into_range(after.begin(), str))
+ if (QtPrivate::q_points_into_range(after.begin(), str)) {
// Copy after if it lies inside our own d.b area (which we could
// possibly invalidate via a realloc or modify by replacement)
- replace_in_place(str, indices, blen, QVarLengthArray(after.begin(), after.end()));
- else
- replace_in_place(str, indices, blen, after);
+ A::replace_helper(str, blen, QVarLengthArray(after.begin(), after.end()), indices);
+ } else {
+ A::replace_helper(str, blen, after, indices);
+ }
}
/*!
@@ -3811,8 +3740,8 @@ QString &QString::replace(qsizetype pos, qsizetype len, const QChar *after, qsiz
if (len > this->size() - pos)
len = this->size() - pos;
- size_t index = pos;
- replace_helper(*this, QSpan(&index, 1), len, QStringView{after, alen});
+ qsizetype indices[] = {pos};
+ replace_helper(*this, indices, len, QStringView{after, alen});
return *this;
}
@@ -3890,7 +3819,7 @@ QString &QString::replace(const QChar *before, qsizetype blen,
qsizetype index = 0;
- QVarLengthArray<size_t> indices;
+ QVarLengthArray<qsizetype> indices;
while ((index = matcher.indexIn(*this, index)) != -1) {
indices.push_back(index);
if (blen) // Step over before:
@@ -3925,7 +3854,7 @@ QString& QString::replace(QChar ch, const QString &after, Qt::CaseSensitivity cs
const char16_t cc = (cs == Qt::CaseSensitive ? ch.unicode() : ch.toCaseFolded().unicode());
- QVarLengthArray<size_t> indices;
+ QVarLengthArray<qsizetype> indices;
if (cs == Qt::CaseSensitive) {
const char16_t *begin = d.begin();
const char16_t *end = d.end();
diff --git a/src/corelib/time/qgregoriancalendar.cpp b/src/corelib/time/qgregoriancalendar.cpp
index d46d24ac30d..dfb99c5073d 100644
--- a/src/corelib/time/qgregoriancalendar.cpp
+++ b/src/corelib/time/qgregoriancalendar.cpp
@@ -31,6 +31,7 @@ static_assert(qDivMod<86400>(-172800).remainder == 0);
/*!
\since 5.14
+ \internal
\class QGregorianCalendar
\inmodule QtCore
diff --git a/src/corelib/time/qjalalicalendar.cpp b/src/corelib/time/qjalalicalendar.cpp
index 8bc9fe125e7..683ce6e7712 100644
--- a/src/corelib/time/qjalalicalendar.cpp
+++ b/src/corelib/time/qjalalicalendar.cpp
@@ -39,6 +39,7 @@ qint64 firstDayOfYear(int year, int cycleNo)
/*!
\since 5.14
+ \internal
\class QJalaliCalendar
\inmodule QtCore
diff --git a/src/corelib/time/qjuliancalendar.cpp b/src/corelib/time/qjuliancalendar.cpp
index 47da952b84a..cf3718f471d 100644
--- a/src/corelib/time/qjuliancalendar.cpp
+++ b/src/corelib/time/qjuliancalendar.cpp
@@ -13,6 +13,7 @@ using namespace QRoundingDown;
/*!
\since 5.14
+ \internal
\class QJulianCalendar
\inmodule QtCore
diff --git a/src/corelib/time/qmilankoviccalendar.cpp b/src/corelib/time/qmilankoviccalendar.cpp
index a3ffa2a3053..14aef83afe3 100644
--- a/src/corelib/time/qmilankoviccalendar.cpp
+++ b/src/corelib/time/qmilankoviccalendar.cpp
@@ -13,6 +13,7 @@ using namespace QRoundingDown;
/*!
\since 5.14
+ \internal
\class QMilankovicCalendar
\inmodule QtCore
diff --git a/src/corelib/time/qromancalendar.cpp b/src/corelib/time/qromancalendar.cpp
index ae113cf8323..a8ce027275a 100644
--- a/src/corelib/time/qromancalendar.cpp
+++ b/src/corelib/time/qromancalendar.cpp
@@ -9,6 +9,7 @@ QT_BEGIN_NAMESPACE
/*!
\since 5.14
+ \internal
\class QRomanCalendar
\inmodule QtCore
diff --git a/src/corelib/time/qtimezone.cpp b/src/corelib/time/qtimezone.cpp
index f44c681ea80..7b43aab22d1 100644
--- a/src/corelib/time/qtimezone.cpp
+++ b/src/corelib/time/qtimezone.cpp
@@ -29,7 +29,7 @@ static QTimeZonePrivate *newBackendTimeZone()
return new QMacTimeZonePrivate();
#elif defined(Q_OS_ANDROID)
return new QAndroidTimeZonePrivate();
-#elif defined(Q_OS_UNIX)
+#elif defined(Q_OS_UNIX) && !defined(Q_OS_VXWORKS)
return new QTzTimeZonePrivate();
#elif QT_CONFIG(icu)
return new QIcuTimeZonePrivate();
@@ -50,7 +50,7 @@ static QTimeZonePrivate *newBackendTimeZone(const QByteArray &ianaId)
return new QMacTimeZonePrivate(ianaId);
#elif defined(Q_OS_ANDROID)
return new QAndroidTimeZonePrivate(ianaId);
-#elif defined(Q_OS_UNIX)
+#elif defined(Q_OS_UNIX) && !defined(Q_OS_VXWORKS)
return new QTzTimeZonePrivate(ianaId);
#elif QT_CONFIG(icu)
return new QIcuTimeZonePrivate(ianaId);
@@ -1482,7 +1482,8 @@ QTimeZone QTimeZone::utc()
bool QTimeZone::isTimeZoneIdAvailable(const QByteArray &ianaId)
{
-#if defined(Q_OS_UNIX) && !(defined(Q_OS_ANDROID) || defined(Q_OS_DARWIN))
+#if defined(Q_OS_UNIX) && !(QT_CONFIG(timezone_tzdb) || defined(Q_OS_DARWIN) \
+ || defined(Q_OS_ANDROID) || defined(Q_OS_VXWORKS))
// Keep #if-ery consistent with selection of QTzTimeZonePrivate in
// newBackendTimeZone(). Skip the pre-check, as the TZ backend accepts POSIX
// zone IDs, which need not be valid IANA IDs. See also QTBUG-112006.
diff --git a/src/corelib/time/qtimezonelocale.cpp b/src/corelib/time/qtimezonelocale.cpp
index a794682fe0b..6ad4aa1479c 100644
--- a/src/corelib/time/qtimezonelocale.cpp
+++ b/src/corelib/time/qtimezonelocale.cpp
@@ -611,6 +611,27 @@ QString QTimeZonePrivate::localeName(qint64 atMSecsSinceEpoch, int offsetFromUtc
// Custom zone with perverse m_id ?
return;
}
+ const auto isMixedCaseAbbrev = [tail](char ch) {
+ // cv-RU and en-GU abbreviate Chamorro as ChST
+ // scn-IT abbreviates Cuba as CuT/CuST/CuDT
+ // blo-BJ abbreviates GMT as Gk
+ switch (tail.size()) {
+ case 2: return tail == "Gk";
+ case 3: return tail == "CuT";
+ case 4:
+ if (tail[0] == 'C' && tail[1] == ch && tail[3] == 'T') {
+ switch (ch) {
+ case 'h': return tail[2] == 'S';
+ case 'u': return tail[2] == 'S' || tail[2] == 'D';
+ default: break;
+ }
+ }
+ return false;
+ default:
+ break;
+ }
+ return false;
+ };
// Even if it is abbr or city name, we don't care if we've found one before.
bool maybeAbbr = ianaAbbrev.isEmpty(), maybeCityName = ianaTail.isEmpty(), inword = false;
@@ -632,7 +653,7 @@ QString QTimeZonePrivate::localeName(qint64 atMSecsSinceEpoch, int offsetFromUtc
maybeCityName = false;
inword = false;
} else if (QChar::isLower(ch)) {
- maybeAbbr = false;
+ maybeAbbr = isMixedCaseAbbrev(ch);
// Dar_es_Salaam shows both cases as word starts
inword = true;
} else if (QChar::isUpper(ch)) {
@@ -891,8 +912,11 @@ QTimeZonePrivate::findLongNamePrefix(QStringView text, const QLocale &locale,
if (best.ianaIdIndex != invalidIanaId)
return { QByteArray(ianaIdData + best.ianaIdIndex), best.nameLength, best.timeType };
- // Now try for a region format:
- best = {};
+ // Now try for a region format.
+ // Since we may get the IANA ID directly from a zone, we may not need an
+ // ianaIdIndex from CLDR-derived tables: and the active backend may know
+ // some zones newer than our latest CLDR.
+ NamePrefixMatch found;
for (const qsizetype locInd : indices) {
const LocaleZoneData &locData = localeZoneData[locInd];
const LocaleZoneData &nextData = localeZoneData[locInd + 1];
@@ -928,11 +952,11 @@ QTimeZonePrivate::findLongNamePrefix(QStringView text, const QLocale &locale,
QStringView city = row.exemplarCity().viewData(exemplarCityTable);
if (textMatches(city)) {
qsizetype length = cut + city.size() + suffix.size();
- if (length > best.nameLength) {
- bool gotZone = row.ianaIdIndex == best.ianaIdIndex
+ if (length > found.nameLength) {
+ bool gotZone = row.ianaId() == found.ianaId // (cheap pre-test)
|| QTimeZone::isTimeZoneIdAvailable(row.ianaId().toByteArray());
if (gotZone)
- best = { length, timeType, row.ianaIdIndex };
+ found = { row.ianaId().toByteArray(), length, timeType };
}
}
}
@@ -945,38 +969,16 @@ QTimeZonePrivate::findLongNamePrefix(QStringView text, const QLocale &locale,
QString city = QString::fromLatin1(local.replace('_', ' '));
if (textMatches(city)) {
qsizetype length = cut + city.size() + suffix.size();
- if (length > best.nameLength) {
- // Have to find iana in ianaIdData. Although its entries
- // from locale-independent data are nicely sorted, the
- // rest are (sadly) not.
- QByteArrayView run(ianaIdData, qstrlen(ianaIdData));
- // std::size includes the trailing '\0', so subtract one:
- const char *stop = ianaIdData + std::size(ianaIdData) - 1;
- while (run != iana) {
- if (run.end() < stop) { // Step to the next:
- run = QByteArrayView(run.end() + 1);
- } else {
- run = QByteArrayView();
- break;
- }
- }
- if (!run.isEmpty()) {
- Q_ASSERT(run == iana);
- const auto ianaIdIndex = run.begin() - ianaIdData;
- Q_ASSERT(ianaIdIndex <= (std::numeric_limits<quint16>::max)());
- best = { length, timeType, quint16(ianaIdIndex) };
- }
- }
+ if (length > found.nameLength)
+ found = { iana, length, timeType };
}
}
// TODO: similar for territories, at least once localeName() does so.
}
}
- if (best.ianaIdIndex != invalidIanaId)
- return { QByteArray(ianaIdData + best.ianaIdIndex), best.nameLength, best.timeType };
#undef localeRows
- return {}; // No match found.
+ return found;
}
QTimeZonePrivate::NamePrefixMatch
diff --git a/src/corelib/time/qtimezoneprivate.cpp b/src/corelib/time/qtimezoneprivate.cpp
index 556f7e21402..3f0254b1c5f 100644
--- a/src/corelib/time/qtimezoneprivate.cpp
+++ b/src/corelib/time/qtimezoneprivate.cpp
@@ -1177,7 +1177,7 @@ QUtcTimeZonePrivate::QUtcTimeZonePrivate(qint32 offsetSeconds)
}
Q_ASSERT(!name.isEmpty());
} else { // Fall back to a UTC-offset name:
- name = isoOffsetFormat(offsetSeconds, QTimeZone::ShortName);
+ name = isoOffsetFormat(offsetSeconds, QTimeZone::OffsetName);
id = name.toUtf8();
}
init(id, offsetSeconds, name, name, QLocale::AnyTerritory, name);
@@ -1292,12 +1292,16 @@ QString QUtcTimeZonePrivate::displayName(QTimeZone::TimeType timeType,
if (!(name.startsWith("GMT"_L1) || name.startsWith("UTC"_L1)) || name.size() < 5)
return false;
// Fallback drops trailing ":00" minute:
- QStringView tail{avoid};
+ QStringView tail{avoid}; // TODO: deal with sign earlier ! Also: invisible Unicode !
tail = tail.sliced(3);
- if (tail.endsWith(":00"_L1))
- tail = tail.chopped(3);
if (name.sliced(3) == tail)
return true;
+ while (tail.endsWith(":00"_L1))
+ tail = tail.chopped(3);
+ while (name.endsWith(":00"_L1))
+ name = name.chopped(3);
+ if (name == tail)
+ return true;
// Accept U+2212 as minus sign:
const QChar sign = name[3] == u'\u2212' ? u'-' : name[3];
// Fallback doesn't zero-pad hour:
diff --git a/src/corelib/time/qtimezoneprivate_p.h b/src/corelib/time/qtimezoneprivate_p.h
index 804c28af372..9a86ded6efb 100644
--- a/src/corelib/time/qtimezoneprivate_p.h
+++ b/src/corelib/time/qtimezoneprivate_p.h
@@ -50,7 +50,7 @@ class Q_AUTOTEST_EXPORT QTimeZonePrivate : public QSharedData
{
// Nothing should be copy-assigning instances of either this or its derived
// classes (only clone() should copy, using the copy-constructor):
- bool operator=(const QTimeZonePrivate &) const = delete;
+ QTimeZonePrivate &operator=(const QTimeZonePrivate &) const = delete;
protected:
QTimeZonePrivate(const QTimeZonePrivate &other) = default;
public:
@@ -210,7 +210,7 @@ Q_DECLARE_TYPEINFO(QTimeZonePrivate::Data, Q_RELOCATABLE_TYPE);
class Q_AUTOTEST_EXPORT QUtcTimeZonePrivate final : public QTimeZonePrivate
{
- bool operator=(const QUtcTimeZonePrivate &) const = delete;
+ QUtcTimeZonePrivate &operator=(const QUtcTimeZonePrivate &) const = delete;
QUtcTimeZonePrivate(const QUtcTimeZonePrivate &other);
public:
// Create default UTC time zone
@@ -273,7 +273,7 @@ private:
#if QT_CONFIG(timezone_tzdb)
class QChronoTimeZonePrivate final : public QTimeZonePrivate
{
- bool operator=(const QChronoTimeZonePrivate &) const = delete;
+ QChronoTimeZonePrivate &operator=(const QChronoTimeZonePrivate &) const = delete;
QChronoTimeZonePrivate(const QChronoTimeZonePrivate &) = default;
public:
QChronoTimeZonePrivate();
@@ -307,7 +307,7 @@ private:
#elif defined(Q_OS_DARWIN)
class Q_AUTOTEST_EXPORT QMacTimeZonePrivate final : public QTimeZonePrivate
{
- bool operator=(const QMacTimeZonePrivate &) const = delete;
+ QMacTimeZonePrivate &operator=(const QMacTimeZonePrivate &) const = delete;
QMacTimeZonePrivate(const QMacTimeZonePrivate &other);
public:
// Create default time zone
@@ -353,7 +353,7 @@ private:
#elif defined(Q_OS_ANDROID)
class QAndroidTimeZonePrivate final : public QTimeZonePrivate
{
- bool operator=(const QAndroidTimeZonePrivate &) const = delete;
+ QAndroidTimeZonePrivate &operator=(const QAndroidTimeZonePrivate &) const = delete;
QAndroidTimeZonePrivate(const QAndroidTimeZonePrivate &) = default;
public:
// Create default time zone
@@ -388,7 +388,7 @@ private:
QJniObject androidTimeZone;
};
-#elif defined(Q_OS_UNIX)
+#elif defined(Q_OS_UNIX) && !defined(Q_OS_VXWORKS)
struct QTzTransitionTime
{
qint64 atMSecsSinceEpoch;
@@ -421,7 +421,7 @@ struct QTzTimeZoneCacheEntry
class Q_AUTOTEST_EXPORT QTzTimeZonePrivate final : public QTimeZonePrivate
{
- bool operator=(const QTzTimeZonePrivate &) const = delete;
+ QTzTimeZonePrivate &operator=(const QTzTimeZonePrivate &) const = delete;
QTzTimeZonePrivate(const QTzTimeZonePrivate &) = default;
public:
// Create default time zone
@@ -474,7 +474,7 @@ private:
#elif QT_CONFIG(icu)
class Q_AUTOTEST_EXPORT QIcuTimeZonePrivate final : public QTimeZonePrivate
{
- bool operator=(const QIcuTimeZonePrivate &) const = delete;
+ QIcuTimeZonePrivate &operator=(const QIcuTimeZonePrivate &) const = delete;
QIcuTimeZonePrivate(const QIcuTimeZonePrivate &other);
public:
// Create default time zone
@@ -518,7 +518,7 @@ private:
#elif defined(Q_OS_WIN)
class Q_AUTOTEST_EXPORT QWinTimeZonePrivate final : public QTimeZonePrivate
{
- bool operator=(const QWinTimeZonePrivate &) const = delete;
+ QWinTimeZonePrivate &operator=(const QWinTimeZonePrivate &) const = delete;
QWinTimeZonePrivate(const QWinTimeZonePrivate &) = default;
public:
struct QWinTransitionRule {
diff --git a/src/corelib/tools/qiterator.qdoc b/src/corelib/tools/qiterator.qdoc
index 3d8ea595167..d517457027a 100644
--- a/src/corelib/tools/qiterator.qdoc
+++ b/src/corelib/tools/qiterator.qdoc
@@ -165,7 +165,7 @@
position between the second and third item, and returns the second
item; and so on.
- \image javaiterators1.png
+ \image javaiterators1.svg Java-style iterators point between items
Here's how to iterate over the elements in reverse order:
@@ -211,7 +211,7 @@
position between the second and third item, returning the second
item; and so on.
- \image javaiterators1.png
+ \image javaiterators1.svg Java-style iterators point between items
If you want to find all occurrences of a particular value, use
findNext() in a loop.
@@ -260,7 +260,7 @@
position between the second and third item, returning the second
item; and so on.
- \image javaiterators1.png
+ \image javaiterators1.svg Java-style iterators point between items
Here's how to iterate over the elements in reverse order:
@@ -321,7 +321,7 @@
position between the second and third item, returning the second
item; and so on.
- \image javaiterators1.png
+ \image javaiterators1.svg Java-style iterators point between items
If you want to remove items as you iterate over the set, use
remove().
@@ -718,7 +718,7 @@
next() advances the iterator to the position between the second
and third item; and so on.
- \image javaiterators1.png
+ \image javaiterators1.svg Java-style iterators point between items
Here's how to iterate over the elements in reverse order:
@@ -768,7 +768,7 @@
next() advances the iterator to the position between the second
and third item; and so on.
- \image javaiterators1.png
+ \image javaiterators1.svg Java-style iterators point between items
Here's how to iterate over the elements in reverse order:
@@ -819,7 +819,7 @@
next() advances the iterator to the position between the second
and third item; and so on.
- \image javaiterators1.png
+ \image javaiterators1.svg Java-style iterators point between items
If you want to find all occurrences of a particular value, use
findNext() in a loop. For example:
@@ -867,7 +867,7 @@
next() advances the iterator to the position between the second
and third item; and so on.
- \image javaiterators1.png
+ \image javaiterators1.svg Java-style iterators point between items
Here's how to iterate over the elements in reverse order:
@@ -931,7 +931,7 @@
next() advances the iterator to the position between the second
and third item; and so on.
- \image javaiterators1.png
+ \image javaiterators1.svg Java-style iterators point between items
Here's how to iterate over the elements in reverse order:
@@ -994,7 +994,7 @@
next() advances the iterator to the position between the second
and third item; and so on.
- \image javaiterators1.png
+ \image javaiterators1.svg Java-style iterators point between items
If you want to find all occurrences of a particular value, use
findNext() in a loop. For example:
diff --git a/src/corelib/tools/quniquehandle_p.h b/src/corelib/tools/quniquehandle_p.h
index 3ba557e838d..fd6ab693912 100644
--- a/src/corelib/tools/quniquehandle_p.h
+++ b/src/corelib/tools/quniquehandle_p.h
@@ -18,6 +18,7 @@
#include <QtCore/qtconfigmacros.h>
#include <QtCore/qassert.h>
#include <QtCore/qcompare.h>
+#include <QtCore/qfunctionaltools_impl.h>
#include <QtCore/qswap.h>
#include <QtCore/qtclasshelpermacros.h>
@@ -99,6 +100,42 @@ QT_BEGIN_NAMESPACE
...
+ Example 3:
+
+ struct TempFileTraits {
+ using Type = FILE*;
+
+ static Type invalidValue() {
+ return nullptr;
+ }
+
+ static bool close(Type handle) {
+ return fclose(handle) == 0;
+ }
+ };
+
+ struct TempFileDeleter {
+ using Type = TempFileTraits::Type;
+
+ void operator()(Type handle) {
+ if (handle != TempFileTraits::invalidValue()) {
+ TempFileTraits::close(handle);
+ if (path)
+ remove(path);
+ }
+ }
+
+ const char* path{ nullptr };
+ };
+
+ using TempFileHandle = QUniqueHandle<TempFileTraits, TempFileDeleter>;
+
+ Usage:
+
+ TempFileHandle tempFile(fopen("temp.bin", "wb"), TempFileDeleter{ "my_temp.bin" });
+
+ ...
+
NOTE: The QUniqueHandle assumes that closing a resource is
guaranteed to succeed, and provides no support for handling failure
to close a resource. It is therefore only recommended for use cases
@@ -108,9 +145,32 @@ QT_BEGIN_NAMESPACE
// clang-format off
+namespace QtUniqueHandleTraits {
+
template <typename HandleTraits>
-class QUniqueHandle
+struct DefaultDeleter
{
+ using Type = typename HandleTraits::Type;
+
+ void operator()(Type handle) const noexcept
+ {
+ if (handle != HandleTraits::invalidValue()) {
+ const bool success = HandleTraits::close(handle);
+ Q_ASSERT(success);
+ }
+ }
+};
+
+} // namespace QtUniqueHandleTraits
+
+template <typename HandleTraits, typename Deleter = QtUniqueHandleTraits::DefaultDeleter<HandleTraits>>
+class QUniqueHandle : private QtPrivate::CompactStorage<Deleter>
+{
+ using Storage = QtPrivate::CompactStorage<Deleter>;
+
+ template <typename D>
+ using if_default_constructible = std::enable_if_t<std::is_default_constructible_v<D>, bool>;
+
public:
using Type = typename HandleTraits::Type;
static_assert(std::is_nothrow_default_constructible_v<Type>);
@@ -120,6 +180,11 @@ public:
static_assert(std::is_nothrow_copy_assignable_v<Type>);
static_assert(std::is_nothrow_move_assignable_v<Type>);
static_assert(std::is_nothrow_destructible_v<Type>);
+ static_assert(std::is_nothrow_copy_constructible_v<Deleter>);
+ static_assert(std::is_nothrow_move_constructible_v<Deleter>);
+ static_assert(std::is_nothrow_copy_assignable_v<Deleter>);
+ static_assert(std::is_nothrow_move_assignable_v<Deleter>);
+ static_assert(std::is_nothrow_destructible_v<Deleter>);
static_assert(noexcept(std::declval<Type>() == std::declval<Type>()));
static_assert(noexcept(std::declval<Type>() != std::declval<Type>()));
static_assert(noexcept(std::declval<Type>() < std::declval<Type>()));
@@ -127,16 +192,24 @@ public:
static_assert(noexcept(std::declval<Type>() > std::declval<Type>()));
static_assert(noexcept(std::declval<Type>() >= std::declval<Type>()));
- QUniqueHandle() = default;
-
- explicit QUniqueHandle(const Type &handle) noexcept
+ template <if_default_constructible<Deleter> = true>
+ explicit QUniqueHandle(const Type& handle = HandleTraits::invalidValue()) noexcept
: m_handle{ handle }
{}
- QUniqueHandle(QUniqueHandle &&other) noexcept
- : m_handle{ other.release() }
+ QUniqueHandle(const Type &handle, const Deleter &deleter) noexcept
+ : Storage{ deleter }, m_handle{ handle }
+ {}
+
+ QUniqueHandle(const Type &handle, Deleter &&deleter) noexcept
+ : Storage{ std::move(deleter) }, m_handle{ handle }
{}
+ QUniqueHandle(QUniqueHandle &&other) noexcept
+ : Storage{ std::move(other.deleter()) }, m_handle{ other.release() }
+ {
+ }
+
~QUniqueHandle() noexcept
{
close();
@@ -145,6 +218,7 @@ public:
void swap(QUniqueHandle &other) noexcept
{
qSwap(m_handle, other.m_handle);
+ qSwap(deleter(), other.deleter());
}
QT_MOVE_ASSIGNMENT_OPERATOR_IMPL_VIA_MOVE_AND_SWAP(QUniqueHandle)
@@ -168,6 +242,16 @@ public:
return m_handle;
}
+ [[nodiscard]] Deleter& deleter() noexcept
+ {
+ return Storage::object();
+ }
+
+ [[nodiscard]] const Deleter& deleter() const noexcept
+ {
+ return Storage::object();
+ }
+
void reset(const Type& handle = HandleTraits::invalidValue()) noexcept
{
if (handle == m_handle)
@@ -193,8 +277,7 @@ public:
if (!isValid())
return;
- const bool success = HandleTraits::close(m_handle);
- Q_ASSERT(success);
+ deleter()(m_handle);
m_handle = HandleTraits::invalidValue();
}
@@ -222,8 +305,8 @@ private:
// clang-format on
-template <typename Trait>
-void swap(QUniqueHandle<Trait> &lhs, QUniqueHandle<Trait> &rhs) noexcept
+template <typename Trait, typename Deleter>
+void swap(QUniqueHandle<Trait, Deleter> &lhs, QUniqueHandle<Trait, Deleter> &rhs) noexcept
{
lhs.swap(rhs);
}
diff --git a/src/gui/kernel/qevent.cpp b/src/gui/kernel/qevent.cpp
index ae730a9b3af..7b1e76cc78f 100644
--- a/src/gui/kernel/qevent.cpp
+++ b/src/gui/kernel/qevent.cpp
@@ -1146,6 +1146,33 @@ Q_IMPL_POINTER_EVENT(QHoverEvent)
*/
/*!
+ \property QWheelEvent::device
+ \brief the device from which the wheel event originated
+
+ \sa pointingDevice()
+*/
+
+/*!
+ \property QWheelEvent::inverted
+ \since 5.7
+ \brief whether the delta values delivered with the event are inverted
+
+ Normally, a vertical wheel will produce a QWheelEvent with positive delta
+ values if the top of the wheel is rotating away from the hand operating it.
+ Similarly, a horizontal wheel movement will produce a QWheelEvent with
+ positive delta values if the top of the wheel is moved to the left.
+
+ However, on some platforms this is configurable, so that the same
+ operations described above will produce negative delta values (but with the
+ same magnitude). With the inverted property a wheel event consumer can
+ choose to always follow the direction of the wheel, regardless of the
+ system settings, but only for specific widgets.
+
+ \note Many platforms provide no such information. On such platforms
+ \l inverted always returns false.
+*/
+
+/*!
\fn bool QWheelEvent::inverted() const
\since 5.7
@@ -1236,6 +1263,24 @@ bool QWheelEvent::isEndEvent() const
#endif // QT_CONFIG(wheelevent)
/*!
+ \property QWheelEvent::pixelDelta
+ \brief the scrolling distance in pixels on screen
+
+ This value is provided on platforms that support high-resolution
+ pixel-based delta values, such as \macos. The value should be used
+ directly to scroll content on screen.
+
+ \note On platforms that support scrolling \l{phase()}{phases}, the delta
+ may be null when scrolling is about to begin (Qt::ScrollBegin) or has
+ ended (Qt::ScrollEnd).
+
+ \note On X11 this value is driver-specific and unreliable, use
+ angleDelta() instead.
+
+ \sa angleDelta()
+*/
+
+/*!
\fn QPoint QWheelEvent::pixelDelta() const
Returns the scrolling distance in pixels on screen. This value is
@@ -1256,6 +1301,27 @@ bool QWheelEvent::isEndEvent() const
*/
/*!
+ \property QWheelEvent::angleDelta
+ \brief the relative amount that the wheel was rotated, in eighths of a degree
+
+ A positive value indicates that the wheel was rotated forwards away from the
+ user; a negative value indicates that the wheel was rotated backwards toward
+ the user. \c angleDelta().y() provides the angle through which the common
+ vertical mouse wheel was rotated since the previous event. \c angleDelta().x()
+ provides the angle through which the horizontal mouse wheel was rotated, if
+ the mouse has a horizontal wheel; otherwise it stays at zero.
+
+ Most mouse types work in steps of 15 degrees, in which case the delta value
+ is a multiple of 120; i.e., 120 units * 1/8 = 15 degrees.
+
+ \note On platforms that support scrolling \l{phase()}{phases}, the delta
+ may be null when scrolling is about to begin (Qt::ScrollBegin) or has
+ ended (Qt::ScrollEnd).
+
+ \sa pixelDelta()
+*/
+
+/*!
\fn QPoint QWheelEvent::angleDelta() const
Returns the relative amount that the wheel was rotated, in eighths of a
@@ -1294,6 +1360,15 @@ bool QWheelEvent::isEndEvent() const
*/
/*!
+ \property QWheelEvent::phase
+ \since 5.2
+ \brief the scrolling phase of this wheel event
+
+ \note The Qt::ScrollBegin and Qt::ScrollEnd phases are currently
+ supported only on \macos.
+*/
+
+/*!
\fn Qt::ScrollPhase QWheelEvent::phase() const
\since 5.2
diff --git a/src/gui/kernel/qinputdevice.cpp b/src/gui/kernel/qinputdevice.cpp
index 8e5c38922e0..caed0fc6135 100644
--- a/src/gui/kernel/qinputdevice.cpp
+++ b/src/gui/kernel/qinputdevice.cpp
@@ -187,6 +187,11 @@ QString QInputDevice::name() const
}
/*!
+ \property QInputDevice::type
+ \brief the device type
+*/
+
+/*!
Returns the device type.
*/
QInputDevice::DeviceType QInputDevice::type() const
diff --git a/src/gui/kernel/qpointingdevice.cpp b/src/gui/kernel/qpointingdevice.cpp
index dcce354688a..7062340b287 100644
--- a/src/gui/kernel/qpointingdevice.cpp
+++ b/src/gui/kernel/qpointingdevice.cpp
@@ -241,6 +241,11 @@ void QPointingDevice::setMaximumTouchPoints(int c)
#endif // QT_DEPRECATED_SINCE(6, 0)
/*!
+ \property QPointingDevice::pointerType
+ \brief the pointer type
+*/
+
+/*!
Returns the pointer type.
*/
QPointingDevice::PointerType QPointingDevice::pointerType() const
@@ -250,6 +255,12 @@ QPointingDevice::PointerType QPointingDevice::pointerType() const
}
/*!
+ \property QPointingDevice::maximumPoints
+ \brief the maximum number of simultaneous touch points (fingers) that
+ can be detected
+*/
+
+/*!
Returns the maximum number of simultaneous touch points (fingers) that
can be detected.
*/
@@ -260,6 +271,11 @@ int QPointingDevice::maximumPoints() const
}
/*!
+ \property QPointingDevice::buttonCount
+ \brief the maximum number of on-device buttons that can be detected
+*/
+
+/*!
Returns the maximum number of on-device buttons that can be detected.
*/
int QPointingDevice::buttonCount() const
@@ -269,6 +285,13 @@ int QPointingDevice::buttonCount() const
}
/*!
+ \property QPointingDevice::uniqueId
+ \brief a unique ID (of dubious utility) for the device
+
+ You probably should rather be concerned with QPointerEventPoint::uniqueId().
+*/
+
+/*!
Returns a unique ID (of dubious utility) for the device.
You probably should rather be concerned with QPointerEventPoint::uniqueId().
diff --git a/src/gui/rhi/qrhi.cpp b/src/gui/rhi/qrhi.cpp
index 62b7ab6efb0..5590f2fb431 100644
--- a/src/gui/rhi/qrhi.cpp
+++ b/src/gui/rhi/qrhi.cpp
@@ -7186,6 +7186,26 @@ QRhiResource::Type QRhiGraphicsPipeline::resourceType() const
*/
/*!
+ \fn bool QRhiGraphicsPipeline::hasDepthClamp() const
+ \return true if depth clamp is enabled.
+
+ \since 6.11
+ */
+
+/*!
+ \fn void QRhiGraphicsPipeline::setDepthClamp(bool enable)
+
+ Enables depth clamping when \a enable is true. When depth clamping is
+ enabled, primitives that would otherwise be clipped by the near or far
+ clip plane are rasterized and their depth values are clamped to the
+ depth range. When disabled (the default), such primitives are clipped.
+
+ \note This setting is ignored on OpenGL ES.
+
+ \since 6.11
+ */
+
+/*!
\fn QRhiGraphicsPipeline::CompareOp QRhiGraphicsPipeline::depthOp() const
\return the depth comparison function.
*/
diff --git a/src/gui/rhi/qrhi.h b/src/gui/rhi/qrhi.h
index b5a3f7b43be..5ee2a9acd13 100644
--- a/src/gui/rhi/qrhi.h
+++ b/src/gui/rhi/qrhi.h
@@ -1453,6 +1453,9 @@ public:
bool hasDepthWrite() const { return m_depthWrite; }
void setDepthWrite(bool enable) { m_depthWrite = enable; }
+ bool hasDepthClamp() const { return m_depthClamp; }
+ void setDepthClamp(bool enable) { m_depthClamp = enable; }
+
CompareOp depthOp() const { return m_depthOp; }
void setDepthOp(CompareOp op) { m_depthOp = op; }
@@ -1524,6 +1527,7 @@ protected:
QVarLengthArray<TargetBlend, 8> m_targetBlends;
bool m_depthTest = false;
bool m_depthWrite = false;
+ bool m_depthClamp = false;
CompareOp m_depthOp = Less;
bool m_stencilTest = false;
StencilOpState m_stencilFront;
diff --git a/src/gui/rhi/qrhid3d11.cpp b/src/gui/rhi/qrhid3d11.cpp
index a5f860e7724..1441be24043 100644
--- a/src/gui/rhi/qrhid3d11.cpp
+++ b/src/gui/rhi/qrhid3d11.cpp
@@ -4673,7 +4673,7 @@ bool QD3D11GraphicsPipeline::create()
rastDesc.FrontCounterClockwise = m_frontFace == CCW;
rastDesc.DepthBias = m_depthBias;
rastDesc.SlopeScaledDepthBias = m_slopeScaledDepthBias;
- rastDesc.DepthClipEnable = true;
+ rastDesc.DepthClipEnable = m_depthClamp ? FALSE : TRUE;
rastDesc.ScissorEnable = m_flags.testFlag(UsesScissor);
rastDesc.MultisampleEnable = rhiD->effectiveSampleDesc(m_sampleCount).Count > 1;
HRESULT hr = rhiD->dev->CreateRasterizerState(&rastDesc, &rastState);
diff --git a/src/gui/rhi/qrhid3d12.cpp b/src/gui/rhi/qrhid3d12.cpp
index 4f09b3c136b..b68b65b1063 100644
--- a/src/gui/rhi/qrhid3d12.cpp
+++ b/src/gui/rhi/qrhid3d12.cpp
@@ -6263,7 +6263,7 @@ bool QD3D12GraphicsPipeline::create()
stream.rasterizerState.object.FrontCounterClockwise = m_frontFace == CCW;
stream.rasterizerState.object.DepthBias = m_depthBias;
stream.rasterizerState.object.SlopeScaledDepthBias = m_slopeScaledDepthBias;
- stream.rasterizerState.object.DepthClipEnable = TRUE;
+ stream.rasterizerState.object.DepthClipEnable = m_depthClamp ? FALSE : TRUE;
stream.rasterizerState.object.MultisampleEnable = sampleDesc.Count > 1;
stream.depthStencilState.object.DepthEnable = m_depthTest;
diff --git a/src/gui/rhi/qrhigles2.cpp b/src/gui/rhi/qrhigles2.cpp
index 15f5cd8f7e8..1308d4362e5 100644
--- a/src/gui/rhi/qrhigles2.cpp
+++ b/src/gui/rhi/qrhigles2.cpp
@@ -585,6 +585,10 @@ QT_BEGIN_NAMESPACE
#define GL_PROGRAM 0x82E2
#endif
+#ifndef GL_DEPTH_CLAMP
+#define GL_DEPTH_CLAMP 0x864F
+#endif
+
/*!
Constructs a new QRhiGles2InitParams.
@@ -998,6 +1002,13 @@ bool QRhiGles2::create(QRhi::Flags flags)
}
if (caps.gles)
+ caps.depthClamp = false;
+ else
+ caps.depthClamp = caps.ctxMajor > 3 || (caps.ctxMajor == 3 && caps.ctxMinor >= 2); // Desktop 3.2
+ if (!caps.depthClamp)
+ caps.depthClamp = ctx->hasExtension("GL_EXT_depth_clamp") || ctx->hasExtension("GL_ARB_depth_clamp");
+
+ if (caps.gles)
caps.textureCompareMode = caps.ctxMajor >= 3; // ES 3.0
else
caps.textureCompareMode = true;
@@ -3959,6 +3970,7 @@ void QRhiGles2::executeCommandBuffer(QRhiCommandBuffer *cb)
break;
case QGles2CommandBuffer::Command::InvalidateFramebuffer:
if (caps.gles && caps.ctxMajor >= 3) {
+ f->glBindFramebuffer(GL_FRAMEBUFFER, cmd.args.invalidateFramebuffer.fbo);
f->glInvalidateFramebuffer(GL_DRAW_FRAMEBUFFER,
cmd.args.invalidateFramebuffer.attCount,
cmd.args.invalidateFramebuffer.att);
@@ -4095,6 +4107,15 @@ void QRhiGles2::executeBindGraphicsPipeline(QGles2CommandBuffer *cbD, QGles2Grap
f->glDepthMask(depthWrite);
}
+ const bool depthClamp = psD->m_depthClamp;
+ if (caps.depthClamp && (forceUpdate || depthClamp != state.depthClamp)) {
+ state.depthClamp = depthClamp;
+ if (depthClamp)
+ f->glEnable(GL_DEPTH_CLAMP);
+ else
+ f->glDisable(GL_DEPTH_CLAMP);
+ }
+
const GLenum depthFunc = toGlCompareOp(psD->m_depthOp);
if (forceUpdate || depthFunc != state.depthFunc) {
state.depthFunc = depthFunc;
@@ -4881,6 +4902,7 @@ void QRhiGles2::endPass(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch *resource
if (mayDiscardDepthStencil) {
QGles2CommandBuffer::Command &cmd(cbD->commands.get());
cmd.cmd = QGles2CommandBuffer::Command::InvalidateFramebuffer;
+ cmd.args.invalidateFramebuffer.fbo = rtTex->framebuffer;
if (caps.needsDepthStencilCombinedAttach) {
cmd.args.invalidateFramebuffer.attCount = 1;
cmd.args.invalidateFramebuffer.att[0] = GL_DEPTH_STENCIL_ATTACHMENT;
diff --git a/src/gui/rhi/qrhigles2_p.h b/src/gui/rhi/qrhigles2_p.h
index 725e71a3665..70dd96a8dc7 100644
--- a/src/gui/rhi/qrhigles2_p.h
+++ b/src/gui/rhi/qrhigles2_p.h
@@ -547,6 +547,7 @@ struct QGles2CommandBuffer : public QRhiCommandBuffer
GLbitfield barriers;
} barrier;
struct {
+ GLuint fbo;
int attCount;
GLenum att[3];
} invalidateFramebuffer;
@@ -592,6 +593,7 @@ struct QGles2CommandBuffer : public QRhiCommandBuffer
} blend[16];
bool depthTest;
bool depthWrite;
+ bool depthClamp;
GLenum depthFunc;
bool stencilTest;
GLuint stencilReadMask;
@@ -1074,6 +1076,7 @@ public:
uint baseVertex : 1;
uint compute : 1;
uint textureCompareMode : 1;
+ uint depthClamp : 1;
uint properMapBuffer : 1;
uint nonBaseLevelFramebufferTexture : 1;
uint texelFetch : 1;
diff --git a/src/gui/rhi/qrhimetal.mm b/src/gui/rhi/qrhimetal.mm
index c3f1031b44b..7fa05f69232 100644
--- a/src/gui/rhi/qrhimetal.mm
+++ b/src/gui/rhi/qrhimetal.mm
@@ -403,6 +403,7 @@ struct QMetalGraphicsPipelineData
MTLWinding winding;
MTLCullMode cullMode;
MTLTriangleFillMode triangleFillMode;
+ MTLDepthClipMode depthClipMode;
float depthBias;
float slopeScaledDepthBias;
QMetalShader vs;
@@ -1477,7 +1478,6 @@ void QMetalGraphicsPipeline::makeActiveForCurrentRenderPassEncoder(QMetalCommand
[cbD->d->currentRenderPassEncoder setDepthStencilState: d->ds];
cbD->d->currentDepthStencilState = d->ds;
}
-
if (cbD->currentCullMode == -1 || d->cullMode != uint(cbD->currentCullMode)) {
[cbD->d->currentRenderPassEncoder setCullMode: d->cullMode];
cbD->currentCullMode = int(d->cullMode);
@@ -1486,6 +1486,10 @@ void QMetalGraphicsPipeline::makeActiveForCurrentRenderPassEncoder(QMetalCommand
[cbD->d->currentRenderPassEncoder setTriangleFillMode: d->triangleFillMode];
cbD->currentTriangleFillMode = int(d->triangleFillMode);
}
+ if (cbD->currentDepthClipMode == -1 || d->depthClipMode != uint(cbD->currentDepthClipMode)) {
+ [cbD->d->currentRenderPassEncoder setDepthClipMode: d->depthClipMode];
+ cbD->currentDepthClipMode = int(d->depthClipMode);
+ }
if (cbD->currentFrontFaceWinding == -1 || d->winding != uint(cbD->currentFrontFaceWinding)) {
[cbD->d->currentRenderPassEncoder setFrontFacingWinding: d->winding];
cbD->currentFrontFaceWinding = int(d->winding);
@@ -5035,6 +5039,7 @@ void QMetalGraphicsPipeline::mapStates()
d->winding = m_frontFace == CCW ? MTLWindingCounterClockwise : MTLWindingClockwise;
d->cullMode = toMetalCullMode(m_cullMode);
d->triangleFillMode = toMetalTriangleFillMode(m_polygonMode);
+ d->depthClipMode = m_depthClamp ? MTLDepthClipModeClamp : MTLDepthClipModeClip;
d->depthBias = float(m_depthBias);
d->slopeScaledDepthBias = m_slopeScaledDepthBias;
}
@@ -6257,6 +6262,7 @@ void QMetalCommandBuffer::resetPerPassCachedState()
currentIndexFormat = QRhiCommandBuffer::IndexUInt16;
currentCullMode = -1;
currentTriangleFillMode = -1;
+ currentDepthClipMode = -1;
currentFrontFaceWinding = -1;
currentDepthBiasValues = { 0.0f, 0.0f };
diff --git a/src/gui/rhi/qrhimetal_p.h b/src/gui/rhi/qrhimetal_p.h
index 7c19ae9e767..6649a6cd304 100644
--- a/src/gui/rhi/qrhimetal_p.h
+++ b/src/gui/rhi/qrhimetal_p.h
@@ -299,6 +299,7 @@ struct QMetalCommandBuffer : public QRhiCommandBuffer
QRhiCommandBuffer::IndexFormat currentIndexFormat;
int currentCullMode;
int currentTriangleFillMode;
+ int currentDepthClipMode;
int currentFrontFaceWinding;
std::pair<float, float> currentDepthBiasValues;
diff --git a/src/gui/rhi/qrhivulkan.cpp b/src/gui/rhi/qrhivulkan.cpp
index c5167a6e7de..481ffd57b5d 100644
--- a/src/gui/rhi/qrhivulkan.cpp
+++ b/src/gui/rhi/qrhivulkan.cpp
@@ -949,6 +949,8 @@ bool QRhiVulkan::create(QRhi::Flags flags)
// elsewhere states that the minimum bufferOffset is 4...
texbufAlign = qMax<VkDeviceSize>(4, physDevProperties.limits.optimalBufferCopyOffsetAlignment);
+ caps.depthClamp = physDevFeatures.depthClamp;
+
caps.wideLines = physDevFeatures.wideLines;
caps.texture3DSliceAs2D = caps.apiVersion >= QVersionNumber(1, 1);
@@ -8402,6 +8404,8 @@ bool QVkGraphicsPipeline::create()
VkPipelineRasterizationStateCreateInfo rastInfo = {};
rastInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO;
+ if (m_depthClamp && rhiD->caps.depthClamp)
+ rastInfo.depthClampEnable = m_depthClamp;
rastInfo.cullMode = toVkCullMode(m_cullMode);
rastInfo.frontFace = toVkFrontFace(m_frontFace);
if (m_depthBias != 0 || !qFuzzyIsNull(m_slopeScaledDepthBias)) {
diff --git a/src/gui/rhi/qrhivulkan_p.h b/src/gui/rhi/qrhivulkan_p.h
index d141a84c5fb..1e9318513fd 100644
--- a/src/gui/rhi/qrhivulkan_p.h
+++ b/src/gui/rhi/qrhivulkan_p.h
@@ -936,6 +936,7 @@ public:
struct {
bool compute = false;
+ bool depthClamp = false;
bool wideLines = false;
bool debugUtils = false;
bool vertexAttribDivisor = false;
diff --git a/src/gui/text/qfontvariableaxis.cpp b/src/gui/text/qfontvariableaxis.cpp
index be83a3e02ce..bbc14f4cd11 100644
--- a/src/gui/text/qfontvariableaxis.cpp
+++ b/src/gui/text/qfontvariableaxis.cpp
@@ -60,6 +60,18 @@ QT_DEFINE_QESDP_SPECIALIZATION_DTOR(QFontVariableAxisPrivate)
QFontVariableAxis::QFontVariableAxis(const QFontVariableAxis &axis) = default;
/*!
+ \property QFontVariableAxis::tag
+ \brief the tag of the axis
+
+ This is a four-character sequence which identifies the axis. Certain tags
+ have standardized meanings, such as "wght" (weight) and "wdth" (width),
+ but any sequence of four latin-1 characters is a valid tag. By convention,
+ non-standard/custom axes are denoted by tags in all uppercase.
+
+ \sa QFont::setVariableAxis(), name()
+*/
+
+/*!
Returns the tag of the axis. This is a four-character sequence which identifies the axis.
Certain tags have standardized meanings, such as "wght" (weight) and "wdth" (width), but any
sequence of four latin-1 characters is a valid tag. By convention, non-standard/custom axes
@@ -91,6 +103,13 @@ void QFontVariableAxis::setTag(QFont::Tag tag)
}
/*!
+ \property QFontVariableAxis::name
+ \brief the name of the axis, if provided by the font
+
+ \sa tag()
+*/
+
+/*!
Returns the name of the axis, if provided by the font.
\sa tag()
@@ -153,6 +172,15 @@ void QFontVariableAxis::setMinimumValue(qreal minimumValue)
}
/*!
+ \property QFontVariableAxis::maximumValue
+ \brief the maximum value of the axis
+
+ Setting the axis to a value which is higher than this is not supported.
+
+ \sa minimumValue(), defaultValue()
+*/
+
+/*!
Returns the maximum value of the axis. Setting the axis to a value which is higher than this
is not supported.
@@ -182,6 +210,16 @@ void QFontVariableAxis::setMaximumValue(qreal maximumValue)
}
/*!
+ \property QFontVariableAxis::defaultValue
+ \brief the default value of the axis
+
+ This is the value the axis will have if none has been provided in the
+ QFont query.
+
+ \sa minimumValue(), maximumValue()
+*/
+
+/*!
Returns the default value of the axis. This is the value the axis will have if none has been
provided in the QFont query.
diff --git a/src/network/access/qhttp2protocolhandler.cpp b/src/network/access/qhttp2protocolhandler.cpp
index 3452d0a448e..dbcccd8e943 100644
--- a/src/network/access/qhttp2protocolhandler.cpp
+++ b/src/network/access/qhttp2protocolhandler.cpp
@@ -333,10 +333,16 @@ void QHttp2ProtocolHandler::handleHeadersReceived(const HPack::HttpHeader &heade
// of parsing and related errors/bugs, but it would be nice to have
// more detailed validation of headers.
if (name == ":status") {
- statusCode = value.left(3).toInt();
- httpReply->setStatusCode(statusCode);
- m_channel->lastStatus = statusCode; // Mostly useless for http/2, needed for auth
- httpReply->setReasonPhrase(QString::fromLatin1(value.mid(4)));
+ bool ok = false;
+ if (int status = value.toInt(&ok); ok && status >= 0 && status <= 999) {
+ statusCode = status;
+ httpReply->setStatusCode(statusCode);
+ m_channel->lastStatus = statusCode; // Mostly useless for http/2, needed for auth
+ } else {
+ finishStreamWithError(stream, QNetworkReply::ProtocolInvalidOperationError,
+ "invalid :status value"_L1);
+ return;
+ }
} else if (name == "content-length") {
bool ok = false;
const qlonglong length = value.toLongLong(&ok);
diff --git a/src/network/access/qnetworkreplyhttpimpl.cpp b/src/network/access/qnetworkreplyhttpimpl.cpp
index f680950701c..f76d79571c3 100644
--- a/src/network/access/qnetworkreplyhttpimpl.cpp
+++ b/src/network/access/qnetworkreplyhttpimpl.cpp
@@ -272,6 +272,11 @@ void QNetworkReplyHttpImpl::close()
void QNetworkReplyHttpImpl::abort()
{
+ abortImpl(QNetworkReply::OperationCanceledError);
+}
+
+void QNetworkReplyHttpImpl::abortImpl(QNetworkReply::NetworkError error)
+{
Q_D(QNetworkReplyHttpImpl);
// FIXME
if (d->state == QNetworkReplyPrivate::Finished || d->state == QNetworkReplyPrivate::Aborted)
@@ -282,7 +287,8 @@ void QNetworkReplyHttpImpl::abort()
if (d->state != QNetworkReplyPrivate::Finished) {
// call finished which will emit signals
// FIXME shouldn't this be emitted Queued?
- d->error(OperationCanceledError, tr("Operation canceled"));
+ d->error(error,
+ error == TimeoutError ? tr("Operation timed out") : tr("Operation canceled"));
d->finished();
}
@@ -2120,7 +2126,7 @@ void QNetworkReplyHttpImplPrivate::_q_bufferOutgoingData()
void QNetworkReplyHttpImplPrivate::_q_transferTimedOut()
{
Q_Q(QNetworkReplyHttpImpl);
- q->abort();
+ q->abortImpl(QNetworkReply::TimeoutError);
}
void QNetworkReplyHttpImplPrivate::setupTransferTimeout()
@@ -2242,8 +2248,10 @@ void QNetworkReplyHttpImplPrivate::error(QNetworkReplyImpl::NetworkError code, c
// Can't set and emit multiple errors.
if (errorCode != QNetworkReply::NoError) {
// But somewhat unavoidable if we have cancelled the request:
- if (errorCode != QNetworkReply::OperationCanceledError)
+ if (errorCode != QNetworkReply::OperationCanceledError
+ && errorCode != QNetworkReply::TimeoutError) {
qWarning("QNetworkReplyImplPrivate::error: Internal problem, this method must only be called once.");
+ }
return;
}
diff --git a/src/network/access/qnetworkreplyhttpimpl_p.h b/src/network/access/qnetworkreplyhttpimpl_p.h
index 0d16d02ff53..a354b388ad6 100644
--- a/src/network/access/qnetworkreplyhttpimpl_p.h
+++ b/src/network/access/qnetworkreplyhttpimpl_p.h
@@ -59,6 +59,7 @@ public:
void close() override;
void abort() override;
+ void abortImpl(QNetworkReply::NetworkError error);
qint64 bytesAvailable() const override;
bool isSequential () const override;
qint64 size() const override;
diff --git a/src/plugins/platforms/cocoa/qcocoafiledialoghelper.mm b/src/plugins/platforms/cocoa/qcocoafiledialoghelper.mm
index e0ef6cec794..4c4e5fac962 100644
--- a/src/plugins/platforms/cocoa/qcocoafiledialoghelper.mm
+++ b/src/plugins/platforms/cocoa/qcocoafiledialoghelper.mm
@@ -491,7 +491,7 @@ typedef QSharedPointer<QFileDialogOptions> SharedPointerFileDialogOptions;
return;
if (m_panel.visible) {
- const QString selection = QString::fromNSString(m_panel.URL.path);
+ const QString selection = QString::fromNSString(m_panel.URL.path).normalized(QString::NormalizationForm_C);
if (selection != m_currentSelection) {
m_currentSelection = selection;
emit m_helper->currentChanged(QUrl::fromLocalFile(selection));
diff --git a/src/plugins/platforms/cocoa/qcocoamessagedialog.mm b/src/plugins/platforms/cocoa/qcocoamessagedialog.mm
index dab348beaa4..7a6f010ba8f 100644
--- a/src/plugins/platforms/cocoa/qcocoamessagedialog.mm
+++ b/src/plugins/platforms/cocoa/qcocoamessagedialog.mm
@@ -88,6 +88,11 @@ bool QCocoaMessageDialog::show(Qt::WindowFlags windowFlags, Qt::WindowModality w
return false;
}
+ // Tahoe has issues with window-modal alert buttons not responding to mouse
+ if (windowModality == Qt::WindowModal
+ && QOperatingSystemVersion::current() >= QOperatingSystemVersion::MacOSTahoe)
+ return false;
+
// And without options we don't know what to show
if (!options())
return false;
diff --git a/src/plugins/platforms/wasm/qwasmaccessibility.cpp b/src/plugins/platforms/wasm/qwasmaccessibility.cpp
index a87c33c8346..eb36f7351d0 100644
--- a/src/plugins/platforms/wasm/qwasmaccessibility.cpp
+++ b/src/plugins/platforms/wasm/qwasmaccessibility.cpp
@@ -322,6 +322,16 @@ void QWasmAccessibility::setProperty(emscripten::val element, const std::string
element.set(property, val);
}
+void QWasmAccessibility::setNamedAttribute(QAccessibleInterface *iface, const std::string &attribute, QAccessible::Text text)
+{
+ const emscripten::val element = getHtmlElement(iface);
+ setAttribute(element, attribute, iface->text(text).toStdString());
+}
+void QWasmAccessibility::setNamedProperty(QAccessibleInterface *iface, const std::string &property, QAccessible::Text text)
+{
+ const emscripten::val element = getHtmlElement(iface);
+ setProperty(element, property, iface->text(text).toStdString());
+}
void QWasmAccessibility::addEventListener(QAccessibleInterface *iface, emscripten::val element, const char *eventType)
{
@@ -331,6 +341,17 @@ void QWasmAccessibility::addEventListener(QAccessibleInterface *iface, emscripte
true);
}
+void QWasmAccessibility::sendEvent(QAccessibleInterface *iface, QAccessible::Event eventType)
+{
+ if (iface->object()) {
+ QAccessibleEvent event(iface->object(), eventType);
+ handleUpdateByInterfaceRole(&event);
+ } else {
+ QAccessibleEvent event(iface, eventType);
+ handleUpdateByInterfaceRole(&event);
+ }
+}
+
emscripten::val QWasmAccessibility::createHtmlElement(QAccessibleInterface *iface)
{
// Get the html container element for the interface; this depends on which
@@ -484,11 +505,11 @@ emscripten::val QWasmAccessibility::createHtmlElement(QAccessibleInterface *ifac
m_elements[iface] = element;
setHtmlElementGeometry(iface);
- setHtmlElementTextName(iface);
setHtmlElementDisabled(iface);
setHtmlElementVisibility(iface, !iface->state().invisible);
handleIdentifierUpdate(iface);
handleDescriptionChanged(iface);
+ sendEvent(iface, QAccessible::NameChanged);
linkToParent(iface);
// Link in child elements
@@ -586,14 +607,7 @@ void QWasmAccessibility::linkToParent(QAccessibleInterface *iface)
void QWasmAccessibility::setHtmlElementVisibility(QAccessibleInterface *iface, bool visible)
{
emscripten::val element = getHtmlElement(iface);
-
- if (visible) {
- setAttribute(element, "aria-hidden", false);
- setAttribute(element, "tabindex", "");
- } else {
- setAttribute(element, "aria-hidden", true); // aria-hidden mean completely hidden; maybe some sort of soft-hidden should be used.
- setAttribute(element, "tabindex", "-1");
- }
+ setAttribute(element, "aria-hidden", !visible);
}
void QWasmAccessibility::setHtmlElementGeometry(QAccessibleInterface *iface)
@@ -631,28 +645,6 @@ void QWasmAccessibility::setHtmlElementGeometry(emscripten::val element, QRect g
style.set("height", std::to_string(geometry.height()) + "px");
}
-void QWasmAccessibility::setHtmlElementTextName(QAccessibleInterface *iface)
-{
- const emscripten::val element = getHtmlElement(iface);
- const QString name = iface->text(QAccessible::Name);
- const QString value = iface->text(QAccessible::Value);
-
- // A <div> cannot contain aria-label
- if (iface->role() == QAccessible::StaticText)
- setProperty(element, "innerText", name.toStdString());
- else if (iface->role() == QAccessible::EditableText)
- setProperty(element, "value", value.toStdString());
- else
- setAttribute(element, "aria-label", name.toStdString());
-}
-
-void QWasmAccessibility::setHtmlElementTextNameLE(QAccessibleInterface *iface)
-{
- const emscripten::val element = getHtmlElement(iface);
- QString value = iface->text(QAccessible::Value);
- setProperty(element, "value", value.toStdString());
-}
-
void QWasmAccessibility::setHtmlElementFocus(QAccessibleInterface *iface)
{
const auto element = getHtmlElement(iface);
@@ -684,7 +676,8 @@ void QWasmAccessibility::handleStaticTextUpdate(QAccessibleEvent *event)
{
switch (event->type()) {
case QAccessible::NameChanged: {
- setHtmlElementTextName(event->accessibleInterface());
+ // StaticText is a div
+ setNamedProperty(event->accessibleInterface(), "innerText", QAccessible::Name);
} break;
default:
qCDebug(lcQpaAccessibility) << "TODO: implement handleStaticTextUpdate for event" << event->type();
@@ -705,7 +698,7 @@ void QWasmAccessibility::handleLineEditUpdate(QAccessibleEvent *event)
setProperty(element, "type", "text");
} break;
case QAccessible::NameChanged: {
- setHtmlElementTextName(event->accessibleInterface());
+ setNamedProperty(event->accessibleInterface(), "value", QAccessible::Value);
} break;
case QAccessible::ObjectShow:
case QAccessible::Focus: {
@@ -718,12 +711,12 @@ void QWasmAccessibility::handleLineEditUpdate(QAccessibleEvent *event)
else
setProperty(element, "type", "text");
}
- setHtmlElementTextNameLE(iface);
+ setNamedProperty(event->accessibleInterface(), "value", QAccessible::Value);
} break;
case QAccessible::TextRemoved:
case QAccessible::TextInserted:
case QAccessible::TextCaretMoved: {
- setHtmlElementTextNameLE(event->accessibleInterface());
+ setNamedProperty(event->accessibleInterface(), "value", QAccessible::Value);
} break;
default:
qCDebug(lcQpaAccessibility) << "TODO: implement handleLineEditUpdate for event" << event->type();
@@ -758,7 +751,15 @@ void QWasmAccessibility::handleEventFromHtmlElement(const emscripten::val event)
void QWasmAccessibility::handleButtonUpdate(QAccessibleEvent *event)
{
- qCDebug(lcQpaAccessibility) << "TODO: implement handleButtonUpdate for event" << event->type();
+ switch (event->type()) {
+ case QAccessible::Focus:
+ case QAccessible::NameChanged: {
+ setNamedAttribute(event->accessibleInterface(), "aria-label", QAccessible::Name);
+ } break;
+ default:
+ qCDebug(lcQpaAccessibility) << "TODO: implement handleCheckBoxUpdate for event" << event->type();
+ break;
+ }
}
void QWasmAccessibility::handleCheckBoxUpdate(QAccessibleEvent *event)
@@ -766,7 +767,7 @@ void QWasmAccessibility::handleCheckBoxUpdate(QAccessibleEvent *event)
switch (event->type()) {
case QAccessible::Focus:
case QAccessible::NameChanged: {
- setHtmlElementTextName(event->accessibleInterface());
+ setNamedAttribute(event->accessibleInterface(), "aria-label", QAccessible::Name);
} break;
case QAccessible::StateChanged: {
QAccessibleInterface *accessible = event->accessibleInterface();
@@ -785,7 +786,8 @@ void QWasmAccessibility::handleSwitchUpdate(QAccessibleEvent *event)
switch (event->type()) {
case QAccessible::Focus:
case QAccessible::NameChanged: {
- setHtmlElementTextName(event->accessibleInterface());
+ /* A switch is like a button in this regard */
+ setNamedAttribute(event->accessibleInterface(), "aria-label", QAccessible::Name);
} break;
case QAccessible::StateChanged: {
QAccessibleInterface *accessible = event->accessibleInterface();
@@ -848,7 +850,7 @@ void QWasmAccessibility::handleDialogUpdate(QAccessibleEvent *event) {
case QAccessible::Focus:
case QAccessible::DialogStart:
case QAccessible::StateChanged: {
- setHtmlElementTextName(event->accessibleInterface());
+ setNamedAttribute(event->accessibleInterface(), "aria-label", QAccessible::Name);
} break;
default:
qCDebug(lcQpaAccessibility) << "TODO: implement handleLineEditUpdate for event" << event->type();
@@ -876,10 +878,10 @@ void QWasmAccessibility::populateAccessibilityTree(QAccessibleInterface *iface)
linkToParent(iface);
setHtmlElementVisibility(iface, !iface->state().invisible);
setHtmlElementGeometry(iface);
- setHtmlElementTextName(iface);
setHtmlElementDisabled(iface);
handleIdentifierUpdate(iface);
handleDescriptionChanged(iface);
+ sendEvent(iface, QAccessible::NameChanged);
}
}
for (int i = 0; i < iface->childCount(); ++i)
@@ -891,7 +893,7 @@ void QWasmAccessibility::handleRadioButtonUpdate(QAccessibleEvent *event)
switch (event->type()) {
case QAccessible::Focus:
case QAccessible::NameChanged: {
- setHtmlElementTextName(event->accessibleInterface());
+ setNamedAttribute(event->accessibleInterface(), "aria-label", QAccessible::Name);
} break;
case QAccessible::StateChanged: {
QAccessibleInterface *accessible = event->accessibleInterface();
@@ -912,7 +914,7 @@ void QWasmAccessibility::handleSpinBoxUpdate(QAccessibleEvent *event)
} break;
case QAccessible::Focus:
case QAccessible::NameChanged: {
- setHtmlElementTextName(event->accessibleInterface());
+ setNamedAttribute(event->accessibleInterface(), "aria-label", QAccessible::Name);
} break;
case QAccessible::ValueChanged: {
QAccessibleInterface *accessible = event->accessibleInterface();
@@ -934,7 +936,7 @@ void QWasmAccessibility::handleSliderUpdate(QAccessibleEvent *event)
} break;
case QAccessible::Focus:
case QAccessible::NameChanged: {
- setHtmlElementTextName(event->accessibleInterface());
+ setNamedAttribute(event->accessibleInterface(), "aria-label", QAccessible::Name);
} break;
case QAccessible::ValueChanged: {
QAccessibleInterface *accessible = event->accessibleInterface();
@@ -953,7 +955,7 @@ void QWasmAccessibility::handleScrollBarUpdate(QAccessibleEvent *event)
switch (event->type()) {
case QAccessible::Focus:
case QAccessible::NameChanged: {
- setHtmlElementTextName(event->accessibleInterface());
+ setNamedAttribute(event->accessibleInterface(), "aria-label", QAccessible::Name);
} break;
case QAccessible::ValueChanged: {
QAccessibleInterface *accessible = event->accessibleInterface();
@@ -972,10 +974,10 @@ void QWasmAccessibility::handlePageTabUpdate(QAccessibleEvent *event)
{
switch (event->type()) {
case QAccessible::NameChanged: {
- setHtmlElementTextName(event->accessibleInterface());
+ setNamedAttribute(event->accessibleInterface(), "aria-label", QAccessible::Name);
} break;
case QAccessible::Focus: {
- setHtmlElementTextName(event->accessibleInterface());
+ setNamedAttribute(event->accessibleInterface(), "aria-label", QAccessible::Name);
} break;
default:
qDebug() << "TODO: implement handlePageTabUpdate for event" << event->type();
@@ -987,10 +989,10 @@ void QWasmAccessibility::handlePageTabListUpdate(QAccessibleEvent *event)
{
switch (event->type()) {
case QAccessible::NameChanged: {
- setHtmlElementTextName(event->accessibleInterface());
+ setNamedAttribute(event->accessibleInterface(), "aria-label", QAccessible::Name);
} break;
case QAccessible::Focus: {
- setHtmlElementTextName(event->accessibleInterface());
+ setNamedAttribute(event->accessibleInterface(), "aria-label", QAccessible::Name);
} break;
default:
qDebug() << "TODO: implement handlePageTabUpdate for event" << event->type();
@@ -1113,13 +1115,19 @@ void QWasmAccessibility::relinkParentForChildren(QAccessibleInterface *iface)
void QWasmAccessibility::notifyAccessibilityUpdate(QAccessibleEvent *event)
{
+ if (handleUpdateByEventType(event))
+ handleUpdateByInterfaceRole(event);
+}
+
+bool QWasmAccessibility::handleUpdateByEventType(QAccessibleEvent *event)
+{
if (!m_accessibilityEnabled)
- return;
+ return false;
QAccessibleInterface *iface = event->accessibleInterface();
if (!iface) {
- qWarning() << "notifyAccessibilityUpdate with null a11y interface" << event->type() << event->object();
- return;
+ qWarning() << "handleUpdateByEventType with null a11y interface" << event->type() << event->object();
+ return false;
}
// Handle event types that creates/removes objects.
@@ -1127,13 +1135,13 @@ void QWasmAccessibility::notifyAccessibilityUpdate(QAccessibleEvent *event)
case QAccessible::ObjectCreated:
// Do nothing, there are too many changes to the interface
// before ObjectShow is called
- return;
+ return false;
case QAccessible::ObjectDestroyed:
// The object might be under destruction, and the interface is not valid
// but we can look at the pointer,
removeObject(iface);
- return;
+ return false;
case QAccessible::ObjectShow: // We do not get ObjectCreated from widgets, we get ObjectShow
createObject(iface);
@@ -1149,7 +1157,7 @@ void QWasmAccessibility::notifyAccessibilityUpdate(QAccessibleEvent *event)
};
if (getHtmlElement(iface).isUndefined())
- return;
+ return false;
// Handle some common event types. See
// https://doc.qt.io/qt-5/qaccessible.html#Event-enum
@@ -1162,7 +1170,7 @@ void QWasmAccessibility::notifyAccessibilityUpdate(QAccessibleEvent *event)
case QAccessible::DescriptionChanged:
handleDescriptionChanged(iface);
- return;
+ return false;
case QAccessible::Focus:
// We do not get all callbacks for the geometry
@@ -1173,7 +1181,7 @@ void QWasmAccessibility::notifyAccessibilityUpdate(QAccessibleEvent *event)
case QAccessible::IdentifierChanged:
handleIdentifierUpdate(iface);
- return;
+ return false;
case QAccessible::ObjectShow:
linkToParent(iface);
@@ -1181,23 +1189,37 @@ void QWasmAccessibility::notifyAccessibilityUpdate(QAccessibleEvent *event)
// Sync up properties on show;
setHtmlElementGeometry(iface);
- setHtmlElementTextName(iface);
+ sendEvent(iface, QAccessible::NameChanged);
break;
case QAccessible::ObjectHide:
linkToParent(iface);
setHtmlElementVisibility(iface, false);
- return;
+ return false;
case QAccessible::LocationChanged:
setHtmlElementGeometry(iface);
- return;
+ return false;
// TODO: maybe handle more types here
default:
break;
};
+ return true;
+}
+
+void QWasmAccessibility::handleUpdateByInterfaceRole(QAccessibleEvent *event)
+{
+ if (!m_accessibilityEnabled)
+ return;
+
+ QAccessibleInterface *iface = event->accessibleInterface();
+ if (!iface) {
+ qWarning() << "handleUpdateByInterfaceRole with null a11y interface" << event->type() << event->object();
+ return;
+ }
+
// Switch on interface role, see
// https://doc.qt.io/qt-5/qaccessibleinterface.html#role
switch (iface->role()) {
@@ -1205,7 +1227,7 @@ void QWasmAccessibility::notifyAccessibilityUpdate(QAccessibleEvent *event)
handleStaticTextUpdate(event);
break;
case QAccessible::Button:
- handleStaticTextUpdate(event);
+ handleButtonUpdate(event);
break;
case QAccessible::CheckBox:
handleCheckBoxUpdate(event);
diff --git a/src/plugins/platforms/wasm/qwasmaccessibility.h b/src/plugins/platforms/wasm/qwasmaccessibility.h
index ddbfec918d6..f20c7db5ac3 100644
--- a/src/plugins/platforms/wasm/qwasmaccessibility.h
+++ b/src/plugins/platforms/wasm/qwasmaccessibility.h
@@ -73,8 +73,6 @@ private:
void setHtmlElementVisibility(QAccessibleInterface *iface, bool visible);
void setHtmlElementGeometry(QAccessibleInterface *iface);
void setHtmlElementGeometry(emscripten::val element, QRect geometry);
- void setHtmlElementTextName(QAccessibleInterface *iface);
- void setHtmlElementTextNameLE(QAccessibleInterface *iface);
void setHtmlElementFocus(QAccessibleInterface *iface);
void setHtmlElementDisabled(QAccessibleInterface *iface);
void setHtmlElementOrientation(emscripten::val element, QAccessibleInterface *iface);
@@ -105,6 +103,9 @@ private:
void relinkParentForChildren(QAccessibleInterface *iface);
void notifyAccessibilityUpdate(QAccessibleEvent *event) override;
+ bool handleUpdateByEventType(QAccessibleEvent *event);
+ void handleUpdateByInterfaceRole(QAccessibleEvent *event);
+
void setRootObject(QObject *o) override;
void initialize() override;
void cleanup() override;
@@ -117,7 +118,11 @@ private:
void setProperty(emscripten::val element, const std::string &attr, const char *val);
void setProperty(emscripten::val element, const std::string &attr, bool val);
+ void setNamedAttribute(QAccessibleInterface *iface, const std::string &attribute, QAccessible::Text text);
+ void setNamedProperty(QAccessibleInterface *iface, const std::string &property, QAccessible::Text text);
+
void addEventListener(QAccessibleInterface *, emscripten::val element, const char *eventType);
+ void sendEvent(QAccessibleInterface *iface, QAccessible::Event eventType);
private:
static QWasmAccessibility *s_instance;
diff --git a/src/plugins/platforms/wayland/global/qwaylandclientextension.cpp b/src/plugins/platforms/wayland/global/qwaylandclientextension.cpp
index 92c746d3541..edbeb1f72ea 100644
--- a/src/plugins/platforms/wayland/global/qwaylandclientextension.cpp
+++ b/src/plugins/platforms/wayland/global/qwaylandclientextension.cpp
@@ -40,6 +40,11 @@ void QWaylandClientExtensionPrivate::globalRemoved(const RegistryGlobal &global)
}
}
+/*!
+ \class QWaylandClientExtension
+ \internal
+*/
+
void QWaylandClientExtension::initialize()
{
Q_D(QWaylandClientExtension);
diff --git a/src/plugins/platforms/wayland/qwaylandinputcontext.cpp b/src/plugins/platforms/wayland/qwaylandinputcontext.cpp
index 0ccc4dba57a..5ab285ad97d 100644
--- a/src/plugins/platforms/wayland/qwaylandinputcontext.cpp
+++ b/src/plugins/platforms/wayland/qwaylandinputcontext.cpp
@@ -192,10 +192,12 @@ void QWaylandInputContext::setFocusObject(QObject *object)
if (window && window->handle()) {
if (mCurrentWindow.data() != window) {
if (!inputMethodAccepted()) {
- auto *surface = static_cast<QWaylandWindow *>(window->handle())->wlSurface();
- if (surface)
- inputInterface->disableSurface(surface);
- mCurrentWindow.clear();
+ if (mCurrentWindow) {
+ auto *surface = static_cast<QWaylandWindow *>(mCurrentWindow->handle())->wlSurface();
+ if (surface)
+ inputInterface->disableSurface(surface);
+ mCurrentWindow.clear();
+ }
} else {
auto *surface = static_cast<QWaylandWindow *>(window->handle())->wlSurface();
if (surface) {
diff --git a/src/plugins/platforms/windows/qwindowscontext.cpp b/src/plugins/platforms/windows/qwindowscontext.cpp
index 1c3a3909bc2..15ab167c83f 100644
--- a/src/plugins/platforms/windows/qwindowscontext.cpp
+++ b/src/plugins/platforms/windows/qwindowscontext.cpp
@@ -179,9 +179,6 @@ QWindowsContextPrivate::QWindowsContextPrivate()
QWindowsContext::QWindowsContext() :
d(new QWindowsContextPrivate)
{
-#ifdef Q_CC_MSVC
-# pragma warning( disable : 4996 )
-#endif
m_instance = this;
}
diff --git a/src/plugins/platforms/windows/qwindowsiconengine.cpp b/src/plugins/platforms/windows/qwindowsiconengine.cpp
index 71103183183..edc1ea3a9dc 100644
--- a/src/plugins/platforms/windows/qwindowsiconengine.cpp
+++ b/src/plugins/platforms/windows/qwindowsiconengine.cpp
@@ -63,8 +63,8 @@ static QString getGlyphs(QStringView iconName)
{"go-home"_L1, u"\ue80f"},
// {"go-jump"_L1, u"\uf719"},
//{"go-last"_L1, u"\ue5dd"},
- {"go-next"_L1, u"\ue893"},
- {"go-previous"_L1, u"\ue892"},
+ {"go-next"_L1, u"\ue72a"},
+ {"go-previous"_L1, u"\ue72b"},
//{"go-top"_L1, u"\ue25a"},
{"go-up"_L1, u"\ue74a"},
{"help-about"_L1, u"\ue946"},
@@ -100,7 +100,7 @@ static QString getGlyphs(QStringView iconName)
//{"object-flip-vertical"_L1, u"\u"},
{"object-rotate-left"_L1, u"\ue80c"},
{"object-rotate-right"_L1, u"\ue80d"},
- //{"process-stop"_L1, u"\ue5c9"},
+ {"process-stop"_L1, u"\uf140"},
{"system-lock-screen"_L1, u"\uee3f"},
{"system-log-out"_L1, u"\uf3b1"},
//{"system-run"_L1, u"\u"},
diff --git a/src/plugins/platforms/windows/qwindowswindow.cpp b/src/plugins/platforms/windows/qwindowswindow.cpp
index 8e3ab67ced5..72daffb56b1 100644
--- a/src/plugins/platforms/windows/qwindowswindow.cpp
+++ b/src/plugins/platforms/windows/qwindowswindow.cpp
@@ -466,15 +466,17 @@ static bool applyBlurBehindWindow(HWND hwnd)
return result;
}
+static bool shouldShowTitlebarButton(Qt::WindowFlags flags, Qt::WindowFlags button)
+{
+ return !flags.testFlag(Qt::CustomizeWindowHint) || flags.testFlags(Qt::CustomizeWindowHint | button);
+}
+
// from qwidget_win.cpp, pass flags separately in case they have been "autofixed".
static bool shouldShowMaximizeButton(const QWindow *w, Qt::WindowFlags flags)
{
- if ((flags & Qt::MSWindowsFixedSizeDialogHint) || !(flags & Qt::WindowMaximizeButtonHint))
- return false;
- // if the user explicitly asked for the maximize button, we try to add
- // it even if the window has fixed size.
- return (flags & Qt::CustomizeWindowHint) ||
- w->maximumSize() == QSize(QWINDOWSIZE_MAX, QWINDOWSIZE_MAX);
+ return !flags.testFlag(Qt::MSWindowsFixedSizeDialogHint) &&
+ (shouldShowTitlebarButton(flags, Qt::WindowMaximizeButtonHint) ||
+ w->maximumSize() == QSize(QWINDOWSIZE_MAX, QWINDOWSIZE_MAX));
}
bool QWindowsWindow::hasNoNativeFrame(HWND hwnd, Qt::WindowFlags flags)
@@ -805,6 +807,7 @@ void WindowCreationData::fromWindow(const QWindow *w, const Qt::WindowFlags flag
if (topLevel) {
if ((type == Qt::Window || dialog || tool)) {
+ const bool defaultTitlebar = !flags.testFlag(Qt::CustomizeWindowHint);
if (!(flags & Qt::FramelessWindowHint)) {
style |= WS_POPUP;
if (flags & Qt::MSWindowsFixedSizeDialogHint) {
@@ -812,16 +815,16 @@ void WindowCreationData::fromWindow(const QWindow *w, const Qt::WindowFlags flag
} else {
style |= WS_THICKFRAME;
}
- if (flags & Qt::WindowTitleHint)
+ if (defaultTitlebar || flags.testFlags(Qt::CustomizeWindowHint | Qt::WindowTitleHint))
style |= WS_CAPTION; // Contains WS_DLGFRAME
}
- if (flags & Qt::WindowSystemMenuHint)
+ if (defaultTitlebar || flags.testFlags(Qt::CustomizeWindowHint | Qt::WindowSystemMenuHint))
style |= WS_SYSMENU;
- else if (dialog && (flags & Qt::WindowCloseButtonHint) && !(flags & Qt::FramelessWindowHint)) {
+ else if (dialog && (defaultTitlebar || flags.testFlags(Qt::CustomizeWindowHint | Qt::WindowCloseButtonHint)) && !(flags & Qt::FramelessWindowHint)) {
style |= WS_SYSMENU | WS_BORDER; // QTBUG-2027, dialogs without system menu.
exStyle |= WS_EX_DLGMODALFRAME;
}
- const bool showMinimizeButton = flags & Qt::WindowMinimizeButtonHint;
+ const bool showMinimizeButton = shouldShowTitlebarButton(flags, Qt::WindowMinimizeButtonHint);
if (showMinimizeButton)
style |= WS_MINIMIZEBOX;
const bool showMaximizeButton = shouldShowMaximizeButton(w, flags);
diff --git a/src/plugins/styles/modernwindows/qwindows11style.cpp b/src/plugins/styles/modernwindows/qwindows11style.cpp
index 2944c02fd79..c8cd7c26f61 100644
--- a/src/plugins/styles/modernwindows/qwindows11style.cpp
+++ b/src/plugins/styles/modernwindows/qwindows11style.cpp
@@ -109,6 +109,7 @@ inline ControlState calcControlState(const QStyleOption *option)
#define More u"\uE712"_s
#define Help u"\uE897"_s
+#define Clear u"\uE894"_s
template <typename R, typename P, typename B>
static inline void drawRoundedRect(QPainter *p, R &&rect, P &&pen, B &&brush)
@@ -1720,9 +1721,10 @@ void QWindows11Style::drawControl(ControlElement element, const QStyleOption *op
}
case CE_ItemViewItem: {
if (const QStyleOptionViewItem *vopt = qstyleoption_cast<const QStyleOptionViewItem *>(option)) {
- QRect checkRect = proxy()->subElementRect(SE_ItemViewItemCheckIndicator, vopt, widget);
- QRect iconRect = proxy()->subElementRect(SE_ItemViewItemDecoration, vopt, widget);
- QRect textRect = proxy()->subElementRect(SE_ItemViewItemText, vopt, widget);
+ const auto p = proxy();
+ QRect checkRect = p->subElementRect(SE_ItemViewItemCheckIndicator, vopt, widget);
+ QRect iconRect = p->subElementRect(SE_ItemViewItemDecoration, vopt, widget);
+ QRect textRect = p->subElementRect(SE_ItemViewItemText, vopt, widget);
// draw the background
proxy()->drawPrimitive(PE_PanelItemViewItem, option, painter, widget);
@@ -1823,16 +1825,17 @@ void QWindows11Style::drawControl(ControlElement element, const QStyleOption *op
d->viewItemDrawText(painter, vopt, textRect);
// paint a vertical marker for QListView
- if (vopt->state & State_Selected) {
+ if (vopt->state & State_Selected && !highContrastTheme) {
if (const QListView *lv = qobject_cast<const QListView *>(widget);
- lv && lv->viewMode() != QListView::IconMode && !highContrastTheme) {
- painter->setPen(vopt->palette.accent().color());
- const auto xPos = isRtl ? rect.right() - 1 : rect.left();
- const QLineF lines[2] = {
- QLineF(xPos, rect.y() + 2, xPos, rect.y() + rect.height() - 2),
- QLineF(xPos + 1, rect.y() + 2, xPos + 1, rect.y() + rect.height() - 2),
- };
- painter->drawLines(lines, 2);
+ lv && lv->viewMode() != QListView::IconMode) {
+ const auto col = vopt->palette.accent().color();
+ painter->setBrush(col);
+ painter->setPen(col);
+ const auto xPos = isRtl ? rect.right() - 4.5f : rect.left() + 3.5f;
+ const auto yOfs = rect.height() / 4.;
+ QRectF r(QPointF(xPos, rect.y() + yOfs),
+ QPointF(xPos + 1, rect.y() + rect.height() - yOfs));
+ painter->drawRoundedRect(r, 1, 1);
}
}
}
@@ -1872,7 +1875,7 @@ QRect QWindows11Style::subElementRect(QStyle::SubElement element, const QStyleOp
case QStyle::SE_RadioButtonIndicator:
case QStyle::SE_CheckBoxIndicator:
ret = QWindowsVistaStyle::subElementRect(element, option, widget);
- ret.moveLeft(contentItemHMargin);
+ ret.moveLeft(ret.left() + contentItemHMargin);
break;
case QStyle::SE_ComboBoxFocusRect:
case QStyle::SE_CheckBoxFocusRect:
@@ -1883,22 +1886,29 @@ QRect QWindows11Style::subElementRect(QStyle::SubElement element, const QStyleOp
case QStyle::SE_LineEditContents:
ret = option->rect.adjusted(4,0,-4,0);
break;
- case QStyle::SE_ItemViewItemText:
- if (const auto *item = qstyleoption_cast<const QStyleOptionViewItem *>(option)) {
- const int decorationOffset = item->features.testFlag(QStyleOptionViewItem::HasDecoration) ? item->decorationSize.width() : 0;
- const int checkboxOffset = item->features.testFlag(QStyleOptionViewItem::HasCheckIndicator) ? 16 : 0;
- if (widget && qobject_cast<QComboBoxPrivateContainer *>(widget->parentWidget())) {
- if (option->direction == Qt::LeftToRight)
- ret = option->rect.adjusted(decorationOffset + checkboxOffset + 5, 0, -5, 0);
- else
- ret = option->rect.adjusted(5, 0, decorationOffset - checkboxOffset - 5, 0);
+ case SE_ItemViewItemCheckIndicator:
+ case SE_ItemViewItemDecoration:
+ case SE_ItemViewItemText: {
+ ret = QWindowsVistaStyle::subElementRect(element, option, widget);
+ if (!ret.isValid() || highContrastTheme)
+ return ret;
+
+ if (const QListView *lv = qobject_cast<const QListView *>(widget);
+ lv && lv->viewMode() != QListView::IconMode) {
+ const int xOfs = contentHMargin;
+ const bool isRtl = option->direction == Qt::RightToLeft;
+ if (isRtl) {
+ ret.moveRight(ret.right() - xOfs);
+ if (ret.left() < option->rect.left())
+ ret.setLeft(option->rect.left());
} else {
- ret = QWindowsVistaStyle::subElementRect(element, option, widget);
+ ret.moveLeft(ret.left() + xOfs);
+ if (ret.right() > option->rect.right())
+ ret.setRight(option->rect.right());
}
- } else {
- ret = QWindowsVistaStyle::subElementRect(element, option, widget);
}
break;
+ }
#if QT_CONFIG(progressbar)
case SE_ProgressBarGroove:
case SE_ProgressBarContents:
@@ -2091,6 +2101,19 @@ QRect QWindows11Style::subControlRect(ComplexControl control, const QStyleOption
}
break;
}
+#if QT_CONFIG(groupbox)
+ case CC_GroupBox: {
+ ret = QWindowsVistaStyle::subControlRect(control, option, subControl, widget);
+ switch (subControl) {
+ case SC_GroupBoxCheckBox:
+ ret.moveTop(1);
+ break;
+ default:
+ break;
+ }
+ break;
+ }
+#endif // QT_CONFIG(groupbox)
default:
ret = QWindowsVistaStyle::subControlRect(control, option, subControl, widget);
}
@@ -2234,6 +2257,25 @@ QSize QWindows11Style::sizeFromContents(ContentsType type, const QStyleOption *o
contentSize.rwidth() += 2 * contentHMargin - oldMargin;
break;
}
+ case CT_ItemViewItem: {
+ if (const auto *viewItemOpt = qstyleoption_cast<const QStyleOptionViewItem *>(option)) {
+ if (const QListView *lv = qobject_cast<const QListView *>(widget);
+ lv && lv->viewMode() != QListView::IconMode) {
+ QStyleOptionViewItem vOpt(*viewItemOpt);
+ // viewItemSize only takes PM_FocusFrameHMargin into account but no additional
+ // margin, therefore adjust it here for a correct width during layouting when
+ // WrapText is enabled
+ vOpt.rect.setRight(vOpt.rect.right() - contentHMargin);
+ contentSize = QWindowsVistaStyle::sizeFromContents(type, &vOpt, size, widget);
+ contentSize.rwidth() += contentHMargin;
+ contentSize.rheight() += 2 * contentHMargin;
+
+ } else {
+ contentSize = QWindowsVistaStyle::sizeFromContents(type, option, size, widget);
+ }
+ }
+ break;
+ }
default:
contentSize = QWindowsVistaStyle::sizeFromContents(type, option, size, widget);
break;
@@ -2544,6 +2586,7 @@ void QWindows11Style::polish(QPalette& result)
d->m_titleBarCloseIcon = QIcon();
d->m_titleBarNormalIcon = QIcon();
d->m_toolbarExtensionButton = QIcon();
+ d->m_lineEditClearButton = QIcon();
}
QPixmap QWindows11Style::standardPixmap(StandardPixmap standardPixmap,
@@ -2568,10 +2611,17 @@ QIcon QWindows11Style::standardIcon(StandardPixmap standardIcon,
{
auto *d = const_cast<QWindows11StylePrivate*>(d_func());
switch (standardIcon) {
+ case SP_LineEditClearButton: {
+ if (d->m_lineEditClearButton.isNull()) {
+ auto e = new WinFontIconEngine(Clear.at(0), d->assetFont);
+ d->m_lineEditClearButton = QIcon(e);
+ }
+ return d->m_lineEditClearButton;
+ }
case SP_ToolBarHorizontalExtensionButton:
case SP_ToolBarVerticalExtensionButton: {
if (d->m_toolbarExtensionButton.isNull()) {
- auto e = new WinFontIconEngine(More.at(0), d->assetFont);
+ auto e = new WinFontIconEngine(More, d->assetFont);
e->setScale(1.0);
d->m_toolbarExtensionButton = QIcon(e);
}
diff --git a/src/plugins/styles/modernwindows/qwindows11style_p.h b/src/plugins/styles/modernwindows/qwindows11style_p.h
index 736caae956c..a51a93ddd9b 100644
--- a/src/plugins/styles/modernwindows/qwindows11style_p.h
+++ b/src/plugins/styles/modernwindows/qwindows11style_p.h
@@ -123,6 +123,7 @@ class QWindows11StylePrivate : public QWindowsVistaStylePrivate {
protected:
QIcon m_toolbarExtensionButton;
+ QIcon m_lineEditClearButton;
};
QT_END_NAMESPACE
diff --git a/src/plugins/styles/modernwindows/qwindowsvistastyle.cpp b/src/plugins/styles/modernwindows/qwindowsvistastyle.cpp
index 22ca18b10bf..fa0d0260f3c 100644
--- a/src/plugins/styles/modernwindows/qwindowsvistastyle.cpp
+++ b/src/plugins/styles/modernwindows/qwindowsvistastyle.cpp
@@ -4959,8 +4959,7 @@ QIcon QWindowsVistaStyle::standardIcon(StandardPixmap standardIcon,
return QWindowsStyle::standardIcon(standardIcon, option, widget);
}
-
-WinFontIconEngine::WinFontIconEngine(const QChar &glyph, const QFont &font)
+WinFontIconEngine::WinFontIconEngine(const QString &glyph, const QFont &font)
: QFontIconEngine({}, font)
, m_font(font)
, m_glyph(glyph)
diff --git a/src/plugins/styles/modernwindows/qwindowsvistastyle_p_p.h b/src/plugins/styles/modernwindows/qwindowsvistastyle_p_p.h
index cf982ceb133..23b34547faa 100644
--- a/src/plugins/styles/modernwindows/qwindowsvistastyle_p_p.h
+++ b/src/plugins/styles/modernwindows/qwindowsvistastyle_p_p.h
@@ -184,7 +184,7 @@ private:
class WinFontIconEngine : public QFontIconEngine
{
public:
- WinFontIconEngine(const QChar &glyph, const QFont &font);
+ WinFontIconEngine(const QString &glyph, const QFont &font);
QString key() const override;
QIconEngine *clone() const override;
@@ -194,7 +194,7 @@ public:
protected:
QFont m_font;
- QChar m_glyph;
+ QString m_glyph;
double m_scale = 0.7;
};
diff --git a/src/testlib/qtestcase.cpp b/src/testlib/qtestcase.cpp
index 784e69d2486..a98f5da2389 100644
--- a/src/testlib/qtestcase.cpp
+++ b/src/testlib/qtestcase.cpp
@@ -410,7 +410,7 @@ public:
static QMetaMethod findMethod(const QObject *obj, const char *signature);
private:
- bool invokeTest(int index, QLatin1StringView tag, std::optional<WatchDog> &watchDog) const;
+ void invokeTest(int index, QLatin1StringView tag, std::optional<WatchDog> &watchDog) const;
void invokeTestOnData(int index) const;
QMetaMethod m_initTestCaseMethod; // might not exist, check isValid().
@@ -1315,11 +1315,8 @@ static void printUnknownDataTagError(QLatin1StringView name, QLatin1StringView t
Call slot_data(), init(), slot(), cleanup(), init(), slot(), cleanup(), ...
If data is set then it is the only test that is performed
-
- If the function was successfully called, true is returned, otherwise
- false.
*/
-bool TestMethods::invokeTest(int index, QLatin1StringView tag, std::optional<WatchDog> &watchDog) const
+void TestMethods::invokeTest(int index, QLatin1StringView tag, std::optional<WatchDog> &watchDog) const
{
QBenchmarkTestMethodData benchmarkData;
QBenchmarkTestMethodData::current = &benchmarkData;
@@ -1422,8 +1419,6 @@ bool TestMethods::invokeTest(int index, QLatin1StringView tag, std::optional<Wat
QTestResult::finishedCurrentTestFunction();
QTestResult::setSkipCurrentTest(false);
QTestResult::setBlacklistCurrentTest(false);
-
- return true;
}
void *fetchData(QTestData *data, const char *tagName, int typeId)
@@ -1743,10 +1738,8 @@ void TestMethods::invokeTests(QObject *testObject) const
const char *data = nullptr;
if (i < QTest::testTags.size() && !QTest::testTags.at(i).isEmpty())
data = qstrdup(QTest::testTags.at(i).toLatin1().constData());
- const bool ok = invokeTest(i, QLatin1StringView(data), watchDog);
+ invokeTest(i, QLatin1StringView(data), watchDog);
delete [] data;
- if (!ok)
- break;
}
}
diff --git a/src/widgets/accessible/itemviews.cpp b/src/widgets/accessible/itemviews.cpp
index fc969e17380..265c523eae0 100644
--- a/src/widgets/accessible/itemviews.cpp
+++ b/src/widgets/accessible/itemviews.cpp
@@ -60,7 +60,7 @@ int QAccessibleTable::logicalIndex(const QModelIndex &index) const
}
QAccessibleTable::QAccessibleTable(QWidget *w)
- : QAccessibleObject(w)
+ : QAccessibleWidgetV2(w)
{
Q_ASSERT(view());
@@ -677,7 +677,7 @@ void *QAccessibleTable::interface_cast(QAccessible::InterfaceType t)
return static_cast<QAccessibleSelectionInterface*>(this);
if (t == QAccessible::TableInterface)
return static_cast<QAccessibleTableInterface*>(this);
- return nullptr;
+ return QAccessibleWidgetV2::interface_cast(t);
}
void QAccessibleTable::modelChange(QAccessibleTableModelChangeEvent *event)
diff --git a/src/widgets/accessible/itemviews_p.h b/src/widgets/accessible/itemviews_p.h
index 9b30f36ced3..79f9a7f2f05 100644
--- a/src/widgets/accessible/itemviews_p.h
+++ b/src/widgets/accessible/itemviews_p.h
@@ -31,7 +31,9 @@ QT_BEGIN_NAMESPACE
class QAccessibleTableCell;
class QAccessibleTableHeaderCell;
-class QAccessibleTable :public QAccessibleTableInterface, public QAccessibleSelectionInterface, public QAccessibleObject
+class QAccessibleTable : public QAccessibleTableInterface,
+ public QAccessibleSelectionInterface,
+ public QAccessibleWidgetV2
{
public:
explicit QAccessibleTable(QWidget *w);
diff --git a/src/widgets/accessible/rangecontrols.cpp b/src/widgets/accessible/rangecontrols.cpp
index c0de5357c9a..1f7b20833dd 100644
--- a/src/widgets/accessible/rangecontrols.cpp
+++ b/src/widgets/accessible/rangecontrols.cpp
@@ -65,6 +65,16 @@ QAccessibleInterface *QAccessibleAbstractSpinBox::lineEditIface() const
#endif
}
+QAccessible::State QAccessibleAbstractSpinBox::state() const
+{
+ QAccessible::State state = QAccessibleWidgetV2::state();
+ if (abstractSpinBox()->isReadOnly())
+ state.readOnly = true;
+ else
+ state.editable = true;
+ return state;
+}
+
QString QAccessibleAbstractSpinBox::text(QAccessible::Text t) const
{
if (t == QAccessible::Value)
diff --git a/src/widgets/accessible/rangecontrols_p.h b/src/widgets/accessible/rangecontrols_p.h
index dd5a6a4531c..5a023d2f00b 100644
--- a/src/widgets/accessible/rangecontrols_p.h
+++ b/src/widgets/accessible/rangecontrols_p.h
@@ -42,6 +42,7 @@ public:
explicit QAccessibleAbstractSpinBox(QWidget *w);
virtual ~QAccessibleAbstractSpinBox();
+ QAccessible::State state() const override;
QString text(QAccessible::Text t) const override;
void *interface_cast(QAccessible::InterfaceType t) override;
diff --git a/src/widgets/dialogs/qfontdialog.cpp b/src/widgets/dialogs/qfontdialog.cpp
index 870b0c40faf..c4f8af1a639 100644
--- a/src/widgets/dialogs/qfontdialog.cpp
+++ b/src/widgets/dialogs/qfontdialog.cpp
@@ -172,7 +172,7 @@ void QFontDialogPrivate::init()
sizeAccel = new QLabel(q);
#ifndef QT_NO_SHORTCUT
- sizeAccel->setBuddy(sizeEdit);
+ sizeAccel->setBuddy(sizeList);
#endif
sizeAccel->setIndent(2);
diff --git a/src/widgets/kernel/qlayout.cpp b/src/widgets/kernel/qlayout.cpp
index 00f9766af29..5ba92714f6c 100644
--- a/src/widgets/kernel/qlayout.cpp
+++ b/src/widgets/kernel/qlayout.cpp
@@ -345,6 +345,17 @@ void QLayout::getContentsMargins(int *left, int *top, int *right, int *bottom) c
}
/*!
+ \property QLayout::contentsMargins
+ \since 4.6
+ \brief the margins used around the layout
+
+ By default, QLayout uses the values provided by the style. On
+ most platforms, the margin is 11 pixels in all directions.
+
+ \sa setContentsMargins(), getContentsMargins()
+*/
+
+/*!
\since 4.6
Returns the margins used around the layout.