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