RetroShare/retroshare-gui/src/gui/RemoteDirModel.cpp
csoler 506f14eb2f - Added a parent page widget (class RsAutoUpdatePage) to handle auto-update. The page updates using a timer, only wh
en visible, and each time it gets showed. I already made some RS pages derive from this page.
- Modified and renamed the taskGraphPainterWidget to display info about currently selected file transfers. For know, it only shows file chunks info, but we should use it to display additional info about the transfer. Warning: in its
 current state, only fake chunk info is displayed.
 - Suppressed p3files.h, because it is not used.

 Remains to do (in order):
 - Implement a chunk map class in ft/ to properly manage which chunks should be downloaded 
 - Display correct chunk info by requesting the transfer's chunk map
 - Add check-sum verification of chunks
 - allow RS to import a partially downloaded file by force re-checking chunks
 - Add chunk map exchange from file source peer id to file destination peer id.
 - Manage chunks from different peers.
 - Allow search (turtle search) for partially downloaded files 



git-svn-id: http://svn.code.sf.net/p/retroshare/code/trunk@1832 b45a01b8-16f6-495d-af2f-9b41ad6348cc
2009-11-17 12:45:06 +00:00

1318 lines
30 KiB
C++

/*************************************:***************************
* RetroShare is distributed under the following license:
*
* Copyright (C) 2006 - 2009 RetroShare Team
*
* 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 <set>
#include "RemoteDirModel.h"
#include "rsiface/rsfiles.h"
#include <QtGui>
#include <QIcon>
#include <QPixmap>
#include <iostream>
#include <sstream>
#include <math.h>
#include <algorithm>
#include "util/misc.h"
/*****
* #define RDM_DEBUG
****/
RemoteDirModel::RemoteDirModel(bool mode, QObject *parent)
: QAbstractItemModel(parent),
RemoteMode(mode), nIndex(1), indexSet(1) /* ass zero index cant be used */,
ageIndicator(0)
{
setSupportedDragActions(Qt::CopyAction);
treeStyle();
}
void RemoteDirModel::treeStyle()
{
categoryIcon.addPixmap(QPixmap(":/images/folder16.png"),
QIcon::Normal, QIcon::Off);
categoryIcon.addPixmap(QPixmap(":/images/folder_video.png"),
QIcon::Normal, QIcon::On);
peerIcon = QIcon(":/images/user/identity16.png");
}
bool RemoteDirModel::hasChildren(const QModelIndex &parent) const
{
#ifdef RDM_DEBUG
std::cerr << "RemoteDirModel::hasChildren() :" << parent.internalPointer();
std::cerr << ": ";
#endif
if (!parent.isValid())
{
#ifdef RDM_DEBUG
std::cerr << "root -> true ";
std::cerr << std::endl;
#endif
return true;
}
void *ref = parent.internalPointer();
DirDetails details;
uint32_t flags = DIR_FLAGS_CHILDREN;
if (RemoteMode)
flags |= DIR_FLAGS_REMOTE;
else
flags |= DIR_FLAGS_LOCAL;
if (!rsFiles->RequestDirDetails(ref, details, flags))
{
/* error */
#ifdef RDM_DEBUG
std::cerr << "lookup failed -> false";
std::cerr << std::endl;
#endif
return false;
}
if (details.type == DIR_TYPE_FILE)
{
#ifdef RDM_DEBUG
std::cerr << "lookup FILE -> false";
std::cerr << std::endl;
#endif
return false;
}
/* PERSON/DIR*/
#ifdef RDM_DEBUG
std::cerr << "lookup PER/DIR #" << details.count;
std::cerr << std::endl;
#endif
return (details.count > 0); /* do we have children? */
}
int RemoteDirModel::rowCount(const QModelIndex &parent) const
{
#ifdef RDM_DEBUG
std::cerr << "RemoteDirModel::rowCount(): " << parent.internalPointer();
std::cerr << ": ";
#endif
void *ref = NULL;
if (parent.isValid())
{
ref = parent.internalPointer();
}
DirDetails details;
uint32_t flags = DIR_FLAGS_CHILDREN;
if (RemoteMode)
flags |= DIR_FLAGS_REMOTE;
else
flags |= DIR_FLAGS_LOCAL;
if (!rsFiles->RequestDirDetails(ref, details, flags))
{
#ifdef RDM_DEBUG
std::cerr << "lookup failed -> 0";
std::cerr << std::endl;
#endif
return 0;
}
if (details.type == DIR_TYPE_FILE)
{
#ifdef RDM_DEBUG
std::cerr << "lookup FILE: 0";
std::cerr << std::endl;
#endif
return 0;
}
/* else PERSON/DIR*/
#ifdef RDM_DEBUG
std::cerr << "lookup PER/DIR #" << details.count;
std::cerr << std::endl;
#endif
return details.count;
}
int RemoteDirModel::columnCount(const QModelIndex &parent) const
{
return 5;
}
QString RemoteDirModel::getFlagsString(uint32_t flags)
{
switch(flags & (DIR_FLAGS_NETWORK_WIDE|DIR_FLAGS_BROWSABLE))
{
case DIR_FLAGS_NETWORK_WIDE: return QString("Anonymous") ;
case DIR_FLAGS_NETWORK_WIDE | DIR_FLAGS_BROWSABLE: return QString("Anonymous and browsable by friends") ;
case DIR_FLAGS_BROWSABLE: return QString("Only browsable by friends") ;
default:
return QString() ;
}
}
QString RemoteDirModel::getAgeIndicatorString(const DirDetails &details) const
{
QString ret("");
QString nind("NEW");
QString oind("OLD");
uint32_t age = details.age;
switch (ageIndicator) {
case IND_LAST_DAY:
if (age < 24 * 60 * 60) return nind;
break;
case IND_LAST_WEEK:
if (age < 7 * 24 * 60 * 60) return nind;
break;
case IND_LAST_MONTH:
if (age < 30 * 24 * 60 * 60) return nind;
break;
case IND_OLDER:
if (age >= 30 * 24 * 60 * 60) return oind;
break;
case IND_DEFAULT:
return ret;
default:
return ret;
}
return ret;
}
QVariant RemoteDirModel::data(const QModelIndex &index, int role) const
{
#ifdef RDM_DEBUG
std::cerr << "RemoteDirModel::data(): " << index.internalPointer();
std::cerr << ": ";
std::cerr << std::endl;
#endif
if (!index.isValid())
return QVariant();
/* get the data from the index */
void *ref = index.internalPointer();
int coln = index.column();
DirDetails details;
uint32_t flags = DIR_FLAGS_DETAILS;
if (RemoteMode)
flags |= DIR_FLAGS_REMOTE;
else
flags |= DIR_FLAGS_LOCAL;
if (!rsFiles->RequestDirDetails(ref, details, flags))
{
return QVariant();
}
#if 0
/*if (role == Qt::BackgroundRole)
{*/
/*** colour entries based on rank/age/count **/
/*** rank (0-10) ***/
/ *uint32_t r = details.rank;
if (r > 10) r = 10;
r = 200 + r * 5; /* 0->250 */
/*** age: log2(age) ***
* 1 hour = 3,600 - 250
* 1 day = 86,400 - 200
* 1 week = 604,800 - 100
* 1 month = 2,419,200 - 50
*
*
* 250 - log2( 1 + (age / 100) ) * 10
* 0 => 1 => 0 => 0 => 250
* 900 => 10 => 3.2 => 32 => 220
* 3600 => 37 => 5.2 => 52 => 200
* 86400 => 865 => 9.2 => 92 => 160
* 604800 => 6049 => 12.3 => 120 => 130
* 2419200 => 24193 => 14.4 => 140 => 110
*
* value log2
*
* 1 0
* 2 1
* 4 2
* 8 3
* 16 4
* 32 5
* 64 6
* 128 7
* 256 8
* 512 9
* 1024 10
* 2048 11
* 4096 12
* 8192 13
* 16384 14
* 32K 15
*
*/
/*uint32_t g = (uint32_t) log2 ( 1.0 + ( details.age / 100 ) ) * 4;
if (g > 250) g = 250;
g = 250 - g;
if (details.type == DIR_TYPE_PERSON)
{
return QVariant();
}
else if (details.type == DIR_TYPE_DIR)
{
uint32_t b = 200 + details.count;
if (b > 250) b = 250;
QBrush brush(QColor(r,g,b));
return brush;
}
else if (details.type == DIR_TYPE_FILE)
{
uint32_t b = (uint32_t) (200 + 2 * log2(details.count));
if (b > 250) b = 250;
QBrush brush(QColor(r,g,b));
return brush;
}
else
{
return QVariant();
}
}*/
#endif
if (role == RemoteDirModel::FileNameRole)
{
FileInfo finfo;
rsFiles->FileDetails(details.hash, 0, finfo);
return QString::fromStdString(finfo.path) ;
}
if (role == Qt::DecorationRole)
{
if (details.type == DIR_TYPE_PERSON)
{
switch(coln)
{
case 0:
return (QIcon(peerIcon));
break;
}
}
else if (details.type == DIR_TYPE_DIR)
{
switch(coln)
{
case 0:
QString ext = QFileInfo(QString::fromStdString(details.name)).suffix();
if (ext == "avi" || ext == "mpg" || ext == "movie")
{
QIcon icon(":/images/folder_video.png");
return icon;
}
else
{
return(QIcon(categoryIcon));
}
break;
}
}
else if (details.type == DIR_TYPE_FILE) /* File */
{
// extensions predefined
//QString name;
switch(coln)
{
case 0:
QString ext = QFileInfo(QString::fromStdString(details.name)).suffix();
if (ext == "jpg" || ext == "jpeg" || ext == "png" || ext == "gif"
|| ext == "bmp" || ext == "ico" || ext == "svg")
{
//setIcon(0, QIcon(":/images/FileTypePicture.png"));
QIcon icon(":/images/FileTypePicture.png");
return icon;
}
else if (ext == "avi" || ext == "AVI" || ext == "mpg" || ext == "mpeg" || ext == "wmv" || ext == "ogm"
|| ext == "mkv" || ext == "mp4" || ext == "flv" || ext == "mov"
|| ext == "vob" || ext == "qt" || ext == "rm" || ext == "3gp")
{
//setIcon(0, QIcon(":/images/videofile.png"));
QIcon icon(":/images/FileTypeVideo.png");
return icon;
}
else if (ext == "ogg" || ext == "mp3" || ext == "wav" || ext == "wma" || ext == "xpm")
{
//setIcon(0, QIcon(":/images/soundfile.png"));
QIcon icon(":/images/FileTypeAudio.png");
return icon;
}
else if (ext == "tar" || ext == "bz2" || ext == "zip" || ext == "gz" || ext == "7z"
|| ext == "rar" || ext == "rpm" || ext == "deb")
{
//setIcon(0, QIcon(":/images/compressedfile.png"));
QIcon icon(":/images/FileTypeArchive.png");
return icon;
}
else if (ext == "app" || ext == "bat" || ext == "cgi" || ext == "com"
|| ext == "bin" || ext == "exe" || ext == "js" || ext == "pif"
|| ext == "py" || ext == "pl" || ext == "sh" || ext == "vb" || ext == "ws")
{
return(QIcon(":/images/FileTypeProgram.png"));
}
else if (ext == "iso" || ext == "nrg" || ext == "mdf" )
{
//setIcon(0, QIcon(":/images/txtfile.png"));
QIcon icon(":/images/FileTypeCDImage.png");
return icon;
}
else if (ext == "txt" || ext == "cpp" || ext == "c" || ext == "h")
{
//setIcon(0, QIcon(":/images/txtfile.png"));
QIcon icon(":/images/FileTypeDocument.png");
return icon;
}
else if (ext == "doc" || ext == "rtf" || ext == "sxw" || ext == "xls"
|| ext == "sxc" || ext == "odt" || ext == "ods")
{
//setIcon(0, QIcon(":/images/docfile.png"));
QIcon icon(":/images/FileTypeDocument.png");
return icon;
}
else if (ext == "html" || ext == "htm" || ext == "php")
{
//setIcon(0, QIcon(":/images/netfile.png"));
QIcon icon(":/images/FileTypeDocument.png");
return icon;
}
else
{
//setIcon(0, QIcon(":/images/file.png"));
QIcon icon(":/images/FileTypeAny.png");
return icon;
}
break;
}
}
else
{
return QVariant();
}
}
/*************
Qt::EditRole
Qt::ToolTipRole
Qt::StatusTipRole
Qt::WhatsThisRole
Qt::SizeHintRole
****************/
if (role == Qt::DisplayRole)
{
/*
* Person: name, id, 0, 0;
* File : name, size, rank, (0) ts
* Dir : name, (0) count, (0) path, (0) ts
*/
if (details.type == DIR_TYPE_PERSON) /* Person */
{
switch(coln)
{
case 0:
return QString::fromStdString(details.name);
break;
case 1:
//return QString("");
return QString::fromStdString(details.id);
break;
default:
//return QString("");
return QString::fromStdString("P");
break;
}
}
else if (details.type == DIR_TYPE_FILE) /* File */
{
switch(coln)
{
case 0:
return QString::fromUtf8(details.name.c_str());
break;
case 1:
{
std::ostringstream out;
//out << details.count;
//return QString::fromStdString(out.str());
return misc::friendlyUnit(details.count);
}
break;
case 2:
{
return getFlagsString(details.flags);
}
break;
case 3:
{
std::ostringstream out;
//out << details.age;
return misc::userFriendlyDuration(details.age);
}
break;
case 4:
{
QString ind("");
if (ageIndicator != IND_DEFAULT)
ind = getAgeIndicatorString(details);
return ind;
}
break;
default:
return QString(tr("FILE"));
break;
}
}
else if (details.type == DIR_TYPE_DIR) /* Dir */
{
switch(coln)
{
case 0:
return QString::fromUtf8(details.name.c_str());
break;
case 1:
//return QString("");
{
std::ostringstream out;
out << details.count;
return QString::fromStdString(out.str());
}
break;
case 2:
return getFlagsString(details.flags);
break;
case 3:
return misc::userFriendlyDuration(details.age);
break;
case 4:
{
if (ageIndicator == IND_DEFAULT)
return QString("");
QModelIndex pidx = parent(index);
QModelIndex pidxs = pidx.sibling(pidx.row(), 4);
if (pidxs.isValid() && pidxs.data() != tr(""))
return pidxs.data();
else {
QString ind("");
getAgeIndicatorRec(details, ind);
return ind;
}
}
break;
default:
return QString(tr("DIR"));
break;
}
}
} /* end of DisplayRole */
return QVariant();
if (role == Qt::TextAlignmentRole)
{
if(coln == 1)
{
return int( Qt::AlignLeft | Qt::AlignVCenter);
}
}
return QVariant();
}
void RemoteDirModel::getAgeIndicatorRec(DirDetails &details, QString &ret) const {
if (details.type == DIR_TYPE_FILE) {
ret = getAgeIndicatorString(details);
return;
} else if (details.type == DIR_TYPE_DIR && ret == tr("")) {
std::list<DirStub>::iterator it;
for (it = details.children.begin(); it != details.children.end(); it++) {
void *ref = it->ref;
DirDetails childDetails;
uint32_t flags;
if (RemoteMode)
flags |= DIR_FLAGS_REMOTE;
else
flags |= DIR_FLAGS_LOCAL;
if (rsFiles->RequestDirDetails(ref, childDetails, flags) && ret == tr(""))
getAgeIndicatorRec(childDetails, ret);
}
}
}
QVariant RemoteDirModel::headerData(int section, Qt::Orientation orientation,
int role) const
{
if (role == Qt::SizeHintRole)
{
int defw = 50;
int defh = 21;
if (section < 2)
{
defw = 200;
}
return QSize(defw, defh);
}
if (role != Qt::DisplayRole)
return QVariant();
if (orientation == Qt::Horizontal)
{
switch(section)
{
case 0:
if (RemoteMode)
{
return QString(tr("Friends Directories"));
}
else
{
return QString(tr("My Directories"));
}
break;
case 1:
return QString(tr("Size"));
break;
case 2:
return QString(tr("Share type"));
break;
case 3:
return QString(tr("Age"));
break;
case 4:
return QString(tr("What's new"));
break;
}
return QString("Column %1").arg(section);
}
else
return QString("Row %1").arg(section);
}
QModelIndex RemoteDirModel::index(int row, int column,
const QModelIndex & parent) const
{
#ifdef RDM_DEBUG
std::cerr << "RemoteDirModel::index(): " << parent.internalPointer();
std::cerr << ": row:" << row << " col:" << column << " ";
#endif
void *ref = NULL;
if (parent.isValid())
{
ref = parent.internalPointer();
}
/********
if (!RemoteMode)
{
remote = &(rsiface->getLocalDirectoryList());
}
********/
DirDetails details;
uint32_t flags = DIR_FLAGS_CHILDREN;
if (RemoteMode)
flags |= DIR_FLAGS_REMOTE;
else
flags |= DIR_FLAGS_LOCAL;
if (!rsFiles->RequestDirDetails(ref, details, flags))
{
#ifdef RDM_DEBUG
std::cerr << "lookup failed -> invalid";
std::cerr << std::endl;
#endif
return QModelIndex();
}
/* now iterate through the details to
* get the reference number
*/
std::list<DirStub>::iterator it;
int i = 0;
for(it = details.children.begin();
((i < row) && (it != details.children.end())); it++, i++) ;
if (it == details.children.end())
{
#ifdef RDM_DEBUG
std::cerr << "wrong number of children -> invalid";
std::cerr << std::endl;
#endif
return QModelIndex();
}
#ifdef RDM_DEBUG
std::cerr << "success index(" << row << "," << column << "," << it->ref << ")";
std::cerr << std::endl;
#endif
/* we can just grab the reference now */
QModelIndex qmi = createIndex(row, column, it->ref);
return qmi;
}
QModelIndex RemoteDirModel::parent( const QModelIndex & index ) const
{
#ifdef RDM_DEBUG
std::cerr << "RemoteDirModel::parent(): " << index.internalPointer();
std::cerr << ": ";
#endif
/* create the index */
if (!index.isValid())
{
#ifdef RDM_DEBUG
std::cerr << "Invalid Index -> invalid";
std::cerr << std::endl;
#endif
/* Parent is invalid too */
return QModelIndex();
}
void *ref = index.internalPointer();
DirDetails details;
uint32_t flags = DIR_FLAGS_PARENT;
if (RemoteMode)
flags |= DIR_FLAGS_REMOTE;
else
flags |= DIR_FLAGS_LOCAL;
if (!rsFiles->RequestDirDetails(ref, details, flags))
{
#ifdef RDM_DEBUG
std::cerr << "Failed Lookup -> invalid";
std::cerr << std::endl;
#endif
return QModelIndex();
}
if (!(details.parent))
{
#ifdef RDM_DEBUG
std::cerr << "success. parent is Root/NULL --> invalid";
std::cerr << std::endl;
#endif
return QModelIndex();
}
#ifdef RDM_DEBUG
std::cerr << "success index(" << details.prow << ",0," << details.parent << ")";
std::cerr << std::endl;
#endif
return createIndex(details.prow, 0, details.parent);
}
Qt::ItemFlags RemoteDirModel::flags( const QModelIndex & index ) const
{
#ifdef RDM_DEBUG
std::cerr << "RemoteDirModel::flags()";
std::cerr << std::endl;
#endif
if (!index.isValid())
return (Qt::ItemIsSelectable); // Error.
void *ref = index.internalPointer();
DirDetails details;
uint32_t flags = DIR_FLAGS_DETAILS;
if (RemoteMode)
flags |= DIR_FLAGS_REMOTE;
else
flags |= DIR_FLAGS_LOCAL;
if (!rsFiles->RequestDirDetails(ref, details, flags))
{
return (Qt::ItemIsSelectable); // Error.
}
if (details.type == DIR_TYPE_PERSON)
{
return (Qt::ItemIsEnabled);
}
else if (details.type == DIR_TYPE_DIR)
{
return ( Qt::ItemIsSelectable |
Qt::ItemIsEnabled);
// Qt::ItemIsDragEnabled |
// Qt::ItemIsDropEnabled |
}
else // (details.type == DIR_TYPE_FILE)
{
return ( Qt::ItemIsSelectable |
Qt::ItemIsDragEnabled |
Qt::ItemIsEnabled);
}
}
// The other flags...
//Qt::ItemIsUserCheckable
//Qt::ItemIsEditable
//Qt::ItemIsDropEnabled
//Qt::ItemIsTristate
/* Callback from */
void RemoteDirModel::preMods()
{
#ifdef RDM_DEBUG
std::cerr << "RemoteDirModel::preMods()" << std::endl;
#endif
//modelAboutToBeReset();
// reset();
layoutAboutToBeChanged();
}
/* Callback from */
void RemoteDirModel::postMods()
{
#ifdef RDM_DEBUG
std::cerr << "RemoteDirModel::postMods()" << std::endl;
#endif
//modelReset();
layoutChanged();
//reset();
}
void RemoteDirModel::update (const QModelIndex &index )
{
#ifdef RDM_DEBUG
//std::cerr << "Directory Request(" << id << ") : ";
//std::cerr << path << std::endl;
#endif
//rsFiles -> RequestDirectories(id, path, 1);
}
void RemoteDirModel::downloadSelected(QModelIndexList list)
{
if (!RemoteMode)
{
#ifdef RDM_DEBUG
std::cerr << "Cannot download from local" << std::endl;
#endif
}
/* so for all the selected .... get the name out,
* make it into something the RsControl can understand
*/
std::vector <DirDetails> dirVec;
getDirDetailsFromSelect(list, dirVec);
/* Fire off requests */
for (int i = 0, n = dirVec.size(); i < n; ++i)
{
if (!RemoteMode)
{
continue; /* don't try to download local stuff */
}
const DirDetails& details = dirVec[i];
/* if it is a file */
if (details.type == DIR_TYPE_FILE)
{
std::cerr << "RemoteDirModel::downloadSelected() Calling File Request";
std::cerr << std::endl;
std::list<std::string> srcIds;
srcIds.push_back(details.id);
rsFiles -> FileRequest(details.name, details.hash,
details.count, "", 0, srcIds);
}
/* if it is a dir, copy all files included*/
else if (details.type == DIR_TYPE_DIR)
{
int prefixLen = details.path.rfind(details.name);
if (prefixLen < 0) continue;
downloadDirectory(details, prefixLen);
}
}
}
/* recursively download a directory */
void RemoteDirModel::downloadDirectory(const DirDetails & dirDetails, int prefixLen)
{
if (dirDetails.type & DIR_TYPE_FILE)
{
std::list<std::string> srcIds;
QString cleanPath = QDir::cleanPath((rsFiles->getDownloadDirectory() + "/" + dirDetails.path.substr(prefixLen)).c_str());
srcIds.push_back(dirDetails.id);
rsFiles->FileRequest(dirDetails.name, dirDetails.hash, dirDetails.count, cleanPath.toStdString(), 0, srcIds);
}
else if (dirDetails.type & DIR_TYPE_DIR)
{
std::list<DirStub>::const_iterator it;
QDir dwlDir(rsFiles->getDownloadDirectory().c_str());
QString cleanPath = QDir::cleanPath(QString(dirDetails.path.c_str()).right(dirDetails.path.length() - prefixLen));
if (!dwlDir.mkpath(cleanPath)) return;
for (it = dirDetails.children.begin(); it != dirDetails.children.end(); it++)
{
if (!it->ref) continue;
DirDetails subDirDetails;
uint32_t flags = DIR_FLAGS_CHILDREN | DIR_FLAGS_REMOTE;
if (!rsFiles->RequestDirDetails(it->ref, subDirDetails, flags)) continue;
downloadDirectory(subDirDetails, prefixLen);
}
}
}
void RemoteDirModel::getDirDetailsFromSelect (QModelIndexList list, std::vector <DirDetails>& dirVec)
{
dirVec.clear();
/* Fire off requests */
QModelIndexList::iterator it;
for(it = list.begin(); it != list.end(); it++)
{
if(it->column()==1)
{
void *ref = it -> internalPointer();
DirDetails details;
uint32_t flags = DIR_FLAGS_DETAILS;
if (RemoteMode)
{
flags |= DIR_FLAGS_REMOTE;
}
else
{
flags |= DIR_FLAGS_LOCAL;
}
if (!rsFiles->RequestDirDetails(ref, details, flags))
{
continue;
}
dirVec.push_back(details);
}
}
}
/****************************************************************************
* OLD RECOMMEND SYSTEM - DISABLED
*
*/
void RemoteDirModel::getFileInfoFromIndexList(const QModelIndexList& list, std::list<DirDetails>& file_details)
{
file_details.clear() ;
#ifdef RDM_DEBUG
std::cerr << "recommendSelected()" << std::endl;
#endif
if (RemoteMode)
{
#ifdef RDM_DEBUG
std::cerr << "Cannot recommend remote! (should download)" << std::endl;
#endif
}
/* Fire off requests */
std::set<std::string> already_in ;
for(QModelIndexList::const_iterator it(list.begin()); it != list.end(); ++it)
{
void *ref = it -> internalPointer();
DirDetails details;
uint32_t flags = DIR_FLAGS_DETAILS;
if (RemoteMode)
{
flags |= DIR_FLAGS_REMOTE;
continue; /* don't recommend remote stuff */
}
else
{
flags |= DIR_FLAGS_LOCAL;
}
if (!rsFiles->RequestDirDetails(ref, details, flags))
{
continue;
}
#ifdef RDM_DEBUG
std::cerr << "::::::::::::FileRecommend:::: " << std::endl;
std::cerr << "Name: " << details.name << std::endl;
std::cerr << "Hash: " << details.hash << std::endl;
std::cerr << "Size: " << details.count << std::endl;
std::cerr << "Path: " << details.path << std::endl;
#endif
if(already_in.find(details.hash) == already_in.end())
{
file_details.push_back(details) ;
already_in.insert(details.hash) ;
}
}
#ifdef RDM_DEBUG
std::cerr << "::::::::::::Done FileRecommend" << std::endl;
#endif
}
#if 0
void RemoteDirModel::recommendSelectedOnly(QModelIndexList list)
{
#ifdef RDM_DEBUG
std::cerr << "recommendSelectedOnly()" << std::endl;
#endif
if (RemoteMode)
{
#ifdef RDM_DEBUG
std::cerr << "Cannot recommend remote! (should download)" << std::endl;
#endif
}
rsFiles->ClearInRecommend();
/* Fire off requests */
QModelIndexList::iterator it;
for(it = list.begin(); it != list.end(); it++)
{
void *ref = it -> internalPointer();
DirDetails details;
uint32_t flags = DIR_FLAGS_DETAILS;
if (RemoteMode)
{
flags |= DIR_FLAGS_REMOTE;
continue; /* don't recommend remote stuff */
}
else
{
flags |= DIR_FLAGS_LOCAL;
}
if (!rsFiles->RequestDirDetails(ref, details, flags))
{
continue;
}
#ifdef RDM_DEBUG
std::cerr << "::::::::::::FileRecommend:::: " << std::endl;
std::cerr << "Name: " << details.name << std::endl;
std::cerr << "Hash: " << details.hash << std::endl;
std::cerr << "Size: " << details.count << std::endl;
std::cerr << "Path: " << details.path << std::endl;
#endif
rsFiles -> FileRecommend(details.name, details.hash, details.count);
rsFiles -> SetInRecommend(details.name, true);
}
#ifdef RDM_DEBUG
std::cerr << "::::::::::::Done FileRecommend" << std::endl;
#endif
}
#endif
/****************************************************************************
* OLD RECOMMEND SYSTEM - DISABLED
******/
void RemoteDirModel::openSelected(QModelIndexList qmil, bool openFolder)
{
#ifdef RDM_DEBUG
std::cerr << "RemoteDirModel::openSelected()" << std::endl;
#endif
if (RemoteMode) {
#ifdef RDM_DEBUG
std::cerr << "Cannot open remote. Download first." << std::endl;
#endif
return;
}
std::list<std::string> dirs_to_open;
std::list<DirDetails> files_info;
std::list<DirDetails>::iterator it;
getFileInfoFromIndexList(qmil, files_info);
for (it = files_info.begin(); it != files_info.end(); it++) {
if ((*it).type & DIR_TYPE_PERSON) continue;
std::string fullpath, name;
rsFiles->ConvertSharedFilePath((*it).path, fullpath);
int len = fullpath.length();
if (len && (fullpath[len - 1] != '/')) fullpath += '/';
if ((*it).type & DIR_TYPE_FILE) {
name = fullpath + (*it).name;
} else if ((*it).type & DIR_TYPE_DIR) {
name = fullpath;
}
if (!openFolder) {
if ((*it).type & DIR_TYPE_FILE) {
QDesktopServices::openUrl(QUrl::fromLocalFile(name.c_str()));
}
} else {
if (dirs_to_open.end() == std::find(dirs_to_open.begin(), dirs_to_open.end(), fullpath)) {
dirs_to_open.push_back(fullpath);
}
}
}
if (openFolder) {
std::list<std::string>::iterator dit;
for (dit = dirs_to_open.begin(); dit != dirs_to_open.end(); dit++) {
QDesktopServices::openUrl(QUrl::fromLocalFile((*dit).c_str()));
}
}
#ifdef RDM_DEBUG
std::cerr << "::::::::::::Done RemoteDirModel::openSelected()" << std::endl;
#endif
}
void RemoteDirModel::getFilePaths(QModelIndexList list, std::list<std::string> &fullpaths)
{
#ifdef RDM_DEBUG
std::cerr << "RemoteDirModel::getFilePaths()" << std::endl;
#endif
if (RemoteMode)
{
#ifdef RDM_DEBUG
std::cerr << "No File Paths for remote files" << std::endl;
#endif
return;
}
/* translate */
QModelIndexList::iterator it;
for(it = list.begin(); it != list.end(); it++)
{
void *ref = it -> internalPointer();
DirDetails details;
uint32_t flags = DIR_FLAGS_DETAILS;
flags |= DIR_FLAGS_LOCAL;
if (!rsFiles->RequestDirDetails(ref, details, flags))
{
#ifdef RDM_DEBUG
std::cerr << "getFilePaths() Bad Request" << std::endl;
#endif
continue;
}
if (details.type != DIR_TYPE_FILE)
{
#ifdef RDM_DEBUG
std::cerr << "getFilePaths() Not File" << std::endl;
#endif
continue; /* not file! */
}
#ifdef RDM_DEBUG
std::cerr << "::::::::::::File Details:::: " << std::endl;
std::cerr << "Name: " << details.name << std::endl;
std::cerr << "Hash: " << details.hash << std::endl;
std::cerr << "Size: " << details.count << std::endl;
std::cerr << "Path: " << details.path << std::endl;
#endif
std::string filepath = details.path + "/";
filepath += details.name;
#ifdef RDM_DEBUG
std::cerr << "Constructed FilePath: " << filepath << std::endl;
#endif
if (fullpaths.end() == std::find(fullpaths.begin(), fullpaths.end(), filepath))
{
fullpaths.push_back(filepath);
}
}
#ifdef RDM_DEBUG
std::cerr << "::::::::::::Done getFilePaths" << std::endl;
#endif
}
/* Drag and Drop Functionality */
QMimeData * RemoteDirModel::mimeData ( const QModelIndexList & indexes ) const
{
/* extract from each the member text */
std::string text;
QModelIndexList::const_iterator it;
std::map<std::string, uint64_t> drags;
std::map<std::string, uint64_t>::iterator dit;
for(it = indexes.begin(); it != indexes.end(); it++)
{
void *ref = it -> internalPointer();
DirDetails details;
uint32_t flags = DIR_FLAGS_DETAILS;
if (RemoteMode)
{
flags |= DIR_FLAGS_REMOTE;
}
else
{
flags |= DIR_FLAGS_LOCAL;
}
if (!rsFiles->RequestDirDetails(ref, details, flags))
{
continue;
}
#ifdef RDM_DEBUG
std::cerr << "::::::::::::FileDrag:::: " << std::endl;
std::cerr << "Name: " << details.name << std::endl;
std::cerr << "Hash: " << details.hash << std::endl;
std::cerr << "Size: " << details.count << std::endl;
std::cerr << "Path: " << details.path << std::endl;
#endif
if (details.type != DIR_TYPE_FILE)
{
#ifdef RDM_DEBUG
std::cerr << "RemoteDirModel::mimeData() Not File" << std::endl;
#endif
continue; /* not file! */
}
if (drags.end() != (dit = drags.find(details.hash)))
{
#ifdef RDM_DEBUG
std::cerr << "RemoteDirModel::mimeData() Duplicate" << std::endl;
#endif
continue; /* duplicate */
}
drags[details.hash] = details.count;
std::string line = details.name;
line += "/";
line += details.hash;
line += "/";
{
std::ostringstream out;
out << details.count;
line += out.str();
line += "/";
}
if (RemoteMode)
{
line += "Remote";
}
else
{
line += "Local";
}
line += "/\n";
text += line;
}
#ifdef RDM_DEBUG
std::cerr << "Created MimeData:";
std::cerr << std::endl;
std::cerr << text;
std::cerr << std::endl;
#endif
QMimeData *data = new QMimeData();
data->setData("application/x-rsfilelist", QByteArray(text.c_str()));
return data;
}
QStringList RemoteDirModel::mimeTypes () const
{
QStringList list;
list.push_back("application/x-rsfilelist");
return list;
}
//============================================================================
bool
RemoteDirModel::isDir ( const QModelIndex & index ) const
{
//if (RemoteMode) // only local files can be opened
// return ;
void *ref = index.internalPointer();
if (!ref)
return false;
DirDetails details;
uint32_t flags = DIR_FLAGS_DETAILS;
if (RemoteMode)
flags |= DIR_FLAGS_REMOTE;
else
flags |= DIR_FLAGS_LOCAL;
if (!rsFiles->RequestDirDetails(ref, details, flags))
{
return false;//not good, but....
}
return (details.type == DIR_TYPE_DIR) ;
}