File indexing completed on 2024-12-08 09:42:37
0001 /* This file is part of the KDE libraries 0002 Copyright (C) 2005, 2006 Ian Reinhart Geiser <geiseri@kde.org> 0003 Copyright (C) 2005, 2006 Matt Broadstone <mbroadst@gmail.com> 0004 Copyright (C) 2005, 2006 Richard J. Moore <rich@kde.org> 0005 Copyright (C) 2005, 2006 Erik L. Bunce <kde@bunce.us> 0006 Copyright (C) 2007, 2008 Sebastian Sauer <mail@dipe.org> 0007 0008 This library is free software; you can redistribute it and/or 0009 modify it under the terms of the GNU Library General Public 0010 License as published by the Free Software Foundation; either 0011 version 2 of the License, or (at your option) any later version. 0012 0013 This library is distributed in the hope that it will be useful, 0014 but WITHOUT ANY WARRANTY; without even the implied warranty of 0015 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 0016 Library General Public License for more details. 0017 0018 You should have received a copy of the GNU Library General Public License 0019 along with this library; see the file COPYING.LIB. If not, write to 0020 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 0021 Boston, MA 02110-1301, USA. 0022 */ 0023 0024 #ifndef QOBJECT_BINDING_H 0025 #define QOBJECT_BINDING_H 0026 0027 #include <QObjectCleanupHandler> 0028 #include <QDebug> 0029 0030 #include <kjs/function.h> 0031 0032 #include "binding_support.h" 0033 #include "object_binding.h" 0034 0035 /** 0036 * A simple pointer style method. 0037 * This will extract the pointer, cast it to the native type and place it in "value". 0038 * Any data that should be returned from this method should be placed into "result"; 0039 * 0040 */ 0041 #define START_QOBJECT_METHOD( METHODNAME, TYPE) \ 0042 KJS::JSValue *METHODNAME( KJS::ExecState *exec, KJS::JSObject *self, const KJS::List &args ) \ 0043 { \ 0044 Q_UNUSED( args ); \ 0045 KJS::JSValue *result = KJS::jsNull(); \ 0046 KJSEmbed::QObjectBinding *imp = KJSEmbed::extractBindingImp<KJSEmbed::QObjectBinding>(exec, self ); \ 0047 if( imp ) \ 0048 { \ 0049 TYPE *object = imp->qobject<TYPE>(); \ 0050 if( object ) \ 0051 { 0052 0053 /** 0054 * End a variant method started by START_QOBJECT_METHOD 0055 */ 0056 #define END_QOBJECT_METHOD \ 0057 } \ 0058 else \ 0059 KJS::throwError(exec, KJS::ReferenceError, QString("QO: The internal object died %1:%2.").arg(__FILE__).arg(__LINE__));\ 0060 } \ 0061 else \ 0062 KJS::throwError(exec, KJS::ReferenceError, QString("QObject died."));\ 0063 return result; \ 0064 } 0065 0066 class QObject; 0067 class QMetaMethod; 0068 0069 namespace KJSEmbed 0070 { 0071 0072 KJS_BINDING(QObjectFactory) 0073 0074 class EventProxy; 0075 0076 class KJSEMBED_EXPORT QObjectBinding : public ObjectBinding 0077 { 0078 public: 0079 0080 QObjectBinding(KJS::ExecState *exec, QObject *object); 0081 ~QObjectBinding() override; 0082 0083 static void publishQObject(KJS::ExecState *exec, KJS::JSObject *target, QObject *object); 0084 0085 /** 0086 * Enumeration of access-flags that could be OR-combined to define 0087 * what parts of the QObject should be published. 0088 * Default is AllSlots|AllSignals|AllProperties|AllObjects what 0089 * means that everything got published, even e.g. private slots. 0090 */ 0091 enum Access { 0092 None = 0x00, ///< Don't publish anything. 0093 0094 ScriptableSlots = 0x01, ///< Publish slots that have Q_SCRIPTABLE defined. 0095 NonScriptableSlots = 0x02, ///< Publish slots that don't have Q_SCRIPTABLE defined. 0096 PrivateSlots = 0x04, ///< Publish private slots. 0097 ProtectedSlots = 0x08, ///< Publish protected slots. 0098 PublicSlots = 0x10, ///< Publish public slots. 0099 AllSlots = ScriptableSlots | NonScriptableSlots | PrivateSlots | ProtectedSlots | PublicSlots, 0100 0101 ScriptableSignals = 0x100, ///< Publish signals that have Q_SCRIPTABLE defined. 0102 NonScriptableSignals = 0x200, ///< Publish signals that don't have Q_SCRIPTABLE defined. 0103 PrivateSignals = 0x400, ///< Publish private signals. 0104 ProtectedSignals = 0x800, ///< Publish protected signals. 0105 PublicSignals = 0x1000, ///< Publish public signals. 0106 AllSignals = ScriptableSignals | NonScriptableSignals | PrivateSignals | ProtectedSignals | PublicSignals, 0107 0108 ScriptableProperties = 0x10000, ///< Publish properties that have Q_SCRIPTABLE defined. 0109 NonScriptableProperties = 0x20000, ///< Publish properties that don't have Q_SCRIPTABLE defined. 0110 AllProperties = ScriptableProperties | NonScriptableProperties, 0111 0112 GetParentObject = 0x100000, ///< Provide access to the parent QObject the QObject has. 0113 SetParentObject = 0x200000, ///< Be able to set the parent QObject the QObject has. 0114 ChildObjects = 0x400000, ///< Provide access to the child QObject's the QObject has. 0115 AllObjects = GetParentObject | SetParentObject | ChildObjects 0116 }; 0117 0118 Q_DECLARE_FLAGS(AccessFlags, Access) 0119 0120 /** 0121 * \return the defined \a Access flags. 0122 */ 0123 AccessFlags access() const; 0124 0125 /** 0126 * Set the defined \a Access flags to \p access . 0127 */ 0128 void setAccess(AccessFlags access); 0129 0130 /** 0131 * Set the value \p value of the property \p propertyName . 0132 */ 0133 void put(KJS::ExecState *exec, const KJS::Identifier &propertyName, KJS::JSValue *value, 0134 int attr = KJS::None) override; 0135 using JSObject::put; 0136 0137 /** 0138 * \return true if the property \p propertyName can be changed else false is returned. 0139 */ 0140 bool canPut(KJS::ExecState *exec, const KJS::Identifier &propertyName) const override; 0141 0142 /** 0143 * Called to ask if we have a callback for the named property. 0144 * We return the callback in the property slot. 0145 */ 0146 bool getOwnPropertySlot(KJS::ExecState *exec, const KJS::Identifier &propertyName, 0147 KJS::PropertySlot &slot) override; 0148 using JSObject::getOwnPropertySlot; 0149 0150 /** 0151 * Callback used to get properties. 0152 */ 0153 static KJS::JSValue *propertyGetter(KJS::ExecState *exec, KJS::JSObject *, const KJS::Identifier &name, const KJS::PropertySlot &); 0154 0155 /** 0156 * \return a string-representation of the QObject. For example for a QWidget-instance that 0157 * has the QObject::objectName "mywidget" the string "mywidget (QWidget)" is returned. 0158 */ 0159 KJS::UString toString(KJS::ExecState *exec) const override; 0160 0161 /** 0162 * \return the QObject's classname. For example for a QWidget-instance the string "QWidget" 0163 * is returned. 0164 */ 0165 KJS::UString className() const override; 0166 0167 /** 0168 * Add the QObject \p object to the internal QObjectCleanupHandler to watch the 0169 * lifetime of the QObject to know when the QObject got deleted. 0170 */ 0171 void watchObject(QObject *object); 0172 0173 /** 0174 * \return the internal object as a pointer to type T to the 0175 * internal object that is derived from QObject. 0176 */ 0177 template <typename T> 0178 T *qobject() const 0179 { 0180 QObject *object = QObjectBinding::object<QObject>(); 0181 if (object) { 0182 return qobject_cast<T *>(object); 0183 } else { 0184 return nullptr; 0185 } 0186 } 0187 0188 private: 0189 EventProxy *m_evproxy; 0190 QObjectCleanupHandler *m_cleanupHandler; 0191 AccessFlags m_access; 0192 }; 0193 0194 Q_DECLARE_OPERATORS_FOR_FLAGS(QObjectBinding::AccessFlags) 0195 0196 class KJSEMBED_EXPORT SlotBinding : public KJS::InternalFunctionImp 0197 { 0198 public: 0199 SlotBinding(KJS::ExecState *exec, const QMetaMethod &memberName); 0200 KJS::JSValue *callAsFunction(KJS::ExecState *exec, KJS::JSObject *self, const KJS::List &args) override; 0201 bool implementsCall() const override 0202 { 0203 return true; 0204 } 0205 bool implementsConstruct() const override 0206 { 0207 return false; 0208 } 0209 0210 protected: 0211 QByteArray m_memberName; 0212 }; 0213 0214 /** 0215 * Returns a binding object for the specified QObject. This method walks 0216 * up the meta objects in order to find the most specific binding it can. 0217 * There should always be some kind of binding possible even if it is just 0218 * the QObject binding. 0219 * 0220 * \param exec Represents the current state of script execution. 0221 * \param value The QObject or from it inherited instance we should return 0222 * a binding object for. 0223 * \param owner Defines who's the owner of the QObject. This could be; 0224 * \li CPPOwned what means, that the QObject's lifetime is handled 0225 * within C++ code. So, we just provide access to it and don't 0226 * take any future actions. 0227 * \li QObjOwned means that the QObject got deleted if the parent QObject 0228 * is destroyed. If the QObject has no parent QObject, it behaves like 0229 * JSOwned. 0230 * \li JSOwned means, that the returned KJS::JSObject takes care of 0231 * deleting the QObject. This means, that the QObject got deleted 0232 * as soon as the KJS::JSObject got destroyed what happens if the 0233 * KJS::JSObject is not needed / in use any longer. 0234 * \return the binding object instance that wraps the QObject instance or 0235 * a JSObject with a prototype of jsNull (that is, the ECMAScript "null" value, 0236 * not a null object pointer) if we failed to provide any binding for it. 0237 */ 0238 KJSEMBED_EXPORT KJS::JSObject *createQObject(KJS::ExecState *exec, QObject *value, KJSEmbed::ObjectBinding::Ownership owner = KJSEmbed::ObjectBinding::JSOwned); 0239 0240 } 0241 #endif 0242