PyXR

c:\projects\bitpim\src \ phone_root.py



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