Don't stuck loading on mismatching info-hashes in resume data
[qBittorrent.git] / src / gui / properties / downloadedpiecesbar.cpp
blob486d761d4e65b5686f6ddf17c071b2363179df54
1 /*
2 * Bittorrent Client using Qt and libtorrent.
3 * Copyright (C) 2006 Christophe Dumez <chris@qbittorrent.org>
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License
7 * as published by the Free Software Foundation; either version 2
8 * of the License, or (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
19 * In addition, as a special exception, the copyright holders give permission to
20 * link this program with the OpenSSL project's "OpenSSL" library (or with
21 * modified versions of it that use the same license as the "OpenSSL" library),
22 * and distribute the linked executables. You must obey the GNU General Public
23 * License in all respects for all of the code used other than "OpenSSL". If you
24 * modify file(s), you may extend this exception to your version of the file(s),
25 * but you are not obligated to do so. If you do not wish to do so, delete this
26 * exception statement from your version.
29 #include "downloadedpiecesbar.h"
31 #include <algorithm>
32 #include <cmath>
34 #include <QDebug>
35 #include <QVector>
37 #include "base/global.h"
39 namespace
41 QColor dlPieceColor(const QColor &pieceColor)
43 const QColor green {Qt::green};
44 return QColor::fromHsl(green.hslHue(), pieceColor.hslSaturation(), pieceColor.lightness());
48 DownloadedPiecesBar::DownloadedPiecesBar(QWidget *parent)
49 : base {parent}
50 , m_dlPieceColor {dlPieceColor(pieceColor())}
54 QVector<float> DownloadedPiecesBar::bitfieldToFloatVector(const QBitArray &vecin, int reqSize)
56 QVector<float> result(reqSize, 0.0);
57 if (vecin.isEmpty()) return result;
59 const float ratio = vecin.size() / static_cast<float>(reqSize);
61 // simple linear transformation algorithm
62 // for example:
63 // image.x(0) = pieces.x(0.0 >= x < 1.7)
64 // image.x(1) = pieces.x(1.7 >= x < 3.4)
66 for (int x = 0; x < reqSize; ++x)
68 // R - real
69 const float fromR = x * ratio;
70 const float toR = (x + 1) * ratio;
72 // C - integer
73 int fromC = fromR; // std::floor not needed
74 int toC = std::ceil(toR);
75 if (toC > vecin.size())
76 --toC;
78 // position in pieces table
79 int x2 = fromC;
81 // little speed up for really big pieces table, 10K+ size
82 const int toCMinusOne = toC - 1;
84 // value in returned vector
85 float value = 0;
87 // case when calculated range is (15.2 >= x < 15.7)
88 if (x2 == toCMinusOne)
90 if (vecin[x2])
91 value += ratio;
92 ++x2;
94 // case when (15.2 >= x < 17.8)
95 else
97 // subcase (15.2 >= x < 16)
98 if (x2 != fromR)
100 if (vecin[x2])
101 value += 1.0 - (fromR - fromC);
102 ++x2;
105 // subcase (16 >= x < 17)
106 for (; x2 < toCMinusOne; ++x2)
107 if (vecin[x2])
108 value += 1.0;
110 // subcase (17 >= x < 17.8)
111 if (x2 == toCMinusOne)
113 if (vecin[x2])
114 value += 1.0 - (toC - toR);
115 ++x2;
119 // normalization <0, 1>
120 value /= ratio;
122 // float precision sometimes gives > 1, because it's not possible to store irrational numbers
123 value = std::min(value, 1.0f);
125 result[x] = value;
128 return result;
131 bool DownloadedPiecesBar::updateImage(QImage &image)
133 // qDebug() << "updateImage";
134 QImage image2(width() - 2 * borderWidth, 1, QImage::Format_RGB888);
135 if (image2.isNull())
137 qDebug() << "QImage image2() allocation failed, width():" << width();
138 return false;
141 if (m_pieces.isEmpty())
143 image2.fill(backgroundColor());
144 image = image2;
145 return true;
148 QVector<float> scaledPieces = bitfieldToFloatVector(m_pieces, image2.width());
149 QVector<float> scaledPiecesDl = bitfieldToFloatVector(m_downloadedPieces, image2.width());
151 // filling image
152 for (int x = 0; x < scaledPieces.size(); ++x)
154 float piecesToValue = scaledPieces.at(x);
155 float piecesToValueDl = scaledPiecesDl.at(x);
156 if (piecesToValueDl != 0)
158 float fillRatio = piecesToValue + piecesToValueDl;
159 float ratio = piecesToValueDl / fillRatio;
161 QRgb mixedColor = mixTwoColors(pieceColor().rgb(), m_dlPieceColor.rgb(), ratio);
162 mixedColor = mixTwoColors(backgroundColor().rgb(), mixedColor, fillRatio);
164 image2.setPixel(x, 0, mixedColor);
166 else
168 image2.setPixel(x, 0, pieceColors()[piecesToValue * 255]);
171 image = image2;
172 return true;
175 void DownloadedPiecesBar::setProgress(const QBitArray &pieces, const QBitArray &downloadedPieces)
177 m_pieces = pieces;
178 m_downloadedPieces = downloadedPieces;
180 requestImageUpdate();
183 void DownloadedPiecesBar::clear()
185 m_pieces.clear();
186 m_downloadedPieces.clear();
187 base::clear();
190 QString DownloadedPiecesBar::simpleToolTipText() const
192 const QString borderColor = colorBoxBorderColor().name();
193 const QString rowHTML = u"<tr><td width=20 bgcolor='%1' style='border: 1px solid \"%2\";'></td><td>%3</td></tr>"_s;
194 return u"<table cellspacing=4>"
195 + rowHTML.arg(backgroundColor().name(), borderColor, tr("Missing pieces"))
196 + rowHTML.arg(m_dlPieceColor.name(), borderColor, tr("Partial pieces"))
197 + rowHTML.arg(pieceColor().name(), borderColor, tr("Completed pieces"))
198 + u"</table>";