/*
(c) Copyright 2012 - 2018 Anton Sviridenko
https://picapica.im
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 3 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, see .
*/
#include "filetransferdialog.h"
#include "../contacts.h"
#include "../accounts.h"
#include "../globals.h"
#include
#include
#include
#include
FileTransferDialog::FileTransferDialog(QByteArray peer_id, QString filename, quint64 size,
TransferDirection drct, QWidget *parent) :
peer_id_(peer_id),
QDialog(parent),
dir_(drct),
filename_(filename),
filesize_(size)
{
Contacts ct(config_dbname, Accounts::GetCurrentAccount().id);
peer_name_ = ct.GetContactName(peer_id_);
if (peer_name_.isEmpty())
peer_name_ = peer_id_.toBase64();
else
peer_name_ = QString("%1 (%2...)").arg(peer_name_).arg(peer_id_.toBase64().left(8).constData());
QVBoxLayout *layout = new QVBoxLayout(this);
QHBoxLayout *btlayout = new QHBoxLayout();
lbFilename = new QLabel(this);
lbPeer = new QLabel(this);
lbProgressStatus = new QLabel(this);
lbTransferSpeed = new QLabel(this);
lbRemainingTime = new QLabel(this);
lbTransferStatus = new QLabel(this);
pgbar = new QProgressBar(this);
leftbutton = new QPushButton(this);
rightbutton = new QPushButton(this);
layout->addWidget(lbFilename);
layout->addWidget(lbPeer);
layout->addWidget(lbProgressStatus);
layout->addWidget(lbTransferSpeed);
layout->addWidget(lbRemainingTime);
layout->addWidget(pgbar);
layout->addWidget(lbTransferStatus);
layout->addLayout(btlayout);
btlayout->addWidget(leftbutton);
btlayout->addWidget(rightbutton);
if (drct == RECEIVING)
{
leftbutton->setText(tr("Accept"));
rightbutton->setText(tr("Deny"));
lbPeer->setText("Sender: " + peer_name_);
setWindowTitle(tr("Receiving file %1 from %2").arg(filename_).arg(peer_name_));
}
else if (drct == SENDING)
{
leftbutton->setText(tr("Pause"));
rightbutton->setText(tr("Cancel"));
leftbutton->setEnabled(false);
lbPeer->setText("Receiver: " + peer_name_);
setWindowTitle(tr("Sending file %1 to %2").arg(filename_).arg(peer_name_));
}
setTransferStatus(WAITINGFORACCEPT);
lbFilename->setText(filename_);
pgbar->setMinimum(0);
pgbar->setMaximum(100);
update(0);
timer = new QTimer(this);
connect(timer, SIGNAL(timeout()), this, SLOT(timeout()));
timer->start(1000);
progress_ = 0;
prevprogress_ = 0;
connect(leftbutton, SIGNAL(clicked()), this, SLOT(leftbuttonclick()));
connect(rightbutton, SIGNAL(clicked()), this, SLOT(rightbuttonclick()));
}
void FileTransferDialog::update(quint64 progress)
{
progress_ = progress;
percents = (double)progress / filesize_ * 100.0;
lbProgressStatus->setText(bytestoHumanBase2(progress) + " / "
+ bytestoHumanBase2(filesize_) + QString(" %1 %").arg((int)percents));
pgbar->setValue(percents);
if (progress == filesize_)
{
setTransferStatus(FINISHED);
}
}
void FileTransferDialog::setTransferStatus(TransferStatus st)
{
bool isTerminalState = false;
switch(st)
{
case WAITINGFORACCEPT:
if (dir_ == SENDING)
lbTransferStatus->setText(tr("Waiting for peer to accept the file"));
else
lbTransferStatus->setText(tr("Waiting for acceptance"));
break;
case DENIED:
lbTransferStatus->setText(tr("Denied by peer"));
isTerminalState = true;
break;
case SENDINGFILE:
leftbutton->setEnabled(true);
lbTransferStatus->setText(tr("Sending file"));
break;
case RECEIVINGFILE:
lbTransferStatus->setText(tr("Receiving file"));
break;
case PAUSED:
lbTransferStatus->setText(tr("Paused"));
break;
case CANCELLED:
lbTransferStatus->setText(tr("Cancelled"));
isTerminalState = true;
break;
case FINISHED:
lbTransferStatus->setText(tr("Finished"));
isTerminalState = true;
break;
case PEERDISCONNECTED:
lbTransferStatus->setText(tr("Peer disconnected"));
isTerminalState = true;
break;
case IOERROR:
lbTransferStatus->setText(tr("I/O error"));
isTerminalState = true;
break;
}
if (isTerminalState)
{
leftbutton->setEnabled(false);
rightbutton->setEnabled(false);
QWidget::setAttribute(Qt::WA_DeleteOnClose);
QWidget::setAttribute(Qt::WA_QuitOnClose, false);
}
}
void FileTransferDialog::pausedByPeer()
{
leftbutton->setEnabled(false);
setTransferStatus(PAUSED);
}
void FileTransferDialog::resumedByPeer()
{
leftbutton->setEnabled(true);
setTransferStatus( dir_ == SENDING ? SENDINGFILE : RECEIVINGFILE);
}
void FileTransferDialog::cancelledByPeer()
{
setTransferStatus(CANCELLED);
}
void FileTransferDialog::ioError()
{
setTransferStatus(IOERROR);
}
void FileTransferDialog::peerDisconnected()
{
setTransferStatus(PEERDISCONNECTED);
}
void FileTransferDialog::leftbuttonclick()
{
if (dir_ == RECEIVING)
{
if (leftbutton->text() == tr("Accept"))
{
leftbutton->setText("Pause");
rightbutton->setText("Cancel");
emit acceptedFile(peer_id_);
return;
}
}
if (leftbutton->text() == tr("Pause"))
{
leftbutton->setText(tr("Resume"));
emit pausedFile(peer_id_, this);
setTransferStatus(PAUSED);
}
else if (leftbutton->text() == tr("Resume"))
{
leftbutton->setText(tr("Pause"));
emit resumedFile(peer_id_, this);
setTransferStatus(dir_ == SENDING ? SENDINGFILE : RECEIVINGFILE);
}
}
void FileTransferDialog::rightbuttonclick()
{
if (dir_ == RECEIVING)
{
if (rightbutton->text() == tr("Deny"))
{
emit deniedFile(peer_id_);
setTransferStatus(DENIED);
return;
}
}
if (rightbutton->text() == tr("Cancel"))
{
if (QMessageBox::No == QMessageBox::question(this, tr("Cancel File Transfer"),
tr("Are you sure you want to cancel file transfer?"),
QMessageBox::Yes | QMessageBox::No, QMessageBox::No))
return;
emit cancelledFile(peer_id_, this);
setTransferStatus(CANCELLED);
}
}
QString FileTransferDialog::bytestoHumanBase2(quint64 bytes)
{
const char* units[] = {"B", "KiB", "MiB", "GiB", "TiB", "PiB"};
int i = 0;
double size = bytes;
while (size > 1024)
{
size /= 1024;
i++;
}
return QString("%1 %2").arg(size, 6, 'f', i ? 2 : 0).arg(units[i]);
}
QString FileTransferDialog::bytestoHumanBase10(quint64 bytes)
{
const char* units[] = {"B", "kB", "MB", "GB", "TB", "PB"};
int i = 0;
double size = bytes;
while (size > 1000)
{
size /= 1000;
i++;
}
return QString("%1 %2").arg(size, 6, 'f', i ? 2 : 0).arg(units[i]);
}
QString FileTransferDialog::timeLeft(quint64 seconds)
{
if (seconds < 60)
{
return QString(tr("%1 seconds")).arg(seconds);
}
int minutes = seconds / 60;
int hours = minutes / 60;
double days = (double)hours / 24.0;
if (days > 1.0 )
return QString(tr("%1 days")).arg(days, 6, 'f', 1);
if (hours > 0)
return QString("%1h:%2m").arg(hours).arg(minutes % 60);
return QString("%1:%2").arg(minutes).arg((double)(seconds % 60), 2, 'f', 0, '0');
}
void FileTransferDialog::timeout()
{
if (progress_ >= filesize_)
return;
quint64 bps = progress_ - prevprogress_;
prevprogress_ = progress_;
if (bps != 0)
{
quint64 secondsleft = (filesize_ - progress_) / bps;
lbRemainingTime->setText(timeLeft(secondsleft));
}
else
lbRemainingTime->setText(QString());
lbTransferSpeed->setText(bytestoHumanBase10(bps) + tr("/s"));
}