Ignore:
Timestamp:
Jan 28, 2015, 7:07:03 PM (10 years ago)
Author:
Frederik Heber <heber@…>
Branches:
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
Children:
d2dbb5d
Parents:
6d1e0a
git-author:
Frederik Heber <heber@…> (01/18/15 14:04:26)
git-committer:
Frederik Heber <heber@…> (01/28/15 19:07:03)
Message:

Modified QtMoleculeList to use QtMoleculeItemFactory.

  • setOccurrence() gives index of row back if it should be romoved.
  • i.e. moving a row and removing the row entirely does not mix. Updating it and then removing it is ill-spent time.
  • split off removing a group item from setting its occurrence.
  • emitDirtyState() only uses the first column item despite for the dirty items set. Otherwise we have multiple moves of the same row.
  • this is safer than removing the entry in MoleculeBiMap right away as thread in GUI and Action thread do not access in an orderly fashion.
  • using vector of molecule pointers and set operations to fulfil validity of updates.
Location:
src/UIElements/Views/Qt4/MoleculeList
Files:
6 edited

Legend:

Unmodified
Added
Removed
  • src/UIElements/Views/Qt4/MoleculeList/QtMoleculeItem.cpp

    r6d1e0a r53c1ff  
    4848
    4949QtMoleculeItem::QtMoleculeItem(
    50      const molecule *_mol,
     50     const molecule * const _mol,
    5151     const channellist_t &_channellist,
    5252     const enum MoveTypes _movetype,
     
    104104      signOffFromMolecule();
    105105      // prevent any remaining updates from accessing the molecule
    106       mol = NULL;
     106      //mol = NULL;
    107107      dirty = false;
    108108    } else {
     
    124124{
    125125  IsSignedOn = false;
    126 //  // we have to signal removal
    127 //  emit removeMolecule(this);
     126  dirty = false;
    128127}
  • src/UIElements/Views/Qt4/MoleculeList/QtMoleculeItem.hpp

    r6d1e0a r53c1ff  
    5252
    5353  QtMoleculeItem(
    54       const molecule *_mol,
     54      const molecule * const _mol,
    5555      const channellist_t &_channellist,
    5656      const enum MoveTypes _movetype,
     
    6262   */
    6363  void updateState();
     64
     65  /** Const getter to this item's molecule.
     66   *
     67   * \return const ref to \a mol
     68   */
     69  const molecule * const getMolecule() const
     70  { return mol; }
    6471
    6572private:
     
    7885
    7986  //!> molecule we are signed on to
    80   const molecule *mol;
     87  const molecule * const mol;
    8188
    8289private:
  • src/UIElements/Views/Qt4/MoleculeList/QtMoleculeItemFactory.cpp

    r6d1e0a r53c1ff  
    8585QList<QStandardItem *>
    8686QtMoleculeItemFactory::createMoleculeItems(
    87     const molecule *_mol,
     87    const molecule * const _mol,
    8888    const QtMoleculeItem::emitDirtyState_t &_emitDirtyState)
    8989{
     
    102102  QList<QStandardItem *> groupItems;
    103103  // fill item list
    104   QStandardItem *mainitem = new QStandardItem(QString(""));
     104  QStandardItem *mainitem = new QStandardItem(QString(_formula.c_str()));
    105105  mainitem->setFlags(mainitem->flags() ^ Qt::ItemIsSelectable);
    106106  groupItems << mainitem;
  • src/UIElements/Views/Qt4/MoleculeList/QtMoleculeItemFactory.hpp

    r6d1e0a r53c1ff  
    5151   */
    5252  QList<QStandardItem *> createMoleculeItems(
    53       const molecule *_mol,
     53      const molecule * const _mol,
    5454      const QtMoleculeItem::emitDirtyState_t &_emitDirtyState);
    5555
  • src/UIElements/Views/Qt4/MoleculeList/QtMoleculeList.cpp

    r6d1e0a r53c1ff  
    3535#include "QtMoleculeList.hpp"
    3636
    37 #include <QMetaMethod>
    38 
     37#include <QModelIndex>
     38
     39#include "UIElements/Views/Qt4/MoleculeList/QtMoleculeItem.hpp"
     40#include "UIElements/Views/Qt4/MoleculeList/QtMoleculeItemFactory.hpp"
     41
     42#include <boost/bind.hpp>
    3943#include <iostream>
    4044
    4145#include "CodePatterns/MemDebug.hpp"
    4246
     47#include "CodePatterns/Log.hpp"
    4348#include "CodePatterns/Observer/Notification.hpp"
    4449
     
    5257using namespace std;
    5358
    54 // maybe this should go with the definition of molecules
    55 
    56 // some attributes need to be easier to find for molecules
    57 // these attributes are skipped so far
    58 const int QtMoleculeList::COLUMNCOUNT = COLUMNTYPES_MAX;
    59 const char *QtMoleculeList::COLUMNNAMES[QtMoleculeList::COLUMNCOUNT]={"Name","Visibility", "Atoms","Formula","Occurrence"/*,"Size"*/};
     59const unsigned int QtMoleculeList::update_times_per_second = 20;
    6060
    6161QtMoleculeList::QtMoleculeList() :
    62   Observer("QtMoleculeList")
    63 {
    64   setColumnCount(COLUMNCOUNT);
    65 //  setSelectionMode(QAbstractItemView::MultiSelection);
     62  Observer("QtMoleculeList"),
     63  selecting(false),
     64  changing(false),
     65  ChangingChildrensVisibility(false),
     66  list_accessing(false),
     67  update_timer(NULL),
     68  callback_DirtyItems(boost::bind(&QtMoleculeList::informDirtyState, this, _1, _2))
     69{
     70  setColumnCount(QtMoleculeItemFactory::COLUMNCOUNT);
    6671
    6772  World::getInstance().signOn(this, World::MoleculeInserted);
    6873  World::getInstance().signOn(this, World::MoleculeRemoved);
    6974
    70   dirty = true;
    71   clearing = false;
    72   selecting = false;
    73   changing = false;
    74   ChangingChildrensVisibility = false;
    7575  refill();
    7676
     
    9191  if (role == Qt::DisplayRole) {
    9292    if (orientation == Qt::Horizontal) {
    93       if (section < COLUMNTYPES_MAX)
    94         return QString(COLUMNNAMES[section]);
     93      if (section < QtMoleculeItemFactory::COLUMNTYPES_MAX)
     94        return QString(QtMoleculeItemFactory::COLUMNNAMES[section]);
    9595    }
    9696  }
     
    103103}
    104104
    105 QStandardItem * QtMoleculeList::MoleculeToItem(const molecule * const _mol)
     105QtMoleculeItem * QtMoleculeList::MoleculeToItem(const molecule * const _mol) const
    106106{
    107107  MoleculeItemBiMap_t::left_const_iterator iter =
     
    112112}
    113113
     114const molecule * const QtMoleculeList::ItemToMolecule(const QtMoleculeItem * const _item) const
     115{
     116  const MoleculeItemBiMap_t::right_const_iterator iter =
     117      MoleculeItemBiMap.right.find(const_cast<QtMoleculeItem * const>(_item));
     118  ASSERT( iter != MoleculeItemBiMap.right.end(),
     119      "QtMoleculeList::IndexToMolecule() - index to unknown molecule given.");
     120  return iter->second;
     121}
     122
     123const molecule * const QtMoleculeList::IndexToMolecule(const QModelIndex &_index) const
     124{
     125  QtMoleculeItem * const item = dynamic_cast<QtMoleculeItem *>(itemFromIndex(_index));
     126  if (item == NULL)
     127    return NULL;
     128  else
     129    return ItemToMolecule(item);
     130}
     131
    114132void QtMoleculeList::recieveNotification(Observable *publisher, Notification_ptr notification)
    115133{
     
    119137      {
    120138        const molecule * const mol = World::getInstance().lastChanged<molecule>();
    121         addItem( mol );
     139        while(list_accessing);
     140        list_accessing = true;
     141        newItems.push_back( mol );
     142        list_accessing = false;
    122143        break;
    123144      }
     
    125146      {
    126147        const molecule * const mol = World::getInstance().lastChanged<molecule>();
    127         removeItem(  mol );
     148
     149        while(list_accessing);
     150        list_accessing = true;
     151        toBeRemovedItems.push_back( mol ); // remove in any case, as we also got insert
     152        list_accessing = false;
     153
     154        const QtMoleculeItem *mol_item = MoleculeToItem(mol);
     155        if (mol_item != NULL) {
     156          QStandardItem *parent_item = mol_item->parent();
     157          if (parent_item != NULL)
     158            addToBeSetOccurrence( parent_item );
     159          else
     160            ELOG(2, "QtMoleculeList::recieveNotification() - item to molecule "
     161                +toString(mol)+" has no parent.");
     162        }
    128163        break;
    129164      }
     
    134169    }
    135170  }
    136 
    137   if (selecting)
    138     return;
    139 
    140   dirty = true;
    141171}
    142172
     
    145175    const std::string &_molecule_formula)
    146176{
    147   QList<QStandardItem *> groupItems;
    148   // fill item list
    149   mainitem = new QStandardItem(QString("default"));
    150   mainitem->setFlags(mainitem->flags() ^ Qt::ItemIsSelectable);
     177  QList<QStandardItem *> groupItems =
     178      QtMoleculeItemFactory::getInstance().createGroupItems(_molecule_formula);
     179  mainitem = groupItems.front();
    151180  formula.insert( std::make_pair(_molecule_formula, mainitem) );
    152   groupItems << mainitem;
    153   QStandardItem *visitem = new QStandardItem;
    154   visitem->setCheckState(Qt::Unchecked);
    155   visitem->setFlags(mainitem->flags() | Qt::ItemIsUserCheckable);
    156   groupItems << visitem;
    157   groupItems << new QStandardItem(QString::number(0));
    158   groupItems << new QStandardItem(QString(""));
    159   groupItems << new QStandardItem(QString::number(0));
    160181  invisibleRootItem()->appendRow(groupItems);
    161 //  _groupItem->setData(0, Qt::UserRole, QVariant(-1));
     182}
     183
     184void QtMoleculeList::addToBeSetOccurrence(
     185    QStandardItem *_groupitem)
     186{
     187  while (list_accessing);
     188  list_accessing = true;
     189  toBeSetOccurrenceItems.insert( _groupitem );
     190  list_accessing = false;
    162191}
    163192
    164193void QtMoleculeList::addMoleculeItem(
    165194    QStandardItem *_groupitem,
    166     const molecule *_mol,
     195    const molecule * const _mol,
    167196    const std::string &_molecule_formula)
    168197{
    169   QList<QStandardItem *> molItems;
    170   QStandardItem *mainitem = new QStandardItem(QString(_mol->getName().c_str()));
    171   mainitem->setFlags(mainitem->flags() | Qt::ItemIsSelectable);
    172 //  mainitem->setSelected(World::getInstance().isSelected(_mol));
    173   MoleculeItemBiMap.left.insert( std::make_pair(_mol, mainitem) );
    174   molItems << mainitem;
    175   QStandardItem *visitem = new QStandardItem();
    176   visitem->setCheckState(Qt::Unchecked);
    177   visitem->setFlags(mainitem->flags() | Qt::ItemIsUserCheckable);
    178   molItems << visitem;
    179   molItems << new QStandardItem(QString::number(_mol->getAtomCount()));
    180   molItems << new QStandardItem(QString(_molecule_formula.c_str()));
    181   molItems << new QStandardItem(QString::number(0));
    182 //  const int index = _mol->getId();
    183 //  molItem->setData(0, Qt::UserRole, QVariant(index));
     198  QList<QStandardItem *> molItems =
     199      QtMoleculeItemFactory::getInstance().createMoleculeItems(_mol, callback_DirtyItems);
     200  QtMoleculeItem *mol_item = dynamic_cast<QtMoleculeItem *>(molItems.front());
     201  ASSERT( mol_item != NULL,
     202      "QtMoleculeList::addMoleculeItem() - item from factory was not a QtMoleculeItem?");
     203  MoleculeItemBiMap.left.insert( std::make_pair(_mol, mol_item) );
     204  LOG(1, "Inserting molecule " << _mol->getId() << ": " << _mol);
    184205  _groupitem->appendRow(molItems);
    185 }
    186 
    187 void QtMoleculeList::addItem(const molecule *_mol)
    188 {
    189   if (changing)
    190     return;
    191   changing = true;
     206
     207  // here update for the occurence will happen "one tick" later, but we don't
     208  // have the groupitem any time earlier
     209  addToBeSetOccurrence(_groupitem);
     210}
     211
     212void QtMoleculeList::addMolecule(const molecule * const _mol)
     213{
    192214  // find group if already in list
    193215  QStandardItem *groupItem = NULL;
     
    215237  }
    216238  ASSERT( groupItem != NULL,
    217       "QtMoleculeList::addItem() - item with id "+toString(_mol->getId())
     239      "QtMoleculeList::addMolecule() - item with id "+toString(_mol->getId())
    218240      +" has not parent?");
    219241
    220242  // add molecule
    221243  addMoleculeItem(groupItem, _mol, molecule_formula);
    222 
    223   // increase group occurrence
    224   const int index = groupItem->index().row();
    225   QStandardItem *occ_item = invisibleRootItem()->child(index, OCCURRENCE);
    226   int count = occ_item->text().toInt() + 1;
    227   occ_item->setText(QString::number(count));
    228 
    229   changing = false;
    230 }
    231 
    232 void QtMoleculeList::removeItem(const molecule *_mol)
    233 {
    234   if (changing)
    235     return;
     244}
     245
     246void QtMoleculeList::removeItem(QtMoleculeItem * const _item)
     247{
     248  const QModelIndex mol_index = indexFromItem(_item);
     249  QStandardItem *groupitem = _item->parent();
     250  const QModelIndex group_index = groupitem->index();
     251  removeRows(mol_index.row(), 1, group_index);
     252  MoleculeItemBiMap_t::right_iterator removeiter =
     253      MoleculeItemBiMap.right.find(_item);
     254  ASSERT( removeiter != MoleculeItemBiMap.right.end(),
     255      "QtMoleculeList::removeItem() - could not find item in BiMap.");
     256  LOG(1, "Erasing molecule " << (removeiter->second));
     257  MoleculeItemBiMap.right.erase(removeiter);
     258
     259  // don't need to, groupitem is already present in toBeSetOccurrenceItems
     260//  addToBeSetOccurrence(_groupitem);
     261}
     262
     263void QtMoleculeList::refill()
     264{
     265  // check timer's presence
     266  if (update_timer == NULL) {
     267    update_timer = new QTimer(this);
     268    connect( update_timer, SIGNAL(timeout()), this, SLOT(checkState()));
     269  } else
     270    update_timer->stop();
     271
    236272  changing = true;
    237273
    238   dirty = true;
    239   // TODO: We have to get some Model into the Table in order to "find" items right
    240   // away
    241 //  QTreeWidgetItem *molItem = itemFromIndex(mol->getId());
    242 //  delete molItem1;
    243 
    244   changing = false;
    245 }
    246 
    247 void QtMoleculeList::refill() {
    248   clearing = true;
    249274  const std::vector<molecule*> &molecules = World::getInstance().getAllMolecules();
    250275
     
    252277  formula.clear();
    253278  FormulaVisibilityCountMap.clear();
     279  LOG(1, "Clearing list.");
    254280  MoleculeItemBiMap.clear();
     281  dirtyItems.clear();
     282  toBeMovedItems.clear();
     283  newItems.clear();
     284  toBeRemovedItems.clear();
     285  toBeSetOccurrenceItems.clear();
    255286
    256287  for (std::vector<molecule*>::const_iterator iter = molecules.begin();
    257288      iter != molecules.end();
    258       iter++) {
    259 
    260     addItem(*iter);
    261   }
    262   dirty = false;
    263   clearing = false;
    264 }
    265 
    266 /*
    267 void QtMoleculeList::paintEvent(QPaintEvent * event)
    268 {
     289      iter++)
     290    addMolecule(*iter);
     291
     292  changing = false;
     293
     294  // activate timer
     295  update_timer->start(1000/update_times_per_second);
     296}
     297
     298bool QtMoleculeList::areAnyItemsDirty()
     299{
     300  // get whether any items are dirty
     301  while (list_accessing);
     302  list_accessing = true;
     303  bool dirty = false;
     304  dirty |= !dirtyItems.empty();
     305  dirty |= !newItems.empty();
     306  dirty |= !toBeRemovedItems.empty();
     307  dirty |= !toBeSetOccurrenceItems.empty();
     308  list_accessing = false;
     309  return dirty;
     310}
     311
     312void QtMoleculeList::checkState()
     313{
     314  const bool dirty = areAnyItemsDirty();
     315  // update if required
    269316  if (dirty)
    270     refill();
    271   QTreeWidget::paintEvent(event);
    272 }
    273 */
    274 
    275 void QtMoleculeList::subjectKilled(Observable *publisher) {
    276 }
     317    updateItemStates();
     318}
     319
     320void QtMoleculeList::subjectKilled(Observable *publisher)
     321{}
    277322
    278323/*
     
    280325{
    281326  if ((!changing) && (!clearing) && (!ChangingChildrensVisibility))
    282     if (column == VISIBILITY) {
     327    if (column == QtMoleculeItemFactory::VISIBILITY) {
    283328      const moleculeId_t molid = item->data(0, Qt::UserRole).toInt();
    284       const bool visible = item->checkState(VISIBILITY);
     329      const bool visible = item->checkState(QtMoleculeItemFactory::VISIBILITY);
    285330      if (molid != (unsigned int)-1) { // molecule item
    286331        World::MoleculeConstIterator moliter =
     
    308353          if (FormulaVisibilityCountMap[molecule_formula] ==
    309354              (unsigned int)(groupItem->text(OCCURRENCE).toInt()))
    310             groupItem->setCheckState(VISIBILITY, Qt::Checked);
     355            groupItem->setCheckState(QtMoleculeItemFactory::VISIBILITY, Qt::Checked);
    311356        } else {
    312357          --(FormulaVisibilityCountMap[molecule_formula]);
    313358          // none selected anymore?
    314359          if (FormulaVisibilityCountMap[molecule_formula] == 0)
    315             groupItem->setCheckState(VISIBILITY, Qt::Unchecked);
     360            groupItem->setCheckState(QtMoleculeItemFactory::VISIBILITY, Qt::Unchecked);
    316361        }
    317362        ChangingChildrensVisibility = false;
     
    329374              "QtMoleculeList::visibilityChanged() - to child with index"
    330375              +toString(i)+" there is no molecule?");
    331           molItem->setCheckState(VISIBILITY, visible ? Qt::Checked : Qt::Unchecked);
     376          molItem->setCheckState(QtMoleculeItemFactory::VISIBILITY, visible ? Qt::Checked : Qt::Unchecked);
    332377
    333378          // emit signal
     
    338383            item->text(FORMULA).toStdString();
    339384        FormulaVisibilityCountMap[molecule_formula] =
    340             visible ? item->text(OCCURRENCE).toInt() : 0;
     385            visible ? item->text(QtMoleculeItemFactory::OCCURRENCE).toInt() : 0;
    341386
    342387        ChangingChildrensVisibility = false;
     
    349394  /*int idx = verticalHeaderItem(row)->data(Qt::UserRole).toInt();
    350395  molecule *mol = molecules->ReturnIndex(idx);
    351   string cellValue = item(row,NAME)->text().toStdString();
     396  string cellValue = item(row,QtMoleculeItemFactory::NAME)->text().toStdString();
    352397  if(mol->getName() != cellValue && cellValue !="") {
    353398    mol->setName(cellValue);
    354399  }
    355400  else if(cellValue==""){
    356     item(row,NAME)->setText(QString(mol->getName().c_str()));
     401    item(row,QtMoleculeItemFactory::NAME)->setText(QString(mol->getName().c_str()));
    357402  }*/
    358403}
    359404
    360 /*
    361 void QtMoleculeList::rowsSelected(const QItemSelection & selected, const QItemSelection & deselected){
    362 
    363   if (clearing)
     405
     406int QtMoleculeList::setOccurrence(QStandardItem * const _groupitem)
     407{
     408  QModelIndex modelindex = _groupitem->index();
     409  ASSERT( modelindex.isValid(),
     410      "QtMoleculeList::setOccurrence() - groupitem not associated to model anymore.");
     411  const int index = modelindex.row();
     412  QStandardItem *parent_item =
     413      _groupitem->parent() == NULL ? invisibleRootItem() : _groupitem->parent();
     414  ASSERT( parent_item != NULL,
     415      "QtMoleculeList::setOccurrence() - group item at "+toString(index)
     416      +" does not have a parent?");
     417  QStandardItem *occ_item = parent_item->child(index, QtMoleculeItemFactory::OCCURRENCE);
     418  ASSERT( occ_item != NULL,
     419      "QtMoleculeList::setOccurrence() - group item at "+toString(index)
     420      +" does not have an occurrence?");
     421  const int count = _groupitem->rowCount();
     422  if (count == 0) {
     423    // we have to remove the group item completely
     424    const std::string molecule_formula = _groupitem->text().toStdString();
     425    formula.erase(molecule_formula);
     426    FormulaVisibilityCountMap.erase(molecule_formula);
     427    return index;
     428  } else {
     429    occ_item->setText(QString::number(count));
     430    return -1;
     431  }
     432}
     433
     434void QtMoleculeList::readdItem(QtMoleculeItem *_molitem)
     435{
     436  // use takeRows of molecule ..
     437  QStandardItem *groupitem = _molitem->parent();
     438  ASSERT( groupitem != NULL,
     439      "QtMoleculeList::readdItem() - mol item at "+toString(_molitem->index().row())
     440      +" does not have a groupitem?");
     441  QList<QStandardItem *> mol_row = _molitem->parent()->takeRow(_molitem->index().row());
     442  // call setOccurrence on the old group later
     443  addToBeSetOccurrence(groupitem);
     444  // ..  and re-add where new formula fits
     445  const std::string molecule_formula = _molitem->getMolecule()->getFormula().toString();
     446  FormulaTreeItemMap_t::iterator iter = formula.find(molecule_formula);
     447  if (iter == formula.end()) {
     448    // add new group item and formula entry
     449     addGroupItem(groupitem, molecule_formula);
     450  } else {
     451    groupitem = iter->second;
     452  }
     453  ASSERT( groupitem != NULL,
     454      "QtMoleculeList::readdItem() - failed to create a sensible new groupitem");
     455  // finally add again
     456  groupitem->appendRow(mol_row);
     457  // call setOccurrence on the new group later
     458  addToBeSetOccurrence(groupitem);
     459}
     460
     461void QtMoleculeList::informDirtyState(
     462    QtMoleculeItem *_item,
     463    const QtMoleculeItem::MoveTypes _type)
     464{
     465  while (list_accessing);
     466  list_accessing = true;
     467
     468  dirtyItems.insert(_item);
     469  if (_type == QtMoleculeItem::NeedsMove) {
     470    // we have to convert whatever item raised the dirty signal to the first
     471    // item in the row as otherwise multiple items in the row are selected
     472    // as to be moved, i.e. the same row is moved multiple times
     473    QStandardItem *group_item = _item->parent();
     474    QtMoleculeItem *mol_item =
     475        dynamic_cast<QtMoleculeItem *>(group_item->child(_item->row(), 0));
     476    toBeMovedItems.insert(mol_item);
     477//    // add group item, too
     478//    toBeSetOccurrenceItems.insert(group_item);
     479  }
     480
     481  list_accessing = false;
     482}
     483
     484void QtMoleculeList::updateItemStates()
     485{
     486  // wait till initial refill has been executed
     487  if (changing)
    364488    return;
    365   if (selecting)
    366     return;
    367   selecting = true;
    368 
    369   // Select all molecules which belong to newly selected rows.
    370   QModelIndex index;
     489
     490  changing = true;
     491
     492  /// copy lists such that new signals for dirty/.. may come in right away
     493  // TODO: if we had move semantics ...
     494  while (list_accessing);
     495  list_accessing = true;
     496  list_of_items_t dirtyItems_copy = dirtyItems;
     497  dirtyItems.clear();
     498  list_of_items_t toBeMovedItems_copy = toBeMovedItems;
     499  toBeMovedItems.clear();
     500  std::vector<const molecule *> newItems_copy = newItems;
     501  newItems.clear();
     502  std::vector<const molecule *> toBeRemovedItems_copy = toBeRemovedItems;
     503  toBeRemovedItems.clear();
     504  std::set<QStandardItem*> toBeSetOccurrenceItems_copy = toBeSetOccurrenceItems;
     505  toBeSetOccurrenceItems.clear();
     506  list_accessing = false;
     507
     508  /// first check consistency among the sets:
     509  /// -# if we remove an item, we don't have to update it before anymore
     510  /// -# if we remove an item, we don't have to move it before anymore
     511  /// -# if we remove an item, we don't have to change its visibility
     512  /// -# don't add molecule that are also removed
     513
     514  //  // remove molecules added and removed immediately in both lists
     515  std::vector<const molecule *> addedremoved;
     516  std::sort(newItems_copy.begin(), newItems_copy.end());
     517  std::sort(toBeRemovedItems_copy.begin(), toBeRemovedItems_copy.end());
     518  std::set_intersection(
     519      newItems_copy.begin(), newItems_copy.end(),
     520      toBeRemovedItems_copy.begin(), toBeRemovedItems_copy.end(),
     521      std::back_inserter(addedremoved));
    371522  {
    372     QModelIndexList items = selected.indexes();
    373     molids_t ids;
    374     ids.reserve(items.size());
    375     foreach (index, items)
    376       if (index.column() == 0){
    377         int mol_id = model()->data(index, Qt::UserRole).toInt();
    378         if (mol_id < 0)
    379           continue;
    380         ids.push_back(mol_id);
    381         //std::cout << "select molecule" << std::endl;
    382       }
    383     MoleCuilder::SelectionMoleculeById(ids);
    384   }
    385 
    386   // Unselect all molecules which belong to newly unselected rows.
     523    std::vector<const molecule *>::iterator removeiter = std::set_difference(
     524        newItems_copy.begin(), newItems_copy.end(),
     525        addedremoved.begin(), addedremoved.end(),
     526        newItems_copy.begin());
     527    newItems_copy.erase(removeiter, newItems_copy.end());
     528  }
    387529  {
    388     QModelIndexList items = deselected.indexes();
    389     molids_t ids;
    390     ids.reserve(items.size());
    391     foreach (index, items)
    392       if (index.column() == 0){
    393         int mol_id = model()->data(index, Qt::UserRole).toInt();
    394         if (mol_id < 0)
    395           continue;
    396         //std::cout << "unselect molecule" << std::endl;
    397         ids.push_back(mol_id);
    398       }
    399     MoleCuilder::SelectionNotMoleculeById(ids);
    400   }
    401 
    402   selecting = false;
    403 }
    404 
    405 */
     530    std::vector<const molecule *>::iterator removeiter = std::set_difference(
     531        toBeRemovedItems_copy.begin(), toBeRemovedItems_copy.end(),
     532        addedremoved.begin(), addedremoved.end(),
     533        toBeRemovedItems_copy.begin());
     534    toBeRemovedItems_copy.erase(removeiter, toBeRemovedItems_copy.end());
     535  }
     536  addedremoved.clear();
     537
     538  for (std::vector<const molecule *>::iterator removeiter = toBeRemovedItems_copy.begin();
     539      removeiter != toBeRemovedItems_copy.end(); ++removeiter) {
     540    QtMoleculeItem *item = MoleculeToItem(*removeiter);
     541    dirtyItems_copy.erase(item);
     542    toBeMovedItems_copy.erase(item);
     543  }
     544
     545  /// 1. do the update for each dirty item
     546  for (list_of_items_t::const_iterator dirtyiter = dirtyItems_copy.begin();
     547      dirtyiter != dirtyItems_copy.end(); ++dirtyiter) {
     548    LOG(1, "Updating item " << *dirtyiter);
     549    (*dirtyiter)->updateState();
     550  }
     551
     552  /// 2. move all items that need to be moved
     553  for (list_of_items_t::const_iterator moveiter = toBeMovedItems_copy.begin();
     554      moveiter != toBeMovedItems_copy.end(); ++moveiter) {
     555    LOG(1, "Moving item " << *moveiter);
     556    readdItem(*moveiter);
     557  }
     558
     559  /// 3. remove all items whose molecules have been removed
     560  for (std::vector<const molecule *>::const_iterator removeiter = toBeRemovedItems_copy.begin();
     561      removeiter != toBeRemovedItems_copy.end(); ++removeiter) {
     562    LOG(1, "Removing molecule " << *removeiter); // cannot access directly, molecule is gone
     563    QtMoleculeItem *item = MoleculeToItem(*removeiter);
     564    if (item != NULL)
     565      removeItem(item);
     566  }
     567
     568  /// 4. instantiate all new items
     569  for (std::vector<const molecule *>::const_iterator moliter = newItems_copy.begin();
     570      moliter != newItems_copy.end(); ++moliter) {
     571    LOG(1, "Adding molecule " << (*moliter)->getName());
     572    // check that World knows the molecule still
     573    const molecule * const mol =
     574        World::getInstance().getMolecule(MoleculeById((*moliter)->getId()));
     575    if ((mol != NULL) && (mol == *moliter)) {
     576      addMolecule(mol);
     577    }
     578  }
     579
     580  /// 5a. update the group item's occurrence
     581  std::set<int> RowsToRemove;
     582  for (std::set<QStandardItem*>::const_iterator groupiter = toBeSetOccurrenceItems_copy.begin();
     583      groupiter != toBeSetOccurrenceItems_copy.end(); ++groupiter) {
     584    LOG(1, "Updating group item " << *groupiter);
     585    const int index = setOccurrence(*groupiter);
     586    if (index != -1)
     587      RowsToRemove.insert(index);
     588  }
     589
     590  /// 5b. remove all rows with 0 occurrence starting from last
     591  for (std::set<int>::reverse_iterator riter = RowsToRemove.rbegin();
     592      riter != RowsToRemove.rend(); ++riter) {
     593    LOG(1, "Removing group item at row " << *riter);
     594    removeRows(*riter, 1, invisibleRootItem()->index());
     595  }
     596
     597  // and done
     598  changing = false;
     599}
  • src/UIElements/Views/Qt4/MoleculeList/QtMoleculeList.hpp

    r6d1e0a r53c1ff  
    1414#endif
    1515
     16#include <QtGui/QItemSelection>
    1617#include <QtGui/QStandardItem>
    1718#include <QtGui/QStandardItemModel>
     19#include <QTimer>
    1820
    1921#include <boost/bimap.hpp>
    2022#include <map>
     23#include <set>
    2124#include <string>
    2225
    2326#include "CodePatterns/Observer/Observer.hpp"
     27
     28#include "UIElements/Views/Qt4/MoleculeList/QtMoleculeItem.hpp"
    2429
    2530#include "types.hpp"
     
    2732class molecule;
    2833class MoleculeListClass;
     34class QtMoleculeItem;
    2935class QtMoleculeListView;
    3036
     
    4147  virtual void recieveNotification(Observable *publisher, Notification_ptr notification);
    4248  virtual void subjectKilled(Observable *publisher);
    43 //  virtual void paintEvent(QPaintEvent * event);
     49
    4450  void refill();
    45 
    46   static const int COLUMNCOUNT;
    47   enum {NAME,VISIBILITY,ATOMCOUNT,FORMULA,OCCURRENCE,COLUMNTYPES_MAX} COLUMNTYPES;
    48   static const char *COLUMNNAMES[];
    4951
    5052  QVariant headerData(int section, Qt::Orientation orientation, int role) const;
     
    5355  void moleculeChanged();
    5456//  void visibilityChanged(QStandardItem*, int);
     57  void checkState();
     58
     59  friend class QtMoleculeItem;
    5560
    5661//  void rowsSelected(const QItemSelection & selected, const QItemSelection & deselected);
    57 
     62  void readdItem(QtMoleculeItem *_molitem);
    5863
    5964signals:
     
    6368
    6469private:
    65   bool dirty;
    66   bool clearing;
     70
    6771  bool selecting;
    6872  bool changing;
    6973  bool ChangingChildrensVisibility;
     74  bool list_accessing;
     75
     76  //!> informs the view in regular intervals about updates
     77  QTimer *update_timer;
     78
     79  //!> how often per second update is signalled to view
     80  static const unsigned int update_times_per_second;
    7081
    7182  friend class QtMoleculeListView;
    72   QStandardItem * MoleculeToItem(const molecule * const _mol);
    7383
    74   void addItem(const molecule * const _mol);
     84  QtMoleculeItem * MoleculeToItem(const molecule * const _mol) const;
     85  const molecule * const IndexToMolecule(const QModelIndex &_index) const;
     86  const molecule * const ItemToMolecule(const QtMoleculeItem * const _item) const;
     87
     88  void addMolecule(const molecule * const _mol);
    7589  void addGroupItem(QStandardItem *&mainitem, const std::string &_molecule_formula);
    76   void addMoleculeItem(QStandardItem *_groupitem, const molecule *_mol, const std::string &molecule_formula);
    77   void removeItem(const molecule * const _mol);
     90  void addMoleculeItem(QStandardItem *_groupitem, const molecule * const _mol, const std::string &molecule_formula);
     91  void removeItem(QtMoleculeItem * const _item);
     92  int setOccurrence(QStandardItem * const _groupitem);
     93  bool areAnyItemsDirty();
     94  void addToBeSetOccurrence(QStandardItem *_groupitem);
     95
     96  void informDirtyState(QtMoleculeItem *_item, const QtMoleculeItem::MoveTypes _type);
     97
     98  void updateItemStates();
    7899
    79100  typedef std::map<std::string, unsigned int> FormulaVisibilityCountMap_t;
     
    84105  FormulaTreeItemMap_t formula;
    85106
    86   typedef boost::bimap<const molecule *, QStandardItem*> MoleculeItemBiMap_t;
     107  typedef boost::bimap<const molecule *, QtMoleculeItem*> MoleculeItemBiMap_t;
    87108  MoleculeItemBiMap_t MoleculeItemBiMap;
     109
     110  //!> callback function to hand over to items that inform about requiring update
     111  const QtMoleculeItem::emitDirtyState_t callback_DirtyItems;
     112
     113  typedef std::set<QtMoleculeItem*> list_of_items_t;
     114  //!> list of items that need an update
     115  list_of_items_t dirtyItems;
     116  //!> list of items to molecule's whose formulas has changed and need to be moved
     117  list_of_items_t toBeMovedItems;
     118  //!> list of items to new molecules which need to be added
     119  std::vector<const molecule *> newItems;
     120  //!> list of items to molecules that have been removed
     121  std::vector<const molecule *> toBeRemovedItems;
     122  //!> list of group items that need update due to moved molecule items
     123  std::set<QStandardItem*> toBeSetOccurrenceItems;
    88124};
    89125
Note: See TracChangeset for help on using the changeset viewer.