ehancing marging parsing, again
[web2pdf:web2pdf.git] / WEB2PDF.cpp
1 #include "WEB2PDF.h"
2
3 WebPage::WebPage(QObject * parent) : QWebPage(parent)
4 {
5     this->m_prolix = false;
6     this->m_userAgent = QWebPage::userAgentForUrl(QUrl());
7 }
8
9 QString WebPage::chooseFile(QWebFrame * parentFrame, const QString & suggestedFile)
10 { // disable choosing file.
11     Q_UNUSED(parentFrame)
12     Q_UNUSED(suggestedFile)
13
14     return this->m_choosenFile;
15 }
16
17 QObject * WebPage::createPlugin(const QString & classid, const QUrl & url,
18                                 const QStringList & paramNames,
19                                 const QStringList & paramValues)
20 { // disable usage of plugins such as 'application/x-qt-plugin'
21     Q_UNUSED(classid)
22     Q_UNUSED(url)
23     Q_UNUSED(paramNames)
24     Q_UNUSED(paramValues)
25
26     return NULL;
27 }
28
29 QWebPage * WebPage::createWindow(WebWindowType type)
30 { // disable window creation
31     Q_UNUSED(type)
32
33     return NULL;
34 }
35
36 void WebPage::javaScriptAlert(QWebFrame * frame, const QString & msg)
37 {
38     Q_UNUSED(frame);
39
40     if(!this->m_prolix)
41         qDebug("An alert was prompted: %s", qPrintable(msg));
42 }
43
44 bool WebPage::javaScriptConfirm(QWebFrame * frame, const QString & msg)
45 {
46     Q_UNUSED(frame);
47
48     if(!this->m_prolix)
49         qDebug("A confirmation was prompted: %s (ignoring, and returning false)", qPrintable(msg));
50     return false;
51 }
52
53 bool WebPage::javaScriptPrompt(QWebFrame * frame, const QString & msg, const QString & defaultValue,
54                                QString * result)
55 {
56     Q_UNUSED(frame);
57     Q_UNUSED(result);
58
59     if(!this->m_prolix)
60         qDebug("A prompt box was prompted: %s (default: %s) (ignoring, and returning false)",
61                qPrintable(msg), qPrintable(defaultValue));
62     return false;
63 }
64
65 QString WebPage::userAgentForUrl(const QUrl & url) const
66 {
67     Q_UNUSED(url);
68     return this->m_userAgent;
69 }
70
71 void WebPage::setChoosenFile(const QString & file)
72 {
73     this->m_choosenFile = file;
74 }
75
76 void WebPage::setUserAgent(const QString & userAgent)
77 {
78     this->m_userAgent = userAgent;
79 }
80
81 void WebPage::setProlix()
82 {
83     this->m_prolix = true;
84 }
85
86 // -------------------------------------------------------------------------------------------------
87
88 WEB2PDF::WEB2PDF() {
89     this->m_prolix = false;
90     this->m_hasAnOutputFile = false;
91
92     this->m_webview.setPage(&this->m_webpage);
93
94     this->m_printer.setColorMode(QPrinter::Color);
95     this->m_printer.setCreator("WEB2PDF");
96     this->m_printer.setDocName("WEB2PDF");
97     this->m_printer.setOrientation(QPrinter::Portrait);
98     this->m_printer.setOutputFormat(QPrinter::PdfFormat);
99     this->m_printer.setPageSize(QPrinter::A4);
100
101     this->connect(&this->m_webview, SIGNAL(loadFinished(bool)), this, SLOT(loadDone(bool)));
102     this->connect(this->m_webview.page()->networkAccessManager(),
103                   SIGNAL(sslErrors(QNetworkReply *, QList<QSslError>)),
104                   this, SLOT(treatSslError(QNetworkReply *, QList<QSslError>)));
105
106     this->m_formatHash[QString("A0").toLower()] = QPrinter::A0;
107     this->m_formatHash[QString("A1").toLower()] = QPrinter::A1;
108     this->m_formatHash[QString("A2").toLower()] = QPrinter::A2;
109     this->m_formatHash[QString("A3").toLower()] = QPrinter::A3;
110     this->m_formatHash[QString("A4").toLower()] = QPrinter::A4;
111     this->m_formatHash[QString("A5").toLower()] = QPrinter::A5;
112     this->m_formatHash[QString("A6").toLower()] = QPrinter::A6;
113     this->m_formatHash[QString("A7").toLower()] = QPrinter::A7;
114     this->m_formatHash[QString("A8").toLower()] = QPrinter::A8;
115     this->m_formatHash[QString("A9").toLower()] = QPrinter::A9;
116     this->m_formatHash[QString("B0").toLower()] = QPrinter::B0;
117     this->m_formatHash[QString("B1").toLower()] = QPrinter::B1;
118     this->m_formatHash[QString("B2").toLower()] = QPrinter::B2;
119     this->m_formatHash[QString("B3").toLower()] = QPrinter::B3;
120     this->m_formatHash[QString("B4").toLower()] = QPrinter::B4;
121     this->m_formatHash[QString("B5").toLower()] = QPrinter::B5;
122     this->m_formatHash[QString("B6").toLower()] = QPrinter::B6;
123     this->m_formatHash[QString("B7").toLower()] = QPrinter::B7;
124     this->m_formatHash[QString("B8").toLower()] = QPrinter::B8;
125     this->m_formatHash[QString("B9").toLower()] = QPrinter::B9;
126     this->m_formatHash[QString("B10").toLower()] = QPrinter::B10;
127     this->m_formatHash[QString("C5E").toLower()] = QPrinter::C5E;
128     this->m_formatHash[QString("Comm10E").toLower()] = QPrinter::Comm10E;
129     this->m_formatHash[QString("DLE").toLower()] = QPrinter::DLE;
130     this->m_formatHash[QString("Executive").toLower()] = QPrinter::Executive;
131     this->m_formatHash[QString("Folio").toLower()] = QPrinter::Folio;
132     this->m_formatHash[QString("Ledger").toLower()] = QPrinter::Ledger;
133     this->m_formatHash[QString("Legal").toLower()] = QPrinter::Legal;
134     this->m_formatHash[QString("Letter").toLower()] = QPrinter::Letter;
135     this->m_formatHash[QString("Tabloid").toLower()] = QPrinter::Tabloid;
136
137     this->m_unitHash[QString("Millimeter").toLower()] = QPrinter::Millimeter;
138     this->m_unitHash[QString("mm").toLower()] = QPrinter::Millimeter;
139
140     this->m_unitHash[QString("Point").toLower()] = QPrinter::Point;
141     this->m_unitHash[QString("pt").toLower()] = QPrinter::Point;
142
143     this->m_unitHash[QString("Inch").toLower()] = QPrinter::Inch;
144     this->m_unitHash[QString("i").toLower()] = QPrinter::Inch;
145
146     this->m_unitHash[QString("Pica").toLower()] = QPrinter::Pica;
147     this->m_unitHash[QString("pi").toLower()] = QPrinter::Pica;
148
149     this->m_unitHash[QString("Didot").toLower()] = QPrinter::Didot;
150     this->m_unitHash[QString("d").toLower()] = QPrinter::Didot;
151
152     this->m_unitHash[QString("Cicero").toLower()] = QPrinter::Cicero;
153     this->m_unitHash[QString("c").toLower()] = QPrinter::Cicero;
154
155     this->m_unitHash[QString("DevicePixel").toLower()] = QPrinter::DevicePixel;
156     this->m_unitHash[QString("dp").toLower()] = QPrinter::DevicePixel;
157 }
158
159 void WEB2PDF::setUrl(const QString & url)
160 {
161     this->m_url = QUrl::fromUserInput(url);
162 }
163
164 void WEB2PDF::setOutputFileName(const QString & path)
165 {
166     this->m_hasAnOutputFile = true;
167     QFile file(path);
168     if(file.open(QFile::ReadWrite)) {
169         file.close();
170         this->m_printer.setOutputFileName(path);
171     } else {
172         this->m_errors.append("Error while trying to open the file '");
173         this->m_errors.append(path);
174         this->m_errors.append("'.\n");
175     }
176 }
177
178 void WEB2PDF::setGrayScale()
179 {
180     this->m_printer.setColorMode(QPrinter::GrayScale);
181 }
182
183 void WEB2PDF::setCreator(const QString & creator)
184 {
185     this->m_printer.setCreator(creator);
186 }
187
188 void WEB2PDF::setDocName(const QString & docName)
189 {
190     this->m_printer.setDocName(docName);
191 }
192
193 void WEB2PDF::setFullPage()
194 {
195     this->m_printer.setFullPage(true);
196 }
197
198 void WEB2PDF::setLandscape()
199 {
200     this->m_printer.setOrientation(QPrinter::Landscape);
201 }
202
203 void WEB2PDF::setResolution(const QString & resolutionArg)
204 {
205     bool conversion;
206     int resolution = resolutionArg.toInt(&conversion, 10);
207     if(conversion) {
208         this->m_printer.setResolution(resolution);
209     } else {
210         this->m_errors.append("Unable to convert resolution '");
211         this->m_errors.append(resolutionArg);
212         this->m_errors.append("'.\n");
213     }
214 }
215
216 void WEB2PDF::setFormat(const QString & fmt)
217 {
218     QPrinter::PaperSize pSize = m_formatHash.value(fmt.toLower(), QPrinter::Custom);
219     if(pSize == QPrinter::Custom) {
220         qDebug("Unable to convert '%s' to a well known paper size, using A4.", qPrintable(fmt));
221         pSize = QPrinter::A4;
222     }
223
224     this->m_printer.setPaperSize(pSize);
225 }
226
227 void WEB2PDF::setMargins(const QString & margins)
228 { // the first definition of unit is taken, other are ignored.
229     QRegExp rx("u=(\\w+)");
230     QRectF rect;
231     QPrinter::Unit unit;
232     bool conversion;
233     qreal temp;
234
235     unit = QPrinter::Millimeter;
236     if(rx.indexIn(margins) != -1) {
237         unit = this->m_unitHash.value(rx.cap(1).toLower(), (QPrinter::Unit)-1);
238         if(unit == -1) {
239             unit = QPrinter::Millimeter;
240             qDebug("Unable to translate content '%s', using Millimeter unit.", qPrintable(rx.cap(1)));
241         }
242     }
243
244     rect = this->m_printer.pageRect(unit);
245     foreach(QString item, margins.toLower().split(';', QString::SkipEmptyParts)) {
246         QStringList split = item.split('=', QString::SkipEmptyParts);
247         split.removeDuplicates();
248         if(split.size() == 2 && split.at(0).size() == 1) {
249             switch(split.at(0).at(0).toLatin1()) {
250             case 'l':
251                 temp = rect.left();
252                 rect.setLeft(split.at(1).toDouble(&conversion));
253                 if(!conversion) {
254                     rect.setLeft(temp);
255                     qDebug("Unable to translate content '%s', ignoring left.", qPrintable(item));
256                 }
257                 break;
258             case 't':
259                 temp = rect.top();
260                 rect.setTop(split.at(1).toDouble(&conversion));
261                 if(!conversion) {
262                     rect.setTop(temp);
263                     qDebug("Unable to translate content '%s', ignoring top.", qPrintable(item));
264                 }
265                 break;
266             case 'b':
267                 temp = rect.bottom();
268                 rect.setBottom(split.at(1).toDouble(&conversion));
269                 if(!conversion) {
270                     rect.setBottom(temp);
271                     qDebug("Unable to translate content '%s', ignoring bottom.", qPrintable(item));
272                 }
273                 break;
274             case 'r':
275                 temp = rect.top();
276                 rect.setRight(split.at(1).toDouble(&conversion));
277                 if(!conversion) {
278                     rect.setRight(temp);
279                     qDebug("Unable to translate content '%s', ignoring right.", qPrintable(item));
280                 }
281                 break;
282             case 'u':
283                 break;
284             default:
285                 qDebug("Unknown label name for margin setting '%s', skipping.", qPrintable(item));
286                 break;
287             }
288         } else {
289             qDebug("Skipping '%s'.", qPrintable(item));
290         }
291     }
292
293     this->m_printer.setPageMargins(rect.left(), rect.top(), rect.right(), rect.bottom(), unit);
294 }
295
296 void WEB2PDF::setChoosenFile(const QString & file)
297 {
298     this->m_webpage.setChoosenFile(file);
299 }
300
301 void WEB2PDF::setUserAgent(const QString & userAgent)
302 {
303     this->m_webpage.setUserAgent(userAgent);
304 }
305
306 void WEB2PDF::setProlix()
307 {
308     this->m_prolix = true;
309     this->m_webpage.setProlix();
310 }
311
312
313 void WEB2PDF::startRendering()
314 {
315     this->m_webview.load(this->m_url);
316 }
317
318 bool WEB2PDF::isValid()
319 {
320     return this->m_hasAnOutputFile && this->m_url.isValid() && this->m_errors.isEmpty();
321 }
322
323 QString WEB2PDF::errors()
324 {
325     QString retStr = this->m_errors;
326     if(!this->m_hasAnOutputFile) retStr.append("No specified output file.\n");
327     if(this->m_url.isEmpty()) {
328         retStr.append("No specified URL.\n");
329     } else if(!this->m_url.isValid()) {
330         retStr.append("Unable to process the inputed URL.\n");
331     }
332
333     return retStr;
334 }
335
336 void WEB2PDF::loadDone(bool loaded) {
337     if(loaded) {
338         this->m_webview.print(&this->m_printer);
339         qApp->exit(0);
340     } else {
341         if(!this->m_prolix)
342             qDebug("Unable to connect, or render the content of '%s'.", qPrintable(this->m_url.toString()));
343         qApp->exit(1);
344     }
345 }
346
347 void WEB2PDF::treatSslError(QNetworkReply * reply, const QList<QSslError> & errors)
348 { // allow the rendering of an untrusted page (self-signed, outdated...)
349     if(!this->m_prolix) {
350         foreach(QSslError error, errors) {
351             qDebug("SSL error: %s", qPrintable(error.errorString()));
352         } qDebug("Ignoring SSL errors...");
353     } reply->ignoreSslErrors();
354 }