KJsEmbed

variant_binding.h
1 /* This file is part of the KDE libraries
2  Copyright (C) 2005, 2006 Ian Reinhart Geiser <[email protected]>
3  Copyright (C) 2005, 2006 Matt Broadstone <[email protected]>
4  Copyright (C) 2005, 2006 Richard J. Moore <[email protected]>
5  Copyright (C) 2005, 2006 Erik L. Bunce <[email protected]>
6  Copyright (C) 2007, 2008 Sebastian Sauer <[email protected]>
7 
8  This library is free software; you can redistribute it and/or
9  modify it under the terms of the GNU Library General Public
10  License as published by the Free Software Foundation; either
11  version 2 of the License, or (at your option) any later version.
12 
13  This library is distributed in the hope that it will be useful,
14  but WITHOUT ANY WARRANTY; without even the implied warranty of
15  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16  Library General Public License for more details.
17 
18  You should have received a copy of the GNU Library General Public License
19  along with this library; see the file COPYING.LIB. If not, write to
20  the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
21  Boston, MA 02110-1301, USA.
22 */
23 
24 #ifndef VARIANT_BINDING_H
25 #define VARIANT_BINDING_H
26 
27 #include <QVariant>
28 
29 #include <kjs/object.h>
30 #include <kjs/interpreter.h>
31 
32 #include "static_binding.h"
33 
34 /**
35 * A simple variant style method.
36 * This will extract the QVariant, cast it to the native type and place it in "value".
37 * Any data that should be returned from this method should be placed into "result";
38 *
39 */
40 #define START_VARIANT_METHOD( METHODNAME, TYPE) \
41  KJS::JSValue *METHODNAME( KJS::ExecState *exec, KJS::JSObject *self, const KJS::List &args ) \
42  { \
43  Q_UNUSED(exec);\
44  Q_UNUSED(self);\
45  Q_UNUSED(args);\
46  KJS::JSValue *result = KJS::jsNull(); \
47  KJSEmbed::VariantBinding *imp = KJSEmbed::extractBindingImp<KJSEmbed::VariantBinding>(exec, self ); \
48  if( imp ) \
49  { \
50  TYPE value = imp->value<TYPE>();
51 /**
52 * End a variant method started by START_VARIANT_METHOD
53 */
54 #define END_VARIANT_METHOD \
55  imp->setValue(QVariant::fromValue(value)); \
56  } \
57  else \
58  {\
59  KJS::throwError(exec, KJS::GeneralError, "We have a problem baby");\
60  }\
61  return result; \
62  }
63 
64 #define KJSO_VARIANT_SIMPLE_BINDING_CTOR( NAME, JSNAME, TYPE, BASENAME ) \
65  NAME::NAME(KJS::ExecState *exec, const char* typeName ) \
66  : BASENAME( exec, typeName ) \
67  { \
68  StaticBinding::publish( exec, this, NAME::methods() ); \
69  } \
70  NAME::NAME(KJS::ExecState *exec, const TYPE & value) \
71  : BASENAME( exec, QVariant::fromValue(value)) \
72  { \
73  StaticBinding::publish( exec, this, NAME::methods() ); \
74  }
75 
76 namespace KJSEmbed
77 {
78 /**
79 * QVariant based binding. This class wraps the implementation.
80 * You should never have to use this class directly instead use KJSEmbed::createVariant.
81 */
82 
83 /**
84 * QVariant bindinging implementation.
85 */
86 class KJSEMBED_EXPORT VariantBinding : public ProxyBinding
87 {
88 public:
89  /**
90  * Create a new binding implementation with a QVariant to wrap
91  */
92  VariantBinding(KJS::ExecState *exec, const QVariant &value);
93  ~VariantBinding() override {}
94 
95  void *pointer();
96 
97  KJS::UString toString(KJS::ExecState *) const override;
98  KJS::UString className() const override;
99 
100  /**
101  * Return the wrapped QVariant
102  */
103  QVariant variant() const;
104 
105  /**
106  * Extract the actual value from the wrapper. This method wraps QVariant::value, so it will support
107  * some aspects of casting. If the cast fails a default value of T will be returned.
108  */
109  template<typename T>
110  T value() const
111  {
112  return m_value.value<T>();
113  }
114  /**
115  * Set the internal value of the QVariant.
116  */
117  void setValue(const QVariant &val);
118 
119  /**
120  * Constructs a QGenericArgument that is used with QMetaObject::invokeMember
121  */
122  QGenericArgument arg(const char *type) const;
123 
124  static const KJS::ClassInfo info;
125 
126 private:
127  const KJS::ClassInfo *classInfo() const override
128  {
129  return &info;
130  }
131  QVariant m_value;
132 
133 };
134 
135 /**
136 * Extracts a QVariant from a KJS::JSValue if the conversion fails a QVariant::Null is returned.
137 */
138 QVariant KJSEMBED_EXPORT extractVariant(KJS::ExecState *exec, KJS::JSValue *value);
139 
140 /**
141 * Extracts a value based type from a VariantBinding object. This method calls @ref extractVariant so if
142 * the conversions fails then the default value will be returned. Care should be taken that this method
143 * is not used with KJSEmbed::ObjectBinding objects because the cast will fail.
144 */
145 template< typename T>
146 T extractVariant(KJS::ExecState *exec, KJS::JSValue *arg, const T &defaultValue)
147 {
148  if (!arg) {
149  return defaultValue;
150  } else {
151  QVariant variant = extractVariant(exec, arg);
152  if (!variant.isNull()) {
153  if (variant.canConvert<T>()) {
154  return variant.value<T>();
155  } else {
156  throwError(exec, KJS::TypeError, "Cast failed");
157  return defaultValue;
158  }
159  } else {
160  return defaultValue;
161  }
162  }
163 }
164 
165 /**
166 * Extracts a value from a KJS::List of KJS::JSValues. If the argument is out of range the default value
167 * is returned.
168 */
169 template< typename T>
170 T extractVariant(KJS::ExecState *exec, const KJS::List &args, int idx, const T &defaultValue = T())
171 {
172  if (args.size() >= idx) {
173  return extractVariant<T>(exec, args[idx], defaultValue);
174  } else {
175  return defaultValue;
176  }
177 }
178 
179 /**
180 * Can create any known KJSEmbed::VariantBinding object and set the value.
181 * On failure a KJS::jsNull will be returned and the exception set. Only values
182 * that are supported by QVariant will work.
183 */
184 template< typename T>
185 KJS::JSValue *createVariant(KJS::ExecState *exec, const KJS::UString &className, const T &value)
186 {
187  KJS::JSObject *parent;
188  parent = exec->dynamicInterpreter()->globalObject();
189  KJS::JSObject *returnValue = StaticConstructor::construct(exec, parent, className);
190  if (returnValue) {
191  // If it is a value type setValue
192  KJSEmbed::VariantBinding *imp = extractBindingImp<KJSEmbed::VariantBinding>(exec, returnValue);
193  if (imp) {
194  imp->setValue(QVariant::fromValue(value));
195  } else {
196  throwError(exec, KJS::TypeError, toUString(QString("Created failed to cast to %1 failed").arg(toQString(className))));
197  return KJS::jsNull();
198  }
199  } else {
200  throwError(exec, KJS::TypeError, toUString(QString("Could not construct a %1").arg(toQString(className))));
201  return KJS::jsNull();
202  }
203  return returnValue;
204 }
205 
206 /**
207 * Convert a KJS::JSValue that contains an associative array into a QMap. If you call
208 * this on a normal Javascript object you will get each property as the key and its
209 * data as the value. A normal array will give you a QMap with each key being the
210 * index.
211 */
212 QMap<QString, QVariant> KJSEMBED_EXPORT convertArrayToMap(KJS::ExecState *exec, KJS::JSValue *value);
213 
214 /**
215 * Convert a KJS::JSValue into a QList. If the list contains only strings, or objects that can be
216 * converted to strings you can call to @ref convertArrayToStringList. If you call this on an
217 * associative array or a javascript object the list will return empty. Unless there happens to be
218 * a property with a numeric index present, then all bets are off.
219 */
220 QList<QVariant> KJSEMBED_EXPORT convertArrayToList(KJS::ExecState *exec, KJS::JSValue *value);
221 
222 /**
223 * Convert a KJS::JSValue into a QStringList. @see convertArrayToList.
224 */
225 QStringList KJSEMBED_EXPORT convertArrayToStringList(KJS::ExecState *exec, KJS::JSValue *value);
226 
227 /**
228 * Convert a KJS::JSValue into a QVariant object
229 */
230 QVariant KJSEMBED_EXPORT convertToVariant(KJS::ExecState *exec, KJS::JSValue *value);
231 
232 /**
233 * Convert a QVariant to a KJS::JSValue. If the type is a known type the bindings will be added.
234 * If the type is supported by QVariant, but is not supported by KJSEmbed then it will just be wrapped.
235 * This wrapped value can be used just like normal value bindings, save for the lack of methods available to the object.
236 */
237 KJSEMBED_EXPORT KJS::JSValue *convertToValue(KJS::ExecState *exec, const QVariant &value);
238 
239 /**
240 * The Bindings for the KJSEmbed::VariantBinding
241 */
242 struct Method;
243 class KJSEMBED_EXPORT VariantFactory
244 {
245 public:
246  static const Method VariantMethods[];
247  static const Method *methods()
248  {
249  return VariantMethods;
250  }
251 };
252 
253 }
254 #endif
255 
bool isNull() const const
JSGlobalObject * globalObject() const
QVariant fromValue(const T &value)
T value() const const
int size() const
KJS::JSObject * construct(KJS::ExecState *exec, const KJS::List &args) override
Calls the callback that will in turn create a new instance of this object with the arguments passed i...
QVariant based binding.
bool canConvert(int targetTypeId) const const
void setValue(const QVariant &val)
Set the internal value of the QVariant.
T value() const
Extract the actual value from the wrapper.
Interpreter * dynamicInterpreter() const
This file is part of the KDE documentation.
Documentation copyright © 1996-2023 The KDE developers.
Generated on Sun Dec 10 2023 03:59:19 by doxygen 1.8.17 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.