      1 /*
      2 Script: deluge-bars.js
      3     Contains all objects and functions related to the statusbar, toolbar and
      4 	sidebar.
      5
      6 Copyright:
      7 	(C) Damien Churchill 2009 <damoxc@gmail.com>
      8 	This program is free software; you can redistribute it and/or modify
      9 	it under the terms of the GNU General Public License as published by
     10 	the Free Software Foundation; either version 3, or (at your option)
     11 	any later version.
     12
     13 	This program is distributed in the hope that it will be useful,
     14 	but WITHOUT ANY WARRANTY; without even the implied warranty of
     15 	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     16 	GNU General Public License for more details.
     17
     18 	You should have received a copy of the GNU General Public License
     19 	along with this program.  If not, write to:
     20 		The Free Software Foundation, Inc.,
     21 		51 Franklin Street, Fifth Floor
     22 		Boston, MA  02110-1301, USA.
     23
     24     In addition, as a special exception, the copyright holders give
     25     permission to link the code of portions of this program with the OpenSSL
     26     library.
     27     You must obey the GNU General Public License in all respects for all of
     28     the code used other than OpenSSL. If you modify file(s) with this
     29     exception, you may extend this exception to your version of the file(s),
     30     but you are not obligated to do so. If you do not wish to do so, delete
     31     this exception statement from your version. If you delete this exception
     32     statement from all source files in the program, then also delete it here.
     33
     34 */
     35
     36 // These are just so gen_gettext.py will pick up the strings
     37 // _('State')
     38 // _('Tracker Host')
     39
     40 (function() {
     41 	// Renderer for the items in the filter grids.
     42 	function filterRenderer(value, p, r) {
     43 		var lname = value.toLowerCase().replace('.', '_');
     44
     45 		var image = '';
     46 		if (r.store.id == 'tracker_host') {
     47 			if (value != 'Error') {
     48 				image = String.format('url(/tracker/{0})', value);
     49 			} else {
     50 				lname = null;
     51 			}
     52 		}
     53 		if (image) {
     54 			return String.format('<div class="x-deluge-filter" style="background-image: {2};">{0} ({1})</div>', value, r.data['count'], image);
     55 		} else if (lname) {
     56 			return String.format('<div class="x-deluge-filter x-deluge-{2}">{0} ({1})</div>', value, r.data['count'], lname);
     57 		} else {
     58 			return String.format('<div class="x-deluge-filter">{0} ({1})</div>', value, r.data['count']);
     59 		}
     60 	}
     61
     62 	Ext.deluge.Sidebar = Ext.extend(Ext.Panel, {
     63
     64 		// private
     65 		panels: {},
     66
     67 		// private
     68 		selected: null,
     69
     70 		constructor: function(config) {
     71 			config = Ext.apply({
     72 				id: 'sidebar',
     73 				region: 'west',
     74 				cls: 'deluge-sidebar',
     75 				title: _('Filters'),
     76 				layout: 'accordion',
     77 				split: true,
     78 				width: 200,
     79 				minSize: 175,
     80 				collapsible: true,
     81 				margins: '5 0 0 5',
     82 				cmargins: '5 0 0 5'
     83 			}, config);
     84 			Ext.deluge.Sidebar.superclass.constructor.call(this, config);
     85 		},
     86
     87 		// private
     88 		initComponent: function() {
     89 			Ext.deluge.Sidebar.superclass.initComponent.call(this);
     90 			Deluge.Events.on("disconnect", this.onDisconnect, this);
     91 		},
     92
     93 		createFilter: function(filter, states) {
     94 			var store = new Ext.data.SimpleStore({
     95 				id: filter,
     96 				fields: [
     97 					{name: 'filter'},
     98 					{name: 'count'}
     99 				]
    100 			});
    101
    102 			var title = filter.replace('_', ' ');
    103 			var parts = title.split(' ');
    104 			title = '';
    105 			Ext.each(parts, function(part) {
    106 				firstLetter = part.substring(0, 1);
    107 				firstLetter = firstLetter.toUpperCase();
    108 				part = firstLetter + part.substring(1);
    109 				title += part + ' ';
    110 			});
    111
    112 			var panel = new Ext.grid.GridPanel({
    113 				id: filter + '-panel',
    114 				store: store,
    115 				title: _(title),
    116 				columns: [
    117 					{id: 'filter', sortable: false, renderer: filterRenderer, dataIndex: 'filter'}
    118 				],
    119 				stripeRows: false,
    120 				selModel: new Ext.grid.RowSelectionModel({
    121 					singleSelect: true,
    122 					listeners: {
    123 						'rowselect': {fn: this.onFilterSelect, scope: this}
    124 					}
    125 				}),
    126 				hideHeaders: true,
    127 				autoExpandColumn: 'filter',
    128 				deferredRender: false,
    129 				autoScroll: true
    130 			});
    131
    132 			if (Deluge.config['sidebar_show_zero'] == false) {
    133 				states = this.removeZero(states);
    134 			}
    135
    136 			store.loadData(states);
    137 			this.add(panel);
    138
    139 			this.doLayout();
    140 			this.panels[filter] = panel;
    141
    142 			if (!this.selected) {
    143 				panel.getSelectionModel().selectFirstRow();
    144 				this.selected = {
    145 					row: 0,
    146 					filter: states[0][0],
    147 					panel: panel
    148 				}
    149 			}
    150 		},
    151
    152 		getFilters: function() {
    153 			var filters = {}
    154 			if (!this.selected) {
    155 				return filters;
    156 			}
    157 			if (!this.selected.filter || !this.selected.panel) {
    158 				return filters;
    159 			}
    160 			var filterType = this.selected.panel.store.id;
    161 			if (filterType == "state" && this.selected.filter == "All") {
    162 				return filters;
    163 			}
    164
    165 			filters[filterType] = this.selected.filter;
    166 			return filters;
    167 		},
    168
    169 		// private
    170 		onDisconnect: function() {
    171 			Ext.each(Ext.getKeys(this.panels), function(filter) {
    172 				this.remove(filter + '-panel');
    173 			}, this);
    174 			this.panels = {};
    175 			this.selected = null;
    176 		},
    177
    178 		onFilterSelect: function(selModel, rowIndex, record) {
    179 			if (!this.selected) needsUpdate = true;
    180 			else if (this.selected.row != rowIndex) needsUpdate = true;
    181 			else needsUpdate = false;
    182 			this.selected = {
    183 				row: rowIndex,
    184 				filter: record.get('filter'),
    185 				panel: this.panels[record.store.id]
    186 			}
    187
    188 			if (needsUpdate) Deluge.UI.update();
    189 		},
    190
    191 		/**
    192 		 * Remove the states with zero torrents in them.
    193 		 */
    194 		removeZero: function(states) {
    195 			var newStates = [];
    196 			Ext.each(states, function(state) {
    197 				if (state[1] > 0) {
    198 					newStates.push(state);
    199 				}
    200 			});
    201 			return newStates;
    202 		},
    203
    204 		update: function(filters) {
    205 			for (var filter in filters) {
    206 				var states = filters[filter];
    207 				if (Ext.getKeys(this.panels).indexOf(filter) > -1) {
    208 					this.updateFilter(filter, states);
    209 				} else {
    210 					this.createFilter(filter, states);
    211 				}
    212 			}
    213
    214 			// Perform a cleanup of fitlers that aren't enabled any more
    215 			Ext.each(Ext.keys(this.panels), function(filter) {
    216 				if (Ext.keys(filters).indexOf(filter) == -1) {
    217 					// We need to remove the panel
    218 					this.panels[filter]
    219 				}
    220 			});
    221 		},
    222
    223 		updateFilter: function(filter, states) {
    224 			if (Deluge.config['sidebar_show_zero'] == false) {
    225 				states = this.removeZero(states);
    226 			}
    227
    228 			this.panels[filter].store.loadData(states);
    229 			if (this.selected && this.selected.panel == this.panels[filter]) {
    230 				this.panels[filter].getSelectionModel().selectRow(this.selected.row);
    231 			}
    232 		}
    233
    234 	});
    235 	Deluge.Sidebar = new Ext.deluge.Sidebar();
    236 })();