Cocoa Menus: Allow separators in app menu

We extend QCocoaNSMenuItem with separator items capabilities
and use it as any other custom item in the app menu.

Addition and removal of items in the app menu remains very
basic because that menu doesn't exist as such. Instead, it's
hinted through the QAction's menu role.

Change-Id: Ia13bfcc008c75e49fd21705d2528da5a85ed1c73
Task-number: QTBUG-63756
Reviewed-by: Tor Arne Vestbø <tor.arne.vestbo@qt.io>
bb10
Gabriel de Dietrich 2018-04-17 15:36:09 -07:00
parent 99290faa66
commit 48defe41e1
5 changed files with 30 additions and 11 deletions

View File

@ -205,7 +205,7 @@ void QCocoaMenu::removeMenuItem(QPlatformMenuItem *menuItem)
QCocoaMenuItem *QCocoaMenu::itemOrNull(int index) const
{
if ((index < 0) || (index >= m_menuItems.size()))
return 0;
return nullptr;
return m_menuItems.at(index);
}

View File

@ -219,12 +219,11 @@ void QCocoaMenuItem::setNativeContents(WId item)
NSMenuItem *QCocoaMenuItem::sync()
{
if (m_isSeparator != [m_native isSeparatorItem]) {
if (m_isSeparator != m_native.separatorItem) {
[m_native release];
if (m_isSeparator) {
m_native = [[NSMenuItem separatorItem] retain];
[m_native setTag:reinterpret_cast<NSInteger>(this)];
} else
if (m_isSeparator)
m_native = [[QCocoaNSMenuItem separatorItemWithPlatformMenuItem:this] retain];
else
m_native = nil;
}
@ -435,6 +434,9 @@ void QCocoaMenuItem::setIconSize(int size)
void QCocoaMenuItem::resolveTargetAction()
{
if (m_native.separatorItem)
return;
// Some items created by QCocoaMenuLoader are not
// instances of QCocoaNSMenuItem and have their
// target/action set as Interface Builder would.

View File

@ -272,18 +272,21 @@
- (NSMenuItem *)appSpecificMenuItem:(QCocoaMenuItem *)platformItem
{
// No reason to create the item if it already exists.
for (NSMenuItem *item in appMenu.itemArray)
if ([item isMemberOfClass:[QCocoaNSMenuItem class]]
&& static_cast<QCocoaNSMenuItem *>(item).platformMenuItem == platformItem) {
// No reason to create the item if it already exists.
&& static_cast<QCocoaNSMenuItem *>(item).platformMenuItem == platformItem)
return [[item retain] autorelease];
}
// Create an App-Specific menu item, insert it into the menu and return
// it as an autorelease item.
QCocoaNSMenuItem *item = [[QCocoaNSMenuItem alloc] initWithPlatformMenuItem:platformItem];
QCocoaNSMenuItem *item;
if (platformItem->isSeparator())
item = [[QCocoaNSMenuItem separatorItemWithPlatformMenuItem:platformItem] retain];
else
item = [[QCocoaNSMenuItem alloc] initWithPlatformMenuItem:platformItem];
NSInteger location = [appMenu indexOfItem:lastAppSpecificItem];
const auto location = [appMenu indexOfItem:lastAppSpecificItem];
if (!lastAppSpecificItem.separatorItem)
[lastAppSpecificItem release];

View File

@ -80,6 +80,7 @@ QT_FORWARD_DECLARE_CLASS(QCocoaMenuItem);
@property (nonatomic) QCocoaMenuItem *platformMenuItem;
+ (instancetype)separatorItemWithPlatformMenuItem:(QCocoaMenuItem *)menuItem;
- (instancetype)initWithPlatformMenuItem:(QCocoaMenuItem *)menuItem;
@end

View File

@ -97,6 +97,19 @@ static NSString *qt_mac_removePrivateUnicode(NSString* string)
QPointer<QCocoaMenuItem> _platformMenuItem;
}
+ (instancetype)separatorItemWithPlatformMenuItem:(QCocoaMenuItem *)menuItem
{
// Safe because +[NSMenuItem separatorItem] invokes [[self alloc] init]
auto *item = static_cast<QCocoaNSMenuItem *>([self separatorItem]);
Q_ASSERT_X([item isMemberOfClass:[QCocoaNSMenuItem class]],
qPrintable(__FUNCTION__),
"Did +[NSMenuItem separatorItem] not invoke [[self alloc] init]?");
if (item)
item.platformMenuItem = menuItem;
return item;
}
- (instancetype)initWithPlatformMenuItem:(QCocoaMenuItem *)menuItem
{
if ((self = [super initWithTitle:@"" action:nil keyEquivalent:@""])) {