source: src/UIElements/Views/Qt4/MoleculeList/QtMoleculeList.cpp@ 52c5d4

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 52c5d4 was fcdf05, checked in by Frederik Heber <heber@…>, 10 years ago

Fixing QtMoleculeList with list containing only formulas and ids.

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