Merge remote-tracking branch 'origin/5.6' into 5.7

Conflicts:
	src/plugins/platforms/ios/ios.pro
	src/plugins/platforms/ios/kernel.pro
	src/plugins/platforms/ios/optional/nsphotolibrarysupport/qiosfileengineassetslibrary.h
	src/plugins/platforms/ios/optional/nsphotolibrarysupport/qiosfileengineassetslibrary.mm
	src/plugins/platforms/ios/optional/nsphotolibrarysupport/qiosfileenginefactory.h
	src/plugins/platforms/ios/qiosintegration.h
	src/widgets/widgets/qcombobox.cpp
	tests/auto/widgets/dialogs/qwizard/tst_qwizard.cpp
	tests/auto/widgets/graphicsview/qgraphicsitem/tst_qgraphicsitem.cpp

Change-Id: Ibaee7cbbba99e7c4b1d8926e55932ffa6030ce45
This commit is contained in:
Liang Qi 2016-10-27 10:22:56 +02:00
commit af0d0b9c06
43 changed files with 673 additions and 249 deletions

View File

@ -1,6 +1,7 @@
# Objective-C/C++ sources go in SOURCES, like all other sources # Objective-C/C++ sources go in SOURCES, like all other sources
SOURCES += $$OBJECTIVE_SOURCES SOURCES += $$OBJECTIVE_SOURCES
unset(OBJECTIVE_SOURCES)
# Strip C/C++ flags from QMAKE_OBJECTIVE_CFLAGS just in case # Strip C/C++ flags from QMAKE_OBJECTIVE_CFLAGS just in case
QMAKE_OBJECTIVE_CFLAGS -= $$QMAKE_CFLAGS $$QMAKE_CXXFLAGS QMAKE_OBJECTIVE_CFLAGS -= $$QMAKE_CFLAGS $$QMAKE_CXXFLAGS
@ -8,3 +9,4 @@ QMAKE_OBJECTIVE_CFLAGS -= $$QMAKE_CFLAGS $$QMAKE_CXXFLAGS
# Add Objective-C/C++ flags to C/C++ flags, the compiler can handle it # Add Objective-C/C++ flags to C/C++ flags, the compiler can handle it
QMAKE_CFLAGS += $$QMAKE_OBJECTIVE_CFLAGS QMAKE_CFLAGS += $$QMAKE_OBJECTIVE_CFLAGS
QMAKE_CXXFLAGS += $$QMAKE_OBJECTIVE_CFLAGS QMAKE_CXXFLAGS += $$QMAKE_OBJECTIVE_CFLAGS
unset(QMAKE_OBJECTIVE_CFLAGS)

View File

@ -56,7 +56,7 @@ moc_source.CONFIG = no_link moc_verify
moc_source.dependency_type = TYPE_C moc_source.dependency_type = TYPE_C
moc_source.commands = ${QMAKE_FUNC_mocCmdBase} ${QMAKE_FILE_IN} -o ${QMAKE_FILE_OUT} moc_source.commands = ${QMAKE_FUNC_mocCmdBase} ${QMAKE_FILE_IN} -o ${QMAKE_FILE_OUT}
moc_source.output = $$MOC_DIR/$${QMAKE_CPP_MOD_MOC}${QMAKE_FILE_BASE}$${QMAKE_EXT_CPP_MOC} moc_source.output = $$MOC_DIR/$${QMAKE_CPP_MOD_MOC}${QMAKE_FILE_BASE}$${QMAKE_EXT_CPP_MOC}
moc_source.input = SOURCES OBJECTIVE_SOURCES moc_source.input = SOURCES
moc_source.name = MOC ${QMAKE_FILE_IN} moc_source.name = MOC ${QMAKE_FILE_IN}
moc_source.depends += $$WIN_INCLUDETEMP moc_source.depends += $$WIN_INCLUDETEMP
silent:moc_source.commands = @echo moc ${QMAKE_FILE_IN} && $$moc_source.commands silent:moc_source.commands = @echo moc ${QMAKE_FILE_IN} && $$moc_source.commands

View File

@ -80,3 +80,11 @@ macx-xcode {
QMAKE_CXXFLAGS += $$arch_flags QMAKE_CXXFLAGS += $$arch_flags
QMAKE_LFLAGS += $$arch_flags QMAKE_LFLAGS += $$arch_flags
} }
!xcodebuild:equals(TEMPLATE, app):!isEmpty(QMAKE_INFO_PLIST) {
# Only link in photo library support if Info.plist contains
# NSPhotoLibraryUsageDescription. Otherwise it will be rejected from AppStore.
plist_path = $$absolute_path($$QMAKE_INFO_PLIST, $$_PRO_FILE_PWD_)
system("/usr/libexec/PlistBuddy -c 'Print NSPhotoLibraryUsageDescription' $$system_quote($$plist_path) &>/dev/null"): \
QTPLUGIN += qiosnsphotolibrarysupport
}

View File

@ -1813,6 +1813,12 @@
which qmake will replace with the actual executable name. Other variables which qmake will replace with the actual executable name. Other variables
include @ICON@, @TYPEINFO@, @LIBRARY@, and @SHORT_VERSION@. include @ICON@, @TYPEINFO@, @LIBRARY@, and @SHORT_VERSION@.
If building for iOS, and the \c{.plist} file contains the key
\c NSPhotoLibraryUsageDescription, qmake will include an additional plugin
to the build that adds photo access support (to, e.g.,
\l{QFileDialog::setDirectory()}{QFile/QFileDialog}). See Info.plist
documentation from Apple for more information regarding this key.
\note Most of the time, the default \c{Info.plist} is good enough. \note Most of the time, the default \c{Info.plist} is good enough.
\section1 QMAKE_LFLAGS \section1 QMAKE_LFLAGS

View File

@ -46,6 +46,7 @@
#include <fcntl.h> #include <fcntl.h>
#include <sys/types.h> #include <sys/types.h>
#include <sys/stat.h> #include <sys/stat.h>
#include <limits.h>
#if defined(_MSC_VER) && _MSC_VER >= 1400 #if defined(_MSC_VER) && _MSC_VER >= 1400
#include <share.h> #include <share.h>
#endif #endif
@ -979,9 +980,11 @@ bool QMakeSourceFileInfo::findMocs(SourceFile *file)
continue; continue;
int matchlen = 0, extralines = 0; int matchlen = 0, extralines = 0;
size_t needle_len = strlen(interesting[interest]);
Q_ASSERT(needle_len <= INT_MAX);
if (matchWhileUnsplitting(buffer, buffer_len, y, if (matchWhileUnsplitting(buffer, buffer_len, y,
interesting[interest], interesting[interest],
strlen(interesting[interest]), static_cast<int>(needle_len),
&matchlen, &extralines) &matchlen, &extralines)
&& y + matchlen < buffer_len && y + matchlen < buffer_len
&& !isCWordChar(buffer[y + matchlen])) { && !isCWordChar(buffer[y + matchlen])) {

View File

@ -4268,8 +4268,10 @@ bool QInternal::activateCallbacks(Callback cb, void **parameters)
Compares the floating point value \a p1 and \a p2 and Compares the floating point value \a p1 and \a p2 and
returns \c true if they are considered equal, otherwise \c false. returns \c true if they are considered equal, otherwise \c false.
Note that comparing values where either \a p1 or \a p2 is 0.0 will not work. Note that comparing values where either \a p1 or \a p2 is 0.0 will not work,
The solution to this is to compare against values greater than or equal to 1.0. nor does comparing values where one of the values is NaN or infinity.
If one of the values is always 0.0, use qFuzzyIsNull instead. If one of the
values is likely to be 0.0, one solution is to add 1.0 to both values.
\snippet code/src_corelib_global_qglobal.cpp 46 \snippet code/src_corelib_global_qglobal.cpp 46

View File

@ -60,7 +60,7 @@ QT_BEGIN_NAMESPACE
* There will only be one copy of the section in the output library or application. * There will only be one copy of the section in the output library or application.
*/ */
#if defined(QT_BUILD_CORE_LIB) || defined(QT_BOOTSTRAPPED) || defined(QT_NO_VERSION_TAGGING) #if defined(QT_BUILD_CORE_LIB) || defined(QT_BOOTSTRAPPED) || defined(QT_NO_VERSION_TAGGING) || defined(QT_STATIC)
// don't make tags in QtCore, bootstrapped systems or if the user asked not to // don't make tags in QtCore, bootstrapped systems or if the user asked not to
#elif defined(Q_CC_GNU) && !defined(Q_OS_ANDROID) #elif defined(Q_CC_GNU) && !defined(Q_OS_ANDROID)
# if defined(Q_PROCESSOR_X86) && (defined(Q_OS_LINUX) || defined(Q_OS_FREEBSD_KERNEL)) # if defined(Q_PROCESSOR_X86) && (defined(Q_OS_LINUX) || defined(Q_OS_FREEBSD_KERNEL))

View File

@ -349,7 +349,7 @@ QStringList QFseventsFileSystemWatcherEngine::addPaths(const QStringList &paths,
QStringList p = paths; QStringList p = paths;
QMutableListIterator<QString> it(p); QMutableListIterator<QString> it(p);
while (it.hasNext()) { while (it.hasNext()) {
QString origPath = it.next(); QString origPath = it.next().normalized(QString::NormalizationForm_C);
QString realPath = origPath; QString realPath = origPath;
if (realPath.endsWith(QDir::separator())) if (realPath.endsWith(QDir::separator()))
realPath = realPath.mid(0, realPath.size() - 1); realPath = realPath.mid(0, realPath.size() - 1);

View File

@ -487,48 +487,46 @@ static int ucstrncmp(const QChar *a, const QChar *b, int l)
if (!l) if (!l)
return 0; return 0;
union {
const QChar *w;
const quint32 *d;
quintptr value;
} sa, sb;
sa.w = a;
sb.w = b;
// check alignment // check alignment
if ((sa.value & 2) == (sb.value & 2)) { if ((reinterpret_cast<quintptr>(a) & 2) == (reinterpret_cast<quintptr>(b) & 2)) {
// both addresses have the same alignment // both addresses have the same alignment
if (sa.value & 2) { if (reinterpret_cast<quintptr>(a) & 2) {
// both addresses are not aligned to 4-bytes boundaries // both addresses are not aligned to 4-bytes boundaries
// compare the first character // compare the first character
if (*sa.w != *sb.w) if (*a != *b)
return sa.w->unicode() - sb.w->unicode(); return a->unicode() - b->unicode();
--l; --l;
++sa.w; ++a;
++sb.w; ++b;
// now both addresses are 4-bytes aligned // now both addresses are 4-bytes aligned
} }
// both addresses are 4-bytes aligned // both addresses are 4-bytes aligned
// do a fast 32-bit comparison // do a fast 32-bit comparison
const quint32 *e = sa.d + (l >> 1); const quint32 *da = reinterpret_cast<const quint32 *>(a);
for ( ; sa.d != e; ++sa.d, ++sb.d) { const quint32 *db = reinterpret_cast<const quint32 *>(b);
if (*sa.d != *sb.d) { const quint32 *e = da + (l >> 1);
if (*sa.w != *sb.w) for ( ; da != e; ++da, ++db) {
return sa.w->unicode() - sb.w->unicode(); if (*da != *db) {
return sa.w[1].unicode() - sb.w[1].unicode(); a = reinterpret_cast<const QChar *>(da);
b = reinterpret_cast<const QChar *>(db);
if (*a != *b)
return a->unicode() - b->unicode();
return a[1].unicode() - b[1].unicode();
} }
} }
// do we have a tail? // do we have a tail?
return (l & 1) ? sa.w->unicode() - sb.w->unicode() : 0; a = reinterpret_cast<const QChar *>(da);
b = reinterpret_cast<const QChar *>(db);
return (l & 1) ? a->unicode() - b->unicode() : 0;
} else { } else {
// one of the addresses isn't 4-byte aligned but the other is // one of the addresses isn't 4-byte aligned but the other is
const QChar *e = sa.w + l; const QChar *e = a + l;
for ( ; sa.w != e; ++sa.w, ++sb.w) { for ( ; a != e; ++a, ++b) {
if (*sa.w != *sb.w) if (*a != *b)
return sa.w->unicode() - sb.w->unicode(); return a->unicode() - b->unicode();
} }
} }
return 0; return 0;

View File

@ -9,6 +9,7 @@ QMAKE_DOCS = $$PWD/doc/qtgui.qdocconf
MODULE_PLUGIN_TYPES = \ MODULE_PLUGIN_TYPES = \
platforms \ platforms \
platforms/darwin \
xcbglintegrations \ xcbglintegrations \
platformthemes \ platformthemes \
platforminputcontexts \ platforminputcontexts \

View File

@ -350,6 +350,16 @@ void QWindowGeometrySpecification::applyTo(QWindow *window) const
static QWindowGeometrySpecification windowGeometrySpecification = Q_WINDOW_GEOMETRY_SPECIFICATION_INITIALIZER; static QWindowGeometrySpecification windowGeometrySpecification = Q_WINDOW_GEOMETRY_SPECIFICATION_INITIALIZER;
/*!
\macro qGuiApp
\relates QGuiApplication
A global pointer referring to the unique application object.
Only valid for use when that object is a QGuiApplication.
\sa QCoreApplication::instance(), qApp
*/
/*! /*!
\class QGuiApplication \class QGuiApplication
\brief The QGuiApplication class manages the GUI application's control \brief The QGuiApplication class manages the GUI application's control

View File

@ -807,7 +807,8 @@ QStringList QPlatformFontDatabase::fallbacksForFamily(const QString &family, QFo
Q_UNUSED(family); Q_UNUSED(family);
Q_UNUSED(styleHint); Q_UNUSED(styleHint);
QStringList retList; QStringList preferredFallbacks;
QStringList otherFallbacks;
size_t writingSystem = std::find(scriptForWritingSystem, size_t writingSystem = std::find(scriptForWritingSystem,
scriptForWritingSystem + QFontDatabase::WritingSystemsCount, scriptForWritingSystem + QFontDatabase::WritingSystemsCount,
@ -828,18 +829,18 @@ QStringList QPlatformFontDatabase::fallbacksForFamily(const QString &family, QFo
QtFontFoundry *foundry = f->foundries[j]; QtFontFoundry *foundry = f->foundries[j];
for (int k = 0; k < foundry->count; ++k) { for (int k = 0; k < foundry->count; ++k) {
if (style == foundry->styles[k]->key.style) { QString name = foundry->name.isEmpty()
if (foundry->name.isEmpty()) ? f->name
retList.append(f->name); : f->name + QLatin1String(" [") + foundry->name + QLatin1Char(']');
else if (style == foundry->styles[k]->key.style)
retList.append(f->name + QLatin1String(" [") + foundry->name + QLatin1Char(']')); preferredFallbacks.append(name);
break; else
} otherFallbacks.append(name);
} }
} }
} }
return retList; return preferredFallbacks + otherFallbacks;
} }
static void initializeDb(); static void initializeDb();
@ -1659,9 +1660,6 @@ bool QFontDatabase::isFixedPitch(const QString &family,
bool QFontDatabase::isBitmapScalable(const QString &family, bool QFontDatabase::isBitmapScalable(const QString &family,
const QString &style) const const QString &style) const
{ {
if (QGuiApplicationPrivate::platformIntegration()->fontDatabase()->fontsAlwaysScalable())
return true;
bool bitmapScalable = false; bool bitmapScalable = false;
QString familyName, foundryName; QString familyName, foundryName;
parseFontName(family, foundryName, familyName); parseFontName(family, foundryName, familyName);
@ -1702,9 +1700,6 @@ bool QFontDatabase::isBitmapScalable(const QString &family,
*/ */
bool QFontDatabase::isSmoothlyScalable(const QString &family, const QString &style) const bool QFontDatabase::isSmoothlyScalable(const QString &family, const QString &style) const
{ {
if (QGuiApplicationPrivate::platformIntegration()->fontDatabase()->fontsAlwaysScalable())
return true;
bool smoothScalable = false; bool smoothScalable = false;
QString familyName, foundryName; QString familyName, foundryName;
parseFontName(family, foundryName, familyName); parseFontName(family, foundryName, familyName);

View File

@ -414,8 +414,7 @@ QVariant QMacPasteboardMimeUnicodeText::convertToMime(const QString &mimetype, Q
if (flavor == QLatin1String("public.utf8-plain-text")) { if (flavor == QLatin1String("public.utf8-plain-text")) {
ret = QString::fromUtf8(firstData); ret = QString::fromUtf8(firstData);
} else if (flavor == QLatin1String("public.utf16-plain-text")) { } else if (flavor == QLatin1String("public.utf16-plain-text")) {
ret = QString(reinterpret_cast<const QChar *>(firstData.constData()), ret = QTextCodec::codecForName("UTF-16")->toUnicode(firstData);
firstData.size() / sizeof(QChar));
} else { } else {
qWarning("QMime::convertToMime: unhandled mimetype: %s", qPrintable(mimetype)); qWarning("QMime::convertToMime: unhandled mimetype: %s", qPrintable(mimetype));
} }
@ -429,7 +428,7 @@ QList<QByteArray> QMacPasteboardMimeUnicodeText::convertFromMime(const QString &
if (flavor == QLatin1String("public.utf8-plain-text")) if (flavor == QLatin1String("public.utf8-plain-text"))
ret.append(string.toUtf8()); ret.append(string.toUtf8());
else if (flavor == QLatin1String("public.utf16-plain-text")) else if (flavor == QLatin1String("public.utf16-plain-text"))
ret.append(QByteArray((char*)string.utf16(), string.length()*2)); ret.append(QTextCodec::codecForName("UTF-16")->fromUnicode(string));
return ret; return ret;
} }

View File

@ -76,6 +76,7 @@ private:
static QCocoaWindow *findWindowForMenubar(); static QCocoaWindow *findWindowForMenubar();
static QCocoaMenuBar *findGlobalMenubar(); static QCocoaMenuBar *findGlobalMenubar();
bool needsImmediateUpdate();
bool shouldDisable(QCocoaWindow *active) const; bool shouldDisable(QCocoaWindow *active) const;
NSMenuItem *nativeItemForMenu(QCocoaMenu *menu) const; NSMenuItem *nativeItemForMenu(QCocoaMenu *menu) const;

View File

@ -95,6 +95,32 @@ QCocoaMenuBar::~QCocoaMenuBar()
} }
} }
bool QCocoaMenuBar::needsImmediateUpdate()
{
if (m_window && m_window->window()->isActive()) {
return true;
} else if (!m_window) {
// Only update if the focus/active window has no
// menubar, which means it'll be using this menubar.
// This is to avoid a modification in a parentless
// menubar to affect a window-assigned menubar.
QWindow *fw = QGuiApplication::focusWindow();
if (!fw) {
// Same if there's no focus window, BTW.
return true;
} else {
QCocoaWindow *cw = static_cast<QCocoaWindow *>(fw->handle());
if (cw && !cw->menubar())
return true;
}
}
// Either the menubar is attached to a non-active window,
// or the application's focus window has its own menubar
// (which is different from this one)
return false;
}
void QCocoaMenuBar::insertMenu(QPlatformMenu *platformMenu, QPlatformMenu *before) void QCocoaMenuBar::insertMenu(QPlatformMenu *platformMenu, QPlatformMenu *before)
{ {
QCocoaMenu *menu = static_cast<QCocoaMenu *>(platformMenu); QCocoaMenu *menu = static_cast<QCocoaMenu *>(platformMenu);
@ -135,7 +161,7 @@ void QCocoaMenuBar::insertMenu(QPlatformMenu *platformMenu, QPlatformMenu *befor
syncMenu(menu); syncMenu(menu);
if (m_window && m_window->window()->isActive()) if (needsImmediateUpdate())
updateMenuBarImmediately(); updateMenuBarImmediately();
} }

View File

@ -1,65 +1,2 @@
TARGET = qios TEMPLATE = subdirs
SUBDIRS = kernel.pro optional
QT += core-private gui-private platformsupport-private
LIBS += -framework Foundation -framework UIKit -framework QuartzCore -framework AssetsLibrary -framework AudioToolbox
OBJECTIVE_SOURCES = \
plugin.mm \
qiosintegration.mm \
qioseventdispatcher.mm \
qioswindow.mm \
qiosscreen.mm \
qiosbackingstore.mm \
qiosapplicationdelegate.mm \
qiosapplicationstate.mm \
qiosviewcontroller.mm \
qioscontext.mm \
qiosinputcontext.mm \
qiostheme.mm \
qiosglobal.mm \
qiosservices.mm \
quiview.mm \
qiosclipboard.mm \
quiaccessibilityelement.mm \
qiosplatformaccessibility.mm \
qiostextresponder.mm \
qiosmenu.mm \
qiosfileengineassetslibrary.mm \
qiosfiledialog.mm \
qiosmessagedialog.mm \
qiostextinputoverlay.mm
HEADERS = \
qiosintegration.h \
qioseventdispatcher.h \
qioswindow.h \
qiosscreen.h \
qiosbackingstore.h \
qiosapplicationdelegate.h \
qiosapplicationstate.h \
qiosviewcontroller.h \
qioscontext.h \
qiosinputcontext.h \
qiostheme.h \
qiosglobal.h \
qiosservices.h \
quiview.h \
qiosclipboard.h \
quiaccessibilityelement.h \
qiosplatformaccessibility.h \
qiostextresponder.h \
qiosmenu.h \
qiosfileenginefactory.h \
qiosfileengineassetslibrary.h \
qiosfiledialog.h \
qiosmessagedialog.h \
qiostextinputoverlay.h
OTHER_FILES = \
quiview_textinput.mm \
quiview_accessibility.mm
PLUGIN_TYPE = platforms
PLUGIN_CLASS_NAME = QIOSIntegrationPlugin
!equals(TARGET, $$QT_DEFAULT_QPA_PLUGIN): PLUGIN_EXTENDS = -
load(qt_plugin)

View File

@ -0,0 +1,63 @@
TARGET = qios
QT += core-private gui-private platformsupport-private
LIBS += -framework Foundation -framework UIKit -framework QuartzCore
OBJECTIVE_SOURCES = \
plugin.mm \
qiosintegration.mm \
qioseventdispatcher.mm \
qioswindow.mm \
qiosscreen.mm \
qiosbackingstore.mm \
qiosapplicationdelegate.mm \
qiosapplicationstate.mm \
qiosviewcontroller.mm \
qioscontext.mm \
qiosinputcontext.mm \
qiostheme.mm \
qiosglobal.mm \
qiosservices.mm \
quiview.mm \
qiosclipboard.mm \
quiaccessibilityelement.mm \
qiosplatformaccessibility.mm \
qiostextresponder.mm \
qiosmenu.mm \
qiosfiledialog.mm \
qiosmessagedialog.mm \
qiostextinputoverlay.mm
HEADERS = \
qiosintegration.h \
qioseventdispatcher.h \
qioswindow.h \
qiosscreen.h \
qiosbackingstore.h \
qiosapplicationdelegate.h \
qiosapplicationstate.h \
qiosviewcontroller.h \
qioscontext.h \
qiosinputcontext.h \
qiostheme.h \
qiosglobal.h \
qiosservices.h \
quiview.h \
qiosclipboard.h \
quiaccessibilityelement.h \
qiosplatformaccessibility.h \
qiostextresponder.h \
qiosmenu.h \
qiosfiledialog.h \
qiosmessagedialog.h \
qiostextinputoverlay.h
OTHER_FILES = \
quiview_textinput.mm \
quiview_accessibility.mm
PLUGIN_TYPE = platforms
PLUGIN_CLASS_NAME = QIOSIntegrationPlugin
!equals(TARGET, $$QT_DEFAULT_QPA_PLUGIN): PLUGIN_EXTENDS = -
load(qt_plugin)

View File

@ -0,0 +1,22 @@
TARGET = qiosnsphotolibrarysupport
QT += core gui gui-private
LIBS += -framework UIKit -framework AssetsLibrary
HEADERS = \
qiosfileengineassetslibrary.h \
qiosfileenginefactory.h \
qiosimagepickercontroller.h
OBJECTIVE_SOURCES = \
plugin.mm \
qiosfileengineassetslibrary.mm \
qiosimagepickercontroller.mm \
OTHER_FILES = \
plugin.json
PLUGIN_CLASS_NAME = QIosOptionalPlugin_NSPhotoLibrary
PLUGIN_EXTENDS = -
PLUGIN_TYPE = platforms/darwin
load(qt_plugin)

View File

@ -0,0 +1,3 @@
{
"Keys": [ "NSPhotoLibrarySupport" ]
}

View File

@ -0,0 +1,64 @@
/****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: http://www.qt.io/licensing/
**
** This file is part of the plugins of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL21$
** 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 http://www.qt.io/terms-conditions. For further
** information use the contact form at http://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 2.1 or version 3 as published by the Free
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
** LICENSE.LGPLv3 included in the packaging of this file. Please review the
** following information to ensure the GNU Lesser General Public License
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** As a special exception, The Qt Company gives you certain additional
** rights. These rights are described in The Qt Company LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include "../../qiosoptionalplugininterface.h"
#include "../../qiosfiledialog.h"
#include "qiosimagepickercontroller.h"
#include "qiosfileenginefactory.h"
QT_BEGIN_NAMESPACE
class QIosOptionalPlugin_NSPhotoLibrary : public QObject, QIosOptionalPluginInterface
{
Q_OBJECT
Q_PLUGIN_METADATA(IID QIosOptionalPluginInterface_iid FILE "plugin.json")
Q_INTERFACES(QIosOptionalPluginInterface)
public:
explicit QIosOptionalPlugin_NSPhotoLibrary(QObject* = 0) {};
~QIosOptionalPlugin_NSPhotoLibrary() {}
UIViewController* createImagePickerController(QIOSFileDialog *fileDialog) const override
{
return [[[QIOSImagePickerController alloc] initWithQIOSFileDialog:fileDialog] autorelease];
}
private:
QIOSFileEngineFactory m_fileEngineFactory;
};
QT_END_NAMESPACE
#include "plugin.moc"

View File

@ -51,20 +51,20 @@ public:
QIOSFileEngineAssetsLibrary(const QString &fileName); QIOSFileEngineAssetsLibrary(const QString &fileName);
~QIOSFileEngineAssetsLibrary(); ~QIOSFileEngineAssetsLibrary();
bool open(QIODevice::OpenMode openMode) Q_DECL_OVERRIDE; bool open(QIODevice::OpenMode openMode) override;
bool close() Q_DECL_OVERRIDE; bool close() override;
FileFlags fileFlags(FileFlags type) const Q_DECL_OVERRIDE; FileFlags fileFlags(FileFlags type) const override;
qint64 size() const Q_DECL_OVERRIDE; qint64 size() const override;
qint64 read(char *data, qint64 maxlen) Q_DECL_OVERRIDE; qint64 read(char *data, qint64 maxlen) override;
qint64 pos() const Q_DECL_OVERRIDE; qint64 pos() const override;
bool seek(qint64 pos) Q_DECL_OVERRIDE; bool seek(qint64 pos) override;
QString fileName(FileName file) const Q_DECL_OVERRIDE; QString fileName(FileName file) const override;
void setFileName(const QString &file) Q_DECL_OVERRIDE; void setFileName(const QString &file) override;
QStringList entryList(QDir::Filters filters, const QStringList &filterNames) const Q_DECL_OVERRIDE; QStringList entryList(QDir::Filters filters, const QStringList &filterNames) const override;
#ifndef QT_NO_FILESYSTEMITERATOR #ifndef QT_NO_FILESYSTEMITERATOR
Iterator *beginEntryList(QDir::Filters filters, const QStringList &filterNames) Q_DECL_OVERRIDE; Iterator *beginEntryList(QDir::Filters filters, const QStringList &filterNames) override;
Iterator *endEntryList() Q_DECL_OVERRIDE; Iterator *endEntryList() override;
#endif #endif
void setError(QFile::FileError error, const QString &str) { QAbstractFileEngine::setError(error, str); } void setError(QFile::FileError error, const QString &str) { QAbstractFileEngine::setError(error, str); }

View File

@ -0,0 +1,42 @@
/****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: http://www.qt.io/licensing/
**
** This file is part of the plugins of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL21$
** 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 http://www.qt.io/terms-conditions. For further
** information use the contact form at http://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 2.1 or version 3 as published by the Free
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
** LICENSE.LGPLv3 included in the packaging of this file. Please review the
** following information to ensure the GNU Lesser General Public License
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** As a special exception, The Qt Company gives you certain additional
** rights. These rights are described in The Qt Company LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** $QT_END_LICENSE$
**
****************************************************************************/
#import <UIKit/UIKit.h>
#include "../../qiosfiledialog.h"
@interface QIOSImagePickerController : UIImagePickerController <UIImagePickerControllerDelegate, UINavigationControllerDelegate> {
QIOSFileDialog *m_fileDialog;
}
- (id)initWithQIOSFileDialog:(QIOSFileDialog *)fileDialog;
@end

View File

@ -0,0 +1,66 @@
/****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: http://www.qt.io/licensing/
**
** This file is part of the plugins of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL21$
** 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 http://www.qt.io/terms-conditions. For further
** information use the contact form at http://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 2.1 or version 3 as published by the Free
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
** LICENSE.LGPLv3 included in the packaging of this file. Please review the
** following information to ensure the GNU Lesser General Public License
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** As a special exception, The Qt Company gives you certain additional
** rights. These rights are described in The Qt Company LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** $QT_END_LICENSE$
**
****************************************************************************/
#import <UIKit/UIKit.h>
#include "qiosimagepickercontroller.h"
@implementation QIOSImagePickerController
- (id)initWithQIOSFileDialog:(QIOSFileDialog *)fileDialog
{
self = [super init];
if (self) {
m_fileDialog = fileDialog;
[self setSourceType:UIImagePickerControllerSourceTypePhotoLibrary];
[self setDelegate:self];
}
return self;
}
- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info
{
Q_UNUSED(picker);
NSURL *url = [info objectForKey:UIImagePickerControllerReferenceURL];
QUrl fileUrl = QUrl::fromLocalFile(QString::fromNSString([url description]));
m_fileDialog->selectedFilesChanged(QList<QUrl>() << fileUrl);
emit m_fileDialog->accept();
}
- (void)imagePickerControllerDidCancel:(UIImagePickerController *)picker
{
Q_UNUSED(picker)
emit m_fileDialog->reject();
}
@end

View File

@ -0,0 +1,2 @@
TEMPLATE = subdirs
SUBDIRS = nsphotolibrarysupport

View File

@ -72,6 +72,8 @@ private:
QList<QUrl> m_selection; QList<QUrl> m_selection;
QEventLoop m_eventLoop; QEventLoop m_eventLoop;
UIViewController *m_viewController; UIViewController *m_viewController;
bool showImagePickerDialog(QWindow *parent);
}; };
QT_END_NAMESPACE QT_END_NAMESPACE

View File

@ -37,52 +37,18 @@
** **
****************************************************************************/ ****************************************************************************/
#include "qiosfiledialog.h"
#import <UIKit/UIKit.h> #import <UIKit/UIKit.h>
#include <QtCore/qstandardpaths.h> #include <QtCore/qstandardpaths.h>
#include <QtGui/qwindow.h> #include <QtGui/qwindow.h>
#include <QDebug>
@interface QIOSImagePickerController : UIImagePickerController <UIImagePickerControllerDelegate, UINavigationControllerDelegate> { #include "qiosfiledialog.h"
QIOSFileDialog *m_fileDialog; #include "qiosintegration.h"
} #include "qiosoptionalplugininterface.h"
@end
@implementation QIOSImagePickerController
- (id)initWithQIOSFileDialog:(QIOSFileDialog *)fileDialog
{
self = [super init];
if (self) {
m_fileDialog = fileDialog;
[self setSourceType:UIImagePickerControllerSourceTypePhotoLibrary];
[self setDelegate:self];
}
return self;
}
- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info
{
Q_UNUSED(picker);
NSURL *url = [info objectForKey:UIImagePickerControllerReferenceURL];
QUrl fileUrl = QUrl::fromLocalFile(QString::fromNSString([url description]));
m_fileDialog->selectedFilesChanged(QList<QUrl>() << fileUrl);
emit m_fileDialog->accept();
}
- (void)imagePickerControllerDidCancel:(UIImagePickerController *)picker
{
Q_UNUSED(picker)
emit m_fileDialog->reject();
}
@end
// --------------------------------------------------------------------------
QIOSFileDialog::QIOSFileDialog() QIOSFileDialog::QIOSFileDialog()
: m_viewController(0) : m_viewController(Q_NULLPTR)
{ {
} }
@ -104,17 +70,36 @@ bool QIOSFileDialog::show(Qt::WindowFlags windowFlags, Qt::WindowModality window
bool acceptOpen = options()->acceptMode() == QFileDialogOptions::AcceptOpen; bool acceptOpen = options()->acceptMode() == QFileDialogOptions::AcceptOpen;
QString directory = options()->initialDirectory().toLocalFile(); QString directory = options()->initialDirectory().toLocalFile();
if (acceptOpen && directory.startsWith(QLatin1String("assets-library:"))) { if (acceptOpen && directory.startsWith(QLatin1String("assets-library:")))
m_viewController = [[QIOSImagePickerController alloc] initWithQIOSFileDialog:this]; return showImagePickerDialog(parent);
UIWindow *window = parent ? reinterpret_cast<UIView *>(parent->winId()).window
: [UIApplication sharedApplication].keyWindow;
[window.rootViewController presentViewController:m_viewController animated:YES completion:nil];
return true;
}
return false; return false;
} }
bool QIOSFileDialog::showImagePickerDialog(QWindow *parent)
{
if (!m_viewController) {
QFactoryLoader *plugins = QIOSIntegration::instance()->optionalPlugins();
for (int i = 0; i < plugins->metaData().size(); ++i) {
QIosOptionalPluginInterface *plugin = qobject_cast<QIosOptionalPluginInterface *>(plugins->instance(i));
m_viewController = [plugin->createImagePickerController(this) retain];
if (m_viewController)
break;
}
}
if (!m_viewController) {
qWarning() << "QIOSFileDialog: Could not resolve Qt plugin that gives access to photos on iOS";
return false;
}
UIWindow *window = parent ? reinterpret_cast<UIView *>(parent->winId()).window
: [UIApplication sharedApplication].keyWindow;
[window.rootViewController presentViewController:m_viewController animated:YES completion:nil];
return true;
}
void QIOSFileDialog::hide() void QIOSFileDialog::hide()
{ {
// QFileDialog will remember the last directory set, and open subsequent dialogs in the same // QFileDialog will remember the last directory set, and open subsequent dialogs in the same
@ -126,6 +111,8 @@ void QIOSFileDialog::hide()
emit directoryEntered(QUrl::fromLocalFile(QDir::currentPath())); emit directoryEntered(QUrl::fromLocalFile(QDir::currentPath()));
[m_viewController dismissViewControllerAnimated:YES completion:nil]; [m_viewController dismissViewControllerAnimated:YES completion:nil];
[m_viewController release];
m_viewController = Q_NULLPTR;
m_eventLoop.exit(); m_eventLoop.exit();
} }

View File

@ -44,8 +44,9 @@
#include <qpa/qplatformnativeinterface.h> #include <qpa/qplatformnativeinterface.h>
#include <qpa/qwindowsysteminterface.h> #include <qpa/qwindowsysteminterface.h>
#include <QtCore/private/qfactoryloader_p.h>
#include "qiosapplicationstate.h" #include "qiosapplicationstate.h"
#include "qiosfileenginefactory.h"
#include "qiostextinputoverlay.h" #include "qiostextinputoverlay.h"
QT_BEGIN_NAMESPACE QT_BEGIN_NAMESPACE
@ -100,6 +101,8 @@ public:
void setDebugWindowManagement(bool); void setDebugWindowManagement(bool);
bool debugWindowManagement() const; bool debugWindowManagement() const;
QFactoryLoader *optionalPlugins() { return m_optionalPlugins; }
private: private:
QPlatformFontDatabase *m_fontDatabase; QPlatformFontDatabase *m_fontDatabase;
QPlatformClipboard *m_clipboard; QPlatformClipboard *m_clipboard;
@ -108,7 +111,7 @@ private:
QIOSApplicationState m_applicationState; QIOSApplicationState m_applicationState;
QIOSServices *m_platformServices; QIOSServices *m_platformServices;
mutable QPlatformAccessibility *m_accessibility; mutable QPlatformAccessibility *m_accessibility;
QIOSFileEngineFactory m_fileEngineFactory; QFactoryLoader *m_optionalPlugins;
QIOSTextInputOverlay m_textInputOverlay; QIOSTextInputOverlay m_textInputOverlay;
bool m_debugWindowManagement; bool m_debugWindowManagement;

View File

@ -49,6 +49,7 @@
#include "qiosinputcontext.h" #include "qiosinputcontext.h"
#include "qiostheme.h" #include "qiostheme.h"
#include "qiosservices.h" #include "qiosservices.h"
#include "qiosoptionalplugininterface.h"
#include <QtGui/private/qguiapplication_p.h> #include <QtGui/private/qguiapplication_p.h>
@ -76,6 +77,7 @@ QIOSIntegration::QIOSIntegration()
, m_inputContext(0) , m_inputContext(0)
, m_platformServices(new QIOSServices) , m_platformServices(new QIOSServices)
, m_accessibility(0) , m_accessibility(0)
, m_optionalPlugins(new QFactoryLoader(QIosOptionalPluginInterface_iid, QLatin1String("/platforms/darwin")))
, m_debugWindowManagement(false) , m_debugWindowManagement(false)
{ {
if (Q_UNLIKELY(![UIApplication sharedApplication])) { if (Q_UNLIKELY(![UIApplication sharedApplication])) {
@ -120,6 +122,9 @@ QIOSIntegration::QIOSIntegration()
m_touchDevice->setCapabilities(touchCapabilities); m_touchDevice->setCapabilities(touchCapabilities);
QWindowSystemInterface::registerTouchDevice(m_touchDevice); QWindowSystemInterface::registerTouchDevice(m_touchDevice);
QMacInternalPasteboardMime::initializeMimeTypes(); QMacInternalPasteboardMime::initializeMimeTypes();
for (int i = 0; i < m_optionalPlugins->metaData().size(); ++i)
qobject_cast<QIosOptionalPluginInterface *>(m_optionalPlugins->instance(i))->initPlugin();
} }
QIOSIntegration::~QIOSIntegration() QIOSIntegration::~QIOSIntegration()
@ -142,6 +147,9 @@ QIOSIntegration::~QIOSIntegration()
delete m_accessibility; delete m_accessibility;
m_accessibility = 0; m_accessibility = 0;
delete m_optionalPlugins;
m_optionalPlugins = 0;
} }
bool QIOSIntegration::hasCapability(Capability cap) const bool QIOSIntegration::hasCapability(Capability cap) const

View File

@ -0,0 +1,59 @@
/****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: http://www.qt.io/licensing/
**
** This file is part of the plugins of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL21$
** 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 http://www.qt.io/terms-conditions. For further
** information use the contact form at http://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 2.1 or version 3 as published by the Free
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
** LICENSE.LGPLv3 included in the packaging of this file. Please review the
** following information to ensure the GNU Lesser General Public License
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** As a special exception, The Qt Company gives you certain additional
** rights. These rights are described in The Qt Company LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** $QT_END_LICENSE$
**
****************************************************************************/
#ifndef QIOPLUGININTERFACE_H
#define QIOPLUGININTERFACE_H
#include <QtCore/QtPlugin>
#include "qiosfiledialog.h"
QT_BEGIN_NAMESPACE
Q_FORWARD_DECLARE_OBJC_CLASS(UIViewController);
#define QIosOptionalPluginInterface_iid "org.qt-project.Qt.QPA.ios.optional"
class QIosOptionalPluginInterface
{
public:
virtual ~QIosOptionalPluginInterface() {}
virtual void initPlugin() const {};
virtual UIViewController* createImagePickerController(QIOSFileDialog *) const { return Q_NULLPTR; };
};
Q_DECLARE_INTERFACE(QIosOptionalPluginInterface, QIosOptionalPluginInterface_iid)
QT_END_NAMESPACE
#endif // QIOPLUGININTERFACE_H

View File

@ -900,6 +900,9 @@ void QFileDialogPrivate::_q_goToUrl(const QUrl &url)
{QStandardPaths::standardLocations(QStandardPaths::PicturesLocation).last()}, {QStandardPaths::standardLocations(QStandardPaths::PicturesLocation).last()},
a native image picker dialog will be used for accessing the user's photo album. a native image picker dialog will be used for accessing the user's photo album.
The filename returned can be loaded using QFile and related APIs. The filename returned can be loaded using QFile and related APIs.
For this to be enabled, the Info.plist assigned to QMAKE_INFO_PLIST in the
project file must contain the key \c NSPhotoLibraryUsageDescription. See
Info.plist documentation from Apple for more information regarding this key.
This feature was added in Qt 5.5. This feature was added in Qt 5.5.
*/ */
void QFileDialog::setDirectory(const QString &directory) void QFileDialog::setDirectory(const QString &directory)

View File

@ -4216,13 +4216,10 @@ void QApplication::beep()
\relates QApplication \relates QApplication
A global pointer referring to the unique application object. It is A global pointer referring to the unique application object. It is
equivalent to the pointer returned by the QCoreApplication::instance() equivalent to QCoreApplication::instance(), but cast as a QApplication pointer,
function except that, in GUI applications, it is a pointer to a so only valid when the unique application object is a QApplication.
QApplication instance.
Only one application object can be created. \sa QCoreApplication::instance(), qGuiApp
\sa QCoreApplication::instance()
*/ */
/*! /*!

View File

@ -535,7 +535,7 @@ void QWidgetWindow::handleMouseEvent(QMouseEvent *event)
// activate window of the widget under mouse pointer // activate window of the widget under mouse pointer
if (!w->isActiveWindow()) { if (!w->isActiveWindow()) {
w->activateWindow(); w->activateWindow();
w->raise(); w->window()->raise();
} }
QWindow *win = w->windowHandle(); QWindow *win = w->windowHandle();

View File

@ -1039,6 +1039,8 @@ static QSize qt_aqua_get_known_size(QStyle::ContentsType ct, const QWidget *widg
#if defined(QMAC_QAQUASTYLE_SIZE_CONSTRAIN) || defined(DEBUG_SIZE_CONSTRAINT) #if defined(QMAC_QAQUASTYLE_SIZE_CONSTRAIN) || defined(DEBUG_SIZE_CONSTRAINT)
static QAquaWidgetSize qt_aqua_guess_size(const QWidget *widg, QSize large, QSize small, QSize mini) static QAquaWidgetSize qt_aqua_guess_size(const QWidget *widg, QSize large, QSize small, QSize mini)
{ {
Q_UNUSED(widg);
if (large == QSize(-1, -1)) { if (large == QSize(-1, -1)) {
if (small != QSize(-1, -1)) if (small != QSize(-1, -1))
return QAquaSizeSmall; return QAquaSizeSmall;
@ -1054,7 +1056,7 @@ static QAquaWidgetSize qt_aqua_guess_size(const QWidget *widg, QSize large, QSiz
} }
#ifndef QT_NO_MAINWINDOW #ifndef QT_NO_MAINWINDOW
if (qobject_cast<QDockWidget *>(widg->window()) || qEnvironmentVariableIsSet("QWIDGET_ALL_SMALL")) { if (qEnvironmentVariableIsSet("QWIDGET_ALL_SMALL")) {
//if (small.width() != -1 || small.height() != -1) //if (small.width() != -1 || small.height() != -1)
return QAquaSizeSmall; return QAquaSizeSmall;
} else if (qEnvironmentVariableIsSet("QWIDGET_ALL_MINI")) { } else if (qEnvironmentVariableIsSet("QWIDGET_ALL_MINI")) {

View File

@ -3133,6 +3133,7 @@ void QComboBox::keyPressEvent(QKeyEvent *e)
case Qt::Key_Up: case Qt::Key_Up:
if (e->modifiers() & Qt::ControlModifier) if (e->modifiers() & Qt::ControlModifier)
break; // pass to line edit for auto completion break; // pass to line edit for auto completion
// fall through
case Qt::Key_PageUp: case Qt::Key_PageUp:
#ifdef QT_KEYPAD_NAVIGATION #ifdef QT_KEYPAD_NAVIGATION
if (QApplication::keypadNavigationEnabled()) if (QApplication::keypadNavigationEnabled())
@ -3220,6 +3221,7 @@ void QComboBox::keyPressEvent(QKeyEvent *e)
switch (move) { switch (move) {
case MoveFirst: case MoveFirst:
newIndex = -1; newIndex = -1;
// fall through
case MoveDown: case MoveDown:
newIndex++; newIndex++;
while (newIndex < rowCount && !(d->model->index(newIndex, d->modelColumn, d->root).flags() & Qt::ItemIsEnabled)) while (newIndex < rowCount && !(d->model->index(newIndex, d->modelColumn, d->root).flags() & Qt::ItemIsEnabled))
@ -3227,6 +3229,7 @@ void QComboBox::keyPressEvent(QKeyEvent *e)
break; break;
case MoveLast: case MoveLast:
newIndex = rowCount; newIndex = rowCount;
// fall through
case MoveUp: case MoveUp:
newIndex--; newIndex--;
while ((newIndex >= 0) && !(d->model->flags(d->model->index(newIndex,d->modelColumn,d->root)) & Qt::ItemIsEnabled)) while ((newIndex >= 0) && !(d->model->flags(d->model->index(newIndex,d->modelColumn,d->root)) & Qt::ItemIsEnabled))

View File

@ -3442,7 +3442,7 @@ void tst_QFile::autocloseHandle()
//file is closed, read should fail //file is closed, read should fail
char buf; char buf;
QCOMPARE((int)QT_READ(fd, &buf, 1), -1); QCOMPARE((int)QT_READ(fd, &buf, 1), -1);
QVERIFY(errno = EBADF); QVERIFY(errno == EBADF);
} }
{ {

View File

@ -73,6 +73,8 @@ private slots:
void signalsEmittedAfterFileMoved(); void signalsEmittedAfterFileMoved();
void watchUnicodeCharacters();
private: private:
QString m_tempDirPattern; QString m_tempDirPattern;
#endif // QT_NO_FILESYSTEMWATCHER #endif // QT_NO_FILESYSTEMWATCHER
@ -759,6 +761,25 @@ void tst_QFileSystemWatcher::signalsEmittedAfterFileMoved()
QVERIFY2(changedSpy.count() <= fileCount, changedSpy.receivedFilesMessage()); QVERIFY2(changedSpy.count() <= fileCount, changedSpy.receivedFilesMessage());
QTRY_COMPARE(changedSpy.count(), fileCount); QTRY_COMPARE(changedSpy.count(), fileCount);
} }
void tst_QFileSystemWatcher::watchUnicodeCharacters()
{
QTemporaryDir temporaryDirectory(m_tempDirPattern);
QVERIFY2(temporaryDirectory.isValid(), qPrintable(temporaryDirectory.errorString()));
QDir testDir(temporaryDirectory.path());
const QString subDir(QString::fromLatin1("caf\xe9"));
QVERIFY(testDir.mkdir(subDir));
testDir = QDir(temporaryDirectory.path() + QDir::separator() + subDir);
QFileSystemWatcher watcher;
QVERIFY(watcher.addPath(testDir.path()));
FileSystemWatcherSpy changedSpy(&watcher, FileSystemWatcherSpy::SpyOnDirectoryChanged);
QCOMPARE(changedSpy.count(), 0);
QVERIFY(testDir.mkdir("creme"));
QTRY_COMPARE(changedSpy.count(), 1);
}
#endif // QT_NO_FILESYSTEMWATCHER #endif // QT_NO_FILESYSTEMWATCHER
QTEST_MAIN(tst_QFileSystemWatcher) QTEST_MAIN(tst_QFileSystemWatcher)

View File

@ -1614,28 +1614,44 @@ class SetPage : public Operation
wizard->next(); wizard->next();
} }
QString describe() const { return QLatin1String("set page ") + QString::number(page); } QString describe() const { return QLatin1String("set page ") + QString::number(page); }
const int page; int page;
public: public:
SetPage(int page) : page(page) {} static QSharedPointer<SetPage> create(int page)
{
QSharedPointer<SetPage> o = QSharedPointer<SetPage>::create();
o->page = page;
return o;
}
}; };
class SetStyle : public Operation class SetStyle : public Operation
{ {
void apply(QWizard *wizard) const { wizard->setWizardStyle(style); } void apply(QWizard *wizard) const { wizard->setWizardStyle(style); }
QString describe() const { return QLatin1String("set style ") + QString::number(style); } QString describe() const { return QLatin1String("set style ") + QString::number(style); }
const QWizard::WizardStyle style; QWizard::WizardStyle style;
public: public:
SetStyle(QWizard::WizardStyle style) : style(style) {} static QSharedPointer<SetStyle> create(QWizard::WizardStyle style)
{
QSharedPointer<SetStyle> o = QSharedPointer<SetStyle>::create();
o->style = style;
return o;
}
}; };
class SetOption : public Operation class SetOption : public Operation
{ {
void apply(QWizard *wizard) const { wizard->setOption(option, on); } void apply(QWizard *wizard) const { wizard->setOption(option, on); }
QString describe() const; QString describe() const;
const QWizard::WizardOption option; QWizard::WizardOption option;
const bool on; bool on;
public: public:
SetOption(QWizard::WizardOption option, bool on) : option(option), on(on) {} static QSharedPointer<SetOption> create(QWizard::WizardOption option, bool on)
{
QSharedPointer<SetOption> o = QSharedPointer<SetOption>::create();
o->option = option;
o->on = on;
return o;
}
}; };
class OptionInfo class OptionInfo
@ -1660,16 +1676,16 @@ class OptionInfo
tags[QWizard::HaveCustomButton3] = "15/CB3"; tags[QWizard::HaveCustomButton3] = "15/CB3";
for (int i = 0; i < 2; ++i) { for (int i = 0; i < 2; ++i) {
QMap<QWizard::WizardOption, Operation *> operations_; QMap<QWizard::WizardOption, QSharedPointer<Operation> > operations_;
foreach (QWizard::WizardOption option, tags.keys()) foreach (QWizard::WizardOption option, tags.keys())
operations_[option] = new SetOption(option, i == 1); operations_[option] = SetOption::create(option, i == 1);
operations << operations_; operations << operations_;
} }
} }
OptionInfo(OptionInfo const&); OptionInfo(OptionInfo const&);
OptionInfo& operator=(OptionInfo const&); OptionInfo& operator=(OptionInfo const&);
QMap<QWizard::WizardOption, QString> tags; QMap<QWizard::WizardOption, QString> tags;
QList<QMap<QWizard::WizardOption, Operation *> > operations; QList<QMap<QWizard::WizardOption, QSharedPointer<Operation> > > operations;
public: public:
static OptionInfo &instance() static OptionInfo &instance()
{ {
@ -1678,7 +1694,7 @@ public:
} }
QString tag(QWizard::WizardOption option) const { return tags.value(option); } QString tag(QWizard::WizardOption option) const { return tags.value(option); }
Operation * operation(QWizard::WizardOption option, bool on) const QSharedPointer<Operation> operation(QWizard::WizardOption option, bool on) const
{ return operations.at(on).value(option); } { return operations.at(on).value(option); }
QList<QWizard::WizardOption> options() const { return tags.keys(); } QList<QWizard::WizardOption> options() const { return tags.keys(); }
}; };
@ -1689,10 +1705,7 @@ QString SetOption::describe() const
+ QLatin1Char(on ? '1' : '0'); + QLatin1Char(on ? '1' : '0');
} }
Q_DECLARE_METATYPE(Operation *) Q_DECLARE_METATYPE(QVector<QSharedPointer<Operation> >)
Q_DECLARE_METATYPE(SetPage *)
Q_DECLARE_METATYPE(SetStyle *)
Q_DECLARE_METATYPE(SetOption *)
class TestGroup class TestGroup
{ {
@ -1709,14 +1722,17 @@ public:
combinations.clear(); combinations.clear();
} }
QList<Operation *> &add() QVector<QSharedPointer<Operation> > &add()
{ combinations << new QList<Operation *>; return *(combinations.last()); } {
combinations.resize(combinations.size() + 1);
return combinations.last();
}
void createTestRows() void createTestRows()
{ {
for (int i = 0; i < combinations.count(); ++i) { for (int i = 0; i < combinations.count(); ++i) {
QTest::newRow((name.toLatin1() + ", row " + QByteArray::number(i)).constData()) QTest::newRow((name.toLatin1() + ", row " + QByteArray::number(i)).constData())
<< (i == 0) << (type == Equality) << *(combinations.at(i)); << (i == 0) << (type == Equality) << combinations.at(i);
++nRows_; ++nRows_;
} }
} }
@ -1727,7 +1743,7 @@ private:
QString name; QString name;
Type type; Type type;
int nRows_; int nRows_;
QList<QList<Operation *> *> combinations; QVector<QVector<QSharedPointer<Operation> > > combinations;
}; };
class IntroPage : public QWizardPage class IntroPage : public QWizardPage
@ -1811,9 +1827,9 @@ public:
} }
} }
void applyOperations(const QList<Operation *> &operations) void applyOperations(const QVector<QSharedPointer<Operation> > &operations)
{ {
foreach (Operation * op, operations) { foreach (const QSharedPointer<Operation> &op, operations) {
if (op) { if (op) {
op->apply(this); op->apply(this);
opsDescr += QLatin1Char('(') + op->describe() + QLatin1String(") "); opsDescr += QLatin1Char('(') + op->describe() + QLatin1String(") ");
@ -1833,31 +1849,29 @@ public:
class CombinationsTestData class CombinationsTestData
{ {
TestGroup testGroup; TestGroup testGroup;
QList<Operation *> pageOps; QVector<QSharedPointer<Operation> > pageOps;
QList<Operation *> styleOps; QVector<QSharedPointer<Operation> > styleOps;
QMap<bool, QList<Operation *> *> setAllOptions; QMap<bool, QVector<QSharedPointer<Operation> > > setAllOptions;
public: public:
CombinationsTestData() CombinationsTestData()
{ {
QTest::addColumn<bool>("ref"); QTest::addColumn<bool>("ref");
QTest::addColumn<bool>("testEquality"); QTest::addColumn<bool>("testEquality");
QTest::addColumn<QList<Operation *> >("operations"); QTest::addColumn<QVector<QSharedPointer<Operation> > >("operations");
pageOps << new SetPage(0) << new SetPage(1) << new SetPage(2); pageOps << SetPage::create(0) << SetPage::create(1) << SetPage::create(2);
styleOps << new SetStyle(QWizard::ClassicStyle) << new SetStyle(QWizard::ModernStyle) styleOps << SetStyle::create(QWizard::ClassicStyle) << SetStyle::create(QWizard::ModernStyle)
<< new SetStyle(QWizard::MacStyle); << SetStyle::create(QWizard::MacStyle);
#define SETPAGE(page) pageOps.at(page) #define SETPAGE(page) pageOps.at(page)
#define SETSTYLE(style) styleOps.at(style) #define SETSTYLE(style) styleOps.at(style)
#define OPT(option, on) OptionInfo::instance().operation(option, on) #define OPT(option, on) OptionInfo::instance().operation(option, on)
#define CLROPT(option) OPT(option, false) #define CLROPT(option) OPT(option, false)
#define SETOPT(option) OPT(option, true) #define SETOPT(option) OPT(option, true)
setAllOptions[false] = new QList<Operation *>;
setAllOptions[true] = new QList<Operation *>;
foreach (QWizard::WizardOption option, OptionInfo::instance().options()) { foreach (QWizard::WizardOption option, OptionInfo::instance().options()) {
*setAllOptions.value(false) << CLROPT(option); setAllOptions[false] << CLROPT(option);
*setAllOptions.value(true) << SETOPT(option); setAllOptions[true] << SETOPT(option);
} }
#define CLRALLOPTS *setAllOptions.value(false) #define CLRALLOPTS setAllOptions.value(false)
#define SETALLOPTS *setAllOptions.value(true) #define SETALLOPTS setAllOptions.value(true)
} }
int nRows() const { return testGroup.nRows(); } int nRows() const { return testGroup.nRows(); }
@ -1909,7 +1923,7 @@ public:
testGroup.createTestRows(); testGroup.createTestRows();
for (int i = 0; i < 2; ++i) { for (int i = 0; i < 2; ++i) {
QList<Operation *> setOptions = *setAllOptions.value(i == 1); QVector<QSharedPointer<Operation> > setOptions = setAllOptions.value(i == 1);
testGroup.reset("testAll 3.1"); testGroup.reset("testAll 3.1");
testGroup.add() << setOptions; testGroup.add() << setOptions;
@ -1926,21 +1940,21 @@ public:
testGroup.createTestRows(); testGroup.createTestRows();
} }
foreach (Operation *pageOp, pageOps) { foreach (const QSharedPointer<Operation> &pageOp, pageOps) {
testGroup.reset("testAll 4.1"); testGroup.reset("testAll 4.1");
testGroup.add() << pageOp; testGroup.add() << pageOp;
testGroup.add() << pageOp << pageOp; testGroup.add() << pageOp << pageOp;
testGroup.createTestRows(); testGroup.createTestRows();
for (int i = 0; i < 2; ++i) { for (int i = 0; i < 2; ++i) {
QList<Operation *> optionOps = *setAllOptions.value(i == 1); QVector<QSharedPointer<Operation> > optionOps = setAllOptions.value(i == 1);
testGroup.reset("testAll 4.2"); testGroup.reset("testAll 4.2");
testGroup.add() << optionOps << pageOp; testGroup.add() << optionOps << pageOp;
testGroup.add() << pageOp << optionOps; testGroup.add() << pageOp << optionOps;
testGroup.createTestRows(); testGroup.createTestRows();
foreach (QWizard::WizardOption option, OptionInfo::instance().options()) { foreach (QWizard::WizardOption option, OptionInfo::instance().options()) {
Operation *optionOp = OPT(option, i == 1); QSharedPointer<Operation> optionOp = OPT(option, i == 1);
testGroup.reset("testAll 4.3"); testGroup.reset("testAll 4.3");
testGroup.add() << optionOp << pageOp; testGroup.add() << optionOp << pageOp;
testGroup.add() << pageOp << optionOp; testGroup.add() << pageOp << optionOp;
@ -1949,21 +1963,21 @@ public:
} }
} }
foreach (Operation *styleOp, styleOps) { foreach (const QSharedPointer<Operation> &styleOp, styleOps) {
testGroup.reset("testAll 5.1"); testGroup.reset("testAll 5.1");
testGroup.add() << styleOp; testGroup.add() << styleOp;
testGroup.add() << styleOp << styleOp; testGroup.add() << styleOp << styleOp;
testGroup.createTestRows(); testGroup.createTestRows();
for (int i = 0; i < 2; ++i) { for (int i = 0; i < 2; ++i) {
QList<Operation *> optionOps = *setAllOptions.value(i == 1); QVector<QSharedPointer<Operation> > optionOps = setAllOptions.value(i == 1);
testGroup.reset("testAll 5.2"); testGroup.reset("testAll 5.2");
testGroup.add() << optionOps << styleOp; testGroup.add() << optionOps << styleOp;
testGroup.add() << styleOp << optionOps; testGroup.add() << styleOp << optionOps;
testGroup.createTestRows(); testGroup.createTestRows();
foreach (QWizard::WizardOption option, OptionInfo::instance().options()) { foreach (QWizard::WizardOption option, OptionInfo::instance().options()) {
Operation *optionOp = OPT(option, i == 1); QSharedPointer<Operation> optionOp = OPT(option, i == 1);
testGroup.reset("testAll 5.3"); testGroup.reset("testAll 5.3");
testGroup.add() << optionOp << styleOp; testGroup.add() << optionOp << styleOp;
testGroup.add() << styleOp << optionOp; testGroup.add() << styleOp << optionOp;
@ -1972,8 +1986,8 @@ public:
} }
} }
foreach (Operation *pageOp, pageOps) { foreach (const QSharedPointer<Operation> &pageOp, pageOps) {
foreach (Operation *styleOp, styleOps) { foreach (const QSharedPointer<Operation> &styleOp, styleOps) {
testGroup.reset("testAll 6.1"); testGroup.reset("testAll 6.1");
testGroup.add() << pageOp; testGroup.add() << pageOp;
@ -1991,7 +2005,7 @@ public:
testGroup.createTestRows(); testGroup.createTestRows();
for (int i = 0; i < 2; ++i) { for (int i = 0; i < 2; ++i) {
QList<Operation *> optionOps = *setAllOptions.value(i == 1); QVector<QSharedPointer<Operation> > optionOps = setAllOptions.value(i == 1);
testGroup.reset("testAll 6.4"); testGroup.reset("testAll 6.4");
testGroup.add() << optionOps << pageOp << styleOp; testGroup.add() << optionOps << pageOp << styleOp;
testGroup.add() << pageOp << optionOps << styleOp; testGroup.add() << pageOp << optionOps << styleOp;
@ -2002,7 +2016,7 @@ public:
testGroup.createTestRows(); testGroup.createTestRows();
foreach (QWizard::WizardOption option, OptionInfo::instance().options()) { foreach (QWizard::WizardOption option, OptionInfo::instance().options()) {
Operation *optionOp = OPT(option, i == 1); QSharedPointer<Operation> optionOp = OPT(option, i == 1);
testGroup.reset("testAll 6.5"); testGroup.reset("testAll 6.5");
testGroup.add() << optionOp << pageOp << styleOp; testGroup.add() << optionOp << pageOp << styleOp;
testGroup.add() << pageOp << optionOp << styleOp; testGroup.add() << pageOp << optionOp << styleOp;
@ -2068,7 +2082,7 @@ void tst_QWizard::combinations()
QFETCH(bool, ref); QFETCH(bool, ref);
QFETCH(bool, testEquality); QFETCH(bool, testEquality);
QFETCH(QList<Operation *>, operations); QFETCH(QVector<QSharedPointer<Operation> >, operations);
TestWizard wizard; TestWizard wizard;
#if !defined(QT_NO_STYLE_WINDOWSVISTA) #if !defined(QT_NO_STYLE_WINDOWSVISTA)

View File

@ -845,14 +845,14 @@ void tst_QGraphicsItem::parentItem()
void tst_QGraphicsItem::setParentItem() void tst_QGraphicsItem::setParentItem()
{ {
QGraphicsScene scene; QGraphicsScene scene;
QGraphicsItem *item = scene.addRect(QRectF(0, 0, 10, 10)); const QScopedPointer<QGraphicsItem> item(scene.addRect(QRectF(0, 0, 10, 10)));
QCOMPARE(item->scene(), &scene); QCOMPARE(item->scene(), &scene);
QGraphicsRectItem *child = new QGraphicsRectItem; const QScopedPointer<QGraphicsRectItem> child(new QGraphicsRectItem);
QCOMPARE(child->scene(), (QGraphicsScene *)0); QCOMPARE(child->scene(), (QGraphicsScene *)0);
// This implicitly adds the item to the parent's scene // This implicitly adds the item to the parent's scene
child->setParentItem(item); child->setParentItem(item.data());
QCOMPARE(child->scene(), &scene); QCOMPARE(child->scene(), &scene);
// This just makes it a toplevel // This just makes it a toplevel
@ -860,8 +860,8 @@ void tst_QGraphicsItem::setParentItem()
QCOMPARE(child->scene(), &scene); QCOMPARE(child->scene(), &scene);
// Add the child back to the parent, then remove the parent from the scene // Add the child back to the parent, then remove the parent from the scene
child->setParentItem(item); child->setParentItem(item.data());
scene.removeItem(item); scene.removeItem(item.data());
QCOMPARE(child->scene(), (QGraphicsScene *)0); QCOMPARE(child->scene(), (QGraphicsScene *)0);
} }
@ -959,19 +959,19 @@ void tst_QGraphicsItem::flags()
QCOMPARE(item->pos(), QPointF(10, 10)); QCOMPARE(item->pos(), QPointF(10, 10));
} }
{ {
QGraphicsItem* clippingParent = new QGraphicsRectItem; const QScopedPointer<QGraphicsItem> clippingParent(new QGraphicsRectItem);
clippingParent->setFlag(QGraphicsItem::ItemClipsChildrenToShape, true); clippingParent->setFlag(QGraphicsItem::ItemClipsChildrenToShape, true);
QGraphicsItem* nonClippingParent = new QGraphicsRectItem; const QScopedPointer<QGraphicsItem> nonClippingParent(new QGraphicsRectItem);
nonClippingParent->setFlag(QGraphicsItem::ItemClipsChildrenToShape, false); nonClippingParent->setFlag(QGraphicsItem::ItemClipsChildrenToShape, false);
QGraphicsItem* child = new QGraphicsRectItem(nonClippingParent); QGraphicsItem* child = new QGraphicsRectItem(nonClippingParent.data());
QVERIFY(!child->isClipped()); QVERIFY(!child->isClipped());
child->setParentItem(clippingParent); child->setParentItem(clippingParent.data());
QVERIFY(child->isClipped()); QVERIFY(child->isClipped());
child->setParentItem(nonClippingParent); child->setParentItem(nonClippingParent.data());
QVERIFY(!child->isClipped()); QVERIFY(!child->isClipped());
} }
} }
@ -3130,7 +3130,8 @@ void tst_QGraphicsItem::isAncestorOf()
void tst_QGraphicsItem::commonAncestorItem() void tst_QGraphicsItem::commonAncestorItem()
{ {
QGraphicsItem *ancestor = new QGraphicsRectItem; QGraphicsRectItem ancestorItem;
QGraphicsItem *ancestor = &ancestorItem;
QGraphicsItem *grandMa = new QGraphicsRectItem; QGraphicsItem *grandMa = new QGraphicsRectItem;
QGraphicsItem *grandPa = new QGraphicsRectItem; QGraphicsItem *grandPa = new QGraphicsRectItem;
QGraphicsItem *brotherInLaw = new QGraphicsRectItem; QGraphicsItem *brotherInLaw = new QGraphicsRectItem;
@ -3630,7 +3631,7 @@ void tst_QGraphicsItem::setGroup()
QGraphicsItemGroup group1; QGraphicsItemGroup group1;
QGraphicsItemGroup group2; QGraphicsItemGroup group2;
QGraphicsRectItem *rect = new QGraphicsRectItem; const QScopedPointer<QGraphicsRectItem> rect(new QGraphicsRectItem);
QCOMPARE(rect->group(), (QGraphicsItemGroup *)0); QCOMPARE(rect->group(), (QGraphicsItemGroup *)0);
QCOMPARE(rect->parentItem(), (QGraphicsItem *)0); QCOMPARE(rect->parentItem(), (QGraphicsItem *)0);
rect->setGroup(&group1); rect->setGroup(&group1);
@ -6835,8 +6836,8 @@ void tst_QGraphicsItem::opacity()
QFETCH(qreal, c2_effectiveOpacity); QFETCH(qreal, c2_effectiveOpacity);
QFETCH(qreal, c3_effectiveOpacity); QFETCH(qreal, c3_effectiveOpacity);
QGraphicsRectItem *p = new QGraphicsRectItem; const QScopedPointer<QGraphicsRectItem> p(new QGraphicsRectItem);
QGraphicsRectItem *c1 = new QGraphicsRectItem(p); QGraphicsRectItem *c1 = new QGraphicsRectItem(p.data());
QGraphicsRectItem *c2 = new QGraphicsRectItem(c1); QGraphicsRectItem *c2 = new QGraphicsRectItem(c1);
QGraphicsRectItem *c3 = new QGraphicsRectItem(c2); QGraphicsRectItem *c3 = new QGraphicsRectItem(c2);
@ -7224,11 +7225,12 @@ void tst_QGraphicsItem::sceneTransformCache()
// Test that an item's scene transform is updated correctly when the // Test that an item's scene transform is updated correctly when the
// parent is transformed. // parent is transformed.
QGraphicsScene scene; QGraphicsScene scene;
QGraphicsRectItem *rect = scene.addRect(0, 0, 100, 100);
const QScopedPointer<QGraphicsRectItem> rect(scene.addRect(0, 0, 100, 100));
rect->setPen(QPen(Qt::black, 0)); rect->setPen(QPen(Qt::black, 0));
QGraphicsRectItem *rect2 = scene.addRect(0, 0, 100, 100); QGraphicsRectItem *rect2 = scene.addRect(0, 0, 100, 100);
rect2->setPen(QPen(Qt::black, 0)); rect2->setPen(QPen(Qt::black, 0));
rect2->setParentItem(rect); rect2->setParentItem(rect.data());
rect2->setTransform(QTransform().rotate(90), true); rect2->setTransform(QTransform().rotate(90), true);
rect->setTransform(QTransform::fromTranslate(0, 50), true); rect->setTransform(QTransform::fromTranslate(0, 50), true);
QGraphicsView view(&scene); QGraphicsView view(&scene);
@ -7240,7 +7242,7 @@ void tst_QGraphicsItem::sceneTransformCache()
x.rotate(90); x.rotate(90);
QCOMPARE(rect2->sceneTransform(), x); QCOMPARE(rect2->sceneTransform(), x);
scene.removeItem(rect); scene.removeItem(rect.data());
//Crazy use case : rect4 child of rect3 so the transformation of rect4 will be cached.Good! //Crazy use case : rect4 child of rect3 so the transformation of rect4 will be cached.Good!
//We remove rect4 from the scene, then the validTransform bit flag is set to 0 and the index of the cache //We remove rect4 from the scene, then the validTransform bit flag is set to 0 and the index of the cache
@ -10696,7 +10698,7 @@ void tst_QGraphicsItem::scenePosChange()
{ {
ScenePosChangeTester* root = new ScenePosChangeTester; ScenePosChangeTester* root = new ScenePosChangeTester;
ScenePosChangeTester* child1 = new ScenePosChangeTester(root); ScenePosChangeTester* child1 = new ScenePosChangeTester(root);
ScenePosChangeTester* grandChild1 = new ScenePosChangeTester(child1); const QScopedPointer<ScenePosChangeTester> grandChild1(new ScenePosChangeTester(child1));
ScenePosChangeTester* child2 = new ScenePosChangeTester(root); ScenePosChangeTester* child2 = new ScenePosChangeTester(root);
ScenePosChangeTester* grandChild2 = new ScenePosChangeTester(child2); ScenePosChangeTester* grandChild2 = new ScenePosChangeTester(child2);
@ -10748,7 +10750,7 @@ void tst_QGraphicsItem::scenePosChange()
QCOMPARE(grandChild2->changes.count(QGraphicsItem::ItemScenePositionHasChanged), 3); QCOMPARE(grandChild2->changes.count(QGraphicsItem::ItemScenePositionHasChanged), 3);
// remove // remove
scene.removeItem(grandChild1); scene.removeItem(grandChild1.data());
delete grandChild2; grandChild2 = 0; delete grandChild2; grandChild2 = 0;
QCoreApplication::processEvents(); // QGraphicsScenePrivate::_q_updateScenePosDescendants() QCoreApplication::processEvents(); // QGraphicsScenePrivate::_q_updateScenePosDescendants()
root->moveBy(1.0, 1.0); root->moveBy(1.0, 1.0);

View File

@ -2,3 +2,8 @@ CONFIG += testcase
TARGET = tst_qmenubar TARGET = tst_qmenubar
QT += widgets testlib QT += widgets testlib
SOURCES += tst_qmenubar.cpp SOURCES += tst_qmenubar.cpp
macos: {
OBJECTIVE_SOURCES += tst_qmenubar_mac.mm
LIBS += -framework AppKit
}

View File

@ -130,6 +130,9 @@ private slots:
void cornerWidgets_data(); void cornerWidgets_data();
void cornerWidgets(); void cornerWidgets();
void taskQTBUG53205_crashReparentNested(); void taskQTBUG53205_crashReparentNested();
#ifdef Q_OS_MACOS
void taskQTBUG56275_reinsertMenuInParentlessQMenuBar();
#endif
protected slots: protected slots:
void onSimpleActivated( QAction*); void onSimpleActivated( QAction*);
@ -1496,7 +1499,28 @@ void tst_QMenuBar::slotForTaskQTBUG53205()
taskQTBUG53205MenuBar->setParent(parent); taskQTBUG53205MenuBar->setParent(parent);
} }
#ifdef Q_OS_MACOS
extern bool tst_qmenubar_taskQTBUG56275(QMenuBar *);
void tst_QMenuBar::taskQTBUG56275_reinsertMenuInParentlessQMenuBar()
{
QMenuBar menubar;
QMenu *menu = new QMenu("menu", &menubar);
QMenu* submenu = menu->addMenu("submenu");
submenu->addAction("action1");
submenu->addAction("action2");
menu->addAction("action3");
menubar.addMenu(menu);
QTest::qWait(100);
menubar.clear();
menubar.addMenu(menu);
QTest::qWait(100);
QVERIFY(tst_qmenubar_taskQTBUG56275(&menubar));
}
#endif // Q_OS_MACOS
QTEST_MAIN(tst_QMenuBar) QTEST_MAIN(tst_QMenuBar)
#include "tst_qmenubar.moc" #include "tst_qmenubar.moc"

View File

@ -0,0 +1,44 @@
/****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: http://www.qt.io/licensing/
**
** This file is part of the test suite of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL21$
** 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 http://www.qt.io/terms-conditions. For further
** information use the contact form at http://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 2.1 or version 3 as published by the Free
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
** LICENSE.LGPLv3 included in the packaging of this file. Please review the
** following information to ensure the GNU Lesser General Public License
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** As a special exception, The Qt Company gives you certain additional
** rights. These rights are described in The Qt Company LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** $QT_END_LICENSE$
**
****************************************************************************/
#import <Cocoa/Cocoa.h>
#include <QMenuBar>
#include <QTest>
bool tst_qmenubar_taskQTBUG56275(QMenuBar *menubar)
{
NSMenu *mainMenu = menubar->toNSMenu();
return mainMenu.numberOfItems == 2
&& [[mainMenu itemAtIndex:1].title isEqualToString:@"menu"];
}