summaryrefslogtreecommitdiff
path: root/test-client-catchcopy
diff options
context:
space:
mode:
Diffstat (limited to 'test-client-catchcopy')
-rw-r--r--test-client-catchcopy/catchcopy-api-0002/ClientCatchcopy.cpp380
-rw-r--r--test-client-catchcopy/catchcopy-api-0002/ClientCatchcopy.h114
-rw-r--r--test-client-catchcopy/catchcopy-api-0002/ExtraSocketCatchcopy.cpp31
-rw-r--r--test-client-catchcopy/catchcopy-api-0002/ExtraSocketCatchcopy.h27
-rw-r--r--test-client-catchcopy/catchcopy-api-0002/ServerCatchcopy.cpp725
-rw-r--r--test-client-catchcopy/catchcopy-api-0002/ServerCatchcopy.h162
-rw-r--r--test-client-catchcopy/catchcopy-api-0002/VariablesCatchcopy.h14
-rwxr-xr-xtest-client-catchcopy/catchcopy-api-0002/documentation.dox31
-rw-r--r--test-client-catchcopy/icon.icobin0 -> 101758 bytes
-rw-r--r--test-client-catchcopy/images/dialog-ok-apply.pngbin0 -> 1977 bytes
-rwxr-xr-xtest-client-catchcopy/images/download.pngbin0 -> 3284 bytes
-rw-r--r--test-client-catchcopy/images/main.pngbin0 -> 621 bytes
-rw-r--r--test-client-catchcopy/images/process-stop.pngbin0 -> 2780 bytes
-rw-r--r--test-client-catchcopy/images/tools-report-bug.pngbin0 -> 3329 bytes
-rwxr-xr-xtest-client-catchcopy/images/upload.pngbin0 -> 3193 bytes
-rw-r--r--test-client-catchcopy/main.cpp10
-rw-r--r--test-client-catchcopy/mainwindow.cpp305
-rw-r--r--test-client-catchcopy/mainwindow.h68
-rw-r--r--test-client-catchcopy/mainwindow.ui441
-rwxr-xr-xtest-client-catchcopy/resources-windows.rc2
-rw-r--r--test-client-catchcopy/resources.qrc10
-rw-r--r--test-client-catchcopy/test-client-catchcopy.pro24
22 files changed, 2344 insertions, 0 deletions
diff --git a/test-client-catchcopy/catchcopy-api-0002/ClientCatchcopy.cpp b/test-client-catchcopy/catchcopy-api-0002/ClientCatchcopy.cpp
new file mode 100644
index 0000000..0ac9d04
--- /dev/null
+++ b/test-client-catchcopy/catchcopy-api-0002/ClientCatchcopy.cpp
@@ -0,0 +1,380 @@
+/** \file ClientCatchcopy.cpp
+\brief Define the catchcopy client
+\author alpha_one_x86
+\version 0002
+\date 2010 */
+
+#include "ClientCatchcopy.h"
+#include "VariablesCatchcopy.h"
+#include "ExtraSocketCatchcopy.h"
+#include <QDataStream>
+
+ClientCatchcopy::ClientCatchcopy()
+{
+ disconnectedFromSocket();
+ error_string="Unknown error";
+ detectTimeOut.setSingleShot(true);
+ detectTimeOut.setInterval(CATCHCOPY_COMMUNICATION_TIMEOUT); // the max time to without send packet
+ connect(&socket, SIGNAL(connected()), this, SIGNAL(connected()));
+ connect(&socket, SIGNAL(disconnected()), this, SIGNAL(disconnected()));
+ connect(&socket, SIGNAL(disconnected()), this, SLOT(disconnectedFromSocket()));
+ connect(&socket, SIGNAL(stateChanged(QLocalSocket::LocalSocketState)), this, SIGNAL(stateChanged(QLocalSocket::LocalSocketState)));
+ connect(&socket, SIGNAL(error(QLocalSocket::LocalSocketError)), this, SIGNAL(errorSocket(QLocalSocket::LocalSocketError)));
+ connect(&socket, SIGNAL(readyRead()), this, SLOT(readyRead()));
+ connect(&detectTimeOut, SIGNAL(timeout()), this, SLOT(checkTimeOut()));
+ connect(&socket, SIGNAL(connected()), this, SLOT(socketIsConnected()));
+}
+
+void ClientCatchcopy::checkTimeOut()
+{
+ if(haveData)
+ {
+ error_string="The server is too long to send the next part of the reply";
+ emit error(error_string);
+ disconnectFromServer();
+ }
+}
+
+const QString ClientCatchcopy::errorString()
+{
+ return error_string;
+}
+
+void ClientCatchcopy::socketIsConnected()
+{
+ orderIdFirstSendProtocol=sendProtocol();
+}
+
+void ClientCatchcopy::connectToServer()
+{
+ socket.connectToServer(ExtraSocketCatchcopy::pathSocket());
+}
+
+void ClientCatchcopy::disconnectFromServer()
+{
+ socket.abort();
+ socket.disconnectFromServer();
+}
+
+const QString ClientCatchcopy::errorStringSocket()
+{
+ return socket.errorString();
+}
+
+/// \brief to send stream of string list
+quint32 ClientCatchcopy::sendRawOrderList(const QStringList & order)
+{
+ if(!socket.isValid())
+ {
+ error_string="Socket is not valid, try send: "+order.join(";");
+ emit error(error_string);
+ return -1;
+ }
+ if(socket.state()!=QLocalSocket::ConnectedState)
+ {
+ error_string="Socket is not connected "+QString::number(socket.state());
+ emit error(error_string);
+ return -1;
+ }
+ do
+ {
+ idNextOrder++;
+ if(idNextOrder>2000000000)
+ idNextOrder=0;
+ } while(notRepliedQuery.contains(idNextOrder));
+ notRepliedQuery << idNextOrder;
+ QByteArray block;
+ QDataStream out(&block, QIODevice::WriteOnly);
+ out.setVersion(QDataStream::Qt_4_4);
+ out << int(0);
+ out << idNextOrder;
+ out << order;
+ out.device()->seek(0);
+ out << block.size();
+ if(idNextOrder!=1) // drop if internal protocol send
+ {
+ emit dataSend(idNextOrder,block);
+ emit dataSend(idNextOrder,order);
+ }
+ do //cut string list and send it as block of 32KB
+ {
+ QByteArray blockToSend;
+ int byteWriten;
+ blockToSend=block.left(32*1024);//32KB
+ block.remove(0,blockToSend.size());
+ byteWriten = socket.write(blockToSend);
+ if(!socket.isValid())
+ {
+ error_string="Socket is not valid";
+ emit error(error_string);
+ return -1;
+ }
+ if(socket.errorString()!="Unknown error" && socket.errorString()!="")
+ {
+ error_string=socket.errorString();
+ emit error(error_string);
+ return -1;
+ }
+ if(blockToSend.size()!=byteWriten)
+ {
+ error_string="All the bytes have not be written";
+ emit error(error_string);
+ return -1;
+ }
+ }
+ while(block.size());
+ return idNextOrder;
+}
+
+void ClientCatchcopy::readyRead()
+{
+ while(socket.bytesAvailable()>0)
+ {
+ if(!haveData)
+ {
+ if(socket.bytesAvailable()<(int)sizeof(int))//int of size cuted
+ {
+ /* error_string="Bytes available is not sufficient to do a int";
+ emit error(error_string);
+ disconnectFromServer();*/
+ return;
+ }
+ QDataStream in(&socket);
+ in.setVersion(QDataStream::Qt_4_4);
+ in >> dataSize;
+ dataSize-=sizeof(int);
+ if(dataSize>64*1024*1024) // 64MB
+ {
+ error_string="Reply size is >64MB, seam corrupted";
+ emit error(error_string);
+ disconnectFromServer();
+ return;
+ }
+ if(dataSize<(int)(sizeof(int) //orderId
+ + sizeof(quint32) //returnCode
+ + sizeof(quint32) //string list size
+ ))
+ {
+ error_string="Reply size is too small to have correct code";
+ emit error(error_string);
+ disconnectFromServer();
+ return;
+ }
+ }
+ if(dataSize<(data.size()+socket.bytesAvailable()))
+ data.append(socket.read(dataSize-data.size()));
+ else
+ data.append(socket.readAll());
+ if(dataSize==data.size())
+ {
+ if(!checkDataIntegrity(data))
+ {
+ data.clear();
+ qWarning() << "Data of the reply is wrong";
+ return;
+ }
+ QStringList returnList;
+ quint32 orderId;
+ quint32 returnCode;
+ QDataStream in(data);
+ in.setVersion(QDataStream::Qt_4_4);
+ in >> orderId;
+ in >> returnCode;
+ in >> returnList;
+ data.clear();
+ if(orderId!=orderIdFirstSendProtocol)
+ {
+ if(!notRepliedQuery.contains(orderId))
+ qWarning() << "Unknown query not replied:" << orderId;
+ else
+ {
+ if(!parseReply(orderId,returnCode,returnList))
+ emit unknowReply(orderId);
+ emit newReply(orderId,returnCode,returnList);
+ }
+ }
+ else
+ {
+ if(!sendProtocolReplied)
+ {
+ sendProtocolReplied=true;
+ if(returnCode!=1000)
+ {
+ error_string="Protocol not supported";
+ emit error(error_string);
+ disconnectFromServer();
+ return;
+ }
+ }
+ else
+ {
+ error_string=QString("First send protocol send with the query id %1 have been already previously replied").arg(orderIdFirstSendProtocol);
+ emit error(error_string);
+ disconnectFromServer();
+ return;
+ }
+ }
+ }
+ }
+ if(haveData)
+ detectTimeOut.start();
+ else
+ detectTimeOut.stop();
+}
+
+bool ClientCatchcopy::checkDataIntegrity(QByteArray data)
+{
+ quint32 orderId;
+ qint32 replyCode;
+ qint32 listSize;
+ QDataStream in(data);
+ in.setVersion(QDataStream::Qt_4_4);
+ in >> orderId;
+ in >> replyCode;
+ in >> listSize;
+ if(listSize>65535)
+ {
+ emit error("List size is wrong");
+ qWarning() << "List size is wrong";
+ return false;
+ }
+ int index=0;
+ while(index<listSize)
+ {
+ qint32 stringSize;
+ in >> stringSize;
+ if(stringSize>65535)
+ {
+ emit error("String size is wrong");
+ qWarning() << "String size is wrong";
+ return false;
+ }
+ if(stringSize>(in.device()->size()-in.device()->pos()))
+ {
+ emit error(QString("String size is greater than the data: %1>(%2-%3)").arg(stringSize).arg(in.device()->size()).arg(in.device()->pos()));
+ qWarning() << QString("String size is greater than the data: %1>(%2-%3)").arg(stringSize).arg(in.device()->size()).arg(in.device()->pos());
+ return false;
+ }
+ in.device()->seek(in.device()->pos()+stringSize);
+ index++;
+ }
+ if(in.device()->size()!=in.device()->pos())
+ {
+ emit error("Remaining data after string list parsing");
+ qWarning() << "Remaining data after string list parsing";
+ return false;
+ }
+ return true;
+}
+
+QLocalSocket::LocalSocketState ClientCatchcopy::state()
+{
+ return socket.state();
+}
+
+void ClientCatchcopy::disconnectedFromSocket()
+{
+ haveData = false;
+ orderIdFirstSendProtocol= 0;
+ idNextOrder = 0;
+ sendProtocolReplied = false;
+ notRepliedQuery.clear();
+}
+
+/// \brief to send the protocol version used
+quint32 ClientCatchcopy::sendProtocol()
+{
+ return sendRawOrderList(QStringList() << "protocol" << CATCHCOPY_PROTOCOL_VERSION);
+}
+
+quint32 ClientCatchcopy::askServerName()
+{
+ return sendRawOrderList(QStringList() << "server" << "name?");
+}
+
+quint32 ClientCatchcopy::setClientName(const QString & name)
+{
+ return sendRawOrderList(QStringList() << "client" << name);
+}
+
+quint32 ClientCatchcopy::checkProtocolExtension(const QString & name)
+{
+ return sendRawOrderList(QStringList() << "protocol extension" << name);
+}
+
+quint32 ClientCatchcopy::checkProtocolExtension(const QString & name,const QString & version)
+{
+ return sendRawOrderList(QStringList() << "protocol extension" << name << version);
+}
+
+quint32 ClientCatchcopy::addCopyWithDestination(const QStringList & sources,const QString & destination)
+{
+ return sendRawOrderList(QStringList() << "cp" << sources << destination);
+}
+
+quint32 ClientCatchcopy::addCopyWithoutDestination(const QStringList & sources)
+{
+ return sendRawOrderList(QStringList() << "cp-?" << sources);
+}
+
+quint32 ClientCatchcopy::addMoveWithDestination(const QStringList & sources,const QString & destination)
+{
+ return sendRawOrderList(QStringList() << "mv" << sources << destination);
+}
+
+quint32 ClientCatchcopy::addMoveWithoutDestination(const QStringList & sources)
+{
+ return sendRawOrderList(QStringList() << "mv-?" << sources);
+}
+
+bool ClientCatchcopy::parseReply(quint32 orderId,quint32 returnCode,QStringList returnList)
+{
+ switch(returnCode)
+ {
+ case 1000:
+ emit protocolSupported(orderId);
+ break;
+ case 1001:
+ case 1002:
+ if(returnCode==1001)
+ emit protocolExtensionSupported(orderId,true);
+ else
+ emit protocolExtensionSupported(orderId,false);
+ break;
+ case 1003:
+ emit clientRegistered(orderId);
+ break;
+ case 1004:
+ if(returnList.size()!=1)
+ emit unknowOrder(orderId);
+ else
+ emit serverName(orderId,returnList.last());
+ break;
+ case 1005:
+ case 1006:
+ if(returnCode==1005)
+ emit copyFinished(orderId,false);
+ else
+ emit copyFinished(orderId,true);
+ break;
+ case 1007:
+ emit copyCanceled(orderId);
+ break;
+ case 5000:
+ emit incorrectArgumentListSize(orderId);
+ break;
+ case 5001:
+ emit incorrectArgument(orderId);
+ break;
+ case 5002:
+ emit unknowOrder(orderId); //the server have not understand the order
+ break;
+ case 5003:
+ emit protocolNotSupported(orderId);
+ break;
+ default:
+ return false;
+ }
+ return true;
+}
+
diff --git a/test-client-catchcopy/catchcopy-api-0002/ClientCatchcopy.h b/test-client-catchcopy/catchcopy-api-0002/ClientCatchcopy.h
new file mode 100644
index 0000000..278b0cd
--- /dev/null
+++ b/test-client-catchcopy/catchcopy-api-0002/ClientCatchcopy.h
@@ -0,0 +1,114 @@
+/** \file ClientCatchcopy.h
+\brief Define the catchcopy client
+\author alpha_one_x86
+\version 0002
+\date 2010 */
+
+#ifndef CLIENTCATCHCOPY_H
+#define CLIENTCATCHCOPY_H
+
+#include <QObject>
+#include <QLocalSocket>
+#include <QStringList>
+#include <QString>
+#include <QByteArray>
+#include <QTimer>
+
+/// \brief Define the catchcopy client
+class ClientCatchcopy : public QObject
+{
+ Q_OBJECT
+ public:
+ ClientCatchcopy();
+ /// \brief get the socket stat
+ QLocalSocket::LocalSocketState state();
+ /// \brief error string about the socket
+ const QString errorStringSocket();
+ /// \brief general error string
+ const QString errorString();
+ public slots:
+ void connectToServer();
+ void disconnectFromServer();
+ //to test and internal use
+ /// \brief to send order
+ quint32 sendProtocol();
+ /// \brief ask the server name
+ quint32 askServerName();
+ /// \brief set the client name
+ quint32 setClientName(const QString & name);
+ /// \brief check protocol extension
+ quint32 checkProtocolExtension(const QString & name);
+ /// \brief check protocol extension and version
+ quint32 checkProtocolExtension(const QString & name,const QString & version);
+ /// \brief add copy with destination
+ quint32 addCopyWithDestination(const QStringList & sources,const QString & destination);
+ /// \brief add copy without destination
+ quint32 addCopyWithoutDestination(const QStringList & sources);
+ /// \brief add move with destination
+ quint32 addMoveWithDestination(const QStringList & sources,const QString & destination);
+ /// \brief add move without destination
+ quint32 addMoveWithoutDestination(const QStringList & sources);
+ /// \brief to send stream of string list
+ quint32 sendRawOrderList(const QStringList & order);
+ signals:
+ /// \brief is connected
+ void connected();
+ /// \brief is disconnected
+ void disconnected();
+ /// \brief the socket state have changed
+ void stateChanged(QLocalSocket::LocalSocketState socketState);
+ /// \brief send the error string
+ void error(QString error);
+ /// \brief send socket error
+ void errorSocket(QLocalSocket::LocalSocketError socketError);
+ /// \brief have new reply
+ void newReply(quint32 orderId,quint32 returnCode,QStringList returnList);
+ /// \brief have data send
+ void dataSend(quint32 orderId,QByteArray data);
+ /// \brief have data send by string list
+ void dataSend(quint32 orderId,QStringList data);
+ /// \brief have unknow reply
+ void unknowReply(quint32 orderId);
+ //reply
+ /// \brief protocol is supported
+ void protocolSupported(quint32 orderId);
+ /// \brief incorrect argument list size
+ void incorrectArgumentListSize(quint32 orderId);
+ /// \brief incorrect argument
+ void incorrectArgument(quint32 orderId);
+ /// \brief protocol not supported
+ void protocolNotSupported(quint32 orderId);
+ /// \brief protocol extension supported
+ void protocolExtensionSupported(quint32 orderId,bool isSupported);
+ /// \brief client is registred
+ void clientRegistered(quint32 orderId);
+ /// \brief have the server name
+ void serverName(quint32 orderId,QString name);
+ /// \brief copy finished
+ void copyFinished(quint32 orderId,bool withError);
+ /// \brief copy canceled
+ void copyCanceled(quint32 orderId);
+ /// \brief have unknow order
+ void unknowOrder(quint32 orderId); //the server have not understand the order
+ private:
+ QLocalSocket socket;
+ QString error_string;
+ quint32 idNextOrder;
+ QByteArray data;
+ bool haveData;
+ int dataSize;
+ quint32 orderIdFirstSendProtocol;
+ QTimer detectTimeOut;
+ bool sendProtocolReplied;
+ QList<quint32> notRepliedQuery;
+ bool checkDataIntegrity(QByteArray data);
+ private slots:
+ void readyRead();
+ void disconnectedFromSocket();
+ void socketIsConnected();
+ void checkTimeOut();
+ protected:
+ bool parseReply(quint32 orderId,quint32 returnCode,QStringList returnList);
+};
+
+#endif // CLIENTCATCHCOPY_H
diff --git a/test-client-catchcopy/catchcopy-api-0002/ExtraSocketCatchcopy.cpp b/test-client-catchcopy/catchcopy-api-0002/ExtraSocketCatchcopy.cpp
new file mode 100644
index 0000000..7ee05ed
--- /dev/null
+++ b/test-client-catchcopy/catchcopy-api-0002/ExtraSocketCatchcopy.cpp
@@ -0,0 +1,31 @@
+/** \file ExtraSocketCatchcopy.cpp
+\brief Define the socket of catchcopy
+\author alpha_one_x86
+\version 0002
+\date 2010 */
+
+#include "ExtraSocketCatchcopy.h"
+
+const QString ExtraSocketCatchcopy::pathSocket()
+{
+#ifdef Q_OS_UNIX
+ return "advanced-copier-"+QString::number(getuid());
+#else
+ QString userName;
+ DWORD size=0;
+ if(GetUserNameW(NULL,&size) || (GetLastError()!=ERROR_INSUFFICIENT_BUFFER))
+ {
+ }
+ else
+ {
+ WCHAR * userNameW=new WCHAR[size];
+ if(GetUserNameW(userNameW,&size))
+ {
+ userName.fromWCharArray(userNameW,size*2);
+ userName=QString(QByteArray((char*)userNameW,size*2-2).toHex());
+ }
+ delete userNameW;
+ }
+ return "advanced-copier-"+userName;
+#endif
+}
diff --git a/test-client-catchcopy/catchcopy-api-0002/ExtraSocketCatchcopy.h b/test-client-catchcopy/catchcopy-api-0002/ExtraSocketCatchcopy.h
new file mode 100644
index 0000000..623c668
--- /dev/null
+++ b/test-client-catchcopy/catchcopy-api-0002/ExtraSocketCatchcopy.h
@@ -0,0 +1,27 @@
+/** \file ExtraSocketCatchcopy.h
+\brief Define the socket of catchcopy
+\author alpha_one_x86
+\version 0002
+\date 2010 */
+
+#ifndef EXTRASOCKETCATCHCOPY_H
+#define EXTRASOCKETCATCHCOPY_H
+
+#include <QString>
+
+#ifdef Q_OS_UNIX
+ #include <unistd.h>
+ #include <sys/types.h>
+#else
+ #include <windows.h>
+#endif
+
+/// \brief to have extra socket function
+class ExtraSocketCatchcopy
+{
+public:
+ /// \brief to get the socket path
+ static const QString pathSocket();
+};
+
+#endif // EXTRASOCKETCATCHCOPY_H
diff --git a/test-client-catchcopy/catchcopy-api-0002/ServerCatchcopy.cpp b/test-client-catchcopy/catchcopy-api-0002/ServerCatchcopy.cpp
new file mode 100644
index 0000000..b17fc0a
--- /dev/null
+++ b/test-client-catchcopy/catchcopy-api-0002/ServerCatchcopy.cpp
@@ -0,0 +1,725 @@
+/** \file ServerCatchcopy.cpp
+\brief Define the server of catchcopy
+\author alpha_one_x86
+\version 0002
+\date 2010 */
+
+#include "ServerCatchcopy.h"
+#include "VariablesCatchcopy.h"
+#include "ExtraSocketCatchcopy.h"
+
+ServerCatchcopy::ServerCatchcopy()
+{
+ name="Default avanced copier";
+ autoReply=true;
+ idNextClient=0;
+ error_string="Unknown error";
+ connect(&server, SIGNAL(newConnection()), this, SLOT(newConnection()));
+}
+
+ServerCatchcopy::~ServerCatchcopy()
+{
+ close();
+}
+
+bool ServerCatchcopy::isListening()
+{
+ return server.isListening();
+}
+
+void ServerCatchcopy::setName(const QString & name)
+{
+ this->name=name;
+}
+
+QString ServerCatchcopy::getName()
+{
+ return name;
+}
+
+bool ServerCatchcopy::listen()
+{
+ QLocalSocket socketTestConnection;
+ pathSocket=ExtraSocketCatchcopy::pathSocket();
+ socketTestConnection.connectToServer(pathSocket);
+ if(socketTestConnection.waitForConnected(CATCHCOPY_COMMUNICATION_TIMEOUT))
+ {
+ error_string="Other server is listening";
+ emit error(error_string);
+ return false;
+ }
+ else
+ {
+ server.removeServer(pathSocket);
+ if(server.listen(pathSocket))
+ return true;
+ else
+ {
+ error_string=QString("Unable to listen %1: %2").arg(pathSocket).arg(server.errorString());
+ emit error(error_string);
+ return false;
+ }
+ }
+}
+
+void ServerCatchcopy::close()
+{
+ if(server.isListening())
+ {
+ int index=0;
+ while(index<ClientList.size())
+ {
+ ClientList.at(index).socket->disconnectFromServer();
+ index++;
+ }
+ server.close();
+ QLocalServer::removeServer(pathSocket);
+ }
+}
+
+const QString ServerCatchcopy::errorStringServer()
+{
+ return server.errorString();
+}
+
+const QString ServerCatchcopy::errorString()
+{
+ return error_string;
+}
+
+/// \brief New connexion
+void ServerCatchcopy::newConnection()
+{
+ while(server.hasPendingConnections())
+ {
+ QLocalSocket *clientSocket = server.nextPendingConnection();
+ if(clientSocket!=NULL)
+ {
+ do
+ {
+ idNextClient++;
+ if(idNextClient>2000000000)
+ idNextClient=0;
+ } while(clientIdFound(idNextClient));
+ Client newClient;
+ newClient.id = idNextClient;
+ newClient.socket = clientSocket;
+ newClient.haveData = false;
+ newClient.firstProtocolReplied = false;
+ newClient.detectTimeOut = new QTimer(this);
+ newClient.detectTimeOut->setSingleShot(true);
+ newClient.detectTimeOut->setInterval(CATCHCOPY_COMMUNICATION_TIMEOUT);
+ connect(newClient.socket, SIGNAL(error(QLocalSocket::LocalSocketError)), this, SLOT(connectionError(QLocalSocket::LocalSocketError)));
+ connect(newClient.socket, SIGNAL(readyRead()), this, SLOT(readyRead()));
+ connect(newClient.socket, SIGNAL(disconnected()), this, SLOT(disconnected()));
+ connect(newClient.detectTimeOut,SIGNAL(timeout()), this, SLOT(checkTimeOut()));
+ ClientList << newClient;
+ emit connectedClient(newClient.id);
+ }
+ }
+}
+
+bool ServerCatchcopy::clientIdFound(quint32 id)
+{
+ int index=0;
+ while(index<ClientList.size())
+ {
+ if(ClientList.at(index).id==id)
+ return true;
+ index++;
+ }
+ return false;
+}
+
+/// \brief new error at connexion
+void ServerCatchcopy::connectionError(QLocalSocket::LocalSocketError error)
+{
+ QLocalSocket *socket=qobject_cast<QLocalSocket *>(QObject::sender());
+ if(socket==NULL)
+ {
+ qWarning() << "Unlocated client socket!";
+ return;
+ }
+ int index=0;
+ while(index<ClientList.size())
+ {
+ if(ClientList.at(index).socket==socket)
+ {
+ if(error!=QLocalSocket::PeerClosedError)
+ qWarning() << "error detected for the client: " << index << ", type: " << error;
+ ClientList.at(index).socket->disconnectFromServer();
+ return;
+ }
+ index++;
+ }
+}
+
+void ServerCatchcopy::disconnected()
+{
+ QLocalSocket *socket=qobject_cast<QLocalSocket *>(QObject::sender());
+ if(socket==NULL)
+ {
+ qWarning() << "Unlocated client socket!";
+ return;
+ }
+ int index=0;
+ while(index<ClientList.size())
+ {
+ if(ClientList.at(index).socket==socket)
+ {
+ emit disconnectedClient(ClientList.at(index).id);
+ disconnect(ClientList.at(index).socket);
+ disconnect(ClientList.at(index).detectTimeOut);
+ delete ClientList.at(index).detectTimeOut;
+ ClientList.at(index).socket->abort();
+ ClientList.at(index).socket->disconnectFromServer();
+ ClientList.at(index).socket->deleteLater();
+ ClientList.removeAt(index);
+ return;
+ }
+ index++;
+ }
+ qWarning() << "Unlocated client!";
+}
+
+void ServerCatchcopy::disconnectClient(quint32 id)
+{
+ int index=0;
+ while(index<ClientList.size())
+ {
+ if(ClientList.at(index).id==id)
+ {
+ ClientList.at(index).socket->disconnectFromServer();
+ return;
+ }
+ index++;
+ }
+ qWarning() << "Unlocated client!";
+}
+
+void ServerCatchcopy::readyRead()
+{
+ QLocalSocket *socket=qobject_cast<QLocalSocket *>(QObject::sender());
+ if(socket==NULL)
+ {
+ qWarning() << "Unlocated client socket!";
+ return;
+ }
+ int index=0;
+ while(index<ClientList.size())
+ {
+ if(ClientList.at(index).socket==socket)
+ {
+ while(socket->bytesAvailable()>0)
+ {
+ if(!ClientList.at(index).haveData)
+ {
+ if(socket->bytesAvailable()<(int)sizeof(int))//ignore because first int is cuted!
+ {
+ /*error_string="Bytes available is not sufficient to do a int";
+ emit error(error_string);
+ disconnectClient(ClientList.at(index).id);*/
+ return;
+ }
+ QDataStream in(socket);
+ in.setVersion(QDataStream::Qt_4_4);
+ in >> ClientList[index].dataSize;
+ ClientList[index].dataSize-=sizeof(int);
+ if(ClientList.at(index).dataSize>64*1024*1024) // 64MB
+ {
+ error_string="Reply size is >64MB, seam corrupted";
+ emit error(error_string);
+ disconnectClient(ClientList.at(index).id);
+ return;
+ }
+ if(ClientList.at(index).dataSize<(int)(sizeof(int) //orderId
+ + sizeof(quint32) //returnCode
+ + sizeof(quint32) //string list size
+ ))
+ {
+ error_string="Reply size is too small to have correct code";
+ emit error(error_string);
+ disconnectClient(ClientList.at(index).id);
+ return;
+ }
+ ClientList[index].haveData=true;
+ }
+ if(ClientList.at(index).dataSize<(ClientList.at(index).data.size()+socket->bytesAvailable()))
+ ClientList[index].data.append(socket->read(ClientList.at(index).dataSize-ClientList.at(index).data.size()));
+ else
+ ClientList[index].data.append(socket->readAll());
+ if(ClientList.at(index).dataSize==(quint32)ClientList.at(index).data.size())
+ {
+ if(!checkDataIntegrity(ClientList.at(index).data))
+ {
+ emit error("Data integrity wrong: "+QString(ClientList.at(index).data.toHex()));
+ ClientList[index].data.clear();
+ ClientList[index].haveData=false;
+ qWarning() << "Data integrity wrong";
+ return;
+ }
+ QStringList returnList;
+ quint32 orderId;
+ QDataStream in(ClientList.at(index).data);
+ in.setVersion(QDataStream::Qt_4_4);
+ in >> orderId;
+ in >> returnList;
+ ClientList[index].data.clear();
+ ClientList[index].haveData=false;
+ if(ClientList.at(index).queryNoReplied.contains(orderId))
+ {
+ emit error("Duplicate query id");
+ qWarning() << "Duplicate query id";
+ return;
+ }
+ ClientList[index].queryNoReplied << orderId;
+ if(!ClientList.at(index).firstProtocolReplied && returnList.size()==2 && returnList.first()=="protocol" && autoReply)
+ {
+ ClientList[index].firstProtocolReplied=true;
+ protocolSupported(ClientList.at(index).id,orderId,(returnList.last()==CATCHCOPY_PROTOCOL_VERSION));
+ }
+ else
+ parseInput(ClientList.at(index).id,orderId,returnList);
+ }
+ }
+ if(ClientList.at(index).haveData)
+ ClientList.at(index).detectTimeOut->start();
+ else
+ ClientList.at(index).detectTimeOut->stop();
+ return;
+ }
+ index++;
+ }
+ emit error("Unallocated client!");
+ qWarning() << "Unallocated client!";
+}
+
+bool ServerCatchcopy::checkDataIntegrity(QByteArray data)
+{
+ quint32 orderId;
+ qint32 listSize;
+ QDataStream in(data);
+ in.setVersion(QDataStream::Qt_4_4);
+ in >> orderId;
+ in >> listSize;
+ if(listSize>65535)
+ {
+ emit error("List size is wrong");
+ qWarning() << "List size is wrong";
+ return false;
+ }
+ int index=0;
+ while(index<listSize)
+ {
+ qint32 stringSize;
+ in >> stringSize;
+ if(stringSize>65535)
+ {
+ emit error("String size is wrong");
+ return false;
+ }
+ if(stringSize>(in.device()->size()-in.device()->pos()))
+ {
+ emit error(QString("String size is greater than the data: %1>(%2-%3)").arg(stringSize).arg(in.device()->size()).arg(in.device()->pos()));
+ return false;
+ }
+ in.device()->seek(in.device()->pos()+stringSize);
+ index++;
+ }
+ if(in.device()->size()!=in.device()->pos())
+ {
+ emit error("Remaining data after string list parsing");
+ return false;
+ }
+ return true;
+}
+
+void ServerCatchcopy::parseInput(quint32 client,quint32 orderId,QStringList returnList)
+{
+ switch(parseInputCurrentProtocol(client,orderId,returnList))
+ {
+ case Ok:
+ emit newQuery(client,orderId,returnList);
+ break;
+ case Replied:
+ break;
+ case ExtensionWrong:
+ if(autoReply)
+ protocolExtensionSupported(client,orderId,false);
+ else
+ emit newQuery(client,orderId,returnList);
+ break;
+ case WrongArgument:
+ if(autoReply)
+ incorrectArgument(client,orderId);
+ else
+ emit newQuery(client,orderId,returnList);
+ break;
+ case WrongArgumentListSize:
+ if(autoReply)
+ incorrectArgumentListSize(client,orderId);
+ else
+ emit newQuery(client,orderId,returnList);
+ break;
+ case UnknowOrder:
+ emit error("Unknown query");
+ qWarning() << "Unknown query";
+ if(autoReply)
+ unknowOrder(client,orderId);
+ else
+ emit newQuery(client,orderId,returnList);
+ break;
+ }
+}
+
+ServerCatchcopy::inputReturnType ServerCatchcopy::parseInputCurrentProtocol(quint32 client,quint32 orderId,QStringList returnList)
+{
+ if(returnList.size()==0)
+ return WrongArgumentListSize;
+ //if is supported
+ QString firstArgument=returnList.first();
+ if(firstArgument=="protocol")
+ {
+ if(returnList.size()!=2)
+ return WrongArgumentListSize;
+ emit askProtocolCompatibility(client,orderId,returnList.last());
+ return Ok;
+ }
+ else if(firstArgument=="protocol extension")
+ {
+ if(returnList.size()>3 || returnList.size()<2)
+ return WrongArgumentListSize;
+ if(!autoReply)
+ {
+ if(returnList.size()==2)
+ emit askProtocolExtension(client,orderId,returnList.last());
+ else
+ emit askProtocolExtension(client,orderId,returnList.at(1),returnList.last());
+ }
+ return ExtensionWrong;
+ }
+ else if(firstArgument=="client")
+ {
+ if(returnList.size()!=2)
+ return WrongArgumentListSize;
+ emit clientName(client,returnList.last());
+ if(autoReply)
+ {
+ clientRegistered(client,orderId);
+ return Replied;
+ }
+ else
+ {
+ emit clientName(client,orderId,returnList.last());
+ return Ok;
+ }
+ }
+ else if(firstArgument=="server")
+ {
+ if(returnList.size()!=2)
+ return WrongArgumentListSize;
+ if(returnList.last()!="name?")
+ return WrongArgument;
+ if(autoReply)
+ {
+ serverName(client,orderId,name);
+ return Replied;
+ }
+ else
+ {
+ askServerName(client,orderId);
+ return Ok;
+ }
+ }
+ else if(firstArgument=="cp")
+ {
+ if(returnList.size()<3)
+ return WrongArgumentListSize;
+ QStringList sourceList=returnList;
+ sourceList.removeFirst();
+ sourceList.removeLast();
+ emitNewCopy(client,orderId,sourceList,returnList.last());
+ return Ok;
+ }
+ else if(firstArgument=="cp-?")
+ {
+ if(returnList.size()<2)
+ return WrongArgumentListSize;
+ QStringList sourceList=returnList;
+ sourceList.removeFirst();
+ emitNewCopy(client,orderId,sourceList);
+ return Ok;
+ }
+ else if(firstArgument=="mv")
+ {
+ if(returnList.size()<3)
+ return WrongArgumentListSize;
+ QStringList sourceList=returnList;
+ sourceList.removeFirst();
+ sourceList.removeLast();
+ emitNewMove(client,orderId,sourceList,returnList.last());
+ return Ok;
+ }
+ else if(firstArgument=="mv-?")
+ {
+ if(returnList.size()<2)
+ return WrongArgumentListSize;
+ QStringList sourceList=returnList;
+ sourceList.removeFirst();
+ emitNewMove(client,orderId,sourceList);
+ return Ok;
+ }
+ else //if is not supported
+ return UnknowOrder;
+}
+
+void ServerCatchcopy::emitNewCopy(quint32 client,quint32 orderId,QStringList sources)
+{
+ emit newCopy(client,orderId,sources);
+ LinkGlobalToLocalClient newAssociation;
+ newAssociation.idClient=client;
+ newAssociation.orderId=orderId;
+ newAssociation.globalOrderId=incrementOrderId();
+ LinkGlobalToLocalClientList << newAssociation;
+ emit newCopy(newAssociation.globalOrderId,sources);
+}
+
+void ServerCatchcopy::emitNewCopy(quint32 client,quint32 orderId,QStringList sources,QString destination)
+{
+ emit newCopy(client,orderId,sources,destination);
+ LinkGlobalToLocalClient newAssociation;
+ newAssociation.idClient=client;
+ newAssociation.orderId=orderId;
+ newAssociation.globalOrderId=incrementOrderId();
+ LinkGlobalToLocalClientList << newAssociation;
+ emit newCopy(newAssociation.globalOrderId,sources,destination);
+}
+
+void ServerCatchcopy::emitNewMove(quint32 client,quint32 orderId,QStringList sources)
+{
+ emit newMove(client,orderId,sources);
+ LinkGlobalToLocalClient newAssociation;
+ newAssociation.idClient=client;
+ newAssociation.orderId=orderId;
+ newAssociation.globalOrderId=incrementOrderId();
+ LinkGlobalToLocalClientList << newAssociation;
+ emit newMove(newAssociation.globalOrderId,sources);
+}
+
+void ServerCatchcopy::emitNewMove(quint32 client,quint32 orderId,QStringList sources,QString destination)
+{
+ emit newMove(client,orderId,sources,destination);
+ LinkGlobalToLocalClient newAssociation;
+ newAssociation.idClient=client;
+ newAssociation.orderId=orderId;
+ newAssociation.globalOrderId=incrementOrderId();
+ LinkGlobalToLocalClientList << newAssociation;
+ emit newMove(newAssociation.globalOrderId,sources,destination);
+}
+
+void ServerCatchcopy::copyFinished(quint32 globalOrderId,bool withError)
+{
+ int index=0;
+ while(index<LinkGlobalToLocalClientList.size())
+ {
+ if(LinkGlobalToLocalClientList.at(index).globalOrderId==globalOrderId)
+ {
+ copyFinished(LinkGlobalToLocalClientList.at(index).idClient,LinkGlobalToLocalClientList.at(index).orderId,withError);
+ LinkGlobalToLocalClientList.removeAt(index);
+ orderList.removeOne(globalOrderId);
+ return;
+ }
+ index++;
+ }
+}
+
+void ServerCatchcopy::copyCanceled(quint32 globalOrderId)
+{
+ int index=0;
+ while(index<LinkGlobalToLocalClientList.size())
+ {
+ if(LinkGlobalToLocalClientList.at(index).globalOrderId==globalOrderId)
+ {
+ copyCanceled(LinkGlobalToLocalClientList.at(index).idClient,LinkGlobalToLocalClientList.at(index).orderId);
+ LinkGlobalToLocalClientList.removeAt(index);
+ orderList.removeOne(globalOrderId);
+ return;
+ }
+ index++;
+ }
+}
+
+void ServerCatchcopy::setAutoReply(bool value)
+{
+ autoReply=value;
+}
+
+bool ServerCatchcopy::getAutoReply()
+{
+ return autoReply;
+}
+
+void ServerCatchcopy::reply(quint32 client,quint32 orderId,quint32 returnCode,QString returnString)
+{
+ reply(client,orderId,returnCode,QStringList() << returnString);
+}
+
+void ServerCatchcopy::reply(quint32 client,quint32 orderId,quint32 returnCode,QStringList returnList)
+{
+ int index=0;
+ while(index<ClientList.size())
+ {
+ if(ClientList.at(index).id==client)
+ {
+ if(ClientList.at(index).socket->isValid() && ClientList.at(index).socket->state()==QLocalSocket::ConnectedState)
+ {
+ if(!ClientList.at(index).queryNoReplied.contains(orderId))
+ {
+ qWarning() << "Reply to missing query or previously replied";
+ return;
+ }
+ ClientList[index].queryNoReplied.removeOne(orderId);
+ //cut string list and send it as block of 32KB
+ QByteArray block;
+ QDataStream out(&block, QIODevice::WriteOnly);
+ out.setVersion(QDataStream::Qt_4_4);
+ out << int(0);
+ out << orderId;
+ out << returnCode;
+ out << returnList;
+ out.device()->seek(0);
+ out << block.size();
+ emit dataSend(client,orderId,returnCode,block);
+ emit dataSend(client,orderId,returnCode,returnList);
+ do
+ {
+ QByteArray blockToSend;
+ int byteWriten;
+ blockToSend=block.left(32*1024);//32KB
+ block.remove(0,blockToSend.size());
+ byteWriten = ClientList[index].socket->write(blockToSend);
+ if(!ClientList[index].socket->isValid())
+ {
+ error_string="Socket is not valid";
+ emit error(error_string);
+ return;
+ }
+ if(ClientList[index].socket->errorString()!="Unknown error" && ClientList[index].socket->errorString()!="")
+ {
+ error_string="Error with socket: "+ClientList[index].socket->errorString();
+ emit error(error_string);
+ return;
+ }
+ if(blockToSend.size()!=byteWriten)
+ {
+ error_string="All the bytes have not be written";
+ emit error(error_string);
+ return;
+ }
+ }
+ while(block.size());
+ }
+ else
+ {
+ error_string="Socket is not valid or not connected";
+ emit error(error_string);
+ }
+ return;
+ }
+ index++;
+ }
+ qWarning() << "Client id not found:" << client;
+}
+
+void ServerCatchcopy::protocolSupported(quint32 client,quint32 orderId,bool value)
+{
+ if(value)
+ reply(client,orderId,1000,"protocol supported");
+ else
+ reply(client,orderId,5003,"protocol not supported");
+}
+
+void ServerCatchcopy::incorrectArgumentListSize(quint32 client,quint32 orderId)
+{
+ reply(client,orderId,5000,"incorrect argument list size");
+}
+
+void ServerCatchcopy::incorrectArgument(quint32 client,quint32 orderId)
+{
+ reply(client,orderId,5001,"incorrect argument");
+}
+
+void ServerCatchcopy::protocolExtensionSupported(quint32 client,quint32 orderId,bool value)
+{
+ if(value)
+ reply(client,orderId,1001,"protocol extension supported");
+ else
+ reply(client,orderId,1002,"protocol extension not supported");
+}
+
+void ServerCatchcopy::clientRegistered(quint32 client,quint32 orderId)
+{
+ reply(client,orderId,1003,"client registered");
+}
+
+void ServerCatchcopy::serverName(quint32 client,quint32 orderId,QString name)
+{
+ reply(client,orderId,1004,name);
+}
+
+void ServerCatchcopy::copyFinished(quint32 client,quint32 orderId,bool withError)
+{
+ if(!withError)
+ reply(client,orderId,1005,"finished");
+ else
+ reply(client,orderId,1006,"finished with error(s)");
+}
+
+void ServerCatchcopy::copyCanceled(quint32 client,quint32 orderId)
+{
+ reply(client,orderId,1007,"canceled");
+}
+
+void ServerCatchcopy::unknowOrder(quint32 client,quint32 orderId)
+{
+ reply(client,orderId,5002,"unknown order");
+}
+
+void ServerCatchcopy::checkTimeOut()
+{
+ QTimer *timer=qobject_cast<QTimer *>(QObject::sender());
+ if(timer==NULL)
+ {
+ qWarning() << "Unallocated client timer!";
+ return;
+ }
+ int index=0;
+ while(index<ClientList.size())
+ {
+ if(ClientList.at(index).detectTimeOut==timer)
+ {
+ ClientList.at(index).detectTimeOut->stop();
+ if(ClientList.at(index).haveData)
+ {
+ error_string="The client is too long to send the next part of the reply: "+ClientList.at(index).data;
+ ClientList[index].haveData=false;
+ ClientList[index].data.clear();
+ ClientList.at(index).socket->disconnectFromServer();
+ emit error(error_string);
+ }
+ return;
+ }
+ index++;
+ }
+}
+
+quint32 ServerCatchcopy::incrementOrderId()
+{
+ do
+ {
+ nextOrderId++;
+ if(nextOrderId>2000000)
+ nextOrderId=0;
+ } while(orderList.contains(nextOrderId));
+ return nextOrderId;
+}
diff --git a/test-client-catchcopy/catchcopy-api-0002/ServerCatchcopy.h b/test-client-catchcopy/catchcopy-api-0002/ServerCatchcopy.h
new file mode 100644
index 0000000..5f7af35
--- /dev/null
+++ b/test-client-catchcopy/catchcopy-api-0002/ServerCatchcopy.h
@@ -0,0 +1,162 @@
+/** \file ServerCatchcopy.h
+\brief Define the server of catchcopy
+\author alpha_one_x86
+\version 0002
+\date 2010 */
+
+#ifndef SERVERCATCHCOPY_H
+#define SERVERCATCHCOPY_H
+
+#include <QObject>
+#include <QLocalSocket>
+#include <QLocalServer>
+#include <QStringList>
+#include <QString>
+#include <QByteArray>
+#include <QTimer>
+
+/// \brief Define the server of catchcopy
+class ServerCatchcopy : public QObject
+{
+ Q_OBJECT
+ public:
+ ServerCatchcopy();
+ ~ServerCatchcopy();
+ /// \brief return if is listening
+ bool isListening();
+ /// \brief try listen
+ bool listen();
+ /// \brief try close the server
+ void close();
+ /// \brief get the error string on the QLocalServer
+ const QString errorStringServer();
+ /// \brief get the general error string
+ const QString errorString();
+ /// \brief set if automatic reply is used
+ void setAutoReply(bool value);
+ /// \brief get if autoReply is set
+ bool getAutoReply();
+ /// \brief set the name of the server
+ void setName(const QString & name);
+ /// \brief get the name
+ QString getName();
+ private:
+ QString pathSocket;
+ QString name;
+ QString error_string;
+ QLocalServer server;
+ quint32 idNextClient;
+ struct Client
+ {
+ quint32 id;
+ QLocalSocket *socket;
+ QByteArray data;
+ bool haveData;
+ quint32 dataSize;
+ bool firstProtocolReplied;
+ QList<quint32> queryNoReplied;
+ QTimer *detectTimeOut;
+ };
+ QList<Client> ClientList;
+ struct LinkGlobalToLocalClient
+ {
+ quint32 idClient;
+ quint32 orderId;
+ quint32 globalOrderId;
+ };
+ QList<LinkGlobalToLocalClient> LinkGlobalToLocalClientList;
+ enum inputReturnType{Ok,Replied,ExtensionWrong,WrongArgument,WrongArgumentListSize,UnknowOrder};
+ inputReturnType parseInputCurrentProtocol(quint32 client,quint32 orderId,QStringList returnList);
+ bool autoReply;
+ bool clientIdFound(quint32 id);
+ quint32 nextOrderId;
+ QList<quint32> orderList;
+ quint32 incrementOrderId();
+ void emitNewCopy(quint32 client,quint32 orderId,QStringList sources);
+ void emitNewCopy(quint32 client,quint32 orderId,QStringList sources,QString destination);
+ void emitNewMove(quint32 client,quint32 orderId,QStringList sources);
+ void emitNewMove(quint32 client,quint32 orderId,QStringList sources,QString destination);
+ bool checkDataIntegrity(QByteArray data);
+ protected:
+ void parseInput(quint32 client,quint32 orderId,QStringList returnList);
+ private slots:
+ void newConnection();
+ void connectionError(QLocalSocket::LocalSocketError error);
+ void disconnected();
+ void readyRead();
+ void checkTimeOut();
+ public slots:
+ /// \brief disconnect one client
+ void disconnectClient(quint32 id);
+ /// \brief reply to a client with QStringList
+ void reply(quint32 client,quint32 orderId,quint32 returnCode,QStringList returnList);
+ /// \brief reply to a client
+ void reply(quint32 client,quint32 orderId,quint32 returnCode,QString returnString);
+ //reply
+ /// \brief send if the protocol is supported
+ void protocolSupported(quint32 client,quint32 orderId,bool value);
+ /// \brief send incorrect arguement list size
+ void incorrectArgumentListSize(quint32 client,quint32 orderId);
+ /// \brief send incorrect arguement
+ void incorrectArgument(quint32 client,quint32 orderId);
+ /// \brief send if protocol extension is supported
+ void protocolExtensionSupported(quint32 client,quint32 orderId,bool value);
+ /// \brief the client is registred
+ void clientRegistered(quint32 client,quint32 orderId);
+ /// \brief send the server name
+ void serverName(quint32 client,quint32 orderId,QString name);
+ /// \brief send the copy is finished
+ void copyFinished(quint32 client,quint32 orderId,bool withError);
+ /// \brief send the copy is canceled
+ void copyCanceled(quint32 client,quint32 orderId);
+ /// \brief send the copy is finished by global is order
+ void copyFinished(quint32 globalOrderId,bool withError);
+ /// \brief send copy cancel by global is order
+ void copyCanceled(quint32 globalOrderId);
+ /// \brief send the unknow order
+ void unknowOrder(quint32 client,quint32 orderId);
+ signals:
+ /// \brief send connected client
+ void connectedClient(quint32 id);
+ /// \brief send disconnect client
+ void disconnectedClient(quint32 id);
+ /// \brief have new query
+ void newQuery(quint32 client,quint32 orderId,QStringList returnList);
+ /// \brief send new data as string list
+ void dataSend(quint32 client,quint32 orderId,quint32 returnCode,QStringList returnList);
+ /// \brief send new data as raw data
+ void dataSend(quint32 client,quint32 orderId,quint32 returnCode,QByteArray block);
+ /// \brief have new error
+ void error(QString error);
+ //query
+ /// \brief ask the protocol compatility
+ void askProtocolCompatibility(quint32 client,quint32 orderId,QString version);
+ /// \brief ask protocol extension
+ void askProtocolExtension(quint32 client,quint32 orderId,QString extension);
+ /// \brief ask protocol extension with version
+ void askProtocolExtension(quint32 client,quint32 orderId,QString extension,QString version);
+ /// \brief send the client name, with query id
+ void clientName(quint32 client,quint32 orderId,QString name);
+ /// \brief send the client name, without query id
+ void clientName(quint32 client,QString name);
+ /// \brief send the client have ask the server name
+ void askServerName(quint32 client,quint32 orderId);
+ /// \brief copy is send, without destination
+ void newCopy(quint32 client,quint32 orderId,QStringList sources);
+ /// \brief copy is send, with destination
+ void newCopy(quint32 client,quint32 orderId,QStringList sources,QString destination);
+ /// \brief move is send, without destination
+ void newMove(quint32 client,quint32 orderId,QStringList sources);
+ /// \brief move is send, with destination
+ void newMove(quint32 client,quint32 orderId,QStringList sources,QString destination);
+ /// \brief copy is send, by globalOrderId, without destination
+ void newCopy(quint32 globalOrderId,QStringList sources);
+ /// \brief copy is send, by globalOrderId, with destination
+ void newCopy(quint32 globalOrderId,QStringList sources,QString destination);
+ /// \brief move is send, by globalOrderId, without destination
+ void newMove(quint32 globalOrderId,QStringList sources);
+ /// \brief move is send, by globalOrderId, with destination
+ void newMove(quint32 globalOrderId,QStringList sources,QString destination);
+};
+
+#endif // SERVERCATCHCOPY_H
diff --git a/test-client-catchcopy/catchcopy-api-0002/VariablesCatchcopy.h b/test-client-catchcopy/catchcopy-api-0002/VariablesCatchcopy.h
new file mode 100644
index 0000000..ce73aee
--- /dev/null
+++ b/test-client-catchcopy/catchcopy-api-0002/VariablesCatchcopy.h
@@ -0,0 +1,14 @@
+/** \file VariablesCatchcopy.h
+\brief Define the variable for catchcopy
+\author alpha_one_x86
+\version 0002
+\date 2010 */
+
+#ifndef VARIABLECATCHCOPY_H
+#define VARIABLECATCHCOPY_H
+
+#define CATCHCOPY_PROTOCOL_VERSION "0002"
+#define CATCHCOPY_COMMUNICATION_TIMEOUT 200
+
+#endif // VARIABLECATCHCOPY_H
+
diff --git a/test-client-catchcopy/catchcopy-api-0002/documentation.dox b/test-client-catchcopy/catchcopy-api-0002/documentation.dox
new file mode 100755
index 0000000..8ee4177
--- /dev/null
+++ b/test-client-catchcopy/catchcopy-api-0002/documentation.dox
@@ -0,0 +1,31 @@
+/* -*- mode: C++ ; c-file-style: "stroustrup" -*- **/
+
+/*
+ This file contains NO source code, just some documentation for doxygen to
+ parse.
+*/
+
+/*!
+ \mainpage Catchcopy API
+
+ \section mainpage_overview Overview
+
+ This code is to interface with the catchcopy protocol, the code is provided by the catchcopy projet: <a href="http://catchcopy.first-world.info/">Catchcopy web site</a>
+
+ \section mainpage_platforms Platforms
+
+ This plugin might be usable in all environments where you find Qt 4.\n
+
+ \section mainpage_downloads Downloads
+
+ You can found link on <a href="http://ultracopier.first-world.info/">Ultracopier (Supercopier/Teracopy)</a> project page, via git, snapshot sources, ...
+
+ \section mainpage_algorithm Protocol
+
+ The protocol in version 0.0.0.2 is used, you can see the documentation on <a href="http://catchcopy.first-world.info/">Catchcopy web site</a>
+
+ \section license GPL Version 3
+ The code source is under GPL3. The image is extacted from Oxygen icon pack of KDE4.
+
+*/
+
diff --git a/test-client-catchcopy/icon.ico b/test-client-catchcopy/icon.ico
new file mode 100644
index 0000000..f0296c0
--- /dev/null
+++ b/test-client-catchcopy/icon.ico
Binary files differ
diff --git a/test-client-catchcopy/images/dialog-ok-apply.png b/test-client-catchcopy/images/dialog-ok-apply.png
new file mode 100644
index 0000000..f5feac0
--- /dev/null
+++ b/test-client-catchcopy/images/dialog-ok-apply.png
Binary files differ
diff --git a/test-client-catchcopy/images/download.png b/test-client-catchcopy/images/download.png
new file mode 100755
index 0000000..4ffac41
--- /dev/null
+++ b/test-client-catchcopy/images/download.png
Binary files differ
diff --git a/test-client-catchcopy/images/main.png b/test-client-catchcopy/images/main.png
new file mode 100644
index 0000000..efdc90d
--- /dev/null
+++ b/test-client-catchcopy/images/main.png
Binary files differ
diff --git a/test-client-catchcopy/images/process-stop.png b/test-client-catchcopy/images/process-stop.png
new file mode 100644
index 0000000..a76314c
--- /dev/null
+++ b/test-client-catchcopy/images/process-stop.png
Binary files differ
diff --git a/test-client-catchcopy/images/tools-report-bug.png b/test-client-catchcopy/images/tools-report-bug.png
new file mode 100644
index 0000000..26af8d6
--- /dev/null
+++ b/test-client-catchcopy/images/tools-report-bug.png
Binary files differ
diff --git a/test-client-catchcopy/images/upload.png b/test-client-catchcopy/images/upload.png
new file mode 100755
index 0000000..4e9d532
--- /dev/null
+++ b/test-client-catchcopy/images/upload.png
Binary files differ
diff --git a/test-client-catchcopy/main.cpp b/test-client-catchcopy/main.cpp
new file mode 100644
index 0000000..bbda5ac
--- /dev/null
+++ b/test-client-catchcopy/main.cpp
@@ -0,0 +1,10 @@
+#include <QApplication>
+#include "mainwindow.h"
+
+int main(int argc, char *argv[])
+{
+ QApplication a(argc, argv);
+ MainWindow w;
+ w.show();
+ return a.exec();
+}
diff --git a/test-client-catchcopy/mainwindow.cpp b/test-client-catchcopy/mainwindow.cpp
new file mode 100644
index 0000000..59f2eda
--- /dev/null
+++ b/test-client-catchcopy/mainwindow.cpp
@@ -0,0 +1,305 @@
+#include <QStringList>
+#include <QListWidgetItem>
+
+#include "mainwindow.h"
+#include "ui_mainwindow.h"
+
+MainWindow::MainWindow(QWidget *parent) :
+ QMainWindow(parent),
+ ui(new Ui::MainWindow)
+{
+ ui->setupUi(this);
+ connect(&client,SIGNAL(connected()),this,SLOT(connected()));
+ connect(&client,SIGNAL(disconnected()),this,SLOT(disconnected()));
+ connect(&client,SIGNAL(errorSocket(QLocalSocket::LocalSocketError)),this,SLOT(errorSocket(QLocalSocket::LocalSocketError)));
+ connect(&client,SIGNAL(error(QString)),this,SLOT(error(QString)));
+ connect(&client,SIGNAL(dataSend(quint32 ,QStringList)),this,SLOT(dataSend(quint32 ,QStringList)));
+ connect(&client,SIGNAL(newReply(quint32 ,quint32,QStringList)),this,SLOT(newReply(quint32 ,quint32,QStringList)));
+ ui->groupBoxPredefinedFunction->setEnabled(false);
+ ui->groupBoxRaw->setEnabled(false);
+ ui->groupBoxRawSend->setEnabled(false);
+ ui->groupBoxCopyMove->setEnabled(false);
+}
+
+MainWindow::~MainWindow()
+{
+ delete ui;
+}
+
+void MainWindow::changeEvent(QEvent *e)
+{
+ QMainWindow::changeEvent(e);
+ switch (e->type()) {
+ case QEvent::LanguageChange:
+ ui->retranslateUi(this);
+ break;
+ default:
+ break;
+ }
+}
+
+void MainWindow::connected()
+{
+ ui->groupBoxPredefinedFunction->setEnabled(true);
+ ui->groupBoxRaw->setEnabled(true);
+ ui->groupBoxRawSend->setEnabled(true);
+ ui->groupBoxCopyMove->setEnabled(true);
+ ui->actionConnect->setEnabled(false);
+ ui->actionDisconnect->setEnabled(true);
+ ui->statusBar->showMessage(tr("Connected"),5000);
+}
+
+void MainWindow::disconnected()
+{
+ ui->groupBoxPredefinedFunction->setEnabled(false);
+ ui->groupBoxRaw->setEnabled(false);
+ ui->groupBoxRawSend->setEnabled(false);
+ ui->groupBoxCopyMove->setEnabled(false);
+ ui->actionConnect->setEnabled(true);
+ ui->actionDisconnect->setEnabled(false);
+ ui->listCommand->clear();
+ CommandList.clear();
+ on_listCommand_itemSelectionChanged();
+ ui->statusBar->showMessage(tr("Disconnected"),5000);
+}
+
+void MainWindow::tryConnect()
+{
+ ui->statusBar->showMessage(tr("Connection..."),5000);
+ client.connectToServer();
+}
+
+void MainWindow::tryDisconnect()
+{
+ ui->statusBar->showMessage(tr("Disconnection..."),5000);
+ client.disconnectFromServer();
+}
+
+void MainWindow::errorSocket(QLocalSocket::LocalSocketError socketError)
+{
+ if(socketError==QLocalSocket::ConnectionRefusedError)
+ ui->statusBar->showMessage(tr("Connection refused"),5000);
+ else if(socketError==QLocalSocket::PeerClosedError)
+ ui->statusBar->showMessage(tr("Peer have close the connexion"),5000);
+ else
+ ui->statusBar->showMessage(client.errorStringSocket(),5000);
+}
+
+
+void MainWindow::on_actionDisconnect_triggered()
+{
+ tryDisconnect();
+}
+
+void MainWindow::on_actionConnect_triggered()
+{
+ tryConnect();
+}
+
+void MainWindow::on_RawSendRemove_clicked()
+{
+ int index=0;
+ QList<QListWidgetItem *> list=ui->listRawSend->selectedItems();
+ while(index<list.size())
+ {
+
+ delete list.at(index);
+ index++;
+ }
+}
+
+void MainWindow::on_RawSendAdd_clicked()
+{
+ ui->listRawSend->addItem(new QListWidgetItem(ui->lineEditRawSendText->text()));
+}
+
+void MainWindow::on_sendProtocol_clicked()
+{
+ client.sendProtocol();
+}
+
+void MainWindow::on_sendRawList_clicked()
+{
+ QStringList list;
+ int index=0;
+ while(index<ui->listRawSend->count())
+ {
+ list<<ui->listRawSend->item(index)->text();
+ index++;
+ }
+ client.sendRawOrderList(list);
+}
+
+void MainWindow::stateChanged(QLocalSocket::LocalSocketState socketState)
+{
+ if(socketState==QLocalSocket::UnconnectedState)
+ disconnected();
+ else if(socketState==QLocalSocket::ConnectedState)
+ connected();
+ else
+ {
+ ui->actionConnect->setEnabled(false);
+ ui->groupBoxPredefinedFunction->setEnabled(false);
+ ui->groupBoxRaw->setEnabled(false);
+ ui->groupBoxRawSend->setEnabled(false);
+ ui->groupBoxCopyMove->setEnabled(false);
+ }
+}
+
+void MainWindow::dataSend(quint32 orderId,QStringList data)
+{
+ Command newCommand;
+ newCommand.orderId=orderId;
+ newCommand.sendTime=QTime::currentTime();
+ newCommand.replied=false;
+ newCommand.sendList=data;
+ newCommand.returnCode=0;
+ CommandList << newCommand;
+ ui->listCommand->addItem(new QListWidgetItem(QString(newCommand.sendTime.toString()+" - "+QString::number(orderId))));
+ int index=0;
+ while(index<CommandList.size())
+ {
+ if(orderId==CommandList.at(index).orderId)
+ {
+ if(data.size()!=0)
+ ui->listCommand->item(index)->setText(QString(CommandList.at(index).sendTime.toString()+") "+QString::number(orderId)+" - "+data.first()));
+ return;
+ }
+ index++;
+ }
+}
+
+void MainWindow::on_listCommand_itemSelectionChanged()
+{
+ ui->listCommandListSended->clear();
+ ui->listReplyList->clear();
+ ui->lineReplyCode->setText("");
+ if(ui->listCommand->currentRow()<0)
+ {
+ ui->listCommandListSended->setEnabled(false);
+ ui->listReplyList->setEnabled(false);
+ ui->lineReplyCode->setEnabled(false);
+ ui->timeEditReply->setEnabled(false);
+ }
+ else
+ {
+ if(ui->listCommand->currentRow()<CommandList.size())
+ {
+ ui->listCommandListSended->setEnabled(true);
+ ui->listCommandListSended->addItems(CommandList.at(ui->listCommand->currentRow()).sendList);
+ if(CommandList.at(ui->listCommand->currentRow()).replied)
+ {
+ ui->listReplyList->setEnabled(true);
+ ui->lineReplyCode->setEnabled(true);
+ ui->timeEditReply->setEnabled(true);
+ ui->listReplyList->addItems(CommandList.at(ui->listCommand->currentRow()).returnList);
+ ui->lineReplyCode->setText(QString::number(CommandList.at(ui->listCommand->currentRow()).returnCode));
+ ui->timeEditReply->setTime(CommandList.at(ui->listCommand->currentRow()).replyTime);
+ }
+ else
+ {
+ ui->timeEditReply->setEnabled(false);
+ ui->listReplyList->setEnabled(false);
+ ui->lineReplyCode->setEnabled(false);
+ }
+ }
+ else
+ qWarning() << "out of bound!";
+ }
+}
+
+void MainWindow::newReply(quint32 orderId,quint32 returnCode,QStringList returnList)
+{
+ int index=0;
+ while(index<CommandList.size())
+ {
+ if(orderId==CommandList.at(index).orderId)
+ {
+ CommandList[index].replied=true;
+ CommandList[index].replyTime=QTime::currentTime();
+ CommandList[index].returnCode=returnCode;
+ CommandList[index].returnList=returnList;
+ if(ui->listCommand->currentRow()==index)
+ on_listCommand_itemSelectionChanged();
+ return;
+ }
+ index++;
+ }
+}
+
+void MainWindow::on_pushButtonAskServerName_clicked()
+{
+ client.askServerName();
+}
+
+void MainWindow::on_pushButtonClientName_clicked()
+{
+ client.setClientName(ui->lineEditClientName->text());
+}
+
+void MainWindow::on_pushButtonProtocolName_clicked()
+{
+ client.checkProtocolExtension(ui->lineEditProtocolName->text());
+}
+
+void MainWindow::on_pushButtonProtocolNameVersion_clicked()
+{
+ client.checkProtocolExtension(ui->lineEditProtocolName->text(),ui->lineEditProtocolVersion->text());
+}
+
+void MainWindow::on_pushButtonCopyAdd_clicked()
+{
+ ui->listWidgetCopy->addItem(new QListWidgetItem(ui->lineEditAddCopy->text()));
+}
+
+void MainWindow::on_pushButtonCopyRemove_clicked()
+{
+ int index=0;
+ QList<QListWidgetItem *> list=ui->listWidgetCopy->selectedItems();
+ while(index<list.size())
+ {
+
+ delete list.at(index);
+ index++;
+ }
+}
+
+void MainWindow::on_pushButtonCopyWithoutDestination_clicked()
+{
+ QStringList list;
+ int index=0;
+ while(index<ui->listWidgetCopy->count())
+ {
+ list<<ui->listWidgetCopy->item(index)->text();
+ index++;
+ }
+ if(ui->comboBoxCopyType->currentIndex()==0)
+ client.addCopyWithoutDestination(list);
+ else
+ client.addMoveWithoutDestination(list);
+}
+
+void MainWindow::on_pushButtonCopyWithDestination_clicked()
+{
+ QStringList list;
+ int index=0;
+ while(index<ui->listWidgetCopy->count())
+ {
+ list<<ui->listWidgetCopy->item(index)->text();
+ index++;
+ }
+ if(ui->comboBoxCopyType->currentIndex()==0)
+ client.addCopyWithDestination(list,ui->lineEditCopyDestination->text());
+ else
+ client.addMoveWithDestination(list,ui->lineEditCopyDestination->text());
+}
+
+void MainWindow::error(QString error)
+{
+ ui->listError->addItem(error);
+}
+
+void MainWindow::on_listCommandListSended_itemSelectionChanged()
+{
+ on_listCommand_itemSelectionChanged();
+}
diff --git a/test-client-catchcopy/mainwindow.h b/test-client-catchcopy/mainwindow.h
new file mode 100644
index 0000000..d2dca25
--- /dev/null
+++ b/test-client-catchcopy/mainwindow.h
@@ -0,0 +1,68 @@
+#ifndef MAINWINDOW_H
+#define MAINWINDOW_H
+
+#include <QMainWindow>
+#include <QTime>
+#include <QStringList>
+#include <QList>
+
+#include "catchcopy-api-0002/ClientCatchcopy.h"
+
+namespace Ui {
+ class MainWindow;
+}
+
+class MainWindow : public QMainWindow
+{
+ Q_OBJECT
+ public:
+ explicit MainWindow(QWidget *parent = 0);
+ ~MainWindow();
+ protected:
+ void changeEvent(QEvent *e);
+ private:
+ Ui::MainWindow *ui;
+ ClientCatchcopy client;
+ /// \brief Structure of plugins
+ struct Command
+ {
+ QTime sendTime;
+ quint32 orderId;
+ QStringList sendList;
+ bool replied;
+ QTime replyTime;
+ quint32 returnCode;
+ QStringList returnList;
+ };
+ typedef struct Command Command;
+ QList<Command> CommandList;
+ void addCommand(int orderId);
+ private slots:
+ void connected();
+ void disconnected();
+ void tryConnect();
+ void tryDisconnect();
+ void errorSocket(QLocalSocket::LocalSocketError socketError);
+ void on_actionDisconnect_triggered();
+ void on_actionConnect_triggered();
+ void on_RawSendRemove_clicked();
+ void on_RawSendAdd_clicked();
+ void on_sendProtocol_clicked();
+ void on_sendRawList_clicked();
+ void stateChanged(QLocalSocket::LocalSocketState socketState);
+ void dataSend(quint32 orderId,QStringList data);
+ void on_listCommand_itemSelectionChanged();
+ void newReply(quint32 orderId,quint32 returnCode,QStringList returnList);
+ void on_pushButtonAskServerName_clicked();
+ void on_pushButtonClientName_clicked();
+ void on_pushButtonProtocolName_clicked();
+ void on_pushButtonProtocolNameVersion_clicked();
+ void on_pushButtonCopyAdd_clicked();
+ void on_pushButtonCopyRemove_clicked();
+ void on_pushButtonCopyWithoutDestination_clicked();
+ void on_pushButtonCopyWithDestination_clicked();
+ void error(QString error);
+ void on_listCommandListSended_itemSelectionChanged();
+};
+
+#endif // MAINWINDOW_H
diff --git a/test-client-catchcopy/mainwindow.ui b/test-client-catchcopy/mainwindow.ui
new file mode 100644
index 0000000..5b17ee7
--- /dev/null
+++ b/test-client-catchcopy/mainwindow.ui
@@ -0,0 +1,441 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>MainWindow</class>
+ <widget class="QMainWindow" name="MainWindow">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>569</width>
+ <height>864</height>
+ </rect>
+ </property>
+ <property name="windowTitle">
+ <string>Test client catchcopy</string>
+ </property>
+ <property name="windowIcon">
+ <iconset resource="resources.qrc">
+ <normaloff>:/images/main.png</normaloff>:/images/main.png</iconset>
+ </property>
+ <widget class="QWidget" name="centralWidget">
+ <layout class="QVBoxLayout" name="verticalLayout_7">
+ <item>
+ <layout class="QHBoxLayout" name="horizontalLayout">
+ <item>
+ <widget class="QGroupBox" name="groupBoxRawSend">
+ <property name="maximumSize">
+ <size>
+ <width>300</width>
+ <height>16777215</height>
+ </size>
+ </property>
+ <property name="title">
+ <string>Raw send</string>
+ </property>
+ <layout class="QVBoxLayout" name="verticalLayout_2">
+ <item>
+ <layout class="QHBoxLayout" name="horizontalLayout_2">
+ <item>
+ <widget class="QLineEdit" name="lineEditRawSendText">
+ <property name="minimumSize">
+ <size>
+ <width>128</width>
+ <height>0</height>
+ </size>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QPushButton" name="RawSendAdd">
+ <property name="text">
+ <string>+</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QPushButton" name="RawSendRemove">
+ <property name="text">
+ <string>-</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ <item>
+ <widget class="QListWidget" name="listRawSend">
+ <property name="styleSheet">
+ <string notr="true">background-image: url(:/images/upload.png);
+background-position : center;
+background-repeat : no-repeat;
+background-color : #fff;
+background-attachment : fixed;
+</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QPushButton" name="sendRawList">
+ <property name="text">
+ <string>Send</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ <item>
+ <widget class="QGroupBox" name="groupBoxPredefinedFunction">
+ <property name="title">
+ <string>Predefined function</string>
+ </property>
+ <layout class="QGridLayout" name="gridLayout_3">
+ <item row="0" column="0">
+ <widget class="QPushButton" name="sendProtocol">
+ <property name="text">
+ <string>Send protocol</string>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="0">
+ <widget class="QGroupBox" name="groupBox">
+ <property name="title">
+ <string>protocol extension</string>
+ </property>
+ <layout class="QVBoxLayout" name="verticalLayout_4">
+ <item>
+ <widget class="QLabel" name="label_4">
+ <property name="text">
+ <string>Name:</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QLineEdit" name="lineEditProtocolName">
+ <property name="placeholderText">
+ <string>extension</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QPushButton" name="pushButtonProtocolName">
+ <property name="text">
+ <string>Send name</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QLabel" name="label_5">
+ <property name="text">
+ <string>Version:</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QLineEdit" name="lineEditProtocolVersion">
+ <property name="placeholderText">
+ <string>version</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QPushButton" name="pushButtonProtocolNameVersion">
+ <property name="text">
+ <string>Send name and version</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ <item row="2" column="2">
+ <widget class="QGroupBox" name="groupBox_2">
+ <property name="title">
+ <string>Client</string>
+ </property>
+ <layout class="QVBoxLayout" name="verticalLayout_5">
+ <item>
+ <widget class="QLineEdit" name="lineEditClientName">
+ <property name="placeholderText">
+ <string>Test client catchcopy</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QPushButton" name="pushButtonClientName">
+ <property name="text">
+ <string>Send name</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ <item row="0" column="2">
+ <widget class="QPushButton" name="pushButtonAskServerName">
+ <property name="text">
+ <string>Ask server name</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ <item>
+ <layout class="QHBoxLayout" name="horizontalLayout_4">
+ <item>
+ <widget class="QGroupBox" name="groupBoxCopyMove">
+ <property name="title">
+ <string>Copy/Move</string>
+ </property>
+ <layout class="QVBoxLayout" name="verticalLayout_6">
+ <item>
+ <widget class="QComboBox" name="comboBoxCopyType">
+ <item>
+ <property name="text">
+ <string>Copy</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>Move</string>
+ </property>
+ </item>
+ </widget>
+ </item>
+ <item>
+ <widget class="QLabel" name="label_6">
+ <property name="text">
+ <string>Source:</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <layout class="QHBoxLayout" name="horizontalLayout_3">
+ <item>
+ <widget class="QLineEdit" name="lineEditAddCopy"/>
+ </item>
+ <item>
+ <widget class="QPushButton" name="pushButtonCopyAdd">
+ <property name="text">
+ <string>+</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QPushButton" name="pushButtonCopyRemove">
+ <property name="text">
+ <string>-</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ <item>
+ <widget class="QListWidget" name="listWidgetCopy">
+ <property name="maximumSize">
+ <size>
+ <width>16777215</width>
+ <height>50</height>
+ </size>
+ </property>
+ <property name="styleSheet">
+ <string notr="true">background-image: url(:/images/upload.png);
+background-position : center;
+background-repeat : no-repeat;
+background-color : #fff;
+background-attachment : fixed;</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QPushButton" name="pushButtonCopyWithoutDestination">
+ <property name="text">
+ <string>Send without destination</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QLabel" name="label_7">
+ <property name="text">
+ <string>Destination:</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QLineEdit" name="lineEditCopyDestination"/>
+ </item>
+ <item>
+ <widget class="QPushButton" name="pushButtonCopyWithDestination">
+ <property name="text">
+ <string>Send with destination</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ <item>
+ <widget class="QGroupBox" name="groupBox_3">
+ <property name="title">
+ <string>Error</string>
+ </property>
+ <layout class="QVBoxLayout" name="verticalLayout_3">
+ <item>
+ <widget class="QListWidget" name="listError"/>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ <item>
+ <widget class="QGroupBox" name="groupBoxRaw">
+ <property name="title">
+ <string>Raw</string>
+ </property>
+ <layout class="QGridLayout" name="gridLayout_2">
+ <item row="0" column="1">
+ <widget class="QLabel" name="label">
+ <property name="text">
+ <string>Command</string>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="2">
+ <widget class="QLabel" name="label_2">
+ <property name="text">
+ <string>Sended</string>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="2">
+ <widget class="QListWidget" name="listCommandListSended">
+ <property name="enabled">
+ <bool>false</bool>
+ </property>
+ <property name="styleSheet">
+ <string notr="true">background-image: url(:/images/upload.png);
+background-position : center;
+background-repeat : no-repeat;
+background-color : #fff;
+background-attachment : fixed;
+</string>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="3">
+ <widget class="QLabel" name="label_3">
+ <property name="text">
+ <string>Reply</string>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="3">
+ <layout class="QVBoxLayout" name="verticalLayout">
+ <item>
+ <widget class="QLineEdit" name="lineReplyCode">
+ <property name="enabled">
+ <bool>false</bool>
+ </property>
+ <property name="readOnly">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QTimeEdit" name="timeEditReply">
+ <property name="readOnly">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QListWidget" name="listReplyList">
+ <property name="enabled">
+ <bool>false</bool>
+ </property>
+ <property name="styleSheet">
+ <string notr="true">background-image: url(:/images/download.png);
+background-position : center;
+background-repeat : no-repeat;
+background-color : #fff;
+background-attachment : fixed;
+</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ <item row="2" column="1">
+ <widget class="QListWidget" name="listCommand">
+ <property name="minimumSize">
+ <size>
+ <width>0</width>
+ <height>200</height>
+ </size>
+ </property>
+ <property name="styleSheet">
+ <string notr="true">background-image: url(:/images/tools-report-bug.png);
+background-position : center;
+background-repeat : no-repeat;
+background-color : #fff;
+background-attachment : fixed;
+</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ <widget class="QToolBar" name="mainToolBar">
+ <property name="iconSize">
+ <size>
+ <width>48</width>
+ <height>48</height>
+ </size>
+ </property>
+ <property name="toolButtonStyle">
+ <enum>Qt::ToolButtonTextBesideIcon</enum>
+ </property>
+ <attribute name="toolBarArea">
+ <enum>TopToolBarArea</enum>
+ </attribute>
+ <attribute name="toolBarBreak">
+ <bool>false</bool>
+ </attribute>
+ <addaction name="actionConnect"/>
+ <addaction name="actionDisconnect"/>
+ </widget>
+ <widget class="QStatusBar" name="statusBar"/>
+ <action name="actionConnect">
+ <property name="icon">
+ <iconset resource="resources.qrc">
+ <normaloff>:/images/dialog-ok-apply.png</normaloff>:/images/dialog-ok-apply.png</iconset>
+ </property>
+ <property name="text">
+ <string>Connect</string>
+ </property>
+ </action>
+ <action name="actionDisconnect">
+ <property name="enabled">
+ <bool>false</bool>
+ </property>
+ <property name="icon">
+ <iconset resource="resources.qrc">
+ <normaloff>:/images/process-stop.png</normaloff>:/images/process-stop.png</iconset>
+ </property>
+ <property name="text">
+ <string>Disconnect</string>
+ </property>
+ </action>
+ </widget>
+ <layoutdefault spacing="6" margin="11"/>
+ <resources>
+ <include location="resources.qrc"/>
+ </resources>
+ <connections/>
+</ui>
diff --git a/test-client-catchcopy/resources-windows.rc b/test-client-catchcopy/resources-windows.rc
new file mode 100755
index 0000000..9ca49be
--- /dev/null
+++ b/test-client-catchcopy/resources-windows.rc
@@ -0,0 +1,2 @@
+IDI_ICON1 ICON DISCARDABLE "icon.ico"
+
diff --git a/test-client-catchcopy/resources.qrc b/test-client-catchcopy/resources.qrc
new file mode 100644
index 0000000..061e445
--- /dev/null
+++ b/test-client-catchcopy/resources.qrc
@@ -0,0 +1,10 @@
+<RCC>
+ <qresource prefix="/">
+ <file>images/dialog-ok-apply.png</file>
+ <file>images/download.png</file>
+ <file>images/main.png</file>
+ <file>images/process-stop.png</file>
+ <file>images/upload.png</file>
+ <file>images/tools-report-bug.png</file>
+ </qresource>
+</RCC>
diff --git a/test-client-catchcopy/test-client-catchcopy.pro b/test-client-catchcopy/test-client-catchcopy.pro
new file mode 100644
index 0000000..40b9567
--- /dev/null
+++ b/test-client-catchcopy/test-client-catchcopy.pro
@@ -0,0 +1,24 @@
+#-------------------------------------------------
+#
+# Project created by QtCreator 2010-11-14T13:02:19
+#
+#-------------------------------------------------
+
+QT += core gui network widgets
+
+TARGET = test-client-catchcopy
+TEMPLATE = app
+
+
+SOURCES += main.cpp\
+ mainwindow.cpp \
+ catchcopy-api-0002/ClientCatchcopy.cpp \
+ catchcopy-api-0002/ExtraSocketCatchcopy.cpp
+
+HEADERS += mainwindow.h \
+ catchcopy-api-0002/ClientCatchcopy.h \
+ catchcopy-api-0002/ExtraSocketCatchcopy.h
+
+FORMS += mainwindow.ui
+win32:RC_FILE += resources-windows.rc
+RESOURCES += resources.qrc