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

kalzium

drawtool.cpp

Go to the documentation of this file.
00001 /**********************************************************************
00002   DrawTool - Tool for drawing molecules
00003 
00004   Copyright (C) 2007,2008 Donald Ephraim Curtis
00005   Copyright (C) 2007-2008 Marcus D. Hanwell
00006   Copyright (C) 2008 Tim Vandermeersch
00007   Some Portions Copyright (C) 2007-2008 Geoffrey Hutchison
00008 
00009   This file is part of the Avogadro molecular editor project.
00010   For more information, see <http://avogadro.sourceforge.net/>
00011 
00012   Avogadro is free software; you can redistribute it and/or modify
00013   it under the terms of the GNU General Public License as published by
00014   the Free Software Foundation; either version 2 of the License, or
00015   (at your option) any later version.
00016 
00017   Avogadro is distributed in the hope that it will be useful,
00018   but WITHOUT ANY WARRANTY; without even the implied warranty of
00019   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00020   GNU General Public License for more details.
00021 
00022   You should have received a copy of the GNU General Public License
00023   along with this program; if not, write to the Free Software
00024   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
00025   02110-1301, USA.
00026  **********************************************************************/
00027 
00028 #include "drawtool.h"
00029 #include "drawcommand.h"
00030 
00031 #include <avogadro/navigate.h>
00032 #include <avogadro/primitive.h>
00033 #include <avogadro/color.h>
00034 #include <avogadro/glwidget.h>
00035 #include <avogadro/undosequence.h>
00036 #include <avogadro/elementtranslate.h>
00037 
00038 #include <openbabel/obiter.h>
00039 #include <openbabel/obconversion.h>
00040 
00041 #include <QtPlugin>
00042 #include <QLabel>
00043 #include <QDir>
00044 #include <QDebug>
00045 
00046 using namespace std;
00047 using namespace OpenBabel;
00048 
00049 namespace Avogadro {
00050 
00051   DrawTool::DrawTool(QObject *parent) : Tool(parent),
00052                                         m_beginAtomAdded(false),
00053                                         m_endAtomAdded(false),
00054                                         m_beginAtom(0),
00055                                         m_endAtom(0),
00056                                         m_element(6),
00057                                         m_bond(0),
00058                                         m_bondOrder(1),
00059                                         m_prevAtomElement(0),
00060                                         m_prevBond(0),
00061                                         m_prevBondOrder(0),
00062                                         m_addHydrogens(2),
00063                                         m_comboElements(0),
00064                                         m_addHydrogensCheck(0),
00065                                         m_periodicTable(0),
00066                                         m_fragmentDialog(0),
00067                                         m_settingsWidget(0)
00068   {
00069     QAction *action = activateAction();
00070     action->setIcon(QIcon(QString::fromUtf8(":/draw/draw.png")));
00071     action->setToolTip(tr("Draw Tool (F8)\n\n"
00072                           "Left Mouse: \tClick and Drag to create Atoms and Bonds\n"
00073                           "Right Mouse: Delete Atom"));
00074     action->setShortcut(Qt::Key_F8);
00075 
00076     m_insertFragmentMode = false;
00077     m_forceField = OBForceField::FindForceField("MMFF94");
00078   }
00079 
00080   DrawTool::~DrawTool()
00081   {
00082     if(m_settingsWidget) {
00083       m_settingsWidget->deleteLater();
00084     }
00085   }
00086 
00087   int DrawTool::usefulness() const
00088   {
00089     return 5000000;
00090   }
00091 
00092   // Handle a user click
00093   QUndoCommand* DrawTool::mousePress(GLWidget *widget, const QMouseEvent *event)
00094   {
00095     Molecule *molecule = widget->molecule();
00096     if(!molecule) {
00097       return 0;
00098     }
00099 
00100     QUndoCommand *undo = 0;
00101 
00102     _buttons = event->buttons();
00103 
00104     m_movedSinceButtonPressed = false;
00105     m_lastDraggingPosition = event->pos();
00106     m_initialDraggingPosition = event->pos();
00107 
00109     m_hits = widget->hits(event->pos().x()-SEL_BOX_HALF_SIZE,
00110                           event->pos().y()-SEL_BOX_HALF_SIZE,
00111                           SEL_BOX_SIZE,
00112                           SEL_BOX_SIZE);
00113 
00114     if(_buttons & Qt::LeftButton) {
00115       // The user clicked on an atom
00116       if(m_hits.size() && (m_hits[0].type() == Primitive::AtomType)) {
00117         // "alchemy" -- change this atom to a new element
00118         m_beginAtom = (Atom *)molecule->GetAtom(m_hits[0].name());
00119 
00120         if(m_beginAtom && ((int)m_beginAtom->GetAtomicNum() != m_element)) {
00121           m_prevAtomElement = m_beginAtom->GetAtomicNum();
00122           m_beginAtom->SetAtomicNum(m_element);
00123           m_beginAtom->update();
00124         }
00125       }
00126       else if(m_hits.size() && (m_hits[0].type() == Primitive::BondType)) {
00127         // "alchemy" -- change the bond order of this bond
00128         Bond *bond = (Bond *)molecule->GetBond(m_hits[0].name());
00129         if (bond) { // if we can't find the bond, we can't do anything here
00130 
00131           unsigned int bondOrder, oldBondOrder;
00132           oldBondOrder = bond->GetBondOrder();
00133 
00134           switch (oldBondOrder) {
00135           case 1:
00136             bondOrder = 2;
00137             break;
00138           case 2:
00139             bondOrder = 3;
00140             break;
00141           case 3:
00142             bondOrder = 1;
00143             break;
00144           default:
00145             bondOrder = 1;
00146           }
00147           bond->SetBondOrder(bondOrder);
00148 
00149           undo = new ChangeBondOrderDrawCommand(widget->molecule(), bond,
00150                                                 oldBondOrder, m_addHydrogens);
00151         }
00152       }
00153       else { // a genuine click in new space == create a new atom or fragment
00154         if (m_insertFragmentMode) { // insert a new fragment
00155           Eigen::Vector3d refPoint;
00156           if (m_beginAtom) {
00157             refPoint = m_beginAtom->pos();
00158           } else {
00159             refPoint = widget->center();
00160           }
00161           Eigen::Vector3d newMolPos = widget->camera()->unProject(event->pos(), refPoint);
00162           Molecule m_generatedMolecule = *m_fragmentDialog->fragment();
00163           m_generatedMolecule.Center();
00164           m_generatedMolecule.Translate(vector3(newMolPos.x(),
00165                                                 newMolPos.y(),
00166                                                 newMolPos.z()));
00167           undo = new InsertFragmentCommand(widget->molecule(), m_generatedMolecule);
00168         } // end insert fragment mode
00169         else { // create a new atom
00170           m_beginAtom = newAtom(widget, event->pos());
00171           m_beginAtomAdded = true;
00172           m_forceField->SetIgnoreAtom(m_beginAtom->GetIdx());
00173           m_beginAtom->update();
00174         } // place atoms
00175       } // hits
00176     } // left button
00177 
00178     return undo;
00179   }
00180 
00181   QUndoCommand* DrawTool::mouseMove(GLWidget *widget, const QMouseEvent *event)
00182   {
00183     Molecule *molecule = widget->molecule();
00184     if(!molecule) {
00185       return 0;
00186     }
00187 
00188     if((_buttons & Qt::LeftButton) && m_beginAtom) {
00189       m_hits = widget->hits(event->pos().x()-SEL_BOX_HALF_SIZE,
00190                             event->pos().y()-SEL_BOX_HALF_SIZE,
00191                             SEL_BOX_SIZE,
00192                             SEL_BOX_SIZE);
00193 
00194       bool hitBeginAtom = false;
00195       Atom *existingAtom = 0;
00196       if(m_hits.size()) {
00197         // parse our hits.  we want to know
00198         // if we hit another existing atom that is not
00199         // the m_endAtom which we created
00200         for(int i=0; i < m_hits.size() && !hitBeginAtom; i++) {
00201           if(m_hits[i].type() == Primitive::AtomType) {
00202             // hit the beginning atom: either moved here from somewhere else
00203             // or were already here.
00204             if(m_hits[i].name() == m_beginAtom->GetIdx()) {
00205               hitBeginAtom = true;
00206             }
00207             else if(!m_endAtom) {
00208               // we don't yet have an end atom but
00209               // hit another atom on screen -- bond to this
00210               existingAtom = (Atom *)molecule->GetAtom(m_hits[i].name());
00211             }
00212             else if(m_hits[i].name() != m_endAtom->GetIdx()) {
00213               // hit a new atom which isn't our end atom
00214               existingAtom = (Atom *)molecule->GetAtom(m_hits[i].name());
00215             }
00216           } // end hits.type == AtomType
00217         }
00218       } // end parsing hits
00219 
00220       if(hitBeginAtom) { // we came back to our original atom -- undo the bond
00221         if(m_endAtom) {
00222           molecule->DeleteAtom(m_endAtom); // this also deletes bonds
00223           m_endAtomAdded = false;
00224           m_bond = 0;
00225           m_endAtom = 0;
00226           m_prevAtomElement = m_beginAtom->GetAtomicNum();
00227           m_beginAtom->SetAtomicNum(m_element);
00228           m_forceField->UnsetIgnoreAtom();
00229         }
00230         else if(m_bond) {
00231           //          Atom *oldAtom = (Atom *)m_bond->GetEndAtom();
00232           //          oldAtom->DeleteBond(m_bond);
00233           molecule->DeleteBond(m_bond);
00234           m_bond=0;
00235           m_prevAtomElement = m_beginAtom->GetAtomicNum();
00236           m_beginAtom->SetAtomicNum(m_element);
00237         }
00238       }
00239       else {
00240         if(m_prevAtomElement) {
00241           m_beginAtom->SetAtomicNum(m_prevAtomElement);
00242           m_prevAtomElement = 0;
00243         }
00244 
00245         // we hit an existing atom != m_endAtom
00246         if(existingAtom) {
00247           m_forceField->UnsetIgnoreAtom();
00248           m_forceField->SetFixAtom(existingAtom->GetIdx());
00249           Bond *existingBond = (Bond *)molecule->GetBond(m_beginAtom, existingAtom);
00250           if(!existingBond) {
00251             if(m_prevBond) {
00252               m_prevBond->SetBondOrder(m_prevBondOrder);
00253               m_prevBond = 0;
00254               m_prevBondOrder = 0;
00255             }
00256 
00257             if(m_bond) {
00258               if(m_endAtom) {
00259                 m_endAtom->DeleteBond(m_bond);
00260                 molecule->DeleteAtom(m_endAtom);
00261                 m_endAtomAdded = false;
00262                 m_endAtom = 0;
00263               } else {
00264                 Atom *oldAtom = (Atom *)m_bond->GetEndAtom();
00265                 oldAtom->DeleteBond(m_bond);
00266               }
00267               m_bond->SetEnd(existingAtom);
00268               existingAtom->AddBond(m_bond);
00269             }
00270             else {
00271               m_bond = newBond(molecule, m_beginAtom, existingAtom);
00272             }
00273           } // end no existing bond
00274           else {
00275             if(m_prevBond && m_prevBond != existingBond) {
00276               m_prevBond->SetBondOrder(m_prevBondOrder);
00277               m_prevBond = 0;
00278               m_prevBondOrder = 0;
00279             }
00280             if(!m_prevBond) {
00281               m_prevBond = existingBond;
00282               m_prevBondOrder = existingBond->GetBO();
00283               existingBond->SetBondOrder(m_bondOrder);
00284             }
00285 
00286             if(m_bond && m_bond != existingBond) {
00287               if(m_endAtom) {
00288                 // will delete bonds too (namely m_bond)
00289                 molecule->DeleteAtom(m_endAtom);
00290                 m_endAtomAdded = false;
00291                 m_endAtom = 0;
00292               } else {
00293                 molecule->DeleteBond(m_bond);
00294               }
00295               m_bond = 0;
00296             }
00297           } // existing bond
00298         } // end existing atom
00299 
00300         // (!existingAtom && !hitBeginAtom)
00301         else if(!m_endAtom) {
00302 
00303           if(m_prevBond) {
00304             m_prevBond->SetBondOrder(m_prevBondOrder);
00305             m_prevBond = 0;
00306             m_prevBondOrder = 0;
00307           }
00308           m_endAtom = newAtom(widget, event->pos());
00309           m_endAtomAdded = true;
00310           m_forceField->SetIgnoreAtom(m_endAtom->GetIdx());
00311 
00312           if(!m_bond) {
00313             m_bond = newBond(molecule, m_beginAtom, m_endAtom);
00314           }
00315           else {
00316             Atom *oldAtom = (Atom *)m_bond->GetEndAtom();
00317             oldAtom->DeleteBond(m_bond);
00318             m_bond->SetEnd(m_endAtom);
00319             m_endAtom->AddBond(m_bond);
00320           }
00321         }
00322         else { // we're moving -- stretch a bond
00323           moveAtom(widget, m_endAtom, event->pos());
00324         }
00325       }
00326       molecule->update();
00327     }
00328 
00329     return 0;
00330   }
00331 
00332   QUndoCommand* DrawTool::mouseRelease(GLWidget *widget, const QMouseEvent *event)
00333   {
00334     QUndoCommand *undo = 0;
00335 
00336     if(_buttons & Qt::LeftButton && (event->modifiers() == Qt::NoModifier)) {
00337 
00338       if(m_beginAtomAdded || m_bond) {
00339 
00340         // only add hydrogens to the atoms if it's the only thing 
00341         // we've drawn.  else addbonds will adjust hydrogens.
00342         int atomAddHydrogens = 0;
00343         if(m_addHydrogens)
00344         {
00345           // if no bond then add on undo and redo
00346           if(!m_bond) {
00347             atomAddHydrogens = 1;
00348           }
00349           // if bond then only remove on undo, rest is handled by bond
00350           else
00351           {
00352             atomAddHydrogens = 2;
00353           }
00354         }
00355 
00356         // if we add a bond then we don't need 
00357         // we added At least the beginAtom or we created a bond to
00358         // an existing atom or to endAtom that we also created
00359         AddAtomDrawCommand *beginAtomDrawCommand = 0;
00360         if(m_beginAtomAdded) {
00361           beginAtomDrawCommand = new AddAtomDrawCommand(widget->molecule(), m_beginAtom, atomAddHydrogens);
00362           beginAtomDrawCommand->setText(tr("Draw Atom"));
00363         }
00364 
00365         AddAtomDrawCommand *endAtomDrawCommand = 0;
00366         if(m_endAtomAdded) {
00367           endAtomDrawCommand = new AddAtomDrawCommand(widget->molecule(), m_endAtom, atomAddHydrogens);
00368           endAtomDrawCommand->setText(tr("Draw Atom"));
00369         }
00370 
00371         AddBondDrawCommand *bondCommand = 0;
00372         if(m_bond) {
00373           bondCommand = new AddBondDrawCommand(widget->molecule(), m_bond, m_addHydrogens);
00374           bondCommand->setText(tr("Draw Bond"));
00375         }
00376 
00377         // Set the actual undo command -- combining sequence if possible
00378         // we can have a beginAtom w/out bond or endAtom
00379         // we can have bond w/out endAtom (i.e., to an existing atom)
00380         // we cannot have endAtom w/out bond
00381         if(endAtomDrawCommand || (bondCommand && beginAtomDrawCommand)) {
00382           UndoSequence *seq = new UndoSequence();
00383           seq->setText(tr("Draw"));
00384 
00385           if(beginAtomDrawCommand) {
00386             seq->append(beginAtomDrawCommand);
00387           }
00388           if(endAtomDrawCommand) {
00389             seq->append(endAtomDrawCommand);
00390           }
00391           seq->append(bondCommand);
00392 
00393           undo = seq;
00394         }
00395         else if(bondCommand) {
00396           undo = bondCommand;
00397         }
00398         else {
00399           undo = beginAtomDrawCommand;
00400         }
00401       } else if (m_prevBond) {
00402         // bug #1898118
00403         // both beginAtom, endAtom and bond exist, but the bond order has changed
00404         if ((int)m_prevBond->GetBondOrder() != m_prevBondOrder) {
00405           undo = new ChangeBondOrderDrawCommand(widget->molecule(), m_prevBond,
00406                                                 m_prevBondOrder, m_addHydrogens);
00407           undo->setText(tr("Change Bond Order"));
00408         }
00409       } else if (m_beginAtom) {
00410         // beginAtom exists, but we have no bond, we change the element
00411         if ((int)m_beginAtom->GetAtomicNum() != m_prevAtomElement) {
00412           undo = new ChangeElementDrawCommand(widget->molecule(),
00413                                               m_beginAtom,
00414                                               m_prevAtomElement,
00415                                               m_addHydrogens);
00416         }
00417       }
00418 
00419       // clean up after drawing
00420       m_beginAtom=0;
00421       m_bond=0;
00422       m_endAtom=0;
00423       m_prevBond=0;
00424       m_prevBondOrder=0;
00425       m_prevAtomElement=0;
00426       m_beginAtomAdded=false;
00427       m_endAtomAdded=false;
00428       
00429       m_forceField->UnsetIgnoreAtom();
00430       m_forceField->UnsetFixAtom();
00431 
00432       widget->molecule()->update();
00433       return undo;
00434     }
00435 
00436     // Either use a three-button mouse
00437     // or hold down the Command key (ControlModifier in Qt notation)
00438     // or the Control key (MetaModifier in Qt notation)
00439     else if( (_buttons & Qt::RightButton) ||
00440              ((_buttons & Qt::LeftButton) && (event->modifiers() == Qt::ControlModifier || event->modifiers() == Qt::MetaModifier)) )
00441     {
00442       m_hits = widget->hits(event->pos().x()-SEL_BOX_HALF_SIZE,
00443                             event->pos().y()-SEL_BOX_HALF_SIZE,
00444                             SEL_BOX_SIZE,
00445                             SEL_BOX_SIZE);
00446       if(m_hits.size()) {
00447         // We did a right-click on an atom or bond -- delete it!
00448         if(m_hits[0].type() == Primitive::AtomType) {
00449           // don't delete H-? atom when adjust hydrogens is on
00450           OBAtom *atom = widget->molecule()->GetAtom(m_hits[0].name());
00451           if (m_addHydrogens && atom->IsHydrogen() && atom->GetValence())
00452             return undo;
00453           undo = new DeleteAtomDrawCommand(widget->molecule(), m_hits[0].name(),
00454                                            m_addHydrogens);
00455         }
00456         if(m_hits[0].type() == Primitive::BondType) {
00457           // don't delete ?-H bonds when adjust hydrogens is on
00458           OBBond *bond = widget->molecule()->GetBond(m_hits[0].name());
00459           if (m_addHydrogens)
00460             if (bond->GetBeginAtom()->IsHydrogen() || bond->GetEndAtom()->IsHydrogen())
00461               return undo;
00462           undo = new DeleteBondDrawCommand(widget->molecule(), m_hits[0].name(),
00463                                            m_addHydrogens);
00464         }
00465       }
00466       widget->molecule()->update();
00467     }
00468 
00469     return undo;
00470   }
00471 
00472   // Zoom the camera
00473   QUndoCommand* DrawTool::wheel(GLWidget *widget, const QWheelEvent *event)
00474   {
00475     // let's set the reference to be the center of the visible
00476     // part of the molecule.
00477     Eigen::Vector3d atomsBarycenter(0., 0., 0.);
00478     double sumOfWeights = 0.;
00479     if(widget->molecule()->NumAtoms()) {
00480       std::vector<OpenBabel::OBNodeBase*>::iterator i;
00481       for ( Atom *atom = static_cast<Atom*>(widget->molecule()->BeginAtom(i));
00482             atom; atom = static_cast<Atom*>(widget->molecule()->NextAtom(i))) {
00483         Eigen::Vector3d transformedAtomPos = widget->camera()->modelview() * atom->pos();
00484         double atomDistance = transformedAtomPos.norm();
00485         double dot = transformedAtomPos.z() / atomDistance;
00486         double weight = exp(-30. * (1. + dot));
00487         sumOfWeights += weight;
00488         atomsBarycenter += weight * atom->pos();
00489       }
00490       atomsBarycenter /= sumOfWeights;
00491     }
00492 
00493     Navigate::zoom(widget, atomsBarycenter, -MOUSE_WHEEL_SPEED*event->delta());
00494     widget->update();
00495 
00496     return NULL;
00497   }
00498 
00499   Atom *DrawTool::newAtom(GLWidget *widget, const QPoint& p)
00500   {
00501     widget->molecule()->BeginModify();
00502     Atom *atom = static_cast<Atom*>(widget->molecule()->NewAtom());
00503     moveAtom(widget, atom, p);
00504     atom->SetAtomicNum(element());
00505     widget->molecule()->EndModify();
00506     return atom;
00507   }
00508 
00509   void DrawTool::moveAtom(GLWidget *widget, Atom *atom, const QPoint& p)
00510   {
00511     Eigen::Vector3d refPoint;
00512     if(m_beginAtom) {
00513       refPoint = m_beginAtom->pos();
00514     } else {
00515       refPoint = widget->center();
00516     }
00517     Eigen::Vector3d newAtomPos = widget->camera()->unProject(p, refPoint);
00518 
00519     atom->setPos(newAtomPos);
00520   }
00521 
00522 
00523   Bond *DrawTool::newBond(Molecule *molecule, Atom *beginAtom, Atom *endAtom)
00524   {
00525     molecule->BeginModify();
00526     Bond *bond = (Bond *)molecule->NewBond();
00527     bond->SetBondOrder(bondOrder());
00528     bond->SetBegin(beginAtom);
00529     bond->SetEnd(endAtom);
00530     beginAtom->AddBond(bond);
00531     endAtom->AddBond(bond);
00532     molecule->EndModify();
00533     return bond;
00534   }
00535 
00536   //
00537   // Settings widget
00538   // and associated signals/slots
00539   //
00540 
00541   void DrawTool::elementChanged( int index )
00542   {
00543     // The popup menu returns this signal
00544     // First case: we pick a common element from the popup
00545     if (index < m_elementsIndex.size() - 1) {
00546       setElement(m_elementsIndex[index]);
00547     }
00548     // Second case: we have a custom element "Other..."
00549     // Bring up the periodic table widget
00550     else {
00551       if (m_periodicTable) {
00552         m_periodicTable->show();
00553       }
00554     }
00555   }
00556 
00557   void DrawTool::customElementChanged( int index )
00558   {
00559     // Set the element so we can draw with it
00560     setElement(index);
00561 
00562     // Check to see if we already have this in the comboBox list
00563     // If not, we get back -1 and need to create a new item
00564     int comboItem = m_elementsIndex.indexOf(index);
00565     if (comboItem != -1) {
00566       m_comboElements->setCurrentIndex(comboItem);
00567       return; // we found it in the list, so we're done
00568     }
00569 
00570     // Find where we should put the new entry
00571     // (i.e., in order by atomic number)
00572     int position = 0;
00573     foreach(int entry, m_elementsIndex) {
00574       // Two cases: entry > index -- insert the new element before this one
00575       // Or... we hit the "Other" menu choice -- also insert here
00576       if (entry > index || entry == 0)
00577         break;
00578 
00579       ++position;
00580     }
00581 
00582     // And now we set up a new entry into the combo list
00583     QString entryName(elementTranslator.name(index)); // (e.g., "Hydrogen")
00584     entryName += " (" + QString::number(index) + ')';
00585 
00586     m_elementsIndex.insert(position, index);
00587     m_comboElements->insertItem(position, entryName);
00588     m_comboElements->setCurrentIndex(position);
00589   }
00590 
00591   void DrawTool::setElement( int index )
00592   {
00593     m_element = index;
00594   }
00595 
00596   int DrawTool::element() const
00597   {
00598     return m_element;
00599   }
00600 
00601   void DrawTool::bondOrderChanged( int index )
00602   {
00603     setBondOrder(index + 1);
00604   }
00605 
00606   void DrawTool::setBondOrder( int index )
00607   {
00608     m_bondOrder = index;
00609   }
00610 
00611   int DrawTool::bondOrder() const
00612   {
00613     return m_bondOrder;
00614   }
00615 
00616   void DrawTool::setAddHydrogens( int state )
00617   {
00618     m_addHydrogens = state;
00619   }
00620 
00621   int DrawTool::addHydrogens() const
00622   {
00623     return m_addHydrogens;
00624   }
00625 
00626   void DrawTool::setInsertFragmentMode( bool mode )
00627   {
00628     m_insertFragmentMode = mode;
00629   }
00630 
00631   QWidget *DrawTool::settingsWidget() {
00632     if(!m_settingsWidget) {
00633       m_settingsWidget = new QWidget;
00634 
00635       QLabel *labelElement = new QLabel(tr("Element:"));
00636       labelElement->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred);
00637       labelElement->setMaximumHeight(15);
00638 
00639       // Small popup with 10 most common elements for organic chemistry
00640       // (and extra for "other" to bring up periodic table window)
00641       m_comboElements = new QComboBox(m_settingsWidget);
00642       m_comboElements->addItem(elementTranslator.name(1) + " (1)");
00643       m_elementsIndex.append(1);
00644       m_comboElements->addItem(elementTranslator.name(5) + " (5)");
00645       m_elementsIndex.append(5);
00646       m_comboElements->addItem(elementTranslator.name(6) + " (6)");
00647       m_elementsIndex.append(6);
00648       m_comboElements->addItem(elementTranslator.name(7) + " (7)");
00649       m_elementsIndex.append(7);
00650       m_comboElements->addItem(elementTranslator.name(8) + " (8)");
00651       m_elementsIndex.append(8);
00652       m_comboElements->addItem(elementTranslator.name(9) + " (9)");
00653       m_elementsIndex.append(9);
00654       m_comboElements->addItem(elementTranslator.name(15) + " (15)");
00655       m_elementsIndex.append(15);
00656       m_comboElements->addItem(elementTranslator.name(16) + " (16)");
00657       m_elementsIndex.append(16);
00658       m_comboElements->addItem(elementTranslator.name(17) + " (17)");
00659       m_elementsIndex.append(17);
00660       m_comboElements->addItem(elementTranslator.name(35) + " (35)");
00661       m_elementsIndex.append(35);
00662       m_comboElements->addItem(tr("Other..."));
00663       m_elementsIndex.append(0);
00664       m_comboElements->setCurrentIndex(2);
00665 
00666       QLabel *labelBO = new QLabel(tr("Bond Order:"));
00667       labelBO->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred);
00668       labelBO->setMaximumHeight(15);
00669 
00670       m_comboBondOrder = new QComboBox(m_settingsWidget);
00671       m_comboBondOrder->addItem(tr("Single"));
00672       m_comboBondOrder->addItem(tr("Double"));
00673       m_comboBondOrder->addItem(tr("Triple"));
00674 
00675       // Improve the layout of the widgets
00676       QHBoxLayout* tmp = new QHBoxLayout;
00677       tmp->addWidget(m_comboElements);
00678       tmp->addStretch(1);
00679       QHBoxLayout* tmp2 = new QHBoxLayout;
00680       tmp2->addWidget(m_comboBondOrder);
00681       tmp2->addStretch(1);
00682       QGridLayout* grid = new QGridLayout;
00683       grid->addWidget(labelElement, 0, 0, Qt::AlignRight);
00684       grid->addLayout(tmp, 0, 1);
00685       grid->addWidget(labelBO, 1, 0, Qt::AlignRight);
00686       grid->addLayout(tmp2, 1, 1);
00687 
00688       m_addHydrogensCheck = new QCheckBox(tr("Adjust Hydrogens"), m_settingsWidget);
00689       m_addHydrogensCheck->setCheckState((Qt::CheckState)m_addHydrogens);
00690 
00691       m_fragmentButton = new QPushButton(m_settingsWidget);
00692       m_fragmentButton->setText(tr("Fragment Library..."));
00693       QHBoxLayout* fragmentLayout = new QHBoxLayout;
00694       fragmentLayout->addStretch(1);
00695       fragmentLayout->addWidget(m_fragmentButton);
00696       fragmentLayout->addStretch(1);
00697       connect(m_fragmentButton, SIGNAL(clicked(bool)),
00698               this, SLOT(showFragmentDialog(bool)));
00699 
00700       m_fragmentDialog = new InsertFragmentDialog(m_settingsWidget);
00701       connect(m_fragmentDialog, SIGNAL(setInsertMode(bool)),
00702               this, SLOT(setInsertFragmentMode(bool)));
00703 
00704       m_periodicTable = new PeriodicTableView(m_settingsWidget);
00705       connect(m_periodicTable, SIGNAL(elementChanged(int)),
00706               this, SLOT(customElementChanged(int)));
00707 
00708       m_layout = new QVBoxLayout();
00709       m_layout->addLayout(grid);
00710       m_layout->addWidget(m_addHydrogensCheck);
00711       m_layout->addLayout(fragmentLayout);
00712       m_layout->addStretch(1);
00713       m_settingsWidget->setLayout(m_layout);
00714 
00715       connect(m_comboElements, SIGNAL(currentIndexChanged(int)),
00716               this, SLOT(elementChanged(int)));
00717 
00718       connect(m_comboBondOrder, SIGNAL(currentIndexChanged(int)),
00719               this, SLOT(bondOrderChanged(int)));
00720 
00721       connect(m_addHydrogensCheck, SIGNAL(stateChanged(int)),
00722               this, SLOT(setAddHydrogens(int)));
00723 
00724       connect(m_settingsWidget, SIGNAL(destroyed()),
00725               this, SLOT(settingsWidgetDestroyed()));
00726     }
00727 
00728     return m_settingsWidget;
00729   }
00730 
00731   void DrawTool::settingsWidgetDestroyed() {
00732     m_settingsWidget = 0;
00733   }
00734 
00735   void DrawTool::showFragmentDialog(bool) {
00736         if (m_fragmentDialog->isVisible()) {
00737       m_fragmentDialog->hide();
00738       m_insertFragmentMode = false;
00739     } else {
00740         m_fragmentDialog->show();
00741         }
00742   }
00743 
00744   void DrawTool::writeSettings(QSettings &settings) const
00745   {
00746     Tool::writeSettings(settings);
00747     settings.setValue("currentElement", element());
00748     settings.setValue("bondOrder", m_bondOrder);
00749     settings.setValue("addHydrogens", m_addHydrogens);
00750     if (m_fragmentDialog) {
00751       settings.setValue("smiles", m_fragmentDialog->smilesString());
00752       settings.setValue("fragmentPath", m_fragmentDialog->directoryList().join("\n"));
00753     }
00754   }
00755 
00756   void DrawTool::readSettings(QSettings &settings)
00757   {
00758     Tool::readSettings(settings);
00759     setAddHydrogens(settings.value("addHydrogens", 1).toInt());
00760     setElement(settings.value("currentElement", 6).toInt());
00761     setBondOrder(settings.value("bondOrder", 1).toInt());
00762     if (m_comboElements)
00763     {
00764       int index = 0;
00765       for (int i = 0; i < m_elementsIndex.size() - 1; ++i)
00766         if (m_elementsIndex.at(i) == element()) index = i;
00767       m_comboElements->setCurrentIndex(index);
00768     }
00769     if(m_addHydrogensCheck)
00770       m_addHydrogensCheck->setCheckState((Qt::CheckState)m_addHydrogens);
00771     if(m_fragmentDialog) {
00772       m_fragmentDialog->setSmilesString(settings.value("smiles").toString());
00773       if (settings.contains("fragmentPath")) {
00774         QString directoryList = settings.value("fragmentPath").toString();
00775         m_fragmentDialog->setDirectoryList(directoryList.split('\n'));
00776       }
00777     }
00778   }
00779 }
00780 
00781 #include "drawtool.moc"
00782 
00783 Q_EXPORT_PLUGIN2(drawtool, Avogadro::DrawToolFactory)

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