/*************************************************************************** * 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 #include #include #include #include #include #include #include #include #include #include #include #include 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(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(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.")); } }