#######################################################################
#
# $Id: Project.py,v 1.4 2008-03-28 06:25:37 lorenz Exp $
# 
# Copyright (C) 2004-2008 Petr Lorenz
# All rights reserved.
# 
# ##### BEGIN LICENSE BLOCK #####
#
# Version: MPL 1.1 / GPL 2.0 / LGPL 2.1
#
# The contents of this file are subject to the Mozilla Public License
# Version 1.1 (the "License"); you may not use this file except in
# compliance with the License. You may obtain a copy of the License at
# http://www.mozilla.org/MPL/
# 
# Software distributed under the License is distributed on an "AS IS"
# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
# License for the specific language governing rights and limitations
# under the License.
# 
# The Original Code is Petr Lorenz emGine Graphical User Interface (GUI).
# 
# The Initial Developer of the Original Code is Petr Lorenz.
# Portions created by the Initial Developer are Copyright (C) 2004-2008.
# All Rights Reserved.
# 
# Contributor(s): Bruno Biscontini, Rachid Khlifi.
# 
# Alternatively, the contents of this file may be used under the terms of
# either the GNU General Public License Version 2 or later (the  "GPL"), or the
# GNU Lesser General Public License Version 2.1 or later (the "LGPL"), in which
# case the provisions of the GPL or the LGPL are applicable instead of those
# above.  If you wish to allow use of your version of this file only under the
# terms of either the GPL or the LGPL and not to allow others to use your
# version of this file under the MPL, indicate your decision by deleting the
# provisions above and replace them with the notice and other provisions
# required by the GPL or LGPL.  If you do not delete the provisions above, a
# recipient may use your version of this file under the terms of any one of the
# MPL License, the GPL or the LGPL.
#
# ##### END LICENSE BLOCK #####
#
#######################################################################
# 
# $Log: Project.py,v $
# Revision 1.4  2008-03-28 06:25:37  lorenz
# - Perspective/Orthogonal view
# - Top/Bottom/Front/Back/Left/Right views
# - Boundary conditions setup
# - Platform Info
#
# Revision 1.3  2008-02-07 05:45:25  lorenz
# * Fixed 'Simulation Boundary View' check problem
#   when closing a project.
#
# * Fixed Bounding Box problems when moving/editing a geometry.
#
# Revision 1.2  2008-01-28 16:14:38  lorenz
# Main tag of EMM file changed to 'emGine'
#
# Revision 1.1.1.1  2008-01-28 06:15:35  lorenz
# Import emGine GUI v. 0.7.1
#
# Revision 1.6  2007-07-02 06:37:18  lorenz
# Clean up of old code.
#
# Revision 1.5  2007-06-18 15:55:56  lorenz
# Bugfix for reading a surrounding space with 'None' entries
#
# Revision 1.4  2007-06-14 06:31:51  lorenz
# Added emGine settings handling.
# Better handling of GUI state through GUIState class.
#
# Revision 1.3  2007-05-18 16:37:01  lorenz
# Work on 'surrounding space' simbox and
#  'emgine_gui' tag
#
# Revision 1.2  2007-05-14 04:53:51  lorenz
# New code for multiport time-domain signals and S-parameters
#
# Revision 1.1.1.1  2007-05-08 06:22:35  lorenz
# Initial Import
#
#######################################################################

# January 2006 - March 2008

import os
from xml.dom.minidom import parse, parseString, Node

from SurroundingSpace import SurroundingSpace

import consts

############################################
## Project class
############################################
class Project:
  def __init__(self):
    self.state = consts.PRJ_STATE_INITIALIZED
    self.fname = consts.PRJ_DEFAULT_FNAME
    self.dom = None

  def new(self, prj_args):
    if self.state is not consts.PRJ_STATE_INITIALIZED:
      return
    #new_project = "<emGine version=\"%s\"><project name=\"%s\" units=\"%s\">%s</project></emGine>" %(consts.PRJ_TLMGUI_VERSION, prj_args[0], prj_args[1], consts.DEFAULT_PROJECT)
    new_project = "<emGine version=\"%s\"><project name=\"%s\">%s</project></emGine>" %(consts.PRJ_TLMGUI_VERSION, prj_args[0], consts.DEFAULT_PROJECT)
    #new_project = "<?xml version=\"1.0\" encoding=\"ISO-8859-1\"?>\n<emGine/>"
    #print new_project
    self.dom = parseString(new_project)

    self.set_units(prj_args[1:])
    self.state = consts.PRJ_STATE_NEW
    print "Defining new project"

  ###------------------------------
  ### open_working_file
  ###------------------------------
  def open_working_file(self, fname_):
    if self.state is not consts.PRJ_STATE_INITIALIZED:
      return

    # change the working directory
    pth = os.path.split(fname_)
    print ">> New CWD: ", pth[0]
    os.chdir(pth[0])

    self.fname = pth[1]
    self.dom = parse(self.fname)
    #print self.dom.toxml()
    # TODO: check here for the version
    #print self.dom.getElementsByTagName("emGine")
    self.state = consts.PRJ_STATE_OPENED


  ###------------------------------
  ### save
  ###------------------------------
  def save(self, fname_ = None):
    if not fname_:
      fname_ = self.fname
    f = open(fname_, "w")
    self.dom.writexml(f, indent = "")
    f.close()

    self.fname = fname_
    self.state = consts.PRJ_STATE_SAVED

    # change the working directory
    pth = os.path.split(fname_)
    dir = pth[0]
    if dir:
      os.chdir(pth[0])

  #
  # return True, if the project has been modified
  #
  def modified(self):
    #print "Project::modified called! state = " + str(self.state)
    if self.state == consts.PRJ_STATE_MODIFIED:
      return True
    if self.state == consts.PRJ_STATE_NEW:
      return True
    return False

  ###---------------
  ### get_file_name
  ###---------------
  def get_file_name(self):
    pth = os.path.split(self.fname)
    return pth[1]

  ###--------------------------------
  ### get_project_name
  ###
  ### Return the name of the project
  ###--------------------------------
  def get_project_name(self):
    if not self.dom:
      return ''

    project_node = self.dom.getElementsByTagName(consts.XML_TAG_PROJECT)[0]    # !! TODO: only the first project !
    return project_node.getAttribute(consts.XML_ATTR_NAME)

  ###-----------
  ### get_units
  ###-----------
  def get_units(self):
    if not self.dom:
      return None

    # project_node = self.dom.getElementsByTagName(consts.XML_TAG_PROJECT)[0]    # !! TODO: only the first project !
    # return float(project_node.getAttribute(consts.XML_ATTR_UNITS))

    units_node = self.dom.getElementsByTagName(consts.XML_TAG_UNITS)
    units = {}
    for node in units_node.item(0).childNodes:
      if node.nodeType == Node.ELEMENT_NODE:
	value_node = node.childNodes[0]
	units[node.localName] = float(value_node.nodeValue)

    #print units
    return units


  ###------------------------
  ### get 2D point from node
  ###------------------------
  def get_point2d(self, node):
    point = None
    comp_v = {consts.XML_TAG_POINT2D_COMPONENTS[0] : None, consts.XML_TAG_POINT2D_COMPONENTS[1] : None}   # verbose components in a dictionary
    if node.localName == consts.XML_TAG_POINT2D:
      #print "Project::get_point2d - reading point"
      for data in node.childNodes:
	if data.nodeType == Node.ELEMENT_NODE:
	  if data.localName in consts.XML_TAG_POINT2D_COMPONENTS:
	    value_node = data.childNodes[0]
	    comp_v[data.localName] = value_node.nodeValue

    if None not in comp_v.values():
      point = [0.0, 0.0]
      for ind in range(2):
	point[ind] = float(comp_v[consts.XML_TAG_POINT2D_COMPONENTS[ind]])

    return point

  # get 3D point from node
  def get_point3d(self, node):
    point = None
    comp_v = {consts.XML_TAG_POINT3D_COMPONENTS[0] : None, consts.XML_TAG_POINT3D_COMPONENTS[1] : None, consts.XML_TAG_POINT3D_COMPONENTS[2] : None}   # verbose components in a dictionary
    if node.localName == consts.XML_TAG_POINT3D:
      #print "Project::get_point3d - reading point"
      for data in node.childNodes:
	if data.nodeType == Node.ELEMENT_NODE:
	  if data.localName in consts.XML_TAG_POINT3D_COMPONENTS:
	    value_node = data.childNodes[0]
	    comp_v[data.localName] = value_node.nodeValue

    if None not in comp_v.values():
      point = [0.0, 0.0, 0.0]
      for ind in range(3):
	point[ind] = float(comp_v[consts.XML_TAG_POINT3D_COMPONENTS[ind]])

    return point

  # read a list of 2D points
  def get_list_points2d(self, node):
    points = None
    if node.localName == consts.XML_TAG_POINTS:
      points = []
      for data in node.childNodes:
	if data.nodeType == Node.ELEMENT_NODE:
	  point = self.get_point2d(data)
	  if point:
	    points.append(point)

      if len(points) == 0:
	points = None
    return points

  # get 2D vector components from node
  def get_vector2d(self, node):
    vector = None
    comp_v = {consts.XML_TAG_VECTOR2D_COMPONENTS[0] : None, consts.XML_TAG_VECTOR2D_COMPONENTS[1] : None}   # verbose components in a dictionary
    if node.localName == consts.XML_TAG_VECTOR2D:
      #print "Project::get_vector2d - reading vector"
      for data in node.childNodes:
	if data.nodeType == Node.ELEMENT_NODE:
	  if data.localName in consts.XML_TAG_VECTOR2D_COMPONENTS:
	    value_node = data.childNodes[0]
	    comp_v[data.localName] = value_node.nodeValue

    if None not in comp_v.values():
      vector = [0.0, 0.0]
      for ind in range(2):
	vector[ind] = float(comp_v[consts.XML_TAG_VECTOR2D_COMPONENTS[ind]])

    return vector

  # get 3D vector components from node
  def get_vector3d(self, node):
    vector = None
    comp_v = {consts.XML_TAG_VECTOR3D_COMPONENTS[0] : None, consts.XML_TAG_VECTOR3D_COMPONENTS[1] : None, consts.XML_TAG_VECTOR3D_COMPONENTS[2] : None}   # verbose components in a dictionary
    if node.localName == consts.XML_TAG_VECTOR3D:
      #print "Project::get_vector3d - reading vector"
      for data in node.childNodes:
	if data.nodeType == Node.ELEMENT_NODE:
	  if data.localName in consts.XML_TAG_VECTOR3D_COMPONENTS:
	    value_node = data.childNodes[0]
	    comp_v[data.localName] = value_node.nodeValue

    if None not in comp_v.values():
      vector = [0.0, 0.0, 0.0]
      for ind in range(3):
	vector[ind] = float(comp_v[consts.XML_TAG_VECTOR3D_COMPONENTS[ind]])

    return vector

  def get_all_geometries(self):
    # FIXME: this routine is q&d

    #print "Project::get_all_geometries returning a list of all geometrical objects"
    geometry = self.dom.getElementsByTagName(consts.XML_TAG_GEOMETRY)
    geom_list = list()
    for node in geometry.item(0).childNodes:
      if node.nodeType == Node.ELEMENT_NODE:
        object = {}
        object[consts.XML_ATTR_NAME] = node.getAttribute(consts.XML_ATTR_NAME)
	object[consts.XML_ATTR_GEOMETRY_MATERIAL] = node.getAttribute(consts.XML_ATTR_GEOMETRY_MATERIAL)

        object[consts.XML_TAG_GEOMETRY] = node.localName
	if node.localName == consts.XML_TAG_POLYGON2D:
	  print "Project::get_all_geometries reading polygon"
	  for data in node.childNodes:
	    if data.nodeType == Node.ELEMENT_NODE:
	      if data.localName == consts.XML_TAG_NORMAL:
		#print "Reading normal"
		normal = None
		for ndata in data.childNodes:
		  if ndata.nodeType == Node.ELEMENT_NODE:
		    normal = self.get_vector3d(ndata)
		    break
		if not normal:
		  print "!! Warning !! Definition of normal for POLYGON2D not found!"
		else:
		  object[data.localName] = normal
	      elif data.localName == consts.XML_TAG_LEVEL:
		#print "Reading level"
		value_node = data.childNodes[0]
		level = float(value_node.nodeValue)
		object[data.localName] = level
	      elif data.localName == consts.XML_TAG_POINTS:
		#print "Reading points"
		points = self.get_list_points2d(data)
		if not points:
		  print "!! Warning !! Could not read point list for POLYGON2D!"
		else:
		  object[data.localName] = points
	      else:
		print "!! Warning !! >>", data.localName, "<< Unknown definition for POLYGON2D!"
	else:
	  for data in node.childNodes:
	    if data.nodeType == Node.ELEMENT_NODE:
	      if data.hasChildNodes():
		#
		# FIXME: If ELEMENT_NODE type is a Child
		#        then the value is not necessarily the
		#        first child!, i.e., childNodes[0]
		#
		value = ""
		value_node = data.childNodes[0]
		if value_node.nodeType == Node.TEXT_NODE:
		  value = value_node.nodeValue
		elif value_node.nodeType == Node.ELEMENT_NODE:
		  value = value_node.localName
		object[data.localName] = value
	object[consts.GUI_XML_NODE] = node
        geom_list.append(object)

    return geom_list 

  def get_all_materials(self):
    # FIXME: this routine is q&d
    #
    #print "Project::get_all_materials returning a list of all materials objects"
    material = self.dom.getElementsByTagName(consts.XML_TAG_MATERIALS)
    material_list = list()
    for node in material.item(0).childNodes:
      if node.nodeType == Node.ELEMENT_NODE:
        object = {}
        object[consts.XML_ATTR_NAME] = node.getAttribute(consts.XML_ATTR_NAME)
        object[consts.XML_TAG_MATERIALS] = node.localName
        for data in node.childNodes:
          if data.nodeType == Node.ELEMENT_NODE:
            if data.hasChildNodes():
              #
              # FIXME: If ELEMENT_NODE type is a Child
              #        then the value is not necessarily the
              #        first child!, i.e., childNodes[0]
              #
              value = ""
              value_node = data.childNodes[0]
              if value_node.nodeType == Node.TEXT_NODE:
                value = value_node.nodeValue
              elif value_node.nodeType == Node.ELEMENT_NODE:
                value = value_node.localName
              object[data.localName] = value
	object[consts.GUI_XML_NODE] = node
        material_list.append(object)

    return material_list 

  def get_all_excitations(self):
    print "Project::get_all_excitations returning a list of all excitation objects"
    excitation = self.dom.getElementsByTagName(consts.XML_TAG_EXCITATION)
    excit_list = list()		# the list will be returned
    for node in excitation.item(0).childNodes:
      if node.nodeType == Node.ELEMENT_NODE:
	object = {}		# associative list
	object[consts.XML_ATTR_NAME] = node.getAttribute(consts.XML_ATTR_NAME)
	object[consts.XML_TAG_EXCITATION] = node.localName
	for data in node.childNodes:
	  if data.nodeType == Node.ELEMENT_NODE:
	    if data.hasChildNodes():
              #
              # FIXME: If ELEMENT_NODE type is a Child
              #        then the value is not necessarily the
              #        first child!, i.e., childNodes[0]
              #
	      value = ""
	      value_node = data.childNodes[0]
	      if value_node.nodeType == Node.TEXT_NODE:
		value = value_node.nodeValue
	      elif value_node.nodeType == Node.ELEMENT_NODE:
		value = value_node.localName
	      object[data.localName] = value
	object[consts.GUI_XML_NODE] = node
	excit_list.append(object)

    return excit_list

  def get_all_results(self, type):
    results = self.dom.getElementsByTagName(consts.XML_TAG_RESULTS)
    results_list = list()		# the list will be returned
    if results:
      for node in results.item(0).childNodes:
	if node.nodeType == Node.ELEMENT_NODE:
	  if node.getAttribute(consts.XML_ATTR_RESULT_TYPE) == type:		# is this the result of the given type?
	    for resnode in node.childNodes:
	      if resnode.nodeType == Node.ELEMENT_NODE:
		object = {}		# associative list
		object[consts.XML_ATTR_NAME] = resnode.getAttribute(consts.XML_ATTR_NAME)
		object[consts.XML_TAG_RESULTS] = resnode.localName
		for data in resnode.childNodes:
		  if data.nodeType == Node.ELEMENT_NODE:
		    if data.hasChildNodes():
		      #
		      # FIXME: If ELEMENT_NODE type is a Child
		      #        then the value is not necessarily the
		      #        first child!, i.e., childNodes[0]
		      #
		      value = ""
		      value_node = data.childNodes[0]
		      if value_node.nodeType == Node.TEXT_NODE:
			value = value_node.nodeValue
		      elif value_node.nodeType == Node.ELEMENT_NODE:
			value = value_node.localName
		      object[data.localName] = value
		object[consts.GUI_XML_NODE] = resnode
		results_list.append(object)

    return results_list

  ### Return the settings of the emGine GUI
  def get_emginegui_settings(self):
    emginegui_settings = self.dom.getElementsByTagName(consts.XML_TAG_EMGINE_GUI)
    settings = 	{}	# store all the settings in this dictionary
    if len(emginegui_settings) != 0:	# only if not empty
      for node in emginegui_settings.item(0).childNodes:
	if node.nodeType == Node.ELEMENT_NODE:
	  setting = {}	# dictionary for a setting
	  if node.localName == consts.XML_TAG_SURROUNDING_SPACE:
	    print "Reading surrounding space settings" 
	    setting = self.get_data_as_dictionary(node)

	  settings[node.localName] = setting

    return settings

  # get all file sources defined as children of the node
  def get_file_sources(self, node):
    files = list()
    for child_node in node.childNodes:
      if child_node.nodeType == Node.ELEMENT_NODE:
	if child_node.localName == consts.XML_TAG_FILE:
	  files.append(child_node.getAttribute(consts.XML_ATTR_FILE_SRC))
    return files

  # return a dictionary of results based on the 
  # information in the DOM
  def get_results(self, type = consts.RESULT_TYPE_SIMULATION):
    results = {}
    results["tds_file"] = list()	# erase the list of files
    #results["resobjs"] = list()		# just for testing !!!
    #results["tdsignals"] = list()	# list of time-domain signals
    #results["sparams"] = list()		# list of S-parameters
    #results["zparams"] = list()	# list of impedances

    results_list = self.get_all_results(type)
    #print results_list
    for result in results_list:
      node = result[consts.GUI_XML_NODE]
      if node.localName == consts.XML_TAG_TDSIGNAL:
	for fsource in self.get_file_sources(node):
	  results["tds_file"].append(fsource)

    if len(results["tds_file"]) == 0:	# return None if no results available
      return None
    return results

  # return a dictionary of reference results
  # based on the information in the DOM
  #
  # if no reference - return None
  def get_ref_results(self):
    return self.get_results(consts.RESULT_TYPE_REFERENCE)

  def get_surrounding_space(self):
    # FIXME: this routine not done
    #print "Project::get_surrounding_space called"
    settings = self.get_emginegui_settings()
    if len(settings):
      surr_space = settings[consts.XML_TAG_SURROUNDING_SPACE]

      print surr_space
      box = [None, None, None, None, None, None]
      box[0] = surr_space[consts.XML_TAG_X1]
      box[1] = surr_space[consts.XML_TAG_Y1]
      box[2] = surr_space[consts.XML_TAG_Z1]
      box[3] = surr_space[consts.XML_TAG_X2]
      box[4] = surr_space[consts.XML_TAG_Y2]
      box[5] = surr_space[consts.XML_TAG_Z2]

      for i in range(len(box)):
	box_e = box[i]
	if (not box_e) or (box_e == 'None'):
	  box[i] = None
	else:
	  box[i] = float(box_e)
	       
      surrounding_space = SurroundingSpace([[box[0], box[1], box[2]], [box[3], box[4], box[5]]])
    else:
      surrounding_space = SurroundingSpace()

    return surrounding_space
             
  def delete_geometry_node(self, node):
    self.state = consts.PRJ_STATE_MODIFIED

    geometry = self.dom.getElementsByTagName(consts.XML_TAG_GEOMETRY)
    geometry[0].removeChild(node)       # we use only one geometry block in EMM file
    # FIXME: unlink method should be called?!

  def delete_material_node(self, node):
    self.state = consts.PRJ_STATE_MODIFIED

    materials = self.dom.getElementsByTagName(consts.XML_TAG_MATERIALS)
    materials[0].removeChild(node)       # we use only one material block in EMM file
    # FIXME: unlink method should be called?!

  def delete_excitation_node(self, node):
    self.state = consts.PRJ_STATE_MODIFIED

    excitations = self.dom.getElementsByTagName(consts.XML_TAG_EXCITATION)
    excitations[0].removeChild(node)       # we use only one material block in EMM file
    # FIXME: unlink method should be called?!

  ### FIXME: should the method 'generate_patch_element' 
  ###        be a method of GeometryObjectPatch ?
  def generate_patch_element(self, data):
    name = data[0]
    x1 = data[1]
    y1 = data[2]
    z1 = data[5]
    length_x= data[3]
    length_y = data[4]
    material = data[-1]

    new_geometry = self.dom.createElement(consts.XML_TAG_PATCH)
    attr_geometry = self.dom.createAttribute(consts.XML_ATTR_NAME)
    new_geometry.setAttributeNode(attr_geometry)
    new_geometry.setAttribute(consts.XML_ATTR_NAME, name)

    self.set_attr(new_geometry, consts.XML_ATTR_GEOMETRY_MATERIAL, material)

    x1_node = self.dom.createElement(consts.XML_TAG_X1)
    x1_text = self.dom.createTextNode(x1)
    x1_node.appendChild(x1_text)

    y1_node = self.dom.createElement(consts.XML_TAG_Y1)
    y1_text = self.dom.createTextNode(y1)
    y1_node.appendChild(y1_text)

    z1_node = self.dom.createElement(consts.XML_TAG_Z1)
    z1_text = self.dom.createTextNode(z1)
    z1_node.appendChild(z1_text)

    length_x_node = self.dom.createElement(consts.XML_TAG_LENGTH_X)
    length_x_text = self.dom.createTextNode(length_x)
    length_x_node.appendChild(length_x_text)

    length_y_node = self.dom.createElement(consts.XML_TAG_LENGTH_Y)
    length_y_text = self.dom.createTextNode(length_y)
    length_y_node.appendChild(length_y_text)

    new_geometry.appendChild(x1_node)
    new_geometry.appendChild(y1_node)
    new_geometry.appendChild(z1_node)
    new_geometry.appendChild(length_x_node)
    new_geometry.appendChild(length_y_node)

    return new_geometry

  def add_geometry_patch(self, data):
    self.state = consts.PRJ_STATE_MODIFIED
    
    # update DOM
    geometry_node = self.dom.getElementsByTagName(consts.XML_TAG_GEOMETRY)[0]
    new_geometry = self.generate_patch_element(data)
    geometry_node.appendChild(new_geometry)

    #print geometry_node

  def generate_circle_element(self, data):
    name = data[0]
    x1 = data[1]
    y1 = data[2]
    radius = data[3]
    z1 = data[4]
    material = data[-1]

    new_geometry = self.dom.createElement(consts.XML_TAG_CIRCLE)
    attr_geometry = self.dom.createAttribute(consts.XML_ATTR_NAME)
    new_geometry.setAttributeNode(attr_geometry)
    new_geometry.setAttribute(consts.XML_ATTR_NAME, name)

    self.set_attr(new_geometry, consts.XML_ATTR_GEOMETRY_MATERIAL, material)

    x1_node = self.dom.createElement(consts.XML_TAG_X1)
    x1_text = self.dom.createTextNode(x1)
    x1_node.appendChild(x1_text)

    y1_node = self.dom.createElement(consts.XML_TAG_Y1)
    y1_text = self.dom.createTextNode(y1)
    y1_node.appendChild(y1_text)

    z1_node = self.dom.createElement(consts.XML_TAG_Z1)
    z1_text = self.dom.createTextNode(z1)
    z1_node.appendChild(z1_text)

    orientation_node = self.dom.createElement(consts.XML_TAG_CYLINDER_ORIENTATION)
    orientation_text = self.dom.createElement(consts.XML_TAG_ORIENTATION_Z)
    orientation_node.appendChild(orientation_text)
    
    radius_node = self.dom.createElement(consts.XML_TAG_RADIUS)
    radius_text = self.dom.createTextNode(radius)
    radius_node.appendChild(radius_text)

    new_geometry.appendChild(x1_node)
    new_geometry.appendChild(y1_node)
    new_geometry.appendChild(z1_node)
    new_geometry.appendChild(orientation_node)
    new_geometry.appendChild(radius_node)

    return new_geometry

  def add_geometry_circle(self, data):
    self.state = consts.PRJ_STATE_MODIFIED

    # update DOM
    geometry_node = self.dom.getElementsByTagName(consts.XML_TAG_GEOMETRY)[0]
    new_geometry = self.generate_circle_element(data)
    geometry_node.appendChild(new_geometry)

  def generate_polygon_element(self, data):
    points = data[0]
    data_text = data[1]
    normal_v = data[2]

    name = data_text[0]
    level = float(data_text[1])

    material = data[-1]

    new_geometry = self.dom.createElement(consts.XML_TAG_POLYGON2D)
    attr_geometry = self.dom.createAttribute(consts.XML_ATTR_NAME)
    new_geometry.setAttributeNode(attr_geometry)
    new_geometry.setAttribute(consts.XML_ATTR_NAME, name)

    self.set_attr(new_geometry, consts.XML_ATTR_GEOMETRY_MATERIAL, material)

    # normal
    normal_node = self.dom.createElement(consts.XML_TAG_NORMAL)
    normal = [0.0, 0.0, 1.0]
    if normal_v == 'x':
      normal = [1.0, 0.0, 0.0]
    elif normal_v == 'y':
      normal = [0.0, 1.0, 0.0]
    vect_node = self.dom.createElement(consts.XML_TAG_VECTOR3D)
    for ind in range(3):
      comp_node = self.dom.createElement(consts.XML_TAG_VECTOR3D_COMPONENTS[ind])
      comp_text = self.dom.createTextNode(str(normal[ind]))
      comp_node.appendChild(comp_text)
      vect_node.appendChild(comp_node)
    normal_node.appendChild(vect_node)

    # level
    level_node = self.dom.createElement(consts.XML_TAG_LEVEL)
    level_text = self.dom.createTextNode(str(level))
    level_node.appendChild(level_text)

    # points
    points_node = self.dom.createElement(consts.XML_TAG_POINTS)
    for point in points:
      point_node = self.dom.createElement(consts.XML_TAG_POINT2D)
      for ind in range(2):
	comp_node = self.dom.createElement(consts.XML_TAG_VECTOR3D_COMPONENTS[ind])
	comp_text = self.dom.createTextNode(str(point[ind]))
	comp_node.appendChild(comp_text)
	point_node.appendChild(comp_node)
      points_node.appendChild(point_node)

    # append new tags
    new_geometry.appendChild(normal_node)
    new_geometry.appendChild(level_node)
    new_geometry.appendChild(points_node)

    return new_geometry

  def add_geometry_polygon(self, data):
    self.state = consts.PRJ_STATE_MODIFIED

    #print "Project::add_geometry_polygon - ", name, normal_v, level, points

    # update DOM
    geometry_node = self.dom.getElementsByTagName(consts.XML_TAG_GEOMETRY)[0]
    new_geometry = self.generate_polygon_element(data)
    geometry_node.appendChild(new_geometry)

  def generate_box_element(self, data):
    name = data[0]
    x1 = data[1]
    y1 = data[2]
    z1 = data[3]
    length_x= data[4]
    length_y = data[5]
    length_z = data[6]
    material = data[-1]

    new_geometry = self.dom.createElement(consts.XML_TAG_CUBE)
    attr_geometry = self.dom.createAttribute(consts.XML_ATTR_NAME)
    new_geometry.setAttributeNode(attr_geometry)
    new_geometry.setAttribute(consts.XML_ATTR_NAME, name)

    self.set_attr(new_geometry, consts.XML_ATTR_GEOMETRY_MATERIAL, material)

    x1_node = self.dom.createElement(consts.XML_TAG_X1)
    x1_text = self.dom.createTextNode(x1)
    x1_node.appendChild(x1_text)

    y1_node = self.dom.createElement(consts.XML_TAG_Y1)
    y1_text = self.dom.createTextNode(y1)
    y1_node.appendChild(y1_text)

    z1_node = self.dom.createElement(consts.XML_TAG_Z1)
    z1_text = self.dom.createTextNode(z1)
    z1_node.appendChild(z1_text)

    length_x_node = self.dom.createElement(consts.XML_TAG_LENGTH_X)
    length_x_text = self.dom.createTextNode(length_x)
    length_x_node.appendChild(length_x_text)

    length_y_node = self.dom.createElement(consts.XML_TAG_LENGTH_Y)
    length_y_text = self.dom.createTextNode(length_y)
    length_y_node.appendChild(length_y_text)

    length_z_node = self.dom.createElement(consts.XML_TAG_LENGTH_Z)
    length_z_text = self.dom.createTextNode(length_z)
    length_z_node.appendChild(length_z_text)

    new_geometry.appendChild(x1_node)
    new_geometry.appendChild(y1_node)
    new_geometry.appendChild(z1_node)
    new_geometry.appendChild(length_x_node)
    new_geometry.appendChild(length_y_node)
    new_geometry.appendChild(length_z_node)

    return new_geometry

  def add_geometry_box(self, data):
    self.state = consts.PRJ_STATE_MODIFIED

    # update DOM
    geometry_node = self.dom.getElementsByTagName(consts.XML_TAG_GEOMETRY)[0]
    new_geometry = self.generate_box_element(data)
    geometry_node.appendChild(new_geometry)

  def generate_cylinder_element(self, data):
    name = data[0]
    x1 = data[1]
    y1 = data[2]
    z1 = data[3]
    radius = data[4]
    height = data[5]
    material = data[-1]

    new_geometry = self.dom.createElement(consts.XML_TAG_CYLINDER)
    attr_geometry = self.dom.createAttribute(consts.XML_ATTR_NAME)
    new_geometry.setAttributeNode(attr_geometry)
    new_geometry.setAttribute(consts.XML_ATTR_NAME, name)

    self.set_attr(new_geometry, consts.XML_ATTR_GEOMETRY_MATERIAL, material)

    x1_node = self.dom.createElement(consts.XML_TAG_X1)
    x1_text = self.dom.createTextNode(x1)
    x1_node.appendChild(x1_text)

    y1_node = self.dom.createElement(consts.XML_TAG_Y1)
    y1_text = self.dom.createTextNode(y1)
    y1_node.appendChild(y1_text)

    z1_node = self.dom.createElement(consts.XML_TAG_Z1)
    z1_text = self.dom.createTextNode(z1)
    z1_node.appendChild(z1_text)

    orientation_node = self.dom.createElement(consts.XML_TAG_CYLINDER_ORIENTATION)
    orientation_text = self.dom.createElement(consts.XML_TAG_ORIENTATION_Z)
    orientation_node.appendChild(orientation_text)
    
    radius_node = self.dom.createElement(consts.XML_TAG_RADIUS)
    radius_text = self.dom.createTextNode(radius)
    radius_node.appendChild(radius_text)

    height_node = self.dom.createElement(consts.XML_TAG_HEIGHT)
    height_text = self.dom.createTextNode(height)
    height_node.appendChild(height_text)

    new_geometry.appendChild(x1_node)
    new_geometry.appendChild(y1_node)
    new_geometry.appendChild(z1_node)
    new_geometry.appendChild(orientation_node)
    new_geometry.appendChild(radius_node)
    new_geometry.appendChild(height_node)

    return new_geometry

  def add_geometry_cylinder(self, data):
    self.state = consts.PRJ_STATE_MODIFIED
    
    # update DOM
    geometry_node = self.dom.getElementsByTagName(consts.XML_TAG_GEOMETRY)[0]
    new_geometry = self.generate_cylinder_element(data)
    geometry_node.appendChild(new_geometry)

  def replace_geometry_general(self, data, old_name, geometry_tag, geometry_generating_function):
    self.state = consts.PRJ_STATE_MODIFIED

    geometry_node = self.dom.getElementsByTagName(consts.XML_TAG_GEOMETRY)[0]
    old_node = self.get_node_with_attr(geometry_tag, consts.XML_ATTR_NAME, old_name, geometry_node)
    new_geometry = geometry_generating_function(data)
    geometry_node.replaceChild(new_geometry, old_node)

  def replace_geometry_patch(self, data, old_name):
    self.replace_geometry_general(data, old_name, consts.XML_TAG_PATCH, self.generate_patch_element)

  def replace_geometry_circle(self, data, old_name):
    self.replace_geometry_general(data, old_name, consts.XML_TAG_CIRCLE, self.generate_circle_element)

  def replace_geometry_polygon(self, data, old_name):
    self.replace_geometry_general(data, old_name, consts.XML_TAG_POLYGON2D, self.generate_polygon_element)

  def replace_geometry_box(self, data, old_name):
    self.replace_geometry_general(data, old_name, consts.XML_TAG_CUBE, self.generate_box_element)

  def replace_geometry_cylinder(self, data, old_name):
    self.replace_geometry_general(data, old_name, consts.XML_TAG_CYLINDER, self.generate_cylinder_element)

  #--
  def add_excitation_voltage_port(self, node, data):
    self.state = consts.PRJ_STATE_MODIFIED

    name = data[0]
    x1 = data[1]
    y1 = data[2]
    z1 = data[3]
    x2 = data[4]
    y2 = data[5]
    z2 = data[6]

    excitation_node = self.dom.getElementsByTagName(consts.XML_TAG_EXCITATION)[0]
    #print excitation_node

    new_excitation = self.dom.createElement(consts.XML_TAG_VOLTAGE_PORT)
    attr_geometry = self.dom.createAttribute(consts.XML_ATTR_NAME)
    new_excitation.setAttributeNode(attr_geometry)
    new_excitation.setAttribute(consts.XML_ATTR_NAME, name)

    x1_node = self.dom.createElement(consts.XML_TAG_X1)
    x1_text = self.dom.createTextNode(x1)
    x1_node.appendChild(x1_text)

    y1_node = self.dom.createElement(consts.XML_TAG_Y1)
    y1_text = self.dom.createTextNode(y1)
    y1_node.appendChild(y1_text)

    z1_node = self.dom.createElement(consts.XML_TAG_Z1)
    z1_text = self.dom.createTextNode(z1)
    z1_node.appendChild(z1_text)

    x2_node = self.dom.createElement(consts.XML_TAG_X2)
    x2_text = self.dom.createTextNode(x2)
    x2_node.appendChild(x2_text)

    y2_node = self.dom.createElement(consts.XML_TAG_Y2)
    y2_text = self.dom.createTextNode(y2)
    y2_node.appendChild(y2_text)

    z2_node = self.dom.createElement(consts.XML_TAG_Z2)
    z2_text = self.dom.createTextNode(z2)
    z2_node.appendChild(z2_text)

    new_excitation.appendChild(x1_node)
    new_excitation.appendChild(y1_node)
    new_excitation.appendChild(z1_node)
    new_excitation.appendChild(x2_node)
    new_excitation.appendChild(y2_node)
    new_excitation.appendChild(z2_node)

    excitation_node.appendChild(new_excitation)

  def set_boundary_conditions(self, data):
    self.state = consts.PRJ_STATE_MODIFIED

    boundaries_node = self.get_node(consts.XML_TAG_BOUNDARIES)

    data_ind = 0
    for boundary_name in [consts.XML_TAG_BOUNDARY_XMIN, consts.XML_TAG_BOUNDARY_XMAX, consts.XML_TAG_BOUNDARY_YMIN, consts.XML_TAG_BOUNDARY_YMAX, consts.XML_TAG_BOUNDARY_ZMIN, consts.XML_TAG_BOUNDARY_ZMAX]: 
      boundary_node = self.get_node_with_attr(consts.XML_TAG_BOUNDARY, consts.XML_ATTR_NAME, boundary_name, boundaries_node)
      bc_node = self.get_node(consts.XML_TAG_BC, boundary_node)
      self.set_attr(bc_node, consts.XML_BC_ATTR_TYPE, data[data_ind])
      #bc_node = self.get_node_with_attr(consts.XML_TAG_BC, consts.XML_BC_ATTR_TYPE, data[data_ind], boundary_node)
      data_ind += 1

  def get_boundary_conditions(self):
    # TODO: Check names of tags !!!!
    #       Better handling of incomplete BCs
    boundary_list = [consts.XML_TAG_BOUNDARY_XMIN, consts.XML_TAG_BOUNDARY_XMAX, consts.XML_TAG_BOUNDARY_YMIN, consts.XML_TAG_BOUNDARY_YMAX, consts.XML_TAG_BOUNDARY_ZMIN, consts.XML_TAG_BOUNDARY_ZMAX] 

    boundaries_node = self.get_node(consts.XML_TAG_BOUNDARIES)
    bc_dict = {}
    for node in boundaries_node.childNodes:
      if node.nodeType == Node.ELEMENT_NODE:
	if node.localName == consts.XML_TAG_BOUNDARY:
	  boundary_name = node.getAttribute(consts.XML_ATTR_NAME)
	  for data in node.childNodes:
	    if data.nodeType == Node.ELEMENT_NODE:
	      if data.localName == consts.XML_TAG_BC:
		bc_dict[boundary_name] = data.getAttribute(consts.XML_BC_ATTR_TYPE)
    bc_list = list()
    for bnd in boundary_list:
      try:
	bc_list.append(bc_dict[bnd])
      except:
	return None

    return bc_list

  def add_boundary(self, node, data):
    None
    #### self.state = consts.PRJ_STATE_MODIFIED

    #### name = data[0]
    #### typ = data[1] 
    #### ref  = data[2]

    #### boundary_node = self.dom.getElementsByTagName(consts.XML_TAG_BOUNDARIES)[0]
    #### #print boundary_node
    #### 
    #### new_boundary = self.dom.createElement(consts.XML_TAG_BOUNDARY)
    #### attr_geometry = self.dom.createAttribute(consts.XML_ATTR_NAME)
    #### new_boundary.setAttributeNode(attr_geometry)
    #### new_boundary.setAttribute(consts.XML_ATTR_NAME, name)

    #### typ_node = self.dom.createElement(consts.XML_TAG_TYP)
    #### typ_text = self.dom.createTextNode(typ)
    #### typ_node.appendChild(typ_text)
    #### 
    #### ref_node = self.dom.createElement(consts.XML_TAG_REF)
    #### ref_text = self.dom.createTextNode(ref)
    #### ref_node.appendChild(ref_text)
    #### 
    #### new_boundary.appendChild(typ_node)
    #### new_boundary.appendChild(ref_node)

    #### boundary_node.appendChild(new_boundary)

  def add_material(self, data):
    self.state = consts.PRJ_STATE_MODIFIED

    name = data[0] 
    epsr = data[1] 
    mur  = data[2] 
    cond = data[3] 
    tand = data[4] 
    
    material_node = self.dom.getElementsByTagName(consts.XML_TAG_MATERIALS)[0]
    #print material_node

    new_material = self.dom.createElement(consts.XML_TAG_MATERIAL)
    attr_geometry = self.dom.createAttribute(consts.XML_ATTR_NAME)
    new_material.setAttributeNode(attr_geometry)
    new_material.setAttribute(consts.XML_ATTR_NAME, name)
    
    epsr_node = self.dom.createElement(consts.XML_TAG_EPSR)
    epsr_text = self.dom.createTextNode(epsr)
    epsr_node.appendChild(epsr_text)
    
    mur_node = self.dom.createElement(consts.XML_TAG_MUR)
    mur_text = self.dom.createTextNode(mur)
    mur_node.appendChild(mur_text)

    cond_node = self.dom.createElement(consts.XML_TAG_CONDUCTIVITY)
    cond_text = self.dom.createTextNode(cond)
    cond_node.appendChild(cond_text)

    tand_node = self.dom.createElement(consts.XML_TAG_TAND)
    tand_text = self.dom.createTextNode(tand)
    tand_node.appendChild(tand_text)

    new_material.appendChild(epsr_node)
    new_material.appendChild(mur_node)
    new_material.appendChild(cond_node)
    new_material.appendChild(tand_node)

    material_node.appendChild(new_material)

  def set_units(self, new_units):
    length_u = new_units[0]
    freq_u = new_units[1]
    time_u = new_units[2]

    units_node = self.get_node(consts.XML_TAG_UNITS)
    self.set_value(units_node, consts.XML_TAG_UNITS_LENGTH, length_u)
    self.set_value(units_node, consts.XML_TAG_UNITS_FREQUENCY, freq_u)
    self.set_value(units_node, consts.XML_TAG_UNITS_TIME, time_u)

  def set_emgine_surrounding_space(self, simbox):
    """ Save the surrounding space (simbox) of the project """
    emgine_node = self.get_node(consts.XML_TAG_EMGINE_GUI)
    surrounding_space_node = self.get_node(consts.XML_TAG_SURROUNDING_SPACE, emgine_node)
    self.set_value(surrounding_space_node, consts.XML_TAG_X1, simbox[0][0])
    self.set_value(surrounding_space_node, consts.XML_TAG_Y1, simbox[0][1])
    self.set_value(surrounding_space_node, consts.XML_TAG_Z1, simbox[0][2])
    self.set_value(surrounding_space_node, consts.XML_TAG_X2, simbox[1][0])
    self.set_value(surrounding_space_node, consts.XML_TAG_Y2, simbox[1][1])
    self.set_value(surrounding_space_node, consts.XML_TAG_Z2, simbox[1][2])
    

  def set_signal_fmin_fmax(self, name, fmin, fmax):
    print "Setting fmin fmax for signal: ", name, " ", fmin, " ", fmax
    signals_node = self.get_node(consts.XML_TAG_SIGNALS)
    gaussmod_node = self.get_node(consts.XML_TAG_SIGNAL_GAUSSIAN_MODULATED, signals_node)
    self.set_value(gaussmod_node, consts.XML_TAG_FREQUENCY_MIN, fmin)
    self.set_value(gaussmod_node, consts.XML_TAG_FREQUENCY_MAX, fmax)

  def set_solver_number_of_time_steps(self, name, timesteps):
    print "Setting number of time steps", timesteps
    simulation_node = self.get_node(consts.XML_TAG_SIMULATION)
    tlm_node = self.get_node(consts.XML_TAG_SIMULATION_TLM, simulation_node)
    self.set_value(tlm_node, consts.XML_TAG_NUMBER_OF_TIME_STEPS, timesteps)

  # Description:
  # get the node with tag node_tag; if parent_node not specified,
  # take the dom root as the parent.
  # If the node does not exist, create a one.
  def get_node(self, node_tag, parent_node = None):
    if not parent_node:
      parent_node = self.dom.getElementsByTagName(consts.XML_TAG_PROJECT)[0]    # !! TODO: only the first project !

    nodes = parent_node.getElementsByTagName(node_tag)
    if (len(nodes) == 0):
      node = self.dom.createElement(node_tag)
      parent_node.appendChild(node)
    else:
      node = nodes[0]   # !! TODO: only the first one taken!!!

    return node

  # Description:
  # get the node with tag node_tag and node_attr with attr_value
  # if parent_node not specified,
  # take the dom root as the parent.
  # If the node does not exist, create a one.
  def get_node_with_attr(self, node_tag, node_attr, attr_value, parent_node = None):
    if not parent_node:
      parent_node = self.dom.getElementsByTagName(consts.XML_TAG_PROJECT)[0]    # !! TODO: only the first project !

    nodes = parent_node.getElementsByTagName(node_tag)

    for cn in nodes:
      if cn.getAttribute(node_attr) == attr_value:
	return cn	# node found, return it

    # node does not exist, create a one
    node = self.dom.createElement(node_tag)
    child_attr = self.dom.createAttribute(node_attr)
    node.setAttributeNode(child_attr)
    node.setAttribute(node_attr, attr_value)
    parent_node.appendChild(node)

    return node

  # Description:
  # set the value of the child node specified by child_tag 
  # of the parent node parent_node to value text node.
  # If the text node does not exist, or the child node does not
  # exist, they are created
  #
  # Return the child node
  def set_value(self, parent_node, child_tag, value):
    value = str(value)                                  # convert value to string
    value_tn = self.dom.createTextNode(value)
  
    child_nodes = parent_node.getElementsByTagName(child_tag)
    child_node = None
    if (len(child_nodes) == 0):
      child_node = self.dom.createElement(child_tag)
      parent_node.appendChild(child_node)
    else:
      child_node = child_nodes[0]       # !! TODO: taking only the first element, what if there are two or more?!

    if child_node.hasChildNodes():      # is there a value already set?
      old_value_tn = child_node.childNodes[0]
      child_node.replaceChild(value_tn, old_value_tn)
      old_value_tn.unlink()             # free from memory
    else:
      child_node.appendChild(value_tn)

    return child_node

  # Description:
  # Set the value of an attribute of a node
  def set_attr(self, node, attr_name_, attr_value_):
    attr_value = str(attr_value_)
    attr_name = str(attr_name_)

    if not node.getAttributeNode(attr_name):	# attribute does not exists ?
      child_attr = self.dom.createAttribute(attr_name)
      node.setAttributeNode(child_attr)

    node.setAttribute(attr_name, attr_value)


  # Description:
  # set the value of the child node specified by child_tag 
  # of the parent node parent_node to value text node.
  # If the text node does not exist, or the child node does not
  # exist, they are created
  # child_attr = (attr_name, attr_value)
  def set_value_for_attr(self, parent_node, child_tag, child_attr, value):
    value = str(value)                                  # convert value to string
    value_tn = self.dom.createTextNode(value)

    (attr_name, attr_value) = child_attr
    attr_name = str(attr_name)
    attr_value = str(attr_value)
  
    child_nodes = parent_node.getElementsByTagName(child_tag)
    child_node = None
    must_create_node = True
    if (len(child_nodes) != 0):
      for cn in child_nodes:
        if cn.getAttribute(attr_name) == attr_value:
          must_create_node = False
          child_node = cn
          break

    if must_create_node:
      child_node = self.dom.createElement(child_tag)
      child_attr = self.dom.createAttribute(attr_name)
      child_node.setAttributeNode(child_attr)
      child_node.setAttribute(attr_name, attr_value)
      parent_node.appendChild(child_node)

    if child_node.hasChildNodes():      # is there a value already set?
      old_value_tn = child_node.childNodes[0]
      child_node.replaceChild(value_tn, old_value_tn)
      old_value_tn.unlink()             # free memory
    else:
      child_node.appendChild(value_tn)

    return child_node

  ### Return a simple dictionary of data stored as childs of node
  ### FIXME: This routine is a quick hack, and should be generalized in future
  ###        to support more general form of data...
  def get_data_as_dictionary(self, node):
    return_data = {}
    for data in node.childNodes:
      if data.nodeType == Node.ELEMENT_NODE:
	if data.hasChildNodes():
	  value = ""
	  value_node = data.childNodes[0]
	  if value_node.nodeType == Node.TEXT_NODE:
	    value = value_node.nodeValue
	  elif value_node.nodeType == Node.ELEMENT_NODE:
	    value = value_node.localName
     	  return_data[data.localName] = value

    return return_data

  def set_tlm_mesh(self, mesh, bdist = 10):
    units = self.get_units()
    units_length = units[consts.XML_TAG_UNITS_LENGTH]

    dl = mesh.get_dl()/units_length
    bbox = mesh.get_bbox()
    print "Project::set_tlm_mesh, min_dl = ", dl, "; bbox = ", bbox

    # Quick&Dirty hack to come away from the boundary
    badd = bdist*dl

    mesh_node = self.get_node(consts.XML_TAG_MESH)
    self.set_value(mesh_node, consts.XML_TAG_X1, bbox[0][0] - badd)
    self.set_value(mesh_node, consts.XML_TAG_Y1, bbox[0][1] - badd)
    self.set_value(mesh_node, consts.XML_TAG_Z1, bbox[0][2] - badd)
    self.set_value(mesh_node, consts.XML_TAG_X2, bbox[1][0] + badd)
    self.set_value(mesh_node, consts.XML_TAG_Y2, bbox[1][1] + badd)
    self.set_value(mesh_node, consts.XML_TAG_Z2, bbox[1][2] + badd)
    self.set_value(mesh_node, consts.XML_TAG_DX, dl) 
    self.set_value(mesh_node, consts.XML_TAG_DY, dl) 
    self.set_value(mesh_node, consts.XML_TAG_DZ, dl) 

  def new_file_node(self, file_name):
    new_file = self.dom.createElement(consts.XML_TAG_FILE)
    # TODO: attr_name for the file
    
    file_text = self.dom.createTextNode(file_name)
    new_file.appendChild(file_text)
    return new_file


  ###------------------
  ### update_results
  ###------------------
  def update_results(self, results, ref_results = None):
    """ Update the project tree and the EMM data with the new results """
    self.state = consts.PRJ_STATE_MODIFIED

    print "Project:: Updating results..."
    print results

    if ref_results:
      print ">> reference results:"
      print ref_results

    results_node = self.get_node(consts.XML_TAG_RESULTS)
    # TODO: define "files" in consts.py

    # if we have some results with time-domain signal
    #tdsignals_node = None

    ###
    ### time-domain signals ###
    ###
    # if len(results["tdsignals"]):
    #   tdsignals_node = self.set_value(results_node, consts.XML_TAG_TDSIGNALS, '')

    result_node_simulation = self.get_node_with_attr(consts.XML_TAG_RESULT, consts.XML_ATTR_RESULT_TYPE, consts.RESULT_TYPE_SIMULATION, results_node)	# get the node or create a new one

    for tds in results["tdsignals"]:
      #self.set_value_for_attr(tdsignals_node, consts.XML_TAG_RESULT, (consts.XML_ATTR_NAME, tds.name), '')
      tds_node = self.set_value_for_attr(result_node_simulation, consts.XML_TAG_TDSIGNAL, (consts.XML_ATTR_NAME, tds.name), '')
      file_node = self.set_value_for_attr(tds_node, consts.XML_TAG_FILE, (consts.XML_ATTR_FILE_SRC, tds.file_source), '')
      self.set_attr(file_node, consts.XML_ATTR_FILE_COLUMN, tds.column)

    ###
    ### reference results
    ###
    if ref_results:
      result_node_ref = self.get_node_with_attr(consts.XML_TAG_RESULT, consts.XML_ATTR_RESULT_TYPE, consts.RESULT_TYPE_REFERENCE, results_node)	# get the node or create a new one

      for tds in ref_results["tdsignals"]:
	tds_node = self.set_value_for_attr(result_node_ref, consts.XML_TAG_TDSIGNAL, (consts.XML_ATTR_NAME, tds.name), '')
	file_node = self.set_value_for_attr(tds_node, consts.XML_TAG_FILE, (consts.XML_ATTR_FILE_SRC, tds.file_source), '')
	self.set_attr(file_node, consts.XML_ATTR_FILE_COLUMN, tds.column)


    ###
    ### S-parameters ###
    ###
    # if len(results["sparams"]):
    #   sparams_node = self.set_value(results_node, consts.XML_TAG_SPARAMETERS, '')

    for spar in results["sparams"]:
      for spar_name in spar.get_names():
	#self.set_value_for_attr(sparams_node, consts.XML_TAG_RESULT, (consts.XML_ATTR_NAME, spar_name), '')
	self.set_value_for_attr(results_node, consts.XML_TAG_SPARAMETERS, (consts.XML_ATTR_NAME, spar_name), '')

    ###
    ### Impedance ###
    ###
    for imp in results["zparams"]:
      for zpar_name in imp.get_names():
	self.set_value_for_attr(results_node, consts.XML_TAG_ZPARAMETERS, (consts.XML_ATTR_NAME, zpar_name), '')

    for file in results["files"]:
      results_node.appendChild(self.new_file_node(file))

    for res in results["resobjs"]:
      self.set_value_for_attr(results_node, consts.XML_TAG_RESULT, (consts.XML_ATTR_NAME, res.name), '')

  def close(self):
    self.dom.unlink()		# destroy the DOM object
    del self.dom
    self.dom = None
    self.fname = consts.PRJ_DEFAULT_FNAME
    ## FIXME: the next line was setting state to PRJ_STATE_INITIALIZED, which was used
    ##         in tests in other methods of this class, but has not initiated to the main
    ##         window, that the project was saved; Think of where to set the state of the project
    ##         to PRJ_STATE_INITIALIZED again!
    self.state = consts.PRJ_STATE_INITIALIZED


###############################################
if __name__ == '__main__':
  print "Testing Project Module..."

  prj = Project()
  #prj.new(["TestModule", "1e-3"])
