Merge remote-tracking branch 'origin/5.11' into dev
Change-Id: Idf471ca5c6cf211813466b539ce45bdc1ae9b97cbb10
commit
332ce6734d
|
|
@ -40,7 +40,7 @@ QMAKE_INCDIR_OPENGL = $$sysrootified
|
|||
QMAKESPEC_NAME = $$basename(QMAKESPEC)
|
||||
|
||||
# Resolve SDK version of various tools
|
||||
for(tool, $$list(QMAKE_CC QMAKE_CXX QMAKE_FIX_RPATH QMAKE_AR QMAKE_RANLIB QMAKE_LINK QMAKE_LINK_SHLIB QMAKE_ACTOOL)) {
|
||||
for(tool, $$list(QMAKE_CC QMAKE_CXX QMAKE_FIX_RPATH QMAKE_AR QMAKE_RANLIB QMAKE_LINK QMAKE_LINK_SHLIB QMAKE_ACTOOL QMAKE_LINK_C QMAKE_LINK_C_SHLIB)) {
|
||||
tool_variable = QMAKE_MAC_SDK.$${QMAKESPEC_NAME}.$${QMAKE_MAC_SDK}.$${tool}
|
||||
!isEmpty($$tool_variable) {
|
||||
$$tool = $$eval($$tool_variable)
|
||||
|
|
|
|||
|
|
@ -909,7 +909,7 @@ Mozilla License) is included. The data is then also used in QNetworkCookieJar::v
|
|||
"condition": "features.journald || features.syslog || (config.qnx && features.slog2)",
|
||||
"message": "journald, syslog or slog2 integration is enabled.
|
||||
If your users intend to develop applications against this build,
|
||||
ensure that the IDEs they use either set QT_LOGGING_TO_CONSOLE to 1
|
||||
ensure that the IDEs they use either set QT_FORCE_STDERR_LOGGING to 1
|
||||
or are able to read the logged output from journald, syslog or slog2."
|
||||
},
|
||||
{
|
||||
|
|
|
|||
|
|
@ -41,6 +41,7 @@
|
|||
|
||||
#include "qglobal_p.h"
|
||||
#include "qlogging.h"
|
||||
#include "qlogging_p.h"
|
||||
#include "qlist.h"
|
||||
#include "qbytearray.h"
|
||||
#include "qstring.h"
|
||||
|
|
@ -204,56 +205,102 @@ static bool isDefaultCategory(const char *category)
|
|||
return !category || strcmp(category, "default") == 0;
|
||||
}
|
||||
|
||||
static bool willLogToConsole()
|
||||
/*!
|
||||
Returns true if writing to \c stderr is supported.
|
||||
|
||||
\sa stderrHasConsoleAttached()
|
||||
*/
|
||||
static bool systemHasStderr()
|
||||
{
|
||||
#if defined(Q_OS_WINRT)
|
||||
// these systems have no stderr, so always log to the system log
|
||||
return false;
|
||||
#else
|
||||
// rules to determine if we'll log preferably to the console:
|
||||
// 1) if QT_LOGGING_TO_CONSOLE is set, it determines behavior:
|
||||
// - if it's set to 0, we will not log to console
|
||||
// - if it's set to 1, we will log to console
|
||||
// 2) otherwise, we will log to console if we have a console window (Windows)
|
||||
// or a controlling TTY (Unix). This is done even if stderr was redirected
|
||||
// to the blackhole device (NUL or /dev/null).
|
||||
|
||||
bool ok = true;
|
||||
uint envcontrol = qgetenv("QT_LOGGING_TO_CONSOLE").toUInt(&ok);
|
||||
if (ok)
|
||||
return envcontrol;
|
||||
|
||||
# ifdef Q_OS_WIN
|
||||
return GetConsoleWindow();
|
||||
# elif defined(Q_OS_UNIX)
|
||||
# ifndef _PATH_TTY
|
||||
# define _PATH_TTY "/dev/tty"
|
||||
# endif
|
||||
// if /dev/tty exists, we can only open it if we have a controlling TTY
|
||||
int devtty = qt_safe_open(_PATH_TTY, O_RDONLY);
|
||||
if (devtty == -1 && (errno == ENOENT || errno == EPERM || errno == ENXIO)) {
|
||||
// no /dev/tty, fall back to isatty on stderr
|
||||
return isatty(STDERR_FILENO);
|
||||
} else if (devtty != -1) {
|
||||
// there is a /dev/tty and we could open it: we have a controlling TTY
|
||||
qt_safe_close(devtty);
|
||||
return true;
|
||||
}
|
||||
|
||||
// no controlling TTY
|
||||
return false;
|
||||
# else
|
||||
# error "Not Unix and not Windows?"
|
||||
# endif
|
||||
return false; // WinRT has no stderr
|
||||
#endif
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
Q_CORE_EXPORT bool qt_logging_to_console()
|
||||
/*!
|
||||
Returns true if writing to \c stderr will end up in a console/terminal visible to the user.
|
||||
|
||||
This is typically the case if the application was started from the command line.
|
||||
|
||||
If the application is started without a controlling console/terminal, but the parent
|
||||
process reads \c stderr and presents it to the user in some other way, the parent process
|
||||
may override the detection in this function by setting the QT_ASSUME_STDERR_HAS_CONSOLE
|
||||
environment variable to \c 1.
|
||||
|
||||
\note Qt Creator does not implement a pseudo TTY, nor does it launch apps with
|
||||
the override environment variable set, but it will read stderr and print it to
|
||||
the user, so in effect this function can not be used to conclude that stderr
|
||||
output will _not_ be visible to the user, as even if this function returns false,
|
||||
the output might still end up visible to the user. For this reason, we don't guard
|
||||
the stderr output in the default message handler with stderrHasConsoleAttached().
|
||||
|
||||
\sa systemHasStderr()
|
||||
*/
|
||||
bool stderrHasConsoleAttached()
|
||||
{
|
||||
static const bool logToConsole = willLogToConsole();
|
||||
return logToConsole;
|
||||
static const bool stderrHasConsoleAttached = []() -> bool {
|
||||
if (!systemHasStderr())
|
||||
return false;
|
||||
|
||||
if (qEnvironmentVariableIntValue("QT_LOGGING_TO_CONSOLE")) {
|
||||
fprintf(stderr, "warning: Environment variable QT_LOGGING_TO_CONSOLE is deprecated, use\n"
|
||||
"QT_ASSUME_STDERR_HAS_CONSOLE and/or QT_FORCE_STDERR_LOGGING instead.\n");
|
||||
return true;
|
||||
}
|
||||
|
||||
if (qEnvironmentVariableIntValue("QT_ASSUME_STDERR_HAS_CONSOLE"))
|
||||
return true;
|
||||
|
||||
#if defined(Q_OS_WIN) && !defined(Q_OS_WINRT)
|
||||
return GetConsoleWindow();
|
||||
#elif defined(Q_OS_UNIX)
|
||||
# ifndef _PATH_TTY
|
||||
# define _PATH_TTY "/dev/tty"
|
||||
# endif
|
||||
|
||||
// If we can open /dev/tty, we have a controlling TTY
|
||||
int ttyDevice = -1;
|
||||
if ((ttyDevice = qt_safe_open(_PATH_TTY, O_RDONLY)) >= 0) {
|
||||
qt_safe_close(ttyDevice);
|
||||
return true;
|
||||
} else if (errno == ENOENT || errno == EPERM || errno == ENXIO) {
|
||||
// Fall back to isatty for some non-critical errors
|
||||
return isatty(STDERR_FILENO);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
#else
|
||||
return false; // No way to detect if stderr has a console attached
|
||||
#endif
|
||||
}();
|
||||
|
||||
return stderrHasConsoleAttached;
|
||||
}
|
||||
|
||||
|
||||
namespace QtPrivate {
|
||||
|
||||
/*!
|
||||
Returns true if logging \c stderr should be ensured.
|
||||
|
||||
This is normally the case if \c stderr has a console attached, but may be overridden
|
||||
by the user by setting the QT_FORCE_STDERR_LOGGING environment variable to \c 1.
|
||||
|
||||
\sa stderrHasConsoleAttached()
|
||||
*/
|
||||
bool shouldLogToStderr()
|
||||
{
|
||||
static bool forceStderrLogging = qEnvironmentVariableIntValue("QT_FORCE_STDERR_LOGGING");
|
||||
return forceStderrLogging || stderrHasConsoleAttached();
|
||||
}
|
||||
|
||||
|
||||
} // QtPrivate
|
||||
|
||||
using namespace QtPrivate;
|
||||
|
||||
/*!
|
||||
\class QMessageLogContext
|
||||
\inmodule QtCore
|
||||
|
|
@ -1472,8 +1519,8 @@ static QBasicAtomicPointer<void (QtMsgType, const QMessageLogContext &, const QS
|
|||
|
||||
static bool slog2_default_handler(QtMsgType type, const QMessageLogContext &context, const QString &message)
|
||||
{
|
||||
if (qt_logging_to_console())
|
||||
return false;
|
||||
if (shouldLogToStderr())
|
||||
return false; // Leave logging up to stderr handler
|
||||
|
||||
QString formattedMessage = qFormatLogMessage(type, context, message);
|
||||
formattedMessage.append(QLatin1Char('\n'));
|
||||
|
|
@ -1528,8 +1575,8 @@ static bool systemd_default_message_handler(QtMsgType type,
|
|||
const QMessageLogContext &context,
|
||||
const QString &message)
|
||||
{
|
||||
if (qt_logging_to_console())
|
||||
return false;
|
||||
if (shouldLogToStderr())
|
||||
return false; // Leave logging up to stderr handler
|
||||
|
||||
QString formattedMessage = qFormatLogMessage(type, context, message);
|
||||
|
||||
|
|
@ -1567,8 +1614,8 @@ static bool systemd_default_message_handler(QtMsgType type,
|
|||
#if QT_CONFIG(syslog)
|
||||
static bool syslog_default_message_handler(QtMsgType type, const QMessageLogContext &context, const QString &message)
|
||||
{
|
||||
if (qt_logging_to_console())
|
||||
return false;
|
||||
if (shouldLogToStderr())
|
||||
return false; // Leave logging up to stderr handler
|
||||
|
||||
QString formattedMessage = qFormatLogMessage(type, context, message);
|
||||
|
||||
|
|
@ -1602,8 +1649,8 @@ static bool android_default_message_handler(QtMsgType type,
|
|||
const QMessageLogContext &context,
|
||||
const QString &message)
|
||||
{
|
||||
if (qt_logging_to_console())
|
||||
return false;
|
||||
if (shouldLogToStderr())
|
||||
return false; // Leave logging up to stderr handler
|
||||
|
||||
QString formattedMessage = qFormatLogMessage(type, context, message);
|
||||
|
||||
|
|
@ -1627,8 +1674,8 @@ static bool android_default_message_handler(QtMsgType type,
|
|||
#ifdef Q_OS_WIN
|
||||
static bool win_message_handler(QtMsgType type, const QMessageLogContext &context, const QString &message)
|
||||
{
|
||||
if (qt_logging_to_console())
|
||||
return false;
|
||||
if (shouldLogToStderr())
|
||||
return false; // Leave logging up to stderr handler
|
||||
|
||||
QString formattedMessage = qFormatLogMessage(type, context, message);
|
||||
formattedMessage.append(QLatin1Char('\n'));
|
||||
|
|
@ -1756,7 +1803,7 @@ static void qt_message_print(const QString &message)
|
|||
OutputDebugString(reinterpret_cast<const wchar_t*>(message.utf16()));
|
||||
return;
|
||||
#elif defined(Q_OS_WIN) && !defined(QT_BOOTSTRAPPED)
|
||||
if (!qt_logging_to_console()) {
|
||||
if (!shouldLogToStderr()) {
|
||||
OutputDebugString(reinterpret_cast<const wchar_t*>(message.utf16()));
|
||||
return;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,64 @@
|
|||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2018 The Qt Company Ltd.
|
||||
** Contact: https://www.qt.io/licensing/
|
||||
**
|
||||
** This file is part of the QtCore module of the Qt Toolkit.
|
||||
**
|
||||
** $QT_BEGIN_LICENSE:LGPL$
|
||||
** Commercial License Usage
|
||||
** Licensees holding valid commercial Qt licenses may use this file in
|
||||
** accordance with the commercial license agreement provided with the
|
||||
** Software or, alternatively, in accordance with the terms contained in
|
||||
** a written agreement between you and The Qt Company. For licensing terms
|
||||
** and conditions see https://www.qt.io/terms-conditions. For further
|
||||
** information use the contact form at https://www.qt.io/contact-us.
|
||||
**
|
||||
** GNU Lesser General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU Lesser
|
||||
** General Public License version 3 as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.LGPL3 included in the
|
||||
** packaging of this file. Please review the following information to
|
||||
** ensure the GNU Lesser General Public License version 3 requirements
|
||||
** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 2.0 or (at your option) the GNU General
|
||||
** Public license version 3 or any later version approved by the KDE Free
|
||||
** Qt Foundation. The licenses are as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
|
||||
** included in the packaging of this file. Please review the following
|
||||
** information to ensure the GNU General Public License requirements will
|
||||
** be met: https://www.gnu.org/licenses/gpl-2.0.html and
|
||||
** https://www.gnu.org/licenses/gpl-3.0.html.
|
||||
**
|
||||
** $QT_END_LICENSE$
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef QLOGGING_P_H
|
||||
#define QLOGGING_P_H
|
||||
|
||||
//
|
||||
// W A R N I N G
|
||||
// -------------
|
||||
//
|
||||
// This file is not part of the Qt API. It exists for the convenience
|
||||
// of a number of Qt sources files. This header file may change from
|
||||
// version to version without notice, or even be removed.
|
||||
//
|
||||
// We mean it.
|
||||
//
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
namespace QtPrivate {
|
||||
|
||||
Q_CORE_EXPORT bool shouldLogToStderr();
|
||||
|
||||
}
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
||||
#endif // QLOGGING_P_H
|
||||
|
|
@ -175,8 +175,12 @@ public:
|
|||
void append(const T *buf, int size);
|
||||
inline QVarLengthArray<T, Prealloc> &operator<<(const T &t)
|
||||
{ append(t); return *this; }
|
||||
inline QVarLengthArray<T, Prealloc> &operator<<(T &&t)
|
||||
{ append(t); return *this; }
|
||||
inline QVarLengthArray<T, Prealloc> &operator+=(const T &t)
|
||||
{ append(t); return *this; }
|
||||
inline QVarLengthArray<T, Prealloc> &operator+=(T &&t)
|
||||
{ append(t); return *this; }
|
||||
|
||||
void prepend(T &&t);
|
||||
void prepend(const T &t);
|
||||
|
|
|
|||
|
|
@ -832,6 +832,14 @@
|
|||
\sa append(), operator+=()
|
||||
*/
|
||||
|
||||
/*! \fn template<class T, int Prealloc> QVarLengthArray<T, Prealloc> &QVarLengthArray<T, Prealloc>::operator<<(T &&value)
|
||||
\since 5.11
|
||||
|
||||
\overload
|
||||
|
||||
\sa append(), operator+=()
|
||||
*/
|
||||
|
||||
/*! \fn template<class T, int Prealloc> QVarLengthArray<T, Prealloc> &QVarLengthArray<T, Prealloc>::operator+=(const T &value)
|
||||
|
||||
\since 4.8
|
||||
|
|
@ -840,6 +848,14 @@
|
|||
\sa append(), operator<<()
|
||||
*/
|
||||
|
||||
/*! \fn template<class T, int Prealloc> QVarLengthArray<T, Prealloc> &QVarLengthArray<T, Prealloc>::operator+=(T &&value)
|
||||
\since 5.11
|
||||
|
||||
\overload
|
||||
|
||||
\sa append(), operator<<()
|
||||
*/
|
||||
|
||||
/*! \fn template<class T, int Prealloc> int QVarLengthArray<T, Prealloc>::indexOf(const T &value, int from = 0) const
|
||||
|
||||
\since 5.3
|
||||
|
|
|
|||
|
|
@ -283,6 +283,10 @@ public:
|
|||
{ append(t); return *this; }
|
||||
inline QVector<T> &operator<<(const QVector<T> &l)
|
||||
{ *this += l; return *this; }
|
||||
inline QVector<T> &operator+=(T &&t)
|
||||
{ append(t); return *this; }
|
||||
inline QVector<T> &operator<<(T &&t)
|
||||
{ append(t); return *this; }
|
||||
|
||||
QList<T> toList() const;
|
||||
|
||||
|
|
|
|||
|
|
@ -1162,6 +1162,14 @@
|
|||
\sa append(), operator<<()
|
||||
*/
|
||||
|
||||
/*! \fn template <typename T> void QVector<T>::operator+=(T &&value)
|
||||
\since 5.11
|
||||
|
||||
\overload
|
||||
|
||||
\sa append(), operator<<()
|
||||
*/
|
||||
|
||||
/*! \fn template <typename T> QVector<T> QVector<T>::operator+(const QVector<T> &other) const
|
||||
|
||||
Returns a vector that contains all the items in this vector
|
||||
|
|
@ -1178,6 +1186,15 @@
|
|||
\sa append(), operator+=()
|
||||
*/
|
||||
|
||||
/*! \fn template <typename T> QVector<T> &QVector<T>::operator<<(T &&value)
|
||||
\since 5.11
|
||||
|
||||
\overload
|
||||
|
||||
\sa append(), operator+=()
|
||||
*/
|
||||
|
||||
|
||||
/*! \fn template <typename T> QVector<T> &QVector<T>::operator<<(const QVector<T> &other)
|
||||
|
||||
Appends \a other to the vector and returns a reference to the
|
||||
|
|
|
|||
|
|
@ -455,7 +455,7 @@ void QStandardItemModelPrivate::_q_emitItemChanged(const QModelIndex &topLeft,
|
|||
bool QStandardItemPrivate::insertRows(int row, const QList<QStandardItem*> &items)
|
||||
{
|
||||
Q_Q(QStandardItem);
|
||||
if ((row < 0) || (row > rowCount()))
|
||||
if ((row < 0) || (row > rowCount()) || items.isEmpty())
|
||||
return false;
|
||||
int count = items.count();
|
||||
if (model)
|
||||
|
|
@ -486,7 +486,7 @@ bool QStandardItemPrivate::insertRows(int row, const QList<QStandardItem*> &item
|
|||
bool QStandardItemPrivate::insertRows(int row, int count, const QList<QStandardItem*> &items)
|
||||
{
|
||||
Q_Q(QStandardItem);
|
||||
if ((count < 1) || (row < 0) || (row > rowCount()))
|
||||
if ((count < 1) || (row < 0) || (row > rowCount()) || count == 0)
|
||||
return false;
|
||||
if (model)
|
||||
model->d_func()->rowsAboutToBeInserted(q, row, row + count - 1);
|
||||
|
|
@ -528,7 +528,7 @@ bool QStandardItemPrivate::insertRows(int row, int count, const QList<QStandardI
|
|||
bool QStandardItemPrivate::insertColumns(int column, int count, const QList<QStandardItem*> &items)
|
||||
{
|
||||
Q_Q(QStandardItem);
|
||||
if ((count < 1) || (column < 0) || (column > columnCount()))
|
||||
if ((count < 1) || (column < 0) || (column > columnCount()) || count == 0)
|
||||
return false;
|
||||
if (model)
|
||||
model->d_func()->columnsAboutToBeInserted(q, column, column + count - 1);
|
||||
|
|
|
|||
|
|
@ -96,6 +96,8 @@ public:
|
|||
|
||||
void syncMenuItem_helper(QPlatformMenuItem *menuItem, bool menubarUpdate);
|
||||
|
||||
void setItemTargetAction(QCocoaMenuItem *item) const;
|
||||
|
||||
private:
|
||||
QCocoaMenuItem *itemOrNull(int index) const;
|
||||
void insertNative(QCocoaMenuItem *item, QCocoaMenuItem *beforeItem);
|
||||
|
|
|
|||
|
|
@ -132,9 +132,8 @@ void QCocoaMenu::insertMenuItem(QPlatformMenuItem *menuItem, QPlatformMenuItem *
|
|||
|
||||
void QCocoaMenu::insertNative(QCocoaMenuItem *item, QCocoaMenuItem *beforeItem)
|
||||
{
|
||||
setItemTargetAction(item);
|
||||
NSMenuItem *nativeItem = item->nsItem();
|
||||
nativeItem.target = m_nativeMenu.delegate;
|
||||
nativeItem.action = @selector(itemFired:);
|
||||
// Someone's adding new items after aboutToShow() was emitted
|
||||
if (isOpen() && nativeItem && item->menu())
|
||||
item->menu()->setAttachedItem(nativeItem);
|
||||
|
|
@ -494,4 +493,11 @@ NSMenuItem *QCocoaMenu::attachedItem() const
|
|||
return m_attachedItem;
|
||||
}
|
||||
|
||||
void QCocoaMenu::setItemTargetAction(QCocoaMenuItem *item) const
|
||||
{
|
||||
auto *nsItem = item->nsItem();
|
||||
nsItem.target = m_nativeMenu;
|
||||
nsItem.action = @selector(qt_itemFired:);
|
||||
}
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
|
|
|||
|
|
@ -307,14 +307,12 @@ void QCocoaMenuBar::redirectKnownMenuItemsToFirstResponder()
|
|||
void QCocoaMenuBar::resetKnownMenuItemsToQt()
|
||||
{
|
||||
// Undo the effect of redirectKnownMenuItemsToFirstResponder():
|
||||
// set the menu items' actions to itemFired and their targets to
|
||||
// the QCocoaMenuDelegate.
|
||||
// reset the menu items' target/action.
|
||||
foreach (QCocoaMenuBar *mb, static_menubars) {
|
||||
foreach (QCocoaMenu *m, mb->m_menus) {
|
||||
foreach (QCocoaMenuItem *i, m->items()) {
|
||||
if (i->effectiveRole() >= QPlatformMenuItem::ApplicationSpecificRole) {
|
||||
[i->nsItem() setTarget:m->nsMenu().delegate];
|
||||
[i->nsItem() setAction:@selector(itemFired:)];
|
||||
m->setItemTargetAction(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -68,8 +68,6 @@ typedef QPointer<QCocoaMenu> QCocoaMenuPointer;
|
|||
forKey:(NSString *)key
|
||||
modifiers:(NSUInteger)modifiers;
|
||||
|
||||
- (BOOL)validateMenuItem:(NSMenuItem *)item; // NSMenuValidation
|
||||
|
||||
@end
|
||||
|
||||
@interface QT_MANGLE_NAMESPACE(QCocoaNSMenu) : NSMenu
|
||||
|
|
@ -78,6 +76,11 @@ typedef QPointer<QCocoaMenu> QCocoaMenuPointer;
|
|||
|
||||
- (instancetype)initWithQPAMenu:(QCocoaMenu *)menu;
|
||||
|
||||
- (void)qt_itemFired:(NSMenuItem *)item;
|
||||
|
||||
- (BOOL)worksWhenModal;
|
||||
- (BOOL)validateMenuItem:(NSMenuItem*)item; // NSMenuValidation
|
||||
|
||||
@end
|
||||
|
||||
QT_NAMESPACE_ALIAS_OBJC_CLASS(QCocoaNSMenu);
|
||||
|
|
|
|||
|
|
@ -82,6 +82,43 @@ static NSString *qt_mac_removePrivateUnicode(NSString* string)
|
|||
return self;
|
||||
}
|
||||
|
||||
// Cocoa will query the menu item's target for the worksWhenModal selector.
|
||||
// So we need to implement this to allow the items to be handled correctly
|
||||
// when a modal dialog is visible. See documentation for NSMenuItem.target.
|
||||
- (BOOL)worksWhenModal
|
||||
{
|
||||
if (!QGuiApplication::modalWindow())
|
||||
return YES;
|
||||
if (const auto *mb = qobject_cast<QCocoaMenuBar *>(self.qpaMenu->menuParent()))
|
||||
return QGuiApplication::modalWindow()->handle() == mb->cocoaWindow() ? YES : NO;
|
||||
return YES;
|
||||
}
|
||||
|
||||
- (void)qt_itemFired:(NSMenuItem *)item
|
||||
{
|
||||
auto *qpaItem = reinterpret_cast<QCocoaMenuItem *>(item.tag);
|
||||
// Menu-holding items also get a target to play nicely
|
||||
// with NSMenuValidation but should not trigger.
|
||||
if (!qpaItem || qpaItem->menu())
|
||||
return;
|
||||
|
||||
QScopedScopeLevelCounter scopeLevelCounter(QGuiApplicationPrivate::instance()->threadData);
|
||||
QGuiApplicationPrivate::modifier_buttons = [QNSView convertKeyModifiers:[NSEvent modifierFlags]];
|
||||
|
||||
static QMetaMethod activatedSignal = QMetaMethod::fromSignal(&QCocoaMenuItem::activated);
|
||||
activatedSignal.invoke(qpaItem, Qt::QueuedConnection);
|
||||
}
|
||||
|
||||
- (BOOL)validateMenuItem:(NSMenuItem*)item
|
||||
{
|
||||
auto *qpaItem = reinterpret_cast<QCocoaMenuItem *>(item.tag);
|
||||
// Menu-holding items are always enabled, as it's conventional in Cocoa
|
||||
if (!qpaItem || qpaItem->menu())
|
||||
return YES;
|
||||
|
||||
return qpaItem->isEnabled();
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
#define CHECK_MENU_CLASS(menu) Q_ASSERT([menu isMemberOfClass:[QCocoaNSMenu class]])
|
||||
|
|
@ -160,31 +197,6 @@ static NSString *qt_mac_removePrivateUnicode(NSString* string)
|
|||
emit qpaMenu->aboutToHide();
|
||||
}
|
||||
|
||||
- (void)itemFired:(NSMenuItem *)item
|
||||
{
|
||||
auto *qpaItem = reinterpret_cast<QCocoaMenuItem *>(item.tag);
|
||||
// Menu-holding items also get a target to play nicely
|
||||
// with NSMenuValidation but should not trigger.
|
||||
if (!qpaItem || qpaItem->menu())
|
||||
return;
|
||||
|
||||
QScopedScopeLevelCounter scopeLevelCounter(QGuiApplicationPrivate::instance()->threadData);
|
||||
QGuiApplicationPrivate::modifier_buttons = [QNSView convertKeyModifiers:[NSEvent modifierFlags]];
|
||||
|
||||
static QMetaMethod activatedSignal = QMetaMethod::fromSignal(&QCocoaMenuItem::activated);
|
||||
activatedSignal.invoke(qpaItem, Qt::QueuedConnection);
|
||||
}
|
||||
|
||||
- (BOOL)validateMenuItem:(NSMenuItem*)item
|
||||
{
|
||||
auto *qpaItem = reinterpret_cast<QCocoaMenuItem *>(item.tag);
|
||||
// Menu-holding items are always enabled, as it's conventional in Cocoa
|
||||
if (!qpaItem || qpaItem->menu())
|
||||
return YES;
|
||||
|
||||
return qpaItem->isEnabled();
|
||||
}
|
||||
|
||||
- (BOOL)menuHasKeyEquivalent:(NSMenu *)menu forEvent:(NSEvent *)event target:(id *)target action:(SEL *)action
|
||||
{
|
||||
/*
|
||||
|
|
@ -293,19 +305,6 @@ static NSString *qt_mac_removePrivateUnicode(NSString* string)
|
|||
return nil;
|
||||
}
|
||||
|
||||
// Cocoa will query the menu item's target for the worksWhenModal selector.
|
||||
// So we need to implement this to allow the items to be handled correctly
|
||||
// when a modal dialog is visible.
|
||||
- (BOOL)worksWhenModal
|
||||
{
|
||||
if (!QGuiApplication::modalWindow())
|
||||
return YES;
|
||||
const auto &qpaMenu = static_cast<QCocoaNSMenu *>(self).qpaMenu;
|
||||
if (auto *mb = qobject_cast<QCocoaMenuBar *>(qpaMenu->menuParent()))
|
||||
return QGuiApplication::modalWindow()->handle() == mb->cocoaWindow() ? YES : NO;
|
||||
return YES;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
#undef CHECK_MENU_CLASS
|
||||
|
|
|
|||
|
|
@ -412,7 +412,8 @@ QWindowsOleDropSource::QueryContinueDrag(BOOL fEscapePressed, DWORD grfKeyState)
|
|||
const QPoint localPos = m_windowUnderMouse->handle()->mapFromGlobal(globalPos);
|
||||
QWindowSystemInterface::handleMouseEvent(m_windowUnderMouse.data(),
|
||||
QPointF(localPos), QPointF(globalPos),
|
||||
QWindowsMouseHandler::queryMouseButtons());
|
||||
QWindowsMouseHandler::queryMouseButtons(),
|
||||
Qt::LeftButton, QEvent::MouseButtonRelease);
|
||||
}
|
||||
}
|
||||
m_currentButtons = Qt::NoButton;
|
||||
|
|
|
|||
|
|
@ -318,6 +318,15 @@ void QWindowsScreen::handleChanges(const QWindowsScreenData &newData)
|
|||
}
|
||||
}
|
||||
|
||||
QRect QWindowsScreen::virtualGeometry(const QPlatformScreen *screen) // cf QScreen::virtualGeometry()
|
||||
{
|
||||
QRect result;
|
||||
const auto siblings = screen->virtualSiblings();
|
||||
for (const QPlatformScreen *sibling : siblings)
|
||||
result |= sibling->geometry();
|
||||
return result;
|
||||
}
|
||||
|
||||
enum OrientationPreference // matching Win32 API ORIENTATION_PREFERENCE
|
||||
#if defined(Q_COMPILER_CLASS_ENUM) || defined(Q_CC_MSVC)
|
||||
: DWORD
|
||||
|
|
|
|||
|
|
@ -113,6 +113,8 @@ public:
|
|||
|
||||
const QWindowsScreenData &data() const { return m_data; }
|
||||
|
||||
static QRect virtualGeometry(const QPlatformScreen *screen);
|
||||
|
||||
private:
|
||||
QWindowsScreenData m_data;
|
||||
#ifndef QT_NO_CURSOR
|
||||
|
|
|
|||
|
|
@ -421,7 +421,8 @@ bool QWindowsTabletSupport::translateTabletPacketEvent()
|
|||
// in which case we snap the position to the mouse position.
|
||||
// It seems there is no way to find out the mode programmatically, the LOGCONTEXT orgX/Y/Ext
|
||||
// area is always the virtual desktop.
|
||||
const QRect virtualDesktopArea = QGuiApplication::primaryScreen()->virtualGeometry();
|
||||
const QRect virtualDesktopArea =
|
||||
QWindowsScreen::virtualGeometry(QGuiApplication::primaryScreen()->handle());
|
||||
|
||||
qCDebug(lcQpaTablet) << __FUNCTION__ << "processing " << packetCount
|
||||
<< "target:" << QGuiApplicationPrivate::tabletDevicePoint(uniqueId).target;
|
||||
|
|
@ -455,7 +456,9 @@ bool QWindowsTabletSupport::translateTabletPacketEvent()
|
|||
if (!target)
|
||||
continue;
|
||||
|
||||
const QPoint localPos = target->mapFromGlobal(globalPos);
|
||||
const QPlatformWindow *platformWindow = target->handle();
|
||||
Q_ASSERT(platformWindow);
|
||||
const QPoint localPos = platformWindow->mapFromGlobal(globalPos);
|
||||
|
||||
const qreal pressureNew = packet.pkButtons && (currentPointer == QTabletEvent::Pen || currentPointer == QTabletEvent::Eraser) ?
|
||||
m_devices.at(m_currentDevice).scalePressure(packet.pkNormalPressure) :
|
||||
|
|
|
|||
|
|
@ -57,29 +57,7 @@
|
|||
#include <libpq-fe.h>
|
||||
#include <pg_config.h>
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <math.h>
|
||||
// below code taken from an example at http://www.gnu.org/software/hello/manual/autoconf/Function-Portability.html
|
||||
#ifndef isnan
|
||||
# define isnan(x) \
|
||||
(sizeof (x) == sizeof (long double) ? isnan_ld (x) \
|
||||
: sizeof (x) == sizeof (double) ? isnan_d (x) \
|
||||
: isnan_f (x))
|
||||
static inline int isnan_f (float x) { return x != x; }
|
||||
static inline int isnan_d (double x) { return x != x; }
|
||||
static inline int isnan_ld (long double x) { return x != x; }
|
||||
#endif
|
||||
|
||||
#ifndef isinf
|
||||
# define isinf(x) \
|
||||
(sizeof (x) == sizeof (long double) ? isinf_ld (x) \
|
||||
: sizeof (x) == sizeof (double) ? isinf_d (x) \
|
||||
: isinf_f (x))
|
||||
static inline int isinf_f (float x) { return isnan (x - x); }
|
||||
static inline int isinf_d (double x) { return isnan (x - x); }
|
||||
static inline int isinf_ld (long double x) { return isnan (x - x); }
|
||||
#endif
|
||||
|
||||
#include <cmath>
|
||||
|
||||
// workaround for postgres defining their OIDs in a private header file
|
||||
#define QBOOLOID 16
|
||||
|
|
@ -135,7 +113,7 @@ static const StatementId InvalidStatementId = 0;
|
|||
|
||||
class QPSQLResultPrivate;
|
||||
|
||||
class QPSQLResult: public QSqlResult
|
||||
class QPSQLResult final : public QSqlResult
|
||||
{
|
||||
Q_DECLARE_PRIVATE(QPSQLResult)
|
||||
|
||||
|
|
@ -164,7 +142,7 @@ protected:
|
|||
bool exec() override;
|
||||
};
|
||||
|
||||
class QPSQLDriverPrivate : public QSqlDriverPrivate
|
||||
class QPSQLDriverPrivate final : public QSqlDriverPrivate
|
||||
{
|
||||
Q_DECLARE_PUBLIC(QPSQLDriver)
|
||||
public:
|
||||
|
|
@ -671,7 +649,7 @@ QVariant QPSQLResult::data(int i)
|
|||
return QString::fromLatin1(val).toULongLong();
|
||||
case QVariant::Int:
|
||||
return atoi(val);
|
||||
case QVariant::Double:
|
||||
case QVariant::Double: {
|
||||
if (ptype == QNUMERICOID) {
|
||||
if (numericalPrecisionPolicy() != QSql::HighPrecision) {
|
||||
QVariant retval;
|
||||
|
|
@ -689,7 +667,12 @@ QVariant QPSQLResult::data(int i)
|
|||
}
|
||||
return QString::fromLatin1(val);
|
||||
}
|
||||
if (qstricmp(val, "Infinity") == 0)
|
||||
return qInf();
|
||||
if (qstricmp(val, "-Infinity") == 0)
|
||||
return -qInf();
|
||||
return QString::fromLatin1(val).toDouble();
|
||||
}
|
||||
case QVariant::Date:
|
||||
if (val[0] == '\0') {
|
||||
return QVariant(QDate());
|
||||
|
|
@ -1497,18 +1480,10 @@ QSqlRecord QPSQLDriver::record(const QString& tablename) const
|
|||
template <class FloatType>
|
||||
inline void assignSpecialPsqlFloatValue(FloatType val, QString *target)
|
||||
{
|
||||
if (isnan(val)) {
|
||||
*target = QLatin1String("'NaN'");
|
||||
} else {
|
||||
switch (isinf(val)) {
|
||||
case 1:
|
||||
*target = QLatin1String("'Infinity'");
|
||||
break;
|
||||
case -1:
|
||||
*target = QLatin1String("'-Infinity'");
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (qIsNaN(val))
|
||||
*target = QStringLiteral("'NaN'");
|
||||
else if (qIsInf(val))
|
||||
*target = (val < 0) ? QStringLiteral("'-Infinity'") : QStringLiteral("'Infinity'");
|
||||
}
|
||||
|
||||
QString QPSQLDriver::formatValue(const QSqlField &field, bool trimStrings) const
|
||||
|
|
|
|||
|
|
@ -48,52 +48,52 @@ class QSqlFieldPrivate
|
|||
public:
|
||||
QSqlFieldPrivate(const QString &name,
|
||||
QVariant::Type type, const QString &tableName) :
|
||||
ref(1), nm(name), ro(false), type(type), req(QSqlField::Unknown),
|
||||
len(-1), prec(-1), tp(-1), gen(true), autoval(false), table(tableName)
|
||||
{
|
||||
}
|
||||
ref(1), nm(name), table(tableName), def(QVariant()), type(type),
|
||||
req(QSqlField::Unknown), len(-1), prec(-1), tp(-1),
|
||||
ro(false), gen(true), autoval(false)
|
||||
{}
|
||||
|
||||
QSqlFieldPrivate(const QSqlFieldPrivate &other)
|
||||
: ref(1),
|
||||
nm(other.nm),
|
||||
ro(other.ro),
|
||||
table(other.table),
|
||||
def(other.def),
|
||||
type(other.type),
|
||||
req(other.req),
|
||||
len(other.len),
|
||||
prec(other.prec),
|
||||
def(other.def),
|
||||
tp(other.tp),
|
||||
ro(other.ro),
|
||||
gen(other.gen),
|
||||
autoval(other.autoval),
|
||||
table(other.table)
|
||||
autoval(other.autoval)
|
||||
{}
|
||||
|
||||
bool operator==(const QSqlFieldPrivate& other) const
|
||||
{
|
||||
return (nm == other.nm
|
||||
&& ro == other.ro
|
||||
&& table == other.table
|
||||
&& def == other.def
|
||||
&& type == other.type
|
||||
&& req == other.req
|
||||
&& len == other.len
|
||||
&& prec == other.prec
|
||||
&& def == other.def
|
||||
&& ro == other.ro
|
||||
&& gen == other.gen
|
||||
&& autoval == other.autoval
|
||||
&& table == other.table);
|
||||
&& autoval == other.autoval);
|
||||
}
|
||||
|
||||
QAtomicInt ref;
|
||||
QString nm;
|
||||
uint ro: 1;
|
||||
QString table;
|
||||
QVariant def;
|
||||
QVariant::Type type;
|
||||
QSqlField::RequiredStatus req;
|
||||
int len;
|
||||
int prec;
|
||||
QVariant def;
|
||||
int tp;
|
||||
uint gen: 1;
|
||||
uint autoval: 1;
|
||||
QString table;
|
||||
bool ro: 1;
|
||||
bool gen: 1;
|
||||
bool autoval: 1;
|
||||
};
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -44,6 +44,8 @@
|
|||
#include <QtTest/private/qbenchmark_p.h>
|
||||
#include <QtTest/private/qbenchmarkmetric_p.h>
|
||||
|
||||
#include <QtCore/private/qlogging_p.h>
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
|
@ -205,15 +207,11 @@ namespace QTest {
|
|||
}
|
||||
}
|
||||
|
||||
#if defined(Q_OS_WIN)
|
||||
Q_CORE_EXPORT bool qt_logging_to_console(); // defined in qlogging.cpp
|
||||
#endif
|
||||
|
||||
void QPlainTestLogger::outputMessage(const char *str)
|
||||
{
|
||||
#if defined(Q_OS_WIN)
|
||||
// log to system log only if output is not redirected, and no console is attached
|
||||
if (!qt_logging_to_console() && stream == stdout) {
|
||||
// Log to system log only if output is not redirected and stderr not preferred
|
||||
if (stream == stdout && !QtPrivate::shouldLogToStderr()) {
|
||||
OutputDebugStringA(str);
|
||||
return;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -112,7 +112,7 @@ namespace QTest
|
|||
{
|
||||
bool becameActive = qWaitFor([&]() { return window->isActive(); }, timeout);
|
||||
|
||||
// Try ensuring the platform window receives the real position and geometry.
|
||||
// Try ensuring the platform window receives the real position.
|
||||
// (i.e. that window->pos() reflects reality)
|
||||
// isActive() ( == FocusIn in case of X) does not guarantee this. It seems some WMs randomly
|
||||
// send the final ConfigureNotify (the one with the non-bogus 0,0 position) after the FocusIn.
|
||||
|
|
@ -120,7 +120,7 @@ namespace QTest
|
|||
// qWaitForWindowShown() will generate bogus results.
|
||||
if (becameActive) {
|
||||
int waitNo = 0; // 0, 0 might be a valid position after all, so do not wait for ever
|
||||
while (window->frameGeometry().isNull()) {
|
||||
while (window->position().isNull()) {
|
||||
if (waitNo++ > timeout / 10)
|
||||
break;
|
||||
qWait(10);
|
||||
|
|
|
|||
|
|
@ -2191,7 +2191,11 @@ void QHeaderViewPrivate::_q_sectionsAboutToBeChanged(const QList<QPersistentMode
|
|||
if (stretchLastSection && lastSectionLogicalIdx >= 0 && lastSectionLogicalIdx < sectionItems.count()) {
|
||||
const int visual = visualIndex(lastSectionLogicalIdx);
|
||||
if (visual >= 0 && visual < sectionItems.size()) {
|
||||
sectionItems[visual].size = lastSectionSize;
|
||||
auto &itemRef = sectionItems[visual];
|
||||
if (itemRef.size != lastSectionSize) {
|
||||
length += lastSectionSize - itemRef.size;
|
||||
itemRef.size = lastSectionSize;
|
||||
}
|
||||
}
|
||||
}
|
||||
for (int i = 0; i < sectionItems.size(); ++i) {
|
||||
|
|
|
|||
|
|
@ -195,6 +195,11 @@ public:
|
|||
void _q_removeTab(int);
|
||||
void _q_tabMoved(int from, int to);
|
||||
void init();
|
||||
bool isAutoHidden() const
|
||||
{
|
||||
// see QTabBarPrivate::autoHideTabs()
|
||||
return (tabs->autoHide() && tabs->count() <= 1);
|
||||
}
|
||||
|
||||
void initBasicStyleOption(QStyleOptionTabWidgetFrame *option) const;
|
||||
|
||||
|
|
@ -841,11 +846,14 @@ QSize QTabWidget::sizeHint() const
|
|||
that->setUpLayout(true);
|
||||
}
|
||||
QSize s(d->stack->sizeHint());
|
||||
QSize t(d->tabs->sizeHint());
|
||||
if(usesScrollButtons())
|
||||
t = t.boundedTo(QSize(200,200));
|
||||
else
|
||||
t = t.boundedTo(QDesktopWidgetPrivate::size());
|
||||
QSize t;
|
||||
if (!d->isAutoHidden()) {
|
||||
t = d->tabs->sizeHint();
|
||||
if (usesScrollButtons())
|
||||
t = t.boundedTo(QSize(200,200));
|
||||
else
|
||||
t = t.boundedTo(QDesktopWidgetPrivate::size());
|
||||
}
|
||||
|
||||
QSize sz = basicSize(d->pos == North || d->pos == South, lc, rc, s, t);
|
||||
|
||||
|
|
@ -873,7 +881,9 @@ QSize QTabWidget::minimumSizeHint() const
|
|||
that->setUpLayout(true);
|
||||
}
|
||||
QSize s(d->stack->minimumSizeHint());
|
||||
QSize t(d->tabs->minimumSizeHint());
|
||||
QSize t;
|
||||
if (!d->isAutoHidden())
|
||||
t = d->tabs->minimumSizeHint();
|
||||
|
||||
QSize sz = basicSize(d->pos == North || d->pos == South, lc, rc, s, t);
|
||||
|
||||
|
|
@ -908,12 +918,14 @@ int QTabWidget::heightForWidth(int width) const
|
|||
QTabWidget *that = const_cast<QTabWidget*>(this);
|
||||
that->setUpLayout(true);
|
||||
}
|
||||
QSize t(d->tabs->sizeHint());
|
||||
|
||||
if(usesScrollButtons())
|
||||
t = t.boundedTo(QSize(200,200));
|
||||
else
|
||||
t = t.boundedTo(QDesktopWidgetPrivate::size());
|
||||
QSize t;
|
||||
if (!d->isAutoHidden()) {
|
||||
t = d->tabs->sizeHint();
|
||||
if (usesScrollButtons())
|
||||
t = t.boundedTo(QSize(200,200));
|
||||
else
|
||||
t = t.boundedTo(QDesktopWidgetPrivate::size());
|
||||
}
|
||||
|
||||
const bool tabIsHorizontal = (d->pos == North || d->pos == South);
|
||||
const int contentsWidth = width - padding.width();
|
||||
|
|
|
|||
|
|
@ -132,7 +132,7 @@ private slots:
|
|||
void taskQTBUG_45114_setItemData();
|
||||
|
||||
private:
|
||||
QAbstractItemModel *m_model;
|
||||
QStandardItemModel *m_model;
|
||||
QPersistentModelIndex persistent;
|
||||
QVector<QModelIndex> rcParent;
|
||||
QVector<int> rcFirst;
|
||||
|
|
@ -292,6 +292,12 @@ void tst_QStandardItemModel::insertRows()
|
|||
|
||||
// check header data has moved
|
||||
QCOMPARE(m_model->headerData(3, Qt::Vertical).toString(), headerLabel);
|
||||
|
||||
// do not assert on empty list
|
||||
QStandardItem *si = m_model->invisibleRootItem();
|
||||
si->insertRow(0, QList<QStandardItem*>());
|
||||
si->insertRows(0, 0);
|
||||
si->insertRows(0, QList<QStandardItem*>());
|
||||
}
|
||||
|
||||
void tst_QStandardItemModel::insertRowsItems()
|
||||
|
|
@ -402,6 +408,11 @@ void tst_QStandardItemModel::insertColumns()
|
|||
|
||||
// check header data has moved
|
||||
QCOMPARE(m_model->headerData(3, Qt::Horizontal).toString(), headerLabel);
|
||||
|
||||
// do not assert on empty list
|
||||
QStandardItem *si = m_model->invisibleRootItem();
|
||||
si->insertColumn(0, QList<QStandardItem*>());
|
||||
si->insertColumns(0, 0);
|
||||
}
|
||||
|
||||
void tst_QStandardItemModel::removeRows()
|
||||
|
|
|
|||
|
|
@ -7,6 +7,8 @@ osx-10.12 ci
|
|||
ubuntu-16.04
|
||||
[modalWithChildWindow]
|
||||
ubuntu-16.04
|
||||
# QTBUG-66851
|
||||
opensuse
|
||||
[setVisible]
|
||||
[modalWindowEnterEventOnHide_QTBUG35109]
|
||||
ubuntu-16.04
|
||||
|
|
|
|||
|
|
@ -16,7 +16,6 @@ SUBDIRS=\
|
|||
qcomplextext \
|
||||
qfocusevent \
|
||||
qnetworkaccessmanager_and_qprogressdialog \
|
||||
qobjectperformance \
|
||||
qobjectrace \
|
||||
qsharedpointer_and_qwidget \
|
||||
qprocess_and_guieventloop \
|
||||
|
|
@ -44,7 +43,6 @@ SUBDIRS=\
|
|||
lancelot \
|
||||
networkselftest \
|
||||
qnetworkaccessmanager_and_qprogressdialog \
|
||||
qobjectperformance
|
||||
|
||||
cross_compile: SUBDIRS -= \
|
||||
atwrapper \
|
||||
|
|
|
|||
|
|
@ -1 +0,0 @@
|
|||
tst_qobjectperformance
|
||||
|
|
@ -1,7 +0,0 @@
|
|||
CONFIG += testcase
|
||||
TARGET = tst_qobjectperformance
|
||||
SOURCES += tst_qobjectperformance.cpp
|
||||
|
||||
QT = core network testlib
|
||||
|
||||
|
||||
|
|
@ -1,110 +0,0 @@
|
|||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2016 The Qt Company Ltd.
|
||||
** Contact: https://www.qt.io/licensing/
|
||||
**
|
||||
** This file is part of the test suite of the Qt Toolkit.
|
||||
**
|
||||
** $QT_BEGIN_LICENSE:GPL-EXCEPT$
|
||||
** Commercial License Usage
|
||||
** Licensees holding valid commercial Qt licenses may use this file in
|
||||
** accordance with the commercial license agreement provided with the
|
||||
** Software or, alternatively, in accordance with the terms contained in
|
||||
** a written agreement between you and The Qt Company. For licensing terms
|
||||
** and conditions see https://www.qt.io/terms-conditions. For further
|
||||
** information use the contact form at https://www.qt.io/contact-us.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 3 as published by the Free Software
|
||||
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
|
||||
** included in the packaging of this file. Please review the following
|
||||
** information to ensure the GNU General Public License requirements will
|
||||
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
|
||||
**
|
||||
** $QT_END_LICENSE$
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
|
||||
#include <QtTest/QtTest>
|
||||
|
||||
#include <qcoreapplication.h>
|
||||
|
||||
#include <qobject.h>
|
||||
|
||||
class tst_QObjectPerformance : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
|
||||
private slots:
|
||||
void emitToManyReceivers();
|
||||
};
|
||||
|
||||
class SimpleSenderObject : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
signals:
|
||||
void signal();
|
||||
|
||||
public:
|
||||
void emitSignal()
|
||||
{
|
||||
emit signal();
|
||||
}
|
||||
};
|
||||
|
||||
class SimpleReceiverObject : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public slots:
|
||||
void slot()
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
void tst_QObjectPerformance::emitToManyReceivers()
|
||||
{
|
||||
// ensure that emission times remain mostly linear as the number of receivers increase
|
||||
|
||||
SimpleSenderObject sender;
|
||||
int elapsed = 0;
|
||||
const int increase = 3000;
|
||||
const int base = 5000;
|
||||
|
||||
for (int i = 0; i < 4; ++i) {
|
||||
const int size = base + i * increase;
|
||||
const double increaseRatio = double(size) / (double)(size - increase);
|
||||
|
||||
QList<SimpleReceiverObject *> receivers;
|
||||
for (int k = 0; k < size; ++k) {
|
||||
SimpleReceiverObject *receiver = new SimpleReceiverObject;
|
||||
QObject::connect(&sender, SIGNAL(signal()), receiver, SLOT(slot()));
|
||||
receivers.append(receiver);
|
||||
}
|
||||
|
||||
QTime timer;
|
||||
timer.start();
|
||||
sender.emitSignal();
|
||||
int e = timer.elapsed();
|
||||
|
||||
if (elapsed > 1) {
|
||||
qDebug() << size << "receivers, elapsed time" << e << "compared to previous time" << elapsed;
|
||||
QVERIFY(double(e) / double(elapsed) <= increaseRatio * 2.0);
|
||||
} else {
|
||||
qDebug() << size << "receivers, elapsed time" << e << "cannot be compared to previous, unmeasurable time";
|
||||
}
|
||||
elapsed = e;
|
||||
|
||||
qDeleteAll(receivers);
|
||||
receivers.clear();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
QTEST_MAIN(tst_QObjectPerformance)
|
||||
#include "tst_qobjectperformance.moc"
|
||||
|
|
@ -126,6 +126,8 @@ private slots:
|
|||
void formatValueTrimStrings();
|
||||
void precisionPolicy_data() { generic_data(); }
|
||||
void precisionPolicy();
|
||||
void infinityAndNan_data() { generic_data(); }
|
||||
void infinityAndNan();
|
||||
void multipleThreads_data() { generic_data(); }
|
||||
void multipleThreads();
|
||||
|
||||
|
|
@ -1467,6 +1469,46 @@ void tst_QSqlDatabase::precisionPolicy()
|
|||
db.setNumericalPrecisionPolicy(oldPrecision);
|
||||
}
|
||||
|
||||
void tst_QSqlDatabase::infinityAndNan()
|
||||
{
|
||||
QFETCH(QString, dbName);
|
||||
QSqlDatabase db = QSqlDatabase::database(dbName);
|
||||
CHECK_DATABASE(db);
|
||||
|
||||
if (tst_Databases::getDatabaseType(db) != QSqlDriver::PostgreSQL)
|
||||
QSKIP("checking for infinity/nan currently only works for PostgreSQL");
|
||||
|
||||
QSqlQuery q(db);
|
||||
const QString tableName(qTableName("infititytest", __FILE__, db));
|
||||
tst_Databases::safeDropTables(db, {tableName});
|
||||
QVERIFY_SQL(q, exec(QString("CREATE TABLE %1 (id smallint, val double precision)").arg(tableName)));
|
||||
|
||||
QVERIFY_SQL(q, prepare(QString("INSERT INTO %1 VALUES (?, ?)").arg(tableName)));
|
||||
|
||||
q.bindValue(0, 1);
|
||||
q.bindValue(1, qQNaN());
|
||||
QVERIFY_SQL(q, exec());
|
||||
q.bindValue(0, 2);
|
||||
q.bindValue(1, qInf());
|
||||
QVERIFY_SQL(q, exec());
|
||||
q.bindValue(0, 3);
|
||||
q.bindValue(1, -qInf());
|
||||
QVERIFY_SQL(q, exec());
|
||||
|
||||
QVERIFY_SQL(q, exec(QString("SELECT val FROM %1 ORDER BY id").arg(tableName)));
|
||||
|
||||
QVERIFY_SQL(q, next());
|
||||
QVERIFY(qIsNaN(q.value(0).toDouble()));
|
||||
|
||||
QVERIFY_SQL(q, next());
|
||||
QVERIFY(qIsInf(q.value(0).toDouble()));
|
||||
QVERIFY(q.value(0).toDouble() > 0);
|
||||
|
||||
QVERIFY_SQL(q, next());
|
||||
QVERIFY(qIsInf(q.value(0).toDouble()));
|
||||
QVERIFY(q.value(0).toDouble() < 0);
|
||||
}
|
||||
|
||||
// This test needs a ODBC data source containing MYSQL in it's name
|
||||
void tst_QSqlDatabase::mysqlOdbc_unsignedIntegers()
|
||||
{
|
||||
|
|
|
|||
|
|
@ -162,6 +162,7 @@ private slots:
|
|||
void renderToPixmap();
|
||||
void styleOptionViewItem();
|
||||
void keyboardNavigationWithDisabled();
|
||||
void saveRestoreState();
|
||||
|
||||
void statusTip_data();
|
||||
void statusTip();
|
||||
|
|
@ -4076,6 +4077,58 @@ void tst_QTreeView::keyboardNavigationWithDisabled()
|
|||
QCOMPARE(view.currentIndex(), model.index(6, 0));
|
||||
}
|
||||
|
||||
class RemoveColumnOne : public QSortFilterProxyModel
|
||||
{
|
||||
public:
|
||||
bool filterAcceptsColumn(int source_column, const QModelIndex &) const override
|
||||
{
|
||||
if (m_removeColumn)
|
||||
return source_column != 1;
|
||||
return true;
|
||||
}
|
||||
void removeColumn()
|
||||
{
|
||||
m_removeColumn = true;
|
||||
invalidate();
|
||||
}
|
||||
private:
|
||||
bool m_removeColumn = false;
|
||||
};
|
||||
|
||||
|
||||
void tst_QTreeView::saveRestoreState()
|
||||
{
|
||||
QStandardItemModel model;
|
||||
for (int i = 0; i < 100; i++) {
|
||||
QList<QStandardItem *> items;
|
||||
items << new QStandardItem(QLatin1String("item ") + QString::number(i)) << new QStandardItem(QStringLiteral("hidden by proxy")) << new QStandardItem(QStringLiteral("hidden by user"));
|
||||
model.appendRow(items);
|
||||
}
|
||||
QCOMPARE(model.columnCount(), 3);
|
||||
|
||||
RemoveColumnOne proxy;
|
||||
proxy.setSourceModel(&model);
|
||||
QCOMPARE(proxy.columnCount(), 3);
|
||||
|
||||
QTreeView view;
|
||||
view.setModel(&proxy);
|
||||
view.resize(500, 500);
|
||||
view.show();
|
||||
view.header()->hideSection(2);
|
||||
QVERIFY(view.header()->isSectionHidden(2));
|
||||
proxy.removeColumn();
|
||||
QCOMPARE(proxy.columnCount(), 2);
|
||||
QVERIFY(view.header()->isSectionHidden(1));
|
||||
const QByteArray data = view.header()->saveState();
|
||||
|
||||
QTreeView view2;
|
||||
view2.setModel(&proxy);
|
||||
view2.resize(500, 500);
|
||||
view2.show();
|
||||
view2.header()->restoreState(data);
|
||||
QVERIFY(view2.header()->isSectionHidden(1));
|
||||
}
|
||||
|
||||
class Model_11466 : public QAbstractItemModel
|
||||
{
|
||||
Q_OBJECT
|
||||
|
|
|
|||
|
|
@ -98,6 +98,7 @@ private slots:
|
|||
void heightForWidth();
|
||||
void tabBarClicked();
|
||||
void moveCurrentTab();
|
||||
void autoHide();
|
||||
|
||||
private:
|
||||
int addPage();
|
||||
|
|
@ -713,5 +714,33 @@ void tst_QTabWidget::moveCurrentTab()
|
|||
QCOMPARE(tabWidget.currentWidget(), secondTab);
|
||||
}
|
||||
|
||||
void tst_QTabWidget::autoHide()
|
||||
{
|
||||
QTabWidget tabWidget;
|
||||
QWidget* firstTab = new QWidget(&tabWidget);
|
||||
tabWidget.addTab(firstTab, "0");
|
||||
const auto sizeHint1 = tabWidget.sizeHint();
|
||||
const auto minSizeHint1 = tabWidget.minimumSizeHint();
|
||||
const auto heightForWidth1 = tabWidget.heightForWidth(20);
|
||||
|
||||
QWidget* secondTab = new QWidget(&tabWidget);
|
||||
tabWidget.addTab(secondTab, "1");
|
||||
const auto sizeHint2 = tabWidget.sizeHint();
|
||||
const auto minSizeHint2 = tabWidget.minimumSizeHint();
|
||||
const auto heightForWidth2 = tabWidget.heightForWidth(20);
|
||||
|
||||
tabWidget.setTabBarAutoHide(true);
|
||||
// size should not change
|
||||
QCOMPARE(sizeHint2, tabWidget.sizeHint());
|
||||
QCOMPARE(minSizeHint2, tabWidget.minimumSizeHint());
|
||||
QCOMPARE(heightForWidth2, tabWidget.heightForWidth(20));
|
||||
|
||||
tabWidget.removeTab(1);
|
||||
// this size should change now since the tab should be hidden
|
||||
QVERIFY(sizeHint1.height() > tabWidget.sizeHint().height());
|
||||
QVERIFY(minSizeHint1.height() > tabWidget.sizeHint().height());
|
||||
QVERIFY(heightForWidth1 > tabWidget.heightForWidth(20));
|
||||
}
|
||||
|
||||
QTEST_MAIN(tst_QTabWidget)
|
||||
#include "tst_qtabwidget.moc"
|
||||
|
|
|
|||
|
|
@ -43,6 +43,8 @@ Q_OBJECT
|
|||
private slots:
|
||||
void signal_slot_benchmark();
|
||||
void signal_slot_benchmark_data();
|
||||
void signal_many_receivers();
|
||||
void signal_many_receivers_data();
|
||||
void qproperty_benchmark_data();
|
||||
void qproperty_benchmark();
|
||||
void dynamic_property_benchmark();
|
||||
|
|
@ -127,13 +129,36 @@ void QObjectBenchmark::signal_slot_benchmark()
|
|||
}
|
||||
}
|
||||
|
||||
void QObjectBenchmark::signal_many_receivers_data()
|
||||
{
|
||||
QTest::addColumn<int>("receiverCount");
|
||||
QTest::newRow("100 receivers") << 100;
|
||||
QTest::newRow("1 000 receivers") << 1000;
|
||||
QTest::newRow("10 000 receivers") << 10000;
|
||||
}
|
||||
|
||||
void QObjectBenchmark::signal_many_receivers()
|
||||
{
|
||||
QFETCH(int, receiverCount);
|
||||
Object sender;
|
||||
std::vector<Object> receivers(receiverCount);
|
||||
|
||||
for (Object &receiver : receivers)
|
||||
QObject::connect(&sender, &Object::signal0, &receiver, &Object::slot0);
|
||||
|
||||
QBENCHMARK {
|
||||
sender.emitSignal0();
|
||||
}
|
||||
}
|
||||
|
||||
void QObjectBenchmark::qproperty_benchmark_data()
|
||||
{
|
||||
QTest::addColumn<QByteArray>("name");
|
||||
const QMetaObject *mo = &QTreeView::staticMetaObject;
|
||||
for (int i = 0; i < mo->propertyCount(); ++i) {
|
||||
QMetaProperty prop = mo->property(i);
|
||||
QTest::newRow(prop.name()) << QByteArray(prop.name());
|
||||
if (prop.isWritable())
|
||||
QTest::newRow(prop.name()) << QByteArray(prop.name());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue