Commit 363a9f5d authored by Christian Schärf's avatar Christian Schärf Committed by Yuri Chornoivan
Browse files

Molecular editor: Enable loading molecules in other formats than cml

Summary:
This patch implements loading Molecules in the XYZ and PDB formats by instantiating the appropriate subclass of Avogadro::Io::FileFormat
based on the file ending.

Additionally, some error handling code was added so Kalzium does not crash when loading a molecule fails.

Note that this patch requires C++14 since make_unique is used. Should it, for some reason, not be possible to include C++14-only code into Kalzium,
this can be worked around by constructing a std::unique_ptr with raw new.

Reviewers: #kalzium, yurchor

Reviewed By: yurchor

Subscribers: aacid, yurchor, kde-edu

Tags: #kde_edu, #kalzium

Differential Revision: https://phabricator.kde.org/D25648
parent 9fb18f8e
......@@ -31,6 +31,8 @@ target_link_libraries(compoundviewer
set_target_properties(compoundviewer PROPERTIES
VERSION ${KALZIUMLIB_VERSION}
SOVERSION ${KALZIUMLIB_SOVERSION}
CXX_STANDARD 14
CXX_STANDARD_REQUIRED ON
)
install(TARGETS compoundviewer ${INSTALL_TARGETS_DEFAULT_ARGS})
......@@ -20,15 +20,18 @@
#include <avogadro/core/molecule.h>
#include <avogadro/io/cmlformat.h>
#include <avogadro/io/pdbformat.h>
#include <avogadro/io/xyzformat.h>
#include <QDebug>
#include <QFile>
#include <QFileInfo>
#include <QMessageBox>
#include <QRegularExpression>
#include <KLocalizedString>
Avogadro::Core::Molecule * IoWrapper::readMolecule(const QString &filename)
std::unique_ptr<Avogadro::Core::Molecule> IoWrapper::readMolecule(const QString &filename)
{
std::ifstream inFileStream(QFile::encodeName(filename).constData());
if (!inFileStream) {
......@@ -37,12 +40,20 @@ Avogadro::Core::Molecule * IoWrapper::readMolecule(const QString &filename)
return nullptr;
}
auto mol = new Avogadro::Core::Molecule;
Avogadro::Io::CmlFormat cmlFormat;
if (!cmlFormat.read(inFileStream, *mol)) {
qCritical() << "Could not read file:" << filename;
auto mol = std::make_unique<Avogadro::Core::Molecule>();
auto format = getFileReader(QFileInfo(filename).suffix());
if (!format){
qCritical() << "Could not initialize file reader for file " << filename;
return nullptr;
}
if (!format->read(inFileStream, *mol)) {
qCritical() << "Could not read file " << filename << "; Error message: "
<< QString().fromStdString(format->error());
return nullptr;
}
return mol;
}
......@@ -72,3 +83,16 @@ QString IoWrapper::getPrettyFormula(Avogadro::QtGui::Molecule *molecule)
formula.replace(QRegularExpression("(\\d+)"), "<sub>\\1</sub>");
return formula;
}
std::unique_ptr<Avogadro::Io::FileFormat> IoWrapper::getFileReader(const QString &format)
{
if (format == QStringLiteral("cml")) {
return std::make_unique<Avogadro::Io::CmlFormat>();
} else if (format == QStringLiteral("pdb")) {
return std::make_unique<Avogadro::Io::PdbFormat>();
} else if (format == QStringLiteral("xyz")) {
return std::make_unique<Avogadro::Io::XyzFormat>();
} else {
return nullptr;
}
}
......@@ -16,10 +16,13 @@
#ifndef IOWRAPPER_H
#define IOWRAPPER_H
#include <avogadro/io/fileformat.h>
#include <avogadro/qtgui/molecule.h>
#include <libkdeedu_compoundviewer_export.h>
#include <memory>
/**
* @author Carsten Niehaus
*/
......@@ -30,13 +33,19 @@ public:
* This class reads the molecule in the file @p filename. It returns 0 if
* the file couldn't be read.
*/
static Avogadro::Core::Molecule * readMolecule(const QString &filename);
static std::unique_ptr<Avogadro::Core::Molecule> readMolecule(const QString &filename);
static bool writeMolecule(const QString& filename, Avogadro::Core::Molecule *);
static QString getFormula(Avogadro::QtGui::Molecule *molecule);
static QString getPrettyFormula(Avogadro::QtGui::Molecule *molecule);
private:
/**
* Get file format reader appropriate for the file format
*/
static std::unique_ptr<Avogadro::Io::FileFormat> getFileReader(const QString &format);
};
#endif
......@@ -187,7 +187,14 @@ void MoleculeDialog::loadMolecule(const QString &filename)
// 2. another workaround for broken copy-constructor that does not
// initialize the m_undoMolecule private member variable;
// this molecule should be created on the heap instead of the stack
m_molecule = *IoWrapper::readMolecule(filename);
auto molecule_ptr = IoWrapper::readMolecule(filename);
if (!molecule_ptr)
{
KMessageBox::error(this, i18n("Could not load molecule"), i18n("Loading the molecule failed."));
return;
}
m_molecule = *molecule_ptr;
if (m_molecule.atomCount() != 0) {
disconnect(ui.glWidget->molecule(), 0, this, 0);
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment