iOS: enable changing menu items in QIOSMenu while it's showing
If the menu items change while a menu is showing, the current implementation would crash. The current code tried to take this scenario into account by using a copy of the item list inside the native menus, but failed since the list contained pointers to menu items. And those items would be deleted in a higher layer when removed from the owning QMenu, even if the native menu was visible. One could argue that the list of items should not change while the menu is visible, but from testing, other platforms handle this scenario gracefully. So this patch will ensure we do the same on iOS. Task-number: QTBUG-44275 Change-Id: I5508e1d6d47039a9aa948c246b33479bd6801868 Reviewed-by: Gabriel de Dietrich <gabriel.dedietrich@theqtcompany.com>
This commit is contained in:
parent
f40cf77b0f
commit
ce4a759c3d
@ -88,7 +88,7 @@ public:
|
|||||||
|
|
||||||
void insertMenuItem(QPlatformMenuItem *menuItem, QPlatformMenuItem *before) Q_DECL_OVERRIDE;
|
void insertMenuItem(QPlatformMenuItem *menuItem, QPlatformMenuItem *before) Q_DECL_OVERRIDE;
|
||||||
void removeMenuItem(QPlatformMenuItem *menuItem) Q_DECL_OVERRIDE;
|
void removeMenuItem(QPlatformMenuItem *menuItem) Q_DECL_OVERRIDE;
|
||||||
void syncMenuItem(QPlatformMenuItem *) Q_DECL_OVERRIDE {}
|
void syncMenuItem(QPlatformMenuItem *) Q_DECL_OVERRIDE;
|
||||||
void syncSeparatorsCollapsible(bool) Q_DECL_OVERRIDE {}
|
void syncSeparatorsCollapsible(bool) Q_DECL_OVERRIDE {}
|
||||||
|
|
||||||
void setTag(quintptr tag) Q_DECL_OVERRIDE;
|
void setTag(quintptr tag) Q_DECL_OVERRIDE;
|
||||||
|
@ -60,6 +60,14 @@ static NSString *const kSelectorPrefix = @"_qtMenuItem_";
|
|||||||
- (id)initWithVisibleMenuItems:(const QIOSMenuItemList &)visibleMenuItems
|
- (id)initWithVisibleMenuItems:(const QIOSMenuItemList &)visibleMenuItems
|
||||||
{
|
{
|
||||||
if (self = [super init]) {
|
if (self = [super init]) {
|
||||||
|
[self setVisibleMenuItems:visibleMenuItems];
|
||||||
|
}
|
||||||
|
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)setVisibleMenuItems:(const QIOSMenuItemList &)visibleMenuItems
|
||||||
|
{
|
||||||
m_visibleMenuItems = visibleMenuItems;
|
m_visibleMenuItems = visibleMenuItems;
|
||||||
NSMutableArray *menuItemArray = [NSMutableArray arrayWithCapacity:m_visibleMenuItems.size()];
|
NSMutableArray *menuItemArray = [NSMutableArray arrayWithCapacity:m_visibleMenuItems.size()];
|
||||||
// Create an array of UIMenuItems, one for each visible QIOSMenuItem. Each
|
// Create an array of UIMenuItems, one for each visible QIOSMenuItem. Each
|
||||||
@ -73,9 +81,8 @@ static NSString *const kSelectorPrefix = @"_qtMenuItem_";
|
|||||||
[menuItemArray addObject:[[[UIMenuItem alloc] initWithTitle:item->m_text.toNSString() action:sel] autorelease]];
|
[menuItemArray addObject:[[[UIMenuItem alloc] initWithTitle:item->m_text.toNSString() action:sel] autorelease]];
|
||||||
}
|
}
|
||||||
[UIMenuController sharedMenuController].menuItems = menuItemArray;
|
[UIMenuController sharedMenuController].menuItems = menuItemArray;
|
||||||
}
|
if ([UIMenuController sharedMenuController].menuVisible)
|
||||||
|
[[UIMenuController sharedMenuController] setMenuVisible:YES animated:NO];
|
||||||
return self;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
- (id)targetForAction:(SEL)action withSender:(id)sender
|
- (id)targetForAction:(SEL)action withSender:(id)sender
|
||||||
@ -122,12 +129,9 @@ static NSString *const kSelectorPrefix = @"_qtMenuItem_";
|
|||||||
- (id)initWithVisibleMenuItems:(const QIOSMenuItemList &)visibleMenuItems selectItem:(const QIOSMenuItem *)selectItem
|
- (id)initWithVisibleMenuItems:(const QIOSMenuItemList &)visibleMenuItems selectItem:(const QIOSMenuItem *)selectItem
|
||||||
{
|
{
|
||||||
if (self = [super init]) {
|
if (self = [super init]) {
|
||||||
self.autoresizingMask = UIViewAutoresizingFlexibleWidth;
|
[self setVisibleMenuItems:visibleMenuItems selectItem:selectItem];
|
||||||
m_visibleMenuItems = visibleMenuItems;
|
|
||||||
m_selectedRow = visibleMenuItems.indexOf(const_cast<QIOSMenuItem *>(selectItem));
|
|
||||||
if (m_selectedRow == -1)
|
|
||||||
m_selectedRow = 0;
|
|
||||||
|
|
||||||
|
self.autoresizingMask = UIViewAutoresizingFlexibleWidth;
|
||||||
self.toolbar = [[[UIToolbar alloc] init] autorelease];
|
self.toolbar = [[[UIToolbar alloc] init] autorelease];
|
||||||
self.toolbar.frame.size = [self.toolbar sizeThatFits:self.bounds.size];
|
self.toolbar.frame.size = [self.toolbar sizeThatFits:self.bounds.size];
|
||||||
self.toolbar.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
|
self.toolbar.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
|
||||||
@ -152,6 +156,15 @@ static NSString *const kSelectorPrefix = @"_qtMenuItem_";
|
|||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (void)setVisibleMenuItems:(const QIOSMenuItemList &)visibleMenuItems selectItem:(const QIOSMenuItem *)selectItem
|
||||||
|
{
|
||||||
|
m_visibleMenuItems = visibleMenuItems;
|
||||||
|
m_selectedRow = visibleMenuItems.indexOf(const_cast<QIOSMenuItem *>(selectItem));
|
||||||
|
if (m_selectedRow == -1)
|
||||||
|
m_selectedRow = 0;
|
||||||
|
[self reloadAllComponents];
|
||||||
|
}
|
||||||
|
|
||||||
-(void)listenForKeyboardWillHideNotification:(BOOL)listen
|
-(void)listenForKeyboardWillHideNotification:(BOOL)listen
|
||||||
{
|
{
|
||||||
if (listen) {
|
if (listen) {
|
||||||
@ -333,11 +346,30 @@ void QIOSMenu::insertMenuItem(QPlatformMenuItem *menuItem, QPlatformMenuItem *be
|
|||||||
int index = m_menuItems.indexOf(static_cast<QIOSMenuItem *>(before)) + 1;
|
int index = m_menuItems.indexOf(static_cast<QIOSMenuItem *>(before)) + 1;
|
||||||
m_menuItems.insert(index, static_cast<QIOSMenuItem *>(menuItem));
|
m_menuItems.insert(index, static_cast<QIOSMenuItem *>(menuItem));
|
||||||
}
|
}
|
||||||
|
if (m_currentMenu == this)
|
||||||
|
syncMenuItem(menuItem);
|
||||||
}
|
}
|
||||||
|
|
||||||
void QIOSMenu::removeMenuItem(QPlatformMenuItem *menuItem)
|
void QIOSMenu::removeMenuItem(QPlatformMenuItem *menuItem)
|
||||||
{
|
{
|
||||||
m_menuItems.removeOne(static_cast<QIOSMenuItem *>(menuItem));
|
m_menuItems.removeOne(static_cast<QIOSMenuItem *>(menuItem));
|
||||||
|
if (m_currentMenu == this)
|
||||||
|
syncMenuItem(menuItem);
|
||||||
|
}
|
||||||
|
|
||||||
|
void QIOSMenu::syncMenuItem(QPlatformMenuItem *)
|
||||||
|
{
|
||||||
|
if (m_currentMenu != this)
|
||||||
|
return;
|
||||||
|
|
||||||
|
switch (m_effectiveMenuType) {
|
||||||
|
case EditMenu:
|
||||||
|
[m_menuController setVisibleMenuItems:visibleMenuItems()];
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
[m_pickerView setVisibleMenuItems:visibleMenuItems() selectItem:m_targetItem];
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void QIOSMenu::setTag(quintptr tag)
|
void QIOSMenu::setTag(quintptr tag)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user