Ticket #378: piecesbar_gtk_js.patch

File piecesbar_gtk_js.patch, 35.1 KB (added by James_Kern, 14 years ago)
  • deluge/core/torrent.py

    diff --git a/deluge/core/torrent.py b/deluge/core/torrent.py
    index 74c8885..444fc82 100644
    a b def get_queue_position(self): 
    497497        """Returns the torrents queue position""" 
    498498        return self.handle.queue_position() 
    499499 
     500    def get_pieces(self):  
     501        if not self.handle.has_metadata():  
     502            return None  
     503        else: 
     504            return [1 if piece else 0 for piece in self.handle.status().pieces] 
     505 
    500506    def get_file_progress(self): 
    501507        """Returns the file progress as a list of floats.. 0.0 -> 1.0""" 
    502508        if not self.handle.has_metadata(): 
    def ti_piece_length(): 
    690696            "num_pieces": ti_num_pieces, 
    691697            "peers": self.get_peers, 
    692698            "piece_length": ti_piece_length, 
     699            "pieces": self.get_pieces, 
    693700            "private": ti_priv, 
    694701            "queue": self.handle.queue_position, 
    695702            "ratio": self.get_ratio, 
  • deluge/ui/gtkui/glade/main_window.glade

    diff --git a/deluge/ui/gtkui/glade/main_window.glade b/deluge/ui/gtkui/glade/main_window.glade
    index c3fd1f6..4f80493 100644
    a b  
    676676                        <property name="orientation">vertical</property> 
    677677                        <property name="spacing">5</property> 
    678678                        <child> 
    679                           <widget class="GtkProgressBar" id="progressbar"> 
     679                          <widget class="GtkVBox" id="vbox2"> 
    680680                            <property name="visible">True</property> 
    681                             <property name="show_text">True</property> 
    682                             <property name="pulse_step">0.10000000149</property> 
     681                            <child> 
     682                              <widget class="GtkLabel" id="label23"> 
     683                                <property name="visible">True</property> 
     684                                <property name="xalign">0</property> 
     685                                <property name="label" translatable="yes">&lt;b&gt;Completed Pieces:&lt;/b&gt;</property> 
     686                                <property name="use_markup">True</property> 
     687                              </widget> 
     688                              <packing> 
     689                                <property name="expand">False</property> 
     690                                <property name="position">0</property> 
     691                              </packing> 
     692                            </child> 
     693                            <child> 
     694                              <widget class="GtkAlignment" id="alignment1"> 
     695                                <property name="height_request">35</property> 
     696                                <property name="visible">True</property> 
     697                                <property name="top_padding">3</property> 
     698                                <property name="left_padding">12</property> 
     699                                <child> 
     700                                  <placeholder/> 
     701                                </child> 
     702                              </widget> 
     703                              <packing> 
     704                                <property name="position">1</property> 
     705                              </packing> 
     706                            </child> 
    683707                          </widget> 
    684708                          <packing> 
    685709                            <property name="expand">False</property> 
    686                             <property name="fill">False</property> 
    687710                            <property name="position">0</property> 
    688711                          </packing> 
    689712                        </child> 
  • deluge/ui/gtkui/status_tab.py

    diff --git a/deluge/ui/gtkui/status_tab.py b/deluge/ui/gtkui/status_tab.py
    index 6feed8e..010280b 100644
    a b def __init__(self): 
    7474        self._child_widget = glade.get_widget("status_tab") 
    7575        self._tab_label = glade.get_widget("status_tab_label") 
    7676 
     77        self.pieces_bar = PiecesBar() 
     78        glade.get_widget("alignment1").add(self.pieces_bar) 
     79 
    7780        self.label_widgets = [ 
    7881            (glade.get_widget("summary_pieces"), fpeer_size_second, ("num_pieces", "piece_length")), 
    7982            (glade.get_widget("summary_availability"), fratio, ("distributed_copies",)), 
    def __init__(self): 
    9194            (glade.get_widget("summary_seed_time"), deluge.common.ftime, ("seeding_time",)), 
    9295            (glade.get_widget("summary_seed_rank"), str, ("seed_rank",)), 
    9396            (glade.get_widget("summary_auto_managed"), str, ("is_auto_managed",)), 
    94             (glade.get_widget("progressbar"), fpcnt, ("progress",)), 
    95             (glade.get_widget("summary_date_added"), deluge.common.fdate, ("time_added",)) 
     97            (glade.get_widget("summary_date_added"), deluge.common.fdate, ("time_added",)), 
     98            (self.pieces_bar, None, ("pieces",)), 
    9699        ] 
    97100 
    98101    def update(self): 
    def update(self): 
    107110            return 
    108111 
    109112        # Get the torrent status 
    110         status_keys = ["progress", "num_pieces", "piece_length", 
     113        status_keys = ["pieces", "num_pieces", "piece_length", 
    111114            "distributed_copies", "all_time_download", "total_payload_download", 
    112115            "total_uploaded", "total_payload_upload", "download_payload_rate", 
    113116            "upload_payload_rate", "num_peers", "num_seeds", "total_peers", 
    def _on_get_torrent_status(self, status): 
    142145            if widget[0].get_text() != txt: 
    143146                widget[0].set_text(txt) 
    144147 
    145         # Do the progress bar because it's a special case (not a label) 
    146         w = component.get("MainWindow").main_glade.get_widget("progressbar") 
    147         fraction = status["progress"] / 100 
    148         if w.get_fraction() != fraction: 
    149             w.set_fraction(fraction) 
     148        # If this is true the torrent should be completely downloaded so  
     149        # display a full bar  
     150        if int(status["num_pieces"]) != len(status["pieces"]):  
     151            self.pieces_bar.pieces = [True]  
     152            self.pieces_bar.update()  
     153        # Don't update if the pieces haven't changed      
     154        elif status["pieces"] != self.pieces_bar.pieces:  
     155            self.pieces_bar.pieces = status["pieces"]  
     156            self.pieces_bar.update()  
    150157 
    151158    def clear(self): 
    152159        for widget in self.label_widgets: 
    153160            widget[0].set_text("") 
    154161 
    155         component.get("MainWindow").main_glade.get_widget("progressbar").set_fraction(0.0) 
     162        self.pieces_bar.clear() 
     163 
     164class PiecesBar(gtk.DrawingArea): 
     165    def __init__(self): 
     166        gtk.DrawingArea.__init__(self) 
     167        self.width = 0 
     168        self.height = 0 
     169        self.pieces = [] 
     170         
     171        self.connect('size-allocate', self.on_size_allocate) 
     172        self.connect('expose-event', self.update) 
     173        self.connect('realize', self.on_realize) 
     174 
     175        self.show() 
     176 
     177    def on_realize(self, widget): 
     178        map = widget.get_colormap() 
     179        done_color = map.alloc_color("#325891") 
     180        wait_color = map.alloc_color("#a8a8a9") 
     181        outline_color = map.alloc_color("#888888") 
     182         
     183        self.gc_done = widget.window.new_gc(foreground=done_color) 
     184        self.gc_wait = widget.window.new_gc(foreground=wait_color) 
     185        self.gc_outline = widget.window.new_gc(foreground=outline_color) 
     186     
     187    def on_size_allocate(self, widget, size): 
     188        self.width = size.width 
     189        self.height = size.height 
     190         
     191    def update(self, widget=None, event=None): 
     192        num_pieces = len(self.pieces) 
     193         
     194        if num_pieces < 1: 
     195            self.clear() 
     196            return None 
     197         
     198        self.window.draw_rectangle(self.gc_outline, False, 0, 0, 
     199                                   self.width - 1, self.height - 1) 
     200         
     201        width = self.width - 2 
     202        pieces = self.collapse_pieces(width, num_pieces) 
     203        piece_size = width / len(pieces) 
     204        padding = (width % len(pieces)) 
     205        start_pos = 1 
     206         
     207        for piece in pieces: 
     208            if padding > 0: 
     209                this_piece_size = piece_size + 1 
     210                padding -= 1 
     211            else: 
     212                this_piece_size = piece_size 
     213         
     214            self.draw_piece(piece, start_pos, 1, this_piece_size,  
     215                            self.height - 2) 
     216            start_pos += this_piece_size 
     217     
     218    def collapse_pieces(self, width, num_pieces): 
     219        group_size = num_pieces / width 
     220         
     221        padding = num_pieces % width 
     222        i = 0 
     223        pieces = [] 
     224         
     225        while i < num_pieces: 
     226            if padding > 0: 
     227                this_group_size = group_size + 1 
     228                padding -= 1 
     229            else: 
     230                this_group_size = group_size 
     231         
     232            pieces.append(1 if all(self.pieces[i:i+this_group_size]) else 0) 
     233            i += this_group_size 
     234        return pieces 
     235     
     236    def draw_piece(self, piece, start_x, start_y, width, height): 
     237        if piece: 
     238            self.window.draw_rectangle(self.gc_done, True, start_x, start_y,  
     239                                       width, height) 
     240        else: 
     241            self.window.draw_rectangle(self.gc_wait, True, start_x, start_y,  
     242                                       width, height) 
     243     
     244    def clear(self): 
     245        self.pieces = [0] 
     246        self.update() 
     247     
     248    def get_text(self): 
     249        return "" 
     250     
     251    def set_text(self, text): 
     252        pass 
  • deluge/ui/web/css/deluge.css

    diff --git a/deluge/ui/web/css/deluge.css b/deluge/ui/web/css/deluge.css
    index c1da56f..a74e351 100644
    a b dl.singleline dd { 
    288288        /*background-image: url(../icons/mixed.png);*/ 
    289289} 
    290290 
     291.x-piecesbar { 
     292    border: 1px solid #888888; 
     293    margin: 5px; 
     294    margin-bottom: 0px; 
     295    background: #ffffff; 
     296    height: 20px; 
     297} 
     298 
     299.x-piecesbar-done { 
     300    background: #325891; 
     301    height: 20px; 
     302    float: left; 
     303} 
     304 
     305.x-piecesbar-blank { 
     306    background: #a8a8a9; 
     307    height: 20px; 
     308    float: left; 
     309} 
     310 
    291311/** 
    292312 * Deluge Default Icon Set 
    293313 * n.b. this needs to be forked out at some point 
  • deluge/ui/web/js/deluge-all-debug.js

    diff --git a/deluge/ui/web/js/deluge-all-debug.js b/deluge/ui/web/js/deluge-all-debug.js
    index d1c8485..9f2c031 100644
    a b Ext.ns('Deluge.details'); 
    12621262 * @class Deluge.details.StatusTab 
    12631263 * @extends Ext.Panel 
    12641264 */ 
     1265 
    12651266Deluge.details.StatusTab = Ext.extend(Ext.Panel, { 
    12661267        title: _('Status'), 
    12671268        autoScroll: true, 
    Deluge.details.StatusTab = Ext.extend(Ext.Panel, { 
    12691270        onRender: function(ct, position) { 
    12701271                Deluge.details.StatusTab.superclass.onRender.call(this, ct, position); 
    12711272                 
    1272                 this.progressBar = this.add({ 
    1273                         xtype: 'progress', 
    1274                         cls: 'x-deluge-status-progressbar' 
    1275                 }); 
    1276                  
     1273                this.piecesBar = this.add({ 
     1274            xtype: "box", 
     1275            cls: "x-piecesbar", 
     1276            tpl: new Ext.Template("<div class=\"x-piecesbar-{0}\" style=\"width: {1}px;\"></div>"), 
     1277            compare_pieces: function(pieces) { 
     1278                if (!this.pieces || pieces.length != this.pieces.length) { 
     1279                    return false; 
     1280                } 
     1281                 
     1282                for (var i = 0; i < pieces.length; i++) { 
     1283                    if (pieces[i] != this.pieces[i]) { 
     1284                        return false; 
     1285                    } 
     1286                } 
     1287                return true; 
     1288            }, 
     1289             
     1290            collapse_pieces: function(width, pieces) { 
     1291                var group_size = pieces.length / width; 
     1292 
     1293                var padding = pieces.length % width; 
     1294                        var i = 0; 
     1295                        var new_pieces = [];  
     1296                var this_group_size; 
     1297                  
     1298                        while (i < pieces.length) {  
     1299                    this_group_size = group_size; 
     1300                            if (padding > 0) {  
     1301                                this_group_size = group_size + 1; 
     1302                                padding -= 1; 
     1303                    } 
     1304                     
     1305                    if (pieces.slice(i, i+this_group_size).indexOf(0) == -1) { 
     1306                        new_pieces.push(1); 
     1307                    } 
     1308                    else { 
     1309                        new_pieces.push(0); 
     1310                    } 
     1311                            i += this_group_size; 
     1312                } 
     1313                        return new_pieces; 
     1314            }, 
     1315             
     1316            update: function(pieces) { 
     1317                if (!this.compare_pieces(pieces) && typeof(pieces) != "number") { 
     1318                    this.pieces = pieces; 
     1319                     
     1320                    if (pieces.length > this.getWidth()) { 
     1321                        pieces = this.collapse_pieces(this.getWidth(), pieces); 
     1322                    } 
     1323                                     
     1324                    while (this.el.dom.hasChildNodes()) { 
     1325                        this.el.dom.removeChild(this.el.dom.lastChild); 
     1326                    } 
     1327                     
     1328                    var piece_size = Math.floor((this.getWidth() - 2) / pieces.length); 
     1329                    var padding = (this.getWidth() - 2) % pieces.length; 
     1330                    var this_size; 
     1331                     
     1332                    for (var i = 0; i < pieces.length; i++) { 
     1333                        this_size = piece_size; 
     1334 
     1335                        if (padding > 0) { 
     1336                            this_size = piece_size + 1; 
     1337                            padding -= 1; 
     1338                        } 
     1339 
     1340                        if (pieces[i] == 1) { 
     1341                            this.tpl.append(this.el, ["done", this_size]); 
     1342                        } 
     1343                        else { 
     1344                            this.tpl.append(this.el, ["blank", this_size]); 
     1345                        } 
     1346                    } 
     1347                } 
     1348            } 
     1349        }); 
     1350                
    12771351                this.status = this.add({ 
    12781352                        cls: 'x-deluge-status', 
    12791353                        id: 'deluge-details-status', 
    Deluge.details.StatusTab = Ext.extend(Ext.Panel, { 
    12961370        }, 
    12971371         
    12981372        clear: function() { 
    1299                 this.progressBar.updateProgress(0, ' '); 
     1373                this.piecesBar.update([0]); 
    13001374                for (var k in this.fields) { 
    13011375                        this.fields[k].innerHTML = ''; 
    13021376                } 
    Deluge.details.StatusTab = Ext.extend(Ext.Panel, { 
    13461420                for (var field in this.fields) { 
    13471421                        this.fields[field].innerHTML = data[field]; 
    13481422                } 
    1349                 var text = status.state + ' ' + status.progress.toFixed(2) + '%'; 
    1350                 this.progressBar.updateProgress(status.progress / 100.0, text); 
     1423         
     1424                if (parseInt(status.num_pieces) != status.pieces.length) { 
     1425            this.piecesBar.update([1]); 
     1426        } 
     1427        else { 
     1428            this.piecesBar.update(status.pieces); 
     1429        } 
    13511430        } 
    13521431}); 
    13531432/*! 
    Deluge.Keys = { 
    68786957    Status: [ 
    68796958        'total_done', 'total_payload_download', 'total_uploaded', 
    68806959        'total_payload_upload', 'next_announce', 'tracker_status', 'num_pieces', 
    6881         'piece_length', 'is_auto_managed', 'active_time', 'seeding_time', 
    6882         'seed_rank' 
     6960        'piece_length', 'pieces', 'is_auto_managed', 'active_time',  
     6961        'seeding_time', 'seed_rank' 
    68836962    ], 
    68846963     
    68856964    /** 
  • deluge/ui/web/js/deluge-all.js

    diff --git a/deluge/ui/web/js/deluge-all.js b/deluge/ui/web/js/deluge-all.js
    index 8cdee93..178c848 100644
    a b Deluge.details.OptionsTab=Ext.extend(Ext.form.FormPanel,{constructor:function(a) 
    253253 * this exception statement from your version. If you delete this exception 
    254254 * statement from all source files in the program, then also delete it here. 
    255255 */ 
    256 Ext.ns("Deluge.details");Deluge.details.StatusTab=Ext.extend(Ext.Panel,{title:_("Status"),autoScroll:true,onRender:function(b,a){Deluge.details.StatusTab.superclass.onRender.call(this,b,a);this.progressBar=this.add({xtype:"progress",cls:"x-deluge-status-progressbar"});this.status=this.add({cls:"x-deluge-status",id:"deluge-details-status",border:false,width:1000,listeners:{render:{fn:function(c){c.load({url:deluge.config.base+"render/tab_status.html",text:_("Loading")+"..."});c.getUpdater().on("update",this.onPanelUpdate,this)},scope:this}}})},clear:function(){this.progressBar.updateProgress(0," ");for(var a in this.fields){this.fields[a].innerHTML=""}},update:function(a){if(!this.fields){this.getFields()}deluge.client.web.get_torrent_status(a,Deluge.Keys.Status,{success:this.onRequestComplete,scope:this})},onPanelUpdate:function(b,a){this.fields={};Ext.each(Ext.query("dd",this.status.body.dom),function(c){this.fields[c.className]=c},this)},onRequestComplete:function(a){seeders=a.total_seeds>-1?a.num_seeds+" ("+a.total_seeds+")":a.num_seeds;peers=a.total_peers>-1?a.num_peers+" ("+a.total_peers+")":a.num_peers;var b={downloaded:fsize(a.total_done,true),uploaded:fsize(a.total_uploaded,true),share:(a.ratio==-1)?"&infin;":a.ratio.toFixed(3),announce:ftime(a.next_announce),tracker_status:a.tracker_status,downspeed:(a.download_payload_rate)?fspeed(a.download_payload_rate):"0.0 KiB/s",upspeed:(a.upload_payload_rate)?fspeed(a.upload_payload_rate):"0.0 KiB/s",eta:ftime(a.eta),pieces:a.num_pieces+" ("+fsize(a.piece_length)+")",seeders:seeders,peers:peers,avail:a.distributed_copies.toFixed(3),active_time:ftime(a.active_time),seeding_time:ftime(a.seeding_time),seed_rank:a.seed_rank,time_added:fdate(a.time_added)};b.auto_managed=_((a.is_auto_managed)?"True":"False");b.downloaded+=" ("+((a.total_payload_download)?fsize(a.total_payload_download):"0.0 KiB")+")";b.uploaded+=" ("+((a.total_payload_download)?fsize(a.total_payload_download):"0.0 KiB")+")";for(var c in this.fields){this.fields[c].innerHTML=b[c]}var d=a.state+" "+a.progress.toFixed(2)+"%";this.progressBar.updateProgress(a.progress/100,d)}}); 
     256Ext.ns("Deluge.details");Deluge.details.StatusTab=Ext.extend(Ext.Panel,{title:_("Status"),autoScroll:true,onRender:function(b,a){Deluge.details.StatusTab.superclass.onRender.call(this,b,a);this.piecesBar=this.add({xtype:"box",cls:"x-piecesbar",tpl:new Ext.Template('<div class="x-piecesbar-{0}" style="width: {1}px;"></div>'),compare_pieces:function(d){if(!this.pieces||d.length!=this.pieces.length){return false}for(var c=0;c<d.length;c++){if(d[c]!=this.pieces[c]){return false}}return true},collapse_pieces:function(e,f){var c=f.length/e;var h=f.length%e;var d=0;var j=[];var g;while(d<f.length){g=c;if(h>0){g=c+1;h-=1}if(f.slice(d,d+g).indexOf(0)==-1){j.push(1)}else{j.push(0)}d+=g}return j},update:function(e){if(!this.compare_pieces(e)&&typeof(e)!="number"){this.pieces=e;if(e.length>this.getWidth()){e=this.collapse_pieces(this.getWidth(),e)}while(this.el.dom.hasChildNodes()){this.el.dom.removeChild(this.el.dom.lastChild)}var g=Math.floor((this.getWidth()-2)/e.length);var f=(this.getWidth()-2)%e.length;var c;for(var d=0;d<e.length;d++){c=g;if(f>0){c=g+1;f-=1}if(e[d]==1){this.tpl.append(this.el,["done",c])}else{this.tpl.append(this.el,["blank",c])}}}}});this.status=this.add({cls:"x-deluge-status",id:"deluge-details-status",border:false,width:1000,listeners:{render:{fn:function(c){c.load({url:deluge.config.base+"render/tab_status.html",text:_("Loading")+"..."});c.getUpdater().on("update",this.onPanelUpdate,this)},scope:this}}})},clear:function(){this.piecesBar.update([0]);for(var a in this.fields){this.fields[a].innerHTML=""}},update:function(a){if(!this.fields){this.getFields()}deluge.client.web.get_torrent_status(a,Deluge.Keys.Status,{success:this.onRequestComplete,scope:this})},onPanelUpdate:function(b,a){this.fields={};Ext.each(Ext.query("dd",this.status.body.dom),function(c){this.fields[c.className]=c},this)},onRequestComplete:function(a){seeders=a.total_seeds>-1?a.num_seeds+" ("+a.total_seeds+")":a.num_seeds;peers=a.total_peers>-1?a.num_peers+" ("+a.total_peers+")":a.num_peers;var b={downloaded:fsize(a.total_done,true),uploaded:fsize(a.total_uploaded,true),share:(a.ratio==-1)?"&infin;":a.ratio.toFixed(3),announce:ftime(a.next_announce),tracker_status:a.tracker_status,downspeed:(a.download_payload_rate)?fspeed(a.download_payload_rate):"0.0 KiB/s",upspeed:(a.upload_payload_rate)?fspeed(a.upload_payload_rate):"0.0 KiB/s",eta:ftime(a.eta),pieces:a.num_pieces+" ("+fsize(a.piece_length)+")",seeders:seeders,peers:peers,avail:a.distributed_copies.toFixed(3),active_time:ftime(a.active_time),seeding_time:ftime(a.seeding_time),seed_rank:a.seed_rank,time_added:fdate(a.time_added)};b.auto_managed=_((a.is_auto_managed)?"True":"False");b.downloaded+=" ("+((a.total_payload_download)?fsize(a.total_payload_download):"0.0 KiB")+")";b.uploaded+=" ("+((a.total_payload_download)?fsize(a.total_payload_download):"0.0 KiB")+")";for(var c in this.fields){this.fields[c].innerHTML=b[c]}if(parseInt(a.num_pieces)!=a.pieces.length){this.piecesBar.update([1])}else{this.piecesBar.update(a.pieces)}}}); 
    257257/* 
    258258 * Deluge.add.Window.js 
    259259 *  
    Ext.ns("Deluge");Deluge.FilterPanel=Ext.extend(Ext.Panel,{border:false,show_zero 
    14051405 * this exception statement from your version. If you delete this exception 
    14061406 * statement from all source files in the program, then also delete it here. 
    14071407 */ 
    1408 Deluge.Keys={Grid:["queue","name","total_size","state","progress","num_seeds","total_seeds","num_peers","total_peers","download_payload_rate","upload_payload_rate","eta","ratio","distributed_copies","is_auto_managed","time_added","tracker_host","save_path"],Status:["total_done","total_payload_download","total_uploaded","total_payload_upload","next_announce","tracker_status","num_pieces","piece_length","is_auto_managed","active_time","seeding_time","seed_rank"],Files:["files","file_progress","file_priorities"],Peers:["peers"],Details:["name","save_path","total_size","num_files","tracker_status","tracker","comment"],Options:["max_download_speed","max_upload_speed","max_connections","max_upload_slots","is_auto_managed","stop_at_ratio","stop_ratio","remove_at_ratio","private","prioritize_first_last"]};Ext.each(Deluge.Keys.Grid,function(a){Deluge.Keys.Status.push(a)}); 
     1408Deluge.Keys={Grid:["queue","name","total_size","state","progress","num_seeds","total_seeds","num_peers","total_peers","download_payload_rate","upload_payload_rate","eta","ratio","distributed_copies","is_auto_managed","time_added","tracker_host","save_path"],Status:["total_done","total_payload_download","total_uploaded","total_payload_upload","next_announce","tracker_status","num_pieces","piece_length","pieces","is_auto_managed","active_time","seeding_time","seed_rank"],Files:["files","file_progress","file_priorities"],Peers:["peers"],Details:["name","save_path","total_size","num_files","tracker_status","tracker","comment"],Options:["max_download_speed","max_upload_speed","max_connections","max_upload_slots","is_auto_managed","stop_at_ratio","stop_ratio","remove_at_ratio","private","prioritize_first_last"]};Ext.each(Deluge.Keys.Grid,function(a){Deluge.Keys.Status.push(a)}); 
    14091409/* 
    14101410 * Deluge.LoginWindow.js 
    14111411 *  
    Deluge.Toolbar=Ext.extend(Ext.Toolbar,{constructor:function(a){a=Ext.apply({item 
    17891789 * this exception statement from your version. If you delete this exception 
    17901790 * statement from all source files in the program, then also delete it here. 
    17911791 */ 
    1792 deluge.ui={errorCount:0,filters:null,initialize:function(){deluge.add=new Deluge.add.AddWindow();deluge.details=new Deluge.details.DetailsPanel();deluge.connectionManager=new Deluge.ConnectionManager();deluge.editTrackers=new Deluge.EditTrackersWindow();deluge.login=new Deluge.LoginWindow();deluge.preferences=new Deluge.preferences.PreferencesWindow();deluge.sidebar=new Deluge.Sidebar();deluge.statusbar=new Deluge.Statusbar();this.MainPanel=new Ext.Panel({id:"mainPanel",iconCls:"x-deluge-main-panel",title:"Deluge",layout:"border",tbar:deluge.toolbar,items:[deluge.sidebar,deluge.details,deluge.torrents],bbar:deluge.statusbar});this.Viewport=new Ext.Viewport({layout:"fit",items:[this.MainPanel]});deluge.events.on("connect",this.onConnect,this);deluge.events.on("disconnect",this.onDisconnect,this);deluge.events.on("PluginDisabledEvent",this.onPluginDisabled,this);deluge.events.on("PluginEnabledEvent",this.onPluginEnabled,this);deluge.client=new Ext.ux.util.RpcClient({url:deluge.config.base+"json"});for(var a in Deluge.pluginStore){a=Deluge.createPlugin(a);a.enable();deluge.plugins[a.name]=a}Ext.QuickTips.init();deluge.client.on("connected",function(b){deluge.login.show()},this,{single:true});this.update=this.update.createDelegate(this);this.checkConnection=this.checkConnection.createDelegate(this);this.originalTitle=document.title},checkConnection:function(){deluge.client.web.connected({success:this.onConnectionSuccess,failure:this.onConnectionError,scope:this})},update:function(){var a=deluge.sidebar.getFilterStates();deluge.client.web.update_ui(Deluge.Keys.Grid,a,{success:this.onUpdate,failure:this.onUpdateError,scope:this});deluge.details.update()},onConnectionError:function(a){},onConnectionSuccess:function(a){deluge.statusbar.setStatus({iconCls:"x-deluge-statusbar icon-ok",text:_("Connection restored")});clearInterval(this.checking);if(!a){deluge.connectionManager.show()}},onUpdateError:function(a){if(this.errorCount==2){Ext.MessageBox.show({title:"Lost Connection",msg:"The connection to the webserver has been lost!",buttons:Ext.MessageBox.OK,icon:Ext.MessageBox.ERROR});deluge.events.fire("disconnect");deluge.statusbar.setStatus({text:"Lost connection to webserver"});this.checking=setInterval(this.checkConnection,2000)}this.errorCount++},onUpdate:function(a){if(!a.connected){deluge.connectionManager.disconnect(true);return}if(deluge.config.show_session_speed){document.title=this.originalTitle+" (Down: "+fspeed(a.stats.download_rate,true)+" Up: "+fspeed(a.stats.upload_rate,true)+")"}deluge.torrents.update(a.torrents);deluge.statusbar.update(a.stats);deluge.sidebar.update(a.filters);this.errorCount=0},onConnect:function(){if(!this.running){this.running=setInterval(this.update,2000);this.update()}deluge.client.web.get_plugins({success:this.onGotPlugins,scope:this})},onDisconnect:function(){this.stop()},onGotPlugins:function(a){Ext.each(a.enabled_plugins,function(b){if(deluge.plugins[b]){return}deluge.client.web.get_plugin_resources(b,{success:this.onGotPluginResources,scope:this})},this)},onPluginEnabled:function(a){if(deluge.plugins[a]){deluge.plugins[a].enable()}else{deluge.client.web.get_plugin_resources(a,{success:this.onGotPluginResources,scope:this})}},onGotPluginResources:function(b){var a=(Deluge.debug)?b.debug_scripts:b.scripts;Ext.each(a,function(c){Ext.ux.JSLoader({url:c,onLoad:this.onPluginLoaded,pluginName:b.name})},this)},onPluginDisabled:function(a){deluge.plugins[a].disable()},onPluginLoaded:function(a){if(!Deluge.hasPlugin(a.pluginName)){return}plugin=Deluge.createPlugin(a.pluginName);plugin.enable();deluge.plugins[plugin.name]=plugin},stop:function(){if(this.running){clearInterval(this.running);this.running=false;deluge.torrents.getStore().removeAll()}}};Ext.onReady(function(a){deluge.ui.initialize()}); 
    1793  No newline at end of file 
     1792deluge.ui={errorCount:0,filters:null,initialize:function(){deluge.add=new Deluge.add.AddWindow();deluge.details=new Deluge.details.DetailsPanel();deluge.connectionManager=new Deluge.ConnectionManager();deluge.editTrackers=new Deluge.EditTrackersWindow();deluge.login=new Deluge.LoginWindow();deluge.preferences=new Deluge.preferences.PreferencesWindow();deluge.sidebar=new Deluge.Sidebar();deluge.statusbar=new Deluge.Statusbar();this.MainPanel=new Ext.Panel({id:"mainPanel",iconCls:"x-deluge-main-panel",title:"Deluge",layout:"border",tbar:deluge.toolbar,items:[deluge.sidebar,deluge.details,deluge.torrents],bbar:deluge.statusbar});this.Viewport=new Ext.Viewport({layout:"fit",items:[this.MainPanel]});deluge.events.on("connect",this.onConnect,this);deluge.events.on("disconnect",this.onDisconnect,this);deluge.events.on("PluginDisabledEvent",this.onPluginDisabled,this);deluge.events.on("PluginEnabledEvent",this.onPluginEnabled,this);deluge.client=new Ext.ux.util.RpcClient({url:deluge.config.base+"json"});for(var a in Deluge.pluginStore){a=Deluge.createPlugin(a);a.enable();deluge.plugins[a.name]=a}Ext.QuickTips.init();deluge.client.on("connected",function(b){deluge.login.show()},this,{single:true});this.update=this.update.createDelegate(this);this.checkConnection=this.checkConnection.createDelegate(this);this.originalTitle=document.title},checkConnection:function(){deluge.client.web.connected({success:this.onConnectionSuccess,failure:this.onConnectionError,scope:this})},update:function(){var a=deluge.sidebar.getFilterStates();deluge.client.web.update_ui(Deluge.Keys.Grid,a,{success:this.onUpdate,failure:this.onUpdateError,scope:this});deluge.details.update()},onConnectionError:function(a){},onConnectionSuccess:function(a){deluge.statusbar.setStatus({iconCls:"x-deluge-statusbar icon-ok",text:_("Connection restored")});clearInterval(this.checking);if(!a){deluge.connectionManager.show()}},onUpdateError:function(a){if(this.errorCount==2){Ext.MessageBox.show({title:"Lost Connection",msg:"The connection to the webserver has been lost!",buttons:Ext.MessageBox.OK,icon:Ext.MessageBox.ERROR});deluge.events.fire("disconnect");deluge.statusbar.setStatus({text:"Lost connection to webserver"});this.checking=setInterval(this.checkConnection,2000)}this.errorCount++},onUpdate:function(a){if(!a.connected){deluge.connectionManager.disconnect(true);return}if(deluge.config.show_session_speed){document.title=this.originalTitle+" (Down: "+fspeed(a.stats.download_rate,true)+" Up: "+fspeed(a.stats.upload_rate,true)+")"}deluge.torrents.update(a.torrents);deluge.statusbar.update(a.stats);deluge.sidebar.update(a.filters);this.errorCount=0},onConnect:function(){if(!this.running){this.running=setInterval(this.update,2000);this.update()}deluge.client.web.get_plugins({success:this.onGotPlugins,scope:this})},onDisconnect:function(){this.stop()},onGotPlugins:function(a){Ext.each(a.enabled_plugins,function(b){if(deluge.plugins[b]){return}deluge.client.web.get_plugin_resources(b,{success:this.onGotPluginResources,scope:this})},this)},onPluginEnabled:function(a){if(deluge.plugins[a]){deluge.plugins[a].enable()}else{deluge.client.web.get_plugin_resources(a,{success:this.onGotPluginResources,scope:this})}},onGotPluginResources:function(b){var a=(Deluge.debug)?b.debug_scripts:b.scripts;Ext.each(a,function(c){Ext.ux.JSLoader({url:c,onLoad:this.onPluginLoaded,pluginName:b.name})},this)},onPluginDisabled:function(a){deluge.plugins[a].disable()},onPluginLoaded:function(a){if(!Deluge.hasPlugin(a.pluginName)){return}plugin=Deluge.createPlugin(a.pluginName);plugin.enable();deluge.plugins[plugin.name]=plugin},stop:function(){if(this.running){clearInterval(this.running);this.running=false;deluge.torrents.getStore().removeAll()}}};Ext.onReady(function(a){deluge.ui.initialize()}); 
  • deluge/ui/web/js/deluge-all/Keys.js

    diff --git a/deluge/ui/web/js/deluge-all/Keys.js b/deluge/ui/web/js/deluge-all/Keys.js
    index fe1c0b4..1766c4d 100644
    a b Deluge.Keys = { 
    6262    Status: [ 
    6363        'total_done', 'total_payload_download', 'total_uploaded', 
    6464        'total_payload_upload', 'next_announce', 'tracker_status', 'num_pieces', 
    65         'piece_length', 'is_auto_managed', 'active_time', 'seeding_time', 
    66         'seed_rank' 
     65        'piece_length', 'pieces', 'is_auto_managed', 'active_time',  
     66        'seeding_time', 'seed_rank' 
    6767    ], 
    6868     
    6969    /** 
  • deluge/ui/web/js/deluge-all/details/StatusTab.js

    diff --git a/deluge/ui/web/js/deluge-all/details/StatusTab.js b/deluge/ui/web/js/deluge-all/details/StatusTab.js
    index ba99a2a..1ded249 100644
    a b Ext.ns('Deluge.details'); 
    3535 * @class Deluge.details.StatusTab 
    3636 * @extends Ext.Panel 
    3737 */ 
     38 
    3839Deluge.details.StatusTab = Ext.extend(Ext.Panel, { 
    3940        title: _('Status'), 
    4041        autoScroll: true, 
    Deluge.details.StatusTab = Ext.extend(Ext.Panel, { 
    4243        onRender: function(ct, position) { 
    4344                Deluge.details.StatusTab.superclass.onRender.call(this, ct, position); 
    4445                 
    45                 this.progressBar = this.add({ 
    46                         xtype: 'progress', 
    47                         cls: 'x-deluge-status-progressbar' 
    48                 }); 
    49                  
     46                this.piecesBar = this.add({ 
     47            xtype: "box", 
     48            cls: "x-piecesbar", 
     49            tpl: new Ext.Template("<div class=\"x-piecesbar-{0}\" style=\"width: {1}px;\"></div>"), 
     50            compare_pieces: function(pieces) { 
     51                if (!this.pieces || pieces.length != this.pieces.length) { 
     52                    return false; 
     53                } 
     54                 
     55                for (var i = 0; i < pieces.length; i++) { 
     56                    if (pieces[i] != this.pieces[i]) { 
     57                        return false; 
     58                    } 
     59                } 
     60                return true; 
     61            }, 
     62             
     63            collapse_pieces: function(width, pieces) { 
     64                var group_size = pieces.length / width; 
     65 
     66                var padding = pieces.length % width; 
     67                        var i = 0; 
     68                        var new_pieces = [];  
     69                var this_group_size; 
     70                  
     71                        while (i < pieces.length) {  
     72                    this_group_size = group_size; 
     73                            if (padding > 0) {  
     74                                this_group_size = group_size + 1; 
     75                                padding -= 1; 
     76                    } 
     77                     
     78                    if (pieces.slice(i, i+this_group_size).indexOf(0) == -1) { 
     79                        new_pieces.push(1); 
     80                    } 
     81                    else { 
     82                        new_pieces.push(0); 
     83                    } 
     84                            i += this_group_size; 
     85                } 
     86                        return new_pieces; 
     87            }, 
     88             
     89            update: function(pieces) { 
     90                if (!this.compare_pieces(pieces) && typeof(pieces) != "number") { 
     91                    this.pieces = pieces; 
     92                     
     93                    if (pieces.length > this.getWidth()) { 
     94                        pieces = this.collapse_pieces(this.getWidth(), pieces); 
     95                    } 
     96                                     
     97                    while (this.el.dom.hasChildNodes()) { 
     98                        this.el.dom.removeChild(this.el.dom.lastChild); 
     99                    } 
     100                     
     101                    var piece_size = Math.floor((this.getWidth() - 2) / pieces.length); 
     102                    var padding = (this.getWidth() - 2) % pieces.length; 
     103                    var this_size; 
     104                     
     105                    for (var i = 0; i < pieces.length; i++) { 
     106                        this_size = piece_size; 
     107 
     108                        if (padding > 0) { 
     109                            this_size = piece_size + 1; 
     110                            padding -= 1; 
     111                        } 
     112 
     113                        if (pieces[i] == 1) { 
     114                            this.tpl.append(this.el, ["done", this_size]); 
     115                        } 
     116                        else { 
     117                            this.tpl.append(this.el, ["blank", this_size]); 
     118                        } 
     119                    } 
     120                } 
     121            } 
     122        }); 
     123                
    50124                this.status = this.add({ 
    51125                        cls: 'x-deluge-status', 
    52126                        id: 'deluge-details-status', 
    Deluge.details.StatusTab = Ext.extend(Ext.Panel, { 
    69143        }, 
    70144         
    71145        clear: function() { 
    72                 this.progressBar.updateProgress(0, ' '); 
     146                this.piecesBar.update([0]); 
    73147                for (var k in this.fields) { 
    74148                        this.fields[k].innerHTML = ''; 
    75149                } 
    Deluge.details.StatusTab = Ext.extend(Ext.Panel, { 
    119193                for (var field in this.fields) { 
    120194                        this.fields[field].innerHTML = data[field]; 
    121195                } 
    122                 var text = status.state + ' ' + status.progress.toFixed(2) + '%'; 
    123                 this.progressBar.updateProgress(status.progress / 100.0, text); 
     196         
     197                if (parseInt(status.num_pieces) != status.pieces.length) { 
     198            this.piecesBar.update([1]); 
     199        } 
     200        else { 
     201            this.piecesBar.update(status.pieces); 
     202        } 
    124203        } 
    125204});