diff --git a/avogadro/qtgui/rwmolecule.h b/avogadro/qtgui/rwmolecule.h index fad573e15..12dae4889 100644 --- a/avogadro/qtgui/rwmolecule.h +++ b/avogadro/qtgui/rwmolecule.h @@ -529,7 +529,28 @@ class AVOGADROQTGUI_EXPORT RWMolecule : public QObject * @param cartTol Cartesian tolerance for comparing atom positions. * @return True if the algorithm succeeded, and false if it failed. */ - bool reduceCellToAsymmetricUnit(unsigned short hallNumber, double cartTol = 1e-5); + bool reduceCellToAsymmetricUnit(unsigned short hallNumber, + double cartTol = 1e-5); + + /** + * Call this function when you wish to merge all undo commands. + * It turns on interactive mode to merge similar undo commands in a series + * (in order to save space), and it uses QUndoStack's beginMacro() to merge + * dissimilar undo commands together. You must call endMergeMode() to end + * the merging section (undo and redo are unavailable while merge mode is + * on). + * @param undoName The name of the undo command + */ + void beginMergeMode(const QString& undoName = "Draw"); + + /** + * Call this function when you wish merge mode to end. This will turn off + * interactive mode, and it will call QUndoStack's endMacro(). All of the + * undo commands pushed between beginMergeMode() and endMergeMode() will be + * merged into one undo command. beginMergeMode() should have been called + * before this is called. + */ + void endMergeMode(); /** * @brief Begin or end an interactive edit. @@ -771,6 +792,18 @@ inline std::pair RWMolecule::bondPair(Index bondId) const return m_molecule.bondPair(bondId); } +inline void RWMolecule::beginMergeMode(const QString& undoName) +{ + m_interactive = true; + m_undoStack.beginMacro(undoName); +} + +inline void RWMolecule::endMergeMode() +{ + m_interactive = false; + m_undoStack.endMacro(); +} + inline void RWMolecule::setInteractive(bool b) { m_interactive = b; diff --git a/avogadro/qtplugins/editor/editor.cpp b/avogadro/qtplugins/editor/editor.cpp index eecb171be..350ef9b1c 100644 --- a/avogadro/qtplugins/editor/editor.cpp +++ b/avogadro/qtplugins/editor/editor.cpp @@ -103,27 +103,28 @@ QWidget *Editor::toolWidget() const QUndoCommand *Editor::mousePressEvent(QMouseEvent *e) { clearKeyPressBuffer(); - if (!m_renderer) + if (!m_renderer || !m_molecule) return NULL; updatePressedButtons(e, false); m_clickPosition = e->pos(); - if (m_molecule) { - m_molecule->setInteractive(true); - } - if (m_pressedButtons & Qt::LeftButton) { m_clickedObject = m_renderer->hit(e->pos().x(), e->pos().y()); switch (m_clickedObject.type) { case Rendering::InvalidType: + m_molecule->beginMergeMode(tr("Draw Atom")); emptyLeftClick(e); return NULL; case Rendering::AtomType: + // We don't know yet if we are drawing a bond/atom or replacing an atom + // unfortunately... + m_molecule->beginMergeMode(tr("Draw")); atomLeftClick(e); return NULL; case Rendering::BondType: + m_molecule->beginMergeMode(tr("Change Bond Type")); bondLeftClick(e); return NULL; } @@ -133,9 +134,11 @@ QUndoCommand *Editor::mousePressEvent(QMouseEvent *e) switch (m_clickedObject.type) { case Rendering::AtomType: + m_molecule->beginMergeMode(tr("Remove Atom")); atomRightClick(e); return NULL; case Rendering::BondType: + m_molecule->beginMergeMode(tr("Remove Bond")); bondRightClick(e); return NULL; default: @@ -148,15 +151,11 @@ QUndoCommand *Editor::mousePressEvent(QMouseEvent *e) QUndoCommand *Editor::mouseReleaseEvent(QMouseEvent *e) { - if (!m_renderer) + if (!m_renderer || !m_molecule) return NULL; updatePressedButtons(e, true); - if (m_molecule) { - m_molecule->setInteractive(false); - } - if (m_clickedObject.type == Rendering::InvalidType) return NULL; @@ -165,6 +164,12 @@ QUndoCommand *Editor::mouseReleaseEvent(QMouseEvent *e) case Qt::RightButton: reset(); e->accept(); + m_molecule->endMergeMode(); + // Let's cover all possible changes - the undo stack won't update + // without this + m_molecule->emitChanged(Molecule::Atoms | Molecule::Bonds | + Molecule::Added | Molecule::Removed | + Molecule::Modified); break; default: break; @@ -599,7 +604,8 @@ void Editor::atomLeftDrag(QMouseEvent *e) RWBond bond = m_molecule->bond(newAtom, clickedAtom); if (bond.isValid()) { int bondOrder = expectedBondOrder(newAtom, clickedAtom); - bond.setOrder(bondOrder); + if (bondOrder != bond.order()) + bond.setOrder(bondOrder); changes |= Molecule::Bonds | Molecule::Modified; }