mirror of
https://github.com/RetroShare/RetroShare.git
synced 2025-07-28 08:54:13 -04:00
merged branch 0.5.0 commits 2576, 2579, 2581-2583 into trunk
git-svn-id: http://svn.code.sf.net/p/retroshare/code/trunk@2592 b45a01b8-16f6-495d-af2f-9b41ad6348cc
This commit is contained in:
parent
294f4207ed
commit
b000245ef5
14 changed files with 201 additions and 247 deletions
|
@ -49,11 +49,16 @@ class RetroShareLink
|
|||
|
||||
/// returns the string retroshare://file|name|size|hash
|
||||
QString toString() const ;
|
||||
/// returns the string <a href="retroshare://file|name|size|hash">retroshare://file|name|size|hash</a>
|
||||
/// returns the string <a href="retroshare://file|name|size|hash">name</a>
|
||||
QString toHtml() const ;
|
||||
/// returns the string <a href="retroshare://file|name|size|hash">retroshare://file|name|size|hash</a>
|
||||
QString toHtmlFull() const ;
|
||||
|
||||
QUrl toUrl() const ;
|
||||
|
||||
bool valid() const { return _size > 0 ; }
|
||||
|
||||
bool operator==(const RetroShareLink& l) const { return _hash == l._hash ; }
|
||||
private:
|
||||
void check() ;
|
||||
static bool checkHash(const QString& hash) ;
|
||||
|
@ -68,32 +73,42 @@ class RetroShareLink
|
|||
|
||||
/// This class handles the copy/paste of links. Every member is static to ensure unicity.
|
||||
/// I put no mutex, because all calls supposely com from the GUI thread.
|
||||
///
|
||||
/// All links are stored in html format into the clipboard. Why? Because this allows to import
|
||||
/// links from both the clipboard and the RS application, e.g. paste links from an internet forum.
|
||||
/// This requires many clipboard parsing operations, but this is not a problem because this code is
|
||||
/// not performances-critical.
|
||||
//
|
||||
class RSLinkClipboard
|
||||
{
|
||||
public:
|
||||
static void copyLinks(const std::vector<RetroShareLink>& links)
|
||||
{
|
||||
_links = links ;
|
||||
}
|
||||
static const std::vector<RetroShareLink>& pasteLinks()
|
||||
{
|
||||
return _links ;
|
||||
}
|
||||
static QString toHtml()
|
||||
{
|
||||
QString res ;
|
||||
for(uint32_t i=0;i<_links.size();++i)
|
||||
res += _links[i].toHtml() + "<br/>" ;
|
||||
// Copy these links to the RS clipboard. Also copy them to the system clipboard
|
||||
//
|
||||
static void copyLinks(const std::vector<RetroShareLink>& links) ;
|
||||
|
||||
// Get the liste of pasted links, either from the internal RS links, or by default
|
||||
// from the clipboard.
|
||||
//
|
||||
static std::vector<RetroShareLink> pasteLinks() ;
|
||||
|
||||
// Produces a list of links with no html structure.
|
||||
static QString toString() ;
|
||||
|
||||
// produces a list of html links that displays with the file names only
|
||||
//
|
||||
static QString toHtml();
|
||||
|
||||
// produces a list of html links that displays the full links
|
||||
//
|
||||
static QString toHtmlFull();
|
||||
|
||||
// Returns true is no links are found to paste.
|
||||
// Useful for menus.
|
||||
//
|
||||
static bool empty();
|
||||
|
||||
return res ;
|
||||
}
|
||||
static bool empty()
|
||||
{
|
||||
return _links.empty();
|
||||
}
|
||||
private:
|
||||
static std::vector<RetroShareLink> _links ;
|
||||
static std::vector<RetroShareLink> parseClipboard() ;
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -104,7 +104,7 @@ void ShareManager::load()
|
|||
for(it = dirs.begin(); it != dirs.end(); it++,++row)
|
||||
{
|
||||
listWidget->insertRow(row) ;
|
||||
listWidget->setItem(row,0,new QTableWidgetItem(QString::fromStdString((*it).filename)));
|
||||
listWidget->setItem(row,0,new QTableWidgetItem(QString::fromUtf8((*it).filename.c_str())));
|
||||
#ifdef USE_COMBOBOX
|
||||
QComboBox *cb = new QComboBox ;
|
||||
cb->addItem(QString("Network Wide")) ;
|
||||
|
@ -173,8 +173,7 @@ void ShareManager::addShareDirectory()
|
|||
*/
|
||||
|
||||
|
||||
QString qdir = QFileDialog::getExistingDirectory(this, tr("Select A Folder To Share"), "",
|
||||
QFileDialog::ShowDirsOnly | QFileDialog::DontResolveSymlinks);
|
||||
QString qdir = QFileDialog::getExistingDirectory(this, tr("Select A Folder To Share"), "", QFileDialog::DontUseNativeDialog | QFileDialog::ShowDirsOnly | QFileDialog::DontResolveSymlinks);
|
||||
|
||||
/* add it to the server */
|
||||
std::string dir = qdir.toStdString();
|
||||
|
|
|
@ -201,6 +201,7 @@ TransfersDialog::TransfersDialog(QWidget *parent)
|
|||
|
||||
#endif
|
||||
|
||||
QObject::connect(ui._showCacheTransfers_CB,SIGNAL(toggled(bool)),this,SLOT(insertTransfers())) ;
|
||||
|
||||
}
|
||||
|
||||
|
@ -663,50 +664,23 @@ void TransfersDialog::insertTransfers()
|
|||
// std::list<DwlDetails> dwlDetails;
|
||||
// rsFiles->getDwlDetails(dwlDetails);
|
||||
|
||||
//first clean the model in case some files are not download anymore
|
||||
//remove items that are not fiends anymore
|
||||
int removeIndex = 0;
|
||||
while (removeIndex < DLListModel->rowCount()) {
|
||||
std::string hash = DLListModel->item(removeIndex, ID)->data(Qt::EditRole).toString().toStdString();
|
||||
std::list<std::string>::iterator downHashesIt;
|
||||
bool found = false;
|
||||
for (downHashesIt = downHashes.begin(); downHashesIt != downHashes.end(); downHashesIt++) {
|
||||
if (hash == *downHashesIt) {
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
// if (!found) {
|
||||
// //look in the queued files
|
||||
// std::list<DwlDetails>::iterator dwlDetailsIt;
|
||||
// for (dwlDetailsIt = dwlDetails.begin(); dwlDetailsIt != dwlDetails.end(); dwlDetailsIt++) {
|
||||
// if (hash == dwlDetailsIt->hash) {
|
||||
// found = true;
|
||||
// break;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
if (!found) {
|
||||
DLListModel->takeRow(removeIndex);
|
||||
} else {
|
||||
removeIndex++;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
std::set<std::string> used_hashes ;
|
||||
|
||||
// clear all source peers.
|
||||
|
||||
std::list<std::string>::iterator it;
|
||||
for (it = downHashes.begin(); it != downHashes.end(); it++) {
|
||||
for (it = downHashes.begin(); it != downHashes.end(); it++)
|
||||
{
|
||||
FileInfo info;
|
||||
if (!rsFiles->FileDetails(*it, RS_FILE_HINTS_DOWNLOAD, info)) {
|
||||
//if file transfer is a cache file index file, don't show it
|
||||
continue;
|
||||
}
|
||||
|
||||
if ((info.flags & CB_CODE_CACHE)) {
|
||||
/*(!_show_cache_transfers) &&*/
|
||||
if((info.flags & CB_CODE_CACHE) && !ui._showCacheTransfers_CB->isChecked())
|
||||
continue;
|
||||
}
|
||||
|
||||
QString fileName = QString::fromUtf8(info.fname.c_str());
|
||||
QString fileHash = QString::fromStdString(info.hash);
|
||||
|
@ -763,6 +737,7 @@ void TransfersDialog::insertTransfers()
|
|||
pinfo.nb_chunks = pinfo.cmap._map.empty()?0:fcinfo.chunks.size() ;
|
||||
|
||||
int addedRow = addItem("", fileName, fileHash, fileSize, pinfo, fileDlspeed, sources, status, priority, completed, remaining, downloadtime);
|
||||
used_hashes.insert(info.hash) ;
|
||||
|
||||
/* continue to next download item if no peers to add */
|
||||
if (!info.peers.size()) continue;
|
||||
|
@ -810,7 +785,7 @@ void TransfersDialog::insertTransfers()
|
|||
// std::cerr << std::endl ;
|
||||
// std::cerr << std::endl ;
|
||||
|
||||
std::cout << "adding peer " << peerName.toStdString() << " to row " << addedRow << ", hashfile and peerid=" << hashFileAndPeerId.toStdString() << std::endl ;
|
||||
// std::cout << "adding peer " << peerName.toStdString() << " to row " << addedRow << ", hashfile and peerid=" << hashFileAndPeerId.toStdString() << std::endl ;
|
||||
int row_id = addPeerToItem(addedRow, peerName, hashFileAndPeerId, peerDlspeed, status, peerpinfo);
|
||||
|
||||
used_rows.insert(row_id) ;
|
||||
|
@ -825,31 +800,22 @@ void TransfersDialog::insertTransfers()
|
|||
if(used_rows.find(r) == used_rows.end())
|
||||
dlItem->takeRow(r) ;
|
||||
}
|
||||
// remove hashes that where not shown
|
||||
//first clean the model in case some files are not download anymore
|
||||
//remove items that are not fiends anymore
|
||||
int removeIndex = 0;
|
||||
while (removeIndex < DLListModel->rowCount())
|
||||
{
|
||||
std::string hash = DLListModel->item(removeIndex, ID)->data(Qt::EditRole).toString().toStdString();
|
||||
|
||||
/* here i will insert files from the download queue - which are
|
||||
* not started yet and can't be find in FileDownloads
|
||||
* */
|
||||
// std::list<DwlDetails>::iterator dit;
|
||||
// for (dit = dwlDetails.begin(); dit != dwlDetails.end(); dit ++)
|
||||
// {
|
||||
//// switch (dit->priority) {
|
||||
//// case 0: priority = tr("Low"); break;
|
||||
//// case 1: priority = tr("Normal"); break;
|
||||
//// case 2: priority = tr("High"); break;
|
||||
//// case 3: priority = tr("Auto"); break;
|
||||
//// default: priority = tr("Auto"); break;
|
||||
//// }
|
||||
//
|
||||
// FileProgressInfo pinfo ;
|
||||
// pinfo.progress = 0.0 ;
|
||||
// pinfo.nb_chunks = 0 ;
|
||||
//
|
||||
// addItem("", QString::fromUtf8(dit->fname.c_str()),
|
||||
// QString::fromStdString(dit->hash), dit->count, pinfo, 0, 0,
|
||||
// tr("Queued"), "", 0, 0, 0);
|
||||
// }
|
||||
//
|
||||
if(used_hashes.find(hash) == used_hashes.end())
|
||||
DLListModel->takeRow(removeIndex);
|
||||
else
|
||||
removeIndex++;
|
||||
}
|
||||
|
||||
// Now show upload hashes
|
||||
//
|
||||
std::list<std::string> upHashes;
|
||||
rsFiles->FileUploads(upHashes);
|
||||
//first clean the model in case some files are not uploaded anymore
|
||||
|
@ -881,7 +847,7 @@ void TransfersDialog::insertTransfers()
|
|||
if (!rsFiles->FileDetails(*it, RS_FILE_HINTS_UPLOAD, info)) {
|
||||
continue;
|
||||
}
|
||||
if (/*(!_show_cache_transfers) &&*/ (info.flags & CB_CODE_CACHE))
|
||||
if((info.flags & CB_CODE_CACHE) && !ui._showCacheTransfers_CB->isChecked())
|
||||
continue ;
|
||||
|
||||
std::list<TransferInfo>::iterator pit;
|
||||
|
|
|
@ -602,6 +602,13 @@ p, li { white-space: pre-wrap; }
|
|||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="_showCacheTransfers_CB">
|
||||
<property name="text">
|
||||
<string>Show cache transfers</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
|
@ -658,9 +665,6 @@ p, li { white-space: pre-wrap; }
|
|||
<attribute name="headerStretchLastSection">
|
||||
<bool>false</bool>
|
||||
</attribute>
|
||||
<attribute name="headerStretchLastSection">
|
||||
<bool>false</bool>
|
||||
</attribute>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
|
@ -843,8 +847,8 @@ p, li { white-space: pre-wrap; }
|
|||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>98</width>
|
||||
<height>28</height>
|
||||
<width>578</width>
|
||||
<height>113</height>
|
||||
</rect>
|
||||
</property>
|
||||
</widget>
|
||||
|
|
|
@ -26,9 +26,9 @@
|
|||
#include <iostream>
|
||||
#include <sstream>
|
||||
|
||||
#include "rsiface/rsiface.h"
|
||||
#include "rsiface/rsfiles.h"
|
||||
#include "rsiface/rspeers.h"
|
||||
#include <rsiface/rsiface.h>
|
||||
#include <rsiface/rsfiles.h>
|
||||
#include <rsiface/rspeers.h>
|
||||
|
||||
#include <QTimer>
|
||||
|
||||
|
@ -38,15 +38,15 @@ TransferPage::TransferPage(QWidget * parent, Qt::WFlags flags)
|
|||
/* Invoke the Qt Designer generated object setup routine */
|
||||
ui.setupUi(this);
|
||||
|
||||
// QTimer *timer = new QTimer(this);
|
||||
// timer->connect(timer, SIGNAL(timeout()), this, SLOT(updateStatus()));
|
||||
// timer->start(1000);
|
||||
|
||||
updateStatus();
|
||||
|
||||
ui._queueSize_SB->setValue(rsFiles->getQueueSize()) ;
|
||||
|
||||
if(rsFiles->defaultChunkStrategy() == FileChunksInfo::CHUNK_STRATEGY_STREAMING)
|
||||
ui._defaultStrategy_CB->setCurrentIndex(0) ;
|
||||
else
|
||||
ui._defaultStrategy_CB->setCurrentIndex(1) ;
|
||||
|
||||
QObject::connect(ui._queueSize_SB,SIGNAL(valueChanged(int)),this,SLOT(updateQueueSize(int))) ;
|
||||
QObject::connect(ui._defaultStrategy_CB,SIGNAL(activated(int)),this,SLOT(updateDefaultStrategy(int))) ;
|
||||
|
||||
/* Hide platform specific features */
|
||||
#ifdef Q_WS_WIN
|
||||
|
@ -54,6 +54,20 @@ TransferPage::TransferPage(QWidget * parent, Qt::WFlags flags)
|
|||
#endif
|
||||
}
|
||||
|
||||
void TransferPage::updateDefaultStrategy(int i)
|
||||
{
|
||||
switch(i)
|
||||
{
|
||||
case 0: rsFiles->setDefaultChunkStrategy(FileChunksInfo::CHUNK_STRATEGY_STREAMING) ;
|
||||
break ;
|
||||
|
||||
case 1: rsFiles->setDefaultChunkStrategy(FileChunksInfo::CHUNK_STRATEGY_RANDOM) ;
|
||||
break ;
|
||||
|
||||
default: ;
|
||||
}
|
||||
}
|
||||
|
||||
void TransferPage::updateQueueSize(int s)
|
||||
{
|
||||
rsFiles->setQueueSize(s) ;
|
||||
|
@ -65,46 +79,3 @@ void TransferPage::closeEvent (QCloseEvent * event)
|
|||
}
|
||||
|
||||
|
||||
/** Saves the changes on this page */
|
||||
bool
|
||||
TransferPage::save(QString &errmsg)
|
||||
{
|
||||
|
||||
/* save the server address */
|
||||
/* save local address */
|
||||
/* save the url for DNS access */
|
||||
|
||||
/* restart server */
|
||||
|
||||
/* save all? */
|
||||
//saveAddresses();
|
||||
return true;
|
||||
}
|
||||
|
||||
/** Loads the settings for this page */
|
||||
void TransferPage::load()
|
||||
{
|
||||
|
||||
/* load up configuration from rsPeers */
|
||||
// RsPeerDetails detail;
|
||||
// if (!rsPeers->getPeerDetails(rsPeers->getOwnId(), detail))
|
||||
// {
|
||||
// return;
|
||||
// }
|
||||
|
||||
|
||||
}
|
||||
|
||||
/** Loads the settings for this page */
|
||||
void TransferPage::updateStatus()
|
||||
{
|
||||
/* load up configuration from rsPeers */
|
||||
// RsPeerDetails detail;
|
||||
// if (!rsPeers->getPeerDetails(rsPeers->getOwnId(), detail))
|
||||
// {
|
||||
// return;
|
||||
// }
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -36,13 +36,13 @@ class TransferPage: public ConfigPage
|
|||
~TransferPage() {}
|
||||
|
||||
/** Saves the changes on this page */
|
||||
bool save(QString &errmsg);
|
||||
virtual bool save(QString &errmsg) {}
|
||||
/** Loads the settings for this page */
|
||||
void load();
|
||||
virtual void load() {}
|
||||
|
||||
public slots:
|
||||
void updateStatus();
|
||||
void updateQueueSize(int) ;
|
||||
void updateDefaultStrategy(int) ;
|
||||
|
||||
private:
|
||||
|
||||
|
|
|
@ -13,31 +13,36 @@
|
|||
<property name="windowTitle">
|
||||
<string>Form</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
<item row="0" column="0">
|
||||
<widget class="QTabWidget" name="tabWidget">
|
||||
<property name="currentIndex">
|
||||
<number>0</number>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<widget class="QGroupBox" name="groupBox">
|
||||
<property name="title">
|
||||
<string>Transfer options</string>
|
||||
</property>
|
||||
<widget class="QWidget" name="Seite">
|
||||
<attribute name="title">
|
||||
<string>Transfer</string>
|
||||
</attribute>
|
||||
<layout class="QGridLayout" name="gridLayout_3">
|
||||
<item row="0" column="0">
|
||||
<widget class="QGroupBox" name="groupBox">
|
||||
<property name="title">
|
||||
<string>Transfer options</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_2">
|
||||
<item row="0" column="0">
|
||||
<layout class="QVBoxLayout" name="verticalLayout_3">
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<item>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_4">
|
||||
<item>
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="text">
|
||||
<string>Queue Size:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<item>
|
||||
<widget class="QLabel" name="label_3">
|
||||
<property name="text">
|
||||
<string>Default chunk strategy:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_2">
|
||||
<item>
|
||||
<widget class="QSpinBox" name="_queueSize_SB">
|
||||
<property name="enabled">
|
||||
<bool>true</bool>
|
||||
|
@ -53,40 +58,10 @@
|
|||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="label_2">
|
||||
<property name="text">
|
||||
<string>Maximum Download speed per file:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QSpinBox" name="downspeedspinBox">
|
||||
<item>
|
||||
<widget class="QComboBox" name="_defaultStrategy_CB">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="suffix">
|
||||
<string> kB/s</string>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>100000</number>
|
||||
</property>
|
||||
<property name="value">
|
||||
<number>1024</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="label_3">
|
||||
<property name="text">
|
||||
<string>Default chunk strategy:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="QComboBox" name="strategycomboBox">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<item>
|
||||
<property name="text">
|
||||
|
@ -100,46 +75,17 @@
|
|||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0" colspan="2">
|
||||
<widget class="QCheckBox" name="checkBox">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Show Cache Transfers</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<spacer name="verticalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>248</width>
|
||||
<height>138</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QWidget" name="tab_3">
|
||||
<attribute name="title">
|
||||
<string>F2F Routing</string>
|
||||
</attribute>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_3">
|
||||
<item>
|
||||
<widget class="QTextEdit" name="textEdit">
|
||||
<property name="readOnly">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="html">
|
||||
<string><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QTextEdit" name="textEdit">
|
||||
<property name="readOnly">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="html">
|
||||
<string><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">
|
||||
<html><head><meta name="qrichtext" content="1" /><style type="text/css">
|
||||
p, li { white-space: pre-wrap; }
|
||||
</style></head><body style=" font-family:'Sans'; font-size:10pt; font-weight:400; font-style:normal;">
|
||||
|
@ -148,11 +94,10 @@ p, li { white-space: pre-wrap; }
|
|||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">You can separately setup share flags for each shared directory in the shared files dialog to be:</span></p>
|
||||
<ul style="-qt-list-indent: 1;"><li style=" font-size:8pt;" style=" margin-top:12px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Browsable by friends</span>: files are seen by your friends.</li>
|
||||
<li style=" font-size:8pt;" style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Anonymously shared</span>: files are anonymously reachable through distant F2F tunnels.</li></ul></body></html></string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue