summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/plugins/platforms/ios/ios.pro2
-rw-r--r--src/plugins/platforms/ios/qiosmenu.h144
-rw-r--r--src/plugins/platforms/ios/qiosmenu.mm525
-rw-r--r--src/plugins/platforms/ios/qiostheme.h3
-rw-r--r--src/plugins/platforms/ios/qiostheme.mm12
-rw-r--r--src/plugins/platforms/ios/quiview.mm8
6 files changed, 694 insertions, 0 deletions
diff --git a/src/plugins/platforms/ios/ios.pro b/src/plugins/platforms/ios/ios.pro
index 82f0bd91c4..6b67a42f69 100644
--- a/src/plugins/platforms/ios/ios.pro
+++ b/src/plugins/platforms/ios/ios.pro
@@ -28,6 +28,7 @@ OBJECTIVE_SOURCES = \
quiaccessibilityelement.mm \
qiosplatformaccessibility.mm \
qiostextresponder.mm \
+ qiosmenu.mm \
HEADERS = \
qiosintegration.h \
@@ -48,6 +49,7 @@ HEADERS = \
quiaccessibilityelement.h \
qiosplatformaccessibility.h \
qiostextresponder.h \
+ qiosmenu.h \
OTHER_FILES = \
quiview_textinput.mm \
diff --git a/src/plugins/platforms/ios/qiosmenu.h b/src/plugins/platforms/ios/qiosmenu.h
new file mode 100644
index 0000000000..9897483a3e
--- /dev/null
+++ b/src/plugins/platforms/ios/qiosmenu.h
@@ -0,0 +1,144 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/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 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QIOSMENU_H
+#define QIOSMENU_H
+
+#import <UIKit/UIKit.h>
+
+#include <QtCore/QtCore>
+#include <qpa/qplatformmenu.h>
+
+#import "quiview.h"
+
+@class QUIMenuController;
+@class QUIPickerView;
+
+class QIOSMenuItem : public QPlatformMenuItem
+{
+public:
+ QIOSMenuItem();
+
+ void setTag(quintptr tag) Q_DECL_OVERRIDE;
+ quintptr tag()const Q_DECL_OVERRIDE;
+
+ void setText(const QString &text) Q_DECL_OVERRIDE;
+ void setIcon(const QIcon &) Q_DECL_OVERRIDE {}
+ void setMenu(QPlatformMenu *) Q_DECL_OVERRIDE {}
+ void setVisible(bool isVisible) Q_DECL_OVERRIDE;
+ void setIsSeparator(bool) Q_DECL_OVERRIDE {}
+ void setFont(const QFont &) Q_DECL_OVERRIDE {}
+ void setRole(MenuRole role) Q_DECL_OVERRIDE;
+ void setCheckable(bool) Q_DECL_OVERRIDE {}
+ void setChecked(bool) Q_DECL_OVERRIDE {}
+ void setShortcut(const QKeySequence&) Q_DECL_OVERRIDE {}
+ void setEnabled(bool enabled) Q_DECL_OVERRIDE;
+ void setIconSize(int) Q_DECL_OVERRIDE {}
+
+ quintptr m_tag;
+ bool m_visible;
+ QString m_text;
+ MenuRole m_role;
+ bool m_enabled;
+
+private:
+ QString removeMnemonics(const QString &original);
+};
+
+typedef QList<QIOSMenuItem *> QIOSMenuItemList;
+
+class QIOSMenu : public QPlatformMenu
+{
+public:
+ QIOSMenu();
+ ~QIOSMenu();
+
+ void insertMenuItem(QPlatformMenuItem *menuItem, QPlatformMenuItem *before) Q_DECL_OVERRIDE;
+ void removeMenuItem(QPlatformMenuItem *menuItem) Q_DECL_OVERRIDE;
+ void syncMenuItem(QPlatformMenuItem *) Q_DECL_OVERRIDE {}
+ void syncSeparatorsCollapsible(bool) Q_DECL_OVERRIDE {}
+
+ void setTag(quintptr tag) Q_DECL_OVERRIDE;
+ quintptr tag()const Q_DECL_OVERRIDE;
+
+ void setText(const QString &) Q_DECL_OVERRIDE;
+ void setIcon(const QIcon &) Q_DECL_OVERRIDE {}
+ void setEnabled(bool enabled) Q_DECL_OVERRIDE;
+ void setVisible(bool visible) Q_DECL_OVERRIDE;
+ void setMenuType(MenuType type) Q_DECL_OVERRIDE;
+
+ void showPopup(const QWindow *parentWindow, const QRect &targetRect, const QPlatformMenuItem *item) Q_DECL_OVERRIDE;
+ void dismiss() Q_DECL_OVERRIDE;
+
+ QPlatformMenuItem *menuItemAt(int position) const Q_DECL_OVERRIDE;
+ QPlatformMenuItem *menuItemForTag(quintptr tag) const Q_DECL_OVERRIDE;
+
+ static QIOSMenu *currentMenu() { return m_currentMenu; }
+ static id menuActionTarget() { return m_currentMenu ? m_currentMenu->m_menuController : 0; }
+
+protected:
+ bool eventFilter(QObject *obj, QEvent *event);
+
+private:
+ quintptr m_tag;
+ bool m_enabled;
+ bool m_visible;
+ bool m_effectiveVisible;
+ QString m_text;
+ MenuType m_menuType;
+ MenuType m_effectiveMenuType;
+ QRect m_targetRect;
+ const QIOSMenuItem *m_targetItem;
+ QUIMenuController *m_menuController;
+ QUIPickerView *m_pickerView;
+ QIOSMenuItemList m_menuItems;
+
+ static QIOSMenu *m_currentMenu;
+
+ void updateVisibility();
+ void updateVisibilityUsingUIMenuController();
+ void updateVisibilityUsingUIPickerView();
+ QIOSMenuItemList visibleMenuItems() const;
+ void repositionMenu();
+ void hide() { setVisible(false); }
+};
+
+#endif // QIOSMENU_H
diff --git a/src/plugins/platforms/ios/qiosmenu.mm b/src/plugins/platforms/ios/qiosmenu.mm
new file mode 100644
index 0000000000..8f7baa9756
--- /dev/null
+++ b/src/plugins/platforms/ios/qiosmenu.mm
@@ -0,0 +1,525 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/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 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <qglobal.h>
+#include <qguiapplication.h>
+
+#include "qiosglobal.h"
+#include "qiosmenu.h"
+#include "qioswindow.h"
+#include "qiosinputcontext.h"
+#include "qiosintegration.h"
+#include "qiostextresponder.h"
+
+// m_currentMenu points to the currently visible menu.
+// Only one menu will be visible at a time, and if a second menu
+// is shown on top of a first, the first one will be told to hide.
+QIOSMenu *QIOSMenu::m_currentMenu = 0;
+
+// -------------------------------------------------------------------------
+
+static NSString *const kSelectorPrefix = @"_qtMenuItem_";
+
+@interface QUIMenuController : UIResponder {
+ QIOSMenuItemList m_visibleMenuItems;
+}
+@end
+
+@implementation QUIMenuController
+
+- (id)initWithVisibleMenuItems:(const QIOSMenuItemList &)visibleMenuItems
+{
+ if (self = [super init]) {
+ m_visibleMenuItems = visibleMenuItems;
+ NSMutableArray *menuItemArray = [NSMutableArray arrayWithCapacity:m_visibleMenuItems.size()];
+ // Create an array of UIMenuItems, one for each visible QIOSMenuItem. Each
+ // UIMenuItem needs a callback assigned, so we assign one of the placeholder methods
+ // added to UIWindow (QIOSMenuActionTargets) below. Each method knows its own index, which
+ // corresponds to the index of the corresponding QIOSMenuItem in m_visibleMenuItems. When
+ // triggered, menuItemActionCallback will end up being called.
+ for (int i = 0; i < m_visibleMenuItems.count(); ++i) {
+ QIOSMenuItem *item = m_visibleMenuItems.at(i);
+ SEL sel = NSSelectorFromString([NSString stringWithFormat:@"%@%i:", kSelectorPrefix, i]);
+ [menuItemArray addObject:[[[UIMenuItem alloc] initWithTitle:item->m_text.toNSString() action:sel] autorelease]];
+ }
+ [UIMenuController sharedMenuController].menuItems = menuItemArray;
+ }
+
+ return self;
+}
+
+- (id)targetForAction:(SEL)action withSender:(id)sender
+{
+ BOOL containsPrefix = ([NSStringFromSelector(action) rangeOfString:kSelectorPrefix].location != NSNotFound);
+ return (containsPrefix && [sender isKindOfClass:[UIMenuController class]]) ? self : 0;
+}
+
+- (NSMethodSignature *)methodSignatureForSelector:(SEL)selector
+{
+ Q_UNUSED(selector);
+ // Just return a dummy signature that NSObject can create an NSInvocation from.
+ // We end up only checking selector in forwardInvocation anyway.
+ return [super methodSignatureForSelector:@selector(methodSignatureForSelector:)];
+}
+
+- (void)forwardInvocation:(NSInvocation *)invocation
+{
+ // Since none of the menu item selector methods actually exist, this function
+ // will end up being called as a final resort. We can then handle the action.
+ NSString *selector = NSStringFromSelector(invocation.selector);
+ NSRange range = NSMakeRange(kSelectorPrefix.length, selector.length - kSelectorPrefix.length - 1);
+ NSInteger selectedIndex = [[selector substringWithRange:range] integerValue];
+
+ emit m_visibleMenuItems.at(selectedIndex)->activated();
+ QIOSMenu::currentMenu()->setVisible(false);
+}
+
+@end
+
+// -------------------------------------------------------------------------
+
+@interface QUIPickerView : UIPickerView <UIPickerViewDelegate, UIPickerViewDataSource> {
+ QIOSMenuItemList m_visibleMenuItems;
+ QPointer<QObject> m_focusObjectWithPickerView;
+ NSInteger m_selectedRow;
+}
+
+@property(retain) UIToolbar *toolbar;
+
+@end
+
+@implementation QUIPickerView
+
+- (id)initWithVisibleMenuItems:(const QIOSMenuItemList &)visibleMenuItems selectItem:(const QIOSMenuItem *)selectItem
+{
+ if (self = [super init]) {
+ self.autoresizingMask = UIViewAutoresizingFlexibleWidth;
+ m_visibleMenuItems = visibleMenuItems;
+ m_selectedRow = visibleMenuItems.indexOf(const_cast<QIOSMenuItem *>(selectItem));
+ if (m_selectedRow == -1)
+ m_selectedRow = 0;
+
+ self.toolbar = [[[UIToolbar alloc] initWithFrame:CGRectMake(0, 0, 100, 44)] autorelease];
+ self.toolbar.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
+
+ UIBarButtonItem *doneButton = [[[UIBarButtonItem alloc]
+ initWithBarButtonSystemItem:UIBarButtonSystemItemDone
+ target:self action:@selector(closeMenu)] autorelease];
+ UIBarButtonItem *spaceButton = [[[UIBarButtonItem alloc]
+ initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace
+ target:self action:@selector(closeMenu)] autorelease];
+ UIBarButtonItem *cancelButton = [[[UIBarButtonItem alloc]
+ initWithBarButtonSystemItem:UIBarButtonSystemItemCancel
+ target:self action:@selector(cancelMenu)] autorelease];
+ [self.toolbar setItems:[NSArray arrayWithObjects:doneButton, spaceButton, cancelButton, nil]];
+
+ [self setDelegate:self];
+ [self setDataSource:self];
+ [self selectRow:m_selectedRow inComponent:0 animated:false];
+ }
+
+ return self;
+}
+
+-(void)dealloc
+{
+ self.toolbar = 0;
+ [super dealloc];
+}
+
+- (NSString *)pickerView:(UIPickerView *)pickerView titleForRow:(NSInteger)row forComponent:(NSInteger)component
+{
+ Q_UNUSED(pickerView);
+ Q_UNUSED(component);
+ return m_visibleMenuItems.at(row)->m_text.toNSString();
+}
+
+- (NSInteger)numberOfComponentsInPickerView:(UIPickerView *)pickerView
+{
+ Q_UNUSED(pickerView);
+ return 1;
+}
+
+- (NSInteger)pickerView:(UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component
+{
+ Q_UNUSED(pickerView);
+ Q_UNUSED(component);
+ return m_visibleMenuItems.length();
+}
+
+- (void)pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component
+{
+ Q_UNUSED(pickerView);
+ Q_UNUSED(component);
+ m_selectedRow = row;
+}
+
+- (void)closeMenu
+{
+ if (!m_visibleMenuItems.isEmpty())
+ emit m_visibleMenuItems.at(m_selectedRow)->activated();
+ QIOSMenu::currentMenu()->setVisible(false);
+}
+
+- (void)cancelMenu
+{
+ QIOSMenu::currentMenu()->setVisible(false);
+}
+
+@end
+
+// -------------------------------------------------------------------------
+
+QIOSMenuItem::QIOSMenuItem()
+ : QPlatformMenuItem()
+ , m_tag(0)
+ , m_visible(true)
+ , m_text(QString())
+ , m_role(MenuRole(0))
+ , m_enabled(true)
+{
+}
+
+void QIOSMenuItem::setTag(quintptr tag)
+{
+ m_tag = tag;
+}
+
+quintptr QIOSMenuItem::tag() const
+{
+ return m_tag;
+}
+
+void QIOSMenuItem::setText(const QString &text)
+{
+ m_text = removeMnemonics(text);
+}
+
+void QIOSMenuItem::setVisible(bool isVisible)
+{
+ m_visible = isVisible;
+}
+
+void QIOSMenuItem::setRole(QPlatformMenuItem::MenuRole role)
+{
+ m_role = role;
+}
+
+void QIOSMenuItem::setEnabled(bool enabled)
+{
+ m_enabled = enabled;
+}
+
+QString QIOSMenuItem::removeMnemonics(const QString &original)
+{
+ // Copied from qcocoahelpers
+ QString returnText(original.size(), 0);
+ int finalDest = 0;
+ int currPos = 0;
+ int l = original.length();
+ while (l) {
+ if (original.at(currPos) == QLatin1Char('&')
+ && (l == 1 || original.at(currPos + 1) != QLatin1Char('&'))) {
+ ++currPos;
+ --l;
+ if (l == 0)
+ break;
+ } else if (original.at(currPos) == QLatin1Char('(') && l >= 4 &&
+ original.at(currPos + 1) == QLatin1Char('&') &&
+ original.at(currPos + 2) != QLatin1Char('&') &&
+ original.at(currPos + 3) == QLatin1Char(')')) {
+ /* remove mnemonics its format is "\s*(&X)" */
+ int n = 0;
+ while (finalDest > n && returnText.at(finalDest - n - 1).isSpace())
+ ++n;
+ finalDest -= n;
+ currPos += 4;
+ l -= 4;
+ continue;
+ }
+ returnText[finalDest] = original.at(currPos);
+ ++currPos;
+ ++finalDest;
+ --l;
+ }
+ returnText.truncate(finalDest);
+ return returnText;
+}
+
+QIOSMenu::QIOSMenu()
+ : QPlatformMenu()
+ , m_tag(0)
+ , m_enabled(true)
+ , m_visible(false)
+ , m_effectiveVisible(false)
+ , m_text(QString())
+ , m_menuType(DefaultMenu)
+ , m_effectiveMenuType(DefaultMenu)
+ , m_targetRect(QRect(qGuiApp->primaryScreen()->availableGeometry().center(), QSize()))
+ , m_targetItem(0)
+ , m_menuController(0)
+ , m_pickerView(0)
+{
+}
+
+QIOSMenu::~QIOSMenu()
+{
+ dismiss();
+}
+
+void QIOSMenu::insertMenuItem(QPlatformMenuItem *menuItem, QPlatformMenuItem *before)
+{
+ if (!before) {
+ m_menuItems.append(static_cast<QIOSMenuItem *>(menuItem));
+ } else {
+ int index = m_menuItems.indexOf(static_cast<QIOSMenuItem *>(before)) + 1;
+ m_menuItems.insert(index, static_cast<QIOSMenuItem *>(menuItem));
+ }
+}
+
+void QIOSMenu::removeMenuItem(QPlatformMenuItem *menuItem)
+{
+ m_menuItems.removeOne(static_cast<QIOSMenuItem *>(menuItem));
+}
+
+void QIOSMenu::setTag(quintptr tag)
+{
+ m_tag = tag;
+}
+
+quintptr QIOSMenu::tag() const
+{
+ return m_tag;
+}
+
+void QIOSMenu::setText(const QString &text)
+{
+ m_text = text;
+}
+
+void QIOSMenu::setEnabled(bool enabled)
+{
+ if (m_enabled == enabled)
+ return;
+
+ m_enabled = enabled;
+ updateVisibility();
+}
+
+void QIOSMenu::showPopup(const QWindow *parentWindow, const QRect &targetRect, const QPlatformMenuItem *item)
+{
+ if (!parentWindow->isActive())
+ const_cast<QWindow *>(parentWindow)->requestActivate();
+ m_targetRect = QRect(parentWindow->mapToGlobal(targetRect.topLeft()), targetRect.size());
+ m_targetItem = static_cast<const QIOSMenuItem *>(item);
+ setVisible(true);
+}
+
+void QIOSMenu::dismiss()
+{
+ setVisible(false);
+}
+
+void QIOSMenu::setVisible(bool visible)
+{
+ if (m_visible == visible)
+ return;
+
+ m_visible = visible;
+ updateVisibility();
+}
+
+void QIOSMenu::updateVisibility()
+{
+ bool visibleAndEnabled = m_visible && m_enabled;
+ if ((visibleAndEnabled && m_effectiveVisible) || (!visibleAndEnabled && m_currentMenu != this))
+ return;
+
+ if (visibleAndEnabled && !qApp->focusObject()) {
+ // Since the menus depend on communicating with a focus object, a focus object is required to show
+ // the menu. Note that QIOSMenu::showPopup() will activate the parent window (and set a focus object)
+ // before this function is called, so this should normally be the case. Not having a focus object is only
+ // expected in a hybrid environment where the first responder can be something else than a QUIView (then
+ // no QWindow will be active). If the focus object changes while the menu is visible, the menu will hide.
+ qWarning() << "QIOSMenu: cannot open menu without any active QWindows!";
+ return;
+ }
+
+ m_effectiveVisible = visibleAndEnabled;
+
+ if (m_effectiveVisible) {
+ Q_ASSERT(m_currentMenu != this);
+ if (m_currentMenu) {
+ // The current implementation allow only one visible
+ // menu at a time, so close the one currently showing.
+ m_currentMenu->setVisible(false);
+ }
+
+ m_currentMenu = this;
+ m_effectiveMenuType = m_menuType;
+ connect(qGuiApp, &QGuiApplication::focusObjectChanged, this, &QIOSMenu::hide);
+ } else {
+ disconnect(qGuiApp, &QGuiApplication::focusObjectChanged, this, &QIOSMenu::hide);
+ m_currentMenu = 0;
+ }
+
+ switch (m_effectiveMenuType) {
+ case EditMenu:
+ updateVisibilityUsingUIMenuController();
+ break;
+ default:
+ updateVisibilityUsingUIPickerView();
+ break;
+ }
+
+ // Emit the signal after the fact in case a
+ // receiver opens a new menu when receiving it.
+ emit (m_effectiveVisible ? aboutToShow() : aboutToHide());
+}
+
+void QIOSMenu::setMenuType(QPlatformMenu::MenuType type)
+{
+ m_menuType = type;
+}
+
+void QIOSMenu::updateVisibilityUsingUIMenuController()
+{
+ if (m_effectiveVisible) {
+ Q_ASSERT(!m_menuController);
+ m_menuController = [[QUIMenuController alloc] initWithVisibleMenuItems:visibleMenuItems()];
+ repositionMenu();
+ connect(qGuiApp->inputMethod(), &QInputMethod::keyboardRectangleChanged, this, &QIOSMenu::repositionMenu);
+ } else {
+ disconnect(qGuiApp->inputMethod(), &QInputMethod::keyboardRectangleChanged, this, &QIOSMenu::repositionMenu);
+
+ Q_ASSERT(m_menuController);
+ [[UIMenuController sharedMenuController] setMenuVisible:NO animated:YES];
+ [m_menuController release];
+ m_menuController = 0;
+ }
+}
+
+void QIOSMenu::updateVisibilityUsingUIPickerView()
+{
+ static QObject *focusObjectWithPickerView = 0;
+
+ if (m_effectiveVisible) {
+ Q_ASSERT(!m_pickerView);
+ m_pickerView = [[QUIPickerView alloc] initWithVisibleMenuItems:visibleMenuItems() selectItem:m_targetItem];
+
+ Q_ASSERT(!focusObjectWithPickerView);
+ focusObjectWithPickerView = qApp->focusWindow()->focusObject();
+ focusObjectWithPickerView->installEventFilter(this);
+ qApp->inputMethod()->update(Qt::ImPlatformData);
+ } else {
+ Q_ASSERT(focusObjectWithPickerView);
+ focusObjectWithPickerView->removeEventFilter(this);
+ qApp->inputMethod()->update(Qt::ImPlatformData);
+ focusObjectWithPickerView = 0;
+
+ Q_ASSERT(m_pickerView);
+ [m_pickerView release];
+ m_pickerView = 0;
+ }
+}
+
+bool QIOSMenu::eventFilter(QObject *obj, QEvent *event)
+{
+ if (event->type() == QEvent::InputMethodQuery) {
+ QInputMethodQueryEvent *queryEvent = static_cast<QInputMethodQueryEvent *>(event);
+ if (queryEvent->queries() & Qt::ImPlatformData) {
+ // Let object fill inn default query results
+ obj->event(queryEvent);
+
+ QVariantMap imPlatformData = queryEvent->value(Qt::ImPlatformData).toMap();
+ imPlatformData.insert(kImePlatformDataInputView, QVariant::fromValue(static_cast<void *>(m_pickerView)));
+ imPlatformData.insert(kImePlatformDataInputAccessoryView, QVariant::fromValue(static_cast<void *>(m_pickerView.toolbar)));
+ queryEvent->setValue(Qt::ImPlatformData, imPlatformData);
+
+ return true;
+ }
+ }
+
+ return QObject::eventFilter(obj, event);
+}
+
+QIOSMenuItemList QIOSMenu::visibleMenuItems() const
+{
+ QIOSMenuItemList visibleMenuItems = m_menuItems;
+
+ for (int i = visibleMenuItems.count() - 1; i >= 0; --i) {
+ QIOSMenuItem *item = visibleMenuItems.at(i);
+ if (!item->m_enabled || !item->m_visible)
+ visibleMenuItems.removeAt(i);
+ }
+
+ return visibleMenuItems;
+}
+
+void QIOSMenu::repositionMenu()
+{
+ switch (m_effectiveMenuType) {
+ case EditMenu: {
+ UIView *view = [UIApplication sharedApplication].keyWindow.rootViewController.view;
+ [[UIMenuController sharedMenuController] setTargetRect:toCGRect(m_targetRect) inView:view];
+ [[UIMenuController sharedMenuController] setMenuVisible:YES animated:YES];
+ break; }
+ default:
+ break;
+ }
+}
+
+QPlatformMenuItem *QIOSMenu::menuItemAt(int position) const
+{
+ if (position < 0 || position >= m_menuItems.size())
+ return 0;
+ return m_menuItems.at(position);
+}
+
+QPlatformMenuItem *QIOSMenu::menuItemForTag(quintptr tag) const
+{
+ for (int i = 0; i < m_menuItems.size(); ++i) {
+ QPlatformMenuItem *item = m_menuItems.at(i);
+ if (item->tag() == tag)
+ return item;
+ }
+ return 0;
+}
diff --git a/src/plugins/platforms/ios/qiostheme.h b/src/plugins/platforms/ios/qiostheme.h
index b03f65f556..b4b7b8977b 100644
--- a/src/plugins/platforms/ios/qiostheme.h
+++ b/src/plugins/platforms/ios/qiostheme.h
@@ -55,6 +55,9 @@ public:
QVariant themeHint(ThemeHint hint) const;
+ QPlatformMenuItem* createPlatformMenuItem() const Q_DECL_OVERRIDE;
+ QPlatformMenu* createPlatformMenu() const Q_DECL_OVERRIDE;
+
const QFont *font(Font type = SystemFont) const;
static const char *name;
diff --git a/src/plugins/platforms/ios/qiostheme.mm b/src/plugins/platforms/ios/qiostheme.mm
index e51e97bd5a..cbeb157cf2 100644
--- a/src/plugins/platforms/ios/qiostheme.mm
+++ b/src/plugins/platforms/ios/qiostheme.mm
@@ -53,6 +53,8 @@
#include <UIKit/UIFont.h>
#include <UIKit/UIInterface.h>
+#include "qiosmenu.h"
+
QT_BEGIN_NAMESPACE
const char *QIOSTheme::name = "ios";
@@ -66,6 +68,16 @@ QIOSTheme::~QIOSTheme()
qDeleteAll(m_fonts);
}
+QPlatformMenuItem* QIOSTheme::createPlatformMenuItem() const
+{
+ return new QIOSMenuItem();
+}
+
+QPlatformMenu* QIOSTheme::createPlatformMenu() const
+{
+ return new QIOSMenu();
+}
+
QVariant QIOSTheme::themeHint(ThemeHint hint) const
{
switch (hint) {
diff --git a/src/plugins/platforms/ios/quiview.mm b/src/plugins/platforms/ios/quiview.mm
index 5687c078ea..3040e89864 100644
--- a/src/plugins/platforms/ios/quiview.mm
+++ b/src/plugins/platforms/ios/quiview.mm
@@ -44,6 +44,7 @@
#include "qiosglobal.h"
#include "qiosintegration.h"
#include "qioswindow.h"
+#include "qiosmenu.h"
#include <QtGui/private/qguiapplication_p.h>
#include <QtGui/private/qwindow_p.h>
@@ -347,6 +348,13 @@
QWindowSystemInterface::flushWindowSystemEvents();
}
+- (id)targetForAction:(SEL)action withSender:(id)sender
+{
+ // Check first if QIOSMenu should handle the action before continuing up the responder chain
+ id target = [QIOSMenu::menuActionTarget() targetForAction:action withSender:sender];
+ return target ? target : [super targetForAction:action withSender:sender];
+}
+
@end
@implementation UIView (QtHelpers)