## $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()
syntax highlighted by Code2HTML, v. 0.9.1