Merge remote-tracking branch 'origin/5.9' into 5.10

Conflicts:
	src/corelib/io/qstandardpaths_win.cpp
	src/plugins/platforms/ios/qioswindow.mm
	src/plugins/platforms/ios/quiview.mm
	tests/auto/widgets/itemviews/qtreeview/tst_qtreeview.cpp

Change-Id: I5deb0a0176a454a9c566e924d074ba60ce04f0bc
This commit is contained in:
Liang Qi 2017-11-23 12:32:56 +01:00 committed by Tor Arne Vestbø
commit 7c4b0aa970
36 changed files with 601 additions and 91 deletions

View File

@ -82,7 +82,7 @@ Build options:
-debug-and-release ... Build two versions of Qt, with and without
debugging turned on [yes] (Apple and Windows only)
-optimize-debug ...... Enable debug-friendly optimizations in debug builds
[auto] (Not supported with MSVC)
[auto] (Not supported with MSVC or Clang toolchains)
-optimize-size ....... Optimize release builds for size instead of speed [no]
-optimized-tools ..... Build optimized host tools even in debug build [no]
-force-debug-info .... Create symbol files for release builds [no]

View File

@ -704,7 +704,7 @@
},
"optimize_debug": {
"label": "Optimize debug build",
"condition": "!config.msvc && (features.debug || features.debug_and_release) && tests.optimize_debug",
"condition": "!config.msvc && !config.clang && (features.debug || features.debug_and_release) && tests.optimize_debug",
"output": [ "privateConfig" ]
},
"optimize_size": {
@ -1352,7 +1352,7 @@ Configure with '-qreal float' to create a build that is binary-compatible with 5
{
"type": "feature",
"args": "optimize_debug",
"condition": "!config.msvc && (features.debug || features.debug_and_release)"
"condition": "!config.msvc && !config.clang && (features.debug || features.debug_and_release)"
},
{
"type": "feature",

View File

@ -137,6 +137,9 @@ function(QT5_CREATE_MOC_COMMAND infile outfile moc_flags moc_options moc_target
DEPENDS ${infile} ${moc_depends}
${_moc_working_dir}
VERBATIM)
set_source_files_properties(${infile} PROPERTIES SKIP_AUTOMOC ON)
set_source_files_properties(${outfile} PROPERTIES SKIP_AUTOMOC ON)
set_source_files_properties(${outfile} PROPERTIES SKIP_AUTOUIC ON)
endfunction()
@ -155,7 +158,6 @@ function(QT5_GENERATE_MOC infile outfile )
set(moc_target ${ARGV3})
endif()
qt5_create_moc_command(${abs_infile} ${_outfile} "${moc_flags}" "" "${moc_target}" "")
set_source_files_properties(${outfile} PROPERTIES SKIP_AUTOMOC TRUE) # dont run automoc on this file
endfunction()
@ -246,6 +248,7 @@ function(QT5_ADD_BINARY_RESOURCES target )
get_filename_component(infile ${it} ABSOLUTE)
_QT5_PARSE_QRC_FILE(${infile} _out_depends _rc_depends)
set_source_files_properties(${infile} PROPERTIES SKIP_AUTORCC ON)
set(infiles ${infiles} ${infile})
set(out_depends ${out_depends} ${_out_depends})
set(rc_depends ${rc_depends} ${_rc_depends})
@ -255,7 +258,6 @@ function(QT5_ADD_BINARY_RESOURCES target )
COMMAND ${Qt5Core_RCC_EXECUTABLE}
ARGS ${rcc_options} --binary --name ${target} --output ${rcc_destination} ${infiles}
DEPENDS ${rc_depends} ${out_depends} VERBATIM)
add_custom_target(${target} ALL DEPENDS ${rcc_destination})
endfunction()
@ -283,12 +285,15 @@ function(QT5_ADD_RESOURCES outfiles )
set(outfile ${CMAKE_CURRENT_BINARY_DIR}/qrc_${outfilename}.cpp)
_QT5_PARSE_QRC_FILE(${infile} _out_depends _rc_depends)
set_source_files_properties(${infile} PROPERTIES SKIP_AUTORCC ON)
add_custom_command(OUTPUT ${outfile}
COMMAND ${Qt5Core_RCC_EXECUTABLE}
ARGS ${rcc_options} --name ${outfilename} --output ${outfile} ${infile}
MAIN_DEPENDENCY ${infile}
DEPENDS ${_rc_depends} "${out_depends}" VERBATIM)
set_source_files_properties(${outfile} PROPERTIES SKIP_AUTOMOC ON)
set_source_files_properties(${outfile} PROPERTIES SKIP_AUTOUIC ON)
list(APPEND ${outfiles} ${outfile})
endforeach()
set(${outfiles} ${${outfiles}} PARENT_SCOPE)

View File

@ -44,7 +44,16 @@
#include <QtCore/qmetatype.h>
#include <string.h>
#if defined __F16C__
#if defined(QT_COMPILER_SUPPORTS_F16C) && defined(__AVX2__) && !defined(__F16C__)
// All processors that support AVX2 do support F16C too. That doesn't mean
// we're allowed to use the intrinsics directly, so we'll do it only for
// the Intel and Microsoft's compilers.
# if defined(Q_CC_INTEL) || defined(Q_CC_MSVC)
# define __F16C__ 1
# endif
#endif
#if defined(QT_COMPILER_SUPPORTS_F16C) && defined(__F16C__)
#include <immintrin.h>
#endif
@ -116,7 +125,7 @@ QT_WARNING_DISABLE_CLANG("-Wc99-extensions")
QT_WARNING_DISABLE_GCC("-Wold-style-cast")
inline qfloat16::qfloat16(float f) Q_DECL_NOTHROW
{
#if defined(QT_COMPILER_SUPPORTS_F16C) && (defined(__F16C__) || defined(__AVX2__))
#if defined(QT_COMPILER_SUPPORTS_F16C) && defined(__F16C__)
__m128 packsingle = _mm_set_ss(f);
__m128i packhalf = _mm_cvtps_ph(packsingle, 0);
b16 = _mm_extract_epi16(packhalf, 0);
@ -134,7 +143,7 @@ QT_WARNING_POP
inline qfloat16::operator float() const Q_DECL_NOTHROW
{
#if defined(QT_COMPILER_SUPPORTS_F16C) && (defined(__F16C__) || defined(__AVX2__))
#if defined(QT_COMPILER_SUPPORTS_F16C) && defined(__F16C__)
__m128i packhalf = _mm_cvtsi32_si128(b16);
__m128 packsingle = _mm_cvtph_ps(packhalf);
return _mm_cvtss_f32(packsingle);

View File

@ -201,6 +201,10 @@ QString QStandardPaths::writableLocation(StandardLocation type)
return result;
}
#ifndef QT_BOOTSTRAPPED
extern QString qAppFileName();
#endif
QStringList QStandardPaths::standardLocations(StandardLocation type)
{
QStringList dirs;
@ -217,8 +221,13 @@ QStringList QStandardPaths::standardLocations(StandardLocation type)
dirs.append(programData);
}
#ifndef QT_BOOTSTRAPPED
dirs.append(QCoreApplication::applicationDirPath());
const QString dataDir = QCoreApplication::applicationDirPath() + QLatin1String("/data");
// Note: QCoreApplication::applicationDirPath(), while static, requires
// an application instance. But we might need to resolve the standard
// locations earlier than that, so we fall back to qAppFileName().
QString applicationDirPath = qApp ? QCoreApplication::applicationDirPath()
: QFileInfo(qAppFileName()).path();
dirs.append(applicationDirPath);
const QString dataDir = applicationDirPath + QLatin1String("/data");
dirs.append(dataDir);
if (!isGenericConfigLocation(type)) {

View File

@ -58,6 +58,9 @@ QT_BEGIN_NAMESPACE
*/
QPlatformPixmap *QPlatformPixmap::create(int w, int h, PixelType type)
{
if (Q_UNLIKELY(!QGuiApplicationPrivate::platformIntegration()))
qFatal("QPlatformPixmap: QGuiApplication required");
QPlatformPixmap *data = QGuiApplicationPrivate::platformIntegration()->createPlatformPixmap(static_cast<QPlatformPixmap::PixelType>(type));
data->resize(w, h);
return data;

View File

@ -265,12 +265,12 @@ void QWindowSystemInterface::handleWindowScreenChanged(QWindow *window, QScreen
QWindowSystemInterfacePrivate::handleWindowSystemEvent(e);
}
void QWindowSystemInterface::handleApplicationStateChanged(Qt::ApplicationState newState, bool forcePropagate)
QT_DEFINE_QPA_EVENT_HANDLER(void, handleApplicationStateChanged, Qt::ApplicationState newState, bool forcePropagate)
{
Q_ASSERT(QGuiApplicationPrivate::platformIntegration()->hasCapability(QPlatformIntegration::ApplicationState));
QWindowSystemInterfacePrivate::ApplicationStateChangedEvent *e =
new QWindowSystemInterfacePrivate::ApplicationStateChangedEvent(newState, forcePropagate);
QWindowSystemInterfacePrivate::handleWindowSystemEvent(e);
QWindowSystemInterfacePrivate::handleWindowSystemEvent<Delivery>(e);
}
QWindowSystemInterfacePrivate::GeometryChangeEvent::GeometryChangeEvent(QWindow *window, const QRect &newGeometry)

View File

@ -180,6 +180,7 @@ public:
static void handleWindowStateChanged(QWindow *window, Qt::WindowStates newState, int oldState = -1);
static void handleWindowScreenChanged(QWindow *window, QScreen *newScreen);
template<typename Delivery = QWindowSystemInterface::DefaultDelivery>
static void handleApplicationStateChanged(Qt::ApplicationState newState, bool forcePropagate = false);
#ifndef QT_NO_DRAGANDDROP

View File

@ -1027,8 +1027,7 @@ QNetworkConfiguration QNetworkAccessManager::configuration() const
if (session) {
return session->configuration();
} else {
QNetworkConfigurationManager manager;
return manager.defaultConfiguration();
return d->networkConfigurationManager.defaultConfiguration();
}
}
@ -1052,12 +1051,11 @@ QNetworkConfiguration QNetworkAccessManager::activeConfiguration() const
Q_D(const QNetworkAccessManager);
QSharedPointer<QNetworkSession> networkSession(d->getNetworkSession());
QNetworkConfigurationManager manager;
if (networkSession) {
return manager.configurationFromIdentifier(
return d->networkConfigurationManager.configurationFromIdentifier(
networkSession->sessionProperty(QLatin1String("ActiveConfiguration")).toString());
} else {
return manager.defaultConfiguration();
return d->networkConfigurationManager.defaultConfiguration();
}
}
@ -1384,17 +1382,16 @@ QNetworkReply *QNetworkAccessManager::createRequest(QNetworkAccessManager::Opera
}
if (!d->networkSessionStrongRef && (d->initializeSession || !d->networkConfiguration.identifier().isEmpty())) {
QNetworkConfigurationManager manager;
if (!d->networkConfiguration.identifier().isEmpty()) {
if ((d->networkConfiguration.state() & QNetworkConfiguration::Defined)
&& d->networkConfiguration != manager.defaultConfiguration())
d->createSession(manager.defaultConfiguration());
&& d->networkConfiguration != d->networkConfigurationManager.defaultConfiguration())
d->createSession(d->networkConfigurationManager.defaultConfiguration());
else
d->createSession(d->networkConfiguration);
} else {
if (manager.capabilities() & QNetworkConfigurationManager::NetworkSessionRequired)
d->createSession(manager.defaultConfiguration());
if (d->networkSessionRequired)
d->createSession(d->networkConfigurationManager.defaultConfiguration());
else
d->initializeSession = false;
}
@ -1926,8 +1923,8 @@ void QNetworkAccessManagerPrivate::_q_onlineStateChanged(bool isOnline)
online = (networkConfiguration.state() & QNetworkConfiguration::Active);
} else {
if (online != isOnline) {
_q_networkSessionClosed();
createSession(q->configuration());
_q_networkSessionClosed();
createSession(q->configuration());
online = isOnline;
}
}
@ -1951,13 +1948,13 @@ void QNetworkAccessManagerPrivate::_q_configurationChanged(const QNetworkConfigu
const QString id = configuration.identifier();
if (configuration.state().testFlag(QNetworkConfiguration::Active)) {
if (!onlineConfigurations.contains(id)) {
QSharedPointer<QNetworkSession> session(getNetworkSession());
if (session) {
if (online && session->configuration().identifier()
!= networkConfigurationManager.defaultConfiguration().identifier()) {
onlineConfigurations.insert(id);
// CHECK: If it's having Active flag - why would it be disconnected ???
//this one disconnected but another one is online,
// close and create new session
_q_networkSessionClosed();
@ -1968,6 +1965,7 @@ void QNetworkAccessManagerPrivate::_q_configurationChanged(const QNetworkConfigu
} else if (onlineConfigurations.contains(id)) {
//this one is disconnecting
// CHECK: If it disconnected while we create a session over a down configuration ???
onlineConfigurations.remove(id);
if (!onlineConfigurations.isEmpty()) {
_q_networkSessionClosed();

View File

@ -112,9 +112,11 @@ static bool isDBusTrayAvailable() {
#ifndef QT_NO_DBUS
static bool checkDBusGlobalMenuAvailable()
{
QDBusConnection connection = QDBusConnection::sessionBus();
QString registrarService = QStringLiteral("com.canonical.AppMenu.Registrar");
return connection.interface()->isServiceRegistered(registrarService);
const QDBusConnection connection = QDBusConnection::sessionBus();
static const QString registrarService = QStringLiteral("com.canonical.AppMenu.Registrar");
if (const auto iface = connection.interface())
return iface->isServiceRegistered(registrarService);
return false;
}
static bool isDBusGlobalMenuAvailable()

View File

@ -39,6 +39,8 @@
#include "qiosapplicationstate.h"
#include "qiosglobal.h"
#include <qpa/qwindowsysteminterface.h>
#include <QtCore/qcoreapplication.h>
@ -72,8 +74,8 @@ static Qt::ApplicationState qtApplicationState(UIApplicationState uiApplicationS
static void handleApplicationStateChanged(UIApplicationState uiApplicationState)
{
Qt::ApplicationState state = qtApplicationState(uiApplicationState);
QWindowSystemInterface::handleApplicationStateChanged(state);
QWindowSystemInterface::flushWindowSystemEvents();
qCDebug(lcQpaApplication) << "moved to" << state;
QWindowSystemInterface::handleApplicationStateChanged<QWindowSystemInterface::SynchronousDelivery>(state);
}
QT_BEGIN_NAMESPACE

View File

@ -165,8 +165,6 @@ bool QIOSContext::makeCurrent(QPlatformSurface *surface)
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER,
framebufferObject.depthRenderbuffer);
}
connect(static_cast<QIOSWindow *>(surface), SIGNAL(destroyed(QObject*)), this, SLOT(windowDestroyed(QObject*)));
} else {
glBindFramebuffer(GL_FRAMEBUFFER, framebufferObject.handle);
}
@ -249,8 +247,13 @@ QIOSContext::FramebufferObject &QIOSContext::backingFramebufferObjectFor(QPlatfo
// should probably use QOpenGLMultiGroupSharedResource to track the shared default-FBOs.
if (m_sharedContext)
return m_sharedContext->backingFramebufferObjectFor(surface);
else
return m_framebufferObjects[surface];
if (!m_framebufferObjects.contains(surface)) {
// We're about to create a new FBO, make sure it's cleaned up as well
connect(static_cast<QIOSWindow *>(surface), SIGNAL(destroyed(QObject*)), this, SLOT(windowDestroyed(QObject*)));
}
return m_framebufferObjects[surface];
}
GLuint QIOSContext::defaultFramebufferObject(QPlatformSurface *surface) const

View File

@ -47,7 +47,9 @@
QT_BEGIN_NAMESPACE
Q_DECLARE_LOGGING_CATEGORY(lcQpaApplication);
Q_DECLARE_LOGGING_CATEGORY(lcQpaInputMethods);
Q_DECLARE_LOGGING_CATEGORY(lcQpaWindow);
#if !defined(QT_NO_DEBUG)
#define qImDebug \

View File

@ -44,7 +44,9 @@
QT_BEGIN_NAMESPACE
Q_LOGGING_CATEGORY(lcQpaApplication, "qt.qpa.application");
Q_LOGGING_CATEGORY(lcQpaInputMethods, "qt.qpa.input.methods");
Q_LOGGING_CATEGORY(lcQpaWindow, "qt.qpa.window");
bool isQtApplication()
{

View File

@ -239,15 +239,28 @@ void QIOSWindow::setWindowState(Qt::WindowStates state)
if (window()->isTopLevel() && window()->isVisible() && window()->isActive())
[m_view.qtViewController updateProperties];
if (state & Qt::WindowMinimized)
if (state & Qt::WindowMinimized) {
applyGeometry(QRect());
else if (state & Qt::WindowFullScreen)
applyGeometry(screen()->geometry());
else if (state & Qt::WindowMaximized)
applyGeometry(window()->flags() & Qt::MaximizeUsingFullscreenGeometryHint ?
screen()->geometry() : screen()->availableGeometry());
else
} else if (state & (Qt::WindowFullScreen | Qt::WindowMaximized)) {
// When an application is in split-view mode, the UIScreen still has the
// same geometry, but the UIWindow is resized to the area reserved for the
// application. We use this to constrain the geometry used when applying the
// fullscreen or maximized window states. Note that we do not do this
// in applyGeometry(), as we don't want to artificially limit window
// placement "outside" of the screen bounds if that's what the user wants.
QRect uiWindowBounds = QRectF::fromCGRect(m_view.window.bounds).toRect();
QRect fullscreenGeometry = screen()->geometry().intersected(uiWindowBounds);
QRect maximizedGeometry = window()->flags() & Qt::MaximizeUsingFullscreenGeometryHint ?
fullscreenGeometry : screen()->availableGeometry().intersected(uiWindowBounds);
if (state & Qt::WindowFullScreen)
applyGeometry(fullscreenGeometry);
else
applyGeometry(maximizedGeometry);
} else {
applyGeometry(m_normalGeometry);
}
}
void QIOSWindow::setParent(const QPlatformWindow *parentWindow)

View File

@ -161,6 +161,7 @@
QWindow *window = m_qioswindow->window();
QRect lastReportedGeometry = qt_window_private(window)->geometry;
QRect currentGeometry = QRectF::fromCGRect(self.frame).toRect();
qCDebug(lcQpaWindow) << m_qioswindow->window() << "new geometry is" << currentGeometry;
QWindowSystemInterface::handleGeometryChange<QWindowSystemInterface::SynchronousDelivery>(window, currentGeometry);
if (currentGeometry.size() != lastReportedGeometry.size()) {
@ -193,6 +194,7 @@
region = QRect(QPoint(), bounds);
}
qCDebug(lcQpaWindow) << m_qioswindow->window() << region << "isExposed" << m_qioswindow->isExposed();
QWindowSystemInterface::handleExposeEvent<QWindowSystemInterface::SynchronousDelivery>(m_qioswindow->window(), region);
}

View File

@ -59,6 +59,9 @@ function(QT5_WRAP_UI outfiles )
COMMAND ${Qt5Widgets_UIC_EXECUTABLE}
ARGS ${ui_options} -o ${outfile} ${infile}
MAIN_DEPENDENCY ${infile} VERBATIM)
set_source_files_properties(${infile} PROPERTIES SKIP_AUTOUIC ON)
set_source_files_properties(${outfile} PROPERTIES SKIP_AUTOMOC ON)
set_source_files_properties(${outfile} PROPERTIES SKIP_AUTOUIC ON)
list(APPEND ${outfiles} ${outfile})
endforeach()
set(${outfiles} ${${outfiles}} PARENT_SCOPE)

View File

@ -2086,40 +2086,26 @@ void QHeaderViewPrivate::_q_layoutChanged()
{
Q_Q(QHeaderView);
viewport->update();
if (persistentHiddenSections.isEmpty() || modelIsEmpty()) {
if (modelSectionCount() != sectionCount())
q->initializeSections();
persistentHiddenSections.clear();
const auto hiddenSections = persistentHiddenSections;
persistentHiddenSections.clear();
clear();
q->initializeSections();
invalidateCachedSizeHint();
if (modelIsEmpty()) {
return;
}
QBitArray oldSectionHidden = sectionsHiddenToBitVector();
oldSectionHidden.resize(sectionItems.size());
bool sectionCountChanged = false;
for (int i = 0; i < persistentHiddenSections.count(); ++i) {
QModelIndex index = persistentHiddenSections.at(i);
for (const auto &index : hiddenSections) {
if (index.isValid()) {
const int logical = (orientation == Qt::Horizontal
? index.column()
: index.row());
q->setSectionHidden(logical, true);
oldSectionHidden.setBit(logical, false);
} else if (!sectionCountChanged && (modelSectionCount() != sectionCount())) {
sectionCountChanged = true;
break;
}
}
persistentHiddenSections.clear();
for (int i = 0; i < oldSectionHidden.count(); ++i) {
if (oldSectionHidden.testBit(i))
q->setSectionHidden(i, false);
}
// the number of sections changed; we need to reread the state of the model
if (sectionCountChanged)
q->initializeSections();
}
/*!

View File

@ -1397,6 +1397,9 @@ void QTableView::paintEvent(QPaintEvent *event)
} else {
dirtyArea.setRight(qMin(dirtyArea.right(), int(x)));
}
// dirtyArea may be invalid when the horizontal header is not stretched
if (!dirtyArea.isValid())
continue;
// get the horizontal start and end visual sections
int left = horizontalHeader->visualIndexAt(dirtyArea.left());

View File

@ -736,7 +736,10 @@ void QTreeView::dataChanged(const QModelIndex &topLeft, const QModelIndex &botto
void QTreeView::hideColumn(int column)
{
Q_D(QTreeView);
if (d->header->isSectionHidden(column))
return;
d->header->hideSection(column);
doItemsLayout();
}
/*!
@ -747,7 +750,10 @@ void QTreeView::hideColumn(int column)
void QTreeView::showColumn(int column)
{
Q_D(QTreeView);
if (!d->header->isSectionHidden(column))
return;
d->header->showSection(column);
doItemsLayout();
}
/*!
@ -1008,11 +1014,16 @@ void QTreeView::keyboardSearch(const QString &search)
if (!d->model->rowCount(d->root) || !d->model->columnCount(d->root))
return;
// Do a relayout nows, so that we can utilize viewItems
d->executePostedLayout();
if (d->viewItems.isEmpty())
return;
QModelIndex start;
if (currentIndex().isValid())
start = currentIndex();
else
start = d->model->index(0, 0, d->root);
start = d->viewItems.at(0).index;
bool skipRow = false;
bool keyboardTimeWasValid = d->keyboardInputTime.isValid();
@ -1040,13 +1051,16 @@ void QTreeView::keyboardSearch(const QString &search)
// skip if we are searching for the same key or a new search started
if (skipRow) {
if (indexBelow(start).isValid())
if (indexBelow(start).isValid()) {
start = indexBelow(start);
else
start = d->model->index(0, start.column(), d->root);
} else {
const int origCol = start.column();
start = d->viewItems.at(0).index;
if (origCol != start.column())
start = start.sibling(start.row(), origCol);
}
}
d->executePostedLayout();
int startIndex = d->viewIndex(start);
if (startIndex <= -1)
return;

View File

@ -476,8 +476,10 @@ void QFusionStyle::drawPrimitive(PrimitiveElement elem,
break;
if (option->state & State_Open)
drawPrimitive(PE_IndicatorArrowDown, option, painter, widget);
else
drawPrimitive(PE_IndicatorArrowRight, option, painter, widget);
else {
const bool reverse = (option->direction == Qt::RightToLeft);
drawPrimitive(reverse ? PE_IndicatorArrowLeft : PE_IndicatorArrowRight, option, painter, widget);
}
break;
}
#if QT_CONFIG(tabbar)

View File

@ -1119,6 +1119,8 @@ static bool waitForPopup(QToolBar *tb, QWidget *popup)
static void enableMacToolBar(QToolBar *toolbar, bool enable)
{
QPlatformNativeInterface *nativeInterface = QApplication::platformNativeInterface();
if (!nativeInterface)
return;
QPlatformNativeInterface::NativeResourceForIntegrationFunction function =
nativeInterface->nativeResourceFunctionForIntegration("setContentBorderAreaEnabled");
if (!function)

View File

@ -157,7 +157,13 @@ if (NOT CMAKE_VERSION VERSION_LESS 2.8.11 AND NOT NO_WIDGETS)
expect_pass(test_interface)
endif()
if (NOT CMAKE_VERSION VERSION_LESS 2.8.12)
expect_pass(test_interface_link_libraries)
expect_pass(test_moc_macro_target)
expect_pass(test_interface_link_libraries)
expect_pass(test_moc_macro_target)
if (NOT CMAKE_VERSION VERSION_LESS 3.8)
# With earlier CMake versions, this test would simply run moc multiple times and lead to:
# /usr/bin/ld: error: CMakeFiles/mywidget.dir/mywidget_automoc.cpp.o: multiple definition of 'MyWidget::qt_static_metacall(QObject*, QMetaObject::Call, int, void**)'
# /usr/bin/ld: CMakeFiles/mywidget.dir/moc_mywidget.cpp.o: previous definition here
# Reason: SKIP_* properties were added in CMake 3.8 only
expect_pass(test_QTBUG-63422)
endif()

View File

@ -0,0 +1,30 @@
cmake_minimum_required(VERSION 2.8)
project(test_dependent_modules)
find_package(Qt5Widgets REQUIRED)
set(CMAKE_AUTOMOC ON)
set(CMAKE_AUTOUIC ON)
set(CMAKE_AUTORCC ON)
set(CMAKE_INCLUDE_CURRENT_DIR ON)
# make sure CMP0071 warnings cause a test failure
set(CMAKE_SUPPRESS_DEVELOPER_ERRORS FALSE CACHE INTERNAL "" FORCE)
qt5_wrap_cpp(moc_files mywidget.h)
qt5_wrap_ui(ui_files mywidget.ui)
qt5_add_resources(qrc_files res.qrc)
add_executable(mywidget
# source files
mywidget.cpp
mywidget.h
mywidget.ui
res.qrc
# generated files
${moc_files}
${ui_files}
${qrc_files}
)
target_link_libraries(mywidget ${Qt5Widgets_LIBRARIES})

View File

@ -0,0 +1,43 @@
/****************************************************************************
**
** Copyright (C) 2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Kevin Funk <kevin.funk@kdab.com>
** 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 "mywidget.h"
#include "ui_mywidget.h"
MyWidget::MyWidget(QWidget *parent)
: QWidget(parent)
{
emit someSignal();
}
int main(int argc, char **argv)
{
QApplication app(argc, argv);
MyWidget myWidget;
return 0;
}

View File

@ -0,0 +1,52 @@
/****************************************************************************
**
** Copyright (C) 2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Kevin Funk <kevin.funk@kdab.com>
** 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$
**
****************************************************************************/
#ifndef MYWIDGET_H
#define MYWIDGET_H
#include <QWidget>
namespace Ui
{
class MyWidget;
}
class MyWidget : public QWidget
{
Q_OBJECT
public:
MyWidget(QWidget *parent = nullptr);
signals:
void someSignal();
private:
Ui::MyWidget *ui = nullptr;
};
#endif

View File

@ -0,0 +1,34 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>Form</class>
<widget class="QWidget" name="Form">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>400</width>
<height>300</height>
</rect>
</property>
<property name="windowTitle">
<string>Form</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QPushButton" name="pushButton">
<property name="text">
<string>PushButton</string>
</property>
</widget>
</item>
<item>
<widget class="QLineEdit" name="lineEdit"/>
</item>
<item>
<widget class="QTextEdit" name="textEdit"/>
</item>
</layout>
</widget>
<resources/>
<connections/>
</ui>

View File

@ -0,0 +1,4 @@
<!DOCTYPE RCC><RCC version="1.0">
<qresource>
</qresource>
</RCC>

View File

@ -95,6 +95,7 @@ private slots:
void stackSize();
void stressTest();
void takeAllAndIncreaseMaxThreadCount();
void waitForDoneAfterTake();
private:
QMutex m_functionTestMutex;
@ -1267,5 +1268,72 @@ void tst_QThreadPool::takeAllAndIncreaseMaxThreadCount() {
delete task3;
}
void tst_QThreadPool::waitForDoneAfterTake()
{
class Task : public QRunnable
{
public:
Task(QSemaphore *mainBarrier, QSemaphore *threadBarrier)
: m_mainBarrier(mainBarrier)
, m_threadBarrier(threadBarrier)
{}
void run()
{
m_mainBarrier->release();
m_threadBarrier->acquire();
}
private:
QSemaphore *m_mainBarrier = nullptr;
QSemaphore *m_threadBarrier = nullptr;
};
int threadCount = 4;
// Blocks the main thread from releasing the threadBarrier before all run() functions have started
QSemaphore mainBarrier;
// Blocks the tasks from completing their run function
QSemaphore threadBarrier;
QThreadPool manager;
manager.setMaxThreadCount(threadCount);
// Fill all the threads with runnables that wait for the threadBarrier
for (int i = 0; i < threadCount; i++) {
auto *task = new Task(&mainBarrier, &threadBarrier);
manager.start(task);
}
QVERIFY(manager.activeThreadCount() == manager.maxThreadCount());
// Add runnables that are immediately removed from the pool queue.
// This sets the queue elements to nullptr in QThreadPool and we want to test that
// the threads keep going through the queue after encountering a nullptr.
for (int i = 0; i < threadCount; i++) {
QRunnable *runnable = createTask(emptyFunct);
manager.start(runnable);
QVERIFY(manager.tryTake(runnable));
}
// Add another runnable that will not be removed
manager.start(createTask(emptyFunct));
// Wait for the first runnables to start
mainBarrier.acquire(threadCount);
QVERIFY(mainBarrier.available() == 0);
QVERIFY(threadBarrier.available() == 0);
// Release runnables that are waiting and expect all runnables to complete
threadBarrier.release(threadCount);
// Using qFatal instead of QVERIFY to force exit if threads are still running after timeout.
// Otherwise, QCoreApplication will still wait for the stale threads and never exit the test.
if (!manager.waitForDone(5 * 60 * 1000))
qFatal("waitForDone returned false. Aborting to stop background threads.");
}
QTEST_MAIN(tst_QThreadPool);
#include "tst_qthreadpool.moc"

View File

@ -622,7 +622,7 @@ protected:
Q_ASSERT(!client.isNull());
// we need to emulate the bytesWrittenSlot call if the data is empty.
if (dataToTransmit.size() == 0) {
QMetaObject::invokeMethod(this, "bytesWrittenSlot", Qt::QueuedConnection);
emit client->bytesWritten(0);
} else {
client->write(dataToTransmit);
// FIXME: For SSL connections, if we don't flush the socket, the
@ -659,22 +659,26 @@ private slots:
#ifndef QT_NO_SSL
void slotSslErrors(const QList<QSslError>& errors)
{
Q_ASSERT(!client.isNull());
qDebug() << "slotSslErrors" << client->errorString() << errors;
QTcpSocket *currentClient = qobject_cast<QTcpSocket *>(sender());
Q_ASSERT(currentClient);
qDebug() << "slotSslErrors" << currentClient->errorString() << errors;
}
#endif
void slotError(QAbstractSocket::SocketError err)
{
if (client.isNull())
qDebug() << "slotError" << err;
else
qDebug() << "slotError" << err << client->errorString();
QTcpSocket *currentClient = qobject_cast<QTcpSocket *>(sender());
Q_ASSERT(currentClient);
qDebug() << "slotError" << err << currentClient->errorString();
}
public slots:
void readyReadSlot()
{
Q_ASSERT(!client.isNull());
QTcpSocket *currentClient = qobject_cast<QTcpSocket *>(sender());
Q_ASSERT(currentClient);
if (currentClient != client)
client = currentClient;
receivedData += client->readAll();
const int doubleEndlPos = receivedData.indexOf("\r\n\r\n");
@ -8290,11 +8294,23 @@ void tst_QNetworkReply::ioHttpRedirectErrors()
QNetworkReplyPtr reply(manager.get(request));
if (localhost.scheme() == "https")
reply.data()->ignoreSslErrors();
QSignalSpy spy(reply.data(), SIGNAL(error(QNetworkReply::NetworkError)));
QCOMPARE(waitForFinish(reply), int(Failure));
QEventLoop eventLoop;
QTimer watchDog;
watchDog.setSingleShot(true);
QCOMPARE(spy.count(), 1);
reply->connect(reply.data(), QOverload<QNetworkReply::NetworkError>().of(&QNetworkReply::error),
[&eventLoop](QNetworkReply::NetworkError){
eventLoop.exit(Failure);
});
watchDog.connect(&watchDog, &QTimer::timeout, [&eventLoop](){
eventLoop.exit(Timeout);
});
watchDog.start(5000);
QCOMPARE(eventLoop.exec(), int(Failure));
QCOMPARE(reply->error(), error);
}

View File

@ -1,6 +1,4 @@
windows
[waitForConnectedEncryptedReadyRead:WithSocks5ProxyAuth]
*
[protocolServerSide:ssl3-any]
rhel-7.2
[protocolServerSide:tls1.0-any]

View File

@ -1601,7 +1601,12 @@ void tst_QSslSocket::waitForConnectedEncryptedReadyRead()
QFETCH_GLOBAL(bool, setProxy);
if (setProxy && !socket->waitForEncrypted(10000))
QSKIP("Skipping flaky test - See QTBUG-29941");
QVERIFY(socket->waitForReadyRead(10000));
// We only do this if we have no bytes available to read already because readyRead will
// not be emitted again.
if (socket->bytesAvailable() == 0)
QVERIFY(socket->waitForReadyRead(10000));
QVERIFY(!socket->peerCertificate().isNull());
QVERIFY(!socket->peerCertificateChain().isEmpty());
}

View File

@ -210,6 +210,7 @@ private slots:
void QTBUG12268_hiddenMovedSectionSorting();
void QTBUG14242_hideSectionAutoSize();
void QTBUG50171_visualRegionForSwappedItems();
void QTBUG53221_assertShiftHiddenRow();
void ensureNoIndexAtLength();
void offsetConsistent();
@ -2384,6 +2385,54 @@ void tst_QHeaderView::QTBUG50171_visualRegionForSwappedItems()
headerView.testVisualRegionForSelection();
}
class QTBUG53221_Model : public QAbstractItemModel
{
public:
void insertRowAtBeginning()
{
Q_EMIT layoutAboutToBeChanged();
m_displayNames.insert(0, QStringLiteral("Item %1").arg(m_displayNames.count()));
// Rows are always inserted at the beginning, so move all others.
foreach (const QModelIndex &persIndex, persistentIndexList())
{
// The vertical header view will have a persistent index stored here on the second call to insertRowAtBeginning.
changePersistentIndex(persIndex, index(persIndex.row() + 1, persIndex.column(), persIndex.parent()));
}
Q_EMIT layoutChanged();
}
QVariant data(const QModelIndex &index, int role) const override
{
return (role == Qt::DisplayRole) ? m_displayNames.at(index.row()) : QVariant();
}
QModelIndex index(int row, int column, const QModelIndex &) const override { return createIndex(row, column); }
QModelIndex parent(const QModelIndex &) const override { return QModelIndex(); }
int rowCount(const QModelIndex &) const override { return m_displayNames.count(); }
int columnCount(const QModelIndex &) const override { return 1; }
private:
QStringList m_displayNames;
};
void tst_QHeaderView::QTBUG53221_assertShiftHiddenRow()
{
QTableView tableView;
QTBUG53221_Model modelTableView;
tableView.setModel(&modelTableView);
modelTableView.insertRowAtBeginning();
tableView.setRowHidden(0, true);
QCOMPARE(tableView.verticalHeader()->isSectionHidden(0), true);
modelTableView.insertRowAtBeginning();
QCOMPARE(tableView.verticalHeader()->isSectionHidden(0), false);
QCOMPARE(tableView.verticalHeader()->isSectionHidden(1), true);
modelTableView.insertRowAtBeginning();
QCOMPARE(tableView.verticalHeader()->isSectionHidden(0), false);
QCOMPARE(tableView.verticalHeader()->isSectionHidden(1), false);
QCOMPARE(tableView.verticalHeader()->isSectionHidden(2), true);
}
void protected_QHeaderView::testVisualRegionForSelection()
{
QRegion r = visualRegionForSelection(QItemSelection(model()->index(1, 0), model()->index(1, 2)));

View File

@ -196,6 +196,7 @@ private slots:
void taskQTBUG_37813_crash();
void taskQTBUG_45697_crash();
void taskQTBUG_7232_AllowUserToControlSingleStep();
void taskQTBUG_8376();
void testInitialFocus();
};
@ -1086,6 +1087,103 @@ void tst_QTreeView::keyboardSearch()
// The item that starts with B is selected.
view.keyboardSearch(QLatin1String("B"));
QVERIFY(view.selectionModel()->isSelected(model.index(1, 0)));
// Test that it wraps round
model.appendRow(new QStandardItem("Andy"));
QTest::qWait(QApplication::keyboardInputInterval() * 2);
view.keyboardSearch(QLatin1String("A"));
QVERIFY(view.selectionModel()->isSelected(model.index(3, 0)));
QTest::qWait(QApplication::keyboardInputInterval() * 2);
view.keyboardSearch(QLatin1String("A"));
QVERIFY(view.selectionModel()->isSelected(model.index(0, 0)));
QTest::qWait(QApplication::keyboardInputInterval() * 2);
view.keyboardSearch(QLatin1String("A"));
QVERIFY(view.selectionModel()->isSelected(model.index(3, 0)));
// Test that it handles the case where the first item is hidden correctly
model.insertRow(0, new QStandardItem("Hidden item"));
view.setRowHidden(0, QModelIndex(), true);
QTest::qWait(QApplication::keyboardInputInterval() * 2);
view.keyboardSearch(QLatin1String("A"));
QVERIFY(view.selectionModel()->isSelected(model.index(1, 0)));
QTest::qWait(QApplication::keyboardInputInterval() * 2);
view.keyboardSearch(QLatin1String("A"));
QVERIFY(view.selectionModel()->isSelected(model.index(4, 0)));
QTest::qWait(QApplication::keyboardInputInterval() * 2);
view.keyboardSearch(QLatin1String("A"));
QVERIFY(view.selectionModel()->isSelected(model.index(1, 0)));
QTest::qWait(QApplication::keyboardInputInterval() * 2);
model.clear();
view.setCurrentIndex(QModelIndex());
QList<QStandardItem *> items = { new QStandardItem("Andreas"), new QStandardItem("Alicia") };
model.appendRow(items);
items = { new QStandardItem("Baldrian"), new QStandardItem("Belinda") };
model.appendRow(items);
items = { new QStandardItem("Cecilie"), new QStandardItem("Claire") };
model.appendRow(items);
QVERIFY(!view.selectionModel()->hasSelection());
QVERIFY(!view.selectionModel()->isSelected(model.index(0, 0)));
// We want to search on the 2nd column so we have to force it to have
// an index in that column as a starting point
view.setCurrentIndex(QModelIndex(model.index(0, 1)));
// Second item in first row is selected
view.keyboardSearch(QLatin1String("A"));
QTRY_VERIFY(view.selectionModel()->isSelected(model.index(0, 1)));
QVERIFY(view.currentIndex() == model.index(0, 1));
// Second item in first row is still selected
view.keyboardSearch(QLatin1String("l"));
QVERIFY(view.selectionModel()->isSelected(model.index(0, 1)));
QCOMPARE(view.currentIndex(), model.index(0, 1));
// No "AnB" item - keep the same selection.
view.keyboardSearch(QLatin1String("B"));
QVERIFY(view.selectionModel()->isSelected(model.index(0, 1)));
QCOMPARE(view.currentIndex(), model.index(0, 1));
// Wait a bit.
QTest::qWait(QApplication::keyboardInputInterval() * 2);
// The item that starts with B is selected.
view.keyboardSearch(QLatin1String("B"));
QVERIFY(view.selectionModel()->isSelected(model.index(1, 1)));
QCOMPARE(view.currentIndex(), model.index(1, 1));
// Test that it wraps round
items = { new QStandardItem("Andy"), new QStandardItem("Adele") };
model.appendRow(items);
QTest::qWait(QApplication::keyboardInputInterval() * 2);
view.keyboardSearch(QLatin1String("A"));
QVERIFY(view.selectionModel()->isSelected(model.index(3, 1)));
QCOMPARE(view.currentIndex(), model.index(3, 1));
QTest::qWait(QApplication::keyboardInputInterval() * 2);
view.keyboardSearch(QLatin1String("A"));
QVERIFY(view.selectionModel()->isSelected(model.index(0, 1)));
QCOMPARE(view.currentIndex(), model.index(0, 1));
QTest::qWait(QApplication::keyboardInputInterval() * 2);
view.keyboardSearch(QLatin1String("A"));
QVERIFY(view.selectionModel()->isSelected(model.index(3, 1)));
QCOMPARE(view.currentIndex(), model.index(3, 1));
// Test that it handles the case where the first item is hidden correctly
model.insertRow(0, new QStandardItem("Hidden item"));
view.setRowHidden(0, QModelIndex(), true);
QTest::qWait(QApplication::keyboardInputInterval() * 2);
view.keyboardSearch(QLatin1String("A"));
QVERIFY(view.selectionModel()->isSelected(model.index(1, 1)));
QCOMPARE(view.currentIndex(), model.index(1, 1));
QTest::qWait(QApplication::keyboardInputInterval() * 2);
view.keyboardSearch(QLatin1String("A"));
QVERIFY(view.selectionModel()->isSelected(model.index(4, 1)));
QCOMPARE(view.currentIndex(), model.index(4, 1));
QTest::qWait(QApplication::keyboardInputInterval() * 2);
view.keyboardSearch(QLatin1String("A"));
QVERIFY(view.selectionModel()->isSelected(model.index(1, 1)));
QCOMPARE(view.currentIndex(), model.index(1, 1));
}
void tst_QTreeView::keyboardSearchMultiColumn()
@ -4466,5 +4564,51 @@ void tst_QTreeView::statusTip()
QTest::mouseMove(mw.windowHandle(), centerPoint);
QTRY_COMPARE(mw.statusBar()->currentMessage(), QLatin1String("Header 0 -- Status"));
}
static void fillModeltaskQTBUG_8376(QAbstractItemModel &model)
{
model.insertRow(0);
model.insertColumn(0);
model.insertColumn(1);
QModelIndex index = model.index(0, 0);
model.setData(index, "Level0");
{
model.insertRow(0, index);
model.insertRow(1, index);
model.insertColumn(0, index);
model.insertColumn(1, index);
QModelIndex idx;
idx = model.index(0, 0, index);
model.setData(idx, "Level1");
idx = model.index(0, 1, index);
model.setData(idx, "very\nvery\nhigh\ncell");
}
}
void tst_QTreeView::taskQTBUG_8376()
{
QTreeView tv;
QStandardItemModel model;
fillModeltaskQTBUG_8376(model);
tv.setModel(&model);
tv.expandAll(); // init layout
QModelIndex idxLvl0 = model.index(0, 0);
QModelIndex idxLvl1 = model.index(0, 1, idxLvl0);
const int rowHeightLvl0 = tv.rowHeight(idxLvl0);
const int rowHeightLvl1Visible = tv.rowHeight(idxLvl1);
QVERIFY(rowHeightLvl0 < rowHeightLvl1Visible);
tv.hideColumn(1);
const int rowHeightLvl1Hidden = tv.rowHeight(idxLvl1);
QCOMPARE(rowHeightLvl0, rowHeightLvl1Hidden);
tv.showColumn(1);
const int rowHeightLvl1Visible2 = tv.rowHeight(idxLvl1);
QCOMPARE(rowHeightLvl1Visible, rowHeightLvl1Visible2);
}
QTEST_MAIN(tst_QTreeView)
#include "tst_qtreeview.moc"

View File

@ -28,7 +28,7 @@
#include "menuramaapplication.h"
MenuramaApplication::MenuramaApplication(int argc, char **argv)
MenuramaApplication::MenuramaApplication(int &argc, char **argv)
: QApplication (argc, argv)
{
#if 0

View File

@ -36,7 +36,7 @@
class MenuramaApplication : public QApplication
{
public:
MenuramaApplication(int argc, char **argv);
MenuramaApplication(int &argc, char **argv);
void addDynMenu(QLatin1String title, QMenu *parentMenu);
QAction *findAction(QLatin1String title, QMenu *parentMenu);