def updateTable(self, table, args): model = QStandardItemModel(len(args), 2) model.setHorizontalHeaderLabels(["Name", "Value", "Type"]) indexitem = 0 for name, val in args.items(): si = QStandardItem(name) si.setEditable(False) model.setItem(indexitem, 0, si) si = QStandardItem(repr(val)) si.setEditable(False) model.setItem(indexitem, 1, si) try: si = QStandardItem(str(val.__class__.__name__)) except: si = QStandardItem(str(type(val).__name__)) si.setEditable(False) model.setItem(indexitem, 2, si) indexitem += 1 table.setModel(model) table.model = model
class AbstractSimulation: def __init__(self, lpywidget, index = 0, fname = None): self.lpywidget = lpywidget self.index = index self._fname = fname self._tmpfname = None self.textedition = False self._edited = False self._oldedited = False self.code = defaultcode self.textdocument = None self.cursor = None self.optionModel = None self.optionDelegate = None self.readonly = False self._oldreadonly = False self.modulemonitor = pm.ModuleMonitor() def tabbar(self): return self.lpywidget.documentNames def getFname(self) : return self._fname def setFname(self,value) : self._fname = value self.tabbar().setTabText(self.index,self.getShortName()) fname = property(getFname,setFname) def isEdited(self): return self._edited def setEdited(self,value): self._edited = value self.lpywidget.printTitle() self.updateTabName() edited = property(isEdited,setEdited) def textEdited(self): self.textedition = True self._edited = True self.lpywidget.printTitle() self.updateTabName() def isTextEdited(self): r = self.textedition self.textedition = False self.lpywidget.printTitle() self.updateTabName() return r def isCurrent(self): return self.index == self.lpywidget.currentSimulationId def makeCurrent(self): self.lpywidget.changeDocument(self.index) def isDefault(self): if self.isCurrent(): self.saveState() if not self.fname is None : return False if self.code != defaultcode : return False if self.textedition == True : return False if self._edited == True: return False for i in self.desc_items.values(): if len(i) > 0: return False ini = self.getInitialisationCode() if len(ini) > 0: return False return True def getShortName(self): if self._fname is None : return 'New' else : return os.path.splitext(os.path.basename(self.fname))[0] def getBaseName(self): if self._fname is None : return 'New' else : return os.path.basename(self.fname) def getFileName(self): return self._fname def getTabName(self): t = '' #if self.textedition: # t += '*' if self.fname is None: t += 'New' else: t += os.path.splitext(os.path.basename(self.fname))[0] #if self._edited: # t += '*' return t def generateIcon(self): from . import svnmanip if self.readonly is True: pixmap = QPixmap(":/images/icons/lock.png") elif self._edited: pixmap = QPixmap(":/images/icons/codefile-red.png") else: pixmap = QPixmap(":/images/icons/codefile.png") if not self.readonly and not self.fname is None and svnmanip.hasSvnSupport() : if svnmanip.isSvnFile(self.fname): status = svnmanip.svnFileTextStatus(self.fname) self.svnstatus = status if status == svnmanip.modified: pixmap2 = QPixmap(":/images/icons/svn-modified.png") elif status == svnmanip.normal: pixmap2 = QPixmap(":/images/icons/svn-normal.png") elif status == svnmanip.conflicted: pixmap2 = QPixmap(":/images/icons/svn-conflict.png") elif status == svnmanip.added: pixmap2 = QPixmap(":/images/icons/svn-add.png") else: pixmap2 = None if not pixmap2 is None: painter = QPainter(pixmap); painter.drawPixmap(pixmap.width()-pixmap2.width(),pixmap.height()-pixmap2.height(),pixmap2) painter.end() icon = QIcon() icon.addPixmap(pixmap.scaledToHeight(32),QIcon.Normal,QIcon.Off) return icon def registerTab(self): #self.tabbar().insertTab(self.index, self.getTabName()) self.tabbar().insertTab(self.index,self.generateIcon(),self.getTabName()) pass def updateTabName(self, force = False): if self._oldedited != self._edited or self._oldreadonly != self.readonly: self._oldedited = self._edited self._oldreadonly = self.readonly self.tabbar().setTabIcon(self.index,self.generateIcon()) self.tabbar().setTabText(self.index,self.getTabName()) def getBackupName(self): if self.fname: return os.path.join(os.path.dirname(self.fname),'#'+os.path.basename(self.fname)+'#') else: if not self._tmpfname: self._tmpfname = getNewTmpLpyFile() return self._tmpfname def restoreState(self): self.lpywidget.textEditionWatch = False te, tf = self.textedition, self._edited self.lpywidget.codeeditor.restoreSimuState(self) if self.optionModel is None: self.initializeParametersTable() self.lpywidget.parametersTable.setModel(self.optionModel) self.lpywidget.parametersTable.setItemDelegateForColumn(1,self.optionDelegate) self.textedition, self._edited = te, tf for key,editor in self.lpywidget.desc_items.items(): editor.setText(self.desc_items[key]) self.lpywidget.setTimeStep(self.lsystem.context().animation_timestep) self.lpywidget.materialed.setTurtle(self.lsystem.context().turtle) #self.lpywidget.functionDock.setFunctions(self.functions) #self.lpywidget.curveDock.setCurves(self.curves) self.lpywidget.setObjectPanelNb(len(self.visualparameters)) for panel,data in zip(self.lpywidget.getObjectPanels(),self.visualparameters): panelinfo,objects = data panel.setInfo(panelinfo) panel.setObjects(objects) self.lpywidget.scalarEditor.setScalars(self.scalars) if not self.lpywidget.interpreter is None: self.lpywidget.interpreter.locals['lstring'] = self.tree self.lpywidget.interpreter.locals['lsystem'] = self.lsystem self.lpywidget.printTitle() self.lpywidget.setTimeStep(self.lsystem.context().animation_timestep) if self.tabbar().currentIndex() != self.index: self.tabbar().setCurrentIndex(self.index) self.lpywidget.textEditionWatch = True if not self.fname is None: os.chdir(os.path.dirname(self.fname)) self.lpywidget.actionAutoRun.setChecked(self.autorun) self.updateReadOnly() #if not self.lsystem.isCurrent() : self.lsystem.makeCurrent() def saveState(self): #if self.lsystem.isCurrent() :self.lsystem.done() self.lpywidget.codeeditor.saveSimuState(self) for key,editor in self.lpywidget.desc_items.items(): if type(editor) == QLineEdit: self.desc_items[key] = editor.text() else: self.desc_items[key] = editor.toPlainText().encode('iso-8859-1','replace').decode('iso-8859-1') #self.functions = self.lpywidget.functionpanel.getFunctions() #self.curves = self.lpywidget.curvepanel.getCurves() self.visualparameters = [(panel.getInfo(),panel.getObjects()) for panel in self.lpywidget.getObjectPanels()] self.scalars = self.lpywidget.scalarEditor.getScalars() def initializeParametersTable(self): self.optionModel = QStandardItemModel(0, 1) self.optionModel.setHorizontalHeaderLabels(["Parameter", "Value" ]) options = self.lsystem.context().options self.optionDelegate = oed.OptionEditorDelegate() category = None categoryItem = None indexitem = 0 for i in range(len(options)): option = options[i] if option.category != category: category = option.category sc = QStandardItem(category) sc.setEditable(False) sc.setBackground(QBrush(QColor(172,168,153))) sc.setForeground(QBrush(QColor(255,255,255))) qf = QFont() qf.setBold(True) sc.setFont(qf) self.optionModel.setItem(indexitem, 0, sc) sc = QStandardItem() sc.setEditable(False) sc.setBackground(QBrush(QColor(172,168,153))) sc.setForeground(QBrush(QColor(255,255,255))) self.optionModel.setItem(indexitem, 1, sc) indexitem += 1 si = QStandardItem(option.name) si.setToolTip(option.comment) si.setEditable(False) self.optionModel.setItem(indexitem, 0, si) si = QStandardItem(option.currentValue()) si.option = option self.optionModel.setItem(indexitem, 1, si) indexitem += 1 self.optionModel.itemChanged.connect(self.textEdited) # QObject.connect(self.optionModel,SIGNAL('itemChanged(QStandardItem*)'),self.textEdited) def close(self): if self._edited: if not self.isCurrent(): self.makeCurrent() answer = QMessageBox.warning(self.lpywidget,self.getShortName(),"Do you want to save this document ?", QMessageBox.Save | QMessageBox.Discard | QMessageBox.Cancel, QMessageBox.Save) if answer == QMessageBox.Save: self.save() elif answer == QMessageBox.Cancel: return False elif answer == QMessageBox.Discard: bckupname = self.getBackupName() if bckupname and os.path.exists(bckupname): os.remove(bckupname) return True def save(self): if self.fname and not self.readonly: if self.isCurrent(): self.saveState() bckupname = self.getBackupName() if bckupname and os.path.exists(bckupname): os.remove(bckupname) if os.path.exists(self.fname) and self.lpywidget.fileBackupEnabled : try: shutil.copy(self.fname,self.fname+'~') except Exception as e: print('Cannot create backup file',repr(self.fname+'~')) print(e) self.saveToFile(self.fname) self.mtime = os.stat(self.fname).st_mtime self.lpywidget.statusBar().showMessage("Save file '"+self.fname+"'",2000) self.lpywidget.appendInHistory(self.fname) self.lsystem.filename = self.getStrFname() self.setEdited(False) self.updateReadOnly() else: self.saveas() def saveas(self): bckupname = self.getBackupName() qfname, mfilter = QFileDialog.getSaveFileName(self.lpywidget,"Save L-Py file",self.fname if self.fname else '.',"L-Py Files (*.lpy);;All Files (*.*)") if qfname : fname = str(qfname) if not os.path.exists(fname): self.readonly = False else : self.readonly = (not os.access(fname, os.W_OK)) self.fname = fname os.chdir(os.path.dirname(fname)) if not self.readonly and bckupname and os.path.exists(bckupname): os.remove(bckupname) self.save() def removeReadOnly(self): if not os.access(self.fname, os.W_OK): import stat st = os.stat(self.fname)[0] os.chmod(self.fname,st | stat.S_IWRITE) self.readonly = not os.access(self.fname, os.W_OK) self.updateTabName() self.updateReadOnly() def setReadOnly(self): if os.access(self.fname, os.W_OK): import stat st = os.stat(self.fname)[0] os.chmod(self.fname,st ^ stat.S_IWRITE) self.readonly = not os.access(self.fname, os.W_OK) self.updateTabName() self.updateReadOnly() def updateReadOnly(self): self.lpywidget.codeeditor.setReadOnly(self.readonly) self.lpywidget.materialed.setEnabled(not self.readonly) self.lpywidget.parametersTable.setEnabled(not self.readonly) self.lpywidget.scalarEditor.setEnabled(not self.readonly) self.lpywidget.animtimeSpinBox.setEnabled(not self.readonly) self.lpywidget.profileView.setEnabled(not self.readonly) self.lpywidget.descriptionEdit.setEnabled(not self.readonly) self.lpywidget.referenceEdit.setEnabled(not self.readonly) self.lpywidget.authorsEdit.setEnabled(not self.readonly) self.lpywidget.intitutesEdit.setEnabled(not self.readonly) self.lpywidget.copyrightEdit.setEnabled(not self.readonly) self.lpywidget.copyrightEdit.setEnabled(not self.readonly) for panel in self.lpywidget.getObjectPanels(): panel.setEnabled(not self.readonly) def saveToFile(self,fname): f = open(fname,'w') f.write(self.code) initcode = self.getInitialisationCode() if len(initcode) > 0 : if self.code[-1] != '\n': f.write('\n') f.write(initcode) f.close() def getStrFname(self): return self.fname.encode('iso-8859-1','replace').decode('iso-8859-1') def open(self,fname): self.setFname(fname) assert self._fname == fname recovery = False readname = self.fname bckupname = self.getBackupName() if bckupname and os.path.exists(bckupname): answer = QMessageBox.warning(self.lpywidget,"Recovery mode","A backup file '"+os.path.basename(bckupname)+"' exists. Do you want to recover ?",QMessageBox.Ok,QMessageBox.Discard) if answer == QMessageBox.Ok: recovery = True readname = bckupname elif answer == QMessageBox.Discard: os.remove(bckupname) os.chdir(os.path.dirname(self.fname)) code = open(readname,'rU').read() self.readonly = (not os.access(fname, os.W_OK)) self.textedition = recovery self.setEdited(recovery) self.opencode(code) self.mtime = os.stat(self.fname).st_mtime self.updateReadOnly() def importtmpfile(self,fname): self.textedition = True self.setEdited(True) try: lpycode = open(fname,'rU').read() self.opencode(lpycode) self._tmpfname = fname except: exc_info = sys.exc_info() traceback.print_exception(*exc_info) def reload(self): if self.fname: self.open(self.fname) def opencode(self,txt): pass def pre_run(self,task): pass def run(self, task): pass def post_run(self,task): pass def animate(self,task): pass def pre_animate(self,task): pass def post_animate(self,task): pass def pre_step(self,task): pass def step(self,task): pass def post_step(self,task): pass def iterate(self,task,n = None): pass def debug(self): pass def rewind(self): pass def stepInterpretation(self,task): pass def pre_stepInterpretation(self,task): pass def post_stepInterpretation(self,task): pass def profile(self,task): pass def pre_profile(self,task): pass def post_profile(self,task): pass def clear(self): pass def cancel(self): pass def cleanup(self): pass def monitorfile(self): if not hasattr(self,'monitoring'): self.monitoring = True if not self.fname is None: if not os.path.exists(self.fname): answer = QMessageBox.warning(self.lpywidget,"Removed file","File '"+os.path.basename(self.fname)+"' do not exists anymore. Do you want to keep it in editor ?",QMessageBox.Yes,QMessageBox.No) if answer == QMessageBox.No: self.lpywidget.closeDocument(self.index) elif os.stat(self.fname).st_mtime > self.mtime : answer = QMessageBox.warning(self.lpywidget,"File has changed","File '"+os.path.basename(self.fname)+"' has changed on disk. Do you want to reload it ?",QMessageBox.Yes,QMessageBox.No) if answer == QMessageBox.Yes: self.reload() else: self.mtime = os.stat(self.fname).st_mtime +1 self.updateSvnStatus() del self.monitoring def updateSvnStatus(self): from . import svnmanip if svnmanip.hasSvnSupport(): if (not hasattr(self,'svnstatus') and svnmanip.isSvnFile(self.fname)) or (hasattr(self,'svnstatus') and svnmanip.svnFileTextStatus(self.fname) != self.svnstatus): self.updateTabName(force=True) def svnUpdate(self): from . import svnmanip hasupdated = svnmanip.svnUpdate(self.fname,self.lpywidget) if hasupdated: self.reload() self.updateSvnStatus() def svnIsUpToDate(self): from . import svnmanip svnmanip.svnIsUpToDate(self.fname,self.lpywidget) self.updateSvnStatus() def svnAdd(self): from . import svnmanip svnmanip.svnFileAdd(self.fname) self.updateSvnStatus() def svnRevert(self): from . import svnmanip svnmanip.svnFileRevert(self.fname) self.reload() self.updateSvnStatus() def svnCommit(self): from . import svnmanip svnmanip.svnFileCommit(self.fname, None, self.lpywidget) self.updateSvnStatus()