Beispiel #1
0
class DlgConfigureAudio(wx.Dialog):
    def _InitSizers(self):
        szMain = wx.BoxSizer(orient=wx.VERTICAL)

        szCtrls = wx.BoxSizer(orient=wx.HORIZONTAL)

        szAudioCmds = wx.BoxSizer(orient=wx.VERTICAL)

        szCmds = wx.BoxSizer(orient=wx.HORIZONTAL)

        szMain.Add(self.pnlHdr, 0, border=0, flag=wx.EXPAND)
        szMain.Add(self.szMsg, 0, border=8, flag=wx.ALL | wx.EXPAND)
        szMain.Add(szCtrls, 0, border=8, flag=wx.ALL | wx.EXPAND)
        szMain.Add(self.cbAudio, 0, border=8, flag=wx.ALL | wx.EXPAND)
        szMain.Add(szCmds, 0, border=8, flag=wx.ALL | wx.ALIGN_RIGHT)

        szCtrls.Add(self.lvAudio, 1, flag=wx.EXPAND | wx.RIGHT, border=4)
        szCtrls.Add(szAudioCmds)

        szAudioCmds.Add(self.cmdBrowseMusic, border=2, flag=wx.BOTTOM)
        szAudioCmds.Add(self.cmdBrowseAudio, border=2, flag=wx.BOTTOM)
        szAudioCmds.Add(self.cmdAudioPreview, border=2, flag=wx.BOTTOM)
        szAudioCmds.Add(self.cmdAudioMoveUp, border=2, flag=wx.BOTTOM)
        szAudioCmds.Add(self.cmdAudioMoveDown, border=2, flag=wx.BOTTOM)
        szAudioCmds.Add(self.cmdAudioDel, border=2, flag=wx.BOTTOM)

        szCmds.Add(self.cmdCancel, 0, border=0, flag=0)
        szCmds.AddSpacer(8)
        szCmds.Add(self.cmdOk, 0, border=0, flag=0)

        self.SetSizer(szMain)

    def _InitCtrls(self):
        self.pnlHdr = PnlDlgHeader(self)

        self.szMsg = self.CreateTextSizer(
            _("Configure your audio files that are used as a background music."
              ))

        self.lvAudio = wx.ListBox(self, style=wx.LB_SINGLE)
        self.lvAudio.Bind(wx.EVT_LISTBOX, self.OnControlStatusAudio)

        self.cmdBrowseMusic = wx.BitmapButton(
            self,
            bitmap=wx.ArtProvider.GetBitmap('PFS_MUSIC_16'),
            name=u'cmdBrowseMusic',
            style=wx.BU_AUTODRAW)
        self.cmdBrowseMusic.Bind(wx.EVT_BUTTON, self.OnCmdBrowseMusicButton)

        self.cmdBrowseAudio = wx.BitmapButton(
            self,
            bitmap=wx.ArtProvider.GetBitmap('PFS_FOLDER_OPEN_16'),
            name=u'cmdBrowseAudio',
            style=wx.BU_AUTODRAW)
        self.cmdBrowseAudio.Bind(wx.EVT_BUTTON, self.OnCmdBrowseAudioButton)

        self.cmdAudioPreview = wx.BitmapButton(
            self,
            bitmap=wx.ArtProvider.GetBitmap('PFS_PLAY_PAUSE_16'),
            name=u'cmdAudioPreview',
            style=wx.BU_AUTODRAW)
        self.cmdAudioPreview.SetBitmapDisabled(
            wx.ArtProvider.GetBitmap('PFS_PLAY_PAUSE_D_16'))
        self.cmdAudioPreview.Bind(wx.EVT_BUTTON, self.OnCmdAudioPreviewButton)

        self.cmdAudioMoveUp = wx.BitmapButton(
            self,
            bitmap=wx.ArtProvider.GetBitmap('PFS_ARROW_UP_16'),
            name=u'cmdAudioMoveUp',
            style=wx.BU_AUTODRAW)
        self.cmdAudioMoveUp.SetBitmapDisabled(
            wx.ArtProvider.GetBitmap('PFS_ARROW_UP_D_16'))
        self.cmdAudioMoveUp.Bind(wx.EVT_BUTTON, self.OnCmdAudioMove)

        self.cmdAudioMoveDown = wx.BitmapButton(
            self,
            bitmap=wx.ArtProvider.GetBitmap('PFS_ARROW_DOWN_16'),
            name=u'cmdAudioMoveDown',
            style=wx.BU_AUTODRAW)
        self.cmdAudioMoveDown.SetBitmapDisabled(
            wx.ArtProvider.GetBitmap('PFS_ARROW_DOWN_D_16'))
        self.cmdAudioMoveDown.Bind(wx.EVT_BUTTON, self.OnCmdAudioMove)

        self.cmdAudioDel = wx.BitmapButton(
            self,
            bitmap=wx.ArtProvider.GetBitmap('PFS_REMOVE_16'),
            name=u'cmdAudioDel',
            style=wx.BU_AUTODRAW)
        self.cmdAudioDel.SetBitmapDisabled(
            wx.ArtProvider.GetBitmap('PFS_REMOVE_D_16'))
        self.cmdAudioDel.Bind(wx.EVT_BUTTON, self.OnCmdAudioDel)

        self.cbAudio = wx.CheckBox(
            self,
            wx.ID_ANY,
            label=_(
                u'Set the duration of your slideshow to fit your audio files'))

        self.cmdCancel = wx.Button(self,
                                   id=wx.ID_CANCEL,
                                   label=_(u'&Cancel'),
                                   name=u'cmdCancel')
        self.cmdCancel.Bind(wx.EVT_BUTTON,
                            self.OnCmdCancelButton,
                            id=wx.ID_CANCEL)

        self.cmdOk = wx.Button(self,
                               id=wx.ID_OK,
                               label=_(u'&Ok'),
                               name=u'cmdOk')
        self.cmdOk.Bind(wx.EVT_BUTTON, self.OnCmdOkButton, id=wx.ID_OK)

    def __init__(self, parent, project):
        wx.Dialog.__init__(self,
                           parent,
                           name=u'DlgConfigureAudio',
                           style=wx.DEFAULT_DIALOG_STYLE,
                           title=_(u'Configure music'))
        self.Bind(wx.EVT_CLOSE, self.OnClose)

        self._InitCtrls()

        self.pnlHdr.SetTitle(_(u'Configure music'))
        self.pnlHdr.SetBitmap(wx.ArtProvider.GetBitmap('PFS_MUSIC_32'))

        self.lvAudio.SetMinSize(wx.Size(300, -1))

        self.__project = project
        self.__mediaCtrl = None
        self.__musicMap = {}

        self.cmdBrowseMusic.Show(self.__GetAudioDir() is not None)

        if project.GetTimelapse():
            self.cbAudio.SetValue(False)
            self.cbAudio.Show(False)
        else:
            duration = project.GetDuration(False)
            self.cbAudio.SetValue(duration == -1)

        for audioFile in project.GetAudioFiles():
            idx = self.lvAudio.Append(audioFile)
            self.lvAudio.Select(idx)

        self.__ControlStatusAudio()

        self._InitSizers()
        self.Fit()
        self.CenterOnParent()

    def OnControlStatusAudio(self, event):  # pylint: disable=unused-argument
        self.__ControlStatusAudio()

    def OnCmdBrowseMusicButton(self, event):  # pylint: disable=unused-argument
        menu = wx.Menu()

        audioDir = self.__GetAudioDir()
        for filename in os.listdir(audioDir):
            fname, fext = os.path.splitext(filename)
            if fext in FILE_EXTENSIONS_AUDIO:
                audioFile = os.path.join(audioDir, filename)

                ident = wx.NewId()
                CreateMenuItem(menu, ident, fname)

                self.__musicMap[ident] = audioFile

                self.Bind(wx.EVT_MENU, self.__AddMusic, id=ident)

        self.PopupMenu(menu,
                       pos=self.cmdBrowseMusic.GetPosition() +
                       (0, self.cmdBrowseMusic.GetSize()[1]))

    def OnCmdBrowseAudioButton(self, event):  # pylint: disable=unused-argument
        dlg = wx.FileDialog(self, _(u"Select music"),
                            Settings().GetAudioPath(), "",
                            _(u"Audio files") + " (*.*)|*.*",
                            wx.FD_OPEN | wx.FD_MULTIPLE)
        if dlg.ShowModal() == wx.ID_OK:
            path = dlg.GetPath()
            Settings().SetAudioPath(os.path.dirname(path))

            for path in dlg.GetPaths():
                self.lvAudio.Append(path)

        dlg.Destroy()

    def OnCmdAudioPreviewButton(self, event):  # pylint: disable=unused-argument
        selIdx = self.lvAudio.GetSelection()
        if selIdx == wx.NOT_FOUND:
            return

        filename = self.lvAudio.GetString(selIdx)
        if self.__mediaCtrl and self.__mediaCtrl.GetFilename() == filename:
            if self.__mediaCtrl.IsPlaying():
                self.__mediaCtrl.Stop()
            else:
                self.__mediaCtrl.Play()
        else:
            self.__LoadAudioFile(filename)

    def OnCmdAudioMove(self, event):
        selIdx = self.lvAudio.GetSelection()
        if selIdx == wx.NOT_FOUND:
            return

        selAudio = self.lvAudio.GetString(selIdx)

        evtObj = event.GetEventObject()
        if evtObj is self.cmdAudioMoveUp:
            if selIdx > 0:
                prevAudio = self.lvAudio.GetString(selIdx - 1)

                self.lvAudio.SetString(selIdx, prevAudio)
                self.lvAudio.SetString(selIdx - 1, selAudio)
                self.lvAudio.SetSelection(selIdx - 1)
        elif evtObj is self.cmdAudioMoveDown:
            if selIdx < self.lvAudio.GetCount() - 1:
                nextAudio = self.lvAudio.GetString(selIdx + 1)

                self.lvAudio.SetString(selIdx, nextAudio)
                self.lvAudio.SetString(selIdx + 1, selAudio)
                self.lvAudio.SetSelection(selIdx + 1)

        self.__ControlStatusAudio()

    def OnCmdAudioDel(self, event):  # pylint: disable=unused-argument
        selIdx = self.lvAudio.GetSelection()
        if selIdx != wx.NOT_FOUND:
            self.lvAudio.Delete(selIdx)
        self.lvAudio.Select(min(selIdx, self.lvAudio.GetCount() - 1))

        self.__ControlStatusAudio()

    def OnClose(self, event):
        self.__CloseMediaCtrl()
        event.Skip()

    def OnCmdCancelButton(self, event):
        self.__CloseMediaCtrl()
        event.Skip()

    def OnCmdOkButton(self, event):
        self.__CloseMediaCtrl()
        if self.__ValidateAudioFile():
            self.__project.SetAudioFiles(self.lvAudio.GetItems())
            if self.cbAudio.GetValue():
                self.__project.SetDuration(-1)
            elif self.__project.GetDuration(False) == -1:
                # was previously set, so reset the duration
                self.__project.SetDuration(None)

            event.Skip()

    def __ControlStatusAudio(self):
        selected = self.lvAudio.GetSelection()

        self.cmdAudioPreview.Enable(selected != wx.NOT_FOUND)
        self.cmdAudioDel.Enable(selected != wx.NOT_FOUND)
        self.cmdAudioMoveUp.Enable(selected > 0)
        self.cmdAudioMoveDown.Enable(selected < (self.lvAudio.GetCount() - 1))

    def __LoadAudioFile(self, path):
        self.__CloseMediaCtrl()

        if not os.path.exists(path):
            dlg = wx.MessageDialog(
                self,
                _(u"Audio file '%s' does not exist!") % path, _(u"Error"),
                wx.OK | wx.ICON_ERROR)
            dlg.ShowModal()
            dlg.Destroy()

        mediaCtrl = AudioPlayer(path)
        if mediaCtrl.IsOk():
            self.__mediaCtrl = mediaCtrl
            self.__mediaCtrl.Play()
        else:
            dlg = wx.MessageDialog(self, _(u"Audio file not supported!"),
                                   _(u"Error"), wx.OK | wx.ICON_ERROR)
            dlg.ShowModal()
            dlg.Destroy()

    def __ValidateAudioFile(self):
        for path in self.lvAudio.GetItems():
            if not os.path.exists(path):
                dlg = wx.MessageDialog(
                    self,
                    _(u"Audio file '%s' does not exist!") % path, _(u"Error"),
                    wx.OK | wx.ICON_ERROR)
                dlg.ShowModal()
                dlg.Destroy()
                return False
        return True

    def __CloseMediaCtrl(self):
        if self.__mediaCtrl is not None:
            try:
                self.__mediaCtrl.Close()
            except:
                pass
        self.__mediaCtrl = None

    def __GetAudioDir(self):
        return GetDataDir("audio")

    def __AddMusic(self, event):
        self.lvAudio.Append(self.__musicMap.get(event.GetId()))
Beispiel #2
0
class DlgPicDurationByAudio(wx.Dialog):
    def __init__(self, parent, audioFile, expectedSteps):
        '''
        :type parent: wx.Window
        :type audioFile: str
        :type expectedSteps: int
        '''
        wx.Dialog.__init__(self,
                           parent,
                           style=wx.DEFAULT_DIALOG_STYLE | wx.RESIZE_BORDER)
        self.SetTitle(_("Adjust picture durations"))

        self.pnlHdr = PnlDlgHeader(self)
        self.pnlHdr.SetTitle(_("Adjust picture durations to audio file"))
        self.pnlHdr.SetBitmap(
            wx.ArtProvider.GetBitmap('PFS_MUSIC_DURATION',
                                     size=wx.Size(32, 32)))

        szMsg = self.CreateTextSizer(
            _("Find your picture duration by playing the audio file of your project and\n"
              "pressing the hit button to apply the current playing time."))

        self.stAudio = wx.StaticText(self,
                                     wx.ID_ANY,
                                     style=wx.ST_NO_AUTORESIZE)
        font = self.stAudio.GetFont()
        font.SetPointSize(16)
        self.stAudio.SetFont(font)

        self.listbox = wx.ListBox(self, wx.ID_ANY)
        self.listbox.SetSizeHints(wx.Size(-1, 200))
        self.listbox.Bind(wx.EVT_KEY_DOWN, self.__OnStepListKeyDown)
        self.listbox.Bind(wx.EVT_LISTBOX_DCLICK, self.__OnStepListDClickDown)

        self.btnPlay = wx.Button(self, wx.ID_ANY, _("Play"))
        self.btnPlay.Bind(wx.EVT_BUTTON, self.__OnPlay)

        self.btnHit = wx.Button(self, wx.ID_ANY, _("Hit"))
        self.btnHit.Disable()
        self.btnHit.Bind(wx.EVT_BUTTON, self.__OnHit)

        self.btnCancel = wx.Button(self, wx.ID_CANCEL, _('&Cancel'))
        self.btnOk = wx.Button(self, wx.ID_OK, _('&Ok'))

        szButtons = wx.BoxSizer(wx.HORIZONTAL)
        szButtons.Add(self.btnPlay, flag=wx.RIGHT, border=8)
        szButtons.Add(self.btnHit, flag=wx.RIGHT, border=8)
        szButtons.AddStretchSpacer()
        szButtons.Add(self.btnCancel, flag=wx.RIGHT, border=8)
        szButtons.Add(self.btnOk)

        sz = wx.BoxSizer(wx.VERTICAL)
        sz.Add(self.pnlHdr, flag=wx.EXPAND)
        sz.Add(szMsg, flag=wx.EXPAND | wx.ALL, border=8)
        sz.Add(self.stAudio, flag=wx.EXPAND | wx.ALL, border=8)
        sz.Add(self.listbox, 1, wx.EXPAND | wx.ALL, border=8)
        sz.Add(szButtons, flag=wx.ALL | wx.ALIGN_RIGHT, border=8)

        self.SetSizerAndFit(sz)

        self.__audioFile = audioFile
        self.__player = None

        self.__timer = None
        self.__duration = None
        self.__expectedSteps = expectedSteps
        self.__stepIdx = 0
        self.__lastTime = None

        self.__InitStepList()
        self.stAudio.SetLabel(self.__CreateAudioInfoText(None))

        self.SetEscapeId(wx.ID_CANCEL)

        self.Bind(wx.EVT_TIMER, self.__OnTimer)
        self.Bind(wx.EVT_CLOSE, self.__OnClose)
        self.Bind(wx.EVT_BUTTON, self.__OnClose, id=wx.ID_OK)
        self.Bind(wx.EVT_BUTTON, self.__OnClose, id=wx.ID_CANCEL)

    def __OnTimer(self, event):  # pylint: disable=unused-argument
        if self.__player:
            if self.__player.IsPlaying():
                posMiliSecs = self.__player.GetPosition()
                if posMiliSecs:
                    self.stAudio.SetLabel(
                        self.__CreateAudioInfoText(posMiliSecs))
            else:
                self.__ProcessStop()

    def __OnPlay(self, event):  # pylint: disable=unused-argument
        if self.__player is None or not self.__player.IsPlaying():
            self.btnPlay.SetLabel(_("Stop"))
            self.btnHit.Enable()
            self.__InitStepList()

            self.__timer = wx.Timer(self)
            self.__timer.Start(50)

            self.__player = GPlayer(self.__audioFile)
            self.__lastTime = 0
            self.__duration = self.__player.GetLength()
            self.__player.Play()
            #             self.__player.SetPosition(5000)

            self.btnHit.SetFocus()
        else:
            self.__ProcessStop()

    def __OnHit(self, event):  # pylint: disable=unused-argument
        milliSecs = self.__player.GetPosition()
        if self.__stepIdx < self.__expectedSteps - 1:
            milliSecs -= 50  # time to react
            self.__NextStepDuration(milliSecs - self.__lastTime)
            self.__lastTime = milliSecs

        if self.__stepIdx >= self.__expectedSteps - 1:
            self.__NextStepDuration(self.__duration - self.__lastTime)
            self.__ProcessStop()

    def __OnClose(self, event):
        if self.__timer:
            self.__timer.Stop()
        if self.__player and self.__player.IsPlaying():
            self.__player.Stop()
        event.Skip()

    def __OnStepListKeyDown(self, event):
        if event.GetKeyCode() == wx.WXK_DELETE:
            sel = self.listbox.GetSelection()
            if sel != wx.NOT_FOUND:
                self.listbox.SetString(self.__CreateDurationText(sel, None))
                self.listbox.Delete(sel)

    def __OnStepListDClickDown(self, event):
        event.Skip()

    def __InitStepList(self):
        self.__stepIdx = 0
        self.listbox.Clear()
        for ctr in range(self.__expectedSteps):
            self.listbox.Append(self.__CreateDurationText(ctr, None))
        self.listbox.Select(0)

    def __ProcessStop(self):
        self.btnPlay.SetLabel(_("Play"))
        self.btnHit.Disable()
        self.__timer.Stop()
        self.__player.Stop()
        self.__player = None

    def __NextStepDuration(self, duration):
        value = self.__CreateDurationText(self.__stepIdx, duration)
        self.listbox.SetString(self.__stepIdx, value)
        self.listbox.SetClientData(self.__stepIdx, duration)
        self.__stepIdx += 1
        if self.__stepIdx < self.listbox.GetCount():
            self.listbox.Select(self.__stepIdx)

    def __TimeToStr(self, milliSecs):
        if milliSecs is None:
            return "--:--:--,--"
        else:
            secs = milliSecs // 1000.0
            hours = int(secs / 3600.0)
            minutes = int(secs / 60.0) % 60
            seconds = int(secs) % 60
            frac = ((milliSecs / 1000.0) % 1) * 1000
            return "%02d:%02d:%02d,%03d" % (hours, minutes, seconds, frac)

    def __CreateAudioInfoText(self, posMiliSecs):
        return "{}: {}".format(_("Playing time"),
                               self.__TimeToStr(posMiliSecs))

    def __CreateDurationText(self, idx, value):
        return "{}: {}".format(idx + 1, self.__TimeToStr(value))

    def GetDurations(self):
        result = []
        if self.listbox.HasClientData():
            for idx in range(self.__expectedSteps):
                duration = self.listbox.GetClientData(idx)
                if duration is not None:
                    result.append(duration)
                else:
                    break

        return result

    @staticmethod
    def Interact(parent, project):
        '''
        :type parent: wx.Window
        :type project: photofilmstrip.core.Project.Project
        '''
        pics = project.GetPictures()
        if len(pics) == 0:
            return
        if len(project.GetAudioFiles()) == 0:
            dlg = wx.MessageDialog(
                parent,
                _("Your project does not have an audio file configured."),
                _("Error"), wx.OK | wx.ICON_ERROR)
            dlg.ShowModal()
            dlg.Destroy()
            return
        if len(project.GetAudioFiles()) > 1:
            dlg = wx.MessageDialog(
                parent,
                _("Your project uses more than one audio file. Currently the durations can be adjusted only for one audio file."
                  ), _("Error"), wx.OK | wx.ICON_ERROR)
            dlg.ShowModal()
            dlg.Destroy()
            return

        dlg = DlgPicDurationByAudio(parent, project.GetAudioFile(), len(pics))
        if dlg.ShowModal() == wx.ID_OK:
            for idx, duration in enumerate(dlg.GetDurations()):
                try:
                    pics[idx].SetDuration(duration / 1000.0)
                except IndexError:
                    break
        dlg.Destroy()
Beispiel #3
0
class DlgRendererProps(wx.Dialog):

    _custom_classes = {
        "wx.Choice": ["FormatComboBox"],
        "wx.Panel": ["PnlDlgHeader"]
    }

    def _init_coll_sizerCmd_Items(self, parent):
        # generated method, don't edit

        parent.Add(self.cmdHelp, 0, border=0, flag=0)
        parent.AddStretchSpacer(1)
        parent.Add(self.cmdCancel, 0, border=0, flag=0)
        parent.AddSpacer(8)
        parent.Add(self.cmdOk, 0, border=0, flag=0)

    def _init_coll_sizerMain_Items(self, parent):
        # generated method, don't edit

        parent.Add(self.pnlHdr, 0, border=0, flag=wx.EXPAND)
        parent.Add(self.lcProps, 1, border=0, flag=wx.EXPAND)
        parent.Add(self.staticLine,
                   0,
                   border=8,
                   flag=wx.TOP | wx.BOTTOM | wx.EXPAND)
        parent.Add(self.sizerCmd, 0, border=4, flag=wx.EXPAND | wx.ALL)

    def _init_coll_lcProps_Columns(self, parent):
        # generated method, don't edit

        parent.InsertColumn(col=0,
                            format=wx.LIST_FORMAT_LEFT,
                            heading=_("Property"),
                            width=200)
        parent.InsertColumn(col=1,
                            format=wx.LIST_FORMAT_LEFT,
                            heading=_("Value"),
                            width=200)

    def _init_sizers(self):
        # generated method, don't edit
        self.sizerMain = wx.BoxSizer(orient=wx.VERTICAL)

        self.sizerCmd = wx.BoxSizer(orient=wx.HORIZONTAL)

        self._init_coll_sizerMain_Items(self.sizerMain)
        self._init_coll_sizerCmd_Items(self.sizerCmd)

        self.SetSizer(self.sizerMain)

    def _init_ctrls(self, prnt):
        # generated method, don't edit
        wx.Dialog.__init__(self,
                           id=wxID_DLGRENDERERPROPS,
                           name="DlgRendererProps",
                           parent=prnt,
                           pos=wx.Point(-1, -1),
                           size=wx.Size(-1, -1),
                           style=wx.DEFAULT_DIALOG_STYLE | wx.RESIZE_BORDER,
                           title=_("Output properties"))
        self.SetClientSize(wx.Size(400, 250))

        self.pnlHdr = PnlDlgHeader(id=wxID_DLGRENDERERPROPSPNLHDR,
                                   name="pnlHdr",
                                   parent=self,
                                   pos=wx.Point(-1, -1),
                                   size=wx.Size(-1, -1),
                                   style=wx.TAB_TRAVERSAL)

        self.lcProps = wx.ListCtrl(id=wxID_DLGRENDERERPROPSLCPROPS,
                                   name="lcProps",
                                   parent=self,
                                   pos=wx.Point(-1, -1),
                                   size=wx.Size(-1, -1),
                                   style=wx.LC_REPORT | wx.SUNKEN_BORDER)
        self.lcProps.SetMinSize(wx.Size(500, 120))
        self._init_coll_lcProps_Columns(self.lcProps)
        self.lcProps.Bind(wx.EVT_LIST_ITEM_ACTIVATED,
                          self.OnActivateProperty,
                          id=wxID_DLGRENDERERPROPSLCPROPS)

        self.cmdHelp = wx.Button(id=wx.ID_HELP,
                                 label=_("&Help"),
                                 name="cmdHelp",
                                 parent=self,
                                 pos=wx.Point(-1, -1),
                                 size=wx.Size(-1, -1),
                                 style=0)
        self.cmdHelp.Bind(wx.EVT_BUTTON, self.OnCmdHelpButton, id=wx.ID_HELP)

        self.cmdCancel = wx.Button(id=wxID_DLGRENDERERPROPSCMDCANCEL,
                                   label=_("&Cancel"),
                                   name="cmdCancel",
                                   parent=self,
                                   pos=wx.Point(-1, -1),
                                   size=wx.Size(-1, -1),
                                   style=0)
        self.cmdCancel.Bind(wx.EVT_BUTTON,
                            self.OnCmdCancelButton,
                            id=wxID_DLGRENDERERPROPSCMDCANCEL)

        self.cmdOk = wx.Button(id=wxID_DLGRENDERERPROPSCMDOK,
                               label=_("&Ok"),
                               name="cmdOk",
                               parent=self,
                               pos=wx.Point(-1, -1),
                               size=wx.Size(-1, -1),
                               style=0)
        self.cmdOk.Bind(wx.EVT_BUTTON,
                        self.OnCmdOkButton,
                        id=wxID_DLGRENDERERPROPSCMDOK)

        self.staticLine = wx.StaticLine(id=wxID_DLGRENDERERPROPSSTATICLINE,
                                        name="staticLine",
                                        parent=self,
                                        pos=wx.Point(-1, -1),
                                        size=wx.Size(-1, -1),
                                        style=0)

        self._init_sizers()

    def __init__(self, parent, rendererClass):
        self._init_ctrls(parent)
        self.Bind(wx.EVT_CLOSE, self.OnCmdCancelButton)

        self.pnlHdr.SetTitle(_("Edit extended output properties"))
        self.pnlHdr.SetBitmap(
            wx.ArtProvider.GetBitmap('PFS_VIDEO_FORMAT', size=wx.Size(32, 32)))
        self.rendererClass = rendererClass

        self.lcProps.DeleteAllItems()
        savedProps = Settings().GetRenderProperties(rendererClass.__name__)
        for prop in rendererClass.GetProperties():
            value = savedProps.get(prop.lower(),
                                   rendererClass.GetProperty(prop))
            self.lcProps.Append([prop, value])

            rendererClass.SetProperty(prop, value)

        self.SetAffirmativeId(wxID_DLGRENDERERPROPSCMDOK)
        self.SetEscapeId(wxID_DLGRENDERERPROPSCMDCANCEL)
        self.SetInitialSize(self.GetEffectiveMinSize())
        self.CentreOnParent()
        self.SetFocus()

    def OnCmdCancelButton(self, event):
        self.EndModal(wx.ID_CANCEL)

    def OnCmdOkButton(self, event):
        propDict = {}
        for prop in self.rendererClass.GetProperties():
            if self.rendererClass.GetProperty(
                    prop) != self.rendererClass.GetDefaultProperty(prop):
                propDict[prop] = self.rendererClass.GetProperty(prop)

        Settings().SetRenderProperties(self.rendererClass.__name__, propDict)
        self.EndModal(wx.ID_OK)

    def OnActivateProperty(self, event):
        idx = event.GetIndex()
        prop = self.lcProps.GetItemText(idx)
        dlg = wx.TextEntryDialog(self, _("Edit property"), prop,
                                 str(self.rendererClass.GetProperty(prop)))
        if dlg.ShowModal() == wx.ID_OK:
            value = dlg.GetValue()
            if len(value) == 0:
                value = self.rendererClass.GetDefaultProperty(prop)
            self.rendererClass.SetProperty(prop, value)
            self.lcProps.SetItem(idx, 1, str(value))
        dlg.Destroy()

    def OnCmdHelpButton(self, event):
        HelpViewer().DisplayID(HelpViewer.ID_RENDER)
        event.Skip()
Beispiel #4
0
class DlgNewProject(wx.Dialog):
    def _InitSizers(self):
        szMain = wx.BoxSizer(orient=wx.VERTICAL)

        szCtrls = wx.GridBagSizer(hgap=8, vgap=8)

        szCmds = wx.BoxSizer(orient=wx.HORIZONTAL)

        szMain.Add(self.pnlHdr, 0, border=0, flag=wx.EXPAND)
        szMain.Add(szCtrls, 0, border=8, flag=wx.ALL | wx.EXPAND)
        szMain.Add(self.staticLine, 0, border=0, flag=wx.EXPAND)
        szMain.Add(szCmds, 0, border=8, flag=wx.ALL | wx.ALIGN_RIGHT)

        szCtrls.Add(self.stProject, (0, 0),
                    border=0,
                    flag=wx.ALIGN_CENTER_VERTICAL,
                    span=(1, 1))
        szCtrls.Add(self.tcProject, (0, 1),
                    border=0,
                    flag=wx.EXPAND,
                    span=(1, 1))
        szCtrls.Add(self.stFolder, (1, 0),
                    border=0,
                    flag=wx.ALIGN_CENTER_VERTICAL,
                    span=(1, 1))
        szCtrls.Add(self.tcFolder, (1, 1),
                    border=0,
                    flag=wx.ALIGN_CENTER_VERTICAL | wx.EXPAND,
                    span=(1, 1))
        szCtrls.Add(self.cmdBrowseFolder, (1, 2),
                    border=0,
                    flag=0,
                    span=(1, 1))
        szCtrls.Add(self.stAspect, (2, 0),
                    border=0,
                    flag=wx.ALIGN_CENTER_VERTICAL,
                    span=(1, 1))
        szCtrls.Add(self.choiceAspect, (2, 1),
                    border=0,
                    flag=wx.EXPAND,
                    span=(1, 1))
        szCtrls.AddGrowableCol(1)

        szCmds.Add(self.cmdCancel, 0, border=0, flag=0)
        szCmds.AddSpacer(8)
        szCmds.Add(self.cmdOk, 0, border=0, flag=0)

        self.SetSizer(szMain)

    def _InitCtrls(self):
        self.pnlHdr = PnlDlgHeader(self)

        self.stProject = wx.StaticText(self,
                                       label=_("Project name:"),
                                       name="stProject")

        self.tcProject = wx.TextCtrl(self, name="tcProject", value="")

        self.stFolder = wx.StaticText(self,
                                      label=_("Folder:"),
                                      name="stFolder")

        self.tcFolder = wx.TextCtrl(self,
                                    name="tcFolder",
                                    style=wx.TE_READONLY,
                                    value="")

        self.cmdBrowseFolder = wx.BitmapButton(self,
                                               bitmap=wx.ArtProvider.GetBitmap(
                                                   'PFS_FOLDER_OPEN',
                                                   wx.ART_TOOLBAR),
                                               name="cmdBrowseFolder",
                                               style=wx.BU_AUTODRAW)
        self.cmdBrowseFolder.Bind(wx.EVT_BUTTON, self.OnCmdBrowseFolderButton)

        self.stAspect = wx.StaticText(self,
                                      label=_("Aspect ratio:"),
                                      name="stAspect")

        self.choiceAspect = wx.Choice(self, choices=[], name="choiceAspect")

        self.staticLine = wx.StaticLine(self)

        self.cmdCancel = wx.Button(self,
                                   id=wx.ID_CANCEL,
                                   label=_("&Cancel"),
                                   name="cmdCancel")
        self.cmdOk = wx.Button(self, id=wx.ID_OK, label=_("&Ok"), name="cmdOk")
        self.cmdOk.Bind(wx.EVT_BUTTON, self.OnCmdOkButton, id=wx.ID_OK)

    def __init__(self, parent, title):
        wx.Dialog.__init__(self,
                           parent,
                           name="DlgNewProject",
                           style=wx.DEFAULT_DIALOG_STYLE | wx.RESIZE_BORDER,
                           title=title)

        self._InitCtrls()
        self._InitSizers()

        self.pnlHdr.SetTitle(title)
        self.pnlHdr.SetBitmap(
            wx.ArtProvider.GetBitmap('PFS_ICON', size=(32, 32)))

        self.choiceAspect.Append(Aspect.ASPECT_16_9)
        self.choiceAspect.Append(Aspect.ASPECT_16_10)
        self.choiceAspect.Append(Aspect.ASPECT_4_3)
        self.choiceAspect.Append(Aspect.ASPECT_3_2)
        self.choiceAspect.Select(0)

        self.tcProject.SetMinSize(wx.Size(300, -1))
        self.tcFolder.SetMinSize(wx.Size(300, -1))
        self.choiceAspect.SetMinSize(wx.Size(300, -1))

        self.tcProject.SetValue(_("Unnamed project"))
        self.tcProject.SelectAll()
        self.tcProject.SetFocus()

        projPath = Settings().GetProjectPath()
        if not projPath:
            projPath = os.path.join(wx.GetHomeDir(), _("My PhotoFilmStrips"))
            Settings().SetProjectPath(projPath)
        self.tcFolder.SetValue(projPath)

        self.SetInitialSize(self.GetEffectiveMinSize())
        self.Fit()
        self.CenterOnParent()
        self.SetFocus()

    def OnCmdBrowseFolderButton(self, event):
        dlg = wx.DirDialog(self,
                           _("Browse for folder"),
                           defaultPath=self.tcFolder.GetValue())
        if dlg.ShowModal() == wx.ID_OK:
            path = dlg.GetPath()
            if self.__ValidateOutDir(path):
                self.tcFolder.SetValue(path)
                Settings().SetProjectPath(path)
        dlg.Destroy()

    def OnCmdOkButton(self, event):
        if self.__ValidateOutDir() and self.__ValidateProjName():
            event.Skip()

    def __ValidateOutDir(self, path=None):
        if path is None:
            path = self.tcFolder.GetValue().strip()

        if not os.path.isdir(path):
            dlg = wx.MessageDialog(
                self,
                _("Folder does not exists! Do you want %s to create it?") %
                Constants.APP_NAME, _("Question"),
                wx.YES_NO | wx.ICON_QUESTION)
            resp = dlg.ShowModal()
            dlg.Destroy()
            if resp == wx.ID_YES:
                try:
                    os.makedirs(path)
                except Exception as err:
                    dlg = wx.MessageDialog(
                        self,
                        _("Cannot create folder: %s") % str(err), _("Error"),
                        wx.OK | wx.ICON_ERROR)
                    dlg.ShowModal()
                    dlg.Destroy()
                    return False
            else:
                return False
        else:
            if not IsPathWritable(path):
                dlg = wx.MessageDialog(self, _("Cannot write into folder!"),
                                       _("Error"), wx.OK | wx.ICON_ERROR)
                dlg.ShowModal()
                dlg.Destroy()
                return False

        return True

    def __ValidateProjName(self):
        projName = self.tcProject.GetValue().strip()
        projName = projName.strip(".")
        projPath = os.path.join(self.tcFolder.GetValue().strip(), projName)
        if not projName:
            self.pnlHdr.SetErrorMessage(_("The project name must be filled."))
            return False
        elif not os.path.exists(projPath):
            try:
                os.makedirs(projPath)
            except Exception:
                self.pnlHdr.SetErrorMessage(
                    _("The project name contains invalid characters."))
                return False
            os.removedirs(projPath)
            return True
        else:
            self.pnlHdr.SetErrorMessage("")
            return True

    def __GetProjectPath(self):
        projName = self.tcProject.GetValue().strip()
        projName = projName.strip(".")
        filepath = os.path.join(self.tcFolder.GetValue().strip(), projName,
                                "%s.pfs" % projName)
        return filepath

    def GetProject(self):
        project = Project(self.__GetProjectPath())
        project.SetTimelapse(False)
        project.SetAspect(self.choiceAspect.GetStringSelection())
        return project
Beispiel #5
0
class DlgRender(wx.Dialog):

    _custom_classes = {
        "wx.Choice": ["FormatComboBox"],
        "wx.Panel": ["PnlDlgHeader"]
    }

    DEFAULT_PROFILE = u"HD [email protected] fps"

    def _init_coll_sizerMain_Items(self, parent):
        # generated method, don't edit

        parent.Add(self.pnlHdr, 0, border=0, flag=wx.EXPAND)
        parent.Add(self.pnlSettings, 0, border=4, flag=wx.ALL)
        parent.AddSpacer(8)
        parent.Add(self.sizerCmd, 0, border=4, flag=wx.EXPAND | wx.ALL)

    def _init_coll_sizerCmd_Items(self, parent):
        # generated method, don't edit

        parent.Add(self.cmdHelp, 0, border=0, flag=0)
        parent.AddStretchSpacer(1)
        parent.Add(self.cmdCancel, 0, border=0, flag=0)
        parent.AddSpacer(8)
        parent.Add(self.cmdStart, 0, border=0, flag=0)

    def _init_coll_sizerSettings_Items(self, parent):
        # generated method, don't edit

        parent.Add(self.stFormat, 0, border=0, flag=wx.ALIGN_CENTER_VERTICAL)
        parent.Add(self.choiceFormat,
                   0,
                   border=0,
                   flag=wx.ALIGN_CENTER_VERTICAL)
        parent.Add(self.cmdRendererProps, 0, border=0, flag=0)
        parent.Add(self.stProfile, 0, border=0, flag=wx.ALIGN_CENTER_VERTICAL)
        parent.Add(self.choiceProfile, 0, border=0, flag=wx.EXPAND)
        parent.AddSpacer(8)
        parent.AddSpacer(8)
        parent.Add(self.cbDraft, 0, border=0, flag=0)

    def _init_coll_sizerSettings_Growables(self, parent):
        # generated method, don't edit

        parent.AddGrowableCol(2)

    def _init_sizers(self):
        # generated method, don't edit
        self.sizerMain = wx.BoxSizer(orient=wx.VERTICAL)

        self.sizerCmd = wx.BoxSizer(orient=wx.HORIZONTAL)

        self.sizerSettings = wx.FlexGridSizer(cols=3, hgap=8, rows=5, vgap=8)
        self.sizerSettings.SetFlexibleDirection(wx.BOTH)

        self._init_coll_sizerMain_Items(self.sizerMain)
        self._init_coll_sizerCmd_Items(self.sizerCmd)
        self._init_coll_sizerSettings_Items(self.sizerSettings)
        self._init_coll_sizerSettings_Growables(self.sizerSettings)

        self.SetSizer(self.sizerMain)
        self.pnlSettings.SetSizer(self.sizerSettings)

    def _init_ctrls(self, prnt):
        # generated method, don't edit
        wx.Dialog.__init__(self,
                           id=wxID_DLGRENDER,
                           name=u'DlgRender',
                           parent=prnt,
                           pos=wx.Point(-1, -1),
                           size=wx.Size(-1, -1),
                           style=wx.DEFAULT_DIALOG_STYLE | wx.RESIZE_BORDER,
                           title=_(u'Render project'))

        self.pnlHdr = PnlDlgHeader(id=wxID_DLGRENDERPNLHDR,
                                   name=u'pnlHdr',
                                   parent=self,
                                   pos=wx.Point(-1, -1),
                                   size=wx.Size(-1, -1),
                                   style=wx.TAB_TRAVERSAL)

        self.pnlSettings = wx.Panel(id=wxID_DLGRENDERPNLSETTINGS,
                                    name=u'pnlSettings',
                                    parent=self,
                                    pos=wx.Point(-1, -1),
                                    size=wx.Size(-1, -1),
                                    style=wx.TAB_TRAVERSAL)

        self.stFormat = wx.StaticText(id=wxID_DLGRENDERSTFORMAT,
                                      label=_(u'Format:'),
                                      name=u'stFormat',
                                      parent=self.pnlSettings,
                                      pos=wx.Point(-1, -1),
                                      size=wx.Size(-1, -1),
                                      style=0)

        self.choiceFormat = FormatComboBox(choices=[],
                                           id=wxID_DLGRENDERCHOICEFORMAT,
                                           name=u'choiceFormat',
                                           parent=self.pnlSettings,
                                           pos=wx.Point(-1, -1),
                                           size=wx.Size(-1, -1),
                                           style=wx.CB_READONLY)
        self.choiceFormat.SetSizeHints(400, -1)
        self.choiceFormat.Bind(wx.EVT_COMBOBOX,
                               self.OnChoiceFormat,
                               id=wxID_DLGRENDERCHOICEFORMAT)

        self.cmdRendererProps = wx.BitmapButton(
            bitmap=wx.ArtProvider.GetBitmap('PFS_VIDEO_FORMAT_16'),
            id=wxID_DLGRENDERCMDRENDERERPROPS,
            name=u'cmdRendererProps',
            parent=self.pnlSettings,
            pos=wx.Point(-1, -1),
            size=wx.Size(-1, -1),
            style=wx.BU_AUTODRAW)
        self.cmdRendererProps.SetToolTip(_(u"Properties"))
        self.cmdRendererProps.Bind(wx.EVT_BUTTON,
                                   self.OnCmdRendererPropsButton,
                                   id=wxID_DLGRENDERCMDRENDERERPROPS)

        self.stProfile = wx.StaticText(id=wxID_DLGRENDERSTPROFILE,
                                       label=_(u'Profile:'),
                                       name=u'stProfile',
                                       parent=self.pnlSettings,
                                       pos=wx.Point(-1, -1),
                                       size=wx.Size(-1, -1),
                                       style=0)

        self.choiceProfile = wx.Choice(choices=[],
                                       id=wxID_DLGRENDERCHOICEPROFILE,
                                       name=u'choiceProfile',
                                       parent=self.pnlSettings,
                                       pos=wx.Point(-1, -1),
                                       size=wx.Size(-1, -1),
                                       style=0)
        self.choiceProfile.SetSizeHints(400, -1)

        self.cbDraft = wx.CheckBox(id=wxID_DLGRENDERCBDRAFT,
                                   label=_(u'Draft'),
                                   name=u'cbDraft',
                                   parent=self.pnlSettings,
                                   pos=wx.Point(-1, -1),
                                   size=wx.Size(-1, -1),
                                   style=0)
        self.cbDraft.SetValue(False)

        self.cmdHelp = wx.Button(id=wx.ID_HELP,
                                 label=_(u'&Help'),
                                 name=u'cmdHelp',
                                 parent=self,
                                 pos=wx.Point(-1, -1),
                                 size=wx.Size(-1, -1),
                                 style=0)
        self.cmdHelp.Bind(wx.EVT_BUTTON, self.OnCmdHelpButton, id=wx.ID_HELP)

        self.cmdCancel = wx.Button(id=wxID_DLGRENDERCMDCANCEL,
                                   label=_(u'&Cancel'),
                                   name=u'cmdCancel',
                                   parent=self,
                                   pos=wx.Point(-1, -1),
                                   size=wx.Size(-1, -1),
                                   style=0)
        self.cmdCancel.Bind(wx.EVT_BUTTON,
                            self.OnCmdCancelButton,
                            id=wxID_DLGRENDERCMDCANCEL)

        self.cmdStart = wx.Button(id=wxID_DLGRENDERCMDSTART,
                                  label=_(u'&Start'),
                                  name=u'cmdStart',
                                  parent=self,
                                  pos=wx.Point(-1, -1),
                                  size=wx.Size(-1, -1),
                                  style=0)
        self.cmdStart.Bind(wx.EVT_BUTTON,
                           self.OnCmdStartButton,
                           id=wxID_DLGRENDERCMDSTART)

        self._init_sizers()

    def __init__(self, parent, rendererProvider, aspectRatio):
        self._init_ctrls(parent)
        self.Bind(wx.EVT_CLOSE, self.OnCmdCancelButton)

        self.pnlHdr.SetTitle(_('Configure output and start render process'))
        self.pnlHdr.SetBitmap(wx.ArtProvider.GetBitmap('PFS_RENDER_32'))

        self.cbDraft.SetToolTip(
            _(u"Activate this option to generate a preview of your PhotoFilmStrip. The rendering process will speed up dramatically, but results in lower quality."
              ))

        self.aspectRatio = aspectRatio
        self.__InitProfiles()
        self.choiceFormat.SetRendererProvider(rendererProvider)

        defaultFormat = rendererProvider.GetDefault()
        if isinstance(defaultFormat, str):
            self.choiceFormat.SetStringSelection(defaultFormat)
        elif isinstance(defaultFormat, int):
            self.choiceFormat.SetSelection(defaultFormat)
        self.OnChoiceFormat(None)

        settings = Settings()
        self.__SelectProfileByName(settings.GetLastProfile())

        self.SetEscapeId(wxID_DLGRENDERCMDCANCEL)
        self.SetInitialSize(self.GetEffectiveMinSize())
        self.Fit()
        self.CentreOnParent()
        self.SetFocus()

        self.profile = None
        self.draftMode = False
        self.formatData = None

    def __GetChoiceDataSelected(self, choice):
        return choice.GetClientData(choice.GetSelection())

    def __SelectProfileByName(self, profName):
        if profName is None:
            profName = self.DEFAULT_PROFILE
        choice = self.choiceProfile
        for idx in range(choice.GetCount()):
            prof = choice.GetClientData(idx)
            if prof and prof.GetName() == profName:
                choice.Select(idx)
                return

        choice.Select(0)

    def __InitProfiles(self, filtr=None, profiles=None):
        if profiles is None:
            profiles = []
            profs = GetOutputProfiles(self.aspectRatio)
            for prof in profs:
                if prof.GetFriendlyName():
                    profiles.append(prof)
            profiles.append("-")
            profiles.extend(profs)

        selection = self.choiceFormat.GetStringSelection()
        self.choiceProfile.Clear()

        useFriendlyName = True
        for profile in profiles:
            if profile == "-":
                self.choiceProfile.Append(u"----------")
                useFriendlyName = False
                continue

            if filtr and not profile.GetName().startswith(filtr):
                continue

            if useFriendlyName:
                profName = profile.GetFriendlyName()
            else:
                profName = profile.GetName()

            self.choiceProfile.Append(
                u"%s (%sx%s)" % (profName, profile.GetResolution()[0],
                                 profile.GetResolution()[1]), profile)

        self.choiceProfile.SetStringSelection(selection)

    def OnChoiceFormat(self, event):
        if event is None:
            formatData = self.__GetChoiceDataSelected(self.choiceFormat)
        else:
            formatData = event.GetClientData()

        if isinstance(formatData, FormatData):
            self.cmdStart.Enable(formatData.IsOk())
            if formatData.IsMPEG():
                self.__InitProfiles(formatData.GetName().split(" ")[0],
                                    GetMPEGProfiles())
            else:
                self.__InitProfiles()

            if isinstance(formatData.GetData(), MetaBaseRenderer):
                self.cmdRendererProps.Enable(True)
            else:
                self.cmdRendererProps.Enable(False)

        self.__SelectProfileByName(Settings().GetLastProfile())

    def OnCmdStartButton(self, event):
        self.formatData = self.__GetChoiceDataSelected(self.choiceFormat)

        profile = self.__GetChoiceDataSelected(self.choiceProfile)
        if profile is None:
            return

        self.profile = profile
        self.draftMode = self.cbDraft.GetValue()

        self.EndModal(wx.ID_OK)

    def OnCmdCancelButton(self, event):
        self.EndModal(wx.ID_CANCEL)

    def OnCmdRendererPropsButton(self, event):
        data = self.__GetChoiceDataSelected(self.choiceFormat)
        if data is None:
            return
        rendererClass = data.GetData()

        dlg = DlgRendererProps(self, rendererClass)
        dlg.ShowModal()
        dlg.Destroy()

    def OnCmdHelpButton(self, event):
        HelpViewer().DisplayID(HelpViewer.ID_RENDER)
        event.Skip()

    def GetProfile(self):
        return self.profile

    def GetDraftMode(self):
        return self.draftMode

    def GetFormatData(self):
        return self.formatData
Beispiel #6
0
class DlgDuration(wx.Dialog):
    def _InitSizers(self):

        szManual = wx.BoxSizer(wx.HORIZONTAL)
        szManual.Add(self.rbManual, flag=wx.ALIGN_CENTER_VERTICAL)
        szManual.AddSpacer(8)
        szManual.Add(self.timeCtrlTotalLength, 1)

        szCtrls = wx.BoxSizer(orient=wx.VERTICAL)
        szCtrls.AddSpacer(8)
        szCtrls.Add(self.cbTotalLength, border=8, flag=wx.LEFT)
        szCtrls.AddSpacer(8)
        szCtrls.Add(self.rbAudio, border=32, flag=wx.LEFT | wx.EXPAND)
        szCtrls.AddSpacer(8)
        szCtrls.Add(szManual, border=32, flag=wx.LEFT | wx.EXPAND)

        szCmds = wx.BoxSizer(orient=wx.HORIZONTAL)
        szCmds.Add(self.cmdCancel, 0, border=0, flag=0)
        szCmds.AddSpacer(8)
        szCmds.Add(self.cmdOk, 0, border=0, flag=0)

        szMain = wx.BoxSizer(orient=wx.VERTICAL)
        szMain.Add(self.pnlHdr, 0, border=0, flag=wx.EXPAND)
        szMain.Add(szCtrls, 0, border=8, flag=wx.ALL | wx.EXPAND)
        szMain.Add(self.staticLine, 0, border=0, flag=wx.EXPAND)
        szMain.Add(szCmds, 0, border=8, flag=wx.ALL | wx.ALIGN_RIGHT)

        self.SetSizer(szMain)

    def _InitCtrls(self):
        self.pnlHdr = PnlDlgHeader(self)

        self.cbTotalLength = wx.CheckBox(self,
                                         label=_(u'Total length:'),
                                         name=u'cbTotalLength')
        self.cbTotalLength.SetValue(False)
        self.cbTotalLength.SetToolTip(
            _(u'Overrides the duration of single pictures and gives the project this total length.'
              ))
        self.cbTotalLength.Bind(wx.EVT_CHECKBOX,
                                self.OnControlStatusTotalLength)

        self.rbManual = wx.RadioButton(self,
                                       label=_(u'User defined:'),
                                       name=u'rbManual')
        self.rbManual.Bind(wx.EVT_RADIOBUTTON, self.OnControlStatusTotalLength)

        self.timeCtrlTotalLength = wx.lib.masked.timectrl.TimeCtrl(
            self,
            display_seconds=True,
            fmt24hr=True,
            name=u'timeCtrlTotalLength',
            oob_color=wx.YELLOW,
            style=0,
            useFixedWidthFont=True,
            value='12:00:00 AM',
            size=wx.Size(300, -1))
        self.timeCtrlTotalLength.Enable(False)

        self.rbAudio = wx.RadioButton(self,
                                      label=_(u'Fit to audio files'),
                                      name=u'rbAudio')
        self.rbAudio.Bind(wx.EVT_RADIOBUTTON, self.OnControlStatusTotalLength)

        self.staticLine = wx.StaticLine(self)

        self.cmdCancel = wx.Button(self,
                                   id=wx.ID_CANCEL,
                                   label=_(u'&Cancel'),
                                   name=u'cmdCancel')
        self.cmdOk = wx.Button(self,
                               id=wx.ID_OK,
                               label=_(u'&Ok'),
                               name=u'cmdOk')
        self.cmdOk.Bind(wx.EVT_BUTTON, self.OnCmdOkButton, id=wx.ID_OK)
        self.cmdOk.SetDefault()

    def __init__(self, parent, project=None):
        wx.Dialog.__init__(self,
                           parent,
                           name=u'DlgDuration',
                           style=wx.DEFAULT_DIALOG_STYLE | wx.RESIZE_BORDER,
                           title=_(u'Slideshow duration'))

        self._InitCtrls()

        self.pnlHdr.SetTitle(_(u'Configure duration of slideshow'))
        self.pnlHdr.SetBitmap(wx.ArtProvider.GetBitmap('PFS_ICON_32'))

        defTime = wx.DateTime.Now()
        defTime.SetHMS(0, 0, 30)
        minTime = wx.DateTime.Now()
        minTime.SetHMS(0, 0, 1)
        maxTime = wx.DateTime.Now()
        maxTime.SetHMS(1, 59, 59)
        self.timeCtrlTotalLength.SetValue(defTime)
        self.timeCtrlTotalLength.SetMin(minTime)
        self.timeCtrlTotalLength.SetMax(maxTime)
        self.timeCtrlTotalLength.SetLimited(True)

        self.__project = project

        pfsDur = project.GetDuration(calc=True)
        duration = project.GetDuration(calc=False)
        if duration is None:
            self.cbTotalLength.SetValue(False)
        elif duration <= 0:
            self.cbTotalLength.SetValue(True)
            self.rbAudio.SetValue(True)
        else:
            self.cbTotalLength.SetValue(True)
            self.rbManual.SetValue(True)
            pfsDur = duration

        pfsDur = int(round(pfsDur))

        dur = wx.DateTime.Now()
        dur.SetHMS(pfsDur // 3600, (pfsDur % 3600) // 60, pfsDur % 60)
        try:
            self.timeCtrlTotalLength.SetWxDateTime(dur)
        except ValueError:
            # duration is invalid if there are no photos
            pass

        self.__ControlStatusTotalLength()

        self._InitSizers()
        self.SetInitialSize(self.GetEffectiveMinSize())
        self.Fit()
        self.CenterOnParent()
        self.SetFocus()

    def OnControlStatusTotalLength(self, event):
        self.__ControlStatusTotalLength()
        event.Skip()

    def OnCmdOkButton(self, event):
        self.__project.SetDuration(self.__GetTotalLength())
        event.Skip()

    def __ControlStatusTotalLength(self):
        active = self.cbTotalLength.GetValue()
        manual = self.rbManual.GetValue()

        self.rbAudio.Enable(active)
        self.rbManual.Enable(active)
        self.timeCtrlTotalLength.Enable(active and manual)

    def __GetTotalLength(self):
        totalLength = None

        if self.cbTotalLength.GetValue():
            if self.rbManual.GetValue():
                totalLength = 0
                dateTime = self.timeCtrlTotalLength.GetValue(
                    as_wxDateTime=True)
                totalLength += dateTime.GetHour() * 3600
                totalLength += dateTime.GetMinute() * 60
                totalLength += dateTime.GetSecond()
            elif self.rbAudio.GetValue():
                totalLength = -1

        return totalLength
Beispiel #7
0
class DlgPositionInput(wx.Dialog):

    _custom_classes = {"wx.Panel": ["PnlDlgHeader"]}

    def _init_coll_szStart_Items(self, parent):
        # generated method, don't edit

        parent.Add(self.stStartLocation,
                   0,
                   border=0,
                   flag=wx.ALIGN_CENTER_VERTICAL)
        parent.Add(self.spinStartX, 0, border=0, flag=0)
        parent.Add(self.spinStartY, 0, border=0, flag=0)
        parent.Add(self.stStartSize,
                   0,
                   border=0,
                   flag=wx.ALIGN_CENTER_VERTICAL)
        parent.Add(self.spinStartWidth, 0, border=0, flag=0)
        parent.Add(self.spinStartHeight, 0, border=0, flag=0)

    def _init_coll_szStartHdr_Items(self, parent):
        # generated method, don't edit

        parent.Add(self.stStartPos, 0, border=0, flag=0)
        parent.AddSpacer(8)
        parent.Add(self.slStartPos, 1, border=0, flag=wx.ALIGN_CENTER_VERTICAL)

    def _init_coll_szEndCtrls_Items(self, parent):
        # generated method, don't edit

        parent.AddSpacer(16)
        parent.Add(self.szEnd, 1, border=0, flag=0)

    def _init_coll_szEnd_Items(self, parent):
        # generated method, don't edit

        parent.Add(self.stEndLocation,
                   0,
                   border=0,
                   flag=wx.ALIGN_CENTER_VERTICAL)
        parent.Add(self.spinEndX, 0, border=0, flag=0)
        parent.Add(self.spinEndY, 0, border=0, flag=0)
        parent.Add(self.stEndSize, 0, border=0, flag=wx.ALIGN_CENTER_VERTICAL)
        parent.Add(self.spinEndWidth, 0, border=0, flag=0)
        parent.Add(self.spinEndHeight, 0, border=0, flag=0)

    def _init_coll_szCmds_Items(self, parent):
        # generated method, don't edit

        parent.Add(self.cmdReset, 0, border=0, flag=0)
        parent.AddSpacer(8)
        parent.Add(self.cmdCancel, 0, border=0, flag=0)
        parent.AddSpacer(8)
        parent.Add(self.cmdOk, 0, border=0, flag=0)

    def _init_coll_szMain_Items(self, parent):
        # generated method, don't edit

        parent.Add(self.pnlHdr, 0, border=0, flag=wx.EXPAND)
        parent.Add(self.szStartHdr, 0, border=4, flag=wx.ALL | wx.EXPAND)
        parent.Add(self.szStartCtrls, 0, border=4, flag=wx.EXPAND | wx.ALL)
        parent.AddSpacer(16)
        parent.Add(self.szEndHdr, 0, border=4, flag=wx.ALL | wx.EXPAND)
        parent.Add(self.szEndCtrls, 0, border=4, flag=wx.EXPAND | wx.ALL)
        parent.AddSpacer(16)
        parent.Add(self.szCmds, 0, border=4, flag=wx.ALL | wx.ALIGN_RIGHT)

    def _init_coll_szStartCtrls_Items(self, parent):
        # generated method, don't edit

        parent.AddSpacer(8)
        parent.Add(self.szStart, 1, border=0, flag=0)

    def _init_coll_szEndHdr_Items(self, parent):
        # generated method, don't edit

        parent.Add(self.stEndPos, 0, border=0, flag=0)
        parent.AddSpacer(8)
        parent.Add(self.slEndPos, 1, border=0, flag=wx.ALIGN_CENTER_VERTICAL)

    def _init_sizers(self):
        # generated method, don't edit
        self.szMain = wx.BoxSizer(orient=wx.VERTICAL)

        self.szStart = wx.FlexGridSizer(cols=3, hgap=4, rows=2, vgap=8)

        self.szStartHdr = wx.BoxSizer(orient=wx.HORIZONTAL)

        self.szEndHdr = wx.BoxSizer(orient=wx.HORIZONTAL)

        self.szStartCtrls = wx.BoxSizer(orient=wx.HORIZONTAL)

        self.szEnd = wx.FlexGridSizer(cols=3, hgap=4, rows=2, vgap=8)

        self.szEndCtrls = wx.BoxSizer(orient=wx.HORIZONTAL)

        self.szCmds = wx.BoxSizer(orient=wx.HORIZONTAL)

        self._init_coll_szMain_Items(self.szMain)
        self._init_coll_szStart_Items(self.szStart)
        self._init_coll_szStartHdr_Items(self.szStartHdr)
        self._init_coll_szEndHdr_Items(self.szEndHdr)
        self._init_coll_szStartCtrls_Items(self.szStartCtrls)
        self._init_coll_szEnd_Items(self.szEnd)
        self._init_coll_szEndCtrls_Items(self.szEndCtrls)
        self._init_coll_szCmds_Items(self.szCmds)

        self.SetSizer(self.szMain)

    def _init_ctrls(self, prnt):
        # generated method, don't edit
        wx.Dialog.__init__(self,
                           id=wxID_DLGPOSITIONINPUT,
                           name=u'DlgPositionInput',
                           parent=prnt,
                           pos=wx.Point(-1, -1),
                           size=wx.Size(-1, -1),
                           style=wx.DEFAULT_DIALOG_STYLE,
                           title=_(u'Motion positions'))

        self.pnlHdr = PnlDlgHeader(id=wxID_DLGPOSITIONINPUTPNLHDR,
                                   name=u'pnlHdr',
                                   parent=self,
                                   pos=wx.Point(-1, -1),
                                   size=wx.Size(-1, -1),
                                   style=wx.TAB_TRAVERSAL)

        self.stStartPos = wx.StaticText(id=wxID_DLGPOSITIONINPUTSTSTARTPOS,
                                        label=_(u'Start position'),
                                        name=u'stStartPos',
                                        parent=self,
                                        pos=wx.Point(-1, -1),
                                        size=wx.Size(-1, -1),
                                        style=0)

        self.slStartPos = wx.StaticLine(id=wxID_DLGPOSITIONINPUTSLSTARTPOS,
                                        name=u'slStartPos',
                                        parent=self,
                                        pos=wx.Point(-1, -1),
                                        size=wx.Size(-1, -1),
                                        style=0)

        self.stStartLocation = wx.StaticText(
            id=wxID_DLGPOSITIONINPUTSTSTARTLOCATION,
            label=_(u'Location:'),
            name=u'stStartLocation',
            parent=self,
            pos=wx.Point(-1, -1),
            size=wx.Size(-1, -1),
            style=0)

        self.spinStartX = wx.SpinCtrl(id=wxID_DLGPOSITIONINPUTSPINSTARTX,
                                      initial=0,
                                      max=100,
                                      min=0,
                                      name=u'spinStartX',
                                      parent=self,
                                      pos=wx.Point(-1, -1),
                                      size=wx.Size(-1, -1),
                                      style=wx.SP_ARROW_KEYS)
        self.spinStartX.Bind(wx.EVT_TEXT,
                             self.OnSpinChange,
                             id=wxID_DLGPOSITIONINPUTSPINSTARTX)

        self.spinStartY = wx.SpinCtrl(id=wxID_DLGPOSITIONINPUTSPINSTARTY,
                                      initial=0,
                                      max=100,
                                      min=0,
                                      name=u'spinStartY',
                                      parent=self,
                                      pos=wx.Point(-1, -1),
                                      size=wx.Size(-1, -1),
                                      style=wx.SP_ARROW_KEYS)
        self.spinStartY.Bind(wx.EVT_TEXT,
                             self.OnSpinChange,
                             id=wxID_DLGPOSITIONINPUTSPINSTARTY)

        self.stStartSize = wx.StaticText(id=wxID_DLGPOSITIONINPUTSTSTARTSIZE,
                                         label=_(u'Size:'),
                                         name=u'stStartSize',
                                         parent=self,
                                         pos=wx.Point(-1, -1),
                                         size=wx.Size(-1, -1),
                                         style=0)

        self.spinStartWidth = wx.SpinCtrl(
            id=wxID_DLGPOSITIONINPUTSPINSTARTWIDTH,
            initial=0,
            max=100,
            min=0,
            name=u'spinStartWidth',
            parent=self,
            pos=wx.Point(-1, -1),
            size=wx.Size(-1, -1),
            style=wx.SP_ARROW_KEYS)
        self.spinStartWidth.Bind(wx.EVT_TEXT,
                                 self.OnSpinChange,
                                 id=wxID_DLGPOSITIONINPUTSPINSTARTWIDTH)

        self.spinStartHeight = wx.SpinCtrl(
            id=wxID_DLGPOSITIONINPUTSPINSTARTHEIGHT,
            initial=0,
            max=100,
            min=0,
            name=u'spinStartHeight',
            parent=self,
            pos=wx.Point(-1, -1),
            size=wx.Size(-1, -1),
            style=wx.SP_ARROW_KEYS)
        self.spinStartHeight.Bind(wx.EVT_TEXT,
                                  self.OnSpinChange,
                                  id=wxID_DLGPOSITIONINPUTSPINSTARTHEIGHT)

        self.stEndPos = wx.StaticText(id=wxID_DLGPOSITIONINPUTSTENDPOS,
                                      label=_(u'End position'),
                                      name=u'stEndPos',
                                      parent=self,
                                      pos=wx.Point(-1, -1),
                                      size=wx.Size(-1, -1),
                                      style=0)

        self.slEndPos = wx.StaticLine(id=wxID_DLGPOSITIONINPUTSLENDPOS,
                                      name=u'slEndPos',
                                      parent=self,
                                      pos=wx.Point(-1, -1),
                                      size=wx.Size(-1, -1),
                                      style=0)

        self.stEndLocation = wx.StaticText(
            id=wxID_DLGPOSITIONINPUTSTENDLOCATION,
            label=_(u'Location:'),
            name=u'stEndLocation',
            parent=self,
            pos=wx.Point(-1, -1),
            size=wx.Size(-1, -1),
            style=0)

        self.spinEndX = wx.SpinCtrl(id=wxID_DLGPOSITIONINPUTSPINENDX,
                                    initial=0,
                                    max=100,
                                    min=0,
                                    name=u'spinEndX',
                                    parent=self,
                                    pos=wx.Point(-1, -1),
                                    size=wx.Size(-1, -1),
                                    style=wx.SP_ARROW_KEYS)
        self.spinEndX.Bind(wx.EVT_TEXT,
                           self.OnSpinChange,
                           id=wxID_DLGPOSITIONINPUTSPINENDX)

        self.spinEndY = wx.SpinCtrl(id=wxID_DLGPOSITIONINPUTSPINENDY,
                                    initial=0,
                                    max=100,
                                    min=0,
                                    name=u'spinEndY',
                                    parent=self,
                                    pos=wx.Point(-1, -1),
                                    size=wx.Size(-1, -1),
                                    style=wx.SP_ARROW_KEYS)
        self.spinEndY.Bind(wx.EVT_TEXT,
                           self.OnSpinChange,
                           id=wxID_DLGPOSITIONINPUTSPINENDY)

        self.stEndSize = wx.StaticText(id=wxID_DLGPOSITIONINPUTSTENDSIZE,
                                       label=_(u'Size:'),
                                       name=u'stEndSize',
                                       parent=self,
                                       pos=wx.Point(-1, -1),
                                       size=wx.Size(-1, -1),
                                       style=0)

        self.spinEndWidth = wx.SpinCtrl(id=wxID_DLGPOSITIONINPUTSPINENDWIDTH,
                                        initial=0,
                                        max=100,
                                        min=0,
                                        name=u'spinEndWidth',
                                        parent=self,
                                        pos=wx.Point(-1, -1),
                                        size=wx.Size(-1, -1),
                                        style=wx.SP_ARROW_KEYS)
        self.spinEndWidth.Bind(wx.EVT_TEXT,
                               self.OnSpinChange,
                               id=wxID_DLGPOSITIONINPUTSPINENDWIDTH)

        self.spinEndHeight = wx.SpinCtrl(id=wxID_DLGPOSITIONINPUTSPINENDHEIGHT,
                                         initial=0,
                                         max=100,
                                         min=0,
                                         name=u'spinEndHeight',
                                         parent=self,
                                         pos=wx.Point(-1, -1),
                                         size=wx.Size(-1, -1),
                                         style=wx.SP_ARROW_KEYS)
        self.spinEndHeight.Bind(wx.EVT_TEXT,
                                self.OnSpinChange,
                                id=wxID_DLGPOSITIONINPUTSPINENDHEIGHT)

        self.cmdReset = wx.Button(id=wxID_DLGPOSITIONINPUTCMDRESET,
                                  label=_(u'Reset'),
                                  name=u'cmdReset',
                                  parent=self,
                                  pos=wx.Point(-1, -1),
                                  size=wx.Size(-1, -1),
                                  style=0)
        self.cmdReset.Bind(wx.EVT_BUTTON,
                           self.OnCmdResetButton,
                           id=wxID_DLGPOSITIONINPUTCMDRESET)

        self.cmdCancel = wx.Button(id=wx.ID_CANCEL,
                                   label=_(u'&Cancel'),
                                   name=u'cmdCancel',
                                   parent=self,
                                   pos=wx.Point(-1, -1),
                                   size=wx.Size(-1, -1),
                                   style=0)
        self.cmdCancel.Bind(wx.EVT_BUTTON,
                            self.OnCmdCancelButton,
                            id=wx.ID_CANCEL)

        self.cmdOk = wx.Button(id=wx.ID_OK,
                               label=_(u'&Ok'),
                               name=u'cmdOk',
                               parent=self,
                               pos=wx.Point(-1, -1),
                               size=wx.Size(-1, -1),
                               style=0)

        self._init_sizers()

    def __init__(self, parent, pic, aspect):
        self._init_ctrls(parent)

        self.pnlHdr.SetTitle(_(u'Adjust motion positions directly'))
        self.pnlHdr.SetBitmap(wx.ArtProvider.GetBitmap('PFS_MOTION_MANUAL_32'))

        self.__pic = pic
        self.__ratio = Aspect.ToFloat(aspect)
        self.__doOnChange = True

        self.__backupStart = self.__pic.GetStartRect()
        self.__backupEnd = self.__pic.GetTargetRect()

        font = self.stStartPos.GetFont()
        font.SetWeight(wx.FONTWEIGHT_BOLD)
        self.stStartPos.SetFont(font)
        self.stEndPos.SetFont(font)

        self._InitValues()

        self.SetInitialSize(self.GetEffectiveMinSize())
        self.CenterOnParent()
        self.SetFocus()

    def _InitValues(self):
        self.__doOnChange = False
        # Init ranges with max values
        self.spinStartX.SetRange(0, self.__pic.GetWidth())
        self.spinStartY.SetRange(0, self.__pic.GetHeight())
        self.spinStartWidth.SetRange(
            0,
            min(int(round(self.__pic.GetHeight() * self.__ratio)),
                self.__pic.GetWidth()))
        self.spinStartHeight.SetRange(
            0,
            min(int(round(self.__pic.GetWidth() / self.__ratio)),
                self.__pic.GetHeight()))

        self.spinEndX.SetRange(0, self.__pic.GetWidth())
        self.spinEndY.SetRange(0, self.__pic.GetHeight())
        self.spinEndWidth.SetRange(
            0,
            min(int(round(self.__pic.GetHeight() * self.__ratio)),
                self.__pic.GetWidth()))
        self.spinEndHeight.SetRange(
            0,
            min(int(round(self.__pic.GetWidth() / self.__ratio)),
                self.__pic.GetHeight()))

        # Init values
        self.spinStartX.SetValue(self.__pic.GetStartRect()[0])
        self.spinStartY.SetValue(self.__pic.GetStartRect()[1])
        self.spinStartWidth.SetValue(self.__pic.GetStartRect()[2])
        self.spinStartHeight.SetValue(self.__pic.GetStartRect()[3])

        self.spinEndX.SetValue(self.__pic.GetTargetRect()[0])
        self.spinEndY.SetValue(self.__pic.GetTargetRect()[1])
        self.spinEndWidth.SetValue(self.__pic.GetTargetRect()[2])
        self.spinEndHeight.SetValue(self.__pic.GetTargetRect()[3])

        self.__doOnChange = True

        self._SetupRanges()

    def _SetupRanges(self):
        '''
        Limit the location ranges to the current adjusted size
        '''
        self.spinStartX.SetRange(
            0,
            self.__pic.GetWidth() - self.spinStartWidth.GetValue())
        self.spinStartY.SetRange(
            0,
            self.__pic.GetHeight() - self.spinStartHeight.GetValue())

        self.spinEndX.SetRange(
            0,
            self.__pic.GetWidth() - self.spinEndWidth.GetValue())
        self.spinEndY.SetRange(
            0,
            self.__pic.GetHeight() - self.spinEndHeight.GetValue())

    def _PreserveAspect(self, wxId):
        self.__doOnChange = False

        if wxId == wxID_DLGPOSITIONINPUTSPINSTARTWIDTH:
            self.spinStartHeight.SetValue(
                int(round(self.spinStartWidth.GetValue() / self.__ratio)))
        if wxId == wxID_DLGPOSITIONINPUTSPINSTARTHEIGHT:
            self.spinStartWidth.SetValue(
                int(round(self.spinStartHeight.GetValue() * self.__ratio)))

        if wxId == wxID_DLGPOSITIONINPUTSPINENDWIDTH:
            self.spinEndHeight.SetValue(
                int(round(self.spinEndWidth.GetValue() / self.__ratio)))
        if wxId == wxID_DLGPOSITIONINPUTSPINENDHEIGHT:
            self.spinEndWidth.SetValue(
                int(round(self.spinEndHeight.GetValue() * self.__ratio)))

        self.__doOnChange = True

    def OnSpinChange(self, event):
        if not self.__doOnChange:
            return
        self._PreserveAspect(event.GetId())

        startRect = (self.spinStartX.GetValue(), self.spinStartY.GetValue(),
                     self.spinStartWidth.GetValue(),
                     self.spinStartHeight.GetValue())

        endRect = (self.spinEndX.GetValue(), self.spinEndY.GetValue(),
                   self.spinEndWidth.GetValue(), self.spinEndHeight.GetValue())

        if event.GetId() in (wxID_DLGPOSITIONINPUTSPINENDWIDTH,
                             wxID_DLGPOSITIONINPUTSPINENDHEIGHT,
                             wxID_DLGPOSITIONINPUTSPINSTARTWIDTH,
                             wxID_DLGPOSITIONINPUTSPINSTARTHEIGHT):
            self._SetupRanges()

        self.__pic.SetStartRect(startRect)
        self.__pic.SetTargetRect(endRect)

        event.Skip()

    def OnCmdResetButton(self, event):
        self.__pic.SetStartRect(self.__backupStart)
        self.__pic.SetTargetRect(self.__backupEnd)
        self._InitValues()
        event.Skip()

    def OnCmdCancelButton(self, event):
        self.__pic.SetStartRect(self.__backupStart)
        self.__pic.SetTargetRect(self.__backupEnd)
        event.Skip()
Beispiel #8
0
class DlgConfigureAudio(wx.Dialog):
    def _InitSizers(self):
        szMain = wx.BoxSizer(orient=wx.VERTICAL)

        szAudioChoice = wx.BoxSizer(orient=wx.HORIZONTAL)
        szAudioList = wx.BoxSizer(orient=wx.HORIZONTAL)

        szAudioCmds = wx.BoxSizer(orient=wx.VERTICAL)

        szCmds = wx.BoxSizer(orient=wx.HORIZONTAL)

        szMain.Add(self.pnlHdr, 0, border=0, flag=wx.EXPAND)
        szMain.Add(self.szMsg, 0, border=8, flag=wx.ALL | wx.EXPAND)
        szMain.Add(szAudioChoice, 0, border=8, flag=wx.ALL | wx.EXPAND)
        szMain.Add(szAudioList, 1, border=8, flag=wx.ALL | wx.EXPAND)
        szMain.Add(self.cbAudio, 0, border=8, flag=wx.ALL | wx.EXPAND)
        szMain.Add(szCmds, 0, border=8, flag=wx.ALL | wx.ALIGN_RIGHT)

        szAudioChoice.Add(self.choiceAudioFiles,
                          1,
                          flag=wx.ALIGN_CENTER_VERTICAL | wx.RIGHT,
                          border=4)
        szAudioChoice.Add(self.cmdAddMusic)

        szAudioList.Add(self.lvAudio, 1, flag=wx.EXPAND | wx.RIGHT, border=4)
        szAudioList.Add(szAudioCmds)

        szAudioCmds.Add(self.cmdAudioPreview, border=2, flag=wx.BOTTOM)
        szAudioCmds.Add(self.cmdAudioMoveUp, border=2, flag=wx.BOTTOM)
        szAudioCmds.Add(self.cmdAudioMoveDown, border=2, flag=wx.BOTTOM)
        szAudioCmds.Add(self.cmdAudioDel, border=2, flag=wx.BOTTOM)

        szCmds.Add(self.cmdCancel, 0, border=0, flag=0)
        szCmds.AddSpacer(8)
        szCmds.Add(self.cmdOk, 0, border=0, flag=0)

        self.SetSizer(szMain)

    def _InitCtrls(self):
        self.pnlHdr = PnlDlgHeader(self)

        self.szMsg = self.CreateTextSizer(
            _("Configure your audio files that are used as a background music."
              ))

        self.choiceAudioFiles = wx.Choice(self)

        self.lvAudio = wx.ListBox(self, style=wx.LB_SINGLE)
        self.lvAudio.Bind(wx.EVT_LISTBOX, self.OnControlStatusAudio)

        self.cmdAddMusic = wx.BitmapButton(self,
                                           bitmap=wx.ArtProvider.GetBitmap(
                                               "PFS_ADD", wx.ART_TOOLBAR),
                                           name="cmdAddMusic",
                                           style=wx.BU_AUTODRAW)
        self.cmdAddMusic.Bind(wx.EVT_BUTTON, self.OnCmdAddMusicButton)

        self.cmdAudioPreview = wx.BitmapButton(self,
                                               bitmap=wx.ArtProvider.GetBitmap(
                                                   'PFS_PLAY_PAUSE',
                                                   wx.ART_TOOLBAR),
                                               name="cmdAudioPreview",
                                               style=wx.BU_AUTODRAW)
        self.cmdAudioPreview.SetBitmapDisabled(
            wx.ArtProvider.GetBitmap('PFS_PLAY_PAUSE_D', wx.ART_TOOLBAR))
        self.cmdAudioPreview.Bind(wx.EVT_BUTTON, self.OnCmdAudioPreviewButton)

        self.cmdAudioMoveUp = wx.BitmapButton(self,
                                              bitmap=wx.ArtProvider.GetBitmap(
                                                  'PFS_ARROW_UP',
                                                  wx.ART_TOOLBAR),
                                              name="cmdAudioMoveUp",
                                              style=wx.BU_AUTODRAW)
        self.cmdAudioMoveUp.SetBitmapDisabled(
            wx.ArtProvider.GetBitmap('PFS_ARROW_UP_D', wx.ART_TOOLBAR))
        self.cmdAudioMoveUp.Bind(wx.EVT_BUTTON, self.OnCmdAudioMove)

        self.cmdAudioMoveDown = wx.BitmapButton(
            self,
            bitmap=wx.ArtProvider.GetBitmap('PFS_ARROW_DOWN', wx.ART_TOOLBAR),
            name="cmdAudioMoveDown",
            style=wx.BU_AUTODRAW)
        self.cmdAudioMoveDown.SetBitmapDisabled(
            wx.ArtProvider.GetBitmap('PFS_ARROW_DOWN_D', wx.ART_TOOLBAR))
        self.cmdAudioMoveDown.Bind(wx.EVT_BUTTON, self.OnCmdAudioMove)

        self.cmdAudioDel = wx.BitmapButton(self,
                                           bitmap=wx.ArtProvider.GetBitmap(
                                               'PFS_REMOVE', wx.ART_TOOLBAR),
                                           name="cmdAudioDel",
                                           style=wx.BU_AUTODRAW)
        self.cmdAudioDel.SetBitmapDisabled(
            wx.ArtProvider.GetBitmap('PFS_REMOVE_D', wx.ART_TOOLBAR))
        self.cmdAudioDel.Bind(wx.EVT_BUTTON, self.OnCmdAudioDel)

        self.cbAudio = wx.CheckBox(
            self,
            wx.ID_ANY,
            label=_(
                "Set the duration of your slideshow to fit your audio files"))

        self.cmdCancel = wx.Button(self,
                                   id=wx.ID_CANCEL,
                                   label=_("&Cancel"),
                                   name="cmdCancel")
        self.cmdCancel.Bind(wx.EVT_BUTTON,
                            self.OnCmdCancelButton,
                            id=wx.ID_CANCEL)

        self.cmdOk = wx.Button(self, id=wx.ID_OK, label=_("&Ok"), name="cmdOk")
        self.cmdOk.Bind(wx.EVT_BUTTON, self.OnCmdOkButton, id=wx.ID_OK)

    def __init__(self, parent, project):
        wx.Dialog.__init__(self,
                           parent,
                           name="DlgConfigureAudio",
                           style=wx.DEFAULT_DIALOG_STYLE | wx.RESIZE_BORDER,
                           title=_("Configure music"))
        self.Bind(wx.EVT_CLOSE, self.OnClose)

        self._InitCtrls()

        self.pnlHdr.SetTitle(_("Configure music"))
        self.pnlHdr.SetBitmap(
            wx.ArtProvider.GetBitmap('PFS_MUSIC', size=(32, 32)))

        self.lvAudio.SetMinSize(wx.Size(300, -1))

        self.__project = project
        self.__mediaCtrl = None
        self.__musicMap = {}

        self.__idxSelectOption = self.choiceAudioFiles.Append("~ {} ~".format(
            _("Select an entry")))
        self.__idxBrowseAudio = self.choiceAudioFiles.Append("~ {} ~".format(
            _("Browse for audio files")))

        self.__CreateProvidedMusicEntries()

        self.cmdAddMusic.Enable(False)
        self.choiceAudioFiles.Select(self.__idxSelectOption)
        self.choiceAudioFiles.Bind(wx.EVT_CHOICE, self.OnChoiceAudio)

        if project.GetTimelapse():
            self.cbAudio.SetValue(False)
            self.cbAudio.Show(False)
        else:
            duration = project.GetDuration(False)
            self.cbAudio.SetValue(duration == -1)

        for audioFile in project.GetAudioFiles():
            self.__AddAudioItem(audioFile, select=True)

        self.__ControlStatusAudio()

        self._InitSizers()
        self.SetInitialSize(self.GetEffectiveMinSize())
        self.Fit()
        self.CenterOnParent()

    def OnControlStatusAudio(self, event):  # pylint: disable=unused-argument
        self.__ControlStatusAudio()

    def OnChoiceAudio(self, event):
        selIdx = event.GetInt()
        self.cmdAddMusic.Enable(selIdx not in (self.__idxBrowseAudio,
                                               self.__idxSelectOption))
        if selIdx == self.__idxBrowseAudio:
            self.OnCmdBrowseAudioButton(event)
            self.choiceAudioFiles.Select(self.__idxSelectOption)
        elif selIdx != self.__idxSelectOption:
            self.OnCmdAddMusicButton(event)
        else:
            pass

    def OnCmdAddMusicButton(self, event):  # pylint: disable=unused-argument
        selIdx = self.choiceAudioFiles.GetSelection()
        if selIdx == wx.NOT_FOUND:
            return

        audioFile = self.choiceAudioFiles.GetClientData(selIdx)
        if audioFile:
            self.__AddAudioItem(audioFile, select=True)

    def __CreateProvidedMusicEntries(self):
        audioDir = self.__GetAudioDir()
        for filename in os.listdir(audioDir):
            fname, fext = os.path.splitext(filename)
            if fext in FILE_EXTENSIONS_AUDIO:
                audioFile = os.path.join(audioDir, filename)

                self.choiceAudioFiles.Append(fname, audioFile)

    def OnCmdBrowseAudioButton(self, event):  # pylint: disable=unused-argument
        dlg = wx.FileDialog(self, _("Select music"),
                            Settings().GetAudioPath(), "",
                            _("Audio files") + " (*.*)|*.*",
                            wx.FD_OPEN | wx.FD_MULTIPLE)
        if dlg.ShowModal() == wx.ID_OK:
            for path in dlg.GetPaths():
                Settings().SetAudioPath(os.path.dirname(path))
                self.__AddAudioItem(path, select=True)

        dlg.Destroy()

    def OnCmdAudioPreviewButton(self, event):  # pylint: disable=unused-argument
        selIdx = self.lvAudio.GetSelection()
        if selIdx == wx.NOT_FOUND:
            return

        filename = self.lvAudio.GetClientData(selIdx)
        if self.__mediaCtrl and self.__mediaCtrl.GetFilename() == filename:
            if self.__mediaCtrl.IsPlaying():
                self.__mediaCtrl.Stop()
            else:
                self.__mediaCtrl.Play()
        else:
            self.__LoadAudioFile(filename)

    def OnCmdAudioMove(self, event):
        selIdx = self.lvAudio.GetSelection()
        if selIdx == wx.NOT_FOUND:
            return

        selAudio = self.lvAudio.GetClientData(selIdx)

        evtObj = event.GetEventObject()
        if evtObj is self.cmdAudioMoveUp:
            if selIdx > 0:
                prevAudio = self.lvAudio.GetClientData(selIdx - 1)
                self.__UpdateAudioItem(selIdx, prevAudio)
                self.__UpdateAudioItem(selIdx - 1, selAudio)
                self.lvAudio.SetSelection(selIdx - 1)
        elif evtObj is self.cmdAudioMoveDown:
            if selIdx < self.lvAudio.GetCount() - 1:
                nextAudio = self.lvAudio.GetClientData(selIdx + 1)
                self.__UpdateAudioItem(selIdx, nextAudio)
                self.__UpdateAudioItem(selIdx + 1, selAudio)
                self.lvAudio.SetSelection(selIdx + 1)

        self.__ControlStatusAudio()

    def OnCmdAudioDel(self, event):  # pylint: disable=unused-argument
        selIdx = self.lvAudio.GetSelection()
        if selIdx != wx.NOT_FOUND:
            self.lvAudio.Delete(selIdx)
        self.lvAudio.Select(min(selIdx, self.lvAudio.GetCount() - 1))

        self.__ControlStatusAudio()

    def OnClose(self, event):
        self.__CloseMediaCtrl()
        event.Skip()

    def OnCmdCancelButton(self, event):
        self.__CloseMediaCtrl()
        event.Skip()

    def OnCmdOkButton(self, event):
        self.__CloseMediaCtrl()
        if self.__ValidateAudioFile():
            self.__project.SetAudioFiles(
                [ai[2] for ai in self.__IterAudioItems()])
            if self.cbAudio.GetValue():
                self.__project.SetDuration(-1)
            elif self.__project.GetDuration(False) == -1:
                # was previously set, so reset the duration
                self.__project.SetDuration(None)

            event.Skip()

    def __AddAudioItem(self, audioFile, select=False):
        idx = self.lvAudio.Append("")
        self.__UpdateAudioItem(idx, audioFile)
        if select:
            self.lvAudio.Select(idx)

            self.__ControlStatusAudio()
        return idx

    def __UpdateAudioItem(self, idx, audioFile):
        self.lvAudio.SetString(idx, os.path.basename(audioFile))
        self.lvAudio.SetClientData(idx, audioFile)

    def __IterAudioItems(self):
        for idx in range(self.lvAudio.GetCount()):
            yield idx, self.lvAudio.GetString(idx), self.lvAudio.GetClientData(
                idx)

    def __ControlStatusAudio(self):
        selected = self.lvAudio.GetSelection()

        self.cmdAudioPreview.Enable(selected != wx.NOT_FOUND)
        self.cmdAudioDel.Enable(selected != wx.NOT_FOUND)
        self.cmdAudioMoveUp.Enable(selected > 0)
        self.cmdAudioMoveDown.Enable(selected < (self.lvAudio.GetCount() - 1))

    def __LoadAudioFile(self, path):
        self.__CloseMediaCtrl()

        if not os.path.exists(path):
            dlg = wx.MessageDialog(self,
                                   _("Audio file '%s' does not exist!") % path,
                                   _("Error"), wx.OK | wx.ICON_ERROR)
            dlg.ShowModal()
            dlg.Destroy()

        mediaCtrl = AudioPlayer(path)
        if mediaCtrl.IsOk():
            self.__mediaCtrl = mediaCtrl
            self.__mediaCtrl.Play()
        else:
            dlg = wx.MessageDialog(self, _("Audio file not supported!"),
                                   _("Error"), wx.OK | wx.ICON_ERROR)
            dlg.ShowModal()
            dlg.Destroy()

    def __ValidateAudioFile(self):
        for idx, basename, path in self.__IterAudioItems():
            if not os.path.exists(path):
                dlg = wx.MessageDialog(
                    self,
                    _("Audio file '%s' does not exist!") % path, _("Error"),
                    wx.OK | wx.ICON_ERROR)
                dlg.ShowModal()
                dlg.Destroy()
                return False
        return True

    def __CloseMediaCtrl(self):
        if self.__mediaCtrl is not None:
            try:
                self.__mediaCtrl.Close()
            except:
                pass
        self.__mediaCtrl = None

    def __GetAudioDir(self):
        return GetDataDir("audio")
Beispiel #9
0
class DlgProjectProps(wx.Dialog):
    def _InitSizers(self):
        self.szMain = wx.BoxSizer(orient=wx.VERTICAL)

        self.szCtrls = wx.GridBagSizer(hgap=8, vgap=8)

        self.szCmds = wx.BoxSizer(orient=wx.HORIZONTAL)

        self.szAudioCmds = wx.BoxSizer(orient=wx.VERTICAL)

        self.szMain.Add(self.pnlHdr, 0, border=0, flag=wx.EXPAND)
        self.szMain.Add(self.szCtrls, 0, border=8, flag=wx.ALL | wx.EXPAND)
        self.szMain.Add(self.staticLine1, 0, border=0, flag=wx.EXPAND)
        self.szMain.Add(self.szCmds, 0, border=8, flag=wx.ALL | wx.ALIGN_RIGHT)

        self.szCtrls.Add(self.stProject, (0, 0),
                         border=0,
                         flag=wx.ALIGN_CENTER_VERTICAL,
                         span=(1, 1))
        self.szCtrls.Add(self.tcProject, (0, 1),
                         border=0,
                         flag=wx.EXPAND,
                         span=(1, 1))
        self.szCtrls.Add(self.stFolder, (1, 0),
                         border=0,
                         flag=wx.ALIGN_CENTER_VERTICAL,
                         span=(1, 1))
        self.szCtrls.Add(self.tcFolder, (1, 1),
                         border=0,
                         flag=wx.ALIGN_CENTER_VERTICAL | wx.EXPAND,
                         span=(1, 1))
        self.szCtrls.Add(self.cmdBrowseFolder, (1, 2),
                         border=0,
                         flag=0,
                         span=(1, 1))
        self.szCtrls.Add(self.staticLine, (2, 0),
                         border=0,
                         flag=0,
                         span=(1, 4))
        self.szCtrls.Add(self.stAspect, (3, 0),
                         border=0,
                         flag=wx.ALIGN_CENTER_VERTICAL,
                         span=(1, 1))
        self.szCtrls.Add(self.choiceAspect, (3, 1),
                         border=0,
                         flag=wx.EXPAND,
                         span=(1, 1))

        self.szCtrls.Add(self.stAudio, (4, 0),
                         border=0,
                         flag=wx.ALIGN_TOP,
                         span=(1, 1))
        self.szCtrls.Add(self.lvAudio, (4, 1),
                         border=0,
                         flag=wx.EXPAND,
                         span=(1, 1))
        self.szCtrls.Add(self.szAudioCmds, (4, 2),
                         border=0,
                         flag=0,
                         span=(1, 1))

        self.szCtrls.Add(self.cbTotalLength, (5, 0),
                         border=0,
                         flag=0,
                         span=(1, 1))
        self.szCtrls.Add(self.rbAudio, (6, 0),
                         border=32,
                         flag=wx.ALIGN_CENTER_VERTICAL | wx.LEFT,
                         span=(1, 1))
        self.szCtrls.Add(self.rbTimelapse, (7, 0),
                         border=32,
                         flag=wx.ALIGN_CENTER_VERTICAL | wx.LEFT,
                         span=(1, 1))
        self.szCtrls.Add(self.rbManual, (8, 0),
                         border=32,
                         flag=wx.ALIGN_CENTER_VERTICAL | wx.LEFT,
                         span=(1, 1))
        self.szCtrls.Add(self.timeCtrlTotalLength, (8, 1),
                         border=0,
                         flag=0,
                         span=(1, 1))

        self.szAudioCmds.Add(self.cmdBrowseAudio, border=2, flag=wx.BOTTOM)
        self.szAudioCmds.Add(self.cmdAudioPreview, border=2, flag=wx.BOTTOM)
        self.szAudioCmds.Add(self.cmdAudioMoveUp, border=2, flag=wx.BOTTOM)
        self.szAudioCmds.Add(self.cmdAudioMoveDown, border=2, flag=wx.BOTTOM)
        self.szAudioCmds.Add(self.cmdAudioDel, border=2, flag=wx.BOTTOM)

        self.szCmds.Add(self.cmdCancel, 0, border=0, flag=0)
        self.szCmds.AddSpacer(8)
        self.szCmds.Add(self.cmdOk, 0, border=0, flag=0)

        self.SetSizer(self.szMain)

    def _InitCtrls(self, prnt):
        self.pnlHdr = PnlDlgHeader(self)

        self.stProject = wx.StaticText(self,
                                       label=_(u'Project name:'),
                                       name=u'stProject')

        self.tcProject = wx.TextCtrl(self, name=u'tcProject', value=u'')

        self.staticLine2 = wx.StaticLine(self)

        self.stFolder = wx.StaticText(self,
                                      label=_(u'Folder:'),
                                      name=u'stFolder')

        self.tcFolder = wx.TextCtrl(self,
                                    name=u'tcFolder',
                                    style=wx.TE_READONLY,
                                    value=u'')

        self.cmdBrowseFolder = wx.BitmapButton(
            self,
            bitmap=wx.ArtProvider.GetBitmap('PFS_FOLDER_OPEN_16'),
            name=u'cmdBrowseFolder',
            style=wx.BU_AUTODRAW)
        self.cmdBrowseFolder.Bind(wx.EVT_BUTTON, self.OnCmdBrowseFolderButton)

        self.stAspect = wx.StaticText(self,
                                      label=_(u'Aspect ratio:'),
                                      name=u'stAspect')

        self.choiceAspect = wx.Choice(self, choices=[], name=u'choiceAspect')

        self.stAudio = wx.StaticText(self,
                                     label=_(u'Audio files:'),
                                     name=u'stAudio')

        self.lvAudio = wx.ListBox(self, style=wx.LB_SINGLE)
        self.lvAudio.Bind(wx.EVT_LISTBOX, self.OnControlStatusAudio)

        self.cmdBrowseAudio = wx.BitmapButton(
            self,
            bitmap=wx.ArtProvider.GetBitmap('PFS_MUSIC_16'),
            name=u'cmdBrowseAudio',
            style=wx.BU_AUTODRAW)
        self.cmdBrowseAudio.Bind(wx.EVT_BUTTON, self.OnCmdBrowseAudioButton)

        self.cmdAudioPreview = wx.BitmapButton(
            self,
            bitmap=wx.ArtProvider.GetBitmap('PFS_PLAY_PAUSE_16'),
            name=u'cmdAudioPreview',
            style=wx.BU_AUTODRAW)
        self.cmdAudioPreview.SetBitmapDisabled(
            wx.ArtProvider.GetBitmap('PFS_PLAY_PAUSE_D_16'))
        self.cmdAudioPreview.Bind(wx.EVT_BUTTON, self.OnCmdAudioPreviewButton)

        self.cmdAudioMoveUp = wx.BitmapButton(
            self,
            bitmap=wx.ArtProvider.GetBitmap('PFS_ARROW_UP_16'),
            name=u'cmdAudioMoveUp',
            style=wx.BU_AUTODRAW)
        self.cmdAudioMoveUp.SetBitmapDisabled(
            wx.ArtProvider.GetBitmap('PFS_ARROW_UP_D_16'))
        self.cmdAudioMoveUp.Bind(wx.EVT_BUTTON, self.OnCmdAudioMove)

        self.cmdAudioMoveDown = wx.BitmapButton(
            self,
            bitmap=wx.ArtProvider.GetBitmap('PFS_ARROW_DOWN_16'),
            name=u'cmdAudioMoveDown',
            style=wx.BU_AUTODRAW)
        self.cmdAudioMoveDown.SetBitmapDisabled(
            wx.ArtProvider.GetBitmap('PFS_ARROW_DOWN_D_16'))
        self.cmdAudioMoveDown.Bind(wx.EVT_BUTTON, self.OnCmdAudioMove)

        self.cmdAudioDel = wx.BitmapButton(
            self,
            bitmap=wx.ArtProvider.GetBitmap('PFS_REMOVE_16'),
            name=u'cmdAudioDel',
            style=wx.BU_AUTODRAW)
        self.cmdAudioDel.SetBitmapDisabled(
            wx.ArtProvider.GetBitmap('PFS_REMOVE_D_16'))
        self.cmdAudioDel.Bind(wx.EVT_BUTTON, self.OnCmdAudioDel)

        self.cbTotalLength = wx.CheckBox(self,
                                         label=_(u'Total length:'),
                                         name=u'cbTotalLength')
        self.cbTotalLength.SetValue(False)
        self.cbTotalLength.SetToolTip(
            _(u'Overrides the duration of single pictures and gives the project this total length.'
              ))
        self.cbTotalLength.Bind(wx.EVT_CHECKBOX,
                                self.OnControlStatusTotalLength)

        self.rbManual = wx.RadioButton(self,
                                       label=_(u'User defined:'),
                                       name=u'rbManual')
        self.rbManual.Bind(wx.EVT_RADIOBUTTON, self.OnControlStatusTotalLength)

        self.timeCtrlTotalLength = wx.lib.masked.timectrl.TimeCtrl(
            self,
            display_seconds=True,
            fmt24hr=True,
            name=u'timeCtrlTotalLength',
            oob_color=wx.YELLOW,
            style=0,
            useFixedWidthFont=True,
            value='12:00:00 AM')
        self.timeCtrlTotalLength.Enable(False)

        self.rbAudio = wx.RadioButton(self,
                                      label=_(u'Fit to audio files'),
                                      name=u'rbAudio')
        self.rbAudio.Bind(wx.EVT_RADIOBUTTON, self.OnControlStatusTotalLength)

        self.rbTimelapse = wx.RadioButton(self,
                                          label=_(u'Timelapse'),
                                          name=u'rbTimelapse')
        self.rbTimelapse.Bind(wx.EVT_RADIOBUTTON,
                              self.OnControlStatusTotalLength)

        self.staticLine = wx.StaticLine(self)

        self.staticLine1 = wx.StaticLine(self)

        self.cmdCancel = wx.Button(self,
                                   id=wx.ID_CANCEL,
                                   label=_(u'&Cancel'),
                                   name=u'cmdCancel')
        self.cmdCancel.Bind(wx.EVT_BUTTON,
                            self.OnCmdCancelButton,
                            id=wx.ID_CANCEL)

        self.cmdOk = wx.Button(self,
                               id=wx.ID_OK,
                               label=_(u'&Ok'),
                               name=u'cmdOk')
        self.cmdOk.Bind(wx.EVT_BUTTON, self.OnCmdOkButton, id=wx.ID_OK)

        self._InitSizers()

    def __init__(self, parent, project=None):
        wx.Dialog.__init__(self,
                           parent,
                           name=u'DlgProjectProps',
                           style=wx.DEFAULT_DIALOG_STYLE,
                           title=_(u'Project properties'))
        self.Bind(wx.EVT_CLOSE, self.OnDlgProjectPropsClose)

        self._InitCtrls(parent)

        self.SetSizeHints(700, 250)
        self.szCtrls.AddGrowableCol(1)

        self.pnlHdr.SetTitle(_(u'PhotoFilmStrip project'))
        self.pnlHdr.SetBitmap(
            wx.ArtProvider.GetBitmap('PFS_ICON_48', wx.ART_TOOLBAR, (32, 32)))

        self.choiceAspect.Append(Aspect.ASPECT_16_9)
        self.choiceAspect.Append(Aspect.ASPECT_4_3)
        self.choiceAspect.Append(Aspect.ASPECT_3_2)
        self.choiceAspect.Select(0)

        self.tcProject.SetMinSize(wx.Size(300, -1))
        self.tcFolder.SetMinSize(wx.Size(300, -1))
        self.choiceAspect.SetMinSize(wx.Size(300, -1))
        self.timeCtrlTotalLength.SetMinSize(wx.Size(300, -1))
        self.lvAudio.SetMinSize(wx.Size(300, -1))

        defTime = wx.DateTime.Now()
        defTime.SetHMS(0, 0, 30)
        minTime = wx.DateTime.Now()
        minTime.SetHMS(0, 0, 1)
        maxTime = wx.DateTime.Now()
        maxTime.SetHMS(1, 59, 59)
        self.timeCtrlTotalLength.SetValue(defTime)
        self.timeCtrlTotalLength.SetMin(minTime)
        self.timeCtrlTotalLength.SetMax(maxTime)
        self.timeCtrlTotalLength.SetLimited(True)

        self.mediaCtrl = None

        self.__project = project

        if project is None:
            projName = _(u"Unnamed PhotoFilmStrip")
            self.tcProject.SetValue(projName)
            self.tcProject.SelectAll()
            self.tcProject.SetFocus()

            projPath = Settings().GetProjectPath()
            if not projPath:
                projPath = os.path.join(wx.GetHomeDir(),
                                        _(u"My PhotoFilmStrips"))
                Settings().SetProjectPath(projPath)
            self.tcFolder.SetValue(projPath)

            self.cbTotalLength.SetValue(False)
            self.rbManual.SetValue(True)
        else:
            projName = os.path.splitext(os.path.basename(
                project.GetFilename()))[0]
            self.tcProject.SetValue(projName)
            self.tcProject.Enable(False)

            self.tcFolder.SetValue(os.path.dirname(project.GetFilename()))
            self.tcFolder.Enable(False)
            self.cmdBrowseFolder.Enable(False)

            self.choiceAspect.SetStringSelection(project.GetAspect())
            self.choiceAspect.Enable(False)

            pfsDur = project.GetDuration(calc=True)
            duration = project.GetDuration(calc=False)
            if project.GetTimelapse():
                self.cbTotalLength.SetValue(True)
                self.rbTimelapse.SetValue(True)
            elif duration is None:
                self.cbTotalLength.SetValue(False)
            elif duration <= 0:
                self.cbTotalLength.SetValue(True)
                self.rbAudio.SetValue(True)
            else:
                self.cbTotalLength.SetValue(True)
                self.rbManual.SetValue(True)
                pfsDur = duration

            pfsDur = int(round(pfsDur))

            dur = wx.DateTime.Now()
            dur.SetHMS(0, pfsDur // 60, pfsDur % 60)
            try:
                self.timeCtrlTotalLength.SetWxDateTime(dur)
            except ValueError:
                # duration is invalid if there are no photos
                pass

            for audioFile in project.GetAudioFiles():
                idx = self.lvAudio.Append(audioFile)
                self.lvAudio.Select(idx)

        self.__ControlStatusTotalLength()
        self.__ControlStatusAudio()

        self.Fit()
        self.CenterOnParent()
        self.SetFocus()

    def OnCmdBrowseFolderButton(self, event):
        dlg = wx.DirDialog(self,
                           _(u"Browse for folder"),
                           defaultPath=self.tcFolder.GetValue())
        if dlg.ShowModal() == wx.ID_OK:
            path = dlg.GetPath()
            if self.__ValidateOutDir(path):
                self.tcFolder.SetValue(path)
                Settings().SetProjectPath(path)
        dlg.Destroy()

    def OnControlStatusTotalLength(self, event):
        self.__ControlStatusTotalLength()
        event.Skip()

    def OnControlStatusAudio(self, event):
        self.__ControlStatusAudio()

    def OnCmdBrowseAudioButton(self, event):
        dlg = wx.FileDialog(self, _(u"Select music"),
                            Settings().GetAudioPath(), "",
                            _(u"Audio files") + " (*.*)|*.*",
                            wx.FD_OPEN | wx.FD_MULTIPLE)
        if dlg.ShowModal() == wx.ID_OK:
            path = dlg.GetPath()
            Settings().SetAudioPath(os.path.dirname(path))

            for path in dlg.GetPaths():
                self.lvAudio.Append(path)

        dlg.Destroy()

    def OnCmdAudioPreviewButton(self, event):
        selIdx = self.lvAudio.GetSelection()
        if selIdx == wx.NOT_FOUND:
            return

        filename = self.lvAudio.GetString(selIdx)
        if self.mediaCtrl and self.mediaCtrl.GetFilename() == filename:
            if self.mediaCtrl.IsPlaying():
                self.mediaCtrl.Stop()
            else:
                self.mediaCtrl.Play()
        else:
            self.__LoadAudioFile(filename)

    def OnCmdAudioMove(self, event):
        selIdx = self.lvAudio.GetSelection()
        if selIdx == wx.NOT_FOUND:
            return

        selAudio = self.lvAudio.GetString(selIdx)

        evtObj = event.GetEventObject()
        if evtObj is self.cmdAudioMoveUp:
            if selIdx > 0:
                prevAudio = self.lvAudio.GetString(selIdx - 1)

                self.lvAudio.SetString(selIdx, prevAudio)
                self.lvAudio.SetString(selIdx - 1, selAudio)
                self.lvAudio.SetSelection(selIdx - 1)
        elif evtObj is self.cmdAudioMoveDown:
            if selIdx < self.lvAudio.GetCount() - 1:
                nextAudio = self.lvAudio.GetString(selIdx + 1)

                self.lvAudio.SetString(selIdx, nextAudio)
                self.lvAudio.SetString(selIdx + 1, selAudio)
                self.lvAudio.SetSelection(selIdx + 1)

        self.__ControlStatusAudio()

    def OnCmdAudioDel(self, event):
        selIdx = self.lvAudio.GetSelection()
        if selIdx != wx.NOT_FOUND:
            self.lvAudio.Delete(selIdx)
        self.lvAudio.Select(min(selIdx, self.lvAudio.GetCount() - 1))

        self.__ControlStatusAudio()

    def OnDlgProjectPropsClose(self, event):
        self.__CloseMediaCtrl()
        event.Skip()

    def OnCmdCancelButton(self, event):
        self.__CloseMediaCtrl()
        event.Skip()

    def OnCmdOkButton(self, event):
        if self.__ValidateAudioFile() and self.__ValidateOutDir(
        ) and self.__ValidateProjName():
            event.Skip()

#    def __GetChoiceDataSelected(self, choice):
#        return choice.GetClientData(choice.GetSelection())
#
#    def __SetChoiceSelectionByData(self, choice, data):
#        for idx in range(choice.GetCount()):
#            if choice.GetClientData(idx) == data:
#                choice.Select(idx)
#                return

    def __ControlStatusTotalLength(self):
        active = self.cbTotalLength.GetValue()
        manual = self.rbManual.GetValue()

        self.rbAudio.Enable(active)
        self.rbManual.Enable(active)
        self.rbTimelapse.Enable(active)
        self.timeCtrlTotalLength.Enable(active and manual)

    def __ControlStatusAudio(self):
        selected = self.lvAudio.GetSelection()

        self.cmdAudioPreview.Enable(selected != wx.NOT_FOUND)
        self.cmdAudioDel.Enable(selected != wx.NOT_FOUND)
        self.cmdAudioMoveUp.Enable(selected > 0)
        self.cmdAudioMoveDown.Enable(selected < (self.lvAudio.GetCount() - 1))

    def __LoadAudioFile(self, path):
        self.__CloseMediaCtrl()

        if not os.path.exists(path):
            dlg = wx.MessageDialog(
                self,
                _(u"Audio file '%s' does not exist!") % path, _(u"Error"),
                wx.OK | wx.ICON_ERROR)
            dlg.ShowModal()
            dlg.Destroy()

        mediaCtrl = AudioPlayer(path)
        if mediaCtrl.IsOk():
            self.mediaCtrl = mediaCtrl
            self.mediaCtrl.Play()
        else:
            dlg = wx.MessageDialog(self, _(u"Audio file not supported!"),
                                   _(u"Error"), wx.OK | wx.ICON_ERROR)
            dlg.ShowModal()
            dlg.Destroy()

    def __ValidateAudioFile(self):
        for path in self.lvAudio.GetItems():
            if not os.path.exists(path):
                dlg = wx.MessageDialog(
                    self,
                    _(u"Audio file '%s' does not exist!") % path, _(u"Error"),
                    wx.OK | wx.ICON_ERROR)
                dlg.ShowModal()
                dlg.Destroy()
                return False
        return True

    def __CloseMediaCtrl(self):
        if self.mediaCtrl is not None:
            try:
                self.mediaCtrl.Close()
            except:
                pass
        self.mediaCtrl = None

    def __GetTotalLength(self):
        totalLength = None

        if self.cbTotalLength.GetValue():
            if self.rbManual.GetValue():
                totalLength = 0
                dateTime = self.timeCtrlTotalLength.GetValue(
                    as_wxDateTime=True)
                totalLength += dateTime.GetHour() * 3600
                totalLength += dateTime.GetMinute() * 60
                totalLength += dateTime.GetSecond()
            elif self.rbAudio.GetValue():
                totalLength = -1
            elif self.rbTimelapse.GetValue():
                totalLength = None

        return totalLength

    def __ValidateOutDir(self, path=None):
        if path is None:
            path = self.tcFolder.GetValue().strip()

        if not os.path.isdir(path):
            dlg = wx.MessageDialog(
                self,
                _(u"Folder does not exists! Do you want %s to create it?") %
                Constants.APP_NAME, _(u"Question"),
                wx.YES_NO | wx.ICON_QUESTION)
            resp = dlg.ShowModal()
            dlg.Destroy()
            if resp == wx.ID_YES:
                try:
                    os.makedirs(path)
                except Exception as err:
                    dlg = wx.MessageDialog(
                        self,
                        _(u"Cannot create folder: %s") % str(err), _(u"Error"),
                        wx.OK | wx.ICON_ERROR)
                    dlg.ShowModal()
                    dlg.Destroy()
                    return False
            else:
                return False
        else:
            if not IsPathWritable(path):
                dlg = wx.MessageDialog(self, _(u"Cannot write into folder!"),
                                       _(u"Error"), wx.OK | wx.ICON_ERROR)
                dlg.ShowModal()
                dlg.Destroy()
                return False

        return True

    def __ValidateProjName(self):
        projName = self.tcProject.GetValue().strip()
        projName = projName.strip(u".")
        projPath = os.path.join(self.tcFolder.GetValue().strip(), projName)
        if not projName:
            self.pnlHdr.SetErrorMessage(_(u"The project name must be filled."))
            return False
        elif not os.path.exists(projPath):
            try:
                os.makedirs(projPath)
            except Exception:
                self.pnlHdr.SetErrorMessage(
                    _(u"The project name contains invalid characters."))
                return False
            os.removedirs(projPath)
            return True
        else:
            self.pnlHdr.SetErrorMessage(u"")
            return True

    def __GetProjectPath(self):
        projName = self.tcProject.GetValue().strip()
        projName = projName.strip(u".")
        filepath = os.path.join(self.tcFolder.GetValue().strip(), projName,
                                "%s.pfs" % projName)
        return filepath

    def Destroy(self):
        self.__CloseMediaCtrl()
        wx.Dialog.Destroy(self)

    def GetProject(self):
        if self.__project is None:
            self.__project = Project(self.__GetProjectPath())
        self.__project.SetAudioFiles(self.lvAudio.GetItems())

        if self.cbTotalLength.GetValue() and self.rbTimelapse.GetValue():
            self.__project.SetTimelapse(True)
        else:
            self.__project.SetTimelapse(False)

        self.__project.SetDuration(self.__GetTotalLength())
        self.__project.SetAspect(self.choiceAspect.GetStringSelection())
        return self.__project