/*
* 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 "Views/Qt4/QtMoleculeList.hpp"
#include
#include
#include "CodePatterns/MemDebug.hpp"
#include "CodePatterns/Observer/Notification.hpp"
#include "Atom/atom.hpp"
#include "Formula.hpp"
#include "molecule.hpp"
#include "MoleculeListClass.hpp"
#include "Actions/SelectionAction/Molecules/MoleculeByIdAction.hpp"
#include "Actions/SelectionAction/Molecules/NotMoleculeByIdAction.hpp"
using namespace std;
// maybe this should go with the definition of molecules
// some attributes need to be easier to find for molecules
// these attributes are skipped so far
const int QtMoleculeList::COLUMNCOUNT = COLUMNTYPES_MAX;
const char *QtMoleculeList::COLUMNNAMES[QtMoleculeList::COLUMNCOUNT]={"Name","Visibility", "Atoms","Formula","Occurrence"/*,"Size"*/};
QtMoleculeList::QtMoleculeList() :
Observer("QtMoleculeList")
{
setColumnCount(COLUMNCOUNT);
// setSelectionMode(QAbstractItemView::MultiSelection);
// QStringList header;
// for(int i=0; i("QItemSelection");
//connect(this,SIGNAL(cellChanged(int,int)),this,SLOT(moleculeChanged(int,int)));
// connect(selectionModel(),SIGNAL(selectionChanged(QItemSelection, QItemSelection)),this,SLOT(rowsSelected(QItemSelection, QItemSelection)));
// connect(this, SIGNAL(itemChanged(QStandardItem*, int)), this, SLOT(visibilityChanged(QStandardItem*, int)));
}
QtMoleculeList::~QtMoleculeList()
{
World::getInstance().signOff(this, World::MoleculeInserted);
World::getInstance().signOff(this, World::MoleculeRemoved);
}
void QtMoleculeList::update(Observable *publisher) {
ASSERT(0,
"QtMoleculeList::update() - we did not sign up for any global updates.");
}
QStandardItem * QtMoleculeList::MoleculeToItem(const molecule * const _mol)
{
MoleculeItemBiMap_t::left_const_iterator iter =
MoleculeItemBiMap.left.find(_mol);
ASSERT( iter != MoleculeItemBiMap.left.end(),
"QtMoleculeList - could not find molecule "+_mol->getName()+" in my list.");
return iter->second;
}
void QtMoleculeList::recieveNotification(Observable *publisher, Notification_ptr notification)
{
if (dynamic_cast(publisher) != NULL) {
switch (notification->getChannelNo()) {
case World::MoleculeInserted:
{
const molecule * const mol = World::getInstance().lastChanged();
addItem( mol );
break;
}
case World::MoleculeRemoved:
{
const molecule * const mol = World::getInstance().lastChanged();
removeItem( mol );
break;
}
default:
ASSERT(0, "QtMoleculeList::recieveNotification() - cannot get here, not subscribed to channel "
+toString(notification->getChannelNo()));
break;
}
}
if (selecting)
return;
dirty = true;
}
void QtMoleculeList::addGroupItem(
QStandardItem *&mainitem,
const std::string &_molecule_formula)
{
QList groupItems;
// fill item list
mainitem = new QStandardItem(QString("default"));
mainitem->setFlags(mainitem->flags() ^ Qt::ItemIsSelectable);
formula.insert( std::make_pair(_molecule_formula, mainitem) );
groupItems << mainitem;
QStandardItem *visitem = new QStandardItem;
visitem->setCheckState(Qt::Unchecked);
visitem->setFlags(mainitem->flags() | Qt::ItemIsUserCheckable);
groupItems << visitem;
groupItems << new QStandardItem(QString::number(0));
groupItems << new QStandardItem(QString(""));
groupItems << new QStandardItem(QString::number(0));
invisibleRootItem()->appendRow(groupItems);
// _groupItem->setData(0, Qt::UserRole, QVariant(-1));
}
void QtMoleculeList::addMoleculeItem(
QStandardItem *_groupitem,
const molecule *_mol,
const std::string &_molecule_formula)
{
QList molItems;
QStandardItem *mainitem = new QStandardItem(QString(_mol->getName().c_str()));
mainitem->setFlags(mainitem->flags() | Qt::ItemIsSelectable);
// mainitem->setSelected(World::getInstance().isSelected(_mol));
MoleculeItemBiMap.left.insert( std::make_pair(_mol, mainitem) );
molItems << mainitem;
QStandardItem *visitem = new QStandardItem();
visitem->setCheckState(Qt::Unchecked);
visitem->setFlags(mainitem->flags() | Qt::ItemIsUserCheckable);
molItems << visitem;
molItems << new QStandardItem(QString::number(_mol->getAtomCount()));
molItems << new QStandardItem(QString(_molecule_formula.c_str()));
molItems << new QStandardItem(QString::number(0));
// const int index = _mol->getId();
// molItem->setData(0, Qt::UserRole, QVariant(index));
_groupitem->appendRow(molItems);
}
void QtMoleculeList::addItem(const molecule *_mol)
{
if (changing)
return;
changing = true;
// find group if already in list
QStandardItem *groupItem = NULL;
const std::string &molecule_formula = _mol->getFormula().toString();
FormulaTreeItemMap_t::const_iterator formulaiter =
formula.find(molecule_formula);
// new molecule type -> create new group
if (formulaiter == formula.end()){
// 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 = formulaiter->second;
}
ASSERT( groupItem != NULL,
"QtMoleculeList::addItem() - item with id "+toString(_mol->getId())
+" has not parent?");
// add molecule
addMoleculeItem(groupItem, _mol, molecule_formula);
// increase group occurrence
const int index = groupItem->index().row();
QStandardItem *occ_item = invisibleRootItem()->child(index, OCCURRENCE);
int count = occ_item->text().toInt() + 1;
occ_item->setText(QString::number(count));
changing = false;
}
void QtMoleculeList::removeItem(const molecule *_mol)
{
if (changing)
return;
changing = true;
dirty = true;
// TODO: We have to get some Model into the Table in order to "find" items right
// away
// QTreeWidgetItem *molItem = itemFromIndex(mol->getId());
// delete molItem1;
changing = false;
}
void QtMoleculeList::refill() {
clearing = true;
const std::vector &molecules = World::getInstance().getAllMolecules();
clear();
formula.clear();
FormulaVisibilityCountMap.clear();
MoleculeItemBiMap.clear();
for (std::vector::const_iterator iter = molecules.begin();
iter != molecules.end();
iter++) {
addItem(*iter);
}
dirty = false;
clearing = false;
}
/*
void QtMoleculeList::paintEvent(QPaintEvent * event)
{
if (dirty)
refill();
QTreeWidget::paintEvent(event);
}
*/
void QtMoleculeList::subjectKilled(Observable *publisher) {
}
/*
void QtMoleculeList::visibilityChanged(QStandardItem* item, int column)
{
if ((!changing) && (!clearing) && (!ChangingChildrensVisibility))
if (column == VISIBILITY) {
const moleculeId_t molid = item->data(0, Qt::UserRole).toInt();
const bool visible = item->checkState(VISIBILITY);
if (molid != (unsigned int)-1) { // molecule item
World::MoleculeConstIterator moliter =
const_cast(World::getInstance()).getMoleculeIter(MoleculeById(molid));
const molecule * const _molecule = *moliter;
ASSERT( _molecule != NULL,
"QtMoleculeList::visibilityChanged() - molecule with id "
+toString(molid)+" is not known to World.");
const std::string &molecule_formula = _molecule->getFormula().toString();
ASSERT( FormulaVisibilityCountMap.count(molecule_formula) != 0,
"QtMoleculeList::visibilityChanged() - molecule with formula " +molecule_formula
+" is not present in FormulaVisibilityCountMap.");
// get parent
QTreeWidgetItem *groupItem = item->parent();
ASSERT( groupItem != NULL,
"QtMoleculeList::visibilityChanged() - item with id "+toString(molid)
+" has not parent?");
// check whether we have to set the group item
ChangingChildrensVisibility = true;
if (visible) {
++(FormulaVisibilityCountMap[molecule_formula]);
// compare with occurence/total number of molecules
if (FormulaVisibilityCountMap[molecule_formula] ==
(unsigned int)(groupItem->text(OCCURRENCE).toInt()))
groupItem->setCheckState(VISIBILITY, Qt::Checked);
} else {
--(FormulaVisibilityCountMap[molecule_formula]);
// none selected anymore?
if (FormulaVisibilityCountMap[molecule_formula] == 0)
groupItem->setCheckState(VISIBILITY, Qt::Unchecked);
}
ChangingChildrensVisibility = false;
emit moleculesVisibilityChanged(molid, visible);
} else { // group item
// go through all children, but don't enter for groupItem once more
ChangingChildrensVisibility = true;
for (int i=0;ichildCount();++i) {
QTreeWidgetItem *molItem = item->child(i);
const moleculeId_t molid = molItem->data(0, Qt::UserRole).toInt();
ASSERT( molid != (unsigned int)-1,
"QtMoleculeList::visibilityChanged() - to child with index"
+toString(i)+" there is no molecule?");
molItem->setCheckState(VISIBILITY, visible ? Qt::Checked : Qt::Unchecked);
// emit signal
emit moleculesVisibilityChanged(molid, visible);
}
// set current number of visible children
const std::string molecule_formula =
item->text(FORMULA).toStdString();
FormulaVisibilityCountMap[molecule_formula] =
visible ? item->text(OCCURRENCE).toInt() : 0;
ChangingChildrensVisibility = false;
}
}
}
*/
void QtMoleculeList::moleculeChanged() {
/*int idx = verticalHeaderItem(row)->data(Qt::UserRole).toInt();
molecule *mol = molecules->ReturnIndex(idx);
string cellValue = item(row,NAME)->text().toStdString();
if(mol->getName() != cellValue && cellValue !="") {
mol->setName(cellValue);
}
else if(cellValue==""){
item(row,NAME)->setText(QString(mol->getName().c_str()));
}*/
}
/*
void QtMoleculeList::rowsSelected(const QItemSelection & selected, const QItemSelection & deselected){
if (clearing)
return;
if (selecting)
return;
selecting = true;
// Select all molecules which belong to newly selected rows.
QModelIndex index;
{
QModelIndexList items = selected.indexes();
molids_t ids;
ids.reserve(items.size());
foreach (index, items)
if (index.column() == 0){
int mol_id = model()->data(index, Qt::UserRole).toInt();
if (mol_id < 0)
continue;
ids.push_back(mol_id);
//std::cout << "select molecule" << std::endl;
}
MoleCuilder::SelectionMoleculeById(ids);
}
// Unselect all molecules which belong to newly unselected rows.
{
QModelIndexList items = deselected.indexes();
molids_t ids;
ids.reserve(items.size());
foreach (index, items)
if (index.column() == 0){
int mol_id = model()->data(index, Qt::UserRole).toInt();
if (mol_id < 0)
continue;
//std::cout << "unselect molecule" << std::endl;
ids.push_back(mol_id);
}
MoleCuilder::SelectionNotMoleculeById(ids);
}
selecting = false;
}
*/