summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGluzskiy Alexandr <sss@sss.chaoslab.ru>2018-02-09 22:01:26 +0300
committerGluzskiy Alexandr <sss@sss.chaoslab.ru>2018-02-09 22:01:26 +0300
commit7829ddd87d91d1c72f26021f2884330a560d73fd (patch)
tree413840851ca0c762b6a7b800e7369425e303f279
parentb237b41dcff0940171b54893e95c6cc68e2a97e7 (diff)
retrosahre: preview of new filetransfers ui implementation
-rw-r--r--net-p2p/retroshare/files/copy_lobby_name_to_clipboard.patch64
-rw-r--r--net-p2p/retroshare/files/rs-ft-1169.diff1177
-rw-r--r--net-p2p/retroshare/retroshare-scm.ebuild1
-rw-r--r--net-p2p/retroshare/retroshare-scm.ebuild~189
4 files changed, 1431 insertions, 0 deletions
diff --git a/net-p2p/retroshare/files/copy_lobby_name_to_clipboard.patch b/net-p2p/retroshare/files/copy_lobby_name_to_clipboard.patch
new file mode 100644
index 0000000..a1efe6b
--- /dev/null
+++ b/net-p2p/retroshare/files/copy_lobby_name_to_clipboard.patch
@@ -0,0 +1,64 @@
+diff --git a/retroshare-gui/src/gui/ChatLobbyWidget.cpp b/retroshare-gui/src/gui/ChatLobbyWidget.cpp
+index 1ec3d39f0..37c630e1e 100644
+--- a/retroshare-gui/src/gui/ChatLobbyWidget.cpp
++++ b/retroshare-gui/src/gui/ChatLobbyWidget.cpp
+@@ -25,6 +25,7 @@
+ #include <QTextBrowser>
+ #include <QTimer>
+ #include <QTreeWidget>
++#include <QClipboard>
+
+ #include <algorithm>
+ #include <time.h>
+@@ -325,6 +326,9 @@ void ChatLobbyWidget::lobbyTreeWidgetCustomPopupMenu(QPoint)
+ contextMnu.addAction(QIcon(IMAGE_SUBSCRIBE), tr("Add Auto Subscribe"), this, SLOT(autoSubscribeItem()));
+
+ contextMnu.addAction(QIcon(IMAGE_COPYRSLINK), tr("Copy RetroShare Link"), this, SLOT(copyItemLink()));
++
++ if(!item->text(COLUMN_NAME).isEmpty())
++ contextMnu.addAction(QIcon(IMAGE_COPYRSLINK), tr("Copy name to clipboard"), this, SLOT(copyLobbyNameToClipboard()));
+ }
+
+ contextMnu.addSeparator();//-------------------------------------------------------------------
+@@ -898,9 +902,8 @@ void ChatLobbyWidget::autoSubscribeItem()
+ void ChatLobbyWidget::copyItemLink()
+ {
+ QTreeWidgetItem *item = ui.lobbyTreeWidget->currentItem();
+- if (item == NULL || item->type() != TYPE_LOBBY) {
++ if (item == NULL) //this is always lobby, do not need to check twice
+ return;
+- }
+
+ ChatLobbyId id = item->data(COLUMN_DATA, ROLE_ID).toULongLong();
+ QString name = item->text(COLUMN_NAME);
+@@ -913,6 +916,18 @@ void ChatLobbyWidget::copyItemLink()
+ }
+ }
+
++
++void ChatLobbyWidget::copyLobbyNameToClipboard()
++{
++ QTreeWidgetItem *item = ui.lobbyTreeWidget->currentItem();
++ if (item == NULL)
++ return;
++
++ QClipboard *clipboard = QGuiApplication::clipboard();
++ clipboard->setText(item->text(COLUMN_NAME));
++}
++
++
+ QTreeWidgetItem *ChatLobbyWidget::getTreeWidgetItem(ChatLobbyId id)
+ {
+ for(int p=0;p<4;++p)
+diff --git a/retroshare-gui/src/gui/ChatLobbyWidget.h b/retroshare-gui/src/gui/ChatLobbyWidget.h
+index cc3c26af3..86dadb7f0 100644
+--- a/retroshare-gui/src/gui/ChatLobbyWidget.h
++++ b/retroshare-gui/src/gui/ChatLobbyWidget.h
+@@ -79,6 +79,7 @@ protected slots:
+ void updatePeerLeaving(ChatLobbyId);
+ void autoSubscribeItem();
+ void copyItemLink();
++ void copyLobbyNameToClipboard();
+
+ private slots:
+ void filterColumnChanged(int);
diff --git a/net-p2p/retroshare/files/rs-ft-1169.diff b/net-p2p/retroshare/files/rs-ft-1169.diff
new file mode 100644
index 0000000..1896f9b
--- /dev/null
+++ b/net-p2p/retroshare/files/rs-ft-1169.diff
@@ -0,0 +1,1177 @@
+diff --git a/RetroShare.pro b/RetroShare.pro
+index 833173029..dba75453e 100644
+--- a/RetroShare.pro
++++ b/RetroShare.pro
+@@ -56,12 +56,12 @@ retroshare_qml_app {
+ }
+ }
+
+-retroshare_plugins {
+- SUBDIRS += plugins
+- plugins.file = plugins/plugins.pro
+- plugins.depends = retroshare_gui
+- plugins.target = plugins
+-}
++#retroshare_plugins {
++# SUBDIRS += plugins
++# plugins.file = plugins/plugins.pro
++# plugins.depends = retroshare_gui
++# plugins.target = plugins
++#}
+
+ wikipoos {
+ SUBDIRS += pegmarkdown
+diff --git a/libresapi/src/api/FileSharingHandler.cpp b/libresapi/src/api/FileSharingHandler.cpp
+index 856275d9c..a6296973d 100644
+--- a/libresapi/src/api/FileSharingHandler.cpp
++++ b/libresapi/src/api/FileSharingHandler.cpp
+@@ -500,7 +500,7 @@ void FileSharingHandler::handleDownload(Request& req, Response& resp)
+ FileInfo finfo;
+ mRsFiles->FileDetails(hash, RS_FILE_HINTS_REMOTE, finfo);
+
+- for(std::list<TransferInfo>::const_iterator it(finfo.peers.begin());it!=finfo.peers.end();++it)
++ for(std::vector<TransferInfo>::const_iterator it(finfo.peers.begin());it!=finfo.peers.end();++it)
+ srcIds.push_back((*it).peerId);
+
+ if(!mRsFiles->FileRequest(name, hash, static_cast<uint64_t>(size), "",
+diff --git a/libresapi/src/api/TransfersHandler.cpp b/libresapi/src/api/TransfersHandler.cpp
+index f563f377c..c696411da 100644
+--- a/libresapi/src/api/TransfersHandler.cpp
++++ b/libresapi/src/api/TransfersHandler.cpp
+@@ -91,7 +91,7 @@ void TransfersHandler::handleControlDownload(Request &req, Response &resp)
+ FileInfo finfo;
+ mFiles->FileDetails(hash, RS_FILE_HINTS_REMOTE, finfo);
+
+- for(std::list<TransferInfo>::const_iterator it(finfo.peers.begin());it!=finfo.peers.end();++it)
++ for(std::vector<TransferInfo>::const_iterator it(finfo.peers.begin());it!=finfo.peers.end();++it)
+ srcIds.push_back((*it).peerId);
+
+ bool ok = req.mStream.isOK();
+@@ -213,8 +213,7 @@ void TransfersHandler::handleUploads(Request & /* req */, Response &resp)
+ FileInfo fi;
+ if(mFiles->FileDetails(*lit, RS_FILE_HINTS_UPLOAD, fi))
+ {
+- std::list<TransferInfo>::iterator pit;
+- for(pit = fi.peers.begin(); pit != fi.peers.end(); ++pit)
++ for( std::vector<TransferInfo>::iterator pit = fi.peers.begin(); pit != fi.peers.end(); ++pit)
+ {
+ if (pit->peerId == ownId) //don't display transfer to ourselves
+ continue ;
+diff --git a/libretroshare/src/ft/ftcontroller.cc b/libretroshare/src/ft/ftcontroller.cc
+index 382d13cb6..29713cb3e 100644
+--- a/libretroshare/src/ft/ftcontroller.cc
++++ b/libretroshare/src/ft/ftcontroller.cc
+@@ -301,7 +301,7 @@ void ftController::searchForDirectSources()
+ FileInfo info ; // Info needs to be re-allocated each time, to start with a clear list of peers (it's not cleared down there)
+
+ if( mSearch->search(it->first, RS_FILE_HINTS_REMOTE | RS_FILE_HINTS_SPEC_ONLY, info) )
+- for( std::list<TransferInfo>::const_iterator pit = info.peers.begin(); pit != info.peers.end(); ++pit )
++ for( std::vector<TransferInfo>::const_iterator pit = info.peers.begin(); pit != info.peers.end(); ++pit )
+ {
+ bool bAllowDirectDL = false;
+ switch (mFilePermDirectDLPolicy) {
+@@ -1029,7 +1029,7 @@ bool ftController::FileRequest(const std::string& fname, const RsFileHash& hash
+ }
+
+ std::list<RsPeerId>::const_iterator it;
+- std::list<TransferInfo>::const_iterator pit;
++ std::vector<TransferInfo>::const_iterator pit;
+
+ #ifdef CONTROL_DEBUG
+ std::cerr << "ftController::FileRequest(" << fname << ",";
+@@ -1622,6 +1622,8 @@ bool ftController::FileDetails(const RsFileHash &hash, FileInfo &info)
+ bool isDownloading = false;
+ bool isSuspended = false;
+
++ info.peers.clear();
++
+ for(pit = peerIds.begin(); pit != peerIds.end(); ++pit)
+ {
+ if (it->second->mTransfer->getPeerState(*pit, state, tfRate))
+diff --git a/libretroshare/src/retroshare/rstypes.h b/libretroshare/src/retroshare/rstypes.h
+index 9c098db59..cc04d2312 100644
+--- a/libretroshare/src/retroshare/rstypes.h
++++ b/libretroshare/src/retroshare/rstypes.h
+@@ -208,7 +208,7 @@ class FileInfo
+ uint64_t transfered;
+ double tfRate; /* in kbytes */
+ uint32_t downloadStatus; // FT_STATE_DOWNLOADING & co. See rstypes.h
+- std::list<TransferInfo> peers;
++ std::vector<TransferInfo> peers;
+
+ DwlSpeed priority ;
+ time_t lastTS;
+diff --git a/retroshare-gui/src/gui/FileTransfer/DLListDelegate.h b/retroshare-gui/src/gui/FileTransfer/DLListDelegate.h
+index 7516b17af..11bfd149f 100644
+--- a/retroshare-gui/src/gui/FileTransfer/DLListDelegate.h
++++ b/retroshare-gui/src/gui/FileTransfer/DLListDelegate.h
+@@ -27,26 +27,25 @@
+
+
+ // Defines for download list list columns
+-#define COLUMN_NAME 0
+-#define COLUMN_SIZE 1
+-#define COLUMN_COMPLETED 2
+-#define COLUMN_DLSPEED 3
+-#define COLUMN_PROGRESS 4
+-#define COLUMN_SOURCES 5
+-#define COLUMN_STATUS 6
+-#define COLUMN_PRIORITY 7
+-#define COLUMN_REMAINING 8
++#define COLUMN_NAME 0
++#define COLUMN_SIZE 1
++#define COLUMN_COMPLETED 2
++#define COLUMN_DLSPEED 3
++#define COLUMN_PROGRESS 4
++#define COLUMN_SOURCES 5
++#define COLUMN_STATUS 6
++#define COLUMN_PRIORITY 7
++#define COLUMN_REMAINING 8
+ #define COLUMN_DOWNLOADTIME 9
+-#define COLUMN_ID 10
+-#define COLUMN_LASTDL 11
+-#define COLUMN_PATH 12
+-#define COLUMN_COUNT 13
+-
+-#define PRIORITY_NULL 0.0
+-#define PRIORITY_FASTER 0.1
+-#define PRIORITY_AVERAGE 0.2
+-#define PRIORITY_SLOWER 0.3
+-
++#define COLUMN_ID 10
++#define COLUMN_LASTDL 11
++#define COLUMN_PATH 12
++#define COLUMN_COUNT 13
++
++#define PRIORITY_NULL 0.0
++#define PRIORITY_FASTER 0.1
++#define PRIORITY_AVERAGE 0.2
++#define PRIORITY_SLOWER 0.3
+
+ #define MAX_CHAR_TMP 128
+
+diff --git a/retroshare-gui/src/gui/FileTransfer/SearchDialog.cpp b/retroshare-gui/src/gui/FileTransfer/SearchDialog.cpp
+index ee85a1d92..bc2f08644 100644
+--- a/retroshare-gui/src/gui/FileTransfer/SearchDialog.cpp
++++ b/retroshare-gui/src/gui/FileTransfer/SearchDialog.cpp
+@@ -368,7 +368,7 @@ void SearchDialog::getSourceFriendsForHash(const RsFileHash& hash,std::list<RsPe
+ FileInfo finfo ;
+ rsFiles->FileDetails(hash, RS_FILE_HINTS_REMOTE,finfo) ;
+
+- for(std::list<TransferInfo>::const_iterator it(finfo.peers.begin());it!=finfo.peers.end();++it)
++ for(std::vector<TransferInfo>::const_iterator it(finfo.peers.begin());it!=finfo.peers.end();++it)
+ {
+ std::cerr << " adding peerid " << (*it).peerId << std::endl ;
+ srcIds.push_back((*it).peerId) ;
+diff --git a/retroshare-gui/src/gui/FileTransfer/TransfersDialog.cpp b/retroshare-gui/src/gui/FileTransfer/TransfersDialog.cpp
+index 196bc90ac..5cda97e5c 100644
+--- a/retroshare-gui/src/gui/FileTransfer/TransfersDialog.cpp
++++ b/retroshare-gui/src/gui/FileTransfer/TransfersDialog.cpp
+@@ -76,10 +76,10 @@
+ #define IMAGE_STOP ":/images/stop.png"
+ #define IMAGE_PREVIEW ":/images/preview.png"
+ #define IMAGE_PRIORITY ":/images/filepriority.png"
+-#define IMAGE_PRIORITYLOW ":/images/prioritylow.png"
+-#define IMAGE_PRIORITYNORMAL ":/images/prioritynormal.png"
+-#define IMAGE_PRIORITYHIGH ":/images/priorityhigh.png"
+-#define IMAGE_PRIORITYAUTO ":/images/priorityauto.png"
++#define IMAGE_PRIORITYLOW ":/images/prioritylow.png"
++#define IMAGE_PRIORITYNORMAL ":/images/prioritynormal.png"
++#define IMAGE_PRIORITYHIGH ":/images/priorityhigh.png"
++#define IMAGE_PRIORITYAUTO ":/images/priorityauto.png"
+ #define IMAGE_SEARCH ":/icons/svg/magnifying-glass.svg"
+ #define IMAGE_EXPAND ":/images/edit_add24.png"
+ #define IMAGE_COLLAPSE ":/images/edit_remove24.png"
+@@ -98,6 +98,591 @@
+
+ Q_DECLARE_METATYPE(FileProgressInfo)
+
++class RsDownloadListModel : public QAbstractItemModel
++{
++ // Q_OBJECT
++
++public:
++ explicit RsDownloadListModel(QObject *parent = NULL) : QAbstractItemModel(parent) {}
++ ~RsDownloadListModel(){}
++
++ enum Roles{ SortRole = Qt::UserRole+1 };
++
++ int rowCount(const QModelIndex& parent = QModelIndex()) const
++ {
++ void *ref = (parent.isValid())?parent.internalPointer():NULL ;
++
++ if(!ref)
++ return mDownloads.size() ;
++
++ uint32_t entry = 0 ;
++ int source_id ;
++
++ if(!convertRefPointerToTabEntry(ref,entry,source_id) || entry >= mDownloads.size())
++ return 0 ;
++
++ return mDownloads[entry].peers.size(); // costly
++ }
++ int columnCount(const QModelIndex &parent = QModelIndex()) const
++ {
++ return 13 ;
++ }
++ bool hasChildren(const QModelIndex &parent = QModelIndex()) const
++ {
++ void *ref = (parent.isValid())?parent.internalPointer():NULL ;
++ uint32_t entry = 0;
++ int source_id=0 ;
++
++ if(!ref)
++ return true ;
++
++ if(!convertRefPointerToTabEntry(ref,entry,source_id) || entry >= mDownloads.size() || source_id > -1)
++ return false ;
++
++ return !mDownloads[entry].peers.empty(); // costly
++ }
++
++ QModelIndex index(int row, int column, const QModelIndex & parent = QModelIndex()) const
++ {
++ if(row < 0)
++ return QModelIndex();
++
++ void *ref = (parent.isValid())?parent.internalPointer():NULL ;
++ uint32_t entry = 0;
++ int source_id=0 ;
++ void *subref = NULL ;
++
++ if(!ref) // top level. The entry is that of a transfer
++ {
++ if(!convertTabEntryToRefPointer(row,-1,subref))
++ return QModelIndex() ;
++
++ return createIndex(row,column,subref) ;
++ }
++
++ if(!convertRefPointerToTabEntry(ref,entry,source_id) || entry >= mDownloads.size() || int(mDownloads[entry].peers.size()) <= source_id)
++ return QModelIndex() ;
++
++ if(source_id != -1)
++ std::cerr << "ERROR: parent.source_id != -1 in index()" << std::endl;
++
++ if(!convertTabEntryToRefPointer(entry,row,subref))
++ return QModelIndex() ;
++
++ return createIndex(row,column,subref) ;
++ }
++ QModelIndex parent(const QModelIndex& child) const
++ {
++ void *ref = (child.isValid())?child.internalPointer():NULL ;
++ uint32_t entry = 0;
++ int source_id=0 ;
++
++ if(!ref)
++ return QModelIndex() ;
++
++ if(!convertRefPointerToTabEntry(ref,entry,source_id) || entry >= mDownloads.size() || int(mDownloads[entry].peers.size()) <= source_id)
++ return QModelIndex() ;
++
++ if(source_id < 0)
++ return QModelIndex() ;
++
++ void *subref =NULL;
++
++ if(!convertTabEntryToRefPointer(entry,-1,subref))
++ return QModelIndex() ;
++
++ return createIndex(entry,0,subref) ;
++ }
++
++ QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const
++ {
++ if(role != Qt::DisplayRole)
++ return QVariant();
++
++ switch(section)
++ {
++ default:
++ case COLUMN_NAME: return tr("Name", "i.e: file name");
++ case COLUMN_SIZE: return tr("Size", "i.e: file size");
++ case COLUMN_COMPLETED: return tr("Completed", "");
++ case COLUMN_DLSPEED: return tr("Speed", "i.e: Download speed");
++ case COLUMN_PROGRESS: return tr("Progress / Availability", "i.e: % downloaded");
++ case COLUMN_SOURCES: return tr("Sources", "i.e: Sources");
++ case COLUMN_STATUS: return tr("Status");
++ case COLUMN_PRIORITY: return tr("Speed / Queue position");
++ case COLUMN_REMAINING: return tr("Remaining");
++ case COLUMN_DOWNLOADTIME: return tr("Download time", "i.e: Estimated Time of Arrival / Time left");
++ case COLUMN_ID: return tr("Hash");
++ case COLUMN_LASTDL: return tr("Last Time Seen", "i.e: Last Time Receiced Data");
++ case COLUMN_PATH: return tr("Path", "i.e: Where file is saved");
++ }
++ }
++
++ QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const
++ {
++ if(!index.isValid())
++ return QVariant();
++
++ int coln = index.column() ;
++
++ switch(role)
++ {
++ case Qt::SizeHintRole: return sizeHintRole(index.column()) ;
++ case Qt::TextAlignmentRole:
++ case Qt::TextColorRole:
++ case Qt::WhatsThisRole:
++ case Qt::EditRole:
++ case Qt::ToolTipRole:
++ case Qt::StatusTipRole:
++ return QVariant();
++ }
++
++ void *ref = (index.isValid())?index.internalPointer():NULL ;
++ uint32_t entry = 0;
++ int source_id=0 ;
++
++ if(!ref)
++ return false ;
++
++ if(!convertRefPointerToTabEntry(ref,entry,source_id) || entry >= mDownloads.size())
++ {
++ std::cerr << "Bad pointer: " << (void*)ref << std::endl;
++ return false ;
++ }
++
++ const FileInfo& finfo(mDownloads[entry]) ;
++
++ switch(role)
++ {
++ case Qt::DisplayRole: return displayRole (finfo,source_id,index.column()) ;
++ case Qt::DecorationRole: return decorationRole(finfo,source_id,index.column()) ;
++ case Qt::UserRole: return userRole (finfo,source_id,index.column()) ;
++ default:
++ return QVariant();
++ }
++ }
++
++ QVariant sizeHintRole(int col) const
++ {
++ switch(col)
++ {
++ default:
++ case COLUMN_NAME: return QVariant( 170 );
++ case COLUMN_SIZE: return QVariant( 70 );
++ case COLUMN_COMPLETED: return QVariant( 75 );
++ case COLUMN_DLSPEED: return QVariant( 75 );
++ case COLUMN_PROGRESS: return QVariant( 170 );
++ case COLUMN_SOURCES: return QVariant( 90 );
++ case COLUMN_STATUS: return QVariant( 100 );
++ case COLUMN_PRIORITY: return QVariant( 100 );
++ case COLUMN_REMAINING: return QVariant( 100 );
++ case COLUMN_DOWNLOADTIME: return QVariant( 100 );
++ case COLUMN_ID: return QVariant( 100 );
++ case COLUMN_LASTDL: return QVariant( 100 );
++ case COLUMN_PATH: return QVariant( 100 );
++ }
++ }
++
++
++ QVariant displayRole(const FileInfo& fileInfo,int source_id,int col) const
++ {
++ if(source_id == -1) // toplevel
++ switch(col)
++ {
++ case COLUMN_NAME: return QVariant(QString::fromUtf8(fileInfo.fname.c_str()));
++ case COLUMN_COMPLETED: return QVariant((qlonglong)fileInfo.transfered);
++ case COLUMN_DLSPEED: return QVariant((double)((fileInfo.downloadStatus == FT_STATE_DOWNLOADING) ? (fileInfo.tfRate * 1024.0) : 0.0));
++ case COLUMN_PROGRESS: return QVariant((float)((fileInfo.size == 0) ? 0 : (fileInfo.transfered * 100.0 / (float)fileInfo.size)));
++ case COLUMN_STATUS:
++ {
++ QString status;
++ switch (fileInfo.downloadStatus)
++ {
++ case FT_STATE_FAILED: status = tr("Failed"); break;
++ case FT_STATE_OKAY: status = tr("Okay"); break;
++ case FT_STATE_WAITING: status = tr("Waiting"); break;
++ case FT_STATE_DOWNLOADING: status = tr("Downloading"); break;
++ case FT_STATE_COMPLETE: status = tr("Complete"); break;
++ case FT_STATE_QUEUED: status = tr("Queued"); break;
++ case FT_STATE_PAUSED: status = tr("Paused"); break;
++ case FT_STATE_CHECKING_HASH:status = tr("Checking..."); break;
++ default: status = tr("Unknown"); break;
++ }
++ return QVariant(status);
++ }
++
++ case COLUMN_PRIORITY:
++ {
++ double priority = PRIORITY_NULL;
++
++ if (fileInfo.downloadStatus == FT_STATE_QUEUED)
++ priority = fileInfo.queue_position;
++ else if (fileInfo.downloadStatus == FT_STATE_COMPLETE)
++ priority = 0;
++ else
++ switch (fileInfo.priority)
++ {
++ case SPEED_LOW: priority = PRIORITY_SLOWER; break;
++ case SPEED_NORMAL: priority = PRIORITY_AVERAGE; break;
++ case SPEED_HIGH: priority = PRIORITY_FASTER; break;
++ default: priority = PRIORITY_AVERAGE; break;
++ }
++
++ return QVariant(priority);
++ }
++
++ case COLUMN_REMAINING: return QVariant((qlonglong)(fileInfo.size - fileInfo.transfered));
++ case COLUMN_DOWNLOADTIME: return QVariant((qlonglong)(fileInfo.tfRate > 0)?( (fileInfo.size - fileInfo.transfered) / (fileInfo.tfRate * 1024.0) ) : 0);
++ case COLUMN_LASTDL:
++ {
++ qint64 qi64LastDL = fileInfo.lastTS ;
++
++ if (qi64LastDL == 0) // file is complete, or any raison why the time has not been set properly
++ {
++ QFileInfo file;
++
++ if (fileInfo.downloadStatus == FT_STATE_COMPLETE)
++ file = QFileInfo(QString::fromUtf8(fileInfo.path.c_str()), QString::fromUtf8(fileInfo.fname.c_str()));
++ else
++ file = QFileInfo(QString::fromUtf8(rsFiles->getPartialsDirectory().c_str()), QString::fromUtf8(fileInfo.hash.toStdString().c_str()));
++
++ //Get Last Access on File
++ if (file.exists())
++ qi64LastDL = file.lastModified().toTime_t();
++ }
++ return QVariant(qi64LastDL) ;
++ }
++ case COLUMN_PATH:
++ {
++ QString strPath = QString::fromUtf8(fileInfo.path.c_str());
++ QString strPathAfterDL = strPath;
++ strPathAfterDL.replace(QString::fromUtf8(rsFiles->getDownloadDirectory().c_str()),"");
++
++ return QVariant(strPathAfterDL);
++ }
++
++ case COLUMN_SOURCES:
++ {
++ int active = 0;
++ QString fileHash = QString::fromStdString(fileInfo.hash.toStdString());
++
++ if (fileInfo.downloadStatus != FT_STATE_COMPLETE)
++ for (std::vector<TransferInfo>::const_iterator pit = fileInfo.peers.begin() ; pit != fileInfo.peers.end(); ++pit)
++ {
++ const TransferInfo& transferInfo = *pit;
++
++ // //unique combination: fileHash + peerId, variant: hash + peerName (too long)
++ // QString hashFileAndPeerId = fileHash + QString::fromStdString(transferInfo.peerId.toStdString());
++
++ // double peerDlspeed = 0;
++ // if ((uint32_t)transferInfo.status == FT_STATE_DOWNLOADING && fileInfo.downloadStatus != FT_STATE_PAUSED && fileInfo.downloadStatus != FT_STATE_COMPLETE)
++ // peerDlspeed = transferInfo.tfRate * 1024.0;
++
++ // FileProgressInfo peerpinfo;
++ // peerpinfo.cmap = fcinfo.compressed_peer_availability_maps[transferInfo.peerId];
++ // peerpinfo.type = FileProgressInfo::DOWNLOAD_SOURCE ;
++ // peerpinfo.progress = 0.0; // we don't display completion for sources.
++ // peerpinfo.nb_chunks = peerpinfo.cmap._map.empty() ? 0 : fcinfo.chunks.size();
++
++ // get the sources (number of online peers)
++ if (transferInfo.tfRate > 0 && fileInfo.downloadStatus == FT_STATE_DOWNLOADING)
++ ++active;
++ }
++
++ return QVariant( (float)active + fileInfo.peers.size()/1000.0f );
++
++ }
++
++ case COLUMN_SIZE: return QVariant((qlonglong) fileInfo.size);
++
++ case COLUMN_ID: return QVariant(QString::fromStdString(fileInfo.hash.toStdString()));
++
++ default:
++ return QVariant("[ TODO ]");
++ }
++ else
++ {
++ uint32_t chunk_size = 1024*1024 ;
++
++ switch(col)
++ {
++ default:
++ case COLUMN_SOURCES:
++ case COLUMN_COMPLETED:
++ case COLUMN_REMAINING:
++ case COLUMN_LASTDL:
++ case COLUMN_ID:
++ case COLUMN_PATH:
++ case COLUMN_DOWNLOADTIME:
++ case COLUMN_SIZE: return QVariant();
++ case COLUMN_PROGRESS: return QVariant( (fileInfo.size>0)?((fileInfo.peers[source_id].transfered % chunk_size)*100.0/fileInfo.size):0.0) ;
++ case COLUMN_DLSPEED:
++ {
++ double peerDlspeed = 0;
++ if((uint32_t)fileInfo.peers[source_id].status == FT_STATE_DOWNLOADING && fileInfo.downloadStatus != FT_STATE_PAUSED && fileInfo.downloadStatus != FT_STATE_COMPLETE)
++ peerDlspeed = fileInfo.peers[source_id].tfRate * 1024.0;
++
++ return QVariant((double)peerDlspeed) ;
++ }
++ case COLUMN_NAME:
++ {
++ QString iconName,tooltip;
++ return QVariant(TransfersDialog::getPeerName(fileInfo.peers[source_id].peerId, iconName, tooltip));
++ }
++
++ case COLUMN_PRIORITY: return QVariant((double)PRIORITY_NULL);
++ }
++ }
++
++ return QVariant("[ERROR]");
++ }
++
++ virtual QVariant userRole(const FileInfo& fileInfo,int source_id,int col) const
++ {
++ if(source_id == -1)
++ switch(col)
++ {
++ case COLUMN_PROGRESS:
++ {
++ FileChunksInfo fcinfo;
++ if (!rsFiles->FileDownloadChunksDetails(fileInfo.hash, fcinfo))
++ return -1;
++
++ FileProgressInfo pinfo;
++ pinfo.cmap = fcinfo.chunks;
++ pinfo.type = FileProgressInfo::DOWNLOAD_LINE;
++ pinfo.progress = (fileInfo.size == 0) ? 0 : (fileInfo.transfered * 100.0 / fileInfo.size);
++ pinfo.nb_chunks = pinfo.cmap._map.empty() ? 0 : fcinfo.chunks.size();
++
++ for (uint32_t i = 0; i < fcinfo.chunks.size(); ++i)
++ switch(fcinfo.chunks[i])
++ {
++ case FileChunksInfo::CHUNK_CHECKING: pinfo.chunks_in_checking.push_back(i);
++ break ;
++ case FileChunksInfo::CHUNK_ACTIVE: pinfo.chunks_in_progress.push_back(i);
++ break ;
++ case FileChunksInfo::CHUNK_DONE:
++ case FileChunksInfo::CHUNK_OUTSTANDING:
++ break ;
++ }
++
++ return QVariant::fromValue(pinfo);
++ }
++
++ case COLUMN_ID: return QVariant(QString::fromStdString(fileInfo.hash.toStdString()));
++
++
++ default:
++ return QVariant();
++ }
++ else
++ switch(col)
++ {
++ case COLUMN_PROGRESS:
++ {
++ FileProgressInfo peerpinfo ;
++
++ if(!rsFiles->FileUploadChunksDetails(fileInfo.hash, fileInfo.peers[source_id].peerId, peerpinfo.cmap) )
++ return QVariant();
++
++ // Estimate the completion. We need something more accurate, meaning that we need to
++ // transmit the completion info.
++ //
++ uint32_t chunk_size = 1024*1024 ;
++ uint32_t nb_chunks = (uint32_t)((fileInfo.size + (uint64_t)chunk_size - 1) / (uint64_t)(chunk_size)) ;
++
++ uint32_t filled_chunks = peerpinfo.cmap.filledChunks(nb_chunks) ;
++ peerpinfo.type = FileProgressInfo::UPLOAD_LINE ;
++ peerpinfo.nb_chunks = peerpinfo.cmap._map.empty()?0:nb_chunks ;
++ qlonglong completed ;
++
++ if(filled_chunks > 0 && nb_chunks > 0)
++ {
++ completed = peerpinfo.cmap.computeProgress(fileInfo.size,chunk_size) ;
++ peerpinfo.progress = completed / (float)fileInfo.size * 100.0f ;
++ }
++ else
++ {
++ completed = fileInfo.peers[source_id].transfered % chunk_size ; // use the position with respect to last request.
++ peerpinfo.progress = (fileInfo.size>0)?((fileInfo.peers[source_id].transfered % chunk_size)*100.0/fileInfo.size):0 ;
++ }
++
++ return QVariant::fromValue(peerpinfo);
++ }
++
++ case COLUMN_ID: return QVariant(QString::fromStdString(fileInfo.hash.toStdString()) + QString::fromStdString(fileInfo.peers[source_id].peerId.toStdString()));
++
++ default:
++ return QVariant();
++ }
++
++ }
++
++ QVariant decorationRole(const FileInfo& fileInfo,int source_id,int col) const
++ {
++ if(col == COLUMN_NAME)
++ {
++ if(source_id == -1)
++ return QVariant(FilesDefs::getIconFromFilename(QString::fromUtf8(fileInfo.fname.c_str())));
++ else
++ {
++ QString iconName,tooltip;
++ TransfersDialog::getPeerName(fileInfo.peers[source_id].peerId, iconName, tooltip);
++
++ return QVariant(iconName);
++ }
++ }
++ else
++ return QVariant();
++ }
++
++ void update_transfers()
++ {
++// beginResetModel();
++
++ std::list<RsFileHash> downHashes;
++ rsFiles->FileDownloads(downHashes);
++
++ size_t old_size = mDownloads.size();
++
++ mDownloads.resize(downHashes.size()) ;
++
++ if(old_size < mDownloads.size())
++ {
++ beginInsertRows(QModelIndex(), old_size, mDownloads.size());
++ insertRows(old_size, mDownloads.size() - old_size);
++ endInsertRows();
++ }
++ else if(mDownloads.size() < old_size)
++ {
++ beginRemoveRows(QModelIndex(), mDownloads.size(), old_size);
++ removeRows(old_size, old_size - mDownloads.size());
++ endRemoveRows();
++ }
++
++ //std::cerr << "updating file list: found " << mDownloads.size() << " transfers." << std::endl;
++
++ uint32_t i=0;
++
++ for(auto it(downHashes.begin());it!=downHashes.end();++it,++i)
++ {
++ FileInfo& fileInfo(mDownloads[i]);
++ rsFiles->FileDetails(*it, RS_FILE_HINTS_DOWNLOAD, fileInfo);
++ }
++
++// endResetModel();
++
++ QModelIndex topLeft = createIndex(0,0), bottomRight = createIndex(mDownloads.size(), COLUMN_COUNT-1);
++ emit dataChanged(topLeft, bottomRight);
++
++ //shit code follow (rewrite this please)
++ // size_t old_size = neighs.size(), new_size = 0;
++ // std::list<RsPgpId> old_neighs = neighs;
++ //
++ // new_size = new_neighs.size();
++ // //set model data to new cleaned up data
++ // neighs = new_neighs;
++ // neighs.sort();
++ // neighs.unique(); //remove possible dups
++ //
++ // //reflect actual row count in model
++ // if(old_size < new_size)
++ // {
++ // beginInsertRows(QModelIndex(), old_size, new_size);
++ // insertRows(old_size, new_size - old_size);
++ // endInsertRows();
++ // }
++ // else if(new_size < old_size)
++ // {
++ // beginRemoveRows(QModelIndex(), new_size, old_size);
++ // removeRows(old_size, old_size - new_size);
++ // endRemoveRows();
++ // }
++ // //update data in ui, to avoid unnecessary redraw and ui updates, updating only changed elements
++ // //TODO: libretroshare should implement a way to obtain only changed elements via some signalling non-blocking api.
++ // {
++ // size_t ii1 = 0;
++ // for(auto i1 = neighs.begin(), end1 = neighs.end(), i2 = old_neighs.begin(), end2 = old_neighs.end(); i1 != end1; ++i1, ++i2, ii1++)
++ // {
++ // if(i2 == end2)
++ // break;
++ // if(*i1 != *i2)
++ // {
++ // QModelIndex topLeft = createIndex(ii1,0), bottomRight = createIndex(ii1, COLUMN_COUNT-1);
++ // emit dataChanged(topLeft, bottomRight);
++ // }
++ // }
++ // }
++ // if(new_size > old_size)
++ // {
++ // QModelIndex topLeft = createIndex(old_size ? old_size -1 : 0 ,0), bottomRight = createIndex(new_size -1, COLUMN_COUNT-1);
++ // emit dataChanged(topLeft, bottomRight);
++ // }
++ // //dirty solution for initial data fetch
++ // //TODO: do it properly!
++ // if(!old_size)
++ // {
++ // beginResetModel();
++ // endResetModel();
++ // }
++
++
++ }
++private:
++ static const uint32_t TRANSFERS_NB_DOWNLOADS_BITS_32BITS = 22 ; // Means 2^22 simultaneous transfers
++ static const uint32_t TRANSFERS_NB_DOWNLOADS_BIT_MASK_32BITS = 0x003fffff ; // actual bit mask corresponding to previous number of bits
++ static const uint32_t TRANSFERS_NB_SOURCES_BITS_32BITS = 10 ; // Means 2^10 simultaneous sources
++
++ static bool convertTabEntryToRefPointer(uint32_t entry,int source_id,void *& ref)
++ {
++ if(source_id < -1)
++ {
++ std::cerr << "(EE) inconsistent source id = " << source_id << " in convertTabEntryToRefPointer()" << std::endl;
++ return false;
++ }
++ // the pointer is formed the following way:
++ //
++ // [ 10 bits | 22 bits ]
++ //
++ // This means that the whoel software has the following build-in limitation:
++ // * 1023 sources
++ // * 4M simultaenous file transfers
++
++ if(uint32_t(source_id+1) >= (1u<<TRANSFERS_NB_SOURCES_BITS_32BITS) || (entry+1) >= (1u<< TRANSFERS_NB_DOWNLOADS_BITS_32BITS))
++ {
++ std::cerr << "(EE) cannot convert download index " << entry << " and source " << source_id << " to pointer." << std::endl;
++ return false ;
++ }
++
++ ref = reinterpret_cast<void*>( ( uint32_t(1+source_id) << TRANSFERS_NB_DOWNLOADS_BITS_32BITS ) + ( (entry+1) & TRANSFERS_NB_DOWNLOADS_BIT_MASK_32BITS)) ;
++
++ return true;
++ }
++
++ static bool convertRefPointerToTabEntry(void *ref,uint32_t& entry,int& source_id)
++ {
++ // we pack the couple (id of DL, id of source) into a single 32-bits pointer that is required by the AbstractItemModel class.
++
++#pragma GCC diagnostic ignored "-Wstrict-aliasing"
++ uint32_t ntr = uint32_t( *reinterpret_cast<uint32_t*>(&ref) & TRANSFERS_NB_DOWNLOADS_BIT_MASK_32BITS ) ;
++ uint32_t src = ( *reinterpret_cast<uint32_t*>(&ref)) >> TRANSFERS_NB_DOWNLOADS_BITS_32BITS ;
++#pragma GCC diagnostic pop
++
++ if(ntr == 0)
++ {
++ std::cerr << "ERROR! ntr=0!"<< std::endl;
++ return false ;
++ }
++
++ source_id = int(src) - 1 ;
++ entry = ntr - 1 ;
++
++ return true;
++ }
++
++ std::vector<FileInfo> mDownloads ; // store the list of downloads, updated from rsFiles.
++};
++
+ class SortByNameItem : public QStandardItem
+ {
+ public:
+@@ -170,21 +755,9 @@ TransfersDialog::TransfersDialog(QWidget *parent)
+
+ connect( ui.downloadList, SIGNAL( customContextMenuRequested( QPoint ) ), this, SLOT( downloadListCustomPopupMenu( QPoint ) ) );
+
++ DLListModel = new RsDownloadListModel ;
++
+ // Set Download list model
+- DLListModel = new QStandardItemModel(0,COLUMN_COUNT);
+- DLListModel->setHeaderData(COLUMN_NAME, Qt::Horizontal, tr("Name", "i.e: file name"));
+- DLListModel->setHeaderData(COLUMN_SIZE, Qt::Horizontal, tr("Size", "i.e: file size"));
+- DLListModel->setHeaderData(COLUMN_COMPLETED, Qt::Horizontal, tr("Completed", ""));
+- DLListModel->setHeaderData(COLUMN_DLSPEED, Qt::Horizontal, tr("Speed", "i.e: Download speed"));
+- DLListModel->setHeaderData(COLUMN_PROGRESS, Qt::Horizontal, tr("Progress / Availability", "i.e: % downloaded"));
+- DLListModel->setHeaderData(COLUMN_SOURCES, Qt::Horizontal, tr("Sources", "i.e: Sources"));
+- DLListModel->setHeaderData(COLUMN_STATUS, Qt::Horizontal, tr("Status"));
+- DLListModel->setHeaderData(COLUMN_PRIORITY, Qt::Horizontal, tr("Speed / Queue position"));
+- DLListModel->setHeaderData(COLUMN_REMAINING, Qt::Horizontal, tr("Remaining"));
+- DLListModel->setHeaderData(COLUMN_DOWNLOADTIME, Qt::Horizontal, tr("Download time", "i.e: Estimated Time of Arrival / Time left"));
+- DLListModel->setHeaderData(COLUMN_ID, Qt::Horizontal, tr("Hash"));
+- DLListModel->setHeaderData(COLUMN_LASTDL, Qt::Horizontal, tr("Last Time Seen", "i.e: Last Time Receiced Data"));
+- DLListModel->setHeaderData(COLUMN_PATH, Qt::Horizontal, tr("Path", "i.e: Where file is saved"));
+
+ DLLFilterModel = new QSortFilterProxyModel(this);
+ DLLFilterModel->setSourceModel( DLListModel);
+@@ -211,11 +784,9 @@ TransfersDialog::TransfersDialog(QWidget *parent)
+ selection = ui.downloadList->selectionModel();
+
+ ui.downloadList->setSelectionMode(QAbstractItemView::ExtendedSelection);
+-
+ ui.downloadList->setRootIsDecorated(true);
+
+-
+- /* Set header resize modes and initial section sizes Downloads TreeView*/
++// /* Set header resize modes and initial section sizes Downloads TreeView*/
+ QHeaderView * dlheader = ui.downloadList->header () ;
+ QHeaderView_setSectionResizeModeColumn(dlheader, COLUMN_NAME, QHeaderView::Interactive);
+ QHeaderView_setSectionResizeModeColumn(dlheader, COLUMN_SIZE, QHeaderView::Interactive);
+@@ -231,20 +802,6 @@ TransfersDialog::TransfersDialog(QWidget *parent)
+ QHeaderView_setSectionResizeModeColumn(dlheader, COLUMN_LASTDL, QHeaderView::Interactive);
+ QHeaderView_setSectionResizeModeColumn(dlheader, COLUMN_PATH, QHeaderView::Interactive);
+
+- dlheader->resizeSection ( COLUMN_NAME, 170 );
+- dlheader->resizeSection ( COLUMN_SIZE, 70 );
+- dlheader->resizeSection ( COLUMN_COMPLETED, 75 );
+- dlheader->resizeSection ( COLUMN_DLSPEED, 75 );
+- dlheader->resizeSection ( COLUMN_PROGRESS, 170 );
+- dlheader->resizeSection ( COLUMN_SOURCES, 90 );
+- dlheader->resizeSection ( COLUMN_STATUS, 100 );
+- dlheader->resizeSection ( COLUMN_PRIORITY, 100 );
+- dlheader->resizeSection ( COLUMN_REMAINING, 100 );
+- dlheader->resizeSection ( COLUMN_DOWNLOADTIME, 100 );
+- dlheader->resizeSection ( COLUMN_ID, 100 );
+- dlheader->resizeSection ( COLUMN_LASTDL, 100 );
+- dlheader->resizeSection ( COLUMN_PATH, 100 );
+-
+ // set default column and sort order for download
+ ui.downloadList->sortByColumn(COLUMN_NAME, Qt::AscendingOrder);
+
+@@ -309,24 +866,12 @@ TransfersDialog::TransfersDialog(QWidget *parent)
+
+ ui.tabWidget->addTab(localSharedFiles = new LocalSharedFilesDialog(), QIcon(IMAGE_MYFILES), tr("My files")) ;
+
+- //ui.tabWidget->addTab( new TurtleRouterStatistics(), tr("Router Statistics")) ;
+- //ui.tabWidget->addTab( new TurtleRouterDialog(), tr("Router Requests")) ;
+-
+ for(int i=0;i<rsPlugins->nbPlugins();++i)
+ if(rsPlugins->plugin(i) != NULL && rsPlugins->plugin(i)->qt_transfers_tab() != NULL)
+ ui.tabWidget->addTab( rsPlugins->plugin(i)->qt_transfers_tab(),QString::fromUtf8(rsPlugins->plugin(i)->qt_transfers_tab_name().c_str()) ) ;
+
+ ui.tabWidget->setCurrentWidget(ui.uploadsTab);
+
+-// TurtleRouterDialog *trdl = new TurtleRouterDialog();
+-// ui.tunnelInfoWidget->setWidget(trdl);
+-// ui.tunnelInfoWidget->setWidgetResizable(true);
+-// ui.tunnelInfoWidget->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
+-// ui.tunnelInfoWidget->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOn);
+-// ui.tunnelInfoWidget->viewport()->setBackgroundRole(QPalette::NoRole);
+-// ui.tunnelInfoWidget->setFrameStyle(QFrame::NoFrame);
+-// ui.tunnelInfoWidget->setFocusPolicy(Qt::NoFocus);
+-
+ /** Setup the actions for the context menu */
+
+ // Actions. Only need to be defined once.
+@@ -336,14 +881,8 @@ TransfersDialog::TransfersDialog(QWidget *parent)
+ resumeAct = new QAction(QIcon(IMAGE_RESUME), tr("Resume"), this);
+ connect(resumeAct, SIGNAL(triggered()), this, SLOT(resumeFileTransfer()));
+
+-//#ifdef USE_NEW_CHUNK_CHECKING_CODE
+- // *********WARNING**********
+- // csoler: this has been suspended because it needs the file transfer to consider a file as complete only if all chunks are
+- // verified by hash. As users are goign to slowly switch to new checking code, this will not be readily available.
+- //
+ forceCheckAct = new QAction(QIcon(IMAGE_CANCEL), tr( "Force Check" ), this );
+ connect( forceCheckAct , SIGNAL( triggered() ), this, SLOT( forceCheck() ) );
+-//#endif
+
+ cancelAct = new QAction(QIcon(IMAGE_CANCEL), tr( "Cancel" ), this );
+ connect( cancelAct , SIGNAL( triggered() ), this, SLOT( cancel() ) );
+@@ -564,18 +1103,6 @@ void TransfersDialog::processSettings(bool bLoad)
+ m_bProcessSettings = false;
+ }
+
+-// replaced by shortcut
+-//void TransfersDialog::keyPressEvent(QKeyEvent *e)
+-//{
+-// if(e->key() == Qt::Key_Delete)
+-// {
+-// cancel() ;
+-// e->accept() ;
+-// }
+-// else
+-// RsAutoUpdatePage::keyPressEvent(e) ;
+-//}
+-
+ void TransfersDialog::downloadListCustomPopupMenu( QPoint /*point*/ )
+ {
+ std::set<RsFileHash> items ;
+@@ -867,6 +1394,7 @@ void TransfersDialog::setDestinationDirectory()
+ }
+ }
+
++/*
+ int TransfersDialog::addDLItem(int row, const FileInfo &fileInfo)
+ {
+ QString fileHash = QString::fromStdString(fileInfo.hash.toStdString());
+@@ -915,7 +1443,7 @@ int TransfersDialog::addDLItem(int row, const FileInfo &fileInfo)
+ else
+ file = QFileInfo(QString::fromUtf8(rsFiles->getPartialsDirectory().c_str()), QString::fromUtf8(fileInfo.hash.toStdString().c_str()));
+
+- /*Get Last Access on File */
++ //Get Last Access on File
+ if (file.exists())
+ qi64LastDL = file.lastModified().toTime_t();
+ }
+@@ -987,8 +1515,7 @@ int TransfersDialog::addDLItem(int row, const FileInfo &fileInfo)
+ int active = 0;
+
+ if (fileInfo.downloadStatus != FT_STATE_COMPLETE) {
+- for (std::list<TransferInfo>::const_iterator pit = fileInfo.peers.begin()
+- ; pit != fileInfo.peers.end(); ++pit)
++ for (std::vector<TransferInfo>::const_iterator pit = fileInfo.peers.begin() ; pit != fileInfo.peers.end(); ++pit)
+ {
+ const TransferInfo &transferInfo = *pit;
+
+@@ -1009,7 +1536,7 @@ int TransfersDialog::addDLItem(int row, const FileInfo &fileInfo)
+
+ used_rows.insert(row_id);
+
+- /* get the sources (number of online peers) */
++ // get the sources (number of online peers)
+ if (transferInfo.tfRate > 0 && fileInfo.downloadStatus == FT_STATE_DOWNLOADING)
+ ++active;
+ }
+@@ -1144,6 +1671,7 @@ int TransfersDialog::addPeerToDLItem(QStandardItem *dlItem, const RsPeerId& peer
+
+ return childRow;
+ }
++*/
+
+ int TransfersDialog::addULItem(int row, const FileInfo &fileInfo)
+ {
+@@ -1185,8 +1713,7 @@ int TransfersDialog::addULItem(int row, const FileInfo &fileInfo)
+ double peerULSpeedTotal = 0;
+ bool bOnlyOne = ( fileInfo.peers.size() == 1 );
+
+- for(std::list<TransferInfo>::const_iterator pit = fileInfo.peers.begin()
+- ; pit != fileInfo.peers.end(); ++pit)
++ for(std::vector<TransferInfo>::const_iterator pit = fileInfo.peers.begin() ; pit != fileInfo.peers.end(); ++pit)
+ {
+ const TransferInfo &transferInfo = *pit;
+
+@@ -1329,80 +1856,57 @@ void TransfersDialog::updateDisplay()
+
+ void TransfersDialog::insertTransfers()
+ {
+- /* disable for performance issues, enable after insert all transfers */
+- ui.downloadList->setSortingEnabled(false);
++ // Since downloads use an AstractItemModel, we just need to update it, while saving the selected and expanded items.
+
+- /* get the download lists */
+- std::list<RsFileHash> downHashes;
+- rsFiles->FileDownloads(downHashes);
++ std::set<QString> expanded_hashes ;
++ std::set<QString> selected_hashes ;
+
+- /* build set for quick search */
+- std::set<RsFileHash> hashs;
++// ui.downloadList->setSortingEnabled(false);
++// ui.downloadList->blockSignals(true) ;
+
+- for (std::list<RsFileHash>::iterator it = downHashes.begin(); it != downHashes.end(); ++it) {
+- hashs.insert(*it);
+- }
+-
+- /* add downloads, first iterate all rows in list */
+-
+- int rowCount = DLListModel->rowCount();
+-
+- for (int row = 0; row < rowCount; ) {
+- RsFileHash hash ( DLListModel->item(row, COLUMN_ID)->data(Qt::UserRole).toString().toStdString());
+-
+- std::set<RsFileHash>::iterator hashIt = hashs.find(hash);
+- if (hashIt == hashs.end()) {
+- // remove not existing downloads
+- DLListModel->removeRow(row);
+- rowCount = DLListModel->rowCount();
+- continue;
+- }
++ std::cerr << "Updating transfers..." << std::endl;
+
+- FileInfo fileInfo;
+- if (!rsFiles->FileDetails(hash, RS_FILE_HINTS_DOWNLOAD, fileInfo)) {
+- DLListModel->removeRow(row);
+- rowCount = DLListModel->rowCount();
+- continue;
+- }
++/* QAbstractItemModel *model = ui.downloadList->model();
+
+- hashs.erase(hashIt);
++ for(int row = 0; row < model->rowCount(); ++row)
++ {
++ QModelIndex index = model->index(row,0,QModelIndex());
+
+- if (addDLItem(row, fileInfo) < 0) {
+- DLListModel->removeRow(row);
+- rowCount = DLListModel->rowCount();
+- continue;
+- }
++ if(ui.downloadList->isExpanded(index))
++ expanded_hashes.insert(model->index(row,COLUMN_ID).data(Qt::DisplayRole).toString());
+
+- ++row;
+- }
++ if(ui.downloadList->selectionModel()->selection().contains(index))
++ selected_hashes.insert(model->index(row,COLUMN_ID).data(Qt::DisplayRole).toString());
++ } */
+
+- /* then add new downloads to the list */
++ DLListModel->update_transfers();
+
+- for (std::set<RsFileHash>::iterator hashIt = hashs.begin()
+- ; hashIt != hashs.end(); ++hashIt)
++/* for(int row = 0; row < model->rowCount(); ++row) //shitcode, even worse than mine )
+ {
+- FileInfo fileInfo;
+- if (!rsFiles->FileDetails(*hashIt, RS_FILE_HINTS_DOWNLOAD, fileInfo)) {
+- continue;
+- }
++ QModelIndex index = model->index(row,0,QModelIndex());
+
+- addDLItem(-1, fileInfo);
+- }
++ if(expanded_hashes.end() != expanded_hashes.find(model->index(row,COLUMN_ID).data(Qt::DisplayRole).toString()))
++ ui.downloadList->setExpanded(index,true);
++
++ if(selected_hashes.end() != selected_hashes.find(model->index(row,COLUMN_ID).data(Qt::DisplayRole).toString()))
++ ui.downloadList->selectionModel()->select(index, QItemSelectionModel::Select | QItemSelectionModel::Rows);
++ } */
+
+- ui.downloadList->setSortingEnabled(true);
++// ui.downloadList->setSortingEnabled(true);
++// ui.downloadList->blockSignals(false) ;
+
+- // Now show upload hashes
++ // Now show upload hashes. Here we use the "old" way, since the number of uploads is generally not so large.
+ //
+
+ /* disable for performance issues, enable after insert all transfers */
+- ui.uploadsList->setSortingEnabled(false);
++ ui.uploadsList->setSortingEnabled(false);
+
+ /* get the upload lists */
+ std::list<RsFileHash> upHashes;
+ rsFiles->FileUploads(upHashes);
+
+ /* build set for quick search */
+- hashs.clear();
++ std::set<RsFileHash> hashs;
+
+ for(std::list<RsFileHash>::iterator it = upHashes.begin(); it != upHashes.end(); ++it) {
+ hashs.insert(*it);
+@@ -1410,7 +1914,7 @@ void TransfersDialog::insertTransfers()
+
+ /* add uploads, first iterate all rows in list */
+
+- rowCount = ULListModel->rowCount();
++ int rowCount = ULListModel->rowCount();
+
+ for (int row = 0; row < rowCount; ) {
+ RsFileHash hash ( ULListModel->item(row, COLUMN_UHASH)->data(Qt::UserRole).toString().toStdString());
+@@ -1464,7 +1968,7 @@ void TransfersDialog::insertTransfers()
+
+ }
+
+-QString TransfersDialog::getPeerName(const RsPeerId& id, QString &iconName, QString &tooltip) const
++QString TransfersDialog::getPeerName(const RsPeerId& id, QString &iconName, QString &tooltip)
+ {
+ QString res = QString::fromUtf8(rsPeers->getPeerName(id).c_str()) ;
+
+diff --git a/retroshare-gui/src/gui/FileTransfer/TransfersDialog.h b/retroshare-gui/src/gui/FileTransfer/TransfersDialog.h
+index 30efe212d..51bc205d3 100644
+--- a/retroshare-gui/src/gui/FileTransfer/TransfersDialog.h
++++ b/retroshare-gui/src/gui/FileTransfer/TransfersDialog.h
+@@ -44,6 +44,7 @@ class FileProgressInfo;
+ class SearchDialog;
+ class LocalSharedFilesDialog;
+ class RemoteSharedFilesDialog;
++class RsDownloadListModel;
+
+ class TransfersDialog : public RsAutoUpdatePage
+ {
+@@ -78,6 +79,7 @@ public:
+ LocalSharedFilesDialog *localSharedFiles ;
+ RemoteSharedFilesDialog *remoteSharedFiles ;
+
++ static QString getPeerName(const RsPeerId &peer_id, QString &iconName, QString &tooltip) ;
+ public slots:
+ void insertTransfers();
+
+@@ -164,9 +166,8 @@ signals:
+ void playFiles(QStringList files);
+
+ private:
+- QString getPeerName(const RsPeerId &peer_id, QString &iconName, QString &tooltip) const ;
+
+- QStandardItemModel *DLListModel;
++ RsDownloadListModel *DLListModel;
+ QSortFilterProxyModel *DLLFilterModel;
+ QStandardItemModel *ULListModel;
+ QItemSelectionModel *selection;
+@@ -260,8 +261,8 @@ private:
+
+ public slots:
+ // these four functions add entries to the transfers dialog, and return the row id of the entry modified/added
+- int addDLItem(int row, const FileInfo &fileInfo);
+- int addPeerToDLItem(QStandardItem* dlItem, const RsPeerId &peer_ID, const QString &coreID, double dlspeed, uint32_t status, const FileProgressInfo &peerInfo);
++// int addDLItem(int row, const FileInfo &fileInfo);
++// int addPeerToDLItem(QStandardItem* dlItem, const RsPeerId &peer_ID, const QString &coreID, double dlspeed, uint32_t status, const FileProgressInfo &peerInfo);
+ int addULItem(int row, const FileInfo &fileInfo);
+ int addPeerToULItem(QStandardItem* ulItem, const RsPeerId &peer_ID, const QString &coreID, qlonglong completed, double ulspeed, const FileProgressInfo &peerInfo);
+
+diff --git a/retroshare-gui/src/gui/RetroShareLink.cpp b/retroshare-gui/src/gui/RetroShareLink.cpp
+index 266970a54..f4af64017 100644
+--- a/retroshare-gui/src/gui/RetroShareLink.cpp
++++ b/retroshare-gui/src/gui/RetroShareLink.cpp
+@@ -1572,7 +1572,7 @@ static void processList(const QStringList &list, const QString &textSingular, co
+ FileInfo finfo ;
+ rsFiles->FileDetails(RsFileHash(link.hash().toStdString()), RS_FILE_HINTS_REMOTE, finfo) ;
+
+- for(std::list<TransferInfo>::const_iterator it(finfo.peers.begin());it!=finfo.peers.end();++it)
++ for(std::vector<TransferInfo>::const_iterator it(finfo.peers.begin());it!=finfo.peers.end();++it)
+ {
+ #ifdef DEBUG_RSLINK
+ std::cerr << " adding peerid " << (*it).peerId << std::endl ;
+diff --git a/retroshare-gui/src/gui/feeds/SubFileItem.cpp b/retroshare-gui/src/gui/feeds/SubFileItem.cpp
+index 250d85cad..0e3350127 100644
+--- a/retroshare-gui/src/gui/feeds/SubFileItem.cpp
++++ b/retroshare-gui/src/gui/feeds/SubFileItem.cpp
+@@ -630,7 +630,7 @@ void SubFileItem::download()
+ FileInfo finfo ;
+ rsFiles->FileDetails(mFileHash,RS_FILE_HINTS_REMOTE,finfo) ;
+
+- for(std::list<TransferInfo>::const_iterator it(finfo.peers.begin());it!=finfo.peers.end();++it)
++ for(std::vector<TransferInfo>::const_iterator it(finfo.peers.begin());it!=finfo.peers.end();++it)
+ sources.push_back((*it).peerId) ;
+
+ // TEMP
+diff --git a/retroshare-gui/src/gui/gxschannels/GxsChannelFilesStatusWidget.cpp b/retroshare-gui/src/gui/gxschannels/GxsChannelFilesStatusWidget.cpp
+index b9b84b894..b3170efa4 100644
+--- a/retroshare-gui/src/gui/gxschannels/GxsChannelFilesStatusWidget.cpp
++++ b/retroshare-gui/src/gui/gxschannels/GxsChannelFilesStatusWidget.cpp
+@@ -248,7 +248,7 @@ void GxsChannelFilesStatusWidget::download()
+ FileInfo fileInfo;
+ rsFiles->FileDetails(mFile.mHash, RS_FILE_HINTS_REMOTE, fileInfo);
+
+- for(std::list<TransferInfo>::const_iterator it = fileInfo.peers.begin(); it != fileInfo.peers.end(); ++it) {
++ for(std::vector<TransferInfo>::const_iterator it = fileInfo.peers.begin(); it != fileInfo.peers.end(); ++it) {
+ sources.push_back((*it).peerId);
+ }
+
+diff --git a/retroshare-gui/src/gui/msgs/MessageWidget.cpp b/retroshare-gui/src/gui/msgs/MessageWidget.cpp
+index 2f00bcded..38319bafc 100644
+--- a/retroshare-gui/src/gui/msgs/MessageWidget.cpp
++++ b/retroshare-gui/src/gui/msgs/MessageWidget.cpp
+@@ -323,7 +323,7 @@ void MessageWidget::getcurrentrecommended()
+ fi.fname = it->data().toString().toUtf8().constData();
+ break ;
+ case COLUMN_FILE_SIZE:
+- fi.size = it->data().toULongLong() ;
++ fi.size = it->data(Qt::UserRole).toULongLong() ;
+ break ;
+ case COLUMN_FILE_HASH:
+ fi.hash = RsFileHash(it->data().toString().toStdString()) ;
+@@ -502,6 +502,7 @@ void MessageWidget::fill(const std::string &msgId)
+ QTreeWidgetItem *item = new QTreeWidgetItem;
+ item->setText(COLUMN_FILE_NAME, QString::fromUtf8(it->fname.c_str()));
+ item->setText(COLUMN_FILE_SIZE, misc::friendlyUnit(it->size));
++ item->setData(COLUMN_FILE_SIZE, Qt::UserRole, QVariant(qulonglong(it->size)) );
+ item->setText(COLUMN_FILE_HASH, QString::fromStdString(it->hash.toStdString()));
+ item->setTextAlignment( COLUMN_FILE_SIZE, Qt::AlignRight );
+
diff --git a/net-p2p/retroshare/retroshare-scm.ebuild b/net-p2p/retroshare/retroshare-scm.ebuild
index ac96b7b..4d28ff9 100644
--- a/net-p2p/retroshare/retroshare-scm.ebuild
+++ b/net-p2p/retroshare/retroshare-scm.ebuild
@@ -83,6 +83,7 @@ PATCHES=(
"${FILESDIR}/hidden_service.patch"
"${FILESDIR}/cflags.patch"
"${FILESDIR}/disable_key_array_redraw.patch"
+ "${FILESDIR}/rs-ft-1169.diff"
)
diff --git a/net-p2p/retroshare/retroshare-scm.ebuild~ b/net-p2p/retroshare/retroshare-scm.ebuild~
new file mode 100644
index 0000000..ac96b7b
--- /dev/null
+++ b/net-p2p/retroshare/retroshare-scm.ebuild~
@@ -0,0 +1,189 @@
+# Copyright 1999-2015 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Id$
+
+EAPI=6
+
+inherit eutils gnome2-utils multilib qmake-utils git-r3
+
+MY_PV="${PV/_rc/.RC}"
+MY_PV="${MY_PV/_pre/$'\x7e'}" # bug #557276
+
+DESCRIPTION="P2P private sharing application"
+HOMEPAGE="http://retroshare.sourceforge.net"
+SRC_URI=""
+EGIT_REPO_URI="https://github.com/RetroShare/RetroShare.git"
+
+# pegmarkdown can also be used with MIT
+LICENSE="GPL-2 GPL-3 Apache-2.0 LGPL-2.1"
+SLOT="0"
+KEYWORDS=""
+
+IUSE="cli feedreader libressl qt4 +qt5 voip +sqlcipher"
+REQUIRED_USE="|| ( cli qt5 qt4 )
+ feedreader? ( || ( qt5 qt4 ) )
+ voip? ( || ( qt5 qt4 ) )
+ qt4? ( !qt5 )
+ qt5? ( !qt4 )
+ "
+
+RDEPEND="
+ app-arch/bzip2
+ sqlcipher? (
+ dev-db/sqlcipher
+ )
+ !libressl? ( dev-libs/openssl:0[static-libs(+)?] )
+ libressl? ( dev-libs/libressl[static-libs(+)?] )
+ gnome-base/libgnome-keyring
+ net-libs/libmicrohttpd
+ net-libs/libupnp
+ sys-libs/zlib
+ cli? (
+ dev-libs/protobuf
+ net-libs/libssh[server]
+ )
+ feedreader? (
+ dev-libs/libxml2
+ dev-libs/libxslt
+ net-misc/curl
+ )
+ qt5? (
+ x11-libs/libX11
+ x11-libs/libXScrnSaver
+ dev-qt/designer:5
+ dev-qt/qtcore:5
+ dev-qt/qtgui:5
+ dev-qt/qtmultimedia:5
+ dev-qt/qtnetwork:5
+ dev-qt/qtprintsupport:5
+ dev-qt/qtscript:5
+ dev-qt/qtwidgets:5
+ dev-qt/qtx11extras:5
+ dev-qt/qtxml:5
+ )
+ qt4? (
+ x11-libs/libX11
+ x11-libs/libXScrnSaver
+ dev-qt/designer:4
+ dev-qt/qtcore:4
+ dev-qt/qtgui:4
+ dev-qt/qtmultimedia:4
+ dev-qt/qtscript:4
+ )
+ voip? (
+ media-libs/opencv
+ media-libs/speex
+ )"
+DEPEND="${RDEPEND}
+ qt5? ( dev-qt/qtcore:5 )
+ qt4? ( dev-qt/qtcore:4 )
+ virtual/pkgconfig"
+
+PATCHES=(
+ "${FILESDIR}/hidden_service.patch"
+ "${FILESDIR}/cflags.patch"
+ "${FILESDIR}/disable_key_array_redraw.patch"
+)
+
+
+src_prepare() {
+ default
+ local dir
+
+ sed -i \
+ -e "s|/usr/lib/retroshare/extensions6/|/usr/$(get_libdir)/${PN}/extensions6/|" \
+ libretroshare/src/rsserver/rsinit.cc \
+ || die "sed on libretroshare/src/rsserver/rsinit.cc failed"
+
+ rs_src_dirs="libbitdht/src openpgpsdk/src libresapi/src libretroshare/src supportlibs/pegmarkdown"
+ use cli && rs_src_dirs="${rs_src_dirs} retroshare-nogui/src"
+ use feedreader && rs_src_dirs="${rs_src_dirs} plugins/FeedReader"
+ use qt5 && rs_src_dirs="${rs_src_dirs} retroshare-gui/src"
+ use qt4 && rs_src_dirs="${rs_src_dirs} retroshare-gui/src"
+ use voip && rs_src_dirs="${rs_src_dirs} plugins/VOIP"
+
+ # Force linking to sqlcipher ONLY
+ sed -i \
+ -e '/isEmpty(SQLCIPHER_OK) {/aerror(libsqlcipher not found)' \
+ retroshare-gui/src/retroshare-gui.pro \
+ retroshare-nogui/src/retroshare-nogui.pro || die 'sed on retroshare-gui/src/retroshare-gui.pro failed'
+
+ #regenerate translations in case developers just forgot to do so
+ local use_qt4
+ use qt4 && use_qt4="1"
+ if [ use_qt4 == "1" ]; then
+ qtchooser -run-tool=lupdate -qt=4 retroshare-gui/src/retroshare-gui.pro
+ qtchooser -run-tool=lrelease -qt=4 retroshare-gui/src/retroshare-gui.pro
+ else
+ qtchooser -run-tool=lupdate -qt=5 retroshare-gui/src/retroshare-gui.pro
+ qtchooser -run-tool=lrelease -qt=5 retroshare-gui/src/retroshare-gui.pro
+ fi
+
+ epatch_user
+}
+
+src_configure() {
+ local conf_add="release no-debug c++11"
+ use sqlcipher || conf_add="${conf_add} no_sqlcipher"
+ for dir in ${rs_src_dirs} ; do
+ pushd "${S}/${dir}" 2>/dev/null || die
+ use qt5 && eqmake5 CONFIG+="${conf_add}"
+ use qt4 && eqmake4 CONFIG+="${conf_add}"
+ popd 2>/dev/null || die
+ done
+ sed "s/= gcc/= ${CC}/g" -i supportlibs/pegmarkdown/Makefile
+}
+
+src_compile() {
+ local dir
+
+ for dir in ${rs_src_dirs} ; do
+ emake -C "${dir}"
+ done
+
+ unset rs_src_dirs
+}
+
+src_install() {
+ local i
+ local extension_dir="/usr/$(get_libdir)/${PN}/extensions6/"
+
+ use cli && dobin retroshare-nogui/src/retroshare-nogui
+ use qt5 && dobin retroshare-gui/src/retroshare
+ use qt4 && dobin retroshare-gui/src/retroshare
+
+ exeinto "${extension_dir}"
+ use feedreader && doexe plugins/FeedReader/*.so*
+ use voip && doexe plugins/VOIP/*.so*
+
+ insinto /usr/share/retroshare
+ doins libbitdht/src/bitdht/bdboot.txt
+
+ insinto /usr/share/retroshare/webui
+ doins libresapi/src/webui-src/*
+
+ make_desktop_entry RetroShare
+ for i in 24 48 64 ; do
+ doicon -s ${i} "data/${i}x${i}/apps/${PN}.png"
+ done
+ doicon -s 128 "data/${PN}.xpm"
+}
+
+pkg_preinst() {
+ if [[ "${REPLACING_VERSIONS}" = "0.5*" ]]; then
+ elog "You are upgrading from Retroshare 0.5.* to ${PV}"
+ elog "Version 0.6.* is backward-incompatible with 0.5 branch"
+ elog "and clients with 0.6.* can not connect to clients that have 0.5.*"
+ elog "It's recommended to drop all your configuration and either"
+ elog "generate a new certificate or import existing from a backup"
+ fi
+ gnome2_icon_savelist
+}
+
+pkg_postinst() {
+ gnome2_icon_cache_update
+}
+
+pkg_postrm() {
+ gnome2_icon_cache_update
+}