Show files in tooltips for pieces progress bars

In addition to the current tooltip, which shows color legend, if user
holds the Shift key during hovering we show another tooltip which
contains a table of contents for the piece under the moue cursor. The
table lists file sizes and names. If the cursor points to a part of a
file which spans several pieces, those pieces are highlighted.
This commit is contained in:
Eugene Shalygin
2016-02-29 00:44:08 +01:00
parent f9c2bd3502
commit b3378d4599
14 changed files with 756 additions and 237 deletions

View File

@@ -26,6 +26,7 @@
* exception statement from your version.
*/
#include <QDebug>
#include <QString>
#include <QList>
#include <QUrl>
@@ -138,6 +139,12 @@ int TorrentInfo::pieceLength() const
return m_nativeInfo->piece_length();
}
int TorrentInfo::pieceLength(int index) const
{
if (!isValid()) return -1;
return m_nativeInfo->piece_size(index);
}
int TorrentInfo::piecesCount() const
{
if (!isValid()) return -1;
@@ -178,7 +185,7 @@ qlonglong TorrentInfo::fileSize(int index) const
qlonglong TorrentInfo::fileOffset(int index) const
{
if (!isValid()) return -1;
if (!isValid()) return -1;
return m_nativeInfo->file_at(index).offset;
}
@@ -213,24 +220,79 @@ QByteArray TorrentInfo::metadata() const
QStringList TorrentInfo::filesForPiece(int pieceIndex) const
{
if (pieceIndex < 0)
return QStringList();
// no checks here because fileIndicesForPiece() will return an empty list
QVector<int> fileIndices = fileIndicesForPiece(pieceIndex);
std::vector<libtorrent::file_slice> files(
nativeInfo()->map_block(pieceIndex, 0, nativeInfo()->piece_size(pieceIndex)));
QStringList res;
for (const libtorrent::file_slice& s: files) {
res.append(filePath(s.file_index));
}
res.reserve(fileIndices.size());
std::transform(fileIndices.begin(), fileIndices.end(), std::back_inserter(res),
[this](int i) { return filePath(i); });
return res;
}
QVector<int> TorrentInfo::fileIndicesForPiece(int pieceIndex) const
{
if (!isValid() || (pieceIndex < 0) || (pieceIndex >= piecesCount()))
return QVector<int>();
std::vector<libt::file_slice> files(
nativeInfo()->map_block(pieceIndex, 0, nativeInfo()->piece_size(pieceIndex)));
QVector<int> res;
res.reserve(files.size());
std::transform(files.begin(), files.end(), std::back_inserter(res),
[](const libt::file_slice &s) { return s.file_index; });
return res;
}
TorrentInfo::PieceRange TorrentInfo::filePieces(const QString& file) const
{
if (!isValid()) // if we do not check here the debug message will be printed, which would be not correct
return {};
int index = fileIndex(file);
if (index == -1) {
qDebug() << "Filename" << file << "was not found in torrent" << name();
return {};
}
return filePieces(index);
}
TorrentInfo::PieceRange TorrentInfo::filePieces(int fileIndex) const
{
if (!isValid())
return {};
if ((fileIndex < 0) || (fileIndex >= filesCount())) {
qDebug() << "File index (" << fileIndex << ") is out of range for torrent" << name();
return {};
}
const libt::file_storage &files = nativeInfo()->files();
const auto fileSize = files.file_size(fileIndex);
const auto firstOffset = files.file_offset(fileIndex);
return makeInterval(static_cast<int>(firstOffset / pieceLength()),
static_cast<int>((firstOffset + fileSize - 1) / pieceLength()));
}
void TorrentInfo::renameFile(uint index, const QString &newPath)
{
if (!isValid()) return;
nativeInfo()->rename_file(index, Utils::String::toStdString(newPath));
}
int BitTorrent::TorrentInfo::fileIndex(const QString& fileName) const
{
// the check whether the object valid is not needed here
// because filesCount() returns -1 in that case and the loop exits immediately
for (int i = 0; i < filesCount(); ++i)
if (fileName == filePath(i))
return i;
return -1;
}
TorrentInfo::NativePtr TorrentInfo::nativeInfo() const
{
return m_nativeInfo;

View File

@@ -34,12 +34,15 @@
#include <libtorrent/torrent_info.hpp>
#include <libtorrent/version.hpp>
#include "base/indexrange.h"
class QString;
class QUrl;
class QDateTime;
class QStringList;
class QByteArray;
template<typename T> class QList;
template<typename T> class QVector;
namespace BitTorrent
{
@@ -75,6 +78,7 @@ namespace BitTorrent
qlonglong totalSize() const;
int filesCount() const;
int pieceLength() const;
int pieceLength(int index) const;
int piecesCount() const;
QString filePath(int index) const;
QStringList filePaths() const;
@@ -86,12 +90,21 @@ namespace BitTorrent
QList<QUrl> urlSeeds() const;
QByteArray metadata() const;
QStringList filesForPiece(int pieceIndex) const;
QVector<int> fileIndicesForPiece(int pieceIndex) const;
using PieceRange = IndexRange<int>;
// returns pair of the first and the last pieces into which
// the given file extends (maybe partially).
PieceRange filePieces(const QString &file) const;
PieceRange filePieces(int fileIndex) const;
void renameFile(uint index, const QString &newPath);
NativePtr nativeInfo() const;
private:
// returns file index or -1 if fileName is not found
int fileIndex(const QString &fileName) const;
NativePtr m_nativeInfo;
};
}