Merge remote-tracking branch 'origin/5.15' into dev

Conflicts:
	tests/auto/sql/kernel/qsqlquery/tst_qsqlquery.cpp

Change-Id: I6b82507bf9a80a374c40393e72f4843f1557de89
This commit is contained in:
Qt Forward Merge Bot 2019-12-11 01:00:10 +01:00 committed by Edward Welbourne
commit a4a7c1bcf7
101 changed files with 1232 additions and 505 deletions

View File

@ -29,16 +29,18 @@
\example widgets/shapedclock
\title Shaped Clock Example
\ingroup examples-widgets
\brief The Shaped Clock example shows how to apply a widget mask to a top-level
widget to produce a shaped window.
\brief The Shaped Clock example shows how to apply a translucent background
and a widget mask to a top-level widget to produce a shaped window.
\borderedimage shapedclock-example.png
Widget masks are used to customize the shapes of top-level widgets by restricting
the available area for painting. On some window systems, setting certain window flags
will cause the window decoration (title bar, window frame, buttons) to be disabled,
allowing specially-shaped windows to be created. In this example, we use this feature
to create a circular window containing an analog clock.
Widget masks are used to customize the shapes of top-level widgets by
restricting the area available for painting and mouse input. Using a
translucent background facilitates partially transparent windows and smooth
edges. On most window systems, setting certain window flags will cause the
window decoration (title bar, window frame, buttons) to be disabled,
allowing specially-shaped windows to be created. In this example, we use
this feature to create a circular window containing an analog clock.
Since this example's window does not provide a \uicontrol File menu or a close
button, we provide a context menu with an \uicontrol Exit entry so that the example
@ -52,8 +54,10 @@
\snippet widgets/shapedclock/shapedclock.h 0
The \l{QWidget::paintEvent()}{paintEvent()} implementation is the same as that found
in the \c AnalogClock class. We implement \l{QWidget::sizeHint()}{sizeHint()}
The \l{QWidget::paintEvent()}{paintEvent()} implementation is the same as
that found in the \c AnalogClock class, with one important exception: we
now must also draw background (the clock face) ourselves, since the widget
background is just transparent. We implement \l{QWidget::sizeHint()}{sizeHint()}
so that we don't have to resize the widget explicitly. We also provide an event
handler for resize events. This allows us to update the mask if the clock is resized.
@ -70,9 +74,11 @@
\snippet widgets/shapedclock/shapedclock.cpp 0
We inform the window manager that the widget is not to be decorated with a window
frame by setting the Qt::FramelessWindowHint flag on the widget. As a result, we need
to provide a way for the user to move the clock around the screen.
We request a transparent window by setting the Qt::WA_TranslucentBackground
widget attribute. We inform the window manager that the widget is not to be
decorated with a window frame by setting the Qt::FramelessWindowHint flag
on the widget. As a result, we need to provide a way for the user to move
the clock around the screen.
Mouse button events are delivered to the \c mousePressEvent() handler:
@ -94,14 +100,20 @@
widget is moved to the point given by subtracting the \c dragPosition from the current
cursor position in global coordinates. If we drag the widget, we also accept the event.
The \c paintEvent() function is given for completeness. See the
\l{Analog Clock Example}{Analog Clock} example for a description of the process used
to render the clock.
The \c paintEvent() function is mainly the same as described in the
\l{Analog Clock Example}{Analog Clock} example. The one addition is that we
use QPainter::drawEllipse() to draw a round clock face with the current
palette's default background color. We make the clock face a bit smaller
than the widget mask, so that the anti-aliased, semi-transparent pixels on
the edge are not clipped away by the widget mask. This gives the shaped
window smooth edges on the screen.
\snippet widgets/shapedclock/shapedclock.cpp 3
In the \c resizeEvent() handler, we re-use some of the code from the \c paintEvent()
to determine the region of the widget that is visible to the user:
In the \c resizeEvent() handler, we re-use some of the code from the \c
paintEvent() to determine the region of the widget that is visible to the
user. This tells the system the area where mouse clicks should go to us,
and not to whatever window is behind us:
\snippet widgets/shapedclock/shapedclock.cpp 4
@ -121,6 +133,12 @@
\section1 Notes on Widget Masks
Widget masks are used to hint to the window system that the application
does not want mouse events for areas outside the mask. On most systems,
they also result in coarse visual clipping. To get smooth window edges, one
should use translucent background and anti-aliased painting, as shown in
this example.
Since QRegion allows arbitrarily complex regions to be created, widget masks can be
made to suit the most unconventionally-shaped windows, and even allow widgets to be
displayed with holes in them.

View File

@ -61,6 +61,7 @@
ShapedClock::ShapedClock(QWidget *parent)
: QWidget(parent, Qt::FramelessWindowHint | Qt::WindowSystemMenuHint)
{
setAttribute(Qt::WA_TranslucentBackground);
QTimer *timer = new QTimer(this);
connect(timer, &QTimer::timeout, this, QOverload<>::of(&ShapedClock::update));
timer->start(1000);
@ -122,6 +123,10 @@ void ShapedClock::paintEvent(QPaintEvent *)
painter.translate(width() / 2, height() / 2);
painter.scale(side / 200.0, side / 200.0);
painter.setPen(Qt::NoPen);
painter.setBrush(palette().window());
painter.drawEllipse(QPoint(0, 0), 98, 98);
painter.setPen(Qt::NoPen);
painter.setBrush(hourColor);
@ -168,6 +173,6 @@ void ShapedClock::resizeEvent(QResizeEvent * /* event */)
//! [5]
QSize ShapedClock::sizeHint() const
{
return QSize(100, 100);
return QSize(200, 200);
}
//! [5]

View File

@ -71,7 +71,7 @@ contains(TEMPLATE, .*app) {
# replacing the app name placeholder with the actual app name.
apphtml.name = application main html file
apphtml.output = $$DESTDIR/$$TARGET_HTML
apphtml.commands = sed -e s/@APPNAME@/$$TARGET_BASE/g $$WASM_PLUGIN_PATH/wasm_shell.html > $$DESTDIR/$$TARGET_HTML
apphtml.commands = $$QMAKE_STREAM_EDITOR -e s/@APPNAME@/$$TARGET_BASE/g $$WASM_PLUGIN_PATH/wasm_shell.html > $$DESTDIR/$$TARGET_HTML
apphtml.input = $$WASM_PLUGIN_PATH/wasm_shell.html
apphtml.depends = $$apphtml.input
QMAKE_EXTRA_COMPILERS += apphtml

View File

@ -25,7 +25,7 @@ EMTERP_FLAGS = \
-s ASSERTIONS=1 \
--profiling-funcs
EMCC_COMMON_LFLAGS = \
EMCC_COMMON_LFLAGS += \
-s WASM=1 \
-s FULL_ES2=1 \
-s FULL_ES3=1 \

View File

@ -154,7 +154,7 @@ static int doSed(int argc, char **argv)
FILE *f;
if (!strcmp(inFile, "-")) {
f = stdin;
} else if (!(f = fopen(inFile, "r"))) {
} else if (!(f = fopen(inFile, "rb"))) {
perror(inFile);
return 1;
}

View File

@ -492,6 +492,39 @@
# error "Qt has not been tested with this compiler - see http://www.qt-project.org/"
#endif
/*
* SG10's SD-6 feature detection and some useful extensions from Clang and GCC
* https://isocpp.org/std/standing-documents/sd-6-sg10-feature-test-recommendations
* http://clang.llvm.org/docs/LanguageExtensions.html#feature-checking-macros
* Not using wrapper macros, per http://eel.is/c++draft/cpp.cond#7.sentence-2
*/
#ifndef __has_builtin
# define __has_builtin(x) 0
#endif
#ifndef __has_feature
# define __has_feature(x) 0
#endif
#ifndef __has_attribute
# define __has_attribute(x) 0
#endif
#ifndef __has_cpp_attribute
# define __has_cpp_attribute(x) 0
#endif
#ifndef __has_include
# define __has_include(x) 0
#endif
#ifndef __has_include_next
# define __has_include_next(x) 0
#endif
// Kept around until all submodules have transitioned
#define QT_HAS_BUILTIN(x) __has_builtin(x)
#define QT_HAS_FEATURE(x) __has_feature(x)
#define QT_HAS_ATTRIBUTE(x) __has_attribute(x)
#define QT_HAS_CPP_ATTRIBUTE(x) __has_cpp_attribute(x)
#define QT_HAS_INCLUDE(x) __has_include(x)
#define QT_HAS_INCLUDE_NEXT(x) __has_include_next(x)
/*
* C++11 support
*
@ -1018,37 +1051,6 @@
# endif
#endif
/*
* SG10's SD-6 feature detection and some useful extensions from Clang and GCC
* https://isocpp.org/std/standing-documents/sd-6-sg10-feature-test-recommendations
* http://clang.llvm.org/docs/LanguageExtensions.html#feature-checking-macros
*/
#ifdef __has_builtin
# define QT_HAS_BUILTIN(x) __has_builtin(x)
#else
# define QT_HAS_BUILTIN(x) 0
#endif
#ifdef __has_attribute
# define QT_HAS_ATTRIBUTE(x) __has_attribute(x)
#else
# define QT_HAS_ATTRIBUTE(x) 0
#endif
#ifdef __has_cpp_attribute
# define QT_HAS_CPP_ATTRIBUTE(x) __has_cpp_attribute(x)
#else
# define QT_HAS_CPP_ATTRIBUTE(x) 0
#endif
#ifdef __has_include
# define QT_HAS_INCLUDE(x) __has_include(x)
#else
# define QT_HAS_INCLUDE(x) 0
#endif
#ifdef __has_include_next
# define QT_HAS_INCLUDE_NEXT(x) __has_include_next(x)
#else
# define QT_HAS_INCLUDE_NEXT(x) 0
#endif
/*
* C++11 keywords and expressions
*/
@ -1123,7 +1125,7 @@
# define Q_DECL_ALIGN(n) alignas(n)
#endif
#if QT_HAS_CPP_ATTRIBUTE(nodiscard) && !defined(Q_CC_CLANG) // P0188R1
#if __has_cpp_attribute(nodiscard) && !defined(Q_CC_CLANG) // P0188R1
// Can't use [[nodiscard]] with Clang, see https://bugs.llvm.org/show_bug.cgi?id=33518
# undef Q_REQUIRED_RESULT
# define Q_REQUIRED_RESULT [[nodiscard]]
@ -1225,11 +1227,6 @@
#ifndef QT_MAKE_CHECKED_ARRAY_ITERATOR
# define QT_MAKE_CHECKED_ARRAY_ITERATOR(x, N) (x)
#endif
#ifdef __has_feature
# define QT_HAS_FEATURE(x) __has_feature(x)
#else
# define QT_HAS_FEATURE(x) 0
#endif
/*
* Warning/diagnostic handling
@ -1320,11 +1317,11 @@
} while (false)
#if defined(__cplusplus)
#if QT_HAS_CPP_ATTRIBUTE(clang::fallthrough)
#if __has_cpp_attribute(clang::fallthrough)
# define Q_FALLTHROUGH() [[clang::fallthrough]]
#elif QT_HAS_CPP_ATTRIBUTE(gnu::fallthrough)
#elif __has_cpp_attribute(gnu::fallthrough)
# define Q_FALLTHROUGH() [[gnu::fallthrough]]
#elif QT_HAS_CPP_ATTRIBUTE(fallthrough)
#elif __has_cpp_attribute(fallthrough)
# define Q_FALLTHROUGH() [[fallthrough]]
#endif
#endif

View File

@ -77,13 +77,13 @@
#define QT_FEATURE_binaryjson -1
#define QT_FEATURE_cborstream -1
#define QT_CRYPTOGRAPHICHASH_ONLY_SHA1
#define QT_FEATURE_cxx11_random (QT_HAS_INCLUDE(<random>) ? 1 : -1)
#define QT_FEATURE_cxx11_random (__has_include(<random>) ? 1 : -1)
#define QT_NO_DATASTREAM
#define QT_FEATURE_datestring 1
#define QT_FEATURE_datetimeparser -1
#define QT_FEATURE_easingcurve -1
#define QT_FEATURE_etw -1
#define QT_FEATURE_getauxval (QT_HAS_INCLUDE(<sys/auxv.h>) ? 1 : -1)
#define QT_FEATURE_getauxval (__has_include(<sys/auxv.h>) ? 1 : -1)
#define QT_FEATURE_getentropy -1
#define QT_NO_GEOM_VARIANT
#define QT_FEATURE_hijricalendar -1

View File

@ -66,7 +66,7 @@ template <typename T> Q_ALWAYS_INLINE void qToUnaligned(const T src, void *dest)
// Using sizeof(T) inside memcpy function produces internal compiler error with
// MSVC2008/ARM in tst_endian -> use extra indirection to resolve size of T.
const size_t size = sizeof(T);
#if QT_HAS_BUILTIN(__builtin_memcpy)
#if __has_builtin(__builtin_memcpy)
__builtin_memcpy
#else
memcpy
@ -78,7 +78,7 @@ template <typename T> Q_ALWAYS_INLINE T qFromUnaligned(const void *src)
{
T dest;
const size_t size = sizeof(T);
#if QT_HAS_BUILTIN(__builtin_memcpy)
#if __has_builtin(__builtin_memcpy)
__builtin_memcpy
#else
memcpy

View File

@ -92,7 +92,7 @@
# include <sys/systeminfo.h>
#endif
#if defined(Q_OS_DARWIN) && QT_HAS_INCLUDE(<IOKit/IOKitLib.h>)
#if defined(Q_OS_DARWIN) && __has_include(<IOKit/IOKitLib.h>)
# include <IOKit/IOKitLib.h>
# include <private/qcore_mac_p.h>
#endif
@ -3067,7 +3067,7 @@ enum {
*/
QByteArray QSysInfo::machineUniqueId()
{
#if defined(Q_OS_DARWIN) && QT_HAS_INCLUDE(<IOKit/IOKitLib.h>)
#if defined(Q_OS_DARWIN) && __has_include(<IOKit/IOKitLib.h>)
char uuid[UuidStringLen + 1];
io_service_t service = IOServiceGetMatchingService(kIOMasterPortDefault, IOServiceMatching("IOPlatformExpertDevice"));
QCFString stringRef = (CFStringRef)IORegistryEntryCreateCFProperty(service, CFSTR(kIOPlatformUUIDKey), kCFAllocatorDefault, 0);

View File

@ -717,7 +717,7 @@ inline void qt_noop(void) {}
#if !defined(QT_NO_EXCEPTIONS)
# if !defined(Q_MOC_RUN)
# if (defined(Q_CC_CLANG) && !defined(Q_CC_INTEL) && !QT_HAS_FEATURE(cxx_exceptions)) || \
# if (defined(Q_CC_CLANG) && !defined(Q_CC_INTEL) && !__has_feature(cxx_exceptions)) || \
(defined(Q_CC_GNU) && !defined(__EXCEPTIONS))
# define QT_NO_EXCEPTIONS
# endif

View File

@ -74,7 +74,7 @@ Q_CORE_EXPORT time_t qMkTime(struct tm *when);
QT_END_NAMESPACE
#if !QT_HAS_BUILTIN(__builtin_available)
#if !__has_builtin(__builtin_available)
#include <initializer_list>
#include <QtCore/qoperatingsystemversion.h>
#include <QtCore/qversionnumber.h>
@ -142,7 +142,7 @@ QT_END_NAMESPACE
QT_BUILTIN_AVAILABLE1, \
QT_BUILTIN_AVAILABLE0, )
#define __builtin_available(...) QT_BUILTIN_AVAILABLE_CHOOSER(__VA_ARGS__)(__VA_ARGS__)
#endif // !QT_HAS_BUILTIN(__builtin_available)
#endif // !__has_builtin(__builtin_available)
#endif // defined(__cplusplus)
#endif // QGLOBAL_P_H

View File

@ -70,7 +70,7 @@
#if QT_CONFIG(slog2)
#include <sys/slog2.h>
#endif
#if QT_HAS_INCLUDE(<paths.h>)
#if __has_include(<paths.h>)
#include <paths.h>
#endif
@ -106,7 +106,7 @@
# if __UCLIBC_HAS_BACKTRACE__
# define QLOGGING_HAVE_BACKTRACE
# endif
# elif (defined(__GLIBC__) && defined(__GLIBCXX__)) || (QT_HAS_INCLUDE(<cxxabi.h>) && QT_HAS_INCLUDE(<execinfo.h>))
# elif (defined(__GLIBC__) && defined(__GLIBCXX__)) || (__has_include(<cxxabi.h>) && __has_include(<execinfo.h>))
# define QLOGGING_HAVE_BACKTRACE
# endif
#endif
@ -116,7 +116,7 @@ extern char *__progname;
#endif
#ifndef QT_BOOTSTRAPPED
#if defined(Q_OS_LINUX) && (defined(__GLIBC__) || QT_HAS_INCLUDE(<sys/syscall.h>))
#if defined(Q_OS_LINUX) && (defined(__GLIBC__) || __has_include(<sys/syscall.h>))
# include <sys/syscall.h>
# if defined(Q_OS_ANDROID) && !defined(SYS_gettid)
@ -1276,7 +1276,7 @@ void QMessagePattern::setPattern(const QString &pattern)
#if defined(QLOGGING_HAVE_BACKTRACE) && !defined(QT_BOOTSTRAPPED)
// make sure the function has "Message" in the name so the function is removed
#if ((defined(Q_CC_GNU) && defined(QT_COMPILER_SUPPORTS_SIMD_ALWAYS)) || QT_HAS_ATTRIBUTE(optimize)) \
#if ((defined(Q_CC_GNU) && defined(QT_COMPILER_SUPPORTS_SIMD_ALWAYS)) || __has_attribute(optimize)) \
&& !defined(Q_CC_INTEL) && !defined(Q_CC_CLANG)
// force skipping the frame pointer, to save the backtrace() function some work
__attribute__((optimize("omit-frame-pointer")))

View File

@ -253,7 +253,7 @@ QT_WARNING_POP
// size_t. Implementations for 8- and 16-bit types will work but may not be as
// efficient. Implementations for 64-bit may be missing on 32-bit platforms.
#if (defined(Q_CC_GNU) && (Q_CC_GNU >= 500) || (defined(Q_CC_INTEL) && !defined(Q_OS_WIN))) || QT_HAS_BUILTIN(__builtin_add_overflow)
#if (defined(Q_CC_GNU) && (Q_CC_GNU >= 500) || (defined(Q_CC_INTEL) && !defined(Q_OS_WIN))) || __has_builtin(__builtin_add_overflow)
// GCC 5, ICC 18, and Clang 3.8 have builtins to detect overflows
template <typename T> inline

View File

@ -55,7 +55,7 @@
#include <stdio.h>
#include <errno.h>
#if QT_HAS_INCLUDE(<paths.h>)
#if __has_include(<paths.h>)
# include <paths.h>
#endif
#ifndef _PATH_TMP // from <paths.h>

View File

@ -100,7 +100,7 @@ QT_END_NAMESPACE
#include <private/qcore_unix_p.h>
#endif
#if QT_HAS_INCLUDE(<paths.h>)
#if __has_include(<paths.h>)
#include <paths.h>
#endif

View File

@ -48,7 +48,7 @@
#include <qcoreapplication.h>
#endif
#if QT_HAS_INCLUDE(<paths.h>)
#if __has_include(<paths.h>)
#include <paths.h>
#endif

View File

@ -108,7 +108,7 @@
# endif // QT_LARGEFILE_SUPPORT
#endif // Q_OS_BSD4
#if QT_HAS_INCLUDE(<paths.h>)
#if __has_include(<paths.h>)
# include <paths.h>
#endif
#ifndef _PATH_MOUNTED

View File

@ -52,7 +52,7 @@
#include <limits>
#if QT_HAS_INCLUDE(<chrono>)
#if __has_include(<chrono>)
# include <chrono>
#endif
@ -120,7 +120,7 @@ public:
QDeadlineTimer &operator-=(qint64 msecs)
{ *this = *this + (-msecs); return *this; }
#if QT_HAS_INCLUDE(<chrono>) || defined(Q_CLANG_QDOC)
#if __has_include(<chrono>) || defined(Q_CLANG_QDOC)
template <class Clock, class Duration>
QDeadlineTimer(std::chrono::time_point<Clock, Duration> deadline_,
Qt::TimerType type_ = Qt::CoarseTimer) : t2(0)

View File

@ -55,7 +55,7 @@
#include <QtCore/qobject_impl.h>
#if QT_HAS_INCLUDE(<chrono>)
#if __has_include(<chrono>)
# include <chrono>
#endif
@ -154,7 +154,7 @@ public:
void moveToThread(QThread *thread);
int startTimer(int interval, Qt::TimerType timerType = Qt::CoarseTimer);
#if QT_HAS_INCLUDE(<chrono>)
#if __has_include(<chrono>)
Q_ALWAYS_INLINE
int startTimer(std::chrono::milliseconds time, Qt::TimerType timerType = Qt::CoarseTimer)
{

View File

@ -47,7 +47,7 @@
#include <QtCore/qbasictimer.h> // conceptual inheritance
#include <QtCore/qobject.h>
#if QT_HAS_INCLUDE(<chrono>)
#if __has_include(<chrono>)
# include <chrono>
#endif
@ -177,7 +177,7 @@ Q_SIGNALS:
void timeout(QPrivateSignal);
public:
#if QT_HAS_INCLUDE(<chrono>) || defined(Q_QDOC)
#if __has_include(<chrono>) || defined(Q_QDOC)
void setInterval(std::chrono::milliseconds value)
{
setInterval(int(value.count()));
@ -223,7 +223,7 @@ private:
static void singleShotImpl(int msec, Qt::TimerType timerType,
const QObject *receiver, QtPrivate::QSlotObjectBase *slotObj);
#if QT_HAS_INCLUDE(<chrono>)
#if __has_include(<chrono>)
static Qt::TimerType defaultTypeFor(std::chrono::milliseconds interval)
{ return defaultTypeFor(int(interval.count())); }

View File

@ -53,7 +53,7 @@
#include <QtCore/qbytearraylist.h>
#endif
#if QT_HAS_INCLUDE(<variant>) && __cplusplus >= 201703L
#if __has_include(<variant>) && __cplusplus >= 201703L
#include <variant>
#elif defined(Q_CLANG_QDOC)
namespace std { template<typename...> struct variant; }
@ -372,7 +372,7 @@ class Q_CORE_EXPORT QVariant
static inline QVariant fromValue(const T &value)
{ return QVariant(qMetaTypeId<T>(), &value, QTypeInfo<T>::isPointer); }
#if (QT_HAS_INCLUDE(<variant>) && __cplusplus >= 201703L) || defined(Q_CLANG_QDOC)
#if (__has_include(<variant>) && __cplusplus >= 201703L) || defined(Q_CLANG_QDOC)
template<typename... Types>
static inline QVariant fromStdVariant(const std::variant<Types...> &value)
{
@ -538,7 +538,7 @@ inline QVariant QVariant::fromValue(const QVariant &value)
return value;
}
#if QT_HAS_INCLUDE(<variant>) && __cplusplus >= 201703L
#if __has_include(<variant>) && __cplusplus >= 201703L
template<>
inline QVariant QVariant::fromValue(const std::monostate &)
{

View File

@ -214,7 +214,7 @@ public:
bool contains(const QCborValue &value) const;
int compare(const QCborArray &other) const noexcept Q_DECL_PURE_FUNCTION;
#if 0 && QT_HAS_INCLUDE(<compare>)
#if 0 && __has_include(<compare>)
std::strong_ordering operator<=>(const QCborArray &other) const
{
int c = compare(other);

View File

@ -245,7 +245,7 @@ public:
{ const_iterator it = find(key); return it != end(); }
int compare(const QCborMap &other) const noexcept Q_DECL_PURE_FUNCTION;
#if 0 && QT_HAS_INCLUDE(<compare>)
#if 0 && __has_include(<compare>)
std::strong_ordering operator<=>(const QCborMap &other) const
{
int c = compare(other);

View File

@ -59,7 +59,7 @@
# undef False
#endif
#if 0 && QT_HAS_INCLUDE(<compare>)
#if 0 && __has_include(<compare>)
# include <compare>
#endif
@ -265,7 +265,7 @@ public:
QCborValueRef operator[](const QString & key);
int compare(const QCborValue &other) const;
#if 0 && QT_HAS_INCLUDE(<compare>)
#if 0 && __has_include(<compare>)
std::strong_ordering operator<=>(const QCborValue &other) const
{
int c = compare(other);
@ -421,7 +421,7 @@ public:
int compare(const QCborValue &other) const
{ return concrete().compare(other); }
#if 0 && QT_HAS_INCLUDE(<compare>)
#if 0 && __has_include(<compare>)
std::strong_ordering operator<=>(const QCborValue &other) const
{
int c = compare(other);

View File

@ -196,8 +196,7 @@ public:
if (value.container)
return replaceAt_complex(e, value, disp);
e.value = value.value_helper();
e.type = value.type();
e = { value.value_helper(), value.type() };
if (value.isContainer())
e.container = nullptr;
}

View File

@ -334,7 +334,7 @@ int qstricmp(const char *str1, const char *str2)
return int(Incomplete);
};
#if defined(__SSE4_1__) && !(defined(__SANITIZE_ADDRESS__) || QT_HAS_FEATURE(address_sanitizer))
#if defined(__SSE4_1__) && !(defined(__SANITIZE_ADDRESS__) || __has_feature(address_sanitizer))
enum { PageSize = 4096, PageMask = PageSize - 1 };
const __m128i zero = _mm_setzero_si128();
forever {

View File

@ -243,7 +243,7 @@ public:
void chop(int n);
#if defined(Q_COMPILER_REF_QUALIFIERS) && !defined(QT_COMPILING_QSTRING_COMPAT_CPP) && !defined(Q_CLANG_QDOC)
# if defined(Q_CC_GNU) && !defined(Q_CC_CLANG) && !defined(Q_CC_INTEL) && !QT_HAS_CPP_ATTRIBUTE(nodiscard)
# if defined(Q_CC_GNU) && !defined(Q_CC_CLANG) && !defined(Q_CC_INTEL) && !__has_cpp_attribute(nodiscard)
// required due to https://gcc.gnu.org/bugzilla/show_bug.cgi?id=61941
# pragma push_macro("Q_REQUIRED_RESULT")
# undef Q_REQUIRED_RESULT

View File

@ -146,6 +146,9 @@ qsizetype qFindStringBoyerMoore(QStringView haystack, qsizetype from, QStringVie
static inline qsizetype qFindChar(QStringView str, QChar ch, qsizetype from, Qt::CaseSensitivity cs) noexcept;
template <typename Haystack>
static inline qsizetype qLastIndexOf(Haystack haystack, QChar needle, qsizetype from, Qt::CaseSensitivity cs) noexcept;
template <>
inline qsizetype qLastIndexOf(QString haystack, QChar needle,
qsizetype from, Qt::CaseSensitivity cs) noexcept = delete; // unwanted, would detach
static inline qsizetype qt_string_count(QStringView haystack, QStringView needle, Qt::CaseSensitivity cs);
static inline qsizetype qt_string_count(QStringView haystack, QChar needle, Qt::CaseSensitivity cs);
@ -3813,7 +3816,7 @@ int QString::indexOf(const QStringRef &str, int from, Qt::CaseSensitivity cs) co
int QString::lastIndexOf(const QString &str, int from, Qt::CaseSensitivity cs) const
{
// ### Qt6: qsizetype
return int(QtPrivate::lastIndexOf(*this, from, str, cs));
return int(QtPrivate::lastIndexOf(QStringView(*this), from, str, cs));
}
#endif // QT_STRINGVIEW_LEVEL < 2
@ -3852,7 +3855,7 @@ int QString::lastIndexOf(QLatin1String str, int from, Qt::CaseSensitivity cs) co
int QString::lastIndexOf(QChar ch, int from, Qt::CaseSensitivity cs) const
{
// ### Qt6: qsizetype
return int(qLastIndexOf(*this, ch, from, cs));
return int(qLastIndexOf(QStringView(*this), ch, from, cs));
}
#if QT_STRINGVIEW_LEVEL < 2

View File

@ -485,7 +485,7 @@ public:
Q_REQUIRED_RESULT QString rightJustified(int width, QChar fill = QLatin1Char(' '), bool trunc = false) const;
#if defined(Q_COMPILER_REF_QUALIFIERS) && !defined(QT_COMPILING_QSTRING_COMPAT_CPP) && !defined(Q_CLANG_QDOC)
# if defined(Q_CC_GNU) && !defined(Q_CC_CLANG) && !defined(Q_CC_INTEL) && !QT_HAS_CPP_ATTRIBUTE(nodiscard)
# if defined(Q_CC_GNU) && !defined(Q_CC_CLANG) && !defined(Q_CC_INTEL) && !__has_cpp_attribute(nodiscard)
// required due to https://gcc.gnu.org/bugzilla/show_bug.cgi?id=61941
# pragma push_macro("Q_REQUIRED_RESULT")
# undef Q_REQUIRED_RESULT

View File

@ -81,7 +81,7 @@ QT_END_NAMESPACE
// if not defined in linux/futex.h
# define FUTEX_PRIVATE_FLAG 128 // added in v2.6.22
# if QT_HAS_FEATURE(thread_sanitizer) || defined(__SANITIZE_THREAD__)
# if __has_feature(thread_sanitizer) || defined(__SANITIZE_THREAD__)
# include <sanitizer/tsan_interface.h>
inline void _q_tsan_acquire(void *addr, void *addr2)
{
@ -98,7 +98,7 @@ inline void _q_tsan_release(void *addr, void *addr2)
# else
inline void _q_tsan_acquire(void *, void *) {}
inline void _q_tsan_release(void *, void *) {}
# endif // QT_HAS_FEATURE(thread_sanitizer) || defined(__SANITIZE_THREAD__)
# endif // __has_feature(thread_sanitizer) || defined(__SANITIZE_THREAD__)
QT_BEGIN_NAMESPACE
namespace QtLinuxFutex {

View File

@ -44,7 +44,7 @@
#include <QtCore/qatomic.h>
#include <new>
#if QT_HAS_INCLUDE(<chrono>)
#if __has_include(<chrono>)
# include <chrono>
# include <limits>
#endif
@ -147,7 +147,7 @@ public:
// Lockable concept
bool try_lock() QT_MUTEX_LOCK_NOEXCEPT { return tryLock(); }
#if QT_HAS_INCLUDE(<chrono>) || defined(Q_CLANG_QDOC)
#if __has_include(<chrono>) || defined(Q_CLANG_QDOC)
// TimedLockable concept
template <class Rep, class Period>
bool try_lock_for(std::chrono::duration<Rep, Period> duration)
@ -175,7 +175,7 @@ private:
friend class QRecursiveMutex;
friend class ::tst_QMutex;
#if QT_HAS_INCLUDE(<chrono>)
#if __has_include(<chrono>)
template<class Rep, class Period>
static int convertToMilliseconds(std::chrono::duration<Rep, Period> duration)
{
@ -213,7 +213,7 @@ public:
using QMutex::tryLock;
using QMutex::unlock;
using QMutex::try_lock;
#if QT_HAS_INCLUDE(<chrono>)
#if __has_include(<chrono>)
using QMutex::try_lock_for;
using QMutex::try_lock_until;
#endif
@ -295,7 +295,7 @@ public:
inline void unlock() noexcept {}
inline bool isRecursive() const noexcept { return true; }
#if QT_HAS_INCLUDE(<chrono>)
#if __has_include(<chrono>)
template <class Rep, class Period>
inline bool try_lock_for(std::chrono::duration<Rep, Period> duration) noexcept
{

View File

@ -127,7 +127,7 @@ static const char qt_shortMonthNames[][4] = {
"Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
};
static int qt_monthNumberFromShortName(QStringRef shortName)
static int qt_monthNumberFromShortName(QStringView shortName)
{
for (unsigned int i = 0; i < sizeof(qt_shortMonthNames) / sizeof(qt_shortMonthNames[0]); ++i) {
if (shortName == QLatin1String(qt_shortMonthNames[i], 3))
@ -136,9 +136,9 @@ static int qt_monthNumberFromShortName(QStringRef shortName)
return -1;
}
static int qt_monthNumberFromShortName(const QString &shortName)
{ return qt_monthNumberFromShortName(QStringRef(&shortName)); }
{ return qt_monthNumberFromShortName(QStringView(shortName)); }
static int fromShortMonthName(const QStringRef &monthName, int year)
static int fromShortMonthName(QStringView monthName, int year)
{
// Assume that English monthnames are the default
int month = qt_monthNumberFromShortName(monthName);
@ -207,7 +207,7 @@ static QString toOffsetString(Qt::DateFormat format, int offset)
#if QT_CONFIG(datestring)
// Parse offset in [+-]HH[[:]mm] format
static int fromOffsetString(const QStringRef &offsetString, bool *valid) noexcept
static int fromOffsetString(QStringView offsetString, bool *valid) noexcept
{
*valid = false;
@ -228,22 +228,23 @@ static int fromOffsetString(const QStringRef &offsetString, bool *valid) noexcep
return 0;
// Split the hour and minute parts
const QStringRef time = offsetString.mid(1);
int hhLen = time.indexOf(QLatin1Char(':'));
int mmIndex;
const QStringView time = offsetString.mid(1);
qsizetype hhLen = time.indexOf(QLatin1Char(':'));
qsizetype mmIndex;
if (hhLen == -1)
mmIndex = hhLen = 2; // [+-]HHmm or [+-]HH format
else
mmIndex = hhLen + 1;
const QStringRef hhRef = time.left(hhLen);
const QLocale C = QLocale::c();
const QStringView hhRef = time.left(qMin(hhLen, time.size()));
bool ok = false;
const int hour = hhRef.toInt(&ok);
const int hour = C.toInt(hhRef, &ok);
if (!ok)
return 0;
const QStringRef mmRef = time.mid(mmIndex);
const int minute = mmRef.isEmpty() ? 0 : mmRef.toInt(&ok);
const QStringView mmRef = time.mid(qMin(mmIndex, time.size()));
const int minute = mmRef.isEmpty() ? 0 : C.toInt(mmRef, &ok);
if (!ok || minute < 0 || minute > 59)
return 0;
@ -2324,7 +2325,7 @@ int QTime::msecsTo(const QTime &t) const
#if QT_CONFIG(datestring)
static QTime fromIsoTimeString(const QStringRef &string, Qt::DateFormat format, bool *isMidnight24)
static QTime fromIsoTimeString(QStringView string, Qt::DateFormat format, bool *isMidnight24)
{
if (isMidnight24)
*isMidnight24 = false;
@ -2333,11 +2334,12 @@ static QTime fromIsoTimeString(const QStringRef &string, Qt::DateFormat format,
if (size < 5)
return QTime();
const QLocale C(QLocale::c());
bool ok = false;
int hour = string.mid(0, 2).toInt(&ok);
int hour = C.toInt(string.mid(0, 2), &ok);
if (!ok)
return QTime();
const int minute = string.mid(3, 2).toInt(&ok);
const int minute = C.toInt(string.mid(3, 2), &ok);
if (!ok)
return QTime();
int second = 0;
@ -2358,11 +2360,11 @@ static QTime fromIsoTimeString(const QStringRef &string, Qt::DateFormat format,
// seconds is 4. E.g. 12:34,99999 will expand to 12:34:59.9994. The milliseconds
// will then be rounded up AND clamped to 999.
const QStringRef minuteFractionStr = string.mid(6, 5);
const long minuteFractionInt = minuteFractionStr.toLong(&ok);
const QStringView minuteFractionStr = string.mid(6, qMin(qsizetype(5), string.size() - 6));
const long minuteFractionInt = C.toLong(minuteFractionStr, &ok);
if (!ok)
return QTime();
const float minuteFraction = double(minuteFractionInt) / (std::pow(double(10), minuteFractionStr.count()));
const float minuteFraction = double(minuteFractionInt) / (std::pow(double(10), minuteFractionStr.size()));
const float secondWithMs = minuteFraction * 60;
const float secondNoMs = std::floor(secondWithMs);
@ -2371,15 +2373,20 @@ static QTime fromIsoTimeString(const QStringRef &string, Qt::DateFormat format,
msec = qMin(qRound(secondFraction * 1000.0), 999);
} else {
// HH:mm:ss or HH:mm:ss.zzz
second = string.mid(6, 2).toInt(&ok);
second = C.toInt(string.mid(6, qMin(qsizetype(2), string.size() - 6)), &ok);
if (!ok)
return QTime();
if (size > 8 && (string.at(8) == QLatin1Char(',') || string.at(8) == QLatin1Char('.'))) {
const QStringRef msecStr(string.mid(9, 4));
int msecInt = msecStr.isEmpty() ? 0 : msecStr.toInt(&ok);
QStringView msecStr(string.mid(9, qMin(qsizetype(4), string.size() - 9)));
// toInt() ignores leading spaces, so catch them before calling it
if (!msecStr.isEmpty() && !msecStr.at(0).isDigit())
return QTime();
// We do, however, want to ignore *trailing* spaces.
msecStr = msecStr.trimmed();
int msecInt = msecStr.isEmpty() ? 0 : C.toInt(msecStr, &ok);
if (!ok)
return QTime();
const double secondFraction(msecInt / (std::pow(double(10), msecStr.count())));
const double secondFraction(msecInt / (std::pow(double(10), msecStr.size())));
msec = qMin(qRound(secondFraction * 1000.0), 999);
}
}
@ -2428,7 +2435,7 @@ QTime QTime::fromString(const QString &string, Qt::DateFormat format)
case Qt::ISODateWithMs:
case Qt::TextDate:
default:
return fromIsoTimeString(QStringRef(&string), format, nullptr);
return fromIsoTimeString(QStringView(string), format, nullptr);
}
}
@ -3410,6 +3417,7 @@ inline qint64 QDateTimePrivate::zoneMSecsToEpochMSecs(qint64 zoneMSecs, const QT
DaylightStatus hint,
QDate *zoneDate, QTime *zoneTime)
{
Q_ASSERT(zone.isValid());
// Get the effective data from QTimeZone
QTimeZonePrivate::Data data = zone.d->dataForLocalTime(zoneMSecs, int(hint));
// Docs state any time before 1970-01-01 will *not* have any DST applied
@ -3799,8 +3807,9 @@ QTimeZone QDateTime::timeZone() const
case Qt::OffsetFromUTC:
return QTimeZone(d->m_offsetFromUtc);
case Qt::TimeZone:
Q_ASSERT(d->m_timeZone.isValid());
return d->m_timeZone;
if (d->m_timeZone.isValid())
return d->m_timeZone;
break;
case Qt::LocalTime:
return QTimeZone::systemTimeZone();
}
@ -3884,6 +3893,7 @@ QString QDateTime::timeZoneAbbreviation() const
#if !QT_CONFIG(timezone)
break;
#else
Q_ASSERT(d->m_timeZone.isValid());
return d->m_timeZone.d->abbreviation(toMSecsSinceEpoch());
#endif // timezone
case Qt::LocalTime: {
@ -3920,6 +3930,7 @@ bool QDateTime::isDaylightTime() const
#if !QT_CONFIG(timezone)
break;
#else
Q_ASSERT(d->m_timeZone.isValid());
return d->m_timeZone.d->isDaylightTime(toMSecsSinceEpoch());
#endif // timezone
case Qt::LocalTime: {
@ -4044,6 +4055,10 @@ void QDateTime::setTimeZone(const QTimeZone &toZone)
*/
qint64 QDateTime::toMSecsSinceEpoch() const
{
// Note: QDateTimeParser relies on this producing a useful result, even when
// !isValid(), at least when the invalidity is a time in a fall-back (that
// we'll have adjusted to lie outside it, but marked invalid because it's
// not what was asked for). Other things may be doing similar.
switch (getSpec(d)) {
case Qt::UTC:
return getMSecs(d);
@ -4058,12 +4073,13 @@ qint64 QDateTime::toMSecsSinceEpoch() const
}
case Qt::TimeZone:
#if !QT_CONFIG(timezone)
return 0;
#else
return QDateTimePrivate::zoneMSecsToEpochMSecs(d->m_msecs, d->m_timeZone,
extractDaylightStatus(getStatus(d)));
#if QT_CONFIG(timezone)
if (d->m_timeZone.isValid()) {
return QDateTimePrivate::zoneMSecsToEpochMSecs(d->m_msecs, d->m_timeZone,
extractDaylightStatus(getStatus(d)));
}
#endif
return 0;
}
Q_UNREACHABLE();
return 0;
@ -4158,9 +4174,11 @@ void QDateTime::setMSecsSinceEpoch(qint64 msecs)
case Qt::TimeZone:
Q_ASSERT(!d.isShort());
#if QT_CONFIG(timezone)
d.detach();
if (!d->m_timeZone.isValid())
break;
// Docs state any LocalTime before 1970-01-01 will *not* have any DST applied
// but all affected times afterwards will have DST applied.
d.detach();
if (msecs >= 0) {
status = mergeDaylightStatus(status,
d->m_timeZone.d->isDaylightTime(msecs)
@ -4433,7 +4451,7 @@ static inline void massageAdjustedDateTime(const QDateTimeData &d, QDate *date,
QDateTimePrivate::DaylightStatus status = QDateTimePrivate::UnknownDaylightTime;
localMSecsToEpochMSecs(timeToMSecs(*date, *time), &status, date, time);
#if QT_CONFIG(timezone)
} else if (spec == Qt::TimeZone) {
} else if (spec == Qt::TimeZone && d->m_timeZone.isValid()) {
QDateTimePrivate::zoneMSecsToEpochMSecs(timeToMSecs(*date, *time),
d->m_timeZone,
QDateTimePrivate::UnknownDaylightTime,
@ -5094,7 +5112,8 @@ QDateTime QDateTime::fromMSecsSinceEpoch(qint64 msecs, const QTimeZone &timeZone
{
QDateTime dt;
dt.setTimeZone(timeZone);
dt.setMSecsSinceEpoch(msecs);
if (timeZone.isValid())
dt.setMSecsSinceEpoch(msecs);
return dt;
}
@ -5197,16 +5216,17 @@ QDateTime QDateTime::fromString(const QString &string, Qt::DateFormat format)
if (!date.isValid())
return QDateTime();
if (size == 10)
return QDateTime(date);
return date.startOfDay();
Qt::TimeSpec spec = Qt::LocalTime;
QStringRef isoString(&string);
isoString = isoString.mid(10); // trim "yyyy-MM-dd"
QStringView isoString = QStringView(string).mid(10); // trim "yyyy-MM-dd"
// Must be left with T and at least one digit for the hour:
// Must be left with T (or space) and at least one digit for the hour:
if (isoString.size() < 2
|| !(isoString.startsWith(QLatin1Char('T'))
// FIXME: QSql relies on QVariant::toDateTime() accepting a space here:
|| !(isoString.startsWith(QLatin1Char('T'), Qt::CaseInsensitive)
// RFC 3339 (section 5.6) allows a space here. (It actually
// allows any separator one considers more readable, merely
// giving space as an example - but let's not go wild !)
|| isoString.startsWith(QLatin1Char(' ')))) {
return QDateTime();
}
@ -5214,7 +5234,7 @@ QDateTime QDateTime::fromString(const QString &string, Qt::DateFormat format)
int offset = 0;
// Check end of string for Time Zone definition, either Z for UTC or [+-]HH:mm for Offset
if (isoString.endsWith(QLatin1Char('Z'))) {
if (isoString.endsWith(QLatin1Char('Z'), Qt::CaseInsensitive)) {
spec = Qt::UTC;
isoString.chop(1); // trim 'Z'
} else {
@ -5345,7 +5365,7 @@ QDateTime QDateTime::fromString(const QString &string, Qt::DateFormat format)
if (parts.count() == 5)
return QDateTime(date, time, Qt::LocalTime);
QStringRef tz = parts.at(5);
QStringView tz = parts.at(5);
if (!tz.startsWith(QLatin1String("GMT"), Qt::CaseInsensitive))
return QDateTime();
tz = tz.mid(3);

View File

@ -1363,7 +1363,7 @@ QDateTimeParser::scanString(const QDateTime &defaultValue,
// given date (which might be a spring-forward, skipping an hour).
if (parserType == QVariant::DateTime && !(isSet & HourSectionMask) && !when.isValid()) {
qint64 msecs = when.toMSecsSinceEpoch();
// Fortunately, that gets a useful answer ...
// Fortunately, that gets a useful answer, even though when is invalid ...
const QDateTime replace =
#if QT_CONFIG(timezone)
tspec == Qt::TimeZone

View File

@ -381,18 +381,15 @@ QTimeZonePrivate::Data QTimeZonePrivate::dataForLocalTime(qint64 forLocalMSecs,
On the first pass, the case we consider is what hint told us to expect
(except when hint was -1 and didn't actually tell us what to expect),
so it's likely right. We only get a second pass if the first failed,
by which time the second case, that we're trying, is likely right. If
an overwhelming majority of calls have hint == -1, the Q_LIKELY here
shall be wrong half the time; otherwise, its errors shall be rarer
than that.
by which time the second case, that we're trying, is likely right.
*/
if (nextFirst ? i == 0 : i) {
Q_ASSERT(nextStart != invalidMSecs());
if (Q_LIKELY(nextStart <= nextTran.atMSecsSinceEpoch))
if (nextStart <= nextTran.atMSecsSinceEpoch)
return nextTran;
} else {
// If next is invalid, nextFirst is false, to route us here first:
if (nextStart == invalidMSecs() || Q_LIKELY(nextStart > tran.atMSecsSinceEpoch))
if (nextStart == invalidMSecs() || nextStart > tran.atMSecsSinceEpoch)
return tran;
}
}
@ -421,7 +418,7 @@ QTimeZonePrivate::Data QTimeZonePrivate::dataForLocalTime(qint64 forLocalMSecs,
int early = offsetFromUtc(recent);
int late = offsetFromUtc(imminent);
if (Q_LIKELY(early == late)) { // > 99% of the time
if (early == late) { // > 99% of the time
utcEpochMSecs = forLocalMSecs - early * 1000;
} else {
// Close to a DST transition: early > late is near a fall-back,
@ -433,7 +430,7 @@ QTimeZonePrivate::Data QTimeZonePrivate::dataForLocalTime(qint64 forLocalMSecs,
const qint64 forStd = forLocalMSecs - offsetInStd * 1000;
// Best guess at the answer:
const qint64 hinted = hint > 0 ? forDst : forStd;
if (Q_LIKELY(offsetFromUtc(hinted) == (hint > 0 ? offsetInDst : offsetInStd))) {
if (offsetFromUtc(hinted) == (hint > 0 ? offsetInDst : offsetInStd)) {
utcEpochMSecs = hinted;
} else if (hint <= 0 && offsetFromUtc(forDst) == offsetInDst) {
utcEpochMSecs = forDst;

View File

@ -535,7 +535,7 @@ QT_DEPRECATED_X("Use std::binary_search") Q_OUTOFLINE_TEMPLATE RandomAccessItera
# define QT_HAS_BUILTIN_CTZS
Q_DECL_CONSTEXPR Q_ALWAYS_INLINE uint qt_builtin_ctzs(quint16 v) noexcept
{
# if QT_HAS_BUILTIN(__builtin_ctzs)
# if __has_builtin(__builtin_ctzs)
return __builtin_ctzs(v);
# else
return __builtin_ctz(v);
@ -544,7 +544,7 @@ Q_DECL_CONSTEXPR Q_ALWAYS_INLINE uint qt_builtin_ctzs(quint16 v) noexcept
#define QT_HAS_BUILTIN_CLZS
Q_DECL_CONSTEXPR Q_ALWAYS_INLINE uint qt_builtin_clzs(quint16 v) noexcept
{
# if QT_HAS_BUILTIN(__builtin_clzs)
# if __has_builtin(__builtin_clzs)
return __builtin_clzs(v);
# else
return __builtin_clz(v) - 16U;

View File

@ -51,7 +51,7 @@ template <typename F> QScopeGuard<F> qScopeGuard(F f);
template <typename F>
class
#if QT_HAS_CPP_ATTRIBUTE(nodiscard)
#if __has_cpp_attribute(nodiscard)
// Q_REQUIRED_RESULT can be defined as __warn_unused_result__ or as [[nodiscard]]
// but the 1st one has some limitations for example can be placed only on functions.
Q_REQUIRED_RESULT
@ -91,7 +91,7 @@ private:
template <typename F>
#if QT_HAS_CPP_ATTRIBUTE(nodiscard)
#if __has_cpp_attribute(nodiscard)
Q_REQUIRED_RESULT
#endif
QScopeGuard<F> qScopeGuard(F f)

View File

@ -131,6 +131,14 @@ void QPlatformCursor::setPos(const QPoint &pos)
QWindowSystemInterface::handleMouseEvent(nullptr, pos, pos, Qt::NoButton, Qt::NoButton, QEvent::MouseMove);
}
/*!
Returns the size of the cursor, in native pixels.
*/
QSize QPlatformCursor::size() const
{
return QSize(16, 16);
}
// End of display and pointer event handling code
// Beginning of built-in cursor graphics
// from src/gui/embedded/QGraphicsSystemCursorImage_qws.cpp

View File

@ -96,6 +96,7 @@ public:
#endif // QT_NO_CURSOR
virtual QPoint pos() const;
virtual void setPos(const QPoint &pos);
virtual QSize size() const;
static Capabilities capabilities() { return m_capabilities; }
static void setCapabilities(Capabilities c) { m_capabilities = c; }

View File

@ -784,10 +784,12 @@ QDebug operator<<(QDebug dbg, const QColorSpace &colorSpace)
QDebugStateSaver saver(dbg);
dbg.nospace();
dbg << "QColorSpace(";
if (colorSpace.d_ptr->namedColorSpace)
dbg << colorSpace.d_ptr->namedColorSpace << ", ";
dbg << colorSpace.primaries() << ", " << colorSpace.transferFunction();
dbg << ", gamma=" << colorSpace.gamma();
if (colorSpace.d_ptr) {
if (colorSpace.d_ptr->namedColorSpace)
dbg << colorSpace.d_ptr->namedColorSpace << ", ";
dbg << colorSpace.primaries() << ", " << colorSpace.transferFunction();
dbg << ", gamma=" << colorSpace.gamma();
}
dbg << ')';
return dbg;
}

View File

@ -2428,7 +2428,15 @@ void QRhiGles2::bindShaderResources(QRhiGraphicsPipeline *maybeGraphicsPs, QRhiC
f->glUniformMatrix2fv(uniform.glslLocation, 1, GL_FALSE, reinterpret_cast<const float *>(src));
break;
case QShaderDescription::Mat3:
f->glUniformMatrix3fv(uniform.glslLocation, 1, GL_FALSE, reinterpret_cast<const float *>(src));
{
// 4 floats per column (or row, if row-major)
float mat[9];
const float *srcMat = reinterpret_cast<const float *>(src);
memcpy(mat, srcMat, 3 * sizeof(float));
memcpy(mat + 3, srcMat + 4, 3 * sizeof(float));
memcpy(mat + 6, srcMat + 8, 3 * sizeof(float));
f->glUniformMatrix3fv(uniform.glslLocation, 1, GL_FALSE, mat);
}
break;
case QShaderDescription::Mat4:
f->glUniformMatrix4fv(uniform.glslLocation, 1, GL_FALSE, reinterpret_cast<const float *>(src));
@ -2919,21 +2927,64 @@ bool QRhiGles2::linkProgram(GLuint program)
return true;
}
void QRhiGles2::gatherUniforms(GLuint program, const QShaderDescription::UniformBlock &ub,
void QRhiGles2::registerUniformIfActive(const QShaderDescription::BlockVariable &var,
const QByteArray &namePrefix,
int binding,
int baseOffset,
GLuint program,
QVector<QGles2UniformDescription> *dst)
{
if (var.type == QShaderDescription::Struct) {
qWarning("Nested structs are not supported at the moment. '%s' ignored.",
qPrintable(var.name));
return;
}
QGles2UniformDescription uniform;
uniform.type = var.type;
const QByteArray name = namePrefix + var.name.toUtf8();
uniform.glslLocation = f->glGetUniformLocation(program, name.constData());
if (uniform.glslLocation >= 0) {
uniform.binding = binding;
uniform.offset = uint(baseOffset + var.offset);
uniform.size = var.size;
dst->append(uniform);
}
}
void QRhiGles2::gatherUniforms(GLuint program,
const QShaderDescription::UniformBlock &ub,
QVector<QGles2UniformDescription> *dst)
{
const QByteArray prefix = ub.structName.toUtf8() + '.';
QByteArray prefix = ub.structName.toUtf8() + '.';
for (const QShaderDescription::BlockVariable &blockMember : ub.members) {
// ### no array support for now
QGles2UniformDescription uniform;
uniform.type = blockMember.type;
const QByteArray name = prefix + blockMember.name.toUtf8();
uniform.glslLocation = f->glGetUniformLocation(program, name.constData());
if (uniform.glslLocation >= 0) {
uniform.binding = ub.binding;
uniform.offset = uint(blockMember.offset);
uniform.size = blockMember.size;
dst->append(uniform);
if (blockMember.type == QShaderDescription::Struct) {
prefix += blockMember.name.toUtf8();
const int baseOffset = blockMember.offset;
if (blockMember.arrayDims.isEmpty()) {
for (const QShaderDescription::BlockVariable &structMember : blockMember.structMembers)
registerUniformIfActive(structMember, prefix, ub.binding, baseOffset, program, dst);
} else {
if (blockMember.arrayDims.count() > 1) {
qWarning("Array of struct '%s' has more than one dimension. Only the first dimension is used.",
qPrintable(blockMember.name));
}
const int dim = blockMember.arrayDims.first();
const int elemSize = blockMember.size / dim;
int elemOffset = baseOffset;
for (int di = 0; di < dim; ++di) {
const QByteArray arrayPrefix = prefix + '[' + QByteArray::number(di) + ']' + '.';
for (const QShaderDescription::BlockVariable &structMember : blockMember.structMembers)
registerUniformIfActive(structMember, arrayPrefix, ub.binding, elemOffset, program, dst);
elemOffset += elemSize;
}
}
} else {
if (!blockMember.arrayDims.isEmpty()) {
qWarning("Arrays are only supported for structs at the moment. '%s' ignored.",
qPrintable(blockMember.name));
continue;
}
registerUniformIfActive(blockMember, prefix, ub.binding, 0, program, dst);
}
}
}

View File

@ -706,7 +706,14 @@ public:
QByteArray shaderSource(const QRhiShaderStage &shaderStage, int *glslVersion);
bool compileShader(GLuint program, const QRhiShaderStage &shaderStage, int *glslVersion);
bool linkProgram(GLuint program);
void gatherUniforms(GLuint program, const QShaderDescription::UniformBlock &ub,
void registerUniformIfActive(const QShaderDescription::BlockVariable &var,
const QByteArray &namePrefix,
int binding,
int baseOffset,
GLuint program,
QVector<QGles2UniformDescription> *dst);
void gatherUniforms(GLuint program,
const QShaderDescription::UniformBlock &ub,
QVector<QGles2UniformDescription> *dst);
void gatherSamplers(GLuint program, const QShaderDescription::InOutVariable &v,
QVector<QGles2SamplerDescription> *dst);

View File

@ -3215,7 +3215,10 @@ id<MTLLibrary> QRhiMetalData::createMetalLib(const QShader &shader, QShader::Var
[opts release];
// src is autoreleased
if (err) {
// if lib is null and err is non-null, we had errors (fail)
// if lib is non-null and err is non-null, we had warnings (success)
// if lib is non-null and err is null, there were no errors or warnings (success)
if (!lib) {
const QString msg = QString::fromNSString(err.localizedDescription);
*error = msg;
return nil;

View File

@ -2261,6 +2261,7 @@ void QTextCursor::insertFragment(const QTextDocumentFragment &fragment)
d->remove();
fragment.d->insert(*this);
d->priv->endEditBlock();
d->setX();
if (fragment.d && fragment.d->doc)
d->priv->mergeCachedResources(fragment.d->doc->docHandle());

View File

@ -347,7 +347,19 @@ QTextDocument *QTextDocument::clone(QObject *parent) const
{
Q_D(const QTextDocument);
QTextDocument *doc = new QTextDocument(parent);
QTextCursor(doc).insertFragment(QTextDocumentFragment(this));
if (isEmpty()) {
const QTextCursor thisCursor(const_cast<QTextDocument *>(this));
const auto blockFormat = thisCursor.blockFormat();
if (blockFormat.isValid() && !blockFormat.isEmpty())
QTextCursor(doc).setBlockFormat(blockFormat);
const auto blockCharFormat = thisCursor.blockCharFormat();
if (blockCharFormat.isValid() && !blockCharFormat.isEmpty())
QTextCursor(doc).setBlockCharFormat(blockCharFormat);
} else {
QTextCursor(doc).insertFragment(QTextDocumentFragment(this));
}
doc->rootFrame()->setFrameFormat(rootFrame()->frameFormat());
QTextDocumentPrivate *priv = doc->d_func();
priv->title = d->title;

View File

@ -67,7 +67,7 @@ void QCocoaClipboard::setMimeData(QMimeData *data, QClipboard::Mode mode)
}
pasteBoard->sync();
pasteBoard->setMimeData(data);
pasteBoard->setMimeData(data, QMacPasteboard::LazyRequest);
emitChanged(mode);
}
}

View File

@ -56,6 +56,9 @@ public:
void changeCursor(QCursor *cursor, QWindow *window) override;
QPoint pos() const override;
void setPos(const QPoint &position) override;
QSize size() const override;
private:
QHash<Qt::CursorShape, NSCursor *> m_cursors;
NSCursor *convertCursor(QCursor *cursor);

View File

@ -85,6 +85,31 @@ void QCocoaCursor::setPos(const QPoint &position)
CFRelease(e);
}
QSize QCocoaCursor::size() const
{
NSCursor *cocoaCursor = NSCursor.currentSystemCursor;
if (!cocoaCursor)
return QPlatformCursor::size();
NSImage *cursorImage = cocoaCursor.image;
if (!cursorImage)
return QPlatformCursor::size();
QSizeF size = QSizeF::fromCGSize(cursorImage.size);
NSUserDefaults *defaults = NSUserDefaults.standardUserDefaults;
NSDictionary *accessSettings = [defaults persistentDomainForName:@"com.apple.universalaccess"];
if (accessSettings == nil)
return size.toSize();
float sizeScale = [accessSettings[@"mouseDriverCursorSize"] floatValue];
if (sizeScale > 0) {
size.rwidth() *= sizeScale;
size.rheight() *= sizeScale;
}
return size.toSize();
}
NSCursor *QCocoaCursor::convertCursor(QCursor *cursor)
{
if (!cursor)

View File

@ -186,6 +186,7 @@ public:
QAtomicInt serialNumber;
int lastSerial;
bool interrupt;
bool propagateInterrupt = false;
static void postedEventsSourceCallback(void *info);
static void waitingObserverCallback(CFRunLoopObserverRef observer,

View File

@ -84,13 +84,12 @@
#include "private/qthread_p.h"
#include "private/qguiapplication_p.h"
#include <qdebug.h>
#include <qscopeguard.h>
#include <AppKit/AppKit.h>
QT_BEGIN_NAMESPACE
QT_USE_NAMESPACE
static inline CFRunLoopRef mainRunLoop()
{
return CFRunLoopGetMain();
@ -348,6 +347,16 @@ static inline void qt_mac_waitForMoreEvents(NSString *runLoopMode = NSDefaultRun
bool QCocoaEventDispatcher::processEvents(QEventLoop::ProcessEventsFlags flags)
{
Q_D(QCocoaEventDispatcher);
// In rare rather corner cases a user's application messes with
// QEventLoop::exec()/exit() and QCoreApplication::processEvents(),
// we have to undo what bool blocker normally does.
d->propagateInterrupt = false;
const auto boolBlockerUndo = qScopeGuard([d](){
if (d->propagateInterrupt)
d->interrupt = true;
d->propagateInterrupt = false;
});
QBoolBlocker interruptBlocker(d->interrupt, false);
bool interruptLater = false;
@ -496,7 +505,16 @@ bool QCocoaEventDispatcher::processEvents(QEventLoop::ProcessEventsFlags flags)
if ((d->processEventsFlags & QEventLoop::EventLoopExec) == 0) {
// When called "manually", always process posted events and timers
bool oldInterrupt = d->interrupt;
d->processPostedEvents();
if (!oldInterrupt && d->interrupt && !d->currentModalSession()) {
// We had direct processEvent call, coming not from QEventLoop::exec().
// One of the posted events triggered an application to interrupt the loop.
// But bool blocker will reset d->interrupt to false, so the real event
// loop will never notice it was interrupted. Now we'll have to fix it by
// enforcing the value of d->interrupt.
d->propagateInterrupt = true;
}
retVal = d->processTimers() || retVal;
}

View File

@ -86,6 +86,10 @@ private:
QSurfaceFormat m_format;
QVarLengthArray<QMacNotificationObserver, 3> m_updateObservers;
QAtomicInt m_needsUpdate = false;
#ifndef QT_NO_DEBUG_STREAM
friend QDebug operator<<(QDebug debug, const QCocoaGLContext *screen);
#endif
};
QT_END_NAMESPACE

View File

@ -158,6 +158,8 @@ void QCocoaGLContext::initialize()
[m_context setValues:&order forParameter:NSOpenGLCPSurfaceOrder];
updateSurfaceFormat();
qCDebug(lcQpaOpenGLContext).verbosity(3) << "Created" << this << "based on requested" << context()->format();
}
NSOpenGLPixelFormat *QCocoaGLContext::pixelFormatForSurfaceFormat(const QSurfaceFormat &format)
@ -355,7 +357,7 @@ QCocoaGLContext::~QCocoaGLContext()
bool QCocoaGLContext::makeCurrent(QPlatformSurface *surface)
{
qCDebug(lcQpaOpenGLContext) << "Making" << m_context << "current"
qCDebug(lcQpaOpenGLContext) << "Making" << this << "current"
<< "in" << QThread::currentThread() << "for" << surface;
Q_ASSERT(surface->surface()->supportsOpenGL());
@ -555,4 +557,20 @@ QFunctionPointer QCocoaGLContext::getProcAddress(const char *procName)
return (QFunctionPointer)dlsym(RTLD_DEFAULT, procName);
}
#ifndef QT_NO_DEBUG_STREAM
QDebug operator<<(QDebug debug, const QCocoaGLContext *context)
{
QDebugStateSaver saver(debug);
debug.nospace();
debug << "QCocoaGLContext(" << (const void *)context;
if (context) {
if (debug.verbosity() > QDebug::DefaultVerbosity)
debug << ", " << context->format();
debug << ", " << context->nativeContext();
}
debug << ')';
return debug;
}
#endif // !QT_NO_DEBUG_STREAM
QT_END_NAMESPACE

View File

@ -559,7 +559,10 @@ void QCocoaWindow::setWindowFlags(Qt::WindowFlags flags)
Qt::WindowType type = static_cast<Qt::WindowType>(int(flags & Qt::WindowType_Mask));
if ((type & Qt::Popup) != Qt::Popup && (type & Qt::Dialog) != Qt::Dialog) {
NSWindowCollectionBehavior behavior = m_view.window.collectionBehavior;
if ((flags & Qt::WindowFullscreenButtonHint) || m_view.window.qt_fullScreen) {
const bool enableFullScreen = m_view.window.qt_fullScreen
|| !(flags & Qt::CustomizeWindowHint)
|| (flags & Qt::WindowFullscreenButtonHint);
if (enableFullScreen) {
behavior |= NSWindowCollectionBehaviorFullScreenPrimary;
behavior &= ~NSWindowCollectionBehaviorFullScreenAuxiliary;
} else {

View File

@ -138,8 +138,12 @@ QMacPasteboard::QMacPasteboard(CFStringRef name, uchar mt)
QMacPasteboard::~QMacPasteboard()
{
// commit all promises for paste after exit close
resolvingBeforeDestruction = true;
/*
Commit all promises for paste when shutting down,
unless we are the stack-allocated clipboard used by QCocoaDrag.
*/
if (mime_type == QMacInternalPasteboardMime::MIME_DND)
resolvingBeforeDestruction = true;
PasteboardResolvePromises(paste);
if (paste)
CFRelease(paste);

View File

@ -60,6 +60,18 @@ static const int c_screenCode = _PULSE_CODE_MINAVAIL + 0;
static const int c_armCode = _PULSE_CODE_MINAVAIL + 1;
static const int c_quitCode = _PULSE_CODE_MINAVAIL + 2;
#if !defined(screen_register_event)
int screen_register_event(screen_context_t, struct sigevent *event)
{
return MsgRegisterEvent(event, -1);
}
int screen_unregister_event(struct sigevent *event)
{
return MsgUnregisterEvent(event);
}
#endif
QQnxScreenEventThread::QQnxScreenEventThread(screen_context_t context)
: QThread()
, m_screenContext(context)
@ -75,10 +87,14 @@ QQnxScreenEventThread::QQnxScreenEventThread(screen_context_t context)
qFatal("QQnxScreenEventThread: Can't continue without a channel connection");
}
struct sigevent screenEvent;
SIGEV_PULSE_INIT(&screenEvent, m_connectionId, SIGEV_PULSE_PRIO_INHERIT, c_screenCode, 0);
SIGEV_PULSE_INIT(&m_screenEvent, m_connectionId, SIGEV_PULSE_PRIO_INHERIT, c_screenCode, 0);
if (screen_register_event(m_screenContext, &m_screenEvent) == -1) {
ConnectDetach(m_connectionId);
ChannelDestroy(m_channelId);
qFatal("QQnxScreenEventThread: Can't continue without a registered event");
}
screen_notify(m_screenContext, SCREEN_NOTIFY_EVENT, nullptr, &screenEvent);
screen_notify(m_screenContext, SCREEN_NOTIFY_EVENT, nullptr, &m_screenEvent);
}
QQnxScreenEventThread::~QQnxScreenEventThread()
@ -86,6 +102,8 @@ QQnxScreenEventThread::~QQnxScreenEventThread()
// block until thread terminates
shutdown();
screen_notify(m_screenContext, SCREEN_NOTIFY_EVENT, nullptr, nullptr);
screen_unregister_event(&m_screenEvent);
ConnectDetach(m_connectionId);
ChannelDestroy(m_channelId);
}

View File

@ -45,6 +45,7 @@
#include <QtCore/QMutex>
#include <screen/screen.h>
#include <sys/siginfo.h>
QT_BEGIN_NAMESPACE
@ -73,6 +74,7 @@ private:
int m_channelId;
int m_connectionId;
struct sigevent m_screenEvent;
screen_context_t m_screenContext;
bool m_emitNeededOnNextScreenPulse = true;
int m_screenPulsesSinceLastArmPulse = 0;

View File

@ -54,6 +54,8 @@ QWasmScreen::QWasmScreen(const QString &canvasId)
m_compositor = new QWasmCompositor(this);
m_eventTranslator = new QWasmEventTranslator(this);
updateQScreenAndCanvasRenderSize();
emscripten::val canvas = emscripten::val::global(m_canvasId.toUtf8().constData());
canvas.call<void>("focus");
}
QWasmScreen::~QWasmScreen()

View File

@ -50,6 +50,7 @@
#include <QtGui/qscreen.h>
#include <QtGui/private/qguiapplication_p.h> // getPixmapCursor()
#include <QtGui/private/qhighdpiscaling_p.h>
#include <QtCore/private/qwinregistry_p.h>
#include <QtCore/qdebug.h>
#include <QtCore/qscopedpointer.h>
@ -686,6 +687,30 @@ void QWindowsCursor::setPos(const QPoint &pos)
SetCursorPos(pos.x() , pos.y());
}
/*
The standard size is 32x32, even though the cursor is actually just
16 pixels large. If a large cursor is set in the accessibility settings,
then the cursor increases with 8 pixels for each step.
*/
QSize QWindowsCursor::size() const
{
const QPair<DWORD,bool> cursorSizeSetting =
QWinRegistryKey(HKEY_CURRENT_USER, LR"(Control Panel\Cursors)")
.dwordValue(L"CursorBaseSize");
const int baseSize = screenCursorSize(m_screen).width() / 2;
if (!cursorSizeSetting.second)
return QSize(baseSize / 2, baseSize / 2);
// The registry values are dpi-independent, so we need to scale the result.
int cursorSizeValue = cursorSizeSetting.first * m_screen->logicalDpi().first
/ m_screen->logicalBaseDpi().first;
// map from registry value 32-256 to 0-14, and from there to pixels
cursorSizeValue = (cursorSizeValue - 2 * baseSize) / baseSize;
const int cursorSize = baseSize + cursorSizeValue * (baseSize / 2);
return QSize(cursorSize, cursorSize);
}
QPixmap QWindowsCursor::dragDefaultCursor(Qt::DropAction action) const
{
switch (action) {

View File

@ -113,6 +113,8 @@ public:
QPoint pos() const override;
void setPos(const QPoint &pos) override;
QSize size() const override;
static HCURSOR createPixmapCursor(QPixmap pixmap, const QPoint &hotSpot, qreal scaleFactor = 1);
static HCURSOR createPixmapCursor(const PixmapCursor &pc, qreal scaleFactor = 1) { return createPixmapCursor(pc.pixmap, pc.hotSpot, scaleFactor); }
static PixmapCursor customCursor(Qt::CursorShape cursorShape, const QPlatformScreen *screen = nullptr);

View File

@ -57,11 +57,13 @@
#include "qwindowsmenu.h"
#include "qwindowsscreen.h"
#include <QtGui/qguiapplication.h>
#include <QtGui/qpixmap.h>
#include <QtCore/qdebug.h>
#include <QtCore/qrect.h>
#include <QtCore/qvector.h>
#include <QtCore/qsettings.h>
#include <qpa/qwindowsysteminterface.h>
#include <qt_windows.h>
#include <commctrl.h>
@ -134,9 +136,12 @@ static int indexOfHwnd(HWND hwnd)
extern "C" LRESULT QT_WIN_CALLBACK qWindowsTrayIconWndProc(HWND hwnd, UINT message,
WPARAM wParam, LPARAM lParam)
{
// QTBUG-79248: Trigger screen update if there are no other windows.
if (message == WM_DPICHANGED && QGuiApplication::topLevelWindows().isEmpty())
QWindowsContext::instance()->screenManager().handleScreenChanges();
if (message == MYWM_TASKBARCREATED || message == MYWM_NOTIFYICON
|| message == WM_INITMENU || message == WM_INITMENUPOPUP
|| message == WM_COMMAND) {
|| message == WM_CLOSE || message == WM_COMMAND) {
const int index = indexOfHwnd(hwnd);
if (index >= 0) {
MSG msg;
@ -439,6 +444,9 @@ bool QWindowsSystemTrayIcon::winEvent(const MSG &message, long *result)
case WM_INITMENUPOPUP:
QWindowsPopupMenu::notifyAboutToShow(reinterpret_cast<HMENU>(message.wParam));
break;
case WM_CLOSE:
QWindowSystemInterface::handleApplicationTermination<QWindowSystemInterface::SynchronousDelivery>();
break;
case WM_COMMAND:
QWindowsPopupMenu::notifyTriggered(LOWORD(message.wParam));
break;

View File

@ -289,7 +289,8 @@ HRESULT QWindowsUiaMainProvider::GetPatternProvider(PATTERNID idPattern, IUnknow
break;
case UIA_TogglePatternId:
// Checkbox controls.
if (accessible->role() == QAccessible::CheckBox) {
if (accessible->role() == QAccessible::CheckBox
|| (accessible->role() == QAccessible::MenuItem && accessible->state().checkable)) {
*pRetVal = new QWindowsUiaToggleProvider(id());
}
break;

View File

@ -41,6 +41,7 @@
#include "qxcbwindow.h"
#include "qxcbcursor.h"
#include "qxcbimage.h"
#include "qxcbintegration.h"
#include "qnamespace.h"
#include "qxcbxsettings.h"
@ -49,6 +50,7 @@
#include <QDebug>
#include <QtAlgorithms>
#include <qpa/qplatformservices.h>
#include <qpa/qwindowsysteminterface.h>
#include <private/qmath_p.h>
#include <QtGui/private/qhighdpiscaling_p.h>
@ -356,6 +358,15 @@ static QFontEngine::SubpixelAntialiasingType parseXftRgba(const QByteArray& stri
void QXcbVirtualDesktop::readXResources()
{
const QPlatformServices *services = QXcbIntegration::instance()->services();
bool useXftConf = false;
if (services) {
const QList<QByteArray> desktopEnv = services->desktopEnvironment().split(':');
useXftConf = desktopEnv.contains("GNOME") || desktopEnv.contains("UNITY") || desktopEnv.contains("XFCE");
}
if (!useXftConf)
return;
int offset = 0;
QByteArray resources;
while (true) {

View File

@ -838,6 +838,7 @@ QSqlRecord QPSQLResult::record() const
}
int ptype = PQftype(d->result, i);
f.setType(qDecodePSQLType(ptype));
f.setValue(QVariant(f.type())); // only set in setType() when it's invalid before
int len = PQfsize(d->result, i);
int precision = PQfmod(d->result, i);

View File

@ -0,0 +1,14 @@
project(mytest LANGUAGES CXX)
find_package(Qt5Test REQUIRED)
set(CMAKE_INCLUDE_CURRENT_DIR ON)
set(CMAKE_AUTOMOC ON)
enable_testing(true)
add_executable(mytest tst_mytest.cpp)
add_test(NAME mytest COMMAND mytest)
target_link_libraries(mytest PRIVATE Qt5::Test)

View File

@ -83,6 +83,10 @@
\li Custom types can easily be added to the test data and test output.
\endtable
You can use a Qt Creator wizard to create a project that contains Qt tests
and build and run them directly from Qt Creator. For more information, see
\l {Running Autotests}.
\section1 Creating a Test
To create a test, subclass QObject and add one or more private slots to it. Each
@ -133,6 +137,41 @@
\if !defined(qtforpython)
\section1 Building a Test
You can build an executable that contains one test class that typically
tests one class of production code. However, usually you would want to
test several classes in a project by running one command.
See \l {Chapter 1: Writing a Unit Test}{Writing a Unit Test} for a step by
step explanation.
\section2 Building with CMake and CTest
You can use \l {CMake and CTest} to create a test.
\l{https://cmake.org/cmake/help/latest/manual/ctest.1.html}{CTest} enables
you to include or exclude tests based on a regular expression that is
matched against the test name. You can further apply the \c LABELS property
to a test and CTest can then include or exclude tests based on those labels.
All labeled targets will be run when \c {test} target is called on the
command line.
There are several other advantages with CMake. For example, the result of
a test run can be published on a web server using CDash with virtually no
effort.
CTest scales to very different unit test frameworks, and works out of the
box with QTest.
The following is an example of a CMakeLists.txt file that specifies the
project name and the language used (here, \e mytest and C++), the Qt
modules required for building the test (Qt5Test), and the files that are
included in the test (\e tst_mytest.cpp).
\quotefile code/doc_src_cmakelists.txt
For more information about the options you have, see \l {Build with CMake}.
\section2 Building with qmake
If you are using \c qmake as your build tool, just add the
following to your project file:
@ -146,14 +185,14 @@
See the \l{Building a Testcase}{qmake manual} for
more information about \c{make check}.
\section2 Building with Other Tools
If you are using other build tools, make sure that you add the location
of the Qt Test header files to your include path (usually \c{include/QtTest}
under your Qt installation directory). If you are using a release build
of Qt, link your test to the \c QtTest library. For debug builds, use
\c{QtTest_debug}.
See \l {Chapter 1: Writing a Unit Test}{Writing a Unit Test} for a step by
step explanation.
\endif
\section1 Qt Test Command Line Arguments

View File

@ -299,6 +299,8 @@ QAccessible::State QAccessibleMenuItem::state() const
s.disabled = true;
if (m_action->isChecked())
s.checked = true;
if (m_action->isCheckable())
s.checkable = true;
return s;
}

View File

@ -710,14 +710,17 @@ void QProgressDialog::setValue(int progress)
QSize QProgressDialog::sizeHint() const
{
Q_D(const QProgressDialog);
QSize sh = d->label ? d->label->sizeHint() : QSize(0, 0);
QSize bh = d->bar->sizeHint();
int margin = style()->pixelMetric(QStyle::PM_DefaultTopLevelMargin);
int spacing = style()->pixelMetric(QStyle::PM_DefaultLayoutSpacing);
int h = margin * 2 + bh.height() + sh.height() + spacing;
QSize labelSize = d->label ? d->label->sizeHint() : QSize(0, 0);
QSize barSize = d->bar->sizeHint();
int marginBottom = style()->pixelMetric(QStyle::PM_LayoutBottomMargin, 0, this);
int spacing = style()->pixelMetric(QStyle::PM_LayoutVerticalSpacing, 0, this);
int marginLeft = style()->pixelMetric(QStyle::PM_LayoutLeftMargin, 0, this);
int marginRight = style()->pixelMetric(QStyle::PM_LayoutRightMargin, 0, this);
int height = marginBottom * 2 + barSize.height() + labelSize.height() + spacing;
if (d->cancel)
h += d->cancel->sizeHint().height() + spacing;
return QSize(qMax(200, sh.width() + 2 * margin), h);
height += d->cancel->sizeHint().height() + spacing;
return QSize(qMax(200, labelSize.width() + marginLeft + marginRight), height);
}
/*!\reimp

View File

@ -3074,9 +3074,10 @@ void QAbstractItemView::keyboardSearch(const QString &search)
QSize QAbstractItemView::sizeHintForIndex(const QModelIndex &index) const
{
Q_D(const QAbstractItemView);
if (!d->isIndexValid(index) || !d->itemDelegate)
if (!d->isIndexValid(index))
return QSize();
return d->delegateForIndex(index)->sizeHint(d->viewOptionsV1(), index);
const auto delegate = d->delegateForIndex(index);
return delegate ? delegate->sizeHint(d->viewOptionsV1(), index) : QSize();
}
/*!
@ -3318,6 +3319,8 @@ void QAbstractItemView::update(const QModelIndex &index)
The \a roles which have been changed can either be an empty container (meaning everything
has changed), or a non-empty container with the subset of roles which have changed.
\note: Qt::ToolTipRole is not honored by dataChanged() in the views provided by Qt.
*/
void QAbstractItemView::dataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight, const QVector<int> &roles)
{
@ -4451,7 +4454,9 @@ QItemViewPaintPairs QAbstractItemViewPrivate::draggablePaintPairs(const QModelIn
rect |= current;
}
}
rect &= viewportRect;
QRect clipped = rect & viewportRect;
rect.setLeft(clipped.left());
rect.setRight(clipped.right());
return ret;
}

View File

@ -664,7 +664,9 @@ QItemViewPaintPairs QListViewPrivate::draggablePaintPairs(const QModelIndexList
rect |= current;
}
}
rect &= viewportRect;
QRect clipped = rect & viewportRect;
rect.setLeft(clipped.left());
rect.setRight(clipped.right());
return ret;
}

View File

@ -53,11 +53,14 @@
#endif
#include <qtextdocument.h>
#include <qdebug.h>
#include <qpa/qplatformscreen.h>
#include <qpa/qplatformcursor.h>
#include <private/qstylesheetstyle_p.h>
#ifndef QT_NO_TOOLTIP
#include <qlabel.h>
#include <QtWidgets/private/qlabel_p.h>
#include <QtGui/private/qhighdpiscaling_p.h>
#include <qtooltip.h>
QT_BEGIN_NAMESPACE
@ -398,24 +401,34 @@ void QTipLabel::placeTip(const QPoint &pos, QWidget *w)
}
#endif //QT_NO_STYLE_STYLESHEET
QRect screen = QDesktopWidgetPrivate::screenGeometry(getTipScreen(pos, w));
QPoint p = pos;
p += QPoint(2, 16);
int screenNumber = getTipScreen(pos, w);
QScreen *screen = QGuiApplication::screens().at(screenNumber);
if (screen) {
const QPlatformScreen *platformScreen = screen->handle();
const QSize cursorSize = QHighDpi::fromNativePixels(platformScreen->cursor()->size(),
platformScreen);
QPoint offset(2, cursorSize.height());
// assuming an arrow shape, we can just move to the side for very large cursors
if (cursorSize.height() > 2 * this->height())
offset = QPoint(cursorSize.width() / 2, 0);
if (p.x() + this->width() > screen.x() + screen.width())
p += offset;
QRect screenRect = screen->geometry();
if (p.x() + this->width() > screenRect.x() + screenRect.width())
p.rx() -= 4 + this->width();
if (p.y() + this->height() > screen.y() + screen.height())
if (p.y() + this->height() > screenRect.y() + screenRect.height())
p.ry() -= 24 + this->height();
if (p.y() < screen.y())
p.setY(screen.y());
if (p.x() + this->width() > screen.x() + screen.width())
p.setX(screen.x() + screen.width() - this->width());
if (p.x() < screen.x())
p.setX(screen.x());
if (p.y() + this->height() > screen.y() + screen.height())
p.setY(screen.y() + screen.height() - this->height());
if (p.y() < screenRect.y())
p.setY(screenRect.y());
if (p.x() + this->width() > screenRect.x() + screenRect.width())
p.setX(screenRect.x() + screenRect.width() - this->width());
if (p.x() < screenRect.x())
p.setX(screenRect.x());
if (p.y() + this->height() > screenRect.y() + screenRect.height())
p.setY(screenRect.y() + screenRect.height() - this->height());
}
this->move(p);
}

View File

@ -8621,6 +8621,23 @@ bool QWidget::event(QEvent *event)
}
}
switch (event->type()) {
case QEvent::PlatformSurface: {
// Sync up QWidget's view of whether or not the widget has been created
switch (static_cast<QPlatformSurfaceEvent*>(event)->surfaceEventType()) {
case QPlatformSurfaceEvent::SurfaceCreated:
if (!testAttribute(Qt::WA_WState_Created))
create();
break;
case QPlatformSurfaceEvent::SurfaceAboutToBeDestroyed:
if (testAttribute(Qt::WA_WState_Created)) {
// Child windows have already been destroyed by QWindow,
// so we skip them here.
destroy(false, false);
}
break;
}
break;
}
case QEvent::MouseMove:
mouseMoveEvent((QMouseEvent*)event);
break;

View File

@ -1363,7 +1363,6 @@ void QCommonStyle::drawControl(ControlElement element, const QStyleOption *opt,
if (!button->icon.isNull()) {
//Center both icon and text
QRect iconRect;
QIcon::Mode mode = button->state & State_Enabled ? QIcon::Normal : QIcon::Disabled;
if (mode == QIcon::Normal && button->state & State_HasFocus)
mode = QIcon::Active;
@ -1372,28 +1371,29 @@ void QCommonStyle::drawControl(ControlElement element, const QStyleOption *opt,
state = QIcon::On;
QPixmap pixmap = button->icon.pixmap(qt_getWindow(widget), button->iconSize, mode, state);
int pixmapWidth = pixmap.width() / pixmap.devicePixelRatio();
int pixmapHeight = pixmap.height() / pixmap.devicePixelRatio();
int labelWidth = pixmapWidth;
int labelHeight = pixmapHeight;
int iconSpacing = 4;//### 4 is currently hardcoded in QPushButton::sizeHint()
int textWidth = button->fontMetrics.boundingRect(opt->rect, tf, button->text).width();
if (!button->text.isEmpty())
if (!button->text.isEmpty()) {
int textWidth = button->fontMetrics.boundingRect(opt->rect, tf, button->text).width();
labelWidth += (textWidth + iconSpacing);
}
iconRect = QRect(textRect.x() + (textRect.width() - labelWidth) / 2,
textRect.y() + (textRect.height() - labelHeight) / 2,
pixmapWidth, pixmapHeight);
QRect iconRect = QRect(textRect.x() + (textRect.width() - labelWidth) / 2,
textRect.y() + (textRect.height() - labelHeight) / 2,
pixmapWidth, pixmapHeight);
iconRect = visualRect(button->direction, textRect, iconRect);
tf |= Qt::AlignLeft; //left align, we adjust the text-rect instead
if (button->direction == Qt::RightToLeft)
if (button->direction == Qt::RightToLeft) {
tf |= Qt::AlignRight;
textRect.setRight(iconRect.left() - iconSpacing);
else
} else {
tf |= Qt::AlignLeft; //left align, we adjust the text-rect instead
textRect.setLeft(iconRect.left() + iconRect.width() + iconSpacing);
}
if (button->state & (State_On | State_Sunken))
iconRect.translate(proxy()->pixelMetric(PM_ButtonShiftHorizontal, opt, widget),

View File

@ -1770,59 +1770,10 @@ void QFusionStyle::drawControl(ControlElement element, const QStyleOption *optio
break;
case CE_PushButtonLabel:
if (const QStyleOptionButton *button = qstyleoption_cast<const QStyleOptionButton *>(option)) {
QRect ir = button->rect;
uint tf = Qt::AlignVCenter;
if (styleHint(SH_UnderlineShortcut, button, widget))
tf |= Qt::TextShowMnemonic;
else
tf |= Qt::TextHideMnemonic;
if (!button->icon.isNull()) {
//Center both icon and text
QPoint point;
QIcon::Mode mode = button->state & State_Enabled ? QIcon::Normal
: QIcon::Disabled;
if (mode == QIcon::Normal && button->state & State_HasFocus)
mode = QIcon::Active;
QIcon::State state = QIcon::Off;
if (button->state & State_On)
state = QIcon::On;
QPixmap pixmap = button->icon.pixmap(qt_getWindow(widget), button->iconSize, mode, state);
int w = pixmap.width() / pixmap.devicePixelRatio();
int h = pixmap.height() / pixmap.devicePixelRatio();
if (!button->text.isEmpty())
w += button->fontMetrics.boundingRect(option->rect, tf, button->text).width() + 2;
point = QPoint(ir.x() + ir.width() / 2 - w / 2,
ir.y() + ir.height() / 2 - h / 2);
w = pixmap.width() / pixmap.devicePixelRatio();
if (button->direction == Qt::RightToLeft)
point.rx() += w;
painter->drawPixmap(visualPos(button->direction, button->rect, point), pixmap);
if (button->direction == Qt::RightToLeft)
ir.translate(-point.x() - 2, 0);
else
ir.translate(point.x() + w, 0);
// left-align text if there is
if (!button->text.isEmpty())
tf |= Qt::AlignLeft;
} else {
tf |= Qt::AlignHCenter;
}
if (button->features & QStyleOptionButton::HasMenu)
ir = ir.adjusted(0, 0, -proxy()->pixelMetric(PM_MenuButtonIndicator, button, widget), 0);
proxy()->drawItemText(painter, ir, tf, button->palette, (button->state & State_Enabled),
button->text, QPalette::ButtonText);
QStyleOptionButton b(*button);
// no PM_ButtonShiftHorizontal and PM_ButtonShiftVertical for fusion style
b.state &= ~(State_On | State_Sunken);
QCommonStyle::drawControl(element, &b, painter, widget);
}
break;
case CE_MenuBarEmptyArea:

View File

@ -3501,6 +3501,7 @@ void QStyleSheetStyle::drawControl(ControlElement ce, const QStyleOption *opt, Q
} else {
QWindowsStyle::drawControl(ce, &btnOpt, p, w);
}
rule.drawImage(p, rule.contentsRect(opt->rect));
if (!customMenu)
return;
} else {
@ -3730,6 +3731,7 @@ void QStyleSheetStyle::drawControl(ControlElement ce, const QStyleOption *opt, Q
bool dis = !(opt->state & QStyle::State_Enabled),
act = opt->state & QStyle::State_Selected;
int textRectOffset = m->maxIconWidth;
if (!mi.icon.isNull()) {
QIcon::Mode mode = dis ? QIcon::Disabled : QIcon::Normal;
if (act && !dis)
@ -3755,19 +3757,21 @@ void QStyleSheetStyle::drawControl(ControlElement ce, const QStyleOption *opt, Q
p->drawPixmap(pmr.topLeft(), pixmap);
} else if (checkable) {
QRenderRule subSubRule = renderRule(w, opt, PseudoElement_MenuCheckMark);
const QRect cmRect = positionRect(w, subRule, subSubRule, PseudoElement_MenuCheckMark, opt->rect, opt->direction);
if (subSubRule.hasDrawable() || checked) {
QStyleOptionMenuItem newMi = mi;
if (!dis)
newMi.state |= State_Enabled;
if (act)
if (mi.checked)
newMi.state |= State_On;
newMi.rect = positionRect(w, subRule, subSubRule, PseudoElement_MenuCheckMark, opt->rect, opt->direction);
newMi.rect = cmRect;
drawPrimitive(PE_IndicatorMenuCheckMark, &newMi, p, w);
}
textRectOffset = std::max(textRectOffset, cmRect.width());
}
QRect textRect = subRule.contentsRect(opt->rect);
textRect.setLeft(textRect.left() + m->maxIconWidth);
textRect.setLeft(textRect.left() + textRectOffset);
textRect.setWidth(textRect.width() - mi.tabWidth);
const QRect vTextRect = visualRect(opt->direction, m->rect, textRect);

View File

@ -90,12 +90,10 @@ QT_BEGIN_NAMESPACE
today's date, and restricted the valid date range to today plus or
minus 365 days. We've set the order to month, day, year.
The minimum value for QDateTimeEdit is 14 September 1752. You can
change this by calling setMinimumDate(), taking into account that
the minimum value for QDate is 2 January 4713BC.
Other useful functions are setMaximumDate(), setMinimumTime()
and setMaximumTime().
The range of valid values for a QDateTimeEdit is controlled by the properties
\l minimumDateTime, \l maximumDateTime, and their respective date and time
components. By default, any date-time from the start of 100 CE to the end of
9999 CE is valid.
\section1 Using a Pop-up Calendar Widget
@ -223,10 +221,16 @@ QDateTimeEdit::~QDateTimeEdit()
When setting this property the timespec of the QDateTimeEdit remains the same
and the timespec of the new QDateTime is ignored.
By default, this property contains a date that refers to January 1,
2000 and a time of 00:00:00 and 0 milliseconds.
By default, this property is set to the start of 2000 CE. It can only be set
to a valid QDateTime value. If any operation causes this property to have an
invalid date-time as value, it is reset to the value of the \l minimumDateTime
property.
\sa date, time
If the QDateTimeEdit has no date fields, setting this property sets the
widget's date-range to start and end on the date of the new value of this
property.
\sa date, time, minimumDateTime, maximumDateTime
*/
QDateTime QDateTimeEdit::dateTime() const
@ -329,25 +333,23 @@ void QDateTimeEdit::setCalendar(QCalendar calendar)
}
/*!
\property QDateTimeEdit::minimumDateTime
\since 4.4
\property QDateTimeEdit::minimumDateTime
\brief the minimum datetime of the date time edit
When setting this property the \l maximumDateTime() is adjusted if
necessary to ensure that the range remains valid. If the datetime is
not a valid QDateTime object, this function does nothing.
Changing this property implicitly updates the \l minimumDate and \l
minimumTime properties to the date and time parts of this property,
respectively. When setting this property, the \l maximumDateTime is adjusted,
if necessary, to ensure that the range remains valid. Otherwise, changing this
property preserves the \l minimumDateTime property.
The default minimumDateTime can be restored with
clearMinimumDateTime()
This property can only be set to a valid QDateTime value. The earliest
date-time that setMinimumDateTime() accepts is the start of 100 CE. The
property's default is the start of September 14, 1752 CE. This default can be
restored with clearMinimumDateTime().
By default, this property contains a date that refers to September 14,
1752 and a time of 00:00:00 and 0 milliseconds.
\sa maximumDateTime(), minimumTime(), maximumTime(), minimumDate(),
maximumDate(), setDateTimeRange(), setDateRange(), setTimeRange(),
clearMaximumDateTime(), clearMinimumDate(),
clearMaximumDate(), clearMinimumTime(), clearMaximumTime()
\sa maximumDateTime, minimumTime, minimumDate, setDateTimeRange(), QDateTime::isValid()
*/
QDateTime QDateTimeEdit::minimumDateTime() const
@ -372,25 +374,23 @@ void QDateTimeEdit::setMinimumDateTime(const QDateTime &dt)
}
/*!
\property QDateTimeEdit::maximumDateTime
\since 4.4
\property QDateTimeEdit::maximumDateTime
\brief the maximum datetime of the date time edit
When setting this property the \l minimumDateTime() is adjusted if
necessary to ensure that the range remains valid. If the datetime is
not a valid QDateTime object, this function does nothing.
Changing this property implicitly updates the \l maximumDate and \l
maximumTime properties to the date and time parts of this property,
respectively. When setting this property, the \l minimumDateTime is adjusted,
if necessary, to ensure that the range remains valid. Otherwise, changing this
property preserves the \l minimumDateTime property.
The default maximumDateTime can be restored with
This property can only be set to a valid QDateTime value. The latest
date-time that setMaximumDateTime() accepts is the end of 9999 CE. This is the
default for this property. This default can be restored with
clearMaximumDateTime().
By default, this property contains a date that refers to 31 December,
9999 and a time of 23:59:59 and 999 milliseconds.
\sa minimumDateTime(), minimumTime(), maximumTime(), minimumDate(),
maximumDate(), setDateTimeRange(), setDateRange(), setTimeRange(),
clearMinimumDateTime(), clearMinimumDate(),
clearMaximumDate(), clearMinimumTime(), clearMaximumTime()
\sa minimumDateTime, maximumTime, maximumDate(), setDateTimeRange(), QDateTime::isValid()
*/
QDateTime QDateTimeEdit::maximumDateTime() const
@ -414,11 +414,12 @@ void QDateTimeEdit::setMaximumDateTime(const QDateTime &dt)
}
}
/*!
Convenience function to set minimum and maximum date time with one
function call.
\since 4.4
\brief Set the range of allowed date-times for the date time edit.
This convenience function sets the \l minimumDateTime and \l maximumDateTime
properties.
\snippet code/src_gui_widgets_qdatetimeedit.cpp 1
@ -426,21 +427,18 @@ void QDateTimeEdit::setMaximumDateTime(const QDateTime &dt)
\snippet code/src_gui_widgets_qdatetimeedit.cpp 2
If either \a min or \a max are not valid, this function does
nothing.
If either \a min or \a max is invalid, this function does nothing. If \a max
is less than \a min, \a min is used also as \a max.
\sa setMinimumDate(), maximumDate(), setMaximumDate(),
clearMinimumDate(), setMinimumTime(), maximumTime(),
setMaximumTime(), clearMinimumTime(), QDateTime::isValid()
\sa minimumDateTime, maximumDateTime, setDateRange(), setTimeRange(), QDateTime::isValid()
*/
void QDateTimeEdit::setDateTimeRange(const QDateTime &min, const QDateTime &max)
{
Q_D(QDateTimeEdit);
// FIXME: does none of the range checks applied to setMin/setMax methods !
const QDateTime minimum = min.toTimeSpec(d->spec);
QDateTime maximum = max.toTimeSpec(d->spec);
if (min > max)
maximum = minimum;
const QDateTime maximum = (min > max ? minimum : max.toTimeSpec(d->spec));
d->setRange(minimum, maximum);
}
@ -449,15 +447,20 @@ void QDateTimeEdit::setDateTimeRange(const QDateTime &min, const QDateTime &max)
\brief the minimum date of the date time edit
When setting this property the \l maximumDate is adjusted if
necessary, to ensure that the range remains valid. If the date is
not a valid QDate object, this function does nothing.
Changing this property updates the date of the \l minimumDateTime property
while preserving the \l minimumTime property. When setting this property,
the \l maximumDate is adjusted, if necessary, to ensure that the range remains
valid. When this happens, the \l maximumTime property is also adjusted if it
is less than the \l minimumTime property. Otherwise, changes to this property
preserve the \l maximumDateTime property.
By default, this property contains a date that refers to September 14, 1752.
The minimum date must be at least the first day in year 100, otherwise
setMinimumDate() has no effect.
This property can only be set to a valid QDate object describing a date on
which the current \l minimumTime property makes a valid QDateTime object. The
earliest date that setMinimumDate() accepts is the start of 100 CE. The
default for this property is September 14, 1752 CE. This default can be
restored with clearMinimumDateTime().
\sa minimumTime(), maximumTime(), setDateRange()
\sa maximumDate, minimumTime, minimumDateTime, setDateRange(), QDate::isValid()
*/
QDate QDateTimeEdit::minimumDate() const
@ -484,13 +487,20 @@ void QDateTimeEdit::clearMinimumDate()
\brief the maximum date of the date time edit
When setting this property the \l minimumDate is adjusted if
necessary to ensure that the range remains valid. If the date is
not a valid QDate object, this function does nothing.
Changing this property updates the date of the \l maximumDateTime property
while preserving the \l maximumTime property. When setting this property, the
\l minimumDate is adjusted, if necessary, to ensure that the range remains
valid. When this happens, the \l minimumTime property is also adjusted if it
is greater than the \l maximumTime property. Otherwise, changes to this
property preserve the \l minimumDateTime property.
By default, this property contains a date that refers to December 31, 9999.
This property can only be set to a valid QDate object describing a date on
which the current \l maximumTime property makes a valid QDateTime object. The
latest date that setMaximumDate() accepts is the end of 9999 CE. This is the
default for this property. This default can be restored with
clearMaximumDateTime().
\sa minimumDate, minimumTime, maximumTime, setDateRange()
\sa minimumDate, maximumTime, maximumDateTime, setDateRange(), QDate::isValid()
*/
QDate QDateTimeEdit::maximumDate() const
@ -502,9 +512,8 @@ QDate QDateTimeEdit::maximumDate() const
void QDateTimeEdit::setMaximumDate(const QDate &max)
{
Q_D(QDateTimeEdit);
if (max.isValid()) {
if (max.isValid())
setMaximumDateTime(QDateTime(max, d->maximum.toTime(), d->spec));
}
}
void QDateTimeEdit::clearMaximumDate()
@ -517,13 +526,18 @@ void QDateTimeEdit::clearMaximumDate()
\brief the minimum time of the date time edit
When setting this property the \l maximumTime is adjusted if
necessary, to ensure that the range remains valid. If the time is
not a valid QTime object, this function does nothing.
Changing this property updates the time of the \l minimumDateTime property
while preserving the \l minimumDate and \l maximumDate properties. If those
date properties coincide, when setting this property, the \l maximumTime
property is adjusted, if necessary, to ensure that the range remains
valid. Otherwise, changing this property preserves the \l maximumDateTime
property.
By default, this property contains a time of 00:00:00 and 0 milliseconds.
This property can be set to any valid QTime value. By default, this property
contains a time of 00:00:00 and 0 milliseconds. This default can be restored
with clearMinimumTime().
\sa maximumTime, minimumDate, maximumDate, setTimeRange()
\sa maximumTime, minimumDate, minimumDateTime, setTimeRange(), QTime::isValid()
*/
QTime QDateTimeEdit::minimumTime() const
@ -551,13 +565,18 @@ void QDateTimeEdit::clearMinimumTime()
\brief the maximum time of the date time edit
When setting this property, the \l minimumTime is adjusted if
necessary to ensure that the range remains valid. If the time is
not a valid QTime object, this function does nothing.
Changing this property updates the time of the \l maximumDateTime property
while preserving the \l minimumDate and \l maximumDate properties. If those
date properties coincide, when setting this property, the \l minimumTime
property is adjusted, if necessary, to ensure that the range remains
valid. Otherwise, changing this property preserves the \l minimumDateTime
property.
By default, this property contains a time of 23:59:59 and 999 milliseconds.
This property can be set to any valid QTime value. By default, this property
contains a time of 23:59:59 and 999 milliseconds. This default can be restored
with clearMaximumTime().
\sa minimumTime, minimumDate, maximumDate, setTimeRange()
\sa minimumTime, maximumDate, maximumDateTime, setTimeRange(), QTime::isValid()
*/
QTime QDateTimeEdit::maximumTime() const
{
@ -580,8 +599,10 @@ void QDateTimeEdit::clearMaximumTime()
}
/*!
Convenience function to set minimum and maximum date with one
function call.
\brief Set the range of allowed dates for the date time edit.
This convenience function sets the \l minimumDate and \l maximumDate
properties.
\snippet code/src_gui_widgets_qdatetimeedit.cpp 3
@ -589,12 +610,14 @@ void QDateTimeEdit::clearMaximumTime()
\snippet code/src_gui_widgets_qdatetimeedit.cpp 4
If either \a min or \a max are not valid, this function does
nothing.
If either \a min or \a max is invalid, this function does nothing. This
function preserves the \l minimumTime property. If \a max is less than \a min,
the new maximumDateTime property shall be the new minimumDateTime property. If
\a max is equal to \a min and the \l maximumTime property was less then the \l
minimumTime property, the \l maximumTime property is set to the \l minimumTime
property. Otherwise, this preserves the \l maximumTime property.
\sa setMinimumDate(), maximumDate(), setMaximumDate(),
clearMinimumDate(), setMinimumTime(), maximumTime(),
setMaximumTime(), clearMinimumTime(), QDate::isValid()
\sa minimumDate, maximumDate, setDateTimeRange(), QDate::isValid()
*/
void QDateTimeEdit::setDateRange(const QDate &min, const QDate &max)
@ -607,8 +630,16 @@ void QDateTimeEdit::setDateRange(const QDate &min, const QDate &max)
}
/*!
Convenience function to set minimum and maximum time with one
function call.
\brief Set the range of allowed times for the date time edit.
This convenience function sets the \l minimumTime and \l maximumTime
properties.
Note that these only constrain the date time edit's value on,
respectively, the \l minimumDate and \l maximumDate. When these date
properties do not coincide, times after \a maximumTime are allowed on dates
before \l maximumDate and times before \a minimumTime are allowed on dates
after \l minimumDate.
\snippet code/src_gui_widgets_qdatetimeedit.cpp 5
@ -616,12 +647,11 @@ void QDateTimeEdit::setDateRange(const QDate &min, const QDate &max)
\snippet code/src_gui_widgets_qdatetimeedit.cpp 6
If either \a min or \a max are not valid, this function does
nothing.
If either \a min or \a max is invalid, this function does nothing. This
function preserves the \l minimumDate and \l maximumDate properties. If those
properties coincide and max is \a less than \a min, \a min is used as \a max.
\sa setMinimumDate(), maximumDate(), setMaximumDate(),
clearMinimumDate(), setMinimumTime(), maximumTime(),
setMaximumTime(), clearMinimumTime(), QTime::isValid()
\sa minimumTime, maximumTime, setDateTimeRange(), QTime::isValid()
*/
void QDateTimeEdit::setTimeRange(const QTime &min, const QTime &max)
@ -865,7 +895,7 @@ QString QDateTimeEdit::sectionText(Section section) const
Note that if you specify a two digit year, it will be interpreted
to be in the century in which the date time edit was initialized.
The default century is the 21 (2000-2099).
The default century is the 21st (2000-2099).
If you specify an invalid format the format will not be set.

View File

@ -1216,8 +1216,8 @@ QMargins QLineEdit::textMargins() const
\row \li \c a \li ASCII alphabetic character permitted but not required.
\row \li \c N \li ASCII alphanumeric character required. A-Z, a-z, 0-9.
\row \li \c n \li ASCII alphanumeric character permitted but not required.
\row \li \c X \li Any character required.
\row \li \c x \li Any character permitted but not required.
\row \li \c X \li Any non-blank character required.
\row \li \c x \li Any non-blank character permitted but not required.
\row \li \c 9 \li ASCII digit required. 0-9.
\row \li \c 0 \li ASCII digit permitted but not required.
\row \li \c D \li ASCII digit required. 1-9.

View File

@ -792,6 +792,8 @@ void QMenuSloppyState::setSubMenuPopup(const QRect &actionRect, QAction *resetAc
m_use_reset_action = true;
m_time.stop();
m_action_rect = actionRect;
if (m_sub_menu)
QMenuPrivate::get(m_sub_menu)->sloppyState.m_parent = nullptr;
m_sub_menu = subMenu;
QMenuPrivate::get(subMenu)->sloppyState.m_parent = this;
m_reset_action = resetAction;

View File

@ -846,7 +846,8 @@ QMenu *QMenuBar::addMenu(const QIcon &icon, const QString &title)
}
/*!
Appends \a menu to the menu bar. Returns the menu's menuAction().
Appends \a menu to the menu bar. Returns the menu's menuAction(). The menu bar
does not take ownership of the menu.
\note The returned QAction object can be used to hide the corresponding
menu.

View File

@ -2328,6 +2328,7 @@ void QPlainTextEdit::changeEvent(QEvent *e)
d->autoScrollTimer.stop();
} else if (e->type() == QEvent::EnabledChange) {
e->setAccepted(isEnabled());
d->control->setPalette(palette());
d->sendControlEvent(e);
} else if (e->type() == QEvent::PaletteChange) {
d->control->setPalette(palette());

View File

@ -1090,7 +1090,7 @@ bool QWidgetLineControl::isValidInput(QChar key, QChar mask) const
return true;
break;
case 'X':
if (key.isPrint())
if (key.isPrint() && key != m_blank)
return true;
break;
case 'x':

View File

@ -1283,6 +1283,8 @@ void QWidgetTextControlPrivate::keyPressEvent(QKeyEvent *e)
} else {
QTextCursor localCursor = cursor;
localCursor.deletePreviousChar();
if (cursor.d)
cursor.d->setX();
}
goto accept;
}
@ -1322,9 +1324,13 @@ void QWidgetTextControlPrivate::keyPressEvent(QKeyEvent *e)
else if (e == QKeySequence::Delete) {
QTextCursor localCursor = cursor;
localCursor.deleteChar();
if (cursor.d)
cursor.d->setX();
} else if (e == QKeySequence::Backspace) {
QTextCursor localCursor = cursor;
localCursor.deletePreviousChar();
if (cursor.d)
cursor.d->setX();
}else if (e == QKeySequence::DeleteEndOfWord) {
if (!cursor.hasSelection())
cursor.movePosition(QTextCursor::NextWord, QTextCursor::KeepAnchor);

View File

@ -28,7 +28,7 @@
#include <QtCore/qglobal.h>
#if QT_HAS_INCLUDE(<stdbool.h>) || __STDC_VERSION__ >= 199901L
#if __has_include(<stdbool.h>) || __STDC_VERSION__ >= 199901L
# include <stdbool.h>
#else
# undef true

View File

@ -32,7 +32,7 @@
#include <QtCore/QElapsedTimer>
#include <QtTest/QtTest>
#if QT_HAS_INCLUDE(<chrono>)
#if __has_include(<chrono>)
# include <chrono>
#endif
@ -519,7 +519,7 @@ void tst_QDeadlineTimer::expire()
void tst_QDeadlineTimer::stdchrono()
{
#if !QT_HAS_INCLUDE(<chrono>)
#if !__has_include(<chrono>)
QSKIP("std::chrono not found on this system");
#else
using namespace std::chrono;

View File

@ -67,6 +67,7 @@ private slots:
void sendPostedEvents_data();
void sendPostedEvents();
void processEventsOnlySendsQueuedEvents();
void eventLoopExit();
};
bool tst_QEventDispatcher::event(QEvent *e)
@ -314,5 +315,49 @@ void tst_QEventDispatcher::processEventsOnlySendsQueuedEvents()
QCOMPARE(object.eventsReceived, 4);
}
void tst_QEventDispatcher::eventLoopExit()
{
// This test was inspired by QTBUG-79477. A particular
// implementation detail in QCocoaEventDispatcher allowed
// QEventLoop::exit() to fail to really exit the event loop.
// Thus this test is a part of the dispatcher auto-test.
// Imitates QApplication::exec():
QEventLoop mainLoop;
// The test itself is a lambda:
QTimer::singleShot(0, [&mainLoop]() {
// Two more single shots, both will be posted as events
// (zero timeout) and supposed to be processes by the
// mainLoop:
QTimer::singleShot(0, [&mainLoop]() {
// wakeUp triggers QCocoaEventDispatcher into incrementing
// its 'serialNumber':
mainLoop.wakeUp();
// QCocoaEventDispatcher::processEvents() will process
// posted events and execute the second lambda defined below:
QCoreApplication::processEvents();
});
QTimer::singleShot(0, [&mainLoop]() {
// With QCocoaEventDispatcher this is executed while in the
// processEvents (see above) and would fail to actually
// interrupt the loop.
mainLoop.exit();
});
});
bool timeoutObserved = false;
QTimer::singleShot(500, [&timeoutObserved, &mainLoop]() {
// In case the QEventLoop::exit above failed, we have to bail out
// early, not wasting time:
mainLoop.exit();
timeoutObserved = true;
});
mainLoop.exec();
QVERIFY(!timeoutObserved);
}
QTEST_MAIN(tst_QEventDispatcher)
#include "tst_qeventdispatcher.moc"

View File

@ -223,7 +223,7 @@ void tst_QTimer::remainingTimeDuringActivation()
namespace {
#if QT_HAS_INCLUDE(<chrono>)
#if __has_include(<chrono>)
template <typename T>
std::chrono::milliseconds to_ms(T t)
{ return std::chrono::duration_cast<std::chrono::milliseconds>(t); }
@ -233,7 +233,7 @@ namespace {
void tst_QTimer::basic_chrono()
{
#if !QT_HAS_INCLUDE(<chrono>)
#if !__has_include(<chrono>)
QSKIP("This test requires C++11 <chrono> support");
#else
// duplicates zeroTimer, singleShotTimeout, interval and remainingTime
@ -871,7 +871,7 @@ void tst_QTimer::singleShotToFunctors()
void tst_QTimer::singleShot_chrono()
{
#if !QT_HAS_INCLUDE(<chrono>)
#if !__has_include(<chrono>)
QSKIP("This test requires C++11 <chrono> support");
#else
// duplicates singleShotStaticFunctionZeroTimeout and singleShotToFunctors

View File

@ -45,7 +45,7 @@
#include <limits.h>
#include <float.h>
#include <cmath>
#if QT_HAS_INCLUDE(<variant>) && __cplusplus >= 201703L
#if __has_include(<variant>) && __cplusplus >= 201703L
#include <variant>
#endif
#include <QLinkedList>
@ -4568,7 +4568,7 @@ void tst_QVariant::accessSequentialContainerKey()
void tst_QVariant::fromStdVariant()
{
#if QT_HAS_INCLUDE(<variant>) && __cplusplus >= 201703L
#if __has_include(<variant>) && __cplusplus >= 201703L
{
typedef std::variant<int, bool> intorbool_t;
intorbool_t stdvar = 5;

View File

@ -384,7 +384,7 @@ void tst_QCborValue::copyCompare()
QCOMPARE(v, other);
QVERIFY(!(v != other));
QVERIFY(!(v < other));
#if 0 && QT_HAS_INCLUDE(<compare>)
#if 0 && __has_include(<compare>)
QVERIFY(v <= other);
QVERIFY(v >= other);
QVERIFY(!(v > other));
@ -821,9 +821,37 @@ void tst_QCborValue::mapMutation()
QVERIFY(v.isUndefined());
// now mutate the list
// simple -> HasByteData
const QString strValue = QStringLiteral("value");
v = strValue;
QVERIFY(v.isString());
QCOMPARE(v, QCborValue(strValue));
QCOMPARE(m, QCborMap({{42, strValue}}));
// HasByteData -> HasByteData
const QLatin1String otherStrValue("othervalue");
v = otherStrValue;
QVERIFY(v.isString());
QCOMPARE(v, QCborValue(otherStrValue));
QCOMPARE(m, QCborMap({{42, otherStrValue}}));
// HasByteData -> simple
v = 42;
QVERIFY(v.isInteger());
QCOMPARE(v, QCborValue(42));
QCOMPARE(m, QCborMap({{42, 42}}));
// simple -> container
v = QCborArray{1, 2, 3};
QVERIFY(v.isArray());
QCOMPARE(v, QCborArray({1, 2, 3}));
QCOMPARE(m, QCborMap({{42, QCborArray{1, 2, 3}}}));
// container -> simple
v = true;
QVERIFY(v.isBool());
QVERIFY(v.isTrue());
QCOMPARE(m, QCborMap({{42, true}}));
QVERIFY(m.begin()->isTrue());
QVERIFY(m.begin().value() == v);
QVERIFY(v == m.begin().value());

View File

@ -89,7 +89,7 @@ enum {
waitTime = 100
};
#if QT_HAS_INCLUDE(<chrono>)
#if __has_include(<chrono>)
static Q_CONSTEXPR std::chrono::milliseconds waitTimeAsDuration(waitTime);
#endif
@ -100,7 +100,7 @@ void tst_QMutex::convertToMilliseconds_data()
QTest::addColumn<qint64>("intValue");
QTest::addColumn<qint64>("expected");
#if !QT_HAS_INCLUDE(<chrono>)
#if !__has_include(<chrono>)
QSKIP("This test requires <chrono>");
#endif
@ -156,7 +156,7 @@ void tst_QMutex::convertToMilliseconds_data()
void tst_QMutex::convertToMilliseconds()
{
#if !QT_HAS_INCLUDE(<chrono>)
#if !__has_include(<chrono>)
QSKIP("This test requires <chrono>");
#else
QFETCH(TimeUnit, unit);
@ -325,7 +325,7 @@ void tst_QMutex::tryLock_non_recursive()
}
void tst_QMutex::try_lock_for_non_recursive() {
#if !QT_HAS_INCLUDE(<chrono>)
#if !__has_include(<chrono>)
QSKIP("This test requires <chrono>");
#else
class Thread : public QThread
@ -454,7 +454,7 @@ void tst_QMutex::try_lock_for_non_recursive() {
void tst_QMutex::try_lock_until_non_recursive()
{
#if !QT_HAS_INCLUDE(<chrono>)
#if !__has_include(<chrono>)
QSKIP("This test requires <chrono>");
#else
class Thread : public QThread
@ -707,7 +707,7 @@ void tst_QMutex::tryLock_recursive()
void tst_QMutex::try_lock_for_recursive()
{
#if !QT_HAS_INCLUDE(<chrono>)
#if !__has_include(<chrono>)
QSKIP("This test requires <chrono>");
#else
class Thread : public QThread
@ -836,7 +836,7 @@ void tst_QMutex::try_lock_for_recursive()
void tst_QMutex::try_lock_until_recursive()
{
#if !QT_HAS_INCLUDE(<chrono>)
#if !__has_include(<chrono>)
QSKIP("This test requires <chrono>");
#else
class Thread : public QThread

View File

@ -150,6 +150,7 @@ private slots:
void timeZones() const;
void systemTimeZoneChange() const;
void invalid_data() const;
void invalid() const;
void range() const;
@ -2209,6 +2210,13 @@ void tst_QDateTime::fromStringDateFormat_data()
<< Qt::TextDate << QDateTime(QDate(2013, 5, 6), QTime(1, 2, 3, 456));
// Test Qt::ISODate format.
QTest::newRow("trailing space") // QTBUG-80445
<< QString("2000-01-02 03:04:05.678 ")
<< Qt::ISODate << QDateTime(QDate(2000, 1, 2), QTime(3, 4, 5, 678));
QTest::newRow("space before millis")
<< QString("2000-01-02 03:04:05. 678") << Qt::ISODate << QDateTime();
// Normal usage:
QTest::newRow("ISO +01:00") << QString::fromLatin1("1987-02-13T13:24:51+01:00")
<< Qt::ISODate << QDateTime(QDate(1987, 2, 13), QTime(12, 24, 51), Qt::UTC);
QTest::newRow("ISO +00:01") << QString::fromLatin1("1987-02-13T13:24:51+00:01")
@ -2229,11 +2237,17 @@ void tst_QDateTime::fromStringDateFormat_data()
<< Qt::ISODate << QDateTime(QDate(2014, 12, 15), QTime(15, 37, 9), Qt::UTC);
QTest::newRow("ISO zzz-3") << QString::fromLatin1("2014-12-15T12:37:09.745-3")
<< Qt::ISODate << QDateTime(QDate(2014, 12, 15), QTime(15, 37, 9, 745), Qt::UTC);
QTest::newRow("ISO lower-case") << QString::fromLatin1("2005-06-28T07:57:30.002z")
<< Qt::ISODate << QDateTime(QDate(2005, 6, 28), QTime(7, 57, 30, 2), Qt::UTC);
// No time specified - defaults to Qt::LocalTime.
QTest::newRow("ISO data3") << QString::fromLatin1("2002-10-01")
<< Qt::ISODate << QDateTime(QDate(2002, 10, 1), QTime(0, 0, 0, 0), Qt::LocalTime);
// Excess digits in milliseconds, round correctly:
QTest::newRow("ISO") << QString::fromLatin1("2005-06-28T07:57:30.0010000000Z")
<< Qt::ISODate << QDateTime(QDate(2005, 6, 28), QTime(7, 57, 30, 1), Qt::UTC);
QTest::newRow("ISO rounding") << QString::fromLatin1("2005-06-28T07:57:30.0015Z")
<< Qt::ISODate << QDateTime(QDate(2005, 6, 28), QTime(7, 57, 30, 2), Qt::UTC);
// ... and accept comma as separator:
QTest::newRow("ISO with comma 1") << QString::fromLatin1("2005-06-28T07:57:30,0040000000Z")
<< Qt::ISODate << QDateTime(QDate(2005, 6, 28), QTime(7, 57, 30, 4), Qt::UTC);
QTest::newRow("ISO with comma 2") << QString::fromLatin1("2005-06-28T07:57:30,0015Z")
@ -2458,6 +2472,7 @@ void tst_QDateTime::fromStringStringFormat_data()
if (southBrazil.isValid()) {
QTest::newRow("spring-forward-midnight")
<< QString("2008-10-19 23:45.678 America/Sao_Paulo") << QString("yyyy-MM-dd mm:ss.zzz t")
// That's in the hour skipped - expect the matching time after the spring-forward, in DST:
<< QDateTime(QDate(2008, 10, 19), QTime(1, 23, 45, 678), southBrazil);
}
#endif
@ -3359,6 +3374,9 @@ void tst_QDateTime::timeZones() const
QCOMPARE(utc.date(), utcDst.date());
QCOMPARE(utc.time(), utcDst.time());
// Crash test, QTBUG-80146:
QVERIFY(!nzStd.toTimeZone(QTimeZone()).isValid());
// Sydney is 2 hours behind New Zealand
QTimeZone ausTz = QTimeZone("Australia/Sydney");
QDateTime aus = nzStd.toTimeZone(ausTz);
@ -3528,23 +3546,42 @@ void tst_QDateTime::systemTimeZoneChange() const
QCOMPARE(tzDate.toMSecsSinceEpoch(), tzMsecs);
}
void tst_QDateTime::invalid_data() const
{
QTest::addColumn<QDateTime>("when");
QTest::addColumn<Qt::TimeSpec>("spec");
QTest::addColumn<bool>("goodZone");
QTest::newRow("default") << QDateTime() << Qt::LocalTime << true;
QDateTime invalidDate = QDateTime(QDate(0, 0, 0), QTime(-1, -1, -1));
QTest::newRow("simple") << invalidDate << Qt::LocalTime << true;
QTest::newRow("UTC") << invalidDate.toUTC() << Qt::UTC << true;
QTest::newRow("offset")
<< invalidDate.toOffsetFromUtc(3600) << Qt::OffsetFromUTC << true;
QTest::newRow("CET")
<< invalidDate.toTimeZone(QTimeZone("Europe/Oslo")) << Qt::TimeZone << true;
// Crash tests, QTBUG-80146:
QTest::newRow("nozone+construct")
<< QDateTime(QDate(1970, 1, 1), QTime(12, 0), QTimeZone()) << Qt::TimeZone << false;
QTest::newRow("nozone+fromMSecs")
<< QDateTime::fromMSecsSinceEpoch(42, QTimeZone()) << Qt::TimeZone << false;
QDateTime valid(QDate(1970, 1, 1), QTime(12, 0), Qt::UTC);
QTest::newRow("tonozone") << valid.toTimeZone(QTimeZone()) << Qt::TimeZone << false;
}
void tst_QDateTime::invalid() const
{
QDateTime invalidDate = QDateTime(QDate(0, 0, 0), QTime(-1, -1, -1));
QCOMPARE(invalidDate.isValid(), false);
QCOMPARE(invalidDate.timeSpec(), Qt::LocalTime);
QDateTime utcDate = invalidDate.toUTC();
QCOMPARE(utcDate.isValid(), false);
QCOMPARE(utcDate.timeSpec(), Qt::UTC);
QDateTime offsetDate = invalidDate.toOffsetFromUtc(3600);
QCOMPARE(offsetDate.isValid(), false);
QCOMPARE(offsetDate.timeSpec(), Qt::OffsetFromUTC);
QDateTime tzDate = invalidDate.toTimeZone(QTimeZone("Europe/Oslo"));
QCOMPARE(tzDate.isValid(), false);
QCOMPARE(tzDate.timeSpec(), Qt::TimeZone);
QFETCH(QDateTime, when);
QFETCH(Qt::TimeSpec, spec);
QFETCH(bool, goodZone);
QVERIFY(!when.isValid());
QCOMPARE(when.timeSpec(), spec);
QCOMPARE(when.timeZoneAbbreviation(), QString());
if (!goodZone)
QCOMPARE(when.toMSecsSinceEpoch(), 0);
QVERIFY(!when.isDaylightTime());
QCOMPARE(when.timeZone().isValid(), goodZone);
}
void tst_QDateTime::range() const

View File

@ -51,7 +51,7 @@
#ifdef Q_CC_MSVC
#define COMPILER_HAS_STDLIB_INCLUDE(x) 1
#else
#define COMPILER_HAS_STDLIB_INCLUDE(x) QT_HAS_INCLUDE(x)
#define COMPILER_HAS_STDLIB_INCLUDE(x) __has_include(x)
#endif
#if COMPILER_HAS_STDLIB_INCLUDE(<forward_list>)

View File

@ -125,6 +125,7 @@ private slots:
void clonePreservesResources();
void clonePreservesUserStates();
void clonePreservesIndentWidth();
void clonePreservesFormatsWhenEmpty();
void blockCount();
void defaultStyleSheet();
@ -2348,6 +2349,32 @@ void tst_QTextDocument::clonePreservesIndentWidth()
delete clone;
}
void tst_QTextDocument::clonePreservesFormatsWhenEmpty()
{
QTextDocument document;
QTextCursor cursor(&document);
// Change a few char format attributes
QTextCharFormat charFormat;
charFormat.setFontPointSize(charFormat.fontPointSize() + 1);
charFormat.setFontWeight(charFormat.fontWeight() + 1);
cursor.setBlockCharFormat(charFormat);
// Change a few block format attributes
QTextBlockFormat blockFormat;
blockFormat.setAlignment(Qt::AlignRight); // The default is Qt::AlignLeft
blockFormat.setIndent(blockFormat.indent() + 1);
cursor.setBlockFormat(blockFormat);
auto clone = document.clone();
QTextCursor cloneCursor(clone);
QCOMPARE(cloneCursor.blockCharFormat().fontPointSize(), charFormat.fontPointSize());
QCOMPARE(cloneCursor.blockCharFormat().fontWeight(), charFormat.fontWeight());
QCOMPARE(cloneCursor.blockFormat().alignment(), blockFormat.alignment());
QCOMPARE(cloneCursor.blockFormat().indent(), blockFormat.indent());
}
void tst_QTextDocument::blockCount()
{
QCOMPARE(doc->blockCount(), 1);

View File

@ -1,3 +0,0 @@
# QTBUG-65667
[localAddress:linklocal-ipv4]
windows ci

View File

@ -215,31 +215,45 @@ void tst_QNetworkInterface::loopbackIPv6()
}
void tst_QNetworkInterface::localAddress_data()
{
bool ipv6 = isIPv6Working();
QTest::addColumn<QHostAddress>("target");
QTest::newRow("localhost-ipv4") << QHostAddress(QHostAddress::LocalHost);
if (isIPv6Working())
if (ipv6)
QTest::newRow("localhost-ipv6") << QHostAddress(QHostAddress::LocalHostIPv6);
QTest::newRow("test-server") << QtNetworkSettings::serverIP();
// Since we don't actually transmit anything, we can list any IPv4 address
// and it should work. But we're using a linklocal address so that this
// test can pass even machines that failed to reach a DHCP server.
QTest::newRow("linklocal-ipv4") << QHostAddress("169.254.0.1");
QSet<QHostAddress> added;
const QList<QNetworkInterface> ifaces = QNetworkInterface::allInterfaces();
for (const QNetworkInterface &iface : ifaces) {
if ((iface.flags() & QNetworkInterface::IsUp) == 0)
continue;
const QList<QNetworkAddressEntry> addrs = iface.addressEntries();
for (const QNetworkAddressEntry &entry : addrs) {
QHostAddress addr = entry.ip();
if (addr.isLoopback())
continue; // added above
if (isIPv6Working()) {
// On the other hand, we can't list just any IPv6 here. It's very
// likely that this machine has not received a route via ICMPv6-RA or
// DHCPv6, so it won't have a global route. On some OSes, IPv6 may be
// enabled per interface, so we need to know which ones work.
const QList<QHostAddress> addrs = QNetworkInterface::allAddresses();
for (const QHostAddress &addr : addrs) {
QString scope = addr.scopeId();
if (scope.isEmpty())
if (addr.protocol() == QAbstractSocket::IPv4Protocol) {
// add an IPv4 address with bits in the host portion of the address flipped
quint32 ip4 = entry.ip().toIPv4Address();
addr.setAddress(ip4 ^ ~entry.netmask().toIPv4Address());
} else if (!ipv6 || entry.prefixLength() != 64) {
continue;
QTest::addRow("linklocal-ipv6-%s", qPrintable(scope))
<< QHostAddress("fe80::1234%" + scope);
} else {
// add a random node in this IPv6 network
quint64 randomid = qFromBigEndian(Q_UINT64_C(0x8f41f072e5733caa));
QIPv6Address ip6 = addr.toIPv6Address();
memcpy(&ip6[8], &randomid, sizeof(randomid));
addr.setAddress(ip6);
}
if (added.contains(addr))
continue;
added.insert(addr);
QTest::addRow("%s-%s", qPrintable(iface.name()), qPrintable(addr.toString())) << addr;
}
}
}

View File

@ -965,9 +965,7 @@ void tst_QSqlQuery::blob()
//don' make it too big otherwise sybase and mysql will complain
QByteArray ba( BLOBSIZE, 0 );
int i;
for ( i = 0; i < ( int )ba.size(); ++i )
for (int i = 0; i < ba.size(); ++i)
ba[i] = i % 256;
QSqlQuery q( db );
@ -980,7 +978,7 @@ void tst_QSqlQuery::blob()
QVERIFY_SQL(q, prepare("insert into " + qTableName("qtest_blob", __FILE__, db) + " (id, t_blob) values (?, ?)"));
for ( i = 0; i < BLOBCOUNT; ++i ) {
for (int i = 0; i < BLOBCOUNT; ++i) {
q.addBindValue( i );
q.addBindValue( ba );
QVERIFY_SQL( q, exec() );
@ -988,13 +986,13 @@ void tst_QSqlQuery::blob()
QVERIFY_SQL(q, exec("select * from " + qTableName("qtest_blob", __FILE__, db)));
for ( i = 0; i < BLOBCOUNT; ++i ) {
for (int i = 0; i < BLOBCOUNT; ++i) {
QVERIFY( q.next() );
QByteArray res = q.value( 1 ).toByteArray();
QVERIFY2( res.size() >= ba.size(),
QString( "array sizes differ, expected %1, got %2" ).arg( ba.size() ).arg( res.size() ).toLatin1() );
for ( int i2 = 0; i2 < ( int )ba.size(); ++i2 ) {
for (int i2 = 0; i2 < ba.size(); ++i2) {
if ( res[i2] != ba[i2] )
QFAIL( QString( "ByteArrays differ at position %1, expected %2, got %3" ).arg(
i2 ).arg(( int )( unsigned char )ba[i2] ).arg(( int )( unsigned char )res[i2] ).toLatin1() );
@ -1834,7 +1832,7 @@ void tst_QSqlQuery::oci_rawField()
}
// test whether we can fetch values with more than DOUBLE precision
// note that MySQL's 3.x highest precision is that of a double, although
// note that SQLite highest precision is that of a double, although
// you can define field with higher precision
void tst_QSqlQuery::precision()
{
@ -1845,46 +1843,41 @@ void tst_QSqlQuery::precision()
if (dbType == QSqlDriver::Interbase)
QSKIP("DB unable to store high precision");
const auto oldPrecision = db.driver()->numericalPrecisionPolicy();
db.driver()->setNumericalPrecisionPolicy(QSql::HighPrecision);
const QString qtest_precision(qTableName("qtest_precision", __FILE__, db));
static const char precStr[] = "1.2345678901234567891";
const int precStrLen = sizeof(precStr);
static const QLatin1String precStr("1.2345678901234567891");
{
// need a new scope for SQLITE
QSqlQuery q( db );
q.exec("drop table " + qtest_precision);
if ( tst_Databases::isMSAccess( db ) )
QVERIFY_SQL( q, exec( "create table " + qtest_precision + " (col1 number)" ) );
if (tst_Databases::isMSAccess(db))
QVERIFY_SQL(q, exec("CREATE TABLE " + qtest_precision + " (col1 number)"));
else
QVERIFY_SQL( q, exec( "create table " + qtest_precision + " (col1 numeric(21, 20))" ) );
QVERIFY_SQL(q, exec("CREATE TABLE " + qtest_precision + " (col1 numeric(21, 20))"));
QVERIFY_SQL( q, exec( "insert into " + qtest_precision + " (col1) values (1.2345678901234567891)" ) );
QVERIFY_SQL( q, exec( "select * from " + qtest_precision ) );
QVERIFY( q.next() );
QString val = q.value( 0 ).toString();
if ( !val.startsWith( "1.2345678901234567891" ) ) {
QVERIFY_SQL(q, exec("INSERT INTO " + qtest_precision + " (col1) VALUES (" + precStr + ")"));
QVERIFY_SQL(q, exec("SELECT * FROM " + qtest_precision));
QVERIFY(q.next());
const QString val = q.value(0).toString();
if (!val.startsWith(precStr)) {
int i = 0;
while ( i < precStrLen && i < val.size() && precStr[i] != 0 && *( precStr + i ) == val[i].toLatin1() )
while (i < val.size() && precStr[i] != 0 && precStr[i] == val[i].toLatin1())
i++;
// MySQL and TDS have crappy precisions by default
if (dbType == QSqlDriver::MySqlServer) {
if ( i < 17 )
QWARN( "MySQL didn't return the right precision" );
} else if (dbType == QSqlDriver::Sybase) {
if ( i < 18 )
QWARN( "TDS didn't return the right precision" );
// TDS has crappy precisions by default
if (dbType == QSqlDriver::Sybase) {
if (i < 18)
QWARN("TDS didn't return the right precision");
} else {
QWARN( QString( tst_Databases::dbToString( db ) + " didn't return the right precision (" +
QString::number( i ) + " out of 21), " + val ).toLatin1() );
QWARN(QString(tst_Databases::dbToString(db) + " didn't return the right precision (" +
QString::number(i) + " out of 21), " + val).toUtf8());
}
}
} // SQLITE scope
db.driver()->setNumericalPrecisionPolicy(oldPrecision);
}
void tst_QSqlQuery::nullResult()
@ -2840,10 +2833,11 @@ void tst_QSqlQuery::psql_bindWithDoubleColonCastOperator()
QVERIFY_SQL( q, exec() );
QVERIFY_SQL( q, next() );
if ( db.driver()->hasFeature( QSqlDriver::PreparedQueries ) )
QCOMPARE( q.executedQuery(), QString( "select sum((fld1 - fld2)::int) from " + tablename + " where id1 = ? and id2 =? and id3=?" ) );
// the positional placeholders are converted to named placeholders in executedQuery()
if (db.driver()->hasFeature(QSqlDriver::PreparedQueries))
QCOMPARE(q.executedQuery(), QString("select sum((fld1 - fld2)::int) from " + tablename + " where id1 = :myid1 and id2 =:myid2 and id3=:myid3"));
else
QCOMPARE( q.executedQuery(), QString( "select sum((fld1 - fld2)::int) from " + tablename + " where id1 = 1 and id2 =2 and id3=3" ) );
QCOMPARE(q.executedQuery(), QString("select sum((fld1 - fld2)::int) from " + tablename + " where id1 = 1 and id2 =2 and id3=3"));
}
void tst_QSqlQuery::psql_specialFloatValues()
@ -4003,8 +3997,8 @@ void tst_QSqlQuery::QTBUG_2192()
// Check if retrieved value preserves reported precision
int precision = qMax(0, q.record().field("dt").precision());
int diff = qAbs(q.value(0).toDateTime().msecsTo(dt));
int keep = qMin(1000, (int)qPow(10.0, precision));
qint64 diff = qAbs(q.value(0).toDateTime().msecsTo(dt));
qint64 keep = qMin(1000LL, qRound64(qPow(10.0, precision)));
QVERIFY(diff <= 1000 - keep);
}
}
@ -4021,8 +4015,10 @@ void tst_QSqlQuery::QTBUG_36211()
QSqlQuery q(db);
QVERIFY_SQL(q, exec(QString("CREATE TABLE %1 (dtwtz timestamptz, dtwotz timestamp)").arg(tableName)));
QTimeZone l_tzBrazil("BRT");
QTimeZone l_tzChina("CST");
QTimeZone l_tzBrazil("America/Sao_Paulo");
QTimeZone l_tzChina("Asia/Shanghai");
QVERIFY(l_tzBrazil.isValid());
QVERIFY(l_tzChina.isValid());
QDateTime dt = QDateTime(QDate(2014, 10, 30), QTime(14, 12, 02, 357));
QVERIFY_SQL(q, prepare("INSERT INTO " + tableName + " (dtwtz, dtwotz) VALUES (:dt, :dt)"));
q.bindValue(":dt", dt);
@ -4040,8 +4036,8 @@ void tst_QSqlQuery::QTBUG_36211()
for (int j = 0; j < 2; ++j) {
// Check if retrieved value preserves reported precision
int precision = qMax(0, q.record().field(j).precision());
int diff = qAbs(q.value(j).toDateTime().msecsTo(dt));
int keep = qMin(1000, (int)qPow(10.0, precision));
qint64 diff = qAbs(q.value(j).toDateTime().msecsTo(dt));
qint64 keep = qMin(1000LL, qRound64(qPow(10.0, precision)));
QVERIFY(diff <= 1000 - keep);
}
}

View File

@ -1380,6 +1380,7 @@ void tst_QFiledialog::clearLineEdit()
fd.setFileMode(QFileDialog::AnyFile);
fd.show();
QVERIFY(QTest::qWaitForWindowExposed(&fd));
QLineEdit *lineEdit = fd.findChild<QLineEdit*>("fileNameEdit");
QVERIFY(lineEdit);
QCOMPARE(lineEdit->text(), QLatin1String("foo"));

View File

@ -60,6 +60,7 @@
#include <QtGui/qpaintengine.h>
#include <QtGui/qbackingstore.h>
#include <QtGui/qguiapplication.h>
#include <QtGui/qpa/qplatformwindow.h>
#include <QtGui/qscreen.h>
#include <qmenubar.h>
#include <qcompleter.h>
@ -227,6 +228,7 @@ private slots:
void setFixedSize();
void ensureCreated();
void createAndDestroy();
void winIdChangeEvent();
void persistentWinId();
void showNativeChild();
@ -4250,6 +4252,58 @@ public:
int winIdChangeEventCount() const { return m_winIdList.count(); }
};
class CreateDestroyWidget : public WinIdChangeWidget
{
public:
void create() { QWidget::create(); }
void destroy() { QWidget::destroy(); }
};
void tst_QWidget::createAndDestroy()
{
CreateDestroyWidget widget;
// Create and destroy via QWidget
widget.create();
QVERIFY(widget.testAttribute(Qt::WA_WState_Created));
QCOMPARE(widget.winIdChangeEventCount(), 1);
QVERIFY(widget.internalWinId());
widget.destroy();
QVERIFY(!widget.testAttribute(Qt::WA_WState_Created));
QCOMPARE(widget.winIdChangeEventCount(), 2);
QVERIFY(!widget.internalWinId());
// Create via QWidget, destroy via QWindow
widget.create();
QVERIFY(widget.testAttribute(Qt::WA_WState_Created));
QCOMPARE(widget.winIdChangeEventCount(), 3);
QVERIFY(widget.internalWinId());
widget.windowHandle()->destroy();
QVERIFY(!widget.testAttribute(Qt::WA_WState_Created));
QCOMPARE(widget.winIdChangeEventCount(), 4);
QVERIFY(!widget.internalWinId());
// Create via QWidget again
widget.create();
QVERIFY(widget.testAttribute(Qt::WA_WState_Created));
QCOMPARE(widget.winIdChangeEventCount(), 5);
QVERIFY(widget.internalWinId());
// Destroy via QWindow, create via QWindow
widget.windowHandle()->destroy();
QVERIFY(widget.windowHandle());
QVERIFY(!widget.testAttribute(Qt::WA_WState_Created));
QCOMPARE(widget.winIdChangeEventCount(), 6);
QVERIFY(!widget.internalWinId());
widget.windowHandle()->create();
QVERIFY(widget.testAttribute(Qt::WA_WState_Created));
QCOMPARE(widget.winIdChangeEventCount(), 7);
QVERIFY(widget.internalWinId());
}
void tst_QWidget::winIdChangeEvent()
{
{

View File

@ -885,9 +885,6 @@ void tst_QLineEdit::hasAcceptableInputMask()
qApp->sendEvent(testWidget, &lostFocus);
QVERIFY(validInput);
// at the moment we don't strip the blank character if it is valid input, this makes the test between x vs X useless
QEXPECT_FAIL( "Any optional and required", "To eat blanks or not? Known issue. Task 43172", Abort);
// test requiredMask
testWidget->setInputMask(requiredMask);
validInput = true;

View File

@ -155,6 +155,7 @@ private slots:
#if QT_CONFIG(scrollbar)
void updateAfterChangeCenterOnScroll();
#endif
void updateCursorPositionAfterEdit();
private:
void createSelection();
@ -1802,5 +1803,50 @@ void tst_QPlainTextEdit::updateAfterChangeCenterOnScroll()
#endif
void tst_QPlainTextEdit::updateCursorPositionAfterEdit()
{
QPlainTextEdit plaintextEdit;
plaintextEdit.setPlainText("some text some text\nsome text some text");
const auto initialPosition = 1;
// select some text
auto cursor = plaintextEdit.textCursor();
cursor.setPosition(initialPosition, QTextCursor::MoveAnchor);
cursor.setPosition(initialPosition + 3, QTextCursor::KeepAnchor);
plaintextEdit.setTextCursor(cursor);
QVERIFY(plaintextEdit.textCursor().hasSelection());
QTest::keyClick(&plaintextEdit, Qt::Key_Delete);
QTest::keyClick(&plaintextEdit, Qt::Key_Down);
QTest::keyClick(&plaintextEdit, Qt::Key_Up);
// Moving the cursor down and up should bring it to the initial position
QCOMPARE(plaintextEdit.textCursor().position(), initialPosition);
// Test the same with backspace
cursor = plaintextEdit.textCursor();
cursor.setPosition(initialPosition + 3, QTextCursor::KeepAnchor);
plaintextEdit.setTextCursor(cursor);
QVERIFY(plaintextEdit.textCursor().hasSelection());
QTest::keyClick(&plaintextEdit, Qt::Key_Backspace);
QTest::keyClick(&plaintextEdit, Qt::Key_Down);
QTest::keyClick(&plaintextEdit, Qt::Key_Up);
// Moving the cursor down and up should bring it to the initial position
QCOMPARE(plaintextEdit.textCursor().position(), initialPosition);
// Test insertion
const QString txt("txt");
QApplication::clipboard()->setText(txt);
plaintextEdit.paste();
QTest::keyClick(&plaintextEdit, Qt::Key_Down);
QTest::keyClick(&plaintextEdit, Qt::Key_Up);
// The curser should move back to the end of the copied text
QCOMPARE(plaintextEdit.textCursor().position(), initialPosition + txt.length());
}
QTEST_MAIN(tst_QPlainTextEdit)
#include "tst_qplaintextedit.moc"

View File

@ -30,7 +30,7 @@
#include <QtTest/QtTest>
#include <QtCore/private/qmemory_p.h>
#include <mutex>
#if QT_HAS_INCLUDE(<shared_mutex>)
#if __has_include(<shared_mutex>)
#if __cplusplus > 201103L
#include <shared_mutex>
#endif

View File

@ -39,6 +39,7 @@
#include <QButtonGroup>
#include <QLineEdit>
#include <QPlainTextEdit>
#include <QTabWidget>
#include <QScrollBar>
#include <QSlider>
#include <QSpinBox>
@ -51,12 +52,14 @@
#include <QGraphicsView>
#include <QGraphicsTextItem>
#include <QFile>
#include <QFontMetrics>
#include <QMouseEvent>
#include <QTemporaryDir>
#include <QTimer>
#include <QCommandLineParser>
#include <QCommandLineOption>
#include <QDebug>
#include <QElapsedTimer>
#include <private/qhighdpiscaling_p.h>
#include <qpa/qplatformscreen.h>
@ -64,6 +67,12 @@
#include <utility>
static QTextStream &operator<<(QTextStream &str, const QSizeF &s)
{
str << s.width() << 'x' << s.height();
return str;
}
static QTextStream &operator<<(QTextStream &str, const QRect &r)
{
str << r.width() << 'x' << r.height() << Qt::forcesign << r.x() << r.y() << Qt::noforcesign;
@ -1241,7 +1250,7 @@ public:
}
};
class MetricsTest : public QWidget
class MetricsTest : public QTabWidget
{
Q_OBJECT
public:
@ -1258,14 +1267,25 @@ QT_SCREEN_SCALE_FACTORS=N;N;N or QT_SCREEN_SCALE_FACTORS=name:N
QT_SCALE_FACTOR_ROUNDING_POLICY=Round|Ceil|Floor|RoundPreferFloor|PassThrough
QT_DPI_ADJUSTMENT_POLICY=AdjustDpi|DontAdjustDpi|AdjustUpOnly)";
resize(480, 360);
m_textEdit = addTextPage("Parameters");
m_logEdit = addTextPage("Screen Change Log");
auto layout = new QVBoxLayout(this);
const auto screens = QGuiApplication::screens();
for (auto screen : screens)
connectScreenChangeSignals(screen);
connect(qApp, &QGuiApplication::screenAdded, this, &MetricsTest::slotScreenAdded);
connect(qApp, &QGuiApplication::primaryScreenChanged, this, &MetricsTest::slotPrimaryScreenChanged);
connect(qApp, &QGuiApplication::screenRemoved, this, &MetricsTest::slotScreenRemoved);
m_textEdit = new QPlainTextEdit;
m_textEdit->setReadOnly(true);
layout->addWidget(m_textEdit);
setWindowTitle(formatWindowTitle("Screens"));
m_logTimer.start();
logMessage(briefFormatScreens());
// Resize to roughly match the metrics text.
const auto metrics = QFontMetrics(m_textEdit->font(), m_textEdit);
const int width = 10 + metrics.horizontalAdvance(QStringLiteral("X")) * 50;
const int height = 40 + metrics.height() * (10 + 8 * screens.size());
resize(width, height);
}
void setVisible(bool visible) override
@ -1323,15 +1343,118 @@ QT_DPI_ADJUSTMENT_POLICY=AdjustDpi|DontAdjustDpi|AdjustUpOnly)";
private slots:
void screenChanged()
{
qDebug().noquote() << __FUNCTION__ << windowHandle()->screen()->name();
const QString message = QLatin1String("screenChanged ") + windowHandle()->screen()->name();
qInfo("%s", qPrintable(message));
logMessage(message);
updateMetrics();
}
void slotScreenAdded(QScreen *);
void slotScreenRemoved(QScreen *);
void slotPrimaryScreenChanged(QScreen *);
void slotScreenGeometryChanged(const QRect &geometry)
{ logScreenChangeSignal(sender(), "geometry", geometry); }
void slotScreenAvailableGeometryChanged(const QRect &geometry)
{ logScreenChangeSignal(sender(), "availableGeometry", geometry); }
void slotScreenPhysicalSizeChanged(const QSizeF &size)
{ logScreenChangeSignal(sender(), "physicalSize", size); }
void slotScreenPhysicalDotsPerInchChanged(qreal dpi)
{ logScreenChangeSignal(sender(), "physicalDotsPerInch", dpi); }
void slotScreenLogicalDotsPerInchChanged(qreal dpi)
{ logScreenChangeSignal(sender(), "logicalDotsPerInch", dpi); }
void slotScreenVirtualGeometryChanged(const QRect &rect)
{ logScreenChangeSignal(sender(), "virtualGeometry", rect); }
void slotScreenPrimaryOrientationChanged(Qt::ScreenOrientation orientation)
{ logScreenChangeSignal(sender(), "primaryOrientation", orientation); }
void slotScreenOrientationChanged(Qt::ScreenOrientation orientation)
{ logScreenChangeSignal(sender(), "orientation", orientation); }
void slotScreenRefreshRateChanged(qreal refreshRate)
{ logScreenChangeSignal(sender(), "refreshRate", refreshRate); }
private:
QPlainTextEdit *addTextPage(const QString &title);
void logMessage(const QString &);
void connectScreenChangeSignals(QScreen *s);
static QString briefFormatScreens();
template <class T>
void logScreenChangeSignal(const QObject *o, const char *name, const T &value);
QPlainTextEdit *m_textEdit;
QPlainTextEdit *m_logEdit;
QElapsedTimer m_logTimer;
bool m_screenChangedConnected = false;
};
void MetricsTest::slotScreenAdded(QScreen *screen)
{
logMessage(QLatin1String("Added ") + screen->name() + QLatin1Char(' ')
+ briefFormatScreens());
connectScreenChangeSignals(screen);
}
void MetricsTest::slotScreenRemoved(QScreen *screen)
{
logMessage(QLatin1String("Removed ") + screen->name() + QLatin1Char(' ')
+ briefFormatScreens());
}
void MetricsTest::slotPrimaryScreenChanged(QScreen *screen)
{
logMessage(QLatin1String("PrimaryScreenChanged ") + screen->name() + QLatin1Char(' ')
+ briefFormatScreens());
}
QPlainTextEdit *MetricsTest::addTextPage(const QString &title)
{
auto result = new QPlainTextEdit(this);
result->setReadOnly(true);
result->setFont(QFontDatabase::systemFont(QFontDatabase::FixedFont));
addTab(result, title);
return result;
}
void MetricsTest::logMessage(const QString &m)
{
const QString timeStamp =
QStringLiteral("%1ms: %2").arg(m_logTimer.elapsed(), 6, 10, QLatin1Char('0')).arg(m);
m_logEdit->appendPlainText(timeStamp);
}
void MetricsTest::connectScreenChangeSignals(QScreen *s)
{
connect(s, &QScreen::geometryChanged, this, &MetricsTest::slotScreenGeometryChanged);
connect(s, &QScreen::availableGeometryChanged, this, &MetricsTest::slotScreenAvailableGeometryChanged);
connect(s, &QScreen::physicalSizeChanged, this, &MetricsTest::slotScreenPhysicalSizeChanged);
connect(s, &QScreen::physicalDotsPerInchChanged, this, &MetricsTest::slotScreenPhysicalDotsPerInchChanged);
connect(s, &QScreen::logicalDotsPerInchChanged, this, &MetricsTest::slotScreenLogicalDotsPerInchChanged);
connect(s, &QScreen::virtualGeometryChanged, this, &MetricsTest::slotScreenVirtualGeometryChanged);
connect(s, &QScreen::primaryOrientationChanged, this, &MetricsTest::slotScreenPrimaryOrientationChanged);
connect(s, &QScreen::orientationChanged, this, &MetricsTest::slotScreenOrientationChanged);
connect(s, &QScreen::refreshRateChanged, this, &MetricsTest::slotScreenRefreshRateChanged);
}
QString MetricsTest::briefFormatScreens()
{
QString message;
QTextStream str(&message);
const auto screens = QGuiApplication::screens();
for (int i = 0, size = screens.size(); i < size; ++i) {
str << (i ? ", " : "(");
str << screens.at(i)->name() << " " << screens.at(i)->geometry();
}
str << ')';
return message;
}
template <class T>
void MetricsTest::logScreenChangeSignal(const QObject *o, const char *name, const T &value)
{
auto screen = qobject_cast<const QScreen *>(o);
QString message;
QTextStream(&message) << (screen ? screen->name() : QString()) << ' ' << name << " changed: " << value;
logMessage(message);
}
int main(int argc, char **argv)
{
#define NOSCALINGOPTION "noscaling"

View File

@ -1,11 +1,20 @@
version: '2.1'
# The tag of images is used by docker compose file to launch the corresponding
# docker containers. The value of tag comes from the provisioning script
# (coin/provisioning/.../testserver/docker_testserver.sh). The script gets SHA-1
# of each server context as the tag of docker images. If one of the server
# contexts gets changes, please make sure to update this compose file as well.
# You can run command 'docker images' to list all the tags of test server images.
# The tag of images is used by docker compose file to launch the correct
# docker containers. By default we always launch the "latest" tag.
#
# But in the "docker build" phase, we also tag the images with a unique tag,
# the SHA1 hash of all files used for "docker build" - see sha1tree() in
# provisioning.
#
# So if you want to update the docker image at a specific time, make sure that
# 1. you modify this file to run the specific image's SHA1 tag, instead of
# "latest"
# 2. you build two docker images in provisioning, the currently used one,
# plus the new one that you tag as "latest"
# 3. you switch this file to the "latest" tag when ready
# You can run `docker images` to list all the tags of available images:
# For example:
# REPOSITORY TAG
# qt-test-server-apache2 537fe302f61851d1663f41495230d8e3554a4a13
@ -20,7 +29,7 @@ services:
build:
context: .
args:
provisioningImage: qt-test-server-apache2:537fe302f61851d1663f41495230d8e3554a4a13
provisioningImage: qt-test-server-apache2:latest
shareDir: ./common
serviceDir: ./apache2
entrypoint: service/startup.sh
@ -43,7 +52,7 @@ services:
build:
context: .
args:
provisioningImage: qt-test-server-squid:9c32f41b19aca3d778733c4d8fb0ecc5955e893c
provisioningImage: qt-test-server-squid:latest
shareDir: ./common
serviceDir: ./squid
entrypoint: service/startup.sh
@ -58,7 +67,7 @@ services:
build:
context: .
args:
provisioningImage: qt-test-server-vsftpd:f3a9c8d793a77cc007c0e4e481bec01f9e3eeb7e
provisioningImage: qt-test-server-vsftpd:latest
shareDir: ./common
serviceDir: ./vsftpd
entrypoint: service/startup.sh
@ -77,7 +86,7 @@ services:
build:
context: .
args:
provisioningImage: qt-test-server-ftp-proxy:d7de8b28392d173db512a558ccc84ead8bece2ae
provisioningImage: qt-test-server-ftp-proxy:latest
shareDir: ./common
serviceDir: ./ftp-proxy
entrypoint: service/startup.sh
@ -102,7 +111,7 @@ services:
build:
context: .
args:
provisioningImage: qt-test-server-danted:35607f9b790524cf9690c7d12a9a401696b7b6b5
provisioningImage: qt-test-server-danted:latest
shareDir: ./common
serviceDir: ./danted
entrypoint: service/startup.sh
@ -117,7 +126,7 @@ services:
build:
context: .
args:
provisioningImage: qt-test-server-cyrus:c8d72754abc0e501afd624ce838e4df35505abc9
provisioningImage: qt-test-server-cyrus:latest
shareDir: ./common
serviceDir: ./cyrus
entrypoint: service/startup.sh
@ -132,7 +141,7 @@ services:
build:
context: .
args:
provisioningImage: qt-test-server-iptables:cb7a8bd6d28602085a88c8ced7d67e28e75781e2
provisioningImage: qt-test-server-iptables:latest
shareDir: ./common
serviceDir: ./iptables
entrypoint: service/startup.sh
@ -150,7 +159,7 @@ services:
build:
context: .
args:
provisioningImage: qt-test-server-echo:b29ad409e746a834c1055fd0f7a55fd5056da6ea
provisioningImage: qt-test-server-echo:latest
shareDir: ./common
serviceDir: ./echo
entrypoint: service/startup.sh

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