1 /*
2     Actiona
3     Copyright (C) 2005 Jonathan Mercier-Ganady
4 
5     Actiona is free software: you can redistribute it and/or modify
6     it under the terms of the GNU General Public License as published by
7     the Free Software Foundation, either version 3 of the License, or
8     (at your option) any later version.
9 
10     Actiona 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.
14 
15     You should have received a copy of the GNU General Public License
16     along with this program. If not, see <http://www.gnu.org/licenses/>.
17 
18     Contact : jmgr@jmgr.info
19 */
20 
21 #include "prettyprinting.h"
22 
23 #include <QString>
24 #include <QScriptValue>
25 #include <QScriptValueIterator>
26 #include <QScriptContext>
27 #include <QScriptEngine>
28 
29 namespace Code
30 {
31     void prettyPrintScriptValue(QString &result, std::size_t tabCount, const QScriptValue &value, bool quoteString);
32 
prettyPrintArrayOrObject(QString & result,std::size_t tabCount,const QScriptValue & value)33     void prettyPrintArrayOrObject(QString &result, std::size_t tabCount, const QScriptValue &value)
34     {
35         bool isArray = value.isArray();
36 
37         result += isArray ? QStringLiteral("[\n") : QStringLiteral("{\n");
38 
39         ++tabCount;
40 
41         QScriptValueIterator it(value);
42         bool first{true};
43         while(it.hasNext())
44         {
45             it.next();
46 
47             if(it.flags() & QScriptValue::SkipInEnumeration)
48                 continue;
49 
50             if(first)
51                 first = false;
52             else
53                 result += QStringLiteral(",\n");
54 
55             for(std::size_t tabIndex{}; tabIndex < tabCount; ++tabIndex)
56                 result += QStringLiteral("    ");
57 
58             if(!isArray)
59                 result += it.name() + QStringLiteral(": ");
60 
61             prettyPrintScriptValue(result, tabCount, it.value(), true);
62         }
63 
64         result += QStringLiteral("\n");
65 
66         --tabCount;
67 
68         for(std::size_t tabIndex{}; tabIndex < tabCount; ++tabIndex)
69             result += QStringLiteral("    ");
70 
71         result += isArray ? QStringLiteral("]") : QStringLiteral("}");
72     }
73 
prettyPrintScriptValue(QString & result,std::size_t tabCount,const QScriptValue & value,bool quoteString)74     void prettyPrintScriptValue(QString &result, std::size_t tabCount, const QScriptValue &value, bool quoteString)
75     {
76         if(value.isQObject())
77             result += value.toString();
78         else if(value.isArray() || value.isObject())
79             prettyPrintArrayOrObject(result, tabCount, value);
80         else if(value.isString() && quoteString)
81             result += QStringLiteral("\"") + value.toString() + QStringLiteral("\"");
82         else
83             result += value.toString();
84     }
85 
toStringFunction(QScriptContext * context,QScriptEngine * engine)86     QScriptValue toStringFunction(QScriptContext *context, QScriptEngine *engine)
87     {
88         Q_UNUSED(engine)
89 
90         QString result;
91 
92         prettyPrintScriptValue(result, 0, context->thisObject(), false);
93 
94         return result;
95     }
96 
setupPrettyPrinting(QScriptEngine & scriptEngine)97     void setupPrettyPrinting(QScriptEngine &scriptEngine)
98     {
99         // Replace the default toString() functions for Array and Object with a more readable one
100 		QScriptValue arrayPrototypeScriptValue = scriptEngine.globalObject().property(QStringLiteral("Array")).property(QStringLiteral("prototype"));
101 		arrayPrototypeScriptValue.setProperty(QStringLiteral("toString"), scriptEngine.newFunction(toStringFunction));
102 		QScriptValue objectPrototypeScriptValue = scriptEngine.globalObject().property(QStringLiteral("Object")).property(QStringLiteral("prototype"));
103 		objectPrototypeScriptValue.setProperty(QStringLiteral("toString"), scriptEngine.newFunction(toStringFunction));
104     }
105 }
106