diff --git a/src/lib/defaultvariablemodel.cpp b/src/lib/defaultvariablemodel.cpp index b5f4e164..15695387 100644 --- a/src/lib/defaultvariablemodel.cpp +++ b/src/lib/defaultvariablemodel.cpp @@ -1,338 +1,350 @@ /* This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. --- Copyright (C) 2010 Miha Čančula */ #include "defaultvariablemodel.h" #include #include #include "extension.h" #include "backend.h" namespace Cantor { class DefaultVariableModelPrivate { public: QList variables; QStringList functions; Session* session; VariableManagementExtension* extension; }; DefaultVariableModel::DefaultVariableModel(Session* session): QAbstractTableModel(session), d_ptr(new DefaultVariableModelPrivate) { Q_D(DefaultVariableModel); d->session = session; if (session) { d->extension = dynamic_cast(session->backend()->extension(QStringLiteral("VariableManagementExtension"))); } qDebug() << d->session << d->extension; } int DefaultVariableModel::columnCount(const QModelIndex& parent) const { Q_UNUSED(parent); return ColumnCount; } int DefaultVariableModel::rowCount(const QModelIndex& parent) const { if (parent.isValid()) { return 0; } else { Q_D(const DefaultVariableModel); return d->variables.size(); } } QVariant DefaultVariableModel::headerData(int section, Qt::Orientation orientation, int role) const { if(role==Qt::DisplayRole && orientation==Qt::Horizontal) { switch(section) { case NameColumn: return i18nc("@title:column", "Name"); case ValueColumn: return i18nc("@title:column", "Value"); break; } } return QVariant(); } Qt::ItemFlags DefaultVariableModel::flags(const QModelIndex& index) const { return QAbstractItemModel::flags(index) | Qt::ItemIsEditable; } QVariant DefaultVariableModel::data(const QModelIndex& index, int role) const { - if (role != Qt::DisplayRole || !index.isValid()) + if ((role != Qt::DisplayRole && role != DataRole) || !index.isValid()) { return QVariant(); } Q_D(const DefaultVariableModel); switch (index.column()) { case NameColumn: return QVariant(d->variables[index.row()].name); case ValueColumn: - return QVariant(d->variables[index.row()].value); + { + const QString& value = d->variables[index.row()].value; + if (value.size() < 1000 || role == DefaultVariableModel::DataRole) + return QVariant(value); + else + return QVariant(QString::fromLatin1("")); + } default: return QVariant(); } } bool DefaultVariableModel::setData(const QModelIndex& index, const QVariant& value, int role) { if(role!=Qt::EditRole || !value.isValid() || !index.isValid()) { return false; } Q_D(const DefaultVariableModel); if(index.column() == ValueColumn) { // Changing values QString name = data(index.sibling(index.row(), NameColumn)).toString(); d->session->evaluateExpression(d->extension->setValue(name, value.toString()), Expression::DeleteOnFinish); + emit dataChanged(index, index); return true; } else if(index.column() == NameColumn) { // Renaming => copy it, then delete the old one QString oldName = data(index).toString(); QString variableValue = data(index.sibling(index.row(), ValueColumn)).toString(); d->session->evaluateExpression(d->extension->addVariable(value.toString(), variableValue), Expression::DeleteOnFinish); d->session->evaluateExpression(d->extension->removeVariable(oldName), Expression::DeleteOnFinish); + emit dataChanged(index, index); return true; } return false; } void DefaultVariableModel::addVariable(const QString& name, const QString& value) { Variable v; v.name = name; v.value = value; addVariable(v); } void DefaultVariableModel::addVariable(const Cantor::DefaultVariableModel::Variable& variable) { Q_D(DefaultVariableModel); - if ( d->variables.contains(variable) ) + int index = d->variables.indexOf(variable); + if (index != -1) + { + d->variables[index].value = variable.value; + QModelIndex modelIdx = createIndex(index, ValueColumn); + emit dataChanged(modelIdx, modelIdx); + } + else { - // TODO: Why we remove variable here? Set value properly - removeVariable(variable); + beginInsertRows(QModelIndex(), d->variables.size(), d->variables.size()); + d->variables.append(variable); + emit variablesAdded(QStringList(variable.name)); + endInsertRows(); } - beginInsertRows(QModelIndex(), d->variables.size(), d->variables.size()); - d->variables.append(variable); - emit variablesAdded(QStringList(variable.name)); - endInsertRows(); } void DefaultVariableModel::removeVariable(const QString& name) { Variable v; v.name = name; removeVariable(v); } void DefaultVariableModel::removeVariable(const Cantor::DefaultVariableModel::Variable& variable) { Q_D(DefaultVariableModel); int row = d->variables.indexOf(variable); if(row==-1) return; const QString& name = variable.name; beginRemoveRows(QModelIndex(), row, row); d->variables.removeAt(row); endRemoveRows(); emit variablesRemoved(QStringList(name)); } void DefaultVariableModel::clearVariables() { Q_D(DefaultVariableModel); beginResetModel(); QStringList names; for (const Variable var: d->variables) names.append(var.name); d->variables.clear(); endResetModel(); emit variablesRemoved(names); } void DefaultVariableModel::clearFunctions() { Q_D(DefaultVariableModel); QStringList names = d->functions; d->functions.clear(); emit functionsRemoved(names); } void DefaultVariableModel::setVariables(const QList& newVars) { Q_D(DefaultVariableModel); QStringList addedVars; QStringList removedVars; // Handle deleted vars int i = 0; while (i < d->variables.size()) { Variable var = d->variables[i]; bool found = false; for (const Variable& newvar : newVars) if(var.name == newvar.name) { found=true; break; } if (!found) { removedVars << var.name; beginRemoveRows(QModelIndex(), i, i); d->variables.removeAt(i); endRemoveRows(); } else i++; } // Handle added vars const int size = d->variables.size(); for (const Variable newvar : newVars) { bool found = false; for (int i = 0; i < size; i++) if(d->variables[i].name == newvar.name) { found=true; if (d->variables[i].value != newvar.value) { QModelIndex index = createIndex(i, ValueColumn); - QAbstractItemModel::setData(index, newvar.value); d->variables[i].value = newvar.value; emit dataChanged(index, index); } break; } if (!found) { addedVars << newvar.name; beginInsertRows(QModelIndex(), d->variables.size(), d->variables.size()); d->variables.append(newvar); endInsertRows(); } } emit variablesAdded(addedVars); emit variablesRemoved(removedVars); } void DefaultVariableModel::setFunctions(const QStringList& newFuncs) { Q_D(DefaultVariableModel); QStringList addedFuncs; QStringList removedFuncs; //remove the old variables int i = 0; while (i < d->functions.size()) { //check if this var is present in the new variables bool found=false; for (const QString& func : newFuncs) if(d->functions[i] == func) { found=true; break; } if(!found) { removedFuncs<functions[i]; d->functions.removeAt(i); } else i++; } for (const QString& func : newFuncs) { if (!d->functions.contains(func)) { addedFuncs<functions.append(func); } } emit functionsAdded(addedFuncs); emit functionsRemoved(removedFuncs); } Session* DefaultVariableModel::session() const { Q_D(const DefaultVariableModel); return d->session; } QList DefaultVariableModel::variables() const { Q_D(const DefaultVariableModel); return d->variables; } QStringList DefaultVariableModel::variableNames() const { Q_D(const DefaultVariableModel); QStringList names; for (const Variable var: d->variables) names << var.name; return names; } QStringList DefaultVariableModel::functions() const { Q_D(const DefaultVariableModel); return d->functions; } bool operator==(const Cantor::DefaultVariableModel::Variable& one, const Cantor::DefaultVariableModel::Variable& other) { return one.name == other.name; } } diff --git a/src/lib/defaultvariablemodel.h b/src/lib/defaultvariablemodel.h index fe86a496..614a856b 100644 --- a/src/lib/defaultvariablemodel.h +++ b/src/lib/defaultvariablemodel.h @@ -1,195 +1,197 @@ /* This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. --- Copyright (C) 2010 Miha Čančula */ #ifndef CANTOR_DEFAULTVARIABLEMODEL_H #define CANTOR_DEFAULTVARIABLEMODEL_H #include #include "session.h" #include "expression.h" namespace Cantor { class DefaultVariableModelPrivate; /** * @brief * This DefaultVariableModel class is an implementation of QAbstractItemModel * that can be used with the Variable Manager plugin. * * For most uses the addVariable(), removeVariable() and clearVariables() methods are sufficient. * They can be used from session (directly or by connecting signals to them), or called from * a subclass. * * DefaultVariableModel uses the session to run expressions for changing variables, and it * gets the commands from the backend's VariableManagementExtension. * If you do not want this behavior, you can subclass it and reimplement data() and/or setData(). * * @see Session::variableModel() */ class CANTOR_EXPORT DefaultVariableModel : public QAbstractTableModel { Q_OBJECT Q_PROPERTY(Session* session READ session) public: + enum {DataRole = Qt::UserRole + 1}; + /** * A structure representing a variable. */ struct Variable { /** * The variable's name */ QString name; /** * The variable's value, represented as a string */ QString value; }; /** * Default constructor * If you are constructing a DefaultVariableModel without subclassing, the @p session must be valid * and its backends must support a VariableManagementExtension. * * This requirement can be avoided by reimplementing setData() in a subclass. * * @param session the session this Model belongs to, also becomes the Model's parent. */ explicit DefaultVariableModel(Session* session); ~DefaultVariableModel() override = default; /** * Get the session which created this Model and whose variables it contains * @return the session */ Session* session() const; /** * Returns variables, stored in this model, as @see Variable. */ QList variables() const; /** * Returns names of stored variables */ QStringList variableNames() const; /** * Return functions, stored in this model */ QStringList functions() const; //TODO: improve the description? /** * Starts updating variable model (variable lists, etc.). Usually executed after finished all user's commands */ virtual void update() {}; public Q_SLOTS: /** * Adds a variable to the model. * If a variable with the same name already exists, it will be overwritten. * @param name the name of the variable * @param value the value of the variable */ void addVariable(const QString& name, const QString& value); /** * Convenience method, equivalent to addVariable(variable.name, variable.value) * @param variable the variable to add */ void addVariable(const Cantor::DefaultVariableModel::Variable& variable); /** * Remove the variable @p name from the model. * If a variable with the specified @p name doesn't exists, this method does nothing. * @param name the name of the variable to remove */ void removeVariable(const QString& name); /** * Convenience method, equivalent to removeVariable(variable.name) * @param variable the variable to remove */ void removeVariable(const Cantor::DefaultVariableModel::Variable& variable); /** * Clears all variables from the model */ void clearVariables(); /** * Clears all functions */ void clearFunctions(); Q_SIGNALS: /** * Emitted after adding new variables * @param variables list of new variables */ void variablesAdded(const QStringList& variables); /** * Emitted after variables removing * @param variables list of removed variables */ void variablesRemoved(const QStringList& variables); /** * Similar to @c variablesAdded */ void functionsAdded(const QStringList& names); /** * Similar to @c variablesRemoved */ void functionsRemoved(const QStringList funcs); protected: QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const override; bool setData(const QModelIndex& index, const QVariant& value, int role = Qt::EditRole) override; int columnCount(const QModelIndex& parent = QModelIndex()) const override; int rowCount(const QModelIndex& parent = QModelIndex()) const override; QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override; Qt::ItemFlags flags(const QModelIndex& index) const override; void setVariables(const QList& newVars); void setFunctions(const QStringList& newFuns); enum Column { NameColumn = 0, ValueColumn = 1, ColumnCount = 2 }; private: DefaultVariableModelPrivate* const d_ptr; Q_DECLARE_PRIVATE(DefaultVariableModel) }; bool operator==(const Cantor::DefaultVariableModel::Variable& one, const Cantor::DefaultVariableModel::Variable& other); } #endif // CANTOR_DEFAULTVARIABLEMODEL_H