File indexing completed on 2025-01-05 04:26:52

0001 /****************************************************************************************
0002  * Copyright (c) 2013 Anmol Ahuja <darthcodus@gmail.com>                                *
0003  *                                                                                      *
0004  * This program is free software; you can redistribute it and/or modify it under        *
0005  * the terms of the GNU General Public License as published by the Free Software        *
0006  * Foundation; either version 2 of the License, or (at your option) any later           *
0007  * version.                                                                             *
0008  *                                                                                      *
0009  * This program is distributed in the hope that it will be useful, but WITHOUT ANY      *
0010  * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A      *
0011  * PARTICULAR PURPOSE. See the GNU General Public License for more details.             *
0012  *                                                                                      *
0013  * You should have received a copy of the GNU General Public License along with         *
0014  * this program.  If not, see <http://www.gnu.org/licenses/>.                           *
0015  ****************************************************************************************/
0016 
0017 #ifndef AMAROKSCRIPT_SCRIPTING_DEFINES_H
0018 #define AMAROKSCRIPT_SCRIPTING_DEFINES_H
0019 
0020 #include <QHash>
0021 #include <QObject>
0022 #include <QJSEngine>
0023 #include <QJSValue>
0024 #include <QJSValueIterator>
0025 
0026 class QMetaEnum;
0027 
0028 namespace AmarokScript
0029 {
0030     template <class type, class WrapperType>
0031     void fromScriptValue( const QJSValue &obj, type &object )
0032     {
0033         const WrapperType *wrapper = dynamic_cast<WrapperType*>( obj.toQObject() );
0034         if( wrapper )
0035             object = wrapper->data();
0036         else
0037             object = nullptr;
0038     }
0039 
0040     template <class type, class WrapperType>
0041     QJSValue toScriptValue( QJSEngine *engine, type const &object )
0042     {
0043         WrapperType *wrapper = new WrapperType( object );
0044         return engine->newQObject( wrapper );
0045     }
0046 
0047     template <class Container>
0048     QJSValue toScriptArray( QJSEngine *engine, const Container &container )
0049     {
0050         QJSValue scriptArray = engine->newArray();
0051         typename Container::const_iterator begin = container.begin();
0052         typename Container::const_iterator end = container.end();
0053         typename Container::const_iterator it;
0054         for( it = begin; it != end; ++it )
0055             scriptArray.setProperty( quint32(it - begin), engine->toScriptValue(*it) );
0056         return scriptArray;
0057     }
0058 
0059     template <class Container>
0060     void fromScriptArray( const QJSValue &value, Container &container )
0061     {
0062         quint32 len = value.property( QStringLiteral("length") ).toUInt();
0063         for( quint32 i = 0; i < len; ++i )
0064         {
0065             QJSValue item = value.property( i );
0066             typedef typename Container::value_type ContainerValue;
0067             container.push_back( qjsvalue_cast<ContainerValue>(item) );
0068         }
0069     }
0070 
0071     template <class Map>
0072     QJSValue toScriptMap( QJSEngine *engine, const Map &map )
0073     {
0074         QJSValue scriptMap = engine->newObject();
0075         for( typename Map::const_iterator it( map.begin() ); it != map.end(); ++it )
0076             scriptMap.setProperty( it.key(), engine->toScriptValue( it.value() ) );
0077         return scriptMap;
0078     }
0079 
0080     template <class Map>
0081     void fromScriptMap( const QJSValue &value, Map &map )
0082     {
0083         QJSValueIterator it( value );
0084         while( it.hasNext() )
0085         {
0086             it.next();
0087             map[it.name()] = qjsvalue_cast<typename Map::mapped_type>( it.value() );
0088         }
0089     }
0090 
0091     /**
0092      * SCRIPTDOX _
0093      */
0094     class AmarokScriptEngine : public QJSEngine
0095     {
0096         Q_OBJECT
0097 
0098         public:
0099             explicit AmarokScriptEngine( QObject *parent );
0100             ~AmarokScriptEngine() override;
0101 
0102             void setDeprecatedProperty( const QString &parent, const QString &name, const QJSValue &property );
0103             // exposing the metaobject directly also exposes >900 other values
0104             QJSValue enumObject( const QMetaEnum &metaEnum );
0105 
0106             template <class T>
0107             void registerArrayType()
0108             {
0109                 qRegisterMetaType<T>();
0110                 QMetaType::registerConverter<QJSValue,T>( [] (QJSValue scriptObj) {
0111                     T arrayObj;
0112                     fromScriptArray( scriptObj, arrayObj );
0113                     return arrayObj;
0114                 });
0115                 QMetaType::registerConverter<T,QJSValue>( [this] (T arrayObj) { return toScriptArray( this, arrayObj ); } );
0116             }
0117             template <class Map>
0118             void registerMapType()
0119             {
0120                 qRegisterMetaType<Map>();
0121                 QMetaType::registerConverter<QJSValue,Map>( [] (QJSValue scriptObj) {
0122                     Map mapObj;
0123                     fromScriptMap( scriptObj, mapObj );
0124                     return mapObj;
0125                 });
0126                 QMetaType::registerConverter<Map,QJSValue>( [this] (Map mapObj) { return toScriptMap( this, mapObj ); } );
0127             }
0128 
0129             // SCRIPTDOX exclude
0130             Q_INVOKABLE void invokableDeprecatedCall( const QString &call );
0131 
0132             /**
0133              * @param function The function to invoke after time @param time in milliseconds.
0134              * @param thisObject [Optional] The this object this function is invoked with.
0135              * @param args [Optional] An array containing arguments this function is to be invoked with.
0136              */
0137             Q_INVOKABLE void setTimeout( const QJSValue &function, int time,
0138                              const QJSValue &thisObject = QJSValue(),
0139                              const QJSValue &args = QJSValue() );
0140 
0141         private Q_SLOTS:
0142             void slotTimeout();
0143 
0144         Q_SIGNALS:
0145             void deprecatedCall(const QString &);
0146 
0147         private:
0148             const QString internalObject;
0149             QHash<QObject*, QJSValueList> m_callbacks;
0150     };
0151 }
0152 
0153 #endif // AMAROKSCRIPT_SCRIPTING_DEFINES_H