diff --git a/avogadro/qtgui/rwmolecule.cpp b/avogadro/qtgui/rwmolecule.cpp index 42a73bc183..62c240f26e 100644 --- a/avogadro/qtgui/rwmolecule.cpp +++ b/avogadro/qtgui/rwmolecule.cpp @@ -182,10 +182,13 @@ bool RWMolecule::setAtomPosition3d(Index atomId, const Vector3& pos, return true; } -void RWMolecule::setAtomSelected(Index atomId, bool selected) +void RWMolecule::setAtomSelected(Index atomId, bool selected, const QString& undoText) { - // FIXME: Add in an implementation (and use it from the selection tool). - m_molecule.setAtomSelected(atomId, selected); + auto* comm = new ModifySelectionCommand(*this, atomId, selected); + comm->setText(undoText); + comm->setCanMerge(true); + m_undoStack.push(comm); +// m_molecule.setAtomSelected(atomId, selected); } bool RWMolecule::atomSelected(Index atomId) const diff --git a/avogadro/qtgui/rwmolecule.h b/avogadro/qtgui/rwmolecule.h index 82da454fe3..4911652d6f 100644 --- a/avogadro/qtgui/rwmolecule.h +++ b/avogadro/qtgui/rwmolecule.h @@ -203,9 +203,6 @@ class AVOGADROQTGUI_EXPORT RWMolecule : public QObject */ Vector3 atomPosition3d(Index atomId) const; - std::string label(Index atomId) const; - bool setLabel(Index atomId, const std::string& label, - const QString& undoText = QStringLiteral("Change Atom Label")); /** * Replace the current array of 3D atomic coordinates. * @param pos The new coordinate array. Must be of length atomCount(). @@ -214,7 +211,7 @@ class AVOGADROQTGUI_EXPORT RWMolecule : public QObject */ bool setAtomPositions3d( const Core::Array& pos, - const QString& undoText = QStringLiteral("Change Atom Positions")); + const QString& undoText = tr("Change Atom Positions")); /** * Set the 3D position of a single atom. @@ -223,14 +220,18 @@ class AVOGADROQTGUI_EXPORT RWMolecule : public QObject * @param undoText The undo text to be displayed for undo commands. * @return True on success, false otherwise. */ - bool setAtomPosition3d( - Index atomId, const Vector3& pos, - const QString& undoText = QStringLiteral("Change Atom Position")); + bool setAtomPosition3d(Index atomId, const Vector3& pos, + const QString& undoText = tr("Change Atom Position")); + + std::string label(Index atomId) const; + bool setLabel(Index atomId, const std::string& label, + const QString& undoText = tr("Change Atom Label")); /** * Set whether the specified atom is selected or not. */ - void setAtomSelected(Index atomId, bool selected); + void setAtomSelected(Index atomId, bool selected, + const QString& undoText = tr("Change Selection")); /** * Query whether the supplied atom index has been selected. @@ -834,9 +835,8 @@ inline Core::Array RWMolecule::bonds( auto atomBonds = m_molecule.bonds(atomId); Core::Array result; for (Index i = 0; i < atomBonds.size(); ++i) { - result.push_back(BondType( - const_cast(this), atomBonds[i].index() - )); + result.push_back( + BondType(const_cast(this), atomBonds[i].index())); } return result; } diff --git a/avogadro/qtgui/rwmolecule_undo.h b/avogadro/qtgui/rwmolecule_undo.h index 2076806671..f6c1ca1cd6 100644 --- a/avogadro/qtgui/rwmolecule_undo.h +++ b/avogadro/qtgui/rwmolecule_undo.h @@ -6,6 +6,7 @@ #define AVOGADRO_QTGUI_RWMOLECULE_UNDO_H #include "rwmolecule.h" +#include #include #include @@ -28,7 +29,8 @@ class RWMolecule::UndoCommand : public QUndoCommand public: UndoCommand(RWMolecule& m) : QUndoCommand(tr("Modify Molecule")), m_mol(m), m_molecule(m.m_molecule) - {} + { + } protected: Array& positions3d() { return m_molecule.atomPositions3d(); } @@ -45,7 +47,9 @@ enum MergeIds SetPositions3dMergeId = 0, SetPosition3dMergeId, SetForceVectorMergeId, - SetBondOrderMergeId + SetBondOrderMergeId, + ModifySelectionMergeId, + ModifyColorsMergeId }; // Base class for undo commands that can be merged together, overriding the @@ -120,7 +124,8 @@ class RemoveAtomCommand : public RWMolecule::UndoCommand const Vector3& pos) : UndoCommand(m), m_atomId(atomId), m_atomUid(uid), m_atomicNumber(aN), m_position3d(pos) - {} + { + } void redo() override { @@ -156,7 +161,8 @@ class SetAtomicNumbersCommand : public RWMolecule::UndoCommand const Core::Array& newAtomicNumbers) : UndoCommand(m), m_oldAtomicNumbers(oldAtomicNumbers), m_newAtomicNumbers(newAtomicNumbers) - {} + { + } void redo() override { m_molecule.setAtomicNumbers(m_newAtomicNumbers); } @@ -177,7 +183,8 @@ class SetAtomicNumberCommand : public RWMolecule::UndoCommand unsigned char newAtomicNumber) : UndoCommand(m), m_atomId(atomId), m_oldAtomicNumber(oldAtomicNumber), m_newAtomicNumber(newAtomicNumber) - {} + { + } void redo() override { @@ -203,7 +210,8 @@ class SetPositions3dCommand : public MergeUndoCommand const Core::Array& newPositions3d) : MergeUndoCommand(m), m_oldPositions3d(oldPositions3d), m_newPositions3d(newPositions3d) - {} + { + } void redo() override { positions3d() = m_newPositions3d; } @@ -235,7 +243,8 @@ class SetPosition3dCommand : public MergeUndoCommand const Vector3& newPosition3d) : MergeUndoCommand(m), m_atomIds(1, atomId), m_oldPosition3ds(1, oldPosition3d), m_newPosition3ds(1, newPosition3d) - {} + { + } void redo() override { @@ -302,7 +311,8 @@ class SetAtomHybridizationCommand : public RWMolecule::UndoCommand AtomHybridization newHybridization) : UndoCommand(m), m_atomId(atomId), m_oldHybridization(oldHybridization), m_newHybridization(newHybridization) - {} + { + } void redo() override { @@ -328,7 +338,8 @@ class SetAtomFormalChargeCommand : public RWMolecule::UndoCommand signed char newCharge) : UndoCommand(m), m_atomId(atomId), m_oldCharge(oldCharge), m_newCharge(newCharge) - {} + { + } void redo() override { m_molecule.setFormalCharge(m_atomId, m_newCharge); } @@ -348,7 +359,8 @@ class SetAtomColorCommand : public RWMolecule::UndoCommand Vector3ub newColor) : UndoCommand(m), m_atomId(atomId), m_oldColor(oldColor), m_newColor(newColor) - {} + { + } void redo() override { m_molecule.setColor(m_atomId, m_newColor); } @@ -365,7 +377,8 @@ class SetLayerCommand : public RWMolecule::UndoCommand SetLayerCommand(RWMolecule& m, Index atomId, size_t oldLayer, size_t newLayer) : UndoCommand(m), m_atomId(atomId), m_oldLayer(oldLayer), m_newLayer(newLayer) - {} + { + } void redo() override { m_molecule.setLayer(m_atomId, m_newLayer); } @@ -385,7 +398,8 @@ class AddBondCommand : public RWMolecule::UndoCommand Index uid) : UndoCommand(m), m_bondOrder(order), m_bondPair(bondPair), m_bondId(bondId), m_bondUid(uid) - {} + { + } void redo() override { @@ -415,13 +429,15 @@ class RemoveBondCommand : public RWMolecule::UndoCommand unsigned char bondOrder) : UndoCommand(m), m_bondId(bondId), m_bondUid(bondUid), m_bondPair(bondPair), m_bondOrder(bondOrder) - {} + { + } void redo() override { m_molecule.removeBond(m_bondId); } void undo() override { - m_molecule.addBond(m_bondPair.first, m_bondPair.second, m_bondOrder, m_bondUid); + m_molecule.addBond(m_bondPair.first, m_bondPair.second, m_bondOrder, + m_bondUid); Index movedId = m_molecule.bondCount() - 1; m_molecule.swapBond(m_bondId, movedId); } @@ -439,7 +455,8 @@ class SetBondOrdersCommand : public RWMolecule::UndoCommand const Array& newBondOrders) : UndoCommand(m), m_oldBondOrders(oldBondOrders), m_newBondOrders(newBondOrders) - {} + { + } void redo() override { m_molecule.setBondOrders(m_newBondOrders); } @@ -459,7 +476,8 @@ class SetBondOrderCommand : public MergeUndoCommand unsigned char newBondOrder) : MergeUndoCommand(m), m_bondId(bondId), m_oldBondOrder(oldBondOrder), m_newBondOrder(newBondOrder) - {} + { + } void redo() override { m_molecule.setBondOrder(m_bondId, m_newBondOrder); } @@ -490,7 +508,8 @@ class SetBondPairsCommand : public RWMolecule::UndoCommand const Array>& oldBondPairs, const Array>& newBondPairs) : UndoCommand(m), m_oldBondPairs(oldBondPairs), m_newBondPairs(newBondPairs) - {} + { + } void redo() override { m_molecule.setBondPairs(m_newBondPairs); } @@ -511,7 +530,8 @@ class SetBondPairCommand : public RWMolecule::UndoCommand const std::pair& newBondPair) : UndoCommand(m), m_bondId(bondId), m_oldBondPair(oldBondPair), m_newBondPair(newBondPair) - {} + { + } void redo() override { m_molecule.setBondPair(m_bondId, m_newBondPair); } @@ -527,7 +547,8 @@ class AddUnitCellCommand : public RWMolecule::UndoCommand public: AddUnitCellCommand(RWMolecule& m, const UnitCell& newUnitCell) : UndoCommand(m), m_newUnitCell(newUnitCell) - {} + { + } void redo() override { @@ -546,7 +567,8 @@ class RemoveUnitCellCommand : public RWMolecule::UndoCommand public: RemoveUnitCellCommand(RWMolecule& m, const UnitCell& oldUnitCell) : UndoCommand(m), m_oldUnitCell(oldUnitCell) - {} + { + } void redo() override { m_mol.molecule().setUnitCell(nullptr); } @@ -567,7 +589,8 @@ class ModifyMoleculeCommand : public RWMolecule::UndoCommand ModifyMoleculeCommand(RWMolecule& m, const Molecule& oldMolecule, const Molecule& newMolecule) : UndoCommand(m), m_oldMolecule(oldMolecule), m_newMolecule(newMolecule) - {} + { + } void redo() override { m_mol.molecule() = m_newMolecule; } @@ -588,7 +611,8 @@ class SetForceVectorCommand : public MergeUndoCommand const Vector3& newForceVector) : MergeUndoCommand(m), m_atomIds(1, atomId), m_oldForceVectors(1, oldForceVector), m_newForceVectors(1, newForceVector) - {} + { + } void redo() override { @@ -662,6 +686,124 @@ class ModifyLabelCommand : public RWMolecule::UndoCommand }; } // namespace +namespace { +class ModifySelectionCommand : public MergeUndoCommand +{ + std::vector m_newSelectedAtoms; + std::vector m_oldSelectedAtoms; + +public: + ModifySelectionCommand(RWMolecule& m, Index atomId, bool selected) + : MergeUndoCommand(m) + { + Index atomCount = m_mol.molecule().atomCount(); + m_oldSelectedAtoms.resize(atomCount); + m_newSelectedAtoms.resize(atomCount); + + for (Index i = 0; i < atomCount; ++i) { + m_oldSelectedAtoms[i] = m_molecule.atomSelected(i); + m_newSelectedAtoms[i] = m_molecule.atomSelected(i); + } + + m_newSelectedAtoms[atomId] = selected; + } + + void redo() override + { + Index atomCount = m_mol.molecule().atomCount(); + for (Index i = 0; i < atomCount; ++i) + m_mol.molecule().setAtomSelected(i, m_newSelectedAtoms[i]); + } + + void undo() override + { + Index atomCount = m_mol.molecule().atomCount(); + for (Index i = 0; i < atomCount; ++i) + m_mol.molecule().setAtomSelected(i, m_oldSelectedAtoms[i]); + } + + bool mergeWith(const QUndoCommand* other) override + { + const ModifySelectionCommand* o = + dynamic_cast(other); + if (!o) + return false; + + // check if the atom count matches + Index numAtoms = m_oldSelectedAtoms.size(); + + if (numAtoms != o->m_oldSelectedAtoms.size() || + numAtoms != o->m_newSelectedAtoms.size()) + return false; + + // merge these, by grabbing the new selected atoms + m_newSelectedAtoms = o->m_newSelectedAtoms; + return true; + } +}; +} // namespace + +/* +namespace { +class ModifyColorCommand : public MergeUndoCommand +{ + Array m_newSelectedAtoms; + Array m_oldSelectedAtoms; + +public: + ModifySelectionCommand(RWMolecule& m, Index atomId, bool selected) + : MergeUndoCommand(m) + { + Index atomCount = m_mol.molecule().atomCount(); + m_oldSelectedAtoms.reserve(atomCount); + m_newSelectedAtoms.reserve(atomCount); + + for (Index i = 0; i < atomCount; ++i) { + m_oldSelectedAtoms[i] = m_molecule.atomSelected(i); + m_newSelectedAtoms[i] = m_molecule.atomSelected(i); + } + + m_newSelectedAtoms[atomId] = selected; + } + + void redo() override + { + Index atomCount = m_mol.molecule().atomCount(); + for (Index i = 0; i < atomCount; ++i) + m_mol.molecule().setAtomSelected(i, m_newSelectedAtoms[i]); + } + + void undo() override + { + Index atomCount = m_mol.molecule().atomCount(); + for (Index i = 0; i < atomCount; ++i) + m_mol.molecule().setAtomSelected(i, m_oldSelectedAtoms[i]); + } + + bool mergeWith(const QUndoCommand* other) override + { + const ModifySelectionCommand* o = + dynamic_cast(other); + if (o) { + // check if the atom count matches + Index numAtoms = m_oldSelectedAtoms.size(); + if (numAtoms != o->m_oldSelectedAtoms.size() || + numAtoms != o->m_newSelectedAtoms.size()) { + return false; + } + + // merge these, by grabbing the new selected atoms + for (Index i = 0; i < numAtoms; ++i) + m_newSelectedAtoms[i] = o->m_newSelectedAtoms[i]; + + return true; + } + return false; + } +}; +} // namespace +*/ + } // namespace QtGui } // namespace Avogadro #endif diff --git a/avogadro/qtplugins/propertytables/propertyview.cpp b/avogadro/qtplugins/propertytables/propertyview.cpp index a1ea07af52..88900dab54 100644 --- a/avogadro/qtplugins/propertytables/propertyview.cpp +++ b/avogadro/qtplugins/propertytables/propertyview.cpp @@ -78,7 +78,7 @@ void PropertyView::selectionChanged(const QItemSelection& selected, // Start by clearing the molecule selection for (Index i = 0; i < m_molecule->atomCount(); ++i) - m_molecule->atom(i).setSelected(false); + m_molecule->undoMolecule()->setAtomSelected(i, false); foreach (const QModelIndex& index, selected.indexes()) { if (!index.isValid()) @@ -106,24 +106,24 @@ void PropertyView::selectionChanged(const QItemSelection& selected, return; auto bondPair = m_molecule->bondPair(rowNum); - m_molecule->setAtomSelected(bondPair.first, true); - m_molecule->setAtomSelected(bondPair.second, true); + m_molecule->undoMolecule()->setAtomSelected(bondPair.first, true); + m_molecule->undoMolecule()->setAtomSelected(bondPair.second, true); } else if (m_type == PropertyType::AngleType) { if (m_model != nullptr) { auto angle = m_model->getAngle(index.row()); - m_molecule->setAtomSelected(std::get<0>(angle), true); - m_molecule->setAtomSelected(std::get<1>(angle), true); - m_molecule->setAtomSelected(std::get<2>(angle), true); + m_molecule->undoMolecule()->setAtomSelected(std::get<0>(angle), true); + m_molecule->undoMolecule()->setAtomSelected(std::get<1>(angle), true); + m_molecule->undoMolecule()->setAtomSelected(std::get<2>(angle), true); } } else if (m_type == PropertyType::TorsionType) { if (m_model != nullptr) { auto torsion = m_model->getTorsion(index.row()); - m_molecule->setAtomSelected(std::get<0>(torsion), true); - m_molecule->setAtomSelected(std::get<1>(torsion), true); - m_molecule->setAtomSelected(std::get<2>(torsion), true); - m_molecule->setAtomSelected(std::get<3>(torsion), true); + m_molecule->undoMolecule()->setAtomSelected(std::get<0>(torsion), true); + m_molecule->undoMolecule()->setAtomSelected(std::get<1>(torsion), true); + m_molecule->undoMolecule()->setAtomSelected(std::get<2>(torsion), true); + m_molecule->undoMolecule()->setAtomSelected(std::get<3>(torsion), true); } } } // end loop through selected diff --git a/avogadro/qtplugins/select/select.cpp b/avogadro/qtplugins/select/select.cpp index fa1b7115f6..e65119dcdd 100644 --- a/avogadro/qtplugins/select/select.cpp +++ b/avogadro/qtplugins/select/select.cpp @@ -141,7 +141,7 @@ void Select::selectAll() { if (m_molecule) { for (Index i = 0; i < m_molecule->atomCount(); ++i) { - m_molecule->atom(i).setSelected(evalSelect(true, i)); + m_molecule->undoMolecule()->setAtomSelected(i, evalSelect(true, i)); } m_molecule->emitChanged(Molecule::Atoms); @@ -152,7 +152,7 @@ void Select::selectNone() { if (m_molecule) { for (Index i = 0; i < m_molecule->atomCount(); ++i) - m_molecule->atom(i).setSelected(false); + m_molecule->undoMolecule()->setAtomSelected(i, false); m_molecule->emitChanged(Molecule::Atoms); } @@ -177,11 +177,13 @@ void Select::selectElement(int element) if (!m_molecule) return; + QString undoText = tr("Select Element"); + for (Index i = 0; i < m_molecule->atomCount(); ++i) { if (m_molecule->atomicNumber(i) == element) { - m_molecule->atom(i).setSelected(evalSelect(true, i)); + m_molecule->undoMolecule()->setAtomSelected(i, evalSelect(true, i), undoText); } else - m_molecule->atom(i).setSelected(false); + m_molecule->undoMolecule()->setAtomSelected(i, false, undoText); } m_molecule->emitChanged(Molecule::Atoms); @@ -211,29 +213,32 @@ void Select::selectWater() if (!m_molecule) return; + QString undoText = tr("Select Water"); + for (Index i = 0; i < m_molecule->atomCount(); ++i) { auto atomicNumber = m_molecule->atomicNumber(i); if (atomicNumber == 8 && isWaterOxygen(i)) { - m_molecule->atom(i).setSelected(evalSelect(true, i)); + m_molecule->undoMolecule()->setAtomSelected(i, evalSelect(true, i)); continue; } else if (atomicNumber == 1) { // check if it's attached to a water oxygen auto bonds = m_molecule->bonds(i); if (bonds.size() != 1 || !isWaterOxygen(bonds[0].getOtherAtom(i).index())) - m_molecule->atom(i).setSelected(evalSelect(false, i)); + m_molecule->undoMolecule()->setAtomSelected(i, evalSelect(false, i), undoText); else - m_molecule->atom(i).setSelected(evalSelect(true, i)); + m_molecule->undoMolecule()->setAtomSelected(i, evalSelect(true, i), undoText); continue; } - m_molecule->atom(i).setSelected(evalSelect(false, i)); + m_molecule->undoMolecule()->setAtomSelected(i, evalSelect(false, i), undoText); } // also select water residues (which may be isolated "O" atoms) for (const auto residue : m_molecule->residues()) { if (residue.residueName() == "HOH") { for (auto atom : residue.residueAtoms()) { - atom.setSelected(evalSelect(true, atom.index())); + Index i = atom.index(); + m_molecule->undoMolecule()->setAtomSelected(i, evalSelect(true, i), undoText); } } } @@ -246,11 +251,15 @@ void Select::selectBackboneAtoms() // unselect everything selectNone(); + QString undoText = tr("Select Backbone"); + for (const auto residue : m_molecule->residues()) { for (auto atom : residue.residueAtoms()) { auto name = residue.getAtomName(atom); - if (name == "CA" || name == "C" || name == "N" || name == "O") - atom.setSelected(evalSelect(true, atom.index())); + if (name == "CA" || name == "C" || name == "N" || name == "O") { + Index i = atom.index(); + m_molecule->undoMolecule()->setAtomSelected(i, evalSelect(true, i), undoText); + } // also select hydrogens connected to the backbone atoms if (atom.atomicNumber() == 1) { @@ -258,8 +267,11 @@ void Select::selectBackboneAtoms() if (bonds.size() == 1) { auto otherAtom = bonds[0].getOtherAtom(atom.index()); auto otherName = residue.getAtomName(otherAtom); - if (otherName == "CA" || otherName == "C" || otherName == "N" || otherName == "O") - atom.setSelected(evalSelect(true, atom.index())); + if (otherName == "CA" || otherName == "C" || otherName == "N" || + otherName == "O") { + Index i = atom.index(); + m_molecule->undoMolecule()->setAtomSelected(i, evalSelect(true, i), undoText); + } } } } @@ -273,11 +285,15 @@ void Select::selectSidechainAtoms() // unselect everything selectNone(); + QString undoText = tr("Select Sidechain"); + for (const auto residue : m_molecule->residues()) { for (auto atom : residue.residueAtoms()) { auto name = residue.getAtomName(atom); - if (name != "CA" && name != "C" && name != "N" && name != "O") - atom.setSelected(evalSelect(true, atom.index())); + if (name != "CA" && name != "C" && name != "N" && name != "O") { + Index i = atom.index(); + m_molecule->undoMolecule()->setAtomSelected(i, evalSelect(true, i), undoText); + } // or is it a hydrogen connected to a backbone atom? // (then we don't want to select it) @@ -287,8 +303,10 @@ void Select::selectSidechainAtoms() auto otherAtom = bonds[0].getOtherAtom(atom.index()); auto otherName = residue.getAtomName(otherAtom); if (otherName == "CA" || otherName == "C" || otherName == "N" || - otherName == "O") - atom.setSelected(evalSelect(false, atom.index())); + otherName == "O") { + Index i = atom.index(); + m_molecule->undoMolecule()->setAtomSelected(i, evalSelect(false, i), undoText); + } } } } @@ -331,13 +349,16 @@ void Select::enlargeSelection() maxDistance = sqrt(maxDistance) + 2.5; maxDistance *= maxDistance; // square to compare with .squaredNorm() values + QString undoText = tr("Enlarge Selection"); + // now select all atoms within the NEW max distance for (Index i = 0; i < m_molecule->atomCount(); ++i) { if (!m_molecule->atomSelected(i)) { Vector3 displacement = m_molecule->atomPosition3d(i) - center; Real distance = displacement.squaredNorm(); - if (distance < maxDistance) - m_molecule->atom(i).setSelected(evalSelect(true, i)); + if (distance < maxDistance) { + m_molecule->undoMolecule()->setAtomSelected(i, evalSelect(true, i), undoText); + } } } @@ -363,14 +384,16 @@ void Select::shrinkSelection() maxDistance = 0.0; maxDistance *= maxDistance; // square to compare with .squaredNorm() values + QString undoText = tr("Shrink Selection"); + // now select ONLY atoms within the NEW max distance for (Index i = 0; i < m_molecule->atomCount(); ++i) { Vector3 displacement = m_molecule->atomPosition3d(i) - center; Real distance = displacement.squaredNorm(); if (distance < maxDistance) - m_molecule->atom(i).setSelected(evalSelect(true, i)); + m_molecule->undoMolecule()->setAtomSelected(i, evalSelect(true, i), undoText); else - m_molecule->atom(i).setSelected(evalSelect(false, i)); + m_molecule->undoMolecule()->setAtomSelected(i, evalSelect(false, i), undoText); } m_molecule->emitChanged(Molecule::Atoms); @@ -389,6 +412,8 @@ void Select::selectAtomIndex() if (!ok || text.isEmpty()) return; + QString undoText = tr("Select Atom"); + auto list = text.simplified().split(','); foreach (const QString item, list) { // check if it's a range @@ -399,15 +424,14 @@ void Select::selectAtomIndex() int start = range.first().toInt(&ok1); int last = range.back().toInt(&ok2); if (ok1 && ok2) { - for (Index i = start; i <= last; ++i) { - m_molecule->atom(i).setSelected(evalSelect(true, i)); - } + for (Index i = start; i <= last; ++i) + m_molecule->undoMolecule()->setAtomSelected(i, evalSelect(true, i), undoText); } } } else { int i = item.toInt(&ok); if (ok) - m_molecule->atom(i).setSelected(evalSelect(true, i)); + m_molecule->undoMolecule()->setAtomSelected(i, evalSelect(true, i), undoText); } } @@ -427,6 +451,8 @@ void Select::selectResidue() if (!ok || text.isEmpty()) return; + QString undoText = tr("Select Residue"); + auto list = text.simplified().split(','); foreach (const QString item, list) { const QString label = item.simplified(); // get rid of whitespace @@ -438,7 +464,9 @@ void Select::selectResidue() if (index >= 1 && index < residueList.size()) { auto residue = residueList[index]; for (auto& atom : residue.residueAtoms()) { - atom.setSelected(evalSelect(true, atom.index())); + Index i = atom.index(); + m_molecule->undoMolecule()->setAtomSelected(i, evalSelect(true, i), + undoText); } } // index makes sense continue; @@ -456,7 +484,9 @@ void Select::selectResidue() auto residue = residueList[index]; if (name == residue.residueName().c_str()) { for (auto atom : residue.residueAtoms()) { - atom.setSelected(evalSelect(true, atom.index())); + Index i = atom.index(); + m_molecule->undoMolecule()->setAtomSelected(i, evalSelect(true, i), + undoText); } } // check if name matches specified (e.g. HIS57 is really a HIS) } // index makes sense @@ -466,7 +496,9 @@ void Select::selectResidue() if (label == residue.residueName().c_str()) { // select the atoms of the residue for (auto atom : residue.residueAtoms()) { - atom.setSelected(evalSelect(true, atom.index())); + Index i = atom.index(); + m_molecule->undoMolecule()->setAtomSelected(i, evalSelect(true, i), + undoText); } } // residue matches label } // for(residues) @@ -481,8 +513,8 @@ void Select::invertSelection() { if (m_molecule) { for (Index i = 0; i < m_molecule->atomCount(); ++i) - m_molecule->atom(i).setSelected( - evalSelect(!m_molecule->atomSelected(i), i)); + m_molecule->undoMolecule()->setAtomSelected( + i, evalSelect(!m_molecule->atomSelected(i), i), tr("Invert Selection")); m_molecule->emitChanged(Molecule::Atoms); } } diff --git a/avogadro/qtplugins/selectiontool/selectiontool.cpp b/avogadro/qtplugins/selectiontool/selectiontool.cpp index 41537c1b12..4bd662f001 100644 --- a/avogadro/qtplugins/selectiontool/selectiontool.cpp +++ b/avogadro/qtplugins/selectiontool/selectiontool.cpp @@ -287,25 +287,25 @@ void SelectionTool::selectLinkedMolecule(QMouseEvent* e, Index atom) void SelectionTool::clearAtoms() { for (Index i = 0; i < m_molecule->atomCount(); ++i) - m_molecule->atom(i).setSelected(false); + m_molecule->undoMolecule()->setAtomSelected(i, false); } bool SelectionTool::addAtom(const Index& atom) { - m_molecule->atom(atom).setSelected(true); + m_molecule->undoMolecule()->setAtomSelected(atom, true); return true; } bool SelectionTool::removeAtom(const Index& atom) { - m_molecule->atom(atom).setSelected(false); + m_molecule->undoMolecule()->setAtomSelected(atom, false); return true; } bool SelectionTool::toggleAtom(const Index& atom) { Atom a = m_molecule->atom(atom); - a.setSelected(!a.selected()); + m_molecule->undoMolecule()->setAtomSelected(atom, !a.selected()); return a.selected(); }