diff --git a/core/include/Variable/Variable.h b/core/include/Variable/Variable.h index 117dd08..d766027 100644 --- a/core/include/Variable/Variable.h +++ b/core/include/Variable/Variable.h @@ -29,6 +29,7 @@ public: const QVariantHash &metadata = {}); QString name() const noexcept; + void setName(const QString &name) noexcept; SqpRange range() const noexcept; void setRange(const SqpRange &range) noexcept; SqpRange cacheRange() const noexcept; diff --git a/core/include/Variable/VariableModel.h b/core/include/Variable/VariableModel.h index 02c0ca6..f4d30fa 100644 --- a/core/include/Variable/VariableModel.h +++ b/core/include/Variable/VariableModel.h @@ -45,6 +45,7 @@ public: std::shared_ptr variable(int index) const; + std::vector > variables() const; void setDataProgress(std::shared_ptr variable, double progress); diff --git a/core/src/Variable/Variable.cpp b/core/src/Variable/Variable.cpp index 960b3bf..2d56bbb 100644 --- a/core/src/Variable/Variable.cpp +++ b/core/src/Variable/Variable.cpp @@ -75,6 +75,13 @@ QString Variable::name() const noexcept return name; } +void Variable::setName(const QString &name) noexcept +{ + impl->lockWrite(); + impl->m_Name = name; + impl->unlock(); +} + SqpRange Variable::range() const noexcept { impl->lockRead(); diff --git a/core/src/Variable/VariableModel.cpp b/core/src/Variable/VariableModel.cpp index 7e29f47..94f0a7f 100644 --- a/core/src/Variable/VariableModel.cpp +++ b/core/src/Variable/VariableModel.cpp @@ -114,6 +114,11 @@ std::shared_ptr VariableModel::variable(int index) const return (index >= 0 && index < impl->m_Variables.size()) ? impl->m_Variables[index] : nullptr; } +std::vector > VariableModel::variables() const +{ + return impl->m_Variables; +} + void VariableModel::setDataProgress(std::shared_ptr variable, double progress) { if (progress > 0.0) { diff --git a/gui/include/Variable/RenameVariableDialog.h b/gui/include/Variable/RenameVariableDialog.h new file mode 100644 index 0000000..e3f503c --- /dev/null +++ b/gui/include/Variable/RenameVariableDialog.h @@ -0,0 +1,31 @@ +#ifndef SCIQLOP_RENAMEVARIABLEDIALOG_H +#define SCIQLOP_RENAMEVARIABLEDIALOG_H + +#include + +namespace Ui { +class RenameVariableDialog; +} // Ui + +/** + * @brief The RenameVariableDialog class represents the dialog to rename a variable + */ +class RenameVariableDialog : public QDialog { +public: + explicit RenameVariableDialog(const QString &defaultName, + const QVector &forbiddenNames, + QWidget *parent = nullptr); + virtual ~RenameVariableDialog() noexcept; + + QString name() const noexcept; + +public slots: + void accept() override; + +private: + Ui::RenameVariableDialog *ui; + QString m_DefaultName; + QVector m_ForbiddenNames; +}; + +#endif // SCIQLOP_RENAMEVARIABLEDIALOG_H diff --git a/gui/src/Variable/RenameVariableDialog.cpp b/gui/src/Variable/RenameVariableDialog.cpp new file mode 100644 index 0000000..1af8af5 --- /dev/null +++ b/gui/src/Variable/RenameVariableDialog.cpp @@ -0,0 +1,63 @@ +#include "Variable/RenameVariableDialog.h" + +#include + +RenameVariableDialog::RenameVariableDialog(const QString &defaultName, + const QVector &forbiddenNames, QWidget *parent) + : QDialog{parent}, + ui{new Ui::RenameVariableDialog}, + m_DefaultName{defaultName}, + m_ForbiddenNames{forbiddenNames} +{ + ui->setupUi(this); + + connect(ui->nameLineEdit, &QLineEdit::textChanged, [this]() { ui->errorLabel->hide(); }); + + ui->nameLineEdit->setText(defaultName); + ui->nameLineEdit->selectAll(); + ui->nameLineEdit->setFocus(); +} + +RenameVariableDialog::~RenameVariableDialog() noexcept +{ + delete ui; +} + +QString RenameVariableDialog::name() const noexcept +{ + return ui->nameLineEdit->text(); +} + +void RenameVariableDialog::accept() +{ + auto invalidateInput = [this](const auto &error) { + ui->nameLineEdit->selectAll(); + ui->nameLineEdit->setFocus(); + ui->errorLabel->setText(error); + ui->errorLabel->show(); + }; + + // Empty name + auto name = ui->nameLineEdit->text(); + if (name.isEmpty()) { + invalidateInput(tr("A variable name must be specified")); + return; + } + + // Same name when opening dialog + if (name.compare(m_DefaultName, Qt::CaseInsensitive) == 0) { + reject(); + return; + } + + // Forbidden name + auto isForbidden + = [&name](const auto &it) { return name.compare(it, Qt::CaseInsensitive) == 0; }; + if (std::any_of(m_ForbiddenNames.cbegin(), m_ForbiddenNames.cend(), isForbidden)) { + invalidateInput(tr("'%1' is already used").arg(name)); + return; + } + + // Valid name + QDialog::accept(); +} diff --git a/gui/src/Variable/VariableInspectorWidget.cpp b/gui/src/Variable/VariableInspectorWidget.cpp index 3b9066c..53889b0 100644 --- a/gui/src/Variable/VariableInspectorWidget.cpp +++ b/gui/src/Variable/VariableInspectorWidget.cpp @@ -1,3 +1,5 @@ +#include +#include #include #include #include @@ -172,12 +174,33 @@ void VariableInspectorWidget::onTableMenuRequested(const QPoint &pos) noexcept // Adds menu-specific actions if (!selectedVariables.isEmpty()) { + tableMenu.addSeparator(); + + // 'Rename' action (only if one variable selected) + if (selectedVariables.size() == 1) { + auto selectedVariable = selectedVariables.front(); + + auto renameFun = [&selectedVariable, &model, this]() { + // Generates forbidden names (names associated to existing variables) + auto allVariables = model->variables(); + auto forbiddenNames = QVector(allVariables.size()); + std::transform(allVariables.cbegin(), allVariables.cend(), forbiddenNames.begin(), + [](const auto &variable) { return variable->name(); }); + + RenameVariableDialog dialog{selectedVariable->name(), forbiddenNames, this}; + if (dialog.exec() == QDialog::Accepted) { + selectedVariable->setName(dialog.name()); + } + }; + + tableMenu.addAction(tr("Rename..."), renameFun); + } + // 'Delete' action auto deleteFun = [&selectedVariables]() { sqpApp->variableController().deleteVariables(selectedVariables); }; - tableMenu.addSeparator(); tableMenu.addAction(QIcon{":/icones/delete.png"}, tr("Delete"), deleteFun); } diff --git a/gui/ui/Variable/RenameVariableDialog.ui b/gui/ui/Variable/RenameVariableDialog.ui new file mode 100644 index 0000000..987f5ba --- /dev/null +++ b/gui/ui/Variable/RenameVariableDialog.ui @@ -0,0 +1,90 @@ + + + RenameVariableDialog + + + + 0 + 0 + 379 + 109 + + + + Rename variable + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + Qt::Horizontal + + + QDialogButtonBox::Cancel|QDialogButtonBox::Ok + + + + + + + + + + color: rgb(255, 0, 0); + + + Error label + + + + + + + + + buttonBox + accepted() + RenameVariableDialog + accept() + + + 248 + 254 + + + 157 + 274 + + + + + buttonBox + rejected() + RenameVariableDialog + reject() + + + 316 + 260 + + + 286 + 274 + + + + +