File indexing completed on 2024-04-28 03:40:43
0001 /************************************************************************************* 0002 * Copyright (C) 2008 by Aleix Pol <aleixpol@kde.org> * 0003 * * 0004 * This program is free software; you can redistribute it and/or * 0005 * modify it under the terms of the GNU General Public License * 0006 * as published by the Free Software Foundation; either version 2 * 0007 * of the License, or (at your option) any later version. * 0008 * * 0009 * This program is distributed in the hope that it will be useful, * 0010 * but WITHOUT ANY WARRANTY; without even the implied warranty of * 0011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * 0012 * GNU General Public License for more details. * 0013 * * 0014 * You should have received a copy of the GNU General Public License * 0015 * along with this program; if not, write to the Free Software * 0016 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA * 0017 *************************************************************************************/ 0018 0019 #include "htmlexpressionwriter.h" 0020 #include "value.h" 0021 #include "operator.h" 0022 #include "container.h" 0023 #include "vector.h" 0024 #include <QStringList> 0025 #include <QCoreApplication> 0026 0027 #include "list.h" 0028 #include "variable.h" 0029 #include "stringexpressionwriter.h" 0030 #include "apply.h" 0031 #include "analitzautils.h" 0032 #include "matrix.h" 0033 0034 using namespace Analitza; 0035 0036 const double HtmlExpressionWriter::MIN_PRINTABLE_VALUE = 0.0000000000001; // since the precision we choose for 'G' is 12 0037 0038 //we use the one in string* 0039 QMap<Operator::OperatorType, QString> initOperators(); 0040 0041 template <class T> 0042 QStringList HtmlExpressionWriter::allValues(T it, const T& itEnd, AbstractExpressionVisitor* writer) 0043 { 0044 QStringList elements; 0045 for(; it!=itEnd; ++it) 0046 elements += (*it)->accept(writer).toString(); 0047 0048 return elements; 0049 } 0050 0051 0052 static const QMap<Operator::OperatorType, QString> s_operators=initOperators(); 0053 0054 QString oper(const QString& op) { return QCoreApplication::translate("html representation of an operator", "<span class='op'>%1</span>").arg(op); } 0055 QString oper(const QChar& op) { return QCoreApplication::translate("html representation of an operator", "<span class='op'>%1</span>").arg(op); } 0056 QString keyword(const QString& op) { return QCoreApplication::translate("html representation of an operator", "<span class='keyword'>%1</span>").arg(op); } 0057 0058 HtmlExpressionWriter::HtmlExpressionWriter(const Object* o) 0059 { 0060 if(o) 0061 m_result=o->accept(this); 0062 } 0063 0064 QVariant HtmlExpressionWriter::visit(const Vector* vec) 0065 { 0066 return QString(keyword(QStringLiteral("vector "))+oper(QStringLiteral("{ "))+allValues<Vector::const_iterator>(vec->constBegin(), vec->constEnd(), this).join(QString(oper(QStringLiteral(", "))))+oper(QStringLiteral(" }"))); 0067 } 0068 0069 QVariant HtmlExpressionWriter::visit(const Matrix* m) 0070 { 0071 return QString(keyword(QStringLiteral("matrix "))+oper(QStringLiteral("{ "))+allValues(m->constBegin(), m->constEnd(), this).join(QString(oper(QStringLiteral(", "))))+oper(QStringLiteral(" }"))); 0072 } 0073 0074 QVariant HtmlExpressionWriter::visit(const MatrixRow* mr) 0075 { 0076 return QString(keyword(QStringLiteral("matrixrow "))+oper(QStringLiteral("{ "))+allValues(mr->constBegin(), mr->constEnd(), this).join(QString(oper(QStringLiteral(", "))))+oper(QStringLiteral(" }"))); 0077 } 0078 0079 QVariant HtmlExpressionWriter::visit(const List* vec) 0080 { 0081 if(!vec->isEmpty() && vec->at(0)->type()==Object::value && static_cast<Cn*>(vec->at(0))->format()==Cn::Char) { 0082 return QVariant::fromValue<QString>(QStringLiteral("<span class='string'>"") + AnalitzaUtils::listToString(vec) + QStringLiteral(""</span>")); 0083 } else 0084 return QVariant::fromValue<QString>(keyword(QStringLiteral("list "))+oper(QStringLiteral("{ "))+allValues<List::const_iterator>(vec->constBegin(), vec->constEnd(), this).join(QString(oper(QStringLiteral(", "))))+oper(QStringLiteral(" }"))); 0085 } 0086 0087 QVariant HtmlExpressionWriter::visit(const Cn* var) 0088 { 0089 QString innerhtml; 0090 if(var->isBoolean()) 0091 innerhtml = var->isTrue() ? QStringLiteral("true") : QStringLiteral("false"); 0092 else if(var->isCharacter()) 0093 innerhtml = QString(var->character()); 0094 else if(var->isComplex()) { 0095 QString realpart; 0096 QString imagpart; 0097 bool realiszero = false; 0098 const auto complex = var->complexValue(); 0099 if (qAbs(complex.real()) > MIN_PRINTABLE_VALUE) 0100 realpart = QString::number(complex.real(), 'g', 12); 0101 else 0102 realiszero = true; 0103 0104 if (!qFuzzyCompare(qAbs(complex.imag()), 1)) { 0105 if (qAbs(complex.imag()) > MIN_PRINTABLE_VALUE) { 0106 if (!realiszero && complex.imag()>0.) 0107 realpart += QLatin1Char('+'); 0108 imagpart = QString::number(complex.imag(), 'g', 12); 0109 imagpart += QStringLiteral("*i"); 0110 } 0111 } else { 0112 if (!realiszero) 0113 realpart += QLatin1Char('+'); 0114 if (qFuzzyCompare(complex.imag(), 1)) 0115 imagpart = QStringLiteral("i"); 0116 else 0117 imagpart = QStringLiteral("-i"); 0118 } 0119 0120 innerhtml = realpart+imagpart; 0121 } 0122 else 0123 innerhtml = QString::number(var->value(), 'g', 12); 0124 0125 return QVariant::fromValue<QString>(QStringLiteral("<span class='num'>")+innerhtml+"</span>"); 0126 } 0127 0128 QVariant HtmlExpressionWriter::visit(const Analitza::Ci* var) 0129 { 0130 return var->toHtml(); 0131 } 0132 0133 QVariant HtmlExpressionWriter::visit(const Analitza::Operator* o) 0134 { 0135 return QVariant::fromValue<QString>(QStringLiteral("<span class='func'>") + o->toString() + QStringLiteral("</span>")); 0136 } 0137 0138 QVariant HtmlExpressionWriter::visit ( const Analitza::Apply* a ) 0139 { 0140 Operator op=a->firstOperator(); 0141 QStringList ret; 0142 QString toret; 0143 QString bounds; 0144 0145 if(a->ulimit() || a->dlimit()) { 0146 bounds += oper('='); 0147 if(a->dlimit()) 0148 bounds += a->dlimit()->accept(this).toString(); 0149 bounds += oper(QStringLiteral("..")); 0150 if(a->ulimit()) 0151 bounds += a->ulimit()->accept(this).toString(); 0152 } 0153 else if(a->domain()) 0154 bounds += oper('@')+a->domain()->accept(this).toString(); 0155 0156 int i = 0; 0157 foreach(Object* o, a->m_params) { 0158 Object::ObjectType type=o->type(); 0159 switch(type) { 0160 case Object::oper: 0161 Q_ASSERT(false); 0162 break; 0163 case Object::variable: 0164 ret << static_cast<const Ci*>(o)->accept(this).toString(); 0165 break; 0166 case Object::apply: { 0167 Apply *c = (Apply*) o; 0168 QString s = c->accept(this).toString(); 0169 if(s_operators.contains(op.operatorType())) { 0170 Operator child_op = c->firstOperator(); 0171 0172 if(child_op.operatorType() && 0173 StringExpressionWriter::weight(&op, c->countValues(), -1)>StringExpressionWriter::weight(&child_op, c->countValues(), i)) 0174 s=oper('(')+s+oper(')'); 0175 } 0176 ret << s; 0177 } break; 0178 default: 0179 ret << o->accept(this).toString(); 0180 break; 0181 } 0182 ++i; 0183 } 0184 0185 bool func=op.operatorType()==Operator::function; 0186 if(func) { 0187 QString n = ret.takeFirst(); 0188 if(a->m_params.first()->type()!=Object::variable) 0189 n=oper('(')+n+oper(')'); 0190 0191 toret += n+oper('(') + ret.join(oper(QStringLiteral(", "))) + oper(')'); 0192 } else if(op.operatorType()==Operator::selector) { 0193 if(a->m_params.last()->isApply()) { 0194 const Apply* a1=static_cast<const Apply*>(a->m_params.last()); 0195 if(s_operators.contains(a1->firstOperator().operatorType())) 0196 ret.last()=oper('(')+ret.last()+oper(')'); 0197 } 0198 0199 toret += ret.last() + oper('[') + ret.first() + oper(']'); 0200 } else if(ret.count()>1 && s_operators.contains(op.operatorType())) { 0201 toret += ret.join(oper(s_operators.value(op.operatorType()))); 0202 } else if(ret.count()==1 && op.operatorType()==Operator::minus) 0203 toret += oper('-')+ret[0]; 0204 else { 0205 QString bounding; 0206 QStringList bvars; 0207 foreach(const Ci* bvar, a->bvarCi()) 0208 bvars += bvar->accept(this).toString(); 0209 0210 if(!bounds.isEmpty() || !bvars.isEmpty()) { 0211 if(bvars.count()!=1) bounding +=oper('('); 0212 bounding += bvars.join(oper(QStringLiteral(", "))); 0213 if(bvars.count()!=1) bounding +=oper(')'); 0214 0215 bounding = ':'+bounding +bounds; 0216 } 0217 0218 toret += op.accept(this).toString()+oper('(')+ret.join(oper(QStringLiteral(", ")))+bounding+oper(')'); 0219 } 0220 0221 return toret; 0222 } 0223 0224 QVariant HtmlExpressionWriter::visit(const Container* var) 0225 { 0226 QStringList ret = allValues(var->constBegin(), var->constEnd(), this); 0227 0228 0229 QString toret; 0230 switch(var->containerType()) { 0231 case Container::declare: 0232 toret += ret.join(oper(QStringLiteral(":="))); 0233 break; 0234 case Container::lambda: { 0235 QString last=ret.takeLast(); 0236 QStringList bvars; 0237 foreach(const Ci* bvar, var->bvarCi()) 0238 bvars += bvar->accept(this).toString(); 0239 0240 if(bvars.count()!=1) toret +=oper('('); 0241 toret += bvars.join(QStringLiteral(", ")); 0242 if(bvars.count()!=1) toret +=oper(')'); 0243 toret += oper(QStringLiteral("->")) + last; 0244 } break; 0245 case Container::math: 0246 toret += ret.join(oper(QStringLiteral("; "))); 0247 break; 0248 case Container::uplimit: //x->(n1..n2) is put at the same time 0249 case Container::downlimit: 0250 break; 0251 case Container::bvar: 0252 if(ret.count()>1) toret += oper('('); 0253 toret += ret.join(QStringLiteral(", ")); 0254 if(ret.count()>1) toret += oper(')'); 0255 break; 0256 case Container::piece: 0257 toret += ret[1]+oper(QStringLiteral(" ? "))+ret[0]; 0258 break; 0259 case Container::otherwise: 0260 toret += oper(QStringLiteral("? "))+ret[0]; 0261 break; 0262 default: 0263 toret += var->tagName()+oper(QStringLiteral(" { "))+ret.join(oper(QStringLiteral(", ")))+oper(QStringLiteral(" }")); 0264 break; 0265 } 0266 return toret; 0267 } 0268 0269 QVariant HtmlExpressionWriter::visit(const CustomObject*) 0270 { 0271 return QStringLiteral("Custom Object"); 0272 } 0273 0274 QVariant HtmlExpressionWriter::visit(const None* ) 0275 { 0276 return QString(); 0277 }