~ubuntu-branches/ubuntu/edgy/mailcrypt/edgy

« back to all changes in this revision

Viewing changes to tests/remailer/gtkwatcher.py

  • Committer: Bazaar Package Importer
  • Author(s): Davide G. M. Salvetti
  • Date: 2005-10-10 17:49:17 UTC
  • mto: This revision was merged to the branch mainline in revision 4.
  • Revision ID: james.westby@ubuntu.com-20051010174917-rw6qn4l26eodin5q
Tags: upstream-3.5.8+CVS.2005.04.29.1
ImportĀ upstreamĀ versionĀ 3.5.8+CVS.2005.04.29.1

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
#! /usr/bin/python
 
2
 
 
3
if __name__ == '__main__':
 
4
    import pygtk
 
5
    pygtk.require("2.0")
 
6
 
 
7
import time, cPickle
 
8
import gobject, gtk, gtk.glade
 
9
from watcher import Watcher
 
10
 
 
11
def time_string(latency):
 
12
    if latency == None:
 
13
        return "?"
 
14
    latency = int(latency)
 
15
    hours = latency / 3600
 
16
    latency -= hours * 3600
 
17
    minutes = latency / 60
 
18
    latency -= minutes * 60
 
19
    seconds = latency
 
20
    latency = ''
 
21
    if hours:
 
22
        latency = '%dh' % hours
 
23
    if hours or minutes:
 
24
        latency = latency + '%dm' % minutes
 
25
    latency = latency + '%ds' % seconds
 
26
    return latency
 
27
 
 
28
class WatcherGUI:
 
29
    def __init__(self, watcher):
 
30
        self.watcher = watcher
 
31
        watcher.gui = self
 
32
 
 
33
        self.done = 0
 
34
        
 
35
        xml = gtk.glade.XML('gtkwatcher.glade')
 
36
        self.xml = xml
 
37
 
 
38
        # main menu
 
39
        xml.signal_connect('do_poll', self.do_poll)
 
40
        xml.signal_connect('do_exit', self.do_quit)
 
41
 
 
42
        # source panel
 
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")
 
49
 
 
50
        # dest panel
 
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")
 
57
        
 
58
        xml.signal_connect('do_dst_flush', self.do_dst_flush)
 
59
        xml.signal_connect('do_dst_original', self.do_dst_original)
 
60
 
 
61
        # panel contents
 
62
        self.src_model = gtk.ListStore(gobject.TYPE_STRING,
 
63
                                       gobject.TYPE_STRING,
 
64
                                       gobject.TYPE_PYOBJECT)
 
65
        self.dst_model = gtk.ListStore(gobject.TYPE_STRING,
 
66
                                       gobject.TYPE_STRING,
 
67
                                       gobject.TYPE_PYOBJECT)
 
68
        
 
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)
 
78
        self.src_sel = sel
 
79
        
 
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)
 
89
        self.dst_sel = sel
 
90
        
 
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)
 
99
        self.do_update()
 
100
 
 
101
    def do_quit(self, widget):
 
102
        print "doing quit"
 
103
        self.done = 1
 
104
        # mainquit asserts, because we aren't actually in a mainloop
 
105
        #gtk.mainquit()
 
106
        
 
107
    def update_text(self, text, skipHeaders=0):
 
108
        buf = self.text.get_buffer()
 
109
        buf.set_text(text)
 
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
 
117
        # until later
 
118
        mark = buf.create_mark("end", iter, 0)
 
119
        if skipHeaders:
 
120
            self.text.scroll_to_mark(mark, within_margin=0)
 
121
        
 
122
    def do_src_select(self, sel):
 
123
        model, iter = sel.get_selected()
 
124
        if not iter:
 
125
            return  # deselected
 
126
        m = model.get_value(iter, 2)
 
127
        # get the message text from the Outstanding list
 
128
        text = m.data
 
129
        self.update_text(text)
 
130
        # need to deselect the one in the other list so we can sense when it
 
131
        # becomes reselected
 
132
        self.dst_sel.unselect_all()
 
133
 
 
134
    def do_src_popup(self, view, event):
 
135
        if event.button != 3:
 
136
            return
 
137
        pathset = view.get_path_at_pos(event.x, event.y)
 
138
        if pathset:
 
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)
 
148
        else:
 
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)
 
155
 
 
156
    def do_src_abandon(self, menuitem):
 
157
        # which message? find the selection
 
158
        model, iter = self.src_sel.get_selected()
 
159
        if not iter:
 
160
            print "abandon, no iter!"
 
161
            return
 
162
        m = model.get_value(iter, 2)
 
163
        print "abandon msgid", m.msgid
 
164
        self.watcher.abandon(m.msgid)
 
165
        self.do_update()
 
166
 
 
167
    def do_dst_popup(self, view, event):
 
168
        if event.button != 3:
 
169
            return
 
170
        pathset = view.get_path_at_pos(event.x, event.y)
 
171
        if pathset:
 
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)
 
185
        else:
 
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)
 
195
 
 
196
    def do_dst_flush(self, menuitem):
 
197
        # which message? find the selection
 
198
        model, iter = self.dst_sel.get_selected()
 
199
        if not iter:
 
200
            return
 
201
        m = model.get_value(iter, 2)
 
202
        print "flush msgid", m.msgid
 
203
        self.watcher.flush(m.msgid)
 
204
        self.do_update()
 
205
        
 
206
    def do_dst_original(self, menuitem):
 
207
        # which message? find the selection
 
208
        model, iter = self.dst_sel.get_selected()
 
209
        if not iter:
 
210
            return
 
211
        dst_msg = model.get_value(iter, 2)
 
212
        src_msg = self.watcher.source.msgs.get(dst_msg.msgid, None)
 
213
        if src_msg:
 
214
            text = src_msg.data
 
215
            self.update_text(text, skipHeaders=0)
 
216
        #self.dst_sel.unselect_all()
 
217
        
 
218
    def do_dst_select(self, sel):
 
219
        model, iter = sel.get_selected()
 
220
        if not iter:
 
221
            return
 
222
        m = model.get_value(iter, 2)
 
223
        text = m.data
 
224
        self.update_text(text, skipHeaders=1)
 
225
        self.src_sel.unselect_all()
 
226
 
 
227
    def do_poll(self, *args):
 
228
        self.watcher.poll()
 
229
        return 1
 
230
    def do_update(self):
 
231
        src = self.src_model
 
232
        src.clear()
 
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))
 
236
            iter = src.append()
 
237
            src.set(iter,
 
238
                    0, msg.msgid,
 
239
                    1, sent,
 
240
                    2, msg)
 
241
            #ol.set_row_data(row, msgid)
 
242
            #ol.set_selectable(row, 0)
 
243
        #ol.moveto(maxrow, 0, 1.0, 0.0)
 
244
 
 
245
        dst = self.dst_model
 
246
        dst.clear()
 
247
        for msg, latency in self.watcher.received():
 
248
            iter = dst.append()
 
249
            dst.set(iter,
 
250
                    0, msg.msgid,
 
251
                    1, time_string(latency),
 
252
                    2, msg)
 
253
            #rl.set_row_data(row, msgid)
 
254
            #rl.set_selectable(row, 0)
 
255
        #rl.moveto(maxrow, 0, 1.0, 0.0)
 
256
 
 
257
class GtkWatcher(Watcher):
 
258
    def checker(self, m):
 
259
        self.gui.do_update()
 
260
    def start(self):
 
261
        self.gui = WatcherGUI(self)
 
262
        Watcher.start(self)
 
263
    def stop(self):
 
264
        self.gui = None
 
265
        Watcher.stop(self)
 
266
 
 
267
def makeWatcher():
 
268
    from gtkwatcher import GtkWatcher
 
269
    from watcher import DirWatcher, NewsWatcher
 
270
    import sys, getopt
 
271
    w = GtkWatcher()
 
272
    usage = """
 
273
    gtkwatcher.py
 
274
      --source sdir
 
275
      [--dest ddir]...
 
276
      --nntp host:port:user:pass [--group a]..
 
277
    """
 
278
    try:
 
279
        opts, args = getopt.getopt(sys.argv[1:], '',
 
280
                                   ['source=', 'dest=',
 
281
                                    'nntp=', 'group=', 'tag='])
 
282
    except getopt.GetoptError:
 
283
        print usage
 
284
        sys.exit(-1)
 
285
    nntp = None
 
286
    groups = []
 
287
    tag = None
 
288
    for key, value in opts:
 
289
        if key == "--source":
 
290
            print "adding source maildir '%s'" % value
 
291
            w.addSource(DirWatcher(value))
 
292
        if key == "--dest":
 
293
            print "adding dest maildir '%s'" % value
 
294
            w.addDest(DirWatcher(value))
 
295
        if key == "--nntp":
 
296
            nntp = value
 
297
        if key == "--group":
 
298
            groups.append(value)
 
299
        if key == "--tag":
 
300
            tag = value
 
301
    if groups and not nntp:
 
302
        raise "Must have --nntp server specified to use --group"
 
303
    if tag and not nntp:
 
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?"
 
307
    if nntp:
 
308
        # parse server spec
 
309
        fields = nntp.split(':')
 
310
        fields.extend([None] * (4 - len(fields)))
 
311
        host, port, user, passwd = fields
 
312
        if port:
 
313
            port = int(port)
 
314
        nw = NewsWatcher(host, groups,
 
315
                         user, passwd, port, tag)
 
316
        w.addDest(nw)
 
317
    return w
 
318
 
 
319
def main():
 
320
    try:
 
321
        f = open("watcher.pickle", "r")
 
322
        w = cPickle.load(f)
 
323
        f.close()
 
324
    except:
 
325
        print "unable to load pickle"
 
326
        w = makeWatcher()
 
327
    print "running"
 
328
    w.start()
 
329
    while not w.gui.done:
 
330
        gtk.mainiteration()
 
331
    print "done"
 
332
    w.stop()
 
333
    # save pickle of seen messages
 
334
    f = open("watcher.pickle", "w")
 
335
    cPickle.dump(w, f, 1)
 
336
    f.close()
 
337
    
 
338
if __name__ == '__main__': main()