From 3cb574ddf39462511a2a38cbff0dfa0e9bcafacf Mon Sep 17 00:00:00 2001 From: "Marcus D. Hanwell" Date: Sun, 16 Apr 2023 14:03:28 -0400 Subject: [PATCH] Remove the MongoChem plugin from the project This is no longer relevant, there were some great ideas that we worked on but there is no point to keeping this in the repository. It will be in git history if anyone wants to revisit old ideas. Signed-off-by: Marcus D. Hanwell --- avogadro/qtplugins/CMakeLists.txt | 2 - avogadro/qtplugins/mongochem/CMakeLists.txt | 30 -- .../mongochem/calculationsubmitter.cpp | 462 ------------------ .../mongochem/calculationsubmitter.h | 101 ---- .../mongochem/calculationwatcher.cpp | 97 ---- .../qtplugins/mongochem/calculationwatcher.h | 55 --- avogadro/qtplugins/mongochem/configdialog.cpp | 44 -- avogadro/qtplugins/mongochem/configdialog.h | 40 -- avogadro/qtplugins/mongochem/configdialog.ui | 105 ---- .../qtplugins/mongochem/girderrequest.cpp | 141 ------ avogadro/qtplugins/mongochem/girderrequest.h | 64 --- .../mongochem/listmoleculesmodel.cpp | 125 ----- .../qtplugins/mongochem/listmoleculesmodel.h | 42 -- avogadro/qtplugins/mongochem/mongochem.cpp | 85 ---- avogadro/qtplugins/mongochem/mongochem.h | 71 --- .../qtplugins/mongochem/mongochemwidget.cpp | 391 --------------- .../qtplugins/mongochem/mongochemwidget.h | 77 --- .../qtplugins/mongochem/mongochemwidget.ui | 81 --- .../mongochem/submitcalculationdialog.cpp | 60 --- .../mongochem/submitcalculationdialog.h | 39 -- .../mongochem/submitcalculationdialog.ui | 153 ------ 21 files changed, 2265 deletions(-) delete mode 100644 avogadro/qtplugins/mongochem/CMakeLists.txt delete mode 100644 avogadro/qtplugins/mongochem/calculationsubmitter.cpp delete mode 100644 avogadro/qtplugins/mongochem/calculationsubmitter.h delete mode 100644 avogadro/qtplugins/mongochem/calculationwatcher.cpp delete mode 100644 avogadro/qtplugins/mongochem/calculationwatcher.h delete mode 100644 avogadro/qtplugins/mongochem/configdialog.cpp delete mode 100644 avogadro/qtplugins/mongochem/configdialog.h delete mode 100644 avogadro/qtplugins/mongochem/configdialog.ui delete mode 100644 avogadro/qtplugins/mongochem/girderrequest.cpp delete mode 100644 avogadro/qtplugins/mongochem/girderrequest.h delete mode 100644 avogadro/qtplugins/mongochem/listmoleculesmodel.cpp delete mode 100644 avogadro/qtplugins/mongochem/listmoleculesmodel.h delete mode 100644 avogadro/qtplugins/mongochem/mongochem.cpp delete mode 100644 avogadro/qtplugins/mongochem/mongochem.h delete mode 100644 avogadro/qtplugins/mongochem/mongochemwidget.cpp delete mode 100644 avogadro/qtplugins/mongochem/mongochemwidget.h delete mode 100644 avogadro/qtplugins/mongochem/mongochemwidget.ui delete mode 100644 avogadro/qtplugins/mongochem/submitcalculationdialog.cpp delete mode 100644 avogadro/qtplugins/mongochem/submitcalculationdialog.h delete mode 100644 avogadro/qtplugins/mongochem/submitcalculationdialog.ui diff --git a/avogadro/qtplugins/CMakeLists.txt b/avogadro/qtplugins/CMakeLists.txt index bd7f1103a4..a93958a381 100644 --- a/avogadro/qtplugins/CMakeLists.txt +++ b/avogadro/qtplugins/CMakeLists.txt @@ -136,8 +136,6 @@ if(QT_VERSION EQUAL 5) add_subdirectory(molecularproperties) # The SVG library is not available in Qt 6 add_subdirectory(svg) - # Should probably just be removed. - add_subdirectory(mongochem) endif() add_subdirectory(spectra) add_subdirectory(templatetool) diff --git a/avogadro/qtplugins/mongochem/CMakeLists.txt b/avogadro/qtplugins/mongochem/CMakeLists.txt deleted file mode 100644 index 859d4a6a29..0000000000 --- a/avogadro/qtplugins/mongochem/CMakeLists.txt +++ /dev/null @@ -1,30 +0,0 @@ -include_directories(${CMAKE_CURRENT_BINARY_DIR}) - -# Extension -set(srcs - mongochem.cpp - mongochemwidget.cpp - girderrequest.cpp - configdialog.cpp - listmoleculesmodel.cpp - calculationsubmitter.cpp - calculationwatcher.cpp - submitcalculationdialog.cpp -) - -set(uis - mongochemwidget.ui - configdialog.ui - submitcalculationdialog.ui -) - -avogadro_plugin(MongoChem - "HTTP interface with mongochemserver" - ExtensionPlugin - mongochem.h - MongoChem - "${srcs}" - "${uis}" -) - -target_link_libraries(MongoChem PRIVATE ${Qt5Network_LIBRARIES}) diff --git a/avogadro/qtplugins/mongochem/calculationsubmitter.cpp b/avogadro/qtplugins/mongochem/calculationsubmitter.cpp deleted file mode 100644 index aa8cf5715b..0000000000 --- a/avogadro/qtplugins/mongochem/calculationsubmitter.cpp +++ /dev/null @@ -1,462 +0,0 @@ -/****************************************************************************** - This source file is part of the Avogadro project. - This source code is released under the 3-Clause BSD License, (see "LICENSE"). -******************************************************************************/ - -#include "calculationsubmitter.h" - -#include "girderrequest.h" - -#include -#include -#include -#include -#include -#include - -namespace Avogadro::QtPlugins { - -static void deleteRequestWhenFinished(GirderRequest* r) -{ - QObject::connect(r, &GirderRequest::result, r, &GirderRequest::deleteLater); - QObject::connect(r, &GirderRequest::error, r, &GirderRequest::deleteLater); -} - -CalculationSubmitter::CalculationSubmitter( - QSharedPointer manager, const QString& girderUrl, - const QString& girderToken, QObject* parent) - : QObject(parent), m_girderUrl(girderUrl), m_girderToken(girderToken), - m_networkManager(manager) -{} - -CalculationSubmitter::~CalculationSubmitter() = default; - -static bool parseImageName(const QString& imageName, QString& repository, - QString& tag) -{ - auto split = imageName.split(":"); - repository = split[0]; - - if (split.size() > 1) - tag = split[1]; - else - tag = "latest"; - - return true; -} - -void CalculationSubmitter::start() -{ - // Start by uploading the molecule (but note that if a molecule - // with a matching inchikey exists, that one will be used instead) - uploadMolecule(); -} - -void CalculationSubmitter::uploadMolecule() -{ - QJsonObject object({ { "cjson", m_moleculeCjson } }); - QByteArray postData = QJsonDocument(object).toJson(); - - QString url = m_girderUrl + "/molecules"; - - auto* request = - new GirderRequest(m_networkManager.data(), url, m_girderToken); - request->setHeader(QNetworkRequest::ContentTypeHeader, "application/json"); - request->post(postData); - - connect(request, &GirderRequest::result, this, - &CalculationSubmitter::finishUploadMolecule); - connect(request, &GirderRequest::error, this, &CalculationSubmitter::error); - deleteRequestWhenFinished(request); -} - -void CalculationSubmitter::finishUploadMolecule(const QVariant& results) -{ - m_moleculeId = results.toMap()["_id"].toString(); - if (m_moleculeId.isEmpty()) { - emit error("Failed to upload molecule!"); - return; - } - - // Now, upload the particular geometry that we will use - uploadGeometry(); -} - -void CalculationSubmitter::uploadGeometry() -{ - QByteArray postData = m_moleculeCjson.toLatin1(); - - QString url =(m_girderUrl + "/molecules/%1/geometries").arg(m_moleculeId); - - QList> urlQueries = { - { "provenanceType", "Uploaded from Avogadro2" } - }; - - auto* request = - new GirderRequest(m_networkManager.data(), url, m_girderToken); - request->setHeader(QNetworkRequest::ContentTypeHeader, "application/json"); - request->setUrlQueries(urlQueries); - request->post(postData); - - connect(request, &GirderRequest::result, this, - &CalculationSubmitter::finishUploadGeometry); - connect(request, &GirderRequest::error, this, &CalculationSubmitter::error); - deleteRequestWhenFinished(request); -} - -void CalculationSubmitter::finishUploadGeometry(const QVariant& results) -{ - m_geometryId = results.toMap()["_id"].toString(); - if (m_geometryId.isEmpty()) { - emit error("Failed to upload geometry!"); - return; - } - - // Now, make sure the calculation has not already been done before. - fetchCalculation(); -} - -void CalculationSubmitter::fetchCalculation() -{ - QString repository, tag; - parseImageName(m_imageName, repository, tag); - QByteArray inputParams = QJsonDocument::fromVariant(m_inputParameters) - .toJson(QJsonDocument::Compact); - - QString url = m_girderUrl + "/calculations"; - - QList> urlQueries = { - { "moleculeId", m_moleculeId }, - { "geometryId", m_geometryId }, - { "inputParameters", inputParams }, - { "imageName", QString("%1:%2").arg(repository).arg(tag) } - }; - - auto* request = - new GirderRequest(m_networkManager.data(), url, m_girderToken); - request->setUrlQueries(urlQueries); - request->get(); - - connect(request, &GirderRequest::result, this, - &CalculationSubmitter::finishFetchCalculation); - connect(request, &GirderRequest::error, this, - &CalculationSubmitter::handleError); - deleteRequestWhenFinished(request); -} - -void CalculationSubmitter::finishFetchCalculation(const QVariant& results) -{ - auto resultsList = results.toMap()["results"].toList(); - if (resultsList.size() != 0) { - // The calculation has already been done. Get the id and emit it. - QVariantMap output; - output["calculationId"] = resultsList[0].toMap()["_id"].toString(); - // TODO: We are currently always submitting the calculation - // It might be nice in the future to fetch it if it has already - // been done. - /* - emit finished(output); - return; - */ - } - - fetchCluster(); -} - -void CalculationSubmitter::fetchCluster() -{ - // Just grab the first cluster we can find... - QString url = m_girderUrl + "/clusters"; - - auto* request = - new GirderRequest(m_networkManager.data(), url, m_girderToken); - request->get(); - - connect(request, &GirderRequest::result, this, - &CalculationSubmitter::finishFetchCluster); - connect(request, &GirderRequest::error, this, - &CalculationSubmitter::handleError); - deleteRequestWhenFinished(request); -} - -void CalculationSubmitter::finishFetchCluster(const QVariant& results) -{ - auto resultsList = results.toList(); - if (resultsList.size() == 0) { - emit error("No clusters found!"); - return; - } - - m_clusterId = resultsList[0].toMap()["_id"].toString(); - if (m_clusterId.isEmpty()) { - emit error("Cluster ID not found!"); - return; - } - - fetchOrCreateQueue(); -} - -void CalculationSubmitter::fetchOrCreateQueue() -{ - // First try a fetch... - QString url = m_girderUrl + "/queues"; - QList> urlQueries = { { "name", "oc_queue" } }; - - auto* request = - new GirderRequest(m_networkManager.data(), url, m_girderToken); - request->setUrlQueries(urlQueries); - request->get(); - - connect(request, &GirderRequest::result, this, - &CalculationSubmitter::finishFetchOrCreateQueue); - connect(request, &GirderRequest::error, this, - &CalculationSubmitter::handleError); - deleteRequestWhenFinished(request); -} - -void CalculationSubmitter::finishFetchOrCreateQueue(const QVariant& results) -{ - auto resultsList = results.toList(); - if (resultsList.size() == 0) { - // Create the queue - createQueue(); - return; - } - - m_queueId = resultsList[0].toMap()["_id"].toString(); - if (m_queueId.isEmpty()) { - emit error("Queue ID not found!"); - return; - } - - createPendingCalculation(); -} - -void CalculationSubmitter::createQueue() -{ - QString url = m_girderUrl + "/queues"; - QList> urlQueries = { { "name", "oc_queue" }, - { "maxRunning", "5" } }; - - auto* request = - new GirderRequest(m_networkManager.data(), url, m_girderToken); - request->setUrlQueries(urlQueries); - request->setHeader(QNetworkRequest::ContentTypeHeader, - "application/x-www-form-urlencoded"); - - // The post data is empty in this case - request->post(""); - - connect(request, &GirderRequest::result, this, - &CalculationSubmitter::finishCreateQueue); - connect(request, &GirderRequest::error, this, - &CalculationSubmitter::handleError); - deleteRequestWhenFinished(request); -} - -void CalculationSubmitter::finishCreateQueue(const QVariant& results) -{ - m_queueId = results.toMap()["_id"].toString(); - if (m_queueId.isEmpty()) { - emit error("Failed to create queue!"); - return; - } - - createPendingCalculation(); -} - -void CalculationSubmitter::createPendingCalculation() -{ - QString repository, tag; - parseImageName(m_imageName, repository, tag); - - /** - * Needs to look something like this: - * { - * 'moleculeId': molecule_id, - * 'cjson': None, - * 'public': True, - * 'properties': { - * 'pending': True - * }, - * 'input': { - * 'parameters': input_parameters, - * }, - * 'image': { - * 'repository': repository, - * 'tag': tag - * } - * } - * - * - * TODO: Maybe we can find a more concise way to do this in - * the future? - */ - - QJsonObject json; - json["moleculeId"] = m_moleculeId; - json["geometryId"] = m_geometryId; - json["public"] = true; - json["cjson"] = QJsonValue(); - - QJsonObject properties; - properties["pending"] = true; - json["properties"] = properties; - - QJsonObject input; - input["parameters"] = QJsonValue::fromVariant(m_inputParameters); - json["input"] = input; - - QJsonObject image; - image["repository"] = repository; - image["tag"] = tag; - json["image"] = image; - - QString url = m_girderUrl + "/calculations"; - QByteArray postData = QJsonDocument(json).toJson(QJsonDocument::Compact); - - auto* request = - new GirderRequest(m_networkManager.data(), url, m_girderToken); - request->setHeader(QNetworkRequest::ContentTypeHeader, "application/json"); - request->post(postData); - - connect(request, &GirderRequest::result, this, - &CalculationSubmitter::finishCreatePendingCalculation); - connect(request, &GirderRequest::error, this, &CalculationSubmitter::error); - deleteRequestWhenFinished(request); -} - -void CalculationSubmitter::finishCreatePendingCalculation( - const QVariant& results) -{ - m_pendingCalculationId = results.toMap()["_id"].toString(); - if (m_pendingCalculationId.isEmpty()) { - emit error("Failed to create pending calculation"); - return; - } - - createTaskFlow(); -} - -void CalculationSubmitter::createTaskFlow() -{ - QString repository, tag; - parseImageName(m_imageName, repository, tag); - - QJsonObject json; - json["taskFlowClass"] = "taskflows.OpenChemistryTaskFlow"; - - QJsonObject meta; - meta["calculationIds"] = QJsonArray({ m_pendingCalculationId }); - - QJsonObject image; - image["repository"] = repository; - image["tag"] = tag; - meta["image"] = image; - - json["meta"] = meta; - - QString url = m_girderUrl + "/taskflows"; - QByteArray postData = QJsonDocument(json).toJson(QJsonDocument::Compact); - - auto* request = - new GirderRequest(m_networkManager.data(), url, m_girderToken); - request->setHeader(QNetworkRequest::ContentTypeHeader, "application/json"); - request->post(postData); - - connect(request, &GirderRequest::result, this, - &CalculationSubmitter::finishCreateTaskFlow); - connect(request, &GirderRequest::error, this, &CalculationSubmitter::error); - deleteRequestWhenFinished(request); -} - -void CalculationSubmitter::finishCreateTaskFlow(const QVariant& results) -{ - m_taskFlowId = results.toMap()["_id"].toString(); - if (m_taskFlowId.isEmpty()) { - emit error("Failed to create taskflow!"); - return; - } - - addTaskFlowToQueue(); -} - -void CalculationSubmitter::addTaskFlowToQueue() -{ - QString repository, tag; - parseImageName(m_imageName, repository, tag); - - QJsonObject json; - json["runParameters"] = QJsonObject(); - - QJsonObject input; - input["calculations"] = QJsonArray({ m_pendingCalculationId }); - json["input"] = input; - - QJsonObject image; - image["repository"] = repository; - image["tag"] = tag; - json["image"] = image; - - QJsonObject cluster; - cluster["_id"] = m_clusterId; - json["cluster"] = cluster; - - QString url = - (m_girderUrl + "/queues/%1/add/%2").arg(m_queueId).arg(m_taskFlowId); - QByteArray data = QJsonDocument(json).toJson(QJsonDocument::Compact); - - auto* request = - new GirderRequest(m_networkManager.data(), url, m_girderToken); - request->setHeader(QNetworkRequest::ContentTypeHeader, "application/json"); - request->put(data); - - connect(request, &GirderRequest::result, this, - &CalculationSubmitter::finishAddTaskFlowToQueue); - connect(request, &GirderRequest::error, this, &CalculationSubmitter::error); - deleteRequestWhenFinished(request); -} - -void CalculationSubmitter::finishAddTaskFlowToQueue(const QVariant& results) -{ - popQueue(); -} - -void CalculationSubmitter::popQueue() -{ - QString url = (m_girderUrl + "/queues/%1/pop").arg(m_queueId); - - QList> urlQueries = { { "multi", "true" } }; - - auto* request = - new GirderRequest(m_networkManager.data(), url, m_girderToken); - request->setUrlQueries(urlQueries); - request->setHeader(QNetworkRequest::ContentTypeHeader, - "application/x-www-form-urlencoded"); - request->put(""); - - connect(request, &GirderRequest::result, this, - &CalculationSubmitter::finishPopQueue); - connect(request, &GirderRequest::error, this, &CalculationSubmitter::error); - deleteRequestWhenFinished(request); -} - -void CalculationSubmitter::finishPopQueue(const QVariant& results) -{ - QVariantMap output; - output["pendingCalculationId"] = m_pendingCalculationId; - output["taskFlowId"] = m_taskFlowId; - emit finished(output); -} - -void CalculationSubmitter::handleError(const QString& msg, - QNetworkReply* networkReply) -{ - QString message = msg; - if (!msg.startsWith("Girder error:")) - message.prepend("Girder error:"); - - emit error(message, networkReply); -} - -} // namespace Avogadro diff --git a/avogadro/qtplugins/mongochem/calculationsubmitter.h b/avogadro/qtplugins/mongochem/calculationsubmitter.h deleted file mode 100644 index ca479e4373..0000000000 --- a/avogadro/qtplugins/mongochem/calculationsubmitter.h +++ /dev/null @@ -1,101 +0,0 @@ -/****************************************************************************** - This source file is part of the Avogadro project. - This source code is released under the 3-Clause BSD License, (see "LICENSE"). -******************************************************************************/ - -#ifndef AVOGADRO_QTPLUGINS_CALCULATIONSUBMITTER_H -#define AVOGADRO_QTPLUGINS_CALCULATIONSUBMITTER_H - -#include -#include -#include - -class QNetworkAccessManager; -class QNetworkReply; - -namespace Avogadro { -namespace QtPlugins { - -class CalculationSubmitter : public QObject -{ - Q_OBJECT - -public: - explicit CalculationSubmitter(QSharedPointer manager, - const QString& girderUrl, - const QString& girderToken, - QObject* parent = nullptr); - ~CalculationSubmitter() override; - - void setMoleculeCjson(const QString& cjson) { m_moleculeCjson = cjson; } - void setContainerName(const QString& name) { m_containerName = name; } - void setImageName(const QString& name) { m_imageName = name; } - void setInputParameters(const QVariantMap& m) { m_inputParameters = m; } - - void start(); - -signals: - // The results will contain "calculationId" if the calculation has - // already been done before. The results will contain "taskFlowId" - // if a new calculation was submitted. - void finished(const QVariantMap& results); - void error(const QString& errorMessage, QNetworkReply* error = nullptr); - -private slots: - void uploadMolecule(); - void finishUploadMolecule(const QVariant& results); - - void uploadGeometry(); - void finishUploadGeometry(const QVariant& results); - - void fetchCalculation(); - void finishFetchCalculation(const QVariant& results); - - void fetchCluster(); - void finishFetchCluster(const QVariant& results); - - void fetchOrCreateQueue(); - void finishFetchOrCreateQueue(const QVariant& results); - - void createQueue(); - void finishCreateQueue(const QVariant& results); - - void createPendingCalculation(); - void finishCreatePendingCalculation(const QVariant& results); - - void createTaskFlow(); - void finishCreateTaskFlow(const QVariant& results); - - void addTaskFlowToQueue(); - void finishAddTaskFlowToQueue(const QVariant& results); - - void popQueue(); - void finishPopQueue(const QVariant& results); - - void handleError(const QString& msg, QNetworkReply* networkReply); - -private: - QString m_girderUrl = "http://localhost:8080/api/v1"; - QString m_girderToken; - - // These should be set before starting - QString m_moleculeCjson; - QString m_containerName; - QString m_imageName; - QVariantMap m_inputParameters; - - // These will be set during the process - QString m_moleculeId; - QString m_geometryId; - QString m_pendingCalculationId; - QString m_clusterId; - QString m_queueId; - QString m_taskFlowId; - - QSharedPointer m_networkManager; -}; - -} // namespace QtPlugins -} // namespace Avogadro - -#endif // AVOGADRO_QTPLUGINS_CALCULATIONSUBMITTER_H diff --git a/avogadro/qtplugins/mongochem/calculationwatcher.cpp b/avogadro/qtplugins/mongochem/calculationwatcher.cpp deleted file mode 100644 index 3aed6f9b56..0000000000 --- a/avogadro/qtplugins/mongochem/calculationwatcher.cpp +++ /dev/null @@ -1,97 +0,0 @@ -/****************************************************************************** - This source file is part of the Avogadro project. - This source code is released under the 3-Clause BSD License, (see "LICENSE"). -******************************************************************************/ - -#include "calculationwatcher.h" - -#include "girderrequest.h" - -#include -#include -#include -#include - -#include - -namespace Avogadro::QtPlugins { - -static void deleteRequestWhenFinished(GirderRequest* r) -{ - QObject::connect(r, &GirderRequest::result, r, &GirderRequest::deleteLater); - QObject::connect(r, &GirderRequest::error, r, &GirderRequest::deleteLater); -} - -CalculationWatcher::CalculationWatcher( - QSharedPointer manager, const QString& girderUrl, - const QString& girderToken, const QString& pendingCalculationId, - QObject* parent) - : QObject(parent), m_girderUrl(girderUrl), m_girderToken(girderToken), - m_pendingCalculationId(pendingCalculationId), m_networkManager(manager) -{} - -CalculationWatcher::~CalculationWatcher() = default; - -void CalculationWatcher::start() -{ - checkCalculation(); -} - -void CalculationWatcher::checkCalculation() -{ - QString url = (m_girderUrl + "/calculations/%1").arg(m_pendingCalculationId); - - auto* request = - new GirderRequest(m_networkManager.data(), url, m_girderToken); - request->get(); - - qDebug() << "Checking calculation status…"; - - connect(request, &GirderRequest::result, this, - &CalculationWatcher::finishCheckCalculation); - connect(request, &GirderRequest::error, this, - &CalculationWatcher::handleError); - deleteRequestWhenFinished(request); -} - -void CalculationWatcher::finishCheckCalculation(const QVariant& results) -{ - // Perform a couple of sanity checks - QString calculationId = results.toMap()["_id"].toString(); - if (calculationId.isEmpty()) { - emit error("In calculation watcher, calculation id not found!"); - return; - } - - if (calculationId != m_pendingCalculationId) { - emit error("In calculation watcher, calculationId does not match!"); - return; - } - - // We assume the calculation is done when the cjson is present - QVariantMap cjson = results.toMap()["cjson"].toMap(); - if (cjson.isEmpty()) { - qDebug() << "Calculation still running. Trying again in 5 seconds…"; - // No results yet. Try again in 5 seconds. - QTimer::singleShot(5000, this, &CalculationWatcher::checkCalculation); - return; - } - - qDebug() << "Calculation is complete!"; - - QByteArray cjsonData = - QJsonDocument::fromVariant(cjson).toJson(QJsonDocument::Compact); - emit finished(cjsonData); -} - -void CalculationWatcher::handleError(const QString& msg, - QNetworkReply* networkReply) -{ - QString message = msg; - if (!msg.startsWith("Girder error:")) - message.prepend("Girder error:"); - - emit error(message, networkReply); -} - -} // namespace Avogadro diff --git a/avogadro/qtplugins/mongochem/calculationwatcher.h b/avogadro/qtplugins/mongochem/calculationwatcher.h deleted file mode 100644 index 71798d8940..0000000000 --- a/avogadro/qtplugins/mongochem/calculationwatcher.h +++ /dev/null @@ -1,55 +0,0 @@ -/****************************************************************************** - This source file is part of the Avogadro project. - This source code is released under the 3-Clause BSD License, (see "LICENSE"). -******************************************************************************/ - -#ifndef AVOGADRO_QTPLUGINS_CALCULATIONWATCHER_H -#define AVOGADRO_QTPLUGINS_CALCULATIONWATCHER_H - -#include -#include - -class QNetworkAccessManager; -class QNetworkReply; - -namespace Avogadro { -namespace QtPlugins { - -class CalculationWatcher : public QObject -{ - Q_OBJECT - -public: - explicit CalculationWatcher(QSharedPointer manager, - const QString& girderUrl, - const QString& girderToken, - const QString& pendingCalculationId, - QObject* parent); - ~CalculationWatcher() override; - - void start(); - -signals: - void finished(const QByteArray& cjson); - void error(const QString& errorMessage, QNetworkReply* error = nullptr); - -private slots: - void checkCalculation(); - void finishCheckCalculation(const QVariant& results); - - void handleError(const QString& msg, QNetworkReply* networkReply); - -private: - QString m_girderUrl = "http://localhost:8080/api/v1"; - QString m_girderToken; - - // These should be set before starting - QString m_pendingCalculationId; - - QSharedPointer m_networkManager; -}; - -} // namespace QtPlugins -} // namespace Avogadro - -#endif // AVOGADRO_QTPLUGINS_CALCULATIONWATCHER_H diff --git a/avogadro/qtplugins/mongochem/configdialog.cpp b/avogadro/qtplugins/mongochem/configdialog.cpp deleted file mode 100644 index 7b1910f9e7..0000000000 --- a/avogadro/qtplugins/mongochem/configdialog.cpp +++ /dev/null @@ -1,44 +0,0 @@ -/****************************************************************************** - This source file is part of the Avogadro project. - This source code is released under the 3-Clause BSD License, (see "LICENSE"). -******************************************************************************/ - -#include "configdialog.h" -#include "ui_configdialog.h" - -namespace Avogadro::QtPlugins { - -ConfigDialog::ConfigDialog(QWidget* parent) - : QDialog(parent), m_ui(new Ui::ConfigDialog) -{ - m_ui->setupUi(this); -} - -ConfigDialog::~ConfigDialog() = default; - -void ConfigDialog::setGirderUrl(const QString& girderUrl) -{ - m_ui->girderUrl->setText(girderUrl); -} - -void ConfigDialog::setApiKey(const QString& apiKey) -{ - m_ui->apiKey->setText(apiKey); -} - -QString ConfigDialog::girderUrl() const -{ - QString url = m_ui->girderUrl->text(); - if (!url.endsWith("/api/v1")) { - // Append this automatically... - url += "/api/v1"; - } - return url; -} - -QString ConfigDialog::apiKey() const -{ - return m_ui->apiKey->text(); -} - -} // namespace Avogadro diff --git a/avogadro/qtplugins/mongochem/configdialog.h b/avogadro/qtplugins/mongochem/configdialog.h deleted file mode 100644 index d977fb1b40..0000000000 --- a/avogadro/qtplugins/mongochem/configdialog.h +++ /dev/null @@ -1,40 +0,0 @@ -/****************************************************************************** - This source file is part of the Avogadro project. - This source code is released under the 3-Clause BSD License, (see "LICENSE"). -******************************************************************************/ - -#ifndef AVOGADRO_QTPLUGINS_CONFIGDIALOG_H -#define AVOGADRO_QTPLUGINS_CONFIGDIALOG_H - -#include -#include - -namespace Ui { -class ConfigDialog; -} - -namespace Avogadro { -namespace QtPlugins { - -class ConfigDialog : public QDialog -{ - Q_OBJECT - -public: - explicit ConfigDialog(QWidget* parent = nullptr); - ~ConfigDialog(); - - void setGirderUrl(const QString& url); - void setApiKey(const QString& apiKey); - - QString girderUrl() const; - QString apiKey() const; - -private: - QScopedPointer m_ui; -}; - -} // namespace QtPlugins -} // namespace Avogadro - -#endif // AVOGADRO_QTPLUGINS_CONFIGDIALOG_H diff --git a/avogadro/qtplugins/mongochem/configdialog.ui b/avogadro/qtplugins/mongochem/configdialog.ui deleted file mode 100644 index 145416a74c..0000000000 --- a/avogadro/qtplugins/mongochem/configdialog.ui +++ /dev/null @@ -1,105 +0,0 @@ - - - ConfigDialog - - - - 0 - 0 - 400 - 111 - - - - MongoChem Config - - - - - - http://localhost:8080/api/v1 - - - - - - - QLineEdit::Password - - - - - - - API Key: - - - - - - - Qt::Horizontal - - - QDialogButtonBox::Cancel|QDialogButtonBox::Ok - - - - - - - Base URL: - - - - - - - Qt::Vertical - - - - 20 - 40 - - - - - - - - - - buttonBox - accepted() - ConfigDialog - accept() - - - 248 - 254 - - - 157 - 274 - - - - - buttonBox - rejected() - ConfigDialog - reject() - - - 316 - 260 - - - 286 - 274 - - - - - diff --git a/avogadro/qtplugins/mongochem/girderrequest.cpp b/avogadro/qtplugins/mongochem/girderrequest.cpp deleted file mode 100644 index f169135e87..0000000000 --- a/avogadro/qtplugins/mongochem/girderrequest.cpp +++ /dev/null @@ -1,141 +0,0 @@ -/****************************************************************************** - This source file is part of the Avogadro project. - This source code is released under the 3-Clause BSD License, (see "LICENSE"). -******************************************************************************/ - -#include "girderrequest.h" - -#include -#include -#include -#include -#include -#include -#include - -namespace Avogadro::QtPlugins { - -// Some function declarations -static QString handleGirderError(QNetworkReply* reply, const QByteArray& bytes); - -GirderRequest::GirderRequest(QNetworkAccessManager* networkManager, - const QString& girderUrl, - const QString& girderToken, QObject* parent) - : QObject(parent), m_girderUrl(girderUrl), m_girderToken(girderToken), - m_networkManager(networkManager) -{} - -void GirderRequest::get() -{ - QUrl url(m_girderUrl); - - if (!m_urlQueries.isEmpty()) { - // For Qt>=5.13, we can initialize QUrlQuery with m_urlQueries - QUrlQuery query; - query.setQueryItems(m_urlQueries); - url.setQuery(query); - } - - QNetworkRequest request(url); - - // Only set the girder token if there is one - if (!m_girderToken.isEmpty()) - request.setRawHeader(QByteArray("Girder-Token"), m_girderToken.toUtf8()); - - for (auto key : m_headers.keys()) - request.setHeader(key, m_headers[key]); - - auto reply = m_networkManager->get(request); - connect(reply, &QNetworkReply::finished, this, &GirderRequest::onFinished); - - // Delete it after all the connected slots have been called - connect(reply, &QNetworkReply::finished, reply, &QNetworkReply::deleteLater); -} - -void GirderRequest::post(const QByteArray& data) -{ - QUrl url(m_girderUrl); - - if (!m_urlQueries.isEmpty()) { - // For Qt>=5.13, we can initialize QUrlQuery with m_urlQueries - QUrlQuery query; - query.setQueryItems(m_urlQueries); - url.setQuery(query); - } - - QNetworkRequest request(url); - - if (!m_girderToken.isEmpty()) - request.setRawHeader(QByteArray("Girder-Token"), m_girderToken.toUtf8()); - - for (auto key : m_headers.keys()) - request.setHeader(key, m_headers[key]); - - auto reply = m_networkManager->post(request, data); - - connect(reply, &QNetworkReply::finished, this, &GirderRequest::onFinished); - - // Delete it after all the connected slots have been called - connect(reply, &QNetworkReply::finished, reply, &QNetworkReply::deleteLater); -} - -void GirderRequest::put(const QByteArray& data) -{ - QUrl url(m_girderUrl); - - if (!m_urlQueries.isEmpty()) { - // For Qt>=5.13, we can initialize QUrlQuery with m_urlQueries - QUrlQuery query; - query.setQueryItems(m_urlQueries); - url.setQuery(query); - } - - QNetworkRequest request(url); - - if (!m_girderToken.isEmpty()) - request.setRawHeader(QByteArray("Girder-Token"), m_girderToken.toUtf8()); - - for (auto key : m_headers.keys()) - request.setHeader(key, m_headers[key]); - - auto reply = m_networkManager->put(request, data); - - connect(reply, &QNetworkReply::finished, this, &GirderRequest::onFinished); - - // Delete it after all the connected slots have been called - connect(reply, &QNetworkReply::finished, reply, &QNetworkReply::deleteLater); -} - -void GirderRequest::onFinished() -{ - auto* reply = qobject_cast(this->sender()); - QByteArray bytes = reply->readAll(); - if (reply->error()) { - emit error(handleGirderError(reply, bytes), reply); - } else { - QJsonDocument jsonResponse = QJsonDocument::fromJson(bytes.constData()); - emit result(jsonResponse.toVariant()); - } -} - -static QString handleGirderError(QNetworkReply* reply, const QByteArray& bytes) -{ - QJsonDocument jsonResponse = QJsonDocument::fromJson(bytes.constData()); - - QString errorMessage; - - if (!jsonResponse.isObject()) { - errorMessage = reply->errorString(); - } else { - const QJsonObject& object = jsonResponse.object(); - QString message = object.value("message").toString(); - if (!message.isEmpty()) - errorMessage = QString("Girder error: %1").arg(message); - else - errorMessage = QString(bytes); - } - - return errorMessage; -} - -} // namespace Avogadro diff --git a/avogadro/qtplugins/mongochem/girderrequest.h b/avogadro/qtplugins/mongochem/girderrequest.h deleted file mode 100644 index 71cc1d6934..0000000000 --- a/avogadro/qtplugins/mongochem/girderrequest.h +++ /dev/null @@ -1,64 +0,0 @@ -/****************************************************************************** - This source file is part of the Avogadro project. - This source code is released under the 3-Clause BSD License, (see "LICENSE"). -******************************************************************************/ - -#ifndef AVOGADRO_QTPLUGINS_GIRDERREQUEST_H -#define AVOGADRO_QTPLUGINS_GIRDERREQUEST_H - -#include -#include -#include -#include - -class QNetworkAccessManager; -class QNetworkReply; - -namespace Avogadro { - -namespace QtPlugins { - -class GirderRequest : public QObject -{ - Q_OBJECT - -public: - GirderRequest(QNetworkAccessManager* networkManager, const QString& girderUrl, - const QString& girderToken = "", QObject* parent = nullptr); - - // Calls the respective HTTP method on the girder url - void get(); - void post(const QByteArray& data); - void put(const QByteArray& data); - - void setUrlQueries(const QList>& queries) - { - m_urlQueries = queries; - } - - void setHeader(QNetworkRequest::KnownHeaders header, const QVariant& value) - { - m_headers[header] = value; - } - -signals: - // Emitted when there is an error - void error(const QString& msg, QNetworkReply* networkReply = nullptr); - // Emitted when there are results - void result(const QVariant& results); - -protected slots: - void onFinished(); - -protected: - QString m_girderUrl; - QString m_girderToken; - QNetworkAccessManager* m_networkManager; - QList> m_urlQueries; - QMap m_headers; -}; - -} // namespace QtPlugins -} // namespace Avogadro - -#endif diff --git a/avogadro/qtplugins/mongochem/listmoleculesmodel.cpp b/avogadro/qtplugins/mongochem/listmoleculesmodel.cpp deleted file mode 100644 index a628016219..0000000000 --- a/avogadro/qtplugins/mongochem/listmoleculesmodel.cpp +++ /dev/null @@ -1,125 +0,0 @@ -/****************************************************************************** - This source file is part of the Avogadro project. - This source code is released under the 3-Clause BSD License, (see "LICENSE"). -******************************************************************************/ - -#include "listmoleculesmodel.h" - -namespace Avogadro::QtPlugins { - -ListMoleculesModel::ListMoleculesModel(QObject* parent) - : QAbstractTableModel(parent) -{} - -int ListMoleculesModel::rowCount(const QModelIndex& id) const -{ - Q_UNUSED(id) - return m_molecules.size(); -} - -int ListMoleculesModel::columnCount(const QModelIndex& /*parent*/) const -{ - return 3; -} - -QVariant ListMoleculesModel::data(const QModelIndex& index, int role) const -{ - if (!index.isValid()) - return QVariant(); - - switch (role) { - case Qt::DisplayRole: { - const auto& mol = m_molecules[index.row()]; - int column = index.column(); - switch (column) { - case 0: - return mol.value("properties").toMap().value("formula"); - case 1: - return mol.value("smiles"); - case 2: - return mol.value("inchikey"); - default: - return QVariant(); - } - } - } - - return QVariant(); -} - -Qt::ItemFlags ListMoleculesModel::flags(const QModelIndex& index) const -{ - return QAbstractTableModel::flags(index); -} - -QVariant ListMoleculesModel::headerData(int section, - Qt::Orientation orientation, - int role) const -{ - if (role != Qt::DisplayRole) - return QVariant(); - - if (orientation == Qt::Vertical) - return section + 1; - - if (orientation == Qt::Horizontal) { - switch (section) { - case 0: - return tr("Formula"); - - case 1: - return tr("SMILES"); - - case 2: - return tr("InChIKey"); - } - } - - return QVariant(); -} - -QString ListMoleculesModel::moleculeId(int row) -{ - return m_molecules[row]["_id"].toString(); -} - -QString ListMoleculesModel::moleculeName(int row) -{ - auto name = m_molecules[row]["name"].toString(); - - // If there is no name, use the formula instead - if (name.isEmpty()) - name = m_molecules[row]["properties"].toMap()["formula"].toString(); - - return name; -} - -void ListMoleculesModel::addMolecule(const QVariantMap& mol) -{ - beginInsertRows(QModelIndex(), m_molecules.size(), m_molecules.size()); - m_molecules.append(mol); - endInsertRows(); -} - -void ListMoleculesModel::deleteMolecule(const QModelIndex& index) -{ - if (!index.isValid()) - return; - - int row = index.row(); - if (row < m_molecules.size()) { - beginRemoveRows(QModelIndex(), row, row); - m_molecules.removeAt(row); - endRemoveRows(); - } -} - -void ListMoleculesModel::clear() -{ - int lastRow = m_molecules.isEmpty() ? 0 : m_molecules.size() - 1; - beginRemoveRows(QModelIndex(), 0, lastRow); - m_molecules.clear(); - endRemoveRows(); -} - -} // namespace Avogadro diff --git a/avogadro/qtplugins/mongochem/listmoleculesmodel.h b/avogadro/qtplugins/mongochem/listmoleculesmodel.h deleted file mode 100644 index a070c70c44..0000000000 --- a/avogadro/qtplugins/mongochem/listmoleculesmodel.h +++ /dev/null @@ -1,42 +0,0 @@ -/****************************************************************************** - This source file is part of the Avogadro project. - This source code is released under the 3-Clause BSD License, (see "LICENSE"). -******************************************************************************/ - -#ifndef AVOGADRO_QTPLUGINS_LISTMOLECULESMODEL_H -#define AVOGADRO_QTPLUGINS_LISTMOLECULESMODEL_H - -#include -#include -#include - -namespace Avogadro { -namespace QtPlugins { - -class ListMoleculesModel : public QAbstractTableModel -{ - Q_OBJECT - -public: - ListMoleculesModel(QObject* parent = nullptr); - int rowCount(const QModelIndex& parent = QModelIndex()) const override; - int columnCount(const QModelIndex& parent = QModelIndex()) const override; - QVariant data(const QModelIndex& index, - int role = Qt::DisplayRole) const override; - Qt::ItemFlags flags(const QModelIndex& index) const override; - QVariant headerData(int section, Qt::Orientation orientation, - int role) const override; - - QString moleculeId(int row); - QString moleculeName(int row); - void addMolecule(const QVariantMap& molecule); - void deleteMolecule(const QModelIndex& index); - void clear(); - -private: - QList m_molecules; -}; - -} // namespace QtPlugins -} // namespace Avogadro -#endif diff --git a/avogadro/qtplugins/mongochem/mongochem.cpp b/avogadro/qtplugins/mongochem/mongochem.cpp deleted file mode 100644 index 6526278224..0000000000 --- a/avogadro/qtplugins/mongochem/mongochem.cpp +++ /dev/null @@ -1,85 +0,0 @@ -/****************************************************************************** - This source file is part of the Avogadro project. - This source code is released under the 3-Clause BSD License, (see "LICENSE"). -******************************************************************************/ - -#include "mongochem.h" -#include "mongochemwidget.h" - -#include -#include -#include - -#include -#include -#include -#include - -namespace Avogadro::QtPlugins { - -MongoChem::MongoChem(QObject* parent) - : ExtensionPlugin(parent), m_action(new QAction(this)) -{ - m_action->setText(tr("&MongoChem")); - m_actions.push_back(m_action.data()); - connect(m_action.data(), &QAction::triggered, this, - &MongoChem::menuActivated); -} - -MongoChem::~MongoChem() = default; - -QStringList MongoChem::menuPath(QAction*) const -{ - return { tr("&Extensions") }; -} - -void MongoChem::setMolecule(QtGui::Molecule* mol) -{ - m_molecule = mol; -} - -bool MongoChem::readMolecule(QtGui::Molecule& mol) -{ - bool ok = Io::FileFormatManager::instance().readString( - mol, m_moleculeData.data(), "cjson"); - - if (ok) - mol.setData("name", m_moleculeName.toStdString()); - - m_moleculeData.clear(); - m_moleculeName.clear(); - - return ok; -} - -QString MongoChem::currentMoleculeCjson() const -{ - std::string ret; - - if (!m_molecule) - return ""; - - Io::FileFormatManager::instance().writeString(*m_molecule, ret, "cjson"); - return ret.c_str(); -} - -void MongoChem::menuActivated() -{ - if (!m_dialog) { - m_dialog.reset(new QDialog(qobject_cast(this))); - auto* layout = new QVBoxLayout; - layout->addWidget(new MongoChemWidget(this)); - m_dialog->setLayout(layout); - m_dialog->setWindowTitle("MongoChem"); - } - - m_dialog->show(); -} - -void MongoChem::setMoleculeData(const QByteArray& data) -{ - m_moleculeData = data; - emit moleculeReady(1); -} - -} // namespace Avogadro diff --git a/avogadro/qtplugins/mongochem/mongochem.h b/avogadro/qtplugins/mongochem/mongochem.h deleted file mode 100644 index 25a4763053..0000000000 --- a/avogadro/qtplugins/mongochem/mongochem.h +++ /dev/null @@ -1,71 +0,0 @@ -/****************************************************************************** - This source file is part of the Avogadro project. - This source code is released under the 3-Clause BSD License, (see "LICENSE"). -******************************************************************************/ - -#ifndef AVOGADRO_QTPLUGINS_MONGOCHEM_H -#define AVOGADRO_QTPLUGINS_MONGOCHEM_H - -#include - -#include -#include - -class QAction; -class QDialog; - -namespace Avogadro { - -namespace QtPlugins { - -class MongoChem : public QtGui::ExtensionPlugin -{ - Q_OBJECT - -public: - explicit MongoChem(QObject* parent = nullptr); - ~MongoChem() override; - - QString name() const override { return tr("Mongo Chem Server"); } - - QString description() const override - { - return tr("Interface with Mongo Chem Server."); - } - - QList actions() const override { return m_actions; } - - QStringList menuPath(QAction*) const override; - - // This will also emit moleculeReady(1) - void setMoleculeData(const QByteArray& data); - void setMoleculeName(const QString& name) { m_moleculeName = name; } - - // Returns the cjson of the current molecule as a QString - QString currentMoleculeCjson() const; - -public slots: - void setMolecule(QtGui::Molecule* mol) override; - - // This will also clear m_moleculeData and m_moleculeName - bool readMolecule(QtGui::Molecule& mol) override; - -private slots: - void menuActivated(); - -private: - // A non-owning list of the actions - QList m_actions; - QtGui::Molecule* m_molecule; - - QScopedPointer m_action; - QScopedPointer m_dialog; - - // The data to be read by readMolecule() - QByteArray m_moleculeData; - QString m_moleculeName; -}; -} // namespace QtPlugins -} // namespace Avogadro - -#endif // AVOGADRO_QTPLUGINS_MONGOCHEM_H diff --git a/avogadro/qtplugins/mongochem/mongochemwidget.cpp b/avogadro/qtplugins/mongochem/mongochemwidget.cpp deleted file mode 100644 index ac8b7a17d7..0000000000 --- a/avogadro/qtplugins/mongochem/mongochemwidget.cpp +++ /dev/null @@ -1,391 +0,0 @@ -/****************************************************************************** - This source file is part of the Avogadro project. - This source code is released under the 3-Clause BSD License, (see "LICENSE"). -******************************************************************************/ - -#include "mongochemwidget.h" -#include "ui_mongochemwidget.h" - -#include "calculationsubmitter.h" -#include "calculationwatcher.h" -#include "configdialog.h" -#include "girderrequest.h" -#include "listmoleculesmodel.h" -#include "mongochem.h" -#include "submitcalculationdialog.h" - -#include -#include -#include -#include -#include -#include -#include - -namespace Avogadro::QtPlugins { - -MongoChemWidget::MongoChemWidget(MongoChem* plugin, QWidget* parent) - : QWidget(parent), m_plugin(plugin), m_ui(new Ui::MongoChemWidget), - m_networkManager(new QNetworkAccessManager(this)), - m_listMoleculesModel(new ListMoleculesModel(this)) -{ - m_ui->setupUi(this); - m_ui->tableMolecules->setModel(m_listMoleculesModel.data()); - readSettings(); - setupConnections(); -} - -MongoChemWidget::~MongoChemWidget() = default; - -void MongoChemWidget::setupConnections() -{ - connect(m_ui->pushSearch, &QPushButton::clicked, this, - &MongoChemWidget::search); - connect(m_ui->pushConfig, &QPushButton::clicked, this, - &MongoChemWidget::showConfig); - connect(m_ui->pushDownload, &QPushButton::clicked, this, - &MongoChemWidget::downloadSelectedMolecule); - connect(m_ui->pushUpload, &QPushButton::clicked, this, - &MongoChemWidget::uploadMolecule); - connect(m_ui->pushSubmitCalculation, &QPushButton::clicked, this, - &MongoChemWidget::submitCalculation); -} - -void MongoChemWidget::readSettings() -{ - QSettings settings; - settings.beginGroup("mongochem"); - m_girderUrl = settings.value("girderUrl", m_girderUrl).toString(); - m_apiKey = settings.value("apiKey", m_apiKey).toString(); - settings.endGroup(); -} - -void MongoChemWidget::writeSettings() -{ - QSettings settings; - settings.beginGroup("mongochem"); - settings.setValue("girderUrl", m_girderUrl); - settings.setValue("apiKey", m_apiKey); - settings.endGroup(); -} - -void MongoChemWidget::authenticate() -{ - QString url = m_girderUrl + "/api_key/token"; - - static const QString& tokenDuration = "90"; - QByteArray postData; - postData.append(("key=" + m_apiKey + "&").toUtf8()); - postData.append(("duration=" + tokenDuration).toUtf8()); - - auto* request = - new GirderRequest(m_networkManager.data(), url, m_girderToken); - request->setHeader(QNetworkRequest::ContentTypeHeader, - "application/x-www-form-urlencoded"); - request->post(postData); - - connect(request, &GirderRequest::result, this, - &MongoChemWidget::finishAuthentication); - connect(request, &GirderRequest::error, this, &MongoChemWidget::error); - connect(request, &GirderRequest::result, request, - &GirderRequest::deleteLater); - connect(request, &GirderRequest::error, request, &GirderRequest::deleteLater); -} - -void MongoChemWidget::finishAuthentication(const QVariant& results) -{ - - m_girderToken = results.toMap()["authToken"].toMap()["token"].toString(); - if (!m_girderToken.isEmpty()) - QMessageBox::information(this, "MongoChem", "Authentication Successful!"); - else - QMessageBox::critical(this, "MongoChem", "Authentication failed!"); -} - -void MongoChemWidget::showConfig() -{ - if (!m_configDialog) - m_configDialog.reset(new ConfigDialog(this)); - - // Make sure the GUI variables are up-to-date - m_configDialog->setGirderUrl(m_girderUrl); - m_configDialog->setApiKey(m_apiKey); - - if (m_configDialog->exec()) { - m_girderUrl = m_configDialog->girderUrl(); - m_apiKey = m_configDialog->apiKey(); - if (!m_apiKey.isEmpty()) - authenticate(); - - writeSettings(); - } -} - -void MongoChemWidget::search() -{ - QString url = m_girderUrl + "/molecules"; - - QList> urlQueries = { { "limit", "25" } }; - - auto* request = - new GirderRequest(m_networkManager.data(), url, m_girderToken); - request->setUrlQueries(urlQueries); - request->get(); - - connect(request, &GirderRequest::result, this, - &MongoChemWidget::finishSearch); - connect(request, &GirderRequest::error, this, &MongoChemWidget::error); - connect(request, &GirderRequest::result, request, - &GirderRequest::deleteLater); - connect(request, &GirderRequest::error, request, &GirderRequest::deleteLater); -} - -void MongoChemWidget::finishSearch(const QVariant& results) -{ - // Clear the table - m_listMoleculesModel->clear(); - auto resultList = results.toMap()["results"].toList(); - int matches = resultList.size(); - if (matches == 0) { - QString message = "No results found!"; - qDebug() << message; - QMessageBox::critical(this, "MongoChem", message); - return; - } - - for (int i = 0; i < matches; ++i) { - m_listMoleculesModel->addMolecule(resultList[i].toMap()); - } -} - -int MongoChemWidget::selectedRow() -{ - auto rows = m_ui->tableMolecules->selectionModel()->selectedRows(); - if (rows.isEmpty()) { - qDebug() << "No row selected!"; - return -1; - } - - return rows[0].row(); -} - -void MongoChemWidget::downloadSelectedMolecule() -{ - int row = selectedRow(); - if (row < 0) { - QString message = "No molecule selected!"; - qDebug() << message; - QMessageBox::critical(this, "MongoChem", message); - return; - } - - auto moleculeId = m_listMoleculesModel->moleculeId(row); - auto moleculeName = m_listMoleculesModel->moleculeName(row); - - // It would be better if we set the name after downloading the - // molecule succeeded, but that is currently not easy... - m_plugin->setMoleculeName(moleculeName); - - QString url = (m_girderUrl + "/molecules/%1/cjson").arg(moleculeId); - - auto* request = - new GirderRequest(m_networkManager.data(), url, m_girderToken); - request->get(); - - connect(request, &GirderRequest::result, this, - &MongoChemWidget::finishDownloadMolecule); - connect(request, &GirderRequest::error, this, &MongoChemWidget::error); - connect(request, &GirderRequest::result, request, - &GirderRequest::deleteLater); - connect(request, &GirderRequest::error, request, &GirderRequest::deleteLater); -} - -void MongoChemWidget::finishDownloadMolecule(const QVariant& results) -{ - auto cjsonDoc = QJsonDocument::fromVariant(results); - if (cjsonDoc.isEmpty()) { - qDebug() << "No cjson found in the results!"; - return; - } - - m_plugin->setMoleculeData(cjsonDoc.toJson()); -} - -void MongoChemWidget::uploadMolecule() -{ - if (m_girderToken.isEmpty()) { - QString message = "Login required to upload"; - qDebug() << message; - QMessageBox::critical(this, "MongoChem", message); - return; - } - - QString cjson = m_plugin->currentMoleculeCjson(); - - // If there is no molecule, the cjson will look like this: - // {\n \"chemicalJson\": 1\n} - if (!cjson.contains("atoms")) { - QString message = "No molecule found!"; - qDebug() << message; - QMessageBox::critical(this, "MongoChem", message); - return; - } - QJsonObject object({ { "cjson", cjson } }); - QByteArray postData = QJsonDocument(object).toJson(); - - QString url = m_girderUrl + "/molecules"; - - auto* request = - new GirderRequest(m_networkManager.data(), url, m_girderToken); - request->setHeader(QNetworkRequest::ContentTypeHeader, "application/json"); - request->post(postData); - - connect(request, &GirderRequest::result, this, - &MongoChemWidget::finishUploadMolecule); - connect(request, &GirderRequest::error, this, &MongoChemWidget::error); - connect(request, &GirderRequest::result, request, - &GirderRequest::deleteLater); - connect(request, &GirderRequest::error, request, &GirderRequest::deleteLater); -} - -void MongoChemWidget::finishUploadMolecule(const QVariant& results) -{ - auto moleculeId = results.toMap()["_id"].toString(); - if (moleculeId.isEmpty()) { - QString message = "Failed to upload molecule"; - qDebug() << message; - QMessageBox::critical(this, "MongoChem", message); - return; - } - - // Now, upload the particular geometry - uploadGeometry(moleculeId); -} - -void MongoChemWidget::uploadGeometry(const QString& moleculeId) -{ - QByteArray postData = m_plugin->currentMoleculeCjson().toLatin1(); - - QString url =(m_girderUrl + "/molecules/%1/geometries").arg(moleculeId); - - QList> urlQueries = { - { "provenanceType", "Uploaded by Avogadro2 User" } - }; - - auto* request = - new GirderRequest(m_networkManager.data(), url, m_girderToken); - request->setHeader(QNetworkRequest::ContentTypeHeader, "application/json"); - request->setUrlQueries(urlQueries); - request->post(postData); - - connect(request, &GirderRequest::result, this, - &MongoChemWidget::finishUploadGeometry); - connect(request, &GirderRequest::error, this, &MongoChemWidget::error); - connect(request, &GirderRequest::result, request, - &GirderRequest::deleteLater); - connect(request, &GirderRequest::error, request, &GirderRequest::deleteLater); -} - -void MongoChemWidget::finishUploadGeometry(const QVariant& results) -{ - auto geometryId = results.toMap()["_id"].toString(); - if (geometryId.isEmpty()) { - QString message = "Failed to upload geometry"; - qDebug() << message; - QMessageBox::critical(this, "MongoChem", message); - return; - } - - QString message = "Upload successful!"; - qDebug() << message; - QMessageBox::information(this, "MongoChem", message); -} - -void MongoChemWidget::submitCalculation() -{ - if (m_girderToken.isEmpty()) { - QString message = "Login required to submit calculation"; - qDebug() << message; - QMessageBox::critical(this, "MongoChem", message); - return; - } - - QString cjson = m_plugin->currentMoleculeCjson(); - - // If there is no molecule, the cjson will look like this: - // {\n \"chemicalJson\": 1\n} - if (!cjson.contains("atoms")) { - QString message = "No molecule found!"; - qDebug() << message; - QMessageBox::critical(this, "MongoChem", message); - return; - } - - if (!m_submitCalculationDialog) - m_submitCalculationDialog.reset(new SubmitCalculationDialog); - - if (!m_submitCalculationDialog->exec()) - return; - - QString container = m_submitCalculationDialog->containerName(); - QString image = m_submitCalculationDialog->imageName(); - QVariantMap inputParameters = m_submitCalculationDialog->inputParameters(); - - auto calcSubmitter = new CalculationSubmitter(m_networkManager, m_girderUrl, - m_girderToken, this); - - calcSubmitter->setMoleculeCjson(cjson); - calcSubmitter->setContainerName(container); - calcSubmitter->setImageName(image); - calcSubmitter->setInputParameters(inputParameters); - calcSubmitter->start(); - - connect(calcSubmitter, &CalculationSubmitter::finished, this, - &MongoChemWidget::finishSubmitCalculation); - connect(calcSubmitter, &CalculationSubmitter::error, this, - &MongoChemWidget::error); - connect(calcSubmitter, &CalculationSubmitter::finished, calcSubmitter, - &CalculationSubmitter::deleteLater); - connect(calcSubmitter, &CalculationSubmitter::error, calcSubmitter, - &CalculationSubmitter::deleteLater); -} - -void MongoChemWidget::finishSubmitCalculation(const QVariantMap& results) -{ - QString message = "Calculation submitted!"; - qDebug() << message; - QMessageBox::information(this, "MongoChem", message); - - QString pendingCalculationId = results["pendingCalculationId"].toString(); - - auto watcher = new CalculationWatcher( - m_networkManager, m_girderUrl, m_girderToken, pendingCalculationId, this); - - watcher->start(); - - connect(watcher, &CalculationWatcher::finished, this, - &MongoChemWidget::finishWatchCalculation); - connect(watcher, &CalculationWatcher::error, this, &MongoChemWidget::error); - connect(watcher, &CalculationWatcher::finished, watcher, - &CalculationWatcher::deleteLater); - connect(watcher, &CalculationWatcher::error, watcher, - &CalculationWatcher::deleteLater); -} - -void MongoChemWidget::finishWatchCalculation(const QByteArray& cjson) -{ - QString msg = "Calculation complete. Download the results?"; - if (QMessageBox::question(this, "MongoChem", msg)) { - m_plugin->setMoleculeName("calculation"); - m_plugin->setMoleculeData(cjson); - } -} - -void MongoChemWidget::error(const QString& message, QNetworkReply* reply) -{ - Q_UNUSED(reply) - qDebug() << "An error occurred. Message was: " << message; - QMessageBox::critical(this, "MongoChem", message); -} - -} // namespace Avogadro diff --git a/avogadro/qtplugins/mongochem/mongochemwidget.h b/avogadro/qtplugins/mongochem/mongochemwidget.h deleted file mode 100644 index f6a4417e06..0000000000 --- a/avogadro/qtplugins/mongochem/mongochemwidget.h +++ /dev/null @@ -1,77 +0,0 @@ -/****************************************************************************** - This source file is part of the Avogadro project. - This source code is released under the 3-Clause BSD License, (see "LICENSE"). -******************************************************************************/ - -#ifndef AVOGADRO_QTPLUGINS_MONGOCHEMWIDGET_H -#define AVOGADRO_QTPLUGINS_MONGOCHEMWIDGET_H - -#include -#include -#include - -namespace Ui { -class MongoChemWidget; -} - -class QNetworkAccessManager; -class QNetworkReply; - -namespace Avogadro { - -namespace QtPlugins { - -class ConfigDialog; -class ListMoleculesModel; -class MongoChem; -class SubmitCalculationDialog; - -class MongoChemWidget : public QWidget -{ - Q_OBJECT - -public: - explicit MongoChemWidget(MongoChem* plugin, QWidget* parent = nullptr); - ~MongoChemWidget() override; - -private slots: - void showConfig(); - void finishAuthentication(const QVariant& results); - void search(); - void finishSearch(const QVariant& results); - void downloadSelectedMolecule(); - void finishDownloadMolecule(const QVariant& results); - void uploadMolecule(); - void finishUploadMolecule(const QVariant& results); - void uploadGeometry(const QString& moleculeId); - void finishUploadGeometry(const QVariant& results); - void submitCalculation(); - void finishSubmitCalculation(const QVariantMap& results); - void finishWatchCalculation(const QByteArray& cjson); - void error(const QString& message, QNetworkReply* reply = nullptr); - - void readSettings(); - void writeSettings(); - -private: - void setupConnections(); - void authenticate(); - int selectedRow(); - - MongoChem* m_plugin; - - QString m_girderUrl = "http://localhost:8080/api/v1"; - QString m_apiKey; - QString m_girderToken; - - QScopedPointer m_ui; - QSharedPointer m_networkManager; - QScopedPointer m_configDialog; - QScopedPointer m_listMoleculesModel; - QScopedPointer m_submitCalculationDialog; -}; - -} // namespace QtPlugins -} // namespace Avogadro - -#endif // AVOGADRO_QTPLUGINS_MONGOCHEMWIDGET_H diff --git a/avogadro/qtplugins/mongochem/mongochemwidget.ui b/avogadro/qtplugins/mongochem/mongochemwidget.ui deleted file mode 100644 index 153f44426b..0000000000 --- a/avogadro/qtplugins/mongochem/mongochemwidget.ui +++ /dev/null @@ -1,81 +0,0 @@ - - - MongoChemWidget - - - - 0 - 0 - 620 - 410 - - - - - 620 - 410 - - - - Form - - - - - - QAbstractItemView::SingleSelection - - - QAbstractItemView::SelectRows - - - 150 - - - false - - - true - - - - - - - Config - - - - - - - Download - - - - - - - Upload - - - - - - - Search - - - - - - - Submit Calculation... - - - - - - - - diff --git a/avogadro/qtplugins/mongochem/submitcalculationdialog.cpp b/avogadro/qtplugins/mongochem/submitcalculationdialog.cpp deleted file mode 100644 index f25bdb928b..0000000000 --- a/avogadro/qtplugins/mongochem/submitcalculationdialog.cpp +++ /dev/null @@ -1,60 +0,0 @@ -/****************************************************************************** - This source file is part of the Avogadro project. - This source code is released under the 3-Clause BSD License, (see "LICENSE"). -******************************************************************************/ - -#include "submitcalculationdialog.h" -#include "ui_submitcalculationdialog.h" - -#include -#include -#include - -namespace Avogadro::QtPlugins { - -SubmitCalculationDialog::SubmitCalculationDialog(QWidget* parent) - : QDialog(parent), m_ui(new Ui::SubmitCalculationDialog) -{ - m_ui->setupUi(this); -} - -SubmitCalculationDialog::~SubmitCalculationDialog() = default; - -int SubmitCalculationDialog::exec() -{ - // Loop until validation succeeds, or the user cancels - while (true) { - if (!QDialog::exec()) - return QDialog::Rejected; - - QVariantMap inputParams = inputParameters(); - if (inputParams.isEmpty()) { - QString message = "Failed to parse input parameters"; - QMessageBox::critical(this, "MongoChem", message); - continue; - } - - break; - } - - return QDialog::Accepted; -} - -QString SubmitCalculationDialog::containerName() const -{ - return m_ui->container->currentText().toLower(); -} - -QString SubmitCalculationDialog::imageName() const -{ - return m_ui->image->text(); -} - -QVariantMap SubmitCalculationDialog::inputParameters() const -{ - QByteArray jsonData = m_ui->inputParameters->toPlainText().toUtf8(); - auto jsonDoc = QJsonDocument::fromJson(jsonData); - return jsonDoc.object().toVariantMap(); -} - -} // namespace Avogadro diff --git a/avogadro/qtplugins/mongochem/submitcalculationdialog.h b/avogadro/qtplugins/mongochem/submitcalculationdialog.h deleted file mode 100644 index c1b9d6336c..0000000000 --- a/avogadro/qtplugins/mongochem/submitcalculationdialog.h +++ /dev/null @@ -1,39 +0,0 @@ -/****************************************************************************** - This source file is part of the Avogadro project. - This source code is released under the 3-Clause BSD License, (see "LICENSE"). -******************************************************************************/ - -#ifndef AVOGADRO_QTPLUGINS_SUBMITCALCULATIONDIALOG_H -#define AVOGADRO_QTPLUGINS_SUBMITCALCULATIONDIALOG_H - -#include - -namespace Ui { -class SubmitCalculationDialog; -} - -namespace Avogadro { -namespace QtPlugins { - -class SubmitCalculationDialog : public QDialog -{ - Q_OBJECT - -public: - explicit SubmitCalculationDialog(QWidget* parent = nullptr); - ~SubmitCalculationDialog(); - - int exec() override; - - QString containerName() const; - QString imageName() const; - QVariantMap inputParameters() const; - -private: - QScopedPointer m_ui; -}; - -} // namespace QtPlugins -} // namespace Avogadro - -#endif // AVOGADRO_QTPLUGINS_SUBMITCALCULATIONDIALOG_H diff --git a/avogadro/qtplugins/mongochem/submitcalculationdialog.ui b/avogadro/qtplugins/mongochem/submitcalculationdialog.ui deleted file mode 100644 index 3c89c88be2..0000000000 --- a/avogadro/qtplugins/mongochem/submitcalculationdialog.ui +++ /dev/null @@ -1,153 +0,0 @@ - - - SubmitCalculationDialog - - - - 0 - 0 - 400 - 255 - - - - Dialog - - - - - - - Docker - - - - - Singularity - - - - - - - - Container: - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - - Image: - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - - openchemistry/psi4:latest - - - false - - - - - - - - - - Qt::Vertical - - - - 20 - 40 - - - - - - - - Qt::Horizontal - - - QDialogButtonBox::Cancel|QDialogButtonBox::Ok - - - - - - - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> -<html><head><meta name="qrichtext" content="1" /><style type="text/css"> -p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'Ubuntu'; font-size:11pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu';">{</span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu';"> &quot;theory&quot;: &quot;dft&quot;,</span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu';"> &quot;functional&quot;: &quot;b3lyp&quot;,</span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu';"> &quot;basis&quot;: &quot;6-31g&quot;,</span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu';"> &quot;task&quot;: &quot;energy&quot; </span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu';">}</span></p></body></html> - - - false - - - - - - - Input Parameters: - - - Qt::AlignCenter - - - - - - - - - buttonBox - accepted() - SubmitCalculationDialog - accept() - - - 248 - 254 - - - 157 - 274 - - - - - buttonBox - rejected() - SubmitCalculationDialog - reject() - - - 316 - 260 - - - 286 - 274 - - - - -