3
if __name__ == '__main__':
8
import gobject, gtk, gtk.glade
9
from watcher import Watcher
11
def time_string(latency):
14
latency = int(latency)
15
hours = latency / 3600
16
latency -= hours * 3600
17
minutes = latency / 60
18
latency -= minutes * 60
22
latency = '%dh' % hours
24
latency = latency + '%dm' % minutes
25
latency = latency + '%ds' % seconds
29
def __init__(self, watcher):
30
self.watcher = watcher
35
xml = gtk.glade.XML('gtkwatcher.glade')
39
xml.signal_connect('do_poll', self.do_poll)
40
xml.signal_connect('do_exit', self.do_quit)
43
self.src_popup = xml.get_widget("src_popup")
44
xml.signal_connect('do_src_abandon', self.do_src_abandon)
45
xml.get_widget("source_message_options1").set_sensitive(0)
46
self.src_age_item = xml.get_widget("src_age_item")
47
self.src_age_item.set_sensitive(0)
48
self.src_abandon_item = xml.get_widget("src_abandon_item")
51
self.dst_popup = xml.get_widget("dst_popup")
52
xml.get_widget("dest_message_options1").set_sensitive(0)
53
self.dst_sent_item = xml.get_widget("dst_sent_item")
54
self.dst_sent_item.set_sensitive(0)
55
self.dst_original_item = xml.get_widget("dst_original_item")
56
self.dst_flush_item = xml.get_widget("dst_flush_item")
58
xml.signal_connect('do_dst_flush', self.do_dst_flush)
59
xml.signal_connect('do_dst_original', self.do_dst_original)
62
self.src_model = gtk.ListStore(gobject.TYPE_STRING,
64
gobject.TYPE_PYOBJECT)
65
self.dst_model = gtk.ListStore(gobject.TYPE_STRING,
67
gobject.TYPE_PYOBJECT)
69
view = xml.get_widget('src_treeview')
70
view.connect("button_press_event", self.do_src_popup)
71
view.set_model(self.src_model)
72
r = gtk.CellRendererText()
73
view.append_column(gtk.TreeViewColumn("Message ID", r, text=0))
74
view.append_column(gtk.TreeViewColumn("Message Sent", r, text=1))
75
sel = view.get_selection()
76
sel.set_mode(gtk.SELECTION_SINGLE)
77
sel.connect("changed", self.do_src_select)
80
view = xml.get_widget('dst_treeview')
81
view.connect("button_press_event", self.do_dst_popup)
82
view.set_model(self.dst_model)
83
r = gtk.CellRendererText()
84
view.append_column(gtk.TreeViewColumn("Message ID", r, text=0))
85
view.append_column(gtk.TreeViewColumn("Latency", r, text=1))
86
sel = view.get_selection()
87
sel.set_mode(gtk.SELECTION_SINGLE)
88
sel.connect("changed", self.do_dst_select)
91
self.srcwin = xml.get_widget('srcwin')
92
self.dstwin = xml.get_widget('dstwin')
93
#self.src_clist.connect('select-row', self.do_src_select)
94
#self.dst_clist.connect('select-row', self.do_dst_select)
95
self.text = xml.get_widget('text1')
96
self.text.set_wrap_mode(gtk.WRAP_NONE)
97
self.textwin = xml.get_widget('textwin')
98
xml.get_widget('window1').set_size_request(500,300)
101
def do_quit(self, widget):
104
# mainquit asserts, because we aren't actually in a mainloop
107
def update_text(self, text, skipHeaders=0):
108
buf = self.text.get_buffer()
110
# now make the end of the buffer visible
111
# XXX: this flashes. They removed freeze/thaw.. how to fix?
112
# XXX: if skipHeaders, find the first blank line and put that at top
113
iter = buf.get_iter_at_line(-1)
114
#print iter.get_line()
115
# turn it into a mark, as scroll_to_iter depends upon height
116
# calculations that are done in an idle task, so it won't get it right
118
mark = buf.create_mark("end", iter, 0)
120
self.text.scroll_to_mark(mark, within_margin=0)
122
def do_src_select(self, sel):
123
model, iter = sel.get_selected()
126
m = model.get_value(iter, 2)
127
# get the message text from the Outstanding list
129
self.update_text(text)
130
# need to deselect the one in the other list so we can sense when it
132
self.dst_sel.unselect_all()
134
def do_src_popup(self, view, event):
135
if event.button != 3:
137
pathset = view.get_path_at_pos(event.x, event.y)
139
path, viewcol, cell_x, cell_y = pathset
140
iter = self.src_model.get_iter(path)
141
m = self.src_model.get_value(iter, 2)
142
age = self.watcher.age(m.msgid)
143
label = self.src_age_item.get_child()
144
label.set_text("Age[%d]: %s" % (m.msgid, time_string(age)))
145
label = self.src_abandon_item.get_child()
146
label.set_text("Abandon Message [%d]" % m.msgid)
147
self.src_abandon_item.set_sensitive(1)
149
label = self.src_age_item.get_child()
150
label.set_text("Age: --")
151
label = self.src_abandon_item.get_child()
152
label.set_text("Abandon Message")
153
self.src_abandon_item.set_sensitive(0)
154
self.src_popup.popup(None, None, None, event.button, event.time)
156
def do_src_abandon(self, menuitem):
157
# which message? find the selection
158
model, iter = self.src_sel.get_selected()
160
print "abandon, no iter!"
162
m = model.get_value(iter, 2)
163
print "abandon msgid", m.msgid
164
self.watcher.abandon(m.msgid)
167
def do_dst_popup(self, view, event):
168
if event.button != 3:
170
pathset = view.get_path_at_pos(event.x, event.y)
172
path, viewcol, cell_x, cell_y = pathset
173
iter = self.dst_model.get_iter(path)
174
m = self.dst_model.get_value(iter, 2)
175
txtime = self.watcher.txtime(m.msgid)
176
sent = time.strftime("%H:%M %d %b %Y", time.localtime(txtime))
177
label = self.dst_sent_item.get_child()
178
label.set_text("Sent[%d]: %s" % (m.msgid, sent))
179
self.dst_original_item.set_sensitive(1)
180
label = self.dst_original_item.get_child()
181
label.set_text("See Original [%d]" % m.msgid)
182
self.dst_flush_item.set_sensitive(1)
183
label = self.dst_flush_item.get_child()
184
label.set_text("Flush Message [%d]" % m.msgid)
186
label = self.dst_sent_item.get_child()
187
label.set_text("Sent: --")
188
self.dst_original_item.set_sensitive(0)
189
label = self.dst_original_item.get_child()
190
label.set_text("See Original")
191
self.dst_flush_item.set_sensitive(0)
192
label = self.dst_flush_item.get_child()
193
label.set_text("Flush Message")
194
self.dst_popup.popup(None, None, None, event.button, event.time)
196
def do_dst_flush(self, menuitem):
197
# which message? find the selection
198
model, iter = self.dst_sel.get_selected()
201
m = model.get_value(iter, 2)
202
print "flush msgid", m.msgid
203
self.watcher.flush(m.msgid)
206
def do_dst_original(self, menuitem):
207
# which message? find the selection
208
model, iter = self.dst_sel.get_selected()
211
dst_msg = model.get_value(iter, 2)
212
src_msg = self.watcher.source.msgs.get(dst_msg.msgid, None)
215
self.update_text(text, skipHeaders=0)
216
#self.dst_sel.unselect_all()
218
def do_dst_select(self, sel):
219
model, iter = sel.get_selected()
222
m = model.get_value(iter, 2)
224
self.update_text(text, skipHeaders=1)
225
self.src_sel.unselect_all()
227
def do_poll(self, *args):
233
for msg, txtime in self.watcher.outstanding():
234
#elapsed = time_string(int(time.time()) - txtime)
235
sent = time.strftime("%H:%M %d %b %Y", time.localtime(txtime))
241
#ol.set_row_data(row, msgid)
242
#ol.set_selectable(row, 0)
243
#ol.moveto(maxrow, 0, 1.0, 0.0)
247
for msg, latency in self.watcher.received():
251
1, time_string(latency),
253
#rl.set_row_data(row, msgid)
254
#rl.set_selectable(row, 0)
255
#rl.moveto(maxrow, 0, 1.0, 0.0)
257
class GtkWatcher(Watcher):
258
def checker(self, m):
261
self.gui = WatcherGUI(self)
268
from gtkwatcher import GtkWatcher
269
from watcher import DirWatcher, NewsWatcher
276
--nntp host:port:user:pass [--group a]..
279
opts, args = getopt.getopt(sys.argv[1:], '',
281
'nntp=', 'group=', 'tag='])
282
except getopt.GetoptError:
288
for key, value in opts:
289
if key == "--source":
290
print "adding source maildir '%s'" % value
291
w.addSource(DirWatcher(value))
293
print "adding dest maildir '%s'" % value
294
w.addDest(DirWatcher(value))
301
if groups and not nntp:
302
raise "Must have --nntp server specified to use --group"
304
raise "Must have --nntp set to use message filtering tag"
305
if nntp and not groups:
306
raise "Gave NNTP server but no groups to poll: what's the point?"
309
fields = nntp.split(':')
310
fields.extend([None] * (4 - len(fields)))
311
host, port, user, passwd = fields
314
nw = NewsWatcher(host, groups,
315
user, passwd, port, tag)
321
f = open("watcher.pickle", "r")
325
print "unable to load pickle"
329
while not w.gui.done:
333
# save pickle of seen messages
334
f = open("watcher.pickle", "w")
335
cPickle.dump(w, f, 1)
338
if __name__ == '__main__': main()