コード例 #1
0
ファイル: DlgNewProject.py プロジェクト: jensgoe/PFS
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
コード例 #2
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