1
/*************************************************************************************
2
* Copyright (C) 2009 by Milian Wolff <mail@milianw.de> *
3
* Copyright (C) 2011 by Matteo Agostinelli <agostinelli@gmail.com> *
5
* This program is free software; you can redistribute it and/or *
6
* modify it under the terms of the GNU General Public License *
7
* as published by the Free Software Foundation; either version 2 *
8
* of the License, or (at your option) any later version. *
10
* This program is distributed in the hope that it will be useful, *
11
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
12
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
13
* GNU General Public License for more details. *
15
* You should have received a copy of the GNU General Public License *
16
* along with this program; if not, write to the Free Software *
17
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA *
18
*************************************************************************************/
20
#include <config-cantorlib.h>
22
#include "textresult.h"
23
#include "helpresult.h"
24
#include "imageresult.h"
25
#include "epsresult.h"
27
#include "defaultvariablemodel.h"
29
#include "qalculateexpression.h"
30
#include "qalculatesession.h"
31
#include "qalculatesyntaxhelpobject.h"
33
#include <libqalculate/Calculator.h>
34
#include <libqalculate/ExpressionItem.h>
35
#include <libqalculate/Unit.h>
36
#include <libqalculate/Prefix.h>
37
#include <libqalculate/Variable.h>
38
#include <libqalculate/Function.h>
41
// required for the plotting interface of Qalculator
45
#include <KMessageBox>
46
#include <KColorScheme>
50
#include <QApplication>
53
QalculateExpression::QalculateExpression( QalculateSession* session )
54
: Cantor::Expression(session)
59
QalculateExpression::~QalculateExpression()
65
void QalculateExpression::evaluate()
67
setStatus(Cantor::Expression::Computing);
70
if (command().isEmpty()) {
74
if (command().contains("help")) {
75
QalculateSyntaxHelpObject* helper = new QalculateSyntaxHelpObject(command(), (QalculateSession*) session());
76
setResult(new Cantor::HelpResult(helper->answer()));
77
setStatus(Cantor::Expression::Done);
80
else if (command().trimmed().startsWith("plot") &&
81
(command().indexOf("plot")+4 == command().size() ||
82
command()[command().indexOf("plot")+4].isSpace())) {
83
evaluatePlotCommand();
86
else if (command().trimmed().startsWith("saveVariables") &&
87
(command().indexOf("saveVariables")+13 == command().size() ||
88
command()[command().indexOf("saveVariables")+13].isSpace())) {
89
evaluateSaveVariablesCommand();
92
else if (command().trimmed().startsWith("loadVariables") &&
93
(command().indexOf("loadVariables")+13 == command().size() ||
94
command()[command().indexOf("loadVariables")+13].isSpace())) {
95
evaluateLoadVariablesCommand();
99
string expression = unlocalizeExpression(command());
101
kDebug() << "EXPR: " << QString(expression.c_str());
103
EvaluationOptions eo = evaluationOptions();
105
MathStructure result = CALCULATOR->calculate(expression, eo);
107
// update the answer variables
108
static_cast<QalculateSession*>(session())->setLastResult(result);
111
if (checkForCalculatorMessages() & (MSG_WARN | MSG_WARN))
114
updateVariables(CALCULATOR->parse(expression, eo.parse_options));
116
QSharedPointer<PrintOptions> po = printOptions();
120
setResult(new Cantor::TextResult(result.print(*po).c_str()));
124
void QalculateExpression::evaluateSaveVariablesCommand()
126
QString argString = command().mid(command().indexOf("saveVariables")+13);
127
argString = argString.trimmed();
129
QString usage = i18n("Usage: saveVariables file");
131
QString fileName = parseForFilename(argString, usage);
132
if (fileName.isNull())
135
// We want to save Temporary variables, but Qalculate does not.
136
std::vector<Variable*> variables = CALCULATOR->variables;
137
// If somebody saves his variables in Cantor_Internal_Temporary
138
// he deserves unexpected behavior.
139
std::string tmpCategory = "Temporary";
140
std::string newCategory = "Cantor_Internal_Temporary";
141
for (int i = 0; i < variables.size(); ++i) {
142
if (variables[i]->category() == tmpCategory)
143
variables[i]->setCategory(newCategory);
146
int res = CALCULATOR->saveVariables(fileName.toLatin1().data());
148
for (int i = 0; i < variables.size(); ++i) {
149
if (variables[i]->category() == newCategory)
150
variables[i]->setCategory(tmpCategory);
154
if (checkForCalculatorMessages() & (MSG_WARN|MSG_ERR)) {
158
showMessage(i18n("Saving failed."), MESSAGE_ERROR);
165
void QalculateExpression::evaluateLoadVariablesCommand()
167
QString argString = command().mid(command().indexOf("loadVariables")+13);
168
argString = argString.trimmed();
170
QString usage = i18n("Usage: loadVariables file");
172
QString fileName = parseForFilename(argString, usage);
173
if (fileName.isNull())
176
int res = CALCULATOR->loadDefinitions(fileName.toLatin1().data());
177
if (checkForCalculatorMessages() & (MSG_WARN|MSG_ERR)) {
181
showMessage(i18n("Loading failed."), MESSAGE_ERROR);
185
// We have to store temporary variables in a different category
186
// (see parseSaveVariablesCommand())
187
std::vector<Variable*> variables = CALCULATOR->variables;
188
std::string tmpCategory = "Temporary";
189
std::string newCategory = "Cantor_Internal_Temporary";
191
for (int i = 0; i < variables.size(); ++i) {
192
if (variables[i]->category() == newCategory)
193
variables[i]->setCategory(tmpCategory);
199
QString QalculateExpression::parseForFilename(QString argument, QString usage)
201
if (argument.isEmpty()) {
202
showMessage(usage, MESSAGE_ERROR);
206
QString fileName = "";
209
if (argument[0] == '\'' || argument[0] == '"') {
213
while (i < argument.size() && !argument[i].isSpace() &&
214
argument[i] != sep) {
215
if (argument[i] == '\\' && i < argument.size()-1)
217
fileName += argument[i];
221
if (sep != '\0' && i == argument.size()) {
222
showMessage(i18n("missing %1", sep), MESSAGE_ERROR);
226
if (i < argument.size() - 1) {
227
showMessage(usage, MESSAGE_ERROR);
234
void QalculateExpression::evaluatePlotCommand()
236
QString argString = command().mid(command().indexOf("plot")+4);
237
argString = unlocalizeExpression(argString).c_str();
238
argString = argString.trimmed();
240
QList<QStringList> argumentsList;
241
QStringList arguments;
243
// For error handling
244
KColorScheme scheme(QApplication::palette().currentColorGroup());
245
const QString errorColor = scheme.foreground(KColorScheme::NegativeText).color().name();
246
const QString warningColor = scheme.foreground(KColorScheme::NeutralText).color().name();
247
const QString msgFormat("<font color=\"%1\">%2: %3</font><br>\n");
249
if (!CALCULATOR->canPlot()) {
250
showMessage(i18n("Qalculate reports it cannot print. Is gnuplot installed?"), MESSAGE_ERROR);
254
// Split argString into the arguments
258
while (i < argString.size()) {
259
if (argString[i] == '"' || argString[i] == '\'') {
261
while(j < argString.size() && argString[j] != argString[i]) {
262
if (argString[j] == '\\') {
264
if (j == argString.size())
265
continue; // just ignore trailing backslashes
270
if (j == argString.size()) {
271
showMessage(i18n("missing %1", argString[i]), MESSAGE_ERROR);
275
} else if (argString[i] == ',') {
276
argumentsList.append(arguments);
280
while(j < argString.size() && !argString[j].isSpace() &&
281
argString[j] != '=' && argString[j] != ',') {
282
if (argString[j] == '\\') {
284
if (j == argString.size())
285
continue; // just ignore trailing backslashes
291
if (argString[j] == '=') {
292
// Parse things like title="..." as one argument
297
if (!arg.isEmpty()) {
301
while (j < argString.size() && argString[j].isSpace())
305
argumentsList.append(arguments);
307
// Parse the arguments and compute the points to be plotted
308
std::vector<MathStructure> y_vectors;
309
std::vector<MathStructure> x_vectors;
310
std::vector<PlotDataParameters*> plotDataParameterList;
311
PlotParameters plotParameters;
312
EvaluationOptions eo = evaluationOptions();
314
plotParameters.title = "";
315
plotParameters.y_label = "";
316
plotParameters.x_label = "";
317
plotParameters.filename = "";
318
plotParameters.filetype = PLOT_FILETYPE_AUTO;
319
plotParameters.color = QalculateSettings::coloredPlot();
320
plotParameters.auto_y_min = true;
321
plotParameters.auto_x_min = true;
322
plotParameters.auto_x_max = true;
323
plotParameters.auto_y_max = true;
324
plotParameters.y_log = false;
325
plotParameters.x_log = false;
326
plotParameters.grid = QalculateSettings::plotGrid();
327
plotParameters.linewidth = QalculateSettings::plotLineWidth();
328
plotParameters.show_all_borders = QalculateSettings::plotBorder();
329
switch (QalculateSettings::plotLegend()) {
330
case QalculateSettings::LEGEND_NONE:
331
plotParameters.legend_placement = PLOT_LEGEND_NONE;
333
case QalculateSettings::LEGEND_TOP_LEFT:
334
plotParameters.legend_placement = PLOT_LEGEND_TOP_LEFT;
336
case QalculateSettings::LEGEND_TOP_RIGHT:
337
plotParameters.legend_placement = PLOT_LEGEND_TOP_RIGHT;
339
case QalculateSettings::LEGEND_BOTTOM_LEFT:
340
plotParameters.legend_placement = PLOT_LEGEND_BOTTOM_LEFT;
342
case QalculateSettings::LEGEND_BOTTOM_RIGHT:
343
plotParameters.legend_placement = PLOT_LEGEND_BOTTOM_RIGHT;
345
case QalculateSettings::LEGEND_BELOW:
346
plotParameters.legend_placement = PLOT_LEGEND_BELOW;
348
case QalculateSettings::LEGEND_OUTSIDE:
349
plotParameters.legend_placement = PLOT_LEGEND_OUTSIDE;
352
bool plotInline = QalculateSettings::inlinePlot();
357
MathStructure stepLength;
358
stepLength.setUndefined();
359
int steps = QalculateSettings::plotSteps();
361
QString mustBeNumber = i18n("%1 must be a number.");
362
QString mustBeInteger = i18n("%1 must be a integer.");
363
QString mustBeBoolean = i18n("%1 must be a boolean.");
364
QString invalidOption = i18n("invalid option for %1: %2");
366
for (int i = 0; i < argumentsList.size(); ++i) {
367
std::string xVariable = "x";
368
PlotDataParameters* plotDataParams = new PlotDataParameters;
369
plotDataParameterList.push_back(plotDataParams);
370
plotDataParams->title = "";
371
switch(QalculateSettings::plotSmoothing()) {
372
case QalculateSettings::SMOOTHING_NONE:
373
plotDataParams->smoothing = PLOT_SMOOTHING_NONE;
375
case QalculateSettings::SMOOTHING_UNIQUE:
376
plotDataParams->smoothing = PLOT_SMOOTHING_UNIQUE;
378
case QalculateSettings::SMOOTHING_CSPLINES:
379
plotDataParams->smoothing = PLOT_SMOOTHING_CSPLINES;
381
case QalculateSettings::SMOOTHING_BEZIER:
382
plotDataParams->smoothing = PLOT_SMOOTHING_BEZIER;
384
case QalculateSettings::SMOOTHING_SBEZIER:
385
plotDataParams->smoothing = PLOT_SMOOTHING_SBEZIER;
388
switch(QalculateSettings::plotStyle()) {
389
case QalculateSettings::STYLE_LINES:
390
plotDataParams->style = PLOT_STYLE_LINES;
392
case QalculateSettings::STYLE_POINTS:
393
plotDataParams->style = PLOT_STYLE_POINTS;
395
case QalculateSettings::STYLE_LINES_POINTS:
396
plotDataParams->style = PLOT_STYLE_POINTS_LINES;
398
case QalculateSettings::STYLE_BOXES:
399
plotDataParams->style = PLOT_STYLE_BOXES;
401
case QalculateSettings::STYLE_HISTOGRAM:
402
plotDataParams->style = PLOT_STYLE_HISTOGRAM;
404
case QalculateSettings::STYLE_STEPS:
405
plotDataParams->style = PLOT_STYLE_STEPS;
407
case QalculateSettings::STYLE_CANDLESTICKS:
408
plotDataParams->style = PLOT_STYLE_CANDLESTICKS;
410
case QalculateSettings::STYLE_DOTS:
411
plotDataParams->style = PLOT_STYLE_DOTS;
414
plotDataParams->yaxis2 = false;
415
plotDataParams->xaxis2 = false;
416
arguments = argumentsList[i];
417
std::string expression;
418
int lastExpressionEntry = -1;
419
for (int j = 0; j < arguments.size(); ++j) {
420
QString argument = arguments[j];
422
if (argument.startsWith("plottitle="))
423
plotParameters.title = argument.mid(10).toLatin1().data();
424
else if (argument.startsWith("ylabel="))
425
plotParameters.y_label = argument.mid(7).toLatin1().data();
426
else if (argument.startsWith("xlabel="))
427
plotParameters.x_label = argument.mid(7).toLatin1().data();
428
else if (argument.startsWith("filename="))
429
plotParameters.filename = argument.mid(9).toLatin1().data();
430
else if (argument.startsWith("filetype=")) {
431
QString option = argument.mid(9);
432
if (option == "auto")
433
plotParameters.filetype = PLOT_FILETYPE_AUTO;
434
else if (option == "png")
435
plotParameters.filetype = PLOT_FILETYPE_PNG;
436
else if (option == "ps")
437
plotParameters.filetype = PLOT_FILETYPE_PS;
438
else if (option == "eps")
439
plotParameters.filetype = PLOT_FILETYPE_EPS;
440
else if (option == "latex")
441
plotParameters.filetype = PLOT_FILETYPE_LATEX;
442
else if (option == "svg")
443
plotParameters.filetype = PLOT_FILETYPE_SVG;
444
else if (option == "fig")
445
plotParameters.filetype = PLOT_FILETYPE_FIG;
447
QString msg = invalidOption.arg("filetype", option);
448
showMessage(msg, MESSAGE_ERROR);
449
deletePlotDataParameters(plotDataParameterList);
453
else if (argument.startsWith("font="))
454
plotParameters.font = argument.mid(5).toLatin1().data();
455
else if (argument.startsWith("color=")) {
457
plotParameters.color = stringToBool(argument.mid(6), &ok);
459
showMessage(mustBeBoolean.arg("color"),
461
deletePlotDataParameters(plotDataParameterList);
465
else if (argument.startsWith("ylog=")) {
467
plotParameters.y_log = stringToBool(argument.mid(5), &ok);
469
showMessage(mustBeBoolean.arg("ylog"), MESSAGE_ERROR);
470
deletePlotDataParameters(plotDataParameterList);
474
else if (argument.startsWith("xlog=")) {
476
plotParameters.x_log = stringToBool(argument.mid(5), &ok);
478
showMessage(mustBeBoolean.arg("xlog"), MESSAGE_ERROR);
482
else if (argument.startsWith("ylogbase=")) {
483
MathStructure ylogStr = CALCULATOR->calculate(argument.mid(9).toLatin1().data(), eo);
484
if (checkForCalculatorMessages() & (MSG_WARN|MSG_ERR)) {
485
deletePlotDataParameters(plotDataParameterList);
488
if (ylogStr.isNumber()) {
489
Number ylogNum = ylogStr.number();
490
plotParameters.y_log_base = ylogNum.floatValue();
492
showMessage(mustBeNumber.arg("ylogbase"), MESSAGE_ERROR);
493
deletePlotDataParameters(plotDataParameterList);
497
else if (argument.startsWith("xlogbase=")) {
498
MathStructure xlogStr = CALCULATOR->calculate(argument.mid(9).toLatin1().data(), eo);
499
if (checkForCalculatorMessages() & (MSG_WARN|MSG_ERR)) {
500
deletePlotDataParameters(plotDataParameterList);
503
if (xlogStr.isNumber()) {
504
Number xlogNum = xlogStr.number();
505
plotParameters.x_log_base = xlogNum.floatValue();
507
showMessage(mustBeNumber.arg("xlogbase"), MESSAGE_ERROR);
508
deletePlotDataParameters(plotDataParameterList);
512
else if (argument.startsWith("grid=")) {
514
plotParameters.grid = stringToBool(argument.mid(5), &ok);
516
showMessage(mustBeBoolean.arg("grid"), MESSAGE_ERROR);
517
deletePlotDataParameters(plotDataParameterList);
521
else if (argument.startsWith("linewidth=")) {
522
MathStructure lineWidthStr = CALCULATOR->calculate(argument.mid(10).toLatin1().data(), eo);
524
if (lineWidthStr.isNumber() && lineWidthStr.number().isInteger()) {
525
lineWidthNum = lineWidthStr.number();
526
plotParameters.linewidth = lineWidthNum.intValue();
528
showMessage(mustBeInteger.arg("linewidth"), MESSAGE_ERROR);
529
deletePlotDataParameters(plotDataParameterList);
533
else if (argument.startsWith("border=")) {
535
plotParameters.show_all_borders = stringToBool(argument.mid(7), &ok);
537
showMessage(mustBeBoolean.arg("border"), MESSAGE_ERROR);
538
deletePlotDataParameters(plotDataParameterList);
542
else if (argument.startsWith("legend=")) {
543
QString option = argument.mid(7);
544
if (option == "none")
545
plotParameters.legend_placement = PLOT_LEGEND_NONE;
546
else if (option == "top_left")
547
plotParameters.legend_placement = PLOT_LEGEND_TOP_LEFT;
548
else if (option == "top_right")
549
plotParameters.legend_placement = PLOT_LEGEND_TOP_RIGHT;
550
else if (option == "bottom_left")
551
plotParameters.legend_placement = PLOT_LEGEND_BOTTOM_LEFT;
552
else if (option == "bottom_right")
553
plotParameters.legend_placement = PLOT_LEGEND_BOTTOM_RIGHT;
554
else if (option == "below")
555
plotParameters.legend_placement = PLOT_LEGEND_BELOW;
556
else if (option == "outside")
557
plotParameters.legend_placement = PLOT_LEGEND_OUTSIDE;
559
QString msg = invalidOption.arg("legend", option);
560
showMessage(msg, MESSAGE_ERROR);
561
deletePlotDataParameters(plotDataParameterList);
565
// PlotDataParameters
566
else if (argument.startsWith("title=")) {
567
plotDataParams->title = argument.mid(6).toLatin1().data();
569
else if (argument.startsWith("smoothing=")) {
570
QString option = argument.mid(10);
571
if (option == "none")
572
plotDataParams->smoothing = PLOT_SMOOTHING_NONE;
573
else if (option == "monotonic")
574
plotDataParams->smoothing = PLOT_SMOOTHING_UNIQUE;
575
else if (option == "csplines")
576
plotDataParams->smoothing = PLOT_SMOOTHING_CSPLINES;
577
else if (option == "bezier")
578
plotDataParams->smoothing = PLOT_SMOOTHING_BEZIER;
579
else if (option == "sbezier")
580
plotDataParams->smoothing = PLOT_SMOOTHING_SBEZIER;
582
QString msg = invalidOption.arg("smoothing", option);
583
showMessage(msg, MESSAGE_ERROR);
584
deletePlotDataParameters(plotDataParameterList);
587
} else if (argument.startsWith("style=")) {
588
QString option = argument.mid(6);
589
if (option == "lines")
590
plotDataParams->style = PLOT_STYLE_LINES;
591
else if (option == "points")
592
plotDataParams->style = PLOT_STYLE_POINTS;
593
else if (option == "points_lines")
594
plotDataParams->style = PLOT_STYLE_POINTS_LINES;
595
else if (option == "boxes")
596
plotDataParams->style = PLOT_STYLE_BOXES;
597
else if (option == "histogram")
598
plotDataParams->style = PLOT_STYLE_HISTOGRAM;
599
else if (option == "steps")
600
plotDataParams->style = PLOT_STYLE_STEPS;
601
else if (option == "candlesticks")
602
plotDataParams->style = PLOT_STYLE_CANDLESTICKS;
603
else if (option == "dots")
604
plotDataParams->style = PLOT_STYLE_DOTS;
606
QString msg = invalidOption.arg("style", option);
607
showMessage(msg, MESSAGE_ERROR);
608
deletePlotDataParameters(plotDataParameterList);
611
} else if (argument.startsWith("xaxis2=")) {
613
plotDataParams->xaxis2 = stringToBool(argument.mid(7), &ok);
615
showMessage(mustBeBoolean.arg("xaxis2"), MESSAGE_ERROR);
616
deletePlotDataParameters(plotDataParameterList);
619
} else if (argument.startsWith("yaxis2=")) {
621
plotDataParams->yaxis2 = stringToBool(argument.mid(7), &ok);
623
showMessage(mustBeBoolean.arg("yaxis2"), MESSAGE_ERROR);
624
deletePlotDataParameters(plotDataParameterList);
628
// inline, xmin, xmax, step, steps, xvar
630
else if (argument.startsWith("inline=")) {
632
plotInline = stringToBool(argument.mid(7), &ok);
634
showMessage(mustBeBoolean.arg("inline"), MESSAGE_ERROR);
635
deletePlotDataParameters(plotDataParameterList);
639
else if (argument.startsWith("xmin=")) {
640
xMin = CALCULATOR->calculate(argument.mid(5).toLatin1().data(), eo);
641
if (checkForCalculatorMessages() & (MSG_WARN|MSG_ERR)) {
642
deletePlotDataParameters(plotDataParameterList);
646
else if (argument.startsWith("xmax=")) {
647
xMax = CALCULATOR->calculate(argument.mid(5).toLatin1().data(), eo);
648
if (checkForCalculatorMessages() & (MSG_WARN|MSG_ERR)) {
649
deletePlotDataParameters(plotDataParameterList);
653
else if (argument.startsWith("step=")) {
654
stepLength = CALCULATOR->calculate(argument.mid(5).toLatin1().data(), eo);
655
if (checkForCalculatorMessages() & (MSG_WARN|MSG_ERR)) {
656
deletePlotDataParameters(plotDataParameterList);
661
else if (argument.startsWith("steps=")) {
662
MathStructure stepsStr = CALCULATOR->calculate(argument.mid(6).toLatin1().data(), eo);
663
if (checkForCalculatorMessages() & (MSG_WARN|MSG_ERR)) {
664
deletePlotDataParameters(plotDataParameterList);
668
if (stepsStr.isNumber() && stepsStr.number().isInteger()) {
669
stepsNum = stepsStr.number();
670
steps = stepsNum.intValue();
671
stepLength.setUndefined();
673
showMessage(mustBeInteger.arg("steps"), MESSAGE_ERROR);
674
deletePlotDataParameters(plotDataParameterList);
678
else if (argument.startsWith("xvar=")) {
679
xVariable = argument.mid(5).toLatin1().data();
681
else if (expression.empty()) {
682
expression = argument.toLatin1().data();
683
lastExpressionEntry = j;
685
else if (lastExpressionEntry == j-1) {
687
expression += argument.toLatin1().data();
688
lastExpressionEntry = j;
691
QString msg = i18n("found multiple expressions in one plot command (%1 and %2).", QString(expression.c_str()), argument);
692
showMessage(msg, MESSAGE_ERROR);
693
deletePlotDataParameters(plotDataParameterList);
697
if (expression.empty())
699
if (xMin.isUndefined()) {
700
if (!plotParameters.auto_x_min)
701
xMin = plotParameters.x_min;
705
if (xMax.isUndefined()) {
706
if (!plotParameters.auto_x_max)
707
xMax = plotParameters.x_max;
711
if (plotDataParams->title.empty())
712
plotDataParams->title = expression;
713
MathStructure x_vec, y_vec;
715
if (!stepLength.isUndefined())
716
y_vec = CALCULATOR->expressionToPlotVector(expression, xMin, xMax, stepLength, &x_vec, xVariable, eo.parse_options);
718
y_vec = CALCULATOR->expressionToPlotVector(expression, xMin, xMax, steps, &x_vec, xVariable, eo.parse_options);
719
if (checkForCalculatorMessages() & (MSG_WARN|MSG_ERR)) {
720
deletePlotDataParameters(plotDataParameterList);
724
x_vectors.push_back(x_vec);
725
y_vectors.push_back(y_vec);
730
//setResult(new Cantor::TextResult(y_vec.print(po).c_str()));
732
//deletePlotDataParameters(plotDataParameterList);
736
if (plotInline && plotParameters.filename.empty()) {
737
// TODO: get a temporary file name here
739
m_tempFile = new KTemporaryFile();
741
m_tempFile->setSuffix(".eps");
743
m_tempFile->setSuffix(".png");
747
plotParameters.filename = m_tempFile->fileName().toLatin1().data();
748
plotParameters.filetype = PLOT_FILETYPE_AUTO;
751
CALCULATOR->plotVectors(&plotParameters, y_vectors, x_vectors,
752
plotDataParameterList);
753
if (checkForCalculatorMessages() & (MSG_WARN|MSG_ERR)) {
754
deletePlotDataParameters(plotDataParameterList);
758
deletePlotDataParameters(plotDataParameterList);
762
size_t p = plotParameters.filename.size();
763
if (plotParameters.filetype == PLOT_FILETYPE_EPS ||
764
plotParameters.filetype == PLOT_FILETYPE_PS ||
765
(plotParameters.filetype == PLOT_FILETYPE_AUTO && p >= 4 &&
766
plotParameters.filename.substr(p-4,4) == ".eps") ||
767
(plotParameters.filetype == PLOT_FILETYPE_AUTO && p >= 3 &&
768
plotParameters.filename.substr(p-3,3) == ".ps"))
769
setResult(new Cantor::EpsResult(KUrl(plotParameters.filename.c_str())));
771
setResult(new Cantor::ImageResult(KUrl(plotParameters.filename.c_str())));
773
setResult(new Cantor::ImageResult(KUrl(plotParameters.filename.c_str())));
775
setStatus(Cantor::Expression::Done);
780
void QalculateExpression::showMessage(QString msg, MessageType mtype)
782
KColorScheme scheme(QApplication::palette().currentColorGroup());
783
const QString errorColor = scheme.foreground(KColorScheme::NegativeText).color().name();
784
const QString warningColor = scheme.foreground(KColorScheme::NeutralText).color().name();
785
const QString msgFormat("<font color=\"%1\">%2: %3</font><br>\n");
786
if(mtype == MESSAGE_ERROR || mtype == MESSAGE_WARNING) {
787
msg.replace("&", "&");
788
msg.replace(">", ">");
789
msg.replace("<", "<");
791
if (mtype == MESSAGE_ERROR) {
792
msg = msgFormat.arg(errorColor, i18n("ERROR"), msg.toLatin1().data());
794
msg = msgFormat.arg(errorColor, i18n("WARNING"), msg.toLatin1().data());
796
setErrorMessage(msg);
799
KMessageBox::information(QApplication::activeWindow(), msg);
803
EvaluationOptions QalculateExpression::evaluationOptions()
805
EvaluationOptions eo;
807
eo.auto_post_conversion = QalculateSettings::postConversion() ? POST_CONVERSION_BEST : POST_CONVERSION_NONE;
808
eo.keep_zero_units = false;
810
eo.parse_options = parseOptions();
812
switch (QalculateSettings::structuring()) {
814
eo.structuring = STRUCTURING_NONE;
817
eo.structuring = STRUCTURING_SIMPLIFY;
820
eo.structuring = STRUCTURING_FACTORIZE;
827
ParseOptions QalculateExpression::parseOptions()
830
switch (QalculateSettings::angleUnit()) {
832
po.angle_unit = ANGLE_UNIT_NONE;
835
po.angle_unit = ANGLE_UNIT_RADIANS;
838
po.angle_unit = ANGLE_UNIT_DEGREES;
841
po.angle_unit = ANGLE_UNIT_GRADIANS;
845
po.base = QalculateSettings::base();
850
void QalculateExpression::deletePlotDataParameters
851
(const std::vector<PlotDataParameters*>& plotDataParameterList)
853
for(int i = 0; i < plotDataParameterList.size(); ++i)
854
delete plotDataParameterList[i];
857
bool QalculateExpression::stringToBool(const QString &string, bool *ok)
859
if (string == "true" || string == "1") {
862
} else if (string == "false" || string == "0") {
871
int QalculateExpression::checkForCalculatorMessages()
873
// error handling, most of it copied from qalculate-kde
874
int msgType = MSG_NONE;
875
if ( CALCULATOR->message() ) {
877
KColorScheme scheme(QApplication::palette().currentColorGroup());
878
const QString errorColor = scheme.foreground(KColorScheme::NegativeText).color().name();
879
const QString warningColor = scheme.foreground(KColorScheme::NeutralText).color().name();
880
const QString msgFormat("<font color=\"%1\">%2: %3</font><br>\n");
883
mtype = CALCULATOR->message()->type();
885
case MESSAGE_INFORMATION:
886
msgType |= MSG_INFO; break;
887
case MESSAGE_WARNING:
888
msgType |= MSG_WARN; break;
890
msgType |= MSG_ERR; break;
892
if(mtype == MESSAGE_ERROR || mtype == MESSAGE_WARNING) {
893
QString text = CALCULATOR->message()->message().c_str();
894
text.replace("&", "&");
895
text.replace(">", ">");
896
text.replace("<", "<");
898
if (mtype == MESSAGE_ERROR) {
899
msg.append(msgFormat.arg(errorColor, i18n("ERROR"), text));
901
msg.append(msgFormat.arg(errorColor, i18n("WARNING"), text));
904
KMessageBox::information(QApplication::activeWindow(), CALCULATOR->message()->message().c_str());
906
if(!CALCULATOR->nextMessage()) break;
908
if ( !msg.isEmpty() ) {
910
setErrorMessage(m_message);
917
std::string QalculateExpression::unlocalizeExpression(QString expr)
919
// copy'n'pasted from qalculate plasma applet
921
return CALCULATOR->unlocalizeExpression(
922
expr.replace(QChar(0xA3), "GBP")
923
.replace(QChar(0xA5), "JPY")
925
.replace(QChar(0x20AC), "EUR")
930
void QalculateExpression::updateVariables(MathStructure command)
932
Cantor::DefaultVariableModel* model =
933
static_cast<Cantor::DefaultVariableModel*>(session()->variableModel());
934
QStack<MathStructure*> stack;
935
stack.push(&command);
936
QSharedPointer<PrintOptions> po = printOptions();
937
while (!stack.isEmpty()) {
938
MathStructure* current = stack.pop();
939
if (current->isFunction() && current->function()->name() == "save" &&
940
current->countChildren() >= 2 && current->getChild(2)->isSymbolic())
942
// I'd like to use CALCULATOR->getVariable and KnownVariable::get,
943
// but that doesn't work for built in variables, as it keeps
944
// returning the old value
945
std::string name = current->getChild(2)->symbol();
946
MathStructure m = CALCULATOR->calculate(name, evaluationOptions());
948
model->addVariable(name.c_str(), m.print(*po).c_str());
950
for (int i = 0; i < current->countChildren(); ++i) {
951
stack.push(current->getChild(i+1));
956
QSharedPointer<PrintOptions> QalculateExpression::printOptions()
958
QSharedPointer<PrintOptions> po(new PrintOptions);
960
switch (QalculateSettings::fractionFormat()) {
962
po->number_fraction_format = FRACTION_DECIMAL;
965
po->number_fraction_format = FRACTION_DECIMAL_EXACT;
968
po->number_fraction_format = FRACTION_FRACTIONAL;
971
po->number_fraction_format = FRACTION_COMBINED;
974
po->indicate_infinite_series = QalculateSettings::indicateInfiniteSeries();
975
po->use_all_prefixes = QalculateSettings::useAllPrefixes();
976
po->negative_exponents = QalculateSettings::negativeExponents();
978
po->lower_case_e = true;
979
po->base = QalculateSettings::base();
980
po->decimalpoint_sign = KGlobal::locale()->decimalSymbol().toLocal8Bit().data();
982
switch (QalculateSettings::minExp()) {
984
po->min_exp = EXP_NONE;
987
po->min_exp = EXP_PURE;
990
po->min_exp = EXP_SCIENTIFIC;
993
po->min_exp = EXP_PRECISION;
996
po->min_exp = EXP_BASE_3;