.\n"
"\n");
} // namespace massXpert
massxpert-3.6.0/gui/about_history.hpp 0000664 0000000 0000000 00000007515 12577256262 0017764 0 ustar 00root root 0000000 0000000
namespace massXpert
{
QString history ("\n"
"\n"
"\n"
" \n"
" massxpert-history\n"
"\n"
"\n"
"This is a brief history of massXpert
\n"
"
\n"
"
\n"
"1998-2000
\n"
"
\n"
"The name massXpert comes from a project I started while I was a\n"
"post-doctoral fellow of the Ecole Polytechnique at the Institut\n"
"Européen de Chimie et Biologie, Pessac(Bordeaux), France.
\n"
"
\n"
"The massXpert program was published in Bioinformatics(Rusconi, F. and Belghazi, M. Desktop prediction/analysis of mass spectrometric data in proteomic projects by using massXpert. Bioinformatics 2002 18(4):644-5).
\n"
"
\n"
"At that time, MS-Windows was at the Windows NT 4.0 version and the next\n"
"big release was going to be \"you'll see what you'll see\" : MS-Windows\n"
"2000.
\n"
"
\n"
"When I tried massXpert on that new version(one colleague had it with a\n"
"new machine), I discovered that my software would not run normally(the\n"
"editor was broken). The Microsofties would advise to \"buy a new version\n"
"of the compiler environment and rebuild\". Noooo! I did not want to\n"
"continue paying for only using something I had produced !
\n"
"
\n"
"2001-2006
\n"
"
\n"
"I decided during fall 1999 that I would stop using Microsoft products\n"
"for my development. At the beginning of 2000 I started as a CNRS research staff in a new laboratory and decided to start fresh: I switched to GNU/Linux(I never looked back). After some months of learning, I felt mature to start a new development project that would eventually\n"
"become an official GNU package: GNU polyxmass.
\n"
"
\n"
"The GNU polyxmass software, much more powerful than massXpert was, was published in BMC Bioinformatics in 2006(Rusconi, F., GNU polyxmass: a software framework for mass spectrometric simulations of linear(bio-)polymeric analytes. BMC Bioinformatics 2006, 7:226; published 27 April 2006).
\n"
"
\n"
"Following that publication I got a lot of feedback(very positive, in a\n"
"way) along the lines: \"Hey, your software looks very interesting; it's\n"
"only a pity we cannot use it because it runs on GNU/Linux, and we only\n"
"use MS-Windows and MacOSX!\".
\n"
"
\n"
"2007-
\n"
"
\n"
"I decided to make a full rewrite of GNU polyxmass and the software that\n"
"you are running now is the product of that rewrite. I decided to\n"
"\"recycle\" the massXpert name because this soft is written in C++, as\n"
"was its ancestor. Also, because the first MS-Windows-based massXpert\n"
"project is not developed anymore, taking that name was kind of a\n"
"\"revival\" which I enjoyed. However, the toolkit I used this time is\n"
"not the Microsoft Foundation Classes(first massXpert version) but the\n"
"Trolltech Qt framework(this software, see the \"About Qt\" help menu).
\n"
"
\n"
"Coding with Qt has one big advantage: it allows the developer to code\n"
"once and to compile on the three main platforms available today:\n"
"GNU/Linux, MacOSX, MS-Windows. Another advantage is that Qt is\n"
"wonderful software(Free Software).
\n"
"
\n"
"Enjoy massXpert !
\n"
"
\n"
"Filippo Rusconi,
\n"
"author of massXpert
\n"
"
\n"
"\n"
"\n");
} // namespace massXpert
massxpert-3.6.0/gui/application.cpp 0000664 0000000 0000000 00000040651 12577256262 0017365 0 ustar 00root root 0000000 0000000 /* 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
#include
/////////////////////// Local includes
#include "config.h"
#include "application.hpp"
#include "polChemDefCatParser.hpp"
#include "polChemDefWnd.hpp"
#include "calculatorWnd.hpp"
#include "configurationSettingsDlg.hpp"
#include "sequenceEditorWnd.hpp"
namespace massXpert
{
Application::Application(int &argc, char **argv)
: QApplication(argc, argv)
{
QPixmap splashPixmap(":/images/splashscreen.png");
mpa_splash = new QSplashScreen(splashPixmap, Qt::WindowStaysOnTopHint);
mpa_splash->show();
QTimer::singleShot(2000, this, SLOT(destroySplash()));
// We now have to perform a number of initialization steps.
QCoreApplication::setOrganizationName("massXpert");
QCoreApplication::setOrganizationDomain("massxpert.org");
QCoreApplication::setApplicationName("massXpert");
mp_lastFocusedWnd = 0;
QPixmap iconPixmap(":/images/massxpert-icon-32.png");
QIcon icon(iconPixmap);
setWindowIcon(icon);
// Initialize the user specifications.
m_userSpec.setUserName();
m_configSettingsFilePath = QString(QDir::homePath() +
QDir::separator() +
".massxpert" +
QDir::separator() +
"configSettings.ini");
// Initialize the configuration directories.
int result = -1;
if (!m_configSettings.initializeSystemConfig())
{
// We still have a chance to read the settings from the
// configuration settings file for current user in
// $HOME/.massxpert/configSettings.ini.
result = systemConfigReadFileSettings();
if(!result)
result = systemConfigManuallySetSettings();
if(!result)
{
QMessageBox::critical(0, tr("massXpert - Configuration Settings"),
tr("%1@%2\n"
"Failed to configure massXpert.\n"
"The software will not work as "
"intended.")
.arg(__FILE__)
.arg(__LINE__),
QMessageBox::Ok);
}
}
if (!m_configSettings.initializeUserConfig())
{
qDebug() << __FILE__ << __LINE__
<< "User configuration settings result" << result;
}
initializeDecimalPlacesOptions();
PolChemDefCatParser parser;
parser.setConfigSysUser(POLCHEMDEF_CAT_PARSE_BOTH_CONFIG);
parser.setPendingMode(POLCHEMDEF_CAT_PARSE_APPEND_CONFIG);
if (parser.parseFiles(m_configSettings, &m_polChemDefCatList) == -1)
{
QMessageBox::critical(0, tr("massXpert - Configuration Settings"),
tr("%1@%2\n"
"Failed to parse the polymer chemistry "
"definition catalogues.\n"
"The software will not work as intended.")
.arg(__FILE__)
.arg(__LINE__),
QMessageBox::Ok);
}
}
Application::~Application()
{
// List of all the polymer chemistry definition specifications that
// were found in the different catalogue files on the system.
while(! m_polChemDefCatList.isEmpty())
delete m_polChemDefCatList.takeFirst();
}
const QLocale &
Application::locale()
{
return m_locale;
}
UserSpec *
Application::userSpec()
{
return &m_userSpec;
}
ConfigSettings *
Application::configSettings()
{
return &m_configSettings;
}
bool
Application::systemConfigManuallySetSettings()
{
// Apparently, the system configuration directory was not found to
// be of a canonical structure. This might be due to the
// relocation of the package. Let the user tell where the package
// is located.
ConfigurationSettingsDlg dlg(&m_configSettings);
int result = dlg.exec();
if (result)
return true;
else
return false;
}
bool
Application::systemConfigReadFileSettings()
{
QSettings settings(m_configSettingsFilePath,
QSettings::IniFormat);
settings.beginGroup("system_data_config_settings");
QDir dir;
dir.setPath(settings.value("system_data_dir").toString());
if (!dir.exists())
return false;
else
m_configSettings.setSystemDataDir(dir.absolutePath());
dir.setPath(settings.value("system_pol_chem_def_cat_dir").toString());
if (!dir.exists())
return false;
else
m_configSettings.setSystemPolChemDefCatDir(dir.absolutePath());
dir.setPath(settings.value("system_localization_dir").toString());
if (!dir.exists())
return false;
else
m_configSettings.setSystemLocalizationDir(dir.absolutePath());
settings.endGroup();
return true;
}
void
Application::initializeDecimalPlacesOptions()
{
// The decimal places should be read from the configuration
// settings.
QSettings settings(m_configSettingsFilePath,
QSettings::IniFormat);
settings.beginGroup("decimal_places_options");
MXP_ATOM_DEC_PLACES =
settings.value("MXP_ATOM_DEC_PLACES", 10).toInt();
// qDebug() << __FILE__ << __LINE__
// << "MXP_ATOM_DEC_PLACES" << MXP_ATOM_DEC_PLACES;
MXP_OLIGOMER_DEC_PLACES =
settings.value("MXP_OLIGOMER_DEC_PLACES", 5).toInt();
// qDebug() << __FILE__ << __LINE__
// << "MXP_OLIGOMER_DEC_PLACES" << MXP_OLIGOMER_DEC_PLACES;
MXP_POLYMER_DEC_PLACES =
settings.value("MXP_POLYMER_DEC_PLACES", 3).toInt();
// qDebug() << __FILE__ << __LINE__
// << "MXP_POLYMER_DEC_PLACES" << MXP_POLYMER_DEC_PLACES;
MXP_PH_PKA_DEC_PLACES =
settings.value("MXP_PH_PKA_DEC_PLACES", 2).toInt();
// qDebug() << __FILE__ << __LINE__
// << "MXP_PH_PKA_DEC_PLACES" << MXP_PH_PKA_DEC_PLACES;
settings.endGroup();
}
const QString &
Application::configSettingsFilePath()
{
return m_configSettingsFilePath;
}
void
Application::setLastFocusedWnd(SequenceEditorWnd *wnd)
{
mp_lastFocusedWnd = wnd;
// qDebug() << __FILE__<< __LINE__ << wnd;
}
QList *
Application::polChemDefCatList()
{
return &m_polChemDefCatList;
}
QList *
Application::polChemDefList()
{
return &m_polChemDefList;
}
QList *
Application::polChemDefWndList()
{
return &m_polChemDefWndList;
}
QList *
Application::calculatorWndList()
{
return &m_calculatorWndList;
}
QList *
Application::sequenceEditorWndList()
{
return &m_sequenceEditorWndList;
}
QList *
Application::mzLabWndList()
{
return &m_mzLabWndList;
}
PolChemDefSpec *
Application::polChemDefSpecName(const QString &name)
{
PolChemDefSpec *polChemDefSpec = 0;
for (int iter = 0 ; iter < m_polChemDefCatList.size() ; ++iter)
{
polChemDefSpec = m_polChemDefCatList.at(iter);
if(polChemDefSpec->name() == name)
return polChemDefSpec;
}
return 0;
}
PolChemDefSpec *
Application::polChemDefSpecFilePath(const QString &filePath)
{
PolChemDefSpec *polChemDefSpec = 0;
for (int iter = 0 ; iter < m_polChemDefCatList.size() ; ++iter)
{
polChemDefSpec = m_polChemDefCatList.at(iter);
if(polChemDefSpec->filePath() == filePath)
return polChemDefSpec;
}
return 0;
}
PolChemDef *
Application::polChemDefName(const QString &name)
{
PolChemDef *polChemDef = 0;
for (int iter = 0 ; iter < m_polChemDefList.size() ; ++iter)
{
polChemDef = m_polChemDefList.at(iter);
// qDebug() << __FILE__ << __LINE__
// << "iterated polChemDef:" << polChemDef->name();
if(polChemDef->name() == name)
return polChemDef;
}
return 0;
}
void
Application::polChemDefCatStringList(QStringList &stringList)
{
PolChemDefSpec *polChemDefSpec = 0;
for (int iter = 0 ; iter < m_polChemDefCatList.size() ; ++iter)
{
polChemDefSpec = m_polChemDefCatList.at(iter);
stringList << polChemDefSpec->filePath();
}
}
bool
Application::closeAllPolChemDefWnd(bool forcibly)
{
PolChemDefWnd *wnd = 0;
// Returns true is Shutdown can be performed.
QMutableListIterator
iterator(m_polChemDefWndList);
while(iterator.hasNext())
{
wnd = iterator.next();
if(forcibly || !wnd->isWindowModified() || wnd->maybeSave())
{
iterator.remove();
// The close() function removes the window from the list of
// windows by default, so ask that it not be removed because
// we have done that above already.
wnd->m_noDelistWnd = true;
// Do not ask for a save even if the window is not saved,
// because 'forcibly' is true.
wnd->m_forciblyClose = true;
wnd->close();
continue;
}
continue;
}
// At this point, we might have windows still opened.
if (m_polChemDefWndList.size() > 0)
{
QMessageBox::StandardButton ret;
ret = QMessageBox::warning
(0,
tr("massXpert - Polymer chemistry definition"),
tr("Modified polymer chemistry definition(s): %1\n"
"Do you want to save your changes?")
.arg(m_polChemDefWndList.size()),
QMessageBox::Yes | QMessageBox::No);
if(ret == QMessageBox::Yes)
return false;
while(!m_polChemDefWndList.isEmpty())
{
wnd = m_polChemDefWndList.takeFirst();
// Forcible close(no maybeSave() call).
wnd->m_forciblyClose = true;
// No delisting of the window!
wnd->m_noDelistWnd = true;
wnd->close();
}
}
return true;
}
bool
Application::closeAllCalculatorWnd()
{
// Returns true is Shutdown can be performed.
QMutableListIterator iterator(m_calculatorWndList);
while(iterator.hasNext())
{
CalculatorWnd *wnd = iterator.next();
iterator.remove();
// The close() function removes the window from the list of
// windows by default, so ask that it not be removed because we
// have done that above already.
wnd->m_noDelistWnd = true;
wnd->close();
continue;
}
return true;
}
bool
Application::isSequenceEditorWnd(SequenceEditorWnd *seqEdWnd)
{
// Does this pointer correspond to a sequence editor window
// currently opened?
SequenceEditorWnd *SequenceEditorWndPtr = 0;
foreach(SequenceEditorWndPtr, m_sequenceEditorWndList)
{
if(SequenceEditorWndPtr == seqEdWnd)
return true;
}
return false;
}
bool
Application::closeAllSequenceEditorWnd(bool forcibly)
{
SequenceEditorWnd *wnd = 0;
// Returns true is Shutdown can be performed.
QMutableListIterator
iterator(m_sequenceEditorWndList);
while(iterator.hasNext())
{
wnd = iterator.next();
if(forcibly || !wnd->isWindowModified() || wnd->maybeSave())
{
iterator.remove();
// The close() function removes the window from the list of
// windows by default, so ask that it not be removed because
// we have done that above already.
wnd->m_noDelistWnd = true;
// Do not ask for a save even if the window is not saved,
// because 'forcibly' is true.
wnd->m_forciblyClose = true;
wnd->close();
continue;
}
continue;
}
// At this point, we might have windows still opened.
if (m_sequenceEditorWndList.size() > 0)
{
QMessageBox::StandardButton ret;
ret = QMessageBox::warning(0, tr("massXpert - Polymer Sequence Editor"),
tr("Modified sequence(s): %1\n"
"Do you want to really quit?")
.arg(m_sequenceEditorWndList.size()),
QMessageBox::Yes | QMessageBox::No);
if(ret == QMessageBox::No)
return false;
while(!m_sequenceEditorWndList.isEmpty())
{
wnd = m_sequenceEditorWndList.takeFirst();
// Forcible close(no maybeSave() call).
wnd->m_forciblyClose = true;
// No delisting of the window!
wnd->m_noDelistWnd = true;
wnd->close();
}
}
return true;
}
bool
Application::closeAllMzLabWnd(bool forcibly)
{
MzLabWnd *wnd = 0;
// Returns true is Shutdown can be performed.
QMutableListIterator
iterator(m_mzLabWndList);
while(iterator.hasNext())
{
wnd = iterator.next();
if(forcibly || !wnd->isWindowModified() || wnd->maybeSave())
{
iterator.remove();
// The close() function removes the window from the list of
// windows by default, so ask that it not be removed because
// we have done that above already.
wnd->m_noDelistWnd = true;
// Do not ask for a save even if the window is not saved,
// because 'forcibly' is true.
wnd->m_forciblyClose = true;
wnd->close();
continue;
}
continue;
}
// At this point, we might have windows still opened.
if (m_mzLabWndList.size() > 0)
{
QMessageBox::StandardButton ret;
ret = QMessageBox::warning(0, tr("massXpert - mz Lab"),
tr("Modified mz Lab(s): %1\n"
"Close the labs?")
.arg(m_mzLabWndList.size()),
QMessageBox::Yes | QMessageBox::No);
if(ret == QMessageBox::Yes)
{
while(!m_mzLabWndList.isEmpty())
{
wnd = m_mzLabWndList.takeFirst();
// Forcible close(no maybeSave() call).
wnd->m_forciblyClose = true;
// No delisting of the window!
wnd->m_noDelistWnd = true;
wnd->close();
}
return true;
}
else //(ret == QMessageBox::No)
return false;
}
return true;
}
void
Application::destroySplash()
{
delete mpa_splash;
mpa_splash = 0;
}
bool
Application::prepareShutdown()
{
if (!closeAllPolChemDefWnd(false))
return false;
if (!closeAllCalculatorWnd())
return false;
if (!closeAllSequenceEditorWnd(false))
return false;
if (!closeAllMzLabWnd(false))
return false;
return true;
}
} // namespace massXpert
massxpert-3.6.0/gui/application.hpp 0000664 0000000 0000000 00000010576 12577256262 0017375 0 ustar 00root root 0000000 0000000 /* 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.
*/
#ifndef APPLICATION_HPP
#define APPLICATION_HPP
/////////////////////// Qt includes
#include
#include
#include
#include
#include
/////////////////////// Local includes
#include "userSpec.hpp"
#include "configSettings.hpp"
#include "polChemDef.hpp"
#include "polChemDefSpec.hpp"
#include "polChemDefWnd.hpp"
#include "calculatorWnd.hpp"
#include "mzLabWnd.hpp"
#include "sequenceEditorWnd.hpp"
namespace massXpert
{
class Application : public QApplication
{
Q_OBJECT
private:
QLocale m_locale;
UserSpec m_userSpec;
ConfigSettings m_configSettings;
QString m_configSettingsFilePath;
SequenceEditorWnd *mp_lastFocusedWnd;
// List of all the polymer chemistry definition specifications that
// were created during parsing of all the different catalogue files
// on the system.
QList m_polChemDefCatList;
// List of all the polymer chemistry definitions that are loaded in
// memory and usable to load polymer sequences.
QList m_polChemDefList;
// The QList of all the polymer chemistry definition windows.
QList m_polChemDefWndList;
// The QList of all the calculator windows.
QList m_calculatorWndList;
// The QList of all the sequence editor windows.
QList m_sequenceEditorWndList;
// The QList of all the mz lab windows.
QList m_mzLabWndList;
// The splash screen, that we'll remove automatically after
// 2 seconds.
QSplashScreen *mpa_splash;
public:
Application(int &argc, char **argv);
~Application();
const QLocale &locale();
UserSpec *userSpec();
ConfigSettings *configSettings();
bool systemConfigManuallySetSettings();
bool systemConfigReadFileSettings();
const QString &configSettingsFilePath();
void initializeDecimalPlacesOptions();
void setLastFocusedWnd(SequenceEditorWnd *);
QList *polChemDefCatList();
QList *polChemDefList();
void polChemDefCatStringList(QStringList &stringList);
PolChemDefSpec *polChemDefSpecName(const QString &);
PolChemDefSpec *polChemDefSpecFilePath(const QString &);
PolChemDef *polChemDefName(const QString &);
// Window lists for the three modules(polymer chemistry definition
// windows(Def stuff), calculator windows(Calc stuff), editor
// windows(Editor stuff), mz lab windows...
QList *polChemDefWndList();
QList *calculatorWndList();
QList *sequenceEditorWndList();
QList *mzLabWndList();
bool closeAllPolChemDefWnd(bool);
bool closeAllCalculatorWnd();
bool closeAllSequenceEditorWnd(bool);
bool closeAllMzLabWnd(bool);
bool prepareShutdown();
bool isSequenceEditorWnd(SequenceEditorWnd *);
public slots:
void destroySplash();
};
} // namespace massXpert
#endif // APPLICATION_HPP
massxpert-3.6.0/gui/application.qrc 0000664 0000000 0000000 00000000733 12577256262 0017365 0 ustar 00root root 0000000 0000000
images/copy.png
images/cut.png
images/new.png
images/open.png
images/paste.png
images/save.png
images/greenled.png
images/redled.png
images/splashscreen.png
images/massxpert-icon-32.png
images/smile-bad.png
images/smile-fine.png
massxpert-3.6.0/gui/atomDefDlg.cpp 0000664 0000000 0000000 00000055701 12577256262 0017072 0 ustar 00root root 0000000 0000000 /* massXpert - the true massist's program.
--------------------------------------
Copyright(C) 2006,2007 Filippo Rusconi
http://www.filomace.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
/////////////////////// Local includes
#include "application.hpp"
#include "atomDefDlg.hpp"
#include "polChemDef.hpp"
#include "polChemDefWnd.hpp"
namespace massXpert
{
AtomDefDlg::AtomDefDlg(PolChemDef *polChemDef,
PolChemDefWnd *polChemDefWnd)
{
Q_ASSERT(polChemDef);
mp_polChemDef = polChemDef;
mp_list = polChemDef->atomListPtr();
Q_ASSERT(polChemDefWnd);
mp_polChemDefWnd = polChemDefWnd;
if (!initialize())
{
qDebug() << "Failed to initialize the atom definition window";
}
}
void
AtomDefDlg::closeEvent(QCloseEvent *event)
{
// No real close, because we did not ask that
// close==destruction. Thus we only hide the dialog remembering its
// position and size.
mp_polChemDefWnd->m_ui.atomPushButton->setChecked(false);
QSettings settings
(static_cast(qApp)->configSettingsFilePath(),
QSettings::IniFormat);
settings.beginGroup("atom_def_dlg");
settings.setValue("geometry", saveGeometry());
settings.setValue("splitter", m_ui.splitter->saveState());
settings.endGroup();
}
AtomDefDlg::~AtomDefDlg()
{
}
bool
AtomDefDlg::initialize()
{
m_ui.setupUi(this);
// Set all the atoms to the list widget.
for (int iter = 0; iter < mp_list->size(); ++iter)
{
Atom *atom = mp_list->at(iter);
m_ui.atomListWidget->addItem(atom->name());
}
QSettings settings
(static_cast(qApp)->configSettingsFilePath(),
QSettings::IniFormat);
settings.beginGroup("atom_def_dlg");
restoreGeometry(settings.value("geometry").toByteArray());
m_ui.splitter->restoreState(settings.value("splitter").toByteArray());
settings.endGroup();
// Validator stuff for the atom symbol lineedit.
QRegExp symbolRegExp("[A-Z][a-z]*");
QValidator *validator = new QRegExpValidator(symbolRegExp, this);
m_ui.symbolLineEdit->setValidator(validator);
// Make the connections.
connect(m_ui.addAtomPushButton,
SIGNAL(clicked()),
this,
SLOT(addAtomPushButtonClicked()));
connect(m_ui.removeAtomPushButton,
SIGNAL(clicked()),
this,
SLOT(removeAtomPushButtonClicked()));
connect(m_ui.moveUpAtomPushButton,
SIGNAL(clicked()),
this,
SLOT(moveUpAtomPushButtonClicked()));
connect(m_ui.moveDownAtomPushButton,
SIGNAL(clicked()),
this,
SLOT(moveDownAtomPushButtonClicked()));
connect(m_ui.addIsotopePushButton,
SIGNAL(clicked()),
this,
SLOT(addIsotopePushButtonClicked()));
connect(m_ui.removeIsotopePushButton,
SIGNAL(clicked()),
this,
SLOT(removeIsotopePushButtonClicked()));
connect(m_ui.moveUpIsotopePushButton,
SIGNAL(clicked()),
this,
SLOT(moveUpIsotopePushButtonClicked()));
connect(m_ui.moveDownIsotopePushButton,
SIGNAL(clicked()),
this,
SLOT(moveDownIsotopePushButtonClicked()));
connect(m_ui.applyAtomPushButton,
SIGNAL(clicked()),
this,
SLOT(applyAtomPushButtonClicked()));
connect(m_ui.applyIsotopePushButton,
SIGNAL(clicked()),
this,
SLOT(applyIsotopePushButtonClicked()));
connect(m_ui.validatePushButton,
SIGNAL(clicked()),
this,
SLOT(validatePushButtonClicked()));
connect(m_ui.atomListWidget,
SIGNAL(itemSelectionChanged()),
this,
SLOT(atomListWidgetItemSelectionChanged()));
connect(m_ui.isotopeListWidget,
SIGNAL(itemSelectionChanged()),
this,
SLOT(isotopeListWidgetItemSelectionChanged()));
return true;
}
void
AtomDefDlg::addAtomPushButtonClicked()
{
// We are asked to add a new atom. We'll add it right after the
// current item.
// Returns -1 if the list is empty.
int index = m_ui.atomListWidget->currentRow();
Atom *newAtom = new Atom(tr("Type Name"),
tr("Type Symbol"));
mp_list->insert(index, newAtom);
m_ui.atomListWidget->insertItem(index, newAtom->name());
setModified();
// Needed so that the setCurrentRow() call below actually set the
// current row!
if (index <= 0)
index = 0;
m_ui.atomListWidget->setCurrentRow(index);
// Erase isotope data that might be left over by precedent current
// atom.
updateIsotopeDetails(0);
// Set the focus to the lineEdit that holds the name of the atom.
m_ui.nameLineEdit->setFocus();
m_ui.nameLineEdit->selectAll();
}
void
AtomDefDlg::removeAtomPushButtonClicked()
{
QList selectedList =
m_ui.atomListWidget->selectedItems();
if (selectedList.size() != 1)
return;
// Get the index of the current atom.
int index = m_ui.atomListWidget->currentRow();
QListWidgetItem *item = m_ui.atomListWidget->takeItem(index);
delete item;
Atom *atom = mp_list->takeAt(index);
Q_ASSERT(atom);
delete atom;
setModified();
// If there are remaining items, we want to set the next item the
// currentItem. If not, then, the currentItem should be the one
// preceding the atom that we removed.
if (m_ui.atomListWidget->count() >= index + 1)
{
m_ui.atomListWidget->setCurrentRow(index);
atomListWidgetItemSelectionChanged();
}
// If there are no more items in the atom list, remove all the items
// from the isotopeList.
if (!m_ui.atomListWidget->count())
{
m_ui.isotopeListWidget->clear();
clearAllDetails();
}
}
void
AtomDefDlg::moveUpAtomPushButtonClicked()
{
// Move the current row to one index less.
// If no atom is selected, just return.
QList selectedList =
m_ui.atomListWidget->selectedItems();
if (selectedList.size() != 1)
return;
// Get the index of the atom and the atom itself.
int index = m_ui.atomListWidget->currentRow();
// If the item is already at top of list, do nothing.
if (!index)
return;
mp_list->move(index, index - 1);
QListWidgetItem *item = m_ui.atomListWidget->takeItem(index);
m_ui.atomListWidget->insertItem(index - 1, item);
m_ui.atomListWidget->setCurrentRow(index - 1);
atomListWidgetItemSelectionChanged();
setModified();
}
void
AtomDefDlg::moveDownAtomPushButtonClicked()
{
// Move the current row to one index less.
// If no atom is selected, just return.
QList selectedList =
m_ui.atomListWidget->selectedItems();
if (selectedList.size() != 1)
return;
// Get the index of the atom and the atom itself.
int index = m_ui.atomListWidget->currentRow();
// If the item is already at bottom of list, do nothing.
if (index == m_ui.atomListWidget->count() - 1)
return;
mp_list->move(index, index + 1);
QListWidgetItem *item = m_ui.atomListWidget->takeItem(index);
m_ui.atomListWidget->insertItem(index + 1, item);
m_ui.atomListWidget->setCurrentRow(index + 1);
atomListWidgetItemSelectionChanged();
setModified();
}
void
AtomDefDlg::addIsotopePushButtonClicked()
{
Application *application = static_cast(qApp);
QLocale locale = application->locale();
// We are asked to add a new isotope. We'll add it right after the
// current item. Note however, that one atom has to be selected.
QList selectedList =
m_ui.atomListWidget->selectedItems();
if (selectedList.size() != 1)
{
QMessageBox::information(this,
tr("massXpert - Atom definition"),
tr("Please, select an atom first."),
QMessageBox::Ok);
return;
}
// Get the index of the current atom so that we know to which atom
// we'll add the isotope.
int index = m_ui.atomListWidget->currentRow();
// What's the actual atom?
Atom *atom = mp_list->at(index);
Q_ASSERT(atom);
// Allocate the new isotope.
Isotope *newIsotope = new Isotope();
// Get the row index of the current isotope item. Returns -1 if the
// list is empty.
index = m_ui.isotopeListWidget->currentRow();
m_ui.isotopeListWidget->insertItem(index, newIsotope->mass(locale));
// Needed so that the setCurrentRow() call below actually set the
// current row!
if (index <= 0)
index = 0;
atom->insertIsotopeAt(index, newIsotope);
m_ui.isotopeListWidget->setCurrentRow(index);
setModified();
// Set the focus to the lineEdit that holds the mass of the isotope.
m_ui.isotopeMassLineEdit->setFocus();
m_ui.isotopeMassLineEdit->selectAll();
}
void
AtomDefDlg::removeIsotopePushButtonClicked()
{
QList selectedList =
m_ui.isotopeListWidget->selectedItems();
if (selectedList.size() != 1)
return;
// Get the index of the current atom so that we know from which atom
// we'll remove the isotope.
int index = m_ui.atomListWidget->currentRow();
Atom *atom = mp_list->at(index);
Q_ASSERT(atom);
// Get the index of the current isotope.
index = m_ui.isotopeListWidget->currentRow();
// First remove the item from the listwidget because that will have
// isotopeListWidgetItemSelectionChanged() triggered and we have to
// have the item in the isotope list in the atom! Otherwise a crash
// occurs.
QListWidgetItem *item = m_ui.isotopeListWidget->takeItem(index);
delete item;
// Remove the isotope from the atom proper.
QList atomIsotopeList = atom->isotopeList();
Isotope *isotope = atomIsotopeList.at(index);
atom->removeIsotopeAt(index);
delete isotope;
// If there are remaining items, we want to set the next item the
// currentItem. If not, then, the currentItem should be the one
// preceding the atom that we removed.
if (m_ui.isotopeListWidget->count() >= index + 1)
{
m_ui.isotopeListWidget->setCurrentRow(index);
isotopeListWidgetItemSelectionChanged();
}
// We have changed the isotopic constitution of the chemical
// element, we have to recompute the mono/avg masses.
atom->calculateMasses();
// If there are no more items in the isotope list, remove all the
// details.
if (!m_ui.isotopeListWidget->count())
{
updateAtomMassDetails(0);
updateIsotopeDetails(0);
}
else
{
updateAtomMassDetails(atom);
}
setModified();
}
void
AtomDefDlg::moveUpIsotopePushButtonClicked()
{
// Move the current row to one index less.
// If no isotope is selected, just return.
QList selectedList =
m_ui.isotopeListWidget->selectedItems();
if (selectedList.size() != 1)
return;
// Get the atom to which the isotope belongs.
int index = m_ui.atomListWidget->currentRow();
Atom *atom = mp_list->at(index);
// Get the index of the current isotope item.
index = m_ui.isotopeListWidget->currentRow();
// If the item is already at top of list, do nothing.
if (!index)
return;
// Get the isotope itself from the atom.
Isotope *isotope = atom->isotopeList().at(index);
atom->removeIsotopeAt(index);
atom->insertIsotopeAt(index - 1, isotope);
QListWidgetItem *item = m_ui.isotopeListWidget->takeItem(index);
m_ui.isotopeListWidget->insertItem(index - 1, item);
m_ui.isotopeListWidget->setCurrentRow(index - 1);
isotopeListWidgetItemSelectionChanged();
setModified();
}
void
AtomDefDlg::moveDownIsotopePushButtonClicked()
{
// Move the current row to one index less.
// If no isotope is selected, just return.
QList selectedList =
m_ui.isotopeListWidget->selectedItems();
if (selectedList.size() != 1)
return;
// Get the atom to which the isotope belongs.
int index = m_ui.atomListWidget->currentRow();
Atom *atom = mp_list->at(index);
// Get the index of the current isotope item.
index = m_ui.isotopeListWidget->currentRow();
// If the item is already at top of list, do nothing.
if (index == m_ui.isotopeListWidget->count() - 1)
return;
// Get the isotope itself from the atom.
Isotope *isotope = atom->isotopeList().at(index);
atom->removeIsotopeAt(index);
atom->insertIsotopeAt(index + 1, isotope);
QListWidgetItem *item = m_ui.isotopeListWidget->takeItem(index);
m_ui.isotopeListWidget->insertItem(index + 1, item);
m_ui.isotopeListWidget->setCurrentRow(index + 1);
isotopeListWidgetItemSelectionChanged();
setModified();
}
void
AtomDefDlg::applyAtomPushButtonClicked()
{
// We are asked to apply the data for the atom.
// If no atom is selected, just return.
QList selectedList =
m_ui.atomListWidget->selectedItems();
if (selectedList.size() != 1)
return;
// Get the index of the current atom item.
int index = m_ui.atomListWidget->currentRow();
Atom *atom = mp_list->at(index);
// We do not want more than one atom by the same name or the same
// symbol.
QString editName = m_ui.nameLineEdit->text();
// The syntax [A-Z][a-z]* is automatically validated using the
// validator(see initialize()).
QString editSymbol = m_ui.symbolLineEdit->text();
// If an atom is found in the list with any of these two strings,
// and that atom is not the one that is current in the atom list,
// then we are making a double entry, which is not allowed.
int nameRes = Atom::isNameInList(editName, *mp_list);
if (nameRes != -1 && nameRes != index)
{
QMessageBox::warning(this,
tr("massXpert - Atom definition"),
tr("An atom with same name exists already."),
QMessageBox::Ok);
return;
}
int symbolRes = Atom::isSymbolInList(editSymbol, *mp_list);
if (symbolRes != -1 && symbolRes != index)
{
QMessageBox::warning(this,
tr("massXpert - Atom definition"),
tr("An atom with same symbol exists already."),
QMessageBox::Ok);
return;
}
atom->setName(editName);
atom->setSymbol(editSymbol);
// Update the list widget item.
QListWidgetItem *item = m_ui.atomListWidget->currentItem();
item->setData(Qt::DisplayRole, atom->name());
setModified();
}
void
AtomDefDlg::applyIsotopePushButtonClicked()
{
Application *application = static_cast(qApp);
QLocale locale = application->locale();
// We are asked to apply the data for the isotope.
// If no isotope is selected, just return.
QList selectedList =
m_ui.isotopeListWidget->selectedItems();
if (selectedList.size() != 1)
return;
// Get the atom to which the isotope belongs.
int index = m_ui.atomListWidget->currentRow();
Atom *atom = mp_list->at(index);
// Get the index of the current isotope item.
index = m_ui.isotopeListWidget->currentRow();
// Get the isotope itself from the atom.
Isotope *isotope = atom->isotopeList().at(index);
QString editMass = m_ui.isotopeMassLineEdit->text();
QString editAbundance = m_ui.isotopeAbundanceLineEdit->text();
bool ok = false;
double doubleMass = locale.toDouble(editMass, &ok);
if (doubleMass == 0.0 && !ok)
{
QMessageBox::warning(this,
tr("massXpert - Atom definition"),
tr("Failed to convert %1 to a double.")
.arg(editMass),
QMessageBox::Ok);
return;
}
ok = false;
double doubleAbundance = locale.toDouble(editAbundance, &ok);
if (doubleAbundance == 0.0 && !ok)
{
QMessageBox::warning(this,
tr("massXpert - Atom definition"),
tr("Failed to convert %1 to a double.")
.arg(editAbundance),
QMessageBox::Ok);
return;
}
isotope->setMass(doubleMass);
isotope->setAbundance(doubleAbundance);
// Update the list widget item.
QListWidgetItem *item = m_ui.isotopeListWidget->currentItem();
QString mass = isotope->mass(locale, MXP_ATOM_DEC_PLACES);
item->setData(Qt::DisplayRole, mass);
atom->calculateMasses();
updateAtomMassDetails(atom);
setModified();
}
bool
AtomDefDlg::validatePushButtonClicked()
{
QStringList errorList;
// All we have to do is validate the atom definition. For that we'll
// go in the listwidget items one after the other and make sure that
// everything is fine and that colinearity is perfect between the
// atom list and the listwidget.
int itemCount = m_ui.atomListWidget->count();
if (itemCount != mp_list->size())
{
errorList << QString(tr("\nThe number of atoms in in the list widget \n"
"and in the list of atoms is not identical.\n"));
QMessageBox::warning(this,
tr("massXpert - Atom definition"),
errorList.join("\n"),
QMessageBox::Ok);
return false;
}
for (int iter = 0; iter < mp_list->size(); ++iter)
{
QListWidgetItem *item = m_ui.atomListWidget->item(iter);
Atom *atom = mp_list->at(iter);
if(item->text() != atom->name())
errorList << QString(tr("\nAtom at index %1 has not the same\n"
"name as the list widget item at the\n"
"same index.\n")
.arg(iter));
if(!atom->validate())
errorList << QString(tr("\nAtom at index %1 failed to validate.\n")
.arg(iter));
}
if (errorList.size())
{
QMessageBox::warning(this,
tr("massXpert - Atom definition"),
errorList.join("\n"),
QMessageBox::Ok);
return false;
}
else
{
QMessageBox::warning(this,
tr("massXpert - Atom definition"),
("Validation: success\n"),
QMessageBox::Ok);
}
return true;
}
void
AtomDefDlg::atomListWidgetItemSelectionChanged()
{
Application *application = static_cast(qApp);
QLocale locale = application->locale();
// The atom item has changed. Empty the isotope list and update its
// contents. Update the details for the atom.
// The list is a single-item-selection list.
QList selectedList =
m_ui.atomListWidget->selectedItems();
if (selectedList.size() != 1)
return;
// Get the index of the current atom.
int index = m_ui.atomListWidget->currentRow();
Atom *atom = mp_list->at(index);
Q_ASSERT(atom);
// Set the data of the atom to their respective widgets.
updateAtomIdentityDetails(atom);
updateAtomMassDetails(atom);
// The list of isotopes
m_ui.isotopeListWidget->clear();
for (int iter = 0; iter < atom->isotopeList().size(); ++iter)
{
Isotope *isotope = atom->isotopeList().at(iter);
m_ui.isotopeListWidget->
addItem(isotope->mass(locale,MXP_ATOM_DEC_PLACES));
}
if (!m_ui.isotopeListWidget->count())
updateIsotopeDetails(0);
else
{
// And now select the first row in the isotope list widget.
m_ui.isotopeListWidget->setCurrentRow(0);
}
}
void
AtomDefDlg::isotopeListWidgetItemSelectionChanged()
{
// The isotope item has changed. Update the details for the isotope.
// The list is a single-item-selection list.
QList selectedList =
m_ui.isotopeListWidget->selectedItems();
if (selectedList.size() != 1)
return;
// Get the index of the current atom.
int index = m_ui.atomListWidget->currentRow();
// Find the isotope object in the list of isotopes.
Atom *atom = mp_list->at(index);
Q_ASSERT(atom);
// Get the index of the current isotope.
index = m_ui.isotopeListWidget->currentRow();
// Get the isotope that is currently selected from the atom's list
// of isotopes.
Isotope *isotope = atom->isotopeList().at(index);
Q_ASSERT(isotope);
// Set the data of the isotope to their respective widgets.
updateIsotopeDetails(isotope);
}
void
AtomDefDlg::updateAtomIdentityDetails(Atom *atom)
{
if (atom)
{
m_ui.nameLineEdit->setText(atom->name());
m_ui.symbolLineEdit->setText(atom->symbol());
}
else
{
m_ui.nameLineEdit->setText("");
m_ui.symbolLineEdit->setText("");
}
}
void
AtomDefDlg::updateAtomMassDetails(Atom *atom)
{
Application *application = static_cast(qApp);
QLocale locale = application->locale();
if (atom)
{
m_ui.monoMassLineEdit->
setText(atom->mono(locale,MXP_ATOM_DEC_PLACES));
m_ui.avgMassLineEdit->
setText(atom->avg(locale,MXP_ATOM_DEC_PLACES));
}
else
{
m_ui.monoMassLineEdit->setText("");
m_ui.avgMassLineEdit->setText("");
}
}
void
AtomDefDlg::updateIsotopeDetails(Isotope *isotope)
{
Application *application = static_cast(qApp);
QLocale locale = application->locale();
if (isotope)
{
m_ui.isotopeMassLineEdit->
setText(isotope->mass(locale,MXP_ATOM_DEC_PLACES));
m_ui.isotopeAbundanceLineEdit->
setText(isotope->abundance(locale,MXP_ATOM_DEC_PLACES));
}
else
{
m_ui.isotopeMassLineEdit->setText("");
m_ui.isotopeAbundanceLineEdit->setText("");
}
}
void
AtomDefDlg::clearAllDetails()
{
m_ui.nameLineEdit->setText("");
m_ui.symbolLineEdit->setText("");
m_ui.monoMassLineEdit->setText("");
m_ui.avgMassLineEdit->setText("");
m_ui.isotopeMassLineEdit->setText("");
m_ui.isotopeAbundanceLineEdit->setText("");
}
void
AtomDefDlg::setModified()
{
mp_polChemDefWnd->setWindowModified(true);
}
// VALIDATION
bool
AtomDefDlg::validate()
{
return validatePushButtonClicked();
}
} // namespace massXpert
massxpert-3.6.0/gui/atomDefDlg.hpp 0000664 0000000 0000000 00000005535 12577256262 0017077 0 ustar 00root root 0000000 0000000 /* massXpert - the true massist's program.
--------------------------------------
Copyright(C) 2006,2007 Filippo Rusconi
http://www.filomace.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.
*/
#ifndef ATOM_DEF_DLG_HPP
#define ATOM_DEF_DLG_HPP
/////////////////////// Local includes
#include "ui_atomDefDlg.h"
namespace massXpert
{
class PolChemDef;
class PolChemDefWnd;
class Atom;
class Isotope;
class AtomDefDlg : public QDialog
{
Q_OBJECT
private:
Ui::AtomDefDlg m_ui;
PolChemDef *mp_polChemDef;
PolChemDefWnd *mp_polChemDefWnd;
QList *mp_list;
void closeEvent(QCloseEvent *event);
public:
AtomDefDlg(PolChemDef *, PolChemDefWnd *);
~AtomDefDlg();
bool initialize();
void updateAtomIdentityDetails(Atom *);
void updateAtomMassDetails(Atom *);
void updateIsotopeDetails(Isotope *);
void clearAllDetails();
void setModified();
public slots:
// ACTIONS
void addAtomPushButtonClicked();
void removeAtomPushButtonClicked();
void moveUpAtomPushButtonClicked();
void moveDownAtomPushButtonClicked();
void addIsotopePushButtonClicked();
void removeIsotopePushButtonClicked();
void moveUpIsotopePushButtonClicked();
void moveDownIsotopePushButtonClicked();
void applyAtomPushButtonClicked();
void applyIsotopePushButtonClicked();
bool validatePushButtonClicked();
// VALIDATION
bool validate();
// WIDGETRY
void atomListWidgetItemSelectionChanged();
void isotopeListWidgetItemSelectionChanged();
};
} // namespace massXpert
#endif // ATOM_DEF_DLG_HPP
massxpert-3.6.0/gui/calculatorChemPadDlg.cpp 0000664 0000000 0000000 00000041533 12577256262 0021064 0 ustar 00root root 0000000 0000000 /* 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
#include
#include
#include
/////////////////////// Local includes
#include "application.hpp"
#include "calculatorChemPadDlg.hpp"
#include "calculatorChemPadGroupBox.hpp"
#include "chemPadButton.hpp"
#include "calculatorWnd.hpp"
namespace massXpert
{
CalculatorChemPadDlg::CalculatorChemPadDlg(QWidget *parent)
: QDialog(parent)
{
// m_ui.setupUi(this);
setSizeGripEnabled(true);
m_columnCount=3;
m_row = 0;
m_column = 0;
// We need to know the value of this variable, thus set it to 0.
mp_lastGroupbox = 0;
// Create the main vertical box layout.
mpa_mainVBoxLayout = new QVBoxLayout;
setLayout(mpa_mainVBoxLayout);
// Create the scroll area.
mpa_scrollArea = new QScrollArea ();
mpa_scrollArea->setHorizontalScrollBarPolicy(Qt::ScrollBarAsNeeded);
mpa_scrollArea->setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded);
mpa_scrollArea->setWidgetResizable(true);
mpa_mainVBoxLayout->addWidget(mpa_scrollArea);
// Create the main groupbox:
mpa_mainGroupBox = new QGroupBox;
mpa_mainGroupBoxVBLayout = new QVBoxLayout;
mpa_mainGroupBox->setLayout(mpa_mainGroupBoxVBLayout);
// Code to test the appearance of scrollbars: works.
// QLabel *imageLabel = new QLabel;
// QImage image("/home/rusconi/figure.png");
// imageLabel->setPixmap(QPixmap::fromImage(image));
// mpa_scrollArea->setWidget(imageLabel);
// Geometry settings are dealt with in the setup function.
connect(this,
SIGNAL(rejected()),
this,
SLOT(close()));
}
CalculatorChemPadDlg::~CalculatorChemPadDlg()
{
}
void
CalculatorChemPadDlg::keyPressEvent(QKeyEvent *event)
{
CalculatorWnd *wnd = static_cast(parentWidget());
Qt::KeyboardModifiers modifiers = event->modifiers();
int formulaHandling = wnd->m_formulaHandling;
if (modifiers & Qt::ControlModifier)
{
formulaHandling |= MXP_FORMULA_HANDLING_PRINT;
}
if (modifiers & Qt::ShiftModifier)
{
formulaHandling |= MXP_FORMULA_HANDLING_WITH_SPACE;
}
wnd->setFormulaHandling(formulaHandling);
return event->accept();
}
void
CalculatorChemPadDlg::keyReleaseEvent(QKeyEvent *event)
{
CalculatorWnd *wnd = static_cast(parentWidget());
Qt::KeyboardModifiers modifiers = event->modifiers();
int formulaHandling = wnd->m_formulaHandling;
if (!(modifiers & Qt::ControlModifier))
{
formulaHandling &= ~MXP_FORMULA_HANDLING_PRINT;
}
if (!(modifiers & Qt::ShiftModifier))
{
formulaHandling &= ~MXP_FORMULA_HANDLING_WITH_SPACE;
}
wnd->setFormulaHandling(formulaHandling);
return event->accept();
}
bool
CalculatorChemPadDlg::parseColumnCount(QString &line)
{
int percentSign = line.lastIndexOf('%');
int lineLength = line.length();
QString columnsString = line.mid(percentSign + 1,
lineLength -2 - percentSign);
bool ok;
int columnCount = columnsString.toInt(&ok);
if (!columnCount && !ok)
return false;
m_columnCount = columnCount;
return true;
}
QColor
CalculatorChemPadDlg::parseColor(QString &line)
{
QStringList list = line.split("%", QString::SkipEmptyParts);
// The first item of the list is "color", which we have to
// remove.
if (list.first() != "color")
{
qDebug() << __FILE__ << __LINE__
<< tr("Error with chemical pad line")
<< line;
return QColor();
}
list.removeFirst();
// Now the number of items in the list should be 2.
if (list.size() < 2)
{
qDebug() << __FILE__ << __LINE__
<< "Error with chemical pad line"
<< line;
return QColor();
}
// The rgb specification is the second item in the list (index 1)
QStringList rgbList = list.at(1).split(",", QString::SkipEmptyParts);
bool ok = false;
// The red component of the rgb color composition
int r = rgbList.at(0).toInt (&ok);
if ((!r && !ok) || r < 0 || r > 255)
{
qDebug() << __FILE__ << __LINE__
<< tr("Error with chemical pad line: r "
"color component is bad:")
<< r;
return QColor();
}
// The green component of the rgb color composition
int g = rgbList.at(1).toInt (&ok);
if ((!g && !ok) || g < 0 || g > 255)
{
qDebug() << __FILE__ << __LINE__
<< tr("Error with chemical pad line: g "
"color component is bad:")
<< g;
return QColor();
}
// The blue component of the rgb color composition
int b = rgbList.at(2).toInt (&ok);
if ((!b && !ok) || b < 0 || b > 255)
{
qDebug() << __FILE__ << __LINE__
<< tr("Error with chemical pad line: b "
"color component is bad:")
<< b;
return QColor();
}
// We have our r, g and b values: construct a QColor object and
// immediately test it.
QColor color = QColor (r, g, b);
if (!color.isValid())
{
qDebug() << tr("Error with creation of color with: ")
<< line;
return QColor();
}
// Now make a new hash entry with the color name and the color
// itself. The name is the first item in the string list.
if (list.first().isEmpty())
{
qDebug() << __FILE__ << __LINE__
<< tr("Error with chemical pad line: "
"color name cannot be empty.");
return QColor();
}
m_colorHash.insert(list.first(), color);
// qDebug() << __FILE__ << __LINE__
// << "Inserting color:" << list.first() << color;
return color;
}
QStringList
CalculatorChemPadDlg::parseSeparator(QString &line)
{
// The line we get should be of the form
// chempadgroup%Hexoses & Fucose
// or
// chempadgroup%Hexosamines && Sialic%[violet]
QStringList list;
list = line.split("%", QString::SkipEmptyParts);
// The first item is the "chempadgroup" string.
list.removeFirst();
// The now-first item is the string to be used as the title of the
// group box widget. If there is a second item, then it is the
// color of the background of the group box widget. This last item
// is optional, it is of the form [violet].
if (list.size() > 1)
{
list[1].remove('[');
list[1].remove(']');
// Remove the newline character.
list[1].remove (list.at(1).size() -1, 1);
}
return list;
}
ChemPadButton *
CalculatorChemPadDlg::parseKey (QString &line, QStringList &list)
{
CalculatorWnd *wnd = static_cast(parentWidget());
ChemPadButton *button = 0;
list = line.split("%", QString::SkipEmptyParts);
// The first item of the list is "chempadkey", which we have to
// remove.
if (list.first() != "chempadkey")
{
qDebug() << __FILE__ << __LINE__
<< "Error with chemical pad line"
<< line;
return 0;
}
list.removeFirst();
// Now the number of items in the list should be 3 or 4.
if (list.size() < 3)
{
qDebug() << __FILE__ << __LINE__
<< "Error with chemical pad line"
<< line;
return 0;
}
else if (list.size() == 3)
{
// Not color was defined.
button = new ChemPadButton(list.at(0), list.at(1), wnd, this);
button->setToolTip(list.at(2));
}
else if (list.size() == 4)
{
// A set of colors was defined. We have to parse it.
// The format is : [bgHex,fgHex]
QString colorSpec = list.last();
// Remove the newline character.
colorSpec.remove (colorSpec.size() -1, 1);
if (colorSpec.at(0) != '[')
{
qDebug() << __FILE__ << __LINE__
<< "Error with button color specification:"
<< colorSpec;
return 0;
}
else
colorSpec.remove (0, 1);
if (colorSpec.at(colorSpec.size() -1) != ']')
{
qDebug() << __FILE__ << __LINE__
<< "Error with button color specification:"
<< colorSpec;
return 0;
}
else
colorSpec.remove (colorSpec.size() -1, 1);
// We are left with "bgHex,fgHex"
QStringList colorList = colorSpec.split (",", QString::SkipEmptyParts);
if (colorList.size() != 2)
{
qDebug() << __FILE__ << __LINE__
<< "Error with button color specification:"
<< colorSpec;
return 0;
}
// First item in the list is the background color and second
// is the foreground color. These are the names of the
// colors. We have to convert these into QColor instances.
QColor bgColor = m_colorHash.value (colorList.at(0));
if (!bgColor.isValid())
{
// The color might be one Qt-defined color.
bgColor = QColor(colorList.at(0));
if (!bgColor.isValid())
{
qDebug() << __FILE__ << __LINE__
<< "Error with button color specification:"
<< colorList.at(0);
return 0;
}
}
QColor fgColor = m_colorHash.value (colorList.at(1));
if (!fgColor.isValid())
{
// The color might be one Qt-defined color.
fgColor = QColor(colorList.at(1));
if (!fgColor.isValid())
{
qDebug() << __FILE__ << __LINE__
<< "Error with button color specification:"
<< colorList.at(1);
return 0;
}
}
// At this point we have both back-fore-ground colors.
button = new ChemPadButton(list.at(0),
list.at(1),
wnd, this,
bgColor, fgColor);
button->setToolTip(list.at(2));
}
return button;
}
bool
CalculatorChemPadDlg::setup(QString &filePath,
const QString &polChemDefName)
{
QFile file(filePath);
if (! file.open(QFile::ReadOnly))
{
qDebug() << "Chemical pad's configuration file could not be opened.";
return false;
}
if (!parseFile(filePath))
{
qDebug() << "Failed to parse the configuration "
"file for the chemical pad";
return false;
}
QSettings settings
(static_cast(qApp)->configSettingsFilePath(),
QSettings::IniFormat);
settings.beginGroup("calculator_chem_pad_dlg");
QString setting = QString("%1-%2")
.arg(polChemDefName)
.arg("geometry");
restoreGeometry(settings.value(setting).toByteArray());
settings.endGroup();
return true;
}
bool
CalculatorChemPadDlg::parseFile(QString &filePath)
{
qint64 lineLength;
QString line;
char buffer [1024];
QFile file(filePath);
if (! file.open(QFile::ReadOnly))
return false;
// The file we have to parse is like this:
//
// chempad_columns%3
// color%bgHex%125,125,125
// chempadgroup%Hexoses & Fucose
// chempadkey%protonate%+H1%adds a proton
// chempadkey%hydrate%+H2O1%adds a water molecule
// chempadkey%Res-1bRE-Hexose%C6H11O6%residue Hexose (1bRE)%[bgHex,fgHex]
//
// Note that any line starting with something else than 'chempad' is
// ignored.
lineLength = file.readLine(buffer, sizeof(buffer));
while(lineLength != -1)
{
// The line is now in buffer, and we want to convert
// it to Unicode by setting it in a QString.
line = buffer;
// qDebug () << __FILE__ << __LINE__
// << __FILE__ << __LINE__ << line;
if (line.startsWith("chempad", Qt::CaseSensitive))
{
if (line.startsWith("chempad_columns%", Qt::CaseSensitive))
{
bool result = parseColumnCount(line);
if (!result)
{
qDebug() << "Failed parsing the column count. Setting to 3.";
// The default value of 3 remains valid.
m_columnCount = 3;
}
}
else if (line.startsWith("chempadgroup", Qt::CaseSensitive))
{
// One chemical pad separation is being parsed. This
// means that one groupbox should be created by the
// separator string returned below.
QStringList list = parseSeparator(line);
QString separator = list.first();
CalculatorChemPadGroupBox *groupbox =
new CalculatorChemPadGroupBox(separator, mpa_scrollArea);
mp_lastGroupbox = groupbox;
mpa_mainGroupBoxVBLayout->
addWidget(static_cast (groupbox));
groupbox->setCheckable (true);
groupbox->show();
// Now, if the list returned by th call to
// parseSeparator contains a second item, then that item
// is a string containing a color to be used to draw the
// background of the groupbox.
if (list.size() > 1)
{
QColor color = m_colorHash.value (list.at(1));
if (!color.isValid())
{
// The color might be one Qt-defined color.
color = QColor(list.at(1));
if (!color.isValid())
{
qDebug() << "Error with group color specification:"
<< list.at(1);
return 0;
}
}
// OK, we have a correct color specification. Use it.
QString colorString = QString ("rgb(%1,%2,%3)")
.arg(color.red())
.arg(color.green())
.arg(color.blue());
mp_lastGroupbox->
setStyleSheet(QString ("QGroupBox {background: %1}")
.arg(colorString));
}
// Make sure we can hide the groupbox contents upon
// unchecking the checkbox.
connect(groupbox,
SIGNAL(toggled(bool)),
groupbox,
SLOT(toggled(bool)));
// Reset the row and the column!
m_row = 0;
m_column = 0;
}
else
{
if (!line.startsWith("chempadkey", Qt::CaseSensitive))
{
qDebug() << __FILE__ << __LINE__
<< tr("Error parsing the chem_pad.conf file.");
return false;
}
QStringList stringList;
ChemPadButton *button = parseKey(line, stringList);
if (!button)
qDebug() << "Failed parsing the key:" << line;
// OK, now that we have the button, we can set it to the
// last groupbox that was created. NOTE HOWEVER, that
// one author who would forget to create a group
// division in the file before defining the first
// chemical pad button, would expect the chemical pad to
// work nonetheless. Thus we have to test that
// hypothesis. If no section groupbox was ever
// configured before the current button, then create
// one.
if (!mp_lastGroupbox)
{
CalculatorChemPadGroupBox *groupbox =
new CalculatorChemPadGroupBox(tr("No section title"),
mpa_scrollArea);
mp_lastGroupbox = groupbox;
mpa_mainGroupBoxVBLayout->
addWidget(static_cast (groupbox));
groupbox->setCheckable (true);
groupbox->show();
}
mp_lastGroupbox->addChemPadButton(button, m_row, m_column);
button->show();
++m_column;
// Remember, columns are numbered like indexes: starting from 0
//(thus the '=' sign along with '>' below).
if (m_column >= m_columnCount)
{
m_column = 0;
++m_row;
}
}
}
else if (line.startsWith("color%", Qt::CaseSensitive))
{
QColor color = parseColor(line);
if (!color.isValid())
{
qDebug() << __FILE__ << __LINE__
<< "Failed parsing the color:"<< line;
return false;
}
}
lineLength = file.readLine(buffer, sizeof(buffer));
continue;
}
mpa_scrollArea->setWidget(mpa_mainGroupBox);
return true;
}
////////////////////////////// SLOTS ///////////////////////////////
void
CalculatorChemPadDlg::close()
{
// Before closing set the parent checkbox to proper state.
CalculatorWnd *wnd = static_cast(parentWidget());
wnd->chemPadDlgClosed();
}
} // namespace massXpert
massxpert-3.6.0/gui/calculatorChemPadDlg.hpp 0000664 0000000 0000000 00000005532 12577256262 0021070 0 ustar 00root root 0000000 0000000 /* 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.
*/
#ifndef CALCULATOR_CHEM_PAD_DLG_HPP
#define CALCULATOR_CHEM_PAD_DLG_HPP
/////////////////////// Qt includes
#include
#include
#include
#include
#include
#include
#include
/////////////////////// Local includes
// #include "ui_calculatorChemPadDlg.h"
#include "chemPadButton.hpp"
#include "calculatorChemPadGroupBox.hpp"
namespace massXpert
{
class CalculatorChemPadDlg : public QDialog
{
Q_OBJECT
private:
// Ui::CalculatorChemPadDlg m_ui;
QGroupBox *mpa_mainGroupBox;
QVBoxLayout *mpa_mainGroupBoxVBLayout;
QVBoxLayout *mpa_mainVBoxLayout;
QScrollArea *mpa_scrollArea;
QVBoxLayout *mpa_scrollAreaVBoxLayout;
CalculatorChemPadGroupBox *mp_lastGroupbox;
QGridLayout *mp_lastGridLayout;
QHash m_colorHash;
int m_columnCount;
int m_row;
int m_column;
void keyPressEvent(QKeyEvent *);
void keyReleaseEvent(QKeyEvent *);
public:
CalculatorChemPadDlg(QWidget * = 0);
~CalculatorChemPadDlg();
bool parseFile(QString &);
bool setup(QString &, const QString & = QString());
bool parseColumnCount(QString &);
QColor parseColor(QString &);
QStringList parseSeparator(QString &);
ChemPadButton *parseKey (QString &, QStringList &);
public slots:
void close();
};
} // namespace massXpert
#endif // CALCULATOR_CHEM_PAD_DLG_HPP
massxpert-3.6.0/gui/calculatorChemPadGroupBox.cpp 0000664 0000000 0000000 00000005343 12577256262 0022122 0 ustar 00root root 0000000 0000000 /* 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
/////////////////////// Local includes
#include "calculatorChemPadGroupBox.hpp"
namespace massXpert
{
CalculatorChemPadGroupBox::CalculatorChemPadGroupBox(QWidget *parent)
: QGroupBox(parent)
{
mpa_vboxLayout = new QVBoxLayout;
setLayout(mpa_vboxLayout);
mpa_frame = new QFrame;
mpa_vboxLayout->addWidget(mpa_frame);
mpa_gridLayout = new QGridLayout;
mpa_frame->setLayout(mpa_gridLayout);
}
CalculatorChemPadGroupBox::CalculatorChemPadGroupBox (const QString &title,
QWidget * parent)
: QGroupBox(title, parent)
{
mpa_vboxLayout = new QVBoxLayout;
setLayout(mpa_vboxLayout);
mpa_frame = new QFrame;
mpa_vboxLayout->addWidget(mpa_frame);
mpa_gridLayout = new QGridLayout;
mpa_frame->setLayout(mpa_gridLayout);
}
CalculatorChemPadGroupBox::~CalculatorChemPadGroupBox()
{
}
void
CalculatorChemPadGroupBox::addChemPadButton(ChemPadButton *button,
int row, int column)
{
if (!button)
return;
mpa_gridLayout->addWidget(button, row, column);
}
////////////////////////////// SLOTS ///////////////////////////////
void
CalculatorChemPadGroupBox::toggled(bool checked)
{
mpa_frame->setVisible(checked);
}
} // namespace massXpert
massxpert-3.6.0/gui/calculatorChemPadGroupBox.hpp 0000664 0000000 0000000 00000004412 12577256262 0022123 0 ustar 00root root 0000000 0000000 /* 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.
*/
#ifndef CALCULATOR_CHEM_PAD_GROUPBOX_HPP
#define CALCULATOR_CHEM_PAD_GROUPBOX_HPP
/////////////////////// Qt includes
#include
#include
#include
#include
#include
/////////////////////// Local includes
#include "chemPadButton.hpp"
namespace massXpert
{
class CalculatorChemPadGroupBox : public QGroupBox
{
Q_OBJECT
private:
QList m_widgetList;
QVBoxLayout *mpa_vboxLayout;
QFrame *mpa_frame;
QGridLayout *mpa_gridLayout;
public:
CalculatorChemPadGroupBox(QWidget * = 0);
CalculatorChemPadGroupBox (const QString &, QWidget * = 0);
void addChemPadButton(ChemPadButton *, int, int);
~CalculatorChemPadGroupBox();
public slots:
void toggled(bool);
};
} // namespace massXpert
#endif // CALCULATOR_CHEM_PAD_GROUPBOX_HPP
massxpert-3.6.0/gui/calculatorRecorderDlg.cpp 0000664 0000000 0000000 00000005511 12577256262 0021324 0 ustar 00root root 0000000 0000000 /* 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
#include
/////////////////////// Local includes
#include "application.hpp"
#include "calculatorRecorderDlg.hpp"
#include "calculatorWnd.hpp"
namespace massXpert
{
CalculatorRecorderDlg::CalculatorRecorderDlg(QWidget *parent)
: QDialog(parent)
{
m_ui.setupUi(this);
setSizeGripEnabled(true);
m_ui.textEdit->append(tr("Calculator recorder\n"
"===================\n\n"));
QSettings settings
(static_cast(qApp)->configSettingsFilePath(),
QSettings::IniFormat);
restoreGeometry(settings.value("calculator_recorder_dlg/geometry")
.toByteArray());
connect(this,
SIGNAL(rejected()),
this,
SLOT(close()));
}
CalculatorRecorderDlg::~CalculatorRecorderDlg()
{
}
void
CalculatorRecorderDlg::record(const QString &string)
{
m_ui.textEdit->append(string);
}
////////////////////////// SLOTS ///////////////////////////
void
CalculatorRecorderDlg::close()
{
// Before closing set the parent checkbox to proper state.
CalculatorWnd *wnd = static_cast(parentWidget());
QSettings settings
(static_cast(qApp)->configSettingsFilePath(),
QSettings::IniFormat);
settings.setValue("calculator_recorder_dlg/geometry", saveGeometry());
wnd->recorderDlgClosed();
}
} // namespace massXpert
massxpert-3.6.0/gui/calculatorRecorderDlg.hpp 0000664 0000000 0000000 00000003756 12577256262 0021342 0 ustar 00root root 0000000 0000000 /* 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.
*/
#ifndef CALCULATOR_RECORDER_DLG_HPP
#define CALCULATOR_RECORDER_DLG_HPP
/////////////////////// Qt includes
#include
/////////////////////// Local includes
#include "ui_calculatorRecorderDlg.h"
namespace massXpert
{
class CalculatorRecorderDlg : public QDialog
{
Q_OBJECT
private:
Ui::CalculatorRecorderDlg m_ui;
public:
CalculatorRecorderDlg(QWidget *parent = 0);
~CalculatorRecorderDlg();
void record(const QString &);
public slots:
void close();
};
} // namespace massXpert
#endif // CALCULATOR_RECORDER_DLG_HPP
massxpert-3.6.0/gui/calculatorWnd.cpp 0000664 0000000 0000000 00000120542 12577256262 0017662 0 ustar 00root root 0000000 0000000 /* 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
#include
#include
#include
/////////////////////// Local includes
#include "calculatorWnd.hpp"
#include "application.hpp"
#include "calculatorRecorderDlg.hpp"
#include "polChemDefEntity.hpp"
#include "sequence.hpp"
#include "mzCalculationDlg.hpp"
#include "spectrumCalculationDlg.hpp"
namespace massXpert
{
enum formulaActions
{
ADD_FORMULA,
REMOVE_FORMULA,
CLEAR_WHOLE_MEMORY,
SIMPLIFY_FORMULA
};
CalculatorWnd::CalculatorWnd(QString &filePath,
const QString &mono,
const QString &avg)
{
m_forciblyClose = false;
m_noDelistWnd = false;
m_formulaHandling = MXP_FORMULA_HANDLING_IMMEDIATE;
if (filePath.isEmpty())
{
QMessageBox::warning(0,
tr("massXpert - Calculator"),
tr("Polymer chemistry definition filepath empty."),
QMessageBox::Ok);
return;
}
m_polChemDef.setFilePath(filePath);
if (!initialize())
{
QMessageBox::warning(0,
tr("massXpert - Calculator"),
tr("Failed to initialize the calculator window."),
QMessageBox::Ok);
}
QSettings settings
(static_cast(qApp)->configSettingsFilePath(),
QSettings::IniFormat);
QString section = QString ("calculator_wnd/%2")
.arg(m_polChemDef.name());
settings.beginGroup(section);
restoreGeometry(settings.value("geometry").toByteArray());
m_ui.hSplitter->
restoreState(settings.value("hSplitterSize").toByteArray());
int count = settings.beginReadArray("formulas");
for (int iter = 0; iter < count; ++iter)
{
settings.setArrayIndex(iter);
QString index;
index.setNum(iter);
QString value = settings.value(index).toString();
m_ui.formulaComboBox->insertItem(iter, value);
// qDebug () << __FILE__ << __LINE__
// << "Read line:" << value << "and"
// << m_ui.formulaComboBox->itemText(iter);
}
settings.endArray();
settings.endGroup();
// But we want that the formulaComboBox line edit widget be empty
// even when formulas have been loaded. So clear the line edit
// widget of the combo box.
m_ui.formulaComboBox->lineEdit()->clear();
// If the strings mono and avg are non null, then set their values
// to the seed masses.
if(!mono.isNull())
{
m_ui.seedMonoMassLineEdit->setText(mono);
// qDebug() << __FILE__ << __LINE__
// << "Set the mono mass to" << mono;
}
if(!avg.isNull())
{
m_ui.seedAvgMassLineEdit->setText(avg);
// qDebug() << __FILE__ << __LINE__
// << "Set the avg mass to" << avg;
}
show();
}
CalculatorWnd::~CalculatorWnd()
{
}
void
CalculatorWnd::closeEvent(QCloseEvent *event)
{
QSettings settings
(static_cast(qApp)->configSettingsFilePath(),
QSettings::IniFormat);
QString section = QString ("calculator_wnd/%2")
.arg(m_polChemDef.name());
settings.beginGroup(section);
settings.setValue("geometry", saveGeometry());
settings.setValue("hSplitterSize", m_ui.hSplitter->saveState());
settings.beginWriteArray("formulas");
int count = m_ui.formulaComboBox->count();
for (int iter = 0; iter < count; ++iter)
{
settings.setArrayIndex(iter);
QString index;
index.setNum(iter);
settings.setValue(index, m_ui.formulaComboBox->itemText(iter));
// qDebug () << __FILE__ << __LINE__
// << "Set line:" << m_ui.formulaComboBox->itemText(iter);
}
settings.endArray();
settings.endGroup();
// Force the writing of the geometry settings of the chemical pad
// (the settings are specific for each polymer chemistry
// definition). Look at the function to get it.
showChemPad(Qt::Checked);
showChemPad(Qt::Unchecked);
// We are asked not to remove this window from the list of all the
// calculator windows. This occurs when all the windows are closed
// in the application object.
if (m_noDelistWnd)
{
m_noDelistWnd = false;
event->accept();
return;
}
// We must remove this window from the application's list of such
// windows:
Application *application = static_cast(qApp);
int index = application->calculatorWndList()->indexOf(this);
application->calculatorWndList()->takeAt(index);
event->accept();
}
bool
CalculatorWnd::initialize()
{
m_ui.setupUi(this);
QPixmap pixmap(":/images/massxpert-icon-32.png");
QIcon icon(pixmap);
setWindowIcon(icon);
setAttribute(Qt::WA_DeleteOnClose);
statusBar()->setSizeGripEnabled(true);
////// Connection of the SIGNALS and SLOTS //////
connect(m_ui.addToResultPushButton,
SIGNAL(clicked()),
this,
SLOT(addToResult()));
connect(m_ui.sendToResultPushButton,
SIGNAL(clicked()),
this,
SLOT(sendToResult()));
connect(m_ui.removeFromResultPushButton,
SIGNAL(clicked()),
this,
SLOT(removeFromResult()));
connect(m_ui.clearSeedPushButton,
SIGNAL(clicked()),
this,
SLOT(clearSeed()));
connect(m_ui.addToSeedPushButton,
SIGNAL(clicked()),
this,
SLOT(addToSeed()));
connect(m_ui.sendToSeedPushButton,
SIGNAL(clicked()),
this,
SLOT(sendToSeed()));
connect(m_ui.removeFromSeedPushButton,
SIGNAL(clicked()),
this,
SLOT(removeFromSeed()));
connect(m_ui.clearResultPushButton,
SIGNAL(clicked()),
this,
SLOT(clearResult()));
connect(m_ui.showRecorderCheckBox,
SIGNAL(stateChanged(int)),
this,
SLOT(showRecorder(int)));
connect(m_ui.showChemPadCheckBox,
SIGNAL(stateChanged(int)),
this,
SLOT(showChemPad(int)));
connect(m_ui.applyPushButton,
SIGNAL(clicked()),
this,
SLOT(apply()));
connect(m_ui.mzCalculationPushButton,
SIGNAL(clicked()),
this,
SLOT(mzCalculation()));
connect(m_ui.isotopicPatternCalculationPushButton,
SIGNAL(clicked()),
this,
SLOT(isotopicPatternCalculation()));
connect(m_ui.formulaActionsComboBox,
SIGNAL(activated(int)),
this,
SLOT(formulaActionsComboBoxActivated(int)));
m_ui.formulaSpinBox->setRange(-1000000000, 1000000000);
m_ui.monomerSpinBox->setRange(-1000000000, 1000000000);
m_ui.modifSpinBox->setRange(-1000000000, 1000000000);
m_ui.sequenceSpinBox->setRange(-1000000000, 1000000000);
m_recorderDlg.setParent(this, Qt::Dialog);
m_chemPadDlg.setParent(this, Qt::Dialog);
if (!m_polChemDef.renderXmlPolChemDefFile())
return false;
if (!populatePolChemDefComboBoxes())
{
QMessageBox::warning(0,
tr("massXpert - Calculator"),
tr("Failed to populate the polymer"
" chemistry data comboboxes.\n"
"The calculator will not work properly."),
QMessageBox::Ok);
return false;
}
// Populate the formulaActionsComboBox with the actions:
m_ui.formulaActionsComboBox->insertItem(ADD_FORMULA,
tr("Add formula to memory"));
m_ui.formulaActionsComboBox->insertItem(REMOVE_FORMULA,
tr("Remove formula from memory"));
m_ui.formulaActionsComboBox->insertItem(CLEAR_WHOLE_MEMORY,
tr("Clear whole memory"));
m_ui.formulaActionsComboBox->insertItem(SIMPLIFY_FORMULA,
tr("Simplify formula"));
if (!setupChemicalPad())
return false;
updateWindowTitle();
return true;
}
const PolChemDef &
CalculatorWnd::polChemDef()
{
return m_polChemDef;
}
QString
CalculatorWnd::polChemDefName()
{
return m_polChemDef.name();
}
void
CalculatorWnd::updateWindowTitle()
{
setWindowTitle(tr("%1 %2[*]")
.arg(tr("massXpert - Calculator:"))
.arg(m_polChemDef.name()));
}
bool
CalculatorWnd::populatePolChemDefComboBoxes()
{
int iter = 0;
QStringList stringList;
for (iter = 0; iter < m_polChemDef.monomerList().size(); ++iter)
{
Monomer *monomer = m_polChemDef.monomerList().at(iter);
stringList << monomer->name();
}
m_ui.monomerComboBox->addItems(stringList);
stringList.clear();
for (iter = 0; iter < m_polChemDef.modifList().size(); ++iter)
{
Modif *modif = m_polChemDef.modifList().at(iter);
stringList << modif->name();
}
m_ui.modifComboBox->addItems(stringList);
stringList.clear();
// Set the polymer chemistry definition type to its lineEdit.
m_ui.polChemDefTypeLineEdit->setText(m_polChemDef.name());
updateWindowTitle();
return true;
}
bool
CalculatorWnd::setupChemicalPad()
{
QString filePath;
Application *application = static_cast(qApp);
// Each polymer chemistry definition might have a chemical pad
// configuration file associated to it(simply by being stored in
// the directory of the polymer chemistry definition files).
//
// If a polymer chemistry definition file is loaded in the
// calculator, try to get its corresponding chem_pad.conf file(which
// might not exist, as it is not compulsory to have one).
//
// Otherwise, look in the user's config dir.
if (m_polChemDef.name().isEmpty())
{
// See if the user has one chem_pad.conf file in her
// configuration directory.
filePath = application->configSettings()->userDataDir() +
"/chem_pad.conf";
}
else
{
// Get the directory path of the polymer chemistry definition
// and construct a full pathname to the potentially existing
// config file.
filePath = m_polChemDef.dirPath()
+ QDir::separator() + "chem_pad.conf";
}
QFile file(filePath);
// Note that failing to setup the chemical pad is nothing so serious
// that we return false.
if (! file.open(QFile::ReadOnly))
{
QMessageBox::information(0,
tr("massXpert - Calculator"),
tr("Chemical pad config file not found.\n"
"The chemical pad will not work properly."),
QMessageBox::Ok);
return true;
}
bool ret = m_chemPadDlg.setup(filePath, m_polChemDef.name());
return ret;
}
void
CalculatorWnd::recordResult()
{
Application *application = static_cast(qApp);
QLocale locale = application->locale();
QString recorder = tr("Done: mono: %2 -- avg: %3\n")
.arg(m_tempPonderable.mono(locale))
.arg(m_tempPonderable.avg(locale));
m_recorderDlg.record(recorder);
}
void
CalculatorWnd::updateSeedResultLineEdits()
{
Application *application = static_cast(qApp);
QLocale locale = application->locale();
m_ui.seedMonoMassLineEdit->setText(m_seedPonderable.mono(locale));
m_ui.seedAvgMassLineEdit->setText(m_seedPonderable.avg(locale));
// The m_resultPonderable must always be consistent with the data in
// the corresponding lineEdits.
m_resultPonderable.setMono(m_tempPonderable.mono());
m_resultPonderable.setAvg(m_tempPonderable.avg());
m_ui.resultMonoMassLineEdit->setText(m_resultPonderable.mono(locale));
m_ui.resultAvgMassLineEdit->setText(m_resultPonderable.avg(locale));
}
void
CalculatorWnd::recorderDlgClosed()
{
m_ui.showRecorderCheckBox->setCheckState(Qt::Unchecked);
}
void
CalculatorWnd::chemPadDlgClosed()
{
m_ui.showChemPadCheckBox->setCheckState(Qt::Unchecked);
}
////////////////////////////// SLOTS ///////////////////////////////
void
CalculatorWnd::addToResult()
{
Application *application = static_cast(qApp);
QLocale locale = application->locale();
QString mass;
bool ok = true;
// The data in the seed masses lineEdit widgets must be added to the
// result masses.
// Get the masses from the seed lineEdits and put these in their
// respective ponderable.
// mono
mass = m_ui.seedMonoMassLineEdit->text();
m_seedPonderable.setMono(locale.toDouble(mass, &ok));
if (m_seedPonderable.mono() == 0 && !ok)
{
QMessageBox::warning(0,
tr("massXpert - Calculator"),
tr("Error with seed mono mass"),
QMessageBox::Ok);
return;
}
mass = m_ui.seedAvgMassLineEdit->text();
m_seedPonderable.setAvg(locale.toDouble(mass, &ok));
if (m_seedPonderable.avg() == 0 && !ok)
{
QMessageBox::warning(0,
tr("massXpert - Calculator"),
tr("Error with seed avg mass"),
QMessageBox::Ok);
return;
}
// Prepare the recorder string.
QString recorder = tr("Added seed(mono: %1 ; avg: %2) \n"
"to result(was mono:%3 ; avg: %4) \n")
.arg(m_seedPonderable.mono(locale))
.arg(m_seedPonderable.avg(locale))
.arg(m_resultPonderable.mono(locale))
.arg(m_resultPonderable.avg(locale));
// Make the calculations.
m_resultPonderable.incrementMono(m_seedPonderable.mono());
m_resultPonderable.incrementAvg(m_seedPonderable.avg());
// Update the lineEdits.
m_ui.resultMonoMassLineEdit->setText(m_resultPonderable.mono(locale));
m_ui.resultAvgMassLineEdit->setText(m_resultPonderable.avg(locale));
// And now append the new recorder string to the recorder textEdit.
m_recorderDlg.record(recorder);
}
void
CalculatorWnd::sendToResult()
{
Application *application = static_cast(qApp);
QLocale locale = application->locale();
QString mass;
bool ok = true;
// The seed masses must be sent(no computation here) to the results
// masses.
// Get the masses from the seed lineEdits and put these in their
// respective ponderable.
// mono
mass = m_ui.seedMonoMassLineEdit->text();
m_seedPonderable.setMono(locale.toDouble(mass, &ok));
if (m_seedPonderable.mono() == 0 && !ok)
{
QMessageBox::warning(0,
tr("massXpert - Calculator"),
tr("Error with seed mono mass"),
QMessageBox::Ok);
return;
}
// avg
mass = m_ui.seedAvgMassLineEdit->text();
m_seedPonderable.setAvg(locale.toDouble(mass, &ok));
if (m_seedPonderable.avg() == 0 && !ok)
{
QMessageBox::warning(0,
tr("massXpert - Calculator"),
tr("Error with seed avg mass"),
QMessageBox::Ok);
return;
}
// Prepare the recorder string.
QString recorder = tr("Sent seed(mono: %1 ; avg: %2) \n"
"to result(was mono:%3 ; avg: %4) \n")
.arg(m_seedPonderable.mono(locale))
.arg(m_seedPonderable.avg(locale))
.arg(m_resultPonderable.mono(locale))
.arg(m_resultPonderable.avg(locale));
m_resultPonderable.setMono(m_seedPonderable.mono());
m_resultPonderable.setAvg(m_seedPonderable.avg());
// Update the lineEdits.
m_ui.resultMonoMassLineEdit->setText(m_resultPonderable.mono(locale));
m_ui.resultAvgMassLineEdit->setText(m_resultPonderable.avg(locale));
}
void
CalculatorWnd::removeFromResult()
{
Application *application = static_cast(qApp);
QLocale locale = application->locale();
QString mass;
bool ok = true;
// The data in the seed masses lineEdit widgets must be removed from
// the result masses.
// Get the masses from the seed lineEdits and put these in their
// respective ponderable.
// mono
mass = m_ui.seedMonoMassLineEdit->text();
m_seedPonderable.setMono(locale.toDouble(mass, &ok));
if (m_seedPonderable.mono() == 0 && !ok)
{
QMessageBox::warning(0,
tr("massXpert - Calculator"),
tr("Error with seed mono mass"),
QMessageBox::Ok);
return;
}
// avg
mass = m_ui.seedAvgMassLineEdit->text();
m_seedPonderable.setAvg(locale.toDouble(mass, &ok));
if (m_seedPonderable.avg() == 0 && !ok)
{
QMessageBox::warning(0,
tr("massXpert - Calculator"),
tr("Error with seed avg mass"),
QMessageBox::Ok);
return;
}
// Prepare the recorder string.
QString recorder = tr("Removed seed(mono: %1 ; avg: %2) \n"
"from result(was mono:%3 ; avg: %4) \n")
.arg(m_seedPonderable.mono(locale))
.arg(m_seedPonderable.avg(locale))
.arg(m_resultPonderable.mono(locale))
.arg(m_resultPonderable.avg(locale));
// Make the calculations.
m_resultPonderable.decrementMono(m_seedPonderable.mono());
m_resultPonderable.decrementAvg(m_seedPonderable.avg());
// Update the lineEdits.
m_ui.resultMonoMassLineEdit->setText(m_resultPonderable.mono(locale));
m_ui.resultAvgMassLineEdit->setText(m_resultPonderable.avg(locale));
// And now append the new recorder string to the recorder textEdit.
m_recorderDlg.record(recorder);
}
void
CalculatorWnd::clearSeed()
{
m_seedPonderable.clearMasses();
m_ui.seedMonoMassLineEdit->setText("");
m_ui.seedAvgMassLineEdit->setText("");
}
void
CalculatorWnd::addToSeed()
{
Application *application = static_cast(qApp);
QLocale locale = application->locale();
QString mass;
bool ok = true;
// The data in the result masses lineEdit widgets must be added to
// the seed masses.
// Get the masses from the seed lineEdits and put these in their
// respective ponderable.
// mono
mass = m_ui.seedMonoMassLineEdit->text();
m_seedPonderable.setMono(locale.toDouble(mass, &ok));
if (m_seedPonderable.mono() == 0 && !ok)
{
QMessageBox::warning(0,
tr("massXpert - Calculator"),
tr("Error with seed mono mass"),
QMessageBox::Ok);
return;
}
// avg
mass = m_ui.seedAvgMassLineEdit->text();
m_seedPonderable.setAvg(locale.toDouble(mass, &ok));
if (m_seedPonderable.avg() == 0 && !ok)
{
QMessageBox::warning(0,
tr("massXpert - Calculator"),
tr("Error with seed avg mass"),
QMessageBox::Ok);
return;
}
// Prepare the recorder string.
QString recorder = tr("Added result(mono: %1 ; avg: %2) \n"
"to seed(was mono:%3 ; avg: %4) \n")
.arg(m_resultPonderable.mono(locale))
.arg(m_resultPonderable.avg(locale))
.arg(m_seedPonderable.mono(locale))
.arg(m_seedPonderable.avg(locale));
// Make the calculations.
m_seedPonderable.incrementMono(m_resultPonderable.mono());
m_seedPonderable.incrementAvg(m_resultPonderable.avg());
// Update the lineEdits.
m_ui.seedMonoMassLineEdit->setText(m_seedPonderable.mono(locale));
m_ui.seedAvgMassLineEdit->setText(m_seedPonderable.avg(locale));
// And now append the new recorder string to the recorder textEdit.
m_recorderDlg.record(recorder);
}
void
CalculatorWnd::sendToSeed()
{
Application *application = static_cast(qApp);
QLocale locale = application->locale();
// The result masses must be sent(no computation here) to the seed
// masses.
// Prepare the recorder string.
QString recorder = tr("Sent result(mono: %1 ; avg: %2) \n"
"to seed(was mono:%3 ; avg: %4) \n")
.arg(m_resultPonderable.mono(locale))
.arg(m_resultPonderable.avg(locale))
.arg(m_seedPonderable.mono(locale))
.arg(m_seedPonderable.avg(locale));
m_seedPonderable.setMono(m_resultPonderable.mono());
m_seedPonderable.setAvg(m_resultPonderable.avg());
// Update the lineEdits.
m_ui.seedMonoMassLineEdit->setText(m_seedPonderable.mono(locale));
m_ui.seedAvgMassLineEdit->setText(m_seedPonderable.avg(locale));
}
void
CalculatorWnd::removeFromSeed()
{
Application *application = static_cast(qApp);
QLocale locale = application->locale();
QString mass;
bool ok = true;
// The data in the result masses lineEdit widgets must be removed
// from the seed masses.
// Get the masses from the seed lineEdits and put these in their
// respective ponderable.
// mono
mass = m_ui.seedMonoMassLineEdit->text();
m_seedPonderable.setMono(locale.toDouble(mass, &ok));
if (m_seedPonderable.mono() == 0 && !ok)
{
QMessageBox::warning(0,
tr("massXpert - Calculator"),
tr("Error with seed mono mass"),
QMessageBox::Ok);
return;
}
// avg
mass = m_ui.seedAvgMassLineEdit->text();
m_seedPonderable.setAvg(locale.toDouble(mass, &ok));
if (m_seedPonderable.avg() == 0 && !ok)
{
QMessageBox::warning(0,
tr("massXpert - Calculator"),
tr("Error with seed avg mass"),
QMessageBox::Ok);
return;
}
// Prepare the recorder string.
QString recorder = tr("Removed result(mono: %1 ; avg: %2) \n"
"from seed(was mono:%3 ; avg: %4) \n")
.arg(m_resultPonderable.mono(locale))
.arg(m_resultPonderable.avg(locale))
.arg(m_seedPonderable.mono(locale))
.arg(m_seedPonderable.avg(locale));
// Make the calculations.
m_seedPonderable.decrementMono(m_resultPonderable.mono());
m_seedPonderable.decrementAvg(m_resultPonderable.avg());
// Update the lineEdits.
m_ui.seedMonoMassLineEdit->setText(m_seedPonderable.mono(locale));
m_ui.seedAvgMassLineEdit->setText(m_seedPonderable.avg(locale));
// And now append the new recorder string to the recorder textEdit.
m_recorderDlg.record(recorder);
}
void
CalculatorWnd::clearResult()
{
m_resultPonderable.clearMasses();
m_ui.resultMonoMassLineEdit->setText("");
m_ui.resultAvgMassLineEdit->setText("");
}
void
CalculatorWnd::apply(const QString &formula)
{
Application *application = static_cast(qApp);
QLocale locale = application->locale();
QString mass;
bool ok = true;
bool calculationPerformed = false;
int res = -1;
if (m_polChemDef.atomList().size() == 0)
{
QMessageBox::warning(0,
tr("massXpert - Calculator"),
tr("No atom list is available"),
QMessageBox::Ok);
return;
}
// We have to iterate into all the relevant widgets and account
// for the corresponding chemical entities.
// The starting masses are either the seed masses or the result
// masses. If the results masses lineEdits are empty, then we use
// the seed masses. If not, then we prefer using the results masses
// because this way the calculations are incremental, exactly as
// when a desktop calculator is used.
if (!m_ui.resultMonoMassLineEdit->text().isEmpty()
|| !m_ui.resultAvgMassLineEdit->text().isEmpty())
{
// The result masses lineEdits contain something, so we use
// these to perform the calculations.
// We use the m_tempPonderable as a repository for the masses
// actually used for the computation, be them seed or result:
m_tempPonderable.setMono(m_resultPonderable.mono());
m_tempPonderable.setAvg(m_resultPonderable.avg());
// Store the result masses in the seed masses object, because
// we'll need these values to put them in the seed lineEdits to
// provide one level of undo.
m_seedPonderable.setMono(m_resultPonderable.mono());
m_seedPonderable.setAvg(m_resultPonderable.avg());
}
else
{
// The result masses are empty, so consider using the seed
// masses instead.
// We use the m_tempPonderable as a repository for the masses
// actually used for the computation, be them seed or result:
if (m_ui.seedMonoMassLineEdit->text().isEmpty()
|| m_ui.seedAvgMassLineEdit->text().isEmpty())
{
// The seed masses are empty and the result masses
// also. Thus we postulate the user just wants to start
// fresh, that is seed masses are all 0.
m_tempPonderable.setMono(0);
m_tempPonderable.setAvg(0);
}
else
{
mass = m_ui.seedMonoMassLineEdit->text();
m_tempPonderable.setMono(locale.toDouble(mass, &ok));
if (m_tempPonderable.avg() == 0 && !ok)
{
QMessageBox::warning(0,
tr("massXpert - Calculator"),
tr("Error with seed avg mass"),
QMessageBox::Ok);
return;
}
mass = m_ui.seedAvgMassLineEdit->text();
m_tempPonderable.setAvg(locale.toDouble(mass, &ok));
if (m_tempPonderable.avg() == 0 && !ok)
{
QMessageBox::warning(0,
tr("massXpert - Calculator"),
tr("Error with seed avg mass"),
QMessageBox::Ok);
return;
}
}
// Store these same seed masses in the seed masses object,
// because we'll need these values to put them in the seed
// lineEdits to provide one level of undo.
m_seedPonderable.setMono(m_tempPonderable.mono());
m_seedPonderable.setAvg(m_tempPonderable.avg());
}
// Prepare the recorder string.
QString recorder =
tr("===================================================================\n"
"Seed masses: %1 -- %2\n")
.arg(m_seedPonderable.mono())
.arg(m_seedPonderable.avg());
// And now append the new recorder string to the recorder textEdit.
m_recorderDlg.record(recorder);
// Finally we can start doing work with the chemical entities...
// Formulae
// If the 'formula' parameter contains a string, then two cases arise:
// 1. If m_formulaHandling has the MXP_FORMULA_HANDLING_PRINT bit
// set, then do not account the formula, but simply insert it in
// the formula line edit widget.
// 2. If m_formulaHandling has the MXP_FORMULA_HANDLING_WITH_SPACE
// bit set, then also add a space to the formula (this is
// interesting when sending a large number of forumulas, so that
// each sent one is distinct from the next one.
// 2. If m_formulaHandling has the MXP_FORMULA_HANDLING_IMMEDIATE
// bit set, then account the formula immediately and return.
// Both situations 1. and 2. are related to this function being
// called from one chemical pad button.
if (!formula.isEmpty())
{
// There is a formula in the parameter... Check if we have to
// evaluate it immediately or if we have to just insert it in
// the current formula comboBox widget's item.
if (m_formulaHandling & MXP_FORMULA_HANDLING_PRINT)
{
// Get the line edit widget of the comboBox.
QLineEdit* lineEdit = m_ui.formulaComboBox->lineEdit();
if (m_formulaHandling & MXP_FORMULA_HANDLING_WITH_SPACE)
{
lineEdit->insert(QString (" "));
lineEdit->insert(formula);
lineEdit->insert(QString (" "));
}
else
{
lineEdit->insert(formula);
}
return;
}
else
{
int res = accountFormula(formula);
if (res == -1)
QMessageBox::warning(0,
tr("massXpert - Calculator"),
tr("Error accounting formula '%1'")
.arg(formula),
QMessageBox::Ok);
else if (res == 1)
{
recordResult();
updateSeedResultLineEdits();
}
return;
}
}
else
{
// No formula was put into the parameter in the call to this
// function. Just do the whole business as usual.
res = accountFormula();
if (res == -1)
QMessageBox::warning(0,
tr("massXpert - Calculator"),
tr("Error accounting formula"),
QMessageBox::Ok);
else if (res == 1)
{
recordResult();
calculationPerformed = true;
}
}
if (!m_polChemDef.name().isEmpty())
{
// A polymer chemistry definition was loaded, account for its
// potential chemical entities.
res = accountMonomer();
if (res == -1)
QMessageBox::warning(0,
tr("massXpert - Calculator"),
tr("Error accounting monomer"),
QMessageBox::Ok);
else if (res == 1)
{
recordResult();
calculationPerformed = true;
}
res = accountModif ();
if (res == -1)
QMessageBox::warning(0,
tr("massXpert - Calculator"),
tr("Error accounting modif"),
QMessageBox::Ok);
else if (res == 1)
{
recordResult();
calculationPerformed = true;
}
res = accountSequence();
if (res == -1)
QMessageBox::warning(0,
tr("massXpert - Calculator"),
tr("Error accounting sequence"),
QMessageBox::Ok);
else if (res == 1)
{
recordResult();
calculationPerformed = true;
}
}
// End of
// if (!m_polChemDef.type().isEmpty())
// Update the lineEdits only if at last one calculation was
// performed.
if (!calculationPerformed)
return;
updateSeedResultLineEdits();
}
void
CalculatorWnd::mzCalculation()
{
// Call the constructor with mono/avg seeds.
MzCalculationDlg *dlg =
new MzCalculationDlg(this,
&m_polChemDef,
&m_polChemDef.ionizeRule(),
m_resultPonderable.mono(),
m_resultPonderable.avg());
dlg->show();
}
void
CalculatorWnd::isotopicPatternCalculation()
{
SpectrumCalculationDlg *dlg =
new SpectrumCalculationDlg(this,
m_polChemDef.atomList(),
MXP_SPECTRUM_CALCULATION_MODE_CLUSTER);
// We really need that the dialog be set modal because we want to
// be able to access all the atom and oligomer data freely and
// durably.
dlg->setModal(true);
dlg->show();
}
void
CalculatorWnd::formulaActionsComboBoxActivated(int index)
{
if (index == ADD_FORMULA)
{
// qDebug() << __FILE__ << __LINE__ << "ADD_TO_MEMORY";
addFormulaToMemory();
}
if (index == REMOVE_FORMULA)
{
// qDebug() << __FILE__ << __LINE__ << "ADD_TO_MEMORY";
removeFormulaFromMemory();
}
if (index == CLEAR_WHOLE_MEMORY)
{
// qDebug() << __FILE__ << __LINE__ << "CLEAR_MEMORY";
clearWholeMemory();
}
if (index == SIMPLIFY_FORMULA)
{
// qDebug() << __FILE__ << __LINE__ << "SIMPLIFY_FORMULA";
simplifyFormula();
}
}
int
CalculatorWnd::accountFormula(const QString &formula, int times)
{
QString text;
int count;
// This function might be called via the chemical pad, and thus has
// to test existence of atom definitions. The 'apply()' function
// does that test for when the calculation is triggered by clicking
// on the apply button.
if (m_polChemDef.atomList().size() == 0)
{
QMessageBox::warning(0,
tr("massXpert - Calculator"),
tr("No atom list is available"),
QMessageBox::Ok);
return false;
}
if (formula.isEmpty())
{
// No string passed as parameter, get the formula from its
// corresponding comboBox.
text = m_ui.formulaComboBox->currentText();
if (text.isEmpty())
return 0;
// We want to remove spaces from the text. This is useful so
// the user might enter spaces in the formula to ease
// re-reading the formula text (useful when entering complex
// formula for saccharides, for example, in my own
// experience).
text.remove(QRegExp("\\s+"));
// Note that we might also have a title for the formula, which
// is enclosed between `"' at the beginning of the line.
text.remove(QRegExp("\".*\""));
// How many times should the formula be accounted for?
count = m_ui.formulaSpinBox->value();
if (count == 0)
return 0;
}
else
{
text = formula;
// The times param tells us how many times should the formula be
// accounted for.
count = times;
}
Modif fake(&m_polChemDef, "NOT_SET", text);
if (!fake.calculateMasses())
return -1;
// Prepare the recorder string.
QString recorder = tr("Accounting formula: %1(%2 times)... ")
.arg(text)
.arg(count);
// And now append the new recorder string to the recorder textEdit.
m_recorderDlg.record(recorder);
if (!fake.accountMasses(&m_tempPonderable.rmono(),
&m_tempPonderable.ravg(),
count))
return -1;
return 1;
}
int
CalculatorWnd::accountMonomer()
{
QString text;
// Get to see if there is a necessity to account for the displayed
// monomer.
int count = m_ui.monomerSpinBox->value();
if (count == 0)
return 0;
text = m_ui.monomerComboBox->currentText();
// Locate and make a copy of the reference monomer, that we may not
// use itself, as the formula parsing operation do modify the
// object..
Monomer monomer(&m_polChemDef, "NOT_SET");
int index = -1;
index = Monomer::isNameInList(text,
m_polChemDef.monomerList(),
&monomer);
// It cannot be that the text in the combobox does not correspond to
// a known monomer.
if (index == -1)
qFatal("Fatal error at %s@%d. Aborting.",__FILE__, __LINE__);
// Prepare the recorder string.
QString recorder = tr("Accounting monomer: %1(%2 times)... ")
.arg(monomer.name())
.arg(count);
// And now append the new recorder string to the recorder textEdit.
m_recorderDlg.record(recorder);
if (!monomer.accountMasses(&m_tempPonderable.rmono(),
&m_tempPonderable.ravg(),
count))
return -1;
return 1;
}
int
CalculatorWnd::accountModif ()
{
QString text;
// Get to see if there is a necessity to account for the displayed
// modif.
int count = m_ui.modifSpinBox->value();
if (count == 0)
return 0;
text = m_ui.modifComboBox->currentText();
// Locate the reference modif and make a copy of it, as we may not
// use itself, as the parsing operation do modify the object.
Modif modif (&m_polChemDef, "NOT_SET");
int index = -1;
index = Modif::isNameInList(text,
m_polChemDef.modifList(),
&modif);
// It cannot be that the text in the combobox does not correspond to
// a known modif.
if (index == -1)
qFatal("Fatal error at %s@%d. Aborting.",__FILE__, __LINE__);
// Prepare the recorder string.
QString recorder = tr("Accounting modif: %1(%2 times)... ")
.arg(modif.name())
.arg(count);
// And now append the new recorder string to the recorder textEdit.
m_recorderDlg.record(recorder);
if (!modif.accountMasses(&m_tempPonderable.rmono(),
&m_tempPonderable.ravg(),
count))
return -1;
return 1;
}
int
CalculatorWnd::accountSequence()
{
QString text;
// Get to see if there is a necessity to account for the displayed
// sequence.
int count = m_ui.sequenceSpinBox->value();
if (count == 0)
return 0;
text = m_ui.sequenceLineEdit->text();
if (text.isEmpty())
return 0;
Sequence sequence(text);
if (sequence.makeMonomerList(&m_polChemDef, false, 0) == - 1)
return -1;
// Prepare the recorder string.
QString recorder = tr("Accounting sequence: %1(%2 times)... ")
.arg(text)
.arg(count);
// And now append the new recorder string to the recorder textEdit.
m_recorderDlg.record(recorder);
for (int iter = 0; iter < sequence.size(); ++iter)
{
const Monomer *monomer = sequence.at(iter);
Q_ASSERT(monomer);
if (!monomer->accountMasses(&m_tempPonderable.rmono(),
&m_tempPonderable.ravg(),
count))
return -1;
}
return 1;
}
void
CalculatorWnd::showRecorder(int state)
{
if (state == Qt::Checked)
{
QSettings settings
(static_cast(qApp)->configSettingsFilePath(),
QSettings::IniFormat);
m_recorderDlg.restoreGeometry
(settings.value("calculator_recorder_dlg/geometry").toByteArray());
m_recorderDlg.show();
}
else
{
QSettings settings
(static_cast(qApp)->configSettingsFilePath(),
QSettings::IniFormat);
settings.setValue("calculator_recorder_dlg/geometry",
m_recorderDlg.saveGeometry());
m_recorderDlg.hide();
}
}
void
CalculatorWnd::showChemPad(int state)
{
if (state == Qt::Checked)
{
QSettings settings
(static_cast(qApp)->configSettingsFilePath(),
QSettings::IniFormat);
settings.beginGroup("calculator_chem_pad_dlg");
QString setting = QString("%1-%2")
.arg(polChemDefName())
.arg("geometry");
m_chemPadDlg.restoreGeometry(settings.value(setting).toByteArray());
settings.endGroup();
m_chemPadDlg.show();
}
else
{
QSettings settings
(static_cast(qApp)->configSettingsFilePath(),
QSettings::IniFormat);
settings.beginGroup("calculator_chem_pad_dlg");
QString setting = QString("%1-%2")
.arg(polChemDefName())
.arg("geometry");
settings.setValue(setting, m_chemPadDlg.saveGeometry());
settings.endGroup();
m_chemPadDlg.hide();
}
}
void
CalculatorWnd::setFormulaHandling(int val)
{
m_formulaHandling = val;
}
void
CalculatorWnd::addFormulaToMemory()
{
// Get the current text from the comboBox's lineEdit widget.
QString text = m_ui.formulaComboBox->currentText();
// qDebug() << __FILE__ << __LINE__ << "text:" << text;
if (text.isEmpty())
return;
m_ui.formulaComboBox->addItem(text);
}
void
CalculatorWnd::removeFormulaFromMemory()
{
int currentIndex = m_ui.formulaComboBox->currentIndex();
if (currentIndex != -1)
m_ui.formulaComboBox->removeItem (currentIndex);
}
void
CalculatorWnd::clearWholeMemory()
{
m_ui.formulaComboBox->clear();
}
QString
CalculatorWnd::simplifyFormula()
{
// Imagine we do lots of formula stuff, and we want to refactor a
// given series of formulas into one single formula like this:
// We have +CH3 -C +C2H6O4N5P
// We want to have the result of this: that is C2H8O4N5P
// To do the simplification we need the list of atoms of the
// current polymer chemistry definition.
if (m_polChemDef.atomList().size() == 0)
{
QMessageBox::warning(0,
tr("massXpert - Calculator"),
tr("No atom list is available"),
QMessageBox::Ok);
return QString("");;
}
QString text = m_ui.formulaComboBox->currentText();
if (text.isEmpty())
return QString("");
// We want to remove spaces from the text. This is useful so the
// user might enter spaces in the formula to ease re-reading the
// formula text (useful when entering complex formula for
// saccharides, for example, in my own experience).
text.remove(QRegExp("\\s+"));
// Note that we might also have a title for the formula, which is
// enclosed between `"' at the beginning of the line.
text.remove(QRegExp("\".*\""));
// Validate the formula by creating a fake modification object
// with it and by accounting masses for that formula.
Modif fake(&m_polChemDef, "NOT_SET", text);
if (!fake.calculateMasses())
{
QMessageBox::warning(0,
tr("massXpert - Calculator"),
tr("Failed to parse the formula."),
QMessageBox::Ok);
return QString("");
}
QString simplified = fake.elementalComposition();
// qDebug() << "simplified:" << simplified;
if (!simplified.isEmpty())
{
// Store the formula to the memory, so that the user can check
// things.
addFormulaToMemory();
// Set the new simplified formula to the comboBox.
m_ui.formulaComboBox->lineEdit()->setText(simplified);
}
return simplified;
}
} // namespace massXpert
massxpert-3.6.0/gui/calculatorWnd.hpp 0000664 0000000 0000000 00000007364 12577256262 0017675 0 ustar 00root root 0000000 0000000 /* 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.
*/
#ifndef CALCULATOR_WND_HPP
#define CALCULATOR_WND_HPP
/////////////////////// Qt includes
#include
/////////////////////// Local includes
#include "ui_calculatorWnd.h"
#include "ponderable.hpp"
#include "polChemDef.hpp"
#include "calculatorRecorderDlg.hpp"
#include "calculatorChemPadDlg.hpp"
namespace massXpert
{
enum MxpFormulaHandling
{
MXP_FORMULA_HANDLING_IMMEDIATE = 1 << 0,
MXP_FORMULA_HANDLING_PRINT = 1 << 1,
MXP_FORMULA_HANDLING_WITH_SPACE = 1 << 2,
MXP_FORMULA_HANDLING_PRINT_WITH_SPACE =
(MXP_FORMULA_HANDLING_PRINT | MXP_FORMULA_HANDLING_WITH_SPACE),
};
class CalculatorWnd : public QMainWindow
{
Q_OBJECT
private:
Ui::CalculatorWnd m_ui;
Ponderable m_seedPonderable;
Ponderable m_tempPonderable;
Ponderable m_resultPonderable;
CalculatorRecorderDlg m_recorderDlg;
CalculatorChemPadDlg m_chemPadDlg;
PolChemDef m_polChemDef;
void closeEvent(QCloseEvent *event);
public:
bool m_forciblyClose;
bool m_noDelistWnd;
int m_formulaHandling;
CalculatorWnd(QString &,
const QString & = QString(),
const QString & = QString());
~CalculatorWnd();
bool initialize();
const PolChemDef &polChemDef();
QString polChemDefName();
void updateWindowTitle();
bool populatePolChemDefComboBoxes();
bool setupChemicalPad();
void recordResult();
void updateSeedResultLineEdits();
void recorderDlgClosed();
void chemPadDlgClosed();
int accountFormula(const QString & = QString(""), int = 1);
int accountMonomer();
int accountModif();
int accountSequence();
void setFormulaHandling(int);
void addFormulaToMemory();
void removeFormulaFromMemory();
void clearWholeMemory();
QString simplifyFormula();
public slots:
void addToResult();
void sendToResult();
void removeFromResult();
void clearSeed();
void addToSeed();
void sendToSeed();
void removeFromSeed();
void clearResult();
void showRecorder(int);
void formulaActionsComboBoxActivated(int);
void showChemPad(int);
void apply(const QString & = QString(""));
void mzCalculation();
void isotopicPatternCalculation();
};
} // namespace massXpert
#endif // CALCULATOR_WND_HPP
massxpert-3.6.0/gui/chemPadButton.cpp 0000664 0000000 0000000 00000005523 12577256262 0017616 0 ustar 00root root 0000000 0000000 /* 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
#include
#include
/////////////////////// Local includes
#include "chemPadButton.hpp"
#include "calculatorWnd.hpp"
namespace massXpert
{
ChemPadButton::ChemPadButton(const QString & text,
const QString &formula,
QWidget *calculator_wnd,
QWidget *parent,
const QColor &backgroundColor,
const QColor &foregroundColor)
: QPushButton(text, parent)
{
Q_ASSERT(calculator_wnd);
mp_calculatorWnd = static_cast(calculator_wnd);
m_formula = formula;
if (backgroundColor.isValid() && foregroundColor.isValid())
{
QString bgColorString = QString ("rgb(%1,%2,%3)")
.arg(backgroundColor.red())
.arg(backgroundColor.green())
.arg(backgroundColor.blue());
QString fgColorString = QString ("rgb(%1,%2,%3)")
.arg(foregroundColor.red())
.arg(foregroundColor.green())
.arg(foregroundColor.blue());
setStyleSheet(QString ("QPushButton {background: %1 ; color: %2}")
.arg(bgColorString)
.arg(fgColorString));
}
connect(this,
SIGNAL(clicked()),
this,
SLOT(clicked()));
}
ChemPadButton::~ChemPadButton()
{
}
void
ChemPadButton::clicked()
{
// We have to account for the formula corresponding to this button.
return mp_calculatorWnd->apply(m_formula);
}
} // namespace massXpert
massxpert-3.6.0/gui/chemPadButton.hpp 0000664 0000000 0000000 00000003767 12577256262 0017633 0 ustar 00root root 0000000 0000000 /* 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.
*/
#ifndef CHEM_PAD_BUTTON_HPP
#define CHEM_PAD_BUTTON_HPP
/////////////////////// Qt includes
#include
namespace massXpert
{
class CalculatorWnd;
class ChemPadButton : public QPushButton
{
Q_OBJECT
private:
QString m_formula;
CalculatorWnd *mp_calculatorWnd;
public:
ChemPadButton(const QString &,
const QString &,
QWidget *,
QWidget * = 0,
const QColor & = QColor(),
const QColor & = QColor());
~ChemPadButton();
public slots:
void clicked();
};
} // namespace massXpert
#endif // CHEM_PAD_BUTTON_HPP
massxpert-3.6.0/gui/cleavageDlg.cpp 0000664 0000000 0000000 00000064140 12577256262 0017257 0 ustar 00root root 0000000 0000000 /* 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
#include
#include
/////////////////////// Local includes
#include "cleavageDlg.hpp"
#include "application.hpp"
#include "peakShape.hpp"
#include "peakCentroid.hpp"
#include "peakShapeConfig.hpp"
#include "isotopicPatternCalculator.hpp"
#include "spectrumCalculationDlg.hpp"
namespace massXpert
{
CleavageDlg::CleavageDlg(QWidget *parent,
Polymer *polymer,
const PolChemDef *polChemDef,
const CalcOptions &calcOptions,
const IonizeRule *ionizeRule)
: QDialog(parent),
mp_polymer(polymer),
mp_polChemDef(polChemDef),
m_calcOptions(calcOptions),
mp_ionizeRule(ionizeRule)
{
Q_ASSERT(parent);
Q_ASSERT(!mp_polymer.isNull() && mp_polChemDef && mp_ionizeRule);
m_ui.setupUi(this);
mp_editorWnd = static_cast(parent);
m_ui.delimiterLineEdit->setText("$");
populateCleaveSpecListWidget();
populateSelectedOligomerData();
// Set pointers to 0 so that after the setupTableView call below
// they'll get their proper value. We'll then be able to free all
// that stuff in the destructor.
mpa_cleaver = 0;
mpa_proxyModel = 0;
mpa_oligomerTableViewModel = 0;
setupTableView();
// The tolerance when filtering mono/avg masses...
QStringList stringList;
stringList << tr("AMU") << tr("PCT") << tr("PPM");
m_ui.toleranceComboBox->insertItems(0, stringList);
m_ui.toleranceComboBox->setToolTip(tr("AMU: atom mass unit \n"
"PCT: percent \n"
"PPM: part per million"));
filterAct = new QAction(tr("Toggle Filtering"), this);
filterAct->setShortcut(QKeySequence(Qt::CTRL+Qt::Key_F));
this->addAction(filterAct);
connect(filterAct,
SIGNAL(triggered()),
this,
SLOT(filterOptionsToggled()));
m_ui.filteringOptionsGroupBox->addAction(filterAct);
// When the dialog box is created it is created with the groupbox
// unchecked.
m_ui.filteringOptionsFrame->setVisible(false);
// When the filtering group box will be opened, the focus will be
// on the first widget of the groupbox:
mp_focusWidget = m_ui.filterPartialLineEdit;
// The results-exporting menus. ////////////////////////////////
QStringList comboBoxItemList;
comboBoxItemList
<< tr("To Clipboard")
<< tr("To File")
<< tr("Select File")
<< tr("Calculate spectrum");
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(qApp)->configSettingsFilePath(),
QSettings::IniFormat);
settings.beginGroup("cleavage_dlg");
restoreGeometry(settings.value("geometry").toByteArray());
m_ui.oligomersSplitter->
restoreState(settings.value("oligomersSplitter").toByteArray());
m_ui.oligoDetailsSplitter->
restoreState(settings.value("oligoDetailsSplitter").toByteArray());
settings.endGroup();
connect(m_ui.cleavePushButton,
SIGNAL(clicked()),
this,
SLOT(cleave()));
connect(m_ui.filterPartialLineEdit,
SIGNAL(returnPressed()),
this,
SLOT(filterPartial()));
connect(m_ui.filterMonoMassLineEdit,
SIGNAL(returnPressed()),
this,
SLOT(filterMonoMass()));
connect(m_ui.filterAvgMassLineEdit,
SIGNAL(returnPressed()),
this,
SLOT(filterAvgMass()));
connect(m_ui.filterChargeLineEdit,
SIGNAL(returnPressed()),
this,
SLOT(filterCharge()));
connect(m_ui.filteringOptionsGroupBox,
SIGNAL(clicked(bool)),
this,
SLOT(filterOptions(bool)));
}
CleavageDlg::~CleavageDlg()
{
// Delete the oligomers in the list of such instances.
while(!m_oligomerList.isEmpty())
delete m_oligomerList.takeFirst();
delete mpa_resultsString;
delete mpa_oligomerTableViewModel;
delete mpa_proxyModel;
delete mpa_cleaver;
}
bool
CleavageDlg::populateSelectedOligomerData()
{
CoordinateList coordList;
Coordinates *coordinates = 0;
if (!mp_editorWnd->mpa_editorGraphicsView->selectionIndices(&coordList) )
{
// We get the selection indices corresponding to the virtual
// selection, that is the sequence region encompassing the
// first residue of the sequence up to the monomer left of
// point.
// In this case we want the cleavage to be performed on the
// whole polymer sequence. Set its coordinates to the list of
// coordinates.
coordinates = new Coordinates(0, mp_polymer->size() - 1);
// Set the newly created coordinates to the coordinates list
// that we'll feed into the calculation options.
coordList.setCoordinates(*coordinates);
// We do not need the coordinates object anymore, delete it.
delete coordinates;
coordinates = 0;
}
if (coordList.size() > 1)
{
QMessageBox::information(this, tr("massxpert - Polymer Cleavage"),
tr("Cleavage simulations with\n"
"multi-region selection are not"
"supported."),
QMessageBox::Ok);
// Set the selection data as if all of the sequence was to be
// cleaved.
coordinates = new Coordinates(0, mp_polymer->size() - 1);
// Set the newly created coordinates to the coordinates list
// that we'll feed into the calculation options.
coordList.setCoordinates(*coordinates);
// We do not need the coordinates object anymore, delete it.
delete coordinates;
coordinates = 0;
}
// Now, if the checkbox asking for whole sequence cleavage is
// checked, then we have to make the cleavage on the whole
// sequence.
if (m_ui.wholeSequenceCheckBox->isChecked())
{
// The cleavage is to be performed on the whole polymer
// sequence.
coordinates = new Coordinates(0, mp_polymer->size() - 1);
// Set the newly created coordinates to the coordinates list
// that we'll feed into the calculation options.
coordList.setCoordinates(*coordinates);
// We do not need the coordinates object anymore, delete it.
delete coordinates;
coordinates = 0;
}
m_calcOptions.setCoordinateList(coordList);
coordinates = coordList.last();
m_ui.oligomerStartLabel->
setText(QString().setNum(coordinates->start() + 1));
m_ui.oligomerEndLabel->
setText(QString().setNum(coordinates->end() + 1));
// We have to count the incomplete cross-links.
const CrossLinkList &crossLinkList = mp_polymer->crossLinkList();
int crossLinkPartial = 0;
for (int iter = 0; iter < crossLinkList.size(); ++iter)
{
CrossLink *crossLink = crossLinkList.at(iter);
int ret = crossLink->encompassedBy(coordList);
if(ret == MXP_CROSS_LINK_ENCOMPASSED_FULL)
{
// qDebug() << __FILE__ << __LINE__
// << "CrossLink at iter:" << iter
// << "is fully encompassed";
}
else if (ret == MXP_CROSS_LINK_ENCOMPASSED_PARTIAL)
{
// qDebug() << __FILE__ << __LINE__
// << "CrossLink at iter:" << iter
// << "is partially encompassed";
++crossLinkPartial;
}
else
{
// qDebug() << __FILE__ << __LINE__
// << "CrossLink at iter:" << iter
// << "is not encompassed at all";
}
}
if (crossLinkPartial)
{
// Alert the user on the fact that the currently selected
// region does not encompass all of the cross-linked material.
QMessageBox::information(this,
tr("massXpert - Polymer Cleavage"),
tr("There are incomplete cross-links"),
QMessageBox::Ok);
}
return true;
}
void
CleavageDlg::populateCleaveSpecListWidget()
{
PolChemDef *polChemDef = mp_editorWnd->polChemDef();
Q_ASSERT(polChemDef);
for (int iter = 0; iter < polChemDef->cleaveSpecList().size(); ++iter)
{
CleaveSpec *cleaveSpec = polChemDef->cleaveSpecList().at(iter);
Q_ASSERT(cleaveSpec);
m_ui.cleavageAgentListWidget->addItem(cleaveSpec->name());
}
return;
}
void
CleavageDlg::setupTableView()
{
// Model stuff all thought for sorting.
mpa_oligomerTableViewModel =
new CleaveOligomerTableViewModel(&m_oligomerList, this);
mpa_proxyModel = new CleaveOligomerTableViewSortProxyModel(this);
mpa_proxyModel->setSourceModel(mpa_oligomerTableViewModel);
mpa_proxyModel->setFilterKeyColumn(-1);
m_ui.oligomerTableView->setModel(mpa_proxyModel);
m_ui.oligomerTableView->setParentDlg(this);
m_ui.oligomerTableView->setOligomerList(&m_oligomerList);
mpa_oligomerTableViewModel->setTableView(m_ui.oligomerTableView);
}
SequenceEditorWnd *
CleavageDlg::editorWnd()
{
return mp_editorWnd;
}
void
CleavageDlg::cleave()
{
// What's the cleavage agent ?
int value = m_ui.cleavageAgentListWidget->currentRow();
CleaveSpec *cleaveSpec = mp_polChemDef->cleaveSpecList().at(value);
// What's the asked level of partial cleavages?
value = m_ui.partialCleavageSpinBox->value();
CleaveOptions cleaveOptions(*cleaveSpec, value, false);
// Set the ionization levels to the local cleavage options object.
int valueStart = m_ui.ionizeLevelStartSpinBox->value();
int valueEnd = m_ui.ionizeLevelEndSpinBox->value();
cleaveOptions.setIonizeLevels(valueStart, valueEnd);
// The list in which we'll store all the allocated oligomers.
OligomerList tempOligomerList;
delete mpa_cleaver;
mpa_cleaver = 0;
// Update the mass calculation engine's configuration data
// directly from the sequence editor window.
m_calcOptions = mp_editorWnd->calcOptions();
// Update the selection data from the sequence editor window.
if (!populateSelectedOligomerData())
return;
mpa_cleaver= new Cleaver(mp_polymer, mp_polChemDef, cleaveOptions,
m_calcOptions, *mp_ionizeRule);
mpa_cleaver->setOligomerList(&tempOligomerList);
if (!mpa_cleaver->cleave())
{
delete mpa_cleaver;
QMessageBox::critical(this,
tr("massXpert - Polymer Cleavage"),
tr("Failed to perform cleavage."),
QMessageBox::Ok);
return;
}
// At this point we have a brand new set of oligomers in the local
// list of oligomers (tempOligomerList). We either stack these on top
// of the previous ones, or we replace the previous ones with the
// new ones. Are we stacking new oligomers on top of the old
// ones?
if (!m_ui.stackOligomersCheckBox->isChecked())
{
// We are going to remove *all* the previous oligomers.
mpa_oligomerTableViewModel->removeOligomers(0, -1);
}
// At this point we can set up the data to the treeview model.
int initialOligomers = tempOligomerList.size();
// qDebug() << __FILE__ << __LINE__
// << "initialOligomers:" << initialOligomers;
// We are *transferring* the oligomers from tempOligomerList to
// the list of m_oligomerList list oligomers of which there is a
// pointer in the model : we are not duplicating the
// oligomers. When the transfer from tempOligomerList to
// m_oligomerList _via_ the model will have been done,
// tempOligomerList will be empty and m_oligomerList will hold
// them all, with the model having been made aware of that with
// the beginInsertRows/endInsertRows statement pair.
int addedOligomers =
mpa_oligomerTableViewModel->addOligomers(tempOligomerList);
// qDebug() << __FILE__ << __LINE__
// << "addedOligomers:" << addedOligomers;
if (initialOligomers != addedOligomers)
qFatal("Fatal error at %s@%d. Aborting.", __FILE__, __LINE__);
// Now that we have *transferred* (not copied) all the oligomers
// in the model, we can clear the tempOligomerList without freeing the
// instances it currently contain...
tempOligomerList.clear();
// Set focus to the treeView.
m_ui.oligomerTableView->setFocus();
QString title;
int oligomerCount = mpa_oligomerTableViewModel->rowCount();
Application *application = static_cast(qApp);
QLocale locale = application->locale();
if (!oligomerCount)
title = tr("Oligomers (empty list)");
else if (oligomerCount == 1)
title = tr("Oligomers (one item)");
else
title = tr("Oligomers (%1 items)")
.arg(locale.toString(oligomerCount));
m_ui.oligomerGroupBox->setTitle(title);
// Update the cleavage details so that we know how the oligos were
// computed.
updateCleavageDetails(m_calcOptions);
}
void
CleavageDlg::updateCleavageDetails(const CalcOptions &calcOptions)
{
if (calcOptions.capping() & MXT_CAP_LEFT)
m_ui.leftCapCheckBox->setCheckState(Qt::Checked);
else
m_ui.leftCapCheckBox->setCheckState(Qt::Unchecked);
if (calcOptions.capping() & MXT_CAP_RIGHT)
m_ui.rightCapCheckBox->setCheckState(Qt::Checked);
else
m_ui.rightCapCheckBox->setCheckState(Qt::Unchecked);
if (calcOptions.polymerEntities() & MXT_POLYMER_CHEMENT_LEFT_END_MODIF)
m_ui.leftModifCheckBox->setCheckState(Qt::Checked);
else
m_ui.leftModifCheckBox->setCheckState(Qt::Unchecked);
if (calcOptions.polymerEntities() & MXT_POLYMER_CHEMENT_RIGHT_END_MODIF)
m_ui.rightModifCheckBox->setCheckState(Qt::Checked);
else
m_ui.rightModifCheckBox->setCheckState(Qt::Unchecked);
if (calcOptions.monomerEntities() & MXT_MONOMER_CHEMENT_MODIF)
m_ui.modificationsCheckBox->setCheckState(Qt::Checked);
else
m_ui.modificationsCheckBox->setCheckState(Qt::Unchecked);
if (calcOptions.monomerEntities() & MXT_MONOMER_CHEMENT_CROSS_LINK)
m_ui.crossLinksCheckBox->setCheckState(Qt::Checked);
else
m_ui.crossLinksCheckBox->setCheckState(Qt::Unchecked);
}
void
CleavageDlg::updateOligomerSequence(QString *text)
{
Q_ASSERT(text);
m_ui.oligomerSequenceTextEdit->clear();
m_ui.oligomerSequenceTextEdit->append(*text);
}
void
CleavageDlg::closeEvent(QCloseEvent *event)
{
if (event)
printf("%s", "");
QSettings settings
(static_cast(qApp)->configSettingsFilePath(),
QSettings::IniFormat);
settings.beginGroup("cleavage_dlg");
settings.setValue("geometry", saveGeometry());
settings.setValue("oligomersSplitter",
m_ui.oligomersSplitter->saveState());
settings.setValue("oligoDetailsSplitter",
m_ui.oligoDetailsSplitter->saveState());
settings.endGroup();
}
bool
CleavageDlg::calculateTolerance(double mass)
{
// Get the tolerance that is in its lineEdit.
QString text = m_ui.toleranceLineEdit->text();
double tolerance = 0;
bool ok = false;
if (!text.isEmpty())
{
// Convert the string to a double.
Application *application = static_cast(qApp);
QLocale locale = application->locale();
ok = false;
tolerance = locale.toDouble(text, &ok);
if(!tolerance && !ok)
return false;
}
else
{
m_tolerance = 0;
}
// What's the item currently selected in the comboBox?
int index = m_ui.toleranceComboBox->currentIndex();
if (index == 0)
{
// MXT_MASS_TOLERANCE_AMU
m_tolerance = tolerance;
}
else if (index == 1)
{
// MXT_MASS_TOLERANCE_PCT
m_tolerance =(tolerance / 100) * mass;
}
else if (index == 2)
{
// MXT_MASS_TOLERANCE_PPM
m_tolerance =(tolerance / 1000000) * mass;
}
else
Q_ASSERT(0);
return true;
}
void
CleavageDlg::filterOptions(bool checked)
{
if (!checked)
{
mpa_proxyModel->setFilterKeyColumn(-1);
mpa_proxyModel->applyNewFilter();
m_ui.filteringOptionsFrame->setVisible(false);
}
else
{
m_ui.filteringOptionsFrame->setVisible(true);
// In this case, set focus to the last focused widget in the
// groupbox or the first widget in the groubox if this is the
// first time the filtering is used.
mp_focusWidget->setFocus();
}
}
void
CleavageDlg::filterOptionsToggled()
{
bool isChecked = m_ui.filteringOptionsGroupBox->isChecked();
m_ui.filteringOptionsGroupBox->setChecked(!isChecked);
filterOptions(!isChecked);
}
void
CleavageDlg::filterPartial()
{
// First off, we have to get the partial that is in the lineEdit.
QString text = m_ui.filterPartialLineEdit->text();
if (text.isEmpty())
return;
// Convert the string to a int.
Application *application = static_cast(qApp);
QLocale locale = application->locale();
bool ok = false;
int partial = locale.toInt(text, &ok);
if (!partial && !ok)
return;
mpa_proxyModel->setPartialFilter(partial);
mpa_proxyModel->setFilterKeyColumn(0);
mpa_proxyModel->applyNewFilter();
mp_focusWidget = m_ui.filterPartialLineEdit;
}
void
CleavageDlg::filterMonoMass()
{
// First off, we have to get the mass that is in the lineEdit.
QString text = m_ui.filterMonoMassLineEdit->text();
if (text.isEmpty())
return;
// Convert the string to a double.
Application *application = static_cast(qApp);
QLocale locale = application->locale();
bool ok = false;
double mass = locale.toDouble(text, &ok);
if (!mass && !ok)
return;
// At this point, depending on the item that is currently selected
// in the comboBox, we'll have to actually compute the tolerance.
if (!calculateTolerance(mass))
return ;
mpa_proxyModel->setMonoFilter(mass);
mpa_proxyModel->setTolerance(m_tolerance);
mpa_proxyModel->setFilterKeyColumn(3);
mpa_proxyModel->applyNewFilter();
mp_focusWidget = m_ui.filterMonoMassLineEdit;
}
void
CleavageDlg::filterAvgMass()
{
// First off, we have to get the mass that is in the lineEdit.
QString text = m_ui.filterAvgMassLineEdit->text();
if (text.isEmpty())
return;
// Convert the string to a double.
Application *application = static_cast(qApp);
QLocale locale = application->locale();
bool ok = false;
double mass = locale.toDouble(text, &ok);
if (!mass && !ok)
return;
// At this point, depending on the item that is currently selected
// in the comboBox, we'll have to actually compute the tolerance.
if (!calculateTolerance(mass))
return ;
mpa_proxyModel->setAvgFilter(mass);
mpa_proxyModel->setTolerance(m_tolerance);
mpa_proxyModel->setFilterKeyColumn(4);
mpa_proxyModel->applyNewFilter();
mp_focusWidget = m_ui.filterAvgMassLineEdit;
}
void
CleavageDlg::filterCharge()
{
// First off, we have to get the charge that is in the lineEdit.
QString text = m_ui.filterChargeLineEdit->text();
if (text.isEmpty())
return;
// Convert the string to a int.
Application *application = static_cast(qApp);
QLocale locale = application->locale();
bool ok = false;
int charge = locale.toInt(text, &ok);
if (!charge && !ok)
return;
mpa_proxyModel->setChargeFilter(charge);
mpa_proxyModel->setFilterKeyColumn(5);
mpa_proxyModel->applyNewFilter();
mp_focusWidget = m_ui.filterChargeLineEdit;
}
// The results-exporting functions. ////////////////////////////////
// The results-exporting functions. ////////////////////////////////
// The results-exporting functions. ////////////////////////////////
void
CleavageDlg::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)
{
exportResultsToClipboard();
}
else if (index == 1)
{
exportResultsFile();
}
else if (index == 2)
{
selectResultsFile();
}
else if (index == 3)
{
calculateSpectrum();
}
else
Q_ASSERT(0);
}
void
CleavageDlg::prepareResultsTxtString()
{
// Set the delimiter to the char/string that is in the
// corresponding text line edit widget.
QString delimiter = m_ui.delimiterLineEdit->text();
// If delimiter is empty, the function that will prepare the
// string will put the default character, that is '$'.
mpa_resultsString->clear();
// We only put the header info if the user does not want to have
// the data formatted for XpertMiner, which only can get the data
// in the format :
//
// mass charge name coords
//
// Note that name and coords are optional.
bool forXpertMiner = false;
MassType massType = MXT_MASS_NONE;
forXpertMiner = m_ui.forXpertMinerCheckBox->isChecked();
if (!forXpertMiner)
{
*mpa_resultsString += QObject::tr("# \n"
"# ---------------------------\n"
"# Polymer sequence cleavage: \n"
"# ---------------------------\n");
}
else
{
// Then, we should ask whether the masses to be exported are
// the mono or avg masses.
if(m_ui.monoRadioButton->isChecked())
massType = MXT_MASS_MONO;
else
massType = MXT_MASS_AVG;
}
bool withSequence = m_ui.withSequenceCheckBox->isChecked();
QString *text =
m_ui.oligomerTableView->selectedOligomersAsPlainText(delimiter,
withSequence,
forXpertMiner,
massType);
*mpa_resultsString += *text;
delete text;
}
bool
CleavageDlg::exportResultsToClipboard()
{
prepareResultsTxtString();
QClipboard *clipboard = QApplication::clipboard();
clipboard->setText(*mpa_resultsString, QClipboard::Clipboard);
return true;
}
bool
CleavageDlg::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
CleavageDlg::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;
}
bool
CleavageDlg::calculateSpectrum()
{
SpectrumCalculationDlg *dlg =
new SpectrumCalculationDlg(this,
mp_polChemDef->atomList(),
MXP_SPECTRUM_CALCULATION_MODE_SPECTRUM);
// We now have to prepare the land for the calculations.
dlg->setOligomerList(&m_oligomerList);
// We really need that the dialog be set modal because we want to
// be able to access all the atom and oligomer data freely and
// durably.
dlg->setModal(true);
dlg->show();
return true;
}
//////////////////////////////////// The results-exporting functions.
//////////////////////////////////// The results-exporting functions.
//////////////////////////////////// The results-exporting functions.
} // namespace massXpert
massxpert-3.6.0/gui/cleavageDlg.hpp 0000664 0000000 0000000 00000007345 12577256262 0017270 0 ustar 00root root 0000000 0000000 /* 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.
*/
#ifndef CLEAVAGE_DLG_HPP
#define CLEAVAGE_DLG_HPP
/////////////////////// Qt includes
#include
#include
/////////////////////// Local includes
#include "ui_cleavageDlg.h"
#include "cleaver.hpp"
#include "sequenceEditorWnd.hpp"
#include "cleaveOligomerTableViewModel.hpp"
#include "cleaveOligomerTableViewSortProxyModel.hpp"
namespace massXpert
{
class CleaveOligomerTableViewModel;
class CleaveOligomerTableViewSortProxyModel;
class CleavageDlg : public QDialog
{
Q_OBJECT
private:
Ui::CleavageDlg m_ui;
SequenceEditorWnd *mp_editorWnd;
// The results-exporting strings. ////////////////////////////////
QString *mpa_resultsString;
QString m_resultsFilePath;
//////////////////////////////////// The results-exporting strings.
OligomerList m_oligomerList;
const QPointer mp_polymer;
const PolChemDef *mp_polChemDef;
CalcOptions m_calcOptions;
const IonizeRule *mp_ionizeRule;
Cleaver *mpa_cleaver;
CleaveOligomerTableViewModel *mpa_oligomerTableViewModel;
CleaveOligomerTableViewSortProxyModel *mpa_proxyModel;
void closeEvent(QCloseEvent *event);
// For the filtering of the data in the treeview.
QAction *filterAct;
double m_tolerance;
QWidget *mp_focusWidget;
void setupTableView();
public:
CleavageDlg(QWidget *,
Polymer *, const PolChemDef *,
const CalcOptions &, const IonizeRule *);
~CleavageDlg();
bool populateSelectedOligomerData();
void populateCleaveSpecListWidget();
SequenceEditorWnd *editorWnd();
void updateCleavageDetails(const CalcOptions &);
void updateOligomerSequence(QString *);
bool calculateTolerance(double);
// The results-exporting functions. ////////////////////////////////
void prepareResultsTxtString();
bool exportResultsToClipboard();
bool exportResultsFile();
bool selectResultsFile();
bool calculateSpectrum();
//////////////////////////////////// The results-exporting functions.
public slots:
void cleave();
void exportResults(int);
void filterOptions(bool);
void filterOptionsToggled();
void filterPartial();
void filterMonoMass();
void filterAvgMass();
void filterCharge();
};
} // namespace massXpert
#endif // CLEAVAGE_DLG_HPP
massxpert-3.6.0/gui/cleaveOligomerTableView.cpp 0000664 0000000 0000000 00000042125 12577256262 0021620 0 ustar 00root root 0000000 0000000 /* 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
#include
#include
/////////////////////// Local includes
#include "globals.hpp"
#include "cleaveOligomerTableView.hpp"
#include "cleaveOligomerTableViewSortProxyModel.hpp"
#include "oligomer.hpp"
#include "cleavageDlg.hpp"
#include "application.hpp"
#include "cleaveOligomerTableViewMimeData.hpp"
namespace massXpert
{
CleaveOligomerTableView::CleaveOligomerTableView(QWidget *parent)
: QTableView(parent)
{
setAlternatingRowColors(true);
setSortingEnabled(true);
setDragEnabled(true);
connect(this,
SIGNAL(activated(const QModelIndex &)),
this,
SLOT(itemActivated(const QModelIndex &)));
QHeaderView *headerView = horizontalHeader();
headerView->setSectionsClickable(true);
headerView->setSectionsMovable(true);
////// Create the actions for the contextual menu.
// Copy Mono
copyMonoAct = new QAction(tr("Copy Mono To Clipboard"), this);
copyMonoAct->setStatusTip(tr("Copies the monoisotopic mass list "
"to the clipboard"));
connect(copyMonoAct, SIGNAL(triggered()), this, SLOT(copyMono()));
// Copy Avg
copyAvgAct = new QAction(tr("Copy Avg To Clipboard"), this);
copyMonoAct->setStatusTip(tr("Copies the average mass list "
"to the clipboard"));
connect(copyAvgAct, SIGNAL(triggered()), this, SLOT(copyAvg()));
// And now create the contextual menu and add the actions to it.
contextMenu = new QMenu(tr("Copy Mass List"), this);
contextMenu->addAction(copyMonoAct);
contextMenu->addAction(copyAvgAct);
}
CleaveOligomerTableView::~CleaveOligomerTableView()
{
}
void
CleaveOligomerTableView::setOligomerList(OligomerList *oligomerList)
{
mp_oligomerList = oligomerList;
}
const OligomerList *
CleaveOligomerTableView::oligomerList()
{
return mp_oligomerList;
}
CleavageDlg *
CleaveOligomerTableView::parentDlg()
{
return mp_parentDlg;
}
void
CleaveOligomerTableView::setParentDlg(CleavageDlg *dlg)
{
Q_ASSERT(dlg);
mp_parentDlg = dlg;
}
int
CleaveOligomerTableView::selectedOligomers(OligomerList *oligomerList,
int index) const
{
if(!oligomerList)
qFatal("Fatal error at %s@%d. Aborting.",__FILE__, __LINE__);
int count = 0;
int localIndex = 0;
// How many oligomers are there in the list passed as argument?
int oligomerCount = oligomerList->size();
if(index > oligomerCount)
qFatal("Fatal error at %s@%d. Aborting.",__FILE__, __LINE__);
// If index is -1 , then we are asked to append the oligomers to
// the list.
if(index == -1)
localIndex = oligomerList->size();
// For each selected oligomer, duplicate it and append to the list
// passed as argument.
// We first have to get the selection model for the proxy model.
QItemSelectionModel *selModel = selectionModel();
// Now get the selection ranges.
QItemSelection proxyItemSelection = selModel->selection();
QSortFilterProxyModel *sortModel =
static_cast(model());
QItemSelection sourceItemSelection =
sortModel->mapSelectionToSource(proxyItemSelection);
QModelIndexList modelIndexList = sourceItemSelection.indexes();
int modelIndexListSize = modelIndexList.size();
// Attention, if we select one single row, our modelIndexList will
// be of size 7, because in one single row there are seven cells:
// each cell for each column, and there are 7 columns. Thus, when
// we iterate in the modelIndexList, we'll have to take care of
// this and make sure we are not putting each selected row's
// oligomer sevent times. For this, we make sure we are not
// handling the same row twice or more, by storing the processed
// rows in a list of integers and by checking for existence of
// that row each time a new index is processed.
QList processedRowList;
for (int iter = 0; iter < modelIndexListSize; ++iter)
{
QModelIndex oligomerIndex = modelIndexList.at(iter);
Q_ASSERT(oligomerIndex.isValid());
// Get to know what's the row of the index, so that we can get
// to the oligomer.
int row = oligomerIndex.row();
if(processedRowList.contains(row))
continue;
else
processedRowList.append(row);
CleaveOligomer *oligomer =
static_cast(mp_oligomerList->at(row));
CleaveOligomer *newOligomer = new CleaveOligomer(*oligomer);
// Create a NoDeletePointerProp, which might be used later by
// the user of the list of oligomers to highlight regions in
// the sequence editor.
NoDeletePointerProp *prop =
new NoDeletePointerProp("SEQUENCE_EDITOR_WND",
static_cast
(mp_parentDlg->editorWnd()));
newOligomer->appendProp(prop);
oligomerList->insert(localIndex, newOligomer);
++localIndex;
++count;
}
return count;
}
QString *
CleaveOligomerTableView::selectedOligomersAsPlainText(QString delimiter,
bool withSequence,
bool forXpertMiner,
MassType massType) const
{
Application *application = static_cast(qApp);
QLocale locale = application->locale();
// Let's get all the currently selected oligomers in one list.
OligomerList oligomerList;
// Append the selected oligomers to the empty list.
int appendedOligomerCount = selectedOligomers(&oligomerList, -1);
// Sanity check
if(appendedOligomerCount != oligomerList.size())
qFatal("Fatal error at %s@%d. Aborting.",__FILE__, __LINE__);
// If delimiter is empty, then set to "$".
if (delimiter.isEmpty())
delimiter = "$";
// Allocate a string in which we describe all the selected items.
// For export to XpertMiner, we only want the masses asked for:
// MXT_MASS_MONO or MXT_MASS_AVG. Also, we want the format to be :
// mass charge name coords
QString *text = new QString();
while(!oligomerList.isEmpty())
{
CleaveOligomer *oligomer =
static_cast(oligomerList.takeFirst());
if(!forXpertMiner)
*text += QString("\n%1%2")
.arg(oligomer->description())
.arg(delimiter);
if(forXpertMiner && massType == MXT_MASS_AVG)
{
}
else
{
*text += QString("%1%2")
.arg(oligomer->mono(locale, MXP_OLIGOMER_DEC_PLACES))
.arg(delimiter);
}
if(forXpertMiner && massType == MXT_MASS_MONO)
{
}
else
{
*text += QString("%1%2")
.arg(oligomer->avg(locale, MXP_OLIGOMER_DEC_PLACES))
.arg(delimiter);
}
*text += QString("%1%2")
.arg(oligomer->charge())
.arg(delimiter);
*text += QString("%1%2")
.arg(oligomer->name())
.arg(delimiter);
*text += QString("%1%2")
.arg(static_cast(oligomer)->positionsAsText())
.arg(delimiter);
if(!forXpertMiner)
*text += QString("%1%2")
.arg(oligomer->isModified())
.arg(delimiter);
// We cannot export the sequence if data are for XpertMiner
if(!forXpertMiner && withSequence)
{
QString *sequence = oligomer->monomerText();
*text += QString("\n%1")
.arg(*sequence);
delete sequence;
}
// Terminate the stanza
*text += QString("\n");
// We can now delete the allocated oligomer, since we do not
// need it anymore.
delete oligomer;
}
// Terminate the string with a new line.
*text += QString("\n");
return text;
}
void
CleaveOligomerTableView::mousePressEvent(QMouseEvent *mouseEvent)
{
if (mouseEvent->buttons() & Qt::LeftButton)
{
m_dragStartPos = mouseEvent->pos();
}
else if (mouseEvent->buttons() & Qt::RightButton)
{
contextMenu->popup(mouseEvent->globalPos());
return;
}
QTableView::mousePressEvent(mouseEvent);
}
void
CleaveOligomerTableView::mouseMoveEvent(QMouseEvent *mouseEvent)
{
if (mouseEvent->buttons() & Qt::LeftButton)
{
int distance =
(mouseEvent->pos() - m_dragStartPos).manhattanLength();
if(distance >= QApplication::startDragDistance())
{
startDrag();
return;
}
}
QTableView::mousePressEvent(mouseEvent);
}
void
CleaveOligomerTableView::startDrag()
{
CleaveOligomerTableViewMimeData *mimeData =
new CleaveOligomerTableViewMimeData(this,
mp_parentDlg->editorWnd(),
mp_parentDlg);
QDrag *drag = new QDrag(this);
drag->setMimeData(mimeData);
// drag->setPixmap(QPixmap(":/images/greenled.png"));
drag->start(Qt::CopyAction);
}
void
CleaveOligomerTableView::currentChanged(const QModelIndex ¤t,
const QModelIndex &previous)
{
if (!current.isValid())
return;
CleaveOligomerTableViewSortProxyModel *sortModel =
static_cast(model());
QModelIndex sourceIndex = sortModel->mapToSource(current);
int row = sourceIndex.row();
// Get to the list of oligomers that is referenced in this
// tableView (that list actually belongs to the CleavageDlg
// instance.
CleaveOligomer *oligomer =
static_cast(mp_oligomerList->at(row));
// If the oligomers obtained with the cleavage are old and the
// sequence has been changed since the cleavage, then the
// oligomers might point to a sequence element that is no more. We
// want to avoid such kind of errors.
if (oligomer->startIndex() >= oligomer->polymer()->size() ||
oligomer->endIndex() >= oligomer->polymer()->size())
{
QMessageBox::warning(this,
tr("massXpert - Cleavage"),
tr("%1@%2\n"
"The monomer indices do not correspond "
"to a valid polymer sequence range.\n"
"Avoid modifying the sequence while "
"working with cleavages.")
.arg(__FILE__)
.arg(__LINE__),
QMessageBox::Ok);
return;
}
QString *text = oligomer->monomerText();
// We are getting text for an oligomer; it cannot be empty,
// because that would mean the oligomer has no monomers. In that
// case it is not conceivable that the oligomer be in the cleavage
// product list.
Q_ASSERT(!text->isEmpty());
*text += QString(" -- %1")
.arg(oligomer->description());
// Get the formula of the oligomer and display it all along.
QString formula = oligomer->elementalComposition();
*text += QString("(formula: %1)")
.arg(formula);
mp_parentDlg->updateOligomerSequence(text);
delete text;
// Get the mass calculation engine's options out of the oligomer,
// so that we can display them correctly.
CalcOptions calcOptions = oligomer->calcOptions();
mp_parentDlg->updateCleavageDetails(calcOptions);
QTableView::currentChanged(current, previous);
}
void
CleaveOligomerTableView::itemActivated(const QModelIndex &index)
{
if (!index.isValid())
return;
CleaveOligomerTableViewSortProxyModel *sortModel =
static_cast(model());
QModelIndex sourceIndex = sortModel->mapToSource(index);
int row = sourceIndex.row();
// Get to the list of oligomers that is referenced in this
// tableView (that list actually belongs to the CleavageDlg
// instance.
CleaveOligomer *oligomer =
static_cast(mp_oligomerList->at(row));
SequenceEditorWnd *editorWnd = mp_parentDlg->editorWnd();
CoordinateList *coordinateList =
static_cast(oligomer);
// Remove the previous selection, so that we can start fresh.
editorWnd->mpa_editorGraphicsView->resetSelection();
for (int iter = 0; iter < coordinateList->size(); ++iter)
{
Coordinates *coordinates = coordinateList->at(iter);
int start = coordinates->start();
int end = coordinates->end();
if(start >= oligomer->polymer()->size() ||
end >= oligomer->polymer()->size())
{
QMessageBox::warning(this,
tr("massXpert - Cleavage"),
tr("%1@%2\n"
"The monomer indices do not correspond "
"to a valid polymer sequence range.\n"
"Avoid modifying the sequence while "
"working with cleavages.")
.arg(__FILE__)
.arg(__LINE__),
QMessageBox::Ok);
return;
}
editorWnd->mpa_editorGraphicsView->setSelection(*coordinates,
true, false);
}
editorWnd->updateSelectedSequenceMasses();
}
///////// Contextual menu for copying to clipboard of mono/avg
///////// masses.
void
CleaveOligomerTableView::copyMono()
{
return copyMassList(MXT_MASS_MONO);
}
void
CleaveOligomerTableView::copyAvg()
{
return copyMassList(MXT_MASS_AVG);
}
void
CleaveOligomerTableView::copyMassList(int monoOrAvg)
{
Application *application = static_cast(qApp);
QLocale locale = application->locale();
QString massList;
// We want to prepare a textual list of masses (either MONO or
// AVG) of all the oligomers in the tableview, exactly as they are
// currently displayed (that is, according to the proxy's model).
QSortFilterProxyModel *sortModel =
static_cast(model());
// Get number of rows under the model.
int rowCount = sortModel->rowCount();
for(int iter = 0; iter < rowCount; ++iter)
{
// qDebug() << __FILE__ << __LINE__
// << "proxyIter:" << iter;
QModelIndex proxyIndex = sortModel->index(iter, 0);
QModelIndex sourceIndex = sortModel->mapToSource(proxyIndex);
int sourceRow = sourceIndex.row();
// qDebug() << __FILE__ << __LINE__
// << "sourceRow:" << sourceRow;
CleaveOligomer *oligomer =
static_cast(mp_oligomerList->at(sourceRow));
if(monoOrAvg == MXT_MASS_MONO)
massList += oligomer->mono(locale, MXP_OLIGOMER_DEC_PLACES);
else if (monoOrAvg == MXT_MASS_AVG)
massList += oligomer->avg(locale, MXP_OLIGOMER_DEC_PLACES);
else
qFatal("Fatal error at %s@%d. Aborting.", __FILE__, __LINE__);
// End the mass item with a new line.
massList += "\n";
}
if (massList.isEmpty())
return;
QClipboard *clipboard = QApplication::clipboard();
clipboard->setText(massList, QClipboard::Clipboard);
}
} // namespace massXpert
massxpert-3.6.0/gui/cleaveOligomerTableView.hpp 0000664 0000000 0000000 00000005716 12577256262 0021632 0 ustar 00root root 0000000 0000000 /* 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.
*/
#ifndef CLEAVE_OLIGOMER_TABLE_VIEW_HPP
#define CLEAVE_OLIGOMER_TABLE_VIEW_HPP
/////////////////////// Qt includes
#include
/////////////////////// Local includes
#include "oligomerList.hpp"
namespace massXpert
{
class CleavageDlg;
class CleaveOligomerTableView : public QTableView
{
Q_OBJECT
private:
CleavageDlg *mp_parentDlg;
OligomerList *mp_oligomerList;
// For drag operations.
QPoint m_dragStartPos;
void startDrag();
///////// Contextual menu for copying to clipboard of mono/avg
///////// masses.
QMenu *contextMenu;
QAction *copyMonoAct;
QAction *copyAvgAct;
/////////
protected:
void currentChanged(const QModelIndex &, const QModelIndex &);
void copyMassList(int);
public:
CleaveOligomerTableView(QWidget *parent = 0);
~CleaveOligomerTableView();
void setOligomerList(OligomerList *);
const OligomerList *oligomerList();
CleavageDlg *parentDlg();
void setParentDlg(CleavageDlg *);
int selectedOligomers(OligomerList *, int = 0) const;
QString *selectedOligomersAsPlainText(QString = "$",
bool = false,
bool = false,
MassType = MXT_MASS_MONO) const;
void mousePressEvent(QMouseEvent *);
void mouseMoveEvent(QMouseEvent *);
public slots:
void itemActivated(const QModelIndex &);
void copyMono();
void copyAvg();
};
} // namespace massXpert
#endif // CLEAVE_OLIGOMER_TABLE_VIEW_HPP
massxpert-3.6.0/gui/cleaveOligomerTableViewMimeData.cpp 0000664 0000000 0000000 00000005535 12577256262 0023226 0 ustar 00root root 0000000 0000000 /* 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
/////////////////////// Local includes
#include "cleaveOligomerTableViewMimeData.hpp"
namespace massXpert
{
CleaveOligomerTableViewMimeData::CleaveOligomerTableViewMimeData
(const CleaveOligomerTableView *tableView,
SequenceEditorWnd *editorWnd,
CleavageDlg *cleavageDlg)
: mp_tableView(tableView),
mp_editorWnd(editorWnd),
mp_cleavageDlg(cleavageDlg)
{
m_formats << "text/plain";
}
CleaveOligomerTableViewMimeData::~CleaveOligomerTableViewMimeData()
{
}
const CleaveOligomerTableView *
CleaveOligomerTableViewMimeData::tableView() const
{
return mp_tableView;
}
QStringList
CleaveOligomerTableViewMimeData::formats() const
{
return m_formats;
}
QVariant
CleaveOligomerTableViewMimeData::retrieveData(const QString& format,
QVariant::Type preferredType)
const
{
if (format == "text/plain")
{
return selectionAsPlainText();
}
else
{
return QMimeData::retrieveData(format, preferredType);
}
}
QString
CleaveOligomerTableViewMimeData::selectionAsPlainText() const
{
// We just do an export in the form of a simple text. Only the
// selected items should go in the export.
QString *text = mp_tableView->selectedOligomersAsPlainText();
QString returnedString = *text;
delete text;
return returnedString;
}
} // namespace massXpert
massxpert-3.6.0/gui/cleaveOligomerTableViewMimeData.hpp 0000664 0000000 0000000 00000004707 12577256262 0023233 0 ustar 00root root 0000000 0000000 /* 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.
*/
#ifndef CLEAVE_OLIGOMER_TABLE_VIEW_MIME_DATA_HPP
#define CLEAVE_OLIGOMER_TABLE_VIEW_MIME_DATA_HPP
/////////////////////// Qt includes
#include