1 /**************************************************************************************** 2 * Copyright (c) 2013 Anmol Ahuja <darthcodus@gmail.com> * 3 * * 4 * This program is free software; you can redistribute it and/or modify it under * 5 * the terms of the GNU General Public License as published by the Free Software * 6 * Foundation; either version 2 of the License, or (at your option) any later * 7 * version. * 8 * * 9 * This program is distributed in the hope that it will be useful, but WITHOUT ANY * 10 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A * 11 * PARTICULAR PURPOSE. See the GNU General Public License for more details. * 12 * * 13 * You should have received a copy of the GNU General Public License along with * 14 * this program. If not, see <http://www.gnu.org/licenses/>. * 15 ****************************************************************************************/ 16 17 #ifndef AMAROKSCRIPT_SCRIPTING_DEFINES_H 18 #define AMAROKSCRIPT_SCRIPTING_DEFINES_H 19 20 #include <QHash> 21 #include <QObject> 22 #include <QJSEngine> 23 #include <QJSValue> 24 #include <QJSValueIterator> 25 26 class QMetaEnum; 27 28 namespace AmarokScript 29 { 30 template <class type, class WrapperType> fromScriptValue(const QJSValue & obj,type & object)31 void fromScriptValue( const QJSValue &obj, type &object ) 32 { 33 const WrapperType *wrapper = dynamic_cast<WrapperType*>( obj.toQObject() ); 34 if( wrapper ) 35 object = wrapper->data(); 36 else 37 object = 0; 38 } 39 40 template <class type, class WrapperType> toScriptValue(QJSEngine * engine,type const & object)41 QJSValue toScriptValue( QJSEngine *engine, type const &object ) 42 { 43 WrapperType *wrapper = new WrapperType( object ); 44 return engine->newQObject( wrapper ); 45 } 46 47 template <class Container> toScriptArray(QJSEngine * engine,const Container & container)48 QJSValue toScriptArray( QJSEngine *engine, const Container &container ) 49 { 50 QJSValue scriptArray = engine->newArray(); 51 typename Container::const_iterator begin = container.begin(); 52 typename Container::const_iterator end = container.end(); 53 typename Container::const_iterator it; 54 for( it = begin; it != end; ++it ) 55 scriptArray.setProperty( quint32(it - begin), engine->toScriptValue(*it) ); 56 return scriptArray; 57 } 58 59 template <class Container> fromScriptArray(const QJSValue & value,Container & container)60 void fromScriptArray( const QJSValue &value, Container &container ) 61 { 62 quint32 len = value.property( QStringLiteral("length") ).toUInt(); 63 for( quint32 i = 0; i < len; ++i ) 64 { 65 QJSValue item = value.property( i ); 66 typedef typename Container::value_type ContainerValue; 67 container.push_back( qjsvalue_cast<ContainerValue>(item) ); 68 } 69 } 70 71 template <class Map> toScriptMap(QJSEngine * engine,const Map & map)72 QJSValue toScriptMap( QJSEngine *engine, const Map &map ) 73 { 74 QJSValue scriptMap = engine->newObject(); 75 for( typename Map::const_iterator it( map.begin() ); it != map.end(); ++it ) 76 scriptMap.setProperty( it.key(), engine->toScriptValue( it.value() ) ); 77 return scriptMap; 78 } 79 80 template <class Map> fromScriptMap(const QJSValue & value,Map & map)81 void fromScriptMap( const QJSValue &value, Map &map ) 82 { 83 QJSValueIterator it( value ); 84 while( it.hasNext() ) 85 { 86 it.next(); 87 map[it.name()] = qjsvalue_cast<typename Map::mapped_type>( it.value() ); 88 } 89 } 90 91 /** 92 * SCRIPTDOX _ 93 */ 94 class AmarokScriptEngine : public QJSEngine 95 { 96 Q_OBJECT 97 98 public: 99 explicit AmarokScriptEngine( QObject *parent ); 100 ~AmarokScriptEngine() override; 101 102 void setDeprecatedProperty( const QString &parent, const QString &name, const QJSValue &property ); 103 // exposing the metaobject directly also exposes >900 other values 104 QJSValue enumObject( const QMetaEnum &metaEnum ); 105 106 template <class T> registerArrayType()107 void registerArrayType() 108 { 109 qRegisterMetaType<T>(); 110 QMetaType::registerConverter<QJSValue,T>( [] (QJSValue scriptObj) { 111 T arrayObj; 112 fromScriptArray( scriptObj, arrayObj ); 113 return arrayObj; 114 }); 115 QMetaType::registerConverter<T,QJSValue>( [this] (T arrayObj) { return toScriptArray( this, arrayObj ); } ); 116 } 117 template <class Map> registerMapType()118 void registerMapType() 119 { 120 qRegisterMetaType<Map>(); 121 QMetaType::registerConverter<QJSValue,Map>( [] (QJSValue scriptObj) { 122 Map mapObj; 123 fromScriptMap( scriptObj, mapObj ); 124 return mapObj; 125 }); 126 QMetaType::registerConverter<Map,QJSValue>( [this] (Map mapObj) { return toScriptMap( this, mapObj ); } ); 127 } 128 129 // SCRIPTDOX exclude 130 Q_INVOKABLE void invokableDeprecatedCall( const QString &call ); 131 132 /** 133 * @param function The function to invoke after time @param time in milliseconds. 134 * @param thisObject [Optional] The this object this function is invoked with. 135 * @param args [Optional] An array containing arguments this function is to be invoked with. 136 */ 137 Q_INVOKABLE void setTimeout( const QJSValue &function, int time, 138 const QJSValue &thisObject = QJSValue(), 139 const QJSValue &args = QJSValue() ); 140 141 private Q_SLOTS: 142 void slotTimeout(); 143 144 Q_SIGNALS: 145 void deprecatedCall(const QString &); 146 147 private: 148 const QString internalObject; 149 QHash<QObject*, QJSValueList> m_callbacks; 150 }; 151 } 152 153 #endif // AMAROKSCRIPT_SCRIPTING_DEFINES_H 154