2011-04-08 20:55:10 +04:00
|
|
|
#include <iostream>
|
2011-04-08 17:30:50 +04:00
|
|
|
#include <QDebug>
|
2010-12-27 07:04:53 +03:00
|
|
|
|
2011-02-20 09:07:22 +03:00
|
|
|
#include <gifwriter.h>
|
2011-04-08 17:30:50 +04:00
|
|
|
#include "consts.h"
|
|
|
|
#include "utils.h"
|
2011-01-01 19:28:38 +03:00
|
|
|
|
2011-04-08 17:30:50 +04:00
|
|
|
#include "phantom.h"
|
2011-03-25 01:00:53 +03:00
|
|
|
|
2011-03-01 15:09:03 +03:00
|
|
|
#define JS_MOUSEEVENT_CLICK_WEBELEMENT "(function (target) { " \
|
|
|
|
"var evt = document.createEvent('MouseEvents');" \
|
|
|
|
"evt.initMouseEvent(\"click\", true, true, window, 0, 0, 0, 0, 0, false, false, false, false, 0, null);" \
|
|
|
|
"target.dispatchEvent(evt);" \
|
|
|
|
"})(this);"
|
2011-03-01 21:16:44 +03:00
|
|
|
#define JS_INCLUDE_SCRIPT_TAG "var el = document.createElement('script');" \
|
|
|
|
"el.onload = %2 || null;" \
|
|
|
|
"el.src = '%1';" \
|
|
|
|
"document.body.appendChild(el);"
|
2011-03-01 15:09:03 +03:00
|
|
|
|
2011-04-08 17:30:50 +04:00
|
|
|
#define PHANTOMJS_PDF_DPI 72 // Different defaults. OSX: 72, X11: 75(?), Windows: 96
|
2010-12-27 07:04:53 +03:00
|
|
|
|
2011-04-08 17:30:50 +04:00
|
|
|
// public:
|
2010-12-27 07:04:53 +03:00
|
|
|
Phantom::Phantom(QObject *parent)
|
|
|
|
: QObject(parent)
|
2011-03-14 07:35:05 +03:00
|
|
|
, m_proxyPort(1080)
|
2010-12-27 07:04:53 +03:00
|
|
|
, m_returnValue(0)
|
2011-03-02 11:41:23 +03:00
|
|
|
, m_converter(0)
|
2011-04-08 20:55:10 +04:00
|
|
|
, m_netAccessMan(0)
|
2010-12-27 07:04:53 +03:00
|
|
|
{
|
|
|
|
QPalette palette = m_page.palette();
|
|
|
|
palette.setBrush(QPalette::Base, Qt::transparent);
|
|
|
|
m_page.setPalette(palette);
|
|
|
|
|
2011-02-14 08:29:58 +03:00
|
|
|
bool autoLoadImages = true;
|
2011-03-01 02:17:59 +03:00
|
|
|
bool pluginsEnabled = false;
|
2011-02-14 08:29:58 +03:00
|
|
|
|
2010-12-27 07:04:53 +03:00
|
|
|
// second argument: script name
|
2011-02-14 07:41:59 +03:00
|
|
|
QStringList args = QApplication::arguments();
|
2011-02-13 22:38:09 +03:00
|
|
|
|
2011-02-14 07:41:59 +03:00
|
|
|
// Skip the first argument, i.e. the application executable (phantomjs).
|
|
|
|
args.removeFirst();
|
|
|
|
|
|
|
|
// Handle all command-line options.
|
|
|
|
QStringListIterator argIterator(args);
|
2011-02-06 21:55:04 +03:00
|
|
|
while (argIterator.hasNext()) {
|
|
|
|
const QString &arg = argIterator.next();
|
|
|
|
if (arg.startsWith("--upload-file") && argIterator.hasNext()) {
|
|
|
|
const QString &fileInfoString = argIterator.next();
|
|
|
|
QStringList fileInfo = fileInfoString.split("=");
|
|
|
|
const QString &tag = fileInfo.at(0);
|
|
|
|
const QString &fileName = fileInfo.at(1);
|
|
|
|
m_page.m_allowedFiles[tag] = fileName;
|
2011-02-14 07:41:59 +03:00
|
|
|
continue;
|
2011-02-06 21:55:04 +03:00
|
|
|
}
|
2011-02-14 08:29:58 +03:00
|
|
|
if (arg == "--load-images=yes") {
|
|
|
|
autoLoadImages = true;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
if (arg == "--load-images=no") {
|
|
|
|
autoLoadImages = false;
|
|
|
|
continue;
|
|
|
|
}
|
2011-02-14 09:44:00 +03:00
|
|
|
if (arg == "--load-plugins=yes") {
|
|
|
|
pluginsEnabled = true;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
if (arg == "--load-plugins=no") {
|
|
|
|
pluginsEnabled = false;
|
|
|
|
continue;
|
|
|
|
}
|
2011-03-14 07:35:05 +03:00
|
|
|
if (arg.startsWith("--proxy=")) {
|
|
|
|
m_proxyHost = arg.mid(8).trimmed();
|
|
|
|
if (m_proxyHost.lastIndexOf(':') > 0) {
|
|
|
|
bool ok = true;
|
|
|
|
int port = m_proxyHost.mid(m_proxyHost.lastIndexOf(':') + 1).toInt(&ok);
|
|
|
|
if (ok) {
|
|
|
|
m_proxyHost = m_proxyHost.left(m_proxyHost.lastIndexOf(':')).trimmed();
|
|
|
|
m_proxyPort = port;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
continue;
|
|
|
|
}
|
2011-02-14 07:41:59 +03:00
|
|
|
if (arg.startsWith("--")) {
|
2011-04-08 18:49:20 +04:00
|
|
|
qFatal("Unknown option '%s'", qPrintable(arg));
|
2011-02-14 07:41:59 +03:00
|
|
|
exit(-1);
|
|
|
|
return;
|
|
|
|
} else {
|
|
|
|
m_scriptFile = arg;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (m_scriptFile.isEmpty()) {
|
2011-04-08 17:30:50 +04:00
|
|
|
Utils::showUsage();
|
2011-02-14 07:41:59 +03:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2011-03-14 07:35:05 +03:00
|
|
|
if (m_proxyHost.isEmpty()) {
|
|
|
|
QNetworkProxyFactory::setUseSystemConfiguration(true);
|
|
|
|
} else {
|
|
|
|
QNetworkProxy proxy(QNetworkProxy::HttpProxy, m_proxyHost, m_proxyPort);
|
|
|
|
QNetworkProxy::setApplicationProxy(proxy);
|
|
|
|
}
|
|
|
|
|
2011-02-14 08:29:58 +03:00
|
|
|
// The remaining arguments are available for the script.
|
2011-02-14 07:41:59 +03:00
|
|
|
while (argIterator.hasNext()) {
|
|
|
|
const QString &arg = argIterator.next();
|
|
|
|
m_args += arg;
|
2011-02-06 21:55:04 +03:00
|
|
|
}
|
2010-12-27 07:04:53 +03:00
|
|
|
|
2011-04-08 20:55:10 +04:00
|
|
|
// Provide WebPage with a non-standard Network Access Manager
|
|
|
|
m_netAccessMan = new NetworkAccessManager(this);
|
|
|
|
m_page.setNetworkAccessManager(m_netAccessMan);
|
|
|
|
|
2010-12-27 07:04:53 +03:00
|
|
|
connect(m_page.mainFrame(), SIGNAL(javaScriptWindowObjectCleared()), SLOT(inject()));
|
|
|
|
connect(&m_page, SIGNAL(loadFinished(bool)), this, SLOT(finish(bool)));
|
|
|
|
|
2011-02-14 08:29:58 +03:00
|
|
|
m_page.settings()->setAttribute(QWebSettings::AutoLoadImages, autoLoadImages);
|
2011-02-14 09:44:00 +03:00
|
|
|
m_page.settings()->setAttribute(QWebSettings::PluginsEnabled, pluginsEnabled);
|
|
|
|
|
2010-12-27 07:04:53 +03:00
|
|
|
m_page.settings()->setAttribute(QWebSettings::OfflineStorageDatabaseEnabled, true);
|
|
|
|
m_page.settings()->setOfflineStoragePath(QDesktopServices::storageLocation(QDesktopServices::DataLocation));
|
2010-12-28 11:05:50 +03:00
|
|
|
|
2011-01-28 03:51:43 +03:00
|
|
|
m_page.settings()->setAttribute(QWebSettings::LocalStorageDatabaseEnabled, true);
|
2011-01-30 06:13:19 +03:00
|
|
|
|
2011-01-30 06:17:10 +03:00
|
|
|
#if QT_VERSION >= QT_VERSION_CHECK(4, 7, 0)
|
2011-01-28 03:51:43 +03:00
|
|
|
m_page.settings()->setAttribute(QWebSettings::FrameFlatteningEnabled, true);
|
2011-01-30 06:17:10 +03:00
|
|
|
#endif
|
|
|
|
|
|
|
|
#if QT_VERSION >= QT_VERSION_CHECK(4, 6, 0)
|
2011-01-28 03:51:43 +03:00
|
|
|
m_page.settings()->setAttribute(QWebSettings::LocalStorageEnabled, true);
|
|
|
|
m_page.settings()->setLocalStoragePath(QDesktopServices::storageLocation(QDesktopServices::DataLocation));
|
|
|
|
#endif
|
2011-01-28 02:53:51 +03:00
|
|
|
|
2010-12-28 11:05:50 +03:00
|
|
|
// Ensure we have document.body.
|
|
|
|
m_page.mainFrame()->setHtml("<html><body></body></html>");
|
2010-12-31 20:20:19 +03:00
|
|
|
|
|
|
|
m_page.mainFrame()->setScrollBarPolicy(Qt::Horizontal, Qt::ScrollBarAlwaysOff);
|
|
|
|
m_page.mainFrame()->setScrollBarPolicy(Qt::Vertical, Qt::ScrollBarAlwaysOff);
|
2010-12-27 07:04:53 +03:00
|
|
|
}
|
|
|
|
|
2011-01-15 09:24:47 +03:00
|
|
|
QStringList Phantom::args() const
|
2010-12-27 07:04:53 +03:00
|
|
|
{
|
2011-02-13 22:38:09 +03:00
|
|
|
return m_args;
|
2010-12-27 07:04:53 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
QString Phantom::content() const
|
|
|
|
{
|
|
|
|
return m_page.mainFrame()->toHtml();
|
|
|
|
}
|
|
|
|
|
|
|
|
void Phantom::setContent(const QString &content)
|
|
|
|
{
|
|
|
|
m_page.mainFrame()->setHtml(content);
|
|
|
|
}
|
|
|
|
|
2011-02-14 07:41:59 +03:00
|
|
|
bool Phantom::execute()
|
2010-12-27 07:04:53 +03:00
|
|
|
{
|
2011-02-14 07:41:59 +03:00
|
|
|
if (m_scriptFile.isEmpty())
|
|
|
|
return false;
|
|
|
|
|
2010-12-27 07:04:53 +03:00
|
|
|
QFile file;
|
2011-02-14 07:41:59 +03:00
|
|
|
file.setFileName(m_scriptFile);
|
2010-12-27 07:04:53 +03:00
|
|
|
if (!file.open(QFile::ReadOnly)) {
|
2011-04-08 20:55:10 +04:00
|
|
|
std::cerr << "Can't open '" << qPrintable(m_scriptFile) << "'" << std::endl << std::endl;
|
2010-12-28 02:26:08 +03:00
|
|
|
exit(1);
|
2011-02-14 07:41:59 +03:00
|
|
|
return false;
|
2010-12-27 07:04:53 +03:00
|
|
|
}
|
2011-03-25 01:43:49 +03:00
|
|
|
m_script = QString::fromUtf8(file.readAll());
|
2010-12-27 07:04:53 +03:00
|
|
|
file.close();
|
2011-02-13 22:38:09 +03:00
|
|
|
|
2011-02-06 15:53:30 +03:00
|
|
|
if (m_script.startsWith("#!")) {
|
|
|
|
m_script.prepend("//");
|
|
|
|
}
|
2010-12-27 07:04:53 +03:00
|
|
|
|
2011-03-02 11:41:23 +03:00
|
|
|
if (m_scriptFile.endsWith(".coffee")) {
|
|
|
|
if (!m_converter)
|
|
|
|
m_converter = new CSConverter(this);
|
|
|
|
m_script = m_converter->convert(m_script);
|
|
|
|
}
|
|
|
|
|
2010-12-27 07:04:53 +03:00
|
|
|
m_page.mainFrame()->evaluateJavaScript(m_script);
|
2011-02-14 07:41:59 +03:00
|
|
|
return true;
|
2010-12-27 07:04:53 +03:00
|
|
|
}
|
|
|
|
|
2011-04-08 17:30:50 +04:00
|
|
|
int Phantom::returnValue() const
|
2010-12-27 07:04:53 +03:00
|
|
|
{
|
2011-04-08 17:30:50 +04:00
|
|
|
return m_returnValue;
|
2010-12-27 07:04:53 +03:00
|
|
|
}
|
|
|
|
|
2011-04-08 17:30:50 +04:00
|
|
|
QString Phantom::loadStatus() const
|
2010-12-27 07:04:53 +03:00
|
|
|
{
|
2011-04-08 17:30:50 +04:00
|
|
|
return m_loadStatus;
|
2010-12-27 07:04:53 +03:00
|
|
|
}
|
|
|
|
|
2011-04-08 17:30:50 +04:00
|
|
|
void Phantom::setState(const QString &value)
|
2010-12-27 07:04:53 +03:00
|
|
|
{
|
2011-04-08 17:30:50 +04:00
|
|
|
m_state = value;
|
2010-12-27 07:04:53 +03:00
|
|
|
}
|
|
|
|
|
2011-04-08 17:30:50 +04:00
|
|
|
QString Phantom::state() const
|
2010-12-27 07:04:53 +03:00
|
|
|
{
|
2011-04-08 17:30:50 +04:00
|
|
|
return m_state;
|
|
|
|
}
|
|
|
|
|
|
|
|
void Phantom::setUserAgent(const QString &ua)
|
|
|
|
{
|
|
|
|
m_page.m_userAgent = ua;
|
|
|
|
}
|
|
|
|
|
|
|
|
QString Phantom::userAgent() const
|
|
|
|
{
|
|
|
|
return m_page.m_userAgent;
|
|
|
|
}
|
|
|
|
|
|
|
|
QVariantMap Phantom::version() const
|
|
|
|
{
|
|
|
|
QVariantMap result;
|
|
|
|
result["major"] = PHANTOMJS_VERSION_MAJOR;
|
|
|
|
result["minor"] = PHANTOMJS_VERSION_MINOR;
|
|
|
|
result["patch"] = PHANTOMJS_VERSION_PATCH;
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
void Phantom::setViewportSize(const QVariantMap &size)
|
|
|
|
{
|
|
|
|
int w = size.value("width").toInt();
|
|
|
|
int h = size.value("height").toInt();
|
|
|
|
if (w > 0 && h > 0)
|
|
|
|
m_page.setViewportSize(QSize(w, h));
|
|
|
|
}
|
|
|
|
|
|
|
|
QVariantMap Phantom::viewportSize() const
|
|
|
|
{
|
|
|
|
QVariantMap result;
|
|
|
|
QSize size = m_page.viewportSize();
|
|
|
|
result["width"] = size.width();
|
|
|
|
result["height"] = size.height();
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
void Phantom::setClipRect(const QVariantMap &size)
|
|
|
|
{
|
|
|
|
int w = size.value("width").toInt();
|
|
|
|
int h = size.value("height").toInt();
|
|
|
|
int top = size.value("top").toInt();
|
|
|
|
int left = size.value("left").toInt();
|
|
|
|
|
|
|
|
if (w > 0 && h > 0)
|
|
|
|
m_clipRect = QRect(left, top, w, h);
|
|
|
|
}
|
|
|
|
|
|
|
|
QVariantMap Phantom::clipRect() const
|
|
|
|
{
|
|
|
|
QVariantMap result;
|
|
|
|
result["width"] = m_clipRect.width();
|
|
|
|
result["height"] = m_clipRect.height();
|
|
|
|
result["top"] = m_clipRect.top();
|
|
|
|
result["left"] = m_clipRect.left();
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
void Phantom::setPaperSize(const QVariantMap &size)
|
|
|
|
{
|
|
|
|
m_paperSize = size;
|
|
|
|
}
|
|
|
|
|
|
|
|
QVariantMap Phantom::paperSize() const
|
|
|
|
{
|
|
|
|
return m_paperSize;
|
|
|
|
}
|
|
|
|
|
|
|
|
// public slots:
|
|
|
|
void Phantom::exit(int code)
|
|
|
|
{
|
|
|
|
m_returnValue = code;
|
|
|
|
disconnect(&m_page, SIGNAL(loadFinished(bool)), this, SLOT(finish(bool)));
|
|
|
|
QTimer::singleShot(0, qApp, SLOT(quit()));
|
2010-12-27 07:04:53 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
void Phantom::open(const QString &address)
|
|
|
|
{
|
2011-03-01 21:16:44 +03:00
|
|
|
qDebug() << "Opening address: " << qPrintable(address);
|
2010-12-27 07:04:53 +03:00
|
|
|
m_page.triggerAction(QWebPage::Stop);
|
|
|
|
m_loadStatus = "loading";
|
2011-03-01 15:09:03 +03:00
|
|
|
m_page.mainFrame()->load(address);
|
2010-12-27 07:04:53 +03:00
|
|
|
}
|
|
|
|
|
2011-01-01 04:07:25 +03:00
|
|
|
bool Phantom::render(const QString &fileName)
|
|
|
|
{
|
2011-01-02 07:18:39 +03:00
|
|
|
QFileInfo fileInfo(fileName);
|
|
|
|
QDir dir;
|
|
|
|
dir.mkpath(fileInfo.absolutePath());
|
|
|
|
|
Issue 17: Make paper size for the PDF export specifiable
http://code.google.com/p/phantomjs/issues/detail?id=17
Adding a new phantom property called "paperSize". It takes one of
the two possible dictionary variants:
{ width: '200px', height: '300px', border: '0px' }
{ format: 'A4', orientation: 'portrait', border: '1cm' }
- If no paperSize is defined, the size is defined by the web page
- supported dimension units are: mm, cm, in, px. No unit means px.
- border is optional and defaults to 0.
- supported formats are: A3, A4, A5, Legal, Letter, Tabloid
- orientation (portrait|landscape) is optional and defaults to portrait
I'm considering implementing a short form like:
phantom.paperSize = 'A4';
...needs further investigation.
2011-03-18 12:26:45 +03:00
|
|
|
if (fileName.endsWith(".pdf", Qt::CaseInsensitive))
|
|
|
|
return renderPdf(fileName);
|
2011-01-02 07:18:39 +03:00
|
|
|
|
2011-01-01 04:07:25 +03:00
|
|
|
QSize viewportSize = m_page.viewportSize();
|
2011-04-08 17:30:50 +04:00
|
|
|
|
|
|
|
QSize pageSize = m_page.mainFrame()->contentsSize();
|
|
|
|
|
2011-03-29 23:01:40 +04:00
|
|
|
QSize bufferSize;
|
2011-03-30 10:18:47 +04:00
|
|
|
if (!m_clipRect.isEmpty()) {
|
|
|
|
bufferSize = m_clipRect.size();
|
2011-03-29 23:01:40 +04:00
|
|
|
} else {
|
2011-03-30 10:18:47 +04:00
|
|
|
bufferSize = m_page.mainFrame()->contentsSize();
|
2011-03-29 23:01:40 +04:00
|
|
|
}
|
2011-04-08 17:30:50 +04:00
|
|
|
|
2011-01-01 04:07:25 +03:00
|
|
|
if (pageSize.isEmpty())
|
|
|
|
return false;
|
|
|
|
|
2011-03-29 23:01:40 +04:00
|
|
|
QImage buffer(bufferSize, QImage::Format_ARGB32);
|
2011-01-27 18:54:46 +03:00
|
|
|
buffer.fill(qRgba(255, 255, 255, 0));
|
2011-01-01 04:07:25 +03:00
|
|
|
QPainter p(&buffer);
|
2011-04-08 17:30:50 +04:00
|
|
|
|
2011-01-01 04:07:25 +03:00
|
|
|
p.setRenderHint(QPainter::Antialiasing, true);
|
|
|
|
p.setRenderHint(QPainter::TextAntialiasing, true);
|
|
|
|
p.setRenderHint(QPainter::SmoothPixmapTransform, true);
|
2011-03-29 23:01:40 +04:00
|
|
|
|
2011-01-01 04:07:25 +03:00
|
|
|
m_page.setViewportSize(pageSize);
|
2011-04-08 17:30:50 +04:00
|
|
|
|
2011-03-30 10:18:47 +04:00
|
|
|
if (!m_clipRect.isEmpty()) {
|
|
|
|
p.translate(-m_clipRect.left(), -m_clipRect.top());
|
|
|
|
m_page.mainFrame()->render(&p, QRegion(m_clipRect));
|
2011-03-29 23:01:40 +04:00
|
|
|
} else {
|
2011-03-30 10:18:47 +04:00
|
|
|
m_page.mainFrame()->render(&p);
|
2011-03-29 23:01:40 +04:00
|
|
|
}
|
2011-04-08 17:30:50 +04:00
|
|
|
|
2011-01-01 04:07:25 +03:00
|
|
|
p.end();
|
|
|
|
m_page.setViewportSize(viewportSize);
|
2011-02-20 09:07:22 +03:00
|
|
|
|
|
|
|
if (fileName.toLower().endsWith(".gif")) {
|
|
|
|
return exportGif(buffer, fileName);
|
|
|
|
}
|
|
|
|
|
2011-01-01 04:07:25 +03:00
|
|
|
return buffer.save(fileName);
|
|
|
|
}
|
|
|
|
|
2010-12-27 07:04:53 +03:00
|
|
|
void Phantom::sleep(int ms)
|
|
|
|
{
|
|
|
|
QTime startTime = QTime::currentTime();
|
|
|
|
while (true) {
|
|
|
|
QApplication::processEvents(QEventLoop::AllEvents, 25);
|
|
|
|
if (startTime.msecsTo(QTime::currentTime()) > ms)
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-02-13 22:38:09 +03:00
|
|
|
void Phantom::setFormInputFile(QWebElement el, const QString &fileTag)
|
|
|
|
{
|
2011-02-06 21:55:04 +03:00
|
|
|
m_page.m_nextFileTag = fileTag;
|
2011-03-01 15:09:03 +03:00
|
|
|
el.evaluateJavaScript(JS_MOUSEEVENT_CLICK_WEBELEMENT);
|
2011-02-06 21:55:04 +03:00
|
|
|
}
|
|
|
|
|
2011-03-01 15:09:03 +03:00
|
|
|
void Phantom::simulateMouseClick(const QString &selector) {
|
|
|
|
// Execute the equivalent of "querySelectorAll"
|
|
|
|
QWebElementCollection webElements = m_page.currentFrame()->findAllElements(selector);
|
|
|
|
// Click on every one of the elements
|
|
|
|
foreach ( QWebElement el, webElements ) {
|
2011-03-01 21:16:44 +03:00
|
|
|
qDebug() << "Element Clicked Center Position: " << el.geometry().center().x() << "," << el.geometry().center().y();
|
2011-03-01 15:09:03 +03:00
|
|
|
el.evaluateJavaScript(JS_MOUSEEVENT_CLICK_WEBELEMENT);
|
|
|
|
}
|
|
|
|
}
|
2011-02-06 21:55:04 +03:00
|
|
|
|
2011-03-01 21:16:44 +03:00
|
|
|
bool Phantom::loadJs(const QString &jsFilePath) {
|
|
|
|
qDebug() << "Loading JS File: " << jsFilePath;
|
|
|
|
if ( !jsFilePath.isEmpty()) {
|
|
|
|
QFile jsFile;
|
|
|
|
|
|
|
|
jsFile.setFileName(jsFilePath);
|
|
|
|
if ( !jsFile.open(QFile::ReadOnly) ) {
|
|
|
|
qWarning() << "Can't load Javascript File: " << qPrintable(jsFilePath);
|
|
|
|
} else {
|
|
|
|
QString script = QString::fromUtf8(jsFile.readAll());
|
|
|
|
jsFile.close();
|
|
|
|
// Execute JS code in the context of the document
|
|
|
|
m_page.mainFrame()->evaluateJavaScript(script);
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
void Phantom::includeJs(const QString &jsFilePath, const QString &callback) {
|
2011-03-04 13:13:32 +03:00
|
|
|
qDebug() << "Including JS File:" << jsFilePath << "- Callback:" << callback;
|
2011-03-01 21:16:44 +03:00
|
|
|
m_page.mainFrame()->evaluateJavaScript(QString(JS_INCLUDE_SCRIPT_TAG).arg(jsFilePath, callback));
|
|
|
|
}
|
|
|
|
|
2011-04-08 17:30:50 +04:00
|
|
|
// private slots:
|
|
|
|
void Phantom::finish(bool success)
|
Issue 17: Make paper size for the PDF export specifiable
http://code.google.com/p/phantomjs/issues/detail?id=17
Adding a new phantom property called "paperSize". It takes one of
the two possible dictionary variants:
{ width: '200px', height: '300px', border: '0px' }
{ format: 'A4', orientation: 'portrait', border: '1cm' }
- If no paperSize is defined, the size is defined by the web page
- supported dimension units are: mm, cm, in, px. No unit means px.
- border is optional and defaults to 0.
- supported formats are: A3, A4, A5, Legal, Letter, Tabloid
- orientation (portrait|landscape) is optional and defaults to portrait
I'm considering implementing a short form like:
phantom.paperSize = 'A4';
...needs further investigation.
2011-03-18 12:26:45 +03:00
|
|
|
{
|
2011-04-08 17:30:50 +04:00
|
|
|
m_loadStatus = success ? "success" : "fail";
|
|
|
|
m_page.mainFrame()->evaluateJavaScript(m_script);
|
Issue 17: Make paper size for the PDF export specifiable
http://code.google.com/p/phantomjs/issues/detail?id=17
Adding a new phantom property called "paperSize". It takes one of
the two possible dictionary variants:
{ width: '200px', height: '300px', border: '0px' }
{ format: 'A4', orientation: 'portrait', border: '1cm' }
- If no paperSize is defined, the size is defined by the web page
- supported dimension units are: mm, cm, in, px. No unit means px.
- border is optional and defaults to 0.
- supported formats are: A3, A4, A5, Legal, Letter, Tabloid
- orientation (portrait|landscape) is optional and defaults to portrait
I'm considering implementing a short form like:
phantom.paperSize = 'A4';
...needs further investigation.
2011-03-18 12:26:45 +03:00
|
|
|
}
|
|
|
|
|
2011-04-08 17:30:50 +04:00
|
|
|
void Phantom::inject()
|
Issue 17: Make paper size for the PDF export specifiable
http://code.google.com/p/phantomjs/issues/detail?id=17
Adding a new phantom property called "paperSize". It takes one of
the two possible dictionary variants:
{ width: '200px', height: '300px', border: '0px' }
{ format: 'A4', orientation: 'portrait', border: '1cm' }
- If no paperSize is defined, the size is defined by the web page
- supported dimension units are: mm, cm, in, px. No unit means px.
- border is optional and defaults to 0.
- supported formats are: A3, A4, A5, Legal, Letter, Tabloid
- orientation (portrait|landscape) is optional and defaults to portrait
I'm considering implementing a short form like:
phantom.paperSize = 'A4';
...needs further investigation.
2011-03-18 12:26:45 +03:00
|
|
|
{
|
2011-04-08 17:30:50 +04:00
|
|
|
m_page.mainFrame()->addToJavaScriptWindowObject("phantom", this);
|
Issue 17: Make paper size for the PDF export specifiable
http://code.google.com/p/phantomjs/issues/detail?id=17
Adding a new phantom property called "paperSize". It takes one of
the two possible dictionary variants:
{ width: '200px', height: '300px', border: '0px' }
{ format: 'A4', orientation: 'portrait', border: '1cm' }
- If no paperSize is defined, the size is defined by the web page
- supported dimension units are: mm, cm, in, px. No unit means px.
- border is optional and defaults to 0.
- supported formats are: A3, A4, A5, Legal, Letter, Tabloid
- orientation (portrait|landscape) is optional and defaults to portrait
I'm considering implementing a short form like:
phantom.paperSize = 'A4';
...needs further investigation.
2011-03-18 12:26:45 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
bool Phantom::renderPdf(const QString &fileName)
|
|
|
|
{
|
|
|
|
QPrinter printer;
|
|
|
|
printer.setOutputFormat(QPrinter::PdfFormat);
|
|
|
|
printer.setOutputFileName(fileName);
|
|
|
|
printer.setResolution(PHANTOMJS_PDF_DPI);
|
|
|
|
QVariantMap paperSize = m_paperSize;
|
|
|
|
|
|
|
|
if (paperSize.isEmpty()) {
|
|
|
|
const QSize pageSize = m_page.mainFrame()->contentsSize();
|
|
|
|
paperSize.insert("width", QString::number(pageSize.width()) + "px");
|
|
|
|
paperSize.insert("height", QString::number(pageSize.height()) + "px");
|
|
|
|
paperSize.insert("border", "0px");
|
|
|
|
}
|
|
|
|
|
|
|
|
if (paperSize.contains("width") && paperSize.contains("height")) {
|
|
|
|
const QSizeF sizePt(ceil(stringToPointSize(paperSize.value("width").toString())),
|
|
|
|
ceil(stringToPointSize(paperSize.value("height").toString())));
|
|
|
|
printer.setPaperSize(sizePt, QPrinter::Point);
|
|
|
|
} else if (paperSize.contains("format")) {
|
|
|
|
const QPrinter::Orientation orientation = paperSize.contains("orientation")
|
|
|
|
&& paperSize.value("orientation").toString().compare("landscape", Qt::CaseInsensitive) == 0 ?
|
|
|
|
QPrinter::Landscape : QPrinter::Portrait;
|
|
|
|
printer.setOrientation(orientation);
|
|
|
|
static const struct {
|
|
|
|
QString format;
|
|
|
|
QPrinter::PaperSize paperSize;
|
|
|
|
} formats[] = {
|
|
|
|
{ "A3", QPrinter::A3 },
|
|
|
|
{ "A4", QPrinter::A4 },
|
|
|
|
{ "A5", QPrinter::A5 },
|
|
|
|
{ "Legal", QPrinter::Legal },
|
|
|
|
{ "Letter", QPrinter::Letter },
|
|
|
|
{ "Tabloid", QPrinter::Tabloid }
|
|
|
|
};
|
|
|
|
printer.setPaperSize(QPrinter::A4); // Fallback
|
|
|
|
for (uint i = 0; i < sizeof(formats) / sizeof(formats[0]); ++i) {
|
|
|
|
if (paperSize.value("format").toString().compare(formats[i].format, Qt::CaseInsensitive) == 0) {
|
|
|
|
printer.setPaperSize(formats[i].paperSize);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
const qreal border = paperSize.contains("border") ?
|
|
|
|
floor(stringToPointSize(paperSize.value("border").toString())) : 0;
|
|
|
|
printer.setPageMargins(border, border, border, border, QPrinter::Point);
|
|
|
|
|
|
|
|
m_page.mainFrame()->print(&printer);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2011-04-08 17:30:50 +04:00
|
|
|
// private:
|
|
|
|
qreal Phantom::stringToPointSize(const QString &string)
|
2010-12-27 07:04:53 +03:00
|
|
|
{
|
2011-04-08 17:30:50 +04:00
|
|
|
static const struct {
|
|
|
|
QString unit;
|
|
|
|
qreal factor;
|
|
|
|
} units[] = {
|
|
|
|
{ "mm", 72 / 25.4 },
|
|
|
|
{ "cm", 72 / 2.54 },
|
|
|
|
{ "in", 72 },
|
|
|
|
{ "px", 72.0 / PHANTOMJS_PDF_DPI / 2.54 },
|
|
|
|
{ "", 72.0 / PHANTOMJS_PDF_DPI / 2.54 }
|
|
|
|
};
|
|
|
|
for (uint i = 0; i < sizeof(units) / sizeof(units[0]); ++i) {
|
|
|
|
if (string.endsWith(units[i].unit)) {
|
|
|
|
QString value = string;
|
|
|
|
value.chop(units[i].unit.length());
|
|
|
|
return value.toDouble() * units[i].factor;
|
|
|
|
}
|
2011-02-14 07:41:59 +03:00
|
|
|
}
|
2011-04-08 17:30:50 +04:00
|
|
|
return 0;
|
2010-12-27 07:04:53 +03:00
|
|
|
}
|