2010-06-27 97 views
5

我正在嘗試使用Growl Python綁定(來自Growl存儲庫的Growl.py v0.7)來編寫一個小應用程序。目前缺少的功能之一是發送給Python的點擊通知。咆哮Python綁定點擊反饋?

我知道在Objective-C中,當用戶點擊通知時,它會向正在運行的應用程序發送一個觸發器。我想用Python綁定來做類似的事情。當用戶點擊通知時,我想讓Python程序在瀏覽器中打開一個URL(或以其他方式處理事件)。

關於我如何實現它的任何想法?

更新:感謝synthesizerpatel誰提供了一個有前途的解決方案,我把他的話在獅子工作。不幸的是,我開始淡出Mac,所以我不再做Mac編程了。雖然,我做了一些調試,因爲它仍然不是雪豹工作,並在這裏就是爲什麼:

Discussion Growl PyObjC not working with PyObjC 2.2b3

Source code

+0

這裏有什麼運氣?我也很想知道。 – 2011-02-21 16:15:36

+0

這仍然是一個懸而未決的問題〜 – Patrick 2011-11-01 07:50:52

+0

您是否在尋找這個來捕獲所有咆哮通知或者只是一個能夠發送咆哮通知並且能夠在用戶解散它時捕捉鼠標點擊的Python應用程序? – synthesizerpatel 2012-02-07 04:50:50

回答

1

這是你想要的嗎?

#!/usr/bin/env python 
# 
# pyGrr! 
# 
# This code was originally found @ 
# http://www.cocoaforge.com/viewtopic.php?f=6&t=13359&p=91992&hilit=pyobjc+growl 
# It is (to the best of our knowledge) the work of user 'tooru' on the same 
# website. 
# 
# I make no claim to this code, all I did was get it working with PyObjC on Lion 
# reformatted it a bit and added some more verbose explanations of what the script 
# does. To be honest, I haven't touched pyobjc in a couple years and I was amazed 
# that it still works! Even more amazed that I was able to get this example working 
# in about 20 minutes. 
# 
# Great job tooru! 
# 
# I have verified this code works with the following combination of 
# packages/versions 
# 
# * OSX Lion 10.7.3 
# * Python 2.7 
# * Growl 1.3 
# * Growl SDK 1.3.1 
# 
# 
# - Nathan Ramella [email protected] (http://www.remix.net) 
################################################################################## 

import objc 
from Foundation import * 
from AppKit import * 
from PyObjCTools import AppHelper 
import time 
import sys 
import os 

myGrowlBundle = objc.loadBundle(
    "GrowlApplicationBridge", 
    globals(), 
    bundle_path = objc.pathForFramework(
    '/Library/Frameworks/Growl.framework' 
) 
) 

class MenuMakerDelegate(NSObject): 

    """ 
    This is a delegate for Growl, a required element of using the Growl 
    service. 

    There isn't a requirement that delegates actually 'do' anything, but 
    in this case, it does. We'll make a little menu up on the status bar 
    which will be named 'pyGrr!' 

    Inside the menu will be two options, 'Send a Grr!', and 'Quit'. 

    Send a Grr! will emit a growl notification that when clicked calls back 
    to the Python code so you can take some sort of action - if you're that 
    type of person. 
    """ 

    statusbar = None 
    state = 'idle' 

    def applicationDidFinishLaunching_(self, notification): 

    """ 
    Setup the menu and our menu items. Getting excited yet? 
    """ 

    statusbar = NSStatusBar.systemStatusBar() 
    # Create the statusbar item 
    self.statusitem = statusbar.statusItemWithLength_(NSVariableStatusItemLength) 

    self.statusitem.setHighlightMode_(1) # Let it highlight upon clicking 
    self.statusitem.setToolTip_('pyGrr!') # Set a tooltip 
    self.statusitem.setTitle_('pyGrr!') # Set an initial title 

    # Build a very simple menu 
    self.menu = NSMenu.alloc().init() 
    menuitem = NSMenuItem.alloc().initWithTitle_action_keyEquivalent_(
     'Send a Grr!', 
     'rcNotification:', 
     '' 
    ) 
    self.menu.addItem_(menuitem) 

    # Default event 
    menuitem = NSMenuItem.alloc().initWithTitle_action_keyEquivalent_(
     'Quit', 
     'terminate:', 
     '' 
    ) 
    self.menu.addItem_(menuitem) 

    # Bind it to the status item 
    self.statusitem.setMenu_(self.menu) 

    def rcNotification_(self,notification): 

    """ 
    This is run when you select the 'Send a Grr!' menu item. It 
    will lovingly bundle up a Grr and send it Growl's way. 
    """ 

    print "Sending a growl notification at", time.time() 

    GrowlApplicationBridge.notifyWithTitle_description_notificationName_iconData_priority_isSticky_clickContext_(
     "Grr! - I'm a title!", 
     "This is where you put notification information.", 
     "test1", 
     None, 
     0, 
     False, 
     "this ends up being the argument to your context callback" 
    ) 

class rcGrowl(NSObject): 

    """ 
    rcGrowl registers us with Growl to send out Grrs on behalf 
    of the user and do 'something' with the results when a 
    Grr has been clicked. 

    For additional information on what the what is going on 
    please refer to the growl dox @ 

    http://growl.info/documentation/developer/implementing-growl.php 
    """ 

    def rcSetDelegate(self): 
    GrowlApplicationBridge.setGrowlDelegate_(self) 

    def registrationDictionaryForGrowl(self): 

    """ 
    http://growl.info/documentation/developer/implementing-growl.php#registration 
    """ 

    return { 
     u'ApplicationName' : 'rcGrowlMacTidy', 
     u'AllNotifications' : ['test1'], 
     u'DefaultNotifications' : ['test1'], 
     u'NotificationIcon' : None, 
    } 

    # don't know if it is working or not 
    def applicationNameForGrowl(self): 
    """ 
    Identifies the application. 
    """ 
    return 'rcGrowlMacTidy' 

    #def applicationIconDataForGrowl(self): 
    """ 
    If you wish to include a custom icon with the Grr, 
    you can do so here. Disabled by default since I didn't 
    want to bloat up this up 
    """ 
    #icon = NSImage.alloc().init() 
    #icon = icon.initWithContentsOfFile_(u'remix_icon.tiff') 
    #return icon 

    def growlNotificationWasClicked_(self, ctx): 

    """ 
    callback for onClick event 
    """ 
    print "we got a click! " + str(time.time()) + " >>> " + str(ctx) + " <<<\n" 

    def growlNotificationTimedOut_(self, ctx): 

    """ 
    callback for timing out 
    """ 
    print "We timed out" + str(ctx) + "\n" 

    def growlIsReady(self): 

    """ 
    Informs the delegate that GrowlHelperApp was launched 
    successfully. Presumably if it's already running it 
    won't need to run it again? 
    """ 
    print "growl IS READY" 


if __name__ == "__main__": 

    # Both 'growlnotify' and this script seem to have the following 
    # error after emitting a Grr! 
    # 
    # Error Domain=GCDAsyncSocketErrorDomain Code=4 "Read operation timed out" 
    # UserInfo=0x7fa444e00070 {NSLocalizedDescription=Read operation timed out} 
    # 
    # So, we redirect stderr to /dev/null so that it doesn't muck up 
    # the output of this script. Some folks say upgrading Growl fixes it, 
    # others still have the problem. Doesn't seem to make much of a difference 
    # one way or another, things still seem to work regardless. 

    fp = os.open('/dev/null', os.O_RDWR|os.O_CREAT, 0o666) 
    dupped = os.dup(2) 
    os.dup2(fp, 2) 

    # set up system statusbar GUI 
    app = NSApplication.sharedApplication() 
    delegate = MenuMakerDelegate.alloc().init() 
    app.setDelegate_(delegate) 

    # set up growl delegate 
    rcGrowlDelegate=rcGrowl.new() 
    rcGrowlDelegate.rcSetDelegate() 
    AppHelper.runEventLoop() 
+0

嗨,感謝您的腳本。不幸的是,它沒有爲我工作,因爲我有雪豹與咆哮1.2.2 – Patrick 2012-02-08 02:52:05

+0

如果有什麼你應該有較少的問題,在這種情況下。 :D但是,事實確實如此,這正是你要找的。我很想知道你收到了什麼錯誤信息。 – synthesizerpatel 2012-02-08 07:04:20

+0

是的,我應該提供更多的細節......腳本聽起來很有希望,因爲我想要的。運行程序後,它創建了兩個選項的狀態菜單。儘管在點擊「Send a Grr!」之後,我只在控制檯中收到一條消息,內容是「發送咆哮通知......」,沒有實際的Growl通知。 – Patrick 2012-02-08 08:12:12