source: src/UIElements/Views/Qt4/MoleculeList/QtMoleculeList.cpp@ 574d377

Action_Thermostats Add_AtomRandomPerturbation Add_FitFragmentPartialChargesAction Add_RotateAroundBondAction Add_SelectAtomByNameAction Added_ParseSaveFragmentResults AddingActions_SaveParseParticleParameters Adding_Graph_to_ChangeBondActions Adding_MD_integration_tests Adding_ParticleName_to_Atom Adding_StructOpt_integration_tests AtomFragments Automaking_mpqc_open AutomationFragmentation_failures Candidate_v1.5.4 Candidate_v1.6.0 Candidate_v1.6.1 ChangeBugEmailaddress ChangingTestPorts ChemicalSpaceEvaluator CombiningParticlePotentialParsing Combining_Subpackages Debian_Package_split Debian_package_split_molecuildergui_only Disabling_MemDebug Docu_Python_wait EmpiricalPotential_contain_HomologyGraph EmpiricalPotential_contain_HomologyGraph_documentation Enable_parallel_make_install Enhance_userguide Enhanced_StructuralOptimization Enhanced_StructuralOptimization_continued Example_ManyWaysToTranslateAtom Exclude_Hydrogens_annealWithBondGraph FitPartialCharges_GlobalError Fix_BoundInBox_CenterInBox_MoleculeActions Fix_ChargeSampling_PBC Fix_ChronosMutex Fix_FitPartialCharges Fix_FitPotential_needs_atomicnumbers Fix_ForceAnnealing Fix_IndependentFragmentGrids Fix_ParseParticles Fix_ParseParticles_split_forward_backward_Actions Fix_PopActions Fix_QtFragmentList_sorted_selection Fix_Restrictedkeyset_FragmentMolecule Fix_StatusMsg Fix_StepWorldTime_single_argument Fix_Verbose_Codepatterns Fix_fitting_potentials Fixes ForceAnnealing_goodresults ForceAnnealing_oldresults ForceAnnealing_tocheck ForceAnnealing_with_BondGraph ForceAnnealing_with_BondGraph_continued ForceAnnealing_with_BondGraph_continued_betteresults ForceAnnealing_with_BondGraph_contraction-expansion FragmentAction_writes_AtomFragments FragmentMolecule_checks_bonddegrees GeometryObjects Gui_Fixes Gui_displays_atomic_force_velocity ImplicitCharges IndependentFragmentGrids IndependentFragmentGrids_IndividualZeroInstances IndependentFragmentGrids_IntegrationTest IndependentFragmentGrids_Sole_NN_Calculation JobMarket_RobustOnKillsSegFaults JobMarket_StableWorkerPool JobMarket_unresolvable_hostname_fix MoreRobust_FragmentAutomation ODR_violation_mpqc_open PartialCharges_OrthogonalSummation PdbParser_setsAtomName PythonUI_with_named_parameters QtGui_reactivate_TimeChanged_changes Recreated_GuiChecks Rewrite_FitPartialCharges RotateToPrincipalAxisSystem_UndoRedo SaturateAtoms_findBestMatching SaturateAtoms_singleDegree StoppableMakroAction Subpackage_CodePatterns Subpackage_JobMarket Subpackage_LinearAlgebra Subpackage_levmar Subpackage_mpqc_open Subpackage_vmg Switchable_LogView ThirdParty_MPQC_rebuilt_buildsystem TrajectoryDependenant_MaxOrder TremoloParser_IncreasedPrecision TremoloParser_MultipleTimesteps TremoloParser_setsAtomName Ubuntu_1604_changes stable
Last change on this file since 574d377 was 7d0ddb, checked in by Frederik Heber <heber@…>, 10 years ago

FIX: QtMoleculeItem would not correctly signOff prior to molecule being destroyed.

  • Property mode set to 100644
File size: 23.4 KB
RevLine 
[bcf653]1/*
2 * Project: MoleCuilder
3 * Description: creates and alters molecular systems
[0aa122]4 * Copyright (C) 2010-2012 University of Bonn. All rights reserved.
[94d5ac6]5 *
6 *
7 * This file is part of MoleCuilder.
8 *
9 * MoleCuilder is free software: you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation, either version 2 of the License, or
12 * (at your option) any later version.
13 *
14 * MoleCuilder is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with MoleCuilder. If not, see <http://www.gnu.org/licenses/>.
[bcf653]21 */
22
[b47bfc]23/*
[0eb7bf3]24 * QtMoleculeList.cpp
[b47bfc]25 *
26 * Created on: Jan 21, 2010
27 * Author: crueger
28 */
29
[bf3817]30// include config.h
31#ifdef HAVE_CONFIG_H
32#include <config.h>
33#endif
[bbbad5]34
[f62e60]35#include "QtMoleculeList.hpp"
[b47bfc]36
[53c1ff]37#include <QModelIndex>
[2696b1]38#include <QDebug>
[41815a3]39
[53c1ff]40#include "UIElements/Views/Qt4/MoleculeList/QtMoleculeItem.hpp"
41#include "UIElements/Views/Qt4/MoleculeList/QtMoleculeItemFactory.hpp"
42
43#include <boost/bind.hpp>
[b47bfc]44#include <iostream>
45
[ad011c]46#include "CodePatterns/MemDebug.hpp"
[bbbad5]47
[53c1ff]48#include "CodePatterns/Log.hpp"
[6770fa]49#include "CodePatterns/Observer/Notification.hpp"
50
[6f0841]51#include "Atom/atom.hpp"
[d2dbb5d]52#include "Descriptors/MoleculeIdDescriptor.hpp"
[26cf17]53#include "Formula.hpp"
[b47bfc]54#include "molecule.hpp"
[42127c]55#include "MoleculeListClass.hpp"
[b47bfc]56
57using namespace std;
58
[53c1ff]59const unsigned int QtMoleculeList::update_times_per_second = 20;
[b47bfc]60
[8ccf3b]61QtMoleculeList::QtMoleculeList() :
[53c1ff]62 Observer("QtMoleculeList"),
63 ChangingChildrensVisibility(false),
64 update_timer(NULL),
65 callback_DirtyItems(boost::bind(&QtMoleculeList::informDirtyState, this, _1, _2))
[b47bfc]66{
[53c1ff]67 setColumnCount(QtMoleculeItemFactory::COLUMNCOUNT);
[b47bfc]68
[3eb91c]69 World::getInstance().signOn(this, World::MoleculeInserted);
70 World::getInstance().signOn(this, World::MoleculeRemoved);
[41815a3]71
[a39006]72 refill();
[b47bfc]73
[8ccf3b]74// qRegisterMetaType<QItemSelection>("QItemSelection");
[79b59b]75 //connect(this,SIGNAL(cellChanged(int,int)),this,SLOT(moleculeChanged(int,int)));
[8ccf3b]76// connect(selectionModel(),SIGNAL(selectionChanged(QItemSelection, QItemSelection)),this,SLOT(rowsSelected(QItemSelection, QItemSelection)));
[2696b1]77 connect(this, SIGNAL(itemChanged(QStandardItem*)), this, SLOT(checkForVisibilityChange(QStandardItem*)));
[b47bfc]78}
79
[0eb7bf3]80QtMoleculeList::~QtMoleculeList()
[b47bfc]81{
[3eb91c]82 World::getInstance().signOff(this, World::MoleculeInserted);
83 World::getInstance().signOff(this, World::MoleculeRemoved);
[b47bfc]84}
85
[1c3390]86QVariant QtMoleculeList::headerData(int section, Qt::Orientation orientation, int role) const
87{
88 if (role == Qt::DisplayRole) {
89 if (orientation == Qt::Horizontal) {
[53c1ff]90 if (section < QtMoleculeItemFactory::COLUMNTYPES_MAX)
91 return QString(QtMoleculeItemFactory::COLUMNNAMES[section]);
[1c3390]92 }
93 }
94 return QVariant();
95}
96
[0eb7bf3]97void QtMoleculeList::update(Observable *publisher) {
[3eb91c]98 ASSERT(0,
99 "QtMoleculeList::update() - we did not sign up for any global updates.");
100}
101
[69b434]102QtMoleculeItem * QtMoleculeList::MoleculeIdToItem(const moleculeId_t _molid) const
[8ccf3b]103{
104 MoleculeItemBiMap_t::left_const_iterator iter =
[69b434]105 MoleculeItemBiMap.left.find(_molid);
[d2dbb5d]106 if( iter != MoleculeItemBiMap.left.end())
107 return iter->second;
108 else
109 return NULL;
[8ccf3b]110}
111
[69b434]112const moleculeId_t QtMoleculeList::ItemToMoleculeId(const QtMoleculeItem * const _item) const
[53c1ff]113{
114 const MoleculeItemBiMap_t::right_const_iterator iter =
115 MoleculeItemBiMap.right.find(const_cast<QtMoleculeItem * const>(_item));
[d2dbb5d]116 if (iter != MoleculeItemBiMap.right.end())
117 return iter->second;
118 else
[69b434]119 return -1;
[53c1ff]120}
121
[69b434]122const moleculeId_t QtMoleculeList::IndexToMoleculeId(const QModelIndex &_index) const
[53c1ff]123{
124 QtMoleculeItem * const item = dynamic_cast<QtMoleculeItem *>(itemFromIndex(_index));
125 if (item == NULL)
[69b434]126 return -1;
[53c1ff]127 else
[69b434]128 return ItemToMoleculeId(item);
[53c1ff]129}
130
[6770fa]131void QtMoleculeList::recieveNotification(Observable *publisher, Notification_ptr notification)
132{
133 if (dynamic_cast<World *>(publisher) != NULL) {
134 switch (notification->getChannelNo()) {
135 case World::MoleculeInserted:
136 {
137 const molecule * const mol = World::getInstance().lastChanged<molecule>();
[7d0ddb]138 listAccessing_mutex.lock();
[53c1ff]139 newItems.push_back( mol );
[7d0ddb]140 listAccessing_mutex.unlock();
[6770fa]141 break;
142 }
143 case World::MoleculeRemoved:
144 {
145 const molecule * const mol = World::getInstance().lastChanged<molecule>();
[53c1ff]146
[7d0ddb]147 listAccessing_mutex.lock();
[53c1ff]148 toBeRemovedItems.push_back( mol ); // remove in any case, as we also got insert
[7d0ddb]149 listAccessing_mutex.unlock();
[53c1ff]150
[69b434]151 const QtMoleculeItem *mol_item = MoleculeIdToItem(mol->getId());
[53c1ff]152 if (mol_item != NULL) {
153 QStandardItem *parent_item = mol_item->parent();
154 if (parent_item != NULL)
155 addToBeSetOccurrence( parent_item );
156 else
157 ELOG(2, "QtMoleculeList::recieveNotification() - item to molecule "
158 +toString(mol)+" has no parent.");
159 }
[6770fa]160 break;
161 }
162 default:
163 ASSERT(0, "QtMoleculeList::recieveNotification() - cannot get here, not subscribed to channel "
164 +toString(notification->getChannelNo()));
165 break;
166 }
167 }
[a39006]168}
169
[6770fa]170void QtMoleculeList::addGroupItem(
[8ccf3b]171 QStandardItem *&mainitem,
[6770fa]172 const std::string &_molecule_formula)
173{
[53c1ff]174 QList<QStandardItem *> groupItems =
175 QtMoleculeItemFactory::getInstance().createGroupItems(_molecule_formula);
176 mainitem = groupItems.front();
[8ccf3b]177 formula.insert( std::make_pair(_molecule_formula, mainitem) );
178 invisibleRootItem()->appendRow(groupItems);
[53c1ff]179}
180
181void QtMoleculeList::addToBeSetOccurrence(
182 QStandardItem *_groupitem)
183{
[7d0ddb]184 listAccessing_mutex.lock();
[53c1ff]185 toBeSetOccurrenceItems.insert( _groupitem );
[7d0ddb]186 listAccessing_mutex.unlock();
[6770fa]187}
188
189void QtMoleculeList::addMoleculeItem(
[8ccf3b]190 QStandardItem *_groupitem,
[69b434]191 const moleculeId_t _molid,
[6770fa]192 const std::string &_molecule_formula)
193{
[53c1ff]194 QList<QStandardItem *> molItems =
[69b434]195 QtMoleculeItemFactory::getInstance().createMoleculeItems(_molid, callback_DirtyItems);
[53c1ff]196 QtMoleculeItem *mol_item = dynamic_cast<QtMoleculeItem *>(molItems.front());
197 ASSERT( mol_item != NULL,
198 "QtMoleculeList::addMoleculeItem() - item from factory was not a QtMoleculeItem?");
[69b434]199 MoleculeItemBiMap.left.insert( std::make_pair(_molid, mol_item) );
[2050b2]200// LOG(1, "Inserting molecule " << _mol->getId() << ": " << _mol);
[8ccf3b]201 _groupitem->appendRow(molItems);
[53c1ff]202
203 // here update for the occurence will happen "one tick" later, but we don't
204 // have the groupitem any time earlier
205 addToBeSetOccurrence(_groupitem);
[6770fa]206}
207
[53c1ff]208void QtMoleculeList::addMolecule(const molecule * const _mol)
[6770fa]209{
210 // find group if already in list
[8ccf3b]211 QStandardItem *groupItem = NULL;
[6770fa]212
213 const std::string &molecule_formula = _mol->getFormula().toString();
214 FormulaTreeItemMap_t::const_iterator formulaiter =
215 formula.find(molecule_formula);
216
217 // new molecule type -> create new group
218 if (formulaiter == formula.end()){
219 // insert new formula entry into visibility
220#ifndef NDEBUG
221 std::pair< FormulaVisibilityCountMap_t::iterator, bool> visibilityinserter =
222#endif
223 FormulaVisibilityCountMap.insert(
224 std::make_pair( molecule_formula, (unsigned int)0) );
225 ASSERT( visibilityinserter.second,
226 "QtMoleculeList::refill() - molecule with formula "
227 +molecule_formula+" already in FormulaVisibilityCountMap.");
228
229 // create item and place into Map with formula as key
230 addGroupItem(groupItem, molecule_formula);
231 } else {
232 groupItem = formulaiter->second;
233 }
234 ASSERT( groupItem != NULL,
[53c1ff]235 "QtMoleculeList::addMolecule() - item with id "+toString(_mol->getId())
[6770fa]236 +" has not parent?");
237
238 // add molecule
[69b434]239 addMoleculeItem(groupItem, _mol->getId(), molecule_formula);
[6770fa]240}
241
[53c1ff]242void QtMoleculeList::removeItem(QtMoleculeItem * const _item)
[6770fa]243{
[53c1ff]244 const QModelIndex mol_index = indexFromItem(_item);
245 QStandardItem *groupitem = _item->parent();
246 const QModelIndex group_index = groupitem->index();
247 removeRows(mol_index.row(), 1, group_index);
248 MoleculeItemBiMap_t::right_iterator removeiter =
249 MoleculeItemBiMap.right.find(_item);
250 ASSERT( removeiter != MoleculeItemBiMap.right.end(),
251 "QtMoleculeList::removeItem() - could not find item in BiMap.");
252 LOG(1, "Erasing molecule " << (removeiter->second));
253 MoleculeItemBiMap.right.erase(removeiter);
254
255 // don't need to, groupitem is already present in toBeSetOccurrenceItems
256// addToBeSetOccurrence(_groupitem);
257}
[6770fa]258
[53c1ff]259void QtMoleculeList::refill()
260{
261 // check timer's presence
262 if (update_timer == NULL) {
263 update_timer = new QTimer(this);
264 connect( update_timer, SIGNAL(timeout()), this, SLOT(checkState()));
265 } else
266 update_timer->stop();
[6770fa]267
[7d0ddb]268 refill_mutex.lock();
[3eb91c]269
[1259df]270 const std::vector<const molecule*> &molecules =
271 const_cast<const World &>(World::getInstance()).getAllMolecules();
[41815a3]272
[79b59b]273 clear();
[3eb91c]274 formula.clear();
275 FormulaVisibilityCountMap.clear();
[2050b2]276// LOG(1, "Clearing list.");
[8ccf3b]277 MoleculeItemBiMap.clear();
[53c1ff]278 dirtyItems.clear();
[2696b1]279 visibilityItems.clear();
[53c1ff]280 toBeMovedItems.clear();
281 newItems.clear();
282 toBeRemovedItems.clear();
283 toBeSetOccurrenceItems.clear();
[2696b1]284 toBeSetVisibilityItems.clear();
[79b59b]285
[1259df]286 for (std::vector<const molecule*>::const_iterator iter = molecules.begin();
[41815a3]287 iter != molecules.end();
[53c1ff]288 iter++)
289 addMolecule(*iter);
[b47bfc]290
[7d0ddb]291 refill_mutex.unlock();
[53c1ff]292
293 // activate timer
294 update_timer->start(1000/update_times_per_second);
[a39006]295}
296
[53c1ff]297bool QtMoleculeList::areAnyItemsDirty()
[a39006]298{
[53c1ff]299 // get whether any items are dirty
[7d0ddb]300 listAccessing_mutex.lock();
[53c1ff]301 bool dirty = false;
302 dirty |= !dirtyItems.empty();
[2696b1]303 dirty |= !visibilityItems.empty();
[53c1ff]304 dirty |= !newItems.empty();
305 dirty |= !toBeRemovedItems.empty();
306 dirty |= !toBeSetOccurrenceItems.empty();
[2696b1]307 dirty |= !toBeSetVisibilityItems.empty();
[7d0ddb]308 listAccessing_mutex.unlock();
[53c1ff]309 return dirty;
[b47bfc]310}
311
[53c1ff]312void QtMoleculeList::checkState()
313{
314 const bool dirty = areAnyItemsDirty();
315 // update if required
316 if (dirty)
317 updateItemStates();
[b47bfc]318}
319
[53c1ff]320void QtMoleculeList::subjectKilled(Observable *publisher)
321{}
322
[2696b1]323void QtMoleculeList::checkForVisibilityChange(QStandardItem* _item)
[739ee9]324{
[2050b2]325// qDebug() << "Item changed called.";
[2696b1]326
327 if (_item->index().column() == QtMoleculeItemFactory::VISIBILITY) {
[2050b2]328// qDebug() << "visibilityItem changed: " << (_item->checkState() ? "checked" : "unchecked");
[7d0ddb]329 listAccessing_mutex.lock();
[2696b1]330 if ((_item->parent() == NULL) || (_item->parent() == invisibleRootItem()))
331 toBeSetVisibilityItems.insert( _item );
332 else
333 visibilityItems.insert( dynamic_cast<QtMoleculeItem *>(_item) );
[7d0ddb]334 listAccessing_mutex.unlock();
[2696b1]335 }
336}
[3eb91c]337
[2696b1]338void QtMoleculeList::setVisibilityForMoleculeItem(QtMoleculeItem* _item)
339{
340 if (ChangingChildrensVisibility)
341 return;
[3eb91c]342
[2696b1]343 const bool visible = _item->checkState();
[7d0ddb]344 const molecule * const mol = _item->getMolecule();
345 std::string molecule_formula;
346 if (mol != NULL) {
347 molecule_formula = mol->getFormula().toString();
348 ASSERT( FormulaVisibilityCountMap.count(molecule_formula) != 0,
349 "QtMoleculeList::setVisibilityForMoleculeItem() - molecule with formula " +molecule_formula
350 +" is not present in FormulaVisibilityCountMap.");
351 }
[3eb91c]352
[2696b1]353 // get parent
354 QStandardItem *groupItem = _item->parent();
355 QStandardItem *visgroupItem =
356 invisibleRootItem()->child(groupItem->index().row(), QtMoleculeItemFactory::VISIBILITY);
357 ASSERT( groupItem != NULL,
358 "QtMoleculeList::setVisibilityForMoleculeItem() - item with id "
[7d0ddb]359 +toString(_item->getMoleculeId())+" has not parent?");
[2696b1]360 // check whether we have to set the group item
361
362 ChangingChildrensVisibility = true;
363 if (visible) {
364 ++(FormulaVisibilityCountMap[molecule_formula]);
365 // compare with occurence/total number of molecules
366 if (FormulaVisibilityCountMap[molecule_formula] ==
367 (unsigned int)(groupItem->rowCount()))
368 visgroupItem->setCheckState(Qt::Checked);
369 } else {
370 --(FormulaVisibilityCountMap[molecule_formula]);
371 // none selected anymore?
372 if (FormulaVisibilityCountMap[molecule_formula] == 0)
373 visgroupItem->setCheckState(Qt::Unchecked);
374 }
375 ChangingChildrensVisibility = false;
[3eb91c]376
[2696b1]377 emit moleculesVisibilityChanged(_item->getMolecule()->getId(), visible);
378}
[3eb91c]379
[2696b1]380void QtMoleculeList::setVisibilityForGroupItem(QStandardItem* _item)
381{
382 if (ChangingChildrensVisibility)
383 return;
384
385 ChangingChildrensVisibility = true;
386
387 // go through all children, but don't enter for groupItem once more
388 const bool visible = _item->checkState();
389 QStandardItem *groupitem = invisibleRootItem()->child(
390 _item->index().row(), QtMoleculeItemFactory::NAME);
391 for (int i=0;i<groupitem->rowCount();++i) {
392 QtMoleculeItem *molItem = dynamic_cast<QtMoleculeItem *>(
393 groupitem->child(i, QtMoleculeItemFactory::VISIBILITY));
394 if (molItem->checkState() != visible) {
395 molItem->setCheckState(visible ? Qt::Checked : Qt::Unchecked);
396
397 // emit signal
398 emit moleculesVisibilityChanged(molItem->getMolecule()->getId(), visible);
[3eb91c]399 }
[2696b1]400 }
401 // set current number of visible children
402 const std::string molecule_formula =
403 invisibleRootItem()->child(_item->row(), QtMoleculeItemFactory::NAME)->text().toStdString();
404 FormulaVisibilityCountMap_t::iterator countiter =
405 FormulaVisibilityCountMap.find(molecule_formula);
406 ASSERT( countiter != FormulaVisibilityCountMap.end(),
407 "QtMoleculeList::setVisibilityForGroupItem() - molecules "+molecule_formula
408 +" have no entry in visibility count map?");
409 countiter->second = visible ? groupitem->rowCount() : 0;
410
411 ChangingChildrensVisibility = false;
[739ee9]412}
[2696b1]413
[739ee9]414
[0eb7bf3]415void QtMoleculeList::moleculeChanged() {
[79b59b]416 /*int idx = verticalHeaderItem(row)->data(Qt::UserRole).toInt();
[b47bfc]417 molecule *mol = molecules->ReturnIndex(idx);
[53c1ff]418 string cellValue = item(row,QtMoleculeItemFactory::NAME)->text().toStdString();
[b47bfc]419 if(mol->getName() != cellValue && cellValue !="") {
420 mol->setName(cellValue);
421 }
422 else if(cellValue==""){
[53c1ff]423 item(row,QtMoleculeItemFactory::NAME)->setText(QString(mol->getName().c_str()));
[79b59b]424 }*/
[b47bfc]425}
426
[b14efe]427
[53c1ff]428int QtMoleculeList::setOccurrence(QStandardItem * const _groupitem)
429{
430 QModelIndex modelindex = _groupitem->index();
431 ASSERT( modelindex.isValid(),
432 "QtMoleculeList::setOccurrence() - groupitem not associated to model anymore.");
433 const int index = modelindex.row();
434 QStandardItem *parent_item =
435 _groupitem->parent() == NULL ? invisibleRootItem() : _groupitem->parent();
436 ASSERT( parent_item != NULL,
437 "QtMoleculeList::setOccurrence() - group item at "+toString(index)
438 +" does not have a parent?");
439 QStandardItem *occ_item = parent_item->child(index, QtMoleculeItemFactory::OCCURRENCE);
440 ASSERT( occ_item != NULL,
441 "QtMoleculeList::setOccurrence() - group item at "+toString(index)
442 +" does not have an occurrence?");
443 const int count = _groupitem->rowCount();
444 if (count == 0) {
445 // we have to remove the group item completely
446 const std::string molecule_formula = _groupitem->text().toStdString();
447 formula.erase(molecule_formula);
448 FormulaVisibilityCountMap.erase(molecule_formula);
449 return index;
450 } else {
451 occ_item->setText(QString::number(count));
452 return -1;
453 }
454}
455
456void QtMoleculeList::readdItem(QtMoleculeItem *_molitem)
457{
458 // use takeRows of molecule ..
459 QStandardItem *groupitem = _molitem->parent();
460 ASSERT( groupitem != NULL,
461 "QtMoleculeList::readdItem() - mol item at "+toString(_molitem->index().row())
462 +" does not have a groupitem?");
463 QList<QStandardItem *> mol_row = _molitem->parent()->takeRow(_molitem->index().row());
[503a7fd]464 // call setOccurrence on the old group later, if it's not a removal candidate
465 if (groupitem->rowCount() != 0)
466 addToBeSetOccurrence(groupitem);
[53c1ff]467 // .. and re-add where new formula fits
[7d0ddb]468 const molecule * const mol = _molitem->getMolecule();
469 std::string molecule_formula;
470 if (mol != NULL) {
471 molecule_formula = mol->getFormula().toString();
472 FormulaTreeItemMap_t::iterator iter = formula.find(molecule_formula);
473 if (iter == formula.end()) {
474 // add new group item and formula entry
475 addGroupItem(groupitem, molecule_formula);
476 } else {
477 groupitem = iter->second;
478 }
479 ASSERT( groupitem != NULL,
480 "QtMoleculeList::readdItem() - failed to create a sensible new groupitem");
481 // finally add again
482 groupitem->appendRow(mol_row);
[53c1ff]483 }
484 // call setOccurrence on the new group later
485 addToBeSetOccurrence(groupitem);
486}
487
488void QtMoleculeList::informDirtyState(
489 QtMoleculeItem *_item,
490 const QtMoleculeItem::MoveTypes _type)
491{
[7d0ddb]492 refill_mutex.lock();
[53c1ff]493
[7d0ddb]494 listAccessing_mutex.lock();
[53c1ff]495 dirtyItems.insert(_item);
[7d0ddb]496 listAccessing_mutex.unlock();
[53c1ff]497 if (_type == QtMoleculeItem::NeedsMove) {
498 // we have to convert whatever item raised the dirty signal to the first
499 // item in the row as otherwise multiple items in the row are selected
500 // as to be moved, i.e. the same row is moved multiple times
501 QStandardItem *group_item = _item->parent();
502 QtMoleculeItem *mol_item =
503 dynamic_cast<QtMoleculeItem *>(group_item->child(_item->row(), 0));
[7d0ddb]504 listAccessing_mutex.lock();
[53c1ff]505 toBeMovedItems.insert(mol_item);
[7d0ddb]506 listAccessing_mutex.unlock();
[53c1ff]507// // add group item, too
508// toBeSetOccurrenceItems.insert(group_item);
509 }
510
[7d0ddb]511 refill_mutex.unlock();
[53c1ff]512}
513
514void QtMoleculeList::updateItemStates()
515{
516 // wait till initial refill has been executed
[7d0ddb]517 refill_mutex.lock();
[53c1ff]518
519 /// copy lists such that new signals for dirty/.. may come in right away
520 // TODO: if we had move semantics ...
[7d0ddb]521 listAccessing_mutex.lock();
[53c1ff]522 list_of_items_t dirtyItems_copy = dirtyItems;
523 dirtyItems.clear();
[2696b1]524 list_of_items_t visibilityItems_copy = visibilityItems;
525 visibilityItems.clear();
[53c1ff]526 list_of_items_t toBeMovedItems_copy = toBeMovedItems;
527 toBeMovedItems.clear();
528 std::vector<const molecule *> newItems_copy = newItems;
529 newItems.clear();
530 std::vector<const molecule *> toBeRemovedItems_copy = toBeRemovedItems;
531 toBeRemovedItems.clear();
532 std::set<QStandardItem*> toBeSetOccurrenceItems_copy = toBeSetOccurrenceItems;
533 toBeSetOccurrenceItems.clear();
[2696b1]534 std::set<QStandardItem*> toBeSetVisibilityItems_copy = toBeSetVisibilityItems;
535 toBeSetVisibilityItems.clear();
[7d0ddb]536 listAccessing_mutex.unlock();
[53c1ff]537
538 /// first check consistency among the sets:
539 /// -# if we remove an item, we don't have to update it before anymore
540 /// -# if we remove an item, we don't have to move it before anymore
541 /// -# if we remove an item, we don't have to change its visibility
542 /// -# don't add molecule that are also removed
543
544 // // remove molecules added and removed immediately in both lists
545 std::vector<const molecule *> addedremoved;
546 std::sort(newItems_copy.begin(), newItems_copy.end());
547 std::sort(toBeRemovedItems_copy.begin(), toBeRemovedItems_copy.end());
548 std::set_intersection(
549 newItems_copy.begin(), newItems_copy.end(),
550 toBeRemovedItems_copy.begin(), toBeRemovedItems_copy.end(),
551 std::back_inserter(addedremoved));
[d7cad1]552 {
[53c1ff]553 std::vector<const molecule *>::iterator removeiter = std::set_difference(
554 newItems_copy.begin(), newItems_copy.end(),
555 addedremoved.begin(), addedremoved.end(),
556 newItems_copy.begin());
557 newItems_copy.erase(removeiter, newItems_copy.end());
[d7cad1]558 }
559 {
[53c1ff]560 std::vector<const molecule *>::iterator removeiter = std::set_difference(
561 toBeRemovedItems_copy.begin(), toBeRemovedItems_copy.end(),
562 addedremoved.begin(), addedremoved.end(),
563 toBeRemovedItems_copy.begin());
564 toBeRemovedItems_copy.erase(removeiter, toBeRemovedItems_copy.end());
[d7cad1]565 }
[53c1ff]566 addedremoved.clear();
[41815a3]567
[53c1ff]568 for (std::vector<const molecule *>::iterator removeiter = toBeRemovedItems_copy.begin();
569 removeiter != toBeRemovedItems_copy.end(); ++removeiter) {
[69b434]570 QtMoleculeItem *item = MoleculeIdToItem((*removeiter)->getId());
[53c1ff]571 dirtyItems_copy.erase(item);
572 toBeMovedItems_copy.erase(item);
573 }
[2696b1]574 for (list_of_items_t::iterator visiter = visibilityItems_copy.begin();
575 visiter != visibilityItems_copy.end(); ) {
576 QtMoleculeItem * const _item = dynamic_cast<QtMoleculeItem *>(
577 (*visiter)->parent()->child(
578 (*visiter)->index().row(),
579 QtMoleculeItemFactory::NAME));
[69b434]580 const moleculeId_t molid = ItemToMoleculeId(_item);
[63fb7a]581 const molecule *mol = const_cast<const World &>(World::getInstance()).
582 getMolecule(MoleculeById(molid));
[2696b1]583 if (std::binary_search(
584 toBeRemovedItems_copy.begin(), toBeRemovedItems_copy.end(),
585 mol))
586 visibilityItems_copy.erase(visiter++);
587 else
588 ++visiter;
589 }
[8ccf3b]590
[2696b1]591 /// 1a. do the update for each dirty item
[53c1ff]592 for (list_of_items_t::const_iterator dirtyiter = dirtyItems_copy.begin();
593 dirtyiter != dirtyItems_copy.end(); ++dirtyiter) {
594 LOG(1, "Updating item " << *dirtyiter);
595 (*dirtyiter)->updateState();
596 }
597
[2696b1]598 /// 1b. do the visibility update for each dirty item
599 for (list_of_items_t::const_iterator visiter = visibilityItems_copy.begin();
600 visiter != visibilityItems_copy.end(); ++visiter) {
[2050b2]601// LOG(1, "Updating visibility of item " << *visiter);
[2696b1]602 ASSERT(((*visiter)->parent() != NULL) && ((*visiter)->parent() != invisibleRootItem()),
603 "QtMoleculeList::updateItemStates() - a group item ended up in visibilityItems.");
604 setVisibilityForMoleculeItem(*visiter);
605 }
606
[53c1ff]607 /// 2. move all items that need to be moved
608 for (list_of_items_t::const_iterator moveiter = toBeMovedItems_copy.begin();
609 moveiter != toBeMovedItems_copy.end(); ++moveiter) {
[2050b2]610// LOG(1, "Moving item " << *moveiter);
[53c1ff]611 readdItem(*moveiter);
612 }
613
614 /// 3. remove all items whose molecules have been removed
615 for (std::vector<const molecule *>::const_iterator removeiter = toBeRemovedItems_copy.begin();
616 removeiter != toBeRemovedItems_copy.end(); ++removeiter) {
[2050b2]617// LOG(1, "Removing molecule " << *removeiter); // cannot access directly, molecule is gone
[69b434]618 QtMoleculeItem *item = MoleculeIdToItem((*removeiter)->getId());
[53c1ff]619 if (item != NULL)
620 removeItem(item);
621 }
622
623 /// 4. instantiate all new items
624 for (std::vector<const molecule *>::const_iterator moliter = newItems_copy.begin();
625 moliter != newItems_copy.end(); ++moliter) {
[2050b2]626// LOG(1, "Adding molecule " << (*moliter)->getName());
[53c1ff]627 // check that World knows the molecule still
[63fb7a]628 const molecule * const mol = const_cast<const World &>(World::getInstance()).
629 getMolecule(MoleculeById((*moliter)->getId()));
[53c1ff]630 if ((mol != NULL) && (mol == *moliter)) {
631 addMolecule(mol);
632 }
633 }
634
[2696b1]635 /// 5a. update the group item's occurrence and visibility
[53c1ff]636 std::set<int> RowsToRemove;
637 for (std::set<QStandardItem*>::const_iterator groupiter = toBeSetOccurrenceItems_copy.begin();
638 groupiter != toBeSetOccurrenceItems_copy.end(); ++groupiter) {
[2050b2]639// LOG(1, "Updating group item " << *groupiter);
[53c1ff]640 const int index = setOccurrence(*groupiter);
641 if (index != -1)
642 RowsToRemove.insert(index);
643 }
644
[2696b1]645 // remove all visibility updates whose row is removed
646 for (std::set<QStandardItem*>::iterator visiter = toBeSetVisibilityItems_copy.begin();
647 visiter != toBeSetVisibilityItems_copy.end(); ) {
648 if (RowsToRemove.count((*visiter)->index().row()) != 0)
649 toBeSetVisibilityItems_copy.erase(visiter++);
650 else
651 ++visiter;
652 }
653
654 // update visibility of all group items
655 for (std::set<QStandardItem*>::iterator visiter = toBeSetVisibilityItems_copy.begin();
656 visiter != toBeSetVisibilityItems_copy.end(); ++visiter) {
[2050b2]657// LOG(1, "Updating visibility of item " << *visiter);
[2696b1]658 setVisibilityForGroupItem(*visiter);
659 }
660
[53c1ff]661 /// 5b. remove all rows with 0 occurrence starting from last
662 for (std::set<int>::reverse_iterator riter = RowsToRemove.rbegin();
663 riter != RowsToRemove.rend(); ++riter) {
[2050b2]664// LOG(1, "Removing group item at row " << *riter);
[53c1ff]665 removeRows(*riter, 1, invisibleRootItem()->index());
666 }
667
668 // and done
[7d0ddb]669 refill_mutex.unlock();
[53c1ff]670}
Note: See TracBrowser for help on using the repository browser.