diff --git a/avogadro/qtgui/extensionplugin.cpp b/avogadro/qtgui/extensionplugin.cpp index 5603a337fc..ea2052c692 100644 --- a/avogadro/qtgui/extensionplugin.cpp +++ b/avogadro/qtgui/extensionplugin.cpp @@ -7,38 +7,34 @@ namespace Avogadro::QtGui { -ExtensionPlugin::ExtensionPlugin(QObject* parent_) : QObject(parent_) -{ -} +ExtensionPlugin::ExtensionPlugin(QObject* parent_) : QObject(parent_) {} -ExtensionPlugin::~ExtensionPlugin() -{ -} +ExtensionPlugin::~ExtensionPlugin() {} QList ExtensionPlugin::fileFormats() const { return QList(); } -ExtensionPluginFactory::~ExtensionPluginFactory() -{ -} +ExtensionPluginFactory::~ExtensionPluginFactory() {} bool ExtensionPlugin::readMolecule(Molecule&) { return false; } -void ExtensionPlugin::setScene(Rendering::Scene*) -{ -} +void ExtensionPlugin::setScene(Rendering::Scene*) {} -void ExtensionPlugin::setCamera(Rendering::Camera* camera) -{ -} +void ExtensionPlugin::setCamera(Rendering::Camera* camera) {} + +void ExtensionPlugin::setActiveWidget(QWidget* widget) {} -void ExtensionPlugin::setActiveWidget(QWidget* widget) +bool ExtensionPlugin::handleCommand(const QString& command, + const QVariantMap& options) { + Q_UNUSED(command); + Q_UNUSED(options); + return false; } -} // End Avogadro namespace +} // namespace Avogadro::QtGui diff --git a/avogadro/qtgui/extensionplugin.h b/avogadro/qtgui/extensionplugin.h index 35af93a24a..dcc85c2143 100644 --- a/avogadro/qtgui/extensionplugin.h +++ b/avogadro/qtgui/extensionplugin.h @@ -23,7 +23,7 @@ class Molecule; namespace Rendering { class Camera; class Scene; -} +} // namespace Rendering namespace Io { class FileFormat; @@ -103,6 +103,18 @@ public slots: */ virtual void setActiveWidget(QWidget* widget); + /** + * Called by the app to handle a command registered by the extension. + * (e.g., "renderMovie" or "generateSurface", etc.) + * + * The app will turn the command into a string and pass it to the extension. + * and any options will go from a JSON dictionary to a QVariantMap. + * + * @return true if the command was handled, false otherwise. + */ + virtual bool handleCommand(const QString& command, + const QVariantMap& options); + signals: /** * Signal that the extension has a new molecule that is ready to be loaded. @@ -131,6 +143,17 @@ public slots: * would be most readily viewed with a specialized view. */ void requestActiveDisplayTypes(QStringList displayTypes); + + /** + * Register a new command with the application. The command will be available + * through scripting (e.g., "renderMovie" or "generateSurface", etc.) + * + * @param command The name of the command to register. + * @param description A description of the command. + * + * @sa handleCommand + */ + void registerCommand(QString command, QString description); }; /** @@ -146,8 +169,8 @@ class AVOGADROQTGUI_EXPORT ExtensionPluginFactory ~ExtensionPluginFactory() override; }; -} // End QtGui namespace -} // End Avogadro namespace +} // namespace QtGui +} // namespace Avogadro Q_DECLARE_INTERFACE(Avogadro::QtGui::ExtensionPluginFactory, "org.openchemistry.avogadro.ExtensionPluginFactory") diff --git a/avogadro/qtgui/toolplugin.cpp b/avogadro/qtgui/toolplugin.cpp index 8958bfed50..249c2a2638 100644 --- a/avogadro/qtgui/toolplugin.cpp +++ b/avogadro/qtgui/toolplugin.cpp @@ -7,13 +7,9 @@ namespace Avogadro::QtGui { -ToolPlugin::ToolPlugin(QObject* parent_) : QObject(parent_) -{ -} +ToolPlugin::ToolPlugin(QObject* parent_) : QObject(parent_) {} -ToolPlugin::~ToolPlugin() -{ -} +ToolPlugin::~ToolPlugin() {} QUndoCommand* ToolPlugin::mousePressEvent(QMouseEvent*) { @@ -50,12 +46,16 @@ QUndoCommand* ToolPlugin::keyReleaseEvent(QKeyEvent*) return nullptr; } -void ToolPlugin::draw(Rendering::GroupNode&) -{ -} +void ToolPlugin::draw(Rendering::GroupNode&) {} -ToolPluginFactory::~ToolPluginFactory() +bool ToolPlugin::handleCommand(const QString& command, + const QVariantMap& options) { + Q_UNUSED(command); + Q_UNUSED(options); + return false; } -} // End Avogadro namespace +ToolPluginFactory::~ToolPluginFactory() {} + +} // namespace Avogadro::QtGui diff --git a/avogadro/qtgui/toolplugin.h b/avogadro/qtgui/toolplugin.h index d5b3a543b4..b5756f3df8 100644 --- a/avogadro/qtgui/toolplugin.h +++ b/avogadro/qtgui/toolplugin.h @@ -21,7 +21,7 @@ namespace Avogadro { namespace Rendering { class GroupNode; class GLRenderer; -} +} // namespace Rendering namespace QtOpenGL { class GLWidget; @@ -91,6 +91,18 @@ class AVOGADROQTGUI_EXPORT ToolPlugin : public QObject */ virtual void draw(Rendering::GroupNode& node); + /** + * Called by the app to handle a command registered by the plugin. + * (e.g., "renderMovie" or "drawAtom", etc.) + * + * The app will turn the command into a string and pass it to the tool. + * and any options will go from a JSON dictionary to a QVariantMap. + * + * @return true if the command was handled, false otherwise. + */ + virtual bool handleCommand(const QString& command, + const QVariantMap& options); + signals: /** * Emitted when draw() needs to be called again due to updates. @@ -103,6 +115,17 @@ class AVOGADROQTGUI_EXPORT ToolPlugin : public QObject */ void updateRequested(); + /** + * Register a new command with the application. The command will be available + * through scripting (e.g., "renderMovie" or "generateSurface", etc.) + * + * @param command The name of the command to register. + * @param description A description of the command. + * + * @sa handleCommand + */ + void registerCommand(QString command, QString description); + public slots: /** * Called when the current molecule changes. @@ -137,12 +160,12 @@ class AVOGADROQTGUI_EXPORT ToolPluginFactory public: virtual ~ToolPluginFactory(); - virtual ToolPlugin* createInstance(QObject *parent = nullptr) = 0; + virtual ToolPlugin* createInstance(QObject* parent = nullptr) = 0; virtual QString identifier() const = 0; }; -} // End QtGui namespace -} // End Avogadro namespace +} // namespace QtGui +} // namespace Avogadro Q_DECLARE_INTERFACE(Avogadro::QtGui::ToolPluginFactory, "org.openchemistry.avogadro.ToolPluginFactory") diff --git a/avogadro/qtplugins/spectra/spectra.cpp b/avogadro/qtplugins/spectra/spectra.cpp index 6203518e97..f4d5541cb8 100644 --- a/avogadro/qtplugins/spectra/spectra.cpp +++ b/avogadro/qtplugins/spectra/spectra.cpp @@ -9,11 +9,12 @@ #include #include #include +#include -#include #include +#include +#include #include -#include namespace Avogadro::QtPlugins { @@ -26,12 +27,20 @@ Spectra::Spectra(QObject* p) action->setText(tr("Vibrational Modes…")); connect(action, SIGNAL(triggered()), SLOT(openDialog())); m_actions.push_back(action); -} -Spectra::~Spectra() -{ + emit registerCommand("showVibrations", + tr("Show the vibrational modes dialog.")); + emit registerCommand("setVibrationalMode", tr("Set the vibrational mode.")); + emit registerCommand("setVibrationalAmplitude", + tr("Set the vibrational amplitude.")); + emit registerCommand("startVibrationAnimation", + tr("Start the vibrational animation.")); + emit registerCommand("stopVibrationAnimation", + tr("Stop the vibrational animation.")); } +Spectra::~Spectra() {} + QList Spectra::actions() const { return m_actions; @@ -54,6 +63,37 @@ void Spectra::setMolecule(QtGui::Molecule* mol) m_molecule = mol; if (m_dialog) m_dialog->setMolecule(mol); + + if (isVibrational) + openDialog(); +} + +bool Spectra::handleCommand(const QString& command, const QVariantMap& options) +{ + if (m_molecule == nullptr) + return false; // No molecule to handle the command. + + if (command == "showVibrations") { + openDialog(); + return true; + } else if (command == "setVibrationalMode") { + if (options.contains("mode")) { + setMode(options["mode"].toInt()); + return true; + } + } else if (command == "setVibrationalAmplitude") { + if (options.contains("amplitude")) { + setAmplitude(options["amplitude"].toInt()); + return true; + } + } else if (command == "startVibrationAnimation") { + startVibrationAnimation(); + return true; + } else if (command == "stopVibrationAnimation") { + stopVibrationAnimation(); + return true; + } + return false; } void Spectra::setMode(int mode) @@ -66,20 +106,27 @@ void Spectra::setMode(int mode) m_molecule->setCoordinate3d(0); Core::Array atomPositions = m_molecule->atomPositions3d(); Core::Array atomDisplacements = m_molecule->vibrationLx(mode); + // TODO: needs an option (show forces or not) + double factor = 0.01 * m_amplitude; + Index atom = 0; + for (Vector3& v : atomDisplacements) { + v *= 10.0 * factor; + m_molecule->setForceVector(atom, v); + ++atom; + } + m_molecule->emitChanged(QtGui::Molecule::Atoms | QtGui::Molecule::Added); - int frames = 5; + int frames = 5; // TODO: needs an option int frameCounter = 0; m_molecule->setCoordinate3d(atomPositions, frameCounter++); - double factor = 0.01 * m_amplitude; - // Current coords + displacement. for (int i = 1; i <= frames; ++i) { Core::Array framePositions; for (Index atom = 0; atom < m_molecule->atomCount(); ++atom) { - framePositions.push_back(atomPositions[atom] + - atomDisplacements[atom] * factor * - (double(i) / frames)); + framePositions.push_back(atomPositions[atom] + atomDisplacements[atom] * + factor * + (double(i) / frames)); } m_molecule->setCoordinate3d(framePositions, frameCounter++); } @@ -87,9 +134,9 @@ void Spectra::setMode(int mode) for (int i = frames - 1; i >= 0; --i) { Core::Array framePositions; for (Index atom = 0; atom < m_molecule->atomCount(); ++atom) { - framePositions.push_back(atomPositions[atom] + - atomDisplacements[atom] * factor * - (double(i) / frames)); + framePositions.push_back(atomPositions[atom] + atomDisplacements[atom] * + factor * + (double(i) / frames)); } m_molecule->setCoordinate3d(framePositions, frameCounter++); } @@ -97,9 +144,9 @@ void Spectra::setMode(int mode) for (int i = 1; i <= frames; ++i) { Core::Array framePositions; for (Index atom = 0; atom < m_molecule->atomCount(); ++atom) { - framePositions.push_back(atomPositions[atom] - - atomDisplacements[atom] * factor * - (double(i) / frames)); + framePositions.push_back(atomPositions[atom] - atomDisplacements[atom] * + factor * + (double(i) / frames)); } m_molecule->setCoordinate3d(framePositions, frameCounter++); } @@ -107,9 +154,9 @@ void Spectra::setMode(int mode) for (int i = frames - 1; i >= 0; --i) { Core::Array framePositions; for (Index atom = 0; atom < m_molecule->atomCount(); ++atom) { - framePositions.push_back(atomPositions[atom] - - atomDisplacements[atom] * factor * - (double(i) / frames)); + framePositions.push_back(atomPositions[atom] - atomDisplacements[atom] * + factor * + (double(i) / frames)); } m_molecule->setCoordinate3d(framePositions, frameCounter++); } @@ -169,4 +216,4 @@ void Spectra::advanceFrame() m_molecule->setCoordinate3d(m_currentFrame); m_molecule->emitChanged(QtGui::Molecule::Atoms | QtGui::Molecule::Added); } -} +} // namespace Avogadro::QtPlugins diff --git a/avogadro/qtplugins/spectra/spectra.h b/avogadro/qtplugins/spectra/spectra.h index d8cbb8e09f..8f1f51730f 100644 --- a/avogadro/qtplugins/spectra/spectra.h +++ b/avogadro/qtplugins/spectra/spectra.h @@ -42,6 +42,9 @@ class Spectra : public QtGui::ExtensionPlugin void setMolecule(QtGui::Molecule* mol) override; + bool handleCommand(const QString& command, + const QVariantMap& options) override; + public slots: void setMode(int mode); void setAmplitude(int amplitude); @@ -66,7 +69,7 @@ private slots: int m_mode; int m_amplitude; }; -} -} +} // namespace QtPlugins +} // namespace Avogadro #endif // AVOGADRO_QTPLUGINS_Spectra_H