marked members as private where appropriate

This commit is contained in:
Patrick Ulbrich
2012-01-08 13:37:33 +01:00
parent 8491fdbe09
commit b406602d80
5 changed files with 327 additions and 327 deletions

View File

@@ -3,7 +3,7 @@
#
# keyring.py
#
# Copyright 2011 Patrick Ulbrich <zulu99@gmx.net>
# Copyright 2011, 2012 Patrick Ulbrich <zulu99@gmx.net>
# Copyright 2011 Ralf Hersel <ralf.hersel@gmx.net>
#
# This program is free software; you can redistribute it and/or modify
@@ -32,41 +32,41 @@ from common.account import Account
class Keyring:
def __init__(self):
GLib.set_application_name('mailnag')
self.was_locked = False # True if Dialog shown. Required for Sortorder problem
self.keyring_password = ''
self.defaultKeyring = gnomekeyring.get_default_keyring_sync()
if self.defaultKeyring == None:
self.defaultKeyring = 'login'
self._was_locked = False # True if Dialog shown. Required for Sortorder problem
self._keyring_password = ''
self._defaultKeyring = gnomekeyring.get_default_keyring_sync()
if self._defaultKeyring == None:
self._defaultKeyring = 'login'
while gnomekeyring.get_info_sync(self.defaultKeyring).get_is_locked(): # Keyring locked?
self.message_response = 'cancel' # default response for message dialog
while gnomekeyring.get_info_sync(self._defaultKeyring).get_is_locked(): # Keyring locked?
self._message_response = 'cancel' # default response for message dialog
try:
try: gnomekeyring.unlock_sync(self.defaultKeyring, \
self.keyring_password)
try: gnomekeyring.unlock_sync(self._defaultKeyring, \
self._keyring_password)
except gnomekeyring.IOError:
self.show_keyring_dialog() # get keyring password
self._show_keyring_dialog() # get keyring password
Gtk.main() # wait until dialog is closed
result = gnomekeyring.unlock_sync(self.defaultKeyring, \
self.keyring_password)
result = gnomekeyring.unlock_sync(self._defaultKeyring, \
self._keyring_password)
except gnomekeyring.IOError:
self.show_message(_('Failed to unlock Keyring "{0}".\nWrong password.\n\nDo you want to try again?').format(self.defaultKeyring))
self._show_message(_('Failed to unlock Keyring "{0}".\nWrong password.\n\nDo you want to try again?').format(self._defaultKeyring))
Gtk.main() # wait until dialog is closed
if self.message_response == 'cancel': exit(1) # close application (else: continue getting password)
if self._message_response == 'cancel': exit(1) # close application (else: continue getting password)
def get(self, protocol, user, server): # get password for account from Gnome Keyring
if gnomekeyring.list_item_ids_sync(self.defaultKeyring):
if gnomekeyring.list_item_ids_sync(self._defaultKeyring):
displayNameDict = {}
for identity in gnomekeyring.list_item_ids_sync(self.defaultKeyring):
item = gnomekeyring.item_get_info_sync(self.defaultKeyring, identity)
for identity in gnomekeyring.list_item_ids_sync(self._defaultKeyring):
item = gnomekeyring.item_get_info_sync(self._defaultKeyring, identity)
displayNameDict[item.get_display_name()] = identity
if 'Mailnag password for %s://%s@%s' % (protocol, user, server) in displayNameDict:
if gnomekeyring.item_get_info_sync(self.defaultKeyring, \
if gnomekeyring.item_get_info_sync(self._defaultKeyring, \
displayNameDict['Mailnag password for %s://%s@%s' % \
(protocol, user, server)]).get_secret() != '':
return gnomekeyring.item_get_info_sync(self.defaultKeyring, \
return gnomekeyring.item_get_info_sync(self._defaultKeyring, \
displayNameDict['Mailnag password for %s://%s@%s' % \
(protocol, user, server)]).get_secret()
else:
@@ -84,10 +84,10 @@ class Keyring:
def import_accounts(self): # get email accounts from Gnome-Keyring
accounts = []
if gnomekeyring.list_item_ids_sync(self.defaultKeyring):
if gnomekeyring.list_item_ids_sync(self._defaultKeyring):
displayNameDict = {}
for identity in gnomekeyring.list_item_ids_sync(self.defaultKeyring):
item = gnomekeyring.item_get_info_sync(self.defaultKeyring, identity)
for identity in gnomekeyring.list_item_ids_sync(self._defaultKeyring):
item = gnomekeyring.item_get_info_sync(self._defaultKeyring, identity)
displayNameDict[item.get_display_name()] = identity
for displayName in displayNameDict:
if displayName.startswith('pop://') \
@@ -105,7 +105,7 @@ class Keyring:
if ';' in user:
user = user.split(';')[0]
password = gnomekeyring.item_get_info_sync(self.defaultKeyring, \
password = gnomekeyring.item_get_info_sync(self._defaultKeyring, \
displayNameDict[displayName]).get_secret()
accounts.append(Account(enabled = True, name = "%s (%s)" % (server, user), \
@@ -116,22 +116,22 @@ class Keyring:
def set(self, protocol, user, server, password): # store password in Gnome-Keyring
if password != '':
displayNameDict = {}
for identity in gnomekeyring.list_item_ids_sync(self.defaultKeyring):
item = gnomekeyring.item_get_info_sync(self.defaultKeyring, identity)
for identity in gnomekeyring.list_item_ids_sync(self._defaultKeyring):
item = gnomekeyring.item_get_info_sync(self._defaultKeyring, identity)
displayNameDict[item.get_display_name()] = identity
if 'Mailnag password for %s://%s@%s' % (protocol, user, server) in displayNameDict:
if password != gnomekeyring.item_get_info_sync(self.defaultKeyring, \
if password != gnomekeyring.item_get_info_sync(self._defaultKeyring, \
displayNameDict['Mailnag password for %s://%s@%s' % \
(protocol, user, server)]).get_secret():
gnomekeyring.item_create_sync(self.defaultKeyring, \
gnomekeyring.item_create_sync(self._defaultKeyring, \
gnomekeyring.ITEM_GENERIC_SECRET, \
'Mailnag password for %s://%s@%s' % (protocol, user, server), \
{'application':'Mailnag', 'protocol':protocol, 'user':user, 'server':server}, \
password, True)
else:
gnomekeyring.item_create_sync(self.defaultKeyring, \
gnomekeyring.item_create_sync(self._defaultKeyring, \
gnomekeyring.ITEM_GENERIC_SECRET, \
'Mailnag password for %s://%s@%s' % (protocol, user, server), \
{'application':'Mailnag', 'protocol':protocol, 'user':user, 'server':server}, password, True)
@@ -159,49 +159,49 @@ class Keyring:
gnomekeyring.item_delete_sync(defaultKeyring, displayNameDict[key])
def show_keyring_dialog(self): # dialog to get password to unlock keyring
self.was_locked = True
def _show_keyring_dialog(self): # dialog to get password to unlock keyring
self._was_locked = True
builder = Gtk.Builder()
builder.set_translation_domain(PACKAGE_NAME)
builder.add_from_file(get_data_file("keyring_dialog.ui"))
builder.connect_signals({"gtk_main_quit" : self.exit_keyring_dialog, \
"on_button_cancel_clicked" : self.exit_keyring_dialog, \
"on_button_ok_clicked" : self.ok_keyring_dialog, \
"on_entry_password_activate" : self.ok_keyring_dialog}) # hit RETURN in entry field
self.window = builder.get_object("dialog_keyring")
self.password = builder.get_object("entry_password")
self.window.show()
builder.connect_signals({"gtk_main_quit" : self._exit_keyring_dialog, \
"on_button_cancel_clicked" : self._exit_keyring_dialog, \
"on_button_ok_clicked" : self._ok_keyring_dialog, \
"on_entry_password_activate" : self._ok_keyring_dialog}) # hit RETURN in entry field
self._window = builder.get_object("dialog_keyring")
self._password = builder.get_object("entry_password")
self._window.show()
def exit_keyring_dialog(self, widget): # password dialog exit or cancel clicked
self.window.destroy()
def _exit_keyring_dialog(self, widget): # password dialog exit or cancel clicked
self._window.destroy()
Gtk.main_quit() # terminate loop to allow continuation
def ok_keyring_dialog(self, widget): # password dialog ok clicked
self.keyring_password = self.password.get_text() # get text from widget
self.exit_keyring_dialog(widget)
def _ok_keyring_dialog(self, widget): # password dialog ok clicked
self._keyring_password = self._password.get_text() # get text from widget
self._exit_keyring_dialog(widget)
def show_message(self, message): # dialog to show keyring messages
def _show_message(self, message): # dialog to show keyring messages
builder = Gtk.Builder()
builder.set_translation_domain(PACKAGE_NAME)
builder.add_from_file(get_data_file("message_dialog.ui"))
builder.connect_signals({"gtk_main_quit" : self.exit_message, \
"on_button_cancel_clicked" : self.exit_message, \
"on_button_ok_clicked" : self.ok_message})
self.window = builder.get_object("dialog_message")
self.message = builder.get_object("label_message")
self.message.set_text(message) # put message text into label
self.window.show()
builder.connect_signals({"gtk_main_quit" : self._exit_message, \
"on_button_cancel_clicked" : self._exit_message, \
"on_button_ok_clicked" : self._ok_message})
self._window = builder.get_object("dialog_message")
self._message = builder.get_object("label_message")
self._message.set_text(message) # put message text into label
self._window.show()
def exit_message(self, widget): # keyring message dialog exit or cancel clicked
self.window.destroy()
def _exit_message(self, widget): # keyring message dialog exit or cancel clicked
self._window.destroy()
Gtk.main_quit() # terminate loop to allow continuation
def ok_message(self, widget): # keyring message dialog ok clicked
self.message_response = 'ok'
self.exit_message(widget)
def _ok_message(self, widget): # keyring message dialog ok clicked
self._message_response = 'ok'
self._exit_message(widget)

View File

@@ -3,7 +3,7 @@
#
# accountdialog.py
#
# Copyright 2011 Patrick Ulbrich <zulu99@gmx.net>
# Copyright 2011, 2012 Patrick Ulbrich <zulu99@gmx.net>
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
@@ -28,101 +28,101 @@ from common.i18n import PACKAGE_NAME, _
class AccountDialog:
def __init__(self, parent, acc):
self.acc = acc
self._acc = acc
builder = Gtk.Builder()
builder.set_translation_domain(PACKAGE_NAME)
builder.add_from_file(get_data_file("account_dialog.ui"))
builder.connect_signals({ \
"account_type_changed" : self.__on_cmb_account_type_changed, \
"entry_changed" : self.__on_entry_changed, \
"btn_cancel_clicked" : self.__on_btn_cancel_clicked, \
"btn_save_clicked" : self.__on_btn_save_clicked \
"account_type_changed" : self._on_cmb_account_type_changed, \
"entry_changed" : self._on_entry_changed, \
"btn_cancel_clicked" : self._on_btn_cancel_clicked, \
"btn_save_clicked" : self._on_btn_save_clicked \
})
self.window = builder.get_object("account_dialog")
self.window.set_transient_for(parent)
self._window = builder.get_object("account_dialog")
self._window.set_transient_for(parent)
self.cmb_account_type = builder.get_object("cmb_account_type")
self.entry_account_name = builder.get_object("entry_account_name")
self.entry_account_user = builder.get_object("entry_account_user")
self.entry_account_password = builder.get_object("entry_account_password")
self.entry_account_server = builder.get_object("entry_account_server")
self.entry_account_port = builder.get_object("entry_account_port")
self.label_account_folder = builder.get_object("label_account_folder")
self.entry_account_folder = builder.get_object("entry_account_folder")
self.chk_account_push = builder.get_object("chk_account_push")
self.chk_account_ssl = builder.get_object("chk_account_ssl")
self.button_save = builder.get_object("button_save")
self._cmb_account_type = builder.get_object("cmb_account_type")
self._entry_account_name = builder.get_object("entry_account_name")
self._entry_account_user = builder.get_object("entry_account_user")
self._entry_account_password = builder.get_object("entry_account_password")
self._entry_account_server = builder.get_object("entry_account_server")
self._entry_account_port = builder.get_object("entry_account_port")
self._label_account_folder = builder.get_object("label_account_folder")
self._entry_account_folder = builder.get_object("entry_account_folder")
self._chk_account_push = builder.get_object("chk_account_push")
self._chk_account_ssl = builder.get_object("chk_account_ssl")
self._button_save = builder.get_object("button_save")
self.entry_account_port.set_placeholder_text(_("optional"))
self.entry_account_folder.set_placeholder_text(_("optional"))
self._entry_account_port.set_placeholder_text(_("optional"))
self._entry_account_folder.set_placeholder_text(_("optional"))
def run(self):
self.cmb_account_type.set_active(int(self.acc.imap))
self.entry_account_name.set_text(self.acc.name)
self.entry_account_user.set_text(self.acc.user)
self.entry_account_password.set_text(self.acc.password)
self.entry_account_server.set_text(self.acc.server)
self.entry_account_port.set_text(self.acc.port)
self.entry_account_folder.set_text(self.acc.folder)
self.chk_account_push.set_active(self.acc.idle)
self.chk_account_ssl.set_active(self.acc.ssl)
self._cmb_account_type.set_active(int(self._acc.imap))
self._entry_account_name.set_text(self._acc.name)
self._entry_account_user.set_text(self._acc.user)
self._entry_account_password.set_text(self._acc.password)
self._entry_account_server.set_text(self._acc.server)
self._entry_account_port.set_text(self._acc.port)
self._entry_account_folder.set_text(self._acc.folder)
self._chk_account_push.set_active(self._acc.idle)
self._chk_account_ssl.set_active(self._acc.ssl)
res = self.window.run()
res = self._window.run()
if res == 1:
self.acc.name = self.entry_account_name.get_text()
self.acc.user = self.entry_account_user.get_text()
self.acc.password = self.entry_account_password.get_text()
self.acc.server = self.entry_account_server.get_text()
self.acc.port = self.entry_account_port.get_text()
self.acc.ssl = self.chk_account_ssl.get_active()
self._acc.name = self._entry_account_name.get_text()
self._acc.user = self._entry_account_user.get_text()
self._acc.password = self._entry_account_password.get_text()
self._acc.server = self._entry_account_server.get_text()
self._acc.port = self._entry_account_port.get_text()
self._acc.ssl = self._chk_account_ssl.get_active()
if self.cmb_account_type.get_active() == 0: # POP3
self.acc.imap = False
self.acc.folder = ''
self.acc.idle = False
if self._cmb_account_type.get_active() == 0: # POP3
self._acc.imap = False
self._acc.folder = ''
self._acc.idle = False
else: # IMAP
self.acc.imap = True
self.acc.folder = self.entry_account_folder.get_text()
self.acc.idle = self.chk_account_push.get_active()
self._acc.imap = True
self._acc.folder = self._entry_account_folder.get_text()
self._acc.idle = self._chk_account_push.get_active()
self.window.destroy()
self._window.destroy()
return res
def get_account(self):
return self.acc
return self._acc
def __on_btn_cancel_clicked(self, widget):
def _on_btn_cancel_clicked(self, widget):
pass
def __on_btn_save_clicked(self, widget):
def _on_btn_save_clicked(self, widget):
pass
def __on_entry_changed(self, widget):
def _on_entry_changed(self, widget):
# validate
ok = len(self.entry_account_name.get_text()) > 0 and \
len(self.entry_account_user.get_text()) > 0 and \
len(self.entry_account_password.get_text()) > 0 and \
len(self.entry_account_server.get_text()) > 0
ok = len(self._entry_account_name.get_text()) > 0 and \
len(self._entry_account_user.get_text()) > 0 and \
len(self._entry_account_password.get_text()) > 0 and \
len(self._entry_account_server.get_text()) > 0
self.button_save.set_sensitive(ok)
self._button_save.set_sensitive(ok)
def __on_cmb_account_type_changed(self, widget):
if self.cmb_account_type.get_active() == 0: # POP3
self.label_account_folder.set_visible(False)
self.entry_account_folder.set_visible(False)
self.chk_account_push.set_visible(False)
def _on_cmb_account_type_changed(self, widget):
if self._cmb_account_type.get_active() == 0: # POP3
self._label_account_folder.set_visible(False)
self._entry_account_folder.set_visible(False)
self._chk_account_push.set_visible(False)
else: # IMAP
self.label_account_folder.set_visible(True)
self.entry_account_folder.set_visible(True)
self.chk_account_push.set_visible(True)
self._label_account_folder.set_visible(True)
self._entry_account_folder.set_visible(True)
self._chk_account_push.set_visible(True)

View File

@@ -3,7 +3,7 @@
#
# configwindow.py
#
# Copyright 2011 Patrick Ulbrich <zulu99@gmx.net>
# Copyright 2011, 2012 Patrick Ulbrich <zulu99@gmx.net>
# Copyright 2011 Ralf Hersel <ralf.hersel@gmx.net>
#
# This program is free software; you can redistribute it and/or modify
@@ -38,151 +38,151 @@ class ConfigWindow:
builder.set_translation_domain(PACKAGE_NAME)
builder.add_from_file(get_data_file("config_window.ui"))
builder.connect_signals({ \
"config_window_deleted" : self.__on_config_window_deleted, \
"btn_add_clicked" : self.__on_btn_add_clicked, \
"btn_edit_clicked" : self.__on_btn_edit_clicked, \
"btn_remove_clicked" : self.__on_btn_remove_clicked, \
"treeview_accounts_row_activated" : self.__on_treeview_accounts_row_activated, \
"liststore_accounts_row_deleted" : self.__on_liststore_accounts_row_deleted, \
"liststore_accounts_row_inserted" : self.__on_liststore_accounts_row_inserted, \
"chk_enable_filter_toggled" : self.__on_chk_enable_filter_toggled, \
"chk_script0_toggled" : self.__on_chk_script0_toggled, \
"chk_script1_toggled" : self.__on_chk_script1_toggled \
"config_window_deleted" : self._on_config_window_deleted, \
"btn_add_clicked" : self._on_btn_add_clicked, \
"btn_edit_clicked" : self._on_btn_edit_clicked, \
"btn_remove_clicked" : self._on_btn_remove_clicked, \
"treeview_accounts_row_activated" : self._on_treeview_accounts_row_activated, \
"liststore_accounts_row_deleted" : self._on_liststore_accounts_row_deleted, \
"liststore_accounts_row_inserted" : self._on_liststore_accounts_row_inserted, \
"chk_enable_filter_toggled" : self._on_chk_enable_filter_toggled, \
"chk_script0_toggled" : self._on_chk_script0_toggled, \
"chk_script1_toggled" : self._on_chk_script1_toggled \
})
self.window = builder.get_object("config_window")
self.window.set_icon(GdkPixbuf.Pixbuf.new_from_file_at_size(get_data_file("mailnag.svg"), 48, 48));
self.cfg = read_cfg()
self._window = builder.get_object("config_window")
self._window.set_icon(GdkPixbuf.Pixbuf.new_from_file_at_size(get_data_file("mailnag.svg"), 48, 48));
self._cfg = read_cfg()
#
# account tab
#
self.accounts = AccountList()
self._accounts = AccountList()
self.treeview_accounts = builder.get_object("treeview_accounts")
self.liststore_accounts = builder.get_object("liststore_accounts")
self._treeview_accounts = builder.get_object("treeview_accounts")
self._liststore_accounts = builder.get_object("liststore_accounts")
self.button_edit = builder.get_object("button_edit")
self.button_remove = builder.get_object("button_remove")
self._button_edit = builder.get_object("button_edit")
self._button_remove = builder.get_object("button_remove")
renderer_on = Gtk.CellRendererToggle()
renderer_on.connect("toggled", self.__on_account_toggled) # bind toggle signal
renderer_on.connect("toggled", self._on_account_toggled) # bind toggle signal
column_on = Gtk.TreeViewColumn(_('Enabled'), renderer_on) # Account On/Off
column_on.add_attribute(renderer_on, "active", 1)
column_on.set_alignment(0.5) # center column heading
self.treeview_accounts.append_column(column_on)
self._treeview_accounts.append_column(column_on)
renderer_name = Gtk.CellRendererText()
column_name = Gtk.TreeViewColumn(_('Name'), renderer_name, text=2) # Account Name
self.treeview_accounts.append_column(column_name)
self._treeview_accounts.append_column(column_name)
#
# general tab
#
self.entry_label = builder.get_object("entry_label")
self.spinbutton_interval = builder.get_object("spinbutton_interval")
self.cb_notification_mode = builder.get_object("cb_notification_mode")
self._entry_label = builder.get_object("entry_label")
self._spinbutton_interval = builder.get_object("spinbutton_interval")
self._cb_notification_mode = builder.get_object("cb_notification_mode")
cell = Gtk.CellRendererText()
self.cb_notification_mode.pack_start(cell, True)
self.cb_notification_mode.add_attribute(cell, "text", 0)
self.chk_playsound = builder.get_object("chk_playsound")
self.chk_autostart = builder.get_object("chk_autostart")
self._cb_notification_mode.pack_start(cell, True)
self._cb_notification_mode.add_attribute(cell, "text", 0)
self._chk_playsound = builder.get_object("chk_playsound")
self._chk_autostart = builder.get_object("chk_autostart")
#
# spam filter tab
#
self.chk_enable_filter = builder.get_object("chk_enable_filter")
self.textview_filter = builder.get_object("textview_filter")
self.textbuffer_filter = builder.get_object("textbuffer_filter")
self._chk_enable_filter = builder.get_object("chk_enable_filter")
self._textview_filter = builder.get_object("textview_filter")
self._textbuffer_filter = builder.get_object("textbuffer_filter")
#
# events tab
#
self.chk_script0 = builder.get_object("chk_script0")
self.filechooser_script0 = builder.get_object("filechooser_script0")
self.chk_script1 = builder.get_object("chk_script1")
self.filechooser_script1 = builder.get_object("filechooser_script1")
self._chk_script0 = builder.get_object("chk_script0")
self._filechooser_script0 = builder.get_object("filechooser_script0")
self._chk_script1 = builder.get_object("chk_script1")
self._filechooser_script1 = builder.get_object("filechooser_script1")
#
# about tab
#
self.image_logo = builder.get_object("image_logo")
self._image_logo = builder.get_object("image_logo")
pb = GdkPixbuf.Pixbuf.new_from_file_at_size(get_data_file("mailnag.svg"), 200, 200)
self.image_logo.set_from_pixbuf(pb)
self._image_logo.set_from_pixbuf(pb)
self.load_config()
self.window.show()
self._load_config()
self._window.show()
def load_config(self):
self.entry_label.set_text(self.cfg.get('general', 'messagetray_label'))
self.spinbutton_interval.set_value(int(self.cfg.get('general', 'check_interval')))
self.cb_notification_mode.set_active(int(self.cfg.get('general', 'notification_mode')))
self.chk_playsound.set_active(bool(int(self.cfg.get('general', 'playsound'))))
self.chk_autostart.set_active(bool(int(self.cfg.get('general', 'autostart'))))
def _load_config(self):
self._entry_label.set_text(self._cfg.get('general', 'messagetray_label'))
self._spinbutton_interval.set_value(int(self._cfg.get('general', 'check_interval')))
self._cb_notification_mode.set_active(int(self._cfg.get('general', 'notification_mode')))
self._chk_playsound.set_active(bool(int(self._cfg.get('general', 'playsound'))))
self._chk_autostart.set_active(bool(int(self._cfg.get('general', 'autostart'))))
self.chk_enable_filter.set_active(bool(int(self.cfg.get('filter', 'filter_enabled'))))
self.textbuffer_filter.set_text(self.cfg.get('filter', 'filter_text'))
self._chk_enable_filter.set_active(bool(int(self._cfg.get('filter', 'filter_enabled'))))
self._textbuffer_filter.set_text(self._cfg.get('filter', 'filter_text'))
self.chk_script0.set_active(bool(int(self.cfg.get('script', 'script0_enabled'))))
self._chk_script0.set_active(bool(int(self._cfg.get('script', 'script0_enabled'))))
tmp = self.cfg.get('script', 'script0_file')
tmp = self._cfg.get('script', 'script0_file')
if len(tmp) > 0:
self.filechooser_script0.set_filename(tmp)
self._filechooser_script0.set_filename(tmp)
self.chk_script1.set_active(bool(int(self.cfg.get('script', 'script1_enabled'))))
self._chk_script1.set_active(bool(int(self._cfg.get('script', 'script1_enabled'))))
tmp = self.cfg.get('script', 'script1_file')
tmp = self._cfg.get('script', 'script1_file')
if len(tmp) > 0:
self.filechooser_script1.set_filename(tmp)
self._filechooser_script1.set_filename(tmp)
self.accounts.load_from_cfg(self.cfg)
self._accounts.load_from_cfg(self._cfg)
if len(self.accounts) == 0:
self.accounts.import_from_keyring()
if len(self.accounts) > 0 and \
(not self.show_yesno_dialog(_("Mailnag found %s mail accounts on this computer.\n\nDo you want to import them?") % len(self.accounts))):
del self.accounts[:]
if len(self._accounts) == 0:
self._accounts.import_from_keyring()
if len(self._accounts) > 0 and \
(not self._show_yesno_dialog(_("Mailnag found %s mail accounts on this computer.\n\nDo you want to import them?") % len(self._accounts))):
del self._accounts[:]
for acc in self.accounts:
for acc in self._accounts:
row = [acc, acc.enabled, acc.name]
self.liststore_accounts.append(row)
self.select_path((0,))
self._liststore_accounts.append(row)
self._select_path((0,))
def save_config(self):
self.cfg.set('general', 'messagetray_label', self.entry_label.get_text())
self.cfg.set('general', 'check_interval', int(self.spinbutton_interval.get_value()))
self.cfg.set('general', 'notification_mode', int(self.cb_notification_mode.get_active()))
self.cfg.set('general', 'playsound',int(self.chk_playsound.get_active()))
autostart = self.chk_autostart.get_active()
self.cfg.set('general', 'autostart', int(autostart))
def _save_config(self):
self._cfg.set('general', 'messagetray_label', self._entry_label.get_text())
self._cfg.set('general', 'check_interval', int(self._spinbutton_interval.get_value()))
self._cfg.set('general', 'notification_mode', int(self._cb_notification_mode.get_active()))
self._cfg.set('general', 'playsound',int(self._chk_playsound.get_active()))
autostart = self._chk_autostart.get_active()
self._cfg.set('general', 'autostart', int(autostart))
self.cfg.set('filter', 'filter_enabled', int(self.chk_enable_filter.get_active()))
start, end = self.textbuffer_filter.get_bounds()
self.cfg.set('filter', 'filter_text', self.textbuffer_filter.get_text(start, end, True))
self._cfg.set('filter', 'filter_enabled', int(self._chk_enable_filter.get_active()))
start, end = self._textbuffer_filter.get_bounds()
self._cfg.set('filter', 'filter_text', self._textbuffer_filter.get_text(start, end, True))
self.cfg.set('script', 'script0_enabled', int(self.chk_script0.get_active()))
tmp = self.filechooser_script0.get_filename()
self._cfg.set('script', 'script0_enabled', int(self._chk_script0.get_active()))
tmp = self._filechooser_script0.get_filename()
if tmp == None: tmp = ""
self.cfg.set('script', 'script0_file', tmp)
self._cfg.set('script', 'script0_file', tmp)
self.cfg.set('script', 'script1_enabled', int(self.chk_script1.get_active()))
tmp = self.filechooser_script1.get_filename()
self._cfg.set('script', 'script1_enabled', int(self._chk_script1.get_active()))
tmp = self._filechooser_script1.get_filename()
if tmp == None: tmp = ""
self.cfg.set('script', 'script1_file', tmp)
self._cfg.set('script', 'script1_file', tmp)
self.accounts.save_to_cfg(self.cfg)
self._accounts.save_to_cfg(self._cfg)
write_cfg(self.cfg)
write_cfg(self._cfg)
if autostart: self.create_autostart()
else: self.delete_autostart()
if autostart: self._create_autostart()
else: self._delete_autostart()
def show_yesno_dialog(self, text): # Show YesNo Dialog
message = Gtk.MessageDialog(self.window, Gtk.DialogFlags.MODAL, \
def _show_yesno_dialog(self, text): # Show YesNo Dialog
message = Gtk.MessageDialog(self._window, Gtk.DialogFlags.MODAL, \
Gtk.MessageType.QUESTION, Gtk.ButtonsType.YES_NO, text)
resp = message.run() # show dialog window
message.destroy() # close dialog
@@ -190,8 +190,8 @@ class ConfigWindow:
else: return False # if NO clicked
def get_selected_account(self): # return selected row
treeselection = self.treeview_accounts.get_selection() # get tree_selection object
def _get_selected_account(self): # return selected row
treeselection = self._treeview_accounts.get_selection() # get tree_selection object
selection = treeselection.get_selected() # get selected tupel (model, iter)
model, iter = selection # get selected iter
if iter != None: acc = model.get_value(iter, 0) # get account object from treeviews 1. column
@@ -199,22 +199,22 @@ class ConfigWindow:
return acc, model, iter
def select_path(self, path): # select path in treeview
treeselection = self.treeview_accounts.get_selection() # get tree selection object
def _select_path(self, path): # select path in treeview
treeselection = self._treeview_accounts.get_selection() # get tree selection object
treeselection.select_path(path) # select path
self.treeview_accounts.grab_focus() # put focus on treeview
self._treeview_accounts.grab_focus() # put focus on treeview
def edit_account(self):
acc, model, iter = self.get_selected_account()
def _edit_account(self):
acc, model, iter = self._get_selected_account()
if iter != None:
d = AccountDialog(self.window, acc)
d = AccountDialog(self._window, acc)
if d.run() == 1:
model.set_value(iter, 2, acc.name)
def create_autostart(self):
def _create_autostart(self):
curdir = os.getcwd() # get working directory
exec_file = os.path.join(curdir, "mailnag") # path of the shell script to start mailnag.py
@@ -239,88 +239,88 @@ class ConfigWindow:
f.close()
def delete_autostart(self):
def _delete_autostart(self):
autostart_folder = "%s/.config/autostart/" % (os.path.expanduser("~/"))
autostart_file = autostart_folder + "mailnag.desktop"
if os.path.exists(autostart_file):
os.remove(autostart_file)
def __on_account_toggled(self, cell, path): # chk_box account_on toggled
model = self.liststore_accounts
def _on_account_toggled(self, cell, path): # chk_box account_on toggled
model = self._liststore_accounts
iter = model.get_iter(path)
acc = model.get_value(iter, 0)
acc.enabled = not acc.enabled
self.liststore_accounts.set_value(iter, 1, not cell.get_active())
self._liststore_accounts.set_value(iter, 1, not cell.get_active())
def __on_btn_add_clicked(self, widget):
def _on_btn_add_clicked(self, widget):
acc = Account(enabled = True, name = '')
d = AccountDialog(self.window, acc)
d = AccountDialog(self._window, acc)
if d.run() == 1:
self.accounts.append(acc)
self._accounts.append(acc)
row = [acc, acc.enabled, acc.name]
iter = self.liststore_accounts.append(row)
model = self.treeview_accounts.get_model()
iter = self._liststore_accounts.append(row)
model = self._treeview_accounts.get_model()
path = model.get_path(iter)
self.treeview_accounts.set_cursor(path, None, False)
self.treeview_accounts.grab_focus()
self._treeview_accounts.set_cursor(path, None, False)
self._treeview_accounts.grab_focus()
def __on_btn_edit_clicked(self, widget):
self.edit_account()
def _on_btn_edit_clicked(self, widget):
self._edit_account()
def __on_btn_remove_clicked(self, widget):
acc, model, iter = self.get_selected_account()
def _on_btn_remove_clicked(self, widget):
acc, model, iter = self._get_selected_account()
if iter != None:
if self.show_yesno_dialog(_('Delete this account:') + \
if self._show_yesno_dialog(_('Delete this account:') + \
'\n\n' + acc.name):
p = model.get_path(iter)
if not p.prev():
p.next()
self.select_path(p) # select prev/next account
self._select_path(p) # select prev/next account
model.remove(iter) # delete in treeview
self.accounts.remove(acc) # delete in accounts list
self._accounts.remove(acc) # delete in accounts list
def __on_treeview_accounts_row_activated(self, treeview, path, view_column):
self.edit_account()
def _on_treeview_accounts_row_activated(self, treeview, path, view_column):
self._edit_account()
def __on_liststore_accounts_row_deleted(self, model, path):
self.button_edit.set_sensitive(len(model) > 0)
self.button_remove.set_sensitive(len(model) > 0)
def _on_liststore_accounts_row_deleted(self, model, path):
self._button_edit.set_sensitive(len(model) > 0)
self._button_remove.set_sensitive(len(model) > 0)
def __on_liststore_accounts_row_inserted(self, model, path, user_param):
self.button_edit.set_sensitive(len(model) > 0)
self.button_remove.set_sensitive(len(model) > 0)
def _on_liststore_accounts_row_inserted(self, model, path, user_param):
self._button_edit.set_sensitive(len(model) > 0)
self._button_remove.set_sensitive(len(model) > 0)
def __on_chk_enable_filter_toggled(self, widget):
self.textview_filter.set_sensitive(self.chk_enable_filter.get_active())
def _on_chk_enable_filter_toggled(self, widget):
self._textview_filter.set_sensitive(self._chk_enable_filter.get_active())
def __on_chk_script0_toggled(self, widget):
self.filechooser_script0.set_sensitive(self.chk_script0.get_active())
def _on_chk_script0_toggled(self, widget):
self._filechooser_script0.set_sensitive(self._chk_script0.get_active())
def __on_chk_script1_toggled(self, widget):
self.filechooser_script1.set_sensitive(self.chk_script1.get_active())
def _on_chk_script1_toggled(self, widget):
self._filechooser_script1.set_sensitive(self._chk_script1.get_active())
def __save_and_quit(self):
self.save_config()
def _save_and_quit(self):
self._save_config()
Gtk.main_quit()
def __on_config_window_deleted(self, widget, event):
self.__save_and_quit()
def _on_config_window_deleted(self, widget, event):
self._save_and_quit()

View File

@@ -38,30 +38,30 @@ from daemon.pid import Pid
class MailChecker:
def __init__(self, cfg):
self.MAIL_LIST_LIMIT = 10 # prevent flooding of the messaging tray
self.firstcheck = True; # first check after startup
self.mailcheck_lock = threading.Lock()
self.mail_list = []
self.mailsyncer = MailSyncer(cfg)
self.reminder = Reminder()
self.pid = Pid()
self.cfg = cfg
self._firstcheck = True; # first check after startup
self._mailcheck_lock = threading.Lock()
self._mail_list = []
self._mailsyncer = MailSyncer(cfg)
self._reminder = Reminder()
self._pid = Pid()
self._cfg = cfg
# dict that tracks all notifications that need to be closed
self.notifications = {}
self._notifications = {}
self.reminder.load()
self._reminder.load()
Notify.init(cfg.get('general', 'messagetray_label')) # initialize Notification
def check(self, accounts):
with self.mailcheck_lock:
with self._mailcheck_lock:
print 'Checking email accounts at:', time.asctime()
self.pid.kill() # kill all zombies
self._pid.kill() # kill all zombies
if not is_online():
print 'Error: No internet connection'
return
self.mail_list = self.mailsyncer.sync(accounts)
self._mail_list = self._mailsyncer.sync(accounts)
unseen_mails = []
new_mails = []
@@ -69,11 +69,11 @@ class MailChecker:
script_data = ""
script_data_mailcount = 0
for mail in self.mail_list:
if self.reminder.contains(mail.id): # mail was fetched before
if self.reminder.unseen(mail.id): # mail was not marked as seen
for mail in self._mail_list:
if self._reminder.contains(mail.id): # mail was fetched before
if self._reminder.unseen(mail.id): # mail was not marked as seen
unseen_mails.append(mail)
if self.firstcheck:
if self._firstcheck:
new_mails.append(mail)
else: # mail is fetched the first time
@@ -84,39 +84,39 @@ class MailChecker:
script_data = str(script_data_mailcount) + script_data
if len(self.mail_list) == 0:
if len(self._mail_list) == 0:
# no mails (e.g. email client has been launched) -> close notifications
for n in self.notifications.itervalues():
for n in self._notifications.itervalues():
n.close()
self.notifications = {}
self._notifications = {}
elif len(new_mails) > 0:
if self.cfg.get('general', 'notification_mode') == '1':
self.__notify_summary(unseen_mails)
if self._cfg.get('general', 'notification_mode') == '1':
self._notify_summary(unseen_mails)
else:
self.__notify_single(new_mails)
self._notify_single(new_mails)
if self.cfg.get('general', 'playsound') == '1': # play sound?
gstplay(get_data_file(self.cfg.get('general', 'soundfile')))
if self._cfg.get('general', 'playsound') == '1': # play sound?
gstplay(get_data_file(self._cfg.get('general', 'soundfile')))
self.reminder.save(self.mail_list)
self.__run_user_scripts("on_mail_check", script_data) # process user scripts
self._reminder.save(self._mail_list)
self._run_user_scripts("on_mail_check", script_data) # process user scripts
sys.stdout.flush() # write stdout to log file
self.firstcheck = False
self._firstcheck = False
return
def dispose(self):
for n in self.notifications.itervalues():
for n in self._notifications.itervalues():
n.close()
def __notify_summary(self, unseen_mails):
def _notify_summary(self, unseen_mails):
summary = ""
body = ""
if len(self.notifications) == 0:
self.notifications['0'] = self.__get_notification(" ", None, None) # empty string will emit a gtk warning
if len(self._notifications) == 0:
self._notifications['0'] = self._get_notification(" ", None, None) # empty string will emit a gtk warning
ubound = len(unseen_mails) if len(unseen_mails) <= self.MAIL_LIST_LIMIT else self.MAIL_LIST_LIMIT
@@ -131,60 +131,60 @@ class MailChecker:
else:
summary = _("You have a new mail.")
self.notifications['0'].update(summary, body, "mail-unread")
self.notifications['0'].show()
self._notifications['0'].update(summary, body, "mail-unread")
self._notifications['0'].show()
def __notify_single(self, new_mails):
def _notify_single(self, new_mails):
for mail in new_mails:
n = self.__get_notification(mail.sender, mail.subject, "mail-unread")
n = self._get_notification(mail.sender, mail.subject, "mail-unread")
notification_id = str(id(n))
n.add_action("mark-as-read", _("Mark as read"), self.__notification_action_handler, (mail, notification_id), None)
n.add_action("mark-as-read", _("Mark as read"), self._notification_action_handler, (mail, notification_id), None)
n.show()
self.notifications[notification_id] = n
self._notifications[notification_id] = n
def __get_notification(self, summary, body, icon):
def _get_notification(self, summary, body, icon):
n = Notify.Notification.new(summary, body, icon)
n.set_category("email")
n.add_action("default", "default", self.__notification_action_handler, None, None)
n.add_action("default", "default", self._notification_action_handler, None, None)
return n
def __notification_action_handler(self, n, action, user_data):
with self.mailcheck_lock:
def _notification_action_handler(self, n, action, user_data):
with self._mailcheck_lock:
if action == "default":
mailclient = get_default_mail_reader()
if mailclient != None:
self.pid.append(subprocess.Popen(mailclient))
self._pid.append(subprocess.Popen(mailclient))
# clicking the notification bubble has closed all notifications
# so clear the reference array as well.
self.notifications = {}
self._notifications = {}
elif action == "mark-as-read":
self.reminder.set_to_seen(user_data[0].id)
self.reminder.save(self.mail_list)
self._reminder.set_to_seen(user_data[0].id)
self._reminder.save(self._mail_list)
# clicking the action has closed the notification
# so remove its reference
del self.notifications[user_data[1]]
del self._notifications[user_data[1]]
def __run_user_scripts(self, event, data):
def _run_user_scripts(self, event, data):
if event == "on_mail_check":
if self.cfg.get('script', 'script0_enabled') == '1':
script_file = self.cfg.get('script', 'script0_file')
if self._cfg.get('script', 'script0_enabled') == '1':
script_file = self._cfg.get('script', 'script0_file')
if script_file != '' and os.path.exists(script_file):
self.pid.append(subprocess.Popen("%s %s" % (script_file, data), shell = True))
self._pid.append(subprocess.Popen("%s %s" % (script_file, data), shell = True))
else:
print 'Warning: cannot execute script:', script_file
if (data != '0') and (self.cfg.get('script', 'script1_enabled') == '1'):
script_file = self.cfg.get('script', 'script1_file')
if (data != '0') and (self._cfg.get('script', 'script1_enabled') == '1'):
script_file = self._cfg.get('script', 'script1_file')
if script_file != '' and os.path.exists(script_file):
self.pid.append(subprocess.Popen("%s %s" % (script_file, data), shell = True))
self._pid.append(subprocess.Popen("%s %s" % (script_file, data), shell = True))
else:
print 'Warning: cannot execute script:', script_file

View File

@@ -33,17 +33,17 @@ from daemon.mail import Mail
class Mails:
def __init__(self, cfg, accounts):
self.cfg = cfg
self.accounts = accounts
self._cfg = cfg
self._accounts = accounts
def get_mail(self, sort_order = None):
mail_list = [] # initialize list of mails
mail_ids = [] # initialize list of mail ids
filter_enabled = bool(int(self.cfg.get('filter', 'filter_enabled'))) # get filter switch
filter_enabled = bool(int(self._cfg.get('filter', 'filter_enabled'))) # get filter switch
for acc in self.accounts:
for acc in self._accounts:
srv = acc.get_connection(use_existing = True) # get server connection for this account
if srv == None:
continue # continue with next account if server is empty
@@ -77,29 +77,29 @@ class Mails:
continue
try:
try:
sender = self.__format_header('sender', msg['From']) # get sender and format it
sender = self._format_header('sender', msg['From']) # get sender and format it
except KeyError:
print "KeyError exception for key 'From' in message." # debug
sender = self.__format_header('sender', msg['from'])
sender = self._format_header('sender', msg['from'])
except:
print "Could not get sender from IMAP message." # debug
sender = "Error in sender"
try:
try:
datetime, seconds = self.__format_header('date', msg['Date']) # get date and format it
datetime, seconds = self._format_header('date', msg['Date']) # get date and format it
except KeyError:
print "KeyError exception for key 'Date' in message." # debug
datetime, seconds = self.__format_header('date', msg['date'])
datetime, seconds = self._format_header('date', msg['date'])
except:
print "Could not get date from IMAP message." # debug
datetime = time.strftime('%Y.%m.%d %X') # take current time as "2010.12.31 13:57:04"
seconds = time.time() # take current time as seconds
try:
try:
subject = self.__format_header('subject', msg['Subject']) # get subject and format it
subject = self._format_header('subject', msg['Subject']) # get subject and format it
except KeyError:
print "KeyError exception for key 'Subject' in message." # debug
subject = self.__format_header('subject', msg['subject'])
subject = self._format_header('subject', msg['subject'])
except:
print "Could not get subject from IMAP message." # debug
subject = _('No subject')
@@ -113,7 +113,7 @@ class Mails:
id = str(hash(acc.server + acc.user + sender + subject)) # create fallback id
if id not in mail_ids: # prevent duplicates caused by Gmail labels
if not (filter_enabled and self.__in_filter(sender + subject)): # check filter
if not (filter_enabled and self._in_filter(sender + subject)): # check filter
mail_list.append(Mail(seconds, subject, \
sender, datetime, id, acc.get_id()))
mail_ids.append(id) # add id to list
@@ -138,29 +138,29 @@ class Mails:
continue
try:
try:
sender = self.__format_header('sender', msg['From']) # get sender and format it
sender = self._format_header('sender', msg['From']) # get sender and format it
except KeyError:
print "KeyError exception for key 'From' in message." # debug
sender = self.__format_header('sender', msg['from'])
sender = self._format_header('sender', msg['from'])
except:
print "Could not get sender from POP message." # debug
sender = "Error in sender"
try:
try:
datetime, seconds = self.__format_header('date', msg['Date']) # get date and format it
datetime, seconds = self._format_header('date', msg['Date']) # get date and format it
except KeyError:
print "KeyError exception for key 'Date' in message." # debug
datetime, seconds = self.__format_header('date', msg['date'])
datetime, seconds = self._format_header('date', msg['date'])
except:
print "Could not get date from POP message." # debug
datetime = time.strftime('%Y.%m.%d %X') # take current time as "2010.12.31 13:57:04"
seconds = time.time() # take current time as seconds
try:
try:
subject = self.__format_header('subject', msg['Subject']) # get subject and format it
subject = self._format_header('subject', msg['Subject']) # get subject and format it
except KeyError:
print "KeyError exception for key 'Subject' in message." # debug
subject = self.__format_header('subject', msg['subject'])
subject = self._format_header('subject', msg['subject'])
except:
print "Could not get subject from POP message."
subject = _('No subject')
@@ -175,7 +175,7 @@ class Mails:
else:
id = acc.user + uidl.split(' ')[2] # create unique id
if not (filter_enabled and self.__in_filter(sender + subject)): # check filter
if not (filter_enabled and self._in_filter(sender + subject)): # check filter
mail_list.append(Mail(seconds, subject, sender, \
datetime, id, acc.get_id()))
@@ -187,9 +187,9 @@ class Mails:
return mail_list
def __in_filter(self, sendersubject): # check if filter appears in sendersubject
def _in_filter(self, sendersubject): # check if filter appears in sendersubject
status = False
filter_text = self.cfg.get('filter', 'filter_text')
filter_text = self._cfg.get('filter', 'filter_text')
filter_list = filter_text.replace('\n', '').split(',') # convert text to list
for filter_item in filter_list:
filter_stripped_item = filter_item.strip() # remove CR and white space
@@ -217,17 +217,17 @@ class Mails:
return mail_list
def __format_header(self, field, content): # format sender, date, subject etc.
def _format_header(self, field, content): # format sender, date, subject etc.
if field == 'sender':
try:
sender_real, sender_addr = email.utils.parseaddr(content) # get the two parts of the sender
sender_real = self.__convert(sender_real)
sender_addr = self.__convert(sender_addr)
sender_real = self._convert(sender_real)
sender_addr = self._convert(sender_addr)
sender = (sender_real, sender_addr) # create decoded tupel
except:
sender = ('','Error: cannot format sender')
sender_format = self.cfg.get('general', 'sender_format')
sender_format = self._cfg.get('general', 'sender_format')
if sender_format == '1' and sender[0] != '': # real sender name if not empty
sender = sender_real
else:
@@ -248,13 +248,13 @@ class Mails:
if field == 'subject':
try:
subject = self.__convert(content)
subject = self._convert(content)
except:
subject = 'Error: cannot format subject'
return subject
def __convert(self, raw_content): # decode and concatenate multi-coded header parts
def _convert(self, raw_content): # decode and concatenate multi-coded header parts
content = raw_content.replace('\n',' ') # replace newline by space
content = content.replace('?==?','?= =?') # workaround a bug in email.header.decode_header()
tupels = decode_header(content) # list of (text_part, charset) tupels