• Skip to content
  • Skip to link menu
KDE 4.2 API Reference
  • KDE API Reference
  • kdeedu
  • Sitemap
  • Contact Us
 

kalzium

drawcommand.cpp

Go to the documentation of this file.
00001 /**********************************************************************
00002   DrawCommand - Set of command classes for drawing.
00003 
00004   Copyright (C) 2007 Donald Ephraim Curtis
00005   Copyright (C) 2008 Tim Vandermeersch
00006   Copyright (C) 2008 Geoffrey Hutchison
00007 
00008   This file is part of the Avogadro molecular editor project.
00009   For more information, see <http://avogadro.sourceforge.net/>
00010 
00011   Avogadro is free software; you can redistribute it and/or modify
00012   it under the terms of the GNU General Public License as published by
00013   the Free Software Foundation; either version 2 of the License, or
00014   (at your option) any later version.
00015 
00016   Avogadro is distributed in the hope that it will be useful,
00017   but WITHOUT ANY WARRANTY; without even the implied warranty of
00018   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00019   GNU General Public License for more details.
00020 
00021   You should have received a copy of the GNU General Public License
00022   along with this program; if not, write to the Free Software
00023   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
00024   02110-1301, USA.
00025  **********************************************************************/
00026 
00027 #include "drawcommand.h"
00028 #include <avogadro/primitive.h>
00029 #include <openbabel/obiter.h>
00030 
00031 #include <QDebug>
00032 
00033 using namespace OpenBabel;
00034 
00035 namespace Avogadro {
00036 
00038   void UnsetFlags(Molecule *mol)
00039   {
00040     mol->UnsetFlag(OB_AROMATIC_MOL);
00041     mol->UnsetFlag(OB_SSSR_MOL);
00042     mol->UnsetFlag(OB_RINGFLAGS_MOL);
00043     mol->UnsetFlag(OB_ATOMTYPES_MOL);
00044     mol->UnsetFlag(OB_RINGTYPES_MOL);
00045     mol->UnsetFlag(OB_CHIRALITY_MOL);
00046     mol->UnsetFlag(OB_HYBRID_MOL);
00047     mol->UnsetFlag(OB_IMPVAL_MOL);
00048     mol->UnsetFlag(OB_KEKULE_MOL);
00049     mol->UnsetFlag(OB_CLOSURE_MOL);
00050     mol->UnsetFlag(OB_H_ADDED_MOL);
00051     mol->UnsetFlag(OB_AROM_CORRECTED_MOL);
00052   }
00053 
00055   // Add Atom
00057 
00058   class AddAtomDrawCommandPrivate {
00059     public:
00060       AddAtomDrawCommandPrivate() : molecule(0), atom(0), id(-1), prevId(false) {};
00061 
00062       Molecule *molecule;
00063       Atom *atom;
00064       Eigen::Vector3d pos;
00065       unsigned int element;
00066       // if adjustValence == 1 then add on redo and undo
00067       // if adjustValence == 2 then only adjust on undo (remove)
00068       int adjustValence;
00069       unsigned long id;
00070       bool prevId;
00071   };
00072 
00073   AddAtomDrawCommand::AddAtomDrawCommand(Molecule *molecule, const Eigen::Vector3d& pos, unsigned int element, int adjustValence) : d(new AddAtomDrawCommandPrivate)
00074   {
00075     setText(QObject::tr("Add Atom"));
00076     d->molecule = molecule;
00077     d->pos = pos;
00078     d->element = element;
00079     d->adjustValence = adjustValence;
00080     d->prevId = false;
00081   }
00082 
00083   AddAtomDrawCommand::AddAtomDrawCommand(Molecule *molecule, Atom *atom, int adjustValence) : d(new AddAtomDrawCommandPrivate)
00084   {
00085     setText(QObject::tr("Add Atom"));
00086     d->molecule = molecule;
00087     d->pos = atom->pos();
00088     d->element = atom->GetAtomicNum();
00089     d->atom = atom;
00090     d->adjustValence = adjustValence;
00091     d->id = atom->id();
00092     d->prevId = true;
00093   }
00094 
00095   AddAtomDrawCommand::~AddAtomDrawCommand()
00096   {
00097     delete d;
00098   }
00099 
00100   void AddAtomDrawCommand::undo()
00101   {
00102     Atom *atom = d->molecule->getAtomById(d->id);
00103     if(atom)
00104     {
00105       d->molecule->BeginModify();
00106       if (d->adjustValence) {
00107       qDebug() << "Adjusting Atom valence";
00108         if (!atom->IsHydrogen())
00109         {
00110           d->molecule->DeleteHydrogens(atom);
00111         }
00112       }
00113       d->molecule->DeleteAtom(atom);
00114       d->molecule->EndModify();
00115       //      d->molecule->update();
00116     }
00117   }
00118 
00119   void AddAtomDrawCommand::redo()
00120   {
00121     if(d->atom) { // initial creation
00122       if (d->adjustValence==1) {
00123       qDebug() << "Adjusting Atom valence";
00124         if (!d->atom->IsHydrogen()) {
00125           d->molecule->DeleteHydrogens(d->atom);
00126           d->molecule->AddHydrogens(d->atom);
00127         }
00128       }
00129       d->atom = 0;
00130       return;
00131     }
00132 
00133     Atom *atom = 0;
00134     d->molecule->BeginModify();
00135     if(d->prevId)
00136     {
00137       atom = d->molecule->newAtom(d->id);
00138     }
00139     else
00140     {
00141       atom = d->molecule->newAtom();
00142       d->id = atom->id();
00143       d->prevId = true;
00144     }
00145     atom->setPos(d->pos);
00146     atom->SetAtomicNum(d->element);
00147     d->molecule->EndModify();
00148     if (d->adjustValence==1) {
00149       qDebug() << "Adjusting Atom valence";
00150       if (!atom->IsHydrogen()) {
00151         d->molecule->AddHydrogens(atom);
00152       }
00153     }
00154     atom->update();
00155   }
00156 
00158   // Delete Atom
00160 
00161   class DeleteAtomDrawCommandPrivate {
00162     public:
00163       DeleteAtomDrawCommandPrivate() : id(-1) {};
00164 
00165       Molecule *molecule;
00166       Molecule moleculeCopy;
00167       unsigned long id;
00168       int adjustValence;
00169   };
00170 
00171   DeleteAtomDrawCommand::DeleteAtomDrawCommand(Molecule *molecule, int index, int adjustValence) : d(new DeleteAtomDrawCommandPrivate)
00172   {
00173     setText(QObject::tr("Delete Atom"));
00174     d->molecule = molecule;
00175     d->moleculeCopy = (*(molecule));
00176     d->id = static_cast<Atom *>(molecule->GetAtom(index))->id();
00177     d->adjustValence = adjustValence;
00178   }
00179 
00180   DeleteAtomDrawCommand::~DeleteAtomDrawCommand()
00181   {
00182     delete d;
00183   }
00184 
00185   void DeleteAtomDrawCommand::undo()
00186   {
00187     *d->molecule = d->moleculeCopy;
00188     d->molecule->update();
00189   }
00190 
00191   void DeleteAtomDrawCommand::redo()
00192   {
00193     Atom *atom = d->molecule->getAtomById(d->id);
00194     if(atom)
00195     {
00196       QList<OBAtom*> neighbors;
00197 
00198       if (d->adjustValence) {
00199         // Delete any hydrogens on this atom
00200         d->molecule->DeleteHydrogens(atom);
00201         // Now that we've deleted any attached hydrogens,
00202         // Adjust the valence on any bonded atom
00203         FOR_NBORS_OF_ATOM(n, atom) {
00204           neighbors.append(&*n);
00205           d->molecule->DeleteHydrogens(&*n);
00206         }
00207       }
00208       d->molecule->DeleteAtom(atom);
00209 
00210       if (d->adjustValence) {
00211         // Finally, add back hydrogens to neighbors
00212         foreach (OBAtom *n, neighbors)
00213           d->molecule->AddHydrogens(n);
00214       }
00215       d->molecule->update();
00216     }
00217   }
00218 
00220   // Add Bond
00222 
00223   class AddBondDrawCommandPrivate {
00224     public:
00225       AddBondDrawCommandPrivate() : molecule(0), bond(0), id(-1), beginAtomId(-1), endAtomId(-1), prevId(false) {};
00226 
00227       Molecule *molecule;
00228       Bond *bond;
00229       unsigned long id;
00230       unsigned int beginAtomId;
00231       unsigned int endAtomId;
00232       bool prevId;
00233       Eigen::Vector3d pos;
00234       unsigned int order;
00235       int adjustValence;
00236   };
00237 
00238   AddBondDrawCommand::AddBondDrawCommand(Molecule *molecule, Atom *beginAtom, Atom *endAtom, unsigned int order, int adjustValence) : d(new AddBondDrawCommandPrivate)
00239   {
00240     setText(QObject::tr("Add Bond"));
00241     d->molecule = molecule;
00242     d->beginAtomId = beginAtom->id();
00243     d->endAtomId = endAtom->id();
00244     d->order = order;
00245     d->adjustValence = adjustValence;
00246   }
00247 
00248   AddBondDrawCommand::AddBondDrawCommand(Molecule *molecule, Bond *bond, int adjustValence) : d(new AddBondDrawCommandPrivate)
00249   {
00250     setText(QObject::tr("Add Bond"));
00251     d->molecule = molecule;
00252     d->beginAtomId = static_cast<Atom*>(bond->GetBeginAtom())->id();
00253     d->endAtomId = static_cast<Atom*>(bond->GetEndAtom())->id();
00254     d->order = bond->GetBondOrder();
00255     d->bond = bond;
00256     d->prevId = true;
00257     d->id = bond->id();
00258     d->adjustValence = adjustValence;
00259   }
00260 
00261   AddBondDrawCommand::~AddBondDrawCommand()
00262   {
00263     delete d;
00264   }
00265 
00266   void AddBondDrawCommand::undo()
00267   {
00268     Bond *bond = d->molecule->getBondById(d->id);
00269     if(bond)
00270     {
00271       Atom *beginAtom = static_cast<Atom*>(bond->GetBeginAtom());
00272       Atom *endAtom = static_cast<Atom*>(bond->GetEndAtom());
00273 
00274       d->molecule->BeginModify();
00275       d->molecule->DeleteBond(bond);
00276       d->molecule->EndModify();
00277       if (d->adjustValence) {
00278         if (!beginAtom->IsHydrogen()) {
00279           d->molecule->DeleteHydrogens(beginAtom);
00280         }
00281         if (!endAtom->IsHydrogen()) {
00282           d->molecule->DeleteHydrogens(endAtom);
00283         }
00284 
00285         UnsetFlags(d->molecule);
00286 
00287         if (!beginAtom->IsHydrogen()) {
00288           d->molecule->AddHydrogens(beginAtom);
00289         }
00290         if (!endAtom->IsHydrogen()) {
00291           d->molecule->AddHydrogens(endAtom);
00292         }
00293       }
00294       d->molecule->update();
00295       return;
00296     }
00297   }
00298 
00299   void AddBondDrawCommand::redo()
00300   {
00301 
00302     if(d->bond) { // already created the bond
00303       Atom *beginAtom = static_cast<Atom*>(d->bond->GetBeginAtom());
00304       Atom *endAtom = static_cast<Atom*>(d->bond->GetEndAtom());
00305       if (d->adjustValence) {
00306         if (!beginAtom->IsHydrogen()) {
00307           d->molecule->DeleteHydrogens(beginAtom);
00308         }
00309         if (!endAtom->IsHydrogen()) {
00310           d->molecule->DeleteHydrogens(endAtom);
00311         }
00312 
00313         UnsetFlags(d->molecule);
00314 
00315         if (!beginAtom->IsHydrogen()) {
00316           d->molecule->AddHydrogens(beginAtom);
00317         }
00318         if (!endAtom->IsHydrogen()) {
00319           d->molecule->AddHydrogens(endAtom);
00320         }
00321       }
00322       d->bond = 0;
00323       return;
00324     }
00325 
00326     Atom *beginAtom = d->molecule->getAtomById(d->beginAtomId);
00327     Atom *endAtom = d->molecule->getAtomById(d->endAtomId);
00328 
00329     if(!beginAtom || !endAtom)
00330     {
00331       return;
00332     }
00333 
00334     d->molecule->BeginModify();
00335     Bond *bond;
00336     if(d->prevId)
00337     {
00338       bond = d->molecule->newBond(d->id);
00339     }
00340     else
00341     {
00342       bond = d->molecule->newBond();
00343       d->id = bond->id();
00344       d->prevId = true;
00345     }
00346     bond->SetBondOrder(d->order);
00347     bond->SetBegin(beginAtom);
00348     bond->SetEnd(endAtom);
00349     beginAtom->AddBond(bond);
00350     endAtom->AddBond(bond);
00351     d->molecule->EndModify();
00352     if (d->adjustValence) {
00353       if (!beginAtom->IsHydrogen())
00354       {
00355         d->molecule->DeleteHydrogens(beginAtom);
00356       }
00357       if (!endAtom->IsHydrogen())
00358       {
00359         d->molecule->DeleteHydrogens(endAtom);
00360       }
00361 
00362       UnsetFlags(d->molecule);
00363 
00364       if (!beginAtom->IsHydrogen())
00365       {
00366         d->molecule->AddHydrogens(endAtom);
00367       }
00368       if (!endAtom->IsHydrogen())
00369       {
00370         d->molecule->AddHydrogens(beginAtom);
00371       }
00372     }
00373     d->molecule->update();
00374   }
00375 
00377   // Delete Bond
00379 
00380   class DeleteBondDrawCommandPrivate {
00381     public:
00382       DeleteBondDrawCommandPrivate() : id(-1) {};
00383 
00384       Molecule *molecule;
00385       Molecule moleculeCopy;
00386       unsigned long id;
00387       int adjustValence;
00388   };
00389 
00390   DeleteBondDrawCommand::DeleteBondDrawCommand(Molecule *molecule, int index, int adjustValence) : d(new DeleteBondDrawCommandPrivate)
00391   {
00392     setText(QObject::tr("Delete Bond"));
00393     d->molecule = molecule;
00394     d->moleculeCopy = (*(molecule));
00395     d->id = static_cast<Bond *>(molecule->GetBond(index))->id();
00396     d->adjustValence = adjustValence;
00397   }
00398 
00399   DeleteBondDrawCommand::~DeleteBondDrawCommand()
00400   {
00401     delete d;
00402   }
00403 
00404   void DeleteBondDrawCommand::undo()
00405   {
00406     *d->molecule = d->moleculeCopy;
00407     d->molecule->update();
00408   }
00409 
00410   void DeleteBondDrawCommand::redo()
00411   {
00412     Bond *bond = d->molecule->getBondById(d->id);
00413     if(bond)
00414     {
00415       d->molecule->DeleteBond(bond);
00416       if (d->adjustValence) {
00417         OBAtom *a1, *a2;
00418         a1 = bond->GetBeginAtom();
00419         a2 = bond->GetEndAtom();
00420         d->molecule->DeleteHydrogens(a1);
00421         d->molecule->DeleteHydrogens(a2);
00422 
00423         UnsetFlags(d->molecule);
00424 
00425         d->molecule->AddHydrogens(a1);
00426         d->molecule->AddHydrogens(a2);
00427       }
00428       d->molecule->update();
00429     }
00430   }
00431 
00433   // Change Element
00435 
00436   class ChangeElementDrawCommandPrivate {
00437     public:
00438       ChangeElementDrawCommandPrivate() : molecule(0), id(0) {};
00439 
00440       Molecule *molecule;
00441       unsigned int newElement, oldElement;
00442       unsigned long id;
00443       int adjustValence;
00444   };
00445 
00446   ChangeElementDrawCommand::ChangeElementDrawCommand(Molecule *molecule, Atom *atom, unsigned int oldElement, int adjustValence) : d(new ChangeElementDrawCommandPrivate)
00447   {
00448     setText(QObject::tr("Change Element"));
00449     d->molecule = molecule;
00450     d->newElement = atom->GetAtomicNum();
00451     d->oldElement = oldElement;
00452     d->id = atom->id();
00453     d->adjustValence = adjustValence;
00454   }
00455 
00456   ChangeElementDrawCommand::~ChangeElementDrawCommand()
00457   {
00458     delete d;
00459   }
00460 
00461   void ChangeElementDrawCommand::undo()
00462   {
00463     Atom *atom = d->molecule->getAtomById(d->id);
00464 
00465     if(atom)
00466     {
00467       // Make sure we call BeginModify / EndModify (e.g., PR#1720879)
00468       d->molecule->BeginModify();
00469       atom->SetAtomicNum(d->oldElement);
00470       d->molecule->EndModify();
00471       d->molecule->update();
00472       if (d->adjustValence) {
00473         UnsetFlags(d->molecule);
00474         d->molecule->DeleteHydrogens(atom);
00475         d->molecule->AddHydrogens(atom);
00476       }
00477     }
00478   }
00479 
00480   void ChangeElementDrawCommand::redo()
00481   {
00482     Atom *atom = d->molecule->getAtomById(d->id);
00483 
00484     if(atom)
00485     {
00486       // Make sure we call BeginModify / EndModify (e.g., PR#1720879)
00487       d->molecule->BeginModify();
00488       atom->SetAtomicNum(d->newElement);
00489       d->molecule->EndModify();
00490       if (d->adjustValence) {
00491         UnsetFlags(d->molecule);
00492         d->molecule->DeleteHydrogens(atom);
00493         d->molecule->AddHydrogens(atom);
00494       }
00495       d->molecule->update();
00496     }
00497   }
00498 
00500   // Change Bond Order
00502 
00503   class ChangeBondOrderDrawCommandPrivate {
00504     public:
00505       ChangeBondOrderDrawCommandPrivate() : molecule(0), id(-1) {};
00506 
00507       Molecule *molecule;
00508       unsigned long id;
00509       unsigned int newBondOrder, oldBondOrder;
00510       int adjustValence;
00511   };
00512 
00513   ChangeBondOrderDrawCommand::ChangeBondOrderDrawCommand(Molecule *molecule, Bond *bond, unsigned int oldBondOrder, int adjustValence) : d(new ChangeBondOrderDrawCommandPrivate)
00514   {
00515     setText(QObject::tr("Change Bond Order"));
00516     d->molecule = molecule;
00517     d->id = bond->id();
00518     d->newBondOrder = bond->GetBondOrder();
00519     d->oldBondOrder = oldBondOrder;
00520     d->adjustValence = adjustValence;
00521   }
00522 
00523   ChangeBondOrderDrawCommand::~ChangeBondOrderDrawCommand()
00524   {
00525     delete d;
00526   }
00527 
00528   void ChangeBondOrderDrawCommand::undo()
00529   {
00530     Bond *bond = d->molecule->getBondById(d->id);
00531     if(bond)
00532     {
00533       // Make sure we call BeginModify / EndModify (e.g., PR#1720879)
00534       d->molecule->BeginModify();
00535       bond->SetBondOrder(d->oldBondOrder);
00536       d->molecule->EndModify();
00537       if (d->adjustValence) {
00538         OBAtom *a1, *a2;
00539         a1 = bond->GetBeginAtom();
00540         a2 = bond->GetEndAtom();
00541         d->molecule->DeleteHydrogens(a1);
00542         d->molecule->DeleteHydrogens(a2);
00543 
00544         UnsetFlags(d->molecule);
00545         d->molecule->AddHydrogens(a1);
00546         d->molecule->AddHydrogens(a2);
00547       }
00548       d->molecule->update();
00549     }
00550   }
00551 
00552   void ChangeBondOrderDrawCommand::redo()
00553   {
00554     Bond *bond = d->molecule->getBondById(d->id);
00555     if(bond)
00556     {
00557       // Make sure we call BeginModify / EndModify (e.g., PR#1720879)
00558       d->molecule->BeginModify();
00559       bond->SetBondOrder(d->newBondOrder);
00560       d->molecule->EndModify();
00561       if (d->adjustValence) {
00562 
00563         OBAtom *a1, *a2;
00564         a1 = bond->GetBeginAtom();
00565         a2 = bond->GetEndAtom();
00566         d->molecule->DeleteHydrogens(a1);
00567         d->molecule->DeleteHydrogens(a2);
00568 
00569         UnsetFlags(d->molecule);
00570         d->molecule->AddHydrogens(a1);
00571         d->molecule->AddHydrogens(a2);
00572       }
00573       d->molecule->update();
00574     }
00575   }
00576 
00578   // Insert Fragment
00580 
00581   class InsertFragmentCommandPrivate {
00582     public:
00583       InsertFragmentCommandPrivate() : molecule(0), generatedMolecule(0) {};
00584 
00585       Molecule *molecule;
00586       Molecule moleculeCopy, generatedMolecule;
00587   };
00588 
00589   InsertFragmentCommand::InsertFragmentCommand(Molecule *molecule, Molecule &generatedMolecule) : d(new InsertFragmentCommandPrivate)
00590   {
00591     setText(QObject::tr("Insert Fragment"));
00592     d->molecule = molecule;
00593     d->moleculeCopy = *molecule;
00594     d->generatedMolecule = generatedMolecule;
00595   }
00596 
00597   InsertFragmentCommand::~InsertFragmentCommand()
00598   {
00599     delete d;
00600   }
00601 
00602   void InsertFragmentCommand::undo()
00603   {
00604     *(d->molecule) = d->moleculeCopy;
00605     d->molecule->update();
00606   }
00607 
00608   void InsertFragmentCommand::redo()
00609   {
00610     *(d->molecule) += d->generatedMolecule;
00611     d->molecule->update();
00612   }
00613 
00614 
00615 } // end namespace Avogadro

kalzium

Skip menu "kalzium"
  • Main Page
  • Namespace List
  • Class Hierarchy
  • Alphabetical List
  • Class List
  • File List
  • Namespace Members
  • Class Members
  • Related Pages

kdeedu

Skip menu "kdeedu"
  • kalzium
  • kanagram
  • kig
  •   lib
  • klettres
  • kstars
  • libkdeedu
  •   keduvocdocument
  •   docs
  •   src
  • parley
  •   stepcore
Generated for kdeedu by doxygen 1.5.4
This website is maintained by Adriaan de Groot and Allen Winter.
KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal