diff --git a/mgui.py b/mgui.py index 372fde8fa38b55c3667def740d14552548dbc296..0ecb96fe2ca97b62136fd0cebccb8a15470c41b2 100644 --- a/mgui.py +++ b/mgui.py @@ -6,7 +6,7 @@ # Maintainer: HarshaRani # Created: Mon Nov 12 09:38:09 2012 (+0530) # Version: -# Last-Updated: Fri Aug 31 14:54:33 2017 (+0530) +# Last-Updated: Fri Sep 20 00:54:33 2018 (+0530) # By: Harsha # Update #: # URL: @@ -44,11 +44,19 @@ # '''' -Aug 31: Pass file from the command to load into gui - : added dsolver in disableModel function is used to unset the solver for the model - into moose-gui which are not to be run. - -Oct 5: clean up with round trip of dialog_exe +2018 +Sep 20 : Lot of duplicate code removed + Function call made when filename or filepath is passed in command line +Sep 19 : From the cmd line if a directory is passed, then Gui opens up the dialog file for the folder, + window is resized to maximum width, clean warning message if filename or path is wrong + Added model info QmessageBox +Sep 7 : popup is closed if exist +2017 +Aug 31 : Pass file from the command to load into gui + : added dsolver in disableModel function is used to unset the solver for the model + into moose-gui which are not to be run. + +Oct 5 : clean up with round trip of dialog_exe ''' # Code: @@ -193,6 +201,7 @@ class MWindow(QtGui.QMainWindow): pass else: cmdfilepath = os.path.abspath(sys.argv[1]) + try: sys.argv[2] except: @@ -204,6 +213,7 @@ class MWindow(QtGui.QMainWindow): filepath,fileName = os.path.split(cmdfilepath) modelRoot,extension = os.path.splitext(fileName) if extension == '.py': + self.setWindowState(QtCore.Qt.WindowMaximized) self.show() self.createPopup() freeCursor() @@ -212,16 +222,23 @@ class MWindow(QtGui.QMainWindow): QtGui.QApplication.restoreOverrideCursor() return if not os.path.exists(cmdfilepath): + self.setWindowState(QtCore.Qt.WindowMaximized) self.show() self.createPopup() - reply = QtGui.QMessageBox.information(self,"Model file can not open","Check filename or filepath ",QtGui.QMessageBox.Ok) + reply = QtGui.QMessageBox.information(self,"Model file can not open","File Not Found \n \nCheck filename or filepath\n ",QtGui.QMessageBox.Ok) if reply == QtGui.QMessageBox.Ok: QtGui.QApplication.restoreOverrideCursor() return + if os.path.isdir(cmdfilepath): + self.setWindowState(QtCore.Qt.WindowMaximized) + self.show() + self.loadModelDialogFunc(cmdfilepath) + else: filePath = filepath+'/'+fileName ret = loadFile(str(filePath), '%s' % (modelRoot), solver, merge=False) - self.objectEditSlot('/',False) + #self.objectEditSlot('/',False) + self.objectEditSlot(ret['model'].path,False) pluginLookup = '%s/%s' % (ret['modeltype'], ret['subtype']) try: pluginName = subtype_plugin_map['%s/%s' % (ret['modeltype'], ret['subtype'])] @@ -246,26 +263,10 @@ class MWindow(QtGui.QMainWindow): modelAnno.dirpath = str(filepath) self.setPlugin(pluginName, ret['model'].path) + self.setWindowState(QtCore.Qt.WindowMaximized) self.show() - # if pluginName == 'kkit': - # QtCore.QCoreApplication.sendEvent(self.plugin.getEditorView().getCentralWidget().view, QtGui.QKeyEvent(QtCore.QEvent.KeyPress, Qt.Qt.Key_A, Qt.Qt.NoModifier)) - - # noOfCompt = len(moose.wildcardFind(ret['model'].path+'/##[ISA=ChemCompt]')) - # grp = 0 - # for c in moose.wildcardFind(ret['model'].path+'/##[ISA=ChemCompt]'): - # noOfGrp = moose.wildcardFind(moose.element(c).path+'/#[TYPE=Neutral]') - # grp = grp+len(noOfGrp) - - # noOfPool = len(moose.wildcardFind(ret['model'].path+'/##[ISA=PoolBase]')) - # noOfFunc = len(moose.wildcardFind(ret['model'].path+'/##[ISA=Function]')) - # noOfReac = len(moose.wildcardFind(ret['model'].path+'/##[ISA=ReacBase]')) - # noOfEnz = len(moose.wildcardFind(ret['model'].path+'/##[ISA=EnzBase]')) - # noOfStimtab = len(moose.wildcardFind(ret['model'].path+'/##[ISA=StimulusTable]')) - - # reply = QtGui.QMessageBox.information(self,"Model Info","Model has : \n %s Compartment \t \n %s Group \t \n %s Pool \t \n %s Function \t \n %s reaction \t \n %s Enzyme \t \n %s StimulusTable" %(noOfCompt, grp, noOfPool, noOfFunc, noOfReac, noOfEnz, noOfStimtab)) - # if reply == QtGui.QMessageBox.Ok: - # QtGui.QApplication.restoreOverrideCursor() - # return + if pluginName == 'kkit': + self.displaymodelInfo(ret) else: self.createPopup() @@ -568,7 +569,6 @@ class MWindow(QtGui.QMainWindow): if name == 'kkit': self.objectEditDockWidget.objectNameChanged.connect(self.plugin.getEditorView().getCentralWidget().updateItemSlot) self.objectEditDockWidget.colorChanged.connect(self.plugin.getEditorView().getCentralWidget().updateColorSlot) - self.setCurrentView('editor') freeCursor() return self.plugin @@ -643,7 +643,8 @@ class MWindow(QtGui.QMainWindow): self.plugin.setCurrentView(view) if view =='run': #Harsha: This will clear out object editor's objectpath and make it invisible - self.objectEditSlot('/',False) + #self.objectEditSlot('/',False) + self.objectEditDockWidget.setVisible(False) targetView = None newSubWindow = True @@ -1219,6 +1220,15 @@ class MWindow(QtGui.QMainWindow): for table in moose.wildcardFind( modelPath+'/data/graph#/#' ): table.tick = -1 + def loadModelDialogFunc(self,directorypassed): + """ This is from command line the filepath and file name is passed + """ + dialog = LoaderDialog(self, + self.tr('Load model from file'),directorypassed) + + if dialog.exec_(): + self.passtoPluginCheck(dialog) + def loadModelDialogSlot(self): """Start a file dialog to choose a model file. @@ -1237,70 +1247,53 @@ class MWindow(QtGui.QMainWindow): by looking into the model file for a regular expression) """ - self.popup.close() + if self.popup: + self.popup.close() activeWindow = None # This to be used later to refresh the current widget with newly loaded model dialog = LoaderDialog(self, self.tr('Load model from file')) - if dialog.exec_(): - valid = False - ret = [] - ret,pluginName = self.checkPlugin(dialog) + self.passtoPluginCheck(dialog) + + def passtoPluginCheck(self, dialog): + valid = False + ret = [] + ret,pluginName = self.checkPlugin(dialog) + valid,ret = self.dialog_check(ret) + + if valid == True: + modelAnno = moose.Annotator(ret['model'].path+'/info') + if ret['subtype']: + modelAnno.modeltype = ret['subtype'] + else: + modelAnno.modeltype = ret['modeltype'] + modelAnno.dirpath = str(dialog.directory().absolutePath()) + self.loadedModelsAction(ret['model'].path,pluginName) + self.setPlugin(pluginName, ret['model'].path) + if pluginName == 'kkit': - if (ret['subtype'] == 'sbml' and ret['foundlib'] == False): - reply = QtGui.QMessageBox.question(self, "python-libsbml is not found.","\n Read SBML is not possible.\n This can be installed using \n \n pip python-libsbml or \n apt-get install python-libsbml", - QtGui.QMessageBox.Ok) - if reply == QtGui.QMessageBox.Ok: - QtGui.QApplication.restoreOverrideCursor() - return - else: - if ret['loaderror'] != "": - reply = QtGui.QMessageBox.question(self, "Model can't be loaded", ret['loaderror']+" \n \n Do you want another file", - QtGui.QMessageBox.Yes | QtGui.QMessageBox.No) - if reply == QtGui.QMessageBox.Yes: - dialog = LoaderDialog(self,self.tr('Load model from file')) - if dialog.exec_(): - valid = False - ret = [] - pluginName = None - ret,pluginName = self.checkPlugin(dialog) - - valid, ret = self.dialog_check(ret) - else: - QtGui.QApplication.restoreOverrideCursor() - return valid - else: + self.displaymodelInfo(ret) + + def displaymodelInfo(self,ret): + QtCore.QCoreApplication.sendEvent(self.plugin.getEditorView().getCentralWidget().view, QtGui.QKeyEvent(QtCore.QEvent.KeyPress, Qt.Qt.Key_A, Qt.Qt.NoModifier)) + + noOfCompt = len(moose.wildcardFind(ret['model'].path+'/##[ISA=ChemCompt]')) + grp = 0 + for c in moose.wildcardFind(ret['model'].path+'/##[ISA=ChemCompt]'): + noOfGrp = moose.wildcardFind(moose.element(c).path+'/#[TYPE=Neutral]') + grp = grp+len(noOfGrp) + + noOfPool = len(moose.wildcardFind(ret['model'].path+'/##[ISA=PoolBase]')) + noOfFunc = len(moose.wildcardFind(ret['model'].path+'/##[ISA=Function]')) + noOfReac = len(moose.wildcardFind(ret['model'].path+'/##[ISA=ReacBase]')) + noOfEnz = len(moose.wildcardFind(ret['model'].path+'/##[ISA=EnzBase]')) + noOfStimtab = len(moose.wildcardFind(ret['model'].path+'/##[ISA=StimulusTable]')) + + reply = QtGui.QMessageBox.information(self,"Model Info","Model has : \n %s Compartment \t \n %s Group \t \n %s Pool \t \n %s Function \t \n %s reaction \t \n %s Enzyme \t \n %s StimulusTable" %(noOfCompt, grp, noOfPool, noOfFunc, noOfReac, noOfEnz, noOfStimtab)) + if reply == QtGui.QMessageBox.Ok: + QtGui.QApplication.restoreOverrideCursor() + return - valid = True - if valid == True: - modelAnno = moose.Annotator(ret['model'].path+'/info') - if ret['subtype']: - modelAnno.modeltype = ret['subtype'] - else: - modelAnno.modeltype = ret['modeltype'] - modelAnno.dirpath = str(dialog.directory().absolutePath()) - self.loadedModelsAction(ret['model'].path,pluginName) - self.setPlugin(pluginName, ret['model'].path) - if pluginName == 'kkit': - QtCore.QCoreApplication.sendEvent(self.plugin.getEditorView().getCentralWidget().view, QtGui.QKeyEvent(QtCore.QEvent.KeyPress, Qt.Qt.Key_A, Qt.Qt.NoModifier)) - - noOfCompt = len(moose.wildcardFind(ret['model'].path+'/##[ISA=ChemCompt]')) - grp = 0 - for c in moose.wildcardFind(ret['model'].path+'/##[ISA=ChemCompt]'): - noOfGrp = moose.wildcardFind(moose.element(c).path+'/#[TYPE=Neutral]') - grp = grp+len(noOfGrp) - - noOfPool = len(moose.wildcardFind(ret['model'].path+'/##[ISA=PoolBase]')) - noOfFunc = len(moose.wildcardFind(ret['model'].path+'/##[ISA=Function]')) - noOfReac = len(moose.wildcardFind(ret['model'].path+'/##[ISA=ReacBase]')) - noOfEnz = len(moose.wildcardFind(ret['model'].path+'/##[ISA=EnzBase]')) - noOfStimtab = len(moose.wildcardFind(ret['model'].path+'/##[ISA=StimulusTable]')) - - reply = QtGui.QMessageBox.information(self,"Model Info","Model has : \n %s Compartment \t \n %s Group \t \n %s Pool \t \n %s Function \t \n %s reaction \t \n %s Enzyme \t \n %s StimulusTable" %(noOfCompt, grp, noOfPool, noOfFunc, noOfReac, noOfEnz, noOfStimtab)) - if reply == QtGui.QMessageBox.Ok: - QtGui.QApplication.restoreOverrideCursor() - return - def checkPlugin(self,dialog): fileNames = dialog.selectedFiles() for fileName in fileNames: @@ -1356,7 +1349,8 @@ class MWindow(QtGui.QMainWindow): def newModelDialogSlot(self): #Harsha: Create a new dialog widget for model building - self.popup.close() + if self.popup: + self.popup.close() newModelDialog = DialogWidget() if newModelDialog.exec_(): modelPath = str(newModelDialog.modelPathEdit.text()).strip() diff --git a/mload.py b/mload.py index 9fc753e64551b388f7b605d0fe326fc75738e930..3b9783282db59afed47d012d15d0069f2bf83d75 100644 --- a/mload.py +++ b/mload.py @@ -61,7 +61,8 @@ from PyQt4 import QtGui, QtCore, Qt from plugins.setsolver import * from moose.SBML import * from plugins.kkitOrdinateUtil import * - +import moose._moose as moose +import moose.utils as mutils def loadGenCsp(target,filename,solver="gsl"): target = target.replace(" ", "") path = '/'+target @@ -72,7 +73,7 @@ def loadGenCsp(target,filename,solver="gsl"): moose.delete(mpath) modelpath1 = moose.Neutral('%s' %(target)) modelpath = moose.Neutral('%s/%s' %(modelpath1.path,"model")) - model = moose.loadModel(filename, modelpath.path,solver) + model = mutils.loadModel(filename, modelpath.path,solver) if not moose.exists(modelpath1.path+'/data'): graphspath = moose.Neutral('%s/%s' %(modelpath1.path,"data")) @@ -189,7 +190,7 @@ def loadFile(filename, target, solver="gsl", merge=True): moose.Annotator(moose.element(modelpath).path+'/info').modeltype = "kkit" else: print (" path doesn't exists") - moose.le(modelpath) + #moose.le(modelpath) else: print ('Only kkit and prototype files can be loaded.') diff --git a/objectedit.py b/objectedit.py index 08c38bbbae4a49daf6520d833c0c720b5a86027c..11a35b66948262d60c12cdd528ab421e7b5aa873 100644 --- a/objectedit.py +++ b/objectedit.py @@ -6,7 +6,7 @@ # Maintainer: # Created: Wed Jun 30 11:18:34 2010 (+0530) # Version: -# Last-Updated: Tue Jun 19 11:05:59 2017 (+0530) +# Last-Updated: Fri Feb 01 11:05:59 2017 (+0530) # By: Harsha # Update #: # URL: @@ -43,6 +43,7 @@ # Fri May 17 23:45:59 2017 (+0530) - Harsha added, notes header, # Kd is calculated for the second order reaction and value is displayed # Tue Jun 18 12:10:54 IST 2018 - Harsha now group boundary color can be editable from the object editor +# Mon Sep 10 16:21:00 IST 2018 - When name is edited, the editorTitle gets updated # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License as @@ -76,11 +77,13 @@ import sys from collections import deque import traceback -sys.path.append('../python') +#sys.path.append('../python') import moose import defaults import config -from plugins.kkitUtil import getColor +#from plugins.kkitUtil import getColor +from moose.chemUtil.chemConnectUtil import getColor + #these fields will be ignored extra_fields = ['this', 'me', @@ -174,10 +177,14 @@ class ObjectEditModel(QtCore.QAbstractTableModel): self.fields.append(fieldName) #harsha: For signalling models will be pulling out notes field from Annotator # can updates if exist for other types also - if ( isinstance(self.mooseObject, moose.PoolBase) - or isinstance(self.mooseObject,moose.EnzBase) - or isinstance(self.mooseObject,moose.Neutral)) : - self.fields.append("Color") + if (isinstance (self.mooseObject,moose.ChemCompt) or \ + isinstance(self.mooseObject,moose.ReacBase) or \ + isinstance(moose.element(moose.element(self.mooseObject).parent),moose.EnzBase) \ + ): + pass + else: + self.fields.append("Color") + flag = QtCore.Qt.ItemIsEnabled | QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsEditable self.fieldFlags[fieldName] = flag @@ -432,7 +439,7 @@ class ObjectEditView(QtGui.QTableView): def setColor(self, color): self.colorButton.setStyleSheet( "QPushButton {" - + "background-color: {0}; color: {0};".format(color.name()) + + "background-color: {0}; color: {0};".format(color) + "}" ) self.colorDialog.setCurrentColor(color) @@ -522,7 +529,7 @@ class ObjectEditDockWidget(QtGui.QDockWidget): def emitObjectNameChanged(self, mobj): self.objectNameChanged.emit(mobj) - + self.setWindowTitle('Edit:%s'%(mobj.path)) def main(): app = QtGui.QApplication(sys.argv) mainwin = QtGui.QMainWindow() diff --git a/plugins/default.py b/plugins/default.py index 788e8349a82ca1f7d89b155a3a30eef333072a6e..3cb28409e30272d1b32ca23053170ce354ab081e 100644 --- a/plugins/default.py +++ b/plugins/default.py @@ -6,7 +6,7 @@ # Maintainer: # Created: Tue Nov 13 15:58:31 2012 (+0530) # Version: -# Last-Updated: Thu Oct 5 12:35:00 2013 (+0530) +# Last-Updated: Mon Sep 10 23:35:00 2018 (+0530) # By: Harsha # Update #: # URL: @@ -45,6 +45,9 @@ # Code: ''' +2018 +Sep 10: replace addSolver to mooseAddChemSolver from moose.chemUtil's +2013 Oct 5: could not recreate if object already exist in moose which was allowed earlier now if object exist need to use element which is cleaned here @@ -94,7 +97,9 @@ from matplotlib.backends.backend_qt4agg import NavigationToolbar2QT as Navigatio #from EventBlocker import EventBlocker # from PlotNavigationToolbar import PlotNavigationToolbar from global_constants import preferences -from setsolver import * +#from setsolver import * +from moose.chemUtil.add_Delete_ChemicalSolver import * + ELECTRICAL_MODEL = 0 CHEMICAL_MODEL = 1 @@ -636,7 +641,7 @@ class SchedulingWidget(QtGui.QWidget): if not moose.exists(compt[0].path+'/stoich'): chemPref = self.preferences.getChemicalPreferences() solver = chemPref["simulation"]["solver"] - addSolver(self.modelRoot,solver) + mooseAddChemSolver(self.modelRoot,solver) status = self.solverStatus() #print "status ",status # if status != 0 or status == -1: @@ -731,7 +736,7 @@ class SchedulingWidget(QtGui.QWidget): # print("Status =>", status) if status == 1 or status == 2: - nameRE = "\n\nclassName --> parent --> name " + nameRE = "\n\nclassName --> parentName/groupName --> name " for res in moose.wildcardFind(self.modelRoot+'/##[ISA=ReacBase],'+self.modelRoot+'/##[ISA=EnzBase]'): if not len(res.neighbors["sub"]) or not len(res.neighbors["prd"]): nameRE = nameRE+"\n "+res.className + " --> "+res.parent.name+ " --> "+res.name diff --git a/plugins/kkit.py b/plugins/kkit.py index 692de4b2b8aa286717533f32cf321a03419ff9de..c375e06905103bff17f50aaeaea810589327399b 100644 --- a/plugins/kkit.py +++ b/plugins/kkit.py @@ -6,11 +6,20 @@ __version__ = "1.0.0" __maintainer__ = "HarshaRani" __email__ = "hrani@ncbs.res.in" __status__ = "Development" -__updated__ = "Jun 19 2018" +__updated__ = "Feb 22 2019" #Change log: -# 2018 Jun 18: update the color of the group from objecteditor - +#2019 +#Feb 22: cross compartment molecules are checked for destination +# 2018 +#Oct 26: xfer cross compartment molecules are hidden and for cross compartment reaction's +# connection are now dotted line +#Oct 10: filedialog default is sbml +# layout co-ordainates are updated with scenepos +#Sep 11: comparment size is calculated based on group sceneBoundingRect size +#Sep 07: in positionChange all the group's boundingRect is calculated +# and when group is moved the children's position are stored +#Jun 18: update the color of the group from objecteditor #code import math @@ -35,6 +44,7 @@ import RunWidget from os.path import expanduser #from setsolver import * from moose.chemUtil.add_Delete_ChemicalSolver import * +import re class KkitPlugin(MoosePlugin): """Default plugin for MOOSE GUI""" @@ -59,41 +69,25 @@ class KkitPlugin(MoosePlugin): self.getEditorView() def SaveModelDialogSlot(self): - type_sbml = 'SBML' - type_genesis = 'Genesis' + dirpath = "" - # if moose.Annotator(self.modelRoot+'/model/info'): - # moose.Annotator(self.modelRoot+'/model/info') - # mooseAnno = moose.Annotator(self.modelRoot+'/model/info') - #dirpath = mooseAnno.dirpath if not dirpath: dirpath = expanduser("~") - filters = {'SBML(*.xml)': type_sbml,'Genesis(*.g)':type_genesis} - - filename,filter_ = QtGui.QFileDialog.getSaveFileNameAndFilter(None,'Save File',dirpath,';;'.join(filters)) + filters = {'SBML(*.xml)': 'SBML','Genesis(*.g)':'Genesis'} + #filename,filter_ = QtGui.QFileDialog.getSaveFileNameAndFilter(None,'Save File',dirpath,';;'.join(filters)) + filename,filter_ = QtGui.QFileDialog.getSaveFileNameAndFilter(None,'Save File',dirpath,"SBML(*.xml);;Genesis(*.g)") extension = "" if str(filename).rfind('.') != -1: filename = filename[:str(filename).rfind('.')] if str(filter_).rfind('.') != -1: extension = filter_[str(filter_).rfind('.'):len(filter_)-1] + if filename: filename = filename if filters[str(filter_)] == 'SBML': - self.sceneObj = KkitEditorView(self).getCentralWidget().mooseId_GObj self.coOrdinates = {} self.plugin = KkitEditorView(self).getCentralWidget().plugin - self.defaultScenewidth = KkitEditorView(self).getCentralWidget().defaultScenewidth - self.defaultSceneheight = KkitEditorView(self).getCentralWidget().defaultSceneheight self.coOrdinates = KkitEditorView(self).getCentralWidget().getsceneCord() - ''' - for k,v in self.sceneObj.items(): - if moose.exists(moose.element(k).path+'/info'): - annoInfo = Annotator(k.path+'/info') - if moose.element(self.plugin.modelRoot+'/info').modeltype == 'kkit': - self.coOrdinates[k] = {'x':annoInfo.x*self.defaultScenewidth, 'y':annoInfo.y*self.defaultSceneheight} - else: - self.coOrdinates[k] = {'x':annoInfo.x, 'y':annoInfo.y} - ''' #writeerror = moose.writeSBML(self.modelRoot,str(filename),self.coOrdinates) writeerror = -2 conisitencyMessages = "" @@ -341,12 +335,12 @@ class KineticsWidget(EditorWidgetBase): self.arrowsize = 2 self.reset() - self.defaultSceneheight = 800#1000 - self.defaultScenewidth = 1000#2400 + self.defaultSceneheight = 1#800#1000 + self.defaultScenewidth = 1#000#2400 self.positionInfoExist = True self.defaultComptsize = 5 self.srcdesConnection = {} - self.meshEntry = {} + self.meshEntry = {} self.mooseId_GObj = {} self.qGraCompt = {} self.qGraGrp = {} @@ -373,13 +367,10 @@ class KineticsWidget(EditorWidgetBase): def getsceneCord(self): self.cord = {} + self.view.setRefWidget("runView") for item in self.sceneContainer.items(): if isinstance(item,KineticsDisplayItem): - #item.refresh(scale) - #self.update() - xpos = item.scenePos().x() - ypos = item.scenePos().y() - self.cord[item.mobj] = {'x':xpos,'y':ypos} + self.cord[item.mobj] = {'x':item.scenePos().x(),'y':item.scenePos().y()} return self.cord def updateModelView(self): @@ -456,18 +447,15 @@ class KineticsWidget(EditorWidgetBase): self.srcdesConnection = {} setupItem(self.modelRoot,self.srcdesConnection) - - # if not self.positionInfoExist: - # autoCoordinates(self.meshEntry,self.srcdesConnection) + #self.noPositionInfo = False if not self.noPositionInfo: self.autocoordinates = True #self.xmin,self.xmax,self.ymin,self.ymax,self.autoCordinatepos = autoCoordinates(self.meshEntry,self.srcdesConnection) - #print " after ",self.xmin,self.xmax, self.ymin, self.ymax,self.autoCordinatepos autoCoordinates(self.meshEntry,self.srcdesConnection) self.size = QtCore.QSize(1000 ,550) - ''' + ''' if self.xmax-self.xmin != 0: self.xratio = (self.size.width()-10)/(self.xmax-self.xmin) else: self.xratio = self.size.width()-10 @@ -482,7 +470,7 @@ class KineticsWidget(EditorWidgetBase): self.xratio = 1 if self.yratio == 0: self.yratio = 1 - ''' + ''' def sizeHint(self): return QtCore.QSize(800,400) @@ -500,6 +488,7 @@ class KineticsWidget(EditorWidgetBase): self.positionChange(mooseObject) self.view.removeConnector() self.view.showConnector(item) + def updateColorSlot(self,mooseObject, colour): #Color slot for changing background color for Pool,Enz and group from objecteditor anninfo = moose.Annotator(mooseObject.path+'/info') @@ -628,6 +617,7 @@ class KineticsWidget(EditorWidgetBase): elif isinstance(moose.element(v), moose.Neutral): group_parent = self.qGraGrp[v] self.createGroup(k,group_parent) + for cmpt_grp,memb in self.meshEntry.items(): if len(memb): if isinstance(moose.element(cmpt_grp),moose.ChemCompt): @@ -640,6 +630,7 @@ class KineticsWidget(EditorWidgetBase): self.groupChildrenBoundingRect() # compartment's rectangle size is calculated depending on children self.comptChildrenBoundingRect() + def mObjontoscene(self,memb,mclass,qtGrpparent): try: value = memb[mclass] @@ -648,7 +639,6 @@ class KineticsWidget(EditorWidgetBase): else: for mObj in memb[mclass]: minfo = mObj.path+'/info' - if mObj.className in['Enz',"ZombieEnz"]: mItem = EnzItem(mObj,qtGrpparent) @@ -666,18 +656,20 @@ class KineticsWidget(EditorWidgetBase): minfo = (mObj.parent).path+'/info' mItem = CplxItem(mObj,self.mooseId_GObj[element(mObj).parent]) self.mooseId_GObj[element(mObj.getId())] = mItem + elif mclass == "function": if isinstance(moose.element(mObj.parent),moose.PoolBase): minfo = moose.element(mObj).path+'/info' Af = Annotator(minfo) qtGrpparent = self.mooseId_GObj[element(mObj.parent)] mItem = FuncItem(mObj,qtGrpparent) + elif mclass == "stimTab": minfo = mObj.path+'/info' mItem = TableItem(mObj,qtGrpparent) self.mooseId_GObj[element(mObj.getId())] = mItem self.setupDisplay(minfo,mItem,mclass) - + def createGroup(self,key,parent): self.new_GRP = GRPItem(parent,0,0,0,0,key) self.qGraGrp[key] = self.new_GRP @@ -693,12 +685,13 @@ class KineticsWidget(EditorWidgetBase): v.setPen(QtGui.QPen(Qt.QColor(grpcolor), self.comptPen, Qt.Qt.SolidLine, Qt.Qt.RoundCap, Qt.Qt.RoundJoin)) def comptChildrenBoundingRect(self): + comptlist = [] for k, v in self.qGraCompt.items(): # compartment's rectangle size is calculated depending on children rectcompt = calculateChildBoundingRect(v) v.setRect(rectcompt.x()-10,rectcompt.y()-10,(rectcompt.width()+20),(rectcompt.height()+20)) v.setPen(QtGui.QPen(Qt.QColor(66,66,66,100), self.comptPen, Qt.Qt.SolidLine, Qt.Qt.RoundCap, Qt.Qt.RoundJoin)) - + def createCompt(self,key): self.new_Compt = ComptItem(self,0,0,0,0,key) self.qGraCompt[key] = self.new_Compt @@ -735,34 +728,34 @@ class KineticsWidget(EditorWidgetBase): else: xpos,ypos = self.positioninfo(info) - self.xylist = [xpos,ypos] - self.xyCord[moose.element(info).parent] = [xpos,ypos] - elif isinstance(self,kineticRunWidget): self.editormooseId_GObj = self.editor.getCentralWidget().mooseId_GObj editorItem = self.editormooseId_GObj[moose.element(info).parent] xpos = editorItem.scenePos().x() - ypos = editorItem.scenePos().y() - #Annoinfo.x = xpos - #Annoinfo.y = -ypos + ypos = editorItem.scenePos().y() graphicalObj.setDisplayProperties(xpos,ypos,textcolor,bgcolor) - #Annoinfo.x = xpos - #Annoinfo.y = ypos + def positioninfo(self,iteminfo): '''By this time, model loaded from kkit,cspace,SBML would have info field created and co-ordinates are added either by autocoordinates (for cspace,SBML(unless it is not saved from moose)) or from kkit ''' - if moose.Annotator(self.plugin.modelRoot+'/info').modeltype == 'kkit': - x = self.defaultScenewidth * float(element(iteminfo).getField('x')) - y = self.defaultSceneheight * float(element(iteminfo).getField('y')) - #x = x /self.defaultScenewidth - #y = y /self.defaultSceneheight - else: - x = float(element(iteminfo).getField('x')) - y = float(element(iteminfo).getField('y')) - self.defaultScenewidth = 1 - self.defaultSceneheight = 1 + + x = float(element(iteminfo).getField('x')) + y = float(element(iteminfo).getField('y')) + #print " positioninfo", iteminfo,x,y + # if moose.Annotator(self.plugin.modelRoot+'/info').modeltype == 'kkit': + # x = self.defaultScenewidth * float(element(iteminfo).getField('x')) + # y = self.defaultSceneheight * float(element(iteminfo).getField('y')) + # print " positioninfo ",iteminfo, element(iteminfo).getField('x'), element(iteminfo).getField('y'), x, y + + # #x = x /self.defaultScenewidth + # #y = y /self.defaultSceneheight + # else: + # x = float(element(iteminfo).getField('x')) + # y = float(element(iteminfo).getField('y')) + # self.defaultScenewidth = 1 + # self.defaultSceneheight = 1 return(x,y) def drawLine_arrow(self, itemignoreZooming=False): @@ -773,20 +766,39 @@ class KineticsWidget(EditorWidgetBase): # key is Function and value is [list of pool] (list) #src = self.mooseId_GObj[inn] + linetype = "regular" if isinstance(out,tuple): src = self.mooseId_GObj[inn] if len(out[0])== 0: print (inn.className + ' : ' +inn.name+ " doesn't output message") else: for items in (items for items in out[0] ): + if re.search("xfer",element(items[0]).name): + xrefPool = items[0].name[:items[0].name.index("_xfer_")] + xrefCompt = items[0].name[items[0].name.index("_xfer_") + len("_xfer_"):] + orgCompt = moose.wildcardFind(self.modelRoot+'/##[FIELD(name)='+xrefCompt+']')[0] + orgPool = moose.wildcardFind(orgCompt.path+'/##[FIELD(name)='+xrefPool+']')[0] + itemslist = list(items) + itemslist[0] = orgPool + items = tuple(itemslist) + linetype = "crosscompt" des = self.mooseId_GObj[element(items[0])] - self.lineCord(src,des,items,itemignoreZooming) + self.lineCord(src,des,items,itemignoreZooming,linetype) if len(out[1]) == 0: print (inn.className + ' : ' +inn.name+ " doesn't output message") else: for items in (items for items in out[1] ): + if re.search("xfer",element(items[0]).name): + xrefPool = items[0].name[:items[0].name.index("_xfer_")] + xrefCompt = items[0].name[items[0].name.index("_xfer_") + len("_xfer_"):] + orgCompt = moose.wildcardFind(self.modelRoot+'/##[FIELD(name)='+xrefCompt+']')[0] + orgPool = moose.wildcardFind(orgCompt.path+'/##[FIELD(name)='+xrefPool+']')[0] + itemslist = list(items) + itemslist[0] = orgPool + items = tuple(itemslist) + linetype = "crosscompt" des = self.mooseId_GObj[element(items[0])] - self.lineCord(src,des,items,itemignoreZooming) + self.lineCord(src,des,items,itemignoreZooming,linetype) elif isinstance(out,list): if len(out) == 0: if inn.className == "StimulusTable": @@ -796,9 +808,19 @@ class KineticsWidget(EditorWidgetBase): else: src = self.mooseId_GObj[inn] for items in (items for items in out ): + if re.search("xfer",element(items[0]).name): + xrefPool = items[0].name[:items[0].name.index("_xfer_")] + xrefCompt = items[0].name[items[0].name.index("_xfer_") + len("_xfer_"):] + orgCompt = moose.wildcardFind(self.modelRoot+'/##[FIELD(name)='+xrefCompt+']')[0] + orgPool = moose.wildcardFind(orgCompt.path+'/##[FIELD(name)='+xrefPool+']')[0] + itemslist = list(items) + itemslist[0] = orgPool + items = tuple(itemslist) + linetype = "crosscompt" des = self.mooseId_GObj[element(items[0])] - self.lineCord(src,des,items,itemignoreZooming) - def lineCord(self,src,des,type_no,itemignoreZooming): + self.lineCord(src,des,items,itemignoreZooming,linetype) + + def lineCord(self,src,des,type_no,itemignoreZooming,linetype): srcdes_list = [] endtype = type_no[1] line = 0 @@ -807,18 +829,18 @@ class KineticsWidget(EditorWidgetBase): return srcdes_list = [src,des,endtype,line] arrow = calcArrow(srcdes_list,itemignoreZooming,self.iconScale) - self.drawLine(srcdes_list,arrow) + self.drawLine(srcdes_list,arrow,linetype) while(type_no[2] > 1 and line <= (type_no[2]-1)): srcdes_list =[src,des,endtype,line] arrow = calcArrow(srcdes_list,itemignoreZooming,self.iconScale) - self.drawLine(srcdes_list,arrow) + self.drawLine(srcdes_list,arrow,linetype) line = line +1 if type_no[2] > 5: print ("Higher order reaction will not be displayed") - def drawLine(self,srcdes_list,arrow): + def drawLine(self,srcdes_list,arrow,linetype="solid"): src = srcdes_list[0] des = srcdes_list[1] endtype = srcdes_list[2] @@ -836,7 +858,12 @@ class KineticsWidget(EditorWidgetBase): qgLineitem = self.sceneContainer.addPolygon(arrow) qgLineitem.setParentItem(src.parentItem()) pen = QtGui.QPen(QtCore.Qt.green, 0, Qt.Qt.SolidLine, Qt.Qt.RoundCap, Qt.Qt.RoundJoin) + if linetype == "crosscompt": + pen.setStyle(Qt.Qt.CustomDashLine) + pen.setDashPattern([1, 5, 1, 5]) + pen.setWidth(self.arrowsize) + # Green is default color moose.ReacBase and derivatives - already set above if isinstance(source, EnzBase): if ( (endtype == 's') or (endtype == 'p')): @@ -856,8 +883,37 @@ class KineticsWidget(EditorWidgetBase): self.object2line[ src ].append( ( qgLineitem, des,endtype,line) ) self.object2line[ des ].append( ( qgLineitem, src,endtype,line ) ) qgLineitem.setPen(pen) - + def positionChange(self,mooseObject): + #If the item position changes, the corresponding arrow's are calculated + print mooseObject + for k, v in self.qGraCompt.items(): + for rectChilditem in v.childItems(): + self.updateArrow(rectChilditem) + if isinstance(rectChilditem,GRPItem): + for grpChilditem in rectChilditem.childItems(): + self.updateArrow(grpChilditem) + if isinstance(grpChilditem,KineticsDisplayItem): + if moose.exists(grpChilditem.mobj.path+'/info'): + #print grpChilditem.mobj.name, grpChilditem.scenePos() + moose.element(grpChilditem.mobj.path+'/info').x = grpChilditem.scenePos().x() + moose.element(grpChilditem.mobj.path+'/info').y = grpChilditem.scenePos().y() + #self.updateGrpSize(rectChilditem) + if isinstance(rectChilditem,KineticsDisplayItem): + if moose.exists(rectChilditem.mobj.path+'/info'): + #print rectChilditem.mobj.name, rectChilditem.scenePos() + moose.element(rectChilditem.mobj.path+'/info').x = rectChilditem.scenePos().x() + moose.element(rectChilditem.mobj.path+'/info').y = rectChilditem.scenePos().y() + + rectcompt = calculateChildBoundingRect(v) + comptBoundingRect = v.boundingRect() + if not comptBoundingRect.contains(rectcompt): + self.updateCompartmentSize(v) + else: + rectcompt = calculateChildBoundingRect(v) + v.setRect(rectcompt.x()-10,rectcompt.y()-10,(rectcompt.width()+20),(rectcompt.height()+20)) + + def positionChange_old(self,mooseObject): #If the item position changes, the corresponding arrow's are calculated if isinstance(element(mooseObject),ChemCompt): for k, v in self.qGraCompt.items(): @@ -865,63 +921,78 @@ class KineticsWidget(EditorWidgetBase): if k.path == mesh: for rectChilditem in v.childItems(): if isinstance(rectChilditem, KineticsDisplayItem): - if isinstance(moose.element(rectChilditem.mobj.path),PoolBase): - t = moose.element(rectChilditem.mobj.path) - moose.element(t).children - for items in moose.element(t).children: - if isinstance(moose.element(items),Function): - test = moose.element(items.path+'/x') - for i in moose.element(test).neighbors['input']: - j = self.mooseId_GObj[moose.element(i)] - self.updateArrow(j) + if moose.exists(rectChilditem.mobj.path): + iInfo = rectChilditem.mobj.path+'/info' + anno = moose.Annotator(iInfo) + #storing scenePos back to annotator file for further use + x = rectChilditem.scenePos().x() + y = rectChilditem.scenePos().y() + #anno.x = x + #anno.y = y + if isinstance(moose.element(rectChilditem.mobj.path),PoolBase): + t = moose.element(rectChilditem.mobj.path) + moose.element(t).children + for items in moose.element(t).children: + if isinstance(moose.element(items),Function): + test = moose.element(items.path+'/x') + for i in moose.element(test).neighbors['input']: + j = self.mooseId_GObj[moose.element(i)] + self.updateArrow(j) self.updateArrow(rectChilditem) elif element(mooseObject).className == 'Neutral': for k,v in self.qGraGrp.items(): - if k.path == element(mooseObject).path: - for grpChilditem in v.childItems(): - if isinstance(grpChilditem, KineticsDisplayItem): - if moose.exists(grpChilditem.mobj.path): - iInfo = grpChilditem.mobj.path+'/info' - anno = moose.Annotator(iInfo) - if moose.Annotator(self.plugin.modelRoot+'/info').modeltype == 'kkit': - x = grpChilditem.scenePos().x()/self.defaultScenewidth - y = grpChilditem.scenePos().y()/self.defaultSceneheight - else: - x = grpChilditem.scenePos().x() - y = grpChilditem.scenePos().y() - anno.x = x - anno.y = y - - if isinstance(moose.element(grpChilditem.mobj.path),PoolBase): - t = moose.element(grpChilditem.mobj.path) - moose.element(t).children - for items in moose.element(t).children: - if isinstance(moose.element(items),Function): - test = moose.element(items.path+'/x') - for i in moose.element(test).neighbors['input']: - j = self.mooseId_GObj[moose.element(i)] - self.updateArrow(j) - self.updateArrow(grpChilditem) - # grpcompt = self.qGraCompt[self.objPar[k]] - # rectcompt = calculateChildBoundingRect(grpcompt) - rectgrp = calculateChildBoundingRect(v) - v.setRect(rectgrp.x()-10,rectgrp.y()-10,(rectgrp.width()+20),(rectgrp.height()+20)) - + for grpChilditem in v.childItems(): + if isinstance(grpChilditem, KineticsDisplayItem): + if moose.exists(grpChilditem.mobj.path): + iInfo = grpChilditem.mobj.path+'/info' + anno = moose.Annotator(iInfo) + #storing scenePos back to annotator file for further use + x = grpChilditem.scenePos().x() + y = grpChilditem.scenePos().y() + #anno.x = x + #anno.y = y + + if isinstance(moose.element(grpChilditem.mobj.path),PoolBase): + t = moose.element(grpChilditem.mobj.path) + moose.element(t).children + for items in moose.element(t).children: + if isinstance(moose.element(items),Function): + test = moose.element(items.path+'/x') + for i in moose.element(test).neighbors['input']: + j = self.mooseId_GObj[moose.element(i)] + self.updateArrow(j) + self.updateArrow(grpChilditem) + # grpcompt = self.qGraCompt[self.objPar[k]] + # rectcompt = calculateChildBoundingRect(grpcompt) + rectgrp = calculateChildBoundingRect(v) + v.setRect(rectgrp.x()-10,rectgrp.y()-10,(rectgrp.width()+20),(rectgrp.height()+20)) + for k, v in self.qGraCompt.items(): + #rectcompt = v.childrenBoundingRect() + rectcompt = calculateChildBoundingRect(v) + comptBoundingRect = v.boundingRect() + if not comptBoundingRect.contains(rectcompt): + self.updateCompartmentSize(v) + + else: + rectcompt = calculateChildBoundingRect(v) + v.setRect(rectcompt.x()-10,rectcompt.y()-10,(rectcompt.width()+20),(rectcompt.height()+20)) else: mobj = self.mooseId_GObj[element(mooseObject)] self.updateArrow(mobj) - elePath = moose.element(mooseObject).path - pos = elePath.find('/',1) - l = elePath[0:pos] - linfo = moose.Annotator(l+'/info') - if moose.exists(l): - #anno = moose.Annotator(linfo) - if moose.Annotator(self.plugin.modelRoot+'/info').modeltype == 'kkit': - x = mobj.scenePos().x()/self.defaultScenewidth - y = mobj.scenePos().y()/self.defaultSceneheight - else: - x = mobj.scenePos().x() - y = mobj.scenePos().y() + # elePath = moose.element(mooseObject).path + # pos = elePath.find('/',1) + # l = elePath[0:pos] + # linfo = moose.Annotator(l+'/info') + # if moose.exists(l): + # #anno = moose.Annotator(linfo) + # # if moose.Annotator(self.plugin.modelRoot+'/info').modeltype == 'kkit': + # # x = mobj.scenePos().x()/self.defaultScenewidth + # # y = mobj.scenePos().y()/self.defaultSceneheight + # # else: + # # x = mobj.scenePos().x() + # # y = mobj.scenePos().y() + # x = mobj.scenePos().x() + # y = mobj.scenePos().y() #print " x and y at 863 ",mobj.scenePos() # for gk,gv in self.qGraGrp.items(): # rectgrp = calculateChildBoundingRect(gv) @@ -936,11 +1007,15 @@ class KineticsWidget(EditorWidgetBase): comptBoundingRect = v.boundingRect() if not comptBoundingRect.contains(rectcompt): self.updateCompartmentSize(v) + else: rectcompt = calculateChildBoundingRect(v) v.setRect(rectcompt.x()-10,rectcompt.y()-10,(rectcompt.width()+20),(rectcompt.height()+20)) - pass - + # print " position change " + # for item in self.sceneContainer.items(): + # if isinstance(item,KineticsDisplayItem): + # print item.mobj.name, moose.element(item.mobj.path+'/info').x,moose.element(item.mobj.path+'/info').y + def updateGrpSize(self,grp): compartmentBoundary = grp.rect() diff --git a/plugins/kkitOrdinateUtil.py b/plugins/kkitOrdinateUtil.py index dd3b967d4b17c4fa94a9ad0e8130b724ed876c6c..4d27c9ad5f6909056ea8311642c41694810652cb 100644 --- a/plugins/kkitOrdinateUtil.py +++ b/plugins/kkitOrdinateUtil.py @@ -5,9 +5,13 @@ __version__ = "1.0.0" __maintainer__ = "HarshaRani" __email__ = "hrani@ncbs.res.in" __status__ = "Development" -__updated__ = "Oct 18 2017" +__updated__ = "Oct 26 2018" ''' +2018 +Oct 26: xfer molecules are not put into screen +Sep 28: to zoom the kkit co-ordinates a factor of w=1000 and h=800 is multipled here +2017 Oct 18: moved some function to kkitUtil getxyCord, etc function are added ''' @@ -20,6 +24,8 @@ import numpy as np import networkx as nx from kkitUtil import getRandColor,colorCheck,findCompartment, findGroup, findGroup_compt, mooseIsInstance from PyQt4.QtGui import QColor +import re +import moose._moose as moose def getxyCord(xcord,ycord,list1): for item in list1: @@ -198,20 +204,20 @@ def setupMeshObj(modelRoot): # n =n +1 for compt in wildcardFind(modelRoot+'/##[ISA=ChemCompt]'): for m in wildcardFind(compt.path+'/##[ISA=PoolBase]'): - grp_cmpt = findGroup_compt(m) - - xcord.append(xyPosition(m.path+'/info','x')) - ycord.append(xyPosition(m.path+'/info','y')) - if isinstance(element(grp_cmpt),Neutral): - if isinstance(element(m.parent),EnzBase): - populateMeshEntry(meshEntry,grp_cmpt,"cplx",m) - else: - populateMeshEntry(meshEntry,grp_cmpt,"pool",m) - else: - if isinstance(element(m.parent),EnzBase): - populateMeshEntry(meshEntry,compt,"cplx",m) + if not re.search("xfer",m.name): + grp_cmpt = findGroup_compt(m) + xcord.append(xyPosition(m.path+'/info','x')) + ycord.append(xyPosition(m.path+'/info','y')) + if isinstance(element(grp_cmpt),Neutral): + if isinstance(element(m.parent),EnzBase): + populateMeshEntry(meshEntry,grp_cmpt,"cplx",m) + else: + populateMeshEntry(meshEntry,grp_cmpt,"pool",m) else: - populateMeshEntry(meshEntry,compt,"pool",m) + if isinstance(element(m.parent),EnzBase): + populateMeshEntry(meshEntry,compt,"cplx",m) + else: + populateMeshEntry(meshEntry,compt,"pool",m) for r in wildcardFind(compt.path+'/##[ISA=ReacBase]'): rgrp_cmpt = findGroup_compt(r) @@ -384,7 +390,6 @@ def countitems(mitems,objtype): return(uniqItems,countuniqItems) def recalculatecoordinatesforKkit(mObjlist,xcord,ycord): - positionInfoExist = not(len(np.nonzero(xcord)[0]) == 0 \ and len(np.nonzero(ycord)[0]) == 0) @@ -399,8 +404,8 @@ def recalculatecoordinatesforKkit(mObjlist,xcord,ycord): if moose.exists(objInfo): Ix = (xyPosition(objInfo,'x')-xmin)/(xmax-xmin) Iy = (ymin-xyPosition(objInfo,'y'))/(ymax-ymin) - element(objInfo).x = Ix - element(objInfo).y = Iy + element(objInfo).x = Ix*1000 + element(objInfo).y = Iy*800 def xyPosition(objInfo,xory): try: diff --git a/plugins/kkitUtil.py b/plugins/kkitUtil.py index 7185988005fc7c1c15e2795e878870bd1fd9b73f..09170c20e4ae1ebec572e31cca84235f919b98b4 100644 --- a/plugins/kkitUtil.py +++ b/plugins/kkitUtil.py @@ -5,12 +5,18 @@ __version__ = "1.0.0" __maintainer__ = "HarshaRani" __email__ = "hrani@ncbs.res.in" __status__ = "Development" -__updated__ = "Oct 18 2017" +__updated__ = "Oct 11 2018" ''' +2018 +Oct 11: when collision is handled an update of position is done +Sep 28: spell corrected cyclMesh to cylMesh +Sep 17: when vertical or horizontal layout is applied for group, compartment size is recalculated +Sep 11: group size is calculated based on sceneBoundingRect for compartment size +2017 Oct 18 some of the function moved to this file from kkitOrdinateUtils ''' -from moose import Annotator,element +from moose import Annotator,element,ChemCompt from kkitQGraphics import PoolItem, ReacItem,EnzItem,CplxItem,GRPItem,ComptItem from PyQt4 import QtCore,QtGui,QtSvg from PyQt4.QtGui import QColor @@ -127,7 +133,6 @@ def moveX(reference, collider, layoutPt, margin): layoutPt.drawLine_arrow(itemignoreZooming=False) def handleCollisions(compartments, moveCallback, layoutPt,margin = 5.0): - if len(compartments) is 0 : return compartments = sorted(compartments, key = lambda c: c.sceneBoundingRect().center().x()) reference = compartments.pop(0); @@ -138,6 +143,19 @@ def handleCollisions(compartments, moveCallback, layoutPt,margin = 5.0): ) for collider in colliders: moveCallback(reference, collider, layoutPt,margin) + #print (reference.mobj).parent + if isinstance(element(((reference.mobj).parent)),ChemCompt): + v = layoutPt.qGraCompt[element(((reference.mobj).parent))] + #layoutPt.updateCompartmentSize(x) + rectcompt = calculateChildBoundingRect(v) + comptBoundingRect = v.boundingRect() + if not comptBoundingRect.contains(rectcompt): + layoutPt.updateCompartmentSize(v) + + else: + rectcompt = calculateChildBoundingRect(v) + v.setRect(rectcompt.x()-10,rectcompt.y()-10,(rectcompt.width()+20),(rectcompt.height()+20)) + layoutPt.positionChange(compartments) return handleCollisions(compartments, moveCallback, layoutPt,margin) def calculateChildBoundingRect(compt): @@ -149,7 +167,6 @@ def calculateChildBoundingRect(compt): ypos = [] xpos = [] for l in compt.childItems(): - ''' All the children including pool,reac,enz,polygon(arrow),table ''' if not isinstance(l,QtSvg.QGraphicsSvgItem): if (not isinstance(l,QtGui.QGraphicsPolygonItem)): @@ -158,11 +175,18 @@ def calculateChildBoundingRect(compt): xpos.append(l.pos().x()) ypos.append(l.pos().y()+l.boundingRect().bottomRight().y()) ypos.append(l.pos().y()) + else: + xpos.append(l.sceneBoundingRect().x()) + xpos.append(l.sceneBoundingRect().bottomRight().x()) + ypos.append(l.sceneBoundingRect().y()) + ypos.append(l.sceneBoundingRect().bottomRight().y()) + ''' xpos.append(l.rect().x()) xpos.append(l.boundingRect().bottomRight().x()) ypos.append(l.rect().y()) ypos.append(l.boundingRect().bottomRight().y()) + ''' if (isinstance(l,PoolItem) or isinstance(l,EnzItem)): ''' For Enz cplx height and for pool function height needs to be taken''' for ll in l.childItems(): @@ -185,7 +209,7 @@ def mooseIsInstance(melement, classNames): return element(melement).__class__.__name__ in classNames def findCompartment(melement): - while not mooseIsInstance(melement, ["CubeMesh", "CyclMesh"]): + while not mooseIsInstance(melement, ["CubeMesh", "CylMesh"]): melement = melement.parent return melement @@ -195,6 +219,6 @@ def findGroup(melement): return melement def findGroup_compt(melement): - while not (mooseIsInstance(melement, ["Neutral","CubeMesh", "CyclMesh"])): + while not (mooseIsInstance(melement, ["Neutral","CubeMesh", "CylMesh"])): melement = melement.parent return melement \ No newline at end of file diff --git a/plugins/kkitViewcontrol.py b/plugins/kkitViewcontrol.py index 91113596c36985dbe53f4a1b589341f6122e0b04..1f80fca362aecd8a4a0f453129518c4a38af2cfe 100644 --- a/plugins/kkitViewcontrol.py +++ b/plugins/kkitViewcontrol.py @@ -5,23 +5,29 @@ __version__ = "1.0.0" __maintainer__ = "HarshaRani" __email__ = "hrani@ncbs.res.in" __status__ = "Development" -__updated__ = "Jun 8 2018" +__updated__ = "Oct 27 2018" ''' - -Jun8 : If object is moved from one group or compartment to another group or with in same Compartment, - then both at moose level (group or compartment path is updated ) and qt level the setParentItem is set - -If object is moved to Empty place or not allowed place in the GUI its moved back to origin position - -also some clean up when object is just clicked in QsvgItem and v/s clicked and some action done - -with Rubber selection if object are moved then group size is updated 2018 -Oct 3 : At mousePressEvent, a clean way of checking on what object mouse press Event happened is checked. - This is after group is added where Group Interior and Boundary is checked, with in groupInterior if click in - on COMPARTMENT BOUNDARY is clicked then COMPARTMENT_BOUNDARY is return, else top most group object is returned. -Sep 20: Group related function added - -resolveGroupInteriorAndBoundary, findGraphic_groupcompt, graphicsIsInstance - -@resolveItem,editorMousePressEvent,editorMouseMoveEvent,editorMouseReleaseEvent checks made for group +Oct 27 : When group is moved within another group, outer group is resize inturn compartmet is also resized +Oct 10 : Groups are handled with collision detection, + messagebox when object moved from one group to another + layout updated when object moved etc +Sep 18 : one can close the messagebox if doesn't want to plot +Sep 07 : when object qgraphicalparent is changed then connecting arrow's parent also need to be changed +Jun 08 : If object is moved from one group or compartment to another group or with in same Compartment, + then both at moose level (group or compartment path is updated ) and qt level the setParentItem is set + -If object is moved to Empty place or not allowed place in the GUI its moved back to origin position + -also some clean up when object is just clicked in QsvgItem and v/s clicked and some action done + -with Rubber selection if object are moved then group size is updated 2017 +Oct 03 : At mousePressEvent, a clean way of checking on what object mouse press Event happened is checked. + This is after group is added where Group Interior and Boundary is checked, with in groupInterior if click in + on COMPARTMENT BOUNDARY is clicked then COMPARTMENT_BOUNDARY is return, else top most group object is returned. +Sep 20 : Group related function added + -resolveGroupInteriorAndBoundary, findGraphic_groupcompt, graphicsIsInstance + -@resolveItem,editorMousePressEvent,editorMouseMoveEvent,editorMouseReleaseEvent checks made for group + ''' import sys from modelBuild import * @@ -29,9 +35,11 @@ from constants import * from PyQt4.QtGui import QPixmap, QImage, QPen, QGraphicsPixmapItem, QGraphicsLineItem from PyQt4.QtCore import pyqtSignal from kkitUtil import * -from setsolver import * +#from setsolver import * from PyQt4 import QtSvg from moose import utils +from functools import partial + class GraphicalView(QtGui.QGraphicsView): @@ -142,13 +150,14 @@ class GraphicalView(QtGui.QGraphicsView): elif gsolution[1] == GROUP_INTERIOR: groupInteriorfound = True groupList.append(gsolution) - if item.name == COMPARTMENT: csolution = (item, self.resolveCompartmentInteriorAndBoundary(item, position)) if csolution[1] == COMPARTMENT_BOUNDARY: - comptInteriorfound = True - comptBoundary.append(csolution) - + return csolution + # elif csolution[1] == COMPARTMENT_INTERIOR: + # comptInteriorfound = True + # comptBoundary.append(csolution) + if groupInteriorfound: if comptInteriorfound: return comptBoundary[0] @@ -179,7 +188,6 @@ class GraphicalView(QtGui.QGraphicsView): ##This is kept for reference, so that if object (P,R,E,Tab,Fun) is moved outside the compartment, #then it need to be pull back to original position self.state["press"]["scenepos"] = item.parent().scenePos() - if itemType == COMPARTMENT_INTERIOR or itemType == GROUP_BOUNDARY or itemType == GROUP_INTERIOR: self.removeConnector() @@ -189,9 +197,24 @@ class GraphicalView(QtGui.QGraphicsView): else: #If right button clicked self.resetState() + # if itemType == GROUP_INTERIOR: + # print " self.layoutPt.qGraGrp ",item, item.childItems() + # grouplist = [] + # for i in item.childItems(): + # if isinstance(i,KineticsDisplayItem): + # grouplist.append(i) + # popupmenu = QtGui.QMenu('PopupMenu', self) + # popupmenu.addAction("LinearLayout", lambda : handleCollisions(list(grouplist), moveX, self.layoutPt)) + # popupmenu.addAction("VerticalLayout" ,lambda : handleCollisions(list(grouplist), moveMin, self.layoutPt )) + # popupmenu.exec_(self.mapToGlobal(event.pos())) + # self.layoutPt.updateGrpSize(item) + if itemType == GROUP_BOUNDARY: popupmenu = QtGui.QMenu('PopupMenu', self) popupmenu.addAction("DeleteGroup", lambda : self.deleteGroup(item,self.layoutPt)) + popupmenu.addAction("LinearLayout", lambda : handleCollisions(list(self.layoutPt.qGraGrp.values()), moveX, self.layoutPt)) + popupmenu.addAction("VerticalLayout" ,lambda : handleCollisions(list(self.layoutPt.qGraGrp.values()), moveMin, self.layoutPt )) + #popupmenu.addAction("CloneGroup" ,lambda : handleCollisions(comptList, moveMin, self.layoutPt )) popupmenu.exec_(self.mapToGlobal(event.pos())) @@ -257,10 +280,14 @@ class GraphicalView(QtGui.QGraphicsView): self.drawExpectedConnection(event) if itemType == COMPARTMENT_BOUNDARY or itemType == GROUP_BOUNDARY: + '''When Comparement or group is moved from boundary''' initial = self.mapToScene(self.state["press"]["pos"]) final = self.mapToScene(event.pos()) displacement = final - initial item.moveBy(displacement.x(), displacement.y()) + if isinstance(item.parentItem(),GRPItem): + self.layoutPt.updateGrpSize(item.parentItem()) + self.layoutPt.positionChange(item.mobj.path) self.state["press"]["pos"] = event.pos() @@ -327,7 +354,6 @@ class GraphicalView(QtGui.QGraphicsView): #if already built model then compartment size depends on max and min objects rectcompt = calculateChildBoundingRect(v) v.setRect(rectcompt.x()-10,rectcompt.y()-10,(rectcompt.width()+20),(rectcompt.height()+20)) - else: #When group is moved then compartment need to be update which is done here if isinstance(self.state["release"]["item"], KineticsDisplayItem): @@ -343,98 +369,81 @@ class GraphicalView(QtGui.QGraphicsView): elif clickedItemType == CONNECTOR: actionType = str(self.state["press"]["item"].data(0).toString()) pressItem = self.state["press"]["item"] - + initscenepos = self.state["press"]["scenepos"] + finialscenepos = pressItem.parent().scenePos() + xx = finialscenepos.x()-initscenepos.x() + yy = finialscenepos.y()-initscenepos.y() + movedGraphObj = self.state["press"]["item"].parent() + if actionType == "move": - tobemoved = True - movedGraphObj = self.state["press"]["item"].parent() - if itemType != EMPTY: - item = self.findGraphic_groupcompt(item) - if movedGraphObj.parentItem() != item: - if moose.exists(item.mobj.path+'/'+movedGraphObj.mobj.name): - desObj = item.mobj.className - if desObj == "CubeMesh" or desObj == "CyclMesh": - desObj = "compartment" - elif desObj == "Neutral": - desObj = "group" - tobemoved = False - self.layoutPt.setupDisplay(movedGraphObj.mobj.path+'/info',movedGraphObj,"pool") - self.layoutPt.updateArrow(movedGraphObj) - QtGui.QMessageBox.warning(None,'Could not move the object', "The object name \'%s\' exist in \'%s\' %s" %(movedGraphObj.mobj.name,item.mobj.name,desObj)) - else: - movedGraphObj.setParentItem(item) - moose.move(movedGraphObj.mobj, item.mobj) - if tobemoved: - if isinstance(movedGraphObj,KineticsDisplayItem): - itemPath = movedGraphObj.mobj.path - if moose.exists(itemPath): - iInfo = itemPath+'/info' - anno = moose.Annotator(iInfo) - x = movedGraphObj.scenePos().x()/self.layoutPt.defaultScenewidth - y = movedGraphObj.scenePos().y()/self.layoutPt.defaultSceneheight - anno.x = x - anno.y = y - QtGui.QApplication.setOverrideCursor(QtGui.QCursor(Qt.Qt.ArrowCursor)) - self.layoutPt.positionChange(item.mobj) - self.updateScale(self.iconScale) - ''' - QtGui.QApplication.setOverrideCursor(QtGui.QCursor(Qt.Qt.ArrowCursor)) - #If any case, move is not valide need to move back the object to original position is store and calculation - initscenepos = self.state["press"]["scenepos"] - finialscenepos = pressItem.parent().scenePos() - xx = finialscenepos.x()-initscenepos.x() - yy = finialscenepos.y()-initscenepos.y() - if itemType == EMPTY: - pressItem.parent().moveBy(-xx,-yy) - self.layoutPt.updateArrow(pressItem.parent()) - QtGui.QMessageBox.warning(None,'Could not move the object', "The object can't be moved to empty space") + self.objectpullback("Empty",item,movedGraphObj,xx,yy) + else: - if isinstance(self.state["press"]["item"], Qt.QGraphicsSvgItem): - pressedItem = self.state["press"]["item"] - releaseItem = self.state["release"]["item"] - sgrp = findGroup(pressItem.parent().mobj) - scmpt = findCompartment(pressItem.parent().mobj) - dgrp = findGroup(releaseItem.mobj) - dcmpt = findCompartment(releaseItem.mobj) - if isinstance(dgrp,Neutral): - # This is obj moved from group to - # - another group - # - into compartment - if sgrp.path != dgrp.path: - if scmpt.volume == dcmpt.volume: - #With in same compartment but different group - moose.move(pressItem.parent().mobj,dgrp) - lKey = self.layoutPt.qGraGrp[dgrp] - pressItem.parent().setParentItem(lKey) - self.layoutPt.positionChange(sgrp) - self.layoutPt.positionChange(dgrp) - else: - #If object is tried to move to diff compartment, - # then object will be pulled back to origin position which it was moved from - pressItem.parent().moveBy(-xx,-yy) - self.layoutPt.updateArrow(pressItem.parent()) - QtGui.QMessageBox.warning(None,'Could not move the object', "The object can't be moved to empty space") - elif isinstance(dcmpt,CubeMesh): - # This is obj moved from group into compartment - if scmpt.path != dcmpt.path: - if scmpt.volume == dcmpt.volume: - moose.move(pressItem.parent().mobj,dcmpt) - lKey = self.layoutPt.qGraCompt[dcmpt] - pressItem.parent().setParentItem(lKey) - self.layoutPt.positionChange(sgrp) - self.layoutPt.positionChange(dgrp) + grpCmpt = self.findGraphic_groupcompt(item) + + if movedGraphObj.parentItem() != grpCmpt: + '''Not same compartment/group to which it belonged to ''' + if isinstance(movedGraphObj,FuncItem): + funcPool = moose.element((movedGraphObj.mobj.neighbors['valueOut'])[0]) + parentGrapItem = self.layoutPt.mooseId_GObj[moose.element(funcPool)] + if parentGrapItem.parentItem() != grpCmpt: + self.objectpullback("Functionparent",grpCmpt,movedGraphObj,xx,yy) + + if isinstance(movedGraphObj,(EnzItem,MMEnzItem)): + parentPool = moose.element((movedGraphObj.mobj.neighbors['enzDest'])[0]) + if isinstance(parentPool,PoolBase): + if moose.exists(grpCmpt.mobj.path+'/'+parentPool.name): + if moose.exists(grpCmpt.mobj.path+'/'+parentPool.name+'/'+movedGraphObj.name): + self.objectpullback("Enzyme",grpCmpt,movedGraphObj,xx,yy) + else: + reply = QtGui.QMessageBox.question(self, "Moving the Object",'Do want to move \'{movedGraphObj}\' \n from \'{parent}\' to \'{grpCmpt}\''.format(movedGraphObj=movedGraphObj.mobj.name,parent= movedGraphObj.parentItem().mobj.name,grpCmpt=grpCmpt.mobj.name), + QtGui.QMessageBox.Yes | QtGui.QMessageBox.No) + if reply == QtGui.QMessageBox.No: + movedGraphObj.moveBy(-xx,-yy) + self.layoutPt.updateArrow(movedGraphObj) + + else: + self.moveObjSceneParent(grpCmpt,movedGraphObj,item.pos(),self.mapToScene(event.pos())) else: - #If object is tried to move to diff compartment, - # then object will be pulled back to origin position which it was moved from - pressItem.parent().moveBy(-xx,-yy) - self.layoutPt.updateArrow(pressItem.parent()) - QtGui.QMessageBox.warning(None,'Could not move the object', "The object can't be moved to empty space") + self.objectpullback("Enzymeparent",grpCmpt,movedGraphObj,xx,yy) else: - print " Check what moved when! does it reaches this condition" - - self.layoutPt.positionChange(item.mobj) - self.updateScale(self.iconScale) - ''' + ''' All the other moose object ''' + if moose.exists(grpCmpt.mobj.path+'/'+movedGraphObj.mobj.name): + self.objectpullback("All",grpCmpt,movedGraphObj,xx,yy) + else: + reply = QtGui.QMessageBox.question(self, "Moving the Object",'Do want to move \'{movedGraphObj}\' \n from \'{parent}\' to \'{grpCmpt}\''.format(movedGraphObj=movedGraphObj.mobj.name,parent= movedGraphObj.parentItem().mobj.name,grpCmpt=grpCmpt.mobj.name), + QtGui.QMessageBox.Yes | QtGui.QMessageBox.No) + if reply == QtGui.QMessageBox.No: + movedGraphObj.moveBy(-xx,-yy) + self.layoutPt.updateArrow(movedGraphObj) + else: + self.moveObjSceneParent(grpCmpt,movedGraphObj,item.pos(),self.mapToScene(event.pos())) + else: + '''Same compt/grp to which it was belong to ''' + if isinstance(movedGraphObj,KineticsDisplayItem): + itemPath = movedGraphObj.mobj.path + if moose.exists(itemPath): + iInfo = itemPath+'/info' + anno = moose.Annotator(iInfo) + eventpos = self.mapToScene(event.pos()) + itempos = item.pos() + x = eventpos.x()+(15/2)#-itempos.x() + y = eventpos.y()+(2/2)#-itempos.y() + anno.x = x + anno.y = y + self.layoutPt.updateArrow(itemPath) + QtGui.QApplication.setOverrideCursor(QtGui.QCursor(Qt.Qt.ArrowCursor)) + self.layoutPt.updateGrpSize(movedGraphObj.parentItem()) + self.layoutPt.positionChange(movedGraphObj.mobj) + self.updateScale(self.iconScale) + + if isinstance(grpCmpt,GRPItem): + self.layoutPt.updateGrpSize(movedGraphObj.parentItem()) + elif isinstance(grpCmpt,ComptItem): + self.layoutPt.updateCompartmentSize(movedGraphObj.parentItem()) + QtGui.QApplication.setOverrideCursor(QtGui.QCursor(Qt.Qt.ArrowCursor)) + if actionType == "delete": self.removeConnector() pixmap = QtGui.QPixmap(24, 24) @@ -462,29 +471,18 @@ class GraphicalView(QtGui.QGraphicsView): elif actionType == "plot": element = moose.element(item.parent().mobj.path) if isinstance (element,moose.PoolBase): - if moose.exists(self.modelRoot+'/data/graph_0'): - self.graph = moose.element(self.modelRoot+'/data/graph_0') - else: - moose.Neutral(self.modelRoot+'/data') - moose.Neutral(self.modelRoot+'/data/graph_0') - self.graph = moose.element(self.modelRoot+'/data/graph_0') - plotType = "Conc" msgBox = QtGui.QMessageBox() msgBox.setText('What to plot?') - msgBox.addButton(QtGui.QPushButton('Number'), QtGui.QMessageBox.YesRole) - msgBox.addButton(QtGui.QPushButton('Concentration'), QtGui.QMessageBox.NoRole) - ret = msgBox.exec_() - if ret == 0: - plotType = "N" - tablePath = moose.utils.create_table_path(moose.element(self.modelRoot), self.graph, element, plotType) - table = moose.utils.create_table(tablePath, element, plotType,"Table2") - ''' - tablePath = utils.create_table_path(moose.element(self.modelRoot), self.graph, element, "Conc") - table = utils.create_table(tablePath, element, "Conc","Table2") - ''' - self.layoutPt.plugin.view.getCentralWidget().plotWidgetContainer.plotAllData() - reply = QtGui.QMessageBox.information(self, "plot Object","Plot is added to Graph1", - QtGui.QMessageBox.Ok) + self.pushButtonNumber = QtGui.QPushButton(('Number'))#, QtGui.QMessageBox.YesRole) + self.pushButtonConc = QtGui.QPushButton('Concentration')#, QtGui.QMessageBox.NoRole + self.pushButtonConc.setAutoDefault(False) + self.pushButtonNumber.setAutoDefault(False) + msgBox.addButton(self.pushButtonNumber,QtGui.QMessageBox.YesRole) + msgBox.addButton(self.pushButtonConc,QtGui.QMessageBox.NoRole) + msgBox.buttonClicked.connect(partial(self.onClicked, str(self.modelRoot),element)) + msgBox.exec_() + self.removeConnector() + elif actionType == "clone": if self.state["move"]["happened"]: QtGui.QApplication.setOverrideCursor(QtGui.QCursor(Qt.Qt.ArrowCursor)) @@ -594,7 +592,119 @@ class GraphicalView(QtGui.QGraphicsView): popupmenu.addAction("Move", lambda: self.moveSelections()) popupmenu.exec_(self.mapToGlobal(event.pos())) self.resetState() - + + def onClicked(self,modelRoot,element, btn): + self.modelRoot = modelRoot + if moose.exists(self.modelRoot+'/data/graph_0'): + self.graph = moose.element(self.modelRoot+'/data/graph_0') + else: + moose.Neutral(self.modelRoot+'/data') + moose.Neutral(self.modelRoot+'/data/graph_0') + self.graph = moose.element(self.modelRoot+'/data/graph_0') + + plotType = "Conc" + if btn.text() == "Number": + plotType = "N" + else: + plotType = "Conc" + + tablePath = moose.utils.create_table_path(moose.element(self.modelRoot), self.graph, element, plotType) + table = moose.utils.create_table(tablePath, element, plotType,"Table2") + ''' + tablePath = utils.create_table_path(moose.element(self.modelRoot), self.graph, element, "Conc") + table = utils.create_table(tablePath, element, "Conc","Table2") + ''' + self.layoutPt.plugin.view.getCentralWidget().plotWidgetContainer.plotAllData() + reply = QtGui.QMessageBox.information(self, "plot Object","Plot is added to Graph1", + QtGui.QMessageBox.Ok) + self.removeConnector() + + def objectpullback(self,messgtype,item,movedGraphObj,xx,yy): + if messgtype.lower() != "empty": + desObj = item.mobj.className + if desObj == "CubeMesh" or desObj == "CyclMesh": + desObj = "compartment" + elif desObj == "Neutral": + desObj = "group" + + movedGraphObj.moveBy(-xx,-yy) + self.layoutPt.updateArrow(movedGraphObj) + messgstr="" + if messgtype.lower() == "all": + messgstr = "The object name \'{0}\' exist in \'{1}\' {2}".format(movedGraphObj.mobj.name,item.mobj.name,desObj) + elif messgtype.lower() =="enzymeparent": + messgstr = "The Enzyme parent \'{0}\' doesn't exist in \'{2}\' {1} \n If you need to move the enzyme to {1} first move the parent pool".format(movedGraphObj.mobj.parent.name,desObj,item.mobj.name) + elif messgtype.lower() == "enzyme": + messgstr = "The Enzyme \'{0}\' already exist in \'{2}\' {1}".format(movedGraphObj.mobj.name,desObj,item.mobj.name) + elif messgtype.lower() == "empty": + messgstr = "The object can't be moved to empty space" + elif messgtype.lower() =="functionparent": + messgstr = "The Function parent \'{0}\' doesn't exist in \'{2}\' {1} \n If you need to move the function to {1} first move the parent pool".format(movedGraphObj.mobj.parent.name,desObj,item.mobj.name) + + QtGui.QMessageBox.warning(None,'Could not move the object', messgstr ) + QtGui.QApplication.setOverrideCursor(QtGui.QCursor(Qt.Qt.ArrowCursor)) + + def moveObjSceneParent(self,item,movedGraphObj,itempos,eventpos): + ''' Scene parent object needs to be updated ''' + if isinstance(movedGraphObj,FuncItem): + return + prevPar = movedGraphObj.parentItem() + movedGraphObj.setParentItem(item) + + if isinstance(movedGraphObj,ReacItem): + for ll in self.layoutPt.object2line[movedGraphObj]: + ll[0].setParentItem(item) + moose.move(movedGraphObj.mobj, item.mobj) + self.layoutPt.plugin.mainWindow.objectEditSlot(movedGraphObj.mobj, True) + + if isinstance(movedGraphObj ,PoolItem): + ''' if pool is moved, a check is made to see if this pool is parent of a enzyme + if yes then Graphicalparent is changed, and + not moose path since it will be taken care while we move pool + ''' + pl = (movedGraphObj.mobj).neighbors['nOut'] + for es in pl: + if isinstance(moose.element(es), EnzBase): + if moose.element(moose.element(es).neighbors['enzDest'][0]) == movedGraphObj.mobj: + enzGrapObj = self.layoutPt.mooseId_GObj[moose.element(es)] + enzXpos = enzGrapObj.scenePos().x() + enzYpos = enzGrapObj.scenePos().y() + enzGrapObj.setParentItem(item) + enzGrapObj.setGeometry(enzXpos,enzYpos, + enzGrapObj.gobj.boundingRect().width(), + enzGrapObj.gobj.boundingRect().height()) + for ll in self.layoutPt.object2line[enzGrapObj]: + ll[0].setParentItem(item) + self.layoutPt.updateArrow(enzGrapObj) + ''' Re-calculting the group size after the movement ''' + self.setnewPostion(movedGraphObj,itempos,eventpos) + self.layoutPt.updateArrow(movedGraphObj) + self.layoutPt.positionChange(movedGraphObj.mobj) + if isinstance(prevPar,GRPItem): + if item != prevPar: + + self.layoutPt.updateGrpSize(prevPar) + self.layoutPt.updateGrpSize(item) + + def setnewPostion(self,movedGraphObj,itempos,eventpos): + if isinstance(movedGraphObj,KineticsDisplayItem): + itemPath = movedGraphObj.mobj.path + if moose.exists(itemPath): + iInfo = itemPath+'/info' + anno = moose.Annotator(iInfo) + x = eventpos.x()+(15/2)-itempos.x() + y = eventpos.y()+(2/2)-itempos.y() + if isinstance(movedGraphObj,ReacItem) or isinstance(movedGraphObj,EnzItem) or isinstance(movedGraphObj,MMEnzItem): + movedGraphObj.setGeometry(x,y, + movedGraphObj.gobj.boundingRect().width(), + movedGraphObj.gobj.boundingRect().height()) + elif isinstance(movedGraphObj,PoolItem): + movedGraphObj.setGeometry(x, y,movedGraphObj.gobj.boundingRect().width() + +PoolItem.fontMetrics.width(' '), + movedGraphObj.gobj.boundingRect().height()) + movedGraphObj.bg.setRect(0, 0, movedGraphObj.gobj.boundingRect().width()+PoolItem.fontMetrics.width(' '), movedGraphObj.gobj.boundingRect().height()) + QtGui.QApplication.setOverrideCursor(QtGui.QCursor(Qt.Qt.ArrowCursor)) + def deleteGroup(self,item,layoutPt): reply = QtGui.QMessageBox.question(self, "Deleting Object",'Do want to delete group \'{groupname}\' and its children and connections'.format(groupname=item.mobj.name), QtGui.QMessageBox.Yes | QtGui.QMessageBox.No) @@ -811,6 +921,7 @@ class GraphicalView(QtGui.QGraphicsView): #if ( isinstance(v, PoolItem) or isinstance(v, ReacItem) or isinstance(v, EnzItem) or isinstance(v, CplxItem) ): if isinstance(v,KineticsDisplayItem): v.setFlag(QtGui.QGraphicsItem.ItemIgnoresTransformations, on) + def keyPressEvent(self,event): key = event.key() self.removeConnector() @@ -845,20 +956,6 @@ class GraphicalView(QtGui.QGraphicsView): item.refresh(scale) xpos = item.pos().x() ypos = item.pos().y() - if isinstance(item,ReacItem) or isinstance(item,EnzItem) or isinstance(item,MMEnzItem): - item.setGeometry(xpos,ypos, - item.gobj.boundingRect().width(), - item.gobj.boundingRect().height()) - elif isinstance(item,CplxItem): - item.setGeometry(item.gobj.boundingRect().width()/2,item.gobj.boundingRect().height(), - item.gobj.boundingRect().width(), - item.gobj.boundingRect().height()) - elif isinstance(item,PoolItem) or isinstance(item, PoolItemCircle): - item.setGeometry(xpos, ypos,item.gobj.boundingRect().width() - +PoolItem.fontMetrics.width(' '), - item.gobj.boundingRect().height()) - item.bg.setRect(0, 0, item.gobj.boundingRect().width()+PoolItem.fontMetrics.width(' '), item.gobj.boundingRect().height()) - self.layoutPt.drawLine_arrow(itemignoreZooming=False) self.layoutPt.comptChildrenBoundingRect() @@ -882,21 +979,27 @@ class GraphicalView(QtGui.QGraphicsView): if unselectitem.isSelected() == True: unselectitem.setSelected(0) self.rubberbandlist_qpolygon = self.sceneContainerPt.items(self.mapToScene(QtCore.QRect(x0, y0, x1 - x0, y1 - y0)).boundingRect(), Qt.Qt.IntersectsItemShape) - self.deleteObj(self.rubberbandlist) + for item in self.rubberbandlist_qpolygon: + ''' in RubberbandSelection if entire group object contains then group is removed,if partly selected then group is retained''' + if isinstance(item,GRPItem): + if not (self.mapToScene(QtCore.QRect(x0, y0, x1 - x0, y1 - y0)).boundingRect()).contains(item.sceneBoundingRect()): + self.rubberbandlist_qpolygon.remove(item) + + self.deleteObj(self.rubberbandlist_qpolygon) self.selections = [] def deleteObj(self,item): self.rubberbandlist = item mooseDeleteChemSolver(self.layoutPt.modelRoot) - self.Enz_cplxlist = [ i for i in self.rubberbandlist if (isinstance(i,MMEnzItem) or isinstance(i,EnzItem) or isinstance(i,CplxItem) )] - self.PFRSlist = [ i for i in self.rubberbandlist if (isinstance(i,PoolItem) or isinstance(i,TableItem) or isinstance(i,ReacItem) or isinstance(i,FuncItem) )] - self.grp = [ i for i in self.rubberbandlist if isinstance(i,GRPItem)] - for item in self.Enz_cplxlist: + self.list_EnzReccplx = [ i for i in self.rubberbandlist if (isinstance(i,MMEnzItem) or isinstance(i,EnzItem) or isinstance(i,CplxItem) or isinstance(i,ReacItem) )] + self.list_PFS = [ i for i in self.rubberbandlist if (isinstance(i,PoolItem) or isinstance(i,TableItem) or isinstance(i,FuncItem) )] + self.grp = [ i for i in self.rubberbandlist if isinstance(i,GRPItem)] + for item in self.list_EnzReccplx: #First Loop to remove all the enz b'cos if parent (which is a Pool) is removed, #then it will created problem at qgraphicalitem not having parent. - #So first delete enz and then delete pool + #So first delete enz, then Reac and then delete pool self.deleteItem(item) - for item in self.PFRSlist: + for item in self.list_PFS: if isinstance(item,PoolItem) or isinstance(item,BufPool): plot = moose.wildcardFind(self.layoutPt.modelRoot+'/data/graph#/#') for p in plot: @@ -907,6 +1010,12 @@ class GraphicalView(QtGui.QGraphicsView): self.layoutPt.plugin.view.getCentralWidget().plotWidgetContainer.plotAllData() self.deleteItem(item) for item in self.grp: + key = [k for k,v in self.layoutPt.qGraGrp.items() if v == item] + if key[0] in self.layoutPt.qGraGrp: + self.layoutPt.qGraGrp.pop(key[0]) + self.groupItemlist1 = item.childItems() + self.groupItemlist = [ i for i in self.groupItemlist1 if not isinstance(i,QtGui.QGraphicsPolygonItem)] + self.deleteObj(self.groupItemlist) self.deleteItem(item) def deleteObject2line(self,qpolygonline,src,des,endt):