The attached patch fixes the issue here. I will release a v2.0.5 just for
this fix (as it is critical) today, so no need to patch your package.

On Thu, Dec 31, 2009 at 4:52 PM, Chris <ch...@qbittorrent.org> wrote:

> No need to test the patch, it does not fix the issue. I can reproduce it
> now thanks to a torrent that a user sent me. The crash occurs when
> displaying the main properties panel (especially pieces
> downloaded/availability bars) for big torrents (e.g. 8GB crashes here).
>
> This causes a crash in Qt when trying to allocate a pixmap with 1px width
> per piece (35762 pieces in my torrent). I will try to find a solution soon
> (probably scale down the information before creating the pixmap).
>
> On Thu, Dec 31, 2009 at 4:09 PM, Chris <ch...@qbittorrent.org> wrote:
>
>> Could anybody try this patch and tell me if it fixes the issue (I cannot
>> reproduce myself but I may have found a possible cause for this)?
>>
>>
>> On Thu, Dec 31, 2009 at 3:49 PM, Chris <ch...@qbittorrent.org> wrote:
>>
>>> The backtrace looks the same as in :
>>> https://bugs.launchpad.net/debian/+source/qbittorrent/+bug/501058
>>>
>>>
>>> On Thu, Dec 31, 2009 at 3:27 PM, Chris <ch...@qbittorrent.org> wrote:
>>>
>>>> It may also be useful the install libqt4-dbg (and get another backtrace)
>>>> since the error seems to be in Qt4 (when drawing the pieces downloaded bar
>>>> in the main properties panel).
>>>>
>>>> Best regards,
>>>> Chris.
>>>>
>>>>
>>>> On Thu, Dec 31, 2009 at 3:21 PM, Chris <ch...@qbittorrent.org> wrote:
>>>>
>>>>> I may have an idea. Does it still crash when the lower properties panel
>>>>> is hidden? Click on the button corresponding to the currently displayed 
>>>>> tab
>>>>> to hide it.
>>>>> When hidden, qBittorrent no longer refreshes the panel information and
>>>>> the bug might be in that code.
>>>>>
>>>>
>>>>
>>>
>>
>
Index: src/pieceavailabilitybar.h
===================================================================
--- src/pieceavailabilitybar.h	(revision 3245)
+++ src/pieceavailabilitybar.h	(revision 3248)
@@ -36,6 +36,7 @@
 #include <QPixmap>
 #include <QColor>
 #include <numeric>
+#include <math.h>
 
 #define BAR_HEIGHT 18
 
@@ -54,20 +55,43 @@
     double average = 0;
     if(avail.empty()) {
       // Empty bar
-      pixmap = QPixmap(1, 1);
-      QPainter painter(&pixmap);
-      painter.setPen(Qt::white);
-      painter.drawPoint(0,0);
+      QPixmap pix = QPixmap(1, 1);
+      pix.fill();
+      pixmap = pix;
     } else {
       // Look for maximum value
-      average = std::accumulate(avail.begin(), avail.end(), 0)/(double)avail.size();
-      uint nb_pieces = avail.size();
-      pixmap = QPixmap(nb_pieces, 1);
-      QPainter painter(&pixmap);
-      std::vector<int>::iterator it;
-      for(uint i=0; i < nb_pieces; ++i) {
-        painter.setPen(getPieceColor(avail[i], average));
-        painter.drawPoint(i,0);
+      int nb_pieces = avail.size();
+      average = std::accumulate(avail.begin(), avail.end(), 0)/(double)nb_pieces;
+      // Reduce the number of pieces before creating the pixmap
+      // otherwise it can crash when there are too many pieces
+      if(nb_pieces > width()) {
+        int ratio = floor(nb_pieces/(double)width());
+        std::vector<int> scaled_avail;
+        for(int i=0; i<nb_pieces; i+= ratio) {
+          int j = i;
+          int sum = avail[i];
+          for(j=i+1; j<qMin(i+ratio, nb_pieces); ++j) {
+            sum += avail[j];
+          }
+          scaled_avail.push_back(sum/(qMin(ratio, nb_pieces-i)));
+        }
+        QPixmap pix = QPixmap(scaled_avail.size(), 1);
+        pix.fill();
+        QPainter painter(&pix);
+        for(qulonglong i=0; i < scaled_avail.size(); ++i) {
+          painter.setPen(getPieceColor(scaled_avail[i], average));
+          painter.drawPoint(i,0);
+        }
+        pixmap = pix;
+      } else {
+        QPixmap pix = QPixmap(nb_pieces, 1);
+        pix.fill();
+        QPainter painter(&pix);
+        for(int i=0; i < nb_pieces; ++i) {
+          painter.setPen(getPieceColor(avail[i], average));
+          painter.drawPoint(i,0);
+        }
+        pixmap = pix;
       }
     }
     update();
Index: src/downloadedpiecesbar.h
===================================================================
--- src/downloadedpiecesbar.h	(revision 3245)
+++ src/downloadedpiecesbar.h	(revision 3248)
@@ -36,6 +36,7 @@
 #include <QList>
 #include <QPixmap>
 #include <libtorrent/bitfield.hpp>
+#include <math.h>
 
 using namespace libtorrent;
 #define BAR_HEIGHT 18
@@ -55,19 +56,46 @@
   void setProgress(bitfield pieces) {
     if(pieces.empty()) {
       // Empty bar
-      pixmap = QPixmap(1, 1);
-      QPainter painter(&pixmap);
-      painter.setPen(Qt::white);
-      painter.drawPoint(0,0);
+      QPixmap pix = QPixmap(1, 1);
+      pix.fill();
+      pixmap = pix;
     } else {
-      pixmap = QPixmap(pieces.size(), 1);
-      QPainter painter(&pixmap);
-      for(uint i=0; i<pieces.size(); ++i) {
-        if(pieces[i])
-          painter.setPen(Qt::blue);
-        else
-          painter.setPen(Qt::white);
-        painter.drawPoint(i,0);
+      int nb_pieces = pieces.size();
+      // Reduce the number of pieces before creating the pixmap
+      // otherwise it can crash when there are too many pieces
+      if(nb_pieces > width()) {
+        int ratio = floor(nb_pieces/(double)width());
+        QVector<bool> scaled_pieces;
+        for(int i=0; i<nb_pieces; i+= ratio) {
+          bool have = true;
+          for(int j=i; j<qMin(i+ratio, nb_pieces); ++j) {
+            if(!pieces[i]) { have = false; break; }
+          }
+          scaled_pieces << have;
+        }
+        QPixmap pix = QPixmap(scaled_pieces.size(), 1);
+        pix.fill();
+        QPainter painter(&pix);
+        for(int i=0; i<scaled_pieces.size(); ++i) {
+          if(scaled_pieces[i])
+            painter.setPen(Qt::blue);
+          else
+            painter.setPen(Qt::white);
+          painter.drawPoint(i,0);
+        }
+        pixmap = pix;
+      } else {
+        QPixmap pix = QPixmap(pieces.size(), 1);
+        pix.fill();
+        QPainter painter(&pix);
+        for(uint i=0; i<pieces.size(); ++i) {
+          if(pieces[i])
+            painter.setPen(Qt::blue);
+          else
+            painter.setPen(Qt::white);
+          painter.drawPoint(i,0);
+        }
+        pixmap = pix;
       }
     }
     update();

Reply via email to