From aa3418fda456e89305bb42d1d8eb944babd516f1 Mon Sep 17 00:00:00 2001 From: Dilawar Singh <dilawars@ncbs.res.in> Date: Mon, 20 May 2019 09:56:18 +0530 Subject: [PATCH] Squashed 'moose-gui/' changes from d226931..e7786c7 e7786c7 cleanup with mutils 31e493c Objectedit: get color are now place in checkUtil which is now directed, kkit: crosscompartment destination pool is checked 4cee03c importing moose is changed 43a5ace When group is moved within another group, outer group is resize inturn compartmet is also resized c424634 xfer cross compartment molecules are hidden and for cross compartment reaction's connection are now dotted line 8826af5 After collision is handled update of positionchanges is called b375e56 group collision handled, model saving default is sbml,layout coordinates are updated with scenepos for further saving, when object is moved from one group to another message box is setout for confirmation fec1496 coordinates for kkit with factor is done, spell corrected for CylcMesh to CylMesh 9b36f90 Lot of duplicate code removed, seperate function call made when filename or filepath is passed from the command line 33df033 Added model info QmessageBox fd5dfa4 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 68270aa one can close the messagebox if doesn't want to plot 1f2cb4c if object is moved from group/compartment to compartment/group confimation is required before moving c29cede hen vertical or horizontal layout is applied for group, compartment size is recalculated d76d66a Function moved to place other than parentpool location its pullback d034823 color field is not editable for compartment, enzcplxpool and reaction 0a4b1ca compartment boundary is selected if its inside another compartment interior 02b9d39 comparment size is calculated based on group sceneBoundingRect 8dae832 kkitViewcontrol both the groups size are updated if moved from-to is different 44b53bc default: addSolver->mooseAddChemSolver, kkitViewcontrol: while rubberbandselection if entire group is selected then delete if partly selected then delete all the items under the selection 80b599f mgui: is popup exist then close, objectedit: objectwindowTitle is updated with name when changed, kkit: in positionChange all the neutral is updated with size, kkitViewcontrol:when moose object is moved from Compt/group to group/compartment then mooseobject path is set and for qgraphicalItem and qlineitem objects the parentItem is set which will be grpItem or comptItem git-subtree-dir: moose-gui git-subtree-split: e7786c7cb66ca1d78ea75473753464b723cc16d2 --- mgui.py | 170 ++++++++------- mload.py | 7 +- objectedit.py | 25 ++- plugins/default.py | 13 +- plugins/kkit.py | 315 ++++++++++++++++----------- plugins/kkitOrdinateUtil.py | 39 ++-- plugins/kkitUtil.py | 36 +++- plugins/kkitViewcontrol.py | 409 +++++++++++++++++++++++------------- 8 files changed, 617 insertions(+), 397 deletions(-) diff --git a/mgui.py b/mgui.py index 372fde8f..0ecb96fe 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 9fc753e6..3b978328 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 08c38bbb..11a35b66 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 788e8349..3cb28409 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 692de4b2..c375e069 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 dd3b967d..4d27c9ad 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 71859880..09170c20 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 91113596..1f80fca3 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): -- GitLab