/*
 * Project: MoleCuilder
 * Description: creates and alters molecular systems
 * Copyright (C)  2010-2012 University of Bonn. All rights reserved.
 * 
 *
 *   This file is part of MoleCuilder.
 *
 *    MoleCuilder is free software: you can redistribute it and/or modify
 *    it under the terms of the GNU General Public License as published by
 *    the Free Software Foundation, either version 2 of the License, or
 *    (at your option) any later version.
 *
 *    MoleCuilder is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *    GNU General Public License for more details.
 *
 *    You should have received a copy of the GNU General Public License
 *    along with MoleCuilder.  If not, see .
 */
/*
 * QtMoleculeList.cpp
 *
 *  Created on: Jan 21, 2010
 *      Author: crueger
 */
// include config.h
#ifdef HAVE_CONFIG_H
#include 
#endif
#include "QtMoleculeList.hpp"
#include 
#include 
#include "UIElements/Views/Qt4/MoleculeList/QtMoleculeItem.hpp"
#include "UIElements/Views/Qt4/MoleculeList/QtMoleculeItemFactory.hpp"
#include "UIElements/Qt4/InstanceBoard/QtObservedInstanceBoard.hpp"
#include 
#include 
#include 
#include "CodePatterns/MemDebug.hpp"
#include "CodePatterns/Log.hpp"
#include "CodePatterns/Observer/Notification.hpp"
#include "Atom/atom.hpp"
#include "Actions/MoleculeAction/ChangeNameAction.hpp"
#include "Actions/SelectionAction/Molecules/PopMoleculesAction.hpp"
#include "Actions/SelectionAction/Molecules/PushMoleculesAction.hpp"
#include "Actions/SelectionAction/Molecules/MoleculeByIdAction.hpp"
#include "Actions/ActionQueue.hpp"
#include "Actions/ActionSequence.hpp"
#include "Actions/ActionTrait.hpp"
#include "Actions/MakroAction.hpp"
#include "Descriptors/MoleculeIdDescriptor.hpp"
#include "Formula.hpp"
#include "molecule.hpp"
using namespace std;
QtMoleculeList::QtMoleculeList(
    QtObservedInstanceBoard *_board,
    QObject *_parent) :
  QStandardItemModel(_parent),
  board(_board),
  observer(_board),
  nameIsChanged(false)
{
  setColumnCount(QtMoleculeItemFactory::COLUMNCOUNT);
  connect(this,SIGNAL(itemChanged(QStandardItem*)),
      this,SLOT(moleculeNameChanged(QStandardItem*)));
  connect(this, SIGNAL(itemChanged(QStandardItem*)),
      this, SLOT(checkForVisibilityChange(QStandardItem*)));
  connect(&observer, SIGNAL(MoleculeInserted(QtObservedMolecule::ptr)),
      this, SLOT(moleculeInserted(QtObservedMolecule::ptr)));
  connect(&observer, SIGNAL(MoleculeRemoved(ObservedValue_Index_t)),
      this, SLOT(moleculeRemoved(ObservedValue_Index_t)));
  connect(&observer, SIGNAL(FormulaChanged(const QtObservedMolecule::ptr)),
      this, SLOT(formulaChanged(const QtObservedMolecule::ptr)));
  connect(&observer, SIGNAL(NameChanged(const QtObservedMolecule::ptr)),
      this, SLOT(nameChanged(const QtObservedMolecule::ptr)));
  connect(&observer, SIGNAL(AtomCountChanged(const QtObservedMolecule::ptr)),
      this, SLOT(atomcountChanged(const QtObservedMolecule::ptr)));
}
QtMoleculeList::~QtMoleculeList()
{}
QVariant QtMoleculeList::headerData(int section, Qt::Orientation orientation, int role) const
{
  if (role == Qt::DisplayRole) {
    if (orientation == Qt::Horizontal) {
      if (section < QtMoleculeItem::COLUMNTYPES_MAX)
        return QString(QtMoleculeItemFactory::COLUMNNAMES[section]);
    }
  }
  return QVariant();
}
void QtMoleculeList::moleculeInserted(QtObservedMolecule::ptr _mol)
{
  LOG(1, "Adding molecule " << _mol->getMolName());
  // check that World knows the molecule still
  const std::string formula = addMolecule(_mol);
  LOG(1, "Adding " << formula << " to toBeSetOccurrence.");
  setOccurrence(FormulaToGroupItem(formula));
}
void QtMoleculeList::moleculeRemoved(ObservedValue_Index_t _id)
{
  LOG(1, "Removing molecule " << _id);
  if (!isMoleculeItemPresent(_id)) {
    ELOG(1, "QtMoleculeItem to id " << _id << " has disappeared before removal.");
    return;
  }
  QtMoleculeItem *item = MoleculeIdToItem(_id);
  if (item != NULL) {
    const std::string formula = item->parent()->text().toStdString();
    LOG(1, "Adding " << formula << " to toBeSetOccurrence.");
    QStandardItem * const groupitem = FormulaToGroupItem(formula);
    // first remove molitem to reduce count
    removeMoleculeItem(item);
    const int removeindex = setOccurrence(groupitem);
    if (removeindex != -1) {
      LOG(1, "Removing row of group item to " << formula);
      removeRows(removeindex, 1, invisibleRootItem()->index());
    }
  }
}
bool QtMoleculeList::isMoleculeItemPresent(ObservedValue_Index_t _molid) const
{
  MoleculeItemBiMap_t::left_const_iterator iter =
      MoleculeItemBiMap.left.find(_molid);
  return ( iter != MoleculeItemBiMap.left.end());
}
QtMoleculeItem * QtMoleculeList::MoleculeIdToItem(ObservedValue_Index_t _molid) const
{
  MoleculeItemBiMap_t::left_const_iterator iter =
      MoleculeItemBiMap.left.find(_molid);
  ASSERT( iter != MoleculeItemBiMap.left.end(),
      "QtMoleculeList::MoleculeIdToItem() - could not find item to id "
      +toString(_molid));
  return iter->second;
}
ObservedValue_Index_t QtMoleculeList::ItemToMoleculeId(const QtMoleculeItem * const _item) const
{
  const MoleculeItemBiMap_t::right_const_iterator iter =
      MoleculeItemBiMap.right.find(const_cast(_item));
  if (iter != MoleculeItemBiMap.right.end())
    return iter->second;
  else
    return NULL;
}
QtMoleculeItem * QtMoleculeList::getSpecificMoleculeItem(
    const QtMoleculeItem * const _item,
    const enum QtMoleculeItem::COLUMNTYPES _type) const
{
  QStandardItem *parent_item = _item->parent();
  ASSERT( parent_item != NULL,
      "QtMoleculeList::getSpecificMoleculeItem() - parent of molecule item is NULL");
  return static_cast(parent_item->child(_item->index().row(), _type));
}
bool QtMoleculeList::isGroupItemPresent(const std::string &_formula) const
{
  FormulaTreeItemBiMap_t::left_const_iterator iter =
      FormulaItemBiMap.left.find(_formula);
  return ( iter != FormulaItemBiMap.left.end());
}
QStandardItem * QtMoleculeList::FormulaToGroupItem(const std::string &_formula) const
{
  FormulaTreeItemBiMap_t::left_const_iterator iter =
      FormulaItemBiMap.left.find(_formula);
  ASSERT( iter != FormulaItemBiMap.left.end(),
      "QtMoleculeList::FormulaToGroupItem() - could not find item to formula "
      +toString(_formula));
  return iter->second;
}
const std::string& QtMoleculeList::GroupItemToFormula(const QStandardItem * const _item) const
{
  static std::string emptystring;
  const FormulaTreeItemBiMap_t::right_const_iterator iter =
      FormulaItemBiMap.right.find(const_cast(_item));
  if (iter != FormulaItemBiMap.right.end())
    return iter->second;
  else
    return emptystring;
}
QStandardItem * QtMoleculeList::getSpecificGroupItem(
    const QStandardItem * const _item,
    const enum QtMoleculeItem::COLUMNTYPES _type) const
{
  return invisibleRootItem()->child(_item->index().row(), _type);
}
const QModelIndex QtMoleculeList::MoleculeIdToIndex(ObservedValue_Index_t _id) const
{
  QtMoleculeItem * const item = MoleculeIdToItem(_id);
  ASSERT(item != NULL,
      "QtMoleculeList::MoleculeIdToIndex() - could not find item to "
      +toString(_id));
  return indexFromItem(item);
}
ObservedValue_Index_t QtMoleculeList::IndexToMoleculeId(const QModelIndex &_index) const
{
  QtMoleculeItem * const item = dynamic_cast(itemFromIndex(_index));
  if (item == NULL)
    return NULL;
  else
    return ItemToMoleculeId(item);
}
void QtMoleculeList::addGroupItem(
    QStandardItem *&mainitem,
    const std::string &_molecule_formula)
{
  QList groupItems =
      QtMoleculeItemFactory::createGroupItems(_molecule_formula);
  mainitem = groupItems.front();
  FormulaItemBiMap.left.insert( std::make_pair(_molecule_formula, mainitem) );
  if (FormulaVisibilityCountMap.count(_molecule_formula) == 0)
    FormulaVisibilityCountMap.insert( std::make_pair(_molecule_formula, 0));
  invisibleRootItem()->appendRow(groupItems);
}
QList QtMoleculeList::createMoleculeItems(
    QtObservedMolecule::ptr &_ObservedMolecule,
    std::string &_molecule_formula)
{
  QList molItems =
      QtMoleculeItemFactory::createMoleculeItems(_ObservedMolecule);
  QtMoleculeItem *mol_item = dynamic_cast(molItems.front());
  ASSERT( mol_item != NULL,
      "QtMoleculeList::createMoleculeItems() - item from factory was not a QtMoleculeItem?");
  MoleculeItemBiMap.left.insert( std::make_pair(_ObservedMolecule->getIndex(), mol_item) );
  QStandardItem *formulaitem = molItems.at(QtMoleculeItem::FORMULA);
  ASSERT( formulaitem != NULL,
      "QtMoleculeList::createMoleculeItems() - Formula item not created by factory?");
  _molecule_formula = formulaitem->text().toStdString();
  LOG(1, "Adding " << _molecule_formula << " for "
      << _ObservedMolecule->getMolIndex() << " to MoleculeFormulaMap.");
  MoleculeFormulaMap.insert( std::make_pair( _ObservedMolecule->getIndex(), _molecule_formula) );
//  LOG(1, "Inserting molecule " << _molid << ": " << _molecule_formula);
  return molItems;
}
std::string QtMoleculeList::addMolecule(QtObservedMolecule::ptr &_ObservedMolecule)
{
  // find group if already in list
  QStandardItem *groupItem = NULL;
  // create molecule items and obtain the molecule's formula
  std::string molecule_formula;
  QList molItems = createMoleculeItems(_ObservedMolecule, molecule_formula);
  // new molecule type -> create new group
  if (!isGroupItemPresent(molecule_formula)){
    // insert new formula entry into visibility
#ifndef NDEBUG
    std::pair< FormulaVisibilityCountMap_t::iterator, bool> visibilityinserter =
#endif
        FormulaVisibilityCountMap.insert(
            std::make_pair( molecule_formula, (unsigned int)0) );
    ASSERT( visibilityinserter.second,
        "QtMoleculeList::refill() - molecule with formula "
        +molecule_formula+" already in FormulaVisibilityCountMap.");
    // create item and place into Map with formula as key
    addGroupItem(groupItem, molecule_formula);
  } else {
    groupItem = FormulaToGroupItem(molecule_formula);
  }
  ASSERT( groupItem != NULL,
      "QtMoleculeList::addMolecule() - item with id "+toString(_ObservedMolecule->getMolIndex())
      +" has no parent?");
  groupItem->appendRow(molItems);
  return molecule_formula;
}
void QtMoleculeList::removeMoleculeItem(QtMoleculeItem * const _item)
{
  const QModelIndex mol_index = indexFromItem(_item);
  QStandardItem *groupitem = _item->parent();
  const QModelIndex group_index = groupitem->index();
  {
    MoleculeItemBiMap_t::right_iterator removeiter =
        MoleculeItemBiMap.right.find(_item);
    ASSERT( removeiter != MoleculeItemBiMap.right.end(),
        "QtMoleculeList::removeMoleculeItem() - could not find item in MoleculeBiMap.");
  //  LOG(1, "Erasing molecule " << (removeiter->second));
    {
      MoleculeFormulaMap_t::iterator removeformulaiter =
          MoleculeFormulaMap.find(removeiter->second);
      ASSERT( removeformulaiter != MoleculeFormulaMap.end(),
          "QtMoleculeList::removeMoleculeItem() - could not find id "
          +toString(removeiter->second)+" in MoleculeFormulaMap.");
      LOG(1, "Removing " << removeformulaiter->second << " for "
          << removeformulaiter->first << " from MoleculeFormulaMap.");
      MoleculeFormulaMap.erase( removeformulaiter );
    }
    MoleculeItemBiMap.right.erase(removeiter);
  }
  removeRows(mol_index.row(), 1, group_index);
}
void QtMoleculeList::checkForVisibilityChange(QStandardItem* _item)
{
//  qDebug() << "Item changed called.";
  if (_item->index().column() == QtMoleculeItem::VISIBILITY) {
//    qDebug() << "visibilityItem changed: " << (_item->checkState() ? "checked" : "unchecked");
    if ((_item->parent() == NULL) || (_item->parent() == invisibleRootItem())) {
      LOG(1, "Updating visibility of group item " << _item);
      setVisibilityForGroupItem(_item);
    } else {
      LOG(1, "Updating visibility of item " << _item);
      setVisibilityForMoleculeItem( assert_cast(_item) );
    }
  }
}
void QtMoleculeList::setVisibilityForMoleculeItem(QtMoleculeItem* _item)
{
  const bool visible = _item->checkState();
  const ObservedValue_Index_t molid = _item->getMoleculeIndex();
  std::string molecule_formula("illegal");
  {
    const MoleculeFormulaMap_t::const_iterator formulaiter =
        MoleculeFormulaMap.find(molid);
    ASSERT( formulaiter != MoleculeFormulaMap.end(),
        "QtMoleculeList::setVisibilityForMoleculeItem() - formula of molecule "
        +toString(molid)+" unknown.");
    molecule_formula = formulaiter->second;
  }
  ASSERT( FormulaVisibilityCountMap.count(molecule_formula) != 0,
        "QtMoleculeList::setVisibilityForMoleculeItem() - molecule with formula " +molecule_formula
        +" is not present in FormulaVisibilityCountMap.");
  // get parent
  QStandardItem *groupItem = _item->parent();
  QStandardItem *visgroupItem = getSpecificGroupItem(groupItem, QtMoleculeItem::VISIBILITY);
  ASSERT( groupItem != NULL,
      "QtMoleculeList::setVisibilityForMoleculeItem() - item to "
      +toString(molid)+" has not parent?");
  // check whether we have to set the group item
  if (visible) {
    ++(FormulaVisibilityCountMap[molecule_formula]);
    // compare with occurence/total number of molecules
    if (FormulaVisibilityCountMap[molecule_formula] ==
        (unsigned int)(groupItem->rowCount()))
      visgroupItem->setCheckState(Qt::Checked);
  } else {
    --(FormulaVisibilityCountMap[molecule_formula]);
    // none selected anymore?
    if (FormulaVisibilityCountMap[molecule_formula] == 0)
      visgroupItem->setCheckState(Qt::Unchecked);
  }
  emit moleculesVisibilityChanged(molid, visible);
}
void QtMoleculeList::setVisibilityForGroupItem(QStandardItem* _item)
{
  // go through all children, but don't enter for groupItem once more
  const bool visible = _item->checkState();
  QStandardItem *groupitem = getSpecificGroupItem(_item, QtMoleculeItem::NAME);
  for (int i=0;irowCount();++i) {
    QtMoleculeItem * const molItem = dynamic_cast(
        groupitem->child(i, QtMoleculeItem::VISIBILITY));
    if (molItem->checkState() != visible) {
      molItem->setCheckState(visible ? Qt::Checked : Qt::Unchecked);
      // emit signal
      emit moleculesVisibilityChanged(molItem->getMoleculeIndex(), visible);
    }
  }
  // set current number of visible children
  const std::string molecule_formula =
      GroupItemToFormula( getSpecificGroupItem(_item, QtMoleculeItem::NAME) );
  FormulaVisibilityCountMap_t::iterator countiter =
      FormulaVisibilityCountMap.find(molecule_formula);
  ASSERT( countiter != FormulaVisibilityCountMap.end(),
      "QtMoleculeList::setVisibilityForGroupItem() - molecules "+molecule_formula
      +" have no entry in visibility count map?");
  countiter->second = visible ? groupitem->rowCount() : 0;
}
static
MoleCuilder::MakroAction *constructMakroRenameAction(
    MoleCuilder::ActionSequence &sequence,
    const std::string &_new_name,
    const moleculeId_t _molid
    )
{
  MoleCuilder::ActionQueue &AQ = MoleCuilder::ActionQueue::getInstance();
  MoleCuilder::ActionTrait trait("change-single-molecule-name");
  sequence.addAction(AQ.getActionByName("push-molecule-selection").clone(MoleCuilder::Action::NonInteractive));
  MoleCuilder::Action * const selectaction =
      AQ.getActionByName("select-molecule-by-id").clone(MoleCuilder::Action::NonInteractive);
  {
    std::stringstream molid_string;
    molid_string << toString(_molid);
    selectaction->setOptionValue("select-molecule-by-id", molid_string.str());
  }
  sequence.addAction(selectaction);
  MoleCuilder::Action * const changeaction =
      AQ.getActionByName("change-molname").clone(MoleCuilder::Action::NonInteractive);
  changeaction->setOptionValue("change-molname", _new_name);
  sequence.addAction(changeaction);
  sequence.addAction(AQ.getActionByName("pop-molecule-selection").clone(MoleCuilder::Action::NonInteractive));
  MoleCuilder::MakroAction* makroaction =
      new MoleCuilder::MakroAction(trait, sequence);
  return makroaction;
}
void QtMoleculeList::moleculeNameChanged(QStandardItem* item)
{
  // check whether name change came from outside
  if (nameIsChanged)
    return;
  // obtain molecule id
  if ( item->index().column() == QtMoleculeItem::NAME) {
    QtMoleculeItem *molitem = assert_cast(item);
    MoleculeItemBiMap_t::right_const_iterator iter = MoleculeItemBiMap.right.find(molitem);
    ASSERT( iter != MoleculeItemBiMap.right.end(),
        "QtMoleculeList::moleculeChanged() - name of unknown molecule changed.");
    const ObservedValue_Index_t index = iter->second;
    const moleculeId_t molid = board->getMoleculeIdToIndex(index);
    // change the name
    const std::string cellValue = item->text().toStdString();
    const QtObservedMolecule::ptr mol = board->getObservedMolecule(index);
    if (cellValue != mol->getMolName()) {
      if (!cellValue.empty()) {
        // create actions such that we may undo
        static MoleCuilder::ActionSequence sequence;
        MoleCuilder::MakroAction *makroaction =
            constructMakroRenameAction(sequence, cellValue, molid);
        MoleCuilder::ActionQueue &AQ = MoleCuilder::ActionQueue::getInstance();
        AQ.registerAction(makroaction);
        AQ.queueAction("change-single-molecule-name", MoleCuilder::Action::NonInteractive);
      } else {
        if (mol) {
          LOG(2, "WARNING: Not setting changing molecule " << mol->getMolName()
              << " to empty.");
          QtMoleculeItem * const molitem = assert_cast(item);
          molitem->updateState(mol);
        }
      }
    }
  }
}
int QtMoleculeList::setOccurrence(QStandardItem * const _groupitem)
{
  ASSERT( _groupitem != NULL,
      "QtMoleculeList::setOccurrence() - group item at "+toString(_groupitem)
      +" is NULL");
  QModelIndex modelindex = _groupitem->index();
  ASSERT( modelindex.isValid(),
      "QtMoleculeList::setOccurrence() - groupitem not associated to model anymore.");
  const int index = modelindex.row();
  QStandardItem *parent_item =
      _groupitem->parent() == NULL ? invisibleRootItem() : _groupitem->parent();
  ASSERT( parent_item != NULL,
      "QtMoleculeList::setOccurrence() - group item at "+toString(index)
      +" does not have a parent?");
  QStandardItem *occ_item = parent_item->child(index, QtMoleculeItem::OCCURRENCE);
  ASSERT( occ_item != NULL,
      "QtMoleculeList::setOccurrence() - group item at "+toString(index)
      +" does not have an occurrence?");
  const int count = _groupitem->rowCount();
  if (count == 0) {
    // we have to remove the group item completely
    const std::string molecule_formula = _groupitem->text().toStdString();
    FormulaItemBiMap.left.erase(molecule_formula);
    FormulaVisibilityCountMap.erase(molecule_formula);
    return index;
  } else {
    occ_item->setText(QString::number(count));
    return -1;
  }
}
void QtMoleculeList::moveItem(
    QtMoleculeItem *_molitem,
    const std::string &_new_formula)
{
  QStandardItem *groupitem = NULL;
  // prohibit starting of selection actions
  emit MayNotStartSelections();
  // use takeRows of molecule ..
  const QList mol_row = _molitem->parent()->takeRow(_molitem->index().row());
  // ..  and re-add where new formula fits
  if (!isGroupItemPresent(_new_formula)) {
    // add new group item and formula entry
     addGroupItem(groupitem, _new_formula);
  } else {
    groupitem = FormulaToGroupItem(_new_formula);
  }
  ASSERT( groupitem != NULL,
      "QtMoleculeList::readdItem() - failed to create a sensible new groupitem");
  // finally add again
  groupitem->appendRow(mol_row);
  emit MayStartSelections();
}
void QtMoleculeList::formulaChanged(const QtObservedMolecule::ptr _mol)
{
  // we need the id as identifier to the item
  const ObservedValue_Index_t molid = _mol->getIndex();
  LOG(3, "DEBUG: QtMoleculeList got formulaChanged for id " << molid);
  QtMoleculeItem *const molitem = MoleculeIdToItem(molid);
  // update item
  {
    QtMoleculeItem *const formulaitem = getSpecificMoleculeItem(molitem, QtMoleculeItem::FORMULA);
    ASSERT(formulaitem != NULL,
        "QtMoleculeList::formulaChanged() - could not item for FORMULA.");
    formulaitem->updateState(_mol);
  }
  LOG(3, "DEBUG: Moving item to id " << molid);
  const MoleculeFormulaMap_t::iterator formulaiter =
      MoleculeFormulaMap.find(molid);
  ASSERT( formulaiter != MoleculeFormulaMap.end(),
      "QtMoleculeList::updateItemStates() - formula of molecule "
      +toString(molid)+" unknown.");
  // we get old formula from stored map and new formula from the ObservedMolecule
  const std::string old_formula = formulaiter->second;
  const std::string new_formula = _mol->getMolFormula();
  // then we move the item if necessary
  if (old_formula != new_formula) {
    LOG(3, "DEBUG: Moving item " << molitem);
    // remove from formula<->molecule bimap with old formula
    LOG(4, "DEBUG: Removing " << old_formula << " for " << formulaiter->first << " from MoleculeFormulaMap.");
    MoleculeFormulaMap.erase( formulaiter );
    moveItem(molitem, new_formula);
    // changing occurrences for old_formula with possible removal
    const int removeindex = setOccurrence( FormulaToGroupItem(old_formula) );
    if (removeindex != -1) {
      LOG(3, "DEBUG: Removing row of group item to " << old_formula);
      removeRows(removeindex, 1, invisibleRootItem()->index());
    }
    // and add to formula<->molecule bimap with updated new_formula
    LOG(4, "DEBUG: Adding " << new_formula << " for " << molid << " to MoleculeFormulaMap.");
    MoleculeFormulaMap.insert( std::make_pair(molid, new_formula) );
    const int addindex = setOccurrence( FormulaToGroupItem(new_formula) );
    ASSERT( addindex == -1,
        "QtMoleculeList::formulaChanged() - add mol to new formula "+
        toString(new_formula)+" made the row to be removed?");
  }
}
void QtMoleculeList::atomcountChanged(const QtObservedMolecule::ptr _mol)
{
  // we need the id as identifier to the items
  const ObservedValue_Index_t molid = _mol->getIndex();
  LOG(3, "DEBUG: QtMoleculeList got atomcountChanged for id " << molid);
  QtMoleculeItem *const molitem = MoleculeIdToItem(molid);
  // update items
  QtMoleculeItem *const atomcountitem = getSpecificMoleculeItem(molitem, QtMoleculeItem::ATOMCOUNT);
  ASSERT(atomcountitem != NULL,
      "QtMoleculeList::atomcountChanged() - could not item for ATOMCOUNT.");
  atomcountitem->updateState(_mol);
}
void QtMoleculeList::nameChanged(const QtObservedMolecule::ptr _mol)
{
  nameIsChanged = true;
  // we need the id as identifier to the items
  const ObservedValue_Index_t molid = _mol->getIndex();
  LOG(3, "DEBUG: QtMoleculeList got nameChanged for id " << molid);
  QtMoleculeItem *const molitem = MoleculeIdToItem(molid);
  // update items
  QtMoleculeItem *const nameitem = getSpecificMoleculeItem(molitem, QtMoleculeItem::NAME);
  ASSERT(nameitem != NULL,
      "QtMoleculeList::nameChanged() - could not item for NAME.");
  nameitem->updateState(_mol);
  nameIsChanged = false;
}