/* # Copyright (c) 2009, 2010 - OpenSLX Project, Computer Center University of # Freiburg # # This program is free software distributed under the GPL version 2. # See http://openslx.org/COPYING # # If you have any feedback please consult http://openslx.org/feedback and # send your suggestions, praise, or complaints to feedback@openslx.org # # General information about OpenSLX can be found at http://openslx.org/ # ----------------------------------------------------------------------------- # clientFileSendDialog.cpp # - filechooser and progress dialog # ----------------------------------------------------------------------------- */ #include "clientFileSendDialog.h" ClientFileSendDialog::ClientFileSendDialog(QWidget *parent) : QDialog(parent) { setupUi(this); _file = NULL; _socket = NULL; _clientNicklistDialog = new ClientNicklistDialog(this); // connect to D-Bus and get interface QDBusConnection dbus = QDBusConnection::sessionBus(); _ifaceDBus = new OrgOpenslxPvsInterface("org.openslx.pvs", "/", dbus, this); // get current users name from backend QDBusPendingReply reply = _ifaceDBus->chat_getNickname(); reply.waitForFinished(); if (reply.isValid()) _nickname = reply.value(); else _nickname = "unknown"; connect(this, SIGNAL(finished(int)), this, SLOT(deleteLater())); } ClientFileSendDialog::~ClientFileSendDialog() { qDebug("[%s] Deleted!", metaObject()->className()); } //////////////////////////////////////////////////////////////////////////////// // Public void ClientFileSendDialog::open() { // get nick of remote user int result = _clientNicklistDialog->exec(); if (result == 0) // User canceled { reject(); return; } open(_clientNicklistDialog->getNick()); } void ClientFileSendDialog::open(QString nick) { QString filename = QFileDialog::getOpenFileName(this, tr("Open File"), QDir::homePath(), ""); if (filename == "") { reject(); return; } open(nick, filename); } void ClientFileSendDialog::open(QString nick, QString filename) { // open file _file = new QFile(filename); _file->open(QIODevice::ReadOnly); _bytesToWrite = _file->size(); div = 1 + _bytesToWrite / 1000000000; // bc. progressBar supports only int // get host from backend QString host = ""; QDBusPendingReply reply = _ifaceDBus->getIpByNick(nick); reply.waitForFinished(); if (reply.isValid()) host = reply.value(); else // DBus Error, hostname qDebug("[%s] D-Bus ERROR, no hostname available!", metaObject()->className()); // gui filenameLabel->setText(filename); progressBar->setValue(0); progressBar->setMaximum(_bytesToWrite/div); labelNick->setText(nick); labelB->setText(formatSize(_bytesToWrite)); connect(cancelButton, SIGNAL(clicked()), this, SLOT(close())); // open socket _socket = new QTcpSocket(); _socket->connectToHost(host, 29481); qDebug("[%s] Remote host: %s", metaObject()->className(), qPrintable(host)); connect(_socket, SIGNAL(connected()), this, SLOT(sendHeader())); connect(_socket, SIGNAL(disconnected()), this, SLOT(close())); connect(_socket, SIGNAL(error(QAbstractSocket::SocketError)), this, SLOT(error(QAbstractSocket::SocketError))); } //////////////////////////////////////////////////////////////////////////////// // Private void ClientFileSendDialog::sendHeader() { QFileInfo info(_file->fileName()); QString size = QString::number(_bytesToWrite); QString header = _nickname + ";" + info.fileName() + ";" + size + "\n"; _socket->write(header.toLocal8Bit()); connect(_socket, SIGNAL(readyRead()), this, SLOT(receiveAck())); qDebug("[%s] Sending header...", metaObject()->className()); } void ClientFileSendDialog::receiveAck() { QString ack = QString::fromUtf8(_socket->readLine()); if (ack != "ok\n") { qDebug("[%s] Received nack!", metaObject()->className()); close(); return; } qDebug("[%s] Received ack.", metaObject()->className()); disconnect(_socket, SIGNAL(readyRead()), this, SLOT(receiveAck())); connect(_socket, SIGNAL(bytesWritten(qint64)), this, SLOT(sendFile())); show(); qDebug("[%s] Sending file...", metaObject()->className()); sendFile(); } void ClientFileSendDialog::sendFile() { if (_bytesToWrite == 0) { qDebug("[%s] Transfer completed.", metaObject()->className()); close(); // finished } else { qint64 bytesWritten = _socket->write(_file->read(1024)); // data left _bytesToWrite -= bytesWritten; progressBar->setValue(progressBar->value() + bytesWritten/div); labelA->setText(formatSize(progressBar->value()*div)); } } void ClientFileSendDialog::close() { if (_file && _file->isOpen()) { _file->close(); qDebug("[%s] File closed.", metaObject()->className()); } if (_socket && _socket->isOpen()) { disconnect(_socket, SIGNAL(readyRead()), this, SLOT(receiveAck())); disconnect(_socket, SIGNAL(bytesWritten(qint64)), this, SLOT(sendFile())); disconnect(_socket, SIGNAL(disconnected()), this, SLOT(close())); disconnect(_socket, SIGNAL(connected()), this, SLOT(sendHeader())); disconnect(_socket, SIGNAL(error(QAbstractSocket::SocketError)), this, SLOT(error(QAbstractSocket::SocketError))); _socket->disconnectFromHost(); qDebug("[%s] Connection closed.", metaObject()->className()); } disconnect(cancelButton, SIGNAL(clicked()), this, SLOT(close())); if (_bytesToWrite == 0) { accept(); QMessageBox::information(0, tr("PVS - File Transfer"), tr("File Transfer complete.")); } else { reject(); QMessageBox::warning(0, tr("PVS - File Transfer"), tr("File Transfer canceled!")); } } void ClientFileSendDialog::error(QAbstractSocket::SocketError error) { qDebug("[%s] Socket error: %i", metaObject()->className(), error); close(); } QString ClientFileSendDialog::formatSize(qint64 size) { if (size >= 1000000000) // GB return QString("%1GB").arg((qreal)size / 1000000000, 0, 'f',1); else if (size >= 1000000) // MB return QString("%1MB").arg((qreal)size / 1000000, 0, 'f',1); else if (size >= 1000) // KB return QString("%1KB").arg((qreal)size / 1000, 0, 'f',1); else // B return QString("%1B").arg((qreal)size, 0, 'f',1); } //////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////// ClientNicklistDialog::ClientNicklistDialog(QWidget *parent) : QDialog(parent) { setupUi(this); // connect to D-Bus and get interface QDBusConnection dbus = QDBusConnection::sessionBus(); dbus.registerObject("/nicklist", this); dbus.registerService("org.openslx.pvsgui"); _ifaceDBus = new OrgOpenslxPvsInterface("org.openslx.pvs", "/", dbus, this); // get available nicknames QDBusPendingReply reply = _ifaceDBus->chat_getNicknames(); reply.waitForFinished(); QStringList nicknames = reply.value(); if (!reply.isValid() || nicknames.isEmpty()) // DBus Error, nicknames qDebug("[%s] D-Bus ERROR, no nicknames available!", metaObject()->className()); listWidget->addItems(nicknames); listWidget->setCurrentRow(0); } ClientNicklistDialog::~ClientNicklistDialog() { } QString ClientNicklistDialog::getNick() { return listWidget->currentItem()->text(); }