basic scriptability and meta-classing for pack
authorkonrad <konrad@6e3c4bff-ac9f-4ac1-96c5-d2ea494d3e33>
Wed, 20 Oct 2010 20:18:45 +0000 (20:18 +0000)
committerkonrad <konrad@6e3c4bff-ac9f-4ac1-96c5-d2ea494d3e33>
Wed, 20 Oct 2010 20:18:45 +0000 (20:18 +0000)
git-svn-id: https://silmor.de/svn/softmagic/pack/trunk@603 6e3c4bff-ac9f-4ac1-96c5-d2ea494d3e33

qtbase/include/interface.h
qtbase/include/nullable.h
qtbase/include/object.h
qtbase/include/transaction.h
qtbase/src/object.cpp
woc/qt/qtclass.cpp
woc/qt/qtclass.h
woc/qt/qtctrans.cpp
woc/qt/qtctrans.h
woc/qt/qtout.cpp
woc/qt/qtout.h

index b89e9ee..04dc8b4 100644 (file)
@@ -25,6 +25,17 @@ class QNetworkReply;
 class WInterface:public QObject
 {
        Q_OBJECT
+       Q_PROPERTY(QUrl url READ url)
+       Q_PROPERTY(bool useProxy READ useProxy)
+       Q_PROPERTY(bool useProxyAuth READ useProxyAuth)
+       Q_PROPERTY(QString proxyHost READ proxyHost)
+       Q_PROPERTY(unsigned short proxyPort READ proxyPort)
+       Q_PROPERTY(QString proxyUser READ proxyUser)
+       Q_PROPERTY(QString proxyPassword READ proxyPassword)
+       Q_PROPERTY(int webTimeout READ webTimeout)
+       Q_PROPERTY(QString name READ name)
+       Q_ENUMS(LogLevel)
+       Q_PROPERTY(LogLevel logLevel READ logLevel)
        protected:
                ///used by child classes for instantiation
                WInterface(QString name);
index ed82877..304168a 100644 (file)
@@ -62,13 +62,16 @@ template<class T>class Nullable
 };
 
 #include<QString>
+#include<QMetaType>
 //convenience wrappers
+typedef Nullable<bool> Bool;Q_DECLARE_METATYPE(Bool)
 typedef Nullable<int> Int;
-typedef Nullable<qint32> Int32;
-typedef Nullable<qint64> Int64;
-typedef Nullable<quint32> UInt32;
-typedef Nullable<quint64> UInt64;
-typedef Nullable<QString> NString;
+typedef Nullable<qint32> Int32;Q_DECLARE_METATYPE(Int32)
+typedef Nullable<qint64> Int64;Q_DECLARE_METATYPE(Int64)
+typedef Nullable<quint32> UInt32;Q_DECLARE_METATYPE(UInt32)
+typedef Nullable<quint64> UInt64;Q_DECLARE_METATYPE(UInt64)
+typedef Nullable<QString> NString;Q_DECLARE_METATYPE(NString)
+typedef Nullable<QByteArray> NByteArray;Q_DECLARE_METATYPE(NByteArray)
 
 inline bool operator==(Int64 i1,int i2){return i1.operator==(i2);}
 inline bool operator==(UInt32 i1,int i2){return i1.operator==(i2);}
index 57f24e8..5949283 100644 (file)
@@ -22,6 +22,8 @@
 
 class QDomElement;
 class QDomDocument;
+class QScriptValue;
+class QScriptEngine;
 
 /**base class of all web based objects*/
 class WObject:public WHelper
@@ -47,4 +49,17 @@ class WDeserializerException:public WException
  wob& operator=(const wob ## Abstract&w){wob ## Abstract::operator=(w);return *this;} \
  private:
 
+
+#define WOSCRIPT(wob) public: \
+ static QScriptValue toScriptValue(QScriptEngine*,const wob &); \
+ static void fromScriptValue(const QScriptValue&,wob &); \
+ private:
+
+#define WOSCRIPT_IMP(wob)
+/* QScriptValue wob::toScriptValue(QScriptEngine*engine,const wob &obj){\
+  return engine->newQObject(new wob (obj),QScriptEngine::ScriptOwnership);}\
+ void wob::fromScriptValue(const QScriptValue&val,wob &obj){\
+  wob *xobj=qobject_cast< wob *>(val.toQObject());\
+  if(xobj!=0 && &obj!=xobj)obj = *xobj;}*/
+
 #endif
index 25cc027..2457d6e 100644 (file)
@@ -27,6 +27,15 @@ class WTransaction_Private;
 class WTransaction:public WHelper
 {
        Q_OBJECT
+       Q_ENUMS(Stage)
+       Q_PROPERTY(Stage stage READ stage)
+       Q_PROPERTY(bool isInProgress READ isInProgress)
+       Q_PROPERTY(bool isFinished READ isFinished)
+       Q_PROPERTY(bool isUnstarted READ isUnstarted)
+       Q_PROPERTY(bool hasError READ hasError)
+       Q_PROPERTY(QString errorType READ errorType)
+       Q_PROPERTY(QString errorString READ errorString)
+       Q_PROPERTY(QString interfaceName READ interface)
        public:
                /**stage the transaction is in*/
                enum Stage {
@@ -55,10 +64,6 @@ class WTransaction:public WHelper
                /**returns the interface that is used for the transaction*/
                virtual QString interface()const;
                
-               /**waits for this transaction to finish, returns true if the transaction was successful, returns immediately if the transaction is not running
-               \param tmout the maximum amount of milli seconds to wait, if 0 it will not time out*/
-               virtual bool waitForFinished(int tmout=30000);
-               
                /**deconstructor*/
                virtual ~WTransaction();
                
@@ -95,6 +100,12 @@ class WTransaction:public WHelper
                        protected:
                                void loop();
                };
+               
+       public slots:
+               /**waits for this transaction to finish, returns true if the transaction was successful, returns immediately if the transaction is not running
+               \param tmout the maximum amount of milli seconds to wait, if 0 it will not time out*/
+               virtual bool waitForFinished(int tmout=30000);
+               
        protected:
                /**internal: construct the transaction*/
                WTransaction(QString iface=QString());
index fc8a896..ae172b8 100644 (file)
 //
 
 #include "WObject"
+
+//do at least something useful
+#include "Nullable"
+
+static int itype0=
+       qRegisterMetaType<Int32>()+
+       qRegisterMetaType<Int64>()+
+       qRegisterMetaType<UInt32>()+
+       qRegisterMetaType<UInt64>()+
+       qRegisterMetaType<NString>()+
+       qRegisterMetaType<NByteArray>()+
+       qRegisterMetaType<Bool>();
index 2b71781..42a07a8 100644 (file)
@@ -61,7 +61,7 @@ void WocQtClass::newClass(const WocClass&cls)
                        hcd+="#include \""+m_prefix+"O"+cls.propertyPlainType(k[i])+"\"\n";
 
        //class declaration
-       hcd+="class "+cna+":public "+cls.clientBaseClass()+"\n{\n";
+       hcd+="class "+cna+":public "+cls.clientBaseClass()+"\n{\n  Q_OBJECT\n";
        hdr.write(hcd.toAscii());
        
        //enums
@@ -76,12 +76,58 @@ void WocQtClass::newClass(const WocClass&cls)
        //deserializer (constructor)
        classDeserializer(cls,hdr,src,cna);
        
-       //lead out
+       //scripting
+       classScripting(cls,hdr,src,cna,cn);
+       
+       //meta types
+       m_aux+="Q_DECLARE_METATYPE("+cna+")\n";
+       m_aux+="Q_DECLARE_METATYPE(QList<"+cna+">)\n";
+       m_aux+="Q_DECLARE_METATYPE(Nullable<"+cna+">)\n";
+       scd="static int class_metatypeid=";
+       scd+="qRegisterMetaType<"+cna+">()+";
+       scd+="qRegisterMetaType<QList<"+cna+"> >()+";
+       scd+="qRegisterMetaType<Nullable<"+cna+"> >();\n";
+       
+       //end of class, aux stuff, meta types
        hdr.write(QByteArray("\n};\n"));
+       hdr.write(m_aux.toAscii());m_aux.clear();
+       src.write(scd.toAscii());
+       
+       //lead out
        hdr.write(QByteArray(HDREND).replace("%",cna.toAscii()));
        src.write(QByteArray(SRCEND).replace("%",cna.toAscii()));
 }
 
+void WocQtClass::classScripting(const WocClass& cls, MFile& hdr, MFile& src, QString cna,QString cn)
+{
+       Q_UNUSED(cna);Q_UNUSED(hdr);Q_UNUSED(cls);
+       //converters
+       QString hcd,scd;
+       if(cna==cn){
+               hcd+="  public:\n";
+               hcd+="\tstatic QScriptValue toScriptValue(QScriptEngine*,const "+cna+"&);\n";
+               hcd+="\tstatic void fromScriptValue(const QScriptValue&,"+cna+"&);\n";
+       }else{
+               scd+="#include \""+cn+"\"\n";
+       }
+       scd+="#include <QScriptValue>\n";
+       scd+="#include <QScriptEngine>\n";
+       scd+="QScriptValue "+cn+"::toScriptValue(QScriptEngine*engine,const "+cn+"&obj)\n{\n";
+       scd+="\treturn engine->newQObject(new "+cn+"(obj),QScriptEngine::ScriptOwnership);\n}\n";
+       scd+="void "+cn+"::fromScriptValue(const QScriptValue&val,"+cn+"&obj)\n{\n";
+       scd+="\t"+cn+"*xobj=qobject_cast<"+cn+"*>(val.toQObject());\n";
+       scd+="\tif(xobj!=0 && &obj!=xobj)obj = *xobj;\n}\n";
+       hdr.write(hcd.toAscii());
+       src.write(scd.toAscii());
+       //scripting registry
+       m_parent->addScriptInit(
+         "\tgval.setProperty(\""+cn+"\",engine->newQMetaObject(&"+cn+"::staticMetaObject));\n"
+         "\tqScriptRegisterMetaType(engine,"+cn+"::toScriptValue,"+cn+"::fromScriptValue);\n"
+         "\tqScriptRegisterSequenceMetaType<QList<"+cn+"> >(engine);\n"
+       );
+}
+
+
 void WocQtClass::classEnums(const WocClass&cls,MFile&hdr,MFile&src,QString cn)
 {
        QStringList k=cls.enumTypes();
@@ -89,6 +135,12 @@ void WocQtClass::classEnums(const WocClass&cls,MFile&hdr,MFile&src,QString cn)
        QString hcd="  public:\n";
        QString scd;
        for(int i=0;i<k.size();i++){
+               //meta type
+               hcd+="\tQ_ENUMS("+k[i]+");\n";
+               m_aux+="Q_DECLARE_METATYPE("+cn+"::"+k[i]+")\n";
+               m_aux+="Q_DECLARE_METATYPE(QList<"+cn+"::"+k[i]+">)\n";
+               scd+="static int enum_"+k[i]+"_metatypeid=qRegisterMetaType<"+cn+"::"+k[i]+">();\n";
+               scd+="static int enum_"+k[i]+"_metatypeid2=qRegisterMetaType<QList<"+cn+"::"+k[i]+"> >();\n";
                //type
                hcd+="\tenum "+k[i]+"{";
                QList<WocEnum>ev=cls.enumValues(k[i]);
@@ -140,8 +192,12 @@ void WocQtClass::classProperties(const WocClass&cls,MFile&hdr,MFile&)
        QStringList k=cls.propertyNames();
        if(k.size()==0)return;
        QString hcd,scd;
+       //declare property
+       for(int i=0;i<k.size();i++){
+               hcd+="\tQ_PROPERTY("+qttype(cls,k[i])+" "+k[i]+" READ "+k[i]+" WRITE set"+k[i]+")\n";
+       }
        //declare members
-       hcd="  protected:\n";
+       hcd+="  protected:\n";
        for(int i=0;i<k.size();i++){
                hcd+="\t"+qttype(cls,k[i])+" mp_"+k[i]+";\n";
        }
index 4b64942..4555a4f 100644 (file)
@@ -30,6 +30,7 @@ class WocQtClass:public QObject
                virtual void newClass(const WocClass&);
        private:
                WocQtOut*m_parent;
+               QString m_aux;
                
                /**helper: generate enums for classes*/
                void classEnums(const WocClass&,MFile&,MFile&,QString);
@@ -39,6 +40,8 @@ class WocQtClass:public QObject
                void classDeserializer(const WocClass&,MFile&,MFile&,QString);
                /**helper: generate serializers*/
                void classSerializers(const WocClass&,MFile&,MFile&,QString);
+               ///helper: generate scripting stuff
+               void classScripting(const WocClass&,MFile&,MFile&,QString,QString);
        signals:
                void errorFound();
 };
index 6a7fefa..9d51675 100644 (file)
@@ -28,179 +28,257 @@ void WocQtClientTransaction::finalize()
        trnList();
 }
 
+struct QtCTrans{
+       QString cn;//class name
+       QString cnp;//private class name
+       QString defparm;//default interface name
+       //code store
+       QString hcd;//header: class decl
+       QString hdi;//header includes
+       QString pcd;//private class decl
+       QString scd;//cpp source
+       QString sri;//cpp includes
+       //in/out params
+       QStringList in,out;
+       QString inlist;//input param list for function calls (type1 val1,type2 val2,...)
+       QString clist;//input param list, but call values only (val1,val2,...)
+       QString xinlist;//input params plus interface name
+       QString xclist;//input params plus interface name
+       //transaction itself
+       const WocTransaction&trn;
+       QtCTrans(const WocTransaction&t,QString cn_,QString cnp_):trn(t){
+               in=trn.inputNames();
+               out=trn.outputNames();
+               cn=cn_;cnp=cnp_;
+       }
+};
+
 void WocQtClientTransaction::newTransaction(const WocTransaction&trn)
 {
        QString cn=m_prefix+"T"+trn.name();
        QString cnp=cn+"_Private";
        addFile(cn);
-//     addFile(WocQtOut::Header,"prv"+cn+".h");
        MFile hdr(m_basedir+"/"+m_subdir+"/src"+cn+".h");
-//     MFile hdp(m_basedir+"/"+m_subdir+"/prv"+cn+".h");
        MFile src(m_basedir+"/"+m_subdir+"/src"+cn+".cpp");
        if(!hdr.open(QIODevice::WriteOnly|QIODevice::Truncate) ||
-//        !hdp.open(QIODevice::WriteOnly|QIODevice::Truncate) ||
           !src.open(QIODevice::WriteOnly|QIODevice::Truncate)){
                qDebug("Error: cannot create class files for transaction %s.",cn.toAscii().data());
                emit errorFound();
                return;
        }
        //basics
-       QStringList in=trn.inputNames();
-       QStringList out=trn.outputNames();
+       QtCTrans ct(trn,cn,cnp);
+       initList(ct);
        //lead in
        hdr.write(QByteArray(HDRSTART).replace("%",cn.toAscii()));
-//     hdp.write(QByteArray(HDRSTART).replace("%",cnp.toAscii()));
        src.write(QByteArray(SRCSTART).replace("%",cn.toAscii()));
        
        //start constructing code
-       QString hcd;//header: class decl
-       QString hdi;//header includes
-       QString pcd;//private class decl
-       QString scd;//cpp source
-       QString sri;//cpp includes
-       hdi="#include \""+m_transbase+"\"\n";
-//     pcd="#include \"src"+cn+".h\"\n";
-       sri+="#include \"WTransaction_Private\"\n";
-//     sri+="#include \"prv"+cn+".h\"\n";
-       sri+="#include \"WInterface\"\n";
-       sri+="#include <QCoreApplication>\n\n";
-       for(int i=0;i<in.size();i++){
-               QString tp=qtobjtype(trn,in[i],WocQtOut::In);
-               if(tp!="")hdi+="#include <"+tp+">\n";
-       }
-       for(int i=0;i<out.size();i++){
-               QString tp=qtobjtype(trn,out[i],WocQtOut::Out);
-               if(tp!="")hdi+="#include <"+tp+">\n";
-       }
-       hcd+="\nclass "+cnp+";\n";
-       hcd+="\nclass "+cn+":public "+m_transbase+"\n{\n";
-       pcd+="\nclass "+cnp+":public WTransaction_PrivateBase\n{\n";
+       
+       //include section
+       genInclude(ct);
+       //start of class
+       ct.hcd+="\nclass "+cnp+";\n";
+       ct.hcd+="\nclass "+cn+":public "+m_transbase+"\n{\n  Q_OBJECT\n";
+       ct.pcd+="\nclass "+cnp+":public WTransaction_PrivateBase\n{\n";
        
        //create properties
-       QString inlist,clist;
-       hcd+="  private:\n\t"+cnp+"*p;\n\tfriend class "+cnp+";\n";
-       pcd+="  protected:\n\tfriend class "+cn+";\n";
-       pcd+="\t"+cnp+"("+cn+"*parent){parent->p=this;}\n";
-       pcd+="\tvoid attach("+cn+"*parent){parent->p=this;WTransaction_PrivateBase::attach();}\n";
-       pcd+="\tvoid detach("+cn+"*parent){parent->p=0;WTransaction_PrivateBase::detach();}\n";
-       for(int i=0;i<in.size();i++){
-               pcd+="\t"+qttype(trn,in[i],WocQtOut::In)+"in_"+in[i]+";\n";
-               if(i){inlist+=",";clist+=",";}
-               inlist+="const "+qttype(trn,in[i],WocQtOut::In)+"&a"+in[i];
-               clist+="a"+in[i];
-       }
-       for(int i=0;i<out.size();i++)
-               pcd+="\t"+qttype(trn,out[i],WocQtOut::Out)+"out_"+out[i]+";\n";
+       genProperties(ct);
        
-       //query method decl
-       hcd+="\tvoid netquery();\n\tvoid asyncnetquery();\n";
-       hcd+="\tQByteArray encodeData();\n\tvoid decodeData(QByteArray);\n";
-       hcd+="  protected:\n\tvirtual void endQuery();\n";
+       //create constructors
+       ct.defparm="=\""+WocProcessor::instance()->projectName()+"\"";
+       genTors(ct);
        
-       //global interface code
-       QString sif="  "+cn+" query"+trn.name()+"("+inlist+")\n\t";
-       sif+="{return "+cn+"::query("+clist+(clist!=""?",":"")+"name());}\n";
-       m_iface.write(sif.toAscii());sif.clear();
+       //query method implemented
+       genQuery(ct);
+
+       //create getters
+       genGetters(ct);
        
-       //create constructors
-       if(inlist!="")inlist+=",";
-       inlist+="QString iface";
-       if(clist!="")clist+=",";
-       clist+="iface";
-       QString defparm="=\""+WocProcessor::instance()->projectName()+"\"";
+       //create scripting
+       genScripting(ct);
+       
+       //button class up
+       ct.hcd+="};\n\n";
+       ct.pcd+="};\n\n";
+       
+       //make meta object...
+       ct.hcd+="Q_DECLARE_METATYPE("+cn+")\n";
+       ct.scd+="static int mymetatypeid=qRegisterMetaType<"+cn+">();\n";
+       
+       //write code
+       hdr.write(ct.hdi.toAscii());
+       hdr.write(ct.hcd.toAscii());
+       src.write(ct.sri.toAscii());
+       src.write(ct.pcd.toAscii());
+       src.write(ct.scd.toAscii());
+       
+       //lead out
+       hdr.write(QByteArray(HDREND).replace("%",cn.toAscii()));
+       src.write(QByteArray(SRCEND).replace("%",cn.toAscii()));
+}
+
+void WocQtClientTransaction::initList(QtCTrans& ct)
+{
+       for(int i=0;i<ct.in.size();i++){
+               if(i){ct.inlist+=",";ct.clist+=",";}
+               ct.inlist+="const "+qttype(ct.trn,ct.in[i],WocQtOut::In)+"&a"+ct.in[i];
+               ct.clist+="a"+ct.in[i];
+       }
+       ct.xinlist=ct.inlist;
+       ct.xclist=ct.clist;
+       if(ct.xinlist!="")ct.xinlist+=",";
+       ct.xinlist+="QString iface";
+       if(ct.xclist!="")ct.xclist+=",";
+       ct.xclist+="iface";
+}
+
+
+void WocQtClientTransaction::genInclude(QtCTrans&ct)
+{
+       ct.hdi+="#include \""+m_transbase+"\"\n";
+       ct.sri+="#include \"WTransaction_Private\"\n";
+       ct.sri+="#include \"WInterface\"\n";
+       ct.sri+="#include <QCoreApplication>\n\n";
+       for(int i=0;i<ct.in.size();i++){
+               QString tp=qtobjtype(ct.trn,ct.in[i],WocQtOut::In);
+               if(tp!="")ct.hdi+="#include <"+tp+">\n";
+       }
+       for(int i=0;i<ct.out.size();i++){
+               QString tp=qtobjtype(ct.trn,ct.out[i],WocQtOut::Out);
+               if(tp!="")ct.hdi+="#include <"+tp+">\n";
+       }
+}
+
+void WocQtClientTransaction::genProperties(QtCTrans&ct)
+{
+       ct.hcd+="  private:\n\t"+ct.cnp+"*p;\n\tfriend class "+ct.cnp+";\n";
+       ct.pcd+="  protected:\n\tfriend class "+ct.cn+";\n";
+       ct.pcd+="\t"+ct.cnp+"("+ct.cn+"*parent){parent->p=this;}\n";
+       ct.pcd+="\tvoid attach("+ct.cn+"*parent){parent->p=this;WTransaction_PrivateBase::attach();}\n";
+       ct.pcd+="\tvoid detach("+ct.cn+"*parent){parent->p=0;WTransaction_PrivateBase::detach();}\n";
+       for(int i=0;i<ct.in.size();i++){
+               ct.pcd+="\t"+qttype(ct.trn,ct.in[i],WocQtOut::In)+"in_"+ct.in[i]+";\n";
+       }
+       for(int i=0;i<ct.out.size();i++)
+               ct.pcd+="\t"+qttype(ct.trn,ct.out[i],WocQtOut::Out)+"out_"+ct.out[i]+";\n";
+}
+
+void WocQtClientTransaction::genTors(QtCTrans&ct)
+{
        //define parametric constructor
-       hcd+="\t"+cn+"("+inlist+");\n";
+       ct.hcd+="  protected:\n";
+       ct.hcd+="\t"+ct.cn+"("+ct.xinlist+");\n";
        //parametric constructor implementation
-       scd+=cn+"::"+cn+"("+inlist+")\n\t:"+m_transbase+"(iface)\n{\n";
-       scd+="\tnew "+cnp+"(this);\n";
-       for(int i=0;i<in.size();i++){
-               scd+="\tp->in_"+in[i]+"=a"+in[i]+";\n";
+       ct.scd+=ct.cn+"::"+ct.cn+"("+ct.xinlist+")\n\t:"+m_transbase+"(iface)\n{\n";
+       ct.scd+="\tnew "+ct.cnp+"(this);\n";
+       for(int i=0;i<ct.in.size();i++){
+               ct.scd+="\tp->in_"+ct.in[i]+"=a"+ct.in[i]+";\n";
        }
-       scd+="}\n\n";
+       ct.scd+="}\n\n";
        //decl default constructor
-       hcd+="  public:\n";
-       hcd+="\t"+cn+"();\n";
-       scd+=cn+"::"+cn+"()\n{\n\tnew "+cnp+"(this);\n}\n\n";
+       ct.hcd+="  public:\n";
+       ct.hcd+="\t"+ct.cn+"();\n";
+       ct.scd+=ct.cn+"::"+ct.cn+"()\n{\n\tnew "+ct.cnp+"(this);\n}\n\n";
        //decl copy constructor
-       hcd+="\t"+cn+"(const "+cn+"&);\n";
+       ct.hcd+="\t"+ct.cn+"(const "+ct.cn+"&);\n";
        //copy constructor implementation
-       scd+=cn+"::"+cn+"(const "+cn+"&t)\n\t:"+m_transbase+"(t)\n{\n";
-       scd+="\tt.p->attach(this);\n";
-       scd+="}\n\n";
+       ct.scd+=ct.cn+"::"+ct.cn+"(const "+ct.cn+"&t)\n\t:"+m_transbase+"(t)\n{\n";
+       ct.scd+="\tt.p->attach(this);\n";
+       ct.scd+="}\n\n";
        //decl copy operator
-       hcd+="\t"+cn+"& operator=(const "+cn+"&);\n";
+       ct.hcd+="\t"+ct.cn+"& operator=(const "+ct.cn+"&);\n";
        //copy operator implemented
-       scd+=cn+"& "+cn+"::operator=(const "+cn+"&t)\n{\n";
-       scd+="\t"+m_transbase+"::operator=(t);\n";
-       scd+="\tp->detach(this);t.p->attach(this);\n";
-       scd+="\treturn *this;\n}\n\n";
+       ct.scd+=ct.cn+"& "+ct.cn+"::operator=(const "+ct.cn+"&t)\n{\n";
+       ct.scd+="\t"+m_transbase+"::operator=(t);\n";
+       ct.scd+="\tp->detach(this);t.p->attach(this);\n";
+       ct.scd+="\treturn *this;\n}\n\n";
        
        //destructor
-       hcd+="\t~"+cn+"();\n";
-       scd+=cn+"::~"+cn+"()\n{\n\tp->detach(this);\n}\n\n";
-       
-       //query method implemented
-       scd+="void "+cn+"::netquery()\n{\n";
-       scd+="\tWTransaction::Log log(this,\""+trn.name()+"\");\n";
-       scd+="\tQByteArray enc=encodeData();\n";
-       scd+="\tif(enc.isEmpty()){\n\t\temit finished();\n\t\treturn;\n\t}\n";
-       scd+="\texecuteQuery(\""+trn.name()+"\",enc);\n";
-       scd+="}\n";
+       ct.hcd+="\t~"+ct.cn+"();\n";
+       ct.scd+=ct.cn+"::~"+ct.cn+"()\n{\n\tp->detach(this);\n}\n\n";
+}
+
+void WocQtClientTransaction::genQuery(QtCTrans& ct)
+{
+       //global interface code
+       QString sif="  Q_SLOT "+ct.cn+" query"+ct.trn.name()+"("+ct.inlist+")\n\t";
+       sif+="{return "+ct.cn+"::query("+ct.clist+(ct.clist!=""?",":"")+"name());}\n";
+       m_iface.write(sif.toAscii());sif.clear();
+       //query method decl
+       ct.hcd+="  private:\n";
+       ct.hcd+="\tvoid netquery();\n\tvoid asyncnetquery();\n";
+       ct.hcd+="\tQByteArray encodeData();\n\tvoid decodeData(QByteArray);\n";
+       ct.hcd+="  protected:\n\tvirtual void endQuery();\n";
+       //sync query
+       ct.scd+="void "+ct.cn+"::netquery()\n{\n";
+       ct.scd+="\tWTransaction::Log log(this,\""+ct.trn.name()+"\");\n";
+       ct.scd+="\tQByteArray enc=encodeData();\n";
+       ct.scd+="\tif(enc.isEmpty()){\n\t\temit finished();\n\t\treturn;\n\t}\n";
+       ct.scd+="\texecuteQuery(\""+ct.trn.name()+"\",enc);\n";
+       ct.scd+="}\n";
        //async query method implemented
-       scd+="void "+cn+"::asyncnetquery()\n{\n";
-       scd+="\tnew WTransaction::Log(this,\""+trn.name()+"\");\n";
-       scd+="\tQByteArray enc=encodeData();\n";
-       scd+="\tif(enc.isEmpty()){\n\t\temit finished();\n\t\treturn;\n\t}\n";
-       scd+="\tstartQuery(\""+trn.name()+"\",enc);\n";
-       scd+="}\n";
+       ct.scd+="void "+ct.cn+"::asyncnetquery()\n{\n";
+       ct.scd+="\tnew WTransaction::Log(this,\""+ct.trn.name()+"\");\n";
+       ct.scd+="\tQByteArray enc=encodeData();\n";
+       ct.scd+="\tif(enc.isEmpty()){\n\t\temit finished();\n\t\treturn;\n\t}\n";
+       ct.scd+="\tstartQuery(\""+ct.trn.name()+"\",enc);\n";
+       ct.scd+="}\n";
        //encode input
-       scd+="QByteArray "+cn+"::encodeData()\n{\n";
-       scd+=trnInput(trn);
-       scd+="}\n";
+       ct.scd+="QByteArray "+ct.cn+"::encodeData()\n{\n";
+       ct.scd+=trnInput(ct.trn);
+       ct.scd+="}\n";
        //decode output
-       scd+="void "+cn+"::decodeData(QByteArray rba)\n{\n";
-       scd+=trnOutput(trn);
-       scd+="}\n";
-       scd+="void "+cn+"::endQuery()\n{\n";
-       scd+="\tdecodeData(d->m_rspdata.trimmed());\n";
-       scd+="\temit finished();\n}\n";
-       
-       
-       //create getters
-       for(int i=0;i<out.size();i++){
-               QString tp=qttype(trn,out[i],WocQtOut::Out);
-               hcd+="\t"+tp+" get"+out[i]+"();\n";
-               scd+=tp+" "+cn+"::get"+out[i]+"(){return p->out_"+out[i]+";}\n";
-       }
-       
+       ct.scd+="void "+ct.cn+"::decodeData(QByteArray rba)\n{\n";
+       ct.scd+=trnOutput(ct.trn);
+       ct.scd+="}\n";
+       ct.scd+="void "+ct.cn+"::endQuery()\n{\n";
+       ct.scd+="\tdecodeData(d->m_rspdata.trimmed());\n";
+       ct.scd+="\temit finished();\n}\n";
        //create queries
-       hcd+="\tstatic "+cn+" query("+inlist+defparm+");\n";
-       scd+=cn+" "+cn+"::query("+inlist+")\n{\n";
-       scd+="\t"+cn;
-       if(clist!="")scd+=" r("+clist+");\n";else scd+=" r;\n";
-       scd+="\tr.netquery();\n\treturn r;\n}\n";
-       hcd+="\tstatic "+cn+" asyncQuery("+inlist+defparm+");\n";
-       scd+=cn+" "+cn+"::asyncQuery("+inlist+")\n{\n";
-       scd+="\t"+cn;
-       if(clist!="")scd+=" r("+clist+");\n";else scd+=" r;\n";
-       scd+="\tr.asyncnetquery();\n\treturn r;\n}\n";
-       
-       //button up
-       hcd+="};\n\n";
-       pcd+="};\n\n";
-       
-       //write code
-       hdr.write(hdi.toAscii());
-       hdr.write(hcd.toAscii());
-//     hdp.write(pcd.toAscii());
-       src.write(sri.toAscii());
-       src.write(pcd.toAscii());
-       src.write(scd.toAscii());
-       
-       //lead out
-       hdr.write(QByteArray(HDREND).replace("%",cn.toAscii()));
-//     hdp.write(QByteArray(HDREND).replace("%",cnp.toAscii()));
-       src.write(QByteArray(SRCEND).replace("%",cn.toAscii()));
+       ct.hcd+="  public:\n";
+       ct.hcd+="\tstatic "+ct.cn+" query("+ct.xinlist+ct.defparm+");\n";
+       ct.scd+=ct.cn+" "+ct.cn+"::query("+ct.xinlist+")\n{\n";
+       ct.scd+="\t"+ct.cn;
+       ct.scd+=" r("+ct.xclist+");\n";
+       ct.scd+="\tr.netquery();\n\treturn r;\n}\n";
+       ct.hcd+="\tstatic "+ct.cn+" asyncQuery("+ct.xinlist+ct.defparm+");\n";
+       ct.scd+=ct.cn+" "+ct.cn+"::asyncQuery("+ct.xinlist+")\n{\n";
+       ct.scd+="\t"+ct.cn;
+       ct.scd+=" r("+ct.xclist+");\n";
+       ct.scd+="\tr.asyncnetquery();\n\treturn r;\n}\n";
+}
+
+void WocQtClientTransaction::genGetters(QtCTrans& ct)
+{
+       for(int i=0;i<ct.out.size();i++){
+               QString tp=qttype(ct.trn,ct.out[i],WocQtOut::Out);
+               ct.hcd+="\tQ_SLOT "+tp+" get"+ct.out[i]+"();\n";
+               ct.scd+=tp+" "+ct.cn+"::get"+ct.out[i]+"(){return p->out_"+ct.out[i]+";}\n";
+       }
+}
+
+void WocQtClientTransaction::genScripting(QtCTrans& ct)
+{
+       if(!m_parent->doGenerateScripting())return;
+       //converters between transaction and script values
+       ct.hdi+="class QScriptValue;\n";
+       ct.hdi+="class QScriptEngine;\n";
+       ct.sri+="#include <QScriptValue>\n";
+       ct.sri+="#include <QScriptEngine>\n";
+       ct.hcd+="\tstatic QScriptValue toScriptValue(QScriptEngine*,const "+ct.cn+"&);\n";
+       ct.hcd+="\tstatic void fromScriptValue(const QScriptValue&,"+ct.cn+"&);\n";
+       ct.scd+="QScriptValue "+ct.cn+"::toScriptValue(QScriptEngine*engine,const "+ct.cn+"&obj)\n{\n";
+       ct.scd+="\treturn engine->newQObject(new "+ct.cn+"(obj),QScriptEngine::ScriptOwnership);\n}\n";
+       ct.scd+="void "+ct.cn+"::fromScriptValue(const QScriptValue&val,"+ct.cn+"&obj)\n{\n";
+       ct.scd+="\t"+ct.cn+"*xobj=qobject_cast<"+ct.cn+"*>(val.toQObject());\n";
+       ct.scd+="\tif(xobj!=0 && &obj!=xobj)obj = *xobj;\n}\n";
+       //add to engine
+       m_parent->addScriptInit(
+        "\t{QScriptValue mo=engine->newQMetaObject(&"+ct.cn+"::staticMetaObject);\n"
+        "\tgval.setProperty(\""+ct.cn+"\",mo);\n"
+        "\tqScriptRegisterMetaType(engine,"+ct.cn+"::toScriptValue,"+ct.cn+"::fromScriptValue);}\n"
+       );
 }
 
 QString WocQtClientTransaction::trnInput(const WocTransaction&trn)
@@ -342,6 +420,7 @@ void WocQtClientTransaction::trnList()
 {
        QString code;
        //header
+       code+="  Q_ENUMS(Right)\n";
        code+="  enum Right {\n    NoRight";
        QStringList r=WocProcessor::instance()->transactionNames();
        QStringList p=WocProcessor::instance()->privilegeNames();
@@ -351,39 +430,46 @@ void WocQtClientTransaction::trnList()
        for(int i=0;i<p.size();i++)
                code+=",\n    P"+pp[i].replace(':',"_");
        code+="\n  };\n";
-       code+="  static QString rightToString(Right);\n";
-       code+="  static QString rightToLocalString(Right);\n";
-       code+="  static Right stringToRight(QString);\n";
-       code+="  static QStringList allKnownRightsString();\n";
-       code+="  static QList<Right> allKnownRights();\n";
-       m_iface.write(code.toAscii());
+       code+="  typedef QList<Right> RightList;\n";
+       code+="  Q_INVOKABLE static QString rightToString(Right);\n";
+       code+="  Q_INVOKABLE static QString rightToLocalString(Right);\n";
+       code+="  Q_INVOKABLE static Right stringToRight(QString);\n";
+       code+="  Q_INVOKABLE static QStringList allKnownRightsString();\n";
+       code+="  Q_INVOKABLE static "+m_parent->ifaceClassName()+"::RightList allKnownRights();\n";
+       m_iface.write(code.toAscii());code.clear();
        
-       code="QString "+m_prefix+"Interface::rightToString(Right r)\n{\n\tswitch(r){\n";
+       code+="static int righttypeid=";
+       code+="qRegisterMetaType<"+m_parent->ifaceClassName()+"::RightList>()+";
+       code+="qRegisterMetaType<QList<"+m_parent->ifaceClassName()+"::RightList> >();\n";
+       m_parent->addPostIface("Q_DECLARE_METATYPE("+m_parent->ifaceClassName()+"::RightList)\n");
+       m_parent->addPostIface("Q_DECLARE_METATYPE(QList<"+ m_parent->ifaceClassName()+ "::RightList>)\n");
+       m_parent->addScriptInit("\tqScriptRegisterSequenceMetaType<QList<RightList> >(engine);\n");
+       code+="QString "+m_parent->ifaceClassName()+"::rightToString(Right r)\n{\n\tswitch(r){\n";
        for(int i=0;i<r.size();i++)
                code+="\t\tcase R"+r[i]+":return \""+r[i]+"\";\n";
        for(int i=0;i<p.size();i++)
                code+="\t\tcase P"+pp[i]+":return \""+p[i]+"\";\n";
        code+="\t\tdefault:return \"\";\n\t}\n}\n";
-       code+="QString "+m_prefix+"Interface::rightToLocalString(Right r)\n{\n\tswitch(r){\n";
+       code+="QString "+m_parent->ifaceClassName()+"::rightToLocalString(Right r)\n{\n\tswitch(r){\n";
        for(int i=0;i<r.size();i++)
                code+="\t\tcase R"+r[i]+":return tr(\""+r[i]+"\");\n";
        for(int i=0;i<p.size();i++)
                code+="\t\tcase P"+pp[i]+":return tr(\""+p[i]+"\");\n";
        code+="\t\tdefault:return \"\";\n\t}\n}\n";
-       code+=m_prefix+"Interface::Right "+m_prefix+"Interface::stringToRight(QString s)\n{\n";
+       code+=m_parent->ifaceClassName()+"::Right "+m_prefix+"Interface::stringToRight(QString s)\n{\n";
        for(int i=0;i<r.size();i++)
                code+="\tif(s==\""+r[i]+"\")return R"+r[i]+";else\n";
        for(int i=0;i<p.size();i++)
                code+="\tif(s==\""+p[i]+"\")return P"+pp[i]+";else\n";
        code+="\treturn NoRight;\n}\n";
-       code+="QList<"+m_prefix+"Interface::Right> "+m_prefix+"Interface::allKnownRights()\n{\n";
+       code+="QList<"+m_parent->ifaceClassName()+"::Right> "+m_parent->ifaceClassName()+"::allKnownRights()\n{\n";
        code+="\tQList<Right> ret;ret";
        for(int i=0;i<r.size();i++)
                code+="<<R"+r[i];
        for(int i=0;i<p.size();i++)
                code+="<<P"+pp[i];
        code+=";\n\treturn ret;\n}\n";
-       code+="QStringList "+m_prefix+"Interface::allKnownRightsString()\n{\n";
+       code+="QStringList "+m_parent->ifaceClassName()+"::allKnownRightsString()\n{\n";
        code+="\tQStringList ret;ret";
        for(int i=0;i<r.size();i++)
                code+="<<\""+r[i]+"\"";
index 7340b49..fb0a8b6 100644 (file)
@@ -15,6 +15,7 @@
 
 #include "qtout.h"
 
+struct QtCTrans;
 class WocQtOut;
 class WocTransaction;
 class WocClass;
@@ -33,6 +34,20 @@ class WocQtClientTransaction:public WocQtTransaction
                QString trnOutput(const WocTransaction&);
                /**helper generates enums and strings for all transactions*/
                void trnList();
+               ///helper: generate include section
+               void genInclude(QtCTrans&);
+               ///helper: generate properties
+               void genProperties(QtCTrans&);
+               ///helper: generate con- and de-structors
+               void genTors(QtCTrans&);
+               ///helper: generate query methods
+               void genQuery(QtCTrans&);
+               ///helper: generate getter methods
+               void genGetters(QtCTrans&);
+               ///helper: generate QtScript glue code
+               void genScripting(QtCTrans&);
+               ///helper: initialize data in the transaction wrapper
+               void initList(QtCTrans&);
 };
 
 #endif
index d95382b..3cb9581 100644 (file)
@@ -32,6 +32,7 @@ WocQtOut::WocQtOut(QDomElement&el)
        m_clean=str2bool(el.attribute("clean","0"));
        m_prefix=el.attribute("classPrefix","Wob");
        m_transbase=el.attribute("transactionBase","WTransaction");
+       m_genscript=str2bool(el.attribute("scriptable","0"));
        //get/create directory
        QDir d(m_basedir+"/"+m_subdir);
        if(!d.exists())QDir(".").mkpath(m_basedir+"/"+m_subdir);
@@ -49,14 +50,14 @@ WocQtOut::WocQtOut(QDomElement&el)
        //create interface class
        WocProcessor*woc=WocProcessor::instance();
        QString pn=woc->projectName();
-       m_ifacecpp.setFileName(m_basedir+"/"+m_subdir+"/src"+m_prefix+"Interface.cpp");
+       m_ifacecpp.setFileName(m_basedir+"/"+m_subdir+"/src"+ifaceClassName()+".cpp");
        if(!m_ifacecpp.open(QIODevice::WriteOnly|QIODevice::Truncate)){
                qDebug("Error: cannot create Qt interface file %s.",m_ifacecpp.fileName().toAscii().data());
                emit errorFound();
                return;
        }
-       m_ifacecpp.write(QByteArray(SRCSTART).replace('%',m_prefix+"Interface"));
-       m_iface.setFileName(m_basedir+"/"+m_subdir+"/src"+m_prefix+"Interface.h");
+       m_ifacecpp.write(QByteArray(SRCSTART).replace('%',ifaceClassName()));
+       m_iface.setFileName(m_basedir+"/"+m_subdir+"/src"+ifaceClassName()+".h");
        if(!m_iface.open(QIODevice::WriteOnly|QIODevice::Truncate)){
                qDebug("Error: cannot create Qt interface file %s.",m_iface.fileName().toAscii().data());
                emit errorFound();
@@ -65,15 +66,24 @@ WocQtOut::WocQtOut(QDomElement&el)
        m_iface.write(QByteArray(HDRSTART).replace("%",m_prefix.toAscii()+"INTERFACE_H"));
        m_iface.write(QByteArray("#include \""+m_prefix.toAscii()+"IncludeAll\"\n#include \"WInterface\"\n"));
        m_iface.write(QByteArray("#include <QStringList>\n"));
-       m_iface.write(QString("class "+m_prefix+"Interface:public WInterface\n{\n Q_OBJECT\n").toAscii());
-       m_iface.write(QString(" public:\n  "+m_prefix+"Interface(QString name=\""+pn+"\"):WInterface(name){}\n").toAscii());
-       m_iface.write(QString("  static "+m_prefix+"Interface*instance(QString name=\""+pn+"\")\n\t{return qobject_cast<"+m_prefix+"Interface*>(WInterface::instance(name));}\n\n").toAscii());
-       m_iface.write(QString("  static QString commVersion(){return \""+woc->verComm()+"\";}\n").toAscii());
-       m_iface.write(QString("  static QString needCommVersion(){return \""+woc->verNeedComm()+"\";}\n").toAscii());
-       m_iface.write(QString("  static QString version(){return \""+woc->verHR()+"\";}\n").toAscii());
-       m_iface.write(QString("  static QString svnVersion(){return \""+woc->svnRevision()+"\";}\n\n").toAscii());
-       m_iface.write(QString("  static QString svnRepositoryRoot(){return \""+woc->svnRepositoryRoot()+"\";}\n\n").toAscii());
-       m_iface.write(QString("  static QString svnRepositoryUrl(){return \""+woc->svnRepositoryUrl()+"\";}\n\n").toAscii());
+       if(m_genscript)
+               m_iface.write(QByteArray("class QScriptEngine;\n"));
+       m_iface.write(QString("class "+ifaceClassName()+":public WInterface\n{\n Q_OBJECT\n").toAscii());
+       m_iface.write(QString(" public:\n  "+ifaceClassName()+"(QString name=\""+pn+"\"):WInterface(name){}\n").toAscii());
+       m_iface.write(QString("  static "+ifaceClassName()+"*instance(QString name=\""+pn+"\")\n\t{return qobject_cast<"+ifaceClassName()+"*>(WInterface::instance(name));}\n\n").toAscii());
+       m_iface.write(QString("  Q_INVOKABLE static QString commVersion(){return \""+woc->verComm()+"\";}\n").toAscii());
+       m_iface.write(QString("  Q_INVOKABLE static QString needCommVersion(){return \""+woc->verNeedComm()+"\";}\n").toAscii());
+       m_iface.write(QString("  Q_INVOKABLE static QString version(){return \""+woc->verHR()+"\";}\n").toAscii());
+       m_iface.write(QString("  Q_INVOKABLE static QString svnVersion(){return \""+woc->svnRevision()+"\";}\n\n").toAscii());
+       m_iface.write(QString("  Q_INVOKABLE static QString svnRepositoryRoot(){return \""+woc->svnRepositoryRoot()+"\";}\n\n").toAscii());
+       m_iface.write(QString("  Q_INVOKABLE static QString svnRepositoryUrl(){return \""+woc->svnRepositoryUrl()+"\";}\n\n").toAscii());
+       
+       //init scripting
+       m_scriptcode="#include <QScriptEngine>\n";
+       m_scriptcode+="void "+ifaceClassName()+"::initScriptEngine(QScriptEngine*engine)\n{\n";
+       m_scriptcode+="\tQScriptValue gval=engine->globalObject();\n";
+       m_scriptcode+="\tgval.setProperty(\"Interface\",engine->newQMetaObject(this->metaObject()));\n";
+       m_scriptcode+="\tgval.setProperty(\"interface\",engine->newQObject(this,QScriptEngine::QtOwnership, QScriptEngine::ExcludeDeleteLater));\n";
        
        //create all includer
        m_hdr.setFileName(m_basedir+"/"+m_subdir+"/"+m_prefix+"IncludeAll");
@@ -83,20 +93,29 @@ WocQtOut::WocQtOut(QDomElement&el)
                return;
        }
        m_hdr.write(QByteArray(HDRSTART).replace("%",m_prefix.toAscii()+"INCLUDE_H"));
-       addFile(m_prefix.toAscii()+"Interface");
+       addFile(ifaceClassName().toAscii());
 }
 
 WocQtOut::~WocQtOut(){}
 
 void WocQtOut::finalize()
 {
+       //finish sub-classes
        if(qclass)qclass->finalize();
        if(qtable)qtable->finalize();
        if(qtrans)qtrans->finalize();
+       //finish scripting stuff
+       if(m_genscript){
+               m_iface.write(QByteArray("  void initScriptEngine(QScriptEngine*);\n"));
+               m_scriptcode+="}\n\n";
+               m_ifacecpp.write(m_scriptcode.toAscii());
+       }
        //finish sources
        m_ifacecpp.write(SRCEND);
        m_ifacecpp.close();
-       m_iface.write(QByteArray("};\n")+HDREND);
+       m_iface.write(QByteArray("};\n"));
+       m_iface.write(m_postiface.toAscii());
+       m_iface.write(HDREND);
        m_iface.close();
        m_pri.write(QByteArray("\n#END OF AUTOGENERATED PRI FILE\n"));
        m_pri.close();
@@ -114,6 +133,12 @@ void WocQtOut::finalize()
        }
 }
 
+void WocQtOut::addPostIface(QString s)
+{
+       m_postiface+=s;
+}
+
+
 void WocQtOut::newTable(const WocTable&tbl)
 {
        if(qtable)qtable->newTable(tbl);
index 45deeae..a4c83f6 100644 (file)
@@ -54,9 +54,9 @@ class WocQtOut:public WocOutput
                friend class WocQtTransaction;
                friend class WocQtTable;
                
-               QString m_basedir,m_subdir,m_prefix,m_transbase,m_lang;
+               QString m_basedir,m_subdir,m_prefix,m_transbase,m_lang,m_postiface,m_scriptcode;
                MFile m_pri,m_iface,m_ifacecpp,m_hdr;
-               bool m_clean;
+               bool m_clean,m_genscript;
                
                ///types of files generated
                enum FileType{
@@ -80,6 +80,14 @@ class WocQtOut:public WocOutput
                void addFile(FileType kind,QString fname);
                /**helper: add a line to the project file*/
                void addProjectLine(QString);
+               /**helper: adds a line after the class definition of the interface class*/
+               void addPostIface(QString);
+               /**helper: returns the class name of the interface class*/
+               QString ifaceClassName()const{return m_prefix+"Interface";}
+               /**helper: adds a line to the script initializer; this is ignored if scripting is inactive*/
+               void addScriptInit(QString s){m_scriptcode+=s;}
+               ///helper: returns true if sub-classes are supposed to create scripting code
+               bool doGenerateScripting()const{return m_genscript;}
                
                WocQtClass*qclass;
                WocQtTable*qtable;