Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
62 changes: 39 additions & 23 deletions src/gui/models/speciesModel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,21 +7,20 @@
#include "speciesAtomModel.h"
#include <memory>

SpeciesModel::SpeciesModel()
SpeciesModel::SpeciesModel() : node_(nullptr) {}

QString SpeciesModel::name()
{
species_ = std::make_unique<Species>();
atoms_.setSpecies(species_.get());
bonds_.setBonds(species_->bonds());
angles_.setAngles(species_->angles());
torsions_.setTorsions(species_->torsions());
impropers_.setImpropers(species_->impropers());
if (node_ == nullptr)
return "";
return QString::fromStdString(std::string(node_->species().name()));
}

QString SpeciesModel::name() { return QString::fromStdString(std::string(species_->name())); }

void SpeciesModel::setName(QString name)
{
species_->setName(name.toStdString());
if (node_ == nullptr)
return;
node_->species().setName(name.toStdString());
Q_EMIT(nameChanged());
}

Expand All @@ -40,40 +39,57 @@ SpeciesImproperModel *SpeciesModel::impropers() { return &impropers_; }
// Atom information
SpeciesAtomModel *SpeciesModel::atoms() { return &atoms_; }

GraphModel *SpeciesModel::graphModel() { return graphModel_; }

// Produce this species node on the given graph
void SpeciesModel::create(QVariant graphModel)
void SpeciesModel::assignModel(GraphModel *graphModel)
{
graphModel_ = graphModel;
node_ = std::make_unique<SpeciesNode>(graphModel_->graph());
auto &species = node_->species();
atoms_.setSpecies(&species);
bonds_.setBonds(species.bonds());
angles_.setAngles(species.angles());
torsions_.setTorsions(species.torsions());
impropers_.setImpropers(species.impropers());
}

// Finalise the node
void SpeciesModel::create()
{
auto model = graphModel.value<GraphModel *>();
model->addNode(std::move(std::make_unique<SpeciesNode>(model->graph(), std::move(species_))), species_->name());
// Need copy because we're going to move the unique_ptr
auto name = node_->species().name();
// node_->setName(name);
graphModel_->addNode(std::unique_ptr<Node>(std::move(node_)), name);

// Create a new species for the next call
species_ = std::make_unique<Species>();
// Create a new node for next call
node_ = std::make_unique<SpeciesNode>(graphModel_->graph());
}

void SpeciesModel::addBond(int i, int j)
{
bonds_.beginInsertRows({}, species_->nBonds(), species_->nBonds() + 1);
species_->addBond(i - 1, j - 1);
bonds_.beginInsertRows({}, node_->species().nBonds(), node_->species().nBonds() + 1);
node_->species().addBond(i - 1, j - 1);
bonds_.endInsertRows();
}

void SpeciesModel::addAngle(int i, int j, int k)
{
angles_.beginInsertRows({}, species_->nAngles(), species_->nAngles() + 1);
species_->addAngle(i - 1, j - 1, k - 1);
angles_.beginInsertRows({}, node_->species().nAngles(), node_->species().nAngles() + 1);
node_->species().addAngle(i - 1, j - 1, k - 1);
angles_.endInsertRows();
}

void SpeciesModel::addTorsion(int i, int j, int k, int l)
{
torsions_.beginInsertRows({}, species_->nTorsions(), species_->nTorsions() + 1);
species_->addTorsion(i - 1, j - 1, k - 1, l - 1);
torsions_.beginInsertRows({}, node_->species().nTorsions(), node_->species().nTorsions() + 1);
node_->species().addTorsion(i - 1, j - 1, k - 1, l - 1);
torsions_.endInsertRows();
}

void SpeciesModel::addImproper(int i, int j, int k, int l)
{
impropers_.beginInsertRows({}, species_->nImpropers(), species_->nImpropers() + 1);
species_->addImproper(i - 1, j - 1, k - 1, l - 1);
impropers_.beginInsertRows({}, node_->species().nImpropers(), node_->species().nImpropers() + 1);
node_->species().addImproper(i - 1, j - 1, k - 1, l - 1);
impropers_.endInsertRows();
}
14 changes: 10 additions & 4 deletions src/gui/models/speciesModel.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

#pragma once

#include "classes/species.h"
#include "gui/models/nodeGraph/graphModel.h"
#include "gui/models/speciesAngleModel.h"
#include "gui/models/speciesAtomModel.h"
#include "gui/models/speciesBondModel.h"
Expand All @@ -26,10 +26,13 @@ class SpeciesModel : public QObject
Q_PROPERTY(SpeciesTorsionModel *torsions READ torsions NOTIFY speciesChanged)
Q_PROPERTY(SpeciesImproperModel *impropers READ impropers NOTIFY speciesChanged)
Q_PROPERTY(QString name READ name WRITE setName NOTIFY nameChanged)
Q_PROPERTY(GraphModel *graphModel READ graphModel WRITE assignModel NOTIFY speciesChanged);

private:
// Source Species data
std::unique_ptr<Species> species_;
std::unique_ptr<SpeciesNode> node_;
// Parent Graph
GraphModel *graphModel_;
// Atom Model
SpeciesAtomModel atoms_;
// Bond Model
Expand Down Expand Up @@ -74,6 +77,9 @@ class SpeciesModel : public QObject
void setCheckStateData(std::vector<const Species *> &checkedItemsVector);
// Refresh model data
void reset();
GraphModel *graphModel();
// Set the graph onto which the species will be created
void assignModel(GraphModel *graphModel);

Q_SIGNALS:
// We've changed the underlying species
Expand All @@ -82,8 +88,8 @@ class SpeciesModel : public QObject
void nameChanged();

public Q_SLOTS:
// Produce this species node on the given graph
void create(QVariant graphModel);
// Finalise the node
void create();
void addBond(int i, int j);
void addAngle(int i, int j, int k);
void addTorsion(int i, int j, int k, int l);
Expand Down
1 change: 0 additions & 1 deletion src/nodes/configuration.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
// Copyright (c) 2025 Team Dissolve and contributors

#include "nodes/configuration.h"
#include "nodes/dissolve.h"

ConfigurationNode::ConfigurationNode(Graph *parentGraph) : Node(parentGraph)
{
Expand Down
4 changes: 2 additions & 2 deletions src/nodes/edge.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@

#include "nodes/edge.h"
#include "nodes/graph.h"
#include "nodes/outputs.h"
#include "nodes/loopBack.h"
#include "nodes/outputs.h"

Edge::Edge(Node &sourceNode, ParameterBase &sourceOutput, Node &targetNode, ParameterBase &targetInput)
: sourceNode_(sourceNode), sourceOutput_(sourceOutput), targetNode_(targetNode), targetInput_(targetInput)
Expand Down Expand Up @@ -108,7 +108,7 @@ std::unique_ptr<Edge> Edge::create(Graph *parent, const EdgeDefinition &definiti
if (!targetInput->flags().isSet(ParameterBase::ParameterFlags::Input) && !dynamic_cast<LoopBacksNode *>(targetNode))
{
Messenger::error("Target node '{}' has parameter '{}' but it is not an input.\n", definition.targetNode,
definition.targetInput);
definition.targetInput);
return {};
}

Expand Down
20 changes: 4 additions & 16 deletions src/nodes/graph.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,7 @@ Node *Graph::createNode(std::string_view nodeType, std::string_view nodeName)
// Add node to graph
Node *Graph::addNode(std::unique_ptr<Node> node, std::string_view newName)
{
node->setParent(this);
auto nodePtr = node.get();

auto uniqueName = uniqueNodeName(node.get(), newName.empty() ? node->type() : newName);
Expand Down Expand Up @@ -271,22 +272,9 @@ void Graph::deserialise(const SerialisedValue &node)
[this](const auto name, const auto &value)
{
std::string nodeType = toml::find<std::string>(value, "type");
if (nodeType == "Species")
{
// Species cannot be default constructed and requires species handling.
auto species = std::make_shared<Species>();
CoreData coreData;
species->deserialise(value.at("options").at("Species").at("data"), coreData);
species->setName(name);
std::unique_ptr<Node> spNode = std::make_unique<SpeciesNode>(this, std::move(species));
addNode(std::move(spNode), name);
}
else
{
auto child = createNode(nodeType, name);

child->deserialise(value);
}
auto child = createNode(nodeType, name);

child->deserialise(value);
});
toVector(node, "edges", [this](const auto &value) { addEdge(toml::get<EdgeDefinition>(value)); });
}
6 changes: 3 additions & 3 deletions src/nodes/loopBack.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -64,11 +64,11 @@ void LoopBacksNode::setUpdateRequired()
* Serialisation
*/

// Is it appropriate to bother serialising this node?
// Is it appropriate to bother serialising this node?
bool LoopBacksNode::shouldSerialise() const { return false; }

// Express as a serialisable value
void LoopBacksNode::serialise(std::string tag, SerialisedValue& target) const {}
void LoopBacksNode::serialise(std::string tag, SerialisedValue &target) const {}

// Read values from a serialisable value
void LoopBacksNode::deserialise(const SerialisedValue& node) {};
void LoopBacksNode::deserialise(const SerialisedValue &node) {};
4 changes: 2 additions & 2 deletions src/nodes/loopBack.h
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ class LoopBacksNode : public Node
// Is it appropriate to bother serialising this node?
bool shouldSerialise() const override;
// Express as a serialisable value
void serialise(std::string tag, SerialisedValue& target) const override;
void serialise(std::string tag, SerialisedValue &target) const override;
// Read values from a serialisable value
void deserialise(const SerialisedValue& node) override;
void deserialise(const SerialisedValue &node) override;
};
7 changes: 7 additions & 0 deletions src/nodes/node.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -299,6 +299,10 @@ void Node::markIncomingEdgesForPull(const ParameterBase *toParameter) const
// Returns the node parent graph
Graph *Node::parentGraph() const { return parentGraph_; }

// Update the parent graph after a move
// This is private so that only designated friend classes can do this.
void Node::setParent(Graph *graph) { parentGraph_ = graph; }

// Return the Dissolve reference
Dissolve &Node::dissolve() const { return parentGraph_->dissolve(); }

Expand Down Expand Up @@ -330,6 +334,8 @@ void Node::serialise(std::string tag, SerialisedValue &target) const

fromMap(options_, "options", result);

serialiseInternal(result);

target[tag] = result;
}

Expand All @@ -354,6 +360,7 @@ void Node::deserialise(const SerialisedValue &node)
else
Messenger::exception("Node {} does not contain an option {}", name(), k);
});
deserialiseInternal(node);
}

// Express persistent data as a serialisable value
Expand Down
6 changes: 6 additions & 0 deletions src/nodes/node.h
Original file line number Diff line number Diff line change
Expand Up @@ -312,8 +312,14 @@ class Node : public Serialisable<>
protected:
// Persistent data serialisables
std::map<std::string, std::shared_ptr<SerialisableData>> serialisables_;
// Serialise any hidden content
virtual void serialiseInternal(SerialisedValue &target) const {}
// Deserialise any hidden content
virtual void deserialiseInternal(const SerialisedValue &node) {}

public:
// Update the parent graph after a move
void setParent(Graph *graph);
// Is it appropriate to bother serialising this node?
virtual bool shouldSerialise() const { return true; }
// Flag a persistent serialisable quantity
Expand Down
1 change: 1 addition & 0 deletions src/nodes/registry.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ void NodeRegistry::instantiateNodeProducers()
{"NeutronSQ", makeDerivedNode<NeutronSQNode>()},
{"Number", makeDerivedNode<NumberNode>()},
{"SQ", makeDerivedNode<SQNode>()},
{"Species", makeDerivedNode<SpeciesNode>()},
{"Subtract", makeDerivedNode<SubtractNode>()},
{"Vec3Assembly", makeDerivedNode<Vec3AssemblyNode>()},
{"Vec3Decomposition", makeDerivedNode<Vec3DecompositionNode>()},
Expand Down
20 changes: 15 additions & 5 deletions src/nodes/species.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,19 +3,29 @@

#include "species.h"
#include "nodes/constants.h"
#include <memory>
#include <toml11/toml.hpp>
#include <toml11/toml/parser.hpp>

SpeciesNode::SpeciesNode(Graph *parentGraph, std::shared_ptr<Species> &&species)
: Node(parentGraph), species_(std::move(species))
SpeciesNode::SpeciesNode(Graph *parentGraph) : Node(parentGraph)
{
addOption<std::shared_ptr<Species>>("Species", "Created Species", species_);
addPointerOutput<const Species>("Species", "Created species", *species_);
addPointerOutput<const Species>("Species", "Created species", species_);
}

std::string_view SpeciesNode::type() const { return "Species"; }

std::string_view SpeciesNode::summary() const { return "Produce a species"; }

NodeConstants::ProcessResult SpeciesNode::process() { return NodeConstants::ProcessResult::Unchanged; }

Species &SpeciesNode::species() { return species_; }
const Species &SpeciesNode::species() const { return species_; }

// Serialise any hidden content
void SpeciesNode::serialiseInternal(SerialisedValue &target) const { species_.serialise("species", target); }

// Deserialise any hidden content
void SpeciesNode::deserialiseInternal(const SerialisedValue &node)
{
CoreData coreData;
species_.deserialise(node.at("species"), coreData);
}
17 changes: 15 additions & 2 deletions src/nodes/species.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
class SpeciesNode : public Node
{
public:
SpeciesNode(Graph *parentGraph, std::shared_ptr<Species> &&species);
SpeciesNode(Graph *parentGraph);
~SpeciesNode() override = default;

/*
Expand All @@ -25,14 +25,27 @@ class SpeciesNode : public Node
*/
private:
// Species object
std::shared_ptr<Species> species_;
Species species_;
// Atom Types owned by the node
std::vector<std::shared_ptr<AtomType>> atomTypes_;

/*
* Accessors
*/
public:
// Access the species information (Needed for SpeciesModel)
Species &species();
const Species &species() const;

/*
* Processing
*/
private:
// Run main processing
NodeConstants::ProcessResult process() override;

// Serialise any hidden content
void serialiseInternal(SerialisedValue &target) const override;
// Deserialise any hidden content
void deserialiseInternal(const SerialisedValue &target) override;
};
12 changes: 7 additions & 5 deletions tests/gui/speciesModel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,13 @@ TEST(SpeciesModel, Basic)
{

// Stage 1: Simulate GUI interactions to create species
Graph graph(nullptr);
GraphModel graphModel;
graphModel.setGraph(&graph);

SpeciesModel model;
model.assignModel(&graphModel);

model.setName("Water");
model.atoms()->addAtom("O", 0.156743, -0.152502, 0.317676, -0.82);
model.atoms()->addAtom("H", -0.257130, 0.637822, 0.198948, 0.41);
Expand All @@ -34,11 +40,7 @@ TEST(SpeciesModel, Basic)
EXPECT_TRUE(angles->setData(angles->index(0, SpeciesAngleModel::DataType::Form), "Harmonic"));
EXPECT_TRUE(angles->setData(angles->index(0, SpeciesAngleModel::DataType::Parameters), "k=317.5656 eq=113.24"));

// Stage 2: Extract species from node
Graph graph(nullptr);
GraphModel graphModel;
graphModel.setGraph(&graph);
model.create(QVariant::fromValue(&graphModel));
model.create();

ASSERT_EQ(graph.nodes().size(), 3);

Expand Down