consolemodel.cpp 6.66 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
/*************************************************************************************
 *  Copyright (C) 2007-2017 by Aleix Pol <aleixpol@kde.org>                          *
 *                                                                                   *
 *  This program is free software; you can redistribute it and/or                    *
 *  modify it under the terms of the GNU General Public License                      *
 *  as published by the Free Software Foundation; either version 2                   *
 *  of the License, or (at your option) any later version.                           *
 *                                                                                   *
 *  This program is distributed in the hope that it will be useful,                  *
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of                   *
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the                    *
 *  GNU General Public License for more details.                                     *
 *                                                                                   *
 *  You should have received a copy of the GNU General Public License                *
 *  along with this program; if not, write to the Free Software                      *
 *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA   *
 *************************************************************************************/

#include "consolemodel.h"

#include <QFile>
22
#include <QFontMetrics>
23
24
#include <QUrl>
#include <KLocalizedString>
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
#include <QGuiApplication>
#include <QPalette>

Q_GLOBAL_STATIC_WITH_ARGS(QByteArray, s_css, (
    "<style type=\"text/css\">\n"
        "\thtml { background-color: " + qGuiApp->palette().color(QPalette::Active, QPalette::Base).name().toLatin1() + "; }\n"
        "\t.error { border-style: solid; border-width: 1px; border-color: #ff3b21; background-color: #ffe9c4; padding:7px;}\n"
        "\t.last  { border-style: solid; border-width: 1px; border-color: #2020ff; background-color: #e0e0ff; padding:7px;}\n"
        "\t.before { text-align:right; }\n"
        "\t.op  { font-weight: bold; }\n"
    //     "\t.normal:hover  { border-style: solid; border-width: 1px; border-color: #777; }\n";
        "\t.normal:hover  { background-color: #f7f7f7; }\n"
        "\t.cont { color: #560000; }\n"
        "\t.num { color: #0000C4; }\n"
        "\t.sep { font-weight: bold; color: #0000FF; }\n"
        "\t.var { color: #640000; }\n"
        "\t.keyword { color: #000064; }\n"
        "\t.func { color: #008600; }\n"
        "\t.result { padding-left: 10%; }\n"
        "\t.options { font-size: small; text-align:right }\n"
        "\t.string { color: #bb0000 }\n"
46
        "\tli { padding-left: 12px; padding-bottom: 4px; list-style-position: inside; }\n"
47
48
49
50
51
52
53
54
55
56
        "\t.exp { color: #000000 }\n"
        "\ta { color: #0000ff }\n"
        "\ta:link {text-decoration:none;}\n"
        "\ta:visited {text-decoration:none;}\n"
        "\ta:hover {text-decoration:underline;}\n"
        "\ta:active {text-decoration:underline;}\n"
        "\tp { font-size: " +QByteArray::number(QFontMetrics(QGuiApplication::font()).height())+ "px; }\n"
        "</style>\n"))

ConsoleModel::ConsoleModel(QObject* parent)
57
58
59
60
61
62
63
64
65
    : QObject(parent)
{
}

bool ConsoleModel::addOperation(const QString& input)
{
    return addOperation(Analitza::Expression(input), input);
}

66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
bool ConsoleModel::addOperation(const Analitza::Expression& e, const QString& input)
{
    Analitza::Expression res;

    a.setExpression(e);
    if(a.isCorrect()) {
        if (m_mode==ConsoleModel::Evaluation) {
            res=a.evaluate();
        } else {
            res=a.calculate();
        }
    }

    if(a.isCorrect()) {
        a.insertVariable(QStringLiteral("ans"), res);
        m_script += e; //Script won't have the errors
82
        Q_EMIT operationSuccessful(e, res);
83
84

        const auto result = res.toHtml();
85
        addMessage(QStringLiteral("<a title='%1' href='kalgebra:/query?id=copy&func=%2'><span class='exp'>%3</span></a><br />= <a title='kalgebra:%1' href='kalgebra:/query?id=copy&func=%4'><span class='result'>%5</span></a>")
86
                        .arg(i18n("Paste to Input"), e.toString(), e.toHtml(), res.toString(), result), e, res);
87
    } else {
88
        addMessage(i18n("<ul class='error'>Error: <b>%1</b><li>%2</li></ul>", input.toHtmlEscaped(), a.errors().join(QStringLiteral("</li>\n<li>"))), {}, {});
89
90
91
92
93
    }

    return a.isCorrect();
}

94
bool ConsoleModel::loadScript(const QUrl& path)
95
{
96
    Q_ASSERT(!path.isEmpty() && path.isLocalFile());
97
98
99

    //FIXME: We have expression-only script support
    bool correct=false;
100
    QFile file(path.toLocalFile());
101
102
103
104
105
106
107
108

    if(file.open(QIODevice::ReadOnly | QIODevice::Text)) {
        QTextStream stream(&file);

        a.importScript(&stream);
        correct=a.isCorrect();
    }

109
    if(correct)
110
        addMessage(i18n("Imported: %1", path.toDisplayString()), {}, {});
111
    else
112
        addMessage(i18n("<ul class='error'>Error: Could not load %1. <br /> %2</ul>", path.toDisplayString(), a.errors().join(QStringLiteral("<br/>"))), {}, {});
113
114
115
116

    return correct;
}

117
bool ConsoleModel::saveScript(const QUrl& savePath)
118
119
120
{
    Q_ASSERT(!savePath.isEmpty());

121
    QFile file(savePath.toLocalFile());
122
123
124
125
126
    bool correct=file.open(QIODevice::WriteOnly | QIODevice::Text);

    if(correct) {
        QTextStream out(&file);
        foreach(const Analitza::Expression& exp, m_script)
127
            out << exp.toString() << QLatin1Char('\n');
128
129
130
131
    }

    return correct;
}
132
133
134
135
136
137
138
139
140

void ConsoleModel::setMode(ConsoleMode mode)
{
    if (m_mode != mode) {
        m_mode = mode;
        Q_EMIT modeChanged(mode);
    }
}

141
142
143
144
void ConsoleModel::setVariables(const QSharedPointer<Analitza::Variables>& vars)
{
    a.setVariables(vars);
}
145

146
void ConsoleModel::addMessage(const QString& msg, const Analitza::Expression& operation, const Analitza::Expression& result)
147
148
149
{
    m_htmlLog += msg.toUtf8();
    Q_EMIT updateView();
150
    Q_EMIT message(msg, operation, result);
151
152
153
154
155
156
157
158
159
160
161
}

bool ConsoleModel::saveLog(const QUrl& savePath) const
{
    Q_ASSERT(savePath.isLocalFile());
    //FIXME: We have to choose between txt and html
    QFile file(savePath.toLocalFile());
    bool correct = file.open(QIODevice::WriteOnly | QIODevice::Text);

    if(correct) {
        QTextStream out(&file);
162
163
        out << "<html>\n<head>" << *s_css << "</head>" << QLatin1Char('\n');
        out << "<body>" << QLatin1Char('\n');
164
        foreach(const QString &entry, m_htmlLog)
165
166
            out << "<p>" << entry << "</p>" << QLatin1Char('\n');
        out << "</body>\n</html>" << QLatin1Char('\n');
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
    }

    return correct;
}

void ConsoleModel::clear()
{
    m_script.clear();
    m_htmlLog.clear();
}

QByteArray ConsoleModel::css() const
{
    return *s_css;
}