Module phone_root
[hide private]
[frames] | no frames]

Source Code for Module phone_root

  1  ### BITPIM 
  2  ### 
  3  ### Copyright (C) 2003-2005 Roger Binns <rogerb@rogerbinns.com> 
  4  ### Copyright (C) 2006 Simon Capper <skyjunky@sbcglobal.net> 
  5  ### 
  6  ### This program is free software; you can redistribute it and/or modify 
  7  ### it under the terms of the BitPim license as detailed in the LICENSE file. 
  8  ### 
  9  ### $Id: phone_root.py 4390 2007-09-05 00:08:19Z djpham $ 
 10   
 11  """The main gui code for BitPim""" 
 12   
 13  # System modules 
 14  import ConfigParser 
 15  import time 
 16  import os 
 17  import cStringIO 
 18  import zipfile 
 19  import re 
 20  import sys 
 21  import shutil 
 22  import types 
 23  import datetime 
 24  import sha 
 25  import codecs 
 26   
 27  # wx modules 
 28  import wx 
 29   
 30  # my modules 
 31  import guiwidgets 
 32  import common 
 33  import version 
 34  import helpids 
 35  import bpcalendar 
 36  import comdiagnose 
 37  import phonebook 
 38  import importexport 
 39  import wallpaper 
 40  import ringers 
 41  import guihelper 
 42  import database 
 43  import memo 
 44  import todo 
 45  import sms_tab 
 46  import call_history 
 47  import today 
 48  import pubsub 
 49  import playlist 
 50  import filesystem 
 51  import widgets 
 52  import media_root 
 53  import t9editor 
 54  import vtab_media 
 55   
 56  if guihelper.IsMSWindows(): 
 57      import win32api 
 58      import win32con 
 59      import win32gui 
 60   
61 -class PhoneTree(wx.TreeCtrl):
62 - def __init__(self, parent, mw, id):
63 wx.TreeCtrl.__init__(self, parent, id, style=wx.TR_HAS_BUTTONS) 64 self.parent=parent 65 self.mw=mw 66 self.config=mw.config 67 bmsize=(22,22) 68 wx.EVT_TREE_SEL_CHANGED(self,id, self.OnItemSelected) 69 self.image_list=wx.ImageList(22, 22) 70 self.img_dir=self.image_list.Add(wx.ArtProvider_GetBitmap(wx.ART_FOLDER, 71 wx.ART_OTHER, 72 bmsize)) 73 art=["phonebook", "wallpaper", "ringers", "calendar", "callhistory", "calls", "sms", "message", "memo", 74 "file", "log", "todo", "playlist", "protocol", "console", "phone_root", "phone", "root_image", "media", 75 "image", "video", "camera", "sounds"] 76 for k in art: 77 s="self.%s= self.image_list.Add(wx.ArtProvider_GetBitmap(guihelper.ART_SEL_%s,wx.ART_TOOLBAR,bmsize))" % (k,k.upper()) 78 exec(s) 79 self.SetImageList(self.image_list) 80 if self.config.ReadInt('startwithtoday', 0): 81 self.startuppage='Phone' 82 else: 83 self.startuppage=self.config.Read("viewnotebookpage", "") 84 self.startuppage_item=None 85 self.DeleteAllItems() 86 self.active_phone=None 87 self.active_panel=self.root_panel=widgets.RootWidget(self.parent, wx.NewId()) 88 self.root=self.AddPage(None, self.root_panel, "BitPim", self.root_image) 89 self.del_bmp, self.short_help_delete=self.root_panel.GetDeleteInfo() 90 self.add_bmp, self.short_help_add=self.root_panel.GetAddInfo() 91 self.lw=None 92 self.lwdata=None 93 self.filesystemwidget=None 94 95 wx.EVT_RIGHT_UP(self, self.OnRightUp) 96 wx.EVT_KEY_DOWN(self, self.OnKeyDown) 97 wx.EVT_KEY_UP(self, self.OnKeyUp) 98 99 # add shared tabs 100 self.lw=guiwidgets.LogWindow(self.parent) 101 self.lw_id=self.AddPage(self.root, self.lw, "Log", self.log) 102 103 # Final widgets that depend on config 104 lv=self.config.ReadInt("viewlogdata", 0) 105 if lv: 106 self.OnViewLogData(None) 107 108 fv=self.config.ReadInt("viewfilesystem", 0) 109 if fv: 110 self.OnViewFilesystem(None) 111 wx.Yield()
112
113 - def OnKeyUp(self, evt):
114 self.active_panel.OnKeyUp(evt)
115 # pass onto widget 116
117 - def OnKeyDown(self, evt):
118 self.active_panel.OnKeyDown(evt)
119 # pass onto widget 120
121 - def CreatePhone(self, name, config, path, database_name):
122 phone=Phone(self.parent) 123 phone_id=self.AddPage(self.root, phone, name, self.phone, None, helpids.ID_TAB_TODAY) 124 phone.Initialise(self, self.mw, config, path, phone_id, database_name) 125 if self.active_phone==None: 126 self.Expand(phone_id) 127 self.active_phone=phone
128
129 - def GetActivePhone(self):
130 return self.active_phone
131
132 - def GetActiveWidget(self):
133 return self.active_panel
134
135 - def AddPage(self, phone, panel, name, image=None, after=None, help_id=None):
136 if image==None: 137 image=self.img_dir 138 if phone==None: 139 item=self.AddRoot(name) 140 elif after==None: 141 item=self.PrependItem(phone, name) 142 else: 143 item=self.InsertItem(phone, after, name) 144 self.SetPyData(item, panel) 145 self.SetItemImage(item, image) 146 panel.Show(False) 147 panel.InitialiseWidget(self, item, phone, self.config, help_id) 148 if not self.startuppage_item and name==self.startuppage: 149 self.startuppage_item=item 150 return item
151
152 - def SetStartupPage(self):
153 if self.startuppage_item: 154 self.SelectItem(self.startuppage_item)
155
156 - def AddNode(self, panel, name, image=None):
157 if image==None: 158 image=self.img_dir 159 item=self.AppendItem(panel.id, name) 160 self.SetPyData(item, panel) 161 self.SetItemImage(item, image) 162 return item
163
164 - def DeletePage(self, id):
165 self.Delete(id)
166
167 - def OnItemSelected(self, _):
168 item=self.GetSelection() 169 if item.IsOk(): 170 if self.GetItemPyData(item): 171 self.active_panel=self.GetItemPyData(item) 172 self.active_panel.OnSelected(item) 173 text=self.active_panel.GetWidgetName() 174 if text is not None: 175 self.config.Write("viewnotebookpage", text) 176 wx.CallAfter(self.mw.SetActivePanel, self.active_panel) 177 # deal with graying out/in menu items on notebook page changing 178 del_bmp, short_help_delete=self.active_panel.GetDeleteInfo() 179 add_bmp, short_help_add=self.active_panel.GetAddInfo() 180 if del_bmp!=self.del_bmp or add_bmp!=self.add_bmp or self.short_help_delete!=short_help_delete: 181 self.mw.UpdateToolbarOnPanelChange(add_bmp, short_help_add, del_bmp, short_help_delete) 182 self.add_bmp=add_bmp 183 self.del_bmp=del_bmp 184 self.short_help_delete=short_help_delete 185 self.short_help_add=short_help_add
186
187 - def OnRightUp(self, event):
188 pt = event.GetPosition(); 189 item, flags = self.HitTest(pt) 190 if item.IsOk(): 191 self.active_panel=self.GetItemPyData(item) 192 self.active_panel.OnPopupMenu(self, item, pt)
193 194 # update handlers for controls that are not always available
195 - def ViewLogDataUIEvent(self, event):
196 event.Check(self.lwdata != None)
197
198 - def ViewFileSystemUIEvent(self, event):
199 event.Check(self.filesystemwidget != None)
200
201 - def DataSendPhoneUpdateUIEvent(self, event):
202 event.Enable(not wx.GetApp().SAFEMODE)
203
204 - def EditCopyUpdateUIEvent(self, event):
205 event.Enable(self.active_panel.CanCopy())
206
207 - def EditPasteUpdateUIEvent(self, event):
208 event.Enable(self.active_panel.CanPaste())
209
210 - def EditRenameUpdateUIEvent(self, event):
211 event.Enable(self.active_panel.CanRename())
212
213 - def DataDeleteItemUpdateUIEvent(self, event):
214 event.Enable(self.active_panel.CanDelete())
215
216 - def DataAddItemUpdateUIEvent(self, event):
217 event.Enable(self.active_panel.CanAdd())
218
219 - def HistoricalDataUpdateUIEvent(self, event):
220 event.Enable(self.active_panel.HasHistoricalData())
221
222 - def ViewPreviewDataUpdateUIEvent(self, event):
223 event.Enable(self.active_panel.HasPreviewPane()) 224 event.Check(self.active_panel.IsPreviewPaneEnabled())
225
226 - def ViewColumnsUpdateUIEvent(self, event):
227 event.Enable(self.active_panel.HasColumnSelector())
228
229 - def FilePrintDataUpdateUIEvent(self, event):
230 event.Enable(self.active_panel.CanPrint())
231
232 - def SelectAllDataUpdateUIEvent(self, event):
233 event.Enable(self.active_panel.CanSelectAll())
234
235 - def OnFilePrint(self,_):
236 self.active_panel.OnPrintDialog(self, self.config)
237
238 - def OnDataHistorical(self, _):
239 self.active_panel.OnHistoricalData()
240
241 - def OnEditAddEntry(self, evt):
242 self.active_panel.OnAdd(evt)
243
244 - def OnEditDeleteEntry(self, evt):
245 self.active_panel.OnDelete(evt)
246
247 - def OnEditSelectAll(self, evt):
248 self.active_panel.OnSelectAll(evt)
249
250 - def OnCopyEntry(self, evt):
251 self.active_panel.OnCopy(evt)
252
253 - def OnPasteEntry(self, evt):
254 self.active_panel.OnPaste(evt)
255
256 - def OnRenameEntry(self, evt):
257 self.active_panel.OnRename(evt)
258
259 - def OnViewClearLogs(self, _):
260 self.lw.Clear() 261 if self.lwdata is not None: 262 self.lwdata.Clear()
263
264 - def OnViewColumns(self, _):
265 self.active_panel.OnViewColumnSelector()
266
267 - def OnViewPreview(self, evt):
268 if not self.active_panel.IsPreviewPaneEnabled(): 269 config=1 270 preview_on=True 271 else: 272 config=0 273 preview_on=False 274 self.active_panel.OnViewPreview(preview_on)
275
276 - def OnViewLogData(self, _):
277 # toggle state of the log data 278 logdatatitle="Protocol Log" 279 if self.lwdata is None: 280 self.lwdata=guiwidgets.LogWindow(self.parent) 281 self.lwdata_id=self.AddPage(self.root, self.lwdata, logdatatitle, self.log, self.lw_id) 282 self.config.WriteInt("viewlogdata", 1) 283 else: 284 self.lwdata=None 285 self.DeletePage(self.lwdata_id) 286 self.lwdata_id=0 287 self.config.WriteInt("viewlogdata", 0)
288
289 - def OnViewFilesystem(self,_):
290 # toggle filesystem view 291 logtitle="Log" 292 fstitle="Filesystem" 293 if self.filesystemwidget is None: 294 self.filesystemwidget=filesystem.FileSystemView(self.mw, self.parent, id=97) 295 pos=self.GetPrevSibling(self.lw_id) 296 self.filesystemwidget_id=self.AddPage(self.root, self.filesystemwidget, fstitle, self.file, pos) 297 self.config.WriteInt("viewfilesystem", 1) 298 else: 299 self.filesystemwidget=None 300 self.DeletePage(self.filesystemwidget_id) 301 self.config.WriteInt("viewfilesystem", 0)
302
303 - def OnBusyStart(self):
304 return self.mw.OnBusyStart()
305
306 - def OnBusyEnd(self):
307 return self.mw.OnBusyEnd()
308
309 -class Phone(today.TodayWidget):
310 - def __init__(self, parent):
311 self.parent=parent 312 today.TodayWidget.__init__(self, self, self.parent) 313 pubsub.subscribe(self.OnPhoneChanged, pubsub.PHONE_MODEL_CHANGED)
314
315 - def Initialise(self, tree, mw, config, path, phone_id, database_name):
316 self.tree=tree 317 self.mw=mw 318 self.phone_id=phone_id 319 self.config=config 320 self.path=path 321 self.phoneprofile=self.mw.phoneprofile 322 id=None 323 324 blob_path=database_name+"_blobs" 325 self.blob_path=self._fixup(os.path.join(self.path, blob_path)) 326 self.ringerpath=self._fixup(os.path.join(self.path, "ringer")) 327 self.wallpaperpath=self._fixup(os.path.join(self.path, "wallpaper")) 328 self.phonebookpath=self._fixup(os.path.join(self.path, "phonebook")) 329 self.calendarpath=self._fixup(os.path.join(self.path, "calendar")) 330 331 self.EnsureDatabase(self.path, self.path, database_name) 332 # create all the panels for this phone 333 if self.config.ReadInt("console", 0): 334 import developer 335 id=self.tree.AddPage(self.phone_id, developer.DeveloperPanel(self.parent, {'mw': self.mw, 'db': self.database} ), "Console", self.tree.console) 336 self.phonewidget=phonebook.PhoneWidget(self, self.parent, self.config) 337 id=self.tree.AddPage(self.phone_id, self.phonewidget, "PhoneBook", self.tree.phonebook,id) 338 self.mediawidget=media_root.MediaWidget(self, self.parent) 339 id=self.tree.AddPage(self.phone_id, self.mediawidget, 340 "Media", self.tree.media, id, 341 helpids.ID_TAB_MEDIA) 342 self.calendarwidget=bpcalendar.Calendar(self, self.parent) 343 id=self.tree.AddPage(self.phone_id, self.calendarwidget, "Calendar", self.tree.calendar,id) 344 self.memowidget=memo.MemoWidget(self, self.parent) 345 id=self.tree.AddPage(self.phone_id, self.memowidget, "Memo", self.tree.memo,id) 346 self.todowidget=todo.TodoWidget(self, self.parent) 347 id=self.tree.AddPage(self.phone_id, self.todowidget, 'Todo', self.tree.todo,id) 348 self.smswidget=sms_tab.SMSWidget(self, self.parent) 349 id=self.tree.AddPage(self.phone_id, self.smswidget, 'SMS', 350 self.tree.sms,id, helpids.ID_TAB_SMS) 351 self.callhistorywidget=call_history.CallHistoryWidget(self, self.parent) 352 id=self.tree.AddPage(self.phone_id, self.callhistorywidget, 'Call History', self.tree.callhistory, id) 353 self.playlistwidget=playlist.PlaylistWidget(self, self.parent) 354 id=self.tree.AddPage(self.phone_id, self.playlistwidget, 'Play List', self.tree.playlist,id) 355 self.t9editorwidget=t9editor.T9EditorWidget(self, self.parent) 356 id=self.tree.AddPage(self.phone_id, self.t9editorwidget, 'T9 Editor', 357 None, id, helpids.ID_TAB_T9EDITOR) 358 359 # update the the status bar info 360 self.mw.SetPhoneModelStatus() 361 self.mw.SetVersionsStatus() 362 363 # populate all the widgets 364 try: 365 results={} 366 # get info 367 self.phonewidget.getfromfs(results) 368 self.mediawidget.GetWallpaper().getfromfs(results) 369 self.mediawidget.GetRinger().getfromfs(results) 370 self.calendarwidget.getfromfs(results) 371 self.memowidget.getfromfs(results) 372 self.todowidget.getfromfs(results) 373 self.smswidget.getfromfs(results) 374 self.callhistorywidget.getfromfs(results) 375 self.playlistwidget.getfromfs(results) 376 self.t9editorwidget.getfromfs(results) 377 # update controls 378 wx.SafeYield(onlyIfNeeded=True) 379 self.phonewidget.populate(results) 380 wx.SafeYield(onlyIfNeeded=True) 381 self.mediawidget.GetWallpaper().populate(results) 382 wx.SafeYield(onlyIfNeeded=True) 383 self.mediawidget.GetRinger().populate(results) 384 wx.SafeYield(onlyIfNeeded=True) 385 self.calendarwidget.populate(results) 386 wx.SafeYield(onlyIfNeeded=True) 387 self.memowidget.populate(results) 388 wx.SafeYield(onlyIfNeeded=True) 389 self.todowidget.populate(results) 390 wx.SafeYield(onlyIfNeeded=True) 391 self.smswidget.populate(results) 392 wx.SafeYield(onlyIfNeeded=True) 393 self.callhistorywidget.populate(results) 394 wx.SafeYield(onlyIfNeeded=True) 395 self.playlistwidget.populate(results) 396 wx.SafeYield(onlyIfNeeded=True) 397 self.t9editorwidget.populate(results) 398 except Exception, e: 399 if __debug__: 400 raise 401 wx.CallAfter(self.tree.SetStartupPage)
402
403 - def OnPhoneChanged(self, _):
404 self.phoneprofile=self.mw.phoneprofile
405 406 # deal with the database
407 - def EnsureDatabase(self, newpath, oldpath, database_file):
408 newdbpath=os.path.abspath(os.path.join(newpath, database_file)) 409 if oldpath is not None and len(oldpath) and oldpath!=newpath: 410 # copy database to new location 411 if self.database: 412 self.database=None # cause it to be closed 413 olddbpath=os.path.abspath(os.path.join(oldpath, "bitpim.db")) 414 if os.path.exists(olddbpath) and not os.path.exists(newdbpath): 415 shutil.copyfile(olddbpath, newdbpath) 416 self.database=None # allow gc 417 # Preparing for virtual tables to store media data 418 vtabs=[ { 'tablename': 'ringtone-index__mediadata', 419 'modulename': 'ringtonemodule', 420 'moduleclass': vtab_media.Media, 421 'args': (self.ringerpath,) }, 422 { 'tablename': 'wallpaper-index__mediadata', 423 'modulename': 'wallpapermodule', 424 'moduleclass': vtab_media.Media, 425 'args': (self.wallpaperpath,) } 426 ] 427 self.database=database.Database(newdbpath, vtabs)
428
429 - def GetDatabase(self):
430 return self.database
431
432 - def _fixup(self, path):
433 # os.path.join screws up adding root directory of a drive to 434 # a directory. eg join("c:\", "foo") gives "c:\\foo" whch 435 # is invalid. This function fixes that 436 if len(path)>=3: 437 if path[1]==':' and path[2]=='\\' and path[3]=='\\': 438 return path[0:2]+path[3:] 439 return path
440
441 - def OnBusyStart(self):
442 return self.mw.OnBusyStart()
443
444 - def OnBusyEnd(self):
445 return self.mw.OnBusyEnd()
446
447 - def log(self, str):
448 self.mw.log(str)
449