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
SOURCES += $$OBJECTIVE_SOURCES
unset(OBJECTIVE_SOURCES)
# Strip C/C++ flags from QMAKE_OBJECTIVE_CFLAGS just in case
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
QMAKE_CFLAGS += $$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.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.input = SOURCES OBJECTIVE_SOURCES
moc_source.input = SOURCES
moc_source.name = MOC ${QMAKE_FILE_IN}
moc_source.depends += $$WIN_INCLUDETEMP
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_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
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.
\section1 QMAKE_LFLAGS

View File

@ -46,6 +46,7 @@
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <limits.h>
#if defined(_MSC_VER) && _MSC_VER >= 1400
#include <share.h>
#endif
@ -979,9 +980,11 @@ bool QMakeSourceFileInfo::findMocs(SourceFile *file)
continue;
int matchlen = 0, extralines = 0;
size_t needle_len = strlen(interesting[interest]);
Q_ASSERT(needle_len <= INT_MAX);
if (matchWhileUnsplitting(buffer, buffer_len, y,
interesting[interest],
strlen(interesting[interest]),
static_cast<int>(needle_len),
&matchlen, &extralines)
&& y + matchlen < buffer_len
&& !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
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.
The solution to this is to compare against values greater than or equal to 1.0.
Note that comparing values where either \a p1 or \a p2 is 0.0 will not work,
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

View File

@ -60,7 +60,7 @@ QT_BEGIN_NAMESPACE
* 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
#elif defined(Q_CC_GNU) && !defined(Q_OS_ANDROID)
# 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;
QMutableListIterator<QString> it(p);
while (it.hasNext()) {
QString origPath = it.next();
QString origPath = it.next().normalized(QString::NormalizationForm_C);
QString realPath = origPath;
if (realPath.endsWith(QDir::separator()))
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)
return 0;
union {
const QChar *w;
const quint32 *d;
quintptr value;
} sa, sb;
sa.w = a;
sb.w = b;
// 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
if (sa.value & 2) {
if (reinterpret_cast<quintptr>(a) & 2) {
// both addresses are not aligned to 4-bytes boundaries
// compare the first character
if (*sa.w != *sb.w)
return sa.w->unicode() - sb.w->unicode();
if (*a != *b)
return a->unicode() - b->unicode();
--l;
++sa.w;
++sb.w;
++a;
++b;
// now both addresses are 4-bytes aligned
}
// both addresses are 4-bytes aligned
// do a fast 32-bit comparison
const quint32 *e = sa.d + (l >> 1);
for ( ; sa.d != e; ++sa.d, ++sb.d) {
if (*sa.d != *sb.d) {
if (*sa.w != *sb.w)
return sa.w->unicode() - sb.w->unicode();
return sa.w[1].unicode() - sb.w[1].unicode();
const quint32 *da = reinterpret_cast<const quint32 *>(a);
const quint32 *db = reinterpret_cast<const quint32 *>(b);
const quint32 *e = da + (l >> 1);
for ( ; da != e; ++da, ++db) {
if (*da != *db) {
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?
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 {
// one of the addresses isn't 4-byte aligned but the other is
const QChar *e = sa.w + l;
for ( ; sa.w != e; ++sa.w, ++sb.w) {
if (*sa.w != *sb.w)
return sa.w->unicode() - sb.w->unicode();
const QChar *e = a + l;
for ( ; a != e; ++a, ++b) {
if (*a != *b)
return a->unicode() - b->unicode();
}
}
return 0;

View File

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

View File

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

View File

@ -414,8 +414,7 @@ QVariant QMacPasteboardMimeUnicodeText::convertToMime(const QString &mimetype, Q
if (flavor == QLatin1String("public.utf8-plain-text")) {
ret = QString::fromUtf8(firstData);
} else if (flavor == QLatin1String("public.utf16-plain-text")) {
ret = QString(reinterpret_cast<const QChar *>(firstData.constData()),
firstData.size() / sizeof(QChar));
ret = QTextCodec::codecForName("UTF-16")->toUnicode(firstData);
} else {
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"))
ret.append(string.toUtf8());
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;
}

View File

@ -76,6 +76,7 @@ private:
static QCocoaWindow *findWindowForMenubar();
static QCocoaMenuBar *findGlobalMenubar();
bool needsImmediateUpdate();
bool shouldDisable(QCocoaWindow *active) 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)
{
QCocoaMenu *menu = static_cast<QCocoaMenu *>(platformMenu);
@ -135,7 +161,7 @@ void QCocoaMenuBar::insertMenu(QPlatformMenu *platformMenu, QPlatformMenu *befor
syncMenu(menu);
if (m_window && m_window->window()->isActive())
if (needsImmediateUpdate())
updateMenuBarImmediately();
}

View File

@ -1,65 +1,2 @@
TARGET = qios
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)
TEMPLATE = subdirs
SUBDIRS = kernel.pro optional

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();
bool open(QIODevice::OpenMode openMode) Q_DECL_OVERRIDE;
bool close() Q_DECL_OVERRIDE;
FileFlags fileFlags(FileFlags type) const Q_DECL_OVERRIDE;
qint64 size() const Q_DECL_OVERRIDE;
qint64 read(char *data, qint64 maxlen) Q_DECL_OVERRIDE;
qint64 pos() const Q_DECL_OVERRIDE;
bool seek(qint64 pos) Q_DECL_OVERRIDE;
QString fileName(FileName file) const Q_DECL_OVERRIDE;
void setFileName(const QString &file) Q_DECL_OVERRIDE;
QStringList entryList(QDir::Filters filters, const QStringList &filterNames) const Q_DECL_OVERRIDE;
bool open(QIODevice::OpenMode openMode) override;
bool close() override;
FileFlags fileFlags(FileFlags type) const override;
qint64 size() const override;
qint64 read(char *data, qint64 maxlen) override;
qint64 pos() const override;
bool seek(qint64 pos) override;
QString fileName(FileName file) const override;
void setFileName(const QString &file) override;
QStringList entryList(QDir::Filters filters, const QStringList &filterNames) const override;
#ifndef QT_NO_FILESYSTEMITERATOR
Iterator *beginEntryList(QDir::Filters filters, const QStringList &filterNames) Q_DECL_OVERRIDE;
Iterator *endEntryList() Q_DECL_OVERRIDE;
Iterator *beginEntryList(QDir::Filters filters, const QStringList &filterNames) override;
Iterator *endEntryList() override;
#endif
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;
QEventLoop m_eventLoop;
UIViewController *m_viewController;
bool showImagePickerDialog(QWindow *parent);
};
QT_END_NAMESPACE

View File

@ -37,52 +37,18 @@
**
****************************************************************************/
#include "qiosfiledialog.h"
#import <UIKit/UIKit.h>
#include <QtCore/qstandardpaths.h>
#include <QtGui/qwindow.h>
#include <QDebug>
@interface QIOSImagePickerController : UIImagePickerController <UIImagePickerControllerDelegate, UINavigationControllerDelegate> {
QIOSFileDialog *m_fileDialog;
}
@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
// --------------------------------------------------------------------------
#include "qiosfiledialog.h"
#include "qiosintegration.h"
#include "qiosoptionalplugininterface.h"
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;
QString directory = options()->initialDirectory().toLocalFile();
if (acceptOpen && directory.startsWith(QLatin1String("assets-library:"))) {
m_viewController = [[QIOSImagePickerController alloc] initWithQIOSFileDialog:this];
UIWindow *window = parent ? reinterpret_cast<UIView *>(parent->winId()).window
: [UIApplication sharedApplication].keyWindow;
[window.rootViewController presentViewController:m_viewController animated:YES completion:nil];
return true;
}
if (acceptOpen && directory.startsWith(QLatin1String("assets-library:")))
return showImagePickerDialog(parent);
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()
{
// 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()));
[m_viewController dismissViewControllerAnimated:YES completion:nil];
[m_viewController release];
m_viewController = Q_NULLPTR;
m_eventLoop.exit();
}

View File

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

View File

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

View File

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

View File

@ -535,7 +535,7 @@ void QWidgetWindow::handleMouseEvent(QMouseEvent *event)
// activate window of the widget under mouse pointer
if (!w->isActiveWindow()) {
w->activateWindow();
w->raise();
w->window()->raise();
}
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)
static QAquaWidgetSize qt_aqua_guess_size(const QWidget *widg, QSize large, QSize small, QSize mini)
{
Q_UNUSED(widg);
if (large == QSize(-1, -1)) {
if (small != QSize(-1, -1))
return QAquaSizeSmall;
@ -1054,7 +1056,7 @@ static QAquaWidgetSize qt_aqua_guess_size(const QWidget *widg, QSize large, QSiz
}
#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)
return QAquaSizeSmall;
} else if (qEnvironmentVariableIsSet("QWIDGET_ALL_MINI")) {

View File

@ -3133,6 +3133,7 @@ void QComboBox::keyPressEvent(QKeyEvent *e)
case Qt::Key_Up:
if (e->modifiers() & Qt::ControlModifier)
break; // pass to line edit for auto completion
// fall through
case Qt::Key_PageUp:
#ifdef QT_KEYPAD_NAVIGATION
if (QApplication::keypadNavigationEnabled())
@ -3220,6 +3221,7 @@ void QComboBox::keyPressEvent(QKeyEvent *e)
switch (move) {
case MoveFirst:
newIndex = -1;
// fall through
case MoveDown:
newIndex++;
while (newIndex < rowCount && !(d->model->index(newIndex, d->modelColumn, d->root).flags() & Qt::ItemIsEnabled))
@ -3227,6 +3229,7 @@ void QComboBox::keyPressEvent(QKeyEvent *e)
break;
case MoveLast:
newIndex = rowCount;
// fall through
case MoveUp:
newIndex--;
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
char buf;
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 watchUnicodeCharacters();
private:
QString m_tempDirPattern;
#endif // QT_NO_FILESYSTEMWATCHER
@ -759,6 +761,25 @@ void tst_QFileSystemWatcher::signalsEmittedAfterFileMoved()
QVERIFY2(changedSpy.count() <= fileCount, changedSpy.receivedFilesMessage());
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
QTEST_MAIN(tst_QFileSystemWatcher)

View File

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

View File

@ -845,14 +845,14 @@ void tst_QGraphicsItem::parentItem()
void tst_QGraphicsItem::setParentItem()
{
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);
QGraphicsRectItem *child = new QGraphicsRectItem;
const QScopedPointer<QGraphicsRectItem> child(new QGraphicsRectItem);
QCOMPARE(child->scene(), (QGraphicsScene *)0);
// This implicitly adds the item to the parent's scene
child->setParentItem(item);
child->setParentItem(item.data());
QCOMPARE(child->scene(), &scene);
// This just makes it a toplevel
@ -860,8 +860,8 @@ void tst_QGraphicsItem::setParentItem()
QCOMPARE(child->scene(), &scene);
// Add the child back to the parent, then remove the parent from the scene
child->setParentItem(item);
scene.removeItem(item);
child->setParentItem(item.data());
scene.removeItem(item.data());
QCOMPARE(child->scene(), (QGraphicsScene *)0);
}
@ -959,19 +959,19 @@ void tst_QGraphicsItem::flags()
QCOMPARE(item->pos(), QPointF(10, 10));
}
{
QGraphicsItem* clippingParent = new QGraphicsRectItem;
const QScopedPointer<QGraphicsItem> clippingParent(new QGraphicsRectItem);
clippingParent->setFlag(QGraphicsItem::ItemClipsChildrenToShape, true);
QGraphicsItem* nonClippingParent = new QGraphicsRectItem;
const QScopedPointer<QGraphicsItem> nonClippingParent(new QGraphicsRectItem);
nonClippingParent->setFlag(QGraphicsItem::ItemClipsChildrenToShape, false);
QGraphicsItem* child = new QGraphicsRectItem(nonClippingParent);
QGraphicsItem* child = new QGraphicsRectItem(nonClippingParent.data());
QVERIFY(!child->isClipped());
child->setParentItem(clippingParent);
child->setParentItem(clippingParent.data());
QVERIFY(child->isClipped());
child->setParentItem(nonClippingParent);
child->setParentItem(nonClippingParent.data());
QVERIFY(!child->isClipped());
}
}
@ -3130,7 +3130,8 @@ void tst_QGraphicsItem::isAncestorOf()
void tst_QGraphicsItem::commonAncestorItem()
{
QGraphicsItem *ancestor = new QGraphicsRectItem;
QGraphicsRectItem ancestorItem;
QGraphicsItem *ancestor = &ancestorItem;
QGraphicsItem *grandMa = new QGraphicsRectItem;
QGraphicsItem *grandPa = new QGraphicsRectItem;
QGraphicsItem *brotherInLaw = new QGraphicsRectItem;
@ -3630,7 +3631,7 @@ void tst_QGraphicsItem::setGroup()
QGraphicsItemGroup group1;
QGraphicsItemGroup group2;
QGraphicsRectItem *rect = new QGraphicsRectItem;
const QScopedPointer<QGraphicsRectItem> rect(new QGraphicsRectItem);
QCOMPARE(rect->group(), (QGraphicsItemGroup *)0);
QCOMPARE(rect->parentItem(), (QGraphicsItem *)0);
rect->setGroup(&group1);
@ -6835,8 +6836,8 @@ void tst_QGraphicsItem::opacity()
QFETCH(qreal, c2_effectiveOpacity);
QFETCH(qreal, c3_effectiveOpacity);
QGraphicsRectItem *p = new QGraphicsRectItem;
QGraphicsRectItem *c1 = new QGraphicsRectItem(p);
const QScopedPointer<QGraphicsRectItem> p(new QGraphicsRectItem);
QGraphicsRectItem *c1 = new QGraphicsRectItem(p.data());
QGraphicsRectItem *c2 = new QGraphicsRectItem(c1);
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
// parent is transformed.
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));
QGraphicsRectItem *rect2 = scene.addRect(0, 0, 100, 100);
rect2->setPen(QPen(Qt::black, 0));
rect2->setParentItem(rect);
rect2->setParentItem(rect.data());
rect2->setTransform(QTransform().rotate(90), true);
rect->setTransform(QTransform::fromTranslate(0, 50), true);
QGraphicsView view(&scene);
@ -7240,7 +7242,7 @@ void tst_QGraphicsItem::sceneTransformCache()
x.rotate(90);
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!
//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* child1 = new ScenePosChangeTester(root);
ScenePosChangeTester* grandChild1 = new ScenePosChangeTester(child1);
const QScopedPointer<ScenePosChangeTester> grandChild1(new ScenePosChangeTester(child1));
ScenePosChangeTester* child2 = new ScenePosChangeTester(root);
ScenePosChangeTester* grandChild2 = new ScenePosChangeTester(child2);
@ -10748,7 +10750,7 @@ void tst_QGraphicsItem::scenePosChange()
QCOMPARE(grandChild2->changes.count(QGraphicsItem::ItemScenePositionHasChanged), 3);
// remove
scene.removeItem(grandChild1);
scene.removeItem(grandChild1.data());
delete grandChild2; grandChild2 = 0;
QCoreApplication::processEvents(); // QGraphicsScenePrivate::_q_updateScenePosDescendants()
root->moveBy(1.0, 1.0);

View File

@ -2,3 +2,8 @@ CONFIG += testcase
TARGET = tst_qmenubar
QT += widgets testlib
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();
void taskQTBUG53205_crashReparentNested();
#ifdef Q_OS_MACOS
void taskQTBUG56275_reinsertMenuInParentlessQMenuBar();
#endif
protected slots:
void onSimpleActivated( QAction*);
@ -1496,7 +1499,28 @@ void tst_QMenuBar::slotForTaskQTBUG53205()
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)
#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"];
}