Esempio n. 1
0
def main():
	global mailchecker, mainloop, idlers
	
	mainloop = None
	
	set_procname("mailnag")
	
	GObject.threads_init()
	
	signal.signal(signal.SIGTERM, sig_handler)
	
	try:
		write_pid() # write Mailnag's process id to file
		cfg = read_config()
		
		if (cfg == None):
			print 'Error: Cannot find configuration file. Please run mailnag_config first.'
			exit(1)
		
		accounts = AccountList()
		accounts.load_from_cfg(cfg, enabled_only = True)
		
		mailchecker = MailChecker(cfg, accounts)
		
		# immediate check
		mailchecker.check(firstcheck = True)
		
		# start polling thread for POP3 accounts and
		# IMAP accounts without idle support
		if sum(1 for acc in accounts if ((not acc.imap ) or (acc.imap and not acc.idle))) > 0:
			check_interval = int(cfg.get('general', 'check_interval'))
			GObject.timeout_add_seconds(60 * check_interval, mailchecker.check)
		
		# start idler threads for IMAP accounts with idle support
		if sum(1 for acc in accounts if (acc.imap and acc.idle)) > 0:
			idlers = Idlers(accounts, mailchecker.check)
			idlers.run()
		
		mainloop = GObject.MainLoop()
		mainloop.run()
	except KeyboardInterrupt:
		pass # ctrl+c pressed
	finally:
		cleanup()
Esempio n. 2
0
    def __init__(self):
        builder = Gtk.Builder()
        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,
            }
        )

        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.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")

        renderer_on = Gtk.CellRendererToggle()
        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)

        renderer_name = Gtk.CellRendererText()
        column_name = Gtk.TreeViewColumn(_("Name"), renderer_name, text=2)  # Account 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")
        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")

        #
        # 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")

        #
        # 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")

        #
        # about tab
        #
        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.load_config()
        self.window.show()
Esempio n. 3
0
class ConfigWindow:
    def __init__(self):
        builder = Gtk.Builder()
        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,
            }
        )

        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.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")

        renderer_on = Gtk.CellRendererToggle()
        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)

        renderer_name = Gtk.CellRendererText()
        column_name = Gtk.TreeViewColumn(_("Name"), renderer_name, text=2)  # Account 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")
        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")

        #
        # 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")

        #
        # 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")

        #
        # about tab
        #
        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.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"))))

        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"))))

        tmp = self.cfg.get("script", "script0_file")
        if len(tmp) > 0:
            self.filechooser_script0.set_filename(tmp)

        self.chk_script1.set_active(bool(int(self.cfg.get("script", "script1_enabled"))))

        tmp = self.cfg.get("script", "script1_file")
        if len(tmp) > 0:
            self.filechooser_script1.set_filename(tmp)

        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[:]

        for acc in self.accounts:
            row = [acc, acc.enabled, acc.name]
            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))

        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()
        if tmp == None:
            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()
        if tmp == None:
            tmp = ""
        self.cfg.set("script", "script1_file", tmp)

        self.accounts.save_to_cfg(self.cfg)

        write_cfg(self.cfg)

        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, Gtk.MessageType.QUESTION, Gtk.ButtonsType.YES_NO, text
        )
        resp = message.run()  # show dialog window
        message.destroy()  # close dialog
        if resp == Gtk.ResponseType.YES:
            return True  # if YES clicked
        else:
            return False  # if NO clicked

    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
        else:
            acc = None
        return acc, model, iter

    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

    def edit_account(self):
        acc, model, iter = self.get_selected_account()
        if iter != None:
            d = AccountDialog(self.window)

            d.cmb_account_type.set_active(acc.imap)

            d.entry_account_name.set_text(acc.name)
            d.entry_account_user.set_text(acc.user)
            d.entry_account_password.set_text(acc.password)
            d.entry_account_server.set_text(acc.server)
            d.entry_account_port.set_text(acc.port)
            d.entry_account_folder.set_text(acc.folder)
            d.chk_account_push.set_active(acc.idle)
            d.chk_account_ssl.set_active(acc.ssl)

            res = d.run()

            if res == 1:
                acc.name = d.entry_account_name.get_text()
                acc.user = d.entry_account_user.get_text()
                acc.password = d.entry_account_password.get_text()
                acc.server = d.entry_account_server.get_text()
                acc.port = d.entry_account_port.get_text()
                acc.ssl = d.chk_account_ssl.get_active()

                if d.cmb_account_type.get_active() == 0:  # POP3
                    acc.imap = False
                    acc.folder = ""
                    acc.idle = False
                else:  # IMAP
                    acc.imap = True
                    acc.folder = d.entry_account_folder.get_text()
                    acc.idle = d.chk_account_push.get_active()

                model.set_value(iter, 2, acc.name)

            d.destroy()

    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

        content = (
            "\n"
            + "[Desktop Entry]\n"
            + "Type=Application\n"
            + "Exec="
            + exec_file
            + "\n"
            + "Hidden=false\n"
            + "NoDisplay=false\n"
            + "X-GNOME-Autostart-enabled=true\n"
            + "Name=Mailnag\n"
            + "Comment=Email notifier for GNOME 3\n"
            "OnlyShowIn=GNOME;\n"
            "AutostartCondition=GNOME3 if-session gnome"
        )

        autostart_folder = "%s/.config/autostart/" % (os.path.expanduser("~/"))
        if not os.path.exists(autostart_folder):
            os.makedirs(autostart_folder)
        autostart_file = autostart_folder + "mailnag.desktop"
        f = open(autostart_file, "w")
        f.write(content)  # create it
        f.close()

    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
        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())

    def __on_btn_add_clicked(self, widget):
        d = AccountDialog(self.window)
        res = d.run()

        if res == 1:
            if d.cmb_account_type.get_active() == 0:  # POP3
                imap = False
                folder = ""
                idle = False
            else:  # IMAP
                imap = True
                folder = d.entry_account_folder.get_text()
                idle = d.chk_account_push.get_active()

            acc = Account(
                enabled=True,
                name=d.entry_account_name.get_text(),
                user=d.entry_account_user.get_text(),
                password=d.entry_account_password.get_text(),
                server=d.entry_account_server.get_text(),
                port=d.entry_account_port.get_text(),
                ssl=d.chk_account_ssl.get_active(),
                imap=imap,
                idle=idle,
                folder=folder,
            )
            self.accounts.append(acc)

            row = [acc, True, acc.name]
            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()

        d.destroy()

    def __on_btn_edit_clicked(self, widget):
        self.edit_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:") + "\n\n" + acc.name):

                p = model.get_path(iter)
                if not p.prev():
                    p.next()
                self.select_path(p)  # select prev/next account

                model.remove(iter)  # delete in treeview
                self.accounts.remove(acc)  # delete in accounts list

    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_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_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 __save_and_quit(self):
        self.save_config()
        Gtk.main_quit()

    def __on_config_window_deleted(self, widget, event):
        self.__save_and_quit()
Esempio n. 4
0
	def __init__(self):
		builder = Gtk.Builder()
		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 \
		})

		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._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")

		renderer_on = Gtk.CellRendererToggle()
		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)

		renderer_name = Gtk.CellRendererText()
		column_name = Gtk.TreeViewColumn(_('Name'), renderer_name, text=2)	# Account 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")
		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")
		
		#
		# 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")	

		#
		# 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")
		
		#
		# about tab
		#
		self._image_logo = builder.get_object("image_logo")
		pb = GdkPixbuf.Pixbuf.new_from_file_at_size(get_data_file("mailnag.svg"), 180, 180)
		pb = pb.new_subpixbuf(0, 10, 180, 146) # crop whitespace at the bottom
		self._image_logo.set_from_pixbuf(pb)
		self._label_app_desc = builder.get_object("label_app_desc")
		self._label_app_desc.set_markup("<span font=\"24\"><b>Mailnag</b></span>\nVersion %s" % str(APP_VERSION))

		self._load_config()
		self._window.show()
Esempio n. 5
0
class ConfigWindow:
	def __init__(self):
		builder = Gtk.Builder()
		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 \
		})

		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._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")

		renderer_on = Gtk.CellRendererToggle()
		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)

		renderer_name = Gtk.CellRendererText()
		column_name = Gtk.TreeViewColumn(_('Name'), renderer_name, text=2)	# Account 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")
		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")
		
		#
		# 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")	

		#
		# 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")
		
		#
		# about tab
		#
		self._image_logo = builder.get_object("image_logo")
		pb = GdkPixbuf.Pixbuf.new_from_file_at_size(get_data_file("mailnag.svg"), 180, 180)
		pb = pb.new_subpixbuf(0, 10, 180, 146) # crop whitespace at the bottom
		self._image_logo.set_from_pixbuf(pb)
		self._label_app_desc = builder.get_object("label_app_desc")
		self._label_app_desc.set_markup("<span font=\"24\"><b>Mailnag</b></span>\nVersion %s" % str(APP_VERSION))

		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'))))

		
		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'))))
		
		tmp = self._cfg.get('script', 'script0_file')
		if len(tmp) > 0:
			self._filechooser_script0.set_filename(tmp)
		
		self._chk_script1.set_active(bool(int(self._cfg.get('script', 'script1_enabled'))))
		
		tmp = self._cfg.get('script', 'script1_file')
		if len(tmp) > 0:
			self._filechooser_script1.set_filename(tmp)
		
		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[:]

		for acc in self._accounts:
			row = [acc, acc.enabled, acc.name]
			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))

		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()
		if tmp == None: 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()
		if tmp == None: tmp = ""
		self._cfg.set('script', 'script1_file', tmp)
		
		self._accounts.save_to_cfg(self._cfg)
				
		write_cfg(self._cfg)

		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, \
			Gtk.MessageType.QUESTION, Gtk.ButtonsType.YES_NO, text)
		resp = message.run()											# show dialog window
		message.destroy()												# close dialog
		if resp == Gtk.ResponseType.YES: return True					# if YES clicked
		else: return False												# if NO clicked
	
	
	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
		else: acc = None
		return acc, model, iter
	
	
	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


	def _edit_account(self):
		acc, model, iter = self._get_selected_account()
		if iter != None:
			d = AccountDialog(self._window, acc)
			
			if d.run() == 1:
				model.set_value(iter, 2, acc.name)


	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

		content = "\n" + \
		"[Desktop Entry]\n" + \
		"Type=Application\n" + \
		"Exec=" + exec_file + "\n" + \
		"Hidden=false\n" + \
		"NoDisplay=false\n" + \
		"X-GNOME-Autostart-enabled=true\n" + \
		"Name=Mailnag\n" + \
		"Comment=Email notifier for GNOME 3\n" \
		"OnlyShowIn=GNOME;\n" \
		"AutostartCondition=GNOME3 if-session gnome"

		autostart_folder = "%s/.config/autostart/" % (os.path.expanduser("~/"))
		if not os.path.exists(autostart_folder):
			os.makedirs(autostart_folder)
		autostart_file = autostart_folder + "mailnag.desktop"
		f = open(autostart_file, 'w')
		f.write(content) # create it
		f.close()


	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
		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())
		

	def _on_btn_add_clicked(self, widget):
		acc = Account(enabled = True, name = '')
		d = AccountDialog(self._window, acc)
	
		if d.run() == 1:
			self._accounts.append(acc)
			
			row = [acc, acc.enabled, acc.name]
			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()


	def _on_btn_edit_clicked(self, widget):
		self._edit_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:') + \
				'\n\n' + acc.name):
				
				p = model.get_path(iter)
				if not p.prev():
					p.next()
				self._select_path(p)									# select prev/next account
				
				model.remove(iter)										# delete in treeview
				self._accounts.remove(acc)								# delete in accounts list


	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_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_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 _save_and_quit(self):
		self._save_config()	
		Gtk.main_quit()
		

	def _on_config_window_deleted(self, widget, event):
		self._save_and_quit()
Esempio n. 6
0
def main():
	global mainloop, mailchecker, idlers
	
	set_procname("mailnag")
	
	GObject.threads_init()
	
	signal.signal(signal.SIGTERM, sig_handler)
	
	try:
		write_pid() # write Mailnag's process id to file
		cfg = read_config()
		
		if (cfg == None):
			print 'Error: Cannot find configuration file. Please run mailnag_config first.'
			exit(1)
		
		if not is_online():
			print 'Waiting for internet connection...'
			while not is_online():
				time.sleep(5)
		
		accounts = AccountList()
		accounts.load_from_cfg(cfg, enabled_only = True)
		
		mailchecker = MailChecker(cfg)
		
		# immediate check, check *all* accounts
		mailchecker.check(accounts)
		
		idle_accounts = filter(lambda acc: acc.imap and acc.idle, accounts)
		non_idle_accounts = filter(lambda acc: (not acc.imap) or (acc.imap and not acc.idle), accounts)
		
		# start polling thread for POP3 accounts and
		# IMAP accounts without idle support
		if len(non_idle_accounts) > 0:
			def poll_func():
				try:
					mailchecker.check(non_idle_accounts)
				except:
					traceback.print_exc()
				return True
			
			check_interval = int(cfg.get('general', 'check_interval'))
			GObject.timeout_add_seconds(60 * check_interval, poll_func)
		
		# start idler threads for IMAP accounts with idle support
		if len(idle_accounts) > 0:
			def sync_func(account):
				try:
					mailchecker.check([account])
				except:
					traceback.print_exc()
			
			idlers = Idlers(idle_accounts, sync_func)
			idlers.run()
		
		mainloop = GObject.MainLoop()
		mainloop.run()
	except KeyboardInterrupt:
		pass # ctrl+c pressed
	finally:
		cleanup()