Warning, file /education/cantor/src/lib/defaultvariablemodel.cpp was not indexed or was modified since last indexation (in which case cross-reference links may be missing, inaccurate or erroneous).

0001 /*
0002     SPDX-License-Identifier: GPL-2.0-or-later
0003     SPDX-FileCopyrightText: 2010 Miha Čančula <miha.cancula@gmail.com>
0004     SPDX-FileCopyrightText: 2018-2022 Alexander Semke <alexander.semke@web.de>
0005 */
0006 
0007 #include "defaultvariablemodel.h"
0008 #include "extension.h"
0009 #include "backend.h"
0010 
0011 #include <KLocalizedString>
0012 
0013 namespace Cantor
0014 {
0015 
0016 class DefaultVariableModelPrivate
0017 {
0018 public:
0019     QList<DefaultVariableModel::Variable> variables;
0020     QStringList functions;
0021     Session* session = nullptr;
0022     VariableManagementExtension* extension = nullptr;
0023 };
0024 
0025 DefaultVariableModel::DefaultVariableModel(Session* session): QAbstractTableModel(session),
0026 d_ptr(new DefaultVariableModelPrivate)
0027 {
0028     Q_D(DefaultVariableModel);
0029     d->session = session;
0030     if (session)
0031         d->extension = dynamic_cast<Cantor::VariableManagementExtension*>(session->backend()->extension(QStringLiteral("VariableManagementExtension")));
0032 }
0033 
0034 DefaultVariableModel::~DefaultVariableModel()
0035 {
0036     Q_D(DefaultVariableModel);
0037     delete d;
0038 }
0039 
0040 int DefaultVariableModel::columnCount(const QModelIndex& parent) const
0041 {
0042     Q_UNUSED(parent);
0043     Q_D(const DefaultVariableModel);
0044     const auto& capabilities = d->session->backend()->capabilities();
0045     if (capabilities.testFlag(Cantor::Backend::VariableDimension))
0046         return ColumnCount;
0047     else
0048         return ColumnCount - 1;
0049 }
0050 
0051 int DefaultVariableModel::rowCount(const QModelIndex& parent) const
0052 {
0053     if (parent.isValid())
0054     {
0055         return 0;
0056     }
0057     else
0058     {
0059         Q_D(const DefaultVariableModel);
0060         return d->variables.size();
0061     }
0062 }
0063 
0064 QVariant DefaultVariableModel::headerData(int section, Qt::Orientation orientation, int role) const
0065 {
0066     if(role==Qt::DisplayRole && orientation==Qt::Horizontal) {
0067         switch(section) {
0068             case NameColumn:
0069                 return i18nc("@title:column", "Name");
0070             case TypeColumn:
0071                 return i18nc("@title:column", "Type");
0072             case SizeColumn:
0073                 return i18nc("@title:column", "Size [Bytes]");
0074             case DimensionColumn:
0075                 return i18nc("@title:column", "Dimension");
0076             case ValueColumn:
0077                 return i18nc("@title:column", "Value");
0078                 break;
0079         }
0080     }
0081     return QVariant();
0082 }
0083 
0084 Qt::ItemFlags DefaultVariableModel::flags(const QModelIndex& index) const
0085 {
0086     return QAbstractItemModel::flags(index) | Qt::ItemIsEditable;
0087 }
0088 
0089 QVariant DefaultVariableModel::data(const QModelIndex& index, int role) const
0090 {
0091     if ((role != Qt::DisplayRole && role != DataRole) || !index.isValid())
0092         return QVariant();
0093 
0094     Q_D(const DefaultVariableModel);
0095     const auto& variable = d->variables.at(index.row());
0096     switch (index.column())
0097     {
0098         case NameColumn:
0099             return QVariant(variable.name);
0100         case ValueColumn:
0101             if (variable.value.size() <= 100 || role == DefaultVariableModel::DataRole)
0102                 return QVariant(variable.value);
0103             else
0104                 return QVariant(variable.value.left(100) + QStringLiteral("..."));
0105         case TypeColumn:
0106             return QVariant(variable.type);
0107         case SizeColumn:
0108         {
0109             size_t size = variable.size;
0110             if (size != 0)
0111                 return QVariant(qlonglong(size));
0112             else
0113                 return {};
0114         }
0115         case DimensionColumn:
0116             return QVariant(variable.dimension);
0117     }
0118 
0119     return {};
0120 }
0121 
0122 bool DefaultVariableModel::setData(const QModelIndex& index, const QVariant& value, int role)
0123 {
0124     if(role!=Qt::EditRole || !value.isValid() || !index.isValid())
0125     {
0126         return false;
0127     }
0128 
0129     Q_D(const DefaultVariableModel);
0130     if(index.column() == ValueColumn)
0131     {
0132         // Changing values
0133         QString name = data(index.sibling(index.row(), NameColumn)).toString();
0134         d->session->evaluateExpression(d->extension->setValue(name, value.toString()), Expression::DeleteOnFinish);
0135         emit dataChanged(index, index);
0136         return true;
0137     }
0138     else if(index.column() == NameColumn)
0139     {
0140         // Renaming => copy it, then delete the old one
0141         QString oldName = data(index).toString();
0142         QString variableValue = data(index.sibling(index.row(), ValueColumn)).toString();
0143         d->session->evaluateExpression(d->extension->addVariable(value.toString(), variableValue), Expression::DeleteOnFinish);
0144         d->session->evaluateExpression(d->extension->removeVariable(oldName), Expression::DeleteOnFinish);
0145         emit dataChanged(index, index);
0146         return true;
0147     }
0148 
0149     return false;
0150 }
0151 
0152 void DefaultVariableModel::addVariable(const QString& name, const QString& value)
0153 {
0154     Variable v(name, value);
0155     addVariable(v);
0156 }
0157 
0158 void DefaultVariableModel::addVariable(const Cantor::DefaultVariableModel::Variable& variable)
0159 {
0160     Q_D(DefaultVariableModel);
0161     int index = d->variables.indexOf(variable);
0162     if (index != -1)
0163     {
0164         d->variables[index].value = variable.value;
0165         QModelIndex modelIdx = createIndex(index, ValueColumn);
0166         emit dataChanged(modelIdx, modelIdx);
0167     }
0168     else
0169     {
0170         beginInsertRows(QModelIndex(), d->variables.size(), d->variables.size());
0171         d->variables.append(variable);
0172         emit variablesAdded(QStringList(variable.name));
0173         endInsertRows();
0174     }
0175 }
0176 
0177 void DefaultVariableModel::removeVariable(const QString& name)
0178 {
0179     Variable v(name, QString());
0180     removeVariable(v);
0181 }
0182 
0183 void DefaultVariableModel::removeVariable(const Cantor::DefaultVariableModel::Variable& variable)
0184 {
0185     Q_D(DefaultVariableModel);
0186     int row = d->variables.indexOf(variable);
0187     if(row==-1)
0188         return;
0189     const QString& name = variable.name;
0190     beginRemoveRows(QModelIndex(), row, row);
0191     d->variables.removeAt(row);
0192     endRemoveRows();
0193     emit variablesRemoved(QStringList(name));
0194 }
0195 
0196 void DefaultVariableModel::clearVariables()
0197 {
0198     Q_D(DefaultVariableModel);
0199     beginResetModel();
0200 
0201     QStringList names;
0202     for (const Variable& var: d->variables)
0203         names.append(var.name);
0204 
0205     d->variables.clear();
0206     endResetModel();
0207 
0208     emit variablesRemoved(names);
0209 }
0210 
0211 void DefaultVariableModel::clearFunctions()
0212 {
0213     Q_D(DefaultVariableModel);
0214     QStringList names = d->functions;
0215     d->functions.clear();
0216     emit functionsRemoved(names);
0217 }
0218 
0219 void DefaultVariableModel::setVariables(const QList<DefaultVariableModel::Variable>& newVars)
0220 {
0221     Q_D(DefaultVariableModel);
0222 
0223     QStringList addedVars;
0224     QStringList removedVars;
0225 
0226     // Handle deleted vars
0227     int i = 0;
0228     while (i < d->variables.size())
0229     {
0230         Variable var = d->variables[i];
0231         bool found = false;
0232         for (const Variable& newvar : newVars)
0233             if(var.name == newvar.name)
0234             {
0235                 found=true;
0236                 break;
0237             }
0238 
0239         if (!found)
0240         {
0241             removedVars << var.name;
0242             beginRemoveRows(QModelIndex(), i, i);
0243             d->variables.removeAt(i);
0244             endRemoveRows();
0245         }
0246         else
0247             i++;
0248     }
0249 
0250     // Handle added vars
0251     const int size = d->variables.size();
0252     for (const Variable& newvar : newVars)
0253     {
0254         bool found = false;
0255         for (int i = 0; i < size; i++)
0256         {
0257             auto& var = d->variables[i];
0258             if(var.name == newvar.name)
0259             {
0260                 found = true;
0261                 if (var.value != newvar.value || var.size != newvar.size || var.type != newvar.type)
0262                 {
0263                     var.value = newvar.value;
0264                     var.size = newvar.size;
0265                     var.type = newvar.type;
0266                     emit dataChanged(createIndex(i, NameColumn), createIndex(i, SizeColumn));
0267                 }
0268                 break;
0269             }
0270         }
0271 
0272         if (!found)
0273         {
0274             addedVars << newvar.name;
0275             beginInsertRows(QModelIndex(), d->variables.size(), d->variables.size());
0276             d->variables.append(newvar);
0277             endInsertRows();
0278         }
0279     }
0280 
0281     emit variablesAdded(addedVars);
0282     emit variablesRemoved(removedVars);
0283 }
0284 
0285 void DefaultVariableModel::setFunctions(const QStringList& newFuncs)
0286 {
0287     Q_D(DefaultVariableModel);
0288     QStringList addedFuncs;
0289     QStringList removedFuncs;
0290 
0291     //remove the old variables
0292     int i = 0;
0293     while (i < d->functions.size())
0294     {
0295         //check if this var is present in the new variables
0296         bool found=false;
0297         for (const QString& func : newFuncs)
0298             if(d->functions[i] == func)
0299             {
0300                 found=true;
0301                 break;
0302             }
0303 
0304         if(!found)
0305         {
0306             removedFuncs<<d->functions[i];
0307             d->functions.removeAt(i);
0308         }
0309         else
0310             i++;
0311     }
0312 
0313     for (const QString& func : newFuncs)
0314     {
0315         if (!d->functions.contains(func))
0316         {
0317             addedFuncs<<func;
0318             d->functions.append(func);
0319         }
0320     }
0321 
0322     emit functionsAdded(addedFuncs);
0323     emit functionsRemoved(removedFuncs);
0324 }
0325 
0326 Session* DefaultVariableModel::session() const
0327 {
0328     Q_D(const DefaultVariableModel);
0329     return d->session;
0330 }
0331 
0332 QList<DefaultVariableModel::Variable> DefaultVariableModel::variables() const
0333 {
0334     Q_D(const DefaultVariableModel);
0335     return d->variables;
0336 }
0337 
0338 QStringList DefaultVariableModel::variableNames() const
0339 {
0340     Q_D(const DefaultVariableModel);
0341     QStringList names;
0342     for (const Variable& var: d->variables)
0343         names << var.name;
0344     return names;
0345 }
0346 
0347 QStringList DefaultVariableModel::functions() const
0348 {
0349     Q_D(const DefaultVariableModel);
0350     return d->functions;
0351 }
0352 
0353 bool operator==(const Cantor::DefaultVariableModel::Variable& one, const Cantor::DefaultVariableModel::Variable& other)
0354 {
0355     return one.name == other.name;
0356 }
0357 
0358 }