Checkpoint:
* Custom notification providers working for email. * Configuration through the GtkUI working.
This commit is contained in:
parent
8a6ec7232d
commit
1b7a50f88b
|
@ -17,9 +17,9 @@
|
|||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with deluge. If not, write to:
|
||||
# The Free Software Foundation, Inc.,
|
||||
# 51 Franklin Street, Fifth Floor
|
||||
# Boston, MA 02110-1301, USA.
|
||||
# The Free Software Foundation, Inc.,
|
||||
# 51 Franklin Street, Fifth Floor
|
||||
# Boston, MA 02110-1301, USA.
|
||||
#
|
||||
# In addition, as a special exception, the copyright holders give
|
||||
# permission to link the code of portions of this program with the OpenSSL
|
||||
|
@ -41,15 +41,15 @@ and subsequently emitted to the clients.
|
|||
|
||||
"""
|
||||
|
||||
event_list = []
|
||||
known_events = {}
|
||||
|
||||
class DelugeEventMetaClass(type):
|
||||
"""
|
||||
This metaclass simply keeps a list of all events classes created.
|
||||
"""
|
||||
def __init__(cls, name, bases, dct):
|
||||
event_list.append(name)
|
||||
super(DelugeEventMetaClass, cls).__init__(name, bases, dct)
|
||||
known_events[name] = cls
|
||||
|
||||
class DelugeEvent(object):
|
||||
"""
|
||||
|
|
|
@ -22,9 +22,9 @@
|
|||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with deluge. If not, write to:
|
||||
# The Free Software Foundation, Inc.,
|
||||
# 51 Franklin Street, Fifth Floor
|
||||
# Boston, MA 02110-1301, USA.
|
||||
# The Free Software Foundation, Inc.,
|
||||
# 51 Franklin Street, Fifth Floor
|
||||
# Boston, MA 02110-1301, USA.
|
||||
#
|
||||
# In addition, as a special exception, the copyright holders give
|
||||
# permission to link the code of portions of this program with the OpenSSL
|
||||
|
@ -39,4 +39,35 @@
|
|||
|
||||
def get_resource(filename):
|
||||
import pkg_resources, os
|
||||
return pkg_resources.resource_filename("notifications", os.path.join("data", filename))
|
||||
return pkg_resources.resource_filename("notifications",
|
||||
os.path.join("data", filename))
|
||||
|
||||
DEFAULT_PREFS = {
|
||||
# Core -------------------------------------------------------------------------
|
||||
"smtp_enabled": False,
|
||||
"smtp_host": "",
|
||||
"smtp_port": 25,
|
||||
"smtp_user": "",
|
||||
"smtp_pass": "",
|
||||
"smtp_from": "",
|
||||
"smtp_tls": False, # SSL or TLS
|
||||
"smtp_recipients": [],
|
||||
# GTK UI -----------------------------------------------------------------------
|
||||
# BLINK
|
||||
"blink_enabled": False,
|
||||
# FLASH
|
||||
"flash_enabled": False,
|
||||
# POPUP
|
||||
"popup_enabled": False,
|
||||
# SOUND
|
||||
"sound_enabled": False,
|
||||
"sound_path": "",
|
||||
# Subscriptions ----------------------------------------------------------------
|
||||
"subscriptions": {
|
||||
"popup": [],
|
||||
"blink": [],
|
||||
"sound": [],
|
||||
"email": [],
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -39,20 +39,16 @@
|
|||
|
||||
import smtplib
|
||||
from twisted.internet import defer, threads
|
||||
from deluge.event import known_events, DelugeEvent
|
||||
from deluge.log import LOG as log
|
||||
from deluge.plugins.pluginbase import CorePluginBase
|
||||
import deluge.component as component
|
||||
import deluge.configmanager
|
||||
from deluge.core.rpcserver import export
|
||||
|
||||
# Relative imports
|
||||
from manager import Notifications
|
||||
import events
|
||||
from test import TestEmailNotifications
|
||||
|
||||
DEFAULT_PREFS = {
|
||||
# BLINK
|
||||
"blink_enabled": False,
|
||||
# EMAIL
|
||||
"smtp_enabled": False,
|
||||
"smtp_host": "",
|
||||
"smtp_port": 25,
|
||||
|
@ -61,29 +57,36 @@ DEFAULT_PREFS = {
|
|||
"smtp_from": "",
|
||||
"smtp_tls": False, # SSL or TLS
|
||||
"smtp_recipients": [],
|
||||
# FLASH
|
||||
"flash_enabled": False,
|
||||
# POPUP
|
||||
"popup_enabled": False,
|
||||
# SOUND
|
||||
"sound_enabled": False,
|
||||
"sound_path": ""
|
||||
# Subscriptions
|
||||
"subscriptions": {
|
||||
"email": []
|
||||
}
|
||||
}
|
||||
|
||||
class Core(CorePluginBase, component.Component):
|
||||
def __init__(self, plugin_name):
|
||||
CorePluginBase.__init__(self, plugin_name)
|
||||
component.Component.__init__(self, "Notifications")
|
||||
self.email_message_providers = {}
|
||||
self.tn = TestEmailNotifications()
|
||||
|
||||
class Core(CorePluginBase, Notifications):
|
||||
def enable(self):
|
||||
Notifications.enable(self)
|
||||
self.config = deluge.configmanager.ConfigManager("notifications.conf",
|
||||
DEFAULT_PREFS)
|
||||
self.config = deluge.configmanager.ConfigManager(
|
||||
"notifications-core.conf", DEFAULT_PREFS)
|
||||
component.get("EventManager").register_event_handler(
|
||||
"TorrentFinishedEvent", self._on_torrent_finished_event
|
||||
)
|
||||
log.debug("\n\nENABLING CORE NOTIFICATIONS\n\n")
|
||||
self.tn.enable()
|
||||
# import sys
|
||||
# print '\n\n', [(n, k.__module__) for n, k in known_events.items()]
|
||||
# print [f for f in sys.modules.keys() if f.startswith("deluge.event")]
|
||||
|
||||
def disable(self):
|
||||
Notifications.disable(self)
|
||||
self.tn.disable()
|
||||
log.debug("\n\nDISABLING CORE NOTIFICATIONS\n\n")
|
||||
for eventtype in self.email_message_providers.keys():
|
||||
self.deregister_email_message_provider(eventtype)
|
||||
|
||||
def update(self):
|
||||
pass
|
||||
|
@ -100,65 +103,87 @@ class Core(CorePluginBase, Notifications):
|
|||
"returns the config dictionary"
|
||||
return self.config.config
|
||||
|
||||
# Notification methods
|
||||
@export
|
||||
def notify_blink(self):
|
||||
if not self.config["blink_enabled"]:
|
||||
return defer.succeed("Blink notification not enabled")
|
||||
return defer.maybeDeferred(
|
||||
component.get("EventManager").emit, events.NotificationBlinkEvent())
|
||||
def get_handled_events(self):
|
||||
handled_events = []
|
||||
for evt in sorted(known_events.keys()):
|
||||
if known_events[evt].__module__.startswith('deluge.event'):
|
||||
if evt not in ('TorrentFinishedEvent',):
|
||||
# Skip the base class for all events
|
||||
continue
|
||||
classdoc = known_events[evt].__doc__.strip()
|
||||
handled_events.append((evt, classdoc))
|
||||
log.debug("Handled Notification Events: %s", handled_events)
|
||||
return handled_events
|
||||
|
||||
@export
|
||||
def notify_email(self, title='', message='', smtp_from='', recipients=[]):
|
||||
def register_email_message_provider(self, eventtype, handler):
|
||||
"""This is used to register email formatters for custom event types.
|
||||
|
||||
:param event: str, the event name
|
||||
:param handler: function, to be called when `:param:event` is emitted
|
||||
|
||||
You're handler should return a tuple of (subject, email_contents).
|
||||
"""
|
||||
if eventtype not in known_events:
|
||||
raise Exception("The event \"%s\" is not known" % eventtype)
|
||||
if known_events[eventtype].__module__.startswith('deluge.event'):
|
||||
raise Exception("You cannot register email message providers for "
|
||||
"built-in event types.")
|
||||
if eventtype not in self.email_message_providers:
|
||||
def wrapper(*args, **kwargs):
|
||||
return self._handle_custom_email_message_providers(eventtype,
|
||||
*args,
|
||||
**kwargs)
|
||||
self.email_message_providers[eventtype] = (wrapper, handler)
|
||||
else:
|
||||
wrapper, handler = self.email_message_providers[eventtype]
|
||||
component.get("EventManager").register_event_handler(
|
||||
eventtype, wrapper
|
||||
)
|
||||
|
||||
def deregister_email_message_provider(self, eventtype):
|
||||
wrapper, handler = self.email_message_providers[eventtype]
|
||||
component.get("EventManager").deregister_event_handler(
|
||||
eventtype, wrapper
|
||||
)
|
||||
self.email_message_providers.pop(eventtype)
|
||||
|
||||
def _handle_custom_email_message_providers(self, event, *args, **kwargs):
|
||||
if not self.config['smtp_enabled']:
|
||||
return defer.succeed("SMTP notification not enabled")
|
||||
d = threads.deferToThread(self._notify_email, title, message, smtp_from,
|
||||
recipients)
|
||||
d.addCallback(self._on_notify_sucess, 'email')
|
||||
d.addErrback(self._on_notify_failure, 'email')
|
||||
return d
|
||||
return defer.succeed("SMTP notification not enabled.")
|
||||
|
||||
@export
|
||||
def notify_flash(self, title='', message=''):
|
||||
if not self.config["flash_enabled"]:
|
||||
return defer.succeed("Flash notification not enabled")
|
||||
d = defer.maybeDeferred(component.get("EventManager").emit,
|
||||
events.NotificationFlashEvent(title, message))
|
||||
d.addCallback(self._on_notify_event_sucess, 'flash')
|
||||
d.addErrback(self._on_notify_event_failure, 'flash')
|
||||
return d
|
||||
log.debug("\n\nCalling CORE's custom email providers for %s: %s %s",
|
||||
event, args, kwargs)
|
||||
if event in self.config["subscriptions"]["email"]:
|
||||
wrapper, handler = self.email_message_providers[event]
|
||||
log.debug("Found handler: %s", handler)
|
||||
d = defer.maybeDeferred(handler, *args, **kwargs)
|
||||
d.addCallback(self._prepare_email)
|
||||
d.addCallback(self._on_notify_sucess)
|
||||
d.addErrback(self._on_notify_failure)
|
||||
return d
|
||||
|
||||
@export
|
||||
def notify_popup(self, title='', message=''):
|
||||
if not self.config["popup_enabled"]:
|
||||
return defer.succeed("Popup notification not enabled")
|
||||
d = defer.maybeDeferred(component.get("EventManager").emit,
|
||||
events.NotificationPopupEvent(title, message))
|
||||
d.addCallback(self._on_notify_event_sucess, 'popup')
|
||||
d.addErrback(self._on_notify_event_failure, 'popup')
|
||||
return d
|
||||
|
||||
@export
|
||||
def notify_sound(self, sound_path=''):
|
||||
if not self.config["sound_enabled"]:
|
||||
return defer.succeed("Sound notification not enabled")
|
||||
d = defer.maybeDeferred(component.get("EventManager").emit,
|
||||
events.NotificationSoundEvent(sound_path))
|
||||
d.addCallback(self._on_notify_event_sucess, 'sound')
|
||||
d.addErrback(self._on_notify_event_failure, 'sound')
|
||||
return d
|
||||
def _prepare_email(self, result):
|
||||
if not self.config['smtp_enabled']:
|
||||
return defer.succeed("SMTP notification not enabled.")
|
||||
subject, message = result
|
||||
log.debug("\n\nSending email with subject: %s: %s", subject, message)
|
||||
return threads.deferToThread(self._notify_email, subject, message)
|
||||
|
||||
def _notify_email(self, title='', message='', smtp_from='', recipients=[]):
|
||||
|
||||
def _notify_email(self, subject='', message=''):
|
||||
log.debug("Email prepared")
|
||||
config = self.config
|
||||
to_addrs = '; '.join(config['smtp_recipients']+recipients)
|
||||
to_addrs = '; '.join(config['smtp_recipients'])
|
||||
headers = """\
|
||||
From: %(smtp_from)s
|
||||
To: %(smtp_recipients)s
|
||||
Subject: %(title)s
|
||||
Subject: %(subject)s
|
||||
|
||||
|
||||
""" % {'smtp_from': smtp_from and smtp_from or config['smtp_from'],
|
||||
'title': title,
|
||||
""" % {'smtp_from': config['smtp_from'],
|
||||
'subject': subject,
|
||||
'smtp_recipients': to_addrs}
|
||||
|
||||
message = '\r\n'.join((headers + message).splitlines())
|
||||
|
@ -169,7 +194,7 @@ Subject: %(title)s
|
|||
err_msg = _("There was an error sending the notification email:"
|
||||
" %s") % err
|
||||
log.error(err_msg)
|
||||
raise err
|
||||
return err
|
||||
|
||||
security_enabled = config['smtp_tls']
|
||||
|
||||
|
@ -188,12 +213,12 @@ Subject: %(title)s
|
|||
err_msg = _("The server didn't reply properly to the helo "
|
||||
"greeting: %s") % err
|
||||
log.error(err_msg)
|
||||
raise err
|
||||
return err
|
||||
except smtplib.SMTPAuthenticationError, err:
|
||||
err_msg = _("The server didn't accept the username/password "
|
||||
"combination: %s") % err
|
||||
log.error(err_msg)
|
||||
raise err
|
||||
return err
|
||||
|
||||
try:
|
||||
try:
|
||||
|
@ -202,7 +227,7 @@ Subject: %(title)s
|
|||
err_msg = _("There was an error sending the notification email:"
|
||||
" %s") % err
|
||||
log.error(err_msg)
|
||||
raise err
|
||||
return err
|
||||
finally:
|
||||
if security_enabled:
|
||||
# avoid false failure detection when the server closes
|
||||
|
@ -216,12 +241,13 @@ Subject: %(title)s
|
|||
server.quit()
|
||||
return _("Notification email sent.")
|
||||
|
||||
|
||||
def _on_torrent_finished_event(self, torrent_id):
|
||||
log.debug("\n\nhandler for TorrentFinishedEvent called for CORE")
|
||||
log.debug("\n\nHandler for TorrentFinishedEvent called for CORE")
|
||||
torrent = component.get("TorrentManager")[torrent_id]
|
||||
torrent_status = torrent.get_status({})
|
||||
# Email
|
||||
title = _("Finished Torrent \"%(name)s\"") % torrent_status
|
||||
subject = _("Finished Torrent \"%(name)s\"") % torrent_status
|
||||
message = _(
|
||||
"This email is to inform you that Deluge has finished "
|
||||
"downloading \"%(name)s\", which includes %(num_files)i files."
|
||||
|
@ -230,7 +256,17 @@ Subject: %(title)s
|
|||
"Thank you,\nDeluge."
|
||||
) % torrent_status
|
||||
|
||||
d = defer.maybeDeferred(self.notify_email, title, message)
|
||||
d.addCallback(self._on_notify_sucess, 'email')
|
||||
d.addErrback(self._on_notify_failure, 'email')
|
||||
log.debug("Email notification callback yielded")
|
||||
d = defer.maybeDeferred(self._prepare_email, [subject, message])
|
||||
d.addCallback(self._on_notify_sucess)
|
||||
d.addErrback(self._on_notify_failure)
|
||||
return d
|
||||
|
||||
|
||||
def _on_notify_sucess(self, result):
|
||||
log.debug("\n\nEMAIL Notification success: %s", result)
|
||||
return result
|
||||
|
||||
|
||||
def _on_notify_failure(self, failure):
|
||||
log.debug("\n\nEMAIL Notification failure: %s", failure)
|
||||
return failure
|
||||
|
|
|
@ -8,390 +8,537 @@
|
|||
<property name="visible">True</property>
|
||||
<property name="orientation">vertical</property>
|
||||
<child>
|
||||
<widget class="GtkFrame" id="frame2">
|
||||
<widget class="GtkViewport" id="viewport1">
|
||||
<property name="visible">True</property>
|
||||
<property name="label_xalign">0</property>
|
||||
<property name="shadow_type">none</property>
|
||||
<property name="resize_mode">queue</property>
|
||||
<child>
|
||||
<widget class="GtkAlignment" id="alignment2">
|
||||
<widget class="GtkVBox" id="vbox4">
|
||||
<property name="visible">True</property>
|
||||
<property name="left_padding">12</property>
|
||||
<property name="orientation">vertical</property>
|
||||
<child>
|
||||
<widget class="GtkVBox" id="vbox1">
|
||||
<widget class="GtkVBox" id="vbox3">
|
||||
<property name="visible">True</property>
|
||||
<property name="orientation">vertical</property>
|
||||
<child>
|
||||
<widget class="GtkCheckButton" id="blink_enabled">
|
||||
<property name="label" translatable="yes">Blink tray icon</property>
|
||||
<widget class="GtkLabel" id="label22">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">False</property>
|
||||
<property name="draw_indicator">True</property>
|
||||
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
|
||||
<property name="xalign">0</property>
|
||||
<property name="xpad">10</property>
|
||||
<property name="ypad">10</property>
|
||||
<property name="label" translatable="yes"><b><i><big>Notifications</big></i></b></property>
|
||||
<property name="use_markup">True</property>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<widget class="GtkCheckButton" id="popup_enabled">
|
||||
<property name="label" translatable="yes">Show popup</property>
|
||||
<widget class="GtkHSeparator" id="hseparator1">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">False</property>
|
||||
<property name="draw_indicator">True</property>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<widget class="GtkAlignment" id="alignment1">
|
||||
<property name="visible">True</property>
|
||||
<property name="yalign">0</property>
|
||||
<property name="bottom_padding">2</property>
|
||||
<property name="left_padding">2</property>
|
||||
<property name="right_padding">2</property>
|
||||
<child>
|
||||
<widget class="GtkHBox" id="hbox2">
|
||||
<widget class="GtkNotebook" id="notebook1">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<child>
|
||||
<widget class="GtkCheckButton" id="sound_enabled">
|
||||
<property name="label" translatable="yes">Play sound</property>
|
||||
<widget class="GtkVBox" id="vbox2">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">False</property>
|
||||
<property name="draw_indicator">True</property>
|
||||
<signal name="toggled" handler="on_sound_enabled_toggled"/>
|
||||
<property name="orientation">vertical</property>
|
||||
<child>
|
||||
<widget class="GtkFrame" id="frame2">
|
||||
<property name="visible">True</property>
|
||||
<property name="label_xalign">0</property>
|
||||
<property name="shadow_type">none</property>
|
||||
<child>
|
||||
<widget class="GtkAlignment" id="alignment2">
|
||||
<property name="visible">True</property>
|
||||
<property name="left_padding">12</property>
|
||||
<child>
|
||||
<widget class="GtkVBox" id="vbox1">
|
||||
<property name="visible">True</property>
|
||||
<property name="orientation">vertical</property>
|
||||
<child>
|
||||
<widget class="GtkCheckButton" id="blink_enabled">
|
||||
<property name="label" translatable="yes">Tray icon blinks enabled</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">False</property>
|
||||
<property name="draw_indicator">True</property>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<widget class="GtkCheckButton" id="popup_enabled">
|
||||
<property name="label" translatable="yes">Popups enabled</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">False</property>
|
||||
<property name="draw_indicator">True</property>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<widget class="GtkHBox" id="hbox2">
|
||||
<property name="visible">True</property>
|
||||
<child>
|
||||
<widget class="GtkCheckButton" id="sound_enabled">
|
||||
<property name="label" translatable="yes">Sound enabled</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">False</property>
|
||||
<property name="draw_indicator">True</property>
|
||||
<signal name="toggled" handler="on_sound_enabled_toggled"/>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<widget class="GtkFileChooserButton" id="sound_path">
|
||||
<property name="visible">True</property>
|
||||
<property name="create_folders">False</property>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="padding">2</property>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="position">2</property>
|
||||
</packing>
|
||||
</child>
|
||||
</widget>
|
||||
</child>
|
||||
</widget>
|
||||
</child>
|
||||
<child>
|
||||
<widget class="GtkLabel" id="label6">
|
||||
<property name="visible">True</property>
|
||||
<property name="xpad">5</property>
|
||||
<property name="label" translatable="yes"><b>UI Notifications</b></property>
|
||||
<property name="use_markup">True</property>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="type">label_item</property>
|
||||
</packing>
|
||||
</child>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<widget class="GtkFrame" id="frame3">
|
||||
<property name="visible">True</property>
|
||||
<property name="label_xalign">0</property>
|
||||
<property name="shadow_type">none</property>
|
||||
<child>
|
||||
<widget class="GtkAlignment" id="alignment3">
|
||||
<property name="visible">True</property>
|
||||
<property name="left_padding">12</property>
|
||||
<child>
|
||||
<widget class="GtkTable" id="prefs_table">
|
||||
<property name="visible">True</property>
|
||||
<property name="n_rows">7</property>
|
||||
<property name="n_columns">4</property>
|
||||
<property name="column_spacing">2</property>
|
||||
<property name="row_spacing">2</property>
|
||||
<child>
|
||||
<widget class="GtkLabel" id="label1">
|
||||
<property name="visible">True</property>
|
||||
<property name="label" translatable="yes">Hostname:</property>
|
||||
<property name="justify">right</property>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="top_attach">1</property>
|
||||
<property name="bottom_attach">2</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<widget class="GtkEntry" id="smtp_host">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="invisible_char">●</property>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="left_attach">1</property>
|
||||
<property name="right_attach">2</property>
|
||||
<property name="top_attach">1</property>
|
||||
<property name="bottom_attach">2</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<widget class="GtkLabel" id="label2">
|
||||
<property name="visible">True</property>
|
||||
<property name="label" translatable="yes">Port:</property>
|
||||
<property name="justify">right</property>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="left_attach">2</property>
|
||||
<property name="right_attach">3</property>
|
||||
<property name="top_attach">1</property>
|
||||
<property name="bottom_attach">2</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<widget class="GtkSpinButton" id="smtp_port">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="max_length">65535</property>
|
||||
<property name="invisible_char">●</property>
|
||||
<property name="width_chars">5</property>
|
||||
<property name="adjustment">25 1 100 1 10 0</property>
|
||||
<property name="climb_rate">1</property>
|
||||
<property name="snap_to_ticks">True</property>
|
||||
<property name="numeric">True</property>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="left_attach">3</property>
|
||||
<property name="right_attach">4</property>
|
||||
<property name="top_attach">1</property>
|
||||
<property name="bottom_attach">2</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<widget class="GtkLabel" id="label3">
|
||||
<property name="visible">True</property>
|
||||
<property name="label" translatable="yes">Username:</property>
|
||||
<property name="justify">right</property>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="top_attach">2</property>
|
||||
<property name="bottom_attach">3</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<widget class="GtkEntry" id="smtp_user">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="invisible_char">●</property>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="left_attach">1</property>
|
||||
<property name="right_attach">4</property>
|
||||
<property name="top_attach">2</property>
|
||||
<property name="bottom_attach">3</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<widget class="GtkLabel" id="label4">
|
||||
<property name="visible">True</property>
|
||||
<property name="label" translatable="yes">Password:</property>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="top_attach">3</property>
|
||||
<property name="bottom_attach">4</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<widget class="GtkEntry" id="smtp_pass">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="visibility">False</property>
|
||||
<property name="invisible_char">●</property>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="left_attach">1</property>
|
||||
<property name="right_attach">4</property>
|
||||
<property name="top_attach">3</property>
|
||||
<property name="bottom_attach">4</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<widget class="GtkFrame" id="frame1">
|
||||
<property name="visible">True</property>
|
||||
<property name="label_xalign">0</property>
|
||||
<property name="shadow_type">none</property>
|
||||
<child>
|
||||
<widget class="GtkAlignment" id="alignment4">
|
||||
<property name="visible">True</property>
|
||||
<property name="left_padding">12</property>
|
||||
<child>
|
||||
<widget class="GtkHBox" id="hbox1">
|
||||
<property name="visible">True</property>
|
||||
<property name="spacing">2</property>
|
||||
<child>
|
||||
<widget class="GtkScrolledWindow" id="scrolledwindow1">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="hscrollbar_policy">automatic</property>
|
||||
<property name="vscrollbar_policy">automatic</property>
|
||||
<child>
|
||||
<widget class="GtkTreeView" id="smtp_recipients">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="headers_visible">False</property>
|
||||
<property name="enable_grid_lines">horizontal</property>
|
||||
</widget>
|
||||
</child>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<widget class="GtkVButtonBox" id="vbuttonbox1">
|
||||
<property name="visible">True</property>
|
||||
<property name="orientation">vertical</property>
|
||||
<property name="spacing">5</property>
|
||||
<property name="layout_style">start</property>
|
||||
<child>
|
||||
<widget class="GtkButton" id="add_button">
|
||||
<property name="label">gtk-add</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">True</property>
|
||||
<property name="use_stock">True</property>
|
||||
<signal name="clicked" handler="on_add_button_clicked"/>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">False</property>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<widget class="GtkButton" id="delete_button">
|
||||
<property name="label">gtk-delete</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="sensitive">False</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">True</property>
|
||||
<property name="use_stock">True</property>
|
||||
<signal name="clicked" handler="on_delete_button_clicked"/>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">False</property>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="padding">3</property>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
</widget>
|
||||
</child>
|
||||
</widget>
|
||||
</child>
|
||||
<child>
|
||||
<widget class="GtkLabel" id="label5">
|
||||
<property name="visible">True</property>
|
||||
<property name="label" translatable="yes"><b>Recipients</b></property>
|
||||
<property name="use_markup">True</property>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="type">label_item</property>
|
||||
</packing>
|
||||
</child>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="right_attach">4</property>
|
||||
<property name="top_attach">6</property>
|
||||
<property name="bottom_attach">7</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<widget class="GtkCheckButton" id="smtp_tls">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">False</property>
|
||||
<property name="draw_indicator">True</property>
|
||||
<child>
|
||||
<widget class="GtkLabel" id="label9">
|
||||
<property name="visible">True</property>
|
||||
<property name="label" translatable="yes">Server requires TLS/SSL</property>
|
||||
</widget>
|
||||
</child>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="left_attach">1</property>
|
||||
<property name="right_attach">4</property>
|
||||
<property name="top_attach">5</property>
|
||||
<property name="bottom_attach">6</property>
|
||||
<property name="x_padding">10</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<widget class="GtkLabel" id="label8">
|
||||
<property name="visible">True</property>
|
||||
<property name="label" translatable="yes">From:</property>
|
||||
<property name="justify">right</property>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="top_attach">4</property>
|
||||
<property name="bottom_attach">5</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<widget class="GtkEntry" id="smtp_from">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="invisible_char">●</property>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="left_attach">1</property>
|
||||
<property name="right_attach">4</property>
|
||||
<property name="top_attach">4</property>
|
||||
<property name="bottom_attach">5</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<widget class="GtkCheckButton" id="smtp_enabled">
|
||||
<property name="label" translatable="yes">Enabled</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">False</property>
|
||||
<property name="draw_indicator">True</property>
|
||||
<signal name="toggled" handler="on_enabled_toggled"/>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="right_attach">4</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<placeholder/>
|
||||
</child>
|
||||
</widget>
|
||||
</child>
|
||||
</widget>
|
||||
</child>
|
||||
<child>
|
||||
<widget class="GtkLabel" id="label7">
|
||||
<property name="visible">True</property>
|
||||
<property name="xpad">5</property>
|
||||
<property name="label" translatable="yes"><b>Email Notifications</b></property>
|
||||
<property name="use_markup">True</property>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="type">label_item</property>
|
||||
</packing>
|
||||
</child>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
</widget>
|
||||
</child>
|
||||
<child>
|
||||
<widget class="GtkLabel" id="label10">
|
||||
<property name="visible">True</property>
|
||||
<property name="label" translatable="yes">Settings</property>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="position">0</property>
|
||||
<property name="tab_fill">False</property>
|
||||
<property name="type">tab</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<widget class="GtkFileChooserButton" id="sound_path">
|
||||
<widget class="GtkVBox" id="vbox5">
|
||||
<property name="visible">True</property>
|
||||
<property name="create_folders">False</property>
|
||||
<property name="orientation">vertical</property>
|
||||
<child>
|
||||
<placeholder/>
|
||||
</child>
|
||||
<child>
|
||||
<widget class="GtkScrolledWindow" id="scrolledwindow2">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="hscrollbar_policy">automatic</property>
|
||||
<property name="vscrollbar_policy">automatic</property>
|
||||
<child>
|
||||
<widget class="GtkTreeView" id="subscriptions_treeview">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="enable_grid_lines">horizontal</property>
|
||||
</widget>
|
||||
</child>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<widget class="GtkLabel" id="label12">
|
||||
<property name="visible">True</property>
|
||||
<property name="label" translatable="yes">This configuration does not mean that you'll actually receive notifications for all these events.</property>
|
||||
<property name="justify">fill</property>
|
||||
<property name="wrap">True</property>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="padding">2</property>
|
||||
<property name="position">2</property>
|
||||
</packing>
|
||||
</child>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="padding">2</property>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<widget class="GtkLabel" id="label11">
|
||||
<property name="visible">True</property>
|
||||
<property name="label" translatable="yes">Subscriptions</property>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="position">1</property>
|
||||
<property name="tab_fill">False</property>
|
||||
<property name="type">tab</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<placeholder/>
|
||||
</child>
|
||||
<child>
|
||||
<placeholder/>
|
||||
<packing>
|
||||
<property name="type">tab</property>
|
||||
</packing>
|
||||
</child>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="position">2</property>
|
||||
</packing>
|
||||
</child>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
</widget>
|
||||
</child>
|
||||
<child>
|
||||
<widget class="GtkLabel" id="label6">
|
||||
<property name="visible">True</property>
|
||||
<property name="label" translatable="yes"><b>UI Notifications</b></property>
|
||||
<property name="use_markup">True</property>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="type">label_item</property>
|
||||
</packing>
|
||||
</child>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<widget class="GtkFrame" id="frame3">
|
||||
<property name="visible">True</property>
|
||||
<property name="label_xalign">0</property>
|
||||
<property name="shadow_type">none</property>
|
||||
<child>
|
||||
<widget class="GtkAlignment" id="alignment3">
|
||||
<property name="visible">True</property>
|
||||
<property name="left_padding">12</property>
|
||||
<child>
|
||||
<widget class="GtkTable" id="prefs_table">
|
||||
<property name="visible">True</property>
|
||||
<property name="n_rows">7</property>
|
||||
<property name="n_columns">4</property>
|
||||
<property name="column_spacing">2</property>
|
||||
<property name="row_spacing">2</property>
|
||||
<child>
|
||||
<widget class="GtkLabel" id="label1">
|
||||
<property name="visible">True</property>
|
||||
<property name="label" translatable="yes">Hostname:</property>
|
||||
<property name="justify">right</property>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="top_attach">1</property>
|
||||
<property name="bottom_attach">2</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<widget class="GtkEntry" id="smtp_host">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="invisible_char">●</property>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="left_attach">1</property>
|
||||
<property name="right_attach">2</property>
|
||||
<property name="top_attach">1</property>
|
||||
<property name="bottom_attach">2</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<widget class="GtkLabel" id="label2">
|
||||
<property name="visible">True</property>
|
||||
<property name="label" translatable="yes">Port:</property>
|
||||
<property name="justify">right</property>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="left_attach">2</property>
|
||||
<property name="right_attach">3</property>
|
||||
<property name="top_attach">1</property>
|
||||
<property name="bottom_attach">2</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<widget class="GtkSpinButton" id="smtp_port">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="max_length">65535</property>
|
||||
<property name="invisible_char">●</property>
|
||||
<property name="width_chars">5</property>
|
||||
<property name="adjustment">25 1 100 1 10 10</property>
|
||||
<property name="climb_rate">1</property>
|
||||
<property name="snap_to_ticks">True</property>
|
||||
<property name="numeric">True</property>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="left_attach">3</property>
|
||||
<property name="right_attach">4</property>
|
||||
<property name="top_attach">1</property>
|
||||
<property name="bottom_attach">2</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<widget class="GtkLabel" id="label3">
|
||||
<property name="visible">True</property>
|
||||
<property name="label" translatable="yes">Username:</property>
|
||||
<property name="justify">right</property>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="top_attach">2</property>
|
||||
<property name="bottom_attach">3</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<widget class="GtkEntry" id="smtp_user">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="invisible_char">●</property>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="left_attach">1</property>
|
||||
<property name="right_attach">4</property>
|
||||
<property name="top_attach">2</property>
|
||||
<property name="bottom_attach">3</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<widget class="GtkLabel" id="label4">
|
||||
<property name="visible">True</property>
|
||||
<property name="label" translatable="yes">Password:</property>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="top_attach">3</property>
|
||||
<property name="bottom_attach">4</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<widget class="GtkEntry" id="smtp_pass">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="visibility">False</property>
|
||||
<property name="invisible_char">●</property>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="left_attach">1</property>
|
||||
<property name="right_attach">4</property>
|
||||
<property name="top_attach">3</property>
|
||||
<property name="bottom_attach">4</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<widget class="GtkFrame" id="frame1">
|
||||
<property name="visible">True</property>
|
||||
<property name="label_xalign">0</property>
|
||||
<property name="shadow_type">none</property>
|
||||
<child>
|
||||
<widget class="GtkAlignment" id="alignment1">
|
||||
<property name="visible">True</property>
|
||||
<property name="left_padding">12</property>
|
||||
<child>
|
||||
<widget class="GtkHBox" id="hbox1">
|
||||
<property name="visible">True</property>
|
||||
<property name="spacing">2</property>
|
||||
<child>
|
||||
<widget class="GtkScrolledWindow" id="scrolledwindow1">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="hscrollbar_policy">automatic</property>
|
||||
<property name="vscrollbar_policy">automatic</property>
|
||||
<child>
|
||||
<widget class="GtkTreeView" id="smtp_recipients">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="headers_visible">False</property>
|
||||
<property name="enable_grid_lines">horizontal</property>
|
||||
</widget>
|
||||
</child>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<widget class="GtkVButtonBox" id="vbuttonbox1">
|
||||
<property name="visible">True</property>
|
||||
<property name="orientation">vertical</property>
|
||||
<property name="spacing">5</property>
|
||||
<property name="layout_style">start</property>
|
||||
<child>
|
||||
<widget class="GtkButton" id="add_button">
|
||||
<property name="label">gtk-add</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">True</property>
|
||||
<property name="use_stock">True</property>
|
||||
<signal name="clicked" handler="on_add_button_clicked"/>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">False</property>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<widget class="GtkButton" id="delete_button">
|
||||
<property name="label">gtk-delete</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="sensitive">False</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">True</property>
|
||||
<property name="use_stock">True</property>
|
||||
<signal name="clicked" handler="on_delete_button_clicked"/>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">False</property>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="padding">3</property>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
</widget>
|
||||
</child>
|
||||
</widget>
|
||||
</child>
|
||||
<child>
|
||||
<widget class="GtkLabel" id="label5">
|
||||
<property name="visible">True</property>
|
||||
<property name="label" translatable="yes"><b>Recipients</b></property>
|
||||
<property name="use_markup">True</property>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="type">label_item</property>
|
||||
</packing>
|
||||
</child>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="right_attach">4</property>
|
||||
<property name="top_attach">6</property>
|
||||
<property name="bottom_attach">7</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<widget class="GtkCheckButton" id="smtp_tls">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">False</property>
|
||||
<property name="draw_indicator">True</property>
|
||||
<child>
|
||||
<widget class="GtkLabel" id="label9">
|
||||
<property name="visible">True</property>
|
||||
<property name="label" translatable="yes">Server requires TLS/SSL</property>
|
||||
</widget>
|
||||
</child>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="left_attach">1</property>
|
||||
<property name="right_attach">4</property>
|
||||
<property name="top_attach">5</property>
|
||||
<property name="bottom_attach">6</property>
|
||||
<property name="x_padding">10</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<widget class="GtkLabel" id="label8">
|
||||
<property name="visible">True</property>
|
||||
<property name="label" translatable="yes">From:</property>
|
||||
<property name="justify">right</property>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="top_attach">4</property>
|
||||
<property name="bottom_attach">5</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<widget class="GtkEntry" id="smtp_from">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="invisible_char">●</property>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="left_attach">1</property>
|
||||
<property name="right_attach">4</property>
|
||||
<property name="top_attach">4</property>
|
||||
<property name="bottom_attach">5</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<widget class="GtkCheckButton" id="smtp_enabled">
|
||||
<property name="label" translatable="yes">Enabled</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">False</property>
|
||||
<property name="draw_indicator">True</property>
|
||||
<signal name="toggled" handler="on_enabled_toggled"/>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="right_attach">4</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<placeholder/>
|
||||
</child>
|
||||
</widget>
|
||||
</child>
|
||||
</widget>
|
||||
</child>
|
||||
<child>
|
||||
<widget class="GtkLabel" id="label7">
|
||||
<property name="visible">True</property>
|
||||
<property name="label" translatable="yes"><b>Email Notifications</b></property>
|
||||
<property name="use_markup">True</property>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="type">label_item</property>
|
||||
</packing>
|
||||
</child>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
</widget>
|
||||
</child>
|
||||
</widget>
|
||||
|
|
|
@ -40,11 +40,13 @@
|
|||
import gtk
|
||||
|
||||
from twisted.internet import defer
|
||||
from deluge.event import known_events, DelugeEvent
|
||||
from deluge.log import LOG as log
|
||||
from deluge.ui.client import client
|
||||
from deluge.plugins.pluginbase import GtkPluginBase
|
||||
import deluge.component as component
|
||||
import deluge.common
|
||||
import deluge.configmanager
|
||||
|
||||
try:
|
||||
import pygame
|
||||
|
@ -60,44 +62,148 @@ except ImportError:
|
|||
|
||||
# Relative imports
|
||||
from common import get_resource
|
||||
from manager import Notifications
|
||||
|
||||
DEFAULT_PREFS = {
|
||||
# BLINK
|
||||
"blink_enabled": False,
|
||||
# FLASH
|
||||
"flash_enabled": False,
|
||||
# POPUP
|
||||
"popup_enabled": False,
|
||||
# SOUND
|
||||
"sound_enabled": False,
|
||||
"sound_path": "",
|
||||
# Subscriptions
|
||||
"subscriptions": {
|
||||
"popup": [],
|
||||
"blink": [],
|
||||
"sound": [],
|
||||
}
|
||||
}
|
||||
|
||||
RECIPIENT_FIELD, RECIPIENT_EDIT = range(2)
|
||||
(SUB_EVENT, SUB_EVENT_DOC, SUB_NOT_EMAIL, SUB_NOT_POPUP, SUB_NOT_BLINK,
|
||||
SUB_NOT_SOUND) = range(6)
|
||||
|
||||
|
||||
class GtkUI(GtkPluginBase, component.Component):
|
||||
def __init__(self, plugin_name):
|
||||
GtkPluginBase.__init__(self, plugin_name)
|
||||
component.Component.__init__(self, "Notifications")
|
||||
|
||||
class GtkUI(GtkPluginBase, Notifications):
|
||||
def enable(self):
|
||||
Notifications.enable(self)
|
||||
self.config = deluge.configmanager.ConfigManager(
|
||||
"notifications-gtk.conf", DEFAULT_PREFS
|
||||
)
|
||||
self.glade = gtk.glade.XML(get_resource("config.glade"))
|
||||
self.glade.get_widget("smtp_port").set_value(25)
|
||||
self.prefs = self.glade.get_widget("prefs_box")
|
||||
self.prefs.show_all()
|
||||
self.treeview = self.glade.get_widget("smtp_recipients")
|
||||
treeview_selection = self.treeview.get_selection()
|
||||
treeview_selection.connect("changed", self.on_treeview_selection_changed)
|
||||
self.model = gtk.ListStore(str, bool)
|
||||
|
||||
# SMTP Recipients treeview/model
|
||||
self.recipients_treeview = self.glade.get_widget("smtp_recipients")
|
||||
treeview_selection = self.recipients_treeview.get_selection()
|
||||
treeview_selection.connect(
|
||||
"changed", self.on_recipients_treeview_selection_changed
|
||||
)
|
||||
self.recipients_model = gtk.ListStore(str, bool)
|
||||
|
||||
renderer = gtk.CellRendererText()
|
||||
renderer.connect("edited", self.on_cell_edited, self.model)
|
||||
renderer.connect("edited", self.on_cell_edited, self.recipients_model)
|
||||
renderer.set_data("recipient", RECIPIENT_FIELD)
|
||||
column = gtk.TreeViewColumn("Recipients", renderer,
|
||||
text=RECIPIENT_FIELD,
|
||||
editable=RECIPIENT_EDIT)
|
||||
column.set_expand(True)
|
||||
self.treeview.append_column(column)
|
||||
self.treeview.set_model(self.model)
|
||||
self.recipients_treeview.append_column(column)
|
||||
self.recipients_treeview.set_model(self.recipients_model)
|
||||
|
||||
deluge.common.get_default_download_dir()
|
||||
# Notification Subscriptions treeview/model
|
||||
self.subscriptions_treeview = self.glade.get_widget("subscriptions_treeview")
|
||||
subscriptions_selection = self.subscriptions_treeview.get_selection()
|
||||
subscriptions_selection.connect(
|
||||
"changed", self.on_subscriptions_treeview_selection_changed
|
||||
)
|
||||
self.subscriptions_treeview.set_tooltip_column(SUB_EVENT_DOC)
|
||||
self.subscriptions_model = gtk.ListStore(str, str, bool, bool, bool, bool)
|
||||
|
||||
renderer = gtk.CellRendererText()
|
||||
renderer.set_data("event", SUB_EVENT)
|
||||
column = gtk.TreeViewColumn("Event", renderer, text=SUB_EVENT)
|
||||
column.set_expand(True)
|
||||
self.subscriptions_treeview.append_column(column)
|
||||
|
||||
renderer = gtk.CellRendererText()
|
||||
renderer.set_data("event_doc", SUB_EVENT)
|
||||
column = gtk.TreeViewColumn("Doc", renderer, text=SUB_EVENT_DOC)
|
||||
column.set_property('visible', False)
|
||||
self.subscriptions_treeview.append_column(column)
|
||||
|
||||
|
||||
renderer = gtk.CellRendererToggle()
|
||||
renderer.set_property('activatable', True)
|
||||
renderer.connect('toggled', self._on_email_col_toggled)
|
||||
column = gtk.TreeViewColumn("Email", renderer, active=SUB_NOT_EMAIL)
|
||||
column.set_clickable(True)
|
||||
# column.add_attribute(renderer, "active", False)
|
||||
# column.set_expand(True)
|
||||
self.subscriptions_treeview.append_column(column)
|
||||
|
||||
renderer = gtk.CellRendererToggle()
|
||||
# renderer.connect("edited", self.on_cell_edited, self.recipients_model)
|
||||
# renderer.set_data("popup", SUB_NOT_POPUP)
|
||||
renderer.set_property('activatable', True)
|
||||
renderer.connect( 'toggled', self._on_popup_col_toggled)
|
||||
column = gtk.TreeViewColumn("Popup", renderer, active=SUB_NOT_POPUP)
|
||||
column.set_clickable(True)
|
||||
# column.add_attribute(renderer, "active", False)
|
||||
# column.set_expand(True)
|
||||
self.subscriptions_treeview.append_column(column)
|
||||
|
||||
renderer = gtk.CellRendererToggle()
|
||||
# renderer.connect("edited", self.on_cell_edited, self.recipients_model)
|
||||
# renderer.set_data("blink", SUB_NOT_BLINK)
|
||||
renderer.set_property('activatable', True)
|
||||
renderer.connect( 'toggled', self._on_blink_col_toggled)
|
||||
column = gtk.TreeViewColumn("Blink", renderer, active=SUB_NOT_BLINK)
|
||||
column.set_clickable(True)
|
||||
# column.add_attribute(renderer, "active", False)
|
||||
# column.set_expand(True)
|
||||
self.subscriptions_treeview.append_column(column)
|
||||
|
||||
renderer = gtk.CellRendererToggle()
|
||||
# renderer.connect("edited", self.on_cell_edited, self.recipients_model)
|
||||
renderer.set_property('activatable', True)
|
||||
renderer.connect('toggled', self._on_sound_col_toggled)
|
||||
# renderer.set_data("sound", SUB_NOT_SOUND)
|
||||
column = gtk.TreeViewColumn("Sound", renderer, active=SUB_NOT_SOUND)
|
||||
column.set_clickable(True)
|
||||
# column.add_attribute(renderer, "active", False)
|
||||
# column.set_expand(True)
|
||||
self.subscriptions_treeview.append_column(column)
|
||||
self.subscriptions_treeview.set_model(self.subscriptions_model)
|
||||
|
||||
client.notifications.get_handled_events().addCallback(
|
||||
self.popuplate_subscriptions
|
||||
)
|
||||
|
||||
self.glade.signal_autoconnect({
|
||||
'on_add_button_clicked': (self.on_add_button_clicked,
|
||||
self.treeview),
|
||||
self.recipients_treeview),
|
||||
'on_delete_button_clicked': (self.on_delete_button_clicked,
|
||||
self.treeview),
|
||||
self.recipients_treeview),
|
||||
'on_enabled_toggled': self.on_enabled_toggled,
|
||||
'on_sound_enabled_toggled': self.on_sound_enabled_toggled
|
||||
})
|
||||
|
||||
component.get("Preferences").add_page("Notifications", self.prefs)
|
||||
# component.get("Preferences").add_page("Notifications", self.prefs)
|
||||
prefs = component.get("Preferences")
|
||||
parent = self.prefs.get_parent()
|
||||
if parent:
|
||||
parent.remove(self.prefs)
|
||||
index = prefs.notebook.append_page(self.prefs)
|
||||
prefs.liststore.append([index, "Notifications"])
|
||||
|
||||
component.get("PluginManager").register_hook("on_apply_prefs",
|
||||
self.on_apply_prefs)
|
||||
component.get("PluginManager").register_hook("on_show_prefs",
|
||||
|
@ -106,38 +212,93 @@ class GtkUI(GtkPluginBase, Notifications):
|
|||
if not POPUP_AVAILABLE:
|
||||
self.glade.get_widget("popup_enabled").set_property('sensitive',
|
||||
False)
|
||||
else:
|
||||
client.register_event_handler("NotificationPopupEvent",
|
||||
self.notify_popup)
|
||||
|
||||
client.register_event_handler("NotificationBlinkEvent",
|
||||
self.notify_blink)
|
||||
|
||||
self.tray = component.get("SystemTray")
|
||||
if not SOUND_AVAILABLE:
|
||||
self.glade.get_widget("sound_enabled").set_property('sensitive',
|
||||
False)
|
||||
self.glade.get_widget('sound_path').set_property('sensitive', False)
|
||||
else:
|
||||
client.register_event_handler("NotificationSoundEvent",
|
||||
self.notify_sound)
|
||||
|
||||
self.systray = component.get("SystemTray")
|
||||
if not hasattr(self.systray, 'tray'):
|
||||
# Tray is not beeing used
|
||||
self.glade.get_widget('blink_enabled').set_property('sensitive',
|
||||
False)
|
||||
|
||||
|
||||
client.register_event_handler("TorrentFinishedEvent",
|
||||
self._on_torrent_finished_event)
|
||||
# Force config populate
|
||||
client.notifications.get_config().addCallback(self.cb_get_config)
|
||||
|
||||
def disable(self):
|
||||
Notifications.disable(self)
|
||||
component.get("Preferences").remove_page("Notifications")
|
||||
component.get("PluginManager").deregister_hook("on_apply_prefs",
|
||||
self.on_apply_prefs)
|
||||
component.get("PluginManager").deregister_hook("on_show_prefs",
|
||||
self.on_show_prefs)
|
||||
|
||||
def popuplate_subscriptions(self, handled_events, email_subscriptions=[]):
|
||||
subscriptions_dict = self.config['subscriptions']
|
||||
self.subscriptions_model.clear()
|
||||
# self.handled_events = handled_events
|
||||
for event_name, event_doc in handled_events:
|
||||
self.subscriptions_model.set(
|
||||
self.subscriptions_model.append(),
|
||||
SUB_EVENT, event_name,
|
||||
SUB_EVENT_DOC, event_doc,
|
||||
SUB_NOT_EMAIL, event_name in email_subscriptions,
|
||||
SUB_NOT_POPUP, event_name in subscriptions_dict["popup"],
|
||||
SUB_NOT_BLINK, event_name in subscriptions_dict['blink'],
|
||||
SUB_NOT_SOUND, event_name in subscriptions_dict['sound']
|
||||
)
|
||||
|
||||
|
||||
def on_apply_prefs(self):
|
||||
log.debug("applying prefs for Notifications")
|
||||
config = {
|
||||
|
||||
current_popup_subscriptions = []
|
||||
current_blink_subscriptions = []
|
||||
current_sound_subscriptions = []
|
||||
current_email_subscriptions = []
|
||||
for event, doc, email, popup, blink, sound in self.subscriptions_model:
|
||||
if email:
|
||||
current_email_subscriptions.append(event)
|
||||
if popup:
|
||||
current_popup_subscriptions.append(event)
|
||||
if blink:
|
||||
current_blink_subscriptions.append(event)
|
||||
if sound:
|
||||
current_sound_subscriptions.append(event)
|
||||
# saved_popup_subscriptions = self.config['subscriptions']['popup']
|
||||
# saved_blink_subscriptions = self.config['subscriptions']['blink']
|
||||
# saved_sound_subscriptions = self.config['subscriptions']['sound']
|
||||
# for event in current_popup_subscriptions:
|
||||
# saved_popup_subscriptions.remove(event)
|
||||
# for event in saved_blink_subscriptions:
|
||||
# # De register
|
||||
# pass
|
||||
# for event in current_blink_subscriptions:
|
||||
# saved_blink_subscriptions.remove(event)
|
||||
# for event in saved_blink_subscriptions:
|
||||
# # De register
|
||||
# pass
|
||||
# for event in current_sound_subscriptions:
|
||||
# saved_sound_subscriptions.remove(event)
|
||||
# for event in saved_sound_subscriptions:
|
||||
# # De register
|
||||
# pass
|
||||
|
||||
self.config.config.update({
|
||||
"popup_enabled": self.glade.get_widget("popup_enabled").get_active(),
|
||||
"blink_enabled": self.glade.get_widget("blink_enabled").get_active(),
|
||||
"sound_enabled": self.glade.get_widget("sound_enabled").get_active(),
|
||||
"sound_path": self.glade.get_widget("sound_path").get_filename(),
|
||||
"subscriptions": {
|
||||
"popup": current_popup_subscriptions,
|
||||
"blink": current_blink_subscriptions,
|
||||
"sound": current_sound_subscriptions
|
||||
}
|
||||
})
|
||||
self.config.save()
|
||||
|
||||
core_config = {
|
||||
"smtp_enabled": self.glade.get_widget("smtp_enabled").get_active(),
|
||||
"smtp_host": self.glade.get_widget("smtp_host").get_text(),
|
||||
"smtp_port": self.glade.get_widget("smtp_port").get_value(),
|
||||
|
@ -145,45 +306,42 @@ class GtkUI(GtkPluginBase, Notifications):
|
|||
"smtp_pass": self.glade.get_widget("smtp_pass").get_text(),
|
||||
"smtp_from": self.glade.get_widget("smtp_from").get_text(),
|
||||
"smtp_tls": self.glade.get_widget("smtp_tls").get_active(),
|
||||
"smtp_recipients": [dest[0] for dest in self.model if
|
||||
"smtp_recipients": [dest[0] for dest in self.recipients_model if
|
||||
dest[0]!='USER@HOST'],
|
||||
"blink_enabled": self.glade.get_widget("blink_enabled").get_active(),
|
||||
"sound_enabled": self.glade.get_widget("sound_enabled").get_active(),
|
||||
"sound_path": self.glade.get_widget("sound_path").get_filename(),
|
||||
"popup_enabled": self.glade.get_widget("popup_enabled").get_active()
|
||||
"subscriptions": {"email": current_email_subscriptions}
|
||||
}
|
||||
|
||||
client.notifications.set_config(config)
|
||||
client.notifications.set_config(core_config)
|
||||
|
||||
def on_show_prefs(self):
|
||||
client.notifications.get_config().addCallback(self.cb_get_config)
|
||||
|
||||
def cb_get_config(self, config):
|
||||
def cb_get_config(self, core_config):
|
||||
"callback for on show_prefs"
|
||||
self.config = config
|
||||
self.glade.get_widget("smtp_host").set_text(config["smtp_host"])
|
||||
self.glade.get_widget("smtp_port").set_value(config["smtp_port"])
|
||||
self.glade.get_widget("smtp_user").set_text(config["smtp_user"])
|
||||
self.glade.get_widget("smtp_pass").set_text(config["smtp_pass"])
|
||||
self.glade.get_widget("smtp_from").set_text(config["smtp_from"])
|
||||
self.glade.get_widget("smtp_tls").set_active(config["smtp_tls"])
|
||||
self.model.clear()
|
||||
for recipient in config['smtp_recipients']:
|
||||
self.model.set(self.model.append(),
|
||||
RECIPIENT_FIELD, recipient,
|
||||
RECIPIENT_EDIT, False)
|
||||
self.glade.get_widget("smtp_enabled").set_active(config['smtp_enabled'])
|
||||
self.glade.get_widget("smtp_host").set_text(core_config["smtp_host"])
|
||||
self.glade.get_widget("smtp_port").set_value(core_config["smtp_port"])
|
||||
self.glade.get_widget("smtp_user").set_text(core_config["smtp_user"])
|
||||
self.glade.get_widget("smtp_pass").set_text(core_config["smtp_pass"])
|
||||
self.glade.get_widget("smtp_from").set_text(core_config["smtp_from"])
|
||||
self.glade.get_widget("smtp_tls").set_active(core_config["smtp_tls"])
|
||||
self.recipients_model.clear()
|
||||
for recipient in core_config['smtp_recipients']:
|
||||
self.recipients_model.set(self.recipients_model.append(),
|
||||
RECIPIENT_FIELD, recipient,
|
||||
RECIPIENT_EDIT, False)
|
||||
self.glade.get_widget("smtp_enabled").set_active(
|
||||
core_config['smtp_enabled']
|
||||
)
|
||||
self.glade.get_widget("sound_enabled").set_active(
|
||||
config['sound_enabled']
|
||||
self.config['sound_enabled']
|
||||
)
|
||||
self.glade.get_widget("popup_enabled").set_active(
|
||||
config['popup_enabled']
|
||||
self.config['popup_enabled']
|
||||
)
|
||||
self.glade.get_widget("blink_enabled").set_active(
|
||||
config['blink_enabled']
|
||||
self.config['blink_enabled']
|
||||
)
|
||||
if config['sound_path']:
|
||||
sound_path = config['sound_path']
|
||||
if self.config['sound_path']:
|
||||
sound_path = self.config['sound_path']
|
||||
else:
|
||||
sound_path = deluge.common.get_default_download_dir()
|
||||
self.glade.get_widget("sound_path").set_filename(sound_path)
|
||||
|
@ -191,6 +349,11 @@ class GtkUI(GtkPluginBase, Notifications):
|
|||
self.on_enabled_toggled(self.glade.get_widget("smtp_enabled"))
|
||||
self.on_sound_enabled_toggled(self.glade.get_widget('sound_enabled'))
|
||||
|
||||
client.notifications.get_handled_events().addCallback(
|
||||
self.popuplate_subscriptions, core_config['subscriptions']['email']
|
||||
)
|
||||
|
||||
|
||||
def on_add_button_clicked(self, widget, treeview):
|
||||
model = treeview.get_model()
|
||||
model.set(model.append(),
|
||||
|
@ -210,7 +373,7 @@ class GtkUI(GtkPluginBase, Notifications):
|
|||
path = model.get_path(iter)[0]
|
||||
model.set(iter, RECIPIENT_FIELD, new_text)
|
||||
|
||||
def on_treeview_selection_changed(self, selection):
|
||||
def on_recipients_treeview_selection_changed(self, selection):
|
||||
model, selected_connection_iter = selection.get_selected()
|
||||
if selected_connection_iter:
|
||||
self.glade.get_widget("delete_button").set_property('sensitive',
|
||||
|
@ -218,6 +381,16 @@ class GtkUI(GtkPluginBase, Notifications):
|
|||
else:
|
||||
self.glade.get_widget("delete_button").set_property('sensitive',
|
||||
False)
|
||||
|
||||
def on_subscriptions_treeview_selection_changed(self, selection):
|
||||
model, selected_connection_iter = selection.get_selected()
|
||||
if selected_connection_iter:
|
||||
self.glade.get_widget("delete_button").set_property('sensitive',
|
||||
True)
|
||||
else:
|
||||
self.glade.get_widget("delete_button").set_property('sensitive',
|
||||
False)
|
||||
|
||||
def on_enabled_toggled(self, widget):
|
||||
if widget.get_active():
|
||||
for widget in ('smtp_host', 'smtp_port', 'smtp_user', 'smtp_pass',
|
||||
|
@ -237,24 +410,14 @@ class GtkUI(GtkPluginBase, Notifications):
|
|||
else:
|
||||
self.glade.get_widget('sound_path').set_property('sensitive', False)
|
||||
|
||||
def notify_blink(self):
|
||||
defer.maybeDeferred(self.tray.blink, True)
|
||||
return defer.succeed("blink notification shown.")
|
||||
|
||||
def notify_email(self, title='', message='', smtp_from='', recipients=[]):
|
||||
d = client.notifications.notify_email(title, message, smtp_from,
|
||||
recipients)
|
||||
d.addCallback(self._on_notify_sucess, "email")
|
||||
d.addCallback(self._on_notify_failure, "email")
|
||||
# Notification methods
|
||||
def blink(self):
|
||||
d = defer.maybeDeferred(self.systray.blink, True)
|
||||
d.addCallback(self._on_notify_sucess, "blink")
|
||||
d.addCallback(self._on_notify_failure, "blink")
|
||||
return d
|
||||
|
||||
def notify_flash(self, title='', message=''):
|
||||
d = client.notifications.notify_flash(title, message)
|
||||
d.addCallback(self._on_notify_sucess, "flash")
|
||||
d.addCallback(self._on_notify_failure, "flash")
|
||||
return d
|
||||
|
||||
def notify_popup(self, title='', message=''):
|
||||
def popup(self, title='', message=''):
|
||||
if not self.config['popup_enabled']:
|
||||
return defer.succeed(_("Popup notification is not enabled."))
|
||||
if not POPUP_AVAILABLE:
|
||||
|
@ -271,7 +434,7 @@ class GtkUI(GtkPluginBase, Notifications):
|
|||
return defer.fail(err_msg)
|
||||
return defer.succeed(_("Notification popup shown"))
|
||||
|
||||
def notify_sound(self, sound_path=''):
|
||||
def play_sound(self, sound_path=''):
|
||||
if not self.config['sound_enabled']:
|
||||
return defer.succeed(_("Sound notification not enabled"))
|
||||
if not SOUND_AVAILABLE:
|
||||
|
@ -295,15 +458,16 @@ class GtkUI(GtkPluginBase, Notifications):
|
|||
log.info(msg)
|
||||
return defer.succeed(msg)
|
||||
|
||||
# Internal methods
|
||||
def _on_torrent_finished_event(self, torrent_id):
|
||||
log.debug("\n\nhandler for TorrentFinishedEvent GTKUI called")
|
||||
# Blink
|
||||
d0 = defer.maybeDeferred(self.notify_blink)
|
||||
d0 = defer.maybeDeferred(self.blink)
|
||||
d0.addCallback(self._on_notify_sucess, 'blink')
|
||||
d0.addErrback(self._on_notify_failure, 'blink')
|
||||
log.debug("Blink notification callback yielded")
|
||||
# Sound
|
||||
d1 = defer.maybeDeferred(self.notify_sound)
|
||||
d1 = defer.maybeDeferred(self.play_sound)
|
||||
d1.addCallback(self._on_notify_sucess, 'sound')
|
||||
d1.addErrback(self._on_notify_failure, 'sound')
|
||||
log.debug("Sound notification callback yielded")
|
||||
|
@ -311,6 +475,7 @@ class GtkUI(GtkPluginBase, Notifications):
|
|||
d2 = client.core.get_torrent_status(torrent_id, ["name", "num_files"])
|
||||
d2.addCallback(self._on_torrent_finished_event_got_torrent_status)
|
||||
d2.addErrback(self._on_torrent_finished_event_torrent_status_failure)
|
||||
return defer.succeed("\n\nGtkUI on torrent finished")
|
||||
|
||||
def _on_torrent_finished_event_torrent_status_failure(self, failure):
|
||||
log.debug("Failed to get torrent status to be able to show the popup")
|
||||
|
@ -320,8 +485,36 @@ class GtkUI(GtkPluginBase, Notifications):
|
|||
title = _("Finished Torrent")
|
||||
message = _("The torrent \"%(name)s\" including %(num_files)i "
|
||||
"has finished downloading.") % torrent_status
|
||||
d2 = defer.maybeDeferred(self.notify_popup, title, message)
|
||||
d2.addCallback(self._on_notify_sucess, 'popup')
|
||||
d2.addErrback(self._on_notify_failure, 'popup')
|
||||
log.debug("Popup notification callback yielded")
|
||||
d = defer.maybeDeferred(self.popup, title, message)
|
||||
d.addCallback(self._on_notify_sucess, 'popup')
|
||||
d.addErrback(self._on_notify_failure, 'popup')
|
||||
return d
|
||||
|
||||
def _on_notify_sucess(self, result, kind):
|
||||
log.debug("\n\nNotification success using %s: %s", kind, result)
|
||||
return result
|
||||
|
||||
def _on_notify_failure(self, failure, kind):
|
||||
log.debug("\n\nNotification failure using %s: %s", kind, failure)
|
||||
return failure
|
||||
|
||||
def _on_email_col_toggled(self, cell, path):
|
||||
self.subscriptions_model[path][SUB_NOT_EMAIL] = \
|
||||
not self.subscriptions_model[path][SUB_NOT_EMAIL]
|
||||
return
|
||||
|
||||
def _on_popup_col_toggled(self, cell, path):
|
||||
self.subscriptions_model[path][SUB_NOT_POPUP] = \
|
||||
not self.subscriptions_model[path][SUB_NOT_POPUP]
|
||||
return
|
||||
|
||||
def _on_blink_col_toggled(self, cell, path):
|
||||
self.subscriptions_model[path][SUB_NOT_BLINK] = \
|
||||
not self.subscriptions_model[path][SUB_NOT_BLINK]
|
||||
return
|
||||
|
||||
def _on_sound_col_toggled(self, cell, path):
|
||||
self.subscriptions_model[path][SUB_NOT_SOUND] = \
|
||||
not self.subscriptions_model[path][SUB_NOT_SOUND]
|
||||
return
|
||||
|
||||
|
|
|
@ -37,21 +37,49 @@
|
|||
# statement from all source files in the program, then also delete it here.
|
||||
#
|
||||
|
||||
from twisted.internet import defer
|
||||
from deluge.log import LOG as log
|
||||
from deluge.ui.client import client
|
||||
from deluge import component
|
||||
from deluge.plugins.pluginbase import WebPluginBase
|
||||
import deluge.configmanager
|
||||
|
||||
# Relative imports
|
||||
from common import get_resource
|
||||
from manager import Notifications
|
||||
|
||||
class WebUI(WebPluginBase, Notifications):
|
||||
DEFAULT_PREFS = {
|
||||
# FLASH
|
||||
"flash_enabled": False,
|
||||
# Subscriptions
|
||||
"subscriptions": {
|
||||
"flash": []
|
||||
}
|
||||
}
|
||||
|
||||
class WebUI(WebPluginBase, component.Component):
|
||||
|
||||
scripts = [get_resource("notifications.js")]
|
||||
|
||||
def __init__(self, plugin_name):
|
||||
WebPluginBase.__init__(self, plugin_name)
|
||||
component.Component.__init__(self, "Notifications")
|
||||
|
||||
def enable(self):
|
||||
Notifications.enable(self)
|
||||
self.config = deluge.configmanager.ConfigManager(
|
||||
"notifications-web.conf", DEFAULT_PREFS
|
||||
)
|
||||
log.debug("Enabling Web UI notifications")
|
||||
|
||||
def disable(self):
|
||||
Notifications.disable(self)
|
||||
log.debug("Disabling Web UI notifications")
|
||||
|
||||
def flash(self, title, message):
|
||||
return defer.succeed("Web Flash Notifications not implemented yet")
|
||||
|
||||
def _on_notify_sucess(self, result, kind):
|
||||
log.debug("\n\nNotification success using %s: %s", kind, result)
|
||||
return result
|
||||
|
||||
def _on_notify_failure(self, failure, kind):
|
||||
log.debug("\n\nNotification failure using %s: %s", kind, failure)
|
||||
return failure
|
||||
|
|
Loading…
Reference in New Issue