Statistics
| Branch: | Revision:

root / programs / qtjsruntime / pagerunner.cpp @ 62f4506a

History | View | Annotate | Download (6.1 kB)

1 9cf13184 Jos van den Oever
#include "pagerunner.h"
2 9cf13184 Jos van den Oever
3 9cf13184 Jos van den Oever
#include "nam.h"
4 9cf13184 Jos van den Oever
#include "nativeio.h"
5 9cf13184 Jos van den Oever
#include <QtCore/QFileInfo>
6 9cf13184 Jos van den Oever
#include <QtCore/QTemporaryFile>
7 9cf13184 Jos van den Oever
#include <QtCore/QTimer>
8 9cf13184 Jos van den Oever
#include <QtCore/QCoreApplication>
9 9cf13184 Jos van den Oever
#include <QtGui/QPainter>
10 9cf13184 Jos van den Oever
#include <QtGui/QPrinter>
11 9cf13184 Jos van den Oever
#include <QtWebKit/QWebFrame>
12 9cf13184 Jos van den Oever
13 9cf13184 Jos van den Oever
QByteArray getRuntimeBindings() {
14 9cf13184 Jos van den Oever
    return
15 9cf13184 Jos van den Oever
    "if (typeof(runtime) !== 'undefined') {"
16 9cf13184 Jos van den Oever
    "    runtime.readFileSync = function (path, encoding) {"
17 9cf13184 Jos van den Oever
    "        return nativeio.readFileSync(path, encoding);"
18 9cf13184 Jos van den Oever
    "    };"
19 9cf13184 Jos van den Oever
    "    runtime.read = function (path, offset, length, callback) {"
20 9cf13184 Jos van den Oever
    "        var data = nativeio.read(path, offset, length);"
21 9cf13184 Jos van den Oever
    "        data = runtime.byteArrayFromString(data, 'binary');"
22 9cf13184 Jos van den Oever
    "        callback(nativeio.error()||null, data);"
23 9cf13184 Jos van den Oever
    "    };"
24 9cf13184 Jos van den Oever
    "    runtime.writeFile = function (path, data, callback) {"
25 9cf13184 Jos van den Oever
    "        data = runtime.byteArrayToString(data, 'binary');"
26 9cf13184 Jos van den Oever
    "        nativeio.writeFile(path, data);"
27 9cf13184 Jos van den Oever
    "        callback(nativeio.error()||null);"
28 9cf13184 Jos van den Oever
    "    };"
29 9cf13184 Jos van den Oever
    "    runtime.deleteFile = function (path, callback) {"
30 9cf13184 Jos van den Oever
    "        nativeio.unlink(path);"
31 9cf13184 Jos van den Oever
    "        callback(nativeio.error()||null);"
32 9cf13184 Jos van den Oever
    "    };"
33 9cf13184 Jos van den Oever
    "    runtime.getFileSize = function (path, callback) {"
34 9cf13184 Jos van den Oever
    "        callback(nativeio.getFileSize(path));"
35 9cf13184 Jos van den Oever
    "    };"
36 9cf13184 Jos van den Oever
    "    runtime.exit = function (exitCode) {"
37 9cf13184 Jos van den Oever
    "        nativeio.exit(exitCode);"
38 9cf13184 Jos van den Oever
    "    };"
39 9cf13184 Jos van den Oever
    "}";
40 9cf13184 Jos van den Oever
}
41 9cf13184 Jos van den Oever
42 9cf13184 Jos van den Oever
PageRunner::PageRunner(const QStringList& args)
43 9cf13184 Jos van den Oever
    : QWebPage(0),
44 9cf13184 Jos van den Oever
      out(stdout),
45 9cf13184 Jos van den Oever
      err(stderr),
46 9cf13184 Jos van den Oever
      view(new QWidget()),
47 9cf13184 Jos van den Oever
      nativeio(new NativeIO(this)) {
48 9cf13184 Jos van den Oever
49 9cf13184 Jos van den Oever
    QMap<QString, QString> settings = parseArguments(args);
50 9cf13184 Jos van den Oever
    QStringList arguments = args.mid(settings.size() * 2);
51 9cf13184 Jos van den Oever
    exportpdf = settings.value("export-pdf");
52 9cf13184 Jos van den Oever
    exportpng = settings.value("export-png");
53 9cf13184 Jos van den Oever
    url = QUrl(arguments[0]);
54 9cf13184 Jos van den Oever
    if (url.scheme() == "file" || url.isRelative()) {
55 9cf13184 Jos van den Oever
        QFileInfo info(url.toLocalFile());
56 9cf13184 Jos van den Oever
        if (!info.isReadable() || !info.isFile()) {
57 9cf13184 Jos van den Oever
            QTextStream err(stderr);
58 9cf13184 Jos van den Oever
            err << "Cannot read file '" + url.toString() + "'.\n";
59 9cf13184 Jos van den Oever
            qApp->exit(1);
60 9cf13184 Jos van den Oever
        }
61 9cf13184 Jos van den Oever
    }
62 9cf13184 Jos van den Oever
    nam = new NAM(this, QUrl(url).host(), QUrl(url).port());
63 9cf13184 Jos van den Oever
64 9cf13184 Jos van den Oever
    setNetworkAccessManager(nam);
65 9cf13184 Jos van den Oever
    connect(this, SIGNAL(loadFinished(bool)), this, SLOT(finished(bool)));
66 9cf13184 Jos van den Oever
    connect(mainFrame(), SIGNAL(javaScriptWindowObjectCleared()),
67 9cf13184 Jos van den Oever
            this, SLOT(slotInitWindowObjects()));
68 9cf13184 Jos van den Oever
69 9cf13184 Jos van den Oever
    setView(view);
70 9cf13184 Jos van den Oever
    scriptMode = arguments[0].endsWith(".js");
71 9cf13184 Jos van den Oever
    if (scriptMode) {
72 9cf13184 Jos van den Oever
        QByteArray html = "'" + arguments[0].toUtf8().replace('\'', "\\'")
73 9cf13184 Jos van den Oever
                + "'";
74 9cf13184 Jos van den Oever
        for (int i = 1; i < arguments.length(); ++i) {
75 9cf13184 Jos van den Oever
            html += ",'" + arguments[i].toUtf8().replace('\'', "\\'") + "'";
76 9cf13184 Jos van den Oever
        }
77 9cf13184 Jos van den Oever
        html = "<html>"
78 9cf13184 Jos van den Oever
                "<head><base href=\".\"></base><title></title>"
79 9cf13184 Jos van den Oever
                "<script>var arguments=[" + html + "];</script>"
80 9cf13184 Jos van den Oever
                "<script src=\"" + arguments[0].toUtf8() + "\"></script>";
81 9cf13184 Jos van den Oever
        if (arguments[0].endsWith("runtime.js")) {
82 9cf13184 Jos van den Oever
            // add runtime modification
83 9cf13184 Jos van den Oever
            html += "<script>" + getRuntimeBindings() + "</script>";
84 9cf13184 Jos van den Oever
        }
85 9cf13184 Jos van den Oever
        html += "</head><body></body></html>\n";
86 9cf13184 Jos van den Oever
        QTemporaryFile tmp("XXXXXX.html");
87 9cf13184 Jos van den Oever
        tmp.setAutoRemove(true);
88 9cf13184 Jos van den Oever
        tmp.open();
89 9cf13184 Jos van den Oever
        tmp.write(html);
90 9cf13184 Jos van den Oever
        tmp.close();
91 9cf13184 Jos van den Oever
        mainFrame()->load(tmp.fileName());
92 9cf13184 Jos van den Oever
    } else {
93 9cf13184 Jos van den Oever
        // Make the url absolute. If it is not done here, QWebFrame will do
94 9cf13184 Jos van den Oever
        // it, and it will lose the query and fragment part.
95 9cf13184 Jos van den Oever
        QUrl absurl;
96 9cf13184 Jos van den Oever
        if (url.isRelative()) {
97 9cf13184 Jos van den Oever
            absurl = QUrl::fromLocalFile(QFileInfo(url.toLocalFile()).absoluteFilePath());
98 9cf13184 Jos van den Oever
            absurl.setQueryItems(url.queryItems());
99 9cf13184 Jos van den Oever
            absurl.setFragment(url.fragment());
100 9cf13184 Jos van den Oever
        } else {
101 9cf13184 Jos van den Oever
            absurl = url;
102 9cf13184 Jos van den Oever
        }
103 9cf13184 Jos van den Oever
        mainFrame()->load(absurl);
104 9cf13184 Jos van den Oever
    }
105 9cf13184 Jos van den Oever
}
106 9cf13184 Jos van den Oever
PageRunner::~PageRunner() {
107 9cf13184 Jos van den Oever
    delete view;
108 9cf13184 Jos van den Oever
}
109 9cf13184 Jos van den Oever
void PageRunner::finished(bool ok) {
110 9cf13184 Jos van den Oever
    // bind nativeio
111 9cf13184 Jos van den Oever
    if (!ok) {
112 9cf13184 Jos van den Oever
        qApp->exit(1);
113 9cf13184 Jos van den Oever
    }
114 9cf13184 Jos van den Oever
    mainFrame()->evaluateJavaScript(getRuntimeBindings());
115 9cf13184 Jos van den Oever
116 9cf13184 Jos van den Oever
    // connect signals
117 9cf13184 Jos van den Oever
    connect(this, SIGNAL(contentsChanged()), this, SLOT(noteChange()));
118 9cf13184 Jos van den Oever
    connect(this, SIGNAL(downloadRequested(QNetworkRequest)),
119 9cf13184 Jos van den Oever
            this, SLOT(noteChange()));
120 9cf13184 Jos van den Oever
    connect(this, SIGNAL(repaintRequested(QRect)),
121 9cf13184 Jos van den Oever
            this, SLOT(noteChange()));
122 9cf13184 Jos van den Oever
    connect(mainFrame(), SIGNAL(pageChanged()), this, SLOT(noteChange()));
123 9cf13184 Jos van den Oever
    connect(this, SIGNAL(geometryChangeRequested(QRect)),
124 9cf13184 Jos van den Oever
            this, SLOT(noteChange()));
125 9cf13184 Jos van den Oever
    QTimer::singleShot(150, this, SLOT(reallyFinished()));
126 9cf13184 Jos van den Oever
    changed = false;
127 9cf13184 Jos van den Oever
    time.start();
128 9cf13184 Jos van den Oever
}
129 9cf13184 Jos van den Oever
void PageRunner::reallyFinished() {
130 9cf13184 Jos van den Oever
    int latency = time.restart();
131 9cf13184 Jos van den Oever
    // err << latency << " " << changed << " " << nam->hasOutstandingRequests() << endl;
132 9cf13184 Jos van den Oever
    if (changed || latency >= 152 || nam->hasOutstandingRequests()) {
133 9cf13184 Jos van den Oever
        QTimer::singleShot(150, this, SLOT(reallyFinished()));
134 9cf13184 Jos van den Oever
        changed = false;
135 9cf13184 Jos van den Oever
        return;
136 9cf13184 Jos van den Oever
    }
137 9cf13184 Jos van den Oever
    if (!exportpdf.isEmpty() || !exportpng.isEmpty()) {
138 9cf13184 Jos van den Oever
        setViewportSize(mainFrame()->contentsSize());
139 9cf13184 Jos van den Oever
    }
140 9cf13184 Jos van den Oever
    if (!exportpng.isEmpty()) {
141 9cf13184 Jos van den Oever
        renderToFile(exportpng);
142 9cf13184 Jos van den Oever
    }
143 9cf13184 Jos van den Oever
    if (!exportpdf.isEmpty()) {
144 9cf13184 Jos van den Oever
        printToFile(exportpdf);
145 9cf13184 Jos van den Oever
    }
146 9cf13184 Jos van den Oever
    qApp->exit(0);
147 9cf13184 Jos van den Oever
}
148 9cf13184 Jos van den Oever
QMap<QString, QString> PageRunner::parseArguments(const QStringList& args) {
149 9cf13184 Jos van den Oever
    int i = 0;
150 9cf13184 Jos van den Oever
    QMap<QString, QString> settings;
151 9cf13184 Jos van den Oever
    while (i + 2 < args.length()) {
152 9cf13184 Jos van den Oever
        if (args[i].startsWith("--")) {
153 9cf13184 Jos van den Oever
            settings[args[i].mid(2)] = args[i+1];
154 9cf13184 Jos van den Oever
        }
155 9cf13184 Jos van den Oever
        i += 2;
156 9cf13184 Jos van den Oever
    }
157 9cf13184 Jos van den Oever
    return settings;
158 9cf13184 Jos van den Oever
}
159 9cf13184 Jos van den Oever
void PageRunner::slotInitWindowObjects() {
160 9cf13184 Jos van den Oever
    mainFrame()->addToJavaScriptWindowObject("nativeio", nativeio);
161 9cf13184 Jos van den Oever
}
162 9cf13184 Jos van den Oever
void PageRunner::renderToFile(const QString& filename) {
163 9cf13184 Jos van den Oever
    QImage pixmap(mainFrame()->contentsSize().boundedTo(QSize(10000,10000)),
164 9cf13184 Jos van den Oever
                  QImage::Format_ARGB32_Premultiplied);
165 9cf13184 Jos van den Oever
    QPainter painter(&pixmap);
166 9cf13184 Jos van den Oever
    mainFrame()->render(&painter, QWebFrame::ContentsLayer);
167 9cf13184 Jos van den Oever
    painter.end();
168 9cf13184 Jos van den Oever
    pixmap.save(filename);
169 9cf13184 Jos van den Oever
}
170 9cf13184 Jos van den Oever
void PageRunner::printToFile(const QString& filename) {
171 9cf13184 Jos van den Oever
    QPrinter printer(QPrinter::HighResolution);
172 62f4506a Jos van den Oever
    printer.setFontEmbeddingEnabled(true);
173 9cf13184 Jos van den Oever
    printer.setOutputFormat(QPrinter::PdfFormat);
174 9cf13184 Jos van den Oever
    printer.setOutputFileName(filename);
175 9cf13184 Jos van den Oever
    mainFrame()->print(&printer);
176 9cf13184 Jos van den Oever
}