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

Change-Id: Idf471ca5c6cf211813466b539ce45bdc1ae9b97c
bb10
Qt Forward Merge Bot 2018-03-08 09:27:37 +01:00
commit 332ce6734d
34 changed files with 511 additions and 305 deletions

View File

@ -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)

View File

@ -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."
},
{

View File

@ -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;
}

View File

@ -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

View File

@ -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);

View File

@ -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

View File

@ -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;

View File

@ -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

View File

@ -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);

View File

@ -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);

View File

@ -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

View File

@ -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);
}
}
}

View File

@ -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);

View File

@ -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

View File

@ -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;

View File

@ -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

View File

@ -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

View File

@ -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) :

View File

@ -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

View File

@ -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;
};

View File

@ -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;
}

View File

@ -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);

View File

@ -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) {

View File

@ -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();

View File

@ -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()

View File

@ -7,6 +7,8 @@ osx-10.12 ci
ubuntu-16.04
[modalWithChildWindow]
ubuntu-16.04
# QTBUG-66851
opensuse
[setVisible]
[modalWindowEnterEventOnHide_QTBUG35109]
ubuntu-16.04

View File

@ -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 \

View File

@ -1 +0,0 @@
tst_qobjectperformance

View File

@ -1,7 +0,0 @@
CONFIG += testcase
TARGET = tst_qobjectperformance
SOURCES += tst_qobjectperformance.cpp
QT = core network testlib

View File

@ -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"

View File

@ -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()
{

View File

@ -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

View File

@ -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"

View File

@ -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());
}
}