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

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 b9680b was 54bdaa, checked in by Frederik Heber <heber@…>, 10 years ago

Qt4 instance use new lastChanged..Id() in place of lastChanged().

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