""" qtgui/saveDataFiles.py: CCP4MG Molecular Graphics Program Copyright (C) 2001-2008 University of York, CCLRC Copyright (C) 2009 University of York This library is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License version 3, modified in accordance with the provisions of the license to address the requirements of UK law. You should have received a copy of the modified GNU Lesser General Public License along with this library. If not, copies may be downloaded from http://www.ccp4.ac.uk/ccp4license.php This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. """ ''' This utility enables user to save multiple data files with the same tag added to all file names. Currently two modes.. append - save data to file with filename that has __. backup - overwrite current file after saving to file __. Alternative approaches that are not currently implemented: save all data files to one newly created directory or allowing user to specify file names individually. ''' from PyQt4 import QtCore,QtGui from global_definitions import * import os import MGSimpleDialog #------------------------------------------------------------------------- #------------------------------------------------------------------------- #------------------------------------------------------------------------- class saveDataFiles(MGSimpleDialog.MGSimpleDialog): #------------------------------------------------------------------------- #------------------------------------------------------------------------- #------------------------------------------------------------------------- initialise = { 'save_mode' : 'append', 'save_all' : 1, 'tag' : '' } supported_modes = ['append','backup'] #------------------------------------------------------------------------- def __init__(self,parent=None, application_tag='',title=''): #------------------------------------------------------------------------- MGSimpleDialog.MGSimpleDialog.__init__(self) if not title: title = 'Save files from '+application_tag+' application' self.saveFileDialog = None self.DataObj_changed = [] self.DataObj_unchanged = [] self.application_tag = application_tag self.setWindowTitle(title) layout = QtGui.QVBoxLayout() frame = QtGui.QGroupBox('Save data files',self) frame_layout = QtGui.QVBoxLayout() self.save_mode = QtGui.QButtonGroup(self) for item in [ ['append','with tag appended'], ['backup','overwrite file and backup to file with tag'] #['dir','all to sub-directory with tag name'], #['individual','each file specified individually'] ]: line = QtGui.QHBoxLayout() widget = QtGui.QRadioButton(item[1],self) setattr(self,item[0],widget) widget.setObjectName(item[0]) self.save_mode.addButton(widget) line.addWidget(widget) frame_layout.addLayout(line) self.connect(self.save_mode,QtCore.SIGNAL('buttonClicked(int)'),self.reset_tag) frame.setLayout(frame_layout) layout.addWidget(frame) line = QtGui.QHBoxLayout() self.save_all = QtGui.QCheckBox('Save all files even if unchanged',self) line.addWidget(self.save_all) layout.addLayout(line) line = QtGui.QHBoxLayout() line.addWidget(QtGui.QLabel('Add tag to file name',self)) self.tag = QtGui.QLineEdit(self) line.addWidget(self.tag) layout.addLayout(line) button_box = QtGui.QDialogButtonBox(self) button_box.setOrientation(QtCore.Qt.Horizontal) for label,role,slot in [['Apply',QtGui.QDialogButtonBox.ActionRole,self.Apply], ['Close',QtGui.QDialogButtonBox.RejectRole,self.Close]]: button = button_box.addButton(label,role) button.setAutoDefault(0) self.connect(button,QtCore.SIGNAL('clicked()'),slot) layout.addWidget(button_box) self.setLayout(layout) self.setParams(saveDataFiles.initialise) #------------------------------------------------------------------------ def setDataObj(self,DataObj_changed=[],DataObj_unchanged=[]): #------------------------------------------------------------------------ #print 'saveDataFiles.setDataObj',DataObj_changed,DataObj_unchanged self.DataObj_changed = [] self.DataObj_changed.extend(DataObj_changed) self.DataObj_unchanged = [] self.DataObj_unchanged.extend(DataObj_unchanged) self.reset_tag() #------------------------------------------------------------------------ def setParams(self,params): #------------------------------------------------------------------------ if params.has_key('save_mode'): for item in saveDataFiles.supported_modes: getattr(self,item).setChecked(int(item == params['save_mode'])) if params.has_key('tag'): self.tag.setText(params['tag']) if params.has_key('save_all'): self.save_all.setChecked(params['save_all']) #------------------------------------------------------------------------ def getParams(self): #------------------------------------------------------------------------ params = { 'save_mode' : 'append' } for item in saveDataFiles.supported_modes: if getattr(self,item).isChecked(): params['save_mode'] = item params['tag'] = str(self.tag.text()) params['save_all'] = int(self.save_all.isChecked()) return params #------------------------------------------------------------------------ def Apply(self): #------------------------------------------------------------------------ tag = str(self.tag.text()) to_save_list = [] to_save_list.extend(self.DataObj_changed) if self.save_all.isChecked(): to_save_list.extend(self.DataObj_unchanged) save_mode = str(self.save_mode.checkedButton().objectName()) if save_mode == 'dir': pass else: self.save_multi(save_mode=save_mode,tag=tag,to_save_list=to_save_list) DISPLAYTABLE().updateDataObjLabels() self.emit(QtCore.SIGNAL('saved_files')) self.Close() #------------------------------------------------------------------------ def save_multi(self,save_mode='append',to_save_list=[],tag='', project_dir='' ,**keywords): #------------------------------------------------------------------------ error_report = [] saved_list = [] ''' if save_mode == 'dir': # NOT tested save_dir = os.path.join(project_dir,tag) #print "save_dir",save_dir if not os.path.exists(save_dir): try: os.mkdir(save_dir) except: return [1,'error creating directory '+save_dir] for dobj_name in to_save_list: dobj = data(dobj_name) if dobj: save_file = os.path.join(save_dir,os.path.basename(dobj.getFilename())) #print "save_file",save_file rv = dobj.save_file(filename=save_file) if rv: error_report.append('Error saving file: '+save_file) else: saved_list.append(dobj_name) ''' for dobj_name in to_save_list: dobj = data(dobj_name) if dobj: filename = dobj.getFilename() save_file = self.new_filename(filename,tag) if save_mode == 'backup': try: os.rename(filename,save_file) except: error_report.append('Error moving current file to: '+save_file) else: rv = dobj.save_file(filename=filename) if rv: error_report.append('Error saving file: '+filename) else: saved_list.append(dobj_name) elif save_mode == 'append': rv = dobj.save_file(filename=save_file) if rv: error_report.append('Error saving file '+save_file) else: saved_list.append(dobj_name) ''' elif save_mode == 'individual': # NOT tested self.handle_save_individual(to_save_list=to_save_list,application_tag=application_tag) for dobj_name in saved_list: widget = DISPLAYTABLE().getDataObj(dobj_name) if widget: widget.updateLabel() ''' #print 'save_multi',saved_list if error_report: error_text = error_report[0] for item in error_report[1:]: error_text = error_text + '\n' + item QtGui.QMessageBox.warning(None,self.windowTitle(),error_text) #------------------------------------------------------------------------- def new_filename(self,filename,tag): #------------------------------------------------------------------------- tag_pos,tag_len,version = self.extract_tag(filename,self.application_tag) if tag_pos>0: # There is already a tag in the filename that needs removing filename0 = filename[0:tag_pos]+filename[tag_pos+tag_len:] #print 'new_filename tag removed',filename0 else: filename0 = filename splitfile = os.path.splitext(filename0) base = splitfile[0].rstrip('-').rstrip('_') if ['_','-'].count(tag[0]): save_file = base+tag+splitfile[1] else: save_file = base+'_'+tag+splitfile[1] return save_file #------------------------------------------------------------------------- def handle_save_individual(self,to_save_list=[],application_tag='',**keywords): #------------------------------------------------------------------------- if not self.saveFileDialog: import mgWidgets self.saveFileDialog = mgWidgets.MGSaveFileDialog(self,'Save file', [ [ "Coordinate file (*.pdb,*.mmcif)", 'coordinate']]) for dobj_name in to_save_list: dobj = data(dobj_name) if dobj: filename = dobj.getFilename() self.saveFileDialog.setDefaultFileName(filename) self.saveFileDialog.show() #-------------------------------------------------------------------------- def reset_tag(self): #-------------------------------------------------------------------------- if self.save_mode.checkedButton(): save_mode =str(self.save_mode.checkedButton().objectName()) else: save_mode = 'append' save_all = int(self.save_all.isChecked()) tag = self.get_best_tag(save_all=save_all,save_mode=save_mode) self.tag.setText(tag) #-------------------------------------------------------------------------- def get_best_tag(self,save_all=1,save_mode='append'): #-------------------------------------------------------------------------- DataObj_list = [] DataObj_list.extend(self.DataObj_changed) if save_all: DataObj_list.extend(self.DataObj_unchanged) #print 'saveDataFiles.get_best_tag',DataObj_list tested_dir = [] next_tag = 1 for dobj_name in DataObj_list: dobj = data(dobj_name) if dobj: fullpath = os.path.abspath(dobj.getFilename()) dirn = os.path.dirname(fullpath) if not tested_dir.count(dirn): tested_dir.append(dirn) next_tag = max(next_tag,self.next_version_tag(dirn,save_mode,self.application_tag)) return self.application_tag+'_'+str(next_tag) #-------------------------------------------------------------------------- def next_version_tag(self,project_dir='',save_mode='dir',application_tag=''): #-------------------------------------------------------------------------- import glob,utils maxtag = 0 if save_mode == 'dir': dlist = glob.glob(os.path.join(project_dir,application_tag+'*')) #print "dlist",dlist for d in dlist: if os.path.isdir(d): p = d.rfind(application_tag) if p>0: maxtag = max(maxtag,utils.safeInt(d[p+len(application_tag):],-1)) else: if ['backup','append'].count(save_mode): dlist = glob.glob(os.path.join(project_dir,'*_'+application_tag+'*.*')) #print "next_version_tag dlist",application_tag,dlist for d in dlist: p,q,iv = self.extract_tag(d,self.application_tag) if p>=0: maxtag = max(maxtag,iv) return maxtag+1 #-------------------------------------------------------------------------- def extract_tag(self,filename,application_tag): #-------------------------------------------------------------------------- import utils # Find the application tag and version number in filename # Return start and length of application_tag+version_tag and the version number d = os.path.basename(filename) p = d.rfind(application_tag) if p<0: return [-1,-1,0] q = d.find('.',p+len(application_tag)) if q<0: return [-1,-1,0] vtag=d[p+len(application_tag):q].strip('_').strip('-') iv = utils.safeInt(vtag,-1) if ['_','-'].count(filename[p-1]): p = p-1 tag_len = q-p #print 'extract_tag',filename, (p+len(os.path.dirname(filename))+1,tag_len,iv) return (p+len(os.path.dirname(filename))+1,tag_len,iv)