Skip to content

Commit

Permalink
Implementation of custom element assignment from file
Browse files Browse the repository at this point in the history
Signed-off-by: Adarsh Balasubramanian <[email protected]>
  • Loading branch information
badarsh2 committed Aug 2, 2018
1 parent da6ebb9 commit 45d7d55
Show file tree
Hide file tree
Showing 5 changed files with 346 additions and 11 deletions.
2 changes: 1 addition & 1 deletion avogadro/qtplugins/customelements/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,5 @@ avogadro_plugin(CustomElements
ExtensionPlugin
customelements.h
CustomElements
"customelements.cpp"
"customelements.cpp;backgroundfileformat.cpp"
)
86 changes: 86 additions & 0 deletions avogadro/qtplugins/customelements/backgroundfileformat.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
/******************************************************************************
This source file is part of the Avogadro project.
Copyright 2013 Kitware, Inc.
This source code is released under the New BSD License, (the "License").
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
******************************************************************************/

#include "backgroundfileformat.h"

#include <avogadro/io/fileformat.h>

namespace Avogadro {

BackgroundFileFormat::BackgroundFileFormat(Io::FileFormat* format,
QObject* aparent)
: QObject(aparent)
, m_format(format)
, m_molecule(nullptr)
, m_success(false)
{}

BackgroundFileFormat::~BackgroundFileFormat()
{
delete m_format;
}

void BackgroundFileFormat::read()
{
m_success = false;
m_error.clear();

if (!m_molecule)
m_error = tr("No molecule set in BackgroundFileFormat!");

if (!m_format)
m_error = tr("No Io::FileFormat set in BackgroundFileFormat!");

if (m_fileName.isEmpty())
m_error = tr("No file name set in BackgroundFileFormat!");

if (m_error.isEmpty()) {
m_success =
m_format->readFile(m_fileName.toLocal8Bit().data(), *m_molecule);

if (!m_success)
m_error = QString::fromStdString(m_format->error());
}

emit finished();
}

void BackgroundFileFormat::write()
{
m_success = false;
m_error.clear();

if (!m_molecule)
m_error = tr("No molecule set in BackgroundFileFormat!");

if (!m_format)
m_error = tr("No Io::FileFormat set in BackgroundFileFormat!");

if (m_fileName.isEmpty())
m_error = tr("No file name set in BackgroundFileFormat!");

if (m_error.isEmpty()) {
m_success =
m_format->writeFile(m_fileName.toLocal8Bit().data(), *m_molecule);

if (!m_success)
m_error = QString::fromStdString(m_format->error());
}

emit finished();
}

} // namespace Avogadro
107 changes: 107 additions & 0 deletions avogadro/qtplugins/customelements/backgroundfileformat.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
/******************************************************************************
This source file is part of the Avogadro project.
Copyright 2013 Kitware, Inc.
This source code is released under the New BSD License, (the "License").
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
******************************************************************************/

#ifndef AVOGADRO_BACKGROUNDFILEFORMAT_H
#define AVOGADRO_BACKGROUNDFILEFORMAT_H

#include <QtCore/QObject>
#include <QtCore/QString>

namespace Avogadro {

namespace Core {
class Molecule;
}

namespace Io {
class FileFormat;
}

/**
* @brief The BackgroundFileFormat class provides a thin QObject wrapper around
* an instance of Io::FileFormat.
*/
class BackgroundFileFormat : public QObject
{
Q_OBJECT
public:
/**
* This class takes ownership of @a format and will delete it when destructed.
*/
explicit BackgroundFileFormat(Io::FileFormat* format, QObject* aparent = 0);
~BackgroundFileFormat();

/**
* The molecule instance to read/write.
* @{
*/
void setMolecule(Core::Molecule* mol) { m_molecule = mol; }
Core::Molecule* molecule() const { return m_molecule; }
/**@}*/

/**
* The name of the file to read/write.
* @{
*/
void setFileName(const QString& filename) { m_fileName = filename; }
QString fileName() const { return m_fileName; }
/**@}*/

/**
* The Io::FileFormat to use.
*/
Io::FileFormat* fileFormat() const { return m_format; }

/**
* @return True if the operation was successful.
*/
bool success() const { return m_success; }

/**
* @return An error string, set if success() is false.
*/
QString error() const { return m_error; }

signals:

/**
* Emitted when a call to read or write is called.
*/
void finished();

public slots:

/**
* Use the fileFormat() to read fileName() into molecule().
*/
void read();

/**
* Use the fileFormat() to write fileName() from molecule().
*/
void write();

private:
Io::FileFormat* m_format;
Core::Molecule* m_molecule;
QString m_fileName;
QString m_error;
bool m_success;
};

} // namespace Avogadro

#endif // AVOGADRO_BACKGROUNDFILEFORMAT_H
145 changes: 136 additions & 9 deletions avogadro/qtplugins/customelements/customelements.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,29 +15,42 @@
******************************************************************************/

#include "customelements.h"
#include "backgroundfileformat.h"

#include <avogadro/qtgui/customelementdialog.h>
#include <avogadro/qtgui/fileformatdialog.h>
#include <avogadro/qtgui/molecule.h>

#include <QtCore/QSettings>
#include <QtCore/QThread>
#include <QtWidgets/QAction>
#include <QtWidgets/QMessageBox>
#include <QtWidgets/QProgressDialog>

using Avogadro::QtGui::Molecule;

namespace Avogadro {
namespace QtPlugins {

CustomElements::CustomElements(QObject* parent_)
: Avogadro::QtGui::ExtensionPlugin(parent_), m_molecule(nullptr),
m_reassignAction(new QAction(tr("Reassign &Custom Elements..."), this))
: Avogadro::QtGui::ExtensionPlugin(parent_)
, m_molecule(nullptr)
, m_reassignUsingTool(nullptr)
, m_reassignFromFile(nullptr)
, m_fileReadThread(nullptr)
, m_threadedReader(nullptr)
, m_fileReadMolecule(nullptr)
, m_progressDialog(nullptr)
{
connect(m_reassignAction, SIGNAL(triggered()), SLOT(reassign()));
m_reassignUsingTool = new QAction(tr("Using &Mapping tool..."), this);
m_reassignFromFile = new QAction(tr("From &File..."), this);
connect(m_reassignUsingTool, SIGNAL(triggered()), SLOT(reassign()));
connect(m_reassignFromFile, SIGNAL(triggered()), SLOT(importMapFile()));

updateReassignAction();
}

CustomElements::~CustomElements()
{
}
CustomElements::~CustomElements() {}

QString CustomElements::description() const
{
Expand All @@ -46,12 +59,12 @@ QString CustomElements::description() const

QList<QAction*> CustomElements::actions() const
{
return QList<QAction*>() << m_reassignAction;
return QList<QAction*>() << m_reassignUsingTool << m_reassignFromFile;
}

QStringList CustomElements::menuPath(QAction*) const
{
return QStringList() << tr("&Build");
return QStringList() << tr("&Build") << tr("Assign &Custom Elements...");
}

void CustomElements::setMolecule(QtGui::Molecule* mol)
Expand Down Expand Up @@ -86,9 +99,123 @@ void CustomElements::reassign()
}
}

bool CustomElements::openFile(const QString& fileName, Io::FileFormat* reader)
{
if (fileName.isEmpty() || reader == nullptr) {
delete reader;
return false;
}

QString ident = QString::fromStdString(reader->identifier());

// Prepare the background thread to read in the selected file.
if (!m_fileReadThread)
m_fileReadThread = new QThread(qobject_cast<QWidget*>(parent()));
if (m_threadedReader)
m_threadedReader->deleteLater();
m_threadedReader = new BackgroundFileFormat(reader);
if (m_fileReadMolecule)
m_fileReadMolecule->deleteLater();
m_fileReadMolecule = new Molecule(qobject_cast<QWidget*>(parent()));
m_fileReadMolecule->setData("fileName", fileName.toLocal8Bit().data());
m_threadedReader->moveToThread(m_fileReadThread);
m_threadedReader->setMolecule(m_fileReadMolecule);
m_threadedReader->setFileName(fileName);

// Setup a progress dialog in case file loading is slow
m_progressDialog = new QProgressDialog(qobject_cast<QWidget*>(parent()));
m_progressDialog->setRange(0, 0);
m_progressDialog->setValue(0);
m_progressDialog->setMinimumDuration(750);
m_progressDialog->setWindowTitle(tr("Reading File"));
m_progressDialog->setLabelText(
tr("Opening file '%1'\nwith '%2'").arg(fileName).arg(ident));
/// @todo Add API to abort file ops
m_progressDialog->setCancelButton(nullptr);
connect(m_fileReadThread, SIGNAL(started()), m_threadedReader, SLOT(read()));
connect(m_threadedReader, SIGNAL(finished()), m_fileReadThread, SLOT(quit()));
connect(m_threadedReader, SIGNAL(finished()),
SLOT(backgroundReaderFinished()));

// Start the file operation
m_fileReadThread->start();
m_progressDialog->show();

return true;
}

void CustomElements::backgroundReaderFinished()
{
QString fileName = m_threadedReader->fileName();
if (m_progressDialog->wasCanceled()) {
delete m_fileReadMolecule;
} else if (m_threadedReader->success()) {
if (!fileName.isEmpty()) {
m_fileReadMolecule->setData("fileName", fileName.toLocal8Bit().data());
} else {
m_fileReadMolecule->setData("fileName", Core::Variant());
}
setMapFromMolecule(m_fileReadMolecule);
} else {
QMessageBox::critical(qobject_cast<QWidget*>(parent()), tr("File error"),
tr("Error while reading file '%1':\n%2")
.arg(fileName)
.arg(m_threadedReader->error()));
delete m_fileReadMolecule;
}
m_fileReadThread->deleteLater();
m_fileReadThread = nullptr;
m_threadedReader->deleteLater();
m_threadedReader = nullptr;
m_fileReadMolecule = nullptr;
m_progressDialog->hide();
m_progressDialog->deleteLater();
m_progressDialog = nullptr;
}

void CustomElements::setMapFromMolecule(QtGui::Molecule* mol)
{
if (mol->atomCount() != m_molecule->atomCount()) {
QMessageBox::critical(
qobject_cast<QWidget*>(parent()), tr("Error"),
tr("Atom count mismatch.\nExpected %1 atoms, found %2.")
.arg(m_molecule->atomCount())
.arg(mol->atomCount()));
} else {
size_t n = m_molecule->atomCount();
for (size_t i = 0; i < n; ++i) {
m_molecule->atom(i).setAtomicNumber(mol->atom(i).atomicNumber());
}
m_molecule->emitChanged(Molecule::Atoms | Molecule::Modified);
}
}

void CustomElements::importMapFile()
{
QSettings settings;
QString dir = settings.value("MainWindow/lastOpenDir").toString();

QtGui::FileFormatDialog::FormatFilePair reply =
QtGui::FileFormatDialog::fileToRead(qobject_cast<QWidget*>(parent()),
tr("Open Molecule"), dir);

if (reply.first == NULL) // user cancel
return;

dir = QFileInfo(reply.second).absoluteDir().absolutePath();
settings.setValue("MainWindow/lastOpenDir", dir);

if (!openFile(reply.second, reply.first->newInstance())) {
QMessageBox::information(
qobject_cast<QWidget*>(parent()), tr("Cannot open file"),
tr("Can't open supplied file %1").arg(reply.second));
}
}

void CustomElements::updateReassignAction()
{
m_reassignAction->setEnabled(m_molecule && m_molecule->hasCustomElements());
m_reassignUsingTool->setEnabled(m_molecule);
m_reassignFromFile->setEnabled(m_molecule);
}

} // namespace QtPlugins
Expand Down
Loading

0 comments on commit 45d7d55

Please sign in to comment.