2010-06-27 4 views
5

Я пытаюсь использовать привязки Growl Python (Growl.py v0.7 из репозитория Growl), чтобы написать небольшое приложение. Одна из функций, которые в настоящее время отсутствуют, - это уведомление кликов, отправленное на Python.Выращивание Python с обратной связью Click?

Я знаю в Objective-C, когда пользователь нажимает уведомление, он отправит триггер запущенному приложению. Я бы хотел сделать аналогичную вещь с привязками Python. Когда пользователь нажимает на уведомление, я хотел бы, чтобы программа Python открывала URL-адрес в браузере (или обрабатывала событие другим способом).

Любые мысли о том, как я могу это осуществить?

Обновление: благодаря synhesizerpatel, который предоставляет многообещающее решение, и я беру его слова, которые он работал на Lion. К сожалению, я начинаю исчезать с Mac, поэтому я больше не занимаюсь программированием Mac. Хотя, я сделал некоторые отладки, как это до сих пор не работает на Snow Leopard, и вот почему:

Discussion Growl PyObjC not working with PyObjC 2.2b3

Source code

+0

Любые удачи здесь? Я тоже хотел бы знать. –

+0

Это еще открытый вопрос ~ – Patrick

+0

Вы ищете это, чтобы поймать все уведомления о рыке или просто приложение python, которое имеет возможность отправлять уведомления о рыскании, и чтобы он мог поймать щелчок мыши, когда пользователь его уволит? – synthesizerpatel

ответ

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

+0

Если в этом случае у вас должно быть меньше проблем. : D Но как бы то ни было, это именно то, что вы ищете. Мне было бы интересно узнать, какие сообщения об ошибках вы получаете. – synthesizerpatel

+0

Да, я должен был предоставить более подробно ... Сценарий казался многообещающим, как то, что я хочу. После запуска программы она создала меню состояния с двумя параметрами. Хотя после того, как я нажал «Отправить Grr!», Я получил сообщение на консоли с сообщением «Отправка уведомления о рывке ...» без фактического уведомления Growl. – Patrick