3 # Scan MH folder, display results in window
14 from dialog
import dialog
16 mailbox
= os
.environ
['HOME'] + '/Mail'
19 global root
, tk
, top
, mid
, bot
20 global folderbox
, foldermenu
, scanbox
, scanmenu
, viewer
24 # Parse command line options
29 opts
, args
= getopt
.getopt(sys
.argv
[1:], '')
30 except getopt
.error
, msg
:
42 mhf
= mh
.openfolder(folder
)
44 # Build widget hierarchy
50 top
.pack({'expand': 1, 'fill': 'both'})
52 # Build right part: folder list
55 right
.pack({'fill': 'y', 'side': 'right'})
57 folderbar
= Scrollbar(right
, {'relief': 'sunken', 'bd': 2})
58 folderbar
.pack({'fill': 'y', 'side': 'right'})
60 folderbox
= Listbox(right
, {'exportselection': 0})
61 folderbox
.pack({'expand': 1, 'fill': 'both', 'side': 'left'})
63 foldermenu
= Menu(root
)
64 foldermenu
.add('command',
65 {'label': 'Open Folder',
66 'command': open_folder
})
67 foldermenu
.add('separator')
68 foldermenu
.add('command',
71 foldermenu
.bind('<ButtonRelease-3>', folder_unpost
)
73 folderbox
['yscrollcommand'] = (folderbar
, 'set')
74 folderbar
['command'] = (folderbox
, 'yview')
75 folderbox
.bind('<Double-1>', open_folder
, 1)
76 folderbox
.bind('<3>', folder_post
)
78 # Build left part: scan list
81 left
.pack({'expand': 1, 'fill': 'both', 'side': 'left'})
83 scanbar
= Scrollbar(left
, {'relief': 'sunken', 'bd': 2})
84 scanbar
.pack({'fill': 'y', 'side': 'right'})
86 scanbox
= Listbox(left
, {'font': 'fixed'})
87 scanbox
.pack({'expand': 1, 'fill': 'both', 'side': 'left'})
90 scanmenu
.add('command',
91 {'label': 'Open Message',
92 'command': open_message
})
93 scanmenu
.add('command',
94 {'label': 'Remove Message',
95 'command': remove_message
})
96 scanmenu
.add('command',
97 {'label': 'Refile Message',
98 'command': refile_message
})
99 scanmenu
.add('separator')
100 scanmenu
.add('command',
103 scanmenu
.bind('<ButtonRelease-3>', scan_unpost
)
105 scanbox
['yscrollcommand'] = (scanbar
, 'set')
106 scanbar
['command'] = (scanbox
, 'yview')
107 scanbox
.bind('<Double-1>', open_message
)
108 scanbox
.bind('<3>', scan_post
)
110 # Separator between middle and bottom part
112 rule2
= Frame(root
, {'bg': 'black'})
113 rule2
.pack({'fill': 'x'})
115 # Build bottom part: current message
118 bot
.pack({'expand': 1, 'fill': 'both'})
122 # Window manager commands
124 root
.minsize(800, 1) # Make window resizable
126 # Fill folderbox with text
130 # Fill scanbox with text
139 x
, y
= e
.x_root
, e
.y_root
140 foldermenu
.post(x
- 10, y
- 10)
141 foldermenu
.grab_set()
143 def folder_unpost(e
):
144 tk
.call('update', 'idletasks')
145 foldermenu
.grab_release()
147 foldermenu
.invoke('active')
150 x
, y
= e
.x_root
, e
.y_root
151 scanmenu
.post(x
- 10, y
- 10)
155 tk
.call('update', 'idletasks')
156 scanmenu
.grab_release()
158 scanmenu
.invoke('active')
160 scanparser
= regex
.compile('^ *\([0-9]+\)')
162 def open_folder(e
=None):
164 sel
= folderbox
.curselection()
167 msg
= "Please open one folder at a time"
169 msg
= "Please select a folder to open"
170 dialog(root
, "Can't Open Folder", msg
, "", 0, "OK")
173 folder
= folderbox
.get(i
)
174 mhf
= mh
.openfolder(folder
)
177 def open_message(e
=None):
179 sel
= scanbox
.curselection()
182 msg
= "Please open one message at a time"
184 msg
= "Please select a message to open"
185 dialog(root
, "Can't Open Message", msg
, "", 0, "OK")
187 cursor
= scanbox
['cursor']
188 scanbox
['cursor'] = 'watch'
189 tk
.call('update', 'idletasks')
191 line
= scanbox
.get(i
)
192 if scanparser
.match(line
) >= 0:
193 num
= string
.atoi(scanparser
.group(1))
194 m
= mhf
.openmessage(num
)
195 if viewer
: viewer
.destroy()
196 from MimeViewer
import MimeViewer
197 viewer
= MimeViewer(bot
, '+%s/%d' % (folder
, num
), m
)
200 scanbox
['cursor'] = cursor
202 def interestingheader(header
):
203 return header
!= 'received'
205 def remove_message(e
=None):
206 itop
= scanbox
.nearest(0)
207 sel
= scanbox
.curselection()
209 dialog(root
, "No Message To Remove",
210 "Please select a message to remove", "", 0, "OK")
214 line
= scanbox
.get(i
)
215 if scanparser
.match(line
) >= 0:
216 todo
.append(string
.atoi(scanparser
.group(1)))
217 mhf
.removemessages(todo
)
219 fixfocus(min(todo
), itop
)
223 def refile_message(e
=None):
224 global lastrefile
, tofolder
225 itop
= scanbox
.nearest(0)
226 sel
= scanbox
.curselection()
228 dialog(root
, "No Message To Refile",
229 "Please select a message to refile", "", 0, "OK")
231 foldersel
= folderbox
.curselection()
232 if len(foldersel
) != 1:
234 msg
= "Please select a folder to refile to"
236 msg
= "Please select exactly one folder to refile to"
237 dialog(root
, "No Folder To Refile", msg
, "", 0, "OK")
239 refileto
= folderbox
.get(foldersel
[0])
242 line
= scanbox
.get(i
)
243 if scanparser
.match(line
) >= 0:
244 todo
.append(string
.atoi(scanparser
.group(1)))
245 if lastrefile
!= refileto
or not tofolder
:
246 lastrefile
= refileto
248 tofolder
= mh
.openfolder(lastrefile
)
249 mhf
.refilemessages(todo
, tofolder
)
251 fixfocus(min(todo
), itop
)
253 def fixfocus(near
, itop
):
256 line
= scanbox
.get(`i`
)
257 if scanparser
.match(line
) >= 0:
258 num
= string
.atoi(scanparser
.group(1))
263 scanbox
.select_from(i
)
267 folderbox
.delete(0, 'end')
268 for fn
in mh
.listallfolders():
269 folderbox
.insert('end', fn
)
276 scanbox
.delete(0, 'end')
277 for line
in scanfolder(folder
, seq
):
278 scanbox
.insert('end', line
)
280 def scanfolder(folder
= 'inbox', sequence
= 'all'):
282 lambda line
: line
[:-1],
283 os
.popen('scan +%s %s' % (folder
, sequence
), 'r').readlines())