Okular

kjs_util.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_util_p.h"
9 
10 #include <kjs/kjsarguments.h>
11 #include <kjs/kjsobject.h>
12 #include <kjs/kjsprototype.h>
13 
14 #include <QDateTime>
15 #include <QDebug>
16 #include <QLocale>
17 #include <QRegularExpression>
18 #include <QUrl>
19 
20 #include <cmath>
21 
22 using namespace Okular;
23 
24 static KJSPrototype *g_utilProto;
25 
26 static KJSObject crackURL(KJSContext *context, void *, const KJSArguments &arguments)
27 {
28  if (arguments.count() < 1) {
29  return context->throwException(QStringLiteral("Missing URL argument"));
30  }
31  QString cURL = arguments.at(0).toString(context);
32  QUrl url(QUrl::fromLocalFile(cURL));
33  if (!url.isValid()) {
34  return context->throwException(QStringLiteral("Invalid URL"));
35  }
36  if (url.scheme() != QLatin1String("file") || url.scheme() != QLatin1String("http") || url.scheme() != QLatin1String("https")) {
37  return context->throwException(QStringLiteral("Protocol not valid: '") + url.scheme() + QLatin1Char('\''));
38  }
39 
40  KJSObject obj;
41  obj.setProperty(context, QStringLiteral("cScheme"), url.scheme());
42  if (!url.userName().isEmpty()) {
43  obj.setProperty(context, QStringLiteral("cUser"), url.userName());
44  }
45  if (!url.password().isEmpty()) {
46  obj.setProperty(context, QStringLiteral("cPassword"), url.password());
47  }
48  obj.setProperty(context, QStringLiteral("cHost"), url.host());
49  obj.setProperty(context, QStringLiteral("nPort"), url.port(80));
50  // TODO cPath (Optional) The path portion of the URL.
51  // TODO cParameters (Optional) The parameter string portion of the URL.
52  if (url.hasFragment()) {
53  obj.setProperty(context, QStringLiteral("cFragments"), url.fragment(QUrl::FullyDecoded));
54  }
55 
56  return obj;
57 }
58 
59 static KJSObject printd(KJSContext *context, void *, const KJSArguments &arguments)
60 {
61  if (arguments.count() < 2) {
62  return context->throwException(QStringLiteral("Invalid arguments"));
63  }
64 
65  KJSObject oFormat = arguments.at(0);
66  QString format;
67  QLocale defaultLocale;
68 
69  if (oFormat.isNumber()) {
70  int formatType = oFormat.toInt32(context);
71  switch (formatType) {
72  case 0:
73  format = QStringLiteral("D:yyyyMMddHHmmss");
74  break;
75  case 1:
76  format = QStringLiteral("yyyy.MM.dd HH:mm:ss");
77  break;
78  case 2:
79  format = defaultLocale.dateTimeFormat(QLocale::ShortFormat);
80  if (!format.contains(QStringLiteral("ss"))) {
81  format.insert(format.indexOf(QStringLiteral("mm")) + 2, QStringLiteral(":ss"));
82  }
83  break;
84  }
85  } else {
86  format = arguments.at(0).toString(context).replace(QLatin1String("tt"), QLatin1String("ap"));
87  format.replace(QLatin1Char('t'), QLatin1Char('a'));
88  for (QChar &formatChar : format) {
89  if (formatChar == QLatin1Char('M')) {
90  formatChar = QLatin1Char('m');
91  } else if (formatChar == QLatin1Char('m')) {
92  formatChar = QLatin1Char('M');
93  }
94  }
95  }
96 
97  QLocale locale(QStringLiteral("en_US"));
98  const QStringList str = arguments.at(1).toString(context).split(QRegularExpression(QStringLiteral("\\W")));
99 
100  if (str.count() < 7) {
101  qWarning() << "Unexpected printd oDate argument" << arguments.at(1).toString(context);
102  return context->throwException(QStringLiteral("Invalid arguments"));
103  }
104 
105  QString myStr = QStringLiteral("%1/%2/%3 %4:%5:%6").arg(str[1], str[2], str[3], str[4], str[5], str[6]);
106  QDateTime date = locale.toDateTime(myStr, QStringLiteral("MMM/d/yyyy H:m:s"));
107 
108  return KJSString(defaultLocale.toString(date, format));
109 }
110 
111 /** Converts a Number to a String using l10n
112  *
113  * String numberToString( Number number, String format = 'g', int precision = 6,
114  * String LocaleName = system )
115  */
116 static KJSObject numberToString(KJSContext *context, void *, const KJSArguments &arguments)
117 {
118  if (arguments.count() < 1) {
119  return context->throwException(QStringLiteral("Invalid arguments"));
120  }
121 
122  const double number = arguments.at(0).toNumber(context);
123  if (std::isnan(number)) {
124  return KJSString("NaN");
125  }
126 
127  QChar format = QLatin1Char('g');
128  if (arguments.count() >= 2) {
129  const QString fmt = arguments.at(1).toString(context);
130  if (!fmt.isEmpty()) {
131  format = fmt[0];
132  }
133  }
134 
135  int precision = 6;
136  if (arguments.count() >= 3) {
137  precision = arguments.at(2).toInt32(context);
138  }
139 
140  QLocale locale;
141  if (arguments.count() == 4) {
142  locale = QLocale(arguments.at(3).toString(context));
143  }
144 
145  return KJSString(locale.toString(number, format.toLatin1(), precision));
146 }
147 
148 /** Converts a String to a Number trying with the current locale first and
149  * if that fails trying with the reverse locale for the decimal separator
150  *
151  * Number stringToNumber( String number ) */
152 static KJSObject stringToNumber(KJSContext *context, void *, const KJSArguments &arguments)
153 {
154  if (arguments.count() < 1) {
155  return context->throwException(QStringLiteral("Invalid arguments"));
156  }
157 
158  const QString number = arguments.at(0).toString(context);
159  if (number.isEmpty()) {
160  return KJSNumber(0);
161  }
162 
163  const QLocale locale;
164  bool ok;
165  double converted = locale.toDouble(number, &ok);
166 
167  if (!ok) {
168  const QLocale locale2(locale.decimalPoint() == QLatin1Char('.') ? QStringLiteral("de") : QStringLiteral("en"));
169  converted = locale2.toDouble(number, &ok);
170  if (!ok) {
171  return KJSNumber(std::nan(""));
172  }
173  }
174 
175  return KJSNumber(converted);
176 }
177 
178 void JSUtil::initType(KJSContext *ctx)
179 {
180  static bool initialized = false;
181  if (initialized) {
182  return;
183  }
184  initialized = true;
185 
186  g_utilProto = new KJSPrototype();
187  g_utilProto->defineFunction(ctx, QStringLiteral("crackURL"), crackURL);
188  g_utilProto->defineFunction(ctx, QStringLiteral("printd"), printd);
189  g_utilProto->defineFunction(ctx, QStringLiteral("stringToNumber"), stringToNumber);
190  g_utilProto->defineFunction(ctx, QStringLiteral("numberToString"), numberToString);
191 }
192 
193 KJSObject JSUtil::object(KJSContext *ctx)
194 {
195  return g_utilProto->constructObject(ctx, nullptr);
196 }
double toNumber(KJSContext *ctx)
int count() const
The documentation to the global Okular namespace.
Definition: action.h:16
QStringList split(const QString &sep, QString::SplitBehavior behavior, Qt::CaseSensitivity cs) const const
int count(const T &value) const const
bool isNumber() const
QString dateTimeFormat(QLocale::FormatType format) const const
FullyDecoded
KJSObject at(int idx) const
bool isEmpty() const const
QUrl fromLocalFile(const QString &localFile)
KJSObject throwException(const QString &message) const
QString toString(qlonglong i) const const
int toInt32(KJSContext *ctx)
int indexOf(QChar ch, int from, Qt::CaseSensitivity cs) const const
QString & replace(int position, int n, QChar after)
LocaleWrapper locale()
void defineFunction(KJSContext *ctx, const QString &name, FunctionCall callback)
KJSObject constructObject(KJSContext *ctx, void *internalValue=nullptr)
KDB_EXPORT QString numberToString(double value, int decimalPlaces)
QString arg(qlonglong a, int fieldWidth, int base, QChar fillChar) const const
QString & insert(int position, QChar ch)
QString toString(KJSContext *ctx)
KIOCORE_EXPORT QString number(KIO::filesize_t size)
bool contains(QChar ch, Qt::CaseSensitivity cs) const const
char toLatin1() const const
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.