      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.js 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 			store.loadData(states);
    132 			this.add(panel);
    133
    134 			this.doLayout();
    135 			this.panels[filter] = panel;
    136
    137 			if (!this.selected) {
    138 				panel.getSelectionModel().selectFirstRow();
    139 				this.selected = {
    140 					row: 0,
    141 					filter: states[0][0],
    142 					panel: panel
    143 				}
    144 			}
    145 		},
    146
    147 		getFilters: function() {
    148 			var filters = {}
    149 			if (!this.selected) {
    150 				return filters;
    151 			}
    152 			if (!this.selected.filter || !this.selected.panel) {
    153 				return filters;
    154 			}
    155 			var filterType = this.selected.panel.store.id;
    156 			if (filterType == "state" && this.selected.filter == "All") {
    157 				return filters;
    158 			}
    159
    160 			filters[filterType] = this.selected.filter;
    161 			return filters;
    162 		},
    163
    164 		// private
    165 		onDisconnect: function() {
    166 			Ext.each(Ext.getKeys(this.panels), function(filter) {
    167 				this.remove(filter + '-panel');
    168 			}, this);
    169 			this.panels = {};
    170 			this.selected = null;
    171 		},
    172
    173 		onFilterSelect: function(selModel, rowIndex, record) {
    174 			if (!this.selected) needsUpdate = true;
    175 			else if (this.selected.row != rowIndex) needsUpdate = true;
    176 			else needsUpdate = false;
    177 			this.selected = {
    178 				row: rowIndex,
    179 				filter: record.get('filter'),
    180 				panel: this.panels[record.store.id]
    181 			}
    182
    183 			if (needsUpdate) Deluge.UI.update();
    184 		},
    185
    186 		update: function(filters) {
    187 			for (var filter in filters) {
    188 				var states = filters[filter];
    189 				if (Ext.getKeys(this.panels).indexOf(filter) > -1) {
    190 					this.updateFilter(filter, states);
    191 				} else {
    192 					this.createFilter(filter, states);
    193 				}
    194 			}
    195
    196 			// Perform a cleanup of fitlers that aren't enabled any more
    197 			Ext.each(Ext.keys(this.panels), function(filter) {
    198 				if (Ext.keys(filters).indexOf(filter) == -1) {
    199 					// We need to remove the panel
    200 				}
    201 			});
    202 		},
    203
    204 		updateFilter: function(filter, states) {
    205 			this.panels[filter].store.loadData(states);
    206 			if (this.selected && this.selected.panel == this.panels[filter]) {
    207 				this.panels[filter].getSelectionModel().selectRow(this.selected.row);
    208 			}
    209 		}
    210
    211 	});
    212 	Deluge.Sidebar = new Ext.deluge.Sidebar();
    213 })();