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()))
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()
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()
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
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
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
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()
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")
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