## $Id: filter.py,v 1.8 2001/05/02 12:35:36 kjetilja Exp $ ## System modules from gtk import * from gnome.ui import * import string, marshal, re ## Local modules import folderops # Actions to take if filter matches ACTION_FORWARD = 1 ACTION_DELETE = 2 ACTION_MOVE = 3 ACTION_SCORE = 4 ACTION_NONE = 5 ENTRY_TX = 0 ENTRY_IN = 1 ENTRY_AC = 2 ENTRY_TO = 3 ENTRY_RE = 4 actions = { ACTION_FORWARD : 'Forward to: ', ACTION_DELETE : 'Delete', ACTION_MOVE : 'Move to folder: ', ACTION_SCORE : 'Score: ', ACTION_NONE : 'No action', } class FilterEditWindow: def __init__(self, parent, fld, clicked_callback): self.fld = fld self.prefs = self.fld.prefs # Wigdgets self.text_entry = None self.in_combo = None w = GnomeDialog('Edit', 'Ok', 'Cancel') self.win = w w.set_parent(parent) w.connect('clicked', clicked_callback) self.init_match() self.init_action() w.vbox.pack_start(self.matchframe) w.vbox.pack_start(self.actionframe) w.show() ## ## Method init_match (self) ## ## Widgets in the match frame. ## ## def init_match(self): frame = GtkFrame('Match') frame.set_border_width(5) frame.show() t = GtkTable(2,2,0) t.show() ln = GtkLabel("Text:") ln.show() text = GtkEntry() self.text_entry = text text.show() le = GtkLabel("In:") le.show() ic = GtkCombo() self.in_combo = ic ic.entry.set_editable(FALSE) ic.show() ic.set_popdown_strings(['To:', 'From:', 'Sender:', 'Subject:', 'Cc:', 'Any recipient']) t.attach(ln, 0, 1, 0, 1, yoptions=0, ypadding=3, xpadding=5) t.attach(text, 1, 2, 0, 1, xpadding=10, yoptions=0, ypadding=5) t.attach(le, 0, 1, 1, 2, yoptions=0, ypadding=3, xpadding=5) t.attach(ic, 1, 2, 1, 2, xpadding=10, yoptions=0, ypadding=5) frame.add(t) self.matchframe = frame ## ## Method init_action (self) ## ## Widgets in the action frame. ## ## def init_action(self): frame = GtkFrame('Action') frame.set_border_width(5) frame.show() t = GtkTable(2,3,0) t.show() button1 = GtkRadioButton(None, "Move to folder:") self.move_button = button1 button1.show() button2 = GtkRadioButton(button1, "Forward to:") self.forward_button = button2 button2.show() button3 = GtkRadioButton(button1, "Delete message") self.delete_button = button3 button3.show() button4 = GtkRadioButton(button1, "No action") self.none_button = button4 button4.show() forw = GtkEntry() self.forward_entry = forw forw.show() from posixpath import split flds = self.fld.total.keys() for fname in self.prefs.default_folders: flds.remove(fname) flds.sort() move = GtkCombo() self.move_combo = move move.entry.set_editable(FALSE) if len(flds) > 0: move.set_popdown_strings(flds) move.show() t.attach(button1, 0, 1, 0, 1, yoptions=0, ypadding=3, xpadding=5) t.attach(button2, 0, 1, 1, 2, yoptions=0, ypadding=3, xpadding=5) t.attach(button3, 0, 1, 2, 3, yoptions=0, ypadding=3, xpadding=5) t.attach(button4, 0, 1, 3, 4, yoptions=0, ypadding=3, xpadding=5) t.attach(forw, 1, 2, 1, 2, yoptions=0, ypadding=3, xpadding=5) t.attach(move, 1, 2, 0, 1, yoptions=0, ypadding=3, xpadding=5) frame.add(t) self.actionframe = frame ## ## Method set_values () ## def set_filter(self, fi): text, _in, action, to, = fi if text: self.text_entry.set_text(text) if _in: self.in_combo.entry.set_text(_in) ## Actions if action == ACTION_FORWARD and to: self.forward_entry.set_text(to) if action == ACTION_MOVE: self.move_button.set_active(1) if action == ACTION_DELETE: self.delete_button.set_active(1) if action == ACTION_NONE: self.none_button.set_active(1) if action == ACTION_FORWARD: self.forward_button.set_active(1) if action == ACTION_MOVE and to: self.move_combo.entry.set_text(to) def get_filter(self): text = self.text_entry.get_text() _in = self.in_combo.entry.get_text() # Read the setting of the radiobuttons if self.move_button.get_active(): action = ACTION_MOVE parm = self.move_combo.entry.get_text() elif self.forward_button.get_active(): action = ACTION_FORWARD parm = self.forward_entry.get_text() elif self.delete_button.get_active(): action = ACTION_DELETE parm = '' elif self.none_button.get_active(): action = ACTION_NONE parm = '' return (text, _in, action, parm) ## ## ## Main filter window class ## ## class FilterWindow: ## ## Method __init__ (self, folder window class instance) ## ## Filter window constructor. ## ## def __init__(self, fld): self.fld = fld self.prefs = self.fld.prefs self.win = GnomeDialog(':Pygmy - Edit Filters', 'Add', 'Edit', 'Remove', STOCK_BUTTON_OK, STOCK_BUTTON_CANCEL) self.win.set_parent(self.fld.win) self.vbox = self.win.vbox self.win.connect('clicked', self.handle_callbacks) self.win.connect('delete_event', self.destroy) self.win.connect('destroy', self.destroy) self.init_filterlist() self.win.show() def init_filterlist(self): hbox = GtkHBox() hbox.show() self.vbox.pack_start(hbox) self.fdisp = GtkCList(3, ['Text', 'In', 'Action']) self.fdisp.connect("click_column", self.clickcolumn) self.fdisp.connect("select_row", self.selectrow) # Widget attributes self.fdisp.set_selection_mode(SELECTION_SINGLE) self.fdisp.set_column_width(0, 150) self.fdisp.set_column_width(1, 90) self.fdisp.set_column_width(2, 150) self.fdisp.set_border_width(2) self.fdisp.set_usize(0, 256) # Add scrollbars swin = GtkScrolledWindow() swin.set_policy(POLICY_AUTOMATIC, POLICY_AUTOMATIC) hbox.pack_start(swin) swin.add(self.fdisp) swin.show() # Add navigation buttons vbox = GtkVBox() vbox.show() w = GnomeStock(STOCK_PIXMAP_UP) w.show() h = GtkVBox() h.show() h.add(w) b = GtkButton() b.show() b.add(h) b.set_border_width(1) b.set_relief(RELIEF_NONE) b.connect('clicked', self.up_callback) tt = GtkTooltips() tt.set_tip(b, "Increase priority", "inc") vbox.pack_start(b, expand=TRUE, fill=FALSE) w = GnomeStock(STOCK_PIXMAP_DOWN) w.show() h = GtkVBox() h.show() h.add(w) b = GtkButton() b.show() b.add(h) b.set_border_width(1) b.set_relief(RELIEF_NONE) b.connect('clicked', self.down_callback) tt = GtkTooltips() tt.set_tip(b, "Decrease priority", "dec") vbox.pack_start(b, expand=TRUE, fill=FALSE) hbox.pack_start(vbox, FALSE, FALSE) self.fdisp.show() # Store reference to filter list try: self.filters = marshal.load(open(self.prefs.flistfile)) except: self.filters = [] # Inject entries into the listview for fi in self.filters: self.fdisp.append((fi[ENTRY_TX], fi[ENTRY_IN], actions[fi[ENTRY_AC]] + fi[ENTRY_TO])) ## ## Method validate_filter (self, text) ## ## Check that the filter text can be compiled to a regex ## ## def validate_filter(self, text): try: re.compile(text) except: return 0 else: return 1 ## ## Method handle_callbacks (self, button, no) ## ## Handle callbacks for the action buttons. ## ## def handle_callbacks(self, button, no): if no == 0: self.add_callback(button) elif no == 1: self.edit_callback(button) elif no == 2: self.delete_callback(button) elif no == 3: self.ok_callback(button) elif no == 4: self.destroy() else: print "filter -- got unknown button callback event" def delete_callback(self, button=None): if self.fdisp.selection == []: return sel = self.fdisp.selection self.delname = {} for index in sel: self.delname[index] = self.fdisp.get_text(index,0) l = GtkLabel("Are you sure you want to remove '"+ \ string.join(self.delname.values(), "\n") + "' ?") l.show() v = GnomeDialog('Remove filter', 'Ok', 'Cancel') v.set_parent(self.win) v.vbox.pack_start(l) v.connect('clicked', self.do_delete) v.show() def do_delete(self, button, no): if no == 0: # Ok button for index in self.delname.keys(): self.fdisp.remove(index) del self.filters[index] button.destroy() elif no == 1: # Cancel button button.destroy() def edit_callback(self, button=None): if self.fdisp.selection == []: return self.index = self.fdisp.selection[0] text = self.fdisp.get_text(self.index, 0) self.oldname = text fi = self.filters[self.index] _in = fi[ENTRY_IN] self.edit_window = FilterEditWindow(self.win, self.fld, self.do_edit) self.edit_window.set_filter(fi) def add_callback(self, button=None): self.edit_window = FilterEditWindow(self.win, self.fld, self.do_add) def do_add(self, button, no): if no == 0: # Ok button fi = self.edit_window.get_filter() if not self.validate_filter(fi[ENTRY_TX]): w = GnomeErrorDialog("Invalid regular expression in 'Text'") w.set_parent(self.win) w.show() return FALSE self.fdisp.append((fi[ENTRY_TX], fi[ENTRY_IN], actions[fi[ENTRY_AC]] + fi[ENTRY_TO])) self.filters.append(fi) elif no == 1: # Cancel button pass button.destroy() def do_edit(self, button, no): if no == 0: # Ok button fi = self.edit_window.get_filter() if not self.validate_filter(fi[ENTRY_TX]): w = GnomeErrorDialog("Invalid regular expression in 'Text'") w.set_parent(self.win) w.show() return FALSE # Update display self.fdisp.set_text(self.fdisp.selection[0], 0, fi[ENTRY_TX]) self.fdisp.set_text(self.fdisp.selection[0], 1, fi[ENTRY_IN]) self.fdisp.set_text(self.fdisp.selection[0], 2, actions[fi[ENTRY_AC]] + fi[ENTRY_TO]) # Update internal list self.filters[self.index] = fi elif no == 1: # Cancel button pass button.destroy() ## Shortcut function def sort(self, c=0): self.fdisp.set_sort_column(c) self.fdisp.set_sort_type(SORT_ASCENDING) self.fdisp.sort() ## Sort the filter list alphabetically when clicked def clickcolumn(self, clist, c): self.sort(c) ## Need this one to catch double clicks on a list item. def selectrow(self, clist, r, c, event): if hasattr(event, 'type'): # Check for double clicks on the list item if event.type == 5: # Launch a edit box (should something else happen?) self.edit_callback() def set_filterline(self, index, fi): self.fdisp.set_text(self.fdisp.selection[0], 0, fi[ENTRY_TX]) self.fdisp.set_text(self.fdisp.selection[0], 1, fi[ENTRY_IN]) self.fdisp.set_text(self.fdisp.selection[0], 2, actions[fi[ENTRY_AC]] + fi[ENTRY_TO]) def up_callback(self, button=None): if self.fdisp.selection == []: return index = self.fdisp.selection[0] # Check if already at start if index == 0: return # Update internal filter list tmp = self.filters[index] self.filters[index] = self.filters[index-1] self.filters[index-1] = tmp # Update filterview self.fdisp.row_move(index, index-1) def down_callback(self, button=None): if self.fdisp.selection == []: return index = self.fdisp.selection[0] # Check if already at end if index == len(self.filters)-1: return # Update internal filter list tmp = self.filters[index] self.filters[index] = self.filters[index+1] self.filters[index+1] = tmp # Update folderview self.fdisp.row_move(index, index+1) ## ## Method apply_callback (self, button) ## ## Callback for the Apply button. ## ## def apply_callback(self, button): self.prefs.filters = self.filters self.fld.set_filters(self.filters) ## ## Method ok_callback (self, button) ## ## Callback for the Ok button. ## ## def ok_callback(self, button): # Quit self.prefs.filters = self.filters self.fld.set_filters(self.filters) marshal.dump(self.filters, open(self.prefs.flistfile, 'w')) self.destroy() ## ## Method destroy (self, None, None) ## ## Filter edit widget destructor. ## ## def destroy(self, foo=None, bar=None): self.fld.filters_active = 0 self.win.destroy()