From b34909762b01d174d3140e000537d84ed0f1042a Mon Sep 17 00:00:00 2001 From: Dmitry Moiseev Date: Thu, 9 Jan 2014 01:17:36 -0800 Subject: Native OS X system indicator using PyObjC --- SysIndicator.py | 72 ++++++++++++++++++++++++++++++++++++++++++++------------- 1 file changed, 56 insertions(+), 16 deletions(-) diff --git a/SysIndicator.py b/SysIndicator.py index 6f68018..b86048a 100644 --- a/SysIndicator.py +++ b/SysIndicator.py @@ -8,7 +8,32 @@ import tempfile if sys.platform=="linux2" or sys.platform=="win32": import gtk elif sys.platform=="darwin": - import rumps + import objc + from Foundation import * + from AppKit import * + from PyObjCTools import AppHelper + + +class StatusApp(NSApplication): + + def initMenu(self,menu): + statusbar = NSStatusBar.systemStatusBar() + self.statusitem = statusbar.statusItemWithLength_(NSVariableStatusItemLength) + + self.mymenu = menu + #add menu to statusitem + self.statusitem.setMenu_(menu.menubarMenu) + self.statusitem.setToolTip_('Parrot Zik Indicator') + + def setIcon(self,icon,icon_directory): + self.icon = NSImage.alloc().initByReferencingFile_(icon_directory+icon+'.png') + self.icon.setScalesWhenResized_(True) + self.icon.setSize_((20, 20)) + self.statusitem.setImage_(self.icon) + + def clicked_(self, notification): + self.mymenu.actions[notification._.title]() + NSLog('clicked!') class SysIndicator: def __init__(self, icon,menu): @@ -36,7 +61,9 @@ class SysIndicator: sys.stderr = open(tempfile.gettempdir()+os.path.sep+"zik_tray_stderr.log", "w") elif sys.platform=="darwin": - self.statusicon = rumps.App("Parrot Zik") + self.icon_directory = os.path.dirname(os.path.realpath(sys.argv[0])) + os.path.sep+ 'share' + os.path.sep+'icons' + os.path.sep+'zik'+ os.path.sep + self.statusicon = StatusApp.sharedApplication() + self.statusicon.initMenu(menu) self.setIcon(icon) @@ -46,7 +73,7 @@ class SysIndicator: elif sys.platform=="win32": self.statusicon.set_from_file(self.icon_directory+name+'.png') elif sys.platform=="darwin": - self.statusicon.icon=self.icon_directory+name+'.png' + self.statusicon.setIcon(name,self.icon_directory) def gtk_right_click_event(self, icon, button, time): if not self.menu_shown: @@ -60,7 +87,8 @@ class SysIndicator: if sys.platform=="linux2" or sys.platform=="win32": gtk.main() elif sys.platform=="darwin": - self.app.run() + #self.statusicon.run() + AppHelper.runEventLoop() def show_about_dialog(self, widget): if sys.platform=="linux2" or sys.platform=="win32": @@ -80,7 +108,10 @@ class UniversalMenu: self.gtk_quite_item = MenuItem("Quit",sys.exit).gtk_item self.gtk_menu.append(self.gtk_quite_item) elif sys.platform=="darwin": - self.rumps_menu = [] + self.actions = {} + self.menubarMenu = NSMenu.alloc().init() + self.menubarMenu.setAutoenablesItems_(False) + def append(self,MenuItem): if sys.platform=="linux2" or sys.platform=="win32": @@ -88,7 +119,8 @@ class UniversalMenu: self.gtk_menu.append(MenuItem.gtk_item) self.gtk_menu.append(self.gtk_quite_item) elif sys.platform=="darwin": - self.rumps_menu.append(self.rumps_item) + self.actions[MenuItem.title] = MenuItem.action + self.menubarMenu.addItem_(MenuItem.nsmenu_item) class MenuItem: def __init__(self,name,action,sensitive = True, checkitem = False): @@ -101,39 +133,47 @@ class MenuItem: if action: self.gtk_item.connect("activate", action) - if not sensitive: - self.set_sensitive(sensitive) elif sys.platform=="darwin": - self.rumps_item = rumps.MenuItem(name, callback=action) + self.title = name + self.action = action + self.nsmenu_item = NSMenuItem.alloc().initWithTitle_action_keyEquivalent_(name, 'clicked:', '') + + self.set_sensitive(sensitive) def set_sensitive(self,option): if sys.platform=="linux2" or sys.platform=="win32": return self.gtk_item.set_sensitive(option) + elif sys.platform=="darwin": + self.nsmenu_item.setEnabled_(option) def set_active(self,option): if sys.platform=="linux2" or sys.platform=="win32": return self.gtk_item.set_active(option) elif sys.platform=="darwin": - self.rumps_item.state = option + self.nsmenu_item.setState_(option) def get_active(self): if sys.platform=="linux2" or sys.platform=="win32": return self.gtk_item.get_active() elif sys.platform=="darwin": - return self.rumps_item.state + print self.nsmenu_item.state + return self.nsmenu_item.state + def set_label(self,option): if sys.platform=="linux2" or sys.platform=="win32": return self.gtk_item.set_label(option) elif sys.platform=="darwin": - self.rumps_item.title=option + self.title = option + self.nsmenu_item.setTitle_(option) + #self.rumps_item.title=option if __name__ == "__main__": - info_item = MenuItem("Parrot Zik Not connected..",None,False) + quit_item = MenuItem("Quit",sys.exit,True) menu = UniversalMenu() - menu.append(info_item) + menu.append(quit_item) - indicator = SysIndicator(icon = "audio-headset",menu = menu) - indicator.main() + indicator = SysIndicator(icon = "zik-audio-headset",menu = menu) + indicator.main() \ No newline at end of file -- cgit v1.2.1