diff --git a/src/gui/configurationTab.h b/src/gui/configurationTab.h index c989546017..d67c22b307 100644 --- a/src/gui/configurationTab.h +++ b/src/gui/configurationTab.h @@ -84,9 +84,7 @@ class ConfigurationTab : public QWidget, public MainTab * Signals / Slots */ private slots: - // Generate void on_GenerateButton_clicked(bool checked); - // Density units changed void on_DensityUnitsCombo_currentIndexChanged(int index); - void buttonGroupToggled(QAbstractButton *button, bool checked); + void on_ConfigurationButtonGroup_buttonToggled(QAbstractButton *button, bool checked); }; diff --git a/src/gui/configurationTabFuncs.cpp b/src/gui/configurationTabFuncs.cpp index c6f0ae82db..36d127d602 100644 --- a/src/gui/configurationTabFuncs.cpp +++ b/src/gui/configurationTabFuncs.cpp @@ -55,8 +55,6 @@ ConfigurationTab::ConfigurationTab(DissolveWindow *dissolveWindow, Dissolve &dis ui_.GlobalPotentialsFrame->setHidden(true); ui_.TargetedPotentialsFrame->setHidden(true); - connect(ui_.ConfigurationButtonGroup, SIGNAL(buttonToggled(QAbstractButton *, bool)), this, - SLOT(buttonGroupToggled(QAbstractButton *, bool))); } /* @@ -212,11 +210,9 @@ void ConfigurationTab::on_GenerateButton_clicked(bool checked) dissolveWindow_->updateStatusBar(); } -// Density units changed void ConfigurationTab::on_DensityUnitsCombo_currentIndexChanged(int index) { updateDensityLabel(); } -// Button group toggled -void ConfigurationTab::buttonGroupToggled(QAbstractButton *button, bool checked) +void ConfigurationTab::on_ConfigurationButtonGroup_buttonToggled(QAbstractButton *button, bool checked) { if (button == ui_.GeneratorPushButton) { diff --git a/src/gui/models/procedureModel.cpp b/src/gui/models/procedureModel.cpp index 8d63313f01..fe5007e862 100644 --- a/src/gui/models/procedureModel.cpp +++ b/src/gui/models/procedureModel.cpp @@ -11,11 +11,34 @@ ProcedureModel::ProcedureModel(OptionalReferenceWrapper procedure) : procedure_(procedure) {} +void printSequence(const ProcedureNodeSequence &sequence, std::string indent) +{ + fmt::print("{}SEQ {}\n", indent, fmt::ptr(&sequence)); + auto nodeIndent = fmt::format("{} ", indent); + for (auto &node : sequence.sequence()) + { + fmt::print("{} N {}\n", nodeIndent, fmt::ptr(&node)); + fmt::print("{} = {}\n", nodeIndent, node->name()); + if (node->branch()) + printSequence(node->branch()->get(), fmt::format("{} ", indent)); + } +} +void printProcedure(Procedure &proc) +{ + fmt::print("Procedure:\n"); + printSequence(proc.rootSequence(), ""); +} +std::string modelIndexString(const QModelIndex &index) +{ + return index.isValid() ? fmt::format("({},{})", index.row(), index.column()) : "INVALID"; +} + // Set source Procedure void ProcedureModel::setData(Procedure &procedure) { beginResetModel(); procedure_ = procedure; + printProcedure(procedure); endResetModel(); } @@ -58,7 +81,10 @@ int ProcedureModel::rowCount(const QModelIndex &parent) const // If the index doesn't have a valid internal pointer we're probing the root of the model, so return the number of root // sequence nodes if (!parent.internalPointer()) + { + fmt::print("RowCount for parent {} = {} (no valid internalPointer())\n", modelIndexString(parent), procedure_->get().rootSequence().nNodes()); return procedure_->get().rootSequence().nNodes(); + } auto node = static_cast(parent.internalPointer()); if (node && node->branch()) @@ -383,6 +409,9 @@ bool ProcedureModel::dropMimeData(const QMimeData *data, Qt::DropAction action, auto oldParent = parent(oldIndex); auto &oldScope = oldNode->scope()->get(); + fmt::print("dropMimeData::MoveAction old model index is {}\n", modelIndexString(oldIndex)); + fmt::print("dropMimeData::MoveAction old model sequence is {}\n", fmt::ptr(&oldScope)); + // Get the new parent scope auto optNewScope = getScope(newParent); if (!optNewScope) @@ -392,6 +421,10 @@ bool ProcedureModel::dropMimeData(const QMimeData *data, Qt::DropAction action, // Determine the new index of the dragged node in the root sequence or scope auto insertAtRow = row == -1 ? newScope.nNodes() : row; + fmt::print("dropMimeData::MoveAction new parent model index is {}\n", modelIndexString(newParent)); + fmt::print("dropMimeData::MoveAction new model sequence is {}\n", fmt::ptr(&newScope)); + fmt::print("dropMimeData::MoveAction new model row insertion index is {}\n", insertAtRow); + // Create a new row to store the data. insertRows(insertAtRow, 1, newParent); @@ -406,14 +439,8 @@ bool ProcedureModel::dropMimeData(const QMimeData *data, Qt::DropAction action, newScope.sequence()[insertAtRow] = std::move(oldScope.sequence()[oldNodeRow]); oldNode->setScope(newScope); - // Remove the old row - beginRemoveRows(oldParent, oldNodeRow, oldNodeRow); - oldScope.sequence().erase(oldScope.sequence().begin() + oldNodeRow); - endRemoveRows(); - - // Set the new data - we call this just to emit dataChanged() from the correct place. - auto idx = index(insertAtRow, 0, newParent); - return setData(idx, QVariant::fromValue(mimeData->node()), ProcedureModelAction::MoveInternal); + //printProcedure(procedure_->get()); + return true; } else if (action == Qt::CopyAction && data->hasFormat("application/dissolve.procedure.newNode")) { @@ -467,12 +494,47 @@ bool ProcedureModel::removeRows(int row, int count, const QModelIndex &parent) // Get the scope associated to the parent index auto scope = getScope(parent); - - beginRemoveRows(parent, row, row + count - 1); - for (auto i = 0; i < count; ++i) - scope->get().removeNode(data(index(row + i, 0), Qt::UserRole).value>()); + beginRemoveRows(parent, row, row); + if (count > 1) + scope->get().sequence().erase(scope->get().sequence().begin() + row, scope->get().sequence().begin() + row + count - 1); + else + scope->get().sequence().erase(scope->get().sequence().begin() + row); endRemoveRows(); - emit(dataChanged(QModelIndex(), QModelIndex())); return true; } + +QModelIndex ProcedureModel::appendNew(const QString &nodeTypeString) +{ + // Check the node type string is valid + if (!ProcedureNode::nodeTypes().isValid(nodeTypeString.toStdString())) + return {}; + + // Convert the node type string to its enumeration + auto nodeType = ProcedureNode::nodeTypes().enumeration(nodeTypeString.toStdString()); + // Create a node of the node type + auto node = ProcedureNodeRegistry::create(nodeType); + assert(node); + + // Get the parent scope, we know this is the root sequence, but use getScope for consistency + auto scope = getScope(QModelIndex()); + + // Check if the node is relevant to the context of the scope + if (!node->isContextRelevant(scope->get().context())) + return {}; + + // Get the target row for the new node + auto insertAtRow = rowCount(); + + // Create a new row to store the data. Don't use insertRows() here since creating a null node in the vector at this + // point causes no end of issues. + beginInsertRows(QModelIndex(), insertAtRow, insertAtRow); + scope->get().appendNode(node, insertAtRow); + endInsertRows(); + auto idx = index(insertAtRow, 0, QModelIndex()); + + // Call setData() so we emit the right signals + setData(idx, QVariant::fromValue(node), ProcedureModelAction::CreateNew); + + return idx; +} diff --git a/src/gui/models/procedureModel.h b/src/gui/models/procedureModel.h index 181cf6ca83..e49ccb6f04 100644 --- a/src/gui/models/procedureModel.h +++ b/src/gui/models/procedureModel.h @@ -59,6 +59,7 @@ class ProcedureModel : public QAbstractItemModel bool dropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex &newParent) override; bool insertRows(int row, int count, const QModelIndex &parent) override; bool removeRows(int row, int count, const QModelIndex &parent = QModelIndex()) override; + QModelIndex appendNew(const QString &nodeTypeString); signals: void nodeNameChanged(const QModelIndex &, const QString &oldName, const QString &newName); diff --git a/src/gui/procedureWidgetFuncs.cpp b/src/gui/procedureWidgetFuncs.cpp index 3d3e14e375..9d9160355c 100644 --- a/src/gui/procedureWidgetFuncs.cpp +++ b/src/gui/procedureWidgetFuncs.cpp @@ -192,7 +192,7 @@ void ProcedureWidget::on_NodesTree_customContextMenuRequested(const QPoint &pos) void ProcedureWidget::on_AvailableNodesTree_doubleClicked(const QModelIndex &index) { - // nodeLayerModel_.appendNew(nodePaletteModel_.data(index, Qt::DisplayRole).toString()); + procedureModel_.appendNew(nodePaletteFilterProxy_.data(index, Qt::DisplayRole).toString()); } // Delete the currently selected node, and its children diff --git a/src/procedure/nodes/sequence.cpp b/src/procedure/nodes/sequence.cpp index ef9bafc49f..8151b437a3 100644 --- a/src/procedure/nodes/sequence.cpp +++ b/src/procedure/nodes/sequence.cpp @@ -78,19 +78,6 @@ int ProcedureNodeSequence::nNodes() const { return sequence_.size(); } // Return whether the sequence is empty bool ProcedureNodeSequence::empty() const { return sequence_.empty(); } -// Remove a node -bool ProcedureNodeSequence::removeNode(NodeRef node) -{ - // Find the node in the sequence - auto it = std::find_if(sequence_.begin(), sequence_.end(), [node](const auto &n) { return n.get() == node.get(); }); - if (it != sequence_.end()) - { - sequence_.erase(it); - return true; - } - return false; -} - /* * Scope */ diff --git a/src/procedure/nodes/sequence.h b/src/procedure/nodes/sequence.h index 5dc85aeb18..9306fea1ab 100644 --- a/src/procedure/nodes/sequence.h +++ b/src/procedure/nodes/sequence.h @@ -63,8 +63,6 @@ class ProcedureNodeSequence : public Serialisable int nNodes() const; // Return whether the sequence is empty bool empty() const; - // Remove a node - bool removeNode(NodeRef node); /* * Scope diff --git a/src/procedure/procedure.cpp b/src/procedure/procedure.cpp index fcb3b08dea..0736a6dfd4 100644 --- a/src/procedure/procedure.cpp +++ b/src/procedure/procedure.cpp @@ -42,9 +42,6 @@ std::vector Procedure::nodes(std::optional std::vector nodes(std::optional optNodeType = std::nullopt, std::optional optNodeClass = std::nullopt) const; - // Remove a node - bool removeNode(NodeRef node); - /* * Execute */