0001 ### BITPIM 0002 ### 0003 ### Copyright (C) 2003-2005 Roger Binns <rogerb@rogerbinns.com> 0004 ### Copyright (C) 2006 Simon Capper <skyjunky@sbcglobal.net> 0005 ### 0006 ### This program is free software; you can redistribute it and/or modify 0007 ### it under the terms of the BitPim license as detailed in the LICENSE file. 0008 ### 0009 ### $Id: phone_root.py 4390 2007-09-05 00:08:19Z djpham $ 0010 0011 """The main gui code for BitPim""" 0012 0013 # System modules 0014 import ConfigParser 0015 import time 0016 import os 0017 import cStringIO 0018 import zipfile 0019 import re 0020 import sys 0021 import shutil 0022 import types 0023 import datetime 0024 import sha 0025 import codecs 0026 0027 # wx modules 0028 import wx 0029 0030 # my modules 0031 import guiwidgets 0032 import common 0033 import version 0034 import helpids 0035 import bpcalendar 0036 import comdiagnose 0037 import phonebook 0038 import importexport 0039 import wallpaper 0040 import ringers 0041 import guihelper 0042 import database 0043 import memo 0044 import todo 0045 import sms_tab 0046 import call_history 0047 import today 0048 import pubsub 0049 import playlist 0050 import filesystem 0051 import widgets 0052 import media_root 0053 import t9editor 0054 import vtab_media 0055 0056 if guihelper.IsMSWindows(): 0057 import win32api 0058 import win32con 0059 import win32gui 0060 0061 class PhoneTree(wx.TreeCtrl): 0062 def __init__(self, parent, mw, id): 0063 wx.TreeCtrl.__init__(self, parent, id, style=wx.TR_HAS_BUTTONS) 0064 self.parent=parent 0065 self.mw=mw 0066 self.config=mw.config 0067 bmsize=(22,22) 0068 wx.EVT_TREE_SEL_CHANGED(self,id, self.OnItemSelected) 0069 self.image_list=wx.ImageList(22, 22) 0070 self.img_dir=self.image_list.Add(wx.ArtProvider_GetBitmap(wx.ART_FOLDER, 0071 wx.ART_OTHER, 0072 bmsize)) 0073 art=["phonebook", "wallpaper", "ringers", "calendar", "callhistory", "calls", "sms", "message", "memo", 0074 "file", "log", "todo", "playlist", "protocol", "console", "phone_root", "phone", "root_image", "media", 0075 "image", "video", "camera", "sounds"] 0076 for k in art: 0077 s="self.%s= self.image_list.Add(wx.ArtProvider_GetBitmap(guihelper.ART_SEL_%s,wx.ART_TOOLBAR,bmsize))" % (k,k.upper()) 0078 exec(s) 0079 self.SetImageList(self.image_list) 0080 if self.config.ReadInt('startwithtoday', 0): 0081 self.startuppage='Phone' 0082 else: 0083 self.startuppage=self.config.Read("viewnotebookpage", "") 0084 self.startuppage_item=None 0085 self.DeleteAllItems() 0086 self.active_phone=None 0087 self.active_panel=self.root_panel=widgets.RootWidget(self.parent, wx.NewId()) 0088 self.root=self.AddPage(None, self.root_panel, "BitPim", self.root_image) 0089 self.del_bmp, self.short_help_delete=self.root_panel.GetDeleteInfo() 0090 self.add_bmp, self.short_help_add=self.root_panel.GetAddInfo() 0091 self.lw=None 0092 self.lwdata=None 0093 self.filesystemwidget=None 0094 0095 wx.EVT_RIGHT_UP(self, self.OnRightUp) 0096 wx.EVT_KEY_DOWN(self, self.OnKeyDown) 0097 wx.EVT_KEY_UP(self, self.OnKeyUp) 0098 0099 # add shared tabs 0100 self.lw=guiwidgets.LogWindow(self.parent) 0101 self.lw_id=self.AddPage(self.root, self.lw, "Log", self.log) 0102 0103 # Final widgets that depend on config 0104 lv=self.config.ReadInt("viewlogdata", 0) 0105 if lv: 0106 self.OnViewLogData(None) 0107 0108 fv=self.config.ReadInt("viewfilesystem", 0) 0109 if fv: 0110 self.OnViewFilesystem(None) 0111 wx.Yield() 0112 0113 def OnKeyUp(self, evt): 0114 self.active_panel.OnKeyUp(evt) 0115 # pass onto widget 0116 0117 def OnKeyDown(self, evt): 0118 self.active_panel.OnKeyDown(evt) 0119 # pass onto widget 0120 0121 def CreatePhone(self, name, config, path, database_name): 0122 phone=Phone(self.parent) 0123 phone_id=self.AddPage(self.root, phone, name, self.phone, None, helpids.ID_TAB_TODAY) 0124 phone.Initialise(self, self.mw, config, path, phone_id, database_name) 0125 if self.active_phone==None: 0126 self.Expand(phone_id) 0127 self.active_phone=phone 0128 0129 def GetActivePhone(self): 0130 return self.active_phone 0131 0132 def GetActiveWidget(self): 0133 return self.active_panel 0134 0135 def AddPage(self, phone, panel, name, image=None, after=None, help_id=None): 0136 if image==None: 0137 image=self.img_dir 0138 if phone==None: 0139 item=self.AddRoot(name) 0140 elif after==None: 0141 item=self.PrependItem(phone, name) 0142 else: 0143 item=self.InsertItem(phone, after, name) 0144 self.SetPyData(item, panel) 0145 self.SetItemImage(item, image) 0146 panel.Show(False) 0147 panel.InitialiseWidget(self, item, phone, self.config, help_id) 0148 if not self.startuppage_item and name==self.startuppage: 0149 self.startuppage_item=item 0150 return item 0151 0152 def SetStartupPage(self): 0153 if self.startuppage_item: 0154 self.SelectItem(self.startuppage_item) 0155 0156 def AddNode(self, panel, name, image=None): 0157 if image==None: 0158 image=self.img_dir 0159 item=self.AppendItem(panel.id, name) 0160 self.SetPyData(item, panel) 0161 self.SetItemImage(item, image) 0162 return item 0163 0164 def DeletePage(self, id): 0165 self.Delete(id) 0166 0167 def OnItemSelected(self, _): 0168 item=self.GetSelection() 0169 if item.IsOk(): 0170 if self.GetItemPyData(item): 0171 self.active_panel=self.GetItemPyData(item) 0172 self.active_panel.OnSelected(item) 0173 text=self.active_panel.GetWidgetName() 0174 if text is not None: 0175 self.config.Write("viewnotebookpage", text) 0176 wx.CallAfter(self.mw.SetActivePanel, self.active_panel) 0177 # deal with graying out/in menu items on notebook page changing 0178 del_bmp, short_help_delete=self.active_panel.GetDeleteInfo() 0179 add_bmp, short_help_add=self.active_panel.GetAddInfo() 0180 if del_bmp!=self.del_bmp or add_bmp!=self.add_bmp or self.short_help_delete!=short_help_delete: 0181 self.mw.UpdateToolbarOnPanelChange(add_bmp, short_help_add, del_bmp, short_help_delete) 0182 self.add_bmp=add_bmp 0183 self.del_bmp=del_bmp 0184 self.short_help_delete=short_help_delete 0185 self.short_help_add=short_help_add 0186 0187 def OnRightUp(self, event): 0188 pt = event.GetPosition(); 0189 item, flags = self.HitTest(pt) 0190 if item.IsOk(): 0191 self.active_panel=self.GetItemPyData(item) 0192 self.active_panel.OnPopupMenu(self, item, pt) 0193 0194 # update handlers for controls that are not always available 0195 def ViewLogDataUIEvent(self, event): 0196 event.Check(self.lwdata != None) 0197 0198 def ViewFileSystemUIEvent(self, event): 0199 event.Check(self.filesystemwidget != None) 0200 0201 def DataSendPhoneUpdateUIEvent(self, event): 0202 event.Enable(not wx.GetApp().SAFEMODE) 0203 0204 def EditCopyUpdateUIEvent(self, event): 0205 event.Enable(self.active_panel.CanCopy()) 0206 0207 def EditPasteUpdateUIEvent(self, event): 0208 event.Enable(self.active_panel.CanPaste()) 0209 0210 def EditRenameUpdateUIEvent(self, event): 0211 event.Enable(self.active_panel.CanRename()) 0212 0213 def DataDeleteItemUpdateUIEvent(self, event): 0214 event.Enable(self.active_panel.CanDelete()) 0215 0216 def DataAddItemUpdateUIEvent(self, event): 0217 event.Enable(self.active_panel.CanAdd()) 0218 0219 def HistoricalDataUpdateUIEvent(self, event): 0220 event.Enable(self.active_panel.HasHistoricalData()) 0221 0222 def ViewPreviewDataUpdateUIEvent(self, event): 0223 event.Enable(self.active_panel.HasPreviewPane()) 0224 event.Check(self.active_panel.IsPreviewPaneEnabled()) 0225 0226 def ViewColumnsUpdateUIEvent(self, event): 0227 event.Enable(self.active_panel.HasColumnSelector()) 0228 0229 def FilePrintDataUpdateUIEvent(self, event): 0230 event.Enable(self.active_panel.CanPrint()) 0231 0232 def SelectAllDataUpdateUIEvent(self, event): 0233 event.Enable(self.active_panel.CanSelectAll()) 0234 0235 def OnFilePrint(self,_): 0236 self.active_panel.OnPrintDialog(self, self.config) 0237 0238 def OnDataHistorical(self, _): 0239 self.active_panel.OnHistoricalData() 0240 0241 def OnEditAddEntry(self, evt): 0242 self.active_panel.OnAdd(evt) 0243 0244 def OnEditDeleteEntry(self, evt): 0245 self.active_panel.OnDelete(evt) 0246 0247 def OnEditSelectAll(self, evt): 0248 self.active_panel.OnSelectAll(evt) 0249 0250 def OnCopyEntry(self, evt): 0251 self.active_panel.OnCopy(evt) 0252 0253 def OnPasteEntry(self, evt): 0254 self.active_panel.OnPaste(evt) 0255 0256 def OnRenameEntry(self, evt): 0257 self.active_panel.OnRename(evt) 0258 0259 def OnViewClearLogs(self, _): 0260 self.lw.Clear() 0261 if self.lwdata is not None: 0262 self.lwdata.Clear() 0263 0264 def OnViewColumns(self, _): 0265 self.active_panel.OnViewColumnSelector() 0266 0267 def OnViewPreview(self, evt): 0268 if not self.active_panel.IsPreviewPaneEnabled(): 0269 config=1 0270 preview_on=True 0271 else: 0272 config=0 0273 preview_on=False 0274 self.active_panel.OnViewPreview(preview_on) 0275 0276 def OnViewLogData(self, _): 0277 # toggle state of the log data 0278 logdatatitle="Protocol Log" 0279 if self.lwdata is None: 0280 self.lwdata=guiwidgets.LogWindow(self.parent) 0281 self.lwdata_id=self.AddPage(self.root, self.lwdata, logdatatitle, self.log, self.lw_id) 0282 self.config.WriteInt("viewlogdata", 1) 0283 else: 0284 self.lwdata=None 0285 self.DeletePage(self.lwdata_id) 0286 self.lwdata_id=0 0287 self.config.WriteInt("viewlogdata", 0) 0288 0289 def OnViewFilesystem(self,_): 0290 # toggle filesystem view 0291 logtitle="Log" 0292 fstitle="Filesystem" 0293 if self.filesystemwidget is None: 0294 self.filesystemwidget=filesystem.FileSystemView(self.mw, self.parent, id=97) 0295 pos=self.GetPrevSibling(self.lw_id) 0296 self.filesystemwidget_id=self.AddPage(self.root, self.filesystemwidget, fstitle, self.file, pos) 0297 self.config.WriteInt("viewfilesystem", 1) 0298 else: 0299 self.filesystemwidget=None 0300 self.DeletePage(self.filesystemwidget_id) 0301 self.config.WriteInt("viewfilesystem", 0) 0302 0303 def OnBusyStart(self): 0304 return self.mw.OnBusyStart() 0305 0306 def OnBusyEnd(self): 0307 return self.mw.OnBusyEnd() 0308 0309 class Phone(today.TodayWidget): 0310 def __init__(self, parent): 0311 self.parent=parent 0312 today.TodayWidget.__init__(self, self, self.parent) 0313 pubsub.subscribe(self.OnPhoneChanged, pubsub.PHONE_MODEL_CHANGED) 0314 0315 def Initialise(self, tree, mw, config, path, phone_id, database_name): 0316 self.tree=tree 0317 self.mw=mw 0318 self.phone_id=phone_id 0319 self.config=config 0320 self.path=path 0321 self.phoneprofile=self.mw.phoneprofile 0322 id=None 0323 0324 blob_path=database_name+"_blobs" 0325 self.blob_path=self._fixup(os.path.join(self.path, blob_path)) 0326 self.ringerpath=self._fixup(os.path.join(self.path, "ringer")) 0327 self.wallpaperpath=self._fixup(os.path.join(self.path, "wallpaper")) 0328 self.phonebookpath=self._fixup(os.path.join(self.path, "phonebook")) 0329 self.calendarpath=self._fixup(os.path.join(self.path, "calendar")) 0330 0331 self.EnsureDatabase(self.path, self.path, database_name) 0332 # create all the panels for this phone 0333 if self.config.ReadInt("console", 0): 0334 import developer 0335 id=self.tree.AddPage(self.phone_id, developer.DeveloperPanel(self.parent, {'mw': self.mw, 'db': self.database} ), "Console", self.tree.console) 0336 self.phonewidget=phonebook.PhoneWidget(self, self.parent, self.config) 0337 id=self.tree.AddPage(self.phone_id, self.phonewidget, "PhoneBook", self.tree.phonebook,id) 0338 self.mediawidget=media_root.MediaWidget(self, self.parent) 0339 id=self.tree.AddPage(self.phone_id, self.mediawidget, 0340 "Media", self.tree.media, id, 0341 helpids.ID_TAB_MEDIA) 0342 self.calendarwidget=bpcalendar.Calendar(self, self.parent) 0343 id=self.tree.AddPage(self.phone_id, self.calendarwidget, "Calendar", self.tree.calendar,id) 0344 self.memowidget=memo.MemoWidget(self, self.parent) 0345 id=self.tree.AddPage(self.phone_id, self.memowidget, "Memo", self.tree.memo,id) 0346 self.todowidget=todo.TodoWidget(self, self.parent) 0347 id=self.tree.AddPage(self.phone_id, self.todowidget, 'Todo', self.tree.todo,id) 0348 self.smswidget=sms_tab.SMSWidget(self, self.parent) 0349 id=self.tree.AddPage(self.phone_id, self.smswidget, 'SMS', 0350 self.tree.sms,id, helpids.ID_TAB_SMS) 0351 self.callhistorywidget=call_history.CallHistoryWidget(self, self.parent) 0352 id=self.tree.AddPage(self.phone_id, self.callhistorywidget, 'Call History', self.tree.callhistory, id) 0353 self.playlistwidget=playlist.PlaylistWidget(self, self.parent) 0354 id=self.tree.AddPage(self.phone_id, self.playlistwidget, 'Play List', self.tree.playlist,id) 0355 self.t9editorwidget=t9editor.T9EditorWidget(self, self.parent) 0356 id=self.tree.AddPage(self.phone_id, self.t9editorwidget, 'T9 Editor', 0357 None, id, helpids.ID_TAB_T9EDITOR) 0358 0359 # update the the status bar info 0360 self.mw.SetPhoneModelStatus() 0361 self.mw.SetVersionsStatus() 0362 0363 # populate all the widgets 0364 try: 0365 results={} 0366 # get info 0367 self.phonewidget.getfromfs(results) 0368 self.mediawidget.GetWallpaper().getfromfs(results) 0369 self.mediawidget.GetRinger().getfromfs(results) 0370 self.calendarwidget.getfromfs(results) 0371 self.memowidget.getfromfs(results) 0372 self.todowidget.getfromfs(results) 0373 self.smswidget.getfromfs(results) 0374 self.callhistorywidget.getfromfs(results) 0375 self.playlistwidget.getfromfs(results) 0376 self.t9editorwidget.getfromfs(results) 0377 # update controls 0378 wx.SafeYield(onlyIfNeeded=True) 0379 self.phonewidget.populate(results) 0380 wx.SafeYield(onlyIfNeeded=True) 0381 self.mediawidget.GetWallpaper().populate(results) 0382 wx.SafeYield(onlyIfNeeded=True) 0383 self.mediawidget.GetRinger().populate(results) 0384 wx.SafeYield(onlyIfNeeded=True) 0385 self.calendarwidget.populate(results) 0386 wx.SafeYield(onlyIfNeeded=True) 0387 self.memowidget.populate(results) 0388 wx.SafeYield(onlyIfNeeded=True) 0389 self.todowidget.populate(results) 0390 wx.SafeYield(onlyIfNeeded=True) 0391 self.smswidget.populate(results) 0392 wx.SafeYield(onlyIfNeeded=True) 0393 self.callhistorywidget.populate(results) 0394 wx.SafeYield(onlyIfNeeded=True) 0395 self.playlistwidget.populate(results) 0396 wx.SafeYield(onlyIfNeeded=True) 0397 self.t9editorwidget.populate(results) 0398 except Exception, e: 0399 if __debug__: 0400 raise 0401 wx.CallAfter(self.tree.SetStartupPage) 0402 0403 def OnPhoneChanged(self, _): 0404 self.phoneprofile=self.mw.phoneprofile 0405 0406 # deal with the database 0407 def EnsureDatabase(self, newpath, oldpath, database_file): 0408 newdbpath=os.path.abspath(os.path.join(newpath, database_file)) 0409 if oldpath is not None and len(oldpath) and oldpath!=newpath: 0410 # copy database to new location 0411 if self.database: 0412 self.database=None # cause it to be closed 0413 olddbpath=os.path.abspath(os.path.join(oldpath, "bitpim.db")) 0414 if os.path.exists(olddbpath) and not os.path.exists(newdbpath): 0415 shutil.copyfile(olddbpath, newdbpath) 0416 self.database=None # allow gc 0417 # Preparing for virtual tables to store media data 0418 vtabs=[ { 'tablename': 'ringtone-index__mediadata', 0419 'modulename': 'ringtonemodule', 0420 'moduleclass': vtab_media.Media, 0421 'args': (self.ringerpath,) }, 0422 { 'tablename': 'wallpaper-index__mediadata', 0423 'modulename': 'wallpapermodule', 0424 'moduleclass': vtab_media.Media, 0425 'args': (self.wallpaperpath,) } 0426 ] 0427 self.database=database.Database(newdbpath, vtabs) 0428 0429 def GetDatabase(self): 0430 return self.database 0431 0432 def _fixup(self, path): 0433 # os.path.join screws up adding root directory of a drive to 0434 # a directory. eg join("c:\", "foo") gives "c:\\foo" whch 0435 # is invalid. This function fixes that 0436 if len(path)>=3: 0437 if path[1]==':' and path[2]=='\\' and path[3]=='\\': 0438 return path[0:2]+path[3:] 0439 return path 0440 0441 def OnBusyStart(self): 0442 return self.mw.OnBusyStart() 0443 0444 def OnBusyEnd(self): 0445 return self.mw.OnBusyEnd() 0446 0447 def log(self, str): 0448 self.mw.log(str) 0449 0450 0451
Generated by PyXR 0.9.4