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});