Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve tooltips for torrent progress bar #4936

Merged
merged 3 commits into from
Jun 2, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions src/base/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ utils/misc.h
utils/string.h
filesystemwatcher.h
iconprovider.h
indexrange.h
logger.h
preferences.h
qinisettings.h
Expand Down
1 change: 1 addition & 0 deletions src/base/base.pri
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ HEADERS += \
$$PWD/logger.h \
$$PWD/settingsstorage.h \
$$PWD/preferences.h \
$$PWD/indexrange.h \
$$PWD/iconprovider.h \
$$PWD/http/irequesthandler.h \
$$PWD/http/connection.h \
Expand Down
33 changes: 7 additions & 26 deletions src/base/bittorrent/torrenthandle.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -597,25 +597,6 @@ QStringList TorrentHandle::absoluteFilePathsUnwanted() const
return res;
}

QPair<int, int> TorrentHandle::fileExtremityPieces(int index) const
{
if (!hasMetadata()) return qMakePair(-1, -1);

const int numPieces = piecesCount();
const qlonglong pieceSize = pieceLength();

// Determine the first and last piece of the file
int firstPiece = floor((m_torrentInfo.fileOffset(index) + 1) / (float) pieceSize);
Q_ASSERT((firstPiece >= 0) && (firstPiece < numPieces));

int numPiecesInFile = ceil(fileSize(index) / (float) pieceSize);
int lastPiece = firstPiece + numPiecesInFile - 1;
Q_ASSERT((lastPiece >= 0) && (lastPiece < numPieces));

Q_UNUSED(numPieces)
return qMakePair(firstPiece, lastPiece);
}

QVector<int> TorrentHandle::filePriorities() const
{
std::vector<int> fp;
Expand Down Expand Up @@ -733,13 +714,13 @@ bool TorrentHandle::hasFirstLastPiecePriority() const
std::vector<int> fp;
SAFE_GET(fp, file_priorities);

QPair<int, int> extremities;
TorrentInfo::PieceRange extremities;
bool found = false;
int count = static_cast<int>(fp.size());
for (int i = 0; i < count; ++i) {
const QString ext = Utils::Fs::fileExtension(filePath(i));
if (Utils::Misc::isPreviewable(ext) && (fp[i] > 0)) {
extremities = fileExtremityPieces(i);
extremities = info().filePieces(i);
found = true;
break;
}
Expand All @@ -749,8 +730,8 @@ bool TorrentHandle::hasFirstLastPiecePriority() const

int first = 0;
int last = 0;
SAFE_GET(first, piece_priority, extremities.first);
SAFE_GET(last, piece_priority, extremities.second);
SAFE_GET(first, piece_priority, extremities.first());
SAFE_GET(last, piece_priority, extremities.last());

return ((first == 7) && (last == 7));
}
Expand Down Expand Up @@ -1245,13 +1226,13 @@ void TorrentHandle::setFirstLastPiecePriority(bool b)
// Determine the priority to set
int prio = b ? 7 : fp[index];

QPair<int, int> extremities = fileExtremityPieces(index);
TorrentInfo::PieceRange extremities = info().filePieces(index);

// worst case: AVI index = 1% of total file size (at the end of the file)
int nNumPieces = ceil(fileSize(index) * 0.01 / pieceLength());
for (int i = 0; i < nNumPieces; ++i) {
pp[extremities.first + i] = prio;
pp[extremities.second - i] = prio;
pp[extremities.first() + i] = prio;
pp[extremities.last() - i] = prio;
}
}
}
Expand Down
1 change: 0 additions & 1 deletion src/base/bittorrent/torrenthandle.h
Original file line number Diff line number Diff line change
Expand Up @@ -247,7 +247,6 @@ namespace BitTorrent
qlonglong fileSize(int index) const;
QStringList absoluteFilePaths() const;
QStringList absoluteFilePathsUnwanted() const;
QPair<int, int> fileExtremityPieces(int index) const;
QVector<int> filePriorities() const;

TorrentInfo info() const;
Expand Down
78 changes: 70 additions & 8 deletions src/base/bittorrent/torrentinfo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
* exception statement from your version.
*/

#include <QDebug>
#include <QString>
#include <QList>
#include <QUrl>
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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;
}

Expand Down Expand Up @@ -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;
Expand Down
13 changes: 13 additions & 0 deletions src/base/bittorrent/torrentinfo.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Copy link
Member

@sledgehammer999 sledgehammer999 May 30, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Forward declaring indexrange the same way, doesn't work?

Copy link
Contributor Author

@zeule zeule May 30, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It works, of course. Decided that the file is so tiny that such optimisation is not significant, while, naturally, this way it is more easy to use this header.


namespace BitTorrent
{
Expand Down Expand Up @@ -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;
Expand All @@ -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;
};
}
Expand Down
130 changes: 130 additions & 0 deletions src/base/indexrange.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
/*
* Bittorrent Client using Qt and libtorrent.
* Copyright (C) 2016 Eugene Shalygin
*
* 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.
*
* In addition, as a special exception, the copyright holders give permission to
* link this program with the OpenSSL project's "OpenSSL" library (or with
* modified versions of it that use the same license as the "OpenSSL" library),
* and distribute the linked executables. You must obey the GNU General Public
* License in all respects for all of the code used other than "OpenSSL". If you
* modify file(s), you may extend this exception to your version of the file(s),
* but you are not obligated to do so. If you do not wish to do so, delete this
* exception statement from your version.
*/

#ifndef QBT_INDEXRANGE_H
#define QBT_INDEXRANGE_H

#include <QtGlobal>

// Interval is defined via [first;last]
template <typename Index>
class IndexInterval
{
public:
using IndexType = Index;

IndexInterval(IndexType first, IndexType last)
: m_first {first}
, m_last {last}
{
Q_ASSERT(first <= last);
}

IndexType first() const
{
return m_first;
}

IndexType last() const
{
return m_last;
}

private:
IndexType m_first;
IndexType m_last;
};

template <typename T>
inline IndexInterval<T> makeInterval(T first, T last)
{
return {first, last};
}

// range is defined via first index and size
template <typename Index, typename IndexDiff = Index>
class IndexRange
{
public:
using IndexType = Index;
using IndexDiffType = IndexDiff;

constexpr IndexRange()
: m_first {0}
, m_size {0}
{
}

constexpr IndexRange(IndexType first, IndexDiffType size)
: m_first {first}
, m_size {size}
{
}

constexpr IndexRange(const IndexInterval<IndexType> &interval)
: m_first {interval.first()}
, m_size {interval.last() - interval.first() + 1}
{
}

constexpr IndexType begin() const
{
return m_first;
}

constexpr IndexType end() const
{
return m_first + m_size;
}

constexpr IndexDiffType size() const
{
return m_size;
}

constexpr IndexType first() const
{
return m_first;
}

constexpr IndexType last() const
{
return m_first + m_size - 1;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Question: since begin() is the same as first() shouldn't end() be the same as last()?
I am under the impression you offer those for compatibility, right?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You are right, this id for compatibility, and as such, end() must point to one after the last element.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I suppose you mean last() and end() are both correct as they are now, right?

Copy link
Contributor Author

@zeule zeule Jun 2, 2016 via email

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

}

constexpr bool isEmpty() const
{
return m_size == 0;
}

private:
IndexType m_first;
IndexDiffType m_size;
};

#endif // QBT_INDEXRANGE_H
Loading