more on client side transactions
authorkonrad <konrad@6e3c4bff-ac9f-4ac1-96c5-d2ea494d3e33>
Sun, 15 Mar 2009 15:29:01 +0000 (15:29 +0000)
committerkonrad <konrad@6e3c4bff-ac9f-4ac1-96c5-d2ea494d3e33>
Sun, 15 Mar 2009 15:29:01 +0000 (15:29 +0000)
git-svn-id: https://silmor.de/svn/softmagic/smoke/trunk@278 6e3c4bff-ac9f-4ac1-96c5-d2ea494d3e33

src/wbase/WInterface.cpp [new file with mode: 0644]
src/wbase/WInterface.h [new file with mode: 0644]
src/wbase/WTransaction.cpp
src/wbase/WTransaction.h
src/wbase/wbase.pri
wob/magicsmoke.wolf
woc/processor.cpp
woc/processor.h
woc/qtout.cpp
woc/qtout.h

diff --git a/src/wbase/WInterface.cpp b/src/wbase/WInterface.cpp
new file mode 100644 (file)
index 0000000..4eb4f3a
--- /dev/null
@@ -0,0 +1,47 @@
+//
+// C++ Implementation: WInterface
+//
+// Description: 
+//
+//
+// Author: Konrad Rosenbaum <konrad@silmor.de>, (C) 2009
+//
+// Copyright: See README/COPYING files that come with this distribution
+//
+//
+
+#include "WInterface.h"
+
+#include <QMutex>
+#include <QMutexLocker>
+
+QMap<QString,WInterface*> WInterface::inst;
+
+static QMutex mtx;
+
+WInterface*WInterface::instance(QString name)
+{
+       QMutexLocker ml(&mtx);
+       if(inst.contains(name))return inst[name];
+       else return 0;
+}
+
+WInterface::WInterface(QString name)
+{
+       m_proxyport=0;
+       m_wtimeout=30;
+       QMutexLocker ml(&mtx);
+       if(inst.contains(name)){
+               delete inst[name];
+       }
+       inst.insert(name,this);
+}
+
+WInterface::~WInterface()
+{
+}
+
+QMap<QString,QString> WInterface::headers(QString)const
+{
+       return QMap<QString,QString>();
+}
diff --git a/src/wbase/WInterface.h b/src/wbase/WInterface.h
new file mode 100644 (file)
index 0000000..5bfe746
--- /dev/null
@@ -0,0 +1,68 @@
+//
+// C++ Interface: WInterface
+//
+// Description: 
+//
+//
+// Author: Konrad Rosenbaum <konrad@silmor.de>, (C) 2009
+//
+// Copyright: See README/COPYING files that come with this distribution
+//
+//
+
+#ifndef WOB_INTERFACE_H
+#define WOB_INTERFACE_H
+
+#include <QMap>
+#include <QObject>
+#include <QUrl>
+
+class WInterface:public QObject
+{
+       protected:
+               WInterface(QString name);
+               
+       public:
+               virtual ~WInterface();
+               /**overwrite if you need additional headers (eg. session-ids) for certain transactions (transaction name is handed in as string argument); per default returns empty map*/
+               virtual QMap<QString,QString> headers(QString)const;
+               
+               /**returns the URL of the interface*/
+               QUrl url()const{return m_url;}
+               /**sets the URL of the interface*/
+               void setUrl(QUrl u){m_url=u;}
+               
+               /**returns whether the interface uses a proxy*/
+               bool useProxy()const{return m_proxyhost!="";}
+               /**returns whether the proxy needs authentication*/
+               bool useProxyAuth()const{return m_proxyuser!="";}
+               /**resets the proxy settings to no proxy use*/
+               void resetProxy(){m_proxyhost="";m_proxyport=0;m_proxyuser="";m_proxypass="";}
+               /**sets the proxy settings*/
+               void setProxy(QString proxyhost,unsigned short proxyport,QString proxyuser="",QString proxypassword=""){m_proxyhost=proxyhost;m_proxyport=proxyport;m_proxyuser=proxyuser;m_proxypass=proxypassword;}
+               /**returns the proxy host name*/
+               QString proxyHost()const{return m_proxyhost;}
+               /**returns the proxy port*/
+               unsigned short proxyPort()const{return m_proxyport;}
+               /**returns the proxy user name*/
+               QString proxyUser()const{return m_proxyuser;}
+               /**returns the proxy password*/
+               QString proxyPassword()const{return m_proxypass;}
+               
+               /**return timeout in seconds*/
+               int webTimeout()const{return m_wtimeout;}
+               /**set timeout for page loads in seconds*/
+               void setWebTimeout(int t){if(t>0)m_wtimeout=t;}
+               
+               /**returns the instance registered under that name*/
+               static WInterface*instance(QString);
+               
+       private:
+               static QMap<QString,WInterface*>inst;
+               QUrl m_url;
+               QString m_proxyhost,m_proxyuser,m_proxypass;
+               unsigned short m_proxyport;
+               int m_wtimeout;
+};
+
+#endif
index 926ba37..f5f2eba 100644 (file)
@@ -9,3 +9,155 @@
 // Copyright: See README/COPYING files that come with this distribution
 //
 //
+
+#include "WTransaction.h"
+#include "WInterface.h"
+
+//WaitCursor, TODO: refactor this
+#include "main.h"
+
+#include <QDebug>
+#include <QEventLoop>
+#include <QHttp>
+#include <QTimer>
+#include <QUrl>
+
+WTransaction::WTransaction(QString ifc)
+{
+       m_haserror=false;
+       m_httpid=-1;
+       m_iface=ifc;
+}
+WTransaction::WTransaction(const WTransaction&t)
+       :QObject()
+{
+       m_haserror=t.m_haserror;
+       m_errstr=t.m_errstr;
+       m_errtype=t.m_errtype;
+       m_iface=t.m_iface;
+       m_httpid=-1;
+}
+
+static inline QString esc(const QByteArray ar)
+{
+       QString r;
+       for(int i=0;i<ar.size();i++){
+               unsigned char a=ar[i];
+               if(a=='\\')r+="\\\\";else
+               if(a=='\n' || a=='\r' || (a>=32 && a<=127))r+=(char)a;
+               else r+="\\x"+QByteArray((char*)&a,1).toHex();
+       }
+       return r;
+}
+
+QByteArray WTransaction::executeQuery(QString hreq,QByteArray data)
+{
+       QHttp req;
+       connect(&req,SIGNAL(requestFinished(int,bool)),this,SLOT(webReady(int,bool)));
+       //show the user we are waiting
+       WaitCursor wc;
+       //set up request
+       QString log;
+       QEventLoop loop(this);
+       connect(this,SIGNAL(webFinished()),&loop,SLOT(quit()));
+       WInterface *iface=WInterface::instance(m_iface);
+       if(!iface){
+               qDebug("Error: transaction cannot find interface.");
+               m_haserror=true;
+               m_errtype="_iface";
+               return QByteArray();
+       }
+       QUrl url=iface->url();
+       int port=url.port();
+       if(port<=0){
+               if(url.scheme().toLower()=="http")port=80;
+               else port=443;
+       }
+       qDebug()<<QString("New HTTP Request %1 URL %2\n\tto host=%3 port=%4 scheme=%5")
+               .arg(hreq)
+               .arg(url.toString())
+               .arg(url.host())
+               .arg(port)
+               .arg(url.scheme());
+       QHttp::ConnectionMode conm;
+       if(url.scheme().toLower()=="http")conm=QHttp::ConnectionModeHttp;
+       else conm=QHttp::ConnectionModeHttps;
+       req.setHost(url.host(),conm,port);
+       if(iface->useProxy())req.setProxy(iface->proxyHost(),iface->proxyPort(),iface->proxyUser(),iface->proxyPassword());
+       QString pathspec=url.path();
+       if(pathspec=="")pathspec="/";
+       if(url.encodedQuery()!="")pathspec+="?"+url.encodedQuery();
+       QHttpRequestHeader hrh("POST",pathspec);
+       QString hostspec=url.host();
+       if(url.port()>0)hostspec+=":"+QString::number(port);
+       hrh.setValue("Host",hostspec);
+       hrh.setValue("X-Wob-Request",hreq);
+       //TODO: hrh.setValue("X-MagicSmoke-Session",sessionid);
+       hrh.setContentLength(data.size());
+       hrh.setContentType("application/x-webobject; charset=UTF-8");
+       m_httpid=req.request(hrh,data);
+       //if(loglvl>LogMinimal)
+               log=QString("Request %3 with header:\n%1\n\nRequest Body:\n%2\n<---->\n").arg(hrh.toString()).arg(esc(data)).arg(m_httpid);
+       qDebug("started req %i",m_httpid);
+       //start loop
+       QTimer::singleShot(iface->webTimeout()*1000,this,SLOT(webTimeout()));
+       loop.exec();
+       m_httpid=-1;
+       //process result
+       if(m_haserror && m_errtype=="_timeout"){
+               //it did not finish yet, caught a timeout.
+               req.abort();
+               m_errstr="Web Request timed out.";
+               qDebug("Request %i timed out.",m_httpid);
+               //TODO: if(loglvl&LogOnError)
+                       qDebug()<<log;
+               return QByteArray();
+       }else
+       //finished with low-level error?
+       if(m_haserror){
+               m_errstr="HTTP Error: "+req.errorString();
+               log+=QString("Request %2 finished with HTTP level error: %1").arg(m_errstr).arg(m_httpid);
+               //TODO: if(loglvl&LogOnError)
+                       qDebug()<<log;
+               return QByteArray();
+       }
+       QHttpResponseHeader rsph=req.lastResponse();
+       //check for high level error
+       if(rsph.statusCode()!=200){
+               m_errstr="HTTP Error, return code "+QString::number(rsph.statusCode())+" "+rsph.reasonPhrase();
+               m_errtype="_HTTP";
+               m_haserror=true;
+               log+=QString("Request %2 finished with HTTP level error: %1").arg(m_errstr).arg(m_httpid);
+               //TODO: if(loglvl&LogOnError)
+                       qDebug()<<log;
+               return QByteArray();
+       }
+       //get data
+       QByteArray rspdata=req.readAll();
+       //
+       //TODO: if(loglvl==LogDetailed){
+               log+=QString ("----->\nHTTP Response %3 Headers:\n%1\nHTTP Response %3 Body:\n%2\n<------------------").arg(rsph.toString()).arg(esc(rspdata)).arg(m_httpid);
+               qDebug()<<log;
+       //}
+       return rspdata;
+}
+
+void WTransaction::webTimeout()
+{
+       if(m_httpid<0)return;
+       qDebug("web timeout");
+       m_haserror=true;
+       m_errtype="_timeout";
+       emit webFinished();
+}
+
+void WTransaction::webReady(int i,bool e)
+{
+       qDebug("finished req %i",i);
+       if(i!=m_httpid)return;
+       if(e){
+               m_haserror=true;
+               m_errtype="_web";
+       }
+       emit webFinished();
+}
index 15e5a39..98303d0 100644 (file)
 
 #include <QObject>
 #include <QList>
+#include <QString>
 
 #include "nullable.h"
 
 class WTransaction:public QObject
 {
+       Q_OBJECT
+       public:
+               bool hasError()const{return m_haserror;}
+               QString errorType()const{return m_errtype;}
+               QString errorString()const{return m_errstr;}
        protected:
-               WTransaction(){}
-               WTransaction(const WTransaction&){}
+               WTransaction(QString iface=QString());
+               WTransaction(const WTransaction&);
+               
+               QByteArray executeQuery(QString,QByteArray);
+       private slots:
+               void webTimeout();
+               void webReady(int,bool);
+       signals:
+               void webFinished();
+       private:
+               bool m_haserror;
+               QString m_errtype,m_errstr,m_iface;
+               int m_httpid;
 };
 
 #endif
index 90988ba..389787b 100644 (file)
@@ -1,10 +1,12 @@
 HEADERS += \
        wbase/nullable.h \
        wbase/WObject.h \
-       wbase/WTransaction.h
+       wbase/WTransaction.h \
+       wbase/WInterface.h
 
 SOURCES += \
        wbase/WObject.cpp \
-       wbase/WTransaction.cpp
+       wbase/WTransaction.cpp \
+       wbase/WInterface.cpp
 
 INCLUDEPATH += ./wbase ./wob
\ No newline at end of file
index 895aa5e..46e7b4c 100644 (file)
@@ -8,12 +8,12 @@
   -->
 <Wolf>
        <!-- generic settings -->
-       <Project baseDir=".." wobDir="wob"/>
+       <Project baseDir=".." wobDir="wob" name="MagicSmoke"/>
        <Version comm="0100" needcomm="0100" humanReadable="1.1 alpha" svnTarget="."/>
        <DataBase instance="db" schema="dbScheme" version="00.03"/>
        
        <!-- configure output -->
-       <QtClientOutput sourceDir="src" subDir="wob" priInclude="wob.pri"/>
+       <QtClientOutput sourceDir="src" subDir="wob" priInclude="wob.pri" classPrefix="M"/>
        <PHPServerOutput sourceDir="www" subDir="inc/wob" extension=".php" clean="yes">
                <Authenticator isAuthenticated="$::session->isAuthenticated()" hasRole="$::session->canExecute('%')" userName="$::session->getUser()"/>
        </PHPServerOutput>
index 095c2fe..fff55db 100644 (file)
@@ -38,6 +38,7 @@ WocProcessor::WocProcessor()
        m_dbInst="dbInst";
        m_dbSchema="dbSchema";
        m_error=false;
+       m_projname="WobProject";
        
        inst=this;
 }
@@ -105,6 +106,8 @@ bool WocProcessor::processFile(QString fn)
                                m_baseDir=el.attribute("baseDir");
                        if(el.hasAttribute("wobDir"))
                                m_wobDir=el.attribute("wobDir");
+                       if(el.hasAttribute("name"))
+                               m_projname=el.attribute("name");
                }else
                if(tn=="Include"){
                        if(!processFile(m_baseDir+"/"+m_wobDir+"/"+el.attribute("file")))
@@ -119,7 +122,7 @@ bool WocProcessor::processFile(QString fn)
                                m_dbVer=el.attribute("version");
                }else
                if(tn=="QtClientOutput"){
-                       new WocQtClientOut(el.attribute("sourceDir","."), el.attribute("subDir","qtwob"), el.attribute("priInclude","qtwob.pri"),str2bool(el.attribute("clean","0")));
+                       new WocQtClientOut(el);
                        if(m_error)return false;
                }else
                if(tn=="PHPServerOutput"){
index 60dee66..209cc9b 100644 (file)
@@ -312,6 +312,8 @@ class WocProcessor:public QObject
                QString baseDir()const{return m_baseDir;}
                /**returns the directory where WOLFs are found, should normally not be used outside this class*/
                QString wobDir()const{return m_wobDir;}
+               /**returns the project name (default="WobProject")*/
+               QString projectName()const{return m_projname;}
                /**returns the current communication protocol version*/
                QString verComm()const{return m_verComm;}
                /**returns the communication protocol version that is at least needed to be compatible*/
@@ -342,7 +344,7 @@ class WocProcessor:public QObject
        private slots:
                void errorFound();
        private:
-               QString m_baseDir,m_wobDir,m_verComm,m_verNeedComm,m_verHR;
+               QString m_baseDir,m_wobDir,m_verComm,m_verNeedComm,m_verHR,m_projname;
                QString m_svnTarget,m_svnRev,m_svnExe,m_dbInst,m_dbSchema,m_dbVer;
                bool m_error;
                
index 86401b2..f5965e0 100644 (file)
 #include "qtout.h"
 
 #include <QDir>
+#include <QDomElement>
 
-WocQtClientOut::WocQtClientOut(QString srcDir,QString subDir,QString prifile,bool clean)
+//start section of all header files
+static const QByteArray HDRSTART=
+       "//AUTOMATICALLY GENERATED FILE\n"
+       "//DO NOT EDIT THIS FILE DIRECTLY, USE THE XML SOURCE!\n"
+       "#ifndef WOBGEN_%\n"
+       "#define WOBGEN_%\n\n";
+//end section of all header files
+static const QByteArray HDREND="\n//END OF AUTOMATICALLY GENERATED FILE\n#endif\n";
+
+//start section of all source files
+static const QByteArray SRCSTART=
+       "//AUTOMATICALLY GENERATED FILE\n"
+       "//DO NOT EDIT THIS FILE DIRECTLY, USE THE XML SOURCE!\n"
+       "#include \"%.h\"\n"
+       "#include <QDomElement>\n"
+       "#include <QDomNodeList>\n"
+       "#include <QDomDocument>\n";
+//end section of all source files
+static const QByteArray SRCEND="\n//END OF AUTOMATICALLY GENERATED FILE\n";
+
+WocQtClientOut::WocQtClientOut(QDomElement&el)
 {
        qDebug("Info: creating Qt Client Output Generator.");
-       m_basedir=WocProcessor::instance()->baseDir()+"/"+srcDir;
-       m_subdir=subDir;
+       m_basedir=WocProcessor::instance()->baseDir()+"/"+el.attribute("sourceDir",".");
+       m_subdir=el.attribute("subDir","qtwob");
+       bool clean=str2bool(el.attribute("clean","0"));
+       m_prefix=el.attribute("classPrefix","Wob");
        //cleanup directory (remove normal files, assume remainder is harmless)
        QDir d(m_basedir+"/"+m_subdir);
        if(d.exists() && clean){
@@ -28,46 +51,59 @@ WocQtClientOut::WocQtClientOut(QString srcDir,QString subDir,QString prifile,boo
        }
        //get/create directory
        if(!d.exists())QDir(".").mkpath(m_basedir+"/"+m_subdir);
+       
        //create project file
-       m_pri.setFileName(m_basedir+"/"+m_subdir+"/"+prifile);
+       m_pri.setFileName(m_basedir+"/"+m_subdir+"/"+el.attribute("priInclude","qtwob.pri"));
        if(!m_pri.open(QIODevice::WriteOnly|QIODevice::Truncate)){
                qDebug("Error: cannot create Qt project file %s.",m_pri.fileName().toAscii().data());
                emit errorFound();
                return;
        }
        m_pri.write(QByteArray("#AUTOMATICALLY GENERATED FILE - DONT CHANGE!\n"));
+       
+       //create interface class
+       QString pn=WocProcessor::instance()->projectName();
+       m_iface.setFileName(m_basedir+"/"+m_subdir+"/"+m_prefix+"Interface.h");
+       if(!m_iface.open(QIODevice::WriteOnly|QIODevice::Truncate)){
+               qDebug("Error: cannot create Qt interface file %s.",m_iface.fileName().toAscii().data());
+               emit errorFound();
+               return;
+       }
+       m_iface.write(QByteArray(HDRSTART).replace("%",m_prefix.toAscii()+"INTERFACE_H"));
+       m_iface.write(QByteArray("#include \""+m_prefix.toAscii()+"Include.h\"\n#include \"WInterface.h\"\n"));
+       m_iface.write(QString("class "+m_prefix+"Interface:public WInterface\n{\n").toAscii());
+       m_iface.write(QString(" public:\n  "+m_prefix+"Interface(QString name=\""+pn+"\"):WInterface(name){}\n").toAscii());
+       m_iface.write(QString("  static "+pn+"Interface*instance(QString name=\""+pn+"\"){qobject_cast<"+m_prefix+"Interface*>(WInterface::instance(name));}\n").toAscii());
+       
+       //create all includer
+       m_hdr.setFileName(m_basedir+"/"+m_subdir+"/"+m_prefix+"Include.h");
+       if(!m_hdr.open(QIODevice::WriteOnly|QIODevice::Truncate)){
+               qDebug("Error: cannot create Qt header file %s.",m_hdr.fileName().toAscii().data());
+               emit errorFound();
+               return;
+       }
+       m_hdr.write(QByteArray(HDRSTART).replace("%",m_prefix.toAscii()+"INCLUDE_H"));
+       m_hdr.write(QByteArray("#include \""+m_prefix.toAscii()+"Interface.h\"\n"));
+       
 }
 
 WocQtClientOut::~WocQtClientOut(){}
 
 void WocQtClientOut::finalize()
 {
+       m_iface.write(QByteArray("};\n")+HDREND);
+       m_iface.close();
+       m_pri.write(QByteArray("\n#END OF AUTOGENERATED PRI FILE\n"));
        m_pri.close();
+       m_hdr.write(HDREND);
+       m_hdr.close();
 }
 
 void WocQtClientOut::newTable(const WocTable&){/*not needed, Qt client is a few levels higher*/}
 
-//start section of all header files
-static const QByteArray HDRSTART=
-       "//AUTOMATICALLY GENERATED FILE\n"
-       "#ifndef WOBGEN_%\n"
-       "#define WOBGEN_%\n\n";
-//end section of all header files
-static const QByteArray HDREND="\n//END OF FILE\n#endif\n";
-
-//start section of all source files
-static const QByteArray SRCSTART=
-       "//AUTOMATICALLY GENERATED FILE\n"
-       "#include \"%.h\"\n"
-       "#include <QDomElement>\n"
-       "#include <QDomNodeList>\n"
-       "#include <QDomDocument>\n";
-//end section of all source files
-static const QByteArray SRCEND="\n//END OF FILE\n";
-
 void WocQtClientOut::newClass(const WocClass&cls)
 {
-       QString cn="WO"+cls.name();
+       QString cn=m_prefix+"O"+cls.name();
        QString cna=cn;
        if(cls.isAbstract())cna+="Abstract";
        addFile(cna);
@@ -90,7 +126,7 @@ void WocQtClientOut::newClass(const WocClass&cls)
        QStringList k=cls.propertyNames();
        for(int i=0;i<k.size();i++)
                if(cls.propertyIsObject(k[i]))
-                       hcd+="#include \"WO"+cls.propertyPlainType(k[i])+".h\"\n";
+                       hcd+="#include \""+m_prefix+"O"+cls.propertyPlainType(k[i])+".h\"\n";
 
        //class declaration
        hcd+="class "+cna+":public "+cls.clientBaseClass()+"\n{\n";
@@ -188,7 +224,7 @@ QString WocQtClientOut::qttype(const WocClass&cls,QString p,bool dolist)
        else r="Nullable<";
        if(cls.propertyIsString(p))r+="QString";else
        if(cls.propertyIsInt(p))r+="qint64";else
-       if(cls.propertyIsObject(p))r+="WO"+cls.propertyPlainType(p);
+       if(cls.propertyIsObject(p))r+=m_prefix+"O"+cls.propertyPlainType(p);
        else r+=cls.propertyPlainType(p);
        r+=">";
        return r;
@@ -239,7 +275,7 @@ void WocQtClientOut::classDeserializer(const WocClass&cls,QFile&hdr,QFile&src,QS
                                scd+="\t\telse throw WDeserializerException(\"Class "+cn+" property "+k[i]+" is enum list, invalid value was found.\");\n";
                        }else
                        if(cls.propertyIsObject(k[i])){
-                               scd+="\t\tadd"+k[i]+"(WO"+cls.propertyPlainType(k[i])+"(el));\n";
+                               scd+="\t\tadd"+k[i]+"("+m_prefix+"O"+cls.propertyPlainType(k[i])+"(el));\n";
                        }else{
                                scd+="#error \"Internal Generator error.\"\n";
                                qDebug("Error: unable to generate code for property %s of type %s.",k[i].toAscii().data(),cls.propertyType(k[i]).toAscii().data());
@@ -281,7 +317,7 @@ void WocQtClientOut::classDeserializer(const WocClass&cls,QFile&hdr,QFile&src,QS
                                        scd+="\t\tset"+k[i]+"(nl.at(0).toElement().text());\n";
                                }else
                                if(cls.propertyIsObject(k[i])){
-                                       scd+="\t\tset"+k[i]+"(WO"+cls.propertyPlainType(k[i])+"(nl.at(0).toElement()));\n";
+                                       scd+="\t\tset"+k[i]+"("+m_prefix+"O"+cls.propertyPlainType(k[i])+"(nl.at(0).toElement()));\n";
                                }else{
                                        scd+="#error \"Internal Generator error.\"\n";
                                        qDebug("Error: unable to generate code for property %s of type %s.",k[i].toAscii().data(),cls.propertyType(k[i]).toAscii().data());
@@ -380,7 +416,7 @@ void WocQtClientOut::classSerializers(const WocClass&cls,QFile&hdr,QFile&src,QSt
 
 void WocQtClientOut::newTransaction(const WocTransaction&trn)
 {
-       QString cn="WT"+trn.name();
+       QString cn=m_prefix+"T"+trn.name();
        addFile(cn);
        QFile hdr(m_basedir+"/"+m_subdir+"/"+cn+".h");
        QFile src(m_basedir+"/"+m_subdir+"/"+cn+".cpp");
@@ -419,17 +455,30 @@ void WocQtClientOut::newTransaction(const WocTransaction&trn)
                inlist+="const "+qttype(trn,in[i],In)+"&a"+in[i];
                clist+="a"+in[i];
        }
+       if(inlist!="")inlist+=",";
+       inlist+="QString iface";
+       if(clist!="")clist+=",";
+       clist+="iface";
        for(int i=0;i<out.size();i++)
                hcd+="\t"+qttype(trn,out[i],Out)+"out_"+out[i]+";\n";
        hdr.write(hcd.toAscii());
                
        //create constructor
-       hcd="\t"+cn+"("+inlist+");\n";
-       scd+=cn+"::"+cn+"("+inlist+")\n{\n";
+       QString defparm="=\""+WocProcessor::instance()->projectName()+"\"";
+       hcd="\t"+cn+"("+inlist+defparm+");\n";
+       scd+=cn+"::"+cn+"("+inlist+")\n\t:WTransaction(iface)\n{\n";
        for(int i=0;i<in.size();i++){
                scd+="\tin_"+in[i]+"=a"+in[i]+";\n";
        }
-       scd+="}\n";
+       scd+="}\n\n";
+       hcd+="\t"+cn+"(const "+cn+"&);\n";
+       scd+=cn+"::"+cn+"(const "+cn+"&t)\n\t:WTransaction(t)\n{\n";
+       for(int i=0;i<in.size();i++){
+               scd+="\tin_"+in[i]+"=t.in_"+in[i]+";\n";
+       }
+       scd+="}\n\n";
+       
+       //query method
        hcd+="\tvoid netquery();\n";
        scd+="void "+cn+"::netquery()\n{\n";
        //TODO: encode input
@@ -445,8 +494,8 @@ void WocQtClientOut::newTransaction(const WocTransaction&trn)
        hcd="  public:\n";
        scd="";
        //TODO: query should optimize between local & web
-       hcd+="\tstatic "+cn+" query("+inlist+"){return queryWeb("+clist+");}\n";
-       hcd+="\tstatic "+cn+" queryWeb("+inlist+");\n";
+       hcd+="\tstatic "+cn+" query("+inlist+defparm+"){return queryWeb("+clist+");}\n";
+       hcd+="\tstatic "+cn+" queryWeb("+inlist+defparm+");\n";
        scd+=cn+" "+cn+"::queryWeb("+inlist+")\n{\n";
        scd+="\t"+cn;
        if(clist!="")scd+=" r("+clist+");\n";else scd+=" r;";
@@ -458,6 +507,8 @@ void WocQtClientOut::newTransaction(const WocTransaction&trn)
        hdr.write(QByteArray("\n};\n"));
        hdr.write(QByteArray(HDREND).replace("%",cn.toAscii()));
        src.write(QByteArray(SRCEND).replace("%",cn.toAscii()));
+       
+       //TODO:interface
 }
 
 QString WocQtClientOut::qttype(const WocTransaction&trn,QString v,InOut io)
@@ -470,7 +521,7 @@ QString WocQtClientOut::qttype(const WocTransaction&trn,QString v,InOut io)
        }else   r="Nullable<";
        if(tp=="astring" || tp=="string")r+="QString";else
        if(tp=="int")r+="qint64";
-       else r+="WO"+tp.split("/",QString::SkipEmptyParts).at(0);
+       else r+=m_prefix+"O"+tp.split("/",QString::SkipEmptyParts).at(0);
        r+=">";
        return r;
 }
@@ -481,11 +532,12 @@ QString WocQtClientOut::qtobjtype(const WocTransaction&trn,QString v,InOut io)
        if(tp.startsWith("List:"))
                tp=tp.mid(5);
        if(tp=="astring" || tp=="string"||tp=="int")return "";
-       else return "WO"+tp.split("/",QString::SkipEmptyParts).at(0);
+       else return m_prefix+"O"+tp.split("/",QString::SkipEmptyParts).at(0);
 }
 
 void WocQtClientOut::addFile(QString bn)
 {
        QString code="HEADERS+="+m_subdir+"/"+bn+".h\nSOURCES+="+m_subdir+"/"+bn+".cpp\n";
        m_pri.write(code.toAscii());
+       m_hdr.write(QByteArray("#include \"%.h\"\n").replace('%',bn.toAscii()));
 }
\ No newline at end of file
index 91c485e..f7e2932 100644 (file)
 
 #include <QFile>
 
+class QDomElement;
+
 class WocQtClientOut:public WocOutput
 {
        public:
-               WocQtClientOut(QString srcDir,QString subDir,QString prifile,bool clean);
+               WocQtClientOut(QDomElement&);
                ~WocQtClientOut();
        protected:
                virtual void finalize();
@@ -28,8 +30,8 @@ class WocQtClientOut:public WocOutput
                virtual void newTable(const WocTable&);
                virtual void newTransaction(const WocTransaction&);
        private:
-               QString m_basedir,m_subdir;
-               QFile m_pri;
+               QString m_basedir,m_subdir,m_prefix;
+               QFile m_pri,m_iface,m_hdr;
                
                /**helper: adds a file to the project file*/
                void addFile(QString basename);