Okular

kjs_document.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_document_p.h"
9 
10 #include <qwidget.h>
11 
12 #include <kjs/kjsarguments.h>
13 #include <kjs/kjsobject.h>
14 #include <kjs/kjsprototype.h>
15 
16 #include <QDebug>
17 #include <assert.h>
18 
19 #include "../document_p.h"
20 #include "../form.h"
21 #include "../page.h"
22 #include "kjs_data_p.h"
23 #include "kjs_field_p.h"
24 #include "kjs_ocg_p.h"
25 
26 using namespace Okular;
27 
28 static KJSPrototype *g_docProto;
29 
30 // Document.numPages
31 static KJSObject docGetNumPages(KJSContext *, void *object)
32 {
33  DocumentPrivate *doc = reinterpret_cast<DocumentPrivate *>(object);
34 
35  return KJSNumber(doc->m_pagesVector.count());
36 }
37 
38 // Document.pageNum (getter)
39 static KJSObject docGetPageNum(KJSContext *, void *object)
40 {
41  DocumentPrivate *doc = reinterpret_cast<DocumentPrivate *>(object);
42 
43  return KJSNumber(doc->m_parent->currentPage());
44 }
45 
46 // Document.pageNum (setter)
47 static void docSetPageNum(KJSContext *ctx, void *object, KJSObject value)
48 {
49  DocumentPrivate *doc = reinterpret_cast<DocumentPrivate *>(object);
50 
51  int page = value.toInt32(ctx);
52 
53  if (page == (int)doc->m_parent->currentPage()) {
54  return;
55  }
56 
57  doc->m_parent->setViewportPage(page);
58 }
59 
60 // Document.documentFileName
61 static KJSObject docGetDocumentFileName(KJSContext *, void *object)
62 {
63  DocumentPrivate *doc = reinterpret_cast<DocumentPrivate *>(object);
64 
65  return KJSString(doc->m_url.fileName());
66 }
67 
68 // Document.filesize
69 static KJSObject docGetFilesize(KJSContext *, void *object)
70 {
71  DocumentPrivate *doc = reinterpret_cast<DocumentPrivate *>(object);
72 
73  return KJSNumber(doc->m_docSize);
74 }
75 
76 // Document.path
77 static KJSObject docGetPath(KJSContext *, void *object)
78 {
79  DocumentPrivate *doc = reinterpret_cast<DocumentPrivate *>(object);
80 
81  return KJSString(doc->m_url.toDisplayString(QUrl::PreferLocalFile));
82 }
83 
84 // Document.URL
85 static KJSObject docGetURL(KJSContext *, void *object)
86 {
87  DocumentPrivate *doc = reinterpret_cast<DocumentPrivate *>(object);
88 
89  return KJSString(doc->m_url.toDisplayString());
90 }
91 
92 // Document.permStatusReady
93 static KJSObject docGetPermStatusReady(KJSContext *, void *)
94 {
95  return KJSBoolean(true);
96 }
97 
98 // Document.dataObjects
99 static KJSObject docGetDataObjects(KJSContext *ctx, void *object)
100 {
101  DocumentPrivate *doc = reinterpret_cast<DocumentPrivate *>(object);
102 
103  const QList<EmbeddedFile *> *files = doc->m_generator->embeddedFiles();
104 
105  KJSArray dataObjects(ctx, files ? files->count() : 0);
106  if (files) {
107  QList<EmbeddedFile *>::ConstIterator it = files->begin(), itEnd = files->end();
108  for (int i = 0; it != itEnd; ++it, ++i) {
109  KJSObject newdata = JSData::wrapFile(ctx, *it);
110  dataObjects.setProperty(ctx, QString::number(i), newdata);
111  }
112  }
113  return dataObjects;
114 }
115 
116 // Document.external
117 static KJSObject docGetExternal(KJSContext *, void *object)
118 {
119  DocumentPrivate *doc = reinterpret_cast<DocumentPrivate *>(object);
120  QWidget *widget = doc->m_widget;
121 
122  const bool isShell = (widget && widget->parentWidget() && widget->parentWidget()->objectName().startsWith(QLatin1String("okular::Shell")));
123  return KJSBoolean(!isShell);
124 }
125 
126 // Document.numFields
127 static KJSObject docGetNumFields(KJSContext *, void *object)
128 {
129  const DocumentPrivate *doc = reinterpret_cast<DocumentPrivate *>(object);
130 
131  unsigned int numFields = 0;
132 
133  for (const Page *pIt : qAsConst(doc->m_pagesVector)) {
134  numFields += pIt->formFields().size();
135  }
136 
137  return KJSNumber(numFields);
138 }
139 
140 static KJSObject docGetInfo(KJSContext *ctx, void *object)
141 {
142  DocumentPrivate *doc = reinterpret_cast<DocumentPrivate *>(object);
143 
144  KJSObject obj;
147  const DocumentInfo docinfo = doc->m_parent->documentInfo(keys);
148 #define KEY_GET(key, property) \
149  do { \
150  const QString data = docinfo.get(key); \
151  if (!data.isEmpty()) { \
152  const KJSString newval(data); \
153  obj.setProperty(ctx, QStringLiteral(property), newval); \
154  obj.setProperty(ctx, QStringLiteral(property).toLower(), newval); \
155  } \
156  } while (0);
157  KEY_GET(DocumentInfo::Title, "Title");
158  KEY_GET(DocumentInfo::Author, "Author");
159  KEY_GET(DocumentInfo::Subject, "Subject");
160  KEY_GET(DocumentInfo::Keywords, "Keywords");
161  KEY_GET(DocumentInfo::Creator, "Creator");
162  KEY_GET(DocumentInfo::Producer, "Producer");
163 #undef KEY_GET
164  return obj;
165 }
166 
167 #define DOCINFO_GET_METHOD(key, name) \
168  static KJSObject docGet##name(KJSContext *, void *object) \
169  { \
170  DocumentPrivate *doc = reinterpret_cast<DocumentPrivate *>(object); \
171  const DocumentInfo docinfo = doc->m_parent->documentInfo(QSet<DocumentInfo::Key>() << key); \
172  return KJSString(docinfo.get(key)); \
173  }
174 
175 DOCINFO_GET_METHOD(DocumentInfo::Author, Author)
176 DOCINFO_GET_METHOD(DocumentInfo::Creator, Creator)
177 DOCINFO_GET_METHOD(DocumentInfo::Keywords, Keywords)
178 DOCINFO_GET_METHOD(DocumentInfo::Producer, Producer)
179 DOCINFO_GET_METHOD(DocumentInfo::Title, Title)
180 DOCINFO_GET_METHOD(DocumentInfo::Subject, Subject)
181 
182 #undef DOCINFO_GET_METHOD
183 
184 // Document.getField()
185 static KJSObject docGetField(KJSContext *context, void *object, const KJSArguments &arguments)
186 {
187  DocumentPrivate *doc = reinterpret_cast<DocumentPrivate *>(object);
188 
189  QString cName = arguments.at(0).toString(context);
190 
191  QVector<Page *>::const_iterator pIt = doc->m_pagesVector.constBegin(), pEnd = doc->m_pagesVector.constEnd();
192  for (; pIt != pEnd; ++pIt) {
193  const QList<Okular::FormField *> pageFields = (*pIt)->formFields();
194  for (FormField *form : pageFields) {
195  if (form->fullyQualifiedName() == cName) {
196  return JSField::wrapField(context, form, *pIt);
197  }
198  }
199  }
200  return KJSUndefined();
201 }
202 
203 // Document.getPageLabel()
204 static KJSObject docGetPageLabel(KJSContext *ctx, void *object, const KJSArguments &arguments)
205 {
206  DocumentPrivate *doc = reinterpret_cast<DocumentPrivate *>(object);
207  int nPage = arguments.at(0).toInt32(ctx);
208  Page *p = doc->m_pagesVector.value(nPage);
209  return KJSString(p ? p->label() : QString());
210 }
211 
212 // Document.getPageRotation()
213 static KJSObject docGetPageRotation(KJSContext *ctx, void *object, const KJSArguments &arguments)
214 {
215  DocumentPrivate *doc = reinterpret_cast<DocumentPrivate *>(object);
216  int nPage = arguments.at(0).toInt32(ctx);
217  Page *p = doc->m_pagesVector.value(nPage);
218  return KJSNumber(p ? p->orientation() * 90 : 0);
219 }
220 
221 // Document.gotoNamedDest()
222 static KJSObject docGotoNamedDest(KJSContext *ctx, void *object, const KJSArguments &arguments)
223 {
224  DocumentPrivate *doc = reinterpret_cast<DocumentPrivate *>(object);
225 
226  QString dest = arguments.at(0).toString(ctx);
227 
228  DocumentViewport viewport(doc->m_generator->metaData(QStringLiteral("NamedViewport"), dest).toString());
229  if (!viewport.isValid()) {
230  return KJSUndefined();
231  }
232 
233  doc->m_parent->setViewport(viewport);
234 
235  return KJSUndefined();
236 }
237 
238 // Document.syncAnnotScan()
239 static KJSObject docSyncAnnotScan(KJSContext *, void *, const KJSArguments &)
240 {
241  return KJSUndefined();
242 }
243 
244 // Document.getNthFieldName
245 static KJSObject docGetNthFieldName(KJSContext *ctx, void *object, const KJSArguments &arguments)
246 {
247  const DocumentPrivate *doc = reinterpret_cast<DocumentPrivate *>(object);
248 
249  int numField = arguments.at(0).toInt32(ctx);
250 
251  for (const Page *pIt : qAsConst(doc->m_pagesVector)) {
252  const QList<Okular::FormField *> pageFields = pIt->formFields();
253 
254  if (numField < pageFields.size()) {
255  const Okular::FormField *form = pageFields[numField];
256 
257  return KJSString(form->fullyQualifiedName());
258  }
259 
260  numField -= pageFields.size();
261  }
262 
263  return KJSUndefined();
264 }
265 
266 static KJSObject docGetOCGs(KJSContext *ctx, void *object, const KJSArguments &)
267 {
268  const DocumentPrivate *doc = reinterpret_cast<DocumentPrivate *>(object);
269 
270  QAbstractItemModel *model = doc->m_parent->layersModel();
271 
272  KJSArray array(ctx, model->rowCount());
273 
274  for (int i = 0; i < model->rowCount(); ++i) {
275  for (int j = 0; j < model->columnCount(); ++j) {
276  const QModelIndex index = model->index(i, j);
277 
278  KJSObject item = JSOCG::wrapOCGObject(ctx, model, i, j);
279  item.setProperty(ctx, QStringLiteral("name"), model->data(index, Qt::DisplayRole).toString());
280  item.setProperty(ctx, QStringLiteral("initState"), model->data(index, Qt::CheckStateRole).toBool());
281 
282  array.setProperty(ctx, QString::number(i), item);
283  }
284  }
285 
286  return array;
287 }
288 
289 void JSDocument::initType(KJSContext *ctx)
290 {
291  assert(g_docProto);
292 
293  static bool initialized = false;
294  if (initialized) {
295  return;
296  }
297  initialized = true;
298 
299  g_docProto->defineProperty(ctx, QStringLiteral("numPages"), docGetNumPages);
300  g_docProto->defineProperty(ctx, QStringLiteral("pageNum"), docGetPageNum, docSetPageNum);
301  g_docProto->defineProperty(ctx, QStringLiteral("documentFileName"), docGetDocumentFileName);
302  g_docProto->defineProperty(ctx, QStringLiteral("filesize"), docGetFilesize);
303  g_docProto->defineProperty(ctx, QStringLiteral("path"), docGetPath);
304  g_docProto->defineProperty(ctx, QStringLiteral("URL"), docGetURL);
305  g_docProto->defineProperty(ctx, QStringLiteral("permStatusReady"), docGetPermStatusReady);
306  g_docProto->defineProperty(ctx, QStringLiteral("dataObjects"), docGetDataObjects);
307  g_docProto->defineProperty(ctx, QStringLiteral("external"), docGetExternal);
308  g_docProto->defineProperty(ctx, QStringLiteral("numFields"), docGetNumFields);
309 
310  // info properties
311  g_docProto->defineProperty(ctx, QStringLiteral("info"), docGetInfo);
312  g_docProto->defineProperty(ctx, QStringLiteral("author"), docGetAuthor);
313  g_docProto->defineProperty(ctx, QStringLiteral("creator"), docGetCreator);
314  g_docProto->defineProperty(ctx, QStringLiteral("keywords"), docGetKeywords);
315  g_docProto->defineProperty(ctx, QStringLiteral("producer"), docGetProducer);
316  g_docProto->defineProperty(ctx, QStringLiteral("title"), docGetTitle);
317  g_docProto->defineProperty(ctx, QStringLiteral("subject"), docGetSubject);
318 
319  g_docProto->defineFunction(ctx, QStringLiteral("getField"), docGetField);
320  g_docProto->defineFunction(ctx, QStringLiteral("getPageLabel"), docGetPageLabel);
321  g_docProto->defineFunction(ctx, QStringLiteral("getPageRotation"), docGetPageRotation);
322  g_docProto->defineFunction(ctx, QStringLiteral("gotoNamedDest"), docGotoNamedDest);
323  g_docProto->defineFunction(ctx, QStringLiteral("syncAnnotScan"), docSyncAnnotScan);
324  g_docProto->defineFunction(ctx, QStringLiteral("getNthFieldName"), docGetNthFieldName);
325  g_docProto->defineFunction(ctx, QStringLiteral("getOCGs"), docGetOCGs);
326 }
327 
328 KJSGlobalObject JSDocument::wrapDocument(DocumentPrivate *doc)
329 {
330  if (!g_docProto) {
331  g_docProto = new KJSPrototype();
332  }
333  return g_docProto->constructGlobalObject(doc);
334 }
@ Author
The author of the document.
Definition: document.h:86
Collector for all the data belonging to a page.
Definition: page.h:47
The base interface of a form field.
Definition: form.h:39
DisplayRole
QString number(int n, int base)
virtual int rowCount(const QModelIndex &parent) const const=0
The documentation to the global Okular namespace.
Definition: action.h:16
virtual QVariant data(const QModelIndex &index, int role) const const=0
@ Producer
The producer of the document (e.g. some software)
Definition: document.h:88
int count(const T &value) const const
@ Creator
The creator of the document (this can be different from the author)
Definition: document.h:87
@ Title
The title of the document.
Definition: document.h:83
Rotation orientation() const
Returns the orientation of the page as defined by the document.
Definition: page.cpp:165
int size() const const
PreferLocalFile
KJSObject at(int idx) const
char * toString(const T &value)
int toInt32(KJSContext *ctx)
void defineProperty(KJSContext *ctx, const QString &name, PropertyGetter getter, PropertySetter setter=nullptr)
virtual int columnCount(const QModelIndex &parent) const const=0
KJSGlobalObject constructGlobalObject(void *internalValue=nullptr)
@ Keywords
The keywords which describe the content of the document.
Definition: document.h:95
@ Subject
The subject of the document.
Definition: document.h:84
A view on the document.
Definition: document.h:1351
bool toBool() const const
void defineFunction(KJSContext *ctx, const QString &name, FunctionCall callback)
QString label() const
Returns the label of the page, or a null string if not set.
Definition: page.cpp:666
virtual QModelIndex index(int row, int column, const QModelIndex &parent) const const=0
QList::iterator begin()
QString toString(KJSContext *ctx)
virtual QString fullyQualifiedName() const =0
The fully qualified name of the field, is used in the JavaScript scripts.
QVector::const_iterator constBegin() const const
QList::iterator end()
QWidget * parentWidget() const const
The DocumentInfo structure can be filled in by generators to display metadata about the currently ope...
Definition: document.h:74
void setProperty(KJSContext *ctx, const QString &name, bool value)
QString toString() const const
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.