/* * 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 "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(QWidget * _parent) : QTreeWidget (_parent), 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(QTreeWidgetItem*, int)), this, SLOT(visibilityChanged(QTreeWidgetItem*, 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."); } void QtMoleculeList::recieveNotification(Observable *publisher, Notification_ptr notification) { if (selecting) return; dirty = true; } void QtMoleculeList::refill() { clearing = true; const std::vector &molecules = World::getInstance().getAllMolecules(); clear(); formula.clear(); FormulaVisibilityCountMap.clear(); for (std::vector::const_iterator iter = molecules.begin(); iter != molecules.end(); iter++) { // find group if already in list QTreeWidgetItem *groupItem = NULL; const std::string &molecule_formula = (*iter)->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 groupItem = new QTreeWidgetItem(this); formula.insert( std::make_pair(molecule_formula, groupItem) ); // fill item groupItem->setText(NAME, QString("default")); groupItem->setFlags((groupItem->flags() | Qt::ItemIsUserCheckable) ^ Qt::ItemIsSelectable); groupItem->setCheckState(VISIBILITY, Qt::Unchecked); groupItem->setText(ATOMCOUNT, QString::number(0)); groupItem->setText(FORMULA, QString("")); groupItem->setText(OCCURRENCE, "0"); groupItem->setData(0, Qt::UserRole, QVariant(-1)); } else { groupItem = formulaiter->second; } // add molecule QTreeWidgetItem *molItem = new QTreeWidgetItem(groupItem); molItem->setText(NAME, QString((*iter)->getName().c_str())); molItem->setFlags(molItem->flags() | Qt::ItemIsUserCheckable | Qt::ItemIsSelectable); molItem->setCheckState(VISIBILITY, Qt::Unchecked); molItem->setText(ATOMCOUNT, QString::number((*iter)->getAtomCount())); molItem->setText(FORMULA, QString(molecule_formula.c_str())); const int index = (*iter)->getId(); molItem->setData(0, Qt::UserRole, QVariant(index)); molItem->setSelected(World::getInstance().isSelected(*iter)); // increase group occurrence int count = groupItem->text(OCCURRENCE).toInt() + 1; groupItem->setText(OCCURRENCE, QString::number(count)); } dirty = false; clearing = false; } void QtMoleculeList::paintEvent(QPaintEvent * event) { if (dirty) refill(); QTreeWidget::paintEvent(event); } void QtMoleculeList::subjectKilled(Observable *publisher) { } void QtMoleculeList::visibilityChanged(QTreeWidgetItem* item, int column) { if ((!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 const molecule * const _molecule = World::getInstance().getMolecule(MoleculeById(molid)); 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(); foreach (index, items) if (index.column() == 0){ int mol_id = model()->data(index, Qt::UserRole).toInt(); if (mol_id < 0) continue; //std::cout << "select molecule" << std::endl; MoleCuilder::SelectionMoleculeById(mol_id); } // Unselect all molecules which belong to newly unselected rows. items = deselected.indexes(); 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; MoleCuilder::SelectionNotMoleculeById(mol_id); } selecting = false; }