source: src/UIElements/Views/Qt4/MoleculeList/QtMoleculeList.cpp@ 50d49d

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 50d49d was 1b07b1, checked in by Frederik Heber <heber@…>, 9 years ago

QtObservedInstanceBoard now sends QtObserved..::ptr around in signals.

  • this should get rid of the problem that we need to keep the QtObservedAtom until it was requested at least once. And we don't know for how long. Now, we simply place the shared_ptr into the signal (to which it seems to be copied) and hence a representation of the atoms remains valid.
  • cstor of GLMoleculeObject_.. take Observed.. as ref.
  • Property mode set to 100644
File size: 31.6 KB
Line 
1/*
2 * Project: MoleCuilder
3 * Description: creates and alters molecular systems
4 * Copyright (C) 2010-2012 University of Bonn. All rights reserved.
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/>.
21 */
22
23/*
24 * QtMoleculeList.cpp
25 *
26 * Created on: Jan 21, 2010
27 * Author: crueger
28 */
29
30// include config.h
31#ifdef HAVE_CONFIG_H
32#include <config.h>
33#endif
34
35#include "QtMoleculeList.hpp"
36
37#include <QModelIndex>
38#include <QDebug>
39
40#include "UIElements/Views/Qt4/MoleculeList/QtMoleculeItem.hpp"
41#include "UIElements/Views/Qt4/MoleculeList/QtMoleculeItemFactory.hpp"
42#include "UIElements/Qt4/InstanceBoard/QtObservedInstanceBoard.hpp"
43
44#include <boost/bind.hpp>
45#include <boost/thread/locks.hpp>
46#include <iostream>
47
48#include "CodePatterns/MemDebug.hpp"
49
50#include "CodePatterns/Log.hpp"
51#include "CodePatterns/Observer/Notification.hpp"
52
53#include "Atom/atom.hpp"
54#include "Actions/MoleculeAction/ChangeNameAction.hpp"
55#include "Actions/SelectionAction/Molecules/PopMoleculesAction.hpp"
56#include "Actions/SelectionAction/Molecules/PushMoleculesAction.hpp"
57#include "Actions/SelectionAction/Molecules/MoleculeByIdAction.hpp"
58#include "Actions/ActionQueue.hpp"
59#include "Actions/ActionSequence.hpp"
60#include "Actions/ActionTrait.hpp"
61#include "Actions/MakroAction.hpp"
62#include "Descriptors/MoleculeIdDescriptor.hpp"
63#include "Formula.hpp"
64#include "molecule.hpp"
65
66using namespace std;
67
68const unsigned int QtMoleculeList::update_times_per_second = 20;
69
70QtMoleculeList::QtMoleculeList(
71 QtObservedInstanceBoard *_board,
72 QObject *_parent) :
73 QStandardItemModel(_parent),
74 update_timer(NULL),
75 board(_board),
76 callback_DirtyItems(boost::bind(&QtMoleculeList::informDirtyState, this, _1, _2, _3))
77{
78 setColumnCount(QtMoleculeItemFactory::COLUMNCOUNT);
79
80 resetUpdateTimer();
81
82 connect(this,SIGNAL(itemChanged(QStandardItem*)),this,SLOT(moleculeNameChanged(QStandardItem*)));
83 connect(this, SIGNAL(itemChanged(QStandardItem*)), this, SLOT(checkForVisibilityChange(QStandardItem*)));
84 connect(board, SIGNAL(moleculeInserted(QtObservedMolecule::ptr)), this, SLOT(moleculeInserted(QtObservedMolecule::ptr)));
85 connect(board, SIGNAL(moleculeRemoved(const moleculeId_t)), this, SLOT(moleculeRemoved(const moleculeId_t)));
86 connect(board, SIGNAL(moleculeIndexChanged(const moleculeId_t,const moleculeId_t)),
87 this, SLOT(moleculeIndexChanged(const moleculeId_t, const moleculeId_t)));
88}
89
90QtMoleculeList::~QtMoleculeList()
91{}
92
93QVariant QtMoleculeList::headerData(int section, Qt::Orientation orientation, int role) const
94{
95 if (role == Qt::DisplayRole) {
96 if (orientation == Qt::Horizontal) {
97 if (section < QtMoleculeItem::COLUMNTYPES_MAX)
98 return QString(QtMoleculeItemFactory::COLUMNNAMES[section]);
99 }
100 }
101 return QVariant();
102}
103
104void QtMoleculeList::moleculeInserted(QtObservedMolecule::ptr _mol)
105{
106 // get ObservedMolecule from board
107 boost::recursive_mutex::scoped_lock lock(listAccessing_mutex);
108 newMolecules.push_back( _mol );
109}
110
111void QtMoleculeList::moleculeRemoved(const moleculeId_t _id)
112{
113 boost::recursive_mutex::scoped_lock lock(map_mutex);
114 KilledItemsPerMolecule_t::iterator iter = KilledItemsPerMolecule.find(_id);
115 if (iter == KilledItemsPerMolecule.end())
116 KilledItemsPerMolecule.insert( std::make_pair(_id, 1));
117 else
118 ++(iter->second);
119 if (iter->second == QtMoleculeItem::COLUMNTYPES_MAX) {
120 boost::recursive_mutex::scoped_lock lock(listAccessing_mutex);
121 removedMolecules.push_back( _id );
122 }
123}
124
125template<class T>
126void exchangeKeys(
127 T &_container,
128 const moleculeId_t _oldid,
129 const moleculeId_t _newid)
130{
131 typename T::iterator iter = _container.find(_oldid);
132 ASSERT(_container.find(_newid) == _container.end(),
133 "exchangeKeys() - new id "+toString(_newid)
134 +" already exists in container.");
135 _container.insert( std::make_pair(_newid, iter->second) );
136 _container.erase(iter);
137}
138
139template<class T>
140void exchangeKeysInSet(
141 T &_container,
142 const moleculeId_t _oldid,
143 const moleculeId_t _newid)
144{
145 typename T::iterator iter = _container.find(_oldid);
146 ASSERT(_container.find(_newid) == _container.end(),
147 "exchangeKeys() - new id "+toString(_newid)
148 +" already exists in container.");
149 _container.insert( _newid );
150 _container.erase(iter);
151}
152
153template<class T>
154void exchangeKeysOverAllColumns(
155 T &_container,
156 const moleculeId_t _oldid,
157 const moleculeId_t _newid)
158{
159 for (int i=0;i<QtMoleculeItem::COLUMNTYPES_MAX;++i) {
160 typename T::iterator iter =
161 _container.find( std::make_pair(_oldid, (enum QtMoleculeItem::COLUMNTYPES)i) );
162 if (iter == _container.end())
163 continue;
164 ASSERT(_container.find( std::make_pair(_newid,(enum QtMoleculeItem::COLUMNTYPES)i) ) == _container.end(),
165 "exchangeKeys() - new id "+toString(_newid)
166 +" already exists in container.");
167 _container.insert( std::make_pair(_newid, (enum QtMoleculeItem::COLUMNTYPES)i) );
168 _container.erase(iter);
169 }
170}
171
172void QtMoleculeList::moleculeIndexChanged(
173 const moleculeId_t _oldid,
174 const moleculeId_t _newid)
175{
176 // go through all list and change keys
177 exchangeKeys(MoleculeFormulaMap, _oldid, _newid);
178 {
179 MoleculeItemBiMap_t::left_iterator iter = MoleculeItemBiMap.left.find(_oldid);
180 ASSERT(MoleculeItemBiMap.left.count(_newid),
181 "QtMoleculeList::moleculeIndexChanged() - new id "+toString(_newid)
182 +" already exists in MoleculeItemBiMap.");
183 MoleculeItemBiMap.left.insert( std::make_pair(_newid, iter->second) );
184 MoleculeItemBiMap.left.erase(iter);
185 }
186 exchangeKeys(KilledItemsPerMolecule, _oldid, _newid);
187 exchangeKeysOverAllColumns(dirtyMolItems, _oldid, _newid);
188 exchangeKeysInSet(visibilityMolItems, _oldid, _newid);
189 {
190 std::vector<moleculeId_t>::iterator iter =
191 std::find(removedMolecules.begin(), removedMolecules.end(), _oldid);
192 removedMolecules.erase(iter);
193 removedMolecules.push_back(_newid);
194 }
195 exchangeKeysInSet(toBeMovedItems, _oldid, _newid);
196}
197
198bool QtMoleculeList::isMoleculeItemPresent(const moleculeId_t _molid) const
199{
200 boost::recursive_mutex::scoped_lock lock(map_mutex);
201 MoleculeItemBiMap_t::left_const_iterator iter =
202 MoleculeItemBiMap.left.find(_molid);
203 return ( iter != MoleculeItemBiMap.left.end());
204}
205
206QtMoleculeItem * QtMoleculeList::MoleculeIdToItem(const moleculeId_t _molid) const
207{
208 boost::recursive_mutex::scoped_lock lock(map_mutex);
209 MoleculeItemBiMap_t::left_const_iterator iter =
210 MoleculeItemBiMap.left.find(_molid);
211 ASSERT( iter != MoleculeItemBiMap.left.end(),
212 "QtMoleculeList::MoleculeIdToItem() - could not find item to id "
213 +toString(_molid));
214 return iter->second;
215}
216
217const moleculeId_t QtMoleculeList::ItemToMoleculeId(const QtMoleculeItem * const _item) const
218{
219 boost::recursive_mutex::scoped_lock lock(map_mutex);
220 const MoleculeItemBiMap_t::right_const_iterator iter =
221 MoleculeItemBiMap.right.find(const_cast<QtMoleculeItem * const>(_item));
222 if (iter != MoleculeItemBiMap.right.end())
223 return iter->second;
224 else
225 return -1;
226}
227
228QtMoleculeItem * QtMoleculeList::getSpecificMoleculeItem(
229 const QtMoleculeItem * const _item,
230 const enum QtMoleculeItem::COLUMNTYPES _type) const
231{
232 QStandardItem *parent_item = _item->parent();
233 ASSERT( parent_item != NULL,
234 "QtMoleculeList::getSpecificMoleculeItem() - parent of molecule item is NULL");
235 return static_cast<QtMoleculeItem *>(parent_item->child(_item->index().row(), _type));
236}
237
238bool QtMoleculeList::isGroupItemPresent(const std::string &_formula) const
239{
240 boost::recursive_mutex::scoped_lock lock(map_mutex);
241 FormulaTreeItemBiMap_t::left_const_iterator iter =
242 FormulaItemBiMap.left.find(_formula);
243 return ( iter != FormulaItemBiMap.left.end());
244}
245
246QStandardItem * QtMoleculeList::FormulaToGroupItem(const std::string &_formula) const
247{
248 boost::recursive_mutex::scoped_lock lock(map_mutex);
249 FormulaTreeItemBiMap_t::left_const_iterator iter =
250 FormulaItemBiMap.left.find(_formula);
251 ASSERT( iter != FormulaItemBiMap.left.end(),
252 "QtMoleculeList::FormulaToGroupItem() - could not find item to formula "
253 +toString(_formula));
254 return iter->second;
255}
256
257const std::string& QtMoleculeList::GroupItemToFormula(const QStandardItem * const _item) const
258{
259 boost::recursive_mutex::scoped_lock lock(map_mutex);
260 static std::string emptystring;
261 const FormulaTreeItemBiMap_t::right_const_iterator iter =
262 FormulaItemBiMap.right.find(const_cast<QStandardItem * const>(_item));
263 if (iter != FormulaItemBiMap.right.end())
264 return iter->second;
265 else
266 return emptystring;
267}
268
269QStandardItem * QtMoleculeList::getSpecificGroupItem(
270 const QStandardItem * const _item,
271 const enum QtMoleculeItem::COLUMNTYPES _type) const
272{
273 return invisibleRootItem()->child(_item->index().row(), _type);
274}
275
276const QModelIndex QtMoleculeList::MoleculeIdToIndex(const moleculeId_t _id) const
277{
278 boost::recursive_mutex::scoped_lock lock(refill_mutex);
279 QtMoleculeItem * const item = MoleculeIdToItem(_id);
280 ASSERT(item != NULL,
281 "QtMoleculeList::MoleculeIdToIndex() - could not find item to "
282 +toString(_id));
283 return indexFromItem(item);
284}
285
286const moleculeId_t QtMoleculeList::IndexToMoleculeId(const QModelIndex &_index) const
287{
288 boost::recursive_mutex::scoped_lock lock(refill_mutex);
289 QtMoleculeItem * const item = dynamic_cast<QtMoleculeItem *>(itemFromIndex(_index));
290 if (item == NULL)
291 return -1;
292 else
293 return ItemToMoleculeId(item);
294}
295
296void QtMoleculeList::addGroupItem(
297 QStandardItem *&mainitem,
298 const std::string &_molecule_formula)
299{
300 QList<QStandardItem *> groupItems =
301 QtMoleculeItemFactory::getInstance().createGroupItems(_molecule_formula);
302 mainitem = groupItems.front();
303 {
304 boost::recursive_mutex::scoped_lock lock(map_mutex);
305 FormulaItemBiMap.left.insert( std::make_pair(_molecule_formula, mainitem) );
306 }
307 invisibleRootItem()->appendRow(groupItems);
308}
309
310QList<QStandardItem *> QtMoleculeList::createMoleculeItems(
311 QtObservedMolecule::ptr &_ObservedMolecule,
312 std::string &_molecule_formula)
313{
314 QList<QStandardItem *> molItems =
315 QtMoleculeItemFactory::getInstance().createMoleculeItems(
316 _ObservedMolecule,
317 callback_DirtyItems);
318 QtMoleculeItem *mol_item = dynamic_cast<QtMoleculeItem *>(molItems.front());
319 ASSERT( mol_item != NULL,
320 "QtMoleculeList::createMoleculeItems() - item from factory was not a QtMoleculeItem?");
321 MoleculeItemBiMap.left.insert( std::make_pair(_ObservedMolecule->getMolIndex(), mol_item) );
322
323 QStandardItem *formulaitem = molItems.at(QtMoleculeItem::FORMULA);
324 ASSERT( formulaitem != NULL,
325 "QtMoleculeList::createMoleculeItems() - Formula item not created by factory?");
326 _molecule_formula = formulaitem->text().toStdString();
327
328 LOG(1, "Adding " << _molecule_formula << " for "
329 << _ObservedMolecule->getMolIndex() << " to MoleculeFormulaMap.");
330 MoleculeFormulaMap.insert( std::make_pair( _ObservedMolecule->getMolIndex(), _molecule_formula) );
331// LOG(1, "Inserting molecule " << _molid << ": " << _molecule_formula);
332 return molItems;
333}
334
335std::string QtMoleculeList::addMolecule(QtObservedMolecule::ptr &_ObservedMolecule)
336{
337 // find group if already in list
338 QStandardItem *groupItem = NULL;
339
340 // create molecule items and obtain the molecule's formula
341 std::string molecule_formula;
342 QList<QStandardItem *> molItems = createMoleculeItems(_ObservedMolecule, molecule_formula);
343
344 // new molecule type -> create new group
345 if (!isGroupItemPresent(molecule_formula)){
346 // insert new formula entry into visibility
347#ifndef NDEBUG
348 std::pair< FormulaVisibilityCountMap_t::iterator, bool> visibilityinserter =
349#endif
350 FormulaVisibilityCountMap.insert(
351 std::make_pair( molecule_formula, (unsigned int)0) );
352 ASSERT( visibilityinserter.second,
353 "QtMoleculeList::refill() - molecule with formula "
354 +molecule_formula+" already in FormulaVisibilityCountMap.");
355
356 // create item and place into Map with formula as key
357 addGroupItem(groupItem, molecule_formula);
358 } else {
359 groupItem = FormulaToGroupItem(molecule_formula);
360 }
361 ASSERT( groupItem != NULL,
362 "QtMoleculeList::addMolecule() - item with id "+toString(_ObservedMolecule->getMolIndex())
363 +" has no parent?");
364 groupItem->appendRow(molItems);
365
366 return molecule_formula;
367}
368
369void QtMoleculeList::removeMoleculeItem(QtMoleculeItem * const _item)
370{
371 boost::recursive_mutex::scoped_lock lock(refill_mutex);
372 const QModelIndex mol_index = indexFromItem(_item);
373 QStandardItem *groupitem = _item->parent();
374 const QModelIndex group_index = groupitem->index();
375 {
376 boost::recursive_mutex::scoped_lock lock(map_mutex);
377 MoleculeItemBiMap_t::right_iterator removeiter =
378 MoleculeItemBiMap.right.find(_item);
379 ASSERT( removeiter != MoleculeItemBiMap.right.end(),
380 "QtMoleculeList::removeMoleculeItem() - could not find item in MoleculeBiMap.");
381 // LOG(1, "Erasing molecule " << (removeiter->second));
382 {
383 MoleculeFormulaMap_t::iterator removeformulaiter =
384 MoleculeFormulaMap.find(removeiter->second);
385 ASSERT( removeformulaiter != MoleculeFormulaMap.end(),
386 "QtMoleculeList::removeMoleculeItem() - could not find id "
387 +toString(removeiter->second)+" in MoleculeFormulaMap.");
388 LOG(1, "Removing " << removeformulaiter->second << " for "
389 << removeformulaiter->first << " from MoleculeFormulaMap.");
390 MoleculeFormulaMap.erase( removeformulaiter );
391 }
392 MoleculeItemBiMap.right.erase(removeiter);
393 }
394 removeRows(mol_index.row(), 1, group_index);
395}
396
397void QtMoleculeList::resetUpdateTimer()
398{
399 // check timer's presence
400 if (update_timer == NULL) {
401 update_timer = new QTimer(this);
402 connect( update_timer, SIGNAL(timeout()), this, SLOT(checkState()));
403 } else
404 update_timer->stop();
405
406 // activate timer
407 update_timer->start(1000/update_times_per_second);
408}
409
410bool QtMoleculeList::areAnyItemsDirty()
411{
412 // get whether any items are dirty
413 boost::recursive_mutex::scoped_lock lock(listAccessing_mutex);
414 bool dirty = false;
415 dirty |= !dirtyMolItems.empty();
416 dirty |= !visibilityMolItems.empty();
417 dirty |= !dirtyGroupItems.empty();
418 dirty |= !visibilityGroupItems.empty();
419 dirty |= !newMolecules.empty();
420 dirty |= !removedMolecules.empty();
421 dirty |= !toBeMovedItems.empty();
422 return dirty;
423}
424
425void QtMoleculeList::checkState()
426{
427 const bool dirty = areAnyItemsDirty();
428 // update if required
429 if (dirty)
430 updateItemStates();
431}
432
433void QtMoleculeList::checkForVisibilityChange(QStandardItem* _item)
434{
435// qDebug() << "Item changed called.";
436
437 boost::recursive_mutex::scoped_lock lock(refill_mutex);
438 if (_item->index().column() == QtMoleculeItem::VISIBILITY) {
439// qDebug() << "visibilityItem changed: " << (_item->checkState() ? "checked" : "unchecked");
440 boost::recursive_mutex::scoped_lock lock(listAccessing_mutex);
441 if ((_item->parent() == NULL) || (_item->parent() == invisibleRootItem()))
442 visibilityGroupItems.insert( std::make_pair(
443 GroupItemToFormula(_item->parent()), QtMoleculeItem::VISIBILITY) );
444 else
445 visibilityMolItems.insert(
446 static_cast<QtMoleculeItem *>(_item)->getMoleculeId()
447 );
448 }
449}
450
451void QtMoleculeList::setVisibilityForMoleculeItem(QtMoleculeItem* _item)
452{
453 if (ChangingChildrensVisibility)
454 return;
455
456 boost::recursive_mutex::scoped_lock lock(refill_mutex);
457 const bool visible = _item->checkState();
458 const moleculeId_t molid = _item->getMoleculeId();
459 std::string molecule_formula("illegal");
460 {
461 boost::recursive_mutex::scoped_lock lock(map_mutex);
462 MoleculeFormulaMap_t::const_iterator formulaiter =
463 MoleculeFormulaMap.find(molid);
464 ASSERT( formulaiter != MoleculeFormulaMap.end(),
465 "QtMoleculeList::setVisibilityForMoleculeItem() - formula of molecule "
466 +toString(molid)+" unknown.");
467 molecule_formula = formulaiter->second;
468 }
469 ASSERT( FormulaVisibilityCountMap.count(molecule_formula) != 0,
470 "QtMoleculeList::setVisibilityForMoleculeItem() - molecule with formula " +molecule_formula
471 +" is not present in FormulaVisibilityCountMap.");
472
473 // get parent
474 QStandardItem *groupItem = _item->parent();
475 QStandardItem *visgroupItem = getSpecificGroupItem(groupItem, QtMoleculeItem::VISIBILITY);
476 ASSERT( groupItem != NULL,
477 "QtMoleculeList::setVisibilityForMoleculeItem() - item with id "
478 +toString(_item->getMoleculeId())+" has not parent?");
479 // check whether we have to set the group item
480
481 ChangingChildrensVisibility = true;
482 if (visible) {
483 ++(FormulaVisibilityCountMap[molecule_formula]);
484 // compare with occurence/total number of molecules
485 if (FormulaVisibilityCountMap[molecule_formula] ==
486 (unsigned int)(groupItem->rowCount()))
487 visgroupItem->setCheckState(Qt::Checked);
488 } else {
489 --(FormulaVisibilityCountMap[molecule_formula]);
490 // none selected anymore?
491 if (FormulaVisibilityCountMap[molecule_formula] == 0)
492 visgroupItem->setCheckState(Qt::Unchecked);
493 }
494 ChangingChildrensVisibility = false;
495
496 emit moleculesVisibilityChanged(_item->getMoleculeId(), visible);
497}
498
499void QtMoleculeList::setVisibilityForGroupItem(QStandardItem* _item)
500{
501 if (ChangingChildrensVisibility)
502 return;
503
504 ChangingChildrensVisibility = true;
505
506 boost::recursive_mutex::scoped_lock lock(refill_mutex);
507 // go through all children, but don't enter for groupItem once more
508 const bool visible = _item->checkState();
509 QStandardItem *groupitem = getSpecificGroupItem(_item, QtMoleculeItem::NAME);
510 for (int i=0;i<groupitem->rowCount();++i) {
511 QtMoleculeItem *molItem = dynamic_cast<QtMoleculeItem *>(
512 groupitem->child(i, QtMoleculeItem::VISIBILITY));
513 if (molItem->checkState() != visible) {
514 molItem->setCheckState(visible ? Qt::Checked : Qt::Unchecked);
515
516 // emit signal
517 emit moleculesVisibilityChanged(molItem->getMoleculeId(), visible);
518 }
519 }
520 // set current number of visible children
521 const std::string molecule_formula =
522 GroupItemToFormula( getSpecificGroupItem(_item, QtMoleculeItem::NAME) );
523 FormulaVisibilityCountMap_t::iterator countiter =
524 FormulaVisibilityCountMap.find(molecule_formula);
525 ASSERT( countiter != FormulaVisibilityCountMap.end(),
526 "QtMoleculeList::setVisibilityForGroupItem() - molecules "+molecule_formula
527 +" have no entry in visibility count map?");
528 countiter->second = visible ? groupitem->rowCount() : 0;
529
530 ChangingChildrensVisibility = false;
531}
532
533static
534MoleCuilder::MakroAction *constructMakroRenameAction(
535 MoleCuilder::ActionSequence &sequence,
536 const std::string &_new_name,
537 const moleculeId_t _molid
538 )
539{
540 MoleCuilder::ActionQueue &AQ = MoleCuilder::ActionQueue::getInstance();
541 MoleCuilder::ActionTrait trait("change-single-molecule-name");
542 sequence.addAction(AQ.getActionByName("push-molecule-selection").clone(MoleCuilder::Action::NonInteractive));
543 MoleCuilder::Action * const selectaction =
544 AQ.getActionByName("select-molecule-by-id").clone(MoleCuilder::Action::NonInteractive);
545 {
546 std::stringstream molid_string;
547 molid_string << toString(_molid);
548 selectaction->setOptionValue("select-molecule-by-id", molid_string.str());
549 }
550 sequence.addAction(selectaction);
551 MoleCuilder::Action * const changeaction =
552 AQ.getActionByName("change-molname").clone(MoleCuilder::Action::NonInteractive);
553 changeaction->setOptionValue("change-molname", _new_name);
554 sequence.addAction(changeaction);
555 sequence.addAction(AQ.getActionByName("pop-molecule-selection").clone(MoleCuilder::Action::NonInteractive));
556
557 MoleCuilder::MakroAction* makroaction =
558 new MoleCuilder::MakroAction(trait, sequence);
559 return makroaction;
560}
561
562void QtMoleculeList::moleculeNameChanged(QStandardItem* item)
563{
564 boost::recursive_mutex::scoped_lock lock(refill_mutex);
565 // obtain molecule id
566 if ( item->index().column() == QtMoleculeItem::NAME) {
567 QtMoleculeItem *molitem = assert_cast<QtMoleculeItem *>(item);
568 MoleculeItemBiMap_t::right_const_iterator iter = MoleculeItemBiMap.right.find(molitem);
569 ASSERT( iter != MoleculeItemBiMap.right.end(),
570 "QtMoleculeList::moleculeChanged() - name of unknown molecule changed.");
571 const moleculeId_t molid = iter->second;
572 // change the name
573 molecule * const mol = World::getInstance().getMolecule(MoleculeById(molid));
574 std::string cellValue = item->text().toStdString();
575 if ((mol->getName() != cellValue) && (!cellValue.empty())) {
576 // create actions such that we may undo
577 static MoleCuilder::ActionSequence sequence;
578 MoleCuilder::MakroAction *makroaction =
579 constructMakroRenameAction(sequence, cellValue, molid);
580 MoleCuilder::ActionQueue &AQ = MoleCuilder::ActionQueue::getInstance();
581 AQ.registerAction(makroaction);
582 AQ.queueAction("change-single-molecule-name", MoleCuilder::Action::NonInteractive);
583 } else if(cellValue=="") {
584 item->setText(QString(mol->getName().c_str()));
585 }
586}
587}
588
589
590int QtMoleculeList::setOccurrence(QStandardItem * const _groupitem)
591{
592 boost::recursive_mutex::scoped_lock lock(refill_mutex);
593 QModelIndex modelindex = _groupitem->index();
594 ASSERT( modelindex.isValid(),
595 "QtMoleculeList::setOccurrence() - groupitem not associated to model anymore.");
596 const int index = modelindex.row();
597 QStandardItem *parent_item =
598 _groupitem->parent() == NULL ? invisibleRootItem() : _groupitem->parent();
599 ASSERT( parent_item != NULL,
600 "QtMoleculeList::setOccurrence() - group item at "+toString(index)
601 +" does not have a parent?");
602 QStandardItem *occ_item = parent_item->child(index, QtMoleculeItem::OCCURRENCE);
603 ASSERT( occ_item != NULL,
604 "QtMoleculeList::setOccurrence() - group item at "+toString(index)
605 +" does not have an occurrence?");
606 const int count = _groupitem->rowCount();
607 if (count == 0) {
608 // we have to remove the group item completely
609 boost::recursive_mutex::scoped_lock lock(map_mutex);
610 const std::string molecule_formula = _groupitem->text().toStdString();
611 FormulaItemBiMap.left.erase(molecule_formula);
612 FormulaVisibilityCountMap.erase(molecule_formula);
613 return index;
614 } else {
615 occ_item->setText(QString::number(count));
616 return -1;
617 }
618}
619
620std::string QtMoleculeList::readdItem(QtMoleculeItem *_molitem)
621{
622 boost::recursive_mutex::scoped_lock lock(refill_mutex);
623 // use takeRows of molecule ..
624 QStandardItem *groupitem = _molitem->parent();
625 ASSERT( groupitem != NULL,
626 "QtMoleculeList::readdItem() - mol item at "+toString(_molitem->index().row())
627 +" does not have a groupitem?");
628 // get updated formula from the item
629 QStandardItem *formulaitem =
630 _molitem->parent()->child(_molitem->index().row(), QtMoleculeItem::FORMULA);
631 const std::string molecule_formula = formulaitem->text().toStdString();
632 QList<QStandardItem *> mol_row = _molitem->parent()->takeRow(_molitem->index().row());
633 // .. and re-add where new formula fits
634 if (!isGroupItemPresent(molecule_formula)) {
635 // add new group item and formula entry
636 addGroupItem(groupitem, molecule_formula);
637 } else {
638 groupitem = FormulaToGroupItem(molecule_formula);
639 }
640 ASSERT( groupitem != NULL,
641 "QtMoleculeList::readdItem() - failed to create a sensible new groupitem");
642 // finally add again
643 groupitem->appendRow(mol_row);
644
645 return molecule_formula;
646}
647
648void QtMoleculeList::informDirtyState(
649 const moleculeId_t _id,
650 const QtMoleculeItem::COLUMNTYPES _type,
651 const QtMoleculeItem::MoveTypes _movetype)
652{
653 listAccessing_mutex.lock();
654 dirtyMolItems.insert( std::make_pair(_id, _type) );
655 listAccessing_mutex.unlock();
656
657 if (_movetype == QtMoleculeItem::NeedsMove) {
658 // we have to convert whatever item raised the dirty signal to the first
659 // item in the row as otherwise multiple items in the row are selected
660 // as to be moved, i.e. the same row is moved multiple times
661 listAccessing_mutex.lock();
662 toBeMovedItems.insert(_id);
663 listAccessing_mutex.unlock();
664 }
665}
666
667void QtMoleculeList::updateItemStates()
668{
669 /// copy lists such that new signals for dirty/.. may come in right away
670 // TODO: if we had move semantics ...
671 listAccessing_mutex.lock();
672 list_of_molecule_items_t dirtyMolItems_copy = dirtyMolItems;
673 dirtyMolItems.clear();
674 list_of_molecules_t visibilityMolItems_copy = visibilityMolItems;
675 visibilityMolItems.clear();
676 list_of_group_items_t dirtyGroupItems_copy = dirtyGroupItems;
677 dirtyGroupItems.clear();
678 list_of_group_items_t visibilityGroupItems_copy = visibilityGroupItems;
679 visibilityGroupItems.clear();
680 std::vector<QtObservedMolecule::ptr> newMolecules_copy = newMolecules;
681 newMolecules.clear();
682 std::vector<moleculeId_t> removedMolecules_copy = removedMolecules;
683 removedMolecules.clear();
684 list_of_molecules_t toBeMovedItems_copy = toBeMovedItems;
685 toBeMovedItems.clear();
686 listAccessing_mutex.unlock();
687
688 // wait till initial refill has been executed
689 boost::recursive_mutex::scoped_lock lock(refill_mutex);
690
691// LOG(1, "Starting update.");
692
693 // remove removedMolecules from other lists.
694 for (std::vector<moleculeId_t>::const_iterator removeiter = removedMolecules_copy.begin();
695 removeiter != removedMolecules_copy.end(); ++removeiter) {
696 for (unsigned int i=0;i< QtMoleculeItem::COLUMNTYPES_MAX; ++i)
697 dirtyMolItems_copy.erase( std::make_pair(*removeiter,(QtMoleculeItem::COLUMNTYPES)i) );
698 toBeMovedItems_copy.erase(*removeiter);
699 visibilityMolItems_copy.erase(*removeiter);
700 }
701
702 /// 1a. do the update for each dirty item
703 for (list_of_molecule_items_t::const_iterator dirtyiter = dirtyMolItems_copy.begin();
704 dirtyiter != dirtyMolItems_copy.end(); ++dirtyiter) {
705 if (!isMoleculeItemPresent(dirtyiter->first))
706 continue;
707 QtMoleculeItem * const mol_item =
708 getSpecificMoleculeItem(
709 MoleculeIdToItem(dirtyiter->first),
710 dirtyiter->second);
711// LOG(1, "Updating item " << mol_item);
712 mol_item->updateState();
713 }
714
715 /// 1b. do the visibility update for each dirty item
716 for (list_of_molecules_t::const_iterator visiter = visibilityMolItems_copy.begin();
717 visiter != visibilityMolItems_copy.end(); ++visiter) {
718 if (!isMoleculeItemPresent(*visiter))
719 continue;
720 QtMoleculeItem * const visitem =
721 getSpecificMoleculeItem(
722 MoleculeIdToItem(*visiter),
723 QtMoleculeItem::VISIBILITY );
724// LOG(1, "Updating visibility of item " << visitem);
725 setVisibilityForMoleculeItem(visitem);
726 }
727
728 /// 2. move all items that need to be moved
729 typedef std::set<std::string> formulas_t;
730 formulas_t toBeSetOccurrence;
731 for (list_of_molecules_t::const_iterator moveiter = toBeMovedItems_copy.begin();
732 moveiter != toBeMovedItems_copy.end(); ++moveiter) {
733 boost::recursive_mutex::scoped_lock lock(map_mutex);
734// LOG(1, "Moving item " << molitem);
735 MoleculeFormulaMap_t::iterator formulaiter =
736 MoleculeFormulaMap.find(*moveiter);
737 ASSERT( formulaiter != MoleculeFormulaMap.end(),
738 "QtMoleculeList::updateItemStates() - formula of molecule "
739 +toString(*moveiter)+" unknown.");
740// LOG(1, "Adding " << formulaiter->second << " to toBeSetOccurrence.");
741 toBeSetOccurrence.insert( formulaiter->second );
742 if (!isMoleculeItemPresent(*moveiter))
743 continue;
744 QtMoleculeItem *const molitem = MoleculeIdToItem(*moveiter);
745 LOG(1, "Moving item " << molitem);
746 // remove from formula<->molecule bimap with old formula
747 LOG(1, "Removing " << formulaiter->second << " for " << formulaiter->first << " from MoleculeFormulaMap.");
748 MoleculeFormulaMap.erase( formulaiter );
749 const std::string formula = readdItem(molitem);
750 // and add to formula<->molecule bimap with updated formula
751 LOG(1, "Adding " << formula << " for " << *moveiter << " to MoleculeFormulaMap.");
752 MoleculeFormulaMap.insert( std::make_pair(*moveiter, formula) );
753// LOG(1, "Adding " << formula << " to toBeSetOccurrence.");
754 toBeSetOccurrence.insert( formula );
755 }
756
757 /// 3. remove all items whose molecules have been removed
758 for (std::vector<moleculeId_t>::const_iterator removeiter = removedMolecules_copy.begin();
759 removeiter != removedMolecules_copy.end(); ++removeiter) {
760// LOG(1, "Removing molecule " << *removeiter);
761 if (!isMoleculeItemPresent(*removeiter))
762 continue;
763 QtMoleculeItem *item = MoleculeIdToItem(*removeiter);
764 if (item != NULL) {
765 const std::string formula = item->parent()->text().toStdString();
766// LOG(1, "Adding " << formula << " to toBeSetOccurrence.");
767 toBeSetOccurrence.insert( formula );
768 removeMoleculeItem(item);
769 KilledItemsPerMolecule.erase( *removeiter );
770 }
771 }
772
773 // throw out items that we added by an update() while we are in this function
774 listAccessing_mutex.lock();
775 for (std::vector<moleculeId_t>::const_iterator removeiter = removedMolecules_copy.begin();
776 removeiter != removedMolecules_copy.end(); ++removeiter) {
777 for (unsigned int i=0;i< QtMoleculeItem::COLUMNTYPES_MAX; ++i)
778 dirtyMolItems.erase( std::make_pair(*removeiter,(QtMoleculeItem::COLUMNTYPES)i) );
779 toBeMovedItems.erase(*removeiter);
780 visibilityMolItems.erase(*removeiter);
781 }
782 listAccessing_mutex.unlock();
783 // after that it is not a problem as items have been removed (hence signOff() was called)
784
785 /// 4. instantiate all new items
786 for (std::vector<QtObservedMolecule::ptr>::iterator moliter = newMolecules_copy.begin();
787 moliter != newMolecules_copy.end(); ++moliter) {
788// LOG(1, "Adding molecule " << ObservedMolecule->getMoleculeName());
789 // check that World knows the molecule still
790 const std::string formula = addMolecule(*moliter);
791// LOG(1, "Adding " << formula << " to toBeSetOccurrence.");
792 toBeSetOccurrence.insert( formula );
793 }
794
795 /// 5a. update the group item's occurrence and visibility
796 std::set<int> RowsToRemove;
797 for (std::set<std::string>::const_iterator groupiter = toBeSetOccurrence.begin();
798 groupiter != toBeSetOccurrence.end(); ++groupiter) {
799// LOG(1, "Updating group item's occurence " << *groupiter);
800 QStandardItem *groupitem = FormulaToGroupItem(*groupiter);
801 const int index = setOccurrence(groupitem);
802 if (index != -1) {
803// LOG(1, "Removing row of group item " << groupitem);
804 RowsToRemove.insert(index);
805 }
806 }
807 toBeSetOccurrence.clear();
808
809 // remove all visibility updates whose row is removed
810 for (list_of_group_items_t::iterator visiter = visibilityGroupItems_copy.begin();
811 visiter != visibilityGroupItems_copy.end(); ) {
812 QStandardItem * const groupitem = FormulaToGroupItem(visiter->first);
813 if (RowsToRemove.count(groupitem->index().row()) != 0) {
814// LOG(1, "Removing vis item " << *visiter << " because of removed group item.");
815 visibilityGroupItems_copy.erase(visiter++);
816 } else
817 ++visiter;
818 }
819
820 // update visibility of all group items
821 for (list_of_group_items_t::iterator visiter = visibilityGroupItems_copy.begin();
822 visiter != visibilityGroupItems_copy.end(); ++visiter) {
823// LOG(1, "Updating visibility of item " << *visiter);
824 QStandardItem * const groupitem =
825 getSpecificGroupItem(FormulaToGroupItem(visiter->first),
826 visiter->second);
827 setVisibilityForGroupItem(groupitem);
828 }
829
830 /// 5b. remove all rows with 0 occurrence starting from last
831 for (std::set<int>::reverse_iterator riter = RowsToRemove.rbegin();
832 riter != RowsToRemove.rend(); ++riter) {
833// LOG(1, "Removing group item at row " << *riter);
834 removeRows(*riter, 1, invisibleRootItem()->index());
835 }
836
837 // and done
838// LOG(1, "Done with update.");
839}
Note: See TracBrowser for help on using the repository browser.