mirror of
https://invent.kde.org/graphics/okular
synced 2024-08-27 11:40:07 +00:00
302 lines
8 KiB
C++
302 lines
8 KiB
C++
/*
|
|
SPDX-FileCopyrightText: 2008 Pino Toscano <pino@kde.org>
|
|
SPDX-FileCopyrightText: 2008 Harri Porten <porten@kde.org>
|
|
|
|
SPDX-License-Identifier: GPL-2.0-or-later
|
|
*/
|
|
|
|
#include "js_field_p.h"
|
|
|
|
#include <QDebug>
|
|
#include <QHash>
|
|
#include <QJSEngine>
|
|
#include <QTimer>
|
|
|
|
#include "../debug_p.h"
|
|
#include "../document_p.h"
|
|
#include "../form.h"
|
|
#include "../page.h"
|
|
#include "../page_p.h"
|
|
#include "js_display_p.h"
|
|
|
|
using namespace Okular;
|
|
|
|
#define OKULAR_NAME QStringLiteral("okular_name")
|
|
|
|
typedef QHash<FormField *, Page *> FormCache;
|
|
Q_GLOBAL_STATIC(FormCache, g_fieldCache)
|
|
typedef QHash<QString, FormField *> ButtonCache;
|
|
Q_GLOBAL_STATIC(ButtonCache, g_buttonCache)
|
|
|
|
// Helper for modified fields
|
|
static void updateField(FormField *field)
|
|
{
|
|
Page *page = g_fieldCache->value(field);
|
|
if (page) {
|
|
Document *doc = PagePrivate::get(page)->m_doc->m_parent;
|
|
const int pageNumber = page->number();
|
|
QTimer::singleShot(0, doc, [doc, pageNumber] { doc->refreshPixmaps(pageNumber); });
|
|
Q_EMIT doc->refreshFormWidget(field);
|
|
} else {
|
|
qWarning() << "Could not get page of field" << field;
|
|
}
|
|
}
|
|
|
|
// Field.doc
|
|
QJSValue JSField::doc() const
|
|
{
|
|
return qjsEngine(this)->globalObject();
|
|
}
|
|
|
|
// Field.name
|
|
QString JSField::name() const
|
|
{
|
|
return m_field->fullyQualifiedName();
|
|
}
|
|
|
|
// Field.readonly (getter)
|
|
bool JSField::readonly() const
|
|
{
|
|
return m_field->isReadOnly();
|
|
}
|
|
|
|
// Field.readonly (setter)
|
|
void JSField::setReadonly(bool readonly)
|
|
{
|
|
m_field->setReadOnly(readonly);
|
|
|
|
updateField(m_field);
|
|
}
|
|
|
|
static QString fieldGetTypeHelper(const FormField *field)
|
|
{
|
|
switch (field->type()) {
|
|
case FormField::FormButton: {
|
|
const FormFieldButton *button = static_cast<const FormFieldButton *>(field);
|
|
switch (button->buttonType()) {
|
|
case FormFieldButton::Push:
|
|
return QStringLiteral("button");
|
|
case FormFieldButton::CheckBox:
|
|
return QStringLiteral("checkbox");
|
|
case FormFieldButton::Radio:
|
|
return QStringLiteral("radiobutton");
|
|
}
|
|
break;
|
|
}
|
|
case FormField::FormText:
|
|
return QStringLiteral("text");
|
|
case FormField::FormChoice: {
|
|
const FormFieldChoice *choice = static_cast<const FormFieldChoice *>(field);
|
|
switch (choice->choiceType()) {
|
|
case FormFieldChoice::ComboBox:
|
|
return QStringLiteral("combobox");
|
|
case FormFieldChoice::ListBox:
|
|
return QStringLiteral("listbox");
|
|
}
|
|
break;
|
|
}
|
|
case FormField::FormSignature:
|
|
return QStringLiteral("signature");
|
|
}
|
|
return QString();
|
|
}
|
|
|
|
// Field.type
|
|
QString JSField::type() const
|
|
{
|
|
return fieldGetTypeHelper(m_field);
|
|
}
|
|
|
|
QJSValue JSField::fieldGetValueCore(bool asString) const
|
|
{
|
|
QJSValue result(QJSValue::UndefinedValue);
|
|
|
|
switch (m_field->type()) {
|
|
case FormField::FormButton: {
|
|
const FormFieldButton *button = static_cast<const FormFieldButton *>(m_field);
|
|
if (button->state()) {
|
|
result = QStringLiteral("Yes");
|
|
} else {
|
|
result = QStringLiteral("Off");
|
|
}
|
|
break;
|
|
}
|
|
case FormField::FormText: {
|
|
const FormFieldText *text = static_cast<const FormFieldText *>(m_field);
|
|
const QLocale locale;
|
|
bool ok;
|
|
const double textAsNumber = locale.toDouble(text->text(), &ok);
|
|
if (ok && !asString) {
|
|
result = textAsNumber;
|
|
} else {
|
|
result = text->text();
|
|
}
|
|
break;
|
|
}
|
|
case FormField::FormChoice: {
|
|
const FormFieldChoice *choice = static_cast<const FormFieldChoice *>(m_field);
|
|
const QList<int> currentChoices = choice->currentChoices();
|
|
if (currentChoices.count() == 1) {
|
|
result = choice->exportValueForChoice(choice->choices().at(currentChoices[0]));
|
|
}
|
|
break;
|
|
}
|
|
case FormField::FormSignature: {
|
|
break;
|
|
}
|
|
}
|
|
|
|
qCDebug(OkularCoreDebug) << "fieldGetValueCore:"
|
|
<< " Field: " << m_field->fullyQualifiedName() << " Type: " << fieldGetTypeHelper(m_field) << " Value: " << result.toString() << (result.isString() ? "(as string)" : "");
|
|
return result;
|
|
}
|
|
// Field.value (getter)
|
|
QJSValue JSField::value() const
|
|
{
|
|
return fieldGetValueCore(/*asString*/ false);
|
|
}
|
|
|
|
// Field.value (setter)
|
|
void JSField::setValue(const QJSValue &value)
|
|
{
|
|
qCDebug(OkularCoreDebug) << "fieldSetValue: Field: " << m_field->fullyQualifiedName() << " Type: " << fieldGetTypeHelper(m_field) << " Value: " << value.toString();
|
|
switch (m_field->type()) {
|
|
case FormField::FormButton: {
|
|
FormFieldButton *button = static_cast<FormFieldButton *>(m_field);
|
|
const QString text = value.toString();
|
|
if (text == QStringLiteral("Yes")) {
|
|
button->setState(true);
|
|
updateField(m_field);
|
|
} else if (text == QStringLiteral("Off")) {
|
|
button->setState(false);
|
|
updateField(m_field);
|
|
}
|
|
break;
|
|
}
|
|
case FormField::FormText: {
|
|
FormFieldText *textField = static_cast<FormFieldText *>(m_field);
|
|
const QString text = value.toString();
|
|
if (text != textField->text()) {
|
|
textField->setText(text);
|
|
updateField(m_field);
|
|
}
|
|
break;
|
|
}
|
|
case FormField::FormChoice: {
|
|
FormFieldChoice *choice = static_cast<FormFieldChoice *>(m_field);
|
|
Q_UNUSED(choice); // ###
|
|
break;
|
|
}
|
|
case FormField::FormSignature: {
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
// Field.valueAsString (getter)
|
|
QJSValue JSField::valueAsString() const
|
|
{
|
|
return fieldGetValueCore(/*asString*/ true);
|
|
}
|
|
|
|
// Field.hidden (getter)
|
|
bool JSField::hidden() const
|
|
{
|
|
return !m_field->isVisible();
|
|
}
|
|
|
|
// Field.hidden (setter)
|
|
void JSField::setHidden(bool hidden)
|
|
{
|
|
m_field->setVisible(!hidden);
|
|
|
|
updateField(m_field);
|
|
}
|
|
|
|
// Field.display (getter)
|
|
int JSField::display() const
|
|
{
|
|
bool visible = m_field->isVisible();
|
|
if (visible) {
|
|
return m_field->isPrintable() ? FormDisplay::FormVisible : FormDisplay::FormNoPrint;
|
|
}
|
|
return m_field->isPrintable() ? FormDisplay::FormNoView : FormDisplay::FormHidden;
|
|
}
|
|
|
|
// Field.display (setter)
|
|
void JSField::setDisplay(int display)
|
|
{
|
|
switch (display) {
|
|
case FormDisplay::FormVisible:
|
|
m_field->setVisible(true);
|
|
m_field->setPrintable(true);
|
|
break;
|
|
case FormDisplay::FormHidden:
|
|
m_field->setVisible(false);
|
|
m_field->setPrintable(false);
|
|
break;
|
|
case FormDisplay::FormNoPrint:
|
|
m_field->setVisible(true);
|
|
m_field->setPrintable(false);
|
|
break;
|
|
case FormDisplay::FormNoView:
|
|
m_field->setVisible(false);
|
|
m_field->setPrintable(true);
|
|
break;
|
|
}
|
|
updateField(m_field);
|
|
}
|
|
|
|
// Instead of getting the Icon, we pick the field.
|
|
QJSValue JSField::buttonGetIcon([[maybe_unused]] int nFace) const
|
|
{
|
|
QJSValue fieldObject;
|
|
fieldObject.setProperty(OKULAR_NAME, m_field->fullyQualifiedName());
|
|
g_buttonCache->insert(m_field->fullyQualifiedName(), m_field);
|
|
|
|
return fieldObject;
|
|
}
|
|
|
|
/*
|
|
* Now we send to the button what Icon should be drawn on it
|
|
*/
|
|
void JSField::buttonSetIcon(const QJSValue &oIcon, [[maybe_unused]] int nFace)
|
|
{
|
|
const QString fieldName = oIcon.property(OKULAR_NAME).toString();
|
|
|
|
if (m_field->type() == Okular::FormField::FormButton) {
|
|
FormFieldButton *button = static_cast<FormFieldButton *>(m_field);
|
|
button->setIcon(g_buttonCache->value(fieldName));
|
|
}
|
|
|
|
updateField(m_field);
|
|
}
|
|
|
|
JSField::JSField(FormField *field, QObject *parent)
|
|
: QObject(parent)
|
|
, m_field(field)
|
|
{
|
|
}
|
|
|
|
JSField::~JSField() = default;
|
|
|
|
QJSValue JSField::wrapField(QJSEngine *engine, FormField *field, Page *page)
|
|
{
|
|
// ### cache unique wrapper
|
|
QJSValue f = engine->newQObject(new JSField(field));
|
|
f.setProperty(QStringLiteral("page"), page->number());
|
|
g_fieldCache->insert(field, page);
|
|
return f;
|
|
}
|
|
|
|
void JSField::clearCachedFields()
|
|
{
|
|
if (g_fieldCache.exists()) {
|
|
g_fieldCache->clear();
|
|
}
|
|
|
|
if (g_buttonCache.exists()) {
|
|
g_buttonCache->clear();
|
|
}
|
|
}
|