--- /dev/null
+//
+// 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>();
+}
--- /dev/null
+//
+// 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
// 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();
+}
#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
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
-->
<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>
m_dbInst="dbInst";
m_dbSchema="dbSchema";
m_error=false;
+ m_projname="WobProject";
inst=this;
}
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")))
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"){
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*/
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;
#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){
}
//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);
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";
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;
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());
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());
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");
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
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;";
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)
}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;
}
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
#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();
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);