0001 ### BITPIM 0002 ### 0003 ### Copyright (C) 2006 Simon Capper <scapper@sbcglobal.net> 0004 ### 0005 ### This program is free software; you can redistribute it and/or modify 0006 ### it under the terms of the BitPim license as detailed in the LICENSE file. 0007 ### 0008 0009 0010 # standard modules 0011 from __future__ import with_statement 0012 import contextlib 0013 import os 0014 import cStringIO 0015 import copy 0016 import sha 0017 import time 0018 import string 0019 import zipfile 0020 0021 0022 # wx modules 0023 import wx 0024 0025 # BitPim modules 0026 import database 0027 import common 0028 import guiwidgets 0029 import guihelper 0030 import pubsub 0031 import widgets 0032 import wallpaper 0033 import ringers 0034 0035 class MediaWidget(wx.Panel, widgets.BitPimWidget): 0036 def __init__(self, mainwindow, parent): 0037 super(MediaWidget, self).__init__(parent, -1) 0038 self._main_window=mainwindow 0039 self.call_history_tree_nodes={} 0040 self._parent=parent 0041 # main box sizer 0042 self.vbs=wx.BoxSizer(wx.VERTICAL) 0043 # main stats display 0044 self.vbs.Add(wx.StaticText(self, -1, 'Media summary'), 0, wx.ALIGN_LEFT|wx.ALL, 2) 0045 # all done 0046 self.SetSizer(self.vbs) 0047 self.SetAutoLayout(True) 0048 self.vbs.Fit(self) 0049 self.ringernodes={} 0050 self.wallpapernodes={} 0051 self.widget_to_save=None 0052 self.origin_to_save="" 0053 self.SetBackgroundColour(wx.WHITE) 0054 self.ringerwidget=ringers.RingerView(self._main_window, parent, self) 0055 self.wallpaperwidget=wallpaper.WallpaperView(self._main_window, parent, self) 0056 pubsub.subscribe(self.OnPhoneModelChanged, pubsub.PHONE_MODEL_CHANGED) 0057 # populate data 0058 #self._populate() 0059 0060 def DoMediaSummary(self): 0061 summary=[] 0062 summary=self.GetWidgetSummary(self.ringerwidget, summary) 0063 summary=self.GetWidgetSummary(self.wallpaperwidget, summary) 0064 self.vbs.Clear(deleteWindows=True) 0065 self.vbs.Add(wx.StaticText(self, -1, 'Media summary'), 0, wx.ALIGN_LEFT|wx.ALL, 2) 0066 hbs=wx.BoxSizer(wx.HORIZONTAL) 0067 name=wx.BoxSizer(wx.VERTICAL) 0068 count=wx.BoxSizer(wx.VERTICAL) 0069 size=wx.BoxSizer(wx.VERTICAL) 0070 name.Add(wx.StaticText(self, -1, 'Origin'), 0, wx.ALIGN_LEFT|wx.ALL, 2) 0071 count.Add(wx.StaticText(self, -1, 'Number Files'), 0, wx.ALIGN_LEFT|wx.ALL, 2) 0072 size.Add(wx.StaticText(self, -1, 'Size'), 0, wx.ALIGN_LEFT|wx.ALL, 2) 0073 total_files=0 0074 total_size=0 0075 for entry in summary: 0076 name.Add(wx.StaticText(self, -1, entry[0]), 0, wx.ALIGN_LEFT|wx.ALL, 2) 0077 count.Add(wx.StaticText(self, -1, str(entry[1])), 0, wx.ALIGN_LEFT|wx.ALL, 2) 0078 size.Add(wx.StaticText(self, -1, self.GetNiceSizeString(entry[2])), 0, wx.ALIGN_LEFT|wx.ALL, 2) 0079 total_files+=entry[1] 0080 total_size+=entry[2] 0081 hbs.Add(name, 0, wx.ALIGN_LEFT|wx.ALL, 2) 0082 hbs.Add(count, 0, wx.ALIGN_LEFT|wx.ALL, 2) 0083 hbs.Add(size, 0, wx.ALIGN_LEFT|wx.ALL, 2) 0084 self.vbs.Add(hbs, 0, wx.ALIGN_LEFT|wx.ALL, 2) 0085 self.vbs.Add(wx.StaticText(self, -1, "Total number of media files: %d" % total_files), 0, wx.ALIGN_LEFT|wx.ALL, 2) 0086 self.vbs.Add(wx.StaticText(self, -1, "Total size of media files: %s" % self.GetNiceSizeString(total_size)), 0, wx.ALIGN_LEFT|wx.ALL, 2) 0087 self.vbs.Layout() 0088 0089 def GetNiceSizeString(self, size): 0090 orig=size 0091 size=float(size) 0092 if size < 1024: 0093 return "%d bytes" % size 0094 size=size/1024 0095 if size < 1024: 0096 return "%.2f KB (%d bytes)" % (size, orig) 0097 size=size/1024 0098 return "%.2f MB (%d bytes)" % (size, orig) 0099 0100 def GetWidgetSummary(self, widget, res): 0101 for k,e in widget.sections: 0102 num_files=0 0103 total_size=0 0104 for item in e: 0105 total_size+=item.size 0106 num_files+=1 0107 res.append((k.label, num_files, total_size)) 0108 return res 0109 0110 def GetRightClickMenuItems(self, node): 0111 result=[] 0112 result.append((widgets.BitPimWidget.MENU_NORMAL, guihelper.ID_EXPORT_MEDIA_TO_DIR, "Export to Folder ..." , "Export the media to a folder on your hard drive")) 0113 result.append((widgets.BitPimWidget.MENU_NORMAL, guihelper.ID_EXPORT_MEDIA_TO_ZIP, "Export to Zip File ..." , "Export the media to a zip file")) 0114 return result 0115 0116 def GetRinger(self): 0117 return self.ringerwidget 0118 0119 def GetWallpaper(self): 0120 return self.wallpaperwidget 0121 0122 def OnInit(self): 0123 self.AddMediaNode("ringers", self.ringerwidget, self._tree.ringers) 0124 self.AddMediaNode("sounds", self.ringerwidget, self._tree.sounds) 0125 self.AddMediaNode("images", self.wallpaperwidget, self._tree.image) 0126 self.ringerwidget.updateprofilevariables(self._main_window.phoneprofile) 0127 self.wallpaperwidget.updateprofilevariables(self._main_window.phoneprofile) 0128 self.DoMediaSummary() 0129 0130 def OnPhoneModelChanged(self, msg): 0131 for name in self.ringernodes: 0132 self._tree.DeletePage(self.ringernodes[name]) 0133 self.ringernodes={} 0134 for name in self.wallpapernodes: 0135 self._tree.DeletePage(self.wallpapernodes[name]) 0136 self.wallpapernodes={} 0137 self.OnInit() 0138 self.ringerwidget.OnRefresh() 0139 self.wallpaperwidget.OnRefresh() 0140 0141 def SaveToDir(self, directory): 0142 if self.widget_to_save==None: 0143 self.SaveWidgetToDir(directory, self.ringerwidget) 0144 self.SaveWidgetToDir(directory, self.wallpaperwidget) 0145 else: 0146 self.SaveWidgetToDir(directory, self.widget_to_save, self.origin_to_save) 0147 0148 def SaveWidgetToDir(self, directory, widget, filter=""): 0149 for k,e in widget.sections: 0150 # skip unrequested origins 0151 if filter!="" and filter!=k.label: 0152 continue 0153 opath=self._main_window._fixup(os.path.join(directory, k.label)) 0154 try: 0155 os.makedirs(opath) 0156 except: 0157 pass 0158 if not os.path.isdir(opath): 0159 raise Exception("Unable to create export directory "+opath) 0160 for item in e: 0161 me=widget._data[item.datakey][item.key] 0162 if me.mediadata!=None and me.mediadata!='': 0163 fpath=self._main_window._fixup(os.path.join(opath, me.name)) 0164 with file(fpath, "wb") as f: 0165 f.write(me.mediadata) 0166 if me.timestamp!=None: 0167 os.utime(fpath, (me.timestamp, me.timestamp)) 0168 0169 0170 def SaveToZip(self, zip_file): 0171 # create the zipfile in a buffer 0172 # and write to disk after it is all created 0173 op=cStringIO.StringIO() 0174 with contextlib.closing(zipfile.ZipFile(op, "w", zipfile.ZIP_DEFLATED)) as zip: 0175 if self.widget_to_save==None: 0176 self.SaveWidgetToZip(zip, self.ringerwidget) 0177 self.SaveWidgetToZip(zip, self.wallpaperwidget) 0178 else: 0179 self.SaveWidgetToZip(zip, self.widget_to_save, self.origin_to_save) 0180 open(zip_file, "wb").write(op.getvalue()) 0181 0182 def SaveWidgetToZip(self, zip, widget, filter=""): 0183 for k,e in widget.sections: 0184 # skip unrequested origins 0185 if filter!="" and filter!=k.label: 0186 continue 0187 for item in e: 0188 me=widget._data[item.datakey][item.key] 0189 if me.mediadata!=None and me.mediadata!='': 0190 zi=zipfile.ZipInfo() 0191 # zipfile does not like unicode. cp437 works on windows well, may be 0192 # a better choice than ascii, but no phones currently support anything 0193 # other than ascii for filenames 0194 name=k.label+"/"+me.name 0195 zi.filename=common.get_ascii_string(name, 'ignore') 0196 if me.timestamp==None: 0197 zi.date_time=(0,0,0,0,0,0) 0198 else: 0199 zi.date_time=time.localtime(me.timestamp)[:6] 0200 zi.compress_type=zipfile.ZIP_DEFLATED 0201 zip.writestr(zi, me.mediadata) 0202 0203 def GetNodeList(self, widget): 0204 res=[] 0205 if widget==self.ringerwidget: 0206 for name in self.ringernodes: 0207 res.append(name) 0208 else: 0209 for name in self.wallpapernodes: 0210 res.append(name) 0211 res.sort() 0212 return res 0213 0214 def AddMediaNode(self, node_name, widget, icon=None): 0215 if widget==self.ringerwidget: 0216 if node_name not in self.ringernodes: 0217 if icon==None: 0218 if string.find(node_name, "sound")!=-1: 0219 icon=self._tree.sounds 0220 else: 0221 icon=self._tree.ringers 0222 self.ringernodes[node_name]=self.AddSubPage(widget, node_name, icon) 0223 else: 0224 if node_name not in self.wallpapernodes: 0225 if icon==None: 0226 if string.find(node_name, "video")!=-1: 0227 icon=self._tree.video 0228 elif string.find(node_name, "camera")!=-1: 0229 icon=self._tree.camera 0230 else: 0231 icon=self._tree.image 0232 self.wallpapernodes[node_name]=self.AddSubPage(widget, node_name, icon) 0233 0234 def GetNodeName(self, widget, node): 0235 if widget==self.ringerwidget: 0236 for name in self.ringernodes: 0237 if self.ringernodes[name]==node: 0238 return name 0239 else: 0240 for name in self.wallpapernodes: 0241 if self.wallpapernodes[name]==node: 0242 return name 0243 0244 0245 #------------------------------------------------------------------------------ 0246 class ExportMediaToDirDialog(wx.DirDialog): 0247 def __init__(self, parent, title): 0248 super(ExportMediaToDirDialog, self).__init__(parent, message=title, style=wx.DD_DEFAULT_STYLE|wx.DD_NEW_DIR_BUTTON) 0249 self.media_root=parent.GetActiveMediaWidget() 0250 0251 def DoDialog(self): 0252 # do export 0253 rc=self.ShowModal() 0254 if rc==wx.ID_OK: 0255 self.media_root.SaveToDir(self.GetPath()) 0256 0257 class ExportMediaToZipDialog(wx.FileDialog): 0258 def __init__(self, parent, title): 0259 self.media_root=parent.GetActiveMediaWidget() 0260 ext="Zip files (*.zip)|*.zip|All Files (*.*)|*" 0261 if self.media_root.widget_to_save!=None: 0262 default_file=self.media_root.origin_to_save+".zip" 0263 print "here 1 "+default_file 0264 else: 0265 default_file="media.zip" 0266 print "here 2 "+default_file 0267 super(ExportMediaToZipDialog, self).__init__(parent, title, defaultFile=default_file, wildcard=ext, style=wx.SAVE|wx.OVERWRITE_PROMPT|wx.CHANGE_DIR) 0268 0269 def DoDialog(self): 0270 # do export 0271 rc=self.ShowModal() 0272 if rc==wx.ID_OK: 0273 self.media_root.SaveToZip(self.GetPath()) 0274
Generated by PyXR 0.9.4