1# -*- coding: utf-8 -*- 2# 3# PhotoFilmStrip - Creates movies out of your pictures. 4# 5# Copyright (C) 2008 Jens Goepfert 6# 7import wx 8 9from photofilmstrip.core.PicturePattern import PicturePattern 10from photofilmstrip.gui.ImageSectionEditor import ImageProxy 11from photofilmstrip.gui.PnlPfsProject import ( 12 PnlPfsProject, ID_PIC_IMPORT, ID_MUSIC, ID_RENDER_FILMSTRIP) 13 14 15class PnlTimelapse(PnlPfsProject): 16 17 def _GetEditorName(self): 18 return _(u"Timelapse") 19 20 def AddToolBarActions(self, toolBar): 21 toolBar.AddTool(ID_PIC_IMPORT, '', 22 wx.ArtProvider.GetBitmap('PFS_IMPORT_PICTURES_24'), 23 wx.ArtProvider.GetBitmap('PFS_IMPORT_PICTURES_D_24'), 24 wx.ITEM_NORMAL, 25 _(u'Import Pictures'), 26 _(u'Import Pictures'), 27 None) 28 toolBar.AddSeparator() 29 toolBar.AddTool(ID_MUSIC, '', 30 wx.ArtProvider.GetBitmap('PFS_MUSIC_24'), 31 wx.NullBitmap, 32 wx.ITEM_NORMAL, 33 _(u'Configure music'), 34 _(u'Configure music'), 35 None) 36 toolBar.AddSeparator() 37 toolBar.AddTool(ID_RENDER_FILMSTRIP, '', 38 wx.ArtProvider.GetBitmap('PFS_RENDER_24'), 39 wx.ArtProvider.GetBitmap('PFS_RENDER_D_24'), 40 wx.ITEM_NORMAL, 41 _(u'Render filmstrip'), 42 _(u'Render filmstrip'), 43 None) 44 45 def GetStatusText(self, index): 46 project = self.GetProject() 47 48 try: 49 imgCount, frameCount = self.__CalcDuration() 50 except ValueError as err: 51 if index == 0: 52 return str(err) 53 else: 54 return "" 55 56 totalTime = project.GetDuration(False) 57 if totalTime == -1: 58 # TODO: calc from audio files 59 totalTime = 0 60 elif totalTime is None: 61 pass # totalTime = project.GetDuration(True) 62 else: 63 assert True, "totalTime is invalid" 64 65 if index == 0: 66 return u"%s: %d" % (_(u"Images"), imgCount) 67 68 elif index == 1: 69 return u"%s: %d" % (_(u"Frames"), frameCount) 70 else: 71 return u"" 72 73 def __CalcDuration(self): 74 pics = self.GetProject().GetPictures() 75 idxPic = 0 76 imgCount = 0 77 frameCount = 0 78 while idxPic < len(pics) - 1: 79 pic = pics[idxPic] 80 picPattern = PicturePattern.Create(pic.GetFilename()) 81 assert picPattern.IsOk() 82 83 picNum = picPattern.num 84 85 # get number from next pic 86 nextPic = pics[idxPic + 1] 87 nextPicPattern = PicturePattern.Create(nextPic.GetFilename()) 88 assert nextPicPattern.IsOk() 89 90 picCount = nextPicPattern.num - picNum 91 if picCount < 0: 92 raise ValueError(_(u"The picture counter is not " 93 u"increasing: %s") % nextPic.GetFilename()) 94 95 picDur = int(pic.GetDuration()) 96 transDur = int(pic.GetTransitionDuration()) 97 98 imgCount += picCount 99 frameCount += (picCount * (picDur + transDur)) 100 101 idxPic += 1 102 103 return imgCount, frameCount 104 105 def _CheckImportedPic(self, path): 106 picPattern = PicturePattern.Create(path) 107 if not picPattern.IsOk(): 108 dlgErr = wx.MessageDialog( 109 self, 110 _(u"Filename '%s' does not match a number pattern " 111 u"which is necessary for a time lapse slide " 112 u"show!") % path, 113 _(u"Error"), 114 wx.OK | wx.ICON_ERROR) 115 dlgErr.ShowModal() 116 dlgErr.Destroy() 117 return False 118 else: 119 return True 120 121 def _InitImageProxy(self): 122 self.imgProxyLeft = ImageProxy() 123 self.imgProxyLeft.AddObserver(self.bitmapLeft) 124 self.imgProxyRight = ImageProxy() 125 self.imgProxyRight.AddObserver(self.bitmapRight) 126 127 self.bitmapLeft.SetImgProxy(self.imgProxyLeft) 128 self.bitmapRight.SetImgProxy(self.imgProxyRight) 129 130 def _OnPicsSelectionChanged(self, selItems, selPics): 131 if selItems: 132 selIdx = selItems[0] 133 selPic = self.lvPics.GetPicture(selIdx) 134 nextPic = self.lvPics.GetPicture(selIdx + 1) 135 self._CheckAndSetLock(selPic) 136 137 self.imgProxyLeft.SetPicture(selPic) 138 self.bitmapLeft.SetSection(wx.Rect(*selPic.GetStartRect())) 139 if nextPic: 140 self.imgProxyRight.SetPicture(nextPic) 141 self.bitmapRight.SetSection(wx.Rect(*nextPic.GetStartRect())) 142 self.bitmapRight.Enable(True) 143 else: 144 self.bitmapRight.Enable(False) 145