Okular

js_field.cpp
1/*
2 SPDX-FileCopyrightText: 2008 Pino Toscano <pino@kde.org>
3 SPDX-FileCopyrightText: 2008 Harri Porten <porten@kde.org>
4
5 SPDX-License-Identifier: GPL-2.0-or-later
6*/
7
8#include "js_field_p.h"
9
10#include <QDebug>
11#include <QHash>
12#include <QJSEngine>
13#include <QTimer>
14
15#include "../debug_p.h"
16#include "../document_p.h"
17#include "../form.h"
18#include "../page.h"
19#include "../page_p.h"
20#include "js_display_p.h"
21
22using namespace Okular;
23
24#define OKULAR_NAME QStringLiteral("okular_name")
25
27Q_GLOBAL_STATIC(FormCache, g_fieldCache)
29Q_GLOBAL_STATIC(ButtonCache, g_buttonCache)
30
31// Helper for modified fields
32static void updateField(FormField *field)
33{
34 Page *page = g_fieldCache->value(field);
35 if (page) {
36 Document *doc = PagePrivate::get(page)->m_doc->m_parent;
37 const int pageNumber = page->number();
38 QTimer::singleShot(0, doc, [doc, pageNumber] { doc->refreshPixmaps(pageNumber); });
39 Q_EMIT doc->refreshFormWidget(field);
40 } else {
41 qWarning() << "Could not get page of field" << field;
42 }
43}
44
45// Field.doc
46QJSValue JSField::doc() const
47{
48 return qjsEngine(this)->globalObject();
49}
50
51// Field.name
52QString JSField::name() const
53{
54 return m_field->fullyQualifiedName();
55}
56
57// Field.readonly (getter)
58bool JSField::readonly() const
59{
60 return m_field->isReadOnly();
61}
62
63// Field.readonly (setter)
64void JSField::setReadonly(bool readonly)
65{
66 m_field->setReadOnly(readonly);
67
68 updateField(m_field);
69}
70
71static QString fieldGetTypeHelper(const FormField *field)
72{
73 switch (field->type()) {
75 const FormFieldButton *button = static_cast<const FormFieldButton *>(field);
76 switch (button->buttonType()) {
78 return QStringLiteral("button");
80 return QStringLiteral("checkbox");
82 return QStringLiteral("radiobutton");
83 }
84 break;
85 }
87 return QStringLiteral("text");
89 const FormFieldChoice *choice = static_cast<const FormFieldChoice *>(field);
90 switch (choice->choiceType()) {
92 return QStringLiteral("combobox");
94 return QStringLiteral("listbox");
95 }
96 break;
97 }
99 return QStringLiteral("signature");
100 }
101 return QString();
102}
103
104// Field.type
105QString JSField::type() const
106{
107 return fieldGetTypeHelper(m_field);
108}
109
110QJSValue JSField::fieldGetValueCore(bool asString) const
111{
113
114 switch (m_field->type()) {
116 const FormFieldButton *button = static_cast<const FormFieldButton *>(m_field);
117 if (button->state()) {
118 result = QStringLiteral("Yes");
119 } else {
120 result = QStringLiteral("Off");
121 }
122 break;
123 }
124 case FormField::FormText: {
125 const FormFieldText *text = static_cast<const FormFieldText *>(m_field);
126 const QLocale locale;
127 bool ok;
128 const double textAsNumber = locale.toDouble(text->text(), &ok);
129 if (ok && !asString) {
130 result = textAsNumber;
131 } else {
132 result = text->text();
133 }
134 break;
135 }
137 const FormFieldChoice *choice = static_cast<const FormFieldChoice *>(m_field);
138 const QList<int> currentChoices = choice->currentChoices();
139 if (currentChoices.count() == 1) {
140 result = choice->exportValueForChoice(choice->choices().at(currentChoices[0]));
141 }
142 break;
143 }
145 break;
146 }
147 }
148
149 qCDebug(OkularCoreDebug) << "fieldGetValueCore:"
150 << " Field: " << m_field->fullyQualifiedName() << " Type: " << fieldGetTypeHelper(m_field) << " Value: " << result.toString() << (result.isString() ? "(as string)" : "");
151 return result;
152}
153// Field.value (getter)
154QJSValue JSField::value() const
155{
156 return fieldGetValueCore(/*asString*/ false);
157}
158
159// Field.value (setter)
160void JSField::setValue(const QJSValue &value)
161{
162 qCDebug(OkularCoreDebug) << "fieldSetValue: Field: " << m_field->fullyQualifiedName() << " Type: " << fieldGetTypeHelper(m_field) << " Value: " << value.toString();
163 switch (m_field->type()) {
165 FormFieldButton *button = static_cast<FormFieldButton *>(m_field);
166 const QString text = value.toString();
167 if (text == QStringLiteral("Yes")) {
168 button->setState(true);
169 updateField(m_field);
170 } else if (text == QStringLiteral("Off")) {
171 button->setState(false);
172 updateField(m_field);
173 }
174 break;
175 }
176 case FormField::FormText: {
177 FormFieldText *textField = static_cast<FormFieldText *>(m_field);
178 const QString text = value.toString();
179 if (text != textField->text()) {
180 textField->setText(text);
181 updateField(m_field);
182 }
183 break;
184 }
186 FormFieldChoice *choice = static_cast<FormFieldChoice *>(m_field);
187 Q_UNUSED(choice); // ###
188 break;
189 }
191 break;
192 }
193 }
194}
195
196// Field.valueAsString (getter)
197QJSValue JSField::valueAsString() const
198{
199 return fieldGetValueCore(/*asString*/ true);
200}
201
202// Field.hidden (getter)
203bool JSField::hidden() const
204{
205 return !m_field->isVisible();
206}
207
208// Field.hidden (setter)
209void JSField::setHidden(bool hidden)
210{
211 m_field->setVisible(!hidden);
212
213 updateField(m_field);
214}
215
216// Field.display (getter)
217int JSField::display() const
218{
219 bool visible = m_field->isVisible();
220 if (visible) {
221 return m_field->isPrintable() ? FormDisplay::FormVisible : FormDisplay::FormNoPrint;
222 }
223 return m_field->isPrintable() ? FormDisplay::FormNoView : FormDisplay::FormHidden;
224}
225
226// Field.display (setter)
227void JSField::setDisplay(int display)
228{
229 switch (display) {
230 case FormDisplay::FormVisible:
231 m_field->setVisible(true);
232 m_field->setPrintable(true);
233 break;
234 case FormDisplay::FormHidden:
235 m_field->setVisible(false);
236 m_field->setPrintable(false);
237 break;
238 case FormDisplay::FormNoPrint:
239 m_field->setVisible(true);
240 m_field->setPrintable(false);
241 break;
242 case FormDisplay::FormNoView:
243 m_field->setVisible(false);
244 m_field->setPrintable(true);
245 break;
246 }
247 updateField(m_field);
248}
249
250// Instead of getting the Icon, we pick the field.
251QJSValue JSField::buttonGetIcon([[maybe_unused]] int nFace) const
252{
253 QJSValue fieldObject = qjsEngine(this)->newObject();
254 fieldObject.setProperty(OKULAR_NAME, m_field->fullyQualifiedName());
255 g_buttonCache->insert(m_field->fullyQualifiedName(), m_field);
256
257 return fieldObject;
258}
259
260/*
261 * Now we send to the button what Icon should be drawn on it
262 */
263void JSField::buttonSetIcon(const QJSValue &oIcon, [[maybe_unused]] int nFace)
264{
265 const QString fieldName = oIcon.property(OKULAR_NAME).toString();
266
267 if (m_field->type() == Okular::FormField::FormButton) {
268 FormFieldButton *button = static_cast<FormFieldButton *>(m_field);
269 const auto formField = g_buttonCache->value(fieldName);
270 if (formField) {
271 button->setIcon(formField);
272 }
273 }
274
275 updateField(m_field);
276}
277
278JSField::JSField(FormField *field, QObject *parent)
279 : QObject(parent)
280 , m_field(field)
281{
282}
283
284JSField::~JSField() = default;
285
286QJSValue JSField::wrapField(QJSEngine *engine, FormField *field, Page *page)
287{
288 // ### cache unique wrapper
289 QJSValue f = engine->newQObject(new JSField(field));
290 f.setProperty(QStringLiteral("page"), page->number());
291 g_fieldCache->insert(field, page);
292 return f;
293}
294
295void JSField::clearCachedFields()
296{
297 if (g_fieldCache.exists()) {
298 g_fieldCache->clear();
299 }
300
301 if (g_buttonCache.exists()) {
302 g_buttonCache->clear();
303 }
304}
Interface of a button form field.
Definition form.h:198
@ Push
A simple push button.
Definition form.h:204
@ CheckBox
A check box.
Definition form.h:205
@ Radio
A radio button.
Definition form.h:206
virtual void setState(bool state)
Sets the state of the button to the new state .
Definition form.cpp:164
virtual void setIcon(Okular::FormField *field)
Sets the icon of the Button to the Icon of the field parameter.
Definition form.cpp:168
virtual ButtonType buttonType() const =0
The particular type of the button field.
virtual bool state() const =0
The state of the button.
Interface of a choice form field.
Definition form.h:348
QString exportValueForChoice(const QString &choice) const
Returns the export value for a given choice.
Definition form.cpp:323
@ ComboBox
A combo box choice field.
Definition form.h:354
@ ListBox
A list box choice field.
Definition form.h:355
virtual QList< int > currentChoices() const =0
The currently selected choices.
virtual ChoiceType choiceType() const =0
The particular type of the choice field.
virtual QStringList choices() const =0
The possible choices of the choice field.
Interface of a text form field.
Definition form.h:261
virtual void setText(const QString &text)
Sets the new text in the text field.
Definition form.cpp:204
virtual QString text() const =0
The text of text field.
The base interface of a form field.
Definition form.h:40
@ FormText
A field of variable text. See FormFieldText::TextType.
Definition form.h:52
@ FormChoice
A choice field. See FormFieldChoice::ChoiceType.
Definition form.h:53
@ FormButton
A "button". See FormFieldButton::ButtonType.
Definition form.h:51
@ FormSignature
A signature.
Definition form.h:54
FieldType type() const
The type of the field.
Definition form.cpp:47
global.h
Definition action.h:17
QJSValue newQObject(QObject *object)
QJSValue property(const QString &name) const const
void setProperty(const QString &name, const QJSValue &value)
QString toString() const const
const_reference at(qsizetype i) const const
qsizetype count() const const
double toDouble(QStringView s, bool *ok) const const
This file is part of the KDE documentation.
Documentation copyright © 1996-2024 The KDE developers.
Generated on Tue Mar 26 2024 11:17:35 by doxygen 1.10.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.