iOS: Implement support for native menus

Change-Id: I2c7278697499aa046ac7b1240b7bc713ad1fc709
Reviewed-by: Tor Arne Vestbø <tor.arne.vestbo@digia.com>
This commit is contained in:
Richard Moe Gustavsen 2014-05-22 14:11:32 +02:00
parent 79ad2b3799
commit 55bd24e961
6 changed files with 694 additions and 0 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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