move woc
authorkonrad <konrad@6e3c4bff-ac9f-4ac1-96c5-d2ea494d3e33>
Fri, 15 Jan 2010 18:56:26 +0000 (18:56 +0000)
committerkonrad <konrad@6e3c4bff-ac9f-4ac1-96c5-d2ea494d3e33>
Fri, 15 Jan 2010 18:56:26 +0000 (18:56 +0000)
git-svn-id: https://silmor.de/svn/softmagic/pack/trunk@421 6e3c4bff-ac9f-4ac1-96c5-d2ea494d3e33

qtbase/WHelper.cpp [new file with mode: 0644]
qtbase/WHelper.h [new file with mode: 0644]
qtbase/WInterface.cpp [new file with mode: 0644]
qtbase/WInterface.h [new file with mode: 0644]
qtbase/WObject.cpp [new file with mode: 0644]
qtbase/WObject.h [new file with mode: 0644]
qtbase/WTransaction.cpp [new file with mode: 0644]
qtbase/WTransaction.h [new file with mode: 0644]
qtbase/exception.h [new file with mode: 0644]
qtbase/nullable.h [new file with mode: 0644]
qtbase/wbase.pri [new file with mode: 0644]

diff --git a/qtbase/WHelper.cpp b/qtbase/WHelper.cpp
new file mode 100644 (file)
index 0000000..84ec965
--- /dev/null
@@ -0,0 +1,29 @@
+//
+// C++ Implementation: WHelper
+//
+// Description: 
+//
+//
+// Author: Konrad Rosenbaum <konrad@silmor.de>, (C) 2010
+//
+// Copyright: See README/COPYING files that come with this distribution
+//
+//
+
+#include "WHelper.h"
+
+#include <QDomElement>
+#include <QDomNode>
+
+QList<QDomElement>WHelper::elementsByTagName(const QDomElement&root,QString tag)
+{
+       QDomNodeList cn=root.childNodes();
+       QList<QDomElement>ret;
+       for(int i=0;i<cn.size();i++){
+               QDomElement e=cn.at(i).toElement();
+               if(e.isNull())continue;
+               if(e.tagName()!=tag)continue;
+               ret<<e;
+       }
+       return ret;
+}
diff --git a/qtbase/WHelper.h b/qtbase/WHelper.h
new file mode 100644 (file)
index 0000000..f9e0f22
--- /dev/null
@@ -0,0 +1,29 @@
+//
+// C++ Interface: WHelper
+//
+// Description: 
+//
+//
+// Author: Konrad Rosenbaum <konrad@silmor.de>, (C) 2010
+//
+// Copyright: See README/COPYING files that come with this distribution
+//
+//
+
+#ifndef WOLF_HELPER_H
+#define WOLF_HELPER_H
+
+#include <QList>
+#include <QObject>
+
+class QDomElement;
+class QDomNode;
+
+class WHelper:public QObject
+{
+       protected:
+               /**helper for de-serializers: returns direct child elements with given tag name (necessary because QDomElement::elementsByTagName traverses all children)*/
+               static QList<QDomElement>elementsByTagName(const QDomElement&,QString);
+};
+
+#endif
diff --git a/qtbase/WInterface.cpp b/qtbase/WInterface.cpp
new file mode 100644 (file)
index 0000000..aee9cf8
--- /dev/null
@@ -0,0 +1,64 @@
+//
+// 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 <QHttp>
+#include <QMutex>
+#include <QMutexLocker>
+
+QMap<QString,WInterface*> WInterface::inst;
+
+static QMutex mtx(QMutex::Recursive);
+
+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;
+       loglvl=LogOnError;
+       QMutexLocker ml(&mtx);
+       if(inst.contains(name)){
+               delete inst[name];
+       }
+       inst.insert(name,this);
+}
+
+QString WInterface::name()const
+{
+       QMutexLocker ml(&mtx);
+       return inst.key((WInterface*)this);
+}
+
+WInterface::~WInterface()
+{
+       QMutexLocker ml(&mtx);
+       inst.remove(inst.key((WInterface*)this));
+}
+
+QMap<QString,QString> WInterface::headers(QString)const
+{
+       return QMap<QString,QString>();
+}
+
+void WInterface::sslErrors(const QList<QSslError>&)
+{
+       QHttp*src=qobject_cast<QHttp*>(sender());
+       if(!src)return;
+       src->ignoreSslErrors();
+}
diff --git a/qtbase/WInterface.h b/qtbase/WInterface.h
new file mode 100644 (file)
index 0000000..3cac7c4
--- /dev/null
@@ -0,0 +1,101 @@
+//
+// 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>
+#include <QSslError>
+
+class WInterface:public QObject
+{
+       Q_OBJECT
+       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;}
+               
+               /**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!="";}
+               /**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;}
+               
+               /**get the name for this interface (returns empty string if not registered*/
+               QString name()const;
+               
+               /**returns the instance registered under that name*/
+               static WInterface*instance(QString);
+               
+               /**log settings*/
+               enum LogLevel {
+                       /**no logging*/
+                       LogNone=0,
+                       /**minimal logging*/
+                       LogMinimal=1,
+                       /**informational logging (more than minimal, not much yet)*/
+                       LogInfo=2,
+                       /**like LogInfo, but logs additional details on error*/
+                       LogOnError=0x12,
+                       /**always log details*/
+                       LogDetailed=0xff
+               };
+               
+               /**returns the current log level*/
+               LogLevel logLevel()const{return loglvl;}
+               
+       public slots:
+               /**set log level*/
+               void setLogLevel(WInterface::LogLevel l){loglvl=l;}
+               
+               /**set timeout for page loads in seconds*/
+               void setWebTimeout(int t){if(t>0)m_wtimeout=t;}
+               
+               /**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;}
+       
+               /**sets the URL of the interface*/
+               void setUrl(QUrl u){m_url=u;}
+               
+               /**handles SSL errors, per default ignores them, overwrite it if you need more sophisticated behavior*/
+               virtual void sslErrors(const QList<QSslError>&);
+               
+       private:
+               static QMap<QString,WInterface*>inst;
+               QUrl m_url;
+               QString m_proxyhost,m_proxyuser,m_proxypass;
+               unsigned short m_proxyport;
+               int m_wtimeout;
+               LogLevel loglvl;
+};
+
+#endif
diff --git a/qtbase/WObject.cpp b/qtbase/WObject.cpp
new file mode 100644 (file)
index 0000000..85ad4d2
--- /dev/null
@@ -0,0 +1,13 @@
+//
+// C++ Implementation: wobject
+//
+// Description: 
+//
+//
+// Author: Konrad Rosenbaum <konrad@silmor.de>, (C) 2009
+//
+// Copyright: See README/COPYING files that come with this distribution
+//
+//
+
+#include "WObject.h"
\ No newline at end of file
diff --git a/qtbase/WObject.h b/qtbase/WObject.h
new file mode 100644 (file)
index 0000000..1da59ad
--- /dev/null
@@ -0,0 +1,50 @@
+//
+// C++ Interface: wobject
+//
+// Description: 
+//
+//
+// Author: Konrad Rosenbaum <konrad@silmor.de>, (C) 2009
+//
+// Copyright: See README/COPYING files that come with this distribution
+//
+//
+
+#ifndef WOLF_WOBJECT_H
+#define WOLF_WOBJECT_H
+
+#include <QObject>
+#include <QList>
+
+#include "nullable.h"
+#include "exception.h"
+#include "WHelper.h"
+
+class QDomElement;
+class QDomDocument;
+
+/**base class of all web based objects*/
+class WObject:public WHelper
+{
+       protected:
+               WObject(){}
+};
+
+/**this exception is thrown if the deserialization of an object fails on the XML parser level*/
+class WDeserializerException:public WException
+{
+       public:
+               WDeserializerException(QString e):WException(e,"Deserializer"){}
+};
+
+/**the WOBJECT macro defines the necessary constructors if you just want to extend an abstract class without overwriting the constructors yourself*/
+#define WOBJECT(wob) public: \
+ wob():wob ## Abstract(){} \
+ wob(const wob&w):wob ## Abstract(w){} \
+ wob(const wob ## Abstract&w):wob ## Abstract(w){} \
+ wob(const QDomElement&w):wob ## Abstract(w){} \
+ wob& operator=(const wob&w){wob ## Abstract::operator=(w);return *this;} \
+ wob& operator=(const wob ## Abstract&w){wob ## Abstract::operator=(w);return *this;} \
+ private:
+
+#endif
diff --git a/qtbase/WTransaction.cpp b/qtbase/WTransaction.cpp
new file mode 100644 (file)
index 0000000..3023f24
--- /dev/null
@@ -0,0 +1,253 @@
+//
+// C++ Implementation: wtransaction
+//
+// Description: 
+//
+//
+// Author: Konrad Rosenbaum <konrad@silmor.de>, (C) 2009
+//
+// Copyright: See README/COPYING files that come with this distribution
+//
+//
+
+#include "WTransaction.h"
+#include "WInterface.h"
+
+#include "waitcursor.h"
+
+#include <QCoreApplication>
+#include <QDebug>
+#include <QEventLoop>
+#include <QHttp>
+#include <QTimer>
+#include <QUrl>
+
+WTransaction::WTransaction(QString ifc)
+{
+       m_stage=Uninitialized;
+       m_httpid=-1;
+       m_iface=ifc;
+       m_log=0;
+}
+WTransaction::WTransaction(const WTransaction&t)
+       :WHelper()
+{
+       m_stage=t.m_stage;
+       m_errstr=t.m_errstr;
+       m_errtype=t.m_errtype;
+       m_iface=t.m_iface;
+       m_httpid=-1;
+       m_log=0;
+}
+
+WTransaction& WTransaction::operator=(const WTransaction&t)
+{
+       m_stage=t.m_stage;
+       m_errstr=t.m_errstr;
+       m_errtype=t.m_errtype;
+       m_iface=t.m_iface;
+       m_httpid=-1;
+       return *this;
+}
+
+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
+       QEventLoop loop(this);
+       connect(this,SIGNAL(webFinished()),&loop,SLOT(quit()));
+       WInterface *iface=WInterface::instance(m_iface);
+       if(!iface){
+               if(m_log)m_log->setError("cannot find interface.");
+               else qDebug("Error: transaction cannot find interface.");
+               m_stage=Error;
+               m_errtype="_iface";
+               m_errstr=tr("interface not found");
+               return QByteArray();
+       }
+       connect(&req,SIGNAL(sslErrors(const QList<QSslError>&)),iface,SLOT(sslErrors(const QList<QSslError>&)));
+       QUrl url=iface->url();
+       int port=url.port();
+       if(port<=0){
+               if(url.scheme().toLower()=="http")port=80;
+               else port=443;
+       }
+       if(m_log)m_log->setInfo(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);
+       QMap<QString,QString>hdrs=iface->headers(hreq);
+       QStringList hdrn=hdrs.keys();
+       for(int i=0;i<hdrn.size();i++)
+               hrh.setValue("X-"+hdrn[i],hdrs[hdrn[i]]);
+       hrh.setValue("X-WobRequest",hreq);
+       hrh.setContentLength(data.size());
+       hrh.setContentType("application/x-webobject; charset=UTF-8");
+       m_httpid=req.request(hrh,data);
+       if(m_log){
+               m_log->setRequ(hrh.toString(),esc(data),m_httpid);
+               m_log->setInfo(QString("HTTP ID %1").arg(m_httpid));
+       }
+       
+       /////////////////////////////////////////////////////////////////////
+       //start loop
+       QTimer tmr;
+       tmr.setSingleShot(true);tmr.start(iface->webTimeout()*1000);
+       connect(&tmr,SIGNAL(timeout()),this,SLOT(webTimeout()));
+       loop.exec();
+       tmr.stop();tmr.disconnect(SIGNAL(timeout()),this,SLOT(webTimeout()));
+       /////////////////////////////////////////////////////////////////////
+       
+       //process result
+       if(m_stage==Error && m_errtype=="_timeout"){
+               //it did not finish yet, caught a timeout.
+               req.abort();
+               m_errstr=tr("Web Request timed out.");
+               if(m_log)m_log->setError(QString("Request %1 timed out.").arg(m_httpid));
+               return QByteArray();
+       }else
+       //finished with low-level error?
+       if(m_stage==Error){
+               m_errstr="HTTP Error: "+req.errorString();
+               if(m_log)m_log->setError(QString("Request %2 finished with HTTP level error: %1").arg(m_errstr).arg(m_httpid));
+               return QByteArray();
+       }
+       //get data
+       QHttpResponseHeader rsph=req.lastResponse();
+       m_wobstatus=rsph.value("X-WobResponse-Status");
+       m_wobstatus=m_wobstatus.replace("\"","").trimmed().toLower();
+       QByteArray rspdata=req.readAll();
+       if(m_log)m_log->setResp(rsph.toString(),esc(rspdata),m_httpid);
+       //check for high level error
+       if(rsph.statusCode()!=200){
+               m_errstr=tr("HTTP Error, return code %1 %2") .arg(rsph.statusCode()).arg(rsph.reasonPhrase());
+               m_errtype="_HTTP";
+               m_stage=Error;
+               if(m_log)m_log->setError(QString("Request %2 finished with HTTP level error: %1").arg(m_errstr).arg(m_httpid));
+               return QByteArray();
+       }
+       if(m_stage!=Error)m_stage=Success;
+       //remaining high level errors are handled by the generated code
+       return rspdata;
+}
+
+void WTransaction::webTimeout()
+{
+       if(m_httpid<0)return;
+//     qDebug("web timeout");
+       m_stage=Error;
+       m_errtype="_timeout";
+       emit webFinished();
+}
+
+void WTransaction::webReady(int i,bool e)
+{
+       if(i!=m_httpid)return;
+       if(m_log)m_log->setInfo(QString("finished request %1").arg(i));
+       if(e){
+               m_stage=Error;
+               m_errtype="_web";
+       }
+       emit webFinished();
+}
+
+QString WTransaction::errorString()const
+{
+       return QCoreApplication::translate("php::",m_errstr.toUtf8(),0,QCoreApplication::UnicodeUTF8);
+}
+
+
+WTransaction::WTLog::WTLog(WTransaction*p,const QString&s)
+{
+       parent=p;
+       parent->m_log=this;
+       trn=s;
+       WInterface*in=WInterface::instance(p->m_iface);
+       if(in)lvl=in->logLevel();
+       else lvl=WInterface::LogOnError;
+       if(lvl>WInterface::LogNone)
+               qDebug("Running transaction %s",s.toAscii().data());
+}
+
+WTransaction::WTLog::~WTLog()
+{
+       parent->m_log=0;
+}
+
+void WTransaction::WTLog::setRequ(const QString&h,const QString&d,int i)
+{
+       if(lvl<=WInterface::LogInfo)return;
+       QByteArray r="RequestID="+QString::number(i).toAscii()
+        +"\n--Header--\n"+h.trimmed().toAscii()
+        +"\n--Body--\n"+d.trimmed().toAscii()+"\n--End--";
+       if(lvl==WInterface::LogDetailed)
+               qDebug("Transaction %s request: %s",trn.toAscii().data(),r.data());
+       else
+       if(lvl==WInterface::LogOnError)
+               req=r;
+}
+
+void WTransaction::WTLog::setResp(const QString&h,const QString&d,int i)
+{
+       if(lvl<=WInterface::LogInfo)return;
+       QByteArray r="RequestID="+QString::number(i).toAscii()
+        +"\n--Header--\n"+h.trimmed().toAscii()
+        +"\n--Body--\n"+d.trimmed().toAscii()+"\n--End--";
+       if(lvl==WInterface::LogDetailed)
+               qDebug("Transaction %s response: %s",trn.toAscii().data(),r.data());
+       else
+       if(lvl==WInterface::LogOnError)
+               rsp=r;
+}
+
+void WTransaction::WTLog::setInfo(const QString&s)
+{
+       if(lvl>=WInterface::LogInfo)
+               qDebug("Transaction %s info: %s",trn.toAscii().data(),s.toAscii().data());
+}
+
+void WTransaction::WTLog::setError(const QString&s)
+{
+       //bail out if no logging
+       if(lvl<WInterface::LogMinimal)return;
+       //only for LogOnError, these have been stored, replay them:
+       if(req.size()>0){
+               qDebug("Transaction %s on error, request was: %s",trn.toAscii().data(),req.data());
+               req=QByteArray();
+       }
+       if(rsp.size()>0){
+               qDebug("Transaction %s on error, response was: %s",trn.toAscii().data(),rsp.data());
+               rsp=QByteArray();
+       }
+       //show actual error
+       qDebug("Transaction %s Error: %s",trn.toAscii().data(),s.toAscii().data());
+}
\ No newline at end of file
diff --git a/qtbase/WTransaction.h b/qtbase/WTransaction.h
new file mode 100644 (file)
index 0000000..907ae7c
--- /dev/null
@@ -0,0 +1,90 @@
+//
+// C++ Interface: wtransaction
+//
+// Description: 
+//
+//
+// Author: Konrad Rosenbaum <konrad@silmor.de>, (C) 2009
+//
+// Copyright: See README/COPYING files that come with this distribution
+//
+//
+
+#ifndef WOLF_TRANSACTION_H
+#define WOLF_TRANSACTION_H
+
+#include <QObject>
+#include <QList>
+#include <QString>
+
+#include "nullable.h"
+#include "WHelper.h"
+
+/**base class of all transactions*/
+class WTransaction:public WHelper
+{
+       Q_OBJECT
+       public:
+               /**stage the transaction is in*/
+               enum Stage {
+                       Uninitialized,///<transaction has not started yet
+                       Success,///<transaction ended successfully
+                       Error///<transaction ended with an error
+               };
+               
+               /**returns the stage the transaction is in*/
+               Stage stage()const{return m_stage;}
+               
+               /**returns whether the transaction had an error while executing*/
+               bool hasError()const{return m_stage==Error;}
+               /**returns the error type (usually the component causing it)*/
+               QString errorType()const{return m_errtype;}
+               /**returns the (translated) human readable error string*/
+               QString errorString()const;
+               
+               /**returns the interface that is used for the transaction*/
+               QString interface()const{return m_iface;}
+       protected:
+               /**internal: construct the transaction*/
+               WTransaction(QString iface=QString());
+               /**internal: copy the transaction*/
+               WTransaction(const WTransaction&);
+               
+               /**internal: copy the transaction*/
+               WTransaction& operator=(const WTransaction&);
+               
+               /**internal: execute a query on the web, used by subclasses*/
+               QByteArray executeQuery(QString,QByteArray);
+               
+               /**internal logger class*/
+               class WTLog{
+                       public:
+                               WTLog(WTransaction*,const QString&);
+                               ~WTLog();
+                               void setRequ(const QString&,const QString&,int);
+                               void setResp(const QString&,const QString&,int);
+                               void setError(const QString&);
+                               void setInfo(const QString&);
+                       private:
+                               QByteArray req,rsp;
+                               QString trn;
+                               WTransaction*parent;
+                               int lvl;
+               };
+       private slots:
+               /**internal: triggers when the transaction times out*/
+               void webTimeout();
+               /**internal: triggers when the response data is available*/
+               void webReady(int,bool);
+       signals:
+               /**this signal is raised when the transaction finished executing*/
+               void webFinished();
+       protected:
+               friend class WTransaction::WTLog;
+               Stage m_stage;
+               QString m_errtype,m_errstr,m_iface,m_wobstatus;
+               int m_httpid;
+               WTLog*m_log;
+};
+
+#endif
diff --git a/qtbase/exception.h b/qtbase/exception.h
new file mode 100644 (file)
index 0000000..1dff0ea
--- /dev/null
@@ -0,0 +1,29 @@
+//
+// C++ Interface: exception
+//
+// Description: 
+//
+//
+// Author: Konrad Rosenbaum <konrad@silmor.de>, (C) 2009
+//
+// Copyright: See README/COPYING files that come with this distribution
+//
+//
+
+#ifndef WOLF_EXCEPTION_H
+#define WOLF_EXCEPTION_H
+
+#include <QString>
+
+class WException
+{
+       protected:
+               WException(QString e,QString c){err=e;comp=c;}
+       public:
+               QString error()const{return err;}
+               QString component()const{return comp;}
+       private:
+               QString err,comp;
+};
+
+#endif
diff --git a/qtbase/nullable.h b/qtbase/nullable.h
new file mode 100644 (file)
index 0000000..1557cca
--- /dev/null
@@ -0,0 +1,57 @@
+//
+// C++ Interface: nullable
+//
+// Description: 
+//
+//
+// Author: Konrad Rosenbaum <konrad@silmor.de>, (C) 2009
+//
+// Copyright: See README/COPYING files that come with this distribution
+//
+//
+
+
+#ifndef WOLF_NULLABLE_H
+#define WOLF_NULLABLE_H
+
+template<class T>class Nullable
+{
+       public:
+               Nullable(){isnull=true;elem=T();}
+               Nullable(const T&t){isnull=false;elem=t;}
+               Nullable(const Nullable<T>&t){isnull=t.isnull;elem=t.elem;}
+               
+               Nullable<T>& operator=(const T&t){isnull=false;elem=t;return *this;}
+               Nullable<T>& operator=(const Nullable<T>&t){isnull=t.isnull;elem=t.elem;return *this;}
+               
+               bool isNull()const{return isnull;}
+               
+               operator T()const{if(isnull)return T();else return elem;}
+               
+               T& value(){return elem;}
+               T value()const{if(isnull)return T();else return elem;}
+               
+               bool operator==(const T&t){if(isnull)return false;else return elem == t;}
+               bool operator!=(const T&t){if(isnull)return true;else return elem != t;}
+
+               bool operator==(const Nullable<T>&t){
+                       if(isnull != t.isnull)return false;
+                       if(isnull)return true;
+                       else return elem == t.elem;}
+               bool operator!=(const Nullable<T>&t){
+                       if(isnull != t.isnull)return true;
+                       if(isnull)return false;
+                       else return elem != t.elem;}
+       private:
+               bool isnull;
+               T elem;
+};
+
+typedef Nullable<int> Int;
+typedef Nullable<qint32> Int32;
+typedef Nullable<qint64> Int64;
+typedef Nullable<quint32> UInt32;
+typedef Nullable<quint64> UInt64;
+typedef Nullable<QString> NString;
+
+#endif
diff --git a/qtbase/wbase.pri b/qtbase/wbase.pri
new file mode 100644 (file)
index 0000000..656be41
--- /dev/null
@@ -0,0 +1,14 @@
+HEADERS += \
+       wbase/nullable.h \
+       wbase/WHelper.h \
+       wbase/WObject.h \
+       wbase/WTransaction.h \
+       wbase/WInterface.h
+
+SOURCES += \
+       wbase/WObject.cpp \
+       wbase/WHelper.cpp \
+       wbase/WTransaction.cpp \
+       wbase/WInterface.cpp
+
+INCLUDEPATH += ./wbase ./wob
\ No newline at end of file