/*	Author:		Magdin Stoica
	Supervisor: Dr. Ryan Leduc
	
	Project created in conformity with the requirements for the Degree of Master of Engineering in Software Engineering, 
	Computing and Software Department, 
	McMaster University
	2003 - 2007
*/

#include <QTreeWidgetItem>
#include <QResizeEvent>
#include <QHeaderView>
#include <QMessageBox>
#include "HierProjStructureUiPart.h"
#include "DesSubsystem.h"
#include "DesInterface.h"

namespace DESpot
{

const int HierProjStructureUiPart::cHierViewIndex = 0;
const int HierProjStructureUiPart::cLevelViewIndex = 1;
const int HierProjStructureUiPart::cFlatViewIndex = 2; 

const int HierProjStructureUiPart::cHierProjStructColCount = 4;
const int HierProjStructureUiPart::cContainerNameColIndex = 0;
const int HierProjStructureUiPart::cIcColIndex = 1;
const int HierProjStructureUiPart::cNbColIndex = 2;
const int HierProjStructureUiPart::cCtrlColIndex = 3;

const int HierProjStructureUiPart::cLevelDesColCount = 2;
const int HierProjStructureUiPart::cDesNameColIndex = 0;
const int HierProjStructureUiPart::cDesStatusColIndex = 1;

const int HierProjStructureUiPart::cLevelViewProjStructColCount = 1;
const int HierProjStructureUiPart::cSupChildIdx = 0;
const int HierProjStructureUiPart::cPlantChildIdx = 1;

const QString HierProjStructureUiPart::cPropTrueSymbol = "x";
const QString HierProjStructureUiPart::cPropFalseSymbol = "-";


HierProjStructureUiPart::HierProjStructureUiPart(Ui::HierProjectEditorUI* pUiContainer, DesHierProject* pProject,
												 QAction* addHighLvlSubsysAct):
	ProjStructureUiPart(pProject),	
	m_pCrtSubsys(null),
	m_pCrtInterf(null),
	m_addHighLvlSubsysAct(addHighLvlSubsysAct)
{
	initWidgets(pUiContainer);

	m_crtView = ((pProject->getDegree() > 1) || pProject->isNew()) ? cHierViewIndex : cLevelViewIndex;

	setupProjectStructWidget();	

	setupConnections();

	installEventFilters();
}

//_________________________________________________________________________________________________

HierProjStructureUiPart::~HierProjStructureUiPart(void)
{
}

//_________________________________________________________________________________________________

QTreeWidget* HierProjStructureUiPart::getCurrentViewWidget()
{
	switch(m_crtView)
	{
		case cFlatViewIndex:
			return m_fViewProjStructWidg;

		case cHierViewIndex:
			return m_desViewWidg->hasFocus() ? m_desViewWidg: m_hViewProjStructWidg;

		case cLevelViewIndex:
			return m_lViewProjStructWidg;

		default:
			assert(false);
			return null;
	}
}

//_________________________________________________________________________________________________

bool HierProjStructureUiPart::isProjectSelected()
{
	switch(m_crtView)
	{
		case cFlatViewIndex:
			return m_fViewProjStructWidg->currentItem() == m_fViewRootItem;

		case cHierViewIndex:
			return m_hViewProjStructWidg->currentItem() == m_hViewRootItem;

		case cLevelViewIndex:
			return m_lViewProjStructWidg->currentItem() == m_lViewRootItem;

		default:
			assert(false);
			return false;
	}
}

//_________________________________________________________________________________________________

bool HierProjStructureUiPart::isSubsysSelected()
{
	switch(m_crtView)
	{
		case cHierViewIndex:
			return isSubsysHierViewItem(m_hViewProjStructWidg->currentItem());

		case cLevelViewIndex:
			return isSubsysLevelViewItem(m_lViewProjStructWidg->currentItem());

		default:
			return false;
	}
}

//_________________________________________________________________________________________________

bool HierProjStructureUiPart::isSupervisorSelected()
{
	QTreeWidgetItem* crtItem = getCurrentViewWidget()->currentItem();
	return crtItem->text(0) == STR_LEVEL_VIEW_SUPERVISOR;
}

//_________________________________________________________________________________________________

bool HierProjStructureUiPart::isPlantSelected()
{
	QTreeWidgetItem* crtItem = getCurrentViewWidget()->currentItem();
	return crtItem->text(0) == STR_LEVEL_VIEW_PLANT;
}

//_________________________________________________________________________________________________

bool HierProjStructureUiPart::hasCurrentProjComp()
{
	return hasCurrentSubsys() || hasCurrentInterf();
}

//_________________________________________________________________________________________________

bool HierProjStructureUiPart::hasCurrentSubsys()
{
	return (m_pCrtSubsys != null);
}

//_________________________________________________________________________________________________

bool HierProjStructureUiPart::hasCurrentInterf()
{
	return (m_pCrtInterf != null);
}

//_________________________________________________________________________________________________

bool HierProjStructureUiPart::getCurrentLevel(ProjectLevel& out_level)
{
	if (m_pCrtSubsys != null)
	{
		//it's a subsystem level
		out_level = (m_pCrtSubsys == &m_pProject->getRootSubsys() ? eHighLevel : eLowLevel);
		return true;
	}
	else if (m_pCrtInterf != null)
	{
		out_level = eInterfLevel;
		return true;
	}
	else
	{
		//neither an interface nor a des nor a subsystem is selected. So it must be a level
		//or a plant / supervisor node
		if (m_crtView == cLevelViewIndex)
		{
			const QTreeWidgetItem* crtLevelItem = getLevelItem(m_lViewProjStructWidg->currentItem());

			if (crtLevelItem == m_highLevelItem)
			{
				out_level  = eHighLevel;
				return true;
			}
			else if (crtLevelItem == m_interfLevelItem)
			{
				out_level = eInterfLevel;
				return true;
			}
			else if (crtLevelItem == m_lowLevelItem)
			{
				out_level  = eLowLevel;
				return true;
			}
			else
			{
				//can't figure out what it is
				return false;
			}
		}

		//if we couldn't figure it out give up and return false
		return false;
	}
}

//_________________________________________________________________________________________________

bool HierProjStructureUiPart::getCurrentProjComp(std::wstring& out_projCompName)
{
	if (m_pCrtSubsys != null)
	{
		out_projCompName = m_pCrtSubsys->getName();
		return true;
	}
	else if (m_pCrtInterf != null)
	{
		out_projCompName = m_pCrtInterf->getName();
		return true;
	}
	else
	{
		//neither an interface nor a des nor a subsystem is selected. So it must be a level
		//or a plant / supervisor node
		if (m_crtView == cLevelViewIndex)
		{
			QString crtItemText = m_lViewProjStructWidg->currentItem()->text(0);
			if (( crtItemText == STR_LEVEL_VIEW_SUPERVISOR) || (crtItemText == STR_LEVEL_VIEW_PLANT))
			{
				//the current item is a Plant or Supervisor item so figure what what subsystem to they correspond to
				//by going up one level
				QTreeWidgetItem* subsysLevelViewItem = m_lViewProjStructWidg->currentItem()->parent();
				if (isSubsysLevelViewItem(subsysLevelViewItem))
				{
					out_projCompName = getSubsystemFromLItem(subsysLevelViewItem).getName();
					return true;
				}
			}

		}

		return false;
	}
}

//_________________________________________________________________________________________________

bool HierProjStructureUiPart::getCurrentDesLevel(DesLevel& out_desLevel)
{
	switch(m_crtView)
	{
		case cFlatViewIndex:
			return ProjStructureUiPart::getCurrentDesLevel(out_desLevel);

		case cHierViewIndex:
			if (m_plantDesRootItem == null && m_supDesRootItem == null)
				return false;
			
			if (m_desViewWidg->currentItem() == null)
				return false;

			if ((m_desViewWidg->currentItem() == m_plantDesRootItem) ||
				(m_desViewWidg->currentItem()->parent() == m_plantDesRootItem))
			{
				out_desLevel = ePlantDes;
				return true;
			}
			else if ((m_desViewWidg->currentItem() == m_supDesRootItem) ||
				     (m_desViewWidg->currentItem()->parent() == m_supDesRootItem))
			{
				out_desLevel = eSupervisorDes;
				return true;
			}

			return false;

		case cLevelViewIndex:
		{
			QString crtItemText = m_lViewProjStructWidg->currentItem()->text(0);
			QTreeWidgetItem* crtItemParent = m_lViewProjStructWidg->currentItem()->parent();
			QString crtParentText = crtItemParent ? crtItemParent->text(0) : "";

			if (( crtItemText == STR_LEVEL_VIEW_SUPERVISOR) || (crtParentText == STR_LEVEL_VIEW_SUPERVISOR))
			{ 
				out_desLevel = eSupervisorDes;
				return true;
			}
			else if (( crtItemText == STR_LEVEL_VIEW_PLANT) || (crtParentText == STR_LEVEL_VIEW_PLANT))
			{
				out_desLevel = ePlantDes;
				return true;
			}

			return false;
		}

		default:
			assert(false);
			return false;
	}
}

//_________________________________________________________________________________________________

QMenu& HierProjStructureUiPart::accessHViewProjCtxtMenu()
{
	return m_hViewProjCtxtMenu;
}

//_________________________________________________________________________________________________

QMenu& HierProjStructureUiPart::accessHViewDesCtxtMenu()
{
	return m_hViewDesCtxtMenu;
}

//_________________________________________________________________________________________________

QMenu& HierProjStructureUiPart::accessLViewCtxtMenu()
{
	return m_lViewCtxtMenu;
}

//_________________________________________________________________________________________________

void HierProjStructureUiPart::selectDefaults()
{
	m_hViewProjStructWidg->setCurrentItem(m_hViewRootSubsysItem);
	m_lViewProjStructWidg->setCurrentItem(m_lViewRootSubsysItem);
}

//_________________________________________________________________________________________________

DesHierProject* HierProjStructureUiPart::project()
{
	return dynamic_cast<DesHierProject*>(m_pProject);
}

//_________________________________________________________________________________________________

void HierProjStructureUiPart::initWidgets(Ui::HierProjectEditorUI* pUiContainer)
{
	//initialze the base class widgets
	ProjStructureUiPart::initWidgets(pUiContainer);

	m_projStructTabWidget = pUiContainer->m_projStructTabWidget;

	//Hierarchy View
	m_hViewSplitterWidg = pUiContainer->m_hViewSplitterWidg;
	m_hViewProjStructWidg = pUiContainer->m_hViewProjStructWidg;
	m_desViewWidg = pUiContainer->m_desViewWidg;

	//Level View
	m_lViewProjStructWidg = pUiContainer->m_lViewProjStructWidg;
}

//_________________________________________________________________________________________________

void HierProjStructureUiPart::setupConnections()
{
	//initialize the base class connections
	ProjStructureUiPart::setupConnections();

	connect(m_projStructTabWidget, SIGNAL(currentChanged(int)),
		    this, SLOT(onCurrentViewChanged(int)));

	connect(m_hViewProjStructWidg, SIGNAL(onWidthChanged(int)), 
			this, SLOT(resizeProjHierStructHeaders(int)));

	connect(m_hViewProjStructWidg, SIGNAL(currentItemChanged(QTreeWidgetItem*, QTreeWidgetItem*)), 
			this, SLOT(onChangedCurrentHierViewItem(QTreeWidgetItem*, QTreeWidgetItem*)));

	connect(m_hViewProjStructWidg, SIGNAL(onCurrentItemDeleted()),
			this, SLOT(onHViewItemDeleted()));

	connect(m_desViewWidg, SIGNAL(onWidthChanged(int)), 
			this, SLOT(resizeLevelDesHeaders(int)));

	connect(m_desViewWidg, SIGNAL(currentItemChanged(QTreeWidgetItem*, QTreeWidgetItem*)), 
			this, SLOT(onChangedCurrentHierViewDesItem(QTreeWidgetItem*, QTreeWidgetItem*)));

	connect(m_desViewWidg, SIGNAL(itemActivated(QTreeWidgetItem*, int)),
			this, SLOT(onHViewDesItemActivated(QTreeWidgetItem*, int)));

	connect(m_desViewWidg, SIGNAL(onCurrentItemDeleted()),
			this, SLOT(onHViewDesItemDeleted()));

	connect(m_lViewProjStructWidg, SIGNAL(onWidthChanged(int)), 
			this, SLOT(resizeLevelViewHeaders(int)));

	connect(m_lViewProjStructWidg, SIGNAL(currentItemChanged(QTreeWidgetItem*, QTreeWidgetItem*)), 
			this, SLOT(onChangedCurrentLevelViewItem(QTreeWidgetItem*, QTreeWidgetItem*)));

	connect(m_lViewProjStructWidg, SIGNAL(itemActivated(QTreeWidgetItem*, int)),
			this, SLOT(onLViewItemActivated(QTreeWidgetItem*, int)));

	connect(m_lViewProjStructWidg, SIGNAL(onCurrentItemDeleted()),
			this, SLOT(onLViewItemDeleted()));
	
}

//_________________________________________________________________________________________________

void HierProjStructureUiPart::installEventFilters()
{
	m_projStructTabWidget->installEventFilter(this);

}

//_________________________________________________________________________________________________

bool HierProjStructureUiPart::eventFilter(QObject* target, QEvent* event)
{
	if (target == m_projStructTabWidget && event->type() == QEvent::Resize)
	{
		QResizeEvent* resizeEvent = dynamic_cast<QResizeEvent*>(event);
		
		const QSize cLayoutOffset(3,23);		
		m_hViewSplitterWidg->move(-1,-1);
		m_hViewSplitterWidg->resize(resizeEvent->size() - cLayoutOffset);
		
		m_lViewProjStructWidg->move(-1,-1);
		m_lViewProjStructWidg->resize(resizeEvent->size() - cLayoutOffset);
		
		m_fViewProjStructWidg->move(-1,-1);
		m_fViewProjStructWidg->resize(resizeEvent->size() - cLayoutOffset);
	}

	return ProjStructureUiPart::eventFilter(target, event);
}

//_________________________________________________________________________________________________

void HierProjStructureUiPart::setupProjectStructWidget()
{
	//make the sure the base class sets up the flat view of the project structure
	ProjStructureUiPart::setupProjectStructWidget();

	//set the first tab as current
	m_projStructTabWidget->setCurrentIndex(m_crtView);

	//setup the hierarchy view of the project structure
	setupHierView();

	//setup the level view of the project structure
	setupLevelView();

	//load all subsystem and interfaces from the project
	loadProjectStruct();
}

//_________________________________________________________________________________________________

//setup the hierarchy view of the project structure
void HierProjStructureUiPart::setupHierView()
{
	//setup the hierarhcy widget showing the levels
	m_hViewProjStructWidg->header()->setStretchLastSection(false);
	m_hViewProjStructWidg->setColumnCount(cHierProjStructColCount);
	QStringList headerCaption;
	headerCaption << STR_HIER_PROJ_STRUCT_HEADER << STR_HIER_PROJ_IC_HEADER << STR_HIER_PROJ_NB_HEADER << STR_HIER_PROJ_CTRL_HEADER;
	m_hViewProjStructWidg->setHeaderLabels(headerCaption);
	m_hViewProjStructWidg->headerItem()->setTextAlignment(cIcColIndex, Qt::AlignHCenter);
	m_hViewProjStructWidg->headerItem()->setTextAlignment(cNbColIndex, Qt::AlignHCenter);
	m_hViewProjStructWidg->headerItem()->setTextAlignment(cCtrlColIndex, Qt::AlignHCenter);
	m_hViewProjStructWidg->setContextMenu(m_hViewProjCtxtMenu);

	//create the root item corresponding to the project itself
	QString projectName = QString::fromStdWString(project()->getName());
	m_hViewRootItem = createHierViewItem(projectName, projectName);
	m_hViewProjStructWidg->expandItem(m_hViewRootItem);

	//setup the level widget that shows the DESs in the currently selected level
	m_desViewWidg->header()->setStretchLastSection(false);
	m_desViewWidg->setColumnCount(cLevelDesColCount);
	QStringList headerLabels;
	headerLabels << STR_LEVEL_DES_HEADER << STR_LEVEL_DES_STATUS_HEADER;
	m_desViewWidg->setHeaderLabels(headerLabels);
	m_desViewWidg->headerItem()->setTextAlignment(cDesStatusColIndex, Qt::AlignHCenter);
	m_desViewWidg->setContextMenu(m_hViewDesCtxtMenu);

	//create the root item for the subsystem viewer showing that no subsystem is currently selected
	resetDesViewer();
	
}

//_________________________________________________________________________________________________
//Loads high-level subsytem, interfaces and low-level subsystems
void HierProjStructureUiPart::loadProjectStruct()
{
	if (project()->hasRootSubsys())
	{
		onHighLevelSubsysAdded(project()->getRootSubsys());
	}

	//load all interfaces
	DesHierProject::InterfIteratorPtr interfIt = project()->createInterfIterator();
	for(interfIt->first(); interfIt->isDone() == false; interfIt->next())
	{
		const DesInterface& interf = interfIt->currentItem();
		onInterfaceAdded(interf);
	}

	//load all low-level subsystems dependent on the high-level one
	DesSubsystem::DependIteratorPtr lowSubsysIt = project()->getRootSubsys().createDependsIterator();
	for(lowSubsysIt->first(); lowSubsysIt->isDone() == false; lowSubsysIt->next())
	{
		const DesInterface&  interf = *(lowSubsysIt->currentItem().interface);
		const DesSubsystem&  lowSubsys = *(lowSubsysIt->currentItem().subsystem);
		
		onLowLevelSubsysAdded(lowSubsys);
		
		onDependencyAdded(project()->getRootSubsys(), interf, lowSubsys);
	}

}

//_________________________________________________________________________________________________

//setup the level view of the project structure
void HierProjStructureUiPart::setupLevelView()
{
	m_lViewProjStructWidg->setColumnCount(cLevelViewProjStructColCount);
	QStringList headerCaption;
	headerCaption << STR_LEVEL_VIEW_PROJ_STRUCT_HEADER;
	m_lViewProjStructWidg->setHeaderLabels(headerCaption);
	m_lViewProjStructWidg->setContextMenu(m_lViewCtxtMenu);

	//create the root item for the project
	QString projName = QString::fromStdWString(m_pProject->getName());
	m_lViewRootItem = createLevelViewItem(projName, projName);
	m_lViewProjStructWidg->expandItem(m_lViewRootItem);

	//create the high-level item 
	m_highLevelItem = createLevelViewItem(STR_HIGH_LEVEL_ITEM_TEXT, STR_HIGH_LEVEL_ITEM_TEXT, m_lViewRootItem);
	m_lViewProjStructWidg->expandItem(m_highLevelItem);

	//create the interface level item
	m_interfLevelItem = createLevelViewItem(STR_I_LEVEL_ITEM_TEXT, STR_I_LEVEL_ITEM_TEXT, m_lViewRootItem);
	m_lViewProjStructWidg->expandItem(m_interfLevelItem);

	//create the low-level item
	m_lowLevelItem = createLevelViewItem(STR_LOW_LEVEL_ITEM_TEXT, STR_LOW_LEVEL_ITEM_TEXT, m_lViewRootItem);
	m_lViewProjStructWidg->expandItem(m_lowLevelItem);
}

//_________________________________________________________________________________________________

void HierProjStructureUiPart::updateDesViewer(const DesSubsystem& subsys)
{
	resetDesViewer();

	QString rootItemText = QString::fromStdWString(subsys.getName());
	QString supDesCount = QVariant(subsys.getSupDesCount()).toString();
	QString plantDesCount = QVariant(subsys.getPlantDesCount()).toString();
	QString rootItemToolTip = STR_SUBSYS_ITEM_TOOLTIP(rootItemText, supDesCount, plantDesCount);
	m_desViewRootItem->setText(cDesNameColIndex, rootItemText);
	m_desViewRootItem->setToolTip(cDesNameColIndex,rootItemToolTip); 
	QFont font = m_desViewRootItem->font(cDesNameColIndex);
	font.setItalic(false);
	m_desViewRootItem->setFont(cDesNameColIndex, font);

	m_supDesRootItem = new QTreeWidgetItem(m_desViewRootItem);
	m_supDesRootItem->setText(cDesNameColIndex, STR_DES_VIEW_SUPERVISOR);
	m_supDesRootItem->setToolTip(cDesNameColIndex, STR_DES_VIEW_SUPERVISOR_TOOLTIP(supDesCount));
	m_desViewWidg->expandItem(m_supDesRootItem);
	
	//load the supervisor DESs
	DesSubsystem::DesIteratorPtr supDesIt = subsys.createDesIterator(eSupervisorDes);
	for(supDesIt->first(); supDesIt->isDone() == false; supDesIt->next())
	{
		const Des& des = supDesIt->currentItem();
		QString itemText = QString::fromStdWString(des.getName());
		QString itemTooltip = STR_HIER_VIEW_DES_TOOLTIP(itemText, QString::fromStdWString(des.getFileName()));
		createHierViewDesItem(itemText, itemTooltip, m_supDesRootItem, &des);

	}

	m_plantDesRootItem = new QTreeWidgetItem(m_desViewRootItem);
	m_plantDesRootItem->setText(cDesNameColIndex, STR_DES_VIEW_PLANT);
	m_plantDesRootItem->setToolTip(cDesNameColIndex, STR_DES_VIEW_PLANT_TOOLTIP(plantDesCount));
	m_desViewWidg->expandItem(m_plantDesRootItem);

	//load the plant DESs
	DesSubsystem::DesIteratorPtr plantDesIt = subsys.createDesIterator(ePlantDes);
	for(plantDesIt->first(); plantDesIt->isDone() == false; plantDesIt->next())
	{
		const Des& des = plantDesIt->currentItem();
		QString itemText = QString::fromStdWString(des.getName());
		QString itemTooltip = STR_HIER_VIEW_DES_TOOLTIP(itemText, QString::fromStdWString(des.getFileName()));
		createHierViewDesItem(itemText, itemTooltip, m_plantDesRootItem, &des);

	}

}

//_________________________________________________________________________________________________

void HierProjStructureUiPart::updateDesViewer(const DesInterface& interf)
{
	resetDesViewer();

	QFont font = m_desViewRootItem->font(cDesNameColIndex);
	font.setItalic(false);
	QString itemText = QString::fromStdWString(interf.getName());
	QString itemTooltip = STR_INTERF_ITEM_TOOLTIP(itemText, 
												  QVariant(interf.getDesCount()).toString());
	m_desViewRootItem->setFont(cDesNameColIndex, font);
	m_desViewRootItem->setText(cDesNameColIndex, itemText);
	m_desViewRootItem->setToolTip(cDesNameColIndex, itemTooltip);

	//load the interface DESs
	DesInterface::DesIteratorPtr desIt = interf.createDesIterator();
	for(desIt->first(); desIt->isDone() == false; desIt->next())
	{
		const Des& des = desIt->currentItem();
		QString itemText = QString::fromStdWString(des.getName());
		QString itemTooltip = STR_HIER_VIEW_DES_TOOLTIP(itemText, QString::fromStdWString(des.getFileName()));
		createHierViewDesItem(itemText, itemTooltip, m_desViewRootItem, &des);
	}
}

//_________________________________________________________________________________________________

void HierProjStructureUiPart::resetDesViewer()
{
	//first clear everything in case there is something there
	m_desViewWidg->clear();
    m_supDesRootItem = null;
	m_plantDesRootItem = null;

	//add the root item
	m_desViewRootItem = new QTreeWidgetItem(m_desViewWidg);
	m_desViewWidg->expandItem(m_desViewRootItem);
	QFont font = m_desViewRootItem->font(cDesNameColIndex);
	font.setItalic(true);
	m_desViewRootItem->setFont(cDesNameColIndex, font);
	m_desViewRootItem->setText(cDesNameColIndex, STR_NO_SUBSYS_INTERF_SELECTED);
}

//_________________________________________________________________________________________________

void HierProjStructureUiPart::updateHierViewItemProps(QTreeWidgetItem& hViewItem, int column, const DesSubsystem& subsys)
{
	switch(column)
	{
		case cIcColIndex:
			updateHViewItemIConsistProp(hViewItem, subsys);
			break;
		
		case cNbColIndex:
			updateHViewItemLwNonBlockProp(hViewItem, subsys);
			break;

		case cCtrlColIndex:
			updateHViewItemLwCtrlProp(hViewItem, subsys);
			break;
	}
}

//_________________________________________________________________________________________________

void HierProjStructureUiPart::updateHViewItemIConsistProp(QTreeWidgetItem& hViewItem, const DesSubsystem& subsys)
{
	switch(subsys.getIConsistProp())
	{
		case eIConsYes:
			hViewItem.setText(cIcColIndex, cPropTrueSymbol);
			break;

		case eIConsNo:
			hViewItem.setText(cIcColIndex, cPropFalseSymbol);
			break;

		case eIConsNotVerified:
			hViewItem.setText(cIcColIndex,  "");
			break;
	}
}

//_________________________________________________________________________________________________

void HierProjStructureUiPart::updateHViewItemLwNonBlockProp(QTreeWidgetItem& hViewItem, const DesSubsystem& subsys)
{
	switch(subsys.getLwNonBlockProp())
	{
		case eIConsYes:
			hViewItem.setText(cNbColIndex, cPropTrueSymbol);
			break;

		case eIConsNo:
			hViewItem.setText(cNbColIndex, cPropFalseSymbol);
			break;

		case eIConsNotVerified:
			hViewItem.setText(cNbColIndex,  "");
			break;
	}
}

//_________________________________________________________________________________________________

void HierProjStructureUiPart::updateHViewItemLwCtrlProp(QTreeWidgetItem& hViewItem, const DesSubsystem& subsys)
{
	switch(subsys.getLwCtrlProp())
	{
		case eIConsYes:
			hViewItem.setText(cCtrlColIndex, cPropTrueSymbol);
			break;

		case eIConsNo:
			hViewItem.setText(cCtrlColIndex, cPropFalseSymbol);
			break;

		case eIConsNotVerified:
			hViewItem.setText(cCtrlColIndex,  "");
			break;
	}
}

//_________________________________________________________________________________________________

void HierProjStructureUiPart::updateHViewItemIConsistProp(QTreeWidgetItem& hViewItem, const DesInterface& interf)
{
	switch(interf.getIConsistProp())
	{
		case eIConsYes:
			hViewItem.setText(cIcColIndex, cPropTrueSymbol);
			break;

		case eIConsNo:
			hViewItem.setText(cIcColIndex, cPropFalseSymbol);
			break;

		case eIConsNotVerified:
			hViewItem.setText(cIcColIndex,  "");
			break;
	}
}

//_________________________________________________________________________________________________

QTreeWidgetItem* HierProjStructureUiPart::createHierViewItem(const QString& text, 
															 const QString& tooltip, 
															 QTreeWidgetItem* parent /*= null*/,
															 const void* projectComp /*= null*/)
{
	QTreeWidgetItem* hViewItem = null;
	if (parent) 
	{
		hViewItem = new QTreeWidgetItem(parent);
	}
	else
	{
		hViewItem = new QTreeWidgetItem(m_hViewProjStructWidg);
	}

	hViewItem->setTextAlignment(cIcColIndex, Qt::AlignHCenter);
	hViewItem->setTextAlignment(cNbColIndex, Qt::AlignHCenter);
	hViewItem->setTextAlignment(cCtrlColIndex, Qt::AlignHCenter);
	hViewItem->setText(0, text);
	hViewItem->setToolTip(0, tooltip);
	
	if (projectComp)
	{
		hViewItem->setData(0, Qt::UserRole, QVariant(reinterpret_cast<unsigned long long>(projectComp)));
	}
	
	return hViewItem;
}

//_________________________________________________________________________________________________

QTreeWidgetItem* HierProjStructureUiPart::createHierViewDesItem(const QString& text, const QString& tooltip, 
										  QTreeWidgetItem* parent /*= null*/,
										  const Des* pDes /*= null*/)
{
	QTreeWidgetItem* hViewDesItem = null;
	if (parent) 
	{
		hViewDesItem = new QTreeWidgetItem(parent);
	}
	else
	{
		hViewDesItem = new QTreeWidgetItem(m_desViewWidg);
	}

	hViewDesItem->setText(cDesNameColIndex, text);
	hViewDesItem->setToolTip(cDesNameColIndex, tooltip);
	hViewDesItem->setTextAlignment(cDesStatusColIndex, Qt::AlignHCenter);
	
	if (pDes)
	{
		hViewDesItem->setData(0, Qt::UserRole, QVariant(reinterpret_cast<unsigned long long>(pDes)));
	}
	
	return hViewDesItem;
}

//_________________________________________________________________________________________________

QTreeWidgetItem* HierProjStructureUiPart::createLevelViewItem(const QString& text, const QString& tooltip, 
							  	     QTreeWidgetItem* parent /*= null*/,
									 const void* projectComp /*= null*/)
{
	QTreeWidgetItem* levelViewProjItem = null;
	if (parent) 
	{
		levelViewProjItem = new QTreeWidgetItem(parent);
	}
	else
	{
		levelViewProjItem = new QTreeWidgetItem(m_lViewProjStructWidg);
	}

	levelViewProjItem->setText(0, text);
	levelViewProjItem->setToolTip(0, tooltip);

	if (projectComp)
	{
		levelViewProjItem->setData(0, Qt::UserRole, QVariant(reinterpret_cast<unsigned long long>(projectComp)));
	}

	return levelViewProjItem;
}

//_________________________________________________________________________________________________

void HierProjStructureUiPart::resizeProjHierStructHeaders(int width)
{	
	int widthSoFar = 0;
	for(int iCol = 1; iCol < cHierProjStructColCount; iCol++)
	{
		m_hViewProjStructWidg->resizeColumnToContents(iCol);		
		widthSoFar += m_hViewProjStructWidg->header()->sectionSize(iCol);
	}

	m_hViewProjStructWidg->header()->resizeSection(0, width - widthSoFar);
}

//_________________________________________________________________________________________________

void HierProjStructureUiPart::resizeLevelDesHeaders(int width)
{
	int widthSoFar = 0;
	for(int iCol = 1; iCol < cLevelDesColCount; iCol++)
	{
		m_desViewWidg->resizeColumnToContents(iCol);
		widthSoFar += m_desViewWidg->header()->sectionSize(iCol);
	}
	
	m_desViewWidg->header()->resizeSection(0, width - widthSoFar);
}

//_________________________________________________________________________________________________

void HierProjStructureUiPart::resizeLevelViewHeaders(int width)
{
	m_desViewWidg->header()->resizeSection(0, width);
}

//_________________________________________________________________________________________________

void HierProjStructureUiPart::onChangedCurrentFlatViewItem(QTreeWidgetItem * current, QTreeWidgetItem * /*previous*/)
{
	if (m_crtView != cFlatViewIndex)
		return; //this view is not the current one so don't send any notifications

	Des* pOldCrtDes = m_pCrtDes;
	if (current)
	{
		if (isDesFlatViewItem(*current))
		{
			m_pCrtDes = &getDesFromFItem(*current);
		}
		else
		{
			//the current item doesn't represent a DES
			m_pCrtDes = null;
		}
	}
	
	//set the current subsystem or interface that owns the new DES component as they have to always be 
	//synchronized accordingly
	if (m_pCrtDes)
	{
		switch(m_pCrtDes->getType())
		{
			case eSubsystemDes:
			{
				const DesSubsystem* prevSubsys = m_pCrtSubsys;
				const DesInterface* prevInterf = m_pCrtInterf;
				
				m_pCrtSubsys = &project()->getParentSubsystem(*m_pCrtDes);
				m_pCrtInterf = null; //a subsystem is selected so make sure the current interface is reset if there was a current interface

				if (m_pCrtSubsys != prevSubsys)
				{
					emit onChangedCurrentSubsys(m_pCrtSubsys, prevSubsys);					 
				}

				if (m_pCrtInterf != prevInterf)
				{
					emit onChangedCurrentInterf(m_pCrtInterf, prevInterf);
				}

				break;
			}

			case eInterfaceDes:
			{
				const DesInterface* prevInterf = m_pCrtInterf;
				const DesSubsystem* prevSubsys = m_pCrtSubsys;

				m_pCrtInterf = &project()->getParentInterface(*m_pCrtDes);
				m_pCrtSubsys = null; //an interface is selected so make sure the current subsystem is reset if there was a current subsystem

				if (m_pCrtInterf != prevInterf)
				{
					emit onChangedCurrentInterf(m_pCrtInterf, prevInterf);
				}
				
				if (m_pCrtSubsys != prevSubsys)
				{
					emit onChangedCurrentSubsys(m_pCrtSubsys, prevSubsys);
				}

				break;
			}

			default:
				assert(false); //unknown
		}
	}

	if (m_pCrtDes != pOldCrtDes)
	{
		emit onChangedCurrentDes(m_pCrtDes, pOldCrtDes);
	}
}

//_________________________________________________________________________________________________

void HierProjStructureUiPart::onChangedCurrentHierViewItem(QTreeWidgetItem* current, QTreeWidgetItem* /*previous*/)
{
	//Ensure two notifications are NOT sent when the hierachy view is synchronized with the level view
	if (m_crtView != cHierViewIndex)
		return; //this view is not the current one so don't send any notifications

	//This method will fire one or both of the following signals: onChangedCurrentSubsys and / or onChangedCurrentInterf
	const DesSubsystem* prevSubsys = m_pCrtSubsys;
	const DesInterface* prevInterf = m_pCrtInterf;
	
	if (current)
	{
		if (isSubsysHierViewItem(current))
		{
			m_pCrtSubsys = &getSubsystemFromHItem(current);
			m_pCrtInterf = null;
			m_pCrtDes = null;
			updateDesViewer(*m_pCrtSubsys);
		}
		else if (isInterfHierViewItem(current))
		{
			m_pCrtInterf = &getInterfaceFromHItem(current);
			m_pCrtSubsys = null;
			m_pCrtDes = null;
			updateDesViewer(*m_pCrtInterf);
		}
		else
		{
			//the current item is neither a subsytem nor an interface
			m_pCrtSubsys = null;
			m_pCrtInterf = null;
			m_pCrtDes = null;
			resetDesViewer();
		}
	}
	else
	{
		m_pCrtSubsys = null;
		m_pCrtInterf = null;
		m_pCrtDes = null;
		resetDesViewer();
	}
		
	if (m_pCrtSubsys != prevSubsys)
	{
		emit onChangedCurrentSubsys(m_pCrtSubsys, prevSubsys);
	}

	if (m_pCrtInterf != prevInterf)
	{
		emit onChangedCurrentInterf(m_pCrtInterf, prevInterf);
	}

	//if (m_pCrtDes != prevDes)
	//{
	//	emit onChangedCurrentDes(m_pCrtDes, prevDes);
	//}
}

//_________________________________________________________________________________________________

void HierProjStructureUiPart::onChangedCurrentHierViewDesItem(QTreeWidgetItem* current, QTreeWidgetItem* previous)
{
	//Ensure two notifications are NOT sent when the hierachy view is synchronized with the level view
	if (m_crtView != cHierViewIndex)
		return; //this view is not the current one so don't send any notifications

	//This method will fire one or both of the following signals: onChangedCurrentSubsys and / or onChangedCurrentInterf
	Des* crtDes = null;
	if (current)
	{
		if (isDesHierViewItem(current))
		{
			crtDes = &getDesFromHItem(current);
		}
	}
	
	Des* prevDes = null;
	if (previous)
	{
		if (isDesHierViewItem(previous))
		{
			prevDes = &getDesFromHItem(previous);
		}
	}

	if (crtDes != prevDes)
	{
		m_pCrtDes = crtDes;
		emit onChangedCurrentDes(crtDes, prevDes);
	}
}

//_________________________________________________________________________________________________

void HierProjStructureUiPart::onChangedCurrentLevelViewItem(QTreeWidgetItem* current, QTreeWidgetItem* /*previous*/)
{
	//Ensure two notifications are NOT sent when the hierachy view is synchronized with the level view
	if (m_crtView != cLevelViewIndex)
		return; //this view is not the current one so don't send any notifications

	//This method will fire one or both of the following signals: onChangedCurrentSubsys and / or onChangedCurrentInterf
	const DesSubsystem* prevSubsys = m_pCrtSubsys;
	const DesInterface* prevInterf = m_pCrtInterf;
	Des*				prevDes	   = m_pCrtDes;	
	if (current)
	{
		if (isSubsysLevelViewItem(current))
		{
			m_pCrtSubsys = &getSubsystemFromLItem(current);
			m_pCrtInterf = null;
			m_pCrtDes = null;
		}
		else if (isInterfLevelViewItem(current))
		{
			m_pCrtInterf = &getInterfaceFromLItem(current);
			m_pCrtSubsys = null;
			m_pCrtDes = null;
		}
		else if (isDesLevelViewItem(current))
		{
			m_pCrtDes = &getDesFromLItem(current);
			switch(m_pCrtDes->getType())
			{
				case eSubsystemDes:
					m_pCrtSubsys = &project()->getParentSubsystem(*m_pCrtDes);
					m_pCrtInterf = null;
					break;
				
				case eInterfaceDes:
					m_pCrtInterf = &project()->getParentInterface(*m_pCrtDes);
					m_pCrtSubsys = null;
					break;

				default:
					assert(false);
			}
		}
		else
		{
			m_pCrtSubsys = null;
			m_pCrtInterf = null;
			m_pCrtDes = null;
		}
	}
	else
	{
		m_pCrtSubsys = null;
		m_pCrtInterf = null;
		m_pCrtDes = null;
	}
	
	if (m_pCrtSubsys != prevSubsys)
	{
		emit onChangedCurrentSubsys(m_pCrtSubsys, prevSubsys);
	}

	if (m_pCrtInterf != prevInterf)
	{
		emit onChangedCurrentInterf(m_pCrtInterf, prevInterf);
	}

	if (m_pCrtDes != prevDes)
	{
		emit onChangedCurrentDes(m_pCrtDes, prevDes);
	}
}

//_________________________________________________________________________________________________

//Called when the user uses the tab widget to change the view
void HierProjStructureUiPart::onCurrentViewChanged(int iNewCurrentView)
{
	if (m_crtView == iNewCurrentView)
		return; //nothing changed

	try
	{
		//synchronize the current subsystem/interface/desnent with the new current view
		switch(m_crtView)
		{
			case cHierViewIndex:
			{				
				switch(iNewCurrentView)
				{
					case cLevelViewIndex: //old-view = H-View	new-view = L-View
					{
						//synchronize the current subsystem/interface with the new current view
						//DES cannot be synchronized as the level view doesn't allow both a DES
						//and a subsystem /interface to be current in the same time
						if (m_pCrtDes)
						{
							QTreeWidgetItem* lViewDesItem = &getLViewItemFrom(*m_pCrtDes);
							m_lViewProjStructWidg->setCurrentItem(lViewDesItem);
						}
						else if (m_pCrtSubsys)
						{
							assert(m_pCrtInterf == null);

							//A subsystem was current so make it so in the level view
							QTreeWidgetItem* lViewSubsysItem = &getLViewItemFrom(*m_pCrtSubsys);
							m_lViewProjStructWidg->setCurrentItem(lViewSubsysItem);
						}
						else if (m_pCrtInterf)
						{
							assert(m_pCrtSubsys == null);

							//An interface was current so make it so in the level view
							QTreeWidgetItem* lViewInterfItem = &getLViewItemFrom(*m_pCrtInterf);
							m_lViewProjStructWidg->setCurrentItem(lViewInterfItem);
						}
						else
						{
							//no subsystem or interface is current set the root item as current
							m_lViewProjStructWidg->setCurrentItem(m_lViewRootItem);
						}

						break;
					}

					case cFlatViewIndex:	//old-view = H-View	new-view = F-View
					{
						if (m_pCrtDes)
						{
							QTreeWidgetItem* fViewDesItem = &getFViewItemFrom(*m_pCrtDes);
							m_fViewProjStructWidg->setCurrentItem(fViewDesItem);
						}
						else
						{
							m_fViewProjStructWidg->setCurrentItem(m_fViewRootItem);
							m_fViewRootItem->setSelected(true);
						}
						break;
					}

					default:
						assert(false);
				}
				break;
			}

			case cLevelViewIndex:
			{
				switch(iNewCurrentView)		
				{
					//synchronize the current subsystem/interface/DES with the new current view
					case cHierViewIndex:	//old-view = L-View	new-view = H-View
					{						
						//synchronize the current subsystem/interface with the new current view
						if (m_pCrtSubsys)
						{
							assert(m_pCrtInterf == null);

							//A subsystem was current so make it so in the level view
							QTreeWidgetItem* hViewSubsysItem = &getHViewItemFrom(*m_pCrtSubsys);
							m_hViewProjStructWidg->setCurrentItem(hViewSubsysItem);
							updateDesViewer(*m_pCrtSubsys);
						}
						else if (m_pCrtInterf)
						{
							assert(m_pCrtSubsys == null);

							//An interface was current so make it so in the level view
							QTreeWidgetItem* hViewInterfItem = &getHViewItemFrom(*m_pCrtInterf);
							m_hViewProjStructWidg->setCurrentItem(hViewInterfItem);
							updateDesViewer(*m_pCrtInterf);
						}
						else
						{
							//no subsystem or interface is current set the root item as current
							m_hViewProjStructWidg->setCurrentItem(m_hViewRootItem);
							resetDesViewer();
						}

						//synchronize the current des
						if (m_pCrtDes)
						{
							QTreeWidgetItem* hViewDesItem = &getHViewItemFrom(*m_pCrtDes);
							m_desViewWidg->setCurrentItem(hViewDesItem);
							m_desViewWidg->setFocus(); 
						}

						break;
					}

					case cFlatViewIndex:	//old-view = L-View	new-view = F-View
					{
						if (m_pCrtDes)
						{
							QTreeWidgetItem* fViewDesItem = &getFViewItemFrom(*m_pCrtDes);
							m_fViewProjStructWidg->setCurrentItem(fViewDesItem);
						}
						else
						{
							m_fViewProjStructWidg->setCurrentItem(m_fViewRootItem);
							m_fViewRootItem->setSelected(true);
						}
						break;
					}

					default:
						assert(false);
				}
				break;
			}

			case cFlatViewIndex:
			{
				//synchronize the current DES in the new view
				switch(iNewCurrentView)
				{
					case cHierViewIndex:	//old-view = F-View	new-view = H-View
					{
						//synchronize the current subsystem/interface with the new current view
						if (m_pCrtSubsys)
						{
							assert(m_pCrtInterf == null);

							//A subsystem was current so make it so in the level view
							QTreeWidgetItem* hViewSubsysItem = &getHViewItemFrom(*m_pCrtSubsys);
							m_hViewProjStructWidg->setCurrentItem(hViewSubsysItem);
							updateDesViewer(*m_pCrtSubsys);
						}
						else if (m_pCrtInterf)
						{
							assert(m_pCrtSubsys == null);

							//An interface was current so make it so in the level view
							QTreeWidgetItem* hViewInterfItem = &getHViewItemFrom(*m_pCrtInterf);
							m_hViewProjStructWidg->setCurrentItem(hViewInterfItem);
							updateDesViewer(*m_pCrtInterf);
						}
						else
						{
							//no subsystem or interface is current set the root item as current
							m_hViewProjStructWidg->setCurrentItem(m_hViewRootItem);
							resetDesViewer();
						}

						//synchronize the current des
						if (m_pCrtDes)
						{
							QTreeWidgetItem* hViewDesItem = &getHViewItemFrom(*m_pCrtDes);
							m_desViewWidg->setCurrentItem(hViewDesItem);
							m_desViewWidg->setFocus(); 

						}

						break;
					}

					case cLevelViewIndex:   //old-view = F-View	new-view = L-View
					{
						if (m_pCrtDes)
						{
							QTreeWidgetItem* lViewDesItem = &getLViewItemFrom(*m_pCrtDes);
							m_lViewProjStructWidg->setCurrentItem(lViewDesItem);
						}
						else if (m_pCrtSubsys)
						{
							assert(m_pCrtInterf == null);

							//A subsystem was current so make it so in the level view
							QTreeWidgetItem* lViewSubsysItem = &getLViewItemFrom(*m_pCrtSubsys);
							m_lViewProjStructWidg->setCurrentItem(lViewSubsysItem);
						}
						else if (m_pCrtInterf)
						{
							assert(m_pCrtSubsys == null);

							//An interface was current so make it so in the level view
							QTreeWidgetItem* lViewInterfItem = &getLViewItemFrom(*m_pCrtInterf);
							m_lViewProjStructWidg->setCurrentItem(lViewInterfItem);
						}
						else
						{
							//no subsystem or interface is current set the root item as current
							m_lViewProjStructWidg->setCurrentItem(m_lViewRootItem);
						}
						break;
					}

					default:
						assert(false);
				}
				break;
			}

			default:
				assert(false);
		}
	}
	catch_display_ex_in(m_projStructTabWidget->parentWidget())

	//now that the views were synchronized remember the current view
	m_crtView = iNewCurrentView;
}

//_________________________________________________________________________________________________

void HierProjStructureUiPart::onHViewDesItemActivated(QTreeWidgetItem* item, int /*column*/)
{
	if (isDesHierViewItem(item))
	{
		emit onEnterCurrentDes();
	}
}

//_________________________________________________________________________________________________

void HierProjStructureUiPart::onLViewItemActivated(QTreeWidgetItem* item, int /*column*/)
{
	if (isDesLevelViewItem(item))
	{
		emit onEnterCurrentDes();
	}
}

//_________________________________________________________________________________________________

void HierProjStructureUiPart::onHViewItemDeleted()
{
	if (m_pCrtSubsys)
	{
		emit onCurrentSubsystemDeleted();
	}
	else if (m_pCrtInterf)
	{
		emit onCurrentInterfaceDeleted();
	}
}

//_________________________________________________________________________________________________

void HierProjStructureUiPart::onHViewDesItemDeleted()
{
	QTreeWidgetItem* pCrtItem = m_desViewWidg->currentItem();
	if (pCrtItem && isDesHierViewItem(pCrtItem))
	{
		emit onCurrentDesDeleted();
	}
}

//_________________________________________________________________________________________________

void HierProjStructureUiPart::onLViewItemDeleted()
{
	QTreeWidgetItem* pCrtItem = m_lViewProjStructWidg->currentItem();
	if (pCrtItem == null)
		return; //nothing to do anymore as nothing was deleted
	
	if (isDesLevelViewItem(pCrtItem))
	{
		emit onCurrentDesDeleted();
	}
	else if (isSubsysLevelViewItem(pCrtItem))
	{
		emit onCurrentSubsystemDeleted();
	}
	else if (isInterfLevelViewItem(pCrtItem))
	{
		emit onCurrentInterfaceDeleted();
	}
}

//_________________________________________________________________________________________________

bool HierProjStructureUiPart::isSubsysHierViewItem(const QTreeWidgetItem* item)
{
	if (item == m_hViewRootSubsysItem)
		return true;

	if ((item->parent() != null) && isInterfHierViewItem(item->parent()))
		return true;

	return false;
}

//_________________________________________________________________________________________________

const DesSubsystem& HierProjStructureUiPart::getSubsystemFromHItem(QTreeWidgetItem* item)
{
	//Make sure the item is an interface item
	if (isSubsysHierViewItem(item) == false)
	{
		throw EX("The given item is not a subsystem item. Cannot return subsystem")
	}

	DesSubsystem* pSubsys = reinterpret_cast<DesSubsystem*>(item->data(0, Qt::UserRole).toULongLong());
	assert(pSubsys != null);
	return *pSubsys;
}

//_________________________________________________________________________________________________

QTreeWidgetItem& HierProjStructureUiPart::getHViewItemFrom(const DesSubsystem& subsys)
{
	if (&subsys == &project()->getRootSubsys())
	{
		//Got lucky - it was the root subsystem
		return *m_hViewRootSubsysItem;
	}
	else
	{
		//it must be a low-level subsystem so go through the low level items
		for(int iItem = 0; iItem < m_hViewRootSubsysItem->childCount(); iItem++)
		{
			QTreeWidgetItem* crtInterfItem = m_hViewRootSubsysItem->child(iItem);
			QTreeWidgetItem* crtLowSubsysItem = crtInterfItem->child(0); //only one child per interface is allowed
			if (crtLowSubsysItem)
			{
				const DesSubsystem& crtSubsys = getSubsystemFromHItem(crtLowSubsysItem);
				if (&crtSubsys == &subsys)
				{
					//found it
					return *crtLowSubsysItem;
				}
			}
		}
	}

	throw EX("Cannot locate the given subsystem")
}

//_________________________________________________________________________________________________

bool HierProjStructureUiPart::isInterfHierViewItem(const QTreeWidgetItem* item)
{
	if ((item->parent() != null) && (item->parent() == m_hViewRootSubsysItem))
		return true;

	return false;
}

//_________________________________________________________________________________________________

const DesInterface& HierProjStructureUiPart::getInterfaceFromHItem(const QTreeWidgetItem* item)
{
	//Make sure the item is an interface item
	if (item->parent() != m_hViewRootSubsysItem)
	{
		throw EX("The given item is not an interface item. Cannot return interface")
	}

	DesInterface* pInterface = reinterpret_cast<DesInterface*>(item->data(0, Qt::UserRole).toULongLong());
	assert(pInterface != null);
	return *pInterface;
}

//_________________________________________________________________________________________________

QTreeWidgetItem& HierProjStructureUiPart::getHViewItemFrom(const DesInterface& interf)
{
	for(int iItem = 0; iItem < m_hViewRootSubsysItem->childCount(); iItem++)
	{
		QTreeWidgetItem* crtItem = m_hViewRootSubsysItem->child(iItem);
		const DesInterface& crtInterf = getInterfaceFromHItem(crtItem);
		if (&crtInterf == &interf)
		{
			//found it
			return *crtItem;
		}
	}

	throw EX("Cannot locate the given interface")
}

//_________________________________________________________________________________________________

//conversion between Des <-> QTreeWidgetItem for the Hierarchy View (the Des View Widget in this view)
bool HierProjStructureUiPart::isDesHierViewItem(const QTreeWidgetItem* item)
{
	if ((m_supDesRootItem != null) && (m_plantDesRootItem != null))
	{
		//The current container is a subsystem so DES items must be divided into plants and supervisors
		return ((item->parent() == m_supDesRootItem) || (item->parent() == m_plantDesRootItem));
	}
	else if ((m_supDesRootItem == null) && (m_plantDesRootItem == null))
	{
		//The current container is an interface so DES items are directly under the root item
		return (item->parent() == m_desViewRootItem);
	}
	else
	{
		//this means that  one of the supervisor item or plant item are null but not both
		//this shouldn't happen.
		assert(true);
		return false;
	}

	return false;
}

//_________________________________________________________________________________________________

Des& HierProjStructureUiPart::getDesFromHItem(const QTreeWidgetItem* item)
{
	//Make sure the item is an interface item
	if (isDesHierViewItem(item) == false)
	{
		throw EX("The given item is not a DES item. Cannot return DES")
	}

	Des* pDes = reinterpret_cast<Des*>(item->data(0, Qt::UserRole).toULongLong());
	assert(pDes != null);
	return *pDes;
}

//_________________________________________________________________________________________________

QTreeWidgetItem& HierProjStructureUiPart::getHViewItemFrom(const Des& des)
{
	QTreeWidgetItem* foundItem = null;	
	if (findHViewItemFrom(des, foundItem))
	{
		return *foundItem;
	}
	
	throw EX("Cannot locate the given DES")
}

//_________________________________________________________________________________________________

bool HierProjStructureUiPart::findHViewItemFrom(const Des& des, QTreeWidgetItem*& out_foundItem)
{
	if (m_supDesRootItem)
	{
		//Search all the supervisor DES items
		if (searchDesInHViewItem(*m_supDesRootItem, des, out_foundItem))
		{
			return true;
		}
	}
	
	if (m_plantDesRootItem)
	{
		//Search all the plant DES items
		if (searchDesInHViewItem(*m_plantDesRootItem, des, out_foundItem))
		{
			return true;
		}
	}
	
	if ((m_supDesRootItem == null) && (m_plantDesRootItem == null))
	{
		//Look right under the root as the root is not divided into  supervisor and plants
		if (searchDesInHViewItem(*m_desViewRootItem, des, out_foundItem))
		{
			return true;
		}
	}

	return false;
}

//_________________________________________________________________________________________________

bool HierProjStructureUiPart::searchDesInHViewItem(QTreeWidgetItem& desContainerItem, const Des& des, 
												   QTreeWidgetItem*& out_foundItem)
{
	for(int iItem = 0; iItem < desContainerItem.childCount(); iItem++)
	{
		QTreeWidgetItem* crtItem = desContainerItem.child(iItem);
		Des& crtDes = getDesFromHItem(crtItem);
		if (&crtDes == &des)
		{
			//found it
			out_foundItem = crtItem;
			return true;
		}
	}

	return false;
}

//_________________________________________________________________________________________________

//conversion between DesSubsystem <-> QTreeWidgetItem for the Level View
bool HierProjStructureUiPart::isSubsysLevelViewItem(const QTreeWidgetItem* item)
{
	QTreeWidgetItem* itemParent = item->parent();
	if (itemParent)
	{
		return (itemParent == m_highLevelItem) || (itemParent == m_lowLevelItem);
	}
	else
	{
		return false;
	}
}

//_________________________________________________________________________________________________

const DesSubsystem& HierProjStructureUiPart::getSubsystemFromLItem(QTreeWidgetItem* item)
{
	if (isSubsysLevelViewItem(item) == false)
	{
		throw EX("The given item is not a subsystem item. Cannot return subsystem")
	}

	DesSubsystem* pSubsys = reinterpret_cast<DesSubsystem*>(item->data(0, Qt::UserRole).toULongLong());
	assert(pSubsys != null);
	return *pSubsys;
}

//_________________________________________________________________________________________________

QTreeWidgetItem& HierProjStructureUiPart::getLViewItemFrom(const DesSubsystem& subsys)
{
	//try the root subsystem
	if (&subsys == &project()->getRootSubsys())
	{
		//We are luck - this is the root subsystem
		return *m_lViewRootSubsysItem;
	}
	else
	{
		//Go through all the children of the low-level item and see which one is match
		for(int iItem = 0; iItem < m_lowLevelItem->childCount(); iItem++)
		{
			QTreeWidgetItem* crtItem = m_lowLevelItem->child(iItem);
			const DesSubsystem& crtSubsys = getSubsystemFromLItem(crtItem);
			if (&crtSubsys == &subsys)
			{
				//found it
				return *crtItem;
			}
		}

		throw EX("Cannot locate the given subsystem")

	}
}

//_________________________________________________________________________________________________

//conversion between DesInterface <-> QTreeWidgetItem for the Level View
bool HierProjStructureUiPart::isInterfLevelViewItem(const QTreeWidgetItem* item)
{
	QTreeWidgetItem* itemParent = item->parent();
	if (itemParent)
	{
		return (itemParent == m_interfLevelItem);
	}
	else
	{
		return false;
	}
}

//_________________________________________________________________________________________________

const DesInterface& HierProjStructureUiPart::getInterfaceFromLItem(const QTreeWidgetItem* item)
{
	if (isInterfLevelViewItem(item) == false)
	{
		throw EX("The given item is not an interface item. Cannot return interface")
	}

	DesInterface* pInterface = reinterpret_cast<DesInterface*>(item->data(0, Qt::UserRole).toULongLong());
	assert(pInterface != null);
	return *pInterface;
}

//_________________________________________________________________________________________________

QTreeWidgetItem& HierProjStructureUiPart::getLViewItemFrom(const DesInterface& interf)
{
	for(int iItem = 0; iItem < m_interfLevelItem->childCount(); iItem++)
	{
		QTreeWidgetItem* crtItem = m_interfLevelItem->child(iItem);
		const DesInterface& crtInterf = getInterfaceFromLItem(crtItem);
		if (&crtInterf == &interf)
		{
			//found it
			return *crtItem;
		}
	}

	throw EX("Cannot locate the given interface")
}

//_________________________________________________________________________________________________

//conversion between Des <-> QTreeWidgetItem for the Level View
bool HierProjStructureUiPart::isDesLevelViewItem(const QTreeWidgetItem* item)
{
	if (item->treeWidget() != m_lViewProjStructWidg)
	{
		return false;
	}

	//find out what level is the item at (0 = root)
	int level = 0;
	QTreeWidgetItem* parent = item->parent();
	while(parent != null)
	{
		parent = parent->parent();
		level++;
	}

	switch(level)
	{
		case 4:
			//this is the highest level of an item which means it is a leafe and therefore a des item
			return true; 

		case 3:
			//only interface DES can have this level
			return (item->parent()->parent() == m_interfLevelItem);

		case 2:
		case 1:
		case 0:
			return false;

		default:
			assert(level >= 0 && level <= 4);
			return false;
	}
}

//_________________________________________________________________________________________________

Des& HierProjStructureUiPart::getDesFromLItem(const QTreeWidgetItem* item)
{
	if (isDesLevelViewItem(item) == false)
	{
		throw EX("The given item is not a DES item. Cannot return DES")
	}

	Des* pDes = reinterpret_cast<Des*>(item->data(0, Qt::UserRole).toULongLong());
	assert(pDes != null);
	return *pDes;
}

//_________________________________________________________________________________________________

QTreeWidgetItem& HierProjStructureUiPart::getLViewItemFrom(const Des& des)
{
	QTreeWidgetItem* foundItem = null;
	
	//Search throgh all subsystems 
	DesHierProject::SubsysIteratorPtr subsysIt = project()->createSubsysIterator();
	for(subsysIt->first(); subsysIt->isDone() == false; subsysIt->next())
	{
		const DesSubsystem& crtSubsys = subsysIt->currentItem();
		QTreeWidgetItem& crtSubsysItem = getLViewItemFrom(crtSubsys);
		
		//get the supervisor item which is parent of all the supervisor DES in the subsystem
		QTreeWidgetItem& crtSubsysSupItem = *crtSubsysItem.child(0);
		if (searchDesInLViewItem(crtSubsysSupItem, des, foundItem))
		{
			return *foundItem;
		}

		//get the plant item which is parent of all the plant DES in the subsystem
		QTreeWidgetItem& crtSubsysPlantItem = *crtSubsysItem.child(1);
		if (searchDesInLViewItem(crtSubsysPlantItem, des, foundItem))
		{
			return *foundItem;
		}
	}

	//Search through all interfaces
	DesHierProject::InterfIteratorPtr interfIt = project()->createInterfIterator();
	for(interfIt->first(); interfIt->isDone() == false; interfIt->next())
	{
		const DesInterface& crtInterf = interfIt->currentItem();
		QTreeWidgetItem& crtInterfItem = getLViewItemFrom(crtInterf);
		if (searchDesInLViewItem(crtInterfItem, des, foundItem))
		{
			return *foundItem;
		}
	}

	//if we got here it means the DES couldn't be located in either subsystems or interfaces so we can't find it
	throw EX("Cannot locate the given DES")
}

//_________________________________________________________________________________________________

bool HierProjStructureUiPart::searchDesInLViewItem(QTreeWidgetItem& desContainerItem, const Des& des, QTreeWidgetItem*& out_foundItem)
{
	for(int iItem = 0; iItem < desContainerItem.childCount(); iItem++)
	{
		QTreeWidgetItem* crtItem = desContainerItem.child(iItem);
		Des& crtDes = getDesFromLItem(crtItem);
		if (&crtDes == &des)
		{
			//found it
			out_foundItem = crtItem;
			return true;
		}
	}

	return false;
}

//_________________________________________________________________________________________________

const QTreeWidgetItem* HierProjStructureUiPart::getLevelItem(const QTreeWidgetItem* item)
{
	const QTreeWidgetItem* crtItem = item;
	const QTreeWidgetItem* crtItemParent = item->parent();
	if (crtItemParent == null) return null;

	//go up the hierarchy of items until we reach the root. The item whose grand-parent is the root is the
	//level item
	while(crtItemParent->parent() != null)
	{
		crtItem = crtItem->parent();
		crtItemParent = crtItem->parent();
	}
	
	return crtItem;
}

//_________________________________________________________________________________________________

void HierProjStructureUiPart::onProjectNameChanged(const std::wstring& newName, const std::wstring& oldName)
{
	ProjStructureUiPart::onProjectNameChanged(newName, oldName);

	m_hViewRootItem->setText(0, QString::fromStdWString(newName));
	m_lViewRootItem->setText(0, QString::fromStdWString(newName));
}

//_________________________________________________________________________________________________

void HierProjStructureUiPart::onProjectCleaned()
{
	//go through all the items in the hierachy view and reset the item's properties
	const DesSubsystem& rootSubsys = getSubsystemFromHItem(m_hViewRootSubsysItem);
	updateHViewItemIConsistProp(*m_hViewRootSubsysItem, rootSubsys);
	updateHViewItemLwNonBlockProp(*m_hViewRootSubsysItem, rootSubsys);
	updateHViewItemLwCtrlProp(*m_hViewRootSubsysItem, rootSubsys);
	
	//the children of the root subsys are the interfaces
	for(int iItem = 0; iItem < m_hViewRootSubsysItem->childCount(); iItem++)
	{													  
		QTreeWidgetItem* crtInterfItem = m_hViewRootSubsysItem->child(iItem);
		
		const DesInterface& crtInterf = getInterfaceFromHItem(crtInterfItem);
		updateHViewItemIConsistProp(*crtInterfItem, crtInterf);

		//get the low-level subsystem item - only one child per interface is allowed for now
		QTreeWidgetItem* crtLowSubsysItem = crtInterfItem->child(0); 
		if (crtLowSubsysItem)
		{
			const DesSubsystem& crtLowSubsys = getSubsystemFromHItem(crtLowSubsysItem);
			updateHViewItemIConsistProp(*crtLowSubsysItem, crtLowSubsys);
			updateHViewItemLwNonBlockProp(*crtLowSubsysItem, crtLowSubsys);
			updateHViewItemLwCtrlProp(*crtLowSubsysItem, crtLowSubsys);
		}
	}
}

//_________________________________________________________________________________________________

void HierProjStructureUiPart::onIConsistStatusChecked()
{
	//go through all the items in the hierachy view and set the item's interface consistency property
	const DesSubsystem& rootSubsys = getSubsystemFromHItem(m_hViewRootSubsysItem);
	updateHViewItemIConsistProp(*m_hViewRootSubsysItem, rootSubsys);

	//the children of the root subsys are the interfaces
	for(int iItem = 0; iItem < m_hViewRootSubsysItem->childCount(); iItem++)
	{													  
		QTreeWidgetItem* crtInterfItem = m_hViewRootSubsysItem->child(iItem);
		
		const DesInterface& crtInterf = getInterfaceFromHItem(crtInterfItem);
		updateHViewItemIConsistProp(*crtInterfItem, crtInterf);

		//get the low-level subsystem item - only one child per interface is allowed for now
		QTreeWidgetItem* crtLowSubsysItem = crtInterfItem->child(0); 
		if (crtLowSubsysItem)
		{
			const DesSubsystem& crtLowSubsys = getSubsystemFromHItem(crtLowSubsysItem);
			updateHViewItemIConsistProp(*crtLowSubsysItem, crtLowSubsys);
		}
	}
}

//_________________________________________________________________________________________________

void HierProjStructureUiPart::onInterfIConsistStatusChanged(const DesInterface& interf)
{
	//find the item corresponding to the subsystem and display the interf consist property
	QTreeWidgetItem& hViewInterfItem = getHViewItemFrom(interf);
	updateHViewItemIConsistProp(hViewInterfItem, interf);
}

//_________________________________________________________________________________________________

void HierProjStructureUiPart::onSubsysIConsistStatusChanged(const DesSubsystem& subsys)
{
	//find the item corresponding to the subsystem and display the interf consist property
	QTreeWidgetItem& hViewSubsysItem = getHViewItemFrom(subsys);
	updateHViewItemIConsistProp(hViewSubsysItem, subsys);
}

//_________________________________________________________________________________________________

void HierProjStructureUiPart::onLwCtrlStatusChecked()
{
	//go through all the items in the hierachy view and set the item's controllable property
	const DesSubsystem& rootSubsys = getSubsystemFromHItem(m_hViewRootSubsysItem);
	updateHViewItemLwCtrlProp(*m_hViewRootSubsysItem, rootSubsys);

	//the children of the root subsys are the interfaces
	for(int iItem = 0; iItem < m_hViewRootSubsysItem->childCount(); iItem++)
	{													  
		QTreeWidgetItem* crtInterfItem = m_hViewRootSubsysItem->child(iItem);
		
		//get the low-level subsystem item - only one child per interface is allowed for now
		QTreeWidgetItem* crtLowSubsysItem = crtInterfItem->child(0); 
		if (crtLowSubsysItem)
		{
			const DesSubsystem& crtLowSubsys = getSubsystemFromHItem(crtLowSubsysItem);
			updateHViewItemLwCtrlProp(*crtLowSubsysItem, crtLowSubsys);
		}
	}
}

//_________________________________________________________________________________________________

void HierProjStructureUiPart::onSubsysLwCtrlStatusChanged(const DesSubsystem& subsys)
{
	//find the item corresponding to the subsystem and display the controllable property
	QTreeWidgetItem& hViewSubsysItem = getHViewItemFrom(subsys);
	updateHViewItemLwCtrlProp(hViewSubsysItem, subsys);
}

//_________________________________________________________________________________________________

void HierProjStructureUiPart::onLwNonBlockStatusChecked()
{
	//go through all the items in the hierachy view and set the item's nonblocking property
	const DesSubsystem& rootSubsys = getSubsystemFromHItem(m_hViewRootSubsysItem);
	updateHViewItemLwNonBlockProp(*m_hViewRootSubsysItem, rootSubsys);

	//the children of the root subsys are the interfaces
	for(int iItem = 0; iItem < m_hViewRootSubsysItem->childCount(); iItem++)
	{													  
		QTreeWidgetItem* crtInterfItem = m_hViewRootSubsysItem->child(iItem);
		
		//get the low-level subsystem item - only one child per interface is allowed for now
		QTreeWidgetItem* crtLowSubsysItem = crtInterfItem->child(0); 
		if (crtLowSubsysItem)
		{
			const DesSubsystem& crtLowSubsys = getSubsystemFromHItem(crtLowSubsysItem);
			updateHViewItemLwNonBlockProp(*crtLowSubsysItem, crtLowSubsys);
		}
	}
}

//_________________________________________________________________________________________________

void HierProjStructureUiPart::onSubsysLwNonBlockStatusChanged(const DesSubsystem& subsys)
{
	//find the item corresponding to the subsystem and display the interf consist property
	QTreeWidgetItem& hViewSubsysItem = getHViewItemFrom(subsys);
	updateHViewItemLwNonBlockProp(hViewSubsysItem, subsys);
}

//_________________________________________________________________________________________________

void HierProjStructureUiPart::onHighLevelSubsysAdded(const DesSubsystem& highLevelSubsys)
{
	QString itemText = QString::fromStdWString(highLevelSubsys.getName());
	QString itemTooltip = STR_SUBSYS_ITEM_TOOLTIP(itemText, "0");
	
	//add an item in the hierarchy view
	{
		m_hViewRootSubsysItem = createHierViewItem(itemText, itemTooltip, 
												   m_hViewRootItem, &highLevelSubsys);
		
		//set the item's properties
		m_hViewRootSubsysItem->setText(cIcColIndex, highLevelSubsys.isInterfConsist() ? cPropTrueSymbol : cPropFalseSymbol);
		m_hViewRootSubsysItem->setText(cNbColIndex, highLevelSubsys.isNonBlocking() ? cPropTrueSymbol : cPropFalseSymbol);
		m_hViewRootSubsysItem->setText(cCtrlColIndex, highLevelSubsys.isControllable() ? cPropTrueSymbol : cPropFalseSymbol);
		
		m_hViewProjStructWidg->expandItem(m_hViewRootSubsysItem);
	}

	//add an item in the level view
	{
		m_lViewRootSubsysItem = createLevelViewItem(itemText, itemTooltip, 
													m_highLevelItem, &highLevelSubsys);
		m_lViewProjStructWidg->expandItem(m_lViewRootSubsysItem);

		//create a supervisor item for the subsystem
		QTreeWidgetItem* supItem = createLevelViewItem(STR_LEVEL_VIEW_SUPERVISOR, STR_LEVEL_VIEW_SUPERVISOR_TOOLTIP("0"), m_lViewRootSubsysItem);

		//load all the supervisor DES belonging to this subsystem
		DesSubsystem::DesIteratorPtr supDesIt = highLevelSubsys.createDesIterator(eSupervisorDes);
		addSupDesToUiItem(supItem, supDesIt); 
		m_lViewProjStructWidg->expandItem(supItem);

		//create a plant item
		QTreeWidgetItem* plantItem = createLevelViewItem(STR_LEVEL_VIEW_PLANT, STR_LEVEL_VIEW_PLANT_TOOLTIP("0"), m_lViewRootSubsysItem);

		//load all the plant DES belonging to this subsystem
		DesSubsystem::DesIteratorPtr plantDesIt = highLevelSubsys.createDesIterator(ePlantDes);
		addPlantDesToUiItem(plantItem, plantDesIt); 
		m_lViewProjStructWidg->expandItem(plantItem);
	}

	//the flat view doesn't show subsystems so there is no need to add an item for the subsystem but we need to add
	//its components
	{
		DesSubsystem::DesIteratorPtr supDesIt = highLevelSubsys.createDesIterator(eSupervisorDes);
		addSupDesToUiItem(m_flatStructSupUiItem, supDesIt);
		
		DesSubsystem::DesIteratorPtr plantDesIt = highLevelSubsys.createDesIterator(ePlantDes);
		addPlantDesToUiItem(m_flatStructPlantUiItem, plantDesIt);
	}
	
	if (m_addHighLvlSubsysAct)
	{
		m_addHighLvlSubsysAct->setEnabled(false);
	}
}

//_________________________________________________________________________________________________

void HierProjStructureUiPart::onInterfaceAdded(const DesInterface& interf)
{
	QString itemText = QString::fromStdWString(interf.getName());
	QString itemTooltip = STR_SUBSYS_ITEM_TOOLTIP(itemText, "0", "0");
	
	//add an item in the hierarchy view
	{
		QTreeWidgetItem* interfItem = createHierViewItem(itemText, itemTooltip, 
														 m_hViewRootSubsysItem, &interf);
		
		//set the item's properties
		interfItem->setText(cIcColIndex, interf.isInterfConsist() ? cPropTrueSymbol : cPropFalseSymbol);

		m_hViewProjStructWidg->expandItem(interfItem);
	}

	//add an item in the level view
	{
		QTreeWidgetItem* interfItem = createLevelViewItem(itemText, itemTooltip, 
														  m_interfLevelItem, &interf);
		m_lViewProjStructWidg->expandItem(interfItem);
		
		DesInterface::DesIteratorPtr desIt = interf.createDesIterator();
		addSupDesToUiItem(interfItem, desIt);
	}

	//the flat view doesn't show interfaces so there is no need to add and item for the interface
	//but we need to add its components
	{
		DesInterface::DesIteratorPtr desIt = interf.createDesIterator();
		addSupDesToUiItem(m_flatStructSupUiItem, desIt);
	}
	
}

//_________________________________________________________________________________________________

void HierProjStructureUiPart::onLowLevelSubsysAdded(const DesSubsystem& lowLevelSubsys)
{
	QString itemText = QString::fromStdWString(lowLevelSubsys.getName());
	QString itemTooltip = STR_SUBSYS_ITEM_TOOLTIP(itemText, "0", "0");
	
	//the low level subsystem will be added in the hierarcy view when the dependency notification arrives
	
	//add an item in the level view
	{
		QTreeWidgetItem* lViewItem = createLevelViewItem(itemText, itemTooltip, m_lowLevelItem, &lowLevelSubsys);
		m_lViewProjStructWidg->expandItem(lViewItem);

		QTreeWidgetItem* lViewSupItem = createLevelViewItem(STR_LEVEL_VIEW_SUPERVISOR, STR_LEVEL_VIEW_SUPERVISOR_TOOLTIP("0"), lViewItem);
		m_lViewProjStructWidg->expandItem(lViewSupItem);

		//load all the supervisor DES belonging to this subsystem
		DesSubsystem::DesIteratorPtr supDesIt = lowLevelSubsys.createDesIterator(eSupervisorDes);
		addSupDesToUiItem(lViewSupItem, supDesIt); 

		QTreeWidgetItem* lViewPlantItem = createLevelViewItem(STR_LEVEL_VIEW_PLANT, STR_LEVEL_VIEW_PLANT_TOOLTIP("0"), lViewItem);
		m_lViewProjStructWidg->expandItem(lViewPlantItem);

		//load all the plant DES belonging to this subsystem
		DesSubsystem::DesIteratorPtr plantDesIt = lowLevelSubsys.createDesIterator(ePlantDes);
		addPlantDesToUiItem(lViewPlantItem, plantDesIt); 
	}


	//the flat view doesn't show subsystems so there is no need to add and item for the subsystem. However
	//we need to add its components
	{
		DesSubsystem::DesIteratorPtr supDesIt = lowLevelSubsys.createDesIterator(eSupervisorDes);
		addSupDesToUiItem(m_flatStructSupUiItem, supDesIt);
		
		DesSubsystem::DesIteratorPtr plantDesIt = lowLevelSubsys.createDesIterator(ePlantDes);
		addPlantDesToUiItem(m_flatStructPlantUiItem, plantDesIt);
	}
}

//_________________________________________________________________________________________________

void HierProjStructureUiPart::onDependencyAdded(const DesSubsystem& /*subsys*/, 
					   const DesInterface& interf, 
					   const DesSubsystem& dependent)
{
	QString itemText = QString::fromStdWString(dependent.getName());
	QString itemTooltip = STR_SUBSYS_ITEM_TOOLTIP(itemText, "0", "0");
	
	//add an item in the hierarchy view
	QTreeWidgetItem& interfItem = getHViewItemFrom(interf);
	QTreeWidgetItem* lowSubsysItem = createHierViewItem(itemText, itemTooltip, &interfItem, &dependent);

	//set the item's properties
	lowSubsysItem->setText(cIcColIndex, dependent.isInterfConsist() ? cPropTrueSymbol : cPropFalseSymbol);
	lowSubsysItem->setText(cNbColIndex, dependent.isNonBlocking() ? cPropTrueSymbol : cPropFalseSymbol);
	lowSubsysItem->setText(cCtrlColIndex, dependent.isControllable() ? cPropTrueSymbol : cPropFalseSymbol);
}

//_________________________________________________________________________________________________

void HierProjStructureUiPart::onSubsysRenamed(const DesSubsystem& subsys)
{	
	QString itemText = QString::fromStdWString(subsys.getName());
	QString itemTooltip = STR_SUBSYS_ITEM_TOOLTIP(itemText, 
												  QVariant(subsys.getPlantDesCount()).toString(),
												  QVariant(subsys.getSupDesCount()).toString());
	
	//rename the item in the hierarchy view
	QTreeWidgetItem& hViewSubsysItem = getHViewItemFrom(subsys);
	hViewSubsysItem.setText(cContainerNameColIndex, itemText);
	hViewSubsysItem.setToolTip(cContainerNameColIndex, itemTooltip);

	if (m_pCrtSubsys == &subsys)
	{
		//The current subsystem has been renamed so update the details view
		m_desViewRootItem->setText(cDesNameColIndex, itemText);
		m_desViewRootItem->setToolTip(cDesNameColIndex, itemTooltip);
	}
	
	//rename the item in the level view
	QTreeWidgetItem& lViewSubsysItem = getLViewItemFrom(subsys);
	lViewSubsysItem.setText(0, itemText);
	lViewSubsysItem.setToolTip(0, itemTooltip);
}

//_________________________________________________________________________________________________

void HierProjStructureUiPart::onInterfRenamed(const DesInterface& interf)
{
	QString itemText = QString::fromStdWString(interf.getName());
	QString itemTooltip = STR_INTERF_ITEM_TOOLTIP(itemText, 
												  QVariant(interf.getDesCount()).toString());
	
	//rename the item in the hierarchy view
	QTreeWidgetItem& hViewInterfItem = getHViewItemFrom(interf);
	hViewInterfItem.setText(cContainerNameColIndex, itemText);
	hViewInterfItem.setToolTip(cContainerNameColIndex, itemTooltip);

	if (m_pCrtInterf == &interf)
	{
		//The current subsystem has been renamed so update the details view
		m_desViewRootItem->setText(cDesNameColIndex, itemText);
		m_desViewRootItem->setToolTip(cDesNameColIndex, itemTooltip);
	}

	//rename the item in the level view
	QTreeWidgetItem& lViewInterfItem = getLViewItemFrom(interf);
	lViewInterfItem.setText(0, itemText);
	lViewInterfItem.setToolTip(0, itemTooltip);
}

//_________________________________________________________________________________________________

void HierProjStructureUiPart::onDeletingSubsys(const DesSubsystem& subsys)
{
	try
	{
		//delete the subsystem item from the hierarchical view
		{
			QTreeWidgetItem* subsysItem = &getHViewItemFrom(subsys);
			QTreeWidgetItem* subsysParentItem = subsysItem->parent();
			int subsysItemIndex = subsysParentItem->indexOfChild(subsysItem);
			subsysParentItem->takeChild(subsysItemIndex);
			delete subsysItem;
			subsysItem = null;
		}

		//delete the subsystem item from the level view
		{
			QTreeWidgetItem* subsysItem = &getLViewItemFrom(subsys);
			QTreeWidgetItem* subsysParentItem = subsysItem->parent();
			int subsysItemIndex = subsysParentItem->indexOfChild(subsysItem);
			subsysParentItem->takeChild(subsysItemIndex);
			delete subsysItem;
			subsysItem = null;
		}

		//NOTE: the flat view doesn't display subsystems so no need to update anything there
		//the contained DES which do show there will be taken out when the DES notification arives
	}
	catch_display_ex_in(m_projStructTabWidget->parentWidget())
}

//_________________________________________________________________________________________________

void HierProjStructureUiPart::onDeletingInterf(const DesInterface& interf)
{
	try
	{
		//delete the interface item from the hierarchical view
		{
			QTreeWidgetItem* interfItem = &getHViewItemFrom(interf);
			QTreeWidgetItem* interfParentItem = interfItem->parent();
			int interfItemIndex = interfParentItem->indexOfChild(interfItem);
			interfParentItem->takeChild(interfItemIndex);
			delete interfItem;
			interfItem = null;
		}

		//delete the interface item from the level view
		{
			QTreeWidgetItem* interfItem = &getLViewItemFrom(interf);
			QTreeWidgetItem* interfParentItem = interfItem->parent();
			int interfItemIndex = interfParentItem->indexOfChild(interfItem);
			interfParentItem->takeChild(interfItemIndex);
			delete interfItem;
			interfItem = null;
		}

		//NOTE: the flat view doesn't display subsystems so no need to update anything there
		//the contained DES which do show there will be taken out when the DES notification arives
	}
	catch_display_ex_in(m_projStructTabWidget->parentWidget())
}

//_________________________________________________________________________________________________
//A DES has been added a subsystem. Make its item the current item and add an item to each view
void HierProjStructureUiPart::onDesAdded(const Des& des, DesLevel desLevel, const DesSubsystem& subsys)
{
	try
	{
		//Add the DES to the hierachical view
		{
			QTreeWidgetItem* subsysItem = &getHViewItemFrom(subsys);
			m_hViewProjStructWidg->setCurrentItem(subsysItem);
			
			QTreeWidgetItem* parentItem = (desLevel == eSupervisorDes) ? m_supDesRootItem : m_plantDesRootItem;
			QString itemText = QString::fromStdWString(des.getName());
			QString itemTooltip = STR_HIER_VIEW_DES_TOOLTIP(itemText, QString::fromStdWString(des.getFileName()));
			createHierViewDesItem(itemText, itemTooltip, parentItem, &des);
		}

		//Add the DES to the level view
		{
			QTreeWidgetItem* subsysItem = &getLViewItemFrom(subsys);

			QTreeWidgetItem* parentItem = (desLevel == eSupervisorDes) ? subsysItem->child(cSupChildIdx) : 
																					  subsysItem->child(cPlantChildIdx);
			QString itemText = QString::fromStdWString(des.getName());
			QString itemTooltip = STR_LEVEL_VIEW_DES_TOOLTIP(itemText, QString::fromStdWString(des.getFileName()));
			QTreeWidgetItem* item = createLevelViewItem(itemText, itemTooltip, parentItem, &des);
			m_lViewProjStructWidg->setCurrentItem(item);
		}

		//Add the DES to the flat view
		{
			QTreeWidgetItem* parentItem = (desLevel == eSupervisorDes) ? m_flatStructSupUiItem : 
																					  m_flatStructPlantUiItem;
			QString itemText = QString::fromStdWString(des.getName());
			QString itemTooltip = STR_FLAT_VIEW_DES_TOOLTIP(itemText, QString::fromStdWString(subsys.getName()),
															 QString::fromStdWString(des.getFileName()));
			createFlatViewDesItem(itemText, itemTooltip, parentItem, &des);
		}	
	}
	catch_display_ex_in(m_projStructTabWidget->parentWidget())
}

//_________________________________________________________________________________________________

void HierProjStructureUiPart::onDesAdded(const Des& des, const DesInterface& interf)
{
	try
	{
		//Add the DES to the hierachical view
		{
			QTreeWidgetItem* interfItem = &getHViewItemFrom(interf);
			m_hViewProjStructWidg->setCurrentItem(interfItem);
			
			QTreeWidgetItem* parentItem = m_desViewRootItem;
			QString itemText = QString::fromStdWString(des.getName());
			QString itemTooltip = STR_HIER_VIEW_DES_TOOLTIP(itemText, QString::fromStdWString(des.getFileName()));
			createHierViewDesItem(itemText, itemTooltip, parentItem, &des);
		}

		//Add the DES to the level view
		{
			QTreeWidgetItem* parentItem = &getLViewItemFrom(interf);
			
			QString itemText = QString::fromStdWString(des.getName());
			QString itemTooltip = STR_LEVEL_VIEW_DES_TOOLTIP(itemText, QString::fromStdWString(des.getFileName()));
			QTreeWidgetItem* item = createLevelViewItem(itemText, itemTooltip, parentItem, &des);
			m_lViewProjStructWidg->setCurrentItem(item);
		}

		//Add the DES to the flat view
		{
			QTreeWidgetItem* parentItem = m_flatStructSupUiItem;
			QString itemText = QString::fromStdWString(des.getName());
			QString itemTooltip = STR_FLAT_VIEW_DES_TOOLTIP(itemText, QString::fromStdWString(interf.getName()),
															 QString::fromStdWString(des.getFileName()));
			createFlatViewDesItem(itemText, itemTooltip, parentItem, &des);
		}	
	}
	catch_display_ex_in(m_projStructTabWidget->parentWidget())
}

//_________________________________________________________________________________________________

void HierProjStructureUiPart::onRemovingDes(const Des& des, DesLevel /*desLevel*/, const DesSubsystem& /*subsys*/)
{
	try
	{
		//remove it from the hierarhical view
		{
			QTreeWidgetItem* desItem = null;
			if (findHViewItemFrom(des, desItem)) 
			{
				//an item might not exist for this des if its parent subsystem or interface is not the current one
				//since the Hierarhical View doesn't show all DES but only those of the current subsystem / interface
				//thus, we need to remove the DES item only if it's there
				removeDesItem(des, desItem, m_hViewProjStructWidg);
			}
		}

		//remove it from the level view 
		{
			QTreeWidgetItem* desItem = &getLViewItemFrom(des);
			removeDesItem(des, desItem, m_lViewProjStructWidg);
		}

		//remove it from the flat view
		{
			QTreeWidgetItem* desItem = &getFViewItemFrom(des);
			removeDesItem(des, desItem, m_fViewProjStructWidg); 
		}
	}
	catch_display_ex_in(m_projStructTabWidget->parentWidget())

	//reset the current item if the des being deleted is the current one
	if (m_pCrtDes == &des)
	{
		assert(m_pCrtDes != &des); //the current des should have changed
		m_pCrtDes = null;
	}  
}

//_________________________________________________________________________________________________

void HierProjStructureUiPart::onRemovingDes(const Des& des, const DesInterface& /*interf*/)
{
	try
	{
		//remove it from the hierarhical view
		{
			QTreeWidgetItem* desItem = null;
			if (findHViewItemFrom(des, desItem))
			{
				//an item might not exist for this des if its parent subsystem or interface is not the current one
				//since the Hierarhical View doesn't show all DES but only those of the current subsystem / interface
				//thus, we need to remove the DES item only if it's there
				removeDesItem(des, desItem, m_hViewProjStructWidg);
			}
		}

		//remove it from the flat view 
		{
			QTreeWidgetItem* desItem = &getLViewItemFrom(des);
			removeDesItem(des, desItem, m_lViewProjStructWidg);
		}

		//remove it from the flat view
		{
			QTreeWidgetItem* desItem = &getFViewItemFrom(des);
			removeDesItem(des, desItem, m_fViewProjStructWidg); 
		}
	}
	catch_display_ex_in(m_projStructTabWidget->parentWidget())

	//reset the current item if the des being deleted is the current one
	if (m_pCrtDes == &des)
	{
		assert(m_pCrtDes != &des); //the current des should have changed
		m_pCrtDes = null;
	}  
}

void HierProjStructureUiPart::onDesNameChanged(const Des& des, const std::wstring& /*oldName*/)
{
	try
	{
		QString itemText = QString::fromStdWString(des.getName());
		QString desFileName = QString::fromStdWString(des.getFileName());
		QString itemTooltip =  itemText + " - " + desFileName;

		QTreeWidgetItem& desHItem = getHViewItemFrom(des);
		desHItem.setText(0, itemText);
		desHItem.setToolTip(0, itemTooltip);

		QTreeWidgetItem& desLItem = getLViewItemFrom(des);
		desLItem.setText(0, itemText);
		desLItem.setToolTip(0, itemTooltip);

		QTreeWidgetItem& desFItem = getFViewItemFrom(des);
		desFItem.setText(0, itemText);
		desFItem.setToolTip(0, itemTooltip);
	}
	catch_display_ex_in(m_projStructTabWidget->parentWidget())
}

} //end of namespace DESpot
