initial commit
This commit is contained in:
commit
40a3dd027f
9
.gitignore
vendored
Normal file
9
.gitignore
vendored
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
Makefile
|
||||||
|
Doxyfile
|
||||||
|
*.kdevelop
|
||||||
|
*.kdevelop.pcs
|
||||||
|
*.kdevses
|
||||||
|
*~
|
||||||
|
mumodel
|
||||||
|
build
|
||||||
|
ui
|
87
cconnectiondialog.cpp
Normal file
87
cconnectiondialog.cpp
Normal file
@ -0,0 +1,87 @@
|
|||||||
|
/***************************************************************************
|
||||||
|
* Copyright (C) 2008 by Oliver Groß *
|
||||||
|
* z.o.gross@gmx.de *
|
||||||
|
* *
|
||||||
|
* This program is free software; you can redistribute it and/or modify *
|
||||||
|
* it under the terms of the GNU General Public License as published by *
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or *
|
||||||
|
* (at your option) any later version. *
|
||||||
|
* *
|
||||||
|
* This program is distributed in the hope that it will be useful, *
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||||
|
* GNU General Public License for more details. *
|
||||||
|
* *
|
||||||
|
* You should have received a copy of the GNU General Public License *
|
||||||
|
* along with this program; if not, write to the *
|
||||||
|
* Free Software Foundation, Inc., *
|
||||||
|
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
||||||
|
***************************************************************************/
|
||||||
|
#include "cconnectiondialog.h"
|
||||||
|
#include <QDialogButtonBox>
|
||||||
|
#include <QLabel>
|
||||||
|
#include <QLineEdit>
|
||||||
|
#include <QSpinBox>
|
||||||
|
#include <QFormLayout>
|
||||||
|
#include <QVBoxLayout>
|
||||||
|
#include <QMessageBox>
|
||||||
|
|
||||||
|
namespace qftrans {
|
||||||
|
CConnectionDialog::CConnectionDialog(QWidget * parent, Qt::WindowFlags f) : QDialog(parent, f) {
|
||||||
|
setupUi();
|
||||||
|
}
|
||||||
|
|
||||||
|
CConnectionDialog::~CConnectionDialog() {
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CConnectionDialog::execute(bool isServer) {
|
||||||
|
m_HostEdit->setEnabled(!isServer);
|
||||||
|
m_HostLabel->setEnabled(!isServer);
|
||||||
|
|
||||||
|
if (m_HostEdit->text().isEmpty())
|
||||||
|
m_HostEdit->setText("localhost");
|
||||||
|
return exec();
|
||||||
|
}
|
||||||
|
|
||||||
|
QString CConnectionDialog::host() { return m_HostEdit->text(); }
|
||||||
|
quint16 CConnectionDialog::port() { return (quint16)m_PortEdit->value(); }
|
||||||
|
|
||||||
|
inline void CConnectionDialog::setupUi() {
|
||||||
|
m_HostEdit = new QLineEdit(this);
|
||||||
|
m_HostLabel = new QLabel(tr("&Host"), this);
|
||||||
|
m_HostLabel->setBuddy(m_HostEdit);
|
||||||
|
|
||||||
|
m_PortEdit = new QSpinBox(this);
|
||||||
|
m_PortEdit->setMinimum(0);
|
||||||
|
m_PortEdit->setMaximum(65535);
|
||||||
|
m_PortEdit->setValue(8899);
|
||||||
|
m_PortLabel = new QLabel(tr("&Port"), this);
|
||||||
|
m_PortLabel->setBuddy(m_PortLabel);
|
||||||
|
|
||||||
|
QDialogButtonBox * buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel, Qt::Horizontal, this);
|
||||||
|
|
||||||
|
QFormLayout * formLayout = new QFormLayout();
|
||||||
|
formLayout->addRow(m_HostLabel, m_HostEdit);
|
||||||
|
formLayout->addRow(m_PortLabel, m_PortEdit);
|
||||||
|
|
||||||
|
QVBoxLayout * mainLayout = new QVBoxLayout();
|
||||||
|
mainLayout->addLayout(formLayout);
|
||||||
|
mainLayout->addWidget(buttonBox);
|
||||||
|
|
||||||
|
setLayout(mainLayout);
|
||||||
|
|
||||||
|
connect(buttonBox, SIGNAL(accepted()), this, SLOT(checkHost()));
|
||||||
|
connect(buttonBox, SIGNAL(rejected()), this, SLOT(reject()));
|
||||||
|
}
|
||||||
|
|
||||||
|
void CConnectionDialog::checkHost() {
|
||||||
|
if (m_HostEdit->isEnabled()) {
|
||||||
|
if (m_HostEdit->text().isEmpty())
|
||||||
|
QMessageBox::warning(this, tr("Invalid host"), tr("You have to specify a host name/address."));
|
||||||
|
else
|
||||||
|
accept();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
accept();
|
||||||
|
}
|
||||||
|
}
|
55
cconnectiondialog.h
Normal file
55
cconnectiondialog.h
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
/***************************************************************************
|
||||||
|
* Copyright (C) 2008 by Oliver Groß *
|
||||||
|
* z.o.gross@gmx.de *
|
||||||
|
* *
|
||||||
|
* This program is free software; you can redistribute it and/or modify *
|
||||||
|
* it under the terms of the GNU General Public License as published by *
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or *
|
||||||
|
* (at your option) any later version. *
|
||||||
|
* *
|
||||||
|
* This program is distributed in the hope that it will be useful, *
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||||
|
* GNU General Public License for more details. *
|
||||||
|
* *
|
||||||
|
* You should have received a copy of the GNU General Public License *
|
||||||
|
* along with this program; if not, write to the *
|
||||||
|
* Free Software Foundation, Inc., *
|
||||||
|
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
||||||
|
***************************************************************************/
|
||||||
|
#ifndef QFTRANSCCONNECTIONDIALOG_H
|
||||||
|
#define QFTRANSCCONNECTIONDIALOG_H
|
||||||
|
|
||||||
|
#include <QDialog>
|
||||||
|
|
||||||
|
class QLineEdit;
|
||||||
|
class QSpinBox;
|
||||||
|
class QLabel;
|
||||||
|
|
||||||
|
namespace qftrans {
|
||||||
|
/**
|
||||||
|
@author Oliver Groß <z.o.gross@gmx.de>
|
||||||
|
*/
|
||||||
|
class CConnectionDialog : public QDialog {
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
CConnectionDialog(QWidget * parent = 0, Qt::WindowFlags f = 0);
|
||||||
|
~CConnectionDialog();
|
||||||
|
|
||||||
|
bool execute(bool isServer);
|
||||||
|
|
||||||
|
QString host();
|
||||||
|
quint16 port();
|
||||||
|
private:
|
||||||
|
QLabel * m_HostLabel;
|
||||||
|
QLabel * m_PortLabel;
|
||||||
|
QLineEdit * m_HostEdit;
|
||||||
|
QSpinBox * m_PortEdit;
|
||||||
|
|
||||||
|
inline void setupUi();
|
||||||
|
private slots:
|
||||||
|
void checkHost();
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
63
common.h
Normal file
63
common.h
Normal file
@ -0,0 +1,63 @@
|
|||||||
|
/***************************************************************************
|
||||||
|
* Copyright (C) 2008 by Oliver Groß *
|
||||||
|
* z.o.gross@gmx.de *
|
||||||
|
* *
|
||||||
|
* This program is free software; you can redistribute it and/or modify *
|
||||||
|
* it under the terms of the GNU General Public License as published by *
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or *
|
||||||
|
* (at your option) any later version. *
|
||||||
|
* *
|
||||||
|
* This program is distributed in the hope that it will be useful, *
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||||
|
* GNU General Public License for more details. *
|
||||||
|
* *
|
||||||
|
* You should have received a copy of the GNU General Public License *
|
||||||
|
* along with this program; if not, write to the *
|
||||||
|
* Free Software Foundation, Inc., *
|
||||||
|
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
||||||
|
***************************************************************************/
|
||||||
|
#include <QList>
|
||||||
|
#include <QHash>
|
||||||
|
|
||||||
|
#ifndef QFTRANS_COMMON_H
|
||||||
|
#define QFTRANS_COMMON_H
|
||||||
|
|
||||||
|
#define RAWPACKET_SIZE 9
|
||||||
|
#define DATA_BLOCK_SIZE 256
|
||||||
|
#define DESCRIPTOR_STRING "QFTH"
|
||||||
|
|
||||||
|
namespace qftrans {
|
||||||
|
enum TransferStatus {TS_WAITING = 0, TS_ANNOUNCING = 1, TS_TRANSFERING = 2, TS_CLOSING = 3, TS_FINISHED = 4};
|
||||||
|
enum HeaderType {HT_ID = 0, HT_SIZE = 1, HT_NAME = 2, HT_DATA = 3, HT_CLOSE = 4, HT_ACK = 5, HT_CANCEL = 6};
|
||||||
|
|
||||||
|
struct TransferData {
|
||||||
|
QString fileDir;
|
||||||
|
QString fileName;
|
||||||
|
TransferStatus status;
|
||||||
|
bool localFile;
|
||||||
|
qint64 size;
|
||||||
|
qint64 transfered;
|
||||||
|
HeaderType lastHeader;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct TransferHeader {
|
||||||
|
char descriptor[5];
|
||||||
|
quint8 type;
|
||||||
|
quint32 id;
|
||||||
|
quint32 length;
|
||||||
|
TransferHeader() {
|
||||||
|
descriptor[0] = 'Q';
|
||||||
|
descriptor[1] = 'F';
|
||||||
|
descriptor[2] = 'T';
|
||||||
|
descriptor[3] = 'H';
|
||||||
|
descriptor[4] = 0;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef QList<TransferData *> QTransferDataList;
|
||||||
|
typedef QHash<quint32, TransferData *> QTransferDataHash;
|
||||||
|
typedef QHash<TransferData *, quint32> QTransferIdHash;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
169
crecievethread.cpp
Normal file
169
crecievethread.cpp
Normal file
@ -0,0 +1,169 @@
|
|||||||
|
/***************************************************************************
|
||||||
|
* Copyright (C) 2008 by Oliver Groß *
|
||||||
|
* z.o.gross@gmx.de *
|
||||||
|
* *
|
||||||
|
* This program is free software; you can redistribute it and/or modify *
|
||||||
|
* it under the terms of the GNU General Public License as published by *
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or *
|
||||||
|
* (at your option) any later version. *
|
||||||
|
* *
|
||||||
|
* This program is distributed in the hope that it will be useful, *
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||||
|
* GNU General Public License for more details. *
|
||||||
|
* *
|
||||||
|
* You should have received a copy of the GNU General Public License *
|
||||||
|
* along with this program; if not, write to the *
|
||||||
|
* Free Software Foundation, Inc., *
|
||||||
|
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
||||||
|
***************************************************************************/
|
||||||
|
#include "crecievethread.h"
|
||||||
|
#include <QTcpSocket>
|
||||||
|
#include <QByteArray>
|
||||||
|
#include <QDataStream>
|
||||||
|
#include <QFile>
|
||||||
|
#include <QDir>
|
||||||
|
|
||||||
|
namespace qftrans {
|
||||||
|
CRecieveThread::CRecieveThread(QString & destinationDir, QTcpSocket * socket, QObject * parent) :
|
||||||
|
QThread(parent), m_Socket(socket), m_DestinationDir(destinationDir)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
CRecieveThread::~CRecieveThread() {
|
||||||
|
}
|
||||||
|
|
||||||
|
void CRecieveThread::setDestinationDir(QString & value) {
|
||||||
|
m_DestinationDir = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO removeDownload(...)
|
||||||
|
void CRecieveThread::removeDownload(TransferData * /*data*/) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void CRecieveThread::readData() {
|
||||||
|
QDataStream in(m_Socket);
|
||||||
|
in.setVersion(QDataStream::Qt_4_0);
|
||||||
|
|
||||||
|
if (m_Socket->bytesAvailable() >= (qint64)(sizeof(TransferHeader))) {
|
||||||
|
in.readRawData((char *)(&m_LastHeader), sizeof(TransferHeader));
|
||||||
|
m_LastHeaderValid = (qstrcmp(m_LastHeader.descriptor, DESCRIPTOR_STRING) == 0);
|
||||||
|
|
||||||
|
qDebug() << "got header" << m_LastHeader.type;
|
||||||
|
if (m_LastHeaderValid)
|
||||||
|
qDebug() << "valid";
|
||||||
|
else
|
||||||
|
qDebug() << "invalid";
|
||||||
|
qDebug() << "id" << m_LastHeader.id;
|
||||||
|
qDebug() << "length" << m_LastHeader.length;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
m_LastHeaderValid = false;
|
||||||
|
|
||||||
|
TransferData * target = NULL;
|
||||||
|
|
||||||
|
while (m_LastHeaderValid) {
|
||||||
|
qDebug() << "available Bytes" << m_Socket->bytesAvailable();
|
||||||
|
if (m_Socket->bytesAvailable() >= m_LastHeader.length) {
|
||||||
|
//look for existing id
|
||||||
|
if (m_LastHeader.type == HT_ACK) {
|
||||||
|
qDebug() << "got HT_ACK .. requesting to start upload";
|
||||||
|
emit uploadStartRequest(m_LastHeader.id);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (m_DataDict.contains(m_LastHeader.id)) {
|
||||||
|
if (m_LastHeader.type == HT_CLOSE) {
|
||||||
|
//finished or canceled by peer
|
||||||
|
qDebug() << "download closed py peer";
|
||||||
|
emit downloadRemoved(m_DataDict.take(m_LastHeader.id));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
//assign target
|
||||||
|
target = m_DataDict[m_LastHeader.id];
|
||||||
|
}
|
||||||
|
//id not in dict
|
||||||
|
else if (m_LastHeader.type == HT_ID) {
|
||||||
|
//new file announced
|
||||||
|
qDebug() << "download announced";
|
||||||
|
TransferData * newFile = new TransferData;
|
||||||
|
m_DataDict.insert(m_LastHeader.id, newFile);
|
||||||
|
newFile->transfered = 0;
|
||||||
|
newFile->size = 0;
|
||||||
|
newFile->localFile = false;
|
||||||
|
newFile->status = TS_WAITING;
|
||||||
|
newFile->fileDir = m_DestinationDir;
|
||||||
|
}
|
||||||
|
|
||||||
|
//check valid target and data available
|
||||||
|
if (target && m_LastHeader.length) {
|
||||||
|
switch (m_LastHeader.type) {
|
||||||
|
case HT_ID:
|
||||||
|
target->status = TS_WAITING;
|
||||||
|
QFile::remove(target->fileDir + QDir::separator() + target->fileName);
|
||||||
|
emit downloadUpdated(target);
|
||||||
|
break;
|
||||||
|
case HT_SIZE:
|
||||||
|
qDebug() << "reading size..";
|
||||||
|
in >> target->size;
|
||||||
|
qDebug() << "got size:" << target->size;
|
||||||
|
break;
|
||||||
|
case HT_NAME:
|
||||||
|
qDebug() << "reading filename..";
|
||||||
|
in >> target->fileName;
|
||||||
|
qDebug() << "got filename:" << target->fileName;
|
||||||
|
qDebug() << "requesting to send HT_ACK";
|
||||||
|
emit downloadAcknowledged(m_LastHeader.id);
|
||||||
|
break;
|
||||||
|
case HT_DATA: {
|
||||||
|
// qDebug() << "got data" << target->transfered << '/' << target->size;
|
||||||
|
if (target->status == TS_WAITING) {
|
||||||
|
target->status = TS_TRANSFERING;
|
||||||
|
emit downloadAdded(target);
|
||||||
|
}
|
||||||
|
|
||||||
|
char * buffer = new char[m_LastHeader.length];
|
||||||
|
in.readRawData(buffer, m_LastHeader.length);
|
||||||
|
|
||||||
|
// QFile file(target->fileDir + QDir::separator() + target->fileName);
|
||||||
|
// file.open(QIODevice::WriteOnly | QIODevice::Append);
|
||||||
|
// QDataStream out(&file);
|
||||||
|
// out.writeRawData((const char *)(buffer), m_LastHeader.length);
|
||||||
|
target->transfered += m_LastHeader.length;
|
||||||
|
delete[] buffer;
|
||||||
|
|
||||||
|
emit downloadUpdated(target);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
in.skipRawData(m_LastHeader.length);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_Socket->bytesAvailable() >= (qint64)(sizeof(TransferHeader))) {
|
||||||
|
in.readRawData((char *)(&m_LastHeader), sizeof(TransferHeader));
|
||||||
|
m_LastHeaderValid = (qstrcmp(m_LastHeader.descriptor, DESCRIPTOR_STRING) == 0);
|
||||||
|
qDebug() << "got header" << m_LastHeader.type;
|
||||||
|
if (m_LastHeaderValid)
|
||||||
|
qDebug() << "valid";
|
||||||
|
else
|
||||||
|
qDebug() << "invalid";
|
||||||
|
qDebug() << "id" << m_LastHeader.id;
|
||||||
|
qDebug() << "length" << m_LastHeader.length;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
m_LastHeaderValid = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void CRecieveThread::run() {
|
||||||
|
qDebug() << "start reciever thread";
|
||||||
|
connect(m_Socket, SIGNAL(readyRead()), this, SLOT(readData()));
|
||||||
|
exec();
|
||||||
|
disconnect(m_Socket, SIGNAL(readyRead()), this, SLOT(readData()));
|
||||||
|
}
|
||||||
|
}
|
64
crecievethread.h
Normal file
64
crecievethread.h
Normal file
@ -0,0 +1,64 @@
|
|||||||
|
/***************************************************************************
|
||||||
|
* Copyright (C) 2008 by Oliver Groß *
|
||||||
|
* z.o.gross@gmx.de *
|
||||||
|
* *
|
||||||
|
* This program is free software; you can redistribute it and/or modify *
|
||||||
|
* it under the terms of the GNU General Public License as published by *
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or *
|
||||||
|
* (at your option) any later version. *
|
||||||
|
* *
|
||||||
|
* This program is distributed in the hope that it will be useful, *
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||||
|
* GNU General Public License for more details. *
|
||||||
|
* *
|
||||||
|
* You should have received a copy of the GNU General Public License *
|
||||||
|
* along with this program; if not, write to the *
|
||||||
|
* Free Software Foundation, Inc., *
|
||||||
|
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
||||||
|
***************************************************************************/
|
||||||
|
#ifndef QFTRANS_CRECIEVETHREAD_H
|
||||||
|
#define QFTRANS_CRECIEVETHREAD_H
|
||||||
|
|
||||||
|
#include <QThread>
|
||||||
|
#include "common.h"
|
||||||
|
|
||||||
|
class QTcpSocket;
|
||||||
|
|
||||||
|
namespace qftrans {
|
||||||
|
/**
|
||||||
|
@author Oliver Groß <z.o.gross@gmx.de>
|
||||||
|
*/
|
||||||
|
class CRecieveThread : public QThread {
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
CRecieveThread(QString & destinationDir, QTcpSocket * socket, QObject * parent = 0);
|
||||||
|
~CRecieveThread();
|
||||||
|
signals:
|
||||||
|
void downloadAdded(TransferData * data);
|
||||||
|
void downloadRemoved(TransferData * data);
|
||||||
|
void downloadUpdated(TransferData * transfer);
|
||||||
|
|
||||||
|
void downloadAcknowledged(quint32 id);
|
||||||
|
void uploadStartRequest(quint32 id);
|
||||||
|
public slots:
|
||||||
|
void setDestinationDir(QString & value);
|
||||||
|
|
||||||
|
void removeDownload(TransferData * data);
|
||||||
|
protected slots:
|
||||||
|
void readData();
|
||||||
|
protected:
|
||||||
|
QTcpSocket * m_Socket;
|
||||||
|
|
||||||
|
QString m_DestinationDir;
|
||||||
|
|
||||||
|
QTransferDataHash m_DataDict;
|
||||||
|
|
||||||
|
TransferHeader m_LastHeader;
|
||||||
|
bool m_LastHeaderValid;
|
||||||
|
|
||||||
|
void run();
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
217
csendthread.cpp
Normal file
217
csendthread.cpp
Normal file
@ -0,0 +1,217 @@
|
|||||||
|
/***************************************************************************
|
||||||
|
* Copyright (C) 2008 by Oliver Groß *
|
||||||
|
* z.o.gross@gmx.de *
|
||||||
|
* *
|
||||||
|
* This program is free software; you can redistribute it and/or modify *
|
||||||
|
* it under the terms of the GNU General Public License as published by *
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or *
|
||||||
|
* (at your option) any later version. *
|
||||||
|
* *
|
||||||
|
* This program is distributed in the hope that it will be useful, *
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||||
|
* GNU General Public License for more details. *
|
||||||
|
* *
|
||||||
|
* You should have received a copy of the GNU General Public License *
|
||||||
|
* along with this program; if not, write to the *
|
||||||
|
* Free Software Foundation, Inc., *
|
||||||
|
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
||||||
|
***************************************************************************/
|
||||||
|
#include "csenderthread.h"
|
||||||
|
#include <QTcpSocket>
|
||||||
|
#include <QByteArray>
|
||||||
|
#include <QDataStream>
|
||||||
|
#include <QFile>
|
||||||
|
|
||||||
|
namespace qftrans {
|
||||||
|
CSenderThread::CSenderThread(QTcpSocket * socket, QObject * parent) : QThread(parent), m_Socket(socket), m_IdCounter(0) {
|
||||||
|
}
|
||||||
|
|
||||||
|
CSenderThread::~CSenderThread() {
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSenderThread::addUpload(TransferData * upload) {
|
||||||
|
if (!m_DataDict.contains(upload)) {
|
||||||
|
qDebug() << "adding upload";
|
||||||
|
m_DataDict.insert(upload, m_IdCounter);
|
||||||
|
m_IdCounter++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSenderThread::removeUpload(TransferData * transfer) {
|
||||||
|
transfer->status = TS_CLOSING;
|
||||||
|
if (m_Socket->bytesToWrite() == 0) {
|
||||||
|
qDebug() << "executing upload";
|
||||||
|
writeData();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSenderThread::startUpload(TransferData * upload) {
|
||||||
|
if (m_DataDict.contains(upload) && upload->status == TS_WAITING) {
|
||||||
|
qDebug() << "scheduling upload for announce";
|
||||||
|
upload->status = TS_ANNOUNCING;
|
||||||
|
if (m_Socket->bytesToWrite() == 0) {
|
||||||
|
qDebug() << "executing upload";
|
||||||
|
writeData();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSenderThread::startUploadData(quint32 id) {
|
||||||
|
TransferData * transfer = m_DataDict.key(id);
|
||||||
|
if (transfer) {
|
||||||
|
qDebug() << "scheduling upload for transfer";
|
||||||
|
transfer->status = TS_TRANSFERING;
|
||||||
|
if (m_Socket->bytesToWrite() == 0) {
|
||||||
|
qDebug() << "executing upload";
|
||||||
|
writeData();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSenderThread::sendAcknowledge(quint32 id) {
|
||||||
|
QByteArray block;
|
||||||
|
QDataStream out(&block, QIODevice::WriteOnly);
|
||||||
|
out.setVersion(QDataStream::Qt_4_0);
|
||||||
|
|
||||||
|
TransferHeader header;
|
||||||
|
// header.descriptor = DESCRIPTOR_STRING;
|
||||||
|
|
||||||
|
header.type = HT_ACK;
|
||||||
|
header.id = id;
|
||||||
|
header.length = 0;
|
||||||
|
|
||||||
|
out.writeRawData((const char *)(&header), sizeof(TransferHeader));
|
||||||
|
|
||||||
|
qDebug() << "sending HT_ACK" << id;
|
||||||
|
|
||||||
|
m_Socket->write(block);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSendThread::writeData() {
|
||||||
|
if (m_DataDict.isEmpty())
|
||||||
|
exit();
|
||||||
|
|
||||||
|
QByteArray block;
|
||||||
|
QDataStream out(&block, QIODevice::ReadWrite);
|
||||||
|
out.setVersion(QDataStream::Qt_4_0);
|
||||||
|
|
||||||
|
QTransferDataList transfers = m_DataDict.keys();
|
||||||
|
QTransferDataList::iterator i;
|
||||||
|
for (i = transfers.begin(); i != transfers.end(); ++i) {
|
||||||
|
block.clear();
|
||||||
|
|
||||||
|
TransferHeader header;
|
||||||
|
// header.descriptor = DESCRIPTOR_STRING;
|
||||||
|
switch ((*i)->status) {
|
||||||
|
case TS_ANNOUNCING: {
|
||||||
|
qDebug() << "announcing" << m_DataDict[*i];
|
||||||
|
if ((*i)->transfered)
|
||||||
|
(*i)->transfered = 0;
|
||||||
|
|
||||||
|
// ID header with no data
|
||||||
|
header.type = HT_ID;
|
||||||
|
header.id = m_DataDict[*i];
|
||||||
|
header.length = 0;
|
||||||
|
|
||||||
|
out.writeRawData((const char *)(&header), sizeof(TransferHeader));
|
||||||
|
|
||||||
|
//size header with size
|
||||||
|
header.type = HT_SIZE;
|
||||||
|
header.length = sizeof(qint64);
|
||||||
|
|
||||||
|
out.writeRawData((const char *)(&header), sizeof(TransferHeader));
|
||||||
|
|
||||||
|
qDebug() << "sending size" << (*i)->size;
|
||||||
|
out << (*i)->size;
|
||||||
|
|
||||||
|
//name header with file name
|
||||||
|
|
||||||
|
qint64 oldPosition = block.size();
|
||||||
|
|
||||||
|
//fake write filename
|
||||||
|
out << (*i)->fileName;
|
||||||
|
out.device()->seek(oldPosition);
|
||||||
|
|
||||||
|
header.type = HT_NAME;
|
||||||
|
header.length = quint32(block.size() - oldPosition);
|
||||||
|
|
||||||
|
// qDebug() << "pos" << out.device()->pos() << block.size();
|
||||||
|
out.writeRawData((const char *)(&header), sizeof(TransferHeader));
|
||||||
|
// qDebug() << "pos post header" << out.device()->pos() << block.size();
|
||||||
|
|
||||||
|
// qint64 oldPosition = block.size() - sizeof(quint32);
|
||||||
|
|
||||||
|
qDebug() << "sending filename" << (*i)->fileName;
|
||||||
|
out << (*i)->fileName;
|
||||||
|
// qDebug() << "pos post filename" << out.device()->pos() << block.size();
|
||||||
|
// out.device()->seek(oldPosition);
|
||||||
|
// qDebug() << "pos post seek" << out.device()->pos();
|
||||||
|
|
||||||
|
|
||||||
|
/* qDebug() << "filename data length" << header.length;
|
||||||
|
out << header.length;
|
||||||
|
out.device()->seek(oldPosition);
|
||||||
|
out >> header.length;
|
||||||
|
qDebug() << "written length" << header.length;
|
||||||
|
out.device()->seek(block.size());
|
||||||
|
qDebug() << "pos post length correct" << out.device()->pos() << block.size();*/
|
||||||
|
|
||||||
|
(*i)->status = TS_WAITING;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case TS_TRANSFERING: {
|
||||||
|
// qDebug() << "transfering" << m_DataDict[*i];
|
||||||
|
header.type = HT_DATA;
|
||||||
|
header.id = m_DataDict[*i];
|
||||||
|
if ((*i)->transfered + DATA_BLOCK_SIZE < (*i)->size)
|
||||||
|
header.length = DATA_BLOCK_SIZE;
|
||||||
|
else
|
||||||
|
header.length = (*i)->size - (*i)->transfered;
|
||||||
|
|
||||||
|
out.writeRawData((const char *)(&header), sizeof(TransferHeader));
|
||||||
|
|
||||||
|
char * buffer = new char[header.length];
|
||||||
|
|
||||||
|
QFile file((*i)->fileDir + (*i)->fileName);
|
||||||
|
file.open(QIODevice::ReadOnly);
|
||||||
|
QDataStream in(&file);
|
||||||
|
in.readRawData(buffer, header.length);
|
||||||
|
|
||||||
|
out.writeRawData((const char *)(buffer), header.length);
|
||||||
|
(*i)->transfered += header.length;
|
||||||
|
delete[] buffer;
|
||||||
|
|
||||||
|
if ((*i)->transfered >= (*i)->size)
|
||||||
|
(*i)->status = TS_CLOSING;
|
||||||
|
|
||||||
|
emit uploadUpdated(*i);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case TS_CLOSING:
|
||||||
|
header.type = HT_CLOSE;
|
||||||
|
header.id = m_DataDict[*i];
|
||||||
|
header.length = 0;
|
||||||
|
|
||||||
|
out.writeRawData((const char *)(&header), sizeof(TransferHeader));
|
||||||
|
|
||||||
|
(*i)->status = TS_FINISHED;
|
||||||
|
|
||||||
|
m_DataDict.remove(*i);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (!block.isEmpty())
|
||||||
|
m_Socket->write(block);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSendThread::run() {
|
||||||
|
qDebug() << "start sender thread";
|
||||||
|
connect(m_Socket, SIGNAL(bytesWritten(qint64)), this, SLOT(writeData()));
|
||||||
|
exec();
|
||||||
|
disconnect(m_Socket, SIGNAL(bytesWritten(qint64)), this, SLOT(writeData()));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
61
csendthread.h
Normal file
61
csendthread.h
Normal file
@ -0,0 +1,61 @@
|
|||||||
|
/***************************************************************************
|
||||||
|
* Copyright (C) 2008 by Oliver Groß *
|
||||||
|
* z.o.gross@gmx.de *
|
||||||
|
* *
|
||||||
|
* This program is free software; you can redistribute it and/or modify *
|
||||||
|
* it under the terms of the GNU General Public License as published by *
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or *
|
||||||
|
* (at your option) any later version. *
|
||||||
|
* *
|
||||||
|
* This program is distributed in the hope that it will be useful, *
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||||
|
* GNU General Public License for more details. *
|
||||||
|
* *
|
||||||
|
* You should have received a copy of the GNU General Public License *
|
||||||
|
* along with this program; if not, write to the *
|
||||||
|
* Free Software Foundation, Inc., *
|
||||||
|
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
||||||
|
***************************************************************************/
|
||||||
|
#ifndef QFTRANS_CSENDERTHREAD_H
|
||||||
|
#define QFTRANS_CSENDERTHREAD_H
|
||||||
|
|
||||||
|
#include <QThread>
|
||||||
|
#include "common.h"
|
||||||
|
|
||||||
|
class QTcpSocket;
|
||||||
|
|
||||||
|
namespace qftrans {
|
||||||
|
|
||||||
|
/**
|
||||||
|
@author Oliver Groß <z.o.gross@gmx.de>
|
||||||
|
*/
|
||||||
|
class CSendThread : public QThread
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
CSendThread(QTcpSocket * socket, QObject * parent = 0);
|
||||||
|
~CSendThread();
|
||||||
|
signals:
|
||||||
|
void uploadUpdated(TransferData * transfer);
|
||||||
|
public slots:
|
||||||
|
void addUpload(TransferData * transfer);
|
||||||
|
void removeUpload(TransferData * transfer);
|
||||||
|
void startUpload(TransferData * transfer);
|
||||||
|
void startUploadData(quint32 id);
|
||||||
|
|
||||||
|
void sendAcknowledge(quint32 id);
|
||||||
|
protected slots:
|
||||||
|
void writeData();
|
||||||
|
protected:
|
||||||
|
QTcpSocket * m_Socket;
|
||||||
|
|
||||||
|
quint32 m_IdCounter;
|
||||||
|
QTransferIdHash m_DataDict;
|
||||||
|
|
||||||
|
void run();
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
113
csocketmanager.cpp
Normal file
113
csocketmanager.cpp
Normal file
@ -0,0 +1,113 @@
|
|||||||
|
/***************************************************************************
|
||||||
|
* Copyright (C) 2008 by Oliver Groß *
|
||||||
|
* z.o.gross@gmx.de *
|
||||||
|
* *
|
||||||
|
* This program is free software; you can redistribute it and/or modify *
|
||||||
|
* it under the terms of the GNU General Public License as published by *
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or *
|
||||||
|
* (at your option) any later version. *
|
||||||
|
* *
|
||||||
|
* This program is distributed in the hope that it will be useful, *
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||||
|
* GNU General Public License for more details. *
|
||||||
|
* *
|
||||||
|
* You should have received a copy of the GNU General Public License *
|
||||||
|
* along with this program; if not, write to the *
|
||||||
|
* Free Software Foundation, Inc., *
|
||||||
|
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
||||||
|
***************************************************************************/
|
||||||
|
#include "csocketmanager.h"
|
||||||
|
#include "cworker.h"
|
||||||
|
#include <QTcpServer>
|
||||||
|
#include <QThread>
|
||||||
|
|
||||||
|
namespace qftrans {
|
||||||
|
CSocketManager::CSocketManager(QObject * parent) : QObject(parent),
|
||||||
|
m_Server(NULL), m_Socket(NULL), m_Worker(NULL) {
|
||||||
|
}
|
||||||
|
|
||||||
|
CSocketManager::~CSocketManager() {
|
||||||
|
if (m_Socket)
|
||||||
|
delete m_Socket;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSocketManager::setup(bool server, quint16 port, QString & host) {
|
||||||
|
m_Host = host;
|
||||||
|
m_Port = port;
|
||||||
|
|
||||||
|
if (server) {
|
||||||
|
m_Server = new QTcpServer(this); //TODO proper setup server
|
||||||
|
connect(m_Server, SIGNAL(newConnection()), this, SLOT(handleServerConnected()));
|
||||||
|
|
||||||
|
m_Server->listen(QHostAddress(host), port);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
m_Socket = new QTcpSocket(); //TODO proper setup client
|
||||||
|
connect(m_Socket, SIGNAL(connected()), this, SLOT(handleClientConnected()));
|
||||||
|
connect(m_Socket, SIGNAL(disconnected()), this, SLOT(handleDisconnected()));
|
||||||
|
|
||||||
|
m_Socket->connectToHost(host, port);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSocketManager::handleServerConnected() {
|
||||||
|
qDebug() << "srv conn... thread id" << QThread::currentThreadId();
|
||||||
|
|
||||||
|
m_Socket = m_Server->nextPendingConnection();
|
||||||
|
connect(m_Socket, SIGNAL(disconnected()), this, SLOT(handleDisconnected()));
|
||||||
|
|
||||||
|
m_Worker = new CWorker(m_Socket, m_Socket);
|
||||||
|
// emit workerReady(m_Worker);
|
||||||
|
|
||||||
|
emit connectionChanged(true);
|
||||||
|
|
||||||
|
m_Server->close();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSocketManager::handleClientConnected() {
|
||||||
|
qDebug() << "clt conn... thread id" << QThread::currentThreadId();
|
||||||
|
|
||||||
|
m_Worker = new CWorker(m_Socket, m_Socket);
|
||||||
|
|
||||||
|
emit connectionChanged(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSocketManager::handleDisconnected() {
|
||||||
|
qDebug() << "clt/srv disconn.. thread id" << QThread::currentThreadId();
|
||||||
|
/* m_Worker->deleteLater();
|
||||||
|
m_Worker = NULL;*/
|
||||||
|
|
||||||
|
// if (m_ActAsServer) {
|
||||||
|
// m_Socket->deleteLater();
|
||||||
|
// m_Socket = NULL;
|
||||||
|
//
|
||||||
|
// m_Server->listen(, 8899);
|
||||||
|
// emit connectionChanged(false);
|
||||||
|
// }
|
||||||
|
// else {
|
||||||
|
emit connectionChanged(false);
|
||||||
|
|
||||||
|
if (m_Server) {
|
||||||
|
m_Socket->deleteLater();
|
||||||
|
m_Socket = NULL;
|
||||||
|
|
||||||
|
m_Worker = NULL;
|
||||||
|
|
||||||
|
m_Server->listen(QHostAddress(m_Host), m_Port);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
QThread::currentThread()->quit();
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
void CSocketManager::connectToPeer() {
|
||||||
|
if (!m_Server && m_Socket)
|
||||||
|
m_Socket->connectToHost(host, port);
|
||||||
|
}*/
|
||||||
|
|
||||||
|
// void CSocketManager::disconnectFromPeer() {
|
||||||
|
// if (m_Socket)
|
||||||
|
// m_Socket->disconnectFromHost();
|
||||||
|
// }
|
||||||
|
}
|
63
csocketmanager.h
Normal file
63
csocketmanager.h
Normal file
@ -0,0 +1,63 @@
|
|||||||
|
/***************************************************************************
|
||||||
|
* Copyright (C) 2008 by Oliver Groß *
|
||||||
|
* z.o.gross@gmx.de *
|
||||||
|
* *
|
||||||
|
* This program is free software; you can redistribute it and/or modify *
|
||||||
|
* it under the terms of the GNU General Public License as published by *
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or *
|
||||||
|
* (at your option) any later version. *
|
||||||
|
* *
|
||||||
|
* This program is distributed in the hope that it will be useful, *
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||||
|
* GNU General Public License for more details. *
|
||||||
|
* *
|
||||||
|
* You should have received a copy of the GNU General Public License *
|
||||||
|
* along with this program; if not, write to the *
|
||||||
|
* Free Software Foundation, Inc., *
|
||||||
|
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
||||||
|
***************************************************************************/
|
||||||
|
#ifndef QFTRANSCSOCKETMANAGER_H
|
||||||
|
#define QFTRANSCSOCKETMANAGER_H
|
||||||
|
|
||||||
|
#include <QObject>
|
||||||
|
|
||||||
|
class QTcpSocket;
|
||||||
|
class QTcpServer;
|
||||||
|
|
||||||
|
namespace qftrans {
|
||||||
|
class CWorker;
|
||||||
|
|
||||||
|
/**
|
||||||
|
@author Oliver Groß <z.o.gross@gmx.de>
|
||||||
|
*/
|
||||||
|
class CSocketManager : public QObject {
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
CSocketManager(QObject * parent = 0);
|
||||||
|
~CSocketManager();
|
||||||
|
|
||||||
|
CWorker * worker() { return m_Worker; }
|
||||||
|
public slots:
|
||||||
|
void setup(bool server, quint16 port, QString & host);
|
||||||
|
/* void connectToPeer();*/
|
||||||
|
// void disconnectFromPeer();
|
||||||
|
signals:
|
||||||
|
void connectionChanged(bool connected);
|
||||||
|
protected:
|
||||||
|
// bool m_ActAsServer;
|
||||||
|
|
||||||
|
QString m_Host;
|
||||||
|
quint16 m_Port;
|
||||||
|
|
||||||
|
QTcpServer * m_Server;
|
||||||
|
QTcpSocket * m_Socket;
|
||||||
|
CWorker * m_Worker;
|
||||||
|
protected slots:
|
||||||
|
void handleServerConnected();
|
||||||
|
void handleClientConnected();
|
||||||
|
void handleDisconnected();
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
291
ctransfermanager.cpp
Normal file
291
ctransfermanager.cpp
Normal file
@ -0,0 +1,291 @@
|
|||||||
|
/***************************************************************************
|
||||||
|
* Copyright (C) 2008 by Oliver Groß *
|
||||||
|
* z.o.gross@gmx.de *
|
||||||
|
* *
|
||||||
|
* This program is free software; you can redistribute it and/or modify *
|
||||||
|
* it under the terms of the GNU General Public License as published by *
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or *
|
||||||
|
* (at your option) any later version. *
|
||||||
|
* *
|
||||||
|
* This program is distributed in the hope that it will be useful, *
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||||
|
* GNU General Public License for more details. *
|
||||||
|
* *
|
||||||
|
* You should have received a copy of the GNU General Public License *
|
||||||
|
* along with this program; if not, write to the *
|
||||||
|
* Free Software Foundation, Inc., *
|
||||||
|
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
||||||
|
***************************************************************************/
|
||||||
|
#include "ctransfermanager.h"
|
||||||
|
#include "ctransferthread.h"
|
||||||
|
#include "csocketmanager.h"
|
||||||
|
#include "qtransferlistmodel.h"
|
||||||
|
#include "cworker.h"
|
||||||
|
#include "cconnectiondialog.h"
|
||||||
|
|
||||||
|
#include <QDebug>
|
||||||
|
#include <QStatusBar>
|
||||||
|
|
||||||
|
#include <QFileInfo>
|
||||||
|
#include <QDataStream>
|
||||||
|
#include <QTcpServer>
|
||||||
|
#include <QTcpSocket>
|
||||||
|
|
||||||
|
#include <QMenuBar>
|
||||||
|
#include <QMenu>
|
||||||
|
#include <QToolBar>
|
||||||
|
#include <QListView>
|
||||||
|
#include <QFileDialog>
|
||||||
|
#include <QApplication>
|
||||||
|
#include <QMessageBox>
|
||||||
|
|
||||||
|
namespace qftrans {
|
||||||
|
CTransferManager::CTransferManager(QWidget * parent) : QMainWindow(parent),
|
||||||
|
m_ActAsServer(false),
|
||||||
|
m_Connected(false),
|
||||||
|
m_DestinationDir(QDir::homePath()),
|
||||||
|
m_TransferThread(NULL),
|
||||||
|
m_SelectedTransfer(NULL)
|
||||||
|
{
|
||||||
|
setupUi();
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO ~CTransferManager()
|
||||||
|
CTransferManager::~CTransferManager() {
|
||||||
|
cleanupThread();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CTransferManager::openFile() {
|
||||||
|
QStringList files = QFileDialog::getOpenFileNames(this,
|
||||||
|
tr("Select one or more files to open"),
|
||||||
|
QDir::homePath());
|
||||||
|
|
||||||
|
TransferData * newUpload = NULL;
|
||||||
|
QFileInfo fileInfo;
|
||||||
|
|
||||||
|
foreach (QString i, files) {
|
||||||
|
fileInfo.setFile(i);
|
||||||
|
newUpload = new TransferData;
|
||||||
|
newUpload->fileDir = fileInfo.absolutePath();
|
||||||
|
newUpload->fileName = fileInfo.fileName();
|
||||||
|
newUpload->size = fileInfo.size();
|
||||||
|
newUpload->transfered = 0;
|
||||||
|
newUpload->status = TS_WAITING;
|
||||||
|
newUpload->lastHeader = HT_ID;
|
||||||
|
newUpload->localFile = true;
|
||||||
|
|
||||||
|
addTransfer(newUpload);
|
||||||
|
// emit uploadAddRequested(newUpload);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CTransferManager::setDestinationDir() {
|
||||||
|
QString selectedDir = QFileDialog::getExistingDirectory(this, tr("Select a directory to save downloaded files"), m_DestinationDir);
|
||||||
|
if (!selectedDir.isEmpty()) {
|
||||||
|
m_DestinationDir = selectedDir;
|
||||||
|
|
||||||
|
emit destinationDirChanged(m_DestinationDir);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CTransferManager::requestServerThread() {
|
||||||
|
if (!m_ConnectionDialog->execute(true))
|
||||||
|
return;
|
||||||
|
|
||||||
|
createThread();
|
||||||
|
|
||||||
|
m_ActAsServer = true;
|
||||||
|
m_TransferThread->start();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CTransferManager::requestClientThread() {
|
||||||
|
if (!m_ConnectionDialog->execute(false))
|
||||||
|
return;
|
||||||
|
|
||||||
|
createThread();
|
||||||
|
|
||||||
|
m_ActAsServer = false;
|
||||||
|
m_TransferThread->start();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CTransferManager::setupConnection() {
|
||||||
|
connect(m_TransferThread->socketManager(), SIGNAL(connectionChanged(bool)), this, SLOT(updateConnectionState(bool)));
|
||||||
|
|
||||||
|
connect(this, SIGNAL(setupConnectionRequested(bool, quint16, QString &)),
|
||||||
|
m_TransferThread->socketManager(), SLOT(setup(bool, quint16, QString &)));
|
||||||
|
|
||||||
|
QString host = m_ActAsServer ? "0.0.0.0" : m_ConnectionDialog->host();
|
||||||
|
|
||||||
|
emit setupConnectionRequested(m_ActAsServer, m_ConnectionDialog->port(), host);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CTransferManager::cleanupThread() {
|
||||||
|
if (m_TransferThread) {
|
||||||
|
m_TransferThread->quit();
|
||||||
|
m_TransferThread->deleteLater();
|
||||||
|
}
|
||||||
|
m_TransferThread = NULL;
|
||||||
|
statusBar()->showMessage(tr("connected"));
|
||||||
|
}
|
||||||
|
|
||||||
|
void CTransferManager::restartSelected() {
|
||||||
|
emit uploadAddRequested(m_SelectedTransfer);
|
||||||
|
emit uploadRestartRequested(m_SelectedTransfer);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CTransferManager::cancelSelected() {
|
||||||
|
if (m_SelectedTransfer->localFile)
|
||||||
|
emit uploadRemoveRequested(m_SelectedTransfer);
|
||||||
|
else
|
||||||
|
emit downloadRemoveRequested(m_SelectedTransfer);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void CTransferManager::setupUi() {
|
||||||
|
setWindowTitle(tr("QFTrans"));
|
||||||
|
|
||||||
|
QMenu * currentMenu;
|
||||||
|
QToolBar * currentToolBar = addToolBar("Main");
|
||||||
|
|
||||||
|
currentMenu = menuBar()->addMenu(tr("&File"));
|
||||||
|
m_FileOpen = currentMenu->addAction(tr("&Open..."), this, SLOT(openFile()));
|
||||||
|
currentMenu->addAction(tr("Set destination directory..."), this, SLOT(setDestinationDir()));
|
||||||
|
|
||||||
|
currentToolBar->addActions(currentMenu->actions());
|
||||||
|
|
||||||
|
currentMenu->addSeparator();
|
||||||
|
currentMenu->addAction(tr("&Quit"), this, SLOT(close()));
|
||||||
|
|
||||||
|
currentToolBar->addSeparator();
|
||||||
|
|
||||||
|
currentMenu = menuBar()->addMenu(tr("&Connection"));
|
||||||
|
m_ConnectionAsServer = currentMenu->addAction(tr("Act as &server"), this, SLOT(requestServerThread()));
|
||||||
|
m_ConnectionAsClient = currentMenu->addAction(tr("Act as &client"), this, SLOT(requestClientThread()));
|
||||||
|
currentMenu->addSeparator();
|
||||||
|
m_ConnectionDisconnect = currentMenu->addAction(tr("&Disconnect"), this, SLOT(cleanupThread()));
|
||||||
|
|
||||||
|
currentToolBar->addActions(currentMenu->actions());
|
||||||
|
currentToolBar->addSeparator();
|
||||||
|
|
||||||
|
currentMenu = menuBar()->addMenu(tr("&Transfer"));
|
||||||
|
m_TransferRestartAction = currentMenu->addAction(tr("(Re)&Start"), this, SLOT(restartSelected()));
|
||||||
|
m_TransferCancelAction = currentMenu->addAction(tr("&Cancel"), this, SLOT(cancelSelected()));
|
||||||
|
|
||||||
|
m_TransferRestartAction->setEnabled(false);
|
||||||
|
m_TransferCancelAction->setEnabled(false);
|
||||||
|
|
||||||
|
currentToolBar->addActions(currentMenu->actions());
|
||||||
|
|
||||||
|
currentMenu = menuBar()->addMenu(tr("&Help"));
|
||||||
|
currentMenu->addAction(tr("&About"), this, SLOT(about()));
|
||||||
|
currentMenu->addAction(tr("About &Qt"), qApp, SLOT(aboutQt()));
|
||||||
|
|
||||||
|
m_TransferView = new QListView(this);
|
||||||
|
setCentralWidget(m_TransferView);
|
||||||
|
|
||||||
|
QTransferListModel * listModel = new QTransferListModel(&m_Data);
|
||||||
|
|
||||||
|
connect(this, SIGNAL(transferRemoved(TransferData *)), listModel, SIGNAL(layoutChanged()));
|
||||||
|
connect(this, SIGNAL(transferAdded(TransferData *)), listModel, SIGNAL(layoutChanged()));
|
||||||
|
|
||||||
|
m_TransferView->setModel(listModel);
|
||||||
|
|
||||||
|
connect(m_TransferView->selectionModel(), SIGNAL(selectionChanged(const QItemSelection &, const QItemSelection &)),
|
||||||
|
this, SLOT(handleSelectionChanged(const QItemSelection &)));
|
||||||
|
|
||||||
|
updateConnectionState(false);
|
||||||
|
|
||||||
|
m_ConnectionDialog = new CConnectionDialog(this);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void CTransferManager::updateConnectionState(bool connected) {
|
||||||
|
m_Connected = connected;
|
||||||
|
if (connected) {
|
||||||
|
connectToWorker(m_TransferThread->socketManager()->worker());
|
||||||
|
statusBar()->showMessage(tr("connected"));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
statusBar()->showMessage(m_TransferThread ? tr("waiting") : tr("disconnected"));
|
||||||
|
|
||||||
|
m_FileOpen->setEnabled(connected);
|
||||||
|
m_ConnectionAsServer->setDisabled(connected);
|
||||||
|
m_ConnectionAsClient->setDisabled(connected);
|
||||||
|
m_ConnectionDisconnect->setEnabled(connected);
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO cleanup()
|
||||||
|
void CTransferManager::cleanup() {
|
||||||
|
}
|
||||||
|
|
||||||
|
void CTransferManager::connectToWorker(CWorker * worker) {
|
||||||
|
worker->setDestinationDir(m_DestinationDir);
|
||||||
|
|
||||||
|
connect(this, SIGNAL(destinationDirChanged(QString &)), worker, SLOT(setDestinationDir(QString &)));
|
||||||
|
|
||||||
|
connect(worker, SIGNAL(downloadAdded(TransferData *)), this, SLOT(addTransfer(TransferData *)));
|
||||||
|
|
||||||
|
QTransferListModel * model = dynamic_cast<QTransferListModel *>(m_TransferView->model());
|
||||||
|
|
||||||
|
connect(worker, SIGNAL(downloadUpdated(TransferData *)), model, SLOT(updateEntry(TransferData *)));
|
||||||
|
connect(worker, SIGNAL(uploadUpdated(TransferData *)), model, SLOT(updateEntry(TransferData *)));
|
||||||
|
|
||||||
|
connect(this, SIGNAL(uploadAddRequested(TransferData *)), worker, SLOT(addUpload(TransferData *)));
|
||||||
|
connect(this, SIGNAL(uploadRestartRequested(TransferData *)), worker, SLOT(startUpload(TransferData *)));
|
||||||
|
connect(this, SIGNAL(uploadRemoveRequested(TransferData *)), worker, SLOT(removeUpload(TransferData *)));
|
||||||
|
|
||||||
|
connect(this, SIGNAL(downloadRemoveRequested(TransferData *)), worker, SLOT(removeDownload(TransferData *)));
|
||||||
|
}
|
||||||
|
|
||||||
|
void CTransferManager::handleSelectionChanged(const QItemSelection & selected) {
|
||||||
|
QModelIndexList selectedIndexes = selected.indexes();
|
||||||
|
if (selectedIndexes.isEmpty())
|
||||||
|
m_SelectedTransfer = NULL;
|
||||||
|
else
|
||||||
|
m_SelectedTransfer = static_cast<TransferData *>(selectedIndexes[0].internalPointer());
|
||||||
|
|
||||||
|
m_TransferRestartAction->setEnabled(m_SelectedTransfer && m_SelectedTransfer->localFile);
|
||||||
|
m_TransferCancelAction->setEnabled(m_SelectedTransfer && m_SelectedTransfer->status != TS_FINISHED);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CTransferManager::addTransfer(TransferData * transfer) {
|
||||||
|
m_Data << transfer;
|
||||||
|
emit transferAdded(transfer);
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO proper handle removing transfer
|
||||||
|
void CTransferManager::removeTransfer(TransferData * transfer) {
|
||||||
|
int index = m_Data.indexOf(transfer);
|
||||||
|
if (index != -1) {
|
||||||
|
m_Data.removeAt(index);
|
||||||
|
|
||||||
|
emit transferRemoved(transfer);
|
||||||
|
}
|
||||||
|
delete transfer;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void CTransferManager::createThread() {
|
||||||
|
cleanupThread();
|
||||||
|
|
||||||
|
qDebug() << "main thread" << QThread::currentThreadId();
|
||||||
|
m_TransferThread = new CTransferThread();
|
||||||
|
|
||||||
|
connect(m_TransferThread, SIGNAL(terminated()), this, SLOT(cleanupThread()));
|
||||||
|
// connect(m_TransferThread, SIGNAL(finished()), m_TransferThread, SLOT(deleteLater()));
|
||||||
|
|
||||||
|
connect(m_TransferThread, SIGNAL(socketManagerReady()), this, SLOT(setupConnection()));
|
||||||
|
}
|
||||||
|
|
||||||
|
void CTransferManager::updateStatusBar(const QString & message) {
|
||||||
|
if (message.isEmpty()) {
|
||||||
|
if (m_Connected)
|
||||||
|
statusBar()->showMessage(tr("connected"));
|
||||||
|
else
|
||||||
|
statusBar()->showMessage(m_TransferThread ? tr("waiting") : tr("disconnected"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CTransferManager::about() {
|
||||||
|
QMessageBox::about(this, tr("About"), tr("This is a still unfancy \"peer-to-peer\"-like file transfer tool."));
|
||||||
|
}
|
||||||
|
}
|
110
ctransfermanager.h
Normal file
110
ctransfermanager.h
Normal file
@ -0,0 +1,110 @@
|
|||||||
|
/***************************************************************************
|
||||||
|
* Copyright (C) 2008 by Oliver Groß *
|
||||||
|
* z.o.gross@gmx.de *
|
||||||
|
* *
|
||||||
|
* This program is free software; you can redistribute it and/or modify *
|
||||||
|
* it under the terms of the GNU General Public License as published by *
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or *
|
||||||
|
* (at your option) any later version. *
|
||||||
|
* *
|
||||||
|
* This program is distributed in the hope that it will be useful, *
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||||
|
* GNU General Public License for more details. *
|
||||||
|
* *
|
||||||
|
* You should have received a copy of the GNU General Public License *
|
||||||
|
* along with this program; if not, write to the *
|
||||||
|
* Free Software Foundation, Inc., *
|
||||||
|
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
||||||
|
***************************************************************************/
|
||||||
|
#ifndef QFTRANS_CTRANSFERMANAGER_H
|
||||||
|
#define QFTRANS_CTRANSFERMANAGER_H
|
||||||
|
|
||||||
|
#include <QMainWindow>
|
||||||
|
#include "common.h"
|
||||||
|
#include <QItemSelection>
|
||||||
|
// #include <QAbstractSocket>
|
||||||
|
|
||||||
|
class QListView;
|
||||||
|
|
||||||
|
namespace qftrans {
|
||||||
|
class CTransferThread;
|
||||||
|
class CWorker;
|
||||||
|
class CConnectionDialog;
|
||||||
|
|
||||||
|
/**
|
||||||
|
@author Oliver Groß <z.o.gross@gmx.de>
|
||||||
|
*/
|
||||||
|
class CTransferManager : public QMainWindow {
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
CTransferManager(QWidget * parent = 0);
|
||||||
|
~CTransferManager();
|
||||||
|
public slots:
|
||||||
|
void openFile();
|
||||||
|
void setDestinationDir();
|
||||||
|
|
||||||
|
void requestServerThread();
|
||||||
|
void requestClientThread();
|
||||||
|
|
||||||
|
void cleanupThread();
|
||||||
|
|
||||||
|
void restartSelected();
|
||||||
|
void cancelSelected();
|
||||||
|
signals:
|
||||||
|
void transferAdded(TransferData * transfer);
|
||||||
|
void transferRemoved(TransferData * transfer);
|
||||||
|
|
||||||
|
void uploadAddRequested(TransferData * transfer);
|
||||||
|
void uploadRemoveRequested(TransferData * transfer);
|
||||||
|
void uploadRestartRequested(TransferData * transfer);
|
||||||
|
|
||||||
|
void downloadRemoveRequested(TransferData * transfer);
|
||||||
|
|
||||||
|
void destinationDirChanged(QString & value);
|
||||||
|
|
||||||
|
void setupConnectionRequested(bool server, quint16 port, QString & host);
|
||||||
|
private:
|
||||||
|
CConnectionDialog * m_ConnectionDialog;
|
||||||
|
|
||||||
|
QAction * m_FileOpen;
|
||||||
|
QAction * m_ConnectionAsServer;
|
||||||
|
QAction * m_ConnectionAsClient;
|
||||||
|
QAction * m_ConnectionDisconnect;
|
||||||
|
QAction * m_TransferRestartAction;
|
||||||
|
QAction * m_TransferCancelAction;
|
||||||
|
|
||||||
|
bool m_ActAsServer;
|
||||||
|
bool m_Connected;
|
||||||
|
|
||||||
|
QString m_DestinationDir;
|
||||||
|
|
||||||
|
QTransferDataList m_Data;
|
||||||
|
|
||||||
|
CTransferThread * m_TransferThread;
|
||||||
|
|
||||||
|
QListView * m_TransferView;
|
||||||
|
|
||||||
|
TransferData * m_SelectedTransfer;
|
||||||
|
|
||||||
|
void setupUi();
|
||||||
|
|
||||||
|
void removeFileTransfer(TransferData * transfer);
|
||||||
|
void cleanup();
|
||||||
|
|
||||||
|
inline void createThread();
|
||||||
|
private slots:
|
||||||
|
void setupConnection();
|
||||||
|
void connectToWorker(CWorker * worker);
|
||||||
|
void updateConnectionState(bool connected);
|
||||||
|
void handleSelectionChanged(const QItemSelection & selected);
|
||||||
|
|
||||||
|
void addTransfer(TransferData * transfer);
|
||||||
|
void removeTransfer(TransferData * transfer);
|
||||||
|
|
||||||
|
void updateStatusBar(const QString & message);
|
||||||
|
void about();
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
75
ctransferthread.cpp
Normal file
75
ctransferthread.cpp
Normal file
@ -0,0 +1,75 @@
|
|||||||
|
/***************************************************************************
|
||||||
|
* Copyright (C) 2008 by Oliver Groß *
|
||||||
|
* z.o.gross@gmx.de *
|
||||||
|
* *
|
||||||
|
* This program is free software; you can redistribute it and/or modify *
|
||||||
|
* it under the terms of the GNU General Public License as published by *
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or *
|
||||||
|
* (at your option) any later version. *
|
||||||
|
* *
|
||||||
|
* This program is distributed in the hope that it will be useful, *
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||||
|
* GNU General Public License for more details. *
|
||||||
|
* *
|
||||||
|
* You should have received a copy of the GNU General Public License *
|
||||||
|
* along with this program; if not, write to the *
|
||||||
|
* Free Software Foundation, Inc., *
|
||||||
|
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
||||||
|
***************************************************************************/
|
||||||
|
#include "ctransferthread.h"
|
||||||
|
#include "csocketmanager.h"
|
||||||
|
#include <QTcpServer>
|
||||||
|
|
||||||
|
namespace qftrans {
|
||||||
|
CTransferThread::CTransferThread(QObject * parent) : QThread(parent),
|
||||||
|
m_SocketManager(NULL) {
|
||||||
|
}
|
||||||
|
|
||||||
|
CTransferThread::~CTransferThread() {
|
||||||
|
if (m_SocketManager)
|
||||||
|
m_SocketManager->deleteLater();
|
||||||
|
/* if (m_Socket)
|
||||||
|
delete m_Socket;
|
||||||
|
|
||||||
|
if (m_Worker)
|
||||||
|
delete m_Worker;
|
||||||
|
|
||||||
|
if (m_Server)
|
||||||
|
delete m_Server;*/
|
||||||
|
}
|
||||||
|
|
||||||
|
void CTransferThread::run() {
|
||||||
|
qDebug() << "start transfer thread" << currentThreadId();
|
||||||
|
|
||||||
|
m_SocketManager = new CSocketManager();
|
||||||
|
emit socketManagerReady();
|
||||||
|
|
||||||
|
exec();
|
||||||
|
|
||||||
|
qDebug() << "exit transfer thread" << currentThreadId();
|
||||||
|
|
||||||
|
if (m_SocketManager) {
|
||||||
|
delete m_SocketManager;
|
||||||
|
// m_SocketManager->deleteLater();
|
||||||
|
m_SocketManager = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* if (m_Worker) {
|
||||||
|
delete m_Worker;
|
||||||
|
m_Worker = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_Server) {
|
||||||
|
delete m_Server;
|
||||||
|
m_Server = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_Socket) {
|
||||||
|
delete m_Socket;
|
||||||
|
m_Socket = NULL;
|
||||||
|
}*/
|
||||||
|
|
||||||
|
// emit connectionChanged(false);
|
||||||
|
}
|
||||||
|
}
|
50
ctransferthread.h
Normal file
50
ctransferthread.h
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
/***************************************************************************
|
||||||
|
* Copyright (C) 2008 by Oliver Groß *
|
||||||
|
* z.o.gross@gmx.de *
|
||||||
|
* *
|
||||||
|
* This program is free software; you can redistribute it and/or modify *
|
||||||
|
* it under the terms of the GNU General Public License as published by *
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or *
|
||||||
|
* (at your option) any later version. *
|
||||||
|
* *
|
||||||
|
* This program is distributed in the hope that it will be useful, *
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||||
|
* GNU General Public License for more details. *
|
||||||
|
* *
|
||||||
|
* You should have received a copy of the GNU General Public License *
|
||||||
|
* along with this program; if not, write to the *
|
||||||
|
* Free Software Foundation, Inc., *
|
||||||
|
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
||||||
|
***************************************************************************/
|
||||||
|
#ifndef QFTRANS_CTRANSFERTHREAD_H
|
||||||
|
#define QFTRANS_CTRANSFERTHREAD_H
|
||||||
|
|
||||||
|
#include <QThread>
|
||||||
|
#include "common.h"
|
||||||
|
|
||||||
|
namespace qftrans {
|
||||||
|
class CSocketManager;
|
||||||
|
|
||||||
|
/**
|
||||||
|
@author Oliver Groß <z.o.gross@gmx.de>
|
||||||
|
*/
|
||||||
|
class CTransferThread : public QThread {
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
CTransferThread(QObject * parent = 0);
|
||||||
|
|
||||||
|
~CTransferThread();
|
||||||
|
|
||||||
|
// CWorker * worker() { return m_Worker; }
|
||||||
|
CSocketManager * socketManager() { return m_SocketManager; }
|
||||||
|
signals:
|
||||||
|
void socketManagerReady();
|
||||||
|
protected:
|
||||||
|
CSocketManager * m_SocketManager;
|
||||||
|
|
||||||
|
void run();
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
425
cworker.cpp
Normal file
425
cworker.cpp
Normal file
@ -0,0 +1,425 @@
|
|||||||
|
/***************************************************************************
|
||||||
|
* Copyright (C) 2008 by Oliver Groß *
|
||||||
|
* z.o.gross@gmx.de *
|
||||||
|
* *
|
||||||
|
* This program is free software; you can redistribute it and/or modify *
|
||||||
|
* it under the terms of the GNU General Public License as published by *
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or *
|
||||||
|
* (at your option) any later version. *
|
||||||
|
* *
|
||||||
|
* This program is distributed in the hope that it will be useful, *
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||||
|
* GNU General Public License for more details. *
|
||||||
|
* *
|
||||||
|
* You should have received a copy of the GNU General Public License *
|
||||||
|
* along with this program; if not, write to the *
|
||||||
|
* Free Software Foundation, Inc., *
|
||||||
|
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
||||||
|
***************************************************************************/
|
||||||
|
#include "cworker.h"
|
||||||
|
#include <QTcpSocket>
|
||||||
|
#include <QByteArray>
|
||||||
|
#include <QFile>
|
||||||
|
#include <QDir>
|
||||||
|
#include <QThread>
|
||||||
|
|
||||||
|
namespace qftrans {
|
||||||
|
CWorker::CWorker(QTcpSocket * socket, QObject * parent) : QObject(parent), m_Socket(socket), m_IdCounter(0) {
|
||||||
|
connect(m_Socket, SIGNAL(error(QAbstractSocket::SocketError)), this, SLOT(error(QAbstractSocket::SocketError)));
|
||||||
|
connect(m_Socket, SIGNAL(bytesWritten(qint64)), this, SLOT(writeData()), Qt::QueuedConnection);
|
||||||
|
connect(m_Socket, SIGNAL(readyRead()), this, SLOT(readData()), Qt::QueuedConnection);
|
||||||
|
qDebug() << "worker created";
|
||||||
|
}
|
||||||
|
|
||||||
|
CWorker::~CWorker() {
|
||||||
|
qDebug() << "worker removed";
|
||||||
|
}
|
||||||
|
|
||||||
|
//TODO addUpload
|
||||||
|
void CWorker::addUpload(TransferData * transfer) {
|
||||||
|
if (!m_UploadDict.contains(transfer)) {
|
||||||
|
qDebug() << "adding upload";
|
||||||
|
transfer->status = TS_WAITING;
|
||||||
|
m_UploadDict.insert(transfer, m_IdCounter);
|
||||||
|
m_IdCounter++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//TODO removeUpload
|
||||||
|
void CWorker::removeUpload(TransferData * transfer) {
|
||||||
|
if (m_UploadDict.contains(transfer) && transfer->status != TS_WAITING) {
|
||||||
|
transfer->status = TS_CLOSING;
|
||||||
|
if (m_Socket->bytesToWrite() == 0) {
|
||||||
|
qDebug() << "executing upload";
|
||||||
|
writeData();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//TODO startUpload
|
||||||
|
void CWorker::startUpload(TransferData * transfer) {
|
||||||
|
if (m_UploadDict.contains(transfer) && transfer->status == TS_WAITING) {
|
||||||
|
qDebug() << "scheduling upload for announce";
|
||||||
|
transfer->status = TS_ANNOUNCING;
|
||||||
|
if (m_Socket->bytesToWrite() == 0) {
|
||||||
|
qDebug() << "executing upload";
|
||||||
|
writeData();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CWorker::startUploadData(quint32 id) {
|
||||||
|
TransferData * transfer = m_UploadDict.key(id);
|
||||||
|
if (transfer) {
|
||||||
|
qDebug() << "scheduling upload for transfer";
|
||||||
|
transfer->status = TS_TRANSFERING;
|
||||||
|
if (m_Socket->bytesToWrite() == 0) {
|
||||||
|
qDebug() << "executing upload";
|
||||||
|
writeData();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CWorker::sendAcknowledge(quint32 id) {
|
||||||
|
QByteArray block;
|
||||||
|
QDataStream out(&block, QIODevice::WriteOnly);
|
||||||
|
out.setVersion(QDataStream::Qt_4_0);
|
||||||
|
|
||||||
|
TransferHeader header;
|
||||||
|
// header.descriptor = DESCRIPTOR_STRING;
|
||||||
|
|
||||||
|
header.type = HT_ACK;
|
||||||
|
header.id = id;
|
||||||
|
header.length = 0;
|
||||||
|
|
||||||
|
out.writeRawData((const char *)(&header), sizeof(TransferHeader));
|
||||||
|
|
||||||
|
qDebug() << "sending HT_ACK" << id;
|
||||||
|
|
||||||
|
m_Socket->write(block);
|
||||||
|
qDebug() << "sent HT_ACK" << id;
|
||||||
|
}
|
||||||
|
|
||||||
|
//TODO CTransferThread::removeDownload
|
||||||
|
void CWorker::removeDownload(TransferData * /*transfer*/) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void CWorker::setDestinationDir(QString & value) {
|
||||||
|
m_DestinationDir = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CWorker::writeData() {
|
||||||
|
if (m_UploadDict.isEmpty()) {
|
||||||
|
qDebug() << "no more uploads.";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
QByteArray block;
|
||||||
|
QDataStream out(&block, QIODevice::ReadWrite);
|
||||||
|
out.setVersion(QDataStream::Qt_4_0);
|
||||||
|
|
||||||
|
QTransferDataList transfers = m_UploadDict.keys();
|
||||||
|
QTransferDataList::iterator i;
|
||||||
|
for (i = transfers.begin(); i != transfers.end(); ++i) {
|
||||||
|
block.clear();
|
||||||
|
|
||||||
|
TransferHeader header;
|
||||||
|
switch ((*i)->status) {
|
||||||
|
case TS_ANNOUNCING: {
|
||||||
|
qDebug() << "announcing" << m_UploadDict[*i];
|
||||||
|
if ((*i)->transfered)
|
||||||
|
(*i)->transfered = 0;
|
||||||
|
|
||||||
|
// ID header with no data
|
||||||
|
header.type = HT_ID;
|
||||||
|
header.id = m_UploadDict[*i];
|
||||||
|
header.length = 0;
|
||||||
|
|
||||||
|
out.writeRawData((const char *)(&header), sizeof(TransferHeader));
|
||||||
|
|
||||||
|
//size header with size
|
||||||
|
header.type = HT_SIZE;
|
||||||
|
header.length = sizeof(qint64);
|
||||||
|
|
||||||
|
out.writeRawData((const char *)(&header), sizeof(TransferHeader));
|
||||||
|
|
||||||
|
qDebug() << "sending size" << (*i)->size;
|
||||||
|
out << (*i)->size;
|
||||||
|
|
||||||
|
//name header with file name
|
||||||
|
|
||||||
|
qint64 oldPosition = block.size();
|
||||||
|
|
||||||
|
//fake write filename
|
||||||
|
out << (*i)->fileName;
|
||||||
|
out.device()->seek(oldPosition);
|
||||||
|
|
||||||
|
header.type = HT_NAME;
|
||||||
|
header.length = quint32(block.size() - oldPosition);
|
||||||
|
|
||||||
|
// qDebug() << "pos" << out.device()->pos() << block.size();
|
||||||
|
out.writeRawData((const char *)(&header), sizeof(TransferHeader));
|
||||||
|
// qDebug() << "pos post header" << out.device()->pos() << block.size();
|
||||||
|
|
||||||
|
// qint64 oldPosition = block.size() - sizeof(quint32);
|
||||||
|
|
||||||
|
qDebug() << "sending filename" << (*i)->fileName;
|
||||||
|
out << (*i)->fileName;
|
||||||
|
// qDebug() << "pos post filename" << out.device()->pos() << block.size();
|
||||||
|
// out.device()->seek(oldPosition);
|
||||||
|
// qDebug() << "pos post seek" << out.device()->pos();
|
||||||
|
|
||||||
|
|
||||||
|
/* qDebug() << "filename data length" << header.length;
|
||||||
|
out << header.length;
|
||||||
|
out.device()->seek(oldPosition);
|
||||||
|
out >> header.length;
|
||||||
|
qDebug() << "written length" << header.length;
|
||||||
|
out.device()->seek(block.size());
|
||||||
|
qDebug() << "pos post length correct" << out.device()->pos() << block.size();*/
|
||||||
|
|
||||||
|
(*i)->status = TS_WAITING;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case TS_TRANSFERING: {
|
||||||
|
// qDebug() << "transfering" << m_DataDict[*i];
|
||||||
|
header.type = HT_DATA;
|
||||||
|
header.id = m_UploadDict[*i];
|
||||||
|
if ((*i)->transfered + DATA_BLOCK_SIZE < (*i)->size)
|
||||||
|
header.length = DATA_BLOCK_SIZE;
|
||||||
|
else
|
||||||
|
header.length =(*i)->size - (*i)->transfered;
|
||||||
|
|
||||||
|
out.writeRawData((const char *)(&header), sizeof(TransferHeader));
|
||||||
|
|
||||||
|
char * buffer = new char[header.length];
|
||||||
|
|
||||||
|
QFile file((*i)->fileDir + QDir::separator() + (*i)->fileName);
|
||||||
|
file.open(QIODevice::ReadOnly);
|
||||||
|
QDataStream in(&file);
|
||||||
|
if (in.skipRawData((*i)->transfered) == -1) {
|
||||||
|
qDebug() << "filename" << file.fileName();
|
||||||
|
qDebug() << "skip error";
|
||||||
|
qDebug() << "file size" << (*i)->size;
|
||||||
|
qDebug() << "transfered bytes" << (*i)->transfered;
|
||||||
|
}
|
||||||
|
// in.device()->seek((*i)->transfered);
|
||||||
|
if (in.readRawData(buffer, header.length) == -1) {
|
||||||
|
qDebug() << "Read error";
|
||||||
|
qDebug() << "buffer size" << header.length;
|
||||||
|
qDebug() << "file size" << (*i)->size;
|
||||||
|
qDebug() << "transfered bytes" << (*i)->transfered;
|
||||||
|
}
|
||||||
|
|
||||||
|
out.writeRawData((const char *)(buffer), header.length);
|
||||||
|
(*i)->transfered += header.length;
|
||||||
|
delete[] buffer;
|
||||||
|
|
||||||
|
if ((*i)->transfered >= (*i)->size)
|
||||||
|
(*i)->status = TS_CLOSING;
|
||||||
|
|
||||||
|
if ((*i)->transfered > (*i)->size) {
|
||||||
|
qDebug() << "overread?";
|
||||||
|
qDebug() << "file size" << (*i)->size;
|
||||||
|
qDebug() << "transfered bytes" << (*i)->transfered;
|
||||||
|
}
|
||||||
|
|
||||||
|
emit uploadUpdated(*i);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case TS_CLOSING:
|
||||||
|
header.type = HT_CLOSE;
|
||||||
|
header.id = m_UploadDict[*i];
|
||||||
|
header.length = 0;
|
||||||
|
|
||||||
|
out.writeRawData((const char *)(&header), sizeof(TransferHeader));
|
||||||
|
|
||||||
|
(*i)->status = TS_FINISHED;
|
||||||
|
|
||||||
|
m_UploadDict.remove(*i);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (!block.isEmpty())
|
||||||
|
m_Socket->write(block);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CWorker::readHeader(QDataStream & in) {
|
||||||
|
if (m_Socket->bytesAvailable() >= (qint64)(sizeof(TransferHeader))) {
|
||||||
|
in.readRawData((char *)(&m_LastHeader), sizeof(TransferHeader));
|
||||||
|
m_LastHeaderValid = (qstrcmp(m_LastHeader.descriptor, DESCRIPTOR_STRING) == 0);
|
||||||
|
|
||||||
|
if (!m_LastHeaderValid) {
|
||||||
|
qDebug() << "got invalid header data";
|
||||||
|
qDebug() << "available Bytes" << m_Socket->bytesAvailable();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
m_LastHeaderValid = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CWorker::readData() {
|
||||||
|
QDataStream in(m_Socket);
|
||||||
|
in.setVersion(QDataStream::Qt_4_0);
|
||||||
|
|
||||||
|
if (!m_LastHeaderValid)
|
||||||
|
readHeader(in);
|
||||||
|
|
||||||
|
TransferData * target = NULL;
|
||||||
|
|
||||||
|
while (m_LastHeaderValid && m_Socket->bytesAvailable() >= m_LastHeader.length) {
|
||||||
|
// qDebug() << "available Bytes" << m_Socket->bytesAvailable() << "length" << m_LastHeader.length;
|
||||||
|
|
||||||
|
//look for existing id
|
||||||
|
if (m_LastHeader.type == HT_ACK) {
|
||||||
|
qDebug() << "got HT_ACK .. scheduling upload to start";
|
||||||
|
startUploadData(m_LastHeader.id);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (m_DownloadDict.contains(m_LastHeader.id)) {
|
||||||
|
if (m_LastHeader.type == HT_CLOSE) {
|
||||||
|
//finished or canceled by peer
|
||||||
|
|
||||||
|
qDebug() << "download closed py peer";
|
||||||
|
TransferData * closed = m_DownloadDict.take(m_LastHeader.id);
|
||||||
|
closed->status = TS_FINISHED;
|
||||||
|
emit downloadRemoved(closed);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
//assign target
|
||||||
|
target = m_DownloadDict[m_LastHeader.id];
|
||||||
|
}
|
||||||
|
//id not in dict
|
||||||
|
else if (m_LastHeader.type == HT_ID) {
|
||||||
|
//new file announced
|
||||||
|
qDebug() << "download announced";
|
||||||
|
TransferData * newFile = new TransferData;
|
||||||
|
m_DownloadDict.insert(m_LastHeader.id, newFile);
|
||||||
|
newFile->transfered = 0;
|
||||||
|
newFile->size = 0;
|
||||||
|
newFile->localFile = false;
|
||||||
|
newFile->status = TS_WAITING;
|
||||||
|
newFile->fileDir = m_DestinationDir;
|
||||||
|
}
|
||||||
|
|
||||||
|
//check valid target and data available
|
||||||
|
if (target && m_LastHeader.length) {
|
||||||
|
switch (m_LastHeader.type) {
|
||||||
|
case HT_ID:
|
||||||
|
target->status = TS_WAITING;
|
||||||
|
// QFile::remove(target->fileDir + QDir::separator() + target->fileName);
|
||||||
|
emit downloadUpdated(target);
|
||||||
|
break;
|
||||||
|
case HT_SIZE:
|
||||||
|
qDebug() << "reading size..";
|
||||||
|
in >> target->size;
|
||||||
|
qDebug() << "got size:" << target->size;
|
||||||
|
break;
|
||||||
|
case HT_NAME:
|
||||||
|
qDebug() << "reading filename..";
|
||||||
|
in >> target->fileName;
|
||||||
|
qDebug() << "got filename:" << target->fileName;
|
||||||
|
qDebug() << "trying to send HT_ACK";
|
||||||
|
|
||||||
|
//TODO better do this async
|
||||||
|
sendAcknowledge(m_LastHeader.id);
|
||||||
|
break;
|
||||||
|
case HT_DATA: {
|
||||||
|
// qDebug() << "got data" << target->transfered << '/' << target->size;
|
||||||
|
QFile file(target->fileDir + QDir::separator() + target->fileName);
|
||||||
|
if (target->status == TS_WAITING) {
|
||||||
|
target->status = TS_TRANSFERING;
|
||||||
|
emit downloadAdded(target);
|
||||||
|
file.open(QIODevice::WriteOnly | QIODevice::Truncate);
|
||||||
|
}
|
||||||
|
else if (target->status == TS_TRANSFERING)
|
||||||
|
file.open(QIODevice::WriteOnly | QIODevice::Append);
|
||||||
|
else {
|
||||||
|
in.skipRawData(m_LastHeader.length);
|
||||||
|
qDebug() << "transfer not ready to recieve data. status is" << target->status;
|
||||||
|
qDebug() << "skipping" << m_LastHeader.length << "bytes of data";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
char * buffer = new char[m_LastHeader.length];
|
||||||
|
if (in.readRawData(buffer, m_LastHeader.length) == -1) {
|
||||||
|
qDebug() << "error reading from socket";
|
||||||
|
qDebug() << "length" << m_LastHeader.length;
|
||||||
|
qDebug() << "available Bytes" << m_Socket->bytesAvailable();
|
||||||
|
}
|
||||||
|
|
||||||
|
QDataStream out(&file);
|
||||||
|
out.writeRawData((const char *)(buffer), m_LastHeader.length);
|
||||||
|
target->transfered += m_LastHeader.length;
|
||||||
|
delete[] buffer;
|
||||||
|
|
||||||
|
emit downloadUpdated(target);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
in.skipRawData(m_LastHeader.length);
|
||||||
|
qDebug() << "unknown header";
|
||||||
|
qDebug() << "skipping" << m_LastHeader.length << "bytes of data";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
readHeader(in);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CWorker::writePing() {
|
||||||
|
qDebug() << "write ping... thread id" << QThread::currentThreadId();
|
||||||
|
if (m_IdCounter > 10)
|
||||||
|
return;
|
||||||
|
|
||||||
|
QByteArray block;
|
||||||
|
QDataStream out(&block, QIODevice::WriteOnly);
|
||||||
|
out.setVersion(QDataStream::Qt_4_0);
|
||||||
|
|
||||||
|
TransferHeader header;
|
||||||
|
|
||||||
|
header.type = HT_ACK;
|
||||||
|
header.id = m_IdCounter++;
|
||||||
|
header.length = 0;
|
||||||
|
|
||||||
|
out.writeRawData((const char *)(&header), sizeof(TransferHeader));
|
||||||
|
|
||||||
|
qDebug() << "sending Ping..." << header.id;
|
||||||
|
if (m_Socket->write(block) == -1)
|
||||||
|
qDebug() << "error";
|
||||||
|
else
|
||||||
|
qDebug() << "done";
|
||||||
|
}
|
||||||
|
|
||||||
|
void CWorker::readPing() {
|
||||||
|
qDebug() << "read ping... thread id" << QThread::currentThreadId();
|
||||||
|
|
||||||
|
QDataStream in(m_Socket);
|
||||||
|
in.setVersion(QDataStream::Qt_4_0);
|
||||||
|
|
||||||
|
do {
|
||||||
|
if (m_Socket->bytesAvailable() >= (qint64)(sizeof(TransferHeader))) {
|
||||||
|
in.readRawData((char *)(&m_LastHeader), sizeof(TransferHeader));
|
||||||
|
m_LastHeaderValid = (qstrcmp(m_LastHeader.descriptor, DESCRIPTOR_STRING) == 0);
|
||||||
|
|
||||||
|
if (m_LastHeaderValid)
|
||||||
|
qDebug() << "got valid ping" << m_LastHeader.id;
|
||||||
|
else
|
||||||
|
qDebug() << "got invalid ping" << m_LastHeader.id;
|
||||||
|
|
||||||
|
writePing();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
m_LastHeaderValid = false;
|
||||||
|
}
|
||||||
|
while (m_LastHeaderValid);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CWorker::error(QAbstractSocket::SocketError) {
|
||||||
|
qDebug() << m_Socket->errorString();
|
||||||
|
}
|
||||||
|
}
|
80
cworker.h
Normal file
80
cworker.h
Normal file
@ -0,0 +1,80 @@
|
|||||||
|
/***************************************************************************
|
||||||
|
* Copyright (C) 2008 by Oliver Groß *
|
||||||
|
* z.o.gross@gmx.de *
|
||||||
|
* *
|
||||||
|
* This program is free software; you can redistribute it and/or modify *
|
||||||
|
* it under the terms of the GNU General Public License as published by *
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or *
|
||||||
|
* (at your option) any later version. *
|
||||||
|
* *
|
||||||
|
* This program is distributed in the hope that it will be useful, *
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||||
|
* GNU General Public License for more details. *
|
||||||
|
* *
|
||||||
|
* You should have received a copy of the GNU General Public License *
|
||||||
|
* along with this program; if not, write to the *
|
||||||
|
* Free Software Foundation, Inc., *
|
||||||
|
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
||||||
|
***************************************************************************/
|
||||||
|
#ifndef QFTRANSCWORKER_H
|
||||||
|
#define QFTRANSCWORKER_H
|
||||||
|
|
||||||
|
#include <QObject>
|
||||||
|
#include <QTcpSocket>
|
||||||
|
#include <QDataStream>
|
||||||
|
#include "common.h"
|
||||||
|
|
||||||
|
namespace qftrans {
|
||||||
|
/**
|
||||||
|
@author Oliver Groß <z.o.gross@gmx.de>
|
||||||
|
*/
|
||||||
|
class CWorker : public QObject {
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
CWorker(QTcpSocket * socket, QObject * parent = 0);
|
||||||
|
~CWorker();
|
||||||
|
signals:
|
||||||
|
void uploadAdded(TransferData * transfer);
|
||||||
|
void uploadRemoved(TransferData * transfer);
|
||||||
|
void uploadUpdated(TransferData * transfer);
|
||||||
|
|
||||||
|
void downloadAdded(TransferData * transfer);
|
||||||
|
void downloadRemoved(TransferData * transfer);
|
||||||
|
void downloadUpdated(TransferData * transfer);
|
||||||
|
public slots:
|
||||||
|
void addUpload(TransferData * transfer);
|
||||||
|
void removeUpload(TransferData * transfer);
|
||||||
|
void startUpload(TransferData * transfer);
|
||||||
|
|
||||||
|
void removeDownload(TransferData * data);
|
||||||
|
|
||||||
|
void setDestinationDir(QString & value);
|
||||||
|
void writePing();
|
||||||
|
protected slots:
|
||||||
|
void writeData();
|
||||||
|
void readData();
|
||||||
|
|
||||||
|
void readPing();
|
||||||
|
protected:
|
||||||
|
void readHeader(QDataStream & in);
|
||||||
|
|
||||||
|
void startUploadData(quint32 id);
|
||||||
|
void sendAcknowledge(quint32 id);
|
||||||
|
|
||||||
|
QTcpSocket * m_Socket;
|
||||||
|
QString m_DestinationDir;
|
||||||
|
|
||||||
|
quint32 m_IdCounter;
|
||||||
|
QTransferIdHash m_UploadDict;
|
||||||
|
|
||||||
|
QTransferDataHash m_DownloadDict;
|
||||||
|
|
||||||
|
TransferHeader m_LastHeader;
|
||||||
|
bool m_LastHeaderValid;
|
||||||
|
private slots:
|
||||||
|
void error(QAbstractSocket::SocketError socketError);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
51
main.cpp
Normal file
51
main.cpp
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
/***************************************************************************
|
||||||
|
* Copyright (C) 2008 by Oliver Groß *
|
||||||
|
* z.o.gross@gmx.de *
|
||||||
|
* *
|
||||||
|
* This program is free software; you can redistribute it and/or modify *
|
||||||
|
* it under the terms of the GNU General Public License as published by *
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or *
|
||||||
|
* (at your option) any later version. *
|
||||||
|
* *
|
||||||
|
* This program is distributed in the hope that it will be useful, *
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||||
|
* GNU General Public License for more details. *
|
||||||
|
* *
|
||||||
|
* You should have received a copy of the GNU General Public License *
|
||||||
|
* along with this program; if not, write to the *
|
||||||
|
* Free Software Foundation, Inc., *
|
||||||
|
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
||||||
|
***************************************************************************/
|
||||||
|
#include <QtGui>
|
||||||
|
#include <QTranslator>
|
||||||
|
#include <QMetaType>
|
||||||
|
#include "ctransfermanager.h"
|
||||||
|
#include "common.h"
|
||||||
|
//#include "constants.h"
|
||||||
|
|
||||||
|
using namespace qftrans;
|
||||||
|
|
||||||
|
int main(int argc, char * argv[])
|
||||||
|
{
|
||||||
|
QApplication app(argc, argv);
|
||||||
|
qRegisterMetaType<QString>("QString&");
|
||||||
|
|
||||||
|
/* QString locale = QLocale::system().name();
|
||||||
|
QTranslator translator;
|
||||||
|
translator.load(QString(UI_PATH_TRANSLATIONS "qcross_") + locale);
|
||||||
|
app.installTranslator(&translator);*/
|
||||||
|
// app.setQuitOnLastWindowClosed(false);
|
||||||
|
|
||||||
|
// {
|
||||||
|
// QDir workdir(UI_PATH_WORK);
|
||||||
|
// if (!workdir.exists()) {
|
||||||
|
// workdir.cdUp();
|
||||||
|
// workdir.mkdir(UI_DIR_WORK);
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
CTransferManager mainwin;
|
||||||
|
mainwin.show();
|
||||||
|
return app.exec();
|
||||||
|
}
|
22
qftrans.pro
Normal file
22
qftrans.pro
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
SOURCES += main.cpp \
|
||||||
|
ctransfermanager.cpp \
|
||||||
|
qtransferlistmodel.cpp \
|
||||||
|
ctransferthread.cpp \
|
||||||
|
cworker.cpp \
|
||||||
|
csocketmanager.cpp \
|
||||||
|
cconnectiondialog.cpp
|
||||||
|
HEADERS += ctransfermanager.h \
|
||||||
|
qtransferlistmodel.h \
|
||||||
|
common.h \
|
||||||
|
ctransferthread.h \
|
||||||
|
cworker.h \
|
||||||
|
csocketmanager.h \
|
||||||
|
cconnectiondialog.h
|
||||||
|
TEMPLATE = app
|
||||||
|
|
||||||
|
QT += network
|
||||||
|
|
||||||
|
CONFIG -= release
|
||||||
|
|
||||||
|
CONFIG += debug
|
||||||
|
|
111
qtransferlistmodel.cpp
Normal file
111
qtransferlistmodel.cpp
Normal file
@ -0,0 +1,111 @@
|
|||||||
|
/***************************************************************************
|
||||||
|
* Copyright (C) 2008 by Oliver Groß *
|
||||||
|
* z.o.gross@gmx.de *
|
||||||
|
* *
|
||||||
|
* This program is free software; you can redistribute it and/or modify *
|
||||||
|
* it under the terms of the GNU General Public License as published by *
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or *
|
||||||
|
* (at your option) any later version. *
|
||||||
|
* *
|
||||||
|
* This program is distributed in the hope that it will be useful, *
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||||
|
* GNU General Public License for more details. *
|
||||||
|
* *
|
||||||
|
* You should have received a copy of the GNU General Public License *
|
||||||
|
* along with this program; if not, write to the *
|
||||||
|
* Free Software Foundation, Inc., *
|
||||||
|
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
||||||
|
***************************************************************************/
|
||||||
|
#include "qtransferlistmodel.h"
|
||||||
|
|
||||||
|
namespace qftrans {
|
||||||
|
QTransferListModel::QTransferListModel(QTransferDataList * data, QObject * parent) : QAbstractListModel(parent), m_Data(data) {
|
||||||
|
}
|
||||||
|
|
||||||
|
QTransferListModel::~QTransferListModel() {
|
||||||
|
}
|
||||||
|
|
||||||
|
int QTransferListModel::rowCount(const QModelIndex & /*parent*/) const {
|
||||||
|
if (m_Data)
|
||||||
|
return m_Data->size();
|
||||||
|
else
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
QVariant QTransferListModel::data(const QModelIndex & index, int role) const {
|
||||||
|
if (role != Qt::DisplayRole)
|
||||||
|
return QVariant();
|
||||||
|
|
||||||
|
TransferData * data = static_cast<TransferData *>(index.internalPointer());
|
||||||
|
|
||||||
|
if (!data)
|
||||||
|
return QVariant();
|
||||||
|
|
||||||
|
QString status;
|
||||||
|
|
||||||
|
switch (data->status) {
|
||||||
|
case TS_WAITING:
|
||||||
|
status = tr("waiting");
|
||||||
|
break;
|
||||||
|
case TS_ANNOUNCING:
|
||||||
|
status = tr("announcing to peer");
|
||||||
|
break;
|
||||||
|
case TS_TRANSFERING:
|
||||||
|
status = data->localFile ? tr("Sending") : tr("Recieving");
|
||||||
|
break;
|
||||||
|
case TS_CLOSING:
|
||||||
|
status = tr("closing down");
|
||||||
|
break;
|
||||||
|
case TS_FINISHED:
|
||||||
|
status = (data->transfered == data->size) ? tr("finished") : tr("canceled");
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
status = tr("unknown status");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
QString size;
|
||||||
|
unsigned int fancySize = data->size;
|
||||||
|
unsigned int siCount = 0;
|
||||||
|
|
||||||
|
while (fancySize > 1000) {
|
||||||
|
fancySize /= 1000;
|
||||||
|
siCount++;
|
||||||
|
}
|
||||||
|
|
||||||
|
size = QString::number(fancySize);
|
||||||
|
|
||||||
|
switch (siCount) {
|
||||||
|
case 0:
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
size += 'K';
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
size += 'M';
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
size += 'G';
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
size += "*10^" + QString::number(siCount);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
size += 'B';
|
||||||
|
|
||||||
|
return (data->localFile ? "out #" : "in #") + QString::number(index.row()) + " [" + status + "] (" +
|
||||||
|
QString::number((unsigned int)((100.0 * data->transfered) / data->size)) + "%) " +
|
||||||
|
data->fileName + " (size: " + size + ")";
|
||||||
|
}
|
||||||
|
|
||||||
|
QModelIndex QTransferListModel::index (int row, int column, const QModelIndex & /*parent*/) const {
|
||||||
|
return createIndex(row, column, m_Data->at(row));
|
||||||
|
}
|
||||||
|
|
||||||
|
void QTransferListModel::updateEntry(TransferData * /*entry*/) {
|
||||||
|
// TODO proper tranfer entry update
|
||||||
|
emit layoutChanged();
|
||||||
|
}
|
||||||
|
}
|
46
qtransferlistmodel.h
Normal file
46
qtransferlistmodel.h
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
/***************************************************************************
|
||||||
|
* Copyright (C) 2008 by Oliver Groß *
|
||||||
|
* z.o.gross@gmx.de *
|
||||||
|
* *
|
||||||
|
* This program is free software; you can redistribute it and/or modify *
|
||||||
|
* it under the terms of the GNU General Public License as published by *
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or *
|
||||||
|
* (at your option) any later version. *
|
||||||
|
* *
|
||||||
|
* This program is distributed in the hope that it will be useful, *
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||||
|
* GNU General Public License for more details. *
|
||||||
|
* *
|
||||||
|
* You should have received a copy of the GNU General Public License *
|
||||||
|
* along with this program; if not, write to the *
|
||||||
|
* Free Software Foundation, Inc., *
|
||||||
|
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
||||||
|
***************************************************************************/
|
||||||
|
#ifndef QFTRANS_QTRANSFERLISTMODEL_H
|
||||||
|
#define QFTRANS_QTRANSFERLISTMODEL_H
|
||||||
|
|
||||||
|
#include <QAbstractListModel>
|
||||||
|
#include "common.h"
|
||||||
|
|
||||||
|
namespace qftrans {
|
||||||
|
/**
|
||||||
|
@author Oliver Groß <z.o.gross@gmx.de>
|
||||||
|
*/
|
||||||
|
class QTransferListModel : public QAbstractListModel {
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
QTransferListModel(QTransferDataList * data, QObject * parent = 0);
|
||||||
|
~QTransferListModel();
|
||||||
|
|
||||||
|
int rowCount(const QModelIndex & parent = QModelIndex()) const;
|
||||||
|
QVariant data(const QModelIndex & index, int role = Qt::DisplayRole) const;
|
||||||
|
QModelIndex index (int row, int column = 0, const QModelIndex & parent = QModelIndex()) const;
|
||||||
|
public slots:
|
||||||
|
void updateEntry(TransferData * entry);
|
||||||
|
private:
|
||||||
|
QTransferDataList * m_Data;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
Loading…
Reference in New Issue
Block a user