diff --git a/src/gui/painting/qpaintengine.h b/src/gui/painting/qpaintengine.h
index c02b638ed94..0348fb69838 100644
--- a/src/gui/painting/qpaintengine.h
+++ b/src/gui/painting/qpaintengine.h
@@ -166,14 +166,23 @@ class Q_GUI_EXPORT QPaintEngine
virtual void addHyperlink(const QRectF &r, const QUrl &url) {Q_UNUSED(r); Q_UNUSED(url);}
virtual void addAnchor(const QRectF &r, const QString &name) {Q_UNUSED(r); Q_UNUSED(name);}
virtual void addLink(const QRectF &r, const QString &anchor) {Q_UNUSED(r); Q_UNUSED(anchor);}
- virtual void addTextField(const QRectF &r, const QString &text, const QString &name, bool multiLine, bool password, bool readOnly, int maxLength) {
- Q_UNUSED(r); Q_UNUSED(text); Q_UNUSED(name); Q_UNUSED(multiLine); Q_UNUSED(password); Q_UNUSED(readOnly); Q_UNUSED(maxLength);
+ virtual void addTextField(const QRectF &r,const QMap &data, const QString &text, const QString &name, bool multiLine, bool password, bool readOnly, int maxLength) {
+ Q_UNUSED(r); Q_UNUSED(text); Q_UNUSED(name); Q_UNUSED(multiLine); Q_UNUSED(password); Q_UNUSED(readOnly); Q_UNUSED(maxLength); Q_UNUSED(data);
}
- virtual void addCheckBox(const QRectF &r, bool checked, const QString &name, bool readOnly) {
- Q_UNUSED(r); Q_UNUSED(checked); Q_UNUSED(name); Q_UNUSED(readOnly);
+ virtual void addHiddenField(const QRectF &r, const QMap &data, const QString &value, const QString &name) {
+ Q_UNUSED(r); Q_UNUSED(name); Q_UNUSED(value); Q_UNUSED(data);
}
- virtual void addRadioButton(const QRectF &r, const QString & group="", bool checked=false, const QString &name="", bool readOnly=false) {
- Q_UNUSED(r); Q_UNUSED(checked); Q_UNUSED(name); Q_UNUSED(readOnly); Q_UNUSED(group);
+ virtual void addCheckBox(const QRectF &r, const QMap &data, bool checked, const QString &name, bool readOnly) {
+ Q_UNUSED(r); Q_UNUSED(checked); Q_UNUSED(name); Q_UNUSED(readOnly); Q_UNUSED(data);
+ }
+ virtual void addRadioButton(const QRectF &r, const QMap &data, bool checked=false, const QString &name="", const QString &value="", bool readOnly=false) {
+ Q_UNUSED(r); Q_UNUSED(checked); Q_UNUSED(name); Q_UNUSED(readOnly); Q_UNUSED(value); Q_UNUSED(data);
+ }
+ virtual void addComboBox(const QRectF &r, const QMap &data, const QString &name="", const QString &option_list="[]", const QString &default_value="", bool readOnly=false) {
+ Q_UNUSED(r); Q_UNUSED(default_value); Q_UNUSED(name); Q_UNUSED(readOnly); Q_UNUSED(option_list); Q_UNUSED(data);
+ }
+ virtual void addPageJavaScript(const QMap &data, const QString &script) {
+ Q_UNUSED(data); Q_UNUSED(script);
}
virtual void drawLines(const QLine *lines, int lineCount);
diff --git a/src/gui/painting/qpainter.cpp b/src/gui/painting/qpainter.cpp
index 924e02c1c0a..1f9c3206ef7 100644
--- a/src/gui/painting/qpainter.cpp
+++ b/src/gui/painting/qpainter.cpp
@@ -7420,32 +7420,59 @@ void QPainter::addHyperlink(const QRectF &r, const QUrl &url)
d->engine->addHyperlink(worldTransform().mapRect(r), url);
}
-void QPainter::addTextField(const QRectF &r, const QString &text, const QString &name, bool multiLine, bool password, bool readOnly, int maxLength) {
+void QPainter::addHiddenField(const QRectF &r, const QMap &data, const QString &value, const QString &name) {
+ Q_D(QPainter);
+ if (!d->engine) {
+ qWarning("QPainter::addHiddenField: Painter not active");
+ return;
+ }
+ d->engine->addHiddenField(worldTransform().mapRect(r), data, value, name);
+}
+
+void QPainter::addTextField(const QRectF &r, const QMap &data, const QString &text, const QString &name, bool multiLine, bool password, bool readOnly, int maxLength) {
Q_D(QPainter);
if (!d->engine) {
qWarning("QPainter::addTextField: Painter not active");
return;
}
- d->engine->addTextField(worldTransform().mapRect(r), text, name, multiLine, password, readOnly, maxLength);
+ d->engine->addTextField(worldTransform().mapRect(r), data, text, name, multiLine, password, readOnly, maxLength);
+}
+
+void QPainter::addPageJavaScript(const QMap &data, const QString &script) {
+ Q_D(QPainter);
+ if (!d->engine) {
+ qWarning("QPainter::addPageJavascript: Painter not active");
+ return;
+ }
+ d->engine->addPageJavaScript(data, script);
}
-void QPainter::addCheckBox(const QRectF &r, bool checked, const QString &name, bool readOnly) {
+void QPainter::addCheckBox(const QRectF &r, const QMap &data, bool checked, const QString &name, bool readOnly) {
Q_D(QPainter);
if (!d->engine) {
qWarning("QPainter::addCheckBox: Painter not active");
return;
}
- d->engine->addCheckBox(worldTransform().mapRect(r), checked, name, readOnly);
+ d->engine->addCheckBox(worldTransform().mapRect(r), data, checked, name, readOnly);
}
-void QPainter::addRadioButton(const QRectF &r, const QString & group, bool checked, const QString &name, bool readOnly) {
+void QPainter::addRadioButton(const QRectF &r, const QMap &data, bool checked, const QString &name, const QString &value, bool readOnly) {
Q_D(QPainter);
if (!d->engine) {
qWarning("QPainter::addRadioButton: Painter not active");
return;
}
- d->engine->addRadioButton(worldTransform().mapRect(r), group, checked, name, readOnly);
+ d->engine->addRadioButton(worldTransform().mapRect(r), data, checked, name, value, readOnly);
+}
+
+void QPainter::addComboBox(const QRectF &r, const QMap &data, const QString &name, const QString &option_list, const QString &default_value, bool readOnly) {
+ Q_D(QPainter);
+ if (!d->engine) {
+ qWarning("QPainter::addComboBox: Painter not active");
+ return;
+ }
+ d->engine->addComboBox(worldTransform().mapRect(r), data, name, option_list, default_value, readOnly);
}
/*!
diff --git a/src/gui/painting/qpainter.h b/src/gui/painting/qpainter.h
index cfba5f60f41..89ad72ecd46 100644
--- a/src/gui/painting/qpainter.h
+++ b/src/gui/painting/qpainter.h
@@ -454,10 +454,13 @@ class Q_GUI_EXPORT QPainter
inline void addLink(int x, int y, int w, int h, const QString &anchor);
inline void addLink(const QRect &r, const QString &anchor);
void addLink(const QRectF &r, const QString &anchor);
-
- void addTextField(const QRectF &r, const QString &text="", const QString &name="", bool multiLine=false, bool password=false, bool readOnly=false, int maxLength=-1);
- void addCheckBox(const QRectF &r, bool checked=false, const QString &name="", bool readOnly=false);
- void addRadioButton(const QRectF &r, const QString & group="", bool checked=false, const QString &name="", bool readOnly=false);;
+
+ void addHiddenField(const QRectF &r, const QMap &data, const QString &value="", const QString &name="");
+ void addPageJavaScript(const QMap &data, const QString &script);
+ void addTextField(const QRectF &r, const QMap &data, const QString &text="", const QString &name="", bool multiLine=false, bool password=false, bool readOnly=false, int maxLength=-1);
+ void addCheckBox(const QRectF &r, const QMap &data, bool checked=false, const QString &name="", bool readOnly=false);
+ void addRadioButton(const QRectF &r, const QMap &data, bool checked=false, const QString &name="", const QString &value="", bool readOnly=false);
+ void addComboBox(const QRectF &r, const QMap &data, const QString &name="", const QString &option_list="[]", const QString &default_value="", bool readOnly=false);
inline void addHyperlink(int x, int y, int w, int h, const QUrl &url);
inline void addHyperlink(const QRect &r, const QUrl &url);
diff --git a/src/gui/painting/qprintengine_pdf.cpp b/src/gui/painting/qprintengine_pdf.cpp
index a906e3243be..305985b851c 100644
--- a/src/gui/painting/qprintengine_pdf.cpp
+++ b/src/gui/painting/qprintengine_pdf.cpp
@@ -196,6 +196,44 @@ bool QPdfEngine::end()
d->outlineRoot->firstChild->obj, d->outlineRoot->lastChild->obj);
}
+
+ QMapIterator i(d->formFieldParents);
+ while (i.hasNext()) {
+ i.next();
+ QFormFieldParent* formFieldParent = i.value();
+ d->addXrefEntry(formFieldParent->ref);
+ d->xprintf("<<");
+ if (formFieldParent->JSvalidation_ref != -1) {
+ d->xprintf("/AA<>",formFieldParent->JSvalidation_ref);
+ }
+ d->xprintf("/Kids[");
+ foreach(const uint & i, formFieldParent->children)
+ d->xprintf("%d 0 R ",i);
+ d->xprintf("]\n"
+ "/Parent %d 0 R\n", d->formFieldList);
+ d->xprintf("/FT/%s\n",formFieldParent->type.toUtf8().constData());
+ if (!formFieldParent->name.isEmpty()) {
+ d->xprintf("/T");
+ d->printString(formFieldParent->name);
+ }
+ if (!formFieldParent->value.isEmpty()) {
+ d->xprintf("/V");
+ d->printString(formFieldParent->value);
+ d->xprintf("\n");
+ d->xprintf("/DV");
+ d->printString(formFieldParent->value);
+ d->xprintf("\n");
+ }
+ if (formFieldParent->type == "Ch") {
+ d->xprintf("/Opt %s\n", formFieldParent->option_list.toUtf8().constData());
+ d->xprintf("/Ff 131072\n");
+ } else if (formFieldParent->type == "Btn") {
+ // Radio buttons have children
+ d->xprintf("/Ff 49154\n");
+ }
+ d->xprintf(">>endobj\n");
+ }
+
if (d->formFields.size()) {
uint font = d->addXrefEntry(-1);
d->xprintf("<>\n"
@@ -212,6 +250,22 @@ bool QPdfEngine::end()
"endobj\n", font);
}
+ int named_javascript_ref = -1;
+ if (d->pageJavaScripts.size()) {
+ int jsNamesRef = d->addXrefEntry(-1);
+ d->xprintf("< i(d->pageJavaScripts);
+ while (i.hasNext()) {
+ i.next();
+ d->xprintf("(%s)", i.key().toUtf8().constData());
+ d->xprintf("%d 0 R", i.value());
+ }
+ d->xprintf("]>>\nendobj\n");
+
+ named_javascript_ref = d->addXrefEntry(-1);
+ d->xprintf("<>\nendobj\n", jsNamesRef);
+ }
+
d->catalog = d->addXrefEntry(-1);
d->xprintf("<<\n"
"/Type /Catalog\n"
@@ -226,6 +280,8 @@ bool QPdfEngine::end()
if (d->anchors.size())
d->xprintf("/Dests %d 0 R\n", dests);
+ if (named_javascript_ref > 0)
+ d->xprintf("/Names %d 0 R\n", named_javascript_ref);
d->xprintf(">>\n"
"endobj\n");
@@ -238,16 +294,311 @@ bool QPdfEngine::end()
return true;
}
-void QPdfEngine::addCheckBox(const QRectF &r, bool checked, const QString &name, bool readOnly) {
+uint QPdfEngine::addJavaScript(const QString &script) {
Q_D(QPdfEngine);
- uint obj = d->addXrefEntry(-1);
+ uint ref = d->addXrefEntry(-1);
+ d->xprintf("<>\nendobj\n",script.toUtf8().constData());
+ return ref;
+}
+
+void QPdfEngine::addPageJavaScript(const QMap &data, const QString &script) {
+ Q_D(QPdfEngine);
+ QString script_name;
+ if (data.contains("acroform-script-name")) {
+ script_name = data["acroform-script-name"];
+ } else {
+ script_name = QString("UntitledScript%1").arg(d->pageJavaScripts.count());
+ }
+ d->pageJavaScripts[script_name] = this->addJavaScript(script);
+}
+
+// Create resources for radio buttons
+void QPdfEngine::addRadioBtnResources(QRectF rr, int *formRadioBtnResourceChecked, int *formRadioBtnResourceUnChecked) {
+ Q_D(QPdfEngine);
+ float k = 0.552284749831;
+ float cx=((rr.right()-rr.left())/2);
+ float cy=((rr.bottom()-rr.top())/2);
+ float r=cx; // radius is half the total space we have just like the middle of the space.
+ char streambuf[1024];
+
+ // Drawing a circle. use b to stroke, fill, end on checked. Just stroke, end with f on unchecked.
+ snprintf(streambuf,sizeof(streambuf),"1 g\n"
+ "%.3f %.3f m\n"
+ "%.3f %.3f %.3f %.3f %.3f %.3f c\n"
+ "%.3f %.3f %.3f %.3f %.3f %.3f c\n"
+ "%.3f %.3f %.3f %.3f %.3f %.3f c\n"
+ "%.3f %.3f %.3f %.3f %.3f %.3f c\n",
+ (cx-r), cy,
+ cx - r, cy + k * r, cx - k * r, cy + r, cx, cy + r,
+ cx + k * r, cy + r, cx + r, cy + k * r, cx + r, cy,
+ cx + r, cy - k * r, cx + k * r, cy - r, cx, cy - r,
+ cx - k * r, cy - r, cx - r, cy - k * r, cx - r, cy);
+
+ *formRadioBtnResourceChecked = d->addXrefEntry(-1);
+ d->xprintf("<<\n"
+ " /BBox [\n"
+ " 0.0\n"
+ " 0.0\n"
+ " %.3f\n"
+ " %.3f\n"
+ " ]\n"
+ " /FormType 1\n"
+ " /Resources <<\n"
+ " /ProcSet [\n"
+ " /PDF\n"
+ " ]\n"
+ " >>\n"
+ " /Subtype /Form\n"
+ " /Type /XObject\n"
+ " /Length %d\n"
+ ">>\n"
+ "stream\n"
+ "%sb\n"
+ "endstream\n"
+ "endobj\n", (rr.right()-rr.left()), (rr.bottom()-rr.top()), strlen(streambuf)+2, streambuf);
+
+ *formRadioBtnResourceUnChecked = d->addXrefEntry(-1);
+ d->xprintf("<<\n"
+ " /BBox [\n"
+ " 0.0\n"
+ " 0.0\n"
+ " %.3f\n"
+ " %.3f\n"
+ " ]\n"
+ " /FormType 1\n"
+ " /Resources <<\n"
+ " /ProcSet [\n"
+ " /PDF\n"
+ " ]\n"
+ " >>\n"
+ " /Subtype /Form\n"
+ " /Type /XObject\n"
+ " /Length %d\n"
+ ">>\n"
+ "stream\n"
+ "%sf\n"
+ "endstream\n"
+ "endobj\n", (rr.right()-rr.left()), (rr.bottom()-rr.top()), strlen(streambuf)+2, streambuf);
+}
+
+// Create resources used by all checkboxes once
+void QPdfEngine::addCheckBoxResources() {
+ Q_D(QPdfEngine);
+ d->formChkBoxResourceChecked = d->addXrefEntry(-1);
+ d->xprintf("<<"
+ "/BBox [\n"
+ " 0.0\n"
+ " 0.0\n"
+ " 9.5321\n"
+ " 10.7023\n"
+ "]\n"
+ "/FormType 1\n"
+ "/Matrix [\n"
+ " 1.0\n"
+ " 0.0\n"
+ " 0.0\n"
+ " 1.0\n"
+ " 0.0\n"
+ " 0.0\n"
+ "]\n"
+ "/Resources <<\n"
+ " /Font <<\n"
+ " /BaseFont /ZapfDingbats\n"
+ " /Name /ZaDb\n"
+ " /Subtype /Type1\n"
+ " /Type /Font\n"
+ " >>\n"
+ " /ProcSet [\n"
+ " /PDF\n"
+ " /Text\n"
+ " ]\n"
+ ">>\n"
+ "/Subtype /Form\n"
+ "/Type /XObject\n"
+ "/Length 51\n"
+ ">>\n"
+ "stream\n"
+ "q\n"
+ "0 0 1 rg\n"
+ "BT\n"
+ "/ZaDb 4 Tf\n"
+ "0 0 Td\n"
+ "(4) Tj\n"
+ "ET\n"
+ "Q\n"
+ "endstream\n"
+ "endobj\n");
+
+ d->formChkBoxResourceUnChecked = d->addXrefEntry(-1);
+ d->xprintf("<<"
+ " /BBox [\n"
+ " 0.0\n"
+ " 0.0\n"
+ " 9.5321\n"
+ " 10.7023\n"
+ " ]\n"
+ " /FormType 1\n"
+ " /Matrix [\n"
+ " 1.0\n"
+ " 0.0\n"
+ " 0.0\n"
+ " 1.0\n"
+ " 0.0\n"
+ " 0.0\n"
+ " ]\n"
+ " /Resources <<\n"
+ " /ProcSet [\n"
+ " /PDF\n"
+ " ]\n"
+ " >>\n"
+ " /Subtype /Form\n"
+ " /Type /XObject\n"
+ " /Length 216\n"
+ ">>\n"
+ "stream\n"
+ "1 g\n"
+ "0 0 9.5321 10.7023 re\n"
+ "f\n"
+ "0.501953 g\n"
+ "1 1 m\n"
+ "1 9.7023 l\n"
+ "8.5321 9.7023 l\n"
+ "7.5321 8.7023 l\n"
+ "2 8.7023 l\n"
+ "2 2 l\n"
+ "f\n"
+ "0.75293 g\n"
+ "8.5321 9.7023 m\n"
+ "8.5321 1 l\n"
+ "1 1 l\n"
+ "2 2 l\n"
+ "7.5321 2 l\n"
+ "7.5321 8.7023 l\n"
+ "f\n"
+ "0 G\n"
+ "0.5 0.5 8.5321 9.7023 re\n"
+ "s\n"
+ "endstream\n"
+ "endobj\n");
+}
+
+void QPdfEngine::addRadioButton(const QRectF &r, const QMap &data, bool checked, const QString &name, const QString &value, bool readOnly) {
+ Q_D(QPdfEngine);
+ uint obj;
char buf[256];
QRectF rr = d->pageMatrix().mapRect(r);
+ int onBlurRef = -1;
+ int formRadioBtnResourceChecked, formRadioBtnResourceUnChecked;
+
+ addRadioBtnResources(rr, &formRadioBtnResourceChecked, &formRadioBtnResourceUnChecked);
+
if (d->formFieldList == -1) d->formFieldList = d->requestObject();
+
+ if (!d->formFieldParents.contains(name)) {
+ QFormFieldParent* form = new QFormFieldParent();
+ form->ref = d->requestObject();
+ form->type = "Btn";
+ form->name = name;
+ form->value = value;
+ if (data.contains("acroform-validation")) {
+ form->JSvalidation_ref = this->addJavaScript(data["acroform-validation"]);
+ }
+ else {
+ form->JSvalidation_ref = -1;
+ }
+ d->formFields.push_back(form->ref);
+ d->formFieldParents[name] = form;
+ }
+
+ //handling javascript
+ if (data.contains("acroform-on-blur")) {
+ onBlurRef = this->addJavaScript(data["acroform-on-blur"]);
+ }
+
+ obj = d->addXrefEntry(-1);
d->xprintf("<<\n"
"/Type /Annot\n"
+ "/Subtype/Widget\n"
"/Parent %d 0 R\n"
"/F 4\n"
+ "/AP << /N << /%s %d 0 R /Off %d 0 R >> >>\n"
+// "/BS <<\n"
+// "/S\n"
+// "/W 1\n"
+// ">>\n"
+// "/MK <<\n"
+// "/BC [\n"
+// "0.0\n"
+// "0.0\n"
+// "0.0\n"
+// "]\n"
+// ">>\n"
+ "/Rect[", d->formFieldParents[name]->ref, value.toUtf8().data(),
+ formRadioBtnResourceChecked, formRadioBtnResourceUnChecked);
+
+ d->xprintf("%s ", qt_real_to_string(rr.left(),buf));
+ d->xprintf("%s ", qt_real_to_string(rr.top(),buf));
+ d->xprintf("%s ", qt_real_to_string(rr.right(),buf));
+ d->xprintf("%s", qt_real_to_string(rr.bottom(),buf));
+ d->xprintf("]\n"
+ "/P %d 0 R\n", d->pages.back());
+
+ if (checked) {
+ d->xprintf("/AS /%s\n", value.toUtf8().constData());
+ }
+
+ // writing javascript actions
+ if (onBlurRef > 0) {
+ d->xprintf("/AA<>", onBlurRef);
+ }
+ // alignment
+ if (data.contains("acroform-align")) {
+ uint align = -1;
+ if (data["acroform-align"].compare("left", Qt::CaseInsensitive) == 0) {
+ align = 0;
+ }
+ else if (data["acroform-align"].compare("center", Qt::CaseInsensitive) == 0){
+ align = 1;
+ }
+ else if (data["acroform-align"].compare("right", Qt::CaseInsensitive) == 0){
+ align = 2;
+ }
+ if (align != -1) {
+ d->xprintf("/Q %d\n",align);
+ }
+ }
+
+// if (!text.isEmpty()) {
+// d->xprintf("/V");
+// d->printString(text);
+// d->xprintf("\n");
+// }
+ d->xprintf(">>\n"
+ "endobj\n");
+ d->currentPage->annotations.push_back(obj);
+
+ d->formFieldParents[name]->children.push_back(obj);
+}
+
+void QPdfEngine::addCheckBox(const QRectF &r, const QMap &data, bool checked, const QString &name, bool readOnly) {
+ Q_D(QPdfEngine);
+ char buf[256];
+ uint obj;
+ QRectF rr;
+
+ // Put out the resources we need for a checkbox once
+ if (d->formChkBoxResourceChecked == -1) {
+ addCheckBoxResources();
+ }
+ obj = d->addXrefEntry(-1);
+ rr = d->pageMatrix().mapRect(r);
+
+ if (d->formFieldList == -1) d->formFieldList = d->requestObject();
+ d->xprintf("<<\n"
+ "/Type /Annot\n"
+ "/Parent %d 0 R\n"
+ "/F 4\n"
+ "/V /Yes\n"
"/Rect[", d->formFieldList);
d->xprintf("%s ", qt_real_to_string(rr.left(),buf));
d->xprintf("%s ", qt_real_to_string(rr.top(),buf));
@@ -255,8 +606,20 @@ void QPdfEngine::addCheckBox(const QRectF &r, bool checked, const QString &name,
d->xprintf("%s", qt_real_to_string(rr.bottom(),buf));
d->xprintf("]\n"
"/FT/Btn\n"
- "/Subtype/Widget\n"
- "/P %d 0 R\n", d->pages.back());
+ "/Subtype /Widget\n"
+ "/AP << /N << /Yes %d 0 R /Off %d 0 R >> >>\n"
+ "/BS <<\n"
+ "/S\n"
+ "/W 1\n"
+ ">>\n"
+ "/MK <<\n"
+ "/BC [\n"
+ "0.0\n"
+ "0.0\n"
+ "0.0\n"
+ "]\n"
+ ">>\n"
+ "/P %d 0 R\n", d->formChkBoxResourceChecked, d->formChkBoxResourceUnChecked, d->pages.back());
if (checked)
d->xprintf("/AS /Yes\n");
if (!name.isEmpty()) {
@@ -272,7 +635,7 @@ void QPdfEngine::addCheckBox(const QRectF &r, bool checked, const QString &name,
d->formFields.push_back(obj);
}
-void QPdfEngine::addTextField(const QRectF &r, const QString &text, const QString &name, bool multiLine, bool password, bool readOnly, int maxLength)
+void QPdfEngine::addHiddenField(const QRectF &r, const QMap &data, const QString &value, const QString &name)
{
Q_D(QPdfEngine);
uint obj = d->addXrefEntry(-1);
@@ -282,7 +645,6 @@ void QPdfEngine::addTextField(const QRectF &r, const QString &text, const QStrin
d->xprintf("<<\n"
"/Type /Annot\n"
"/Parent %d 0 R\n"
- "/F 4\n"
"/Rect[", d->formFieldList);
d->xprintf("%s ", qt_real_to_string(rr.left(),buf));
d->xprintf("%s ", qt_real_to_string(rr.top(),buf));
@@ -291,11 +653,12 @@ void QPdfEngine::addTextField(const QRectF &r, const QString &text, const QStrin
d->xprintf("]\n"
"/BS<>\n"
"/FT/Tx\n"
+ "/F 6"
"/Subtype/Widget\n"
"/P %d 0 R\n", d->pages.back());
- if (!text.isEmpty()) {
+ if (!value.isEmpty()) {
d->xprintf("/V");
- d->printString(text);
+ d->printString(value);
d->xprintf("\n");
}
if (!name.isEmpty()) {
@@ -303,16 +666,160 @@ void QPdfEngine::addTextField(const QRectF &r, const QString &text, const QStrin
d->printString(name);
d->xprintf("\n");
}
+ d->xprintf("/DA(/Helv 12 Tf 0 g)\n"
+ "/Ff 0\n"
+ ">>\n"
+ "endobj\n");
+ d->currentPage->annotations.push_back(obj);
+ d->formFields.push_back(obj);
+}
+void QPdfEngine::addTextField(const QRectF &r, const QMap &data, const QString &text, const QString &name, bool multiLine, bool password, bool readOnly, int maxLength)
+{
+ Q_D(QPdfEngine);
+ if (d->formFieldList == -1) d->formFieldList = d->requestObject();
+
+ if (!d->formFieldParents.contains(name)) {
+ QFormFieldParent* form = new QFormFieldParent();
+ form->ref = d->requestObject();
+ form->type = "Tx";
+ form->name = name;
+ form->value = text;
+ if (data.contains("acroform-validation")) {
+ form->JSvalidation_ref = this->addJavaScript(data["acroform-validation"]);
+ }
+ else {
+ form->JSvalidation_ref = -1;
+ }
+ d->formFields.push_back(form->ref);
+ d->formFieldParents[name] = form;
+ }
+ int onBlurRef = -1;
+
+ //handling javascript
+ if (data.contains("acroform-on-blur")) {
+ onBlurRef = this->addJavaScript(data["acroform-on-blur"]);
+ }
+
+ uint obj = d->addXrefEntry(-1);
+ char buf[256];
+ QRectF rr = d->pageMatrix().mapRect(r);
+ d->xprintf("<<\n"
+ "/Type /Annot\n"
+ "/Parent %d 0 R\n"
+ "/F 4\n"
+ "/Rect[", d->formFieldParents[name]->ref);
+
+ d->xprintf("%s ", qt_real_to_string(rr.left(),buf));
+ d->xprintf("%s ", qt_real_to_string(rr.top(),buf));
+ d->xprintf("%s ", qt_real_to_string(rr.right(),buf));
+ d->xprintf("%s", qt_real_to_string(rr.bottom(),buf));
+ d->xprintf("]\n"
+ "/BS<>\n"
+ "/FT/Tx\n"
+ "/Subtype/Widget\n"
+ "/P %d 0 R\n", d->pages.back());
+ // writing javascript actions
+ if (onBlurRef > 0) {
+ d->xprintf("/AA<>", onBlurRef);
+ }
+ // alignment
+ if (data.contains("acroform-align")) {
+ uint align = -1;
+ if (data["acroform-align"].compare("left", Qt::CaseInsensitive) == 0) {
+ align = 0;
+ }
+ else if (data["acroform-align"].compare("center", Qt::CaseInsensitive) == 0){
+ align = 1;
+ }
+ else if (data["acroform-align"].compare("right", Qt::CaseInsensitive) == 0){
+ align = 2;
+ }
+ if (align != -1) {
+ d->xprintf("/Q %d\n",align);
+ }
+ }
+
+// if (!text.isEmpty()) {
+// d->xprintf("/V");
+// d->printString(text);
+// d->xprintf("\n");
+// }
if (maxLength >= 0)
d->xprintf("/MaxLen %d\n",maxLength);
- d->xprintf("/DA(/Helv 12 Tf 0 g)\n"
- "/Ff %d\n"
+ d->xprintf("/Ff %d\n"
">>\n"
"endobj\n",
(readOnly?1:0)<<0 | (password?1:0)<<13 | (multiLine?1:0)<<12
);
d->currentPage->annotations.push_back(obj);
- d->formFields.push_back(obj);
+
+ d->formFieldParents[name]->children.push_back(obj);
+}
+
+void QPdfEngine::addComboBox(const QRectF &r, const QMap &data, const QString &name,const QString &option_list,const QString &default_value, bool readOnly) {
+ Q_D(QPdfEngine);
+ //Note that the pdf spec sayes that we should add some sort of default appearence atleast for yes, which we dont ghost script provides one, however acroread does not
+ if (d->formFieldList == -1) d->formFieldList = d->requestObject();
+
+ if (!d->formFieldParents.contains(name)) {
+ QFormFieldParent* form = new QFormFieldParent();
+ form->ref = d->requestObject();
+ form->type = "Ch";
+ form->name = name;
+ form->value = default_value;
+ form->option_list = option_list;
+ if (data.contains("acroform-validation")) {
+ form->JSvalidation_ref = this->addJavaScript(data["acroform-validation"]);
+ }
+ else {
+ form->JSvalidation_ref = -1;
+ }
+ d->formFields.push_back(form->ref);
+ d->formFieldParents[name] = form;
+ }
+ int onBlurRef = -1;
+ //handling javascript
+ if (data.contains("acroform-on-blur")) {
+ onBlurRef = this->addJavaScript(data["acroform-on-blur"]);
+ }
+
+ uint obj = d->addXrefEntry(-1);
+ char buf[256];
+ QRectF rr = d->pageMatrix().mapRect(r);
+ d->xprintf("<
pages.back());
+ d->xprintf("/Parent %d 0 R", d->formFieldParents[name]->ref);
+ // writing javascript actions
+ if (onBlurRef != -1) {
+ d->xprintf("/AA<>", onBlurRef);
+ }
+ // alignment
+ if (data.contains("acroform-align")) {
+ uint align = -1;
+ if (data["acroform-align"].compare("left", Qt::CaseInsensitive) == 0) {
+ align = 0;
+ }
+ else if (data["acroform-align"].compare("center", Qt::CaseInsensitive) == 0){
+ align = 1;
+ }
+ else if (data["acroform-align"].compare("right", Qt::CaseInsensitive) == 0){
+ align = 2;
+ }
+ if (align != -1) {
+ d->xprintf("/Q %d\n",align);
+ }
+ }
+ d->xprintf("/F 4");
+ d->xprintf("/Subtype/Widget/TI 1/Type/Annot");
+ d->xprintf("/Rect[");
+ d->xprintf("%s ", qt_real_to_string(rr.left(),buf));
+ d->xprintf("%s ", qt_real_to_string(rr.top(),buf));
+ d->xprintf("%s ", qt_real_to_string(rr.right(),buf));
+ d->xprintf("%s", qt_real_to_string(rr.bottom(),buf));
+ d->xprintf("]>>\nendobj\n");
+
+ d->currentPage->annotations.push_back(obj);
+ //d->formFields.push_back(obj);
+ d->formFieldParents[name]->children.push_back(obj);
}
void QPdfEngine::drawPixmap (const QRectF &rectangle, const QPixmap &pixmap, const QRectF &sr, const QByteArray * data)
@@ -1268,6 +1775,9 @@ void QPdfEnginePrivate::writeHeader()
pageRoot = requestObject();
formFieldList = -1;
+ formChkBoxResourceChecked = -1;
+ formChkBoxResourceUnChecked = -1;
+
// graphics state
graphicsState = addXrefEntry(-1);
xprintf("<<\n"
diff --git a/src/gui/painting/qprintengine_pdf_p.h b/src/gui/painting/qprintengine_pdf_p.h
index 773706deeb9..108b6bd42a8 100644
--- a/src/gui/painting/qprintengine_pdf_p.h
+++ b/src/gui/painting/qprintengine_pdf_p.h
@@ -116,8 +116,15 @@ class QPdfEngine : public QPdfBaseEngine
virtual void addHyperlink(const QRectF &r, const QUrl &url);
virtual void addAnchor(const QRectF &r, const QString &name);
virtual void addLink(const QRectF &r, const QString &anchor);
- virtual void addTextField(const QRectF &r, const QString &text, const QString &name, bool multiLine, bool password, bool readOnly, int maxLength);
- virtual void addCheckBox(const QRectF &r, bool checked, const QString &name, bool readOnly);
+ virtual uint addJavaScript(const QString &script);
+ virtual void addHiddenField(const QRectF &, const QMap &data, const QString &value, const QString &name);
+ virtual void addTextField(const QRectF &r, const QMap &data, const QString &text, const QString &name, bool multiLine, bool password, bool readOnly, int maxLength);
+ virtual void addPageJavaScript(const QMap &data, const QString &script);
+ virtual void addRadioBtnResources(QRectF rr, int *formRadioBtnResourceChecked, int *formRadioBtnResourceUnChecked);
+ virtual void addCheckBoxResources();
+ virtual void addCheckBox(const QRectF &r, const QMap &data, bool checked, const QString &name, bool readOnly);
+ virtual void addRadioButton(const QRectF &r, const QMap &data, bool checked, const QString &name, const QString &value, bool readOnly);
+ virtual void addComboBox(const QRectF &r, const QMap &data, const QString &name, const QString &option_list, const QString &default_value, bool readOnly);
// ### unused, should have something for this in QPrintEngine
void setAuthor(const QString &author);
@@ -135,7 +142,18 @@ class QPdfEngine : public QPdfBaseEngine
QPrinter::PrinterState state;
};
-
+class QFormFieldParent
+{
+ public:
+ QVector children;
+ QString type;
+ QString name;
+ QString option_list;
+ QString value;
+ int JSonBlur_ref;
+ int JSvalidation_ref;
+ int ref;
+};
class QPdfEnginePrivate : public QPdfBaseEnginePrivate
{
Q_DECLARE_PUBLIC(QPdfEngine)
@@ -209,6 +227,10 @@ class QPdfEnginePrivate : public QPdfBaseEnginePrivate
void embedFont(QFontSubset *font);
int formFieldList;
+ int formChkBoxResourceChecked;
+ int formChkBoxResourceUnChecked;
+ QMap formFieldParents;
+ QMap pageJavaScripts;
QVector formFields;
QVector xrefPositions;
QDataStream* stream;