qftrans/ctransfermanager.cpp
2009-04-23 10:15:30 +02:00

308 lines
11 KiB
C++

/***************************************************************************
* 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_SUSPENDED;
newUpload->lastHeader = HT_ANNOUNCE;
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("disconnected"));
}
void CTransferManager::restartSelected() {
QModelIndexList selectedIndexes = m_TransferView->selectionModel()->selectedIndexes();
foreach (QModelIndex i, selectedIndexes) {
emit uploadAddRequested(static_cast<TransferData *>(i.internalPointer()));
}
// emit uploadAddRequested(m_SelectedTransfer);
}
void CTransferManager::cancelSelected() {
QModelIndexList selectedIndexes = m_TransferView->selectionModel()->selectedIndexes();
foreach (QModelIndex i, selectedIndexes) {
if (static_cast<TransferData *>(i.internalPointer())->localFile)
emit uploadRemoveRequested(static_cast<TransferData *>(i.internalPointer()));
else
emit downloadRemoveRequested(static_cast<TransferData *>(i.internalPointer()));
}
/* 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);
m_TransferView->setSelectionMode(QAbstractItemView::ExtendedSelection);
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->setDisabled(selectedIndexes.isEmpty());
m_TransferCancelAction->setDisabled(selectedIndexes.isEmpty());
/* 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."));
}
}