Enable customizing the save statistics time interval
[qBittorrent.git] / src / gui / properties / downloadedpiecesbar.cpp
blob0f1ec8cea3af18ad82fe5fd4397a2c690625ab33
1 /*
2 * Bittorrent Client using Qt and libtorrent.
3 * Copyright (C) 2024 Vladimir Golovnev <glassez@yandex.ru>
4 * Copyright (C) 2006 Christophe Dumez <chris@qbittorrent.org>
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version 2
9 * of the License, or (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20 * In addition, as a special exception, the copyright holders give permission to
21 * link this program with the OpenSSL project's "OpenSSL" library (or with
22 * modified versions of it that use the same license as the "OpenSSL" library),
23 * and distribute the linked executables. You must obey the GNU General Public
24 * License in all respects for all of the code used other than "OpenSSL". If you
25 * modify file(s), you may extend this exception to your version of the file(s),
26 * but you are not obligated to do so. If you do not wish to do so, delete this
27 * exception statement from your version.
30 #include "downloadedpiecesbar.h"
32 #include <algorithm>
33 #include <cmath>
35 #include <QDebug>
36 #include <QList>
38 #include "base/global.h"
40 namespace
42 QColor dlPieceColor(const QColor &pieceColor)
44 const QColor green {Qt::green};
45 return QColor::fromHsl(green.hslHue(), pieceColor.hslSaturation(), pieceColor.lightness());
49 DownloadedPiecesBar::DownloadedPiecesBar(QWidget *parent)
50 : base(parent)
52 updateColorsImpl();
55 QList<float> DownloadedPiecesBar::bitfieldToFloatVector(const QBitArray &vecin, int reqSize)
57 QList<float> result(reqSize, 0.0);
58 if (vecin.isEmpty()) return result;
60 const float ratio = vecin.size() / static_cast<float>(reqSize);
62 // simple linear transformation algorithm
63 // for example:
64 // image.x(0) = pieces.x(0.0 >= x < 1.7)
65 // image.x(1) = pieces.x(1.7 >= x < 3.4)
67 for (int x = 0; x < reqSize; ++x)
69 // R - real
70 const float fromR = x * ratio;
71 const float toR = (x + 1) * ratio;
73 // C - integer
74 int fromC = fromR; // std::floor not needed
75 int toC = std::ceil(toR);
76 if (toC > vecin.size())
77 --toC;
79 // position in pieces table
80 int x2 = fromC;
82 // little speed up for really big pieces table, 10K+ size
83 const int toCMinusOne = toC - 1;
85 // value in returned vector
86 float value = 0;
88 // case when calculated range is (15.2 >= x < 15.7)
89 if (x2 == toCMinusOne)
91 if (vecin[x2])
92 value += ratio;
93 ++x2;
95 // case when (15.2 >= x < 17.8)
96 else
98 // subcase (15.2 >= x < 16)
99 if (x2 != fromR)
101 if (vecin[x2])
102 value += 1.0 - (fromR - fromC);
103 ++x2;
106 // subcase (16 >= x < 17)
107 for (; x2 < toCMinusOne; ++x2)
108 if (vecin[x2])
109 value += 1.0;
111 // subcase (17 >= x < 17.8)
112 if (x2 == toCMinusOne)
114 if (vecin[x2])
115 value += 1.0 - (toC - toR);
116 ++x2;
120 // normalization <0, 1>
121 value /= ratio;
123 // float precision sometimes gives > 1, because it's not possible to store irrational numbers
124 value = std::min(value, 1.0f);
126 result[x] = value;
129 return result;
132 QImage DownloadedPiecesBar::renderImage()
134 // qDebug() << "updateImage";
135 QImage image {width() - 2 * borderWidth, 1, QImage::Format_RGB888};
136 if (image.isNull())
138 qDebug() << "QImage allocation failed, width():" << width();
139 return image;
142 if (m_pieces.isEmpty())
144 image.fill(backgroundColor());
145 return image;
148 QList<float> scaledPieces = bitfieldToFloatVector(m_pieces, image.width());
149 QList<float> scaledPiecesDl = bitfieldToFloatVector(m_downloadedPieces, image.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 image.setPixel(x, 0, mixedColor);
166 else
168 image.setPixel(x, 0, pieceColors()[piecesToValue * 255]);
172 return image;
175 void DownloadedPiecesBar::setProgress(const QBitArray &pieces, const QBitArray &downloadedPieces)
177 m_pieces = pieces;
178 m_downloadedPieces = downloadedPieces;
180 redraw();
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>";
202 void DownloadedPiecesBar::updateColors()
204 PiecesBar::updateColors();
205 updateColorsImpl();
208 void DownloadedPiecesBar::updateColorsImpl()
210 m_dlPieceColor = dlPieceColor(pieceColor());