# Copyright (c) 2004-5 Marek Hnilica. All rights reserved. # This module contains 'Rename Directory' dialog and functionality. # Distributed under GPL version 2, or (at your option) later import wx,os,string,sys,mboxUpper,mboxFileUtils,shutil,ComboBoxWithHistory,utils,AllTag def PanicExit(parent,text='Error',label='Error'): ErrMsg=wx.MessageDialog(parent,text,label,wx.ICON_WARNING) ErrMsg.ShowModal() ErrMsg.Destroy() parent.Close() class RenameDialog(wx.Dialog): def __init__(self,parent,filename,choices=[],directory='',oklength=1): wx.Dialog.__init__(self,parent,-1,'Rename Directory') self.VeryFirstDir=directory self.FileList=os.listdir(self.VeryFirstDir) self.PrevDirList=[] for self.Element in self.FileList: self.PrevDirList.append(os.path.abspath(self.Element)) self.filename=filename self.mbox=parent MaskSizer=wx.StaticBoxSizer(wx.StaticBox(self,-1,'Controls:')) self.RenameMask=ComboBoxWithHistory.wxComboBoxWithHistory(self,wx.NewId(),choices=choices) self.RenameButton=wx.Button(self,wx.NewId(),'&Rename') self.CancelButton=wx.Button(self,wx.NewId(),'&Cancel') MaskSizer.AddMany([ (self.RenameMask,1), ((20,0),0), (self.RenameButton,0), ((5,0),0), (self.CancelButton,0), ]) TextSizer=wx.BoxSizer(wx.HORIZONTAL) TextPossSizer=wx.StaticBoxSizer(wx.StaticBox(self,-1,'File mask possibilities:')) TextPossSizer.AddMany([ (wx.StaticText(self,-1,'%a = Artist\n%y = Year\n%c = Comment'),0), ((5,0),0), (wx.StaticText(self,-1,'%l = Album\n%g = Genre\n%b = Bitrate'),0), ]) TextSizer.Add(TextPossSizer,0) self.ReplaceSpaces=wx.CheckBox(self,wx.NewId(),"Replace spaces with underscores",style=wx.NO_BORDER) self.ModifyStatus=wx.CheckBox(self,wx.NewId(),"Enable case adjustments",style=wx.NO_BORDER) wx.EVT_CHECKBOX(self,self.ModifyStatus.GetId(),self.ModifyEnable) self.Modify=wx.RadioBox(self,wx.NewId(),"Case:",wx.Point(-1,-1),wx.Size(-1,-1),['lower','UPPER','Capitalize first word','Capitalize First Letter'],2) self.Modify.Enable(0) ModifSizer=wx.StaticBoxSizer(wx.StaticBox(self,-1,'Dir name modifications:'),wx.VERTICAL) ModifSizer.AddMany([ (self.ReplaceSpaces,0), (self.ModifyStatus,0), (self.Modify,0), ]) TextPossSizer.SetMinSize(ModifSizer.GetMinSize()) TextSizer.AddMany([ ((5,5),0), (ModifSizer,0) ]) MainSizer=wx.FlexGridSizer(5,1,10,5) PrevSizer=wx.StaticBoxSizer(wx.StaticBox(self,-1,'Preview:')) self.TempText=wx.StaticText(self,-1,'') PrevSizer.Add(self.TempText,0) MainSizer.AddMany([ (PrevSizer,0), (MaskSizer,0), (TextSizer,0), ((0,10),0), ]) self.TextInMask='' wx.EVT_TEXT(self,self.RenameMask.GetId(), self.RenameMaskEntered) wx.EVT_BUTTON(self,self.RenameButton.GetId(),self.DoRename) wx.EVT_BUTTON(self,self.CancelButton.GetId(),self.Cancel) self.SetSizer(MainSizer) self.SetAutoLayout(True) MainSizer.Fit(self) PrevSizer.SetMinSize((self.GetSize()[0],-1)) MaskSizer.SetMinSize((self.GetSize()[0],-1)) self.CenterOnParent() self.Show() if not oklength: self.WrongSelection=wx.MessageDialog(self,'Wrong files selected, you have to select only one file in tracklist.\nUsing first file for tag info','Error',wx.ICON_INFORMATION) self.WrongSelection.ShowModal() self.WrongSelection.Destroy() def ModifyEnable(self,event): self.Modify.Enable(event.Checked()) def Cancel(self,event): self.Close() self.RetVal='' return def FutName(self,text,var): self.FutureName=string.replace(self.FutureName,text,var) def StripList(self,List): while '' in List: List.remove('') return List def DoRename(self,junk): self.RenameMask.AddToHistory(self.RenameMask.GetValue()) self.MakeVariables() self.FutureName=self.TextInMask self.FutName('',self.NameArtist) self.FutName('',self.NameAlbum) self.FutName('',self.NameYear) self.FutName('',self.NameGenre) self.FutName('',self.NameComment) self.FutName('',`self.NameBitrate`) if self.ReplaceSpaces.GetValue(): self.FutureName=string.replace(self.FutureName,' ','_') self.TempDirName=self.StripList(string.split(self.VeryFirstDir,'/')) del self.TempDirName[len(self.TempDirName)-1] try: if self.FutureName[0]=='/': self.FutureDirSplit=self.StripList(string.split(self.FutureName,'/')) self.FutureDir=self.FutureName else: self.FutureDirSplit=self.TempDirName+self.StripList(string.split(self.FutureName,'/')) self.FutureDir='/'+string.join(self.FutureDirSplit,'/') except IndexError: self.FutureDirSplit=self.TempDirName+self.StripList(string.split(self.FutureName,'/')) self.FutureDir='/'+string.join(self.FutureDirSplit,'/') self.AlreadyAdded='' self.Broken=0 for self.TempDir in self.FutureDirSplit: self.AlreadyAdded+='/'+self.TempDir if os.path.exists(self.AlreadyAdded): if not os.path.isdir(self.AlreadyAdded): self.Broken=1 break continue else: try: os.mkdir(self.AlreadyAdded) except OSError: if self.AlreadyAdded[-1:]==' ': print '*** Failed to create directory "%s", \n\ttrying to strip trailing whitespaces and create dir again...'%self.AlreadyAdded, # Could have failed because some filesystems doesn't allow whitespace character as last character in dirname self.AlreadyAdded=string.rstrip(self.AlreadyAdded) try: os.mkdir(self.AlreadyAdded) print 'succes' except OSError: print 'failed' self.ErrMsg=wx.MessageDialog(self,'Unable to create directory "%s"\n\nPlease check whether you have appropriate permissions.'%self.AlreadyAdded,'Error while renaming',wx.ICON_INFORMATION) self.ErrMsg.ShowModal() self.ErrMsg.Destroy() self.Close() self.RetVal='bye' return if self.Broken: self.FutureName=self.VeryFirstDir self.WarnMessage=wx.MessageDialog(self,'Unable to create directory %s\nPath already exists and is not a directory.'%self.ParDir,'Error message',wx.ICON_WARNING) self.WarnMessage.ShowModal() self.WarnMessage.Destroy() self.Close() self.RetVal='bye' return for self.file in self.PrevDirList: self.Errors=0 try: if not hasattr(self,'MakeCopy'): os.rename(self.file,self.AlreadyAdded+'/'+os.path.basename(self.file)) except OSError,e: if string.find(str(e),'Errno 18')!=-1: if not hasattr(self,'MakeCopy'): ErrMsg=wx.MessageDialog(self,'Unable to rename directory:\nDestination is in other partition.\nDo you want to move that files instead?','Unable to rename',wx.ICON_INFORMATION|wx.OK|wx.CANCEL) if ErrMsg.ShowModal()==wx.ID_OK: self.MakeCopy=1 else: self.MakeCopy=0 ErrMsg.Destroy() break else: ErrMsg=wx.MessageDialog(self,'Unable to process directory "%s"\n\nPlease check whether you have appropriate permissions.'%self.AlreadyAdded,'Error while renaming',wx.ICON_INFORMATION) ErrMsg.ShowModal() ErrMsg.Destroy() try: os.rmdir(self.FutureName) except: pass self.Close() self.RetVal='bye' return if hasattr(self,'MakeCopy'): if self.MakeCopy: try: status=0 ListOfFiles=os.listdir(os.path.split(self.file)[0]) for file in ListOfFiles: if os.path.isdir(file): utils.GeneralError(self,label='Unable to process',text='Directory contains one or more subdirectories.\nmBox is not able to cope with it, you will have to move your files manually.') return if mboxFileUtils.CopyTree(os.path.split(self.file)[0],self.FutureName)==1: raise OSError,'Cannot copy' status=1 shutil.rmtree(os.path.split(self.file)[0]) except (shutil.Error,OSError),e: if status==0: ErrMsg=wx.MessageDialog(self,'Moving failed - cannot copy source directory-tree','Error!',wx.ICON_INFORMATION|wx.OK) elif status==1: ErrMsg=wx.MessageDialog(self,'Moving failed - cannot delete source directory-tree','Error!',wx.ICON_INFORMATION|wx.OK) ErrMsg.ShowModal() ErrMsg.Destroy() self.RetVal='' self.Close() return try: os.rmdir(self.VeryFirstDir) except OSError: pass self.Close() self.FutureName=self.AlreadyAdded self.RetVal='' def RenameMaskEntered(self,event): if not hasattr(self,'TagX'): self.TagX,self.TagY=self.TempText.GetPosition() self.TextInMask=self.ReplacePercents(self.RenameMask.GetValue()) try: self.MaskText.Destroy() except: pass self.MaskText=wx.StaticText(self,-1,self.TextInMask,pos=(self.TagX,self.TagY)) def ModifyCase(self,name): if self.ModifyStatus.GetValue(): if self.Modify.GetStringSelection()=='lower': name=string.lower(name) elif self.Modify.GetStringSelection()=='UPPER': name=string.upper(name) elif self.Modify.GetStringSelection()=='Capitalize first word': name=string.capitalize(name) elif self.Modify.GetStringSelection()=='Capitalize First Letter': name=mboxUpper.BetterCapword(name) return name def MakeVariables(self): self.infofile=AllTag.Tag(self.filename) self.NameArtist=self.ModifyCase(self.infofile.ARTIST) self.NameAlbum=self.ModifyCase(self.infofile.ALBUM) self.NameYear=self.ModifyCase(self.infofile.YEAR) self.NameGenre=self.ModifyCase(self.infofile.GENRE) self.NameComment=self.ModifyCase(self.infofile.COMMENT) self.NameBitrate=self.infofile.BITRATE def ReplacePercents(self,text): text=string.replace(text,'%a','') text=string.replace(text,'%l','') text=string.replace(text,'%y','') text=string.replace(text,'%g','') text=string.replace(text,'%c','') text=string.replace(text,'%b','') return text