Skip to content
Snippets Groups Projects
mtree.py 8.44 KiB
Newer Older
# mtree.py --- 
# 
# Filename: mtree.py
# Description: 
# Author: Subhasis Ray
# Maintainer: 
# Created: Tue May 14 11:51:35 2013 (+0530)
# Version: 
# Last-Updated: Fri Jun 14 16:13:08 2013 (+0530)
#           By: subha
#     Update #: 154
# URL: 
# Keywords: 
# Compatibility: 
# 
# 

# Commentary: 
# 
# Implementation of moose tree widget. This can be used by multiple
# components in the moose gui.
# 
# 

# Change log:
# 
# 
# 
# 
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License as
# published by the Free Software Foundation; either version 3, or
# (at your option) any later version.
# 
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
# General Public License for more details.
# 
# You should have received a copy of the GNU General Public License
# along with this program; see the file COPYING.  If not, write to
# the Free Software Foundation, Inc., 51 Franklin Street, Fifth
# Floor, Boston, MA 02110-1301, USA.
# 
# 

# Code:

import sys
from PyQt4 import QtGui, QtCore
from PyQt4.Qt import Qt
import moose


class MooseTreeModel(QtCore.QAbstractItemModel):
    """Tree model for the MOOSE element tree.
    
    This is not going to work as the MOOSE tree nodes are
    inhomogeneous. The parent of a node is an melement, but the
    children of an melement are vec objects.

    Qt can handle only homogeneous tere nodes.
    """
    def __init__(self, *args):
        super(MooseTreeModel, self).__init__(*args)
        self.rootItem = moose.element('/')

    def index(self, row, column, parent):
        if not self.hasIndex(row, column, parent):
            return QtCore.QModelIndex()
        if not parent.isValid():
            parentItem = self.rootItem
        else:
            parentItem = parent.internalPointer()
        childItem = parentItem.children[row]
        if childItem.path == '/':
            return QtCore.QModelIndex()
        return self.createIndex(row, column, childItem)

    def parent(self, index):
        if not index.isValid():
            return QtCore.QModelIndex()
        childItem = index.internalPointer()
        parentItem = childItem.parent()
        if parentItem == self.rootItem:
            return QtCore.QModelIndex()
        return self.createIndex(parentItem.parent.children.index(parentItem), parentItem.getDataIndex(), parentItem)

    def rowCount(self, parent):
        if not parent.isValid():
            parentItem = self.rootItem
        else:
            parentItem = parent.internalPointer()
        ret = len(parentItem.children)
        return ret

    def columnCount(self, parent):
        if parent.isValid():
            return len(parent.internalPointer())
        ret = len(self.rootItem)
        return ret

    def data(self, index, role):
        if not index.isValid():
            return None
        item = index.internalPointer()
        return QtCore.QVariant(item[index.column()].name)

    def headerData(self, section, orientation, role=Qt.DisplayRole):
        if orientation == QtCore.Qt.Horizontal and role == QtCore.Qt.DisplayRole:  
            return QtCore.QVariant('Model Tree')
        return None

    def flags(self, index):
         if not index.isValid():
             return QtCore.Qt.NoItemFlags
         return QtCore.Qt.ItemIsEnabled | QtCore.Qt.ItemIsSelectable
        
    
class MooseTreeItem(QtGui.QTreeWidgetItem):
    def __init__(self, *args):
	QtGui.QTreeWidgetItem.__init__(self, *args)
	self.mobj = None

    def setObject(self, element):
        self.mobj = moose.element(element)
	self.setText(0, QtCore.QString(self.mobj.path.rpartition('/')[-1]))
	self.setText(1, QtCore.QString(self.mobj.className))
	#self.setToolTip(0, QtCore.QString('class:' + self.mooseObj_.className))

    def updateSlot(self):
	self.setText(0, QtCore.QString(self.mobj.name))


class MooseTreeWidget(QtGui.QTreeWidget):
    """Widget for displaying MOOSE model tree.

    """
    # Author: subhasis ray
    #
    # Created: Tue Jun 23 18:54:14 2009 (+0530)
    #
    # Updated for moose 2 and multiscale GUI: 2012-12-06
    # Further updated for pymoose2: Tue May 14 14:35:35 IST 2013

    # Ignored are elements to be ignored when building the tree
    ignored = ['/Msgs', '/classes']
    elementInserted = QtCore.pyqtSignal('PyQt_PyObject')
    def __init__(self, *args):
        """A tree widget to display model tree in MOOSE.

        Members:
        
        rootElement: melement
                    root element for the tree.

        SIGNAL:

        elementInserted(melement) emitted when a new element is inserted.

        """
	QtGui.QTreeWidget.__init__(self, *args)
        self.header().hide()
	self.rootElement = moose.element('/')
	self.odict = {}
        self.recreateTree()        

    def setupTree(self, obj, parent, odict):
        """Recursively setup the tree items.
        
        Parameters
        ----------
        obj: melement
        object to be associated with the tree item created.

        parent: MooseTreeItem
        parent item of the current tree item
                
        odict: dict
        dictionary to store melement to tree widget item mapping.
        
        """
        for ii in MooseTreeWidget.ignored:
            if obj.path.startswith(ii):
                return None
	item = MooseTreeItem(parent)
	item.setObject(obj)
	odict[obj] = item
        # TODO: check and verify that this still works with synapses -
        # there have been change in API. - Subha, Fri Sep 19 19:04:35 IST 2014

	for child in obj.children:    
            ch = child
            if child.name in obj.getFieldNames('fieldElementFinfo'):
                ch = obj.getField(child.name)
            for elm in ch:
                self.setupTree(moose.element(elm), item, odict)      
	return item

    def recreateTree(self, root=None):        
        """Clears the current tree and recreates the tree. If root is not
        specified it uses the current `root` otherwise replaces the
        rootElement with specified root element.
        
        Parameter
        ---------
        root: str or melement or vec 
              New root element of the tree. Use current rootElement if `None`
        """        
        self.clear()
        self.odict.clear()
        if root is not None:
            self.rootElement = moose.element(root)
        self.setupTree(self.rootElement, self, self.odict)
        self.setCurrentItem(self.rootElement)
        self.expandToDepth(0)

    def insertElementSlot(self, class_name):
        """Creates an instance of the class class_name and inserts it
        under currently selected element in the model tree."""
        # print 'Inserting element ...', class_name
        current = self.currentItem()
        print 'CLASS NAME:', class_name
        self.insertChildElement(current, class_name)

    def insertChildElement(self, item, class_name, name=''):
        if len(name) == 0:
            name = class_name
        path = '%s/%s' % (item.mobj.path, str(name))
        mclassname = 'moose.%s' % (str(class_name))
        mclass = eval(mclassname)
        obj = mclass(path)
        newitem = MooseTreeItem(item)
        newitem.setObject(obj)
        item.addChild(newitem)
        self.odict[obj] = newitem
        self.elementInserted.emit(obj)
        

    def setCurrentItem(self, item):
        """Overloaded version of QTreeWidget.setCurrentItem

        - adds ability to set item by corresponding moose object.
        """
        if isinstance(item, QtGui.QTreeWidgetItem):
            QtGui.QTreeWidget.setCurrentItem(self, item)
            return        
        mobj = moose.element(item)
        QtGui.QTreeWidget.setCurrentItem(self, self.odict[mobj])

    def updateItemSlot(self, element):
        self.odict[element].updateSlot()
        
def main():
    """Test main: load a model and display the tree for it"""
    model = moose.Neutral('/model')
    moose.loadModel('../Demos/Genesis_files/Kholodenko.g', '/model/Kholodenko')
    # tab = moose.element('/model/Kholodenko/graphs/conc1/MAPK_PP.Co')
    # print tab
    # for t in tab.children:
    #     print t
    app = QtGui.QApplication(sys.argv)
    mainwin = QtGui.QMainWindow()
    mainwin.setWindowTitle('Model tree test')
    tree = MooseTreeWidget()
    tree.recreateTree(root='/model/')
    mainwin.setCentralWidget(tree)
    mainwin.show()
    sys.exit(app.exec_())


if __name__ == "__main__":
    main()
    

# 
# mtree.py ends here