Logo Search packages:      
Sourcecode: massxpert version File versions

mzCalculationDlg.cpp

/* massXpert - the true massist's program.
   --------------------------------------
   Copyright(C) 2006,2007 Filippo Rusconi

   http://www.massxpert.org/massXpert

   This file is part of the massXpert project.

   The massxpert project is the successor to the "GNU polyxmass"
   project that is an official GNU project package(see
   www.gnu.org). The massXpert project is not endorsed by the GNU
   project, although it is released ---in its entirety--- under the
   GNU General Public License. A huge part of the code in massXpert
   is actually a C++ rewrite of code in GNU polyxmass. As such
   massXpert was started at the Centre National de la Recherche
   Scientifique(FRANCE), that granted me the formal authorization to
   publish it under this Free Software License.

   This software is free software; you can redistribute it and/or
   modify it under the terms of the GNU  General Public
   License version 3, as published by the Free Software Foundation.
   

   This software is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   General Public License for more details.

   You should have received a copy of the GNU General Public License
   along with this software; if not, write to the

   Free Software Foundation, Inc.,

   51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
*/


/////////////////////// Qt includes
#include <QMessageBox>


/////////////////////// Local includes
#include "mzCalculationDlg.hpp"
#include "application.hpp"
#include "polChemDef.hpp"


namespace massXpert
{

  MzCalculationDlg::MzCalculationDlg(QWidget *parent,
                              const PolChemDef *polChemDef,
                              const IonizeRule *ionizeRule)
    : QDialog(parent), mp_polChemDef(polChemDef)
  {
    Q_ASSERT(parent);
    Q_ASSERT(polChemDef);
    Q_ASSERT(ionizeRule);
  
    m_ionizeRule = *ionizeRule;

    m_ui.setupUi(this);

    setupTreeView();

    m_ui.srcIonizeRuleChargeSpinBox->setRange(1, 1000000000);
    m_ui.srcIonizeRuleLevelSpinBox->setRange(0, 1000000000);
  
    m_ui.destIonizeRuleChargeSpinBox->setRange(1, 1000000000);
    m_ui.destIonizeRuleStartLevelSpinBox->setRange(0, 1000000000);
    m_ui.destIonizeRuleEndLevelSpinBox->setRange(0, 1000000000);


    m_ui.srcIonizeRuleFormulaLineEdit->setText(m_ionizeRule.formula());
    m_ui.srcIonizeRuleChargeSpinBox->setValue(m_ionizeRule.charge());
    m_ui.srcIonizeRuleLevelSpinBox->setValue(m_ionizeRule.level());
    
    m_ui.destIonizeRuleFormulaLineEdit->setText(m_ionizeRule.formula());
    m_ui.destIonizeRuleChargeSpinBox->setValue(m_ionizeRule.charge());
    m_ui.destIonizeRuleStartLevelSpinBox->setValue(m_ionizeRule.level());
    m_ui.destIonizeRuleEndLevelSpinBox->setValue(m_ionizeRule.level());


    // The results-exporting menus. ////////////////////////////////

    QStringList comboBoxItemList;

    comboBoxItemList 
      << tr("To Clipboard") 
      << tr("To File")
      << tr("Select File");
  
    m_ui.exportResultsComboBox->addItems(comboBoxItemList);
  
    connect(m_ui.exportResultsComboBox,
           SIGNAL(activated(int)),
           this,
           SLOT(exportResults(int)));

    mpa_resultsString = new QString();
  
    //////////////////////////////////// The results-exporting menus.
  

    QSettings settings 
     (static_cast<Application *>(qApp)->configSettingsFilePath(), 
       QSettings::IniFormat);
  
    settings.beginGroup("mz_calculation_dlg");

    restoreGeometry(settings.value("geometry").toByteArray());

    m_ui.ponderableSplitter->
      restoreState(settings.value("ponderableSplitter").toByteArray());
  
    settings.endGroup();

    connect(m_ui.calculatePushButton,
           SIGNAL(clicked()),
           this,
           SLOT(calculate()));
  }


  MzCalculationDlg::~MzCalculationDlg()
  {
    delete mpa_resultsString;
  
    delete mpa_mzTreeViewModel;
  
    delete mpa_mzProxyModel;

    freeIonizableList();
  }


  void 
  MzCalculationDlg::closeEvent(QCloseEvent *event)
  {
    if (event)
      printf("%s", "");
  
    QSettings settings 
     (static_cast<Application *>(qApp)->configSettingsFilePath(), 
       QSettings::IniFormat);
  
    settings.beginGroup("mz_calculation_dlg");

    settings.setValue("geometry", saveGeometry());
  
    settings.setValue("ponderableSplitter", 
                   m_ui.ponderableSplitter->saveState());

    settings.endGroup();
  }


  void
  MzCalculationDlg::setupTreeView()
  {
    // Model stuff all thought for sorting.
    mpa_mzTreeViewModel = 
      new MzCalculationTreeViewModel(&m_ionizableList, this);
  
    mpa_mzProxyModel = new MzCalculationTreeViewSortProxyModel(this);
    mpa_mzProxyModel->setSourceModel(mpa_mzTreeViewModel);
  
    m_ui.mzTreeView->setModel(mpa_mzProxyModel);
    m_ui.mzTreeView->setParentDlg(this);
    mpa_mzTreeViewModel->setTreeView(m_ui.mzTreeView);
  }


  void
  MzCalculationDlg::calculate()
  {
    // First get all the data for the source ionizable.

    // The source ionizeRule.
    IonizeRule srcIonizeRule;
    if (!getSrcIonizeRuleData(&srcIonizeRule))
      return;
    
    Ponderable *ponderable = getSourcePonderable();
    if (!ponderable)
      return;
    
    // Create an Ionizable with empty masses but with proper
    // IonizeRule. Note that we check if the IonizeRule has a non-0
    // level, in which case we tell so to the caller with a true
    // boolean.
    Ionizable ionizable(mp_polChemDef, "NOT_SET", *ponderable,
                   srcIonizeRule,
                  (srcIonizeRule.level() ? true : false));
    
    // At this point the ionizable is fully qualified.

    // No longer in use.
    delete ponderable;
    
    // At this point, the source ionizable is filled with data. And we
    // know the data are correct because everything was validated.

    // The destination ionizeRule(note that the m_level member datum
    // is not set as it will be generated during the for loop later;
    // this does not impede validation of the IonizeRule).
    IonizeRule destIonizeRule;
    if (!getDestIonizeRuleData(&destIonizeRule))
      return;
    
    // Get the destination start/end ionization levels and make sure
    // they are in an increasing order.
    int startLevel = m_ui.destIonizeRuleStartLevelSpinBox->value();
    int endLevel = m_ui.destIonizeRuleEndLevelSpinBox->value();
    
    if (startLevel > endLevel)
      {
      int temp = endLevel;
      endLevel = startLevel;
      startLevel = temp;
      }

    // Empty the treeView model, so that we can put fresh data in it.
    mpa_mzTreeViewModel->removeAll();
  
    for (int level = startLevel ; level < endLevel + 1; ++level)
      {
      destIonizeRule.setLevel(level);
      
      // Reionize the ionizable.
      if(ionizable.ionize(destIonizeRule) == -1)
        {
          QMessageBox::warning 
           (this, 
             tr("massXpert - m/z Ratio Calculator"),
             tr("%1@%2\n"
               "Failed to perform reionization.")
             .arg(__FILE__)
             .arg(__LINE__),
             QMessageBox::Ok);
          
          return;
        }
      else
        {
          Ionizable *newIonizable = 
            new Ionizable(ionizable);
          
          mpa_mzTreeViewModel->addIonizable(newIonizable);
        }
      }
  }


  bool
  MzCalculationDlg::getSrcIonizeRuleData(IonizeRule *ionizeRule)
  {
    Q_ASSERT(ionizeRule);

    ionizeRule->setFormula(m_ui.srcIonizeRuleFormulaLineEdit->text());
    ionizeRule->setCharge(m_ui.srcIonizeRuleChargeSpinBox->value());
    ionizeRule->setLevel(m_ui.srcIonizeRuleLevelSpinBox->value());

    if (!ionizeRule->validate(mp_polChemDef->atomList()))
      {
      QMessageBox::warning 
       (this, 
         tr("massXpert - m/z Ratio Calculator"),
         tr("%1@%2\n"
             "Failed to validate initial ionization rule.")
         .arg(__FILE__)
         .arg(__LINE__),
         QMessageBox::Ok);

      return false;
      }
  
    return true;
  }


  bool
  MzCalculationDlg::getDestIonizeRuleData(IonizeRule *ionizeRule)
  {
    Q_ASSERT(ionizeRule);
    
    ionizeRule->setFormula(m_ui.destIonizeRuleFormulaLineEdit->text());
    ionizeRule->setCharge(m_ui.destIonizeRuleChargeSpinBox->value());
    // The level is dealt with in another function, as it might
    // encompass more than one single value(see calculate()). Note
    // that if level is 0, this does not invalidate the ionizeRule.

    if (!ionizeRule->validate(mp_polChemDef->atomList()))
      {
      QMessageBox::warning 
       (this, 
         tr("massXpert - m/z Ratio Calculator"),
         tr("%1@%2\n"
             "Failed to validate target ionization rule.")
         .arg(__FILE__)
         .arg(__LINE__),
         QMessageBox::Ok);

      return false;
      }
    
    return true;
  }


  Ponderable *
  MzCalculationDlg::getSourcePonderable()
  {
    Application *application = static_cast<Application *>(qApp);
    QLocale locale = application->locale();
    
    QString text;
    
    double mono = 0;
    double avg = 0;

    bool ok = false;
    
    // Mono mass
    text = m_ui.monoLineEdit->text();
    
    if (text.isEmpty())
      mono = 0;
    else
      {
      mono = locale.toDouble(text, &ok);

      if(!mono && !ok)
        {
          QMessageBox::warning 
           (this, 
             tr("massXpert - m/z Ratio Calculator"),
             tr("%1@%2\n"
               "Failed to read mono mass.")
             .arg(__FILE__)
             .arg(__LINE__),
             QMessageBox::Ok);
          
          return 0;
        }
      }

    // Avg mass
    text = m_ui.avgLineEdit->text();
    
    if (text.isEmpty())
      avg = 0;
    else
      {
      avg = locale.toDouble(text, &ok);

      if(!avg && !ok)
        {
          QMessageBox::warning 
           (this, 
             tr("massXpert - m/z Ratio Calculator"),
             tr("%1@%2\n"
               "Failed to read mono mass.")
             .arg(__FILE__)
             .arg(__LINE__),
             QMessageBox::Ok);
          
          return 0;
        }
      }

    // At this point we can allocate the Ponderable:
    return new Ponderable(mono, avg);
  }
  

  void 
  MzCalculationDlg::freeIonizableList()
  {
    while(!m_ionizableList.isEmpty())
      delete m_ionizableList.takeFirst();
  }


  // The results-exporting functions. ////////////////////////////////
  // The results-exporting functions. ////////////////////////////////
  // The results-exporting functions. ////////////////////////////////
  void
  MzCalculationDlg::exportResults(int index)
  {
    // Remember that we had set up the combobox with the following strings:
    // << tr("To &Clipboard") 
    // << tr("To &File")
    // << tr("&Select File");

    if (index == 0)
      {
      exportResultsClipboard();
      }
    else if (index == 1)
      {
      exportResultsFile();
      }
    else if (index == 2)
      {
      selectResultsFile();
      }
    else 
      Q_ASSERT(0);
  
  }


  void
  MzCalculationDlg::prepareResultsTxtString()
  {
    mpa_resultsString->clear();
  
    *mpa_resultsString += QObject::tr("\n---------------------------\n"
                               "m/z Calculations: \n"
                               "---------------------------\n");
  
    QString value;
  
    *mpa_resultsString += QObject::tr("\nSource conditions:\n"
                               "------------------\n");
  
    *mpa_resultsString += QObject::tr("Mono mass: %1")
      .arg(m_ui.monoLineEdit->text());
  
    *mpa_resultsString += QObject::tr(" - Avg mass: %1\n")
      .arg(m_ui.avgLineEdit->text());
    
    *mpa_resultsString += QObject::tr("Ionization formula: %1\n")
      .arg(m_ui.srcIonizeRuleFormulaLineEdit->text());
  
    *mpa_resultsString += QObject::tr("Ionization charge: %1 - ")
      .arg(m_ui.srcIonizeRuleChargeSpinBox->value());
  
    *mpa_resultsString += QObject::tr("Ionization level: %1\n")
      .arg(m_ui.srcIonizeRuleLevelSpinBox->value());
  
    *mpa_resultsString += QObject::tr("\nDestination conditions:\n"
                               "-----------------------\n");

    *mpa_resultsString += QObject::tr("Ionization formula: %1\n")
      .arg(m_ui.destIonizeRuleFormulaLineEdit->text());
  
    *mpa_resultsString += QObject::tr("Ionization charge: %1 - ")
      .arg(m_ui.destIonizeRuleChargeSpinBox->value());
  
    *mpa_resultsString += QObject::tr("Start level: %1 - ")
      .arg(m_ui.destIonizeRuleStartLevelSpinBox->value());

    *mpa_resultsString += QObject::tr("End level: %1\n\n\n")
      .arg(m_ui.destIonizeRuleEndLevelSpinBox->value());
  
    MzCalculationTreeViewModel *model = 
      static_cast<MzCalculationTreeViewModel *>(m_ui.mzTreeView->model());
    Q_ASSERT(model);
  
    int rowCount = model->rowCount();
    //   qDebug() << __FILE__ << __LINE__ << "rowCount" << rowCount;
    if (!rowCount)
      return;

    QString mzString;

    for (int iter = 0; iter < rowCount; ++iter)
      {
      QModelIndex currentIndex = model->index(iter,
                                     MZ_CALC_LEVEL_COLUMN,
                                     QModelIndex());

      Q_ASSERT(currentIndex.isValid());

      mzString += 
        QObject::tr("Level: %1 -- ").arg(model->data(currentIndex, 
                                            Qt::DisplayRole)
                                   .toString());
      
      currentIndex = model->index(iter,
                             MZ_CALC_MONO_COLUMN,
                             QModelIndex());
      
      Q_ASSERT(currentIndex.isValid());
      
      mzString += 
        QObject::tr("Mono: %1 -- ").arg(model->data(currentIndex, 
                                           Qt::DisplayRole)
                                  .toString());
      
      currentIndex = model->index(iter,
                             MZ_CALC_AVG_COLUMN,
                             QModelIndex());
      
      Q_ASSERT(currentIndex.isValid());
      
      mzString += 
        QObject::tr("Avg: %1\n").arg(model->data(currentIndex, 
                                          Qt::DisplayRole)
                               .toString());
      }

    *mpa_resultsString += mzString;
  }


  bool 
  MzCalculationDlg::exportResultsClipboard()
  {
    prepareResultsTxtString();
  
    QClipboard *clipboard = QApplication::clipboard();

    clipboard->setText(*mpa_resultsString, QClipboard::Clipboard);
  
    return true;
  }


  bool 
  MzCalculationDlg::exportResultsFile()
  {
    if (m_resultsFilePath.isEmpty())
      {
      if(!selectResultsFile())
        return false;
      }
  
    QFile file(m_resultsFilePath);
  
    if (!file.open(QIODevice::WriteOnly | QIODevice::Append))
      {
      QMessageBox::information(this, 
                          tr("massXpert - Export Data"),
                          tr("Failed to open file in append mode."),
                          QMessageBox::Ok);
      return false;
      }
  
    QTextStream stream(&file);
    stream.setCodec("UTF-8");

    prepareResultsTxtString();
  
    stream << *mpa_resultsString;
  
    file.close();

    return true;
  }


  bool 
  MzCalculationDlg::selectResultsFile()
  {
    m_resultsFilePath = 
      QFileDialog::getSaveFileName(this, tr("Select File To Export Data To"),
                            QDir::homePath(),
                            tr("Data files(*.dat *.DAT)"));
  
    if (m_resultsFilePath.isEmpty())
      return false;

    return true;
  }
  //////////////////////////////////// The results-exporting functions.
  //////////////////////////////////// The results-exporting functions.
  //////////////////////////////////// The results-exporting functions.

} // namespace massXpert

Generated by  Doxygen 1.6.0   Back to index