2014-07-07 00:19:45 +08:00
/*
Copyright ( C ) 2014 by Project Tox < https : //tox.im>
This file is part of qTox , a Qt - based graphical interface for Tox .
This program is libre 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 COPYING file for more details .
*/
2014-06-26 06:30:24 +08:00
# include "filetransfertwidget.h"
2014-06-26 07:48:20 +08:00
# include "widget.h"
# include "core.h"
2014-07-04 23:47:38 +08:00
# include "math.h"
2014-08-11 23:23:41 +08:00
# include "style.h"
2014-06-27 01:45:47 +08:00
# include <QFileDialog>
# include <QPixmap>
2014-07-05 07:59:11 +08:00
# include <QPainter>
2014-07-22 15:51:20 +08:00
# include <QMessageBox>
2014-06-26 06:30:24 +08:00
2014-06-27 01:45:47 +08:00
FileTransfertWidget : : FileTransfertWidget ( ToxFile File )
: lastUpdate { QDateTime : : currentDateTime ( ) } , lastBytesSent { 0 } ,
fileNum { File . fileNum } , friendId { File . friendId } , direction { File . direction }
2014-06-26 06:30:24 +08:00
{
pic = new QLabel ( ) , filename = new QLabel ( ) , size = new QLabel ( ) , speed = new QLabel ( ) , eta = new QLabel ( ) ;
topright = new QPushButton ( ) , bottomright = new QPushButton ( ) ;
progress = new QProgressBar ( ) ;
mainLayout = new QHBoxLayout ( ) , textLayout = new QHBoxLayout ( ) ;
infoLayout = new QVBoxLayout ( ) , buttonLayout = new QVBoxLayout ( ) ;
2014-06-28 21:52:17 +08:00
buttonWidget = new QWidget ( ) ;
2014-06-26 06:30:24 +08:00
QFont prettysmall ;
prettysmall . setPixelSize ( 10 ) ;
2014-07-05 07:59:11 +08:00
this - > setObjectName ( " default " ) ;
2014-08-11 23:23:41 +08:00
this - > setStyleSheet ( Style : : get ( " :/ui/fileTransferWidget/fileTransferWidget.css " ) ) ;
2014-06-26 06:30:24 +08:00
QPalette greybg ;
2014-06-26 07:35:30 +08:00
greybg . setColor ( QPalette : : Window , QColor ( 209 , 209 , 209 ) ) ;
greybg . setColor ( QPalette : : Base , QColor ( 150 , 150 , 150 ) ) ;
2014-06-26 06:30:24 +08:00
setPalette ( greybg ) ;
setAutoFillBackground ( true ) ;
2014-06-28 21:52:17 +08:00
setMinimumSize ( 250 , 58 ) ;
2014-07-03 14:43:23 +08:00
setMaximumHeight ( 58 ) ;
2014-06-26 06:30:24 +08:00
setLayout ( mainLayout ) ;
2014-06-26 07:35:30 +08:00
mainLayout - > setMargin ( 0 ) ;
2014-06-26 06:30:24 +08:00
2014-06-27 01:45:47 +08:00
pic - > setMaximumHeight ( 40 ) ;
pic - > setContentsMargins ( 5 , 0 , 0 , 0 ) ;
filename - > setText ( File . fileName ) ;
2014-06-26 06:30:24 +08:00
filename - > setFont ( prettysmall ) ;
2014-06-27 01:45:47 +08:00
size - > setText ( getHumanReadableSize ( File . filesize ) ) ;
2014-06-26 06:30:24 +08:00
size - > setFont ( prettysmall ) ;
speed - > setText ( " 0B/s " ) ;
speed - > setFont ( prettysmall ) ;
eta - > setText ( " 00:00 " ) ;
eta - > setFont ( prettysmall ) ;
progress - > setValue ( 0 ) ;
2014-06-26 07:35:30 +08:00
progress - > setMinimumHeight ( 11 ) ;
progress - > setFont ( prettysmall ) ;
2014-07-05 09:55:19 +08:00
progress - > setTextVisible ( false ) ;
2014-06-28 21:52:17 +08:00
QPalette whitebg ;
whitebg . setColor ( QPalette : : Window , QColor ( 255 , 255 , 255 ) ) ;
buttonWidget - > setPalette ( whitebg ) ;
buttonWidget - > setAutoFillBackground ( true ) ;
buttonWidget - > setLayout ( buttonLayout ) ;
2014-08-11 23:23:41 +08:00
stopFileButtonStylesheet = Style : : get ( " :/ui/stopFileButton/style.css " ) ;
pauseFileButtonStylesheet = Style : : get ( " :/ui/pauseFileButton/style.css " ) ;
acceptFileButtonStylesheet = Style : : get ( " :/ui/acceptFileButton/style.css " ) ;
2014-06-28 21:52:17 +08:00
topright - > setStyleSheet ( stopFileButtonStylesheet ) ;
2014-06-27 01:45:47 +08:00
if ( File . direction = = ToxFile : : SENDING )
{
2014-06-28 21:52:17 +08:00
bottomright - > setStyleSheet ( pauseFileButtonStylesheet ) ;
2014-06-27 01:45:47 +08:00
connect ( topright , SIGNAL ( clicked ( ) ) , this , SLOT ( cancelTransfer ( ) ) ) ;
connect ( bottomright , SIGNAL ( clicked ( ) ) , this , SLOT ( pauseResumeSend ( ) ) ) ;
QPixmap preview ;
2014-07-02 01:54:26 +08:00
File . file - > seek ( 0 ) ;
2014-07-01 19:33:59 +08:00
if ( preview . loadFromData ( File . file - > readAll ( ) ) )
2014-06-27 01:45:47 +08:00
{
preview = preview . scaledToHeight ( 40 ) ;
pic - > setPixmap ( preview ) ;
}
2014-07-02 01:54:26 +08:00
File . file - > seek ( 0 ) ;
2014-06-27 01:45:47 +08:00
}
2014-06-26 06:30:24 +08:00
else
2014-06-27 01:45:47 +08:00
{
2014-06-28 21:52:17 +08:00
bottomright - > setStyleSheet ( acceptFileButtonStylesheet ) ;
2014-06-27 01:45:47 +08:00
connect ( topright , SIGNAL ( clicked ( ) ) , this , SLOT ( rejectRecvRequest ( ) ) ) ;
connect ( bottomright , SIGNAL ( clicked ( ) ) , this , SLOT ( acceptRecvRequest ( ) ) ) ;
}
2014-06-26 06:30:24 +08:00
2014-06-26 07:35:30 +08:00
QPalette toxgreen ;
toxgreen . setColor ( QPalette : : Button , QColor ( 107 , 194 , 96 ) ) ; // Tox Green
topright - > setIconSize ( QSize ( 10 , 10 ) ) ;
2014-06-28 21:52:17 +08:00
topright - > setMinimumSize ( 25 , 28 ) ;
2014-06-26 07:35:30 +08:00
topright - > setFlat ( true ) ;
topright - > setAutoFillBackground ( true ) ;
topright - > setPalette ( toxgreen ) ;
bottomright - > setIconSize ( QSize ( 10 , 10 ) ) ;
2014-06-28 21:52:17 +08:00
bottomright - > setMinimumSize ( 25 , 28 ) ;
2014-06-26 07:35:30 +08:00
bottomright - > setFlat ( true ) ;
bottomright - > setAutoFillBackground ( true ) ;
bottomright - > setPalette ( toxgreen ) ;
2014-06-26 06:30:24 +08:00
2014-06-28 21:52:17 +08:00
mainLayout - > addStretch ( ) ;
2014-06-26 06:30:24 +08:00
mainLayout - > addWidget ( pic ) ;
2014-06-28 21:52:17 +08:00
mainLayout - > addLayout ( infoLayout , 3 ) ;
mainLayout - > addStretch ( ) ;
mainLayout - > addWidget ( buttonWidget ) ;
mainLayout - > setMargin ( 0 ) ;
mainLayout - > setSpacing ( 0 ) ;
2014-06-26 06:30:24 +08:00
infoLayout - > addWidget ( filename ) ;
infoLayout - > addLayout ( textLayout ) ;
infoLayout - > addWidget ( progress ) ;
2014-06-28 21:52:17 +08:00
infoLayout - > setMargin ( 4 ) ;
infoLayout - > setSpacing ( 4 ) ;
2014-06-26 06:30:24 +08:00
textLayout - > addWidget ( size ) ;
2014-07-06 05:00:22 +08:00
textLayout - > addStretch ( 0 ) ;
2014-06-26 06:30:24 +08:00
textLayout - > addWidget ( speed ) ;
2014-07-06 05:00:22 +08:00
textLayout - > addStretch ( 0 ) ;
2014-06-26 06:30:24 +08:00
textLayout - > addWidget ( eta ) ;
2014-07-05 09:55:19 +08:00
textLayout - > setMargin ( 2 ) ;
2014-06-26 06:30:24 +08:00
textLayout - > setSpacing ( 5 ) ;
2014-06-26 07:35:30 +08:00
buttonLayout - > addWidget ( topright ) ;
2014-06-27 02:13:37 +08:00
buttonLayout - > addSpacing ( 2 ) ;
2014-06-26 07:35:30 +08:00
buttonLayout - > addWidget ( bottomright ) ;
2014-06-28 21:52:17 +08:00
buttonLayout - > setContentsMargins ( 2 , 0 , 0 , 0 ) ;
2014-06-27 02:13:37 +08:00
buttonLayout - > setSpacing ( 0 ) ;
2014-06-26 06:30:24 +08:00
}
QString FileTransfertWidget : : getHumanReadableSize ( int size )
{
2014-06-27 01:45:47 +08:00
static const char * suffix [ ] = { " B " , " kiB " , " MiB " , " GiB " , " TiB " } ;
2014-06-26 06:30:24 +08:00
int exp = 0 ;
if ( size )
2014-06-27 01:45:47 +08:00
exp = std : : min ( ( int ) ( log ( size ) / log ( 1024 ) ) , ( int ) ( sizeof ( suffix ) / sizeof ( suffix [ 0 ] ) - 1 ) ) ;
return QString ( ) . setNum ( size / pow ( 1024 , exp ) , ' g ' , 3 ) . append ( suffix [ exp ] ) ;
2014-06-26 06:30:24 +08:00
}
2014-07-13 00:40:01 +08:00
void FileTransfertWidget : : onFileTransferInfo ( int FriendId , int FileNum , int64_t Filesize , int64_t BytesSent , ToxFile : : FileDirection Direction )
2014-06-26 06:30:24 +08:00
{
2014-06-27 01:45:47 +08:00
if ( FileNum ! = fileNum | | FriendId ! = friendId | | Direction ! = direction )
2014-06-26 06:30:24 +08:00
return ;
QDateTime newtime = QDateTime : : currentDateTime ( ) ;
int timediff = lastUpdate . secsTo ( newtime ) ;
2014-06-27 01:45:47 +08:00
if ( timediff < = 0 )
2014-06-26 06:30:24 +08:00
return ;
2014-07-13 00:40:01 +08:00
qint64 diff = BytesSent - lastBytesSent ;
2014-06-27 01:45:47 +08:00
if ( diff < 0 )
2014-07-02 01:54:26 +08:00
{
qWarning ( ) < < " FileTransfertWidget::onFileTransferInfo: Negative transfer speed ! " ;
2014-06-27 01:45:47 +08:00
diff = 0 ;
2014-07-02 01:54:26 +08:00
}
2014-06-26 06:30:24 +08:00
int rawspeed = diff / timediff ;
speed - > setText ( getHumanReadableSize ( rawspeed ) + " /s " ) ;
2014-06-27 01:45:47 +08:00
size - > setText ( getHumanReadableSize ( Filesize ) ) ;
2014-06-26 06:30:24 +08:00
if ( ! rawspeed )
return ;
2014-06-27 01:45:47 +08:00
int etaSecs = ( Filesize - BytesSent ) / rawspeed ;
2014-06-26 06:30:24 +08:00
QTime etaTime ( 0 , 0 ) ;
etaTime = etaTime . addSecs ( etaSecs ) ;
eta - > setText ( etaTime . toString ( " mm:ss " ) ) ;
2014-06-27 01:45:47 +08:00
if ( ! Filesize )
2014-08-29 01:21:48 +08:00
{
2014-06-27 01:45:47 +08:00
progress - > setValue ( 0 ) ;
2014-08-29 01:21:48 +08:00
qDebug ( ) < < QString ( " FT: received %1 bytes of an empty file, stop sending sequential devices, zetok! " ) . arg ( BytesSent ) ;
}
2014-06-27 01:45:47 +08:00
else
2014-08-29 01:21:48 +08:00
{
2014-06-27 01:45:47 +08:00
progress - > setValue ( BytesSent * 100 / Filesize ) ;
2014-08-29 01:21:48 +08:00
qDebug ( ) < < QString ( " FT: received %1/%2 bytes, progress is %3% " ) . arg ( BytesSent ) . arg ( Filesize ) . arg ( BytesSent * 100 / Filesize ) ;
}
2014-06-26 06:30:24 +08:00
lastUpdate = newtime ;
2014-06-27 01:45:47 +08:00
lastBytesSent = BytesSent ;
2014-06-26 06:30:24 +08:00
}
2014-06-27 01:45:47 +08:00
void FileTransfertWidget : : onFileTransferCancelled ( int FriendId , int FileNum , ToxFile : : FileDirection Direction )
2014-06-26 06:30:24 +08:00
{
2014-06-27 01:45:47 +08:00
if ( FileNum ! = fileNum | | FriendId ! = friendId | | Direction ! = direction )
2014-06-26 07:35:30 +08:00
return ;
2014-07-05 07:59:11 +08:00
buttonLayout - > setContentsMargins ( 0 , 0 , 0 , 0 ) ;
2014-06-26 07:48:20 +08:00
disconnect ( topright ) ;
2014-06-27 01:45:47 +08:00
disconnect ( Widget : : getInstance ( ) - > getCore ( ) , 0 , this , 0 ) ;
2014-06-26 07:35:30 +08:00
progress - > hide ( ) ;
speed - > hide ( ) ;
eta - > hide ( ) ;
topright - > hide ( ) ;
bottomright - > hide ( ) ;
2014-06-28 22:09:22 +08:00
QPalette whiteText ;
whiteText . setColor ( QPalette : : WindowText , Qt : : white ) ;
filename - > setPalette ( whiteText ) ;
size - > setPalette ( whiteText ) ;
2014-07-05 07:59:11 +08:00
this - > setObjectName ( " error " ) ;
this - > style ( ) - > polish ( this ) ;
2014-07-05 09:55:19 +08:00
//Toggle window visibility to fix draw order bug
this - > hide ( ) ;
this - > show ( ) ;
2014-06-26 06:30:24 +08:00
}
2014-06-27 01:45:47 +08:00
void FileTransfertWidget : : onFileTransferFinished ( ToxFile File )
2014-06-26 06:30:24 +08:00
{
2014-06-27 01:45:47 +08:00
if ( File . fileNum ! = fileNum | | File . friendId ! = friendId | | File . direction ! = direction )
2014-06-26 07:35:30 +08:00
return ;
2014-06-27 01:45:47 +08:00
topright - > disconnect ( ) ;
disconnect ( Widget : : getInstance ( ) - > getCore ( ) , 0 , this , 0 ) ;
2014-06-26 07:35:30 +08:00
progress - > hide ( ) ;
speed - > hide ( ) ;
eta - > hide ( ) ;
2014-06-28 21:52:17 +08:00
topright - > hide ( ) ;
2014-06-26 07:35:30 +08:00
bottomright - > hide ( ) ;
2014-07-05 09:55:19 +08:00
buttonLayout - > setContentsMargins ( 0 , 0 , 0 , 0 ) ;
2014-06-28 22:09:22 +08:00
QPalette whiteText ;
whiteText . setColor ( QPalette : : WindowText , Qt : : white ) ;
filename - > setPalette ( whiteText ) ;
size - > setPalette ( whiteText ) ;
2014-07-05 07:59:11 +08:00
this - > setObjectName ( " success " ) ;
this - > style ( ) - > polish ( this ) ;
2014-06-27 01:45:47 +08:00
2014-07-05 09:55:19 +08:00
//Toggle window visibility to fix draw order bug
this - > hide ( ) ;
this - > show ( ) ;
2014-06-27 01:45:47 +08:00
if ( File . direction = = ToxFile : : RECEIVING )
{
QPixmap preview ;
2014-07-13 00:05:25 +08:00
QFile previewFile ( File . filePath ) ;
if ( previewFile . open ( QIODevice : : ReadOnly ) & & previewFile . size ( ) < = 1024 * 1024 * 25 ) // Don't preview big (>25MiB) images
2014-06-27 01:45:47 +08:00
{
2014-07-13 00:05:25 +08:00
if ( preview . loadFromData ( previewFile . readAll ( ) ) )
{
preview = preview . scaledToHeight ( 40 ) ;
pic - > setPixmap ( preview ) ;
}
previewFile . close ( ) ;
2014-06-27 01:45:47 +08:00
}
}
2014-06-26 06:30:24 +08:00
}
2014-06-26 07:48:20 +08:00
void FileTransfertWidget : : cancelTransfer ( )
{
2014-06-27 01:45:47 +08:00
Widget : : getInstance ( ) - > getCore ( ) - > cancelFileSend ( friendId , fileNum ) ;
}
void FileTransfertWidget : : rejectRecvRequest ( )
{
Widget : : getInstance ( ) - > getCore ( ) - > rejectFileRecvRequest ( friendId , fileNum ) ;
onFileTransferCancelled ( friendId , fileNum , direction ) ;
}
2014-07-22 15:51:20 +08:00
// for whatever the fuck reason, QFileInfo::isWritable() always fails for files that don't exist
// which makes it useless for our case
// since QDir doesn't have an isWritable(), the only option I can think of is to make/delete the file
// surely this is a common problem that has a qt-implemented solution?
bool isWritable ( QString & path )
{
QFile file ( path ) ;
bool exists = file . exists ( ) ;
bool out = file . open ( QIODevice : : WriteOnly ) ;
file . close ( ) ;
if ( ! exists )
file . remove ( ) ;
return out ;
}
2014-06-27 01:45:47 +08:00
void FileTransfertWidget : : acceptRecvRequest ( )
{
2014-07-22 15:51:20 +08:00
QString path ;
while ( true )
{
2014-07-23 18:00:55 +08:00
path = QFileDialog : : getSaveFileName ( this , tr ( " Save a file " , " Title of the file saving dialog " ) , QDir : : currentPath ( ) + ' / ' + filename - > text ( ) ) ;
2014-07-22 15:51:20 +08:00
if ( path . isEmpty ( ) )
return ;
else
{
//bool savable = QFileInfo(path).isWritable();
//qDebug() << path << " is writable: " << savable;
//qDebug() << "/home/bill/bliss.pdf writable: " << QFileInfo("/home/bill/bliss.pdf").isWritable();
if ( isWritable ( path ) )
break ;
else
2014-07-23 18:00:55 +08:00
QMessageBox : : warning ( this , tr ( " Location not writable " , " Title of permissions popup " ) , tr ( " You do not have permission to write that location. Choose another, or cancel the save dialog. " , " text of permissions popup " ) ) ;
2014-07-22 15:51:20 +08:00
}
}
2014-06-27 01:45:47 +08:00
savePath = path ;
2014-06-28 21:52:17 +08:00
bottomright - > setStyleSheet ( pauseFileButtonStylesheet ) ;
2014-06-27 01:45:47 +08:00
bottomright - > disconnect ( ) ;
connect ( bottomright , SIGNAL ( clicked ( ) ) , this , SLOT ( pauseResumeRecv ( ) ) ) ;
2014-07-02 01:54:26 +08:00
Widget : : getInstance ( ) - > getCore ( ) - > acceptFileRecvRequest ( friendId , fileNum , path ) ;
2014-06-27 01:45:47 +08:00
}
void FileTransfertWidget : : pauseResumeRecv ( )
{
Widget : : getInstance ( ) - > getCore ( ) - > pauseResumeFileRecv ( friendId , fileNum ) ;
}
void FileTransfertWidget : : pauseResumeSend ( )
{
Widget : : getInstance ( ) - > getCore ( ) - > pauseResumeFileSend ( friendId , fileNum ) ;
2014-06-26 07:48:20 +08:00
}
2014-07-05 07:59:11 +08:00
void FileTransfertWidget : : paintEvent ( QPaintEvent * )
{
QStyleOption opt ;
opt . init ( this ) ;
QPainter p ( this ) ;
style ( ) - > drawPrimitive ( QStyle : : PE_Widget , & opt , & p , this ) ;
}