Okular

kjs_field.cpp
1 /*
2  SPDX-FileCopyrightText: 2008 Pino Toscano <[email protected]>
3  SPDX-FileCopyrightText: 2008 Harri Porten <[email protected]>
4 
5  SPDX-License-Identifier: GPL-2.0-or-later
6 */
7 
8 #include "kjs_field_p.h"
9 
10 #include <kjs/kjsarguments.h>
11 #include <kjs/kjsinterpreter.h>
12 #include <kjs/kjsprototype.h>
13 
14 #include <QHash>
15 
16 #include <QDebug>
17 #include <QTimer>
18 
19 #include "../debug_p.h"
20 #include "../document_p.h"
21 #include "../form.h"
22 #include "../page.h"
23 #include "../page_p.h"
24 #include "kjs_display_p.h"
25 
26 using namespace Okular;
27 
28 #define OKULAR_NAME QStringLiteral("okular_name")
29 
30 static KJSPrototype *g_fieldProto;
31 
33 Q_GLOBAL_STATIC(FormCache, g_fieldCache)
35 Q_GLOBAL_STATIC(ButtonCache, g_buttonCache)
36 
37 // Helper for modified fields
38 static void updateField(FormField *field)
39 {
40  Page *page = g_fieldCache->value(field);
41  if (page) {
42  Document *doc = PagePrivate::get(page)->m_doc->m_parent;
43  const int pageNumber = page->number();
44  QTimer::singleShot(0, doc, [doc, pageNumber] { doc->refreshPixmaps(pageNumber); });
45  Q_EMIT doc->refreshFormWidget(field);
46  } else {
47  qWarning() << "Could not get page of field" << field;
48  }
49 }
50 
51 // Field.doc
52 static KJSObject fieldGetDoc(KJSContext *context, void *)
53 {
54  return context->interpreter().globalObject();
55 }
56 
57 // Field.name
58 static KJSObject fieldGetName(KJSContext *, void *object)
59 {
60  const FormField *field = reinterpret_cast<FormField *>(object);
61  return KJSString(field->fullyQualifiedName());
62 }
63 
64 // Field.readonly (getter)
65 static KJSObject fieldGetReadOnly(KJSContext *, void *object)
66 {
67  const FormField *field = reinterpret_cast<FormField *>(object);
68  return KJSBoolean(field->isReadOnly());
69 }
70 
71 // Field.readonly (setter)
72 static void fieldSetReadOnly(KJSContext *context, void *object, KJSObject value)
73 {
74  FormField *field = reinterpret_cast<FormField *>(object);
75  bool b = value.toBoolean(context);
76  field->setReadOnly(b);
77 
78  updateField(field);
79 }
80 
81 static QString fieldGetTypeHelper(const FormField *field)
82 {
83  switch (field->type()) {
84  case FormField::FormButton: {
85  const FormFieldButton *button = static_cast<const FormFieldButton *>(field);
86  switch (button->buttonType()) {
88  return QStringLiteral("button");
90  return QStringLiteral("checkbox");
92  return QStringLiteral("radiobutton");
93  }
94  break;
95  }
97  return QStringLiteral("text");
98  case FormField::FormChoice: {
99  const FormFieldChoice *choice = static_cast<const FormFieldChoice *>(field);
100  switch (choice->choiceType()) {
102  return QStringLiteral("combobox");
104  return QStringLiteral("listbox");
105  }
106  break;
107  }
109  return QStringLiteral("signature");
110  }
111  return QString();
112 }
113 
114 // Field.type
115 static KJSObject fieldGetType(KJSContext *, void *object)
116 {
117  const FormField *field = reinterpret_cast<FormField *>(object);
118 
119  return KJSString(fieldGetTypeHelper(field));
120 }
121 
122 // Field.value (getter)
123 static KJSObject fieldGetValue(KJSContext * /*context*/, void *object)
124 {
125  FormField *field = reinterpret_cast<FormField *>(object);
126 
127  switch (field->type()) {
128  case FormField::FormButton: {
129  const FormFieldButton *button = static_cast<const FormFieldButton *>(field);
130  if (button->state()) {
131  return KJSString(QStringLiteral("Yes"));
132  }
133  return KJSString(QStringLiteral("Off"));
134  }
135  case FormField::FormText: {
136  const FormFieldText *text = static_cast<const FormFieldText *>(field);
137  return KJSString(text->text());
138  }
139  case FormField::FormChoice: {
140  const FormFieldChoice *choice = static_cast<const FormFieldChoice *>(field);
141  const QList<int> currentChoices = choice->currentChoices();
142  if (currentChoices.count() == 1) {
143  return KJSString(choice->exportValueForChoice(choice->choices().at(currentChoices[0])));
144  }
145  break;
146  }
148  break;
149  }
150  }
151 
152  return KJSUndefined();
153 }
154 
155 // Field.value (setter)
156 static void fieldSetValue(KJSContext *context, void *object, KJSObject value)
157 {
158  FormField *field = reinterpret_cast<FormField *>(object);
159 
160  switch (field->type()) {
161  case FormField::FormButton: {
162  FormFieldButton *button = static_cast<FormFieldButton *>(field);
163  const QString text = value.toString(context);
164  if (text == QStringLiteral("Yes")) {
165  button->setState(true);
166  updateField(field);
167  } else if (text == QStringLiteral("Off")) {
168  button->setState(false);
169  updateField(field);
170  }
171  break;
172  }
173  case FormField::FormText: {
174  FormFieldText *textField = static_cast<FormFieldText *>(field);
175  const QString text = value.toString(context);
176  if (text != textField->text()) {
177  textField->setText(text);
178  updateField(field);
179  }
180  break;
181  }
182  case FormField::FormChoice: {
183  FormFieldChoice *choice = static_cast<FormFieldChoice *>(field);
184  Q_UNUSED(choice); // ###
185  break;
186  }
188  break;
189  }
190  }
191 }
192 
193 // Field.hidden (getter)
194 static KJSObject fieldGetHidden(KJSContext *, void *object)
195 {
196  const FormField *field = reinterpret_cast<FormField *>(object);
197  return KJSBoolean(!field->isVisible());
198 }
199 
200 // Field.hidden (setter)
201 static void fieldSetHidden(KJSContext *context, void *object, KJSObject value)
202 {
203  FormField *field = reinterpret_cast<FormField *>(object);
204  bool b = value.toBoolean(context);
205  field->setVisible(!b);
206 
207  updateField(field);
208 }
209 
210 // Field.display (getter)
211 static KJSObject fieldGetDisplay(KJSContext *, void *object)
212 {
213  const FormField *field = reinterpret_cast<FormField *>(object);
214  bool visible = field->isVisible();
215  if (visible) {
216  return KJSNumber(field->isPrintable() ? FormDisplay::FormVisible : FormDisplay::FormNoPrint);
217  }
218  return KJSNumber(field->isPrintable() ? FormDisplay::FormNoView : FormDisplay::FormHidden);
219 }
220 
221 // Field.display (setter)
222 static void fieldSetDisplay(KJSContext *context, void *object, KJSObject value)
223 {
224  FormField *field = reinterpret_cast<FormField *>(object);
225  const unsigned int b = value.toInt32(context);
226  switch (b) {
227  case FormDisplay::FormVisible:
228  field->setVisible(true);
229  field->setPrintable(true);
230  break;
231  case FormDisplay::FormHidden:
232  field->setVisible(false);
233  field->setPrintable(false);
234  break;
235  case FormDisplay::FormNoPrint:
236  field->setVisible(true);
237  field->setPrintable(false);
238  break;
239  case FormDisplay::FormNoView:
240  field->setVisible(false);
241  field->setPrintable(true);
242  break;
243  }
244  updateField(field);
245 }
246 
247 // Instead of getting the Icon, we pick the field.
248 static KJSObject fieldButtonGetIcon(KJSContext *ctx, void *object, const KJSArguments &)
249 {
250  FormField *field = reinterpret_cast<FormField *>(object);
251 
252  KJSObject fieldObject;
253  fieldObject.setProperty(ctx, OKULAR_NAME, field->fullyQualifiedName());
254  g_buttonCache->insert(field->fullyQualifiedName(), field);
255 
256  return fieldObject;
257 }
258 
259 /*
260  * Now we send to the button what Icon should be drawn on it
261  */
262 static KJSObject fieldButtonSetIcon(KJSContext *ctx, void *object, const KJSArguments &arguments)
263 {
264  FormField *field = reinterpret_cast<FormField *>(object);
265 
266  const QString fieldName = arguments.at(0).property(ctx, OKULAR_NAME).toString(ctx);
267 
268  if (field->type() == Okular::FormField::FormButton) {
269  FormFieldButton *button = static_cast<FormFieldButton *>(field);
270  button->setIcon(g_buttonCache->value(fieldName));
271  }
272 
273  updateField(field);
274 
275  return KJSUndefined();
276 }
277 
278 void JSField::initType(KJSContext *ctx)
279 {
280  static bool initialized = false;
281  if (initialized) {
282  return;
283  }
284  initialized = true;
285 
286  if (!g_fieldProto) {
287  g_fieldProto = new KJSPrototype();
288  }
289 
290  g_fieldProto->defineProperty(ctx, QStringLiteral("doc"), fieldGetDoc);
291  g_fieldProto->defineProperty(ctx, QStringLiteral("name"), fieldGetName);
292  g_fieldProto->defineProperty(ctx, QStringLiteral("readonly"), fieldGetReadOnly, fieldSetReadOnly);
293  g_fieldProto->defineProperty(ctx, QStringLiteral("type"), fieldGetType);
294  g_fieldProto->defineProperty(ctx, QStringLiteral("value"), fieldGetValue, fieldSetValue);
295  g_fieldProto->defineProperty(ctx, QStringLiteral("hidden"), fieldGetHidden, fieldSetHidden);
296  g_fieldProto->defineProperty(ctx, QStringLiteral("display"), fieldGetDisplay, fieldSetDisplay);
297 
298  g_fieldProto->defineFunction(ctx, QStringLiteral("buttonGetIcon"), fieldButtonGetIcon);
299  g_fieldProto->defineFunction(ctx, QStringLiteral("buttonSetIcon"), fieldButtonSetIcon);
300 }
301 
302 KJSObject JSField::wrapField(KJSContext *ctx, FormField *field, Page *page)
303 {
304  // ### cache unique wrapper
305  KJSObject f = g_fieldProto->constructObject(ctx, field);
306  f.setProperty(ctx, QStringLiteral("page"), page->number());
307  g_fieldCache->insert(field, page);
308  return f;
309 }
310 
311 void JSField::clearCachedFields()
312 {
313  if (g_fieldCache.exists()) {
314  g_fieldCache->clear();
315  }
316 
317  if (g_buttonCache.exists()) {
318  g_buttonCache->clear();
319  }
320 }
@ FormButton
A "button". See FormFieldButton::ButtonType.
Definition: form.h:51
@ ComboBox
A combo box choice field.
Definition: form.h:354
Collector for all the data belonging to a page.
Definition: page.h:47
The Document.
Definition: document.h:190
bool toBoolean(KJSContext *ctx)
The base interface of a form field.
Definition: form.h:39
KJSObject globalObject()
@ CheckBox
A check box.
Definition: form.h:205
Interface of a button form field.
Definition: form.h:197
The documentation to the global Okular namespace.
Definition: action.h:16
virtual void setText(const QString &text)
Sets the new text in the text field.
Definition: form.cpp:203
int count(const T &value) const const
virtual ButtonType buttonType() const =0
The particular type of the button field.
@ FormSignature
A signature.
Definition: form.h:54
void refreshFormWidget(Okular::FormField *field)
This signal is emitted whenever a FormField was changed programmatically and the according widget sho...
Interface of a choice form field.
Definition: form.h:347
virtual void setPrintable(bool value)
Set this field printable.
Definition: form.cpp:75
KJSInterpreter interpreter()
virtual bool isReadOnly() const
Whether the field is read-only.
Definition: form.cpp:52
virtual QStringList choices() const =0
The possible choices of the choice field.
virtual void setReadOnly(bool value)
Whether the field is read-only.
Definition: form.cpp:57
Q_GLOBAL_STATIC(Internal::StaticControl, s_instance) class ControlPrivate
virtual ChoiceType choiceType() const =0
The particular type of the choice field.
virtual bool state() const =0
The state of the button.
virtual void setIcon(Okular::FormField *field)
Sets the icon of the Button to the Icon of the field parameter.
Definition: form.cpp:167
@ FormText
A field of variable text. See FormFieldText::TextType.
Definition: form.h:52
virtual void setVisible(bool value)
Whether the field is visible.
Definition: form.cpp:66
KJSObject at(int idx) const
KJSObject property(KJSContext *ctx, const QString &name)
const T & at(int i) const const
virtual QList< int > currentChoices() const =0
The currently selected choices.
int toInt32(KJSContext *ctx)
void defineProperty(KJSContext *ctx, const QString &name, PropertyGetter getter, PropertySetter setter=nullptr)
Interface of a text form field.
Definition: form.h:260
virtual void setState(bool state)
Sets the state of the button to the new state .
Definition: form.cpp:163
void defineFunction(KJSContext *ctx, const QString &name, FunctionCall callback)
KJSObject constructObject(KJSContext *ctx, void *internalValue=nullptr)
@ Push
A simple push button.
Definition: form.h:204
int number() const
Returns the number of the page in the document.
Definition: page.cpp:160
@ Radio
A radio button.
Definition: form.h:206
QString toString(KJSContext *ctx)
virtual QString text() const =0
The text of text field.
virtual QString fullyQualifiedName() const =0
The fully qualified name of the field, is used in the JavaScript scripts.
FieldType type() const
The type of the field.
Definition: form.cpp:46
void refreshPixmaps(int pageNumber)
Refresh the pixmaps for the given pageNumber.
Definition: document.cpp:5301
@ FormChoice
A choice field. See FormFieldChoice::ChoiceType.
Definition: form.h:53
QString exportValueForChoice(const QString &choice) const
Returns the export value for a given choice.
Definition: form.cpp:322
virtual bool isPrintable() const
Whether this field is printable.
Definition: form.cpp:70
@ ListBox
A list box choice field.
Definition: form.h:355
virtual bool isVisible() const
Whether this form field is visible.
Definition: form.cpp:61
virtual QVariant get(ScriptableExtension *callerPrincipal, quint64 objId, const QString &propName)
void setProperty(KJSContext *ctx, const QString &name, bool value)
This file is part of the KDE documentation.
Documentation copyright © 1996-2023 The KDE developers.
Generated on Thu Mar 23 2023 04:04:24 by doxygen 1.8.17 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.