1
2
3
4
5
6
7
8
9
10 "Various helper routines for gui based code"
11
12
13
14
15
16 from __future__ import with_statement
17 import contextlib
18 import os
19 import glob
20 import sys
21
22
23 import wx
24
25
26 import common
27
28
29
30
31
32
33
34 ID_FILENEW=1
35 ID_FILEOPEN=1
36 ID_FILESAVE=1
37 ID_FILEIMPORT=1
38 ID_FILEEXPORT=1
39 ID_FILEPRINT=1
40 ID_FILEPRINTPREVIEW=1
41 ID_FILEEXIT=1
42 ID_EDITADDENTRY=1
43 ID_EDITDELETEENTRY=1
44 ID_EDITSELECTALL=1
45 ID_EDITSETTINGS=1
46 ID_EDITPHONEINFO=1
47 ID_EDITDETECT=1
48 ID_EDITCOPY=1
49 ID_EDITPASTE=1
50 ID_EDITRENAME=1
51 ID_DATAGETPHONE=1
52 ID_DATASENDPHONE=1
53 ID_DATAHISTORICAL=1
54 ID_DATANEWDB=1
55 ID_AUTOSYNCSETTINGS=1
56 ID_AUTOSYNCEXECUTE=1
57 ID_VIEWCOLUMNS=1
58 ID_VIEWPREVIEW=1
59 ID_VIEWLOGDATA=1
60 ID_VIEWCLEARLOGS=1
61 ID_VIEWFILESYSTEM=1
62 ID_HELPHELP=1
63 ID_HELPCONTENTS=1
64 ID_HELPTOUR=1
65 ID_HELPSUPPORT=1
66 ID_HELP_UPDATE=1
67 ID_HELPABOUT=1
68 ID_HELPPHONE=1
69 ID_HELPHOWTOS=1
70 ID_HELPFAQ=1
71 ID_DR_SETTINGS=1
72 ID_DEBUG_SCRIPT=1
73 ID_FILEVIEW_THUMBNAIL=1
74 ID_FILEVIEW_LIST=1
75
76
77 ID_FV_SAVE=1
78 ID_FV_HEXVIEW=1
79 ID_FV_OVERWRITE=1
80 ID_FV_MOVE=1
81 ID_FV_NEWSUBDIR=1
82 ID_FV_NEWFILE=1
83 ID_FV_DELETE=1
84 ID_FV_OPEN=1
85 ID_FV_RENAME=1
86 ID_FV_REFRESH=1
87 ID_FV_PROPERTIES=1
88 ID_FV_ADD=1
89 ID_FV_BACKUP=1
90 ID_FV_BACKUP_TREE=1
91 ID_FV_RESTORE=1
92 ID_FV_PASTE=1
93 ID_FV_TOTAL_REFRESH=1
94 ID_FV_OFFLINEPHONE=1
95 ID_FV_REBOOTPHONE=1
96 ID_FV_MODEMMODE=1
97 ID_FV_COPY=1
98 ID_FV_REPLACE=1
99
100
101 ID_EXPORT_VCARD_CONTACTS=1
102 ID_EXPORT_GROUPWARE_CONTACTS=1
103 ID_EXPORT_CSV_CONTACTS=1
104 ID_EXPORT_CSV_CALENDAR=1
105 ID_EXPORT_SMS=1
106 ID_EXPORT_CSV_CALL_HISTORY=1
107 ID_EXPORT_MEDIA_TO_DIR=1
108 ID_EXPORT_MEDIA_TO_ZIP=1
109 ID_IMPORT_CSV_CONTACTS=1
110 ID_IMPORT_CSV_CALENDAR=1
111 ID_IMPORT_VCARDS=1
112 ID_IMPORT_VCALENDAR=1
113 ID_IMPORT_ICALENDAR=1
114 ID_IMPORT_GCALENDAR=1
115 ID_IMPORT_OUTLOOK_CONTACTS=1
116 ID_IMPORT_OUTLOOK_CALENDAR=1
117 ID_IMPORT_OUTLOOK_NOTES=1
118 ID_IMPORT_OUTLOOK_TASKS=1
119 ID_IMPORT_EVO_CONTACTS=1
120 ID_IMPORT_QTOPIA_CONTACTS=1
121 ID_IMPORT_GROUPWARE_CONTACTS=1
122 ID_CALENDAR_WIZARD=1
123 ID_IMPORT_WPL=1
124 ID_EXPORT_ICALENDAR=1
125
126
127 idmap={}
128
129 for idmapname in locals().keys():
130 if idmapname.startswith('ID_'):
131 idnum=wx.NewId()
132
133 exec "%s = %d" % (idmapname, idnum )
134 idmap[idnum]=idmapname
135
136
137
138
139
140
141
142 _wxmimemapping={
143 'bmp': 'image/x-bmp',
144 'ico': 'image/x-ico',
145 'cur': 'image/x-cur',
146 'ani': 'image/x-ani',
147 'gif': 'image/gif',
148 'iff': 'image/iff',
149 'jpg': 'image/jpeg',
150 'jpeg': 'image/jpeg',
151 'pcx': 'image/pcx',
152 'png': 'image/png',
153 'pnm': 'image/pnm',
154 'xpm': 'image/xpm',
155 }
160
162 def _busywrapper(*args, **kwargs):
163 wx.BeginBusyCursor()
164 try:
165 return method(*args, **kwargs)
166 finally:
167 wx.EndBusyCursor()
168
169 setattr(_busywrapper, "__doc__", getattr(method, "__doc__"))
170
171 return _busywrapper
172
180
183 """ A wrapper for the wx.Dialog class that automatically calls Destroy"""
184 try:
185 yield (dlg, dlg.ShowModal()) if showmodal else dlg
186 finally:
187 dlg.Destroy()
188
191 with WXDialogWrapper(wx.MessageDialog(*args, **kwargs),
192 True):
193 pass
194
195
196
197
198
199 -def getextension(str):
200 """Returns the extension of a filename (characters after last period)
201
202 An empty string is returned if the file has no extension. The period
203 character is not returned"""
204 str=basename(str)
205 if str.rfind('.')>=0:
206 return str[str.rfind('.')+1:]
207 return ""
208
210 """Returns the last part of the name (everything after last /)"""
211 if str.rfind('/')<0: return str
212 return str[str.rfind('/')+1:]
213
215 """Returns everything before the last / in the name"""
216 if str.rfind('/')<0: return ""
217 return str[:str.rfind('/')]
218
220 """Are we running on Windows?
221
222 @rtype: Bool"""
223 return wx.Platform=='__WXMSW__'
224
226 """Are we running on GTK (Linux)
227
228 @rtype: Bool"""
229 return wx.Platform=='__WXGTK__'
230
232 """Are we running on Mac
233
234 @rtype: Bool"""
235 return wx.Platform=='__WXMAC__'
236
239 """Gets a bitmap from the resource directory
240
241 @rtype: wxBitmap
242 """
243 return getimage(name).ConvertToBitmap()
244
246 """Gets an image from the resource directory
247
248 @rtype: wx.Image
249 """
250 for ext in ("", ".png", ".jpg"):
251 if os.path.exists(getresourcefile(name+ext)):
252 return wx.Image(getresourcefile(name+ext))
253 print "You need to make "+name+".png"
254 return getimage('unknown')
255
258 """Returns name of file by adding it to resource directory pathname
259
260 No attempt is made to verify the file exists
261 @rtype: string
262 """
263 return os.path.join(resourcedirectory, filename)
264
266 """Returns what name we use for the helpfile
267
268 Without trailing extension as wxBestHelpController figures that out"""
269
270
271
272 j=os.path.join
273 paths=( (helpdirectory, True),
274 (resourcedirectory, False) )
275
276 if IsMSWindows():
277 name="bitpim.chm"
278 else:
279 name="bitpim.htb"
280
281 for p,mention in paths:
282 if os.path.isfile(j(p, name)):
283 if mention:
284 print "Using help file from "+p
285 return j(p, "bitpim")
286
287 assert False
288
290 "Returns a list of filenames matching the wildcard in the resource directory"
291 l=glob.glob(os.path.join(resourcedirectory, wildcard))
292 l.sort()
293 return l
294
295
296 resourcedirectory=os.path.join(common.get_main_dir(), 'resources')
297 helpdirectory=os.path.join(common.get_main_dir(), 'help')
302 if s is None: return s
303 if isinstance(s, unicode): return s
304 return str(s)
305
306 common.strorunicode=strorunicode
307 del strorunicode
308
309 else:
311 if s is None: return s
312 try:
313 return str(s)
314 except UnicodeEncodeError:
315 return s.encode("ascii", "replace")
316
317 common.strorunicode=strorunicode
318 del strorunicode
335
336
337
338
339 _ourart={
340 "ART_ADD_WALLPAPER": "add_picture",
341 "ART_DEL_WALLPAPER": "delete_picture",
342 "ART_ARROW_UP": "arrow_up",
343 "ART_ARROW_DOWN": "arrow_down",
344 "ART_ARROW_LEFT": "arrow_left",
345 "ART_ARROW_RIGHT": "arrow_right",
346 "ART_ADD_FIELD": "add_field",
347 "ART_DEL_FIELD": "delete_field",
348 "ART_ADD_CONTACT": "add_contact",
349 "ART_DEL_CONTACT": "delete_contact",
350 "ART_ADD_RINGER": "add_ringer",
351 "ART_DEL_RINGER": "delete_ringer",
352 "ART_ADD_MEMO": "add_memo",
353 "ART_DEL_MEMO": "delete_memo",
354 "ART_ADD_TODO": "add_todo",
355 "ART_DEL_TODO": "delete_todo",
356 "ART_ADD_SMS": "add_sms",
357 "ART_DEL_SMS": "delete_sms",
358 "ART_SEL_MEDIA": "select_media",
359 "ART_SEL_IMAGE": "select_image",
360 "ART_SEL_VIDEO": "select_video",
361 "ART_SEL_CAMERA": "select_camera",
362 "ART_SEL_SOUNDS": "select_sounds",
363 "ART_SEL_PHONEBOOK": "select_phonebook",
364 "ART_SEL_WALLPAPER": "select_wallpaper",
365 "ART_SEL_RINGERS": "select_ringers",
366 "ART_SEL_CALENDAR": "select_calendar",
367 "ART_SEL_CALLHISTORY": "select_call_history",
368 "ART_SEL_CALLS": "select_calls",
369 "ART_SEL_SMS": "select_sms",
370 "ART_SEL_MESSAGE": "select_message",
371 "ART_SEL_FILE": "select_file",
372 "ART_SEL_LOG": "select_log",
373 "ART_SEL_MEMO": "select_memo",
374 "ART_SEL_TODO": "select_todo",
375 "ART_SEL_PLAYLIST": "select_playlist",
376 "ART_SEL_PROTOCOL": "select_protocol",
377 "ART_SEL_CONSOLE": "select_console",
378 "ART_SEL_ROOT_IMAGE": "select_root",
379 "ART_SEL_PHONE_ROOT": "phone_root",
380 "ART_SEL_PHONE": "phone_root",
381 "ART_DATAGETPHONE": "datagetphone",
382 "ART_DATASENDPHONE": "datasendphone",
383 "ART_AUTOSYNCEXECUTE": "autosyncexecute",
384 "ART_HELPHELP": "helphelp",
385 "ART_EDITPHONEINFO": "editphoneinfo",
386 "ART_EDITDETECT": "editdetect",
387 "ART_EDITSETTINGS": "editsettings",
388 "ART_DATAHISTORICAL": "data_history",
389 "ART_MEDIA_LIST_VIEW": "media_list_view",
390 "ART_MEDIA_THUMB_VIEW": "media_thumb_view",
391 "ART_FOLDER_OPEN": "folder_open",
392 "ART_FOLDER": "folder"
393 }
399 """ArtProvider manages the art for the application"""
400
402 """Loads a bitmap and returns it depending on the parameters
403 """
404 if artid in _ourart:
405 return getbitmap(_ourart[artid])
406 return wx.NullBitmap
407
409
410 - def __init__(self, parent, title="Bitpim", dlg_msg=""):
411 self.__title=title
412 self.__dlg_msg=dlg_msg
413 self.__parent=parent
414 self.__msgs={}
415
417 """
418 Add a message to the list of messages to be displayed
419 Each message appears on it's own line
420 """
421
422
423
424 loop=0
425 key="%d.%05d" % (priority, loop)
426 while self.__msgs.has_key(key):
427 loop=loop+1
428 key="%d.%05d" % (priority, loop)
429 self.__msgs[key]={'msg': msg}
430 return
431
433 """
434 Displays the messages in a list in a dialog
435 max_rows: Max visible messages, if number of messages exceed
436 this a scroll bar will appear
437 max_columns: Max visible width in characters
438 returns: button pressed to exit dialog
439 """
440 keys=self.__msgs.keys()
441 keys.sort()
442 out_list=[]
443 for k in keys:
444 msg=self.__msgs[k]['msg']
445 out_list.append(msg)
446
447 msg_dlg=wx.Dialog(self.__parent, -1, self.__title,
448 style=wx.DEFAULT_DIALOG_STYLE|wx.RESIZE_BORDER|wx.SYSTEM_MENU|wx.MAXIMIZE_BOX|wx.MINIMIZE_BOX)
449 main_bs=wx.BoxSizer(wx.VERTICAL)
450 main_bs.Add(wx.StaticText(msg_dlg, -1, self.__dlg_msg), 0, wx.ALL|wx.ALIGN_LEFT, 5)
451 msgs=wx.ListBox(msg_dlg)
452 msgs.Set(out_list)
453 main_bs.Add(msgs, 0, wx.ALL|wx.EXPAND, 5)
454 main_bs.Add(wx.Button(msg_dlg, wx.ID_OK, 'OK'), 0, wx.ALIGN_CENTRE|wx.ALL, 5)
455 msg_dlg.SetSizer(main_bs)
456 msg_dlg.SetAutoLayout(True)
457 main_bs.Fit(msg_dlg)
458
459 res=msg_dlg.ShowModal()
460 print "multi "+`res`
461 msg_dlg.Destroy()
462 return res
463
465 return len(self.__msgs)
466
469