/* * 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; } */