5#include <AppKit/AppKit.h>
15#include <QtCore/private/qcore_mac_p.h>
16#include <QtCore/private/qthread_p.h>
17#include <QtCore/qcoreapplication.h>
18#include <QtGui/private/qguiapplication_p.h>
20@implementation QCocoaMenuLoader {
24 NSMenuItem *preferencesItem;
25 NSMenuItem *aboutItem;
26 NSMenuItem *aboutQtItem;
28 NSMenuItem *servicesItem;
29 NSMenuItem *hideAllOthersItem;
30 NSMenuItem *showAllItem;
33+ (instancetype)sharedMenuLoader
35 static QCocoaMenuLoader *shared = nil;
36 static dispatch_once_t onceToken;
37 dispatch_once(&onceToken, ^{
38 shared = [[self alloc] init];
49 if ((self = [super init])) {
50 NSString *appName = qt_mac_applicationName().toNSString();
53 theMenu = [[NSMenu alloc] initWithTitle:@
"Main Menu"];
57 NSMenuItem *appItem = [[[NSMenuItem alloc] init] autorelease];
58 appItem.title = appName;
59 [theMenu addItem:appItem];
60 appMenu = [[QCocoaNSMenu alloc] initWithoutPlatformMenu:appName];
61 appItem.submenu = appMenu;
64 aboutItem = [[QCocoaNSMenuItem alloc] init];
65 aboutItem.title = [@
"About " stringByAppendingString:appName];
68 aboutItem.target = self;
69 aboutItem.action = @selector(orderFrontStandardAboutPanel:);
71 aboutItem.enabled = NO;
72 aboutItem.hidden = YES;
73 [appMenu addItem:aboutItem];
76 aboutQtItem = [[QCocoaNSMenuItem alloc] init];
77 aboutQtItem.title = @
"About Qt";
79 aboutQtItem.enabled = NO;
80 aboutQtItem.hidden = YES;
81 [appMenu addItem:aboutQtItem];
83 [appMenu addItem:[NSMenuItem separatorItem]];
89 preferencesItem = [[QCocoaNSMenuItem alloc] init];
90 preferencesItem.title = @
"Preferences…";
91 preferencesItem.keyEquivalent = @
",";
93 preferencesItem.enabled = NO;
94 preferencesItem.hidden = YES;
95 [appMenu addItem:preferencesItem];
97 [appMenu addItem:[NSMenuItem separatorItem]];
100 servicesItem = [[NSMenuItem alloc] init];
101 servicesItem.title = @
"Services";
102 NSMenu *servicesMenu = [[[NSMenu alloc] initWithTitle:@
"Services"] autorelease];
103 servicesItem.submenu = servicesMenu;
104 [NSApplication sharedApplication].servicesMenu = servicesMenu;
105 [appMenu addItem:servicesItem];
107 [appMenu addItem:[NSMenuItem separatorItem]];
110 hideItem = [[NSMenuItem alloc] initWithTitle:[@
"Hide " stringByAppendingString:appName]
111 action:@selector(hide:)
113 hideItem.target = self;
114 [appMenu addItem:hideItem];
117 hideAllOthersItem = [[NSMenuItem alloc] initWithTitle:@
"Hide Others"
118 action:@selector(hideOtherApplications:)
120 hideAllOthersItem.target = self;
121 hideAllOthersItem.keyEquivalentModifierMask = NSEventModifierFlagCommand | NSEventModifierFlagOption;
122 [appMenu addItem:hideAllOthersItem];
125 showAllItem = [[NSMenuItem alloc] initWithTitle:@
"Show All"
126 action:@selector(unhideAllApplications:)
128 showAllItem.target = self;
129 [appMenu addItem:showAllItem];
131 [appMenu addItem:[NSMenuItem separatorItem]];
134 quitItem = [[QCocoaNSMenuItem alloc] init];
135 quitItem.title = [@
"Quit " stringByAppendingString:appName];
136 quitItem.keyEquivalent = @
"q";
140 quitItem.action = @selector(terminate:);
141 [appMenu addItem:quitItem];
152 [aboutQtItem release];
153 [preferencesItem release];
154 [servicesItem release];
156 [hideAllOthersItem release];
157 [showAllItem release];
163- (
void)ensureAppMenuInMenu:(NSMenu *)menu
169 NSMenu *mainMenu = [NSApp mainMenu];
170 if (mainMenu == menu)
177 auto unparentAppMenu = ^
bool (NSMenu *supermenu) {
178 auto index = [supermenu indexOfItemWithSubmenu:appMenu];
180 [supermenu removeItemAtIndex:index];
186 if (!mainMenu || !unparentAppMenu(mainMenu))
187 if (appMenu.supermenu)
188 unparentAppMenu(appMenu.supermenu);
190 NSMenuItem *appMenuItem = [[[NSMenuItem alloc] initWithTitle:@
"Apple"
191 action:nil keyEquivalent:@
""] autorelease];
192 appMenuItem.submenu = appMenu;
193 [menu insertItem:appMenuItem atIndex:0];
198 return [[theMenu retain] autorelease];
201- (
NSMenu *)applicationMenu
203 return [[appMenu retain] autorelease];
208 return [[quitItem retain] autorelease];
213 return [[preferencesItem retain] autorelease];
218 return [[aboutItem retain] autorelease];
223 return [[aboutQtItem retain] autorelease];
228 return [[hideItem retain] autorelease];
231- (
NSMenuItem *)appSpecificMenuItem:(QCocoaMenuItem *)platformItem
234 for (NSMenuItem *item in appMenu.itemArray)
235 if (qt_objc_cast<QCocoaNSMenuItem *>(item).platformMenuItem == platformItem)
240 QCocoaNSMenuItem *item;
241 if (platformItem->isSeparator())
242 item = [QCocoaNSMenuItem separatorItemWithPlatformMenuItem:platformItem];
244 item = [[[QCocoaNSMenuItem alloc] initWithPlatformMenuItem:platformItem] autorelease];
246 const auto location = [self indexOfLastAppSpecificMenuItem];
247 [appMenu insertItem:item atIndex:NSInteger(location) + 1];
252- (
void)orderFrontStandardAboutPanel:(id)sender
254 [NSApp orderFrontStandardAboutPanel:sender];
257- (
void)hideOtherApplications:(id)sender
259 [NSApp hideOtherApplications:sender];
262- (
void)unhideAllApplications:(id)sender
264 [NSApp unhideAllApplications:sender];
267- (
void)hide:(id)sender
272- (
void)qtTranslateApplicationMenu
274#ifndef QT_NO_TRANSLATION
275 aboutItem.title = qt_mac_applicationmenu_string(AboutAppMenuItem).arg(qt_mac_applicationName()).toNSString();
276 preferencesItem.title = qt_mac_applicationmenu_string(PreferencesAppMenuItem).toNSString();
277 servicesItem.title = qt_mac_applicationmenu_string(ServicesAppMenuItem).toNSString();
278 hideItem.title = qt_mac_applicationmenu_string(HideAppMenuItem).arg(qt_mac_applicationName()).toNSString();
279 hideAllOthersItem.title = qt_mac_applicationmenu_string(HideOthersAppMenuItem).toNSString();
280 showAllItem.title = qt_mac_applicationmenu_string(ShowAllAppMenuItem).toNSString();
281 quitItem.title = qt_mac_applicationmenu_string(QuitAppMenuItem).arg(qt_mac_applicationName()).toNSString();
285- (BOOL)validateMenuItem:(NSMenuItem*)menuItem
287 if (menuItem.action == @selector(hideOtherApplications:)
288 || menuItem.action == @selector(unhideAllApplications:)
289 || menuItem.action == @selector(hide:)) {
290 return [NSApp validateMenuItem:menuItem];
293 return menuItem.enabled;
296- (NSArray<NSMenuItem *> *)mergeable
299 auto items = [NSArray arrayWithObjects:preferencesItem, aboutItem, aboutQtItem,
300 appMenu.itemArray[[self indexOfLastAppSpecificMenuItem]], nil];
308 const auto location = [appMenu.itemArray indexOfObjectWithOptions:NSEnumerationReverse
309 passingTest:^BOOL(NSMenuItem *item, NSUInteger, BOOL *) {
310 if (
auto qtItem = qt_objc_cast<QCocoaNSMenuItem*>(item))
311 return qtItem != quitItem;
314 Q_ASSERT(location != NSNotFound);