1 /************************************************************************ 2 * 3 * Copyright 2010-2011 Jakob Leben (jakob.leben@gmail.com) 4 * 5 * This file is part of SuperCollider Qt GUI. 6 * 7 * This program is free software: you can redistribute it and/or modify 8 * it under the terms of the GNU General Public License as published by 9 * the Free Software Foundation, either version 2 of the License, or 10 * (at your option) any later version. 11 * 12 * This program is distributed in the hope that it will be useful, 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 * GNU General Public License for more details. 16 * 17 * You should have received a copy of the GNU General Public License 18 * along with this program. If not, see <http://www.gnu.org/licenses/>. 19 * 20 ************************************************************************/ 21 22 #pragma once 23 24 #include "Common.h" 25 26 #include <QObject> 27 #include <QString> 28 #include <QVariant> 29 #include <QVector> 30 #include <QEvent> 31 32 #include <PyrObject.h> 33 #include <PyrSlot.h> 34 #include <PyrSymbol.h> 35 36 #define qcProxyDebugMsg(LEVEL, MSG) qcDebugMsg(LEVEL, QStringLiteral("[%1]: ").arg(_scClassName) + QString(MSG)) 37 38 class QObjectProxy; 39 class QcSignalSpy; 40 class QcMethodSignalHandler; 41 class QcFunctionSignalHandler; 42 43 namespace QtCollider { 44 struct SetPropertyEvent; 45 class DestroyEvent; 46 struct ScMethodCallEvent; 47 48 class ProxyToken : public QObject { 49 Q_OBJECT 50 public: ProxyToken(QObjectProxy * p,QObject * parent)51 ProxyToken(QObjectProxy* p, QObject* parent): QObject(parent), proxy(p) {} 52 QObjectProxy* proxy; 53 }; 54 } 55 56 class QObjectProxy : public QObject { 57 friend class QcMethodSignalHandler; 58 friend class QcFunctionSignalHandler; 59 60 Q_OBJECT 61 62 public: 63 enum DestroyAction { 64 DestroyProxy, 65 DestroyObject, 66 DestroyProxyAndObject, 67 }; 68 69 struct EventHandlerData { EventHandlerDataEventHandlerData70 EventHandlerData(): type(QEvent::None) {} 71 int type; 72 PyrSymbol* method; 73 QtCollider::Synchronicity sync; 74 bool enabled; 75 }; 76 77 QObjectProxy(QObject* qObject, PyrObject* scObject); 78 79 virtual ~QObjectProxy(); 80 81 // Check if this is the right thread. 82 // WARNING: must be called with language locked! 83 bool compareThread(); 84 85 // WARNING: must be called with language locked! finalize()86 void finalize() { _scObject = 0; } 87 object()88 inline QObject* object() const { return qObject; } scObject()89 inline PyrObject* scObject() const { return _scObject; } 90 91 // Lock for usage of object() outside Qt thread. lock()92 inline void lock() { mutex.lock(); } unlock()93 inline void unlock() { mutex.unlock(); } 94 scClassName()95 QString scClassName() const { return _scClassName; } 96 97 QList<PyrObject*> children(PyrSymbol* className); 98 PyrObject* parent(PyrSymbol* className); 99 virtual bool setParent(QObjectProxy* parent); 100 101 bool setProperty(const char* property, const QVariant& val); 102 QVariant property(const char* property); 103 104 bool connectObject(const char* signal, PyrObject* object, Qt::ConnectionType); 105 bool connectMethod(const char* signal, PyrSymbol* method, Qt::ConnectionType); 106 bool disconnectObject(const char* signal, PyrObject* object); 107 bool disconnectMethod(const char* signal, PyrSymbol* method); 108 bool setEventHandler(int eventType, PyrSymbol* method, QtCollider::Synchronicity, bool enabled = true); 109 bool setEventHandlerEnabled(int eventType, bool enabled); 110 111 // thread-safe if connection == queued 112 bool invokeMethod(const char* method, PyrSlot* ret, PyrSlot* arg, Qt::ConnectionType); 113 114 void destroy(DestroyAction); 115 116 static QObjectProxy* fromObject(QObject*); 117 118 protected: 119 void invokeScMethod(PyrSymbol* method, const QList<QVariant>& args = QList<QVariant>(), PyrSlot* result = 0, 120 bool locked = false); 121 122 virtual bool eventFilter(QObject* watched, QEvent* event); 123 124 virtual void customEvent(QEvent*); 125 126 virtual bool preProcessEvent(QObject*, QEvent*, EventHandlerData&, QList<QVariant>& args); 127 postProcessEvent(QObject *,QEvent *,bool handled)128 virtual bool postProcessEvent(QObject*, QEvent*, bool handled) { return handled; } 129 130 bool invokeEventHandler(QEvent* e, EventHandlerData&, QList<QVariant>& args); 131 eventHandlers()132 const QVector<EventHandlerData>& eventHandlers() { return _eventHandlers; } 133 134 private Q_SLOTS: 135 136 void invalidate(); 137 138 private: 139 void scMethodCallEvent(QtCollider::ScMethodCallEvent*); 140 bool setPropertyEvent(QtCollider::SetPropertyEvent*); 141 bool destroyEvent(QtCollider::DestroyEvent*); 142 143 QObject* qObject; 144 // NOTE: scObject is protected by the language lock. Should not use it without it! 145 PyrObject* _scObject; 146 // NOTE: for the reason above we extract SC class name at construction 147 QString _scClassName; 148 149 QVector<EventHandlerData> _eventHandlers; 150 QList<QcMethodSignalHandler*> methodSigHandlers; 151 QList<QcFunctionSignalHandler*> funcSigHandlers; 152 QMutex mutex; 153 }; 154 155 namespace QtCollider { 156 157 struct SetPropertyEvent : public QEvent { SetPropertyEventSetPropertyEvent158 SetPropertyEvent(): QEvent((QEvent::Type)QtCollider::Event_Proxy_SetProperty) {} 159 PyrSymbol* property; 160 QVariant value; 161 }; 162 163 class DestroyEvent : public QEvent { 164 public: DestroyEvent(QObjectProxy::DestroyAction act)165 DestroyEvent(QObjectProxy::DestroyAction act): 166 QEvent((QEvent::Type)QtCollider::Event_Proxy_Destroy), 167 _action(act) {} action()168 QObjectProxy::DestroyAction action() { return _action; } 169 170 private: 171 QObjectProxy::DestroyAction _action; 172 }; 173 174 struct ScMethodCallEvent : public QEvent { 175 ScMethodCallEvent(PyrSymbol* m, const QList<QVariant>& l = QList<QVariant>(), bool b_locked = false): 176 QEvent((QEvent::Type)QtCollider::Event_ScMethodCall), 177 method(m), 178 args(l), 179 locked(b_locked) {} 180 181 PyrSymbol* method; 182 QList<QVariant> args; 183 bool locked; 184 }; 185 186 } // namespace 187 188 Q_DECLARE_METATYPE(QObjectProxy*); 189