mirror of
https://github.com/RetroShare/RetroShare.git
synced 2024-10-01 02:35:48 -04:00
dd4c43cf7d
Add a single action to send files as message. Add send as message to the remote files too. The files are now send as recommended files. Disable context menus for the person item. Auto hide the AttachFileItem in all dialogs after the successfully finish of the hash. Removed the column source of the files in messages. git-svn-id: http://svn.code.sf.net/p/retroshare/code/trunk@3759 b45a01b8-16f6-495d-af2f-9b41ad6348cc
526 lines
11 KiB
C++
526 lines
11 KiB
C++
/****************************************************************
|
|
* RetroShare is distributed under the following license:
|
|
*
|
|
* Copyright (C) 2008 Robert Fernie
|
|
*
|
|
* 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., 51 Franklin Street, Fifth Floor,
|
|
* Boston, MA 02110-1301, USA.
|
|
****************************************************************/
|
|
|
|
#include <QTimer>
|
|
|
|
#include "AttachFileItem.h"
|
|
|
|
#include <retroshare/rsfiles.h>
|
|
|
|
/****
|
|
* #define DEBUG_ITEM 1
|
|
****/
|
|
|
|
/*******************************************************************
|
|
* AttachFileItem fully controls the file transfer from the gui side
|
|
*
|
|
* Display: (In order)
|
|
*
|
|
* 1) HASHING
|
|
* 2) REMOTE / DOWNLOAD
|
|
* 3) LOCAL
|
|
* 4) LOCAL / UPLOAD
|
|
*
|
|
* Behaviours:
|
|
* a) Addition to General Dialog (1), (2), (3)
|
|
* (i) (1), request Hash -> (3).
|
|
* (ii) (2), download complete -> (3)
|
|
* (iii) (3)
|
|
*
|
|
* b) Message/Blog/Channel (2), (3)
|
|
* (i) (2), download complete -> (3)
|
|
* (ii) (3)
|
|
*
|
|
* c) Transfers (2), (4)
|
|
* (i) (2)
|
|
* (ii) (3)
|
|
*
|
|
*
|
|
*/
|
|
|
|
|
|
|
|
const uint32_t AFI_DEFAULT_PERIOD = (30 * 3600 * 24); /* 30 Days */
|
|
|
|
/** Constructor */
|
|
AttachFileItem::AttachFileItem(std::string hash, std::string name, uint64_t size,
|
|
uint32_t flags, std::string srcId)
|
|
:QWidget(NULL), mFileHash(hash), mFileName(name), mFileSize(size), mSrcId(srcId)
|
|
{
|
|
/* Invoke the Qt Designer generated object setup routine */
|
|
setupUi(this);
|
|
|
|
setAttribute ( Qt::WA_DeleteOnClose, true );
|
|
|
|
mMode = flags & AFI_MASK_STATE;
|
|
mType = flags & AFI_MASK_TYPE;
|
|
mPicFlag=0;
|
|
|
|
if (mMode == AFI_STATE_EXTRA)
|
|
{
|
|
mMode = AFI_STATE_ERROR;
|
|
}
|
|
/**** Enable ****
|
|
*****/
|
|
|
|
/* all other states are possible */
|
|
|
|
if (!rsFiles)
|
|
{
|
|
mMode = AFI_STATE_ERROR;
|
|
}
|
|
|
|
Setup();
|
|
}
|
|
|
|
/** Constructor */
|
|
AttachFileItem::AttachFileItem(std::string path)
|
|
:QWidget(NULL), mPath(path), mFileSize(0)
|
|
{
|
|
/* Invoke the Qt Designer generated object setup routine */
|
|
setupUi(this);
|
|
|
|
mMode = AFI_STATE_EXTRA;
|
|
mType = AFI_TYPE_ATTACH;
|
|
mPicFlag=0;
|
|
|
|
/* ask for Files to hash/prepare it for us */
|
|
if ((!rsFiles) || (!rsFiles->ExtraFileHash(path, AFI_DEFAULT_PERIOD, 0)))
|
|
{
|
|
mMode = AFI_STATE_ERROR;
|
|
}
|
|
|
|
Setup();
|
|
}
|
|
|
|
void AttachFileItem::Setup()
|
|
{
|
|
|
|
connect( cancelButton, SIGNAL( clicked( void ) ), this, SLOT( cancel ( void ) ) );
|
|
|
|
/* once off check - if remote, check if we have it
|
|
* NB: This check might be expensive - and it'll happen often!
|
|
*/
|
|
#ifdef DEBUG_ITEM
|
|
std::cerr << "AttachFileItem::Setup(): " << mFileName;
|
|
std::cerr << std::endl;
|
|
#endif
|
|
|
|
if (mMode == AFI_STATE_REMOTE)
|
|
{
|
|
FileInfo fi;
|
|
uint32_t hintflags = RS_FILE_HINTS_EXTRA | RS_FILE_HINTS_LOCAL
|
|
| RS_FILE_HINTS_SPEC_ONLY;
|
|
|
|
/* look up path */
|
|
if (rsFiles->FileDetails(mFileHash, hintflags, fi))
|
|
{
|
|
#ifdef DEBUG_ITEM
|
|
std::cerr << "AttachFileItem::Setup() STATE=>Local Found File";
|
|
std::cerr << std::endl;
|
|
std::cerr << "AttachFileItem::Setup() path: " << fi.path;
|
|
std::cerr << std::endl;
|
|
#endif
|
|
mMode = AFI_STATE_LOCAL;
|
|
mPath = fi.path;
|
|
}
|
|
}
|
|
|
|
updateItemStatic();
|
|
updateItem();
|
|
|
|
|
|
}
|
|
|
|
|
|
bool AttachFileItem::done()
|
|
{
|
|
return (mMode >= AFI_STATE_LOCAL);
|
|
}
|
|
|
|
bool AttachFileItem::ready()
|
|
{
|
|
return (mMode >= AFI_STATE_REMOTE);
|
|
}
|
|
|
|
void AttachFileItem::updateItemStatic()
|
|
{
|
|
/* fill in */
|
|
#ifdef DEBUG_ITEM
|
|
std::cerr << "AttachFileItem::updateItemStatic(): " << mFileName;
|
|
std::cerr << std::endl;
|
|
#endif
|
|
|
|
QString filename = QString::fromUtf8(mFileName.c_str());
|
|
mDivisor = 1;
|
|
|
|
if (mFileSize > 10000000) /* 10 Mb */
|
|
{
|
|
progressBar->setRange(0, mFileSize / 1000000);
|
|
progressBar->setFormat("%v MB");
|
|
mDivisor = 1000000;
|
|
}
|
|
else if (mFileSize > 10000) /* 10 Kb */
|
|
{
|
|
progressBar->setRange(0, mFileSize / 1000);
|
|
progressBar->setFormat("%v kB");
|
|
mDivisor = 1000;
|
|
}
|
|
else
|
|
{
|
|
progressBar->setRange(0, mFileSize);
|
|
progressBar->setFormat("%v B");
|
|
mDivisor = 1;
|
|
}
|
|
|
|
/* get full path for local file */
|
|
if ((mMode == AFI_STATE_LOCAL) || (mMode == AFI_STATE_UPLOAD))
|
|
{
|
|
#ifdef DEBUG_ITEM
|
|
std::cerr << "AttachFileItem::updateItemStatic() STATE=Local/Upload checking path";
|
|
std::cerr << std::endl;
|
|
#endif
|
|
if (mPath == "")
|
|
{
|
|
FileInfo fi;
|
|
uint32_t hintflags = RS_FILE_HINTS_UPLOAD | RS_FILE_HINTS_LOCAL
|
|
| RS_FILE_HINTS_SPEC_ONLY;
|
|
|
|
/* look up path */
|
|
if (!rsFiles->FileDetails(mFileHash, hintflags, fi))
|
|
{
|
|
mMode = AFI_STATE_ERROR;
|
|
#ifdef DEBUG_ITEM
|
|
std::cerr << "AttachFileItem::updateItemStatic() STATE=>Error No Details";
|
|
std::cerr << std::endl;
|
|
#endif
|
|
}
|
|
else
|
|
{
|
|
#ifdef DEBUG_ITEM
|
|
std::cerr << "AttachFileItem::updateItemStatic() Updated Path";
|
|
std::cerr << std::endl;
|
|
#endif
|
|
mPath = fi.path;
|
|
}
|
|
}
|
|
}
|
|
|
|
/* do buttons + display */
|
|
switch (mMode)
|
|
{
|
|
case AFI_STATE_ERROR:
|
|
progressBar->setRange(0, 100);
|
|
progressBar->setFormat("ERROR");
|
|
|
|
cancelButton->setEnabled(false);
|
|
|
|
progressBar->setValue(0);
|
|
filename = "[ERROR] " + filename;
|
|
|
|
break;
|
|
|
|
case AFI_STATE_EXTRA:
|
|
filename = QString::fromUtf8(mPath.c_str());
|
|
|
|
progressBar->setRange(0, 100);
|
|
progressBar->setFormat("HASHING");
|
|
|
|
cancelButton->setEnabled(false);
|
|
|
|
progressBar->setValue(0);
|
|
filename = "[EXTRA] " + filename;
|
|
|
|
break;
|
|
|
|
case AFI_STATE_REMOTE:
|
|
cancelButton->setEnabled(false);
|
|
|
|
progressBar->setValue(0);
|
|
filename = "[REMOTE] " + filename;
|
|
|
|
break;
|
|
|
|
case AFI_STATE_DOWNLOAD:
|
|
cancelButton->setEnabled(true);
|
|
filename = "[DOWNLOAD] " + filename;
|
|
|
|
break;
|
|
|
|
case AFI_STATE_LOCAL:
|
|
cancelButton->setEnabled(false);
|
|
|
|
progressBar->setValue(mFileSize / mDivisor);
|
|
filename = "[LOCAL] " + filename;
|
|
|
|
break;
|
|
|
|
case AFI_STATE_UPLOAD:
|
|
cancelButton->setEnabled(false);
|
|
filename = "[UPLOAD] " + filename;
|
|
|
|
break;
|
|
}
|
|
|
|
|
|
switch(mType)
|
|
{
|
|
case AFI_TYPE_CHANNEL:
|
|
{
|
|
if (mMode == AFI_STATE_LOCAL)
|
|
{
|
|
}
|
|
else
|
|
{
|
|
}
|
|
}
|
|
break;
|
|
case AFI_TYPE_ATTACH:
|
|
{
|
|
cancelButton->setEnabled(true);
|
|
cancelButton->setToolTip("Remove Attachment");
|
|
}
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
|
|
|
|
fileLabel->setText(filename);
|
|
fileLabel->setToolTip(filename);
|
|
|
|
}
|
|
|
|
void AttachFileItem::updateItem()
|
|
{
|
|
/* fill in */
|
|
#ifdef DEBUG_ITEM
|
|
std::cerr << "AttachFileItem::updateItem():" << mFileName;
|
|
std::cerr << std::endl;
|
|
#endif
|
|
|
|
/* Extract File Details */
|
|
/* Update State if necessary */
|
|
|
|
FileInfo fi;
|
|
bool stateChanged = false;
|
|
int msec_rate = 1000;
|
|
|
|
if ((mMode == AFI_STATE_ERROR) || (mMode == AFI_STATE_LOCAL))
|
|
{
|
|
#ifdef DEBUG_ITEM
|
|
std::cerr << "AttachFileItem::updateItem() STATE=Local/Error ignore";
|
|
std::cerr << std::endl;
|
|
#endif
|
|
/* ignore - dead file, or done */
|
|
}
|
|
else if (mMode == AFI_STATE_EXTRA)
|
|
{
|
|
#ifdef DEBUG_ITEM
|
|
std::cerr << "AttachFileItem::updateItem() STATE=Extra File";
|
|
std::cerr << std::endl;
|
|
#endif
|
|
/* check for file status */
|
|
if (rsFiles->ExtraFileStatus(mPath, fi))
|
|
{
|
|
#ifdef DEBUG_ITEM
|
|
std::cerr << "AttachFileItem::updateItem() STATE=>Local";
|
|
std::cerr << std::endl;
|
|
#endif
|
|
mMode = AFI_STATE_LOCAL;
|
|
|
|
/* fill in file details */
|
|
mFileName = fi.fname;
|
|
mFileSize = fi.size;
|
|
mFileHash = fi.hash;
|
|
|
|
/* have path already! */
|
|
|
|
stateChanged = true;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
uint32_t hintflags = 0;
|
|
switch(mMode)
|
|
{
|
|
case AFI_STATE_REMOTE:
|
|
hintflags = RS_FILE_HINTS_DOWNLOAD | RS_FILE_HINTS_SPEC_ONLY;
|
|
break;
|
|
case AFI_STATE_DOWNLOAD:
|
|
hintflags = RS_FILE_HINTS_DOWNLOAD | RS_FILE_HINTS_SPEC_ONLY;
|
|
break;
|
|
case AFI_STATE_UPLOAD:
|
|
hintflags = RS_FILE_HINTS_UPLOAD | RS_FILE_HINTS_SPEC_ONLY;
|
|
break;
|
|
}
|
|
|
|
bool detailsOk = rsFiles->FileDetails(mFileHash, hintflags, fi);
|
|
|
|
/* have details - see if state has changed */
|
|
switch(mMode)
|
|
{
|
|
case AFI_STATE_REMOTE:
|
|
#ifdef DEBUG_ITEM
|
|
std::cerr << "AttachFileItem::updateItem() STATE=Remote";
|
|
std::cerr << std::endl;
|
|
#endif
|
|
/* is it downloading? */
|
|
if (detailsOk)
|
|
{
|
|
#ifdef DEBUG_ITEM
|
|
std::cerr << "AttachFileItem::updateItem() STATE=>Download";
|
|
std::cerr << std::endl;
|
|
#endif
|
|
/* downloading */
|
|
mMode = AFI_STATE_DOWNLOAD;
|
|
stateChanged = true;
|
|
}
|
|
break;
|
|
case AFI_STATE_DOWNLOAD:
|
|
#ifdef DEBUG_ITEM
|
|
std::cerr << "AttachFileItem::updateItem() STATE=Download";
|
|
std::cerr << std::endl;
|
|
#endif
|
|
|
|
if (!detailsOk)
|
|
{
|
|
#ifdef DEBUG_ITEM
|
|
std::cerr << "AttachFileItem::updateItem() STATE=>Remote";
|
|
std::cerr << std::endl;
|
|
#endif
|
|
mMode = AFI_STATE_REMOTE;
|
|
stateChanged = true;
|
|
}
|
|
else
|
|
{
|
|
/* has it completed? */
|
|
if (fi.avail == mFileSize)
|
|
{
|
|
#ifdef DEBUG_ITEM
|
|
std::cerr << "AttachFileItem::updateItem() STATE=>Local";
|
|
std::cerr << std::endl;
|
|
#endif
|
|
/* save path */
|
|
/* update progress */
|
|
mMode = AFI_STATE_LOCAL;
|
|
mPath = fi.path;
|
|
stateChanged = true;
|
|
}
|
|
progressBar->setValue(fi.avail / mDivisor);
|
|
}
|
|
break;
|
|
case AFI_STATE_UPLOAD:
|
|
#ifdef DEBUG_ITEM
|
|
std::cerr << "AttachFileItem::updateItem() STATE=Upload";
|
|
std::cerr << std::endl;
|
|
#endif
|
|
|
|
if (detailsOk)
|
|
{
|
|
progressBar->setValue(fi.avail / mDivisor);
|
|
}
|
|
|
|
/* update progress */
|
|
break;
|
|
}
|
|
|
|
}
|
|
|
|
/****** update based on new state ******/
|
|
if (stateChanged)
|
|
{
|
|
updateItemStatic();
|
|
}
|
|
|
|
uint32_t repeat = 0;
|
|
|
|
switch (mMode)
|
|
{
|
|
case AFI_STATE_ERROR:
|
|
repeat = 0;
|
|
break;
|
|
|
|
case AFI_STATE_EXTRA:
|
|
repeat = 1;
|
|
msec_rate = 5000; /* slow */
|
|
break;
|
|
|
|
case AFI_STATE_REMOTE:
|
|
repeat = 1;
|
|
msec_rate = 30000; /* very slow */
|
|
break;
|
|
|
|
case AFI_STATE_DOWNLOAD:
|
|
repeat = 1;
|
|
msec_rate = 2000; /* should be download rate dependent */
|
|
break;
|
|
|
|
case AFI_STATE_LOCAL:
|
|
repeat = 0;
|
|
emit fileFinished(this);
|
|
hide(); // auto hide
|
|
break;
|
|
|
|
case AFI_STATE_UPLOAD:
|
|
repeat = 1;
|
|
msec_rate = 2000; /* should be download rate dependent */
|
|
break;
|
|
}
|
|
|
|
|
|
if (repeat)
|
|
{
|
|
#ifdef DEBUG_ITEM
|
|
std::cerr << "AttachFileItem::updateItem() callback for update!";
|
|
std::cerr << std::endl;
|
|
#endif
|
|
QTimer::singleShot( msec_rate, this, SLOT(updateItem( void ) ));
|
|
}
|
|
|
|
}
|
|
|
|
|
|
void AttachFileItem::cancel()
|
|
{
|
|
#ifdef DEBUG_ITEM
|
|
std::cerr << "AttachFileItem::cancel()";
|
|
std::cerr << std::endl;
|
|
#endif
|
|
//set the state to error mode
|
|
mMode = AFI_STATE_ERROR;
|
|
|
|
/* Only occurs - if it is downloading */
|
|
if (mType == AFI_TYPE_ATTACH)
|
|
{
|
|
hide();
|
|
}
|
|
else
|
|
{
|
|
rsFiles->FileCancel(mFileHash);
|
|
}
|
|
}
|
|
|
|
|
|
uint32_t AttachFileItem::getState() {
|
|
return mMode;
|
|
}
|