File indexing completed on 2023-05-30 10:40:15
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 }