source: src/UIElements/Views/Qt4/MoleculeList/QtMoleculeList.cpp@ 3d5b5b

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 3d5b5b 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
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>
[fcdf05]44#include <boost/thread/locks.hpp>
[b47bfc]45#include <iostream>
46
[ad011c]47#include "CodePatterns/MemDebug.hpp"
[bbbad5]48
[53c1ff]49#include "CodePatterns/Log.hpp"
[6770fa]50#include "CodePatterns/Observer/Notification.hpp"
51
[6f0841]52#include "Atom/atom.hpp"
[d2dbb5d]53#include "Descriptors/MoleculeIdDescriptor.hpp"
[26cf17]54#include "Formula.hpp"
[b47bfc]55#include "molecule.hpp"
[42127c]56#include "MoleculeListClass.hpp"
[b47bfc]57
58using namespace std;
59
[53c1ff]60const unsigned int QtMoleculeList::update_times_per_second = 20;
[b47bfc]61
[8ccf3b]62QtMoleculeList::QtMoleculeList() :
[53c1ff]63 Observer("QtMoleculeList"),
64 ChangingChildrensVisibility(false),
65 update_timer(NULL),
[fcdf05]66 callback_DirtyItems(boost::bind(&QtMoleculeList::informDirtyState, this, _1, _2, _3))
[b47bfc]67{
[53c1ff]68 setColumnCount(QtMoleculeItemFactory::COLUMNCOUNT);
[b47bfc]69
[3eb91c]70 World::getInstance().signOn(this, World::MoleculeInserted);
71 World::getInstance().signOn(this, World::MoleculeRemoved);
[41815a3]72
[a39006]73 refill();
[b47bfc]74
[8ccf3b]75// qRegisterMetaType<QItemSelection>("QItemSelection");
[79b59b]76 //connect(this,SIGNAL(cellChanged(int,int)),this,SLOT(moleculeChanged(int,int)));
[8ccf3b]77// connect(selectionModel(),SIGNAL(selectionChanged(QItemSelection, QItemSelection)),this,SLOT(rowsSelected(QItemSelection, QItemSelection)));
[fcdf05]78 connect(this, SIGNAL(itemChanged(QStandardItem*)), this, SLOT(checkForVisibilityChange(QStandardItem*)), Qt::DirectConnection);
[b47bfc]79}
80
[0eb7bf3]81QtMoleculeList::~QtMoleculeList()
[b47bfc]82{
[3eb91c]83 World::getInstance().signOff(this, World::MoleculeInserted);
84 World::getInstance().signOff(this, World::MoleculeRemoved);
[b47bfc]85}
86
[1c3390]87QVariant QtMoleculeList::headerData(int section, Qt::Orientation orientation, int role) const
88{
89 if (role == Qt::DisplayRole) {
90 if (orientation == Qt::Horizontal) {
[fcdf05]91 if (section < QtMoleculeItem::COLUMNTYPES_MAX)
[53c1ff]92 return QString(QtMoleculeItemFactory::COLUMNNAMES[section]);
[1c3390]93 }
94 }
95 return QVariant();
96}
97
[0eb7bf3]98void QtMoleculeList::update(Observable *publisher) {
[3eb91c]99 ASSERT(0,
100 "QtMoleculeList::update() - we did not sign up for any global updates.");
101}
102
[fcdf05]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
[69b434]111QtMoleculeItem * QtMoleculeList::MoleculeIdToItem(const moleculeId_t _molid) const
[8ccf3b]112{
[fcdf05]113 boost::recursive_mutex::scoped_lock lock(map_mutex);
[8ccf3b]114 MoleculeItemBiMap_t::left_const_iterator iter =
[69b434]115 MoleculeItemBiMap.left.find(_molid);
[fcdf05]116 ASSERT( iter != MoleculeItemBiMap.left.end(),
117 "QtMoleculeList::MoleculeIdToItem() - could not find item to id "
118 +toString(_molid));
119 return iter->second;
[8ccf3b]120}
121
[69b434]122const moleculeId_t QtMoleculeList::ItemToMoleculeId(const QtMoleculeItem * const _item) const
[53c1ff]123{
[fcdf05]124 boost::recursive_mutex::scoped_lock lock(map_mutex);
[53c1ff]125 const MoleculeItemBiMap_t::right_const_iterator iter =
126 MoleculeItemBiMap.right.find(const_cast<QtMoleculeItem * const>(_item));
[d2dbb5d]127 if (iter != MoleculeItemBiMap.right.end())
128 return iter->second;
129 else
[69b434]130 return -1;
[53c1ff]131}
132
[fcdf05]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
[69b434]182const moleculeId_t QtMoleculeList::IndexToMoleculeId(const QModelIndex &_index) const
[53c1ff]183{
[fcdf05]184 boost::recursive_mutex::scoped_lock lock(refill_mutex);
[53c1ff]185 QtMoleculeItem * const item = dynamic_cast<QtMoleculeItem *>(itemFromIndex(_index));
186 if (item == NULL)
[69b434]187 return -1;
[53c1ff]188 else
[69b434]189 return ItemToMoleculeId(item);
[53c1ff]190}
191
[6770fa]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>();
[fcdf05]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 );
[6770fa]203 break;
204 }
205 case World::MoleculeRemoved:
206 {
207 const molecule * const mol = World::getInstance().lastChanged<molecule>();
[53c1ff]208
[fcdf05]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
[6770fa]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 }
[a39006]221}
222
[6770fa]223void QtMoleculeList::addGroupItem(
[8ccf3b]224 QStandardItem *&mainitem,
[6770fa]225 const std::string &_molecule_formula)
226{
[53c1ff]227 QList<QStandardItem *> groupItems =
228 QtMoleculeItemFactory::getInstance().createGroupItems(_molecule_formula);
229 mainitem = groupItems.front();
[fcdf05]230 {
231 boost::recursive_mutex::scoped_lock lock(map_mutex);
232 FormulaItemBiMap.left.insert( std::make_pair(_molecule_formula, mainitem) );
233 }
[8ccf3b]234 invisibleRootItem()->appendRow(groupItems);
[53c1ff]235}
236
[6770fa]237void QtMoleculeList::addMoleculeItem(
[8ccf3b]238 QStandardItem *_groupitem,
[69b434]239 const moleculeId_t _molid,
[6770fa]240 const std::string &_molecule_formula)
241{
[53c1ff]242 QList<QStandardItem *> molItems =
[69b434]243 QtMoleculeItemFactory::getInstance().createMoleculeItems(_molid, callback_DirtyItems);
[53c1ff]244 QtMoleculeItem *mol_item = dynamic_cast<QtMoleculeItem *>(molItems.front());
245 ASSERT( mol_item != NULL,
246 "QtMoleculeList::addMoleculeItem() - item from factory was not a QtMoleculeItem?");
[fcdf05]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 }
[2050b2]253// LOG(1, "Inserting molecule " << _mol->getId() << ": " << _mol);
[8ccf3b]254 _groupitem->appendRow(molItems);
[6770fa]255}
256
[fcdf05]257std::string QtMoleculeList::addMolecule(const molecule * const _mol)
[6770fa]258{
259 // find group if already in list
[8ccf3b]260 QStandardItem *groupItem = NULL;
[6770fa]261
[fcdf05]262 const std::string molecule_formula = _mol->getFormula().toString();
[6770fa]263
264 // new molecule type -> create new group
[fcdf05]265 if (!isGroupItemPresent(molecule_formula)){
[6770fa]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 {
[fcdf05]279 groupItem = FormulaToGroupItem(molecule_formula);
[6770fa]280 }
281 ASSERT( groupItem != NULL,
[53c1ff]282 "QtMoleculeList::addMolecule() - item with id "+toString(_mol->getId())
[fcdf05]283 +" has no parent?");
[6770fa]284
285 // add molecule
[69b434]286 addMoleculeItem(groupItem, _mol->getId(), molecule_formula);
[fcdf05]287
288 return molecule_formula;
[6770fa]289}
290
[fcdf05]291void QtMoleculeList::removeMoleculeItem(QtMoleculeItem * const _item)
[6770fa]292{
[fcdf05]293 boost::recursive_mutex::scoped_lock lock(refill_mutex);
[53c1ff]294 const QModelIndex mol_index = indexFromItem(_item);
295 QStandardItem *groupitem = _item->parent();
296 const QModelIndex group_index = groupitem->index();
[fcdf05]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 }
[53c1ff]316 removeRows(mol_index.row(), 1, group_index);
317}
[6770fa]318
[53c1ff]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();
[6770fa]327
[fcdf05]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 }
[3eb91c]349
[1259df]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();
[41815a3]353 iter != molecules.end();
[53c1ff]354 iter++)
355 addMolecule(*iter);
[b47bfc]356
[53c1ff]357 // activate timer
358 update_timer->start(1000/update_times_per_second);
[a39006]359}
360
[53c1ff]361bool QtMoleculeList::areAnyItemsDirty()
[a39006]362{
[53c1ff]363 // get whether any items are dirty
[fcdf05]364 boost::recursive_mutex::scoped_lock lock(listAccessing_mutex);
[53c1ff]365 bool dirty = false;
[fcdf05]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();
[53c1ff]373 return dirty;
[b47bfc]374}
375
[53c1ff]376void QtMoleculeList::checkState()
377{
378 const bool dirty = areAnyItemsDirty();
379 // update if required
380 if (dirty)
381 updateItemStates();
[b47bfc]382}
383
[53c1ff]384void QtMoleculeList::subjectKilled(Observable *publisher)
385{}
386
[2696b1]387void QtMoleculeList::checkForVisibilityChange(QStandardItem* _item)
[739ee9]388{
[2050b2]389// qDebug() << "Item changed called.";
[2696b1]390
[fcdf05]391 boost::recursive_mutex::scoped_lock lock(refill_mutex);
392 if (_item->index().column() == QtMoleculeItem::VISIBILITY) {
[2050b2]393// qDebug() << "visibilityItem changed: " << (_item->checkState() ? "checked" : "unchecked");
[fcdf05]394 boost::recursive_mutex::scoped_lock lock(listAccessing_mutex);
[2696b1]395 if ((_item->parent() == NULL) || (_item->parent() == invisibleRootItem()))
[fcdf05]396 visibilityGroupItems.insert( std::make_pair(
397 GroupItemToFormula(_item->parent()), QtMoleculeItem::VISIBILITY) );
[2696b1]398 else
[fcdf05]399 visibilityMolItems.insert(
400 static_cast<QtMoleculeItem *>(_item)->getMoleculeId()
401 );
[2696b1]402 }
403}
[3eb91c]404
[2696b1]405void QtMoleculeList::setVisibilityForMoleculeItem(QtMoleculeItem* _item)
406{
407 if (ChangingChildrensVisibility)
408 return;
[3eb91c]409
[fcdf05]410 boost::recursive_mutex::scoped_lock lock(refill_mutex);
[2696b1]411 const bool visible = _item->checkState();
[fcdf05]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,
[7d0ddb]424 "QtMoleculeList::setVisibilityForMoleculeItem() - molecule with formula " +molecule_formula
425 +" is not present in FormulaVisibilityCountMap.");
[3eb91c]426
[2696b1]427 // get parent
428 QStandardItem *groupItem = _item->parent();
[fcdf05]429 QStandardItem *visgroupItem = getSpecificGroupItem(groupItem, QtMoleculeItem::VISIBILITY);
[2696b1]430 ASSERT( groupItem != NULL,
431 "QtMoleculeList::setVisibilityForMoleculeItem() - item with id "
[7d0ddb]432 +toString(_item->getMoleculeId())+" has not parent?");
[2696b1]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;
[3eb91c]449
[2696b1]450 emit moleculesVisibilityChanged(_item->getMolecule()->getId(), visible);
451}
[3eb91c]452
[2696b1]453void QtMoleculeList::setVisibilityForGroupItem(QStandardItem* _item)
454{
455 if (ChangingChildrensVisibility)
456 return;
457
458 ChangingChildrensVisibility = true;
459
[fcdf05]460 boost::recursive_mutex::scoped_lock lock(refill_mutex);
[2696b1]461 // go through all children, but don't enter for groupItem once more
462 const bool visible = _item->checkState();
[fcdf05]463 QStandardItem *groupitem = getSpecificGroupItem(_item, QtMoleculeItem::NAME);
[2696b1]464 for (int i=0;i<groupitem->rowCount();++i) {
465 QtMoleculeItem *molItem = dynamic_cast<QtMoleculeItem *>(
[fcdf05]466 groupitem->child(i, QtMoleculeItem::VISIBILITY));
[2696b1]467 if (molItem->checkState() != visible) {
468 molItem->setCheckState(visible ? Qt::Checked : Qt::Unchecked);
469
470 // emit signal
471 emit moleculesVisibilityChanged(molItem->getMolecule()->getId(), visible);
[3eb91c]472 }
[2696b1]473 }
474 // set current number of visible children
475 const std::string molecule_formula =
[fcdf05]476 GroupItemToFormula( getSpecificGroupItem(_item, QtMoleculeItem::NAME) );
[2696b1]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;
[739ee9]485}
[2696b1]486
[739ee9]487
[0eb7bf3]488void QtMoleculeList::moleculeChanged() {
[79b59b]489 /*int idx = verticalHeaderItem(row)->data(Qt::UserRole).toInt();
[b47bfc]490 molecule *mol = molecules->ReturnIndex(idx);
[fcdf05]491 string cellValue = item(row,QtMoleculeItem::NAME)->text().toStdString();
[b47bfc]492 if(mol->getName() != cellValue && cellValue !="") {
493 mol->setName(cellValue);
494 }
495 else if(cellValue==""){
[fcdf05]496 item(row,QtMoleculeItem::NAME)->setText(QString(mol->getName().c_str()));
[79b59b]497 }*/
[b47bfc]498}
499
[b14efe]500
[53c1ff]501int QtMoleculeList::setOccurrence(QStandardItem * const _groupitem)
502{
[fcdf05]503 boost::recursive_mutex::scoped_lock lock(refill_mutex);
[53c1ff]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?");
[fcdf05]513 QStandardItem *occ_item = parent_item->child(index, QtMoleculeItem::OCCURRENCE);
[53c1ff]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
[fcdf05]520 boost::recursive_mutex::scoped_lock lock(map_mutex);
[53c1ff]521 const std::string molecule_formula = _groupitem->text().toStdString();
[fcdf05]522 FormulaItemBiMap.left.erase(molecule_formula);
[53c1ff]523 FormulaVisibilityCountMap.erase(molecule_formula);
524 return index;
525 } else {
526 occ_item->setText(QString::number(count));
527 return -1;
528 }
529}
530
[fcdf05]531std::string QtMoleculeList::readdItem(QtMoleculeItem *_molitem)
[53c1ff]532{
[fcdf05]533 boost::recursive_mutex::scoped_lock lock(refill_mutex);
[53c1ff]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?");
[fcdf05]539 const molecule * const mol = _molitem->getMolecule();
[53c1ff]540 QList<QStandardItem *> mol_row = _molitem->parent()->takeRow(_molitem->index().row());
541 // .. and re-add where new formula fits
[7d0ddb]542 std::string molecule_formula;
543 if (mol != NULL) {
544 molecule_formula = mol->getFormula().toString();
[fcdf05]545 if (!isGroupItemPresent(molecule_formula)) {
[7d0ddb]546 // add new group item and formula entry
547 addGroupItem(groupitem, molecule_formula);
548 } else {
[fcdf05]549 groupitem = FormulaToGroupItem(molecule_formula);
[7d0ddb]550 }
551 ASSERT( groupitem != NULL,
552 "QtMoleculeList::readdItem() - failed to create a sensible new groupitem");
553 // finally add again
554 groupitem->appendRow(mol_row);
[fcdf05]555 } else {
556 for (QList<QStandardItem *>::iterator iter = mol_row.begin();
557 iter != mol_row.end(); ++iter)
558 delete *iter;
[53c1ff]559 }
[fcdf05]560
561 return molecule_formula;
[53c1ff]562}
563
564void QtMoleculeList::informDirtyState(
[fcdf05]565 const moleculeId_t _id,
566 const QtMoleculeItem::COLUMNTYPES _type,
567 const QtMoleculeItem::MoveTypes _movetype)
[53c1ff]568{
[7d0ddb]569 listAccessing_mutex.lock();
[fcdf05]570 dirtyMolItems.insert( std::make_pair(_id, _type) );
[7d0ddb]571 listAccessing_mutex.unlock();
[95f49f]572
[fcdf05]573 if (_movetype == QtMoleculeItem::NeedsMove) {
[53c1ff]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
[7d0ddb]577 listAccessing_mutex.lock();
[fcdf05]578 toBeMovedItems.insert(_id);
[7d0ddb]579 listAccessing_mutex.unlock();
[53c1ff]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 ...
[7d0ddb]587 listAccessing_mutex.lock();
[fcdf05]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;
[53c1ff]601 toBeMovedItems.clear();
[7d0ddb]602 listAccessing_mutex.unlock();
[53c1ff]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
[fcdf05]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.
[d7cad1]616 {
[fcdf05]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 }
[d7cad1]638 }
[41815a3]639
[95f49f]640 // wait till initial refill has been executed
[fcdf05]641 boost::recursive_mutex::scoped_lock lock(refill_mutex);
[95f49f]642
[fcdf05]643// LOG(1, "Starting update.");
[95f49f]644
[fcdf05]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);
[2696b1]652 }
[8ccf3b]653
[2696b1]654 /// 1a. do the update for each dirty item
[fcdf05]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();
[53c1ff]665 }
666
[2696b1]667 /// 1b. do the visibility update for each dirty item
[fcdf05]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);
[2696b1]678 }
679
[53c1ff]680 /// 2. move all items that need to be moved
[fcdf05]681 typedef std::set<std::string> formulas_t;
682 formulas_t toBeSetOccurrence;
683 for (list_of_molecules_t::const_iterator moveiter = toBeMovedItems_copy.begin();
[53c1ff]684 moveiter != toBeMovedItems_copy.end(); ++moveiter) {
[fcdf05]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);
[53c1ff]723 }
[fcdf05]724 listAccessing_mutex.unlock();
725 // after that it is not a problem as items have been removed (hence signOff() was called)
[53c1ff]726
727 /// 3. remove all items whose molecules have been removed
[fcdf05]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 }
[53c1ff]740 }
741
742 /// 4. instantiate all new items
[fcdf05]743 for (std::vector<moleculeId_t>::const_iterator moliter = newMolecules_copy.begin();
744 moliter != newMolecules_copy.end(); ++moliter) {
745// LOG(1, "Adding molecule " << *moliter);
[53c1ff]746 // check that World knows the molecule still
[63fb7a]747 const molecule * const mol = const_cast<const World &>(World::getInstance()).
[fcdf05]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.");
[53c1ff]756 }
757 }
758
[2696b1]759 /// 5a. update the group item's occurrence and visibility
[53c1ff]760 std::set<int> RowsToRemove;
[fcdf05]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);
[53c1ff]768 RowsToRemove.insert(index);
[fcdf05]769 }
[53c1ff]770 }
[fcdf05]771 toBeSetOccurrence.clear();
[53c1ff]772
[2696b1]773 // remove all visibility updates whose row is removed
[fcdf05]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
[2696b1]781 ++visiter;
782 }
783
784 // update visibility of all group items
[fcdf05]785 for (list_of_group_items_t::iterator visiter = visibilityGroupItems_copy.begin();
786 visiter != visibilityGroupItems_copy.end(); ++visiter) {
[2050b2]787// LOG(1, "Updating visibility of item " << *visiter);
[fcdf05]788 QStandardItem * const groupitem =
789 getSpecificGroupItem(FormulaToGroupItem(visiter->first),
790 visiter->second);
791 setVisibilityForGroupItem(groupitem);
[2696b1]792 }
793
[53c1ff]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) {
[2050b2]797// LOG(1, "Removing group item at row " << *riter);
[53c1ff]798 removeRows(*riter, 1, invisibleRootItem()->index());
799 }
800
801 // and done
[fcdf05]802// LOG(1, "Done with update.");
[53c1ff]803}
Note: See TracBrowser for help on using the repository browser.