Skip to content
Snippets Groups Projects
Commit 8cc708ad authored by Yann Leboulanger's avatar Yann Leboulanger
Browse files

new snarl notification plugin

parent b224467c
No related branches found
No related tags found
No related merge requests found
from plugin import SnarlNotificationsPlugin
[info]
name: Snarl Notifications
short_name: snarl_notifications
version: 0.1
description: Shows events notification using Snarl (http://www.fullphat.net/) under Windows. Snarl needs to be installed in system.
PySnarl bindings are used (http://sourceforge.net/projects/pysnarl/).
authors = Yann Leboulanger <asterix@lagaule.org>
homepage = http://trac-plugins.gajim.org/wiki/SnarlNotificationsPlugin
# -*- coding: utf-8 -*-
##
## This file is part of Gajim.
##
## Gajim is free software; you can redistribute it and/or modify
## it under the terms of the GNU General Public License as published
## by the Free Software Foundation; version 3 only.
##
## Gajim is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
## GNU General Public License for more details.
##
## You should have received a copy of the GNU General Public License
## along with Gajim. If not, see <http://www.gnu.org/licenses/>.
##
'''
Events notifications using Snarl
Fancy events notifications under Windows using Snarl infrastructure.
:note: plugin is at proof-of-concept state.
:author: Yann Leboulanger <asterix@lagaule.org>
:since: 08 April 2012
:copyright: Copyright (2012) Yann Leboulanger <asterix@lagaule.org>
:license: GPL
'''
import pySnarl
from common import gajim
from plugins import GajimPlugin
from plugins.helpers import log_calls, log
from common import ged
import os.path
class SnarlActionHandler(pySnarl.EventHandler):
def OnNotificationInvoked(self, uid):
account, jid, msg_type = uid.split()
gajim.interface.handle_event(account, jid, msg_type)
class SnarlNotificationsPlugin(GajimPlugin):
@log_calls('SnarlNotificationsPlugin')
def init(self):
self.description = _('Shows events notification using Snarl '
'(http://www.fullphat.net/) under Windows. '
'Snarl needs to be installed in system.\n'
'PySnarl bindings are used (http://code.google.com/p/pysnarl/).')
self.config_dialog = None
self.h = SnarlActionHandler
self.snarl_win = pySnarl.SnarlApp(
"pySnarl/Gajim", # app signature
"Gajim", # app title
os.path.abspath("..\data\pixmaps\gajim.ico"), # icon
"", # config Tool
"Gajim will use Snarl to display notifications", # hint
False, # IsDaemon
self.h, # event handler
[] # classes
)
self.events_handlers = {'notification' : (ged.PRECORE, self.notif)}
@log_calls('SnarlNotificationsPlugin')
def notif(self, obj):
if obj.do_popup:
uid = obj.conn.name + " " + obj.jid + " " + obj.popup_msg_type
self.snarl_win.notify(
[], # actions
"", # callbackScript
"", # callbackScriptType
"", # class
"", # defaultCallback
5, # duration
os.path.abspath(obj.popup_image),#r"C:\Documents and Settings\Administrateur\Mes documents\gajim\data\pixmaps\gajim.ico", # icon
"", # mergeUID
0, # priority
"", # replaceUID
obj.popup_text,
obj.popup_title,
uid, # UID
"", # sound
-1, # percent
0, # log
64, # sensitivity
)
obj.do_popup = False
# -*- coding: utf-8 -*-
# ActiveX/COM Snarl python library
# For proper functioning requires Snarl 2.5.1 or later !
# Version 0.0.2
# Changelog (in reverse chronological order):
# -------------------------------------------
# 0.0.2 by Pako 2012-01-30 14:12 UTC+1
# - base64 icon format is now supported
# 0.0.1 by Pako 2012-01-06 15:30 UTC+1
# - initial version
#-------------------------------------------------------
from win32com.client import constants, gencache, Dispatch, DispatchWithEvents
#===============================================================================
def IsRunning():
from win32gui import FindWindow
return FindWindow("w>Snarl", "Snarl")
#===============================================================================
class EventHandler:
def OnActivated(self):
self.fn("DaemonActivated")
def OnNotificationActionSelected(self, uid, command):
self.fn("ActionSelected.%s" % command, payload = uid)
def OnNotificationClosed(self, uid):
self.fn("Closed", payload = uid)
def OnNotificationExpired(self, uid):
self.fn("Expired", payload = uid)
def OnNotificationInvoked(self, uid):
self.fn("Invoked", payload = uid)
def OnQuit(self):
self.fn("AppQuit")
def OnShowAbout(self):
self.fn("ShowAbout")
def OnShowConfig(self):
self.fn("ShowConfig")
def OnSnarlLaunched(self):
self.fn("Launched")
def OnSnarlQuit(self):
self.fn("Quit")
def OnSnarlStarted(self):
self.fn("Started")
def OnSnarlStopped(self):
self.fn("Stopped")
def OnUserAway(self):
self.fn("UserAway")
def OnUserReturned(self):
self.fn("UserReturned")
#===============================================================================
class SnarlApp(object):
"""Creates an SnarlApp object"""
def __init__(
self,
signature,
title,
icon = "",
configTool = "",
hint = "",
isDaemon = False,
eventHandler = None,
classes = []
):
self.app = gencache.EnsureDispatch("libsnarl25.SnarlApp")
for d in constants.__dicts__: # we must find the right dictionary ...
if 'ERROR_NOTIFICATION_NOT_FOUND' in d: # this is it !
break
codes = d.items()
codes.sort(reverse = True)
self.statCodes = dict([[v,k] for k,v in codes[6:]])
self.statCodes[codes[2][1]] = codes[2][0] # added SUCCESS
self.classes = NotifClasses(classes)
if eventHandler:
self.SetEventHandler(eventHandler)
self.SetTo(
configTool,
hint,
icon,
isDaemon,
signature,
title
)
def SetTo(
self,
configTool,
hint,
icon,
isDaemon,
signature,
title
):
self.app.Classes = self.classes.Classes()
self.app.ConfigTool = configTool
self.app.Hint = hint
self.app.Icon = icon
self.app.IsDaemon = isDaemon
self.app.Signature = signature
self.app.Title = title
def GetStatusCode(self, code):
return self.statCodes[code]
def SetEventHandler(self, handler):
self.events = DispatchWithEvents(self.app, handler)
def register(self):
return self.GetStatusCode(self.app.Register())
def unregister(self):
return self.GetStatusCode(self.app.Unregister())
def tidyUp(self):
self.app.TidyUp()
def addClass(
self,
classId,
name,
enabled = True,
title = "",
text = "",
icon = "",
callback = "",
duration = -1,
sound = "",
):
cntOld = self.classes.count()
cntNew = self.classes.add(classId, name, enabled, title, text, icon, callback, duration, sound)
return int(not cntNew == cntOld + 1)
def remClass(self, id):
cntOld = self.classes.count()
cntNew = self.classes.remove(id)
return int(not cntNew == cntOld - 1)
def clearClasses(self):
return self.classes.makeEmpty()
def classesCount(self):
return self.classes.count()
def notify(
self,
actions,
callbackScript,
callbackScriptType,
cls,
defaultCallback,
duration,
icon,
mergeUID,
priority,
replaceUID,
text,
title,
uid,
sound = None,
percent = None,
log = None,
sensitivity = None
):
note = Notification(
actions,
callbackScript,
callbackScriptType,
cls,
defaultCallback,
duration,
"",
mergeUID,
priority,
replaceUID,
text,
title,
uid,
)
if icon:
if icon[1] == ":":
note.Add("icon", icon, True)
else:
note.Add("icon-base64", icon.replace("=","%"), True)
if sound:
note.Add("sound", sound, True)
if percent is not None and percent > -1:
note.Add("value-percent", str(percent), True)
if log is not None:
note.Add("log", str(log), True)
if sensitivity is not None:
note.Add("sensitivity", str(sensitivity), True)
return self.GetStatusCode(self.app.Show(note.Note())[0])
def hideNotification(self, uid):
return self.GetStatusCode(self.app.Hide(uid))
def isVisible(self, uid):
return self.GetStatusCode(self.app.IsVisible(uid))
def getEtcPath(self):
return self.app.GetEtcPath()
def makePath(self, pth):
return self.app.GetEtcPath(pth)
def isInstalled(self):
return self.app.IsSnarlInstalled()
def isRunning(self):
return self.app.IsSnarlRunning()
def version(self):
ver = self.app.SnarlVersion()
return ver if ver > 0 else self.GetStatusCode(-ver)
def isConnected(self):
return self.app.IsConnected
def getLibVersion(self):
return self.app.LibVersion
def getLibRevision(self):
return self.app.LibRevision
def Destroy(self):
self.app.TidyUp()
if self.events:
del self.events
del self.app
#===============================================================================
class NotifClasses(object):
def __init__(self, classes = []):
self.clss = Dispatch("libsnarl25.Classes")
for cls in classes:
self.add(*cls)
def count(self):
return self.clss.Count()
def add(self, *cls):
self.clss.Add(*cls)
return self.clss.Count()
def remove(self, cls):
self.clss.Remove(cls)
return self.clss.Count()
def makeEmpty(self):
self.clss.MakeEmpty()
return self.clss.Count()
def Classes(self):
return self.clss
#===============================================================================
class Notification(object):
def __init__(
self,
actions,
callbackScript,
callbackScriptType,
cls,
defaultCallback,
duration,
icon,
mergeUID,
priority,
replaceUID,
text,
title,
uid,
):
nt = Dispatch("libsnarl25.Notification")
nt.Actions = NotifActions(actions).Actions()
nt.CallbackScript = callbackScript
nt.CallbackScriptType = callbackScriptType
nt.Class = cls
nt.DefaultCallback = defaultCallback
nt.Duration = duration
if icon:
nt.Icon = icon
nt.MergeUID = mergeUID
nt.Priority = priority
nt.ReplaceUID = replaceUID
nt.Text = text
nt.Title = title
nt.UID = uid
self.nt = nt
def Add(self, name, value, update):
self.nt.Add(name, value, True)
def Note(self):
return self.nt
#===============================================================================
class NotifActions(object):
def __init__(self, actions=[]):
self.actns = Dispatch("libsnarl25.Actions")
self.actions = actions
for action in actions:
self.actns.Add(*action)
def add(self, actn):
self.actns.Add(*actn)
self.actions.append(actn)
return self.actns.Count()
def remove(self, actn):
if actn in self.actions:
ix = self.actions.index(actn)
self.actns.Remove(ix + 1)
self.actions.pop(ix)
return self.actns.Count()
def makeEmpty(self):
self.actns.MakeEmpty()
self.actions = []
return self.actns.Count()
def Actions(self):
return self.actns
#===============================================================================
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment