File indexing completed on 2024-04-28 11:20:35
0001 /* 0002 SPDX-License-Identifier: GPL-2.0-or-later 0003 SPDX-FileCopyrightText: 2018 Nikita Sirgienko <warquark@gmail.com> 0004 SPDX-FileCopyrightText: 2022 Alexander Semke <alexander.semke@web.de> 0005 */ 0006 0007 #include "octavevariablemodel.h" 0008 #include "octavesession.h" 0009 #include "textresult.h" 0010 0011 #include <QDebug> 0012 0013 #include "settings.h" 0014 0015 using namespace Cantor; 0016 0017 OctaveVariableModel::OctaveVariableModel(OctaveSession* session): DefaultVariableModel(session) 0018 { 0019 } 0020 0021 void OctaveVariableModel::update() 0022 { 0023 static const QString code = QString::fromLatin1( 0024 "printf('__cantor_delimiter_line__');" 0025 "__cantor_list__ = who();" 0026 "__cantor_split_var__ = split_long_rows(0);" 0027 "__cantor_parse_values__ = %1;" 0028 "for __cantor_index__ = 1:length(__cantor_list__)" 0029 " __cantor_varname__ = char(__cantor_list__{__cantor_index__});" 0030 " printf([__cantor_varname__ '\\n']);" 0031 " if (__cantor_parse_values__)" 0032 " try" 0033 " eval(['__cantor_string__ = disp(' __cantor_varname__ ');']);" 0034 " printf([num2str(eval(['sizeof(' __cantor_varname__ ');'])) '\\n']);" 0035 " printf([eval(['typeinfo(' __cantor_varname__ ');']) '\\n']);" 0036 " printf([num2str(eval(['rows(' __cantor_varname__ ');'])) '\\n']);" 0037 " printf([num2str(eval(['columns(' __cantor_varname__ ');'])) '\\n']);" 0038 " printf(__cantor_string__);" 0039 " catch" 0040 " printf(['<unprintable value>' '\\n']);" 0041 " printf(['0' '\\n']);" 0042 " end_try_catch;" 0043 " else" 0044 " printf('');" 0045 " endif;" 0046 " printf('__cantor_delimiter_line__');" 0047 "endfor;" 0048 "split_long_rows(__cantor_split_var__);" 0049 "clear __cantor_list__;" 0050 "clear __cantor_index__;" 0051 "clear __cantor_varname__;" 0052 "clear __cantor_parse_values__;" 0053 "clear __cantor_string__;" 0054 "clear __cantor_split_var__;" 0055 ); 0056 0057 if (m_expr) 0058 return; 0059 0060 const QString& cmd = code.arg(OctaveSettings::self()->variableManagement() ? QLatin1String("true") : QLatin1String("false")); 0061 m_expr = session()->evaluateExpression(cmd, Expression::FinishingBehavior::DoNotDelete, true); 0062 connect(m_expr, &Expression::statusChanged, this, &OctaveVariableModel::parseNewVariables); 0063 } 0064 0065 void OctaveVariableModel::parseNewVariables(Expression::Status status) 0066 { 0067 switch(status) 0068 { 0069 case Expression::Status::Done: 0070 { 0071 static const QLatin1String delimiter("__cantor_delimiter_line__"); 0072 0073 if (m_expr->results().isEmpty()) 0074 { 0075 qWarning() << "Octave code for parsing variables finish with done status, but without results"; 0076 break; 0077 } 0078 0079 QString text = static_cast<Cantor::TextResult*>(m_expr->result())->plain(); 0080 const QStringList& variableData = text.split(delimiter, QString::SkipEmptyParts); 0081 QList<Variable> vars; 0082 0083 for (const auto& data : variableData) 0084 { 0085 // every variable data has 4 parts/elements separated by a new line - the name of the variable, its size, type and the actual value 0086 const auto& elements = data.split(QLatin1String("\n"), QString::SkipEmptyParts); 0087 int count = elements.count(); 0088 if (count < 6) 0089 continue; 0090 0091 const QString& name = elements.constFirst(); 0092 0093 // skip the output of results that are not assigned to any varialbe ("ans" used by Octave) 0094 if (name == QStringLiteral("ans")) 0095 continue; 0096 0097 const QString& size = elements.at(1); 0098 const QString& type = elements.at(2); 0099 const QString& rows = elements.at(3); 0100 const QString& columns = elements.at(4); 0101 0102 // the last section(s) contain(s) the value (single-line or multi-line output) 0103 QString value; 0104 if (OctaveSettings::self()->variableManagement()) 0105 { 0106 for (int i = 5; i < count; ++i) 0107 { 0108 if (!value.isEmpty()) 0109 value += QStringLiteral("; "); // separate multi-line values like in column vectors or in matrices by a semicolon 0110 value += elements.at(i).trimmed(); 0111 } 0112 } 0113 0114 value = value.replace(QStringLiteral(" "), QStringLiteral(" ")); // for vectors Octave is separating the values with three blanks, replace with one 0115 vars << Variable(name, value, size.toULongLong(), type, rows + QStringLiteral("x") + columns); 0116 } 0117 0118 setVariables(vars); 0119 break; 0120 } 0121 case Expression::Status::Error: 0122 qWarning() << "Octave code for parsing variables finish with error message: " << m_expr->errorMessage(); 0123 break; 0124 0125 default: 0126 return; 0127 } 0128 0129 m_expr->deleteLater(); 0130 m_expr = nullptr; 0131 }