From b75469eca8efbd53d1d49015c7c7d543c7d4a286 Mon Sep 17 00:00:00 2001 From: Robert Klep Date: Sat, 12 Nov 2011 08:13:13 +0100 Subject: [PATCH] Replaced title with images --- ToggleProxy.py | 39 ++++++++++++++++++++++++++------------- resources/active.png | Bin 0 -> 296 bytes resources/inactive.png | Bin 0 -> 272 bytes resources/menuicon.psd | Bin 0 -> 29584 bytes setup.py | 4 ++++ 5 files changed, 30 insertions(+), 13 deletions(-) create mode 100644 resources/active.png create mode 100644 resources/inactive.png create mode 100644 resources/menuicon.psd diff --git a/ToggleProxy.py b/ToggleProxy.py index 7db5745..80c29a7 100644 --- a/ToggleProxy.py +++ b/ToggleProxy.py @@ -8,6 +8,15 @@ import commands, re, time class ToggleProxy(NSObject): def applicationDidFinishLaunching_(self, notification): + # define some title-related stuff + self.active_color = NSColor.colorWithSRGBRed_green_blue_alpha_(0, 0.5, 0, 1) + self.inactive_color = NSColor.colorWithSRGBRed_green_blue_alpha_(0.6, 0, 0, 1) + self.title_font = NSFont.fontWithName_size_('HelveticaNeue-Bold', 12.0) + + # find image files + self.active_image = NSImage.imageNamed_("active") + self.inactive_image = NSImage.imageNamed_("inactive") + # make status bar item self.statusitem = NSStatusBar.systemStatusBar().statusItemWithLength_(NSVariableStatusItemLength) self.statusitem.retain() @@ -16,23 +25,20 @@ class ToggleProxy(NSObject): self.statusitem.setHighlightMode_(False) self.statusitem.setEnabled_(True) - # define some title-related stuff - self.active_color = NSColor.colorWithSRGBRed_green_blue_alpha_(0, 0.5, 0, 1) - self.inactive_color = NSColor.colorWithSRGBRed_green_blue_alpha_(0.6, 0, 0, 1) - self.title_font = NSFont.fontWithName_size_('HelveticaNeue-Bold', 12.0) - # start working self.loadNetworkServices() self.watchForProxyChanges() self.updateProxyStatus() def loadNetworkServices(self): + """ load list of network services, the easy way """ self.services = {} output = commands.getoutput("/usr/sbin/networksetup listnetworkserviceorder") for service, device in re.findall(r'Hardware Port:\s*(.*?), Device:\s*(.*?)\)', output): self.services[device] = service def watchForProxyChanges(self): + """ install a watcher for proxy changes """ store = SCDynamicStoreCreate(None, "name.klep.toggleproxy", self.proxyStateChanged, None) SCDynamicStoreSetNotificationKeys(store, None, [ 'State:/Network/Global/Proxies' ]) @@ -41,32 +47,39 @@ class ToggleProxy(NSObject): CFRunLoopAddSource(loop, source, kCFRunLoopCommonModes) def proxyStateChanged(self, store, keys, info): + """ callback for watcher """ self.updateProxyStatus() def updateProxyStatus(self): + """ update proxy status """ proxydict = SCDynamicStoreCopyProxies(None) interface = proxydict['__SCOPED__'].keys()[0] status = proxydict['__SCOPED__'][interface] self.active = status.get('HTTPEnable', False) and True or False self.device = interface - title = NSAttributedString.alloc().initWithString_attributes_( - "Proxy %sactive" % (not self.active and "in" or ""), { - # NSFontAttributeName : self.title_font, - NSForegroundColorAttributeName : self.active and self.active_color or self.inactive_color, - } - ) - self.statusitem.setAttributedTitle_(title) + # set image + self.statusitem.setImage_( self.active and self.active_image or self.inactive_image ) + + # set tooltip if self.active: tooltip = "Proxy active on %s:%s" % ( proxydict.get('HTTPProxy', '??'), proxydict.get('HTTPPort', '??') ) else: - tooltip = "" + tooltip = "Proxy is not active" self.statusitem.setToolTip_(tooltip) def toggleProxy_(self, sender): + """ callback for clicks on menu item """ + event = NSApp.currentEvent() + + # Ctrl pressed? if so, quit + if event.modifierFlags() & NSControlKeyMask: + NSApp.terminate_(self) + return + servicename = self.services.get(self.device) if not servicename: NSLog("device '%s' not found in services?" % self.device) diff --git a/resources/active.png b/resources/active.png new file mode 100644 index 0000000000000000000000000000000000000000..0f9c6b1bec4ff9e55d0c4116456971214bc3d2f7 GIT binary patch literal 296 zcmeAS@N?(olHy`uVBq!ia0vp^f*{Pn1|+R>-G2co$r9IylHmNblJdl&R0hYC{G?O` z&)mfH)S%SFl*+=BsWw1Gr#xL8Ln>}1{rLaio>`S)$^6a+sZs?yo~0jWw=mCO{HQ%a zNTH7VY4Y{{!vg9G|9DIp+U%W=b{eV3bkr}BWH@ZU@KXivNtQ?U0lW(~+~7;iZ~ye) z`KfWCg#rTg?w_BPulNyT@|8y?gKKx= z4j%uMf2@y06zbZwyJl|8aQen)mC*Jwo#m4Jf+nT_shR(|J0cr@m|yuBan;B$fLY*# s^^ZNyCHEA$c;uWVRs_ytV3A;WBb~WS=&ku-G2co$r9IylHmNblJdl&R0hYC{G?O` z&)mfH)S%SFl*+=BsWw1Gn><|{Ln>}1{rLaio>`S)$^6a+sZs?yo~0jWw=mCO{HQ%a zNTH7VY4Y{{!vg9G|9DIp+U%W=b{eV3bkr}BWH@ZU@KXivNtQ?U0lW(~+~7;iZ~ye) z`KfWCg#rTg?w_BPulNyT@|8y?gKKx= z4j%uMf2@y06zbZwyJl|8aQen)m2m9Y-2EzQVLPhS*t8k~ojpz;b$QLsVZiXiBep=- SlsgpYdInEdKbLh*2~7Y%?_?nW literal 0 HcmV?d00001 diff --git a/resources/menuicon.psd b/resources/menuicon.psd new file mode 100644 index 0000000000000000000000000000000000000000..ba337c4f234bcbf3a47968072838e13a51d6ba64 GIT binary patch literal 29584 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 IdT&Ml0e~pL&Hw-a literal 0 HcmV?d00001 diff --git a/setup.py b/setup.py index 97f78bf..1cf7b35 100644 --- a/setup.py +++ b/setup.py @@ -4,6 +4,10 @@ import py2app, sys, os, commands setup( app = [ 'ToggleProxy.py' ], + data_files = [ + 'resources/active.png', + 'resources/inactive.png' + ], options = dict(py2app = dict( plist = dict( LSBackgroundOnly = True