This commit is contained in:
jim
2025-12-12 15:53:31 +00:00
commit 31a11e3ba4
6051 changed files with 2099864 additions and 0 deletions
@@ -0,0 +1,226 @@
/**
* Script: autoadd.js
* The client-side javascript code for the AutoAdd plugin.
*
* Copyright (C) 2009 GazpachoKing <chase.sterling@gmail.com>
*
* This file is part of Deluge and is licensed under GNU General Public License 3.0, or later, with
* the additional special exception to link portions of this program with the OpenSSL library.
* See LICENSE for more details.
*/
Ext.ns('Deluge.ux.AutoAdd');
Deluge.ux.AutoAdd.onClickFunctions = {};
Ext.ns('Deluge.ux.preferences');
/**
* @class Deluge.ux.preferences.AutoAddPage
* @extends Ext.Panel
*/
Deluge.ux.preferences.AutoAddPage = Ext.extend(Ext.Panel, {
title: _('AutoAdd'),
header: false,
layout: 'fit',
border: false,
watchdirs: {},
initComponent: function () {
Deluge.ux.preferences.AutoAddPage.superclass.initComponent.call(this);
var autoAdd = this;
this.list = new Ext.list.ListView({
store: new Ext.data.JsonStore({
fields: ['id', 'enabled', 'owner', 'path'],
}),
columns: [
{
id: 'enabled',
header: _('Active'),
sortable: true,
dataIndex: 'enabled',
tpl: new Ext.XTemplate('{enabled:this.getCheckbox}', {
getCheckbox: function (checked, selected) {
Deluge.ux.AutoAdd.onClickFunctions[selected.id] =
function () {
if (selected.enabled) {
deluge.client.autoadd.disable_watchdir(
selected.id
);
checked = false;
} else {
deluge.client.autoadd.enable_watchdir(
selected.id
);
checked = true;
}
autoAdd.updateWatchDirs();
};
return (
'<input id="enabled-' +
selected.id +
'" type="checkbox"' +
(checked ? ' checked' : '') +
' onclick="Deluge.ux.AutoAdd.onClickFunctions[' +
selected.id +
']()" />'
);
},
}),
width: 0.15,
},
{
id: 'owner',
header: _('Owner'),
sortable: true,
dataIndex: 'owner',
width: 0.2,
},
{
id: 'path',
header: _('Path'),
sortable: true,
dataIndex: 'path',
},
],
singleSelect: true,
autoExpandColumn: 'path',
});
this.list.on('selectionchange', this.onSelectionChange, this);
this.panel = this.add({
items: [this.list],
bbar: {
items: [
{
text: _('Add'),
iconCls: 'icon-add',
handler: this.onAddClick,
scope: this,
},
{
text: _('Edit'),
iconCls: 'icon-edit',
handler: this.onEditClick,
scope: this,
disabled: true,
},
'->',
{
text: _('Remove'),
iconCls: 'icon-remove',
handler: this.onRemoveClick,
scope: this,
disabled: true,
},
],
},
});
this.on('show', this.onPreferencesShow, this);
},
updateWatchDirs: function () {
deluge.client.autoadd.get_watchdirs({
success: function (watchdirs) {
this.watchdirs = watchdirs;
var watchdirsArray = [];
for (var id in watchdirs) {
if (watchdirs.hasOwnProperty(id)) {
var watchdir = {};
watchdir['id'] = id;
watchdir['enabled'] = watchdirs[id].enabled;
watchdir['owner'] =
watchdirs[id].owner || 'localclient';
watchdir['path'] = watchdirs[id].path;
watchdirsArray.push(watchdir);
}
}
this.list.getStore().loadData(watchdirsArray);
},
scope: this,
});
},
onAddClick: function () {
if (!this.addWin) {
this.addWin = new Deluge.ux.AutoAdd.AddAutoAddCommandWindow();
this.addWin.on(
'watchdiradd',
function () {
this.updateWatchDirs();
},
this
);
}
this.addWin.show();
},
onEditClick: function () {
if (!this.editWin) {
this.editWin = new Deluge.ux.AutoAdd.EditAutoAddCommandWindow();
this.editWin.on(
'watchdiredit',
function () {
this.updateWatchDirs();
},
this
);
}
var id = this.list.getSelectedRecords()[0].id;
this.editWin.show(id, this.watchdirs[id]);
},
onPreferencesShow: function () {
this.updateWatchDirs();
},
onRemoveClick: function () {
var record = this.list.getSelectedRecords()[0];
deluge.client.autoadd.remove(record.id, {
success: function () {
this.updateWatchDirs();
},
scope: this,
});
},
onSelectionChange: function (dv, selections) {
if (selections.length) {
this.panel.getBottomToolbar().items.get(1).enable();
this.panel.getBottomToolbar().items.get(3).enable();
} else {
this.panel.getBottomToolbar().items.get(1).disable();
this.panel.getBottomToolbar().items.get(3).disable();
}
},
});
Deluge.plugins.AutoAddPlugin = Ext.extend(Deluge.Plugin, {
name: 'AutoAdd',
static: {
prefsPage: null,
},
onDisable: function () {
deluge.preferences.removePage(Deluge.plugins.AutoAddPlugin.prefsPage);
Deluge.plugins.AutoAddPlugin.prefsPage = null;
},
onEnable: function () {
/*
* Called for each of the JavaScript files.
* This will prevent adding unnecessary tabs to the preferences window.
*/
if (!Deluge.plugins.AutoAddPlugin.prefsPage) {
Deluge.plugins.AutoAddPlugin.prefsPage = deluge.preferences.addPage(
new Deluge.ux.preferences.AutoAddPage()
);
}
},
});
Deluge.registerPlugin('AutoAdd', Deluge.plugins.AutoAddPlugin);
@@ -0,0 +1,472 @@
/**
* Script: autoadd.js
* The client-side javascript code for the AutoAdd plugin.
*
* Copyright (C) 2009 GazpachoKing <chase.sterling@gmail.com>
*
* This file is part of Deluge and is licensed under GNU General Public License 3.0, or later, with
* the additional special exception to link portions of this program with the OpenSSL library.
* See LICENSE for more details.
*/
Ext.ns('Deluge.ux.AutoAdd');
/**
* @class Deluge.ux.AutoAdd.AutoAddWindowBase
* @extends Ext.Window
*/
Deluge.ux.AutoAdd.AutoAddWindowBase = Ext.extend(Ext.Window, {
width: 350,
height: 500,
layout: 'fit',
closeAction: 'hide',
spin_ids: ['max_download_speed', 'max_upload_speed', 'stop_ratio'],
spin_int_ids: ['max_upload_slots', 'max_connections'],
chk_ids: [
'stop_at_ratio',
'remove_at_ratio',
'move_completed',
'add_paused',
'auto_managed',
'queue_to_top',
],
toggle_ids: [
'append_extension_toggle',
'download_location_toggle',
'label_toggle',
'copy_torrent_toggle',
'delete_copy_torrent_toggle',
'seed_mode',
],
accounts: new Ext.data.ArrayStore({
storeId: 'accountStore',
id: 0,
fields: [
{
name: 'displayText',
type: 'string',
},
],
}),
labels: new Ext.data.ArrayStore({
storeId: 'labelStore',
id: 0,
fields: [
{
name: 'displayText',
type: 'string',
},
],
}),
initComponent: function () {
Deluge.ux.AutoAdd.AutoAddWindowBase.superclass.initComponent.call(this);
this.addButton(_('Cancel'), this.onCancelClick, this);
this.MainTab = new Deluge.ux.AutoAdd.AutoAddMainPanel();
this.OptionsTab = new Deluge.ux.AutoAdd.AutoAddOptionsPanel();
this.form = this.add({
xtype: 'form',
layout: 'fit',
baseCls: 'x-plain',
bodyStyle: 'padding: 5px',
items: [
{
xtype: 'tabpanel',
activeTab: 0,
items: [this.MainTab, this.OptionsTab],
},
],
});
},
onCancelClick: function () {
this.hide();
},
getOptions: function () {
var options = {};
options['enabled'] = Ext.getCmp('enabled').getValue();
options['path'] = Ext.getCmp('path').getValue();
options['download_location'] =
Ext.getCmp('download_location').getValue();
options['move_completed_path'] = Ext.getCmp(
'move_completed_path'
).getValue();
options['copy_torrent'] = Ext.getCmp('copy_torrent').getValue();
options['label'] = Ext.getCmp('label').getValue();
options['append_extension'] = Ext.getCmp('append_extension').getValue();
options['owner'] = Ext.getCmp('owner').getValue();
this.toggle_ids.forEach(function (toggle_id) {
options[toggle_id] = Ext.getCmp(toggle_id).getValue();
});
this.spin_ids.forEach(function (spin_id) {
options[spin_id] = Ext.getCmp(spin_id).getValue();
options[spin_id + '_toggle'] = Ext.getCmp(
spin_id + '_toggle'
).getValue();
});
this.spin_int_ids.forEach(function (spin_int_id) {
options[spin_int_id] = Ext.getCmp(spin_int_id).getValue();
options[spin_int_id + '_toggle'] = Ext.getCmp(
spin_int_id + '_toggle'
).getValue();
});
this.chk_ids.forEach(function (chk_id) {
options[chk_id] = Ext.getCmp(chk_id).getValue();
options[chk_id + '_toggle'] = Ext.getCmp(
chk_id + '_toggle'
).getValue();
});
if (
options['copy_torrent_toggle'] &&
options['path'] === options['copy_torrent']
) {
throw _(
'"Watch Folder" directory and "Copy of .torrent' +
' files to" directory cannot be the same!'
);
}
return options;
},
loadOptions: function (options) {
/*
* Populate all available options data to the UI
*/
var value;
if (options === undefined) {
options = {};
}
Ext.getCmp('enabled').setValue(
options['enabled'] !== undefined ? options['enabled'] : true
);
Ext.getCmp('isnt_append_extension').setValue(true);
Ext.getCmp('append_extension_toggle').setValue(
options['append_extension_toggle'] !== undefined
? options['append_extension_toggle']
: false
);
Ext.getCmp('append_extension').setValue(
options['append_extension'] !== undefined
? options['append_extension']
: '.added'
);
Ext.getCmp('download_location_toggle').setValue(
options['download_location_toggle'] !== undefined
? options['download_location_toggle']
: false
);
Ext.getCmp('copy_torrent_toggle').setValue(
options['copy_torrent_toggle'] !== undefined
? options['copy_torrent_toggle']
: false
);
Ext.getCmp('delete_copy_torrent_toggle').setValue(
options['delete_copy_torrent_toggle'] !== undefined
? options['delete_copy_torrent_toggle']
: false
);
value =
options['seed_mode'] !== undefined ? options['seed_mode'] : false;
Ext.getCmp('seed_mode').setValue(value);
this.accounts.removeAll(true);
this.labels.removeAll(true);
Ext.getCmp('owner').store = this.accounts;
Ext.getCmp('label').store = this.labels;
Ext.getCmp('label').setValue(
options['label'] !== undefined ? options['label'] : ''
);
Ext.getCmp('label_toggle').setValue(
options['label_toggle'] !== undefined
? options['label_toggle']
: false
);
this.spin_ids.forEach(function (spin_id) {
Ext.getCmp(spin_id).setValue(
options[spin_id] !== undefined ? options[spin_id] : 0
);
Ext.getCmp(spin_id + '_toggle').setValue(
options[spin_id + '_toggle'] !== undefined
? options[spin_id + '_toggle']
: false
);
});
this.chk_ids.forEach(function (chk_id) {
Ext.getCmp(chk_id).setValue(
options[chk_id] !== undefined ? options[chk_id] : true
);
Ext.getCmp(chk_id + '_toggle').setValue(
options[chk_id + '_toggle'] !== undefined
? options[chk_id + '_toggle']
: false
);
});
value =
options['add_paused'] !== undefined ? options['add_paused'] : true;
if (!value) {
Ext.getCmp('not_add_paused').setValue(true);
}
value =
options['queue_to_top'] !== undefined
? options['queue_to_top']
: true;
if (!value) {
Ext.getCmp('not_queue_to_top').setValue(true);
}
value =
options['auto_managed'] !== undefined
? options['auto_managed']
: true;
if (!value) {
Ext.getCmp('not_auto_managed').setValue(true);
}
[
'move_completed_path',
'path',
'download_location',
'copy_torrent',
].forEach(function (field) {
value = options[field] !== undefined ? options[field] : '';
Ext.getCmp(field).setValue(value);
});
if (Object.keys(options).length === 0) {
deluge.client.core.get_config({
success: function (config) {
var value;
Ext.getCmp('download_location').setValue(
options['download_location'] !== undefined
? options['download_location']
: config['download_location']
);
value =
options['move_completed_toggle'] !== undefined
? options['move_completed_toggle']
: config['move_completed'];
if (value) {
Ext.getCmp('move_completed_toggle').setValue(
options['move_completed_toggle'] !== undefined
? options['move_completed_toggle']
: false
);
Ext.getCmp('move_completed_path').setValue(
options['move_completed_path'] !== undefined
? options['move_completed_path']
: config['move_completed_path']
);
}
value =
options['copy_torrent_toggle'] !== undefined
? options['copy_torrent_toggle']
: config['copy_torrent_file'];
if (value) {
Ext.getCmp('copy_torrent_toggle').setValue(true);
Ext.getCmp('copy_torrent').setValue(
options['copy_torrent'] !== undefined
? options['copy_torrent']
: config['torrentfiles_location']
);
}
value =
options['delete_copy_torrent_toggle'] !== undefined
? options['copy_torrent_toggle']
: config['del_copy_torrent_file'];
if (value) {
Ext.getCmp('delete_copy_torrent_toggle').setValue(true);
}
},
});
}
deluge.client.core.get_enabled_plugins({
success: function (plugins) {
if (plugins !== undefined && plugins.indexOf('Label') > -1) {
this.MainTab.LabelFset.setVisible(true);
deluge.client.label.get_labels({
success: function (labels) {
for (
var index = 0;
index < labels.length;
index++
) {
labels[index] = [labels[index]];
}
this.labels.loadData(labels, false);
},
failure: function (failure) {
console.error(failure);
},
scope: this,
});
} else {
this.MainTab.LabelFset.setVisible(false);
}
},
scope: this,
});
var me = this;
function on_accounts(accounts, owner) {
for (var index = 0; index < accounts.length; index++) {
accounts[index] = [accounts[index]['username']];
}
me.accounts.loadData(accounts, false);
Ext.getCmp('owner').setValue(owner).enable();
}
function on_accounts_failure(failure) {
deluge.client.autoadd.get_auth_user({
success: function (user) {
me.accounts.loadData([[user]], false);
Ext.getCmp('owner').setValue(user).disable(true);
},
scope: this,
});
}
deluge.client.autoadd.is_admin_level({
success: function (is_admin) {
if (is_admin) {
deluge.client.core.get_known_accounts({
success: function (accounts) {
deluge.client.autoadd.get_auth_user({
success: function (user) {
on_accounts(
accounts,
options['owner'] !== undefined
? options['owner']
: user
);
},
scope: this,
});
},
failure: on_accounts_failure,
scope: this,
});
} else {
on_accounts_failure(null);
}
},
scope: this,
});
},
});
/**
* @class Deluge.ux.AutoAdd.EditAutoAddCommandWindow
* @extends Deluge.ux.AutoAdd.AutoAddWindowBase
*/
Deluge.ux.AutoAdd.EditAutoAddCommandWindow = Ext.extend(
Deluge.ux.AutoAdd.AutoAddWindowBase,
{
title: _('Edit Watch Folder'),
initComponent: function () {
Deluge.ux.AutoAdd.EditAutoAddCommandWindow.superclass.initComponent.call(
this
);
this.addButton(_('Save'), this.onSaveClick, this);
this.addEvents({
watchdiredit: true,
});
},
show: function (watchdir_id, options) {
Deluge.ux.AutoAdd.EditAutoAddCommandWindow.superclass.show.call(
this
);
this.watchdir_id = watchdir_id;
this.loadOptions(options);
},
onSaveClick: function () {
try {
var options = this.getOptions();
deluge.client.autoadd.set_options(this.watchdir_id, options, {
success: function () {
this.fireEvent('watchdiredit', this, options);
},
scope: this,
});
} catch (err) {
Ext.Msg.show({
title: _('Incompatible Option'),
msg: err,
buttons: Ext.Msg.OK,
scope: this,
});
}
this.hide();
},
}
);
/**
* @class Deluge.ux.AutoAdd.AddAutoAddCommandWindow
* @extends Deluge.ux.AutoAdd.AutoAddWindowBase
*/
Deluge.ux.AutoAdd.AddAutoAddCommandWindow = Ext.extend(
Deluge.ux.AutoAdd.AutoAddWindowBase,
{
title: _('Add Watch Folder'),
initComponent: function () {
Deluge.ux.AutoAdd.AddAutoAddCommandWindow.superclass.initComponent.call(
this
);
this.addButton(_('Add'), this.onAddClick, this);
this.addEvents({
watchdiradd: true,
});
},
show: function () {
Deluge.ux.AutoAdd.AddAutoAddCommandWindow.superclass.show.call(
this
);
this.loadOptions();
},
onAddClick: function () {
var options = this.getOptions();
deluge.client.autoadd.add(options, {
success: function () {
this.fireEvent('watchdiradd', this, options);
this.hide();
},
failure: function (err) {
const regex = /: (.*\n)\n?\]/m;
var error;
if ((error = regex.exec(err.error.message)) !== null) {
error = error[1];
} else {
error = err.error.message;
}
Ext.Msg.show({
title: _('Incompatible Option'),
msg: error,
buttons: Ext.Msg.OK,
scope: this,
});
},
scope: this,
});
},
}
);
@@ -0,0 +1,304 @@
/**
* Script: main_tab.js
* The client-side javascript code for the AutoAdd plugin.
*
* Copyright (C) 2009 GazpachoKing <chase.sterling@gmail.com>
*
* This file is part of Deluge and is licensed under GNU General Public License 3.0, or later, with
* the additional special exception to link portions of this program with the OpenSSL library.
* See LICENSE for more details.
*/
Ext.ns('Deluge.ux.AutoAdd');
/**
* @class Deluge.ux.AutoAdd.AutoAddMainPanel
* @extends Ext.Panel
*/
Deluge.ux.AutoAdd.AutoAddMainPanel = Ext.extend(Ext.Panel, {
id: 'main_tab_panel',
title: _('Main'),
initComponent: function () {
Deluge.ux.AutoAdd.AutoAddMainPanel.superclass.initComponent.call(this);
this.watchFolderFset = new Ext.form.FieldSet({
xtype: 'fieldset',
border: false,
title: _('Watch Folder'),
defaultType: 'textfield',
style: 'margin-top: 3px; margin-bottom: 0px; padding-bottom: 0px;',
width: '85%',
labelWidth: 1,
items: [
{
xtype: 'textfield',
id: 'path',
hideLabel: true,
width: 304,
},
{
hideLabel: true,
id: 'enabled',
xtype: 'checkbox',
boxLabel: _('Enable this watch folder'),
checked: true,
},
],
});
this.torrentActionFset = new Ext.form.FieldSet({
xtype: 'fieldset',
border: false,
title: _('Torrent File Action'),
style: 'margin-top: 3px; margin-bottom: 0px; padding-bottom: 0px;',
width: '85%',
labelWidth: 1,
defaults: {
style: 'margin-bottom: 2px',
},
items: [
{
xtype: 'radiogroup',
columns: 1,
items: [
{
xtype: 'radio',
name: 'torrent_action',
id: 'isnt_append_extension',
boxLabel: _('Delete .torrent after adding'),
checked: true,
hideLabel: true,
listeners: {
check: function (cb, newValue) {
if (newValue) {
Ext.getCmp(
'append_extension'
).setDisabled(newValue);
Ext.getCmp('copy_torrent').setDisabled(
newValue
);
Ext.getCmp(
'delete_copy_torrent_toggle'
).setDisabled(newValue);
}
},
},
},
{
xtype: 'container',
layout: 'hbox',
hideLabel: true,
items: [
{
xtype: 'radio',
name: 'torrent_action',
id: 'append_extension_toggle',
boxLabel: _(
'Append extension after adding:'
),
hideLabel: true,
listeners: {
check: function (cb, newValue) {
if (newValue) {
Ext.getCmp(
'append_extension'
).setDisabled(!newValue);
Ext.getCmp(
'copy_torrent'
).setDisabled(newValue);
Ext.getCmp(
'delete_copy_torrent_toggle'
).setDisabled(newValue);
}
},
},
},
{
xtype: 'textfield',
id: 'append_extension',
hideLabel: true,
disabled: true,
style: 'margin-left: 2px',
width: 112,
},
],
},
{
xtype: 'container',
hideLabel: true,
items: [
{
xtype: 'container',
layout: 'hbox',
hideLabel: true,
items: [
{
xtype: 'radio',
name: 'torrent_action',
id: 'copy_torrent_toggle',
boxLabel: _(
'Copy of .torrent files to:'
),
hideLabel: true,
listeners: {
check: function (cb, newValue) {
if (newValue) {
Ext.getCmp(
'append_extension'
).setDisabled(newValue);
Ext.getCmp(
'copy_torrent'
).setDisabled(
!newValue
);
Ext.getCmp(
'delete_copy_torrent_toggle'
).setDisabled(
!newValue
);
}
},
},
},
{
xtype: 'textfield',
id: 'copy_torrent',
hideLabel: true,
disabled: true,
style: 'margin-left: 2px',
width: 152,
},
],
},
{
xtype: 'checkbox',
id: 'delete_copy_torrent_toggle',
boxLabel: _(
'Delete copy of torrent file on remove'
),
style: 'margin-left: 10px',
disabled: true,
},
],
},
],
},
],
});
this.downloadFolderFset = new Ext.form.FieldSet({
xtype: 'fieldset',
border: false,
title: _('Download Folder'),
defaultType: 'textfield',
style: 'margin-top: 3px; margin-bottom: 0px; padding-bottom: 0px;',
width: '85%',
labelWidth: 1,
items: [
{
hideLabel: true,
id: 'download_location_toggle',
xtype: 'checkbox',
boxLabel: _('Set download folder'),
listeners: {
check: function (cb, checked) {
Ext.getCmp('download_location').setDisabled(
!checked
);
},
},
},
{
xtype: 'textfield',
id: 'download_location',
hideLabel: true,
width: 304,
disabled: true,
},
],
});
this.moveCompletedFset = new Ext.form.FieldSet({
xtype: 'fieldset',
border: false,
title: _('Move Completed'),
defaultType: 'textfield',
style: 'margin-top: 3px; margin-bottom: 0px; padding-bottom: 0px;',
width: '85%',
labelWidth: 1,
items: [
{
hideLabel: true,
id: 'move_completed_toggle',
xtype: 'checkbox',
boxLabel: _('Set move completed folder'),
listeners: {
check: function (cb, checked) {
Ext.getCmp('move_completed_path').setDisabled(
!checked
);
},
},
},
{
xtype: 'textfield',
id: 'move_completed_path',
hideLabel: true,
width: 304,
disabled: true,
},
],
});
this.LabelFset = new Ext.form.FieldSet({
xtype: 'fieldset',
border: false,
title: _('Label'),
defaultType: 'textfield',
style: 'margin-top: 3px; margin-bottom: 0px; padding-bottom: 3px;',
//width: '85%',
labelWidth: 1,
//hidden: true,
items: [
{
xtype: 'container',
layout: 'hbox',
hideLabel: true,
items: [
{
hashLabel: false,
id: 'label_toggle',
xtype: 'checkbox',
boxLabel: _('Label:'),
listeners: {
check: function (cb, checked) {
Ext.getCmp('label').setDisabled(!checked);
},
},
},
{
xtype: 'combo',
id: 'label',
hideLabel: true,
//width: 220,
width: 254,
disabled: true,
style: 'margin-left: 2px',
mode: 'local',
valueField: 'displayText',
displayField: 'displayText',
},
],
},
],
});
this.add([
this.watchFolderFset,
this.torrentActionFset,
this.downloadFolderFset,
this.moveCompletedFset,
this.LabelFset,
]);
},
});
@@ -0,0 +1,302 @@
/**
* Script: options_tab.js
* The client-side javascript code for the AutoAdd plugin.
*
* Copyright (C) 2009 GazpachoKing <chase.sterling@gmail.com>
*
* This file is part of Deluge and is licensed under GNU General Public License 3.0, or later, with
* the additional special exception to link portions of this program with the OpenSSL library.
* See LICENSE for more details.
*/
Ext.ns('Deluge.ux.AutoAdd');
/**
* @class Deluge.ux.AutoAdd.AutoAddOptionsPanel
* @extends Ext.Panel
*/
Deluge.ux.AutoAdd.AutoAddOptionsPanel = Ext.extend(Ext.Panel, {
id: 'options_tab_panel',
title: _('Options'),
initComponent: function () {
Deluge.ux.AutoAdd.AutoAddOptionsPanel.superclass.initComponent.call(
this
);
var maxDownload = {
idCheckbox: 'max_download_speed_toggle',
labelCheckbox: 'Max Download Speed (KiB/s):',
idSpinner: 'max_download_speed',
decimalPrecision: 1,
};
var maxUploadSpeed = {
idCheckbox: 'max_upload_speed_toggle',
labelCheckbox: 'Max upload Speed (KiB/s):',
idSpinner: 'max_upload_speed',
decimalPrecision: 1,
};
var maxConnections = {
idCheckbox: 'max_connections_toggle',
labelCheckbox: 'Max Connections::',
idSpinner: 'max_connections',
decimalPrecision: 0,
};
var maxUploadSlots = {
idCheckbox: 'max_upload_slots_toggle',
labelCheckbox: 'Max Upload Slots:',
idSpinner: 'max_upload_slots',
decimalPrecision: 0,
};
// queue data
var addPause = {
idCheckbox: 'add_paused_toggle',
labelCheckbox: 'Add Pause:',
nameRadio: 'add_paused',
labelRadio: {
yes: 'Yes',
no: 'No',
},
};
var queueTo = {
idCheckbox: 'queue_to_top_toggle',
labelCheckbox: 'Queue To:',
nameRadio: 'queue_to_top',
labelRadio: {
yes: 'Top',
no: 'Bottom',
},
};
var autoManaged = {
idCheckbox: 'auto_managed_toggle',
labelCheckbox: 'Auto Managed:',
nameRadio: 'auto_managed',
labelRadio: {
yes: 'Yes',
no: 'No',
},
};
this.ownerFset = new Ext.form.FieldSet({
xtype: 'fieldset',
border: false,
title: _('Owner'),
style: 'margin-top: 3px; margin-bottom: 0px; padding-bottom: 0px;',
//width: '85%',
labelWidth: 1,
items: [
{
xtype: 'combo',
id: 'owner',
hideLabel: true,
width: 312,
mode: 'local',
valueField: 'displayText',
displayField: 'displayText',
},
],
});
this.bandwidthFset = new Ext.form.FieldSet({
xtype: 'fieldset',
border: false,
title: _('Bandwidth'),
style: 'margin-top: 3px; margin-bottom: 0px; padding-bottom: 0px;',
//width: '85%',
labelWidth: 1,
defaults: {
style: 'margin-bottom: 5px',
},
});
this.bandwidthFset.add(this._getBandwidthContainer(maxDownload));
this.bandwidthFset.add(this._getBandwidthContainer(maxUploadSpeed));
this.bandwidthFset.add(this._getBandwidthContainer(maxConnections));
this.bandwidthFset.add(this._getBandwidthContainer(maxUploadSlots));
this.queueFset = new Ext.form.FieldSet({
xtype: 'fieldset',
border: false,
title: _('Queue'),
style: 'margin-top: 3px; margin-bottom: 0px; padding-bottom: 0px;',
//width: '85%',
labelWidth: 1,
defaults: {
style: 'margin-bottom: 5px',
},
items: [
{
xtype: 'container',
layout: 'hbox',
hideLabel: true,
},
],
});
this.queueFset.add(this._getQueueContainer(addPause));
this.queueFset.add(this._getQueueContainer(queueTo));
this.queueFset.add(this._getQueueContainer(autoManaged));
this.queueFset.add({
xtype: 'container',
hideLabel: true,
items: [
{
xtype: 'container',
layout: 'hbox',
hideLabel: true,
items: [
{
xtype: 'checkbox',
id: 'stop_at_ratio_toggle',
boxLabel: _('Stop seed at ratio:'),
hideLabel: true,
width: 175,
listeners: {
check: function (cb, checked) {
Ext.getCmp('stop_ratio').setDisabled(
!checked
);
Ext.getCmp('remove_at_ratio').setDisabled(
!checked
);
},
},
},
{
xtype: 'spinnerfield',
id: 'stop_ratio',
hideLabel: true,
disabled: true,
value: 0.0,
minValue: 0.0,
maxValue: 100.0,
decimalPrecision: 1,
incrementValue: 0.1,
style: 'margin-left: 2px',
width: 100,
},
],
},
{
xtype: 'container',
layout: 'hbox',
hideLabel: true,
style: 'margin-left: 10px',
items: [
{
xtype: 'checkbox',
id: 'remove_at_ratio',
boxLabel: _('Remove at ratio'),
disabled: true,
checked: true,
},
{
xtype: 'checkbox',
id: 'remove_at_ratio_toggle',
disabled: true,
checked: true,
hidden: true,
},
{
xtype: 'checkbox',
id: 'stop_ratio_toggle',
disabled: true,
checked: true,
hidden: true,
},
{
xtype: 'checkbox',
id: 'stop_ratio_toggle',
disabled: true,
checked: true,
hidden: true,
},
],
},
],
});
this.queueFset.add({
xtype: 'checkbox',
id: 'seed_mode',
boxLabel: _('Skip File Hash Check'),
hideLabel: true,
width: 175,
});
this.add([this.ownerFset, this.bandwidthFset, this.queueFset]);
},
_getBandwidthContainer: function (values) {
return new Ext.Container({
xtype: 'container',
layout: 'hbox',
hideLabel: true,
items: [
{
xtype: 'checkbox',
hideLabel: true,
id: values.idCheckbox,
boxLabel: _(values.labelCheckbox),
width: 175,
listeners: {
check: function (cb, checked) {
Ext.getCmp(values.idSpinner).setDisabled(!checked);
},
},
},
{
xtype: 'spinnerfield',
id: values.idSpinner,
hideLabel: true,
disabled: true,
minValue: -1,
maxValue: 10000,
value: 0.0,
decimalPrecision: values.decimalPrecision,
style: 'margin-left: 2px',
width: 100,
},
],
});
},
_getQueueContainer: function (values) {
return new Ext.Container({
xtype: 'container',
layout: 'hbox',
hideLabel: true,
items: [
{
xtype: 'checkbox',
hideLabel: true,
id: values.idCheckbox,
boxLabel: _(values.labelCheckbox),
width: 175,
listeners: {
check: function (cb, checked) {
Ext.getCmp(values.nameRadio).setDisabled(!checked);
Ext.getCmp('not_' + values.nameRadio).setDisabled(
!checked
);
},
},
},
{
xtype: 'radio',
name: values.nameRadio,
id: values.nameRadio,
boxLabel: _(values.labelRadio.yes),
hideLabel: true,
checked: true,
disabled: true,
width: 50,
},
{
xtype: 'radio',
name: values.nameRadio,
id: 'not_' + values.nameRadio,
boxLabel: _(values.labelRadio.no),
hideLabel: true,
disabled: true,
},
],
});
},
});
@@ -0,0 +1,635 @@
/**
* label.js
*
* Copyright (C) Damien Churchill 2010 <damoxc@gmail.com>
*
* This file is part of Deluge and is licensed under GNU General Public License 3.0, or later, with
* the additional special exception to link portions of this program with the OpenSSL library.
* See LICENSE for more details.
*
*/
Ext.ns('Deluge.ux.preferences');
/**
* @class Deluge.ux.preferences.LabelPage
* @extends Ext.Panel
*/
Deluge.ux.preferences.LabelPage = Ext.extend(Ext.Panel, {
title: _('Label'),
layout: 'fit',
border: false,
initComponent: function () {
Deluge.ux.preferences.LabelPage.superclass.initComponent.call(this);
fieldset = this.add({
xtype: 'fieldset',
border: false,
title: _('Label Preferences'),
autoHeight: true,
labelWidth: 1,
defaultType: 'panel',
});
fieldset.add({
border: false,
bodyCfg: {
html: _(
'<p>The Label plugin is enabled.</p><br>' +
'<p>To add, remove or edit labels right-click on the Label filter ' +
'entry in the sidebar.</p><br>' +
'<p>To apply a label right-click on torrent(s).<p>'
),
},
});
},
});
Ext.ns('Deluge.ux');
/**
* @class Deluge.ux.AddLabelWindow
* @extends Ext.Window
*/
Deluge.ux.AddLabelWindow = Ext.extend(Ext.Window, {
title: _('Add Label'),
width: 300,
height: 100,
closeAction: 'hide',
initComponent: function () {
Deluge.ux.AddLabelWindow.superclass.initComponent.call(this);
this.addButton(_('Cancel'), this.onCancelClick, this);
this.addButton(_('Ok'), this.onOkClick, this);
this.form = this.add({
xtype: 'form',
height: 35,
baseCls: 'x-plain',
bodyStyle: 'padding:5px 5px 0',
defaultType: 'textfield',
labelWidth: 50,
items: [
{
fieldLabel: _('Name'),
name: 'name',
allowBlank: false,
width: 220,
listeners: {
specialkey: {
fn: function (field, e) {
if (e.getKey() == 13) this.onOkClick();
},
scope: this,
},
},
},
],
});
},
onCancelClick: function () {
this.hide();
},
onOkClick: function () {
var label = this.form.getForm().getValues().name;
deluge.client.label.add(label, {
success: function () {
deluge.ui.update();
this.fireEvent('labeladded', label);
},
scope: this,
});
this.hide();
},
onHide: function (comp) {
Deluge.ux.AddLabelWindow.superclass.onHide.call(this, comp);
this.form.getForm().reset();
},
onShow: function (comp) {
Deluge.ux.AddLabelWindow.superclass.onShow.call(this, comp);
this.form.getForm().findField('name').focus(false, 150);
},
});
/**
* @class Deluge.ux.LabelOptionsWindow
* @extends Ext.Window
*/
Deluge.ux.LabelOptionsWindow = Ext.extend(Ext.Window, {
title: _('Label Options'),
width: 325,
height: 240,
closeAction: 'hide',
initComponent: function () {
Deluge.ux.LabelOptionsWindow.superclass.initComponent.call(this);
this.addButton(_('Cancel'), this.onCancelClick, this);
this.addButton(_('Ok'), this.onOkClick, this);
this.form = this.add({
xtype: 'form',
});
this.tabs = this.form.add({
xtype: 'tabpanel',
height: 175,
border: false,
items: [
{
title: _('Maximum'),
items: [
{
border: false,
items: [
{
xtype: 'fieldset',
border: false,
labelWidth: 1,
style: 'margin-bottom: 0px; padding-bottom: 0px;',
items: [
{
xtype: 'checkbox',
name: 'apply_max',
fieldLabel: '',
boxLabel: _(
'Apply per torrent max settings:'
),
listeners: {
check: this.onFieldChecked,
},
},
],
},
{
xtype: 'fieldset',
border: false,
defaultType: 'spinnerfield',
style: 'margin-top: 0px; padding-top: 0px;',
items: [
{
fieldLabel: _('Download Speed'),
name: 'max_download_speed',
width: 80,
disabled: true,
value: -1,
minValue: -1,
},
{
fieldLabel: _('Upload Speed'),
name: 'max_upload_speed',
width: 80,
disabled: true,
value: -1,
minValue: -1,
},
{
fieldLabel: _('Upload Slots'),
name: 'max_upload_slots',
width: 80,
disabled: true,
value: -1,
minValue: -1,
},
{
fieldLabel: _('Connections'),
name: 'max_connections',
width: 80,
disabled: true,
value: -1,
minValue: -1,
},
],
},
],
},
],
},
{
title: _('Queue'),
items: [
{
border: false,
items: [
{
xtype: 'fieldset',
border: false,
labelWidth: 1,
style: 'margin-bottom: 0px; padding-bottom: 0px;',
items: [
{
xtype: 'checkbox',
name: 'apply_queue',
fieldLabel: '',
boxLabel: _(
'Apply queue settings:'
),
listeners: {
check: this.onFieldChecked,
},
},
],
},
{
xtype: 'fieldset',
border: false,
labelWidth: 1,
defaultType: 'checkbox',
style: 'margin-top: 0px; padding-top: 0px;',
defaults: {
style: 'margin-left: 20px',
},
items: [
{
boxLabel: _('Auto Managed'),
name: 'is_auto_managed',
disabled: true,
},
{
boxLabel: _('Stop seed at ratio:'),
name: 'stop_at_ratio',
disabled: true,
},
{
xtype: 'spinnerfield',
name: 'stop_ratio',
width: 60,
decimalPrecision: 2,
incrementValue: 0.1,
style: 'position: relative; left: 100px',
disabled: true,
},
{
boxLabel: _('Remove at ratio'),
name: 'remove_at_ratio',
disabled: true,
},
],
},
],
},
],
},
{
title: _('Folders'),
items: [
{
border: false,
items: [
{
xtype: 'fieldset',
border: false,
labelWidth: 1,
style: 'margin-bottom: 0px; padding-bottom: 0px;',
items: [
{
xtype: 'checkbox',
name: 'apply_move_completed',
fieldLabel: '',
boxLabel: _(
'Apply folder settings:'
),
listeners: {
check: this.onFieldChecked,
},
},
],
},
{
xtype: 'fieldset',
border: false,
labelWidth: 1,
defaultType: 'checkbox',
labelWidth: 1,
style: 'margin-top: 0px; padding-top: 0px;',
defaults: {
style: 'margin-left: 20px',
},
items: [
{
boxLabel: _('Move completed to:'),
name: 'move_completed',
disabled: true,
},
{
xtype: 'textfield',
name: 'move_completed_path',
width: 250,
disabled: true,
},
],
},
],
},
],
},
{
title: _('Trackers'),
items: [
{
border: false,
items: [
{
xtype: 'fieldset',
border: false,
labelWidth: 1,
style: 'margin-bottom: 0px; padding-bottom: 0px;',
items: [
{
xtype: 'checkbox',
name: 'auto_add',
fieldLabel: '',
boxLabel: _(
'Automatically apply label:'
),
listeners: {
check: this.onFieldChecked,
},
},
],
},
{
xtype: 'fieldset',
border: false,
labelWidth: 1,
style: 'margin-top: 0px; padding-top: 0px;',
defaults: {
style: 'margin-left: 20px',
},
defaultType: 'textarea',
items: [
{
boxLabel: _('Move completed to:'),
name: 'auto_add_trackers',
width: 250,
height: 100,
disabled: true,
},
],
},
],
},
],
},
],
});
},
getLabelOptions: function () {
deluge.client.label.get_options(this.label, {
success: this.gotOptions,
scope: this,
});
},
gotOptions: function (options) {
this.form.getForm().setValues(options);
},
show: function (label) {
Deluge.ux.LabelOptionsWindow.superclass.show.call(this);
this.label = label;
this.setTitle(_('Label Options') + ': ' + this.label);
this.tabs.setActiveTab(0);
this.getLabelOptions();
},
onCancelClick: function () {
this.hide();
},
onOkClick: function () {
var values = this.form.getForm().getFieldValues();
if (values['auto_add_trackers']) {
values['auto_add_trackers'] =
values['auto_add_trackers'].split('\n');
}
deluge.client.label.set_options(this.label, values);
this.hide();
},
onFieldChecked: function (field, checked) {
var fs = field.ownerCt.nextSibling();
fs.items.each(function (field) {
field.setDisabled(!checked);
});
},
});
Ext.ns('Deluge.plugins');
/**
* @class Deluge.plugins.LabelPlugin
* @extends Deluge.Plugin
*/
Deluge.plugins.LabelPlugin = Ext.extend(Deluge.Plugin, {
name: 'Label',
createMenu: function () {
this.labelMenu = new Ext.menu.Menu({
items: [
{
text: _('Add Label'),
iconCls: 'icon-add',
handler: this.onLabelAddClick,
scope: this,
},
{
text: _('Remove Label'),
disabled: true,
iconCls: 'icon-remove',
handler: this.onLabelRemoveClick,
scope: this,
},
{
text: _('Label Options'),
disabled: true,
handler: this.onLabelOptionsClick,
scope: this,
},
],
});
},
setFilter: function (filter) {
filter.show_zero = true;
filter.list.on('contextmenu', this.onLabelContextMenu, this);
filter.header.on('contextmenu', this.onLabelHeaderContextMenu, this);
this.filter = filter;
},
updateTorrentMenu: function (states) {
this.torrentMenu.removeAll(true);
this.torrentMenu.addMenuItem({
text: _('No Label'),
label: '',
handler: this.onTorrentMenuClick,
scope: this,
});
for (var state in states) {
if (!state || state == 'All') continue;
this.torrentMenu.addMenuItem({
text: state,
label: state,
handler: this.onTorrentMenuClick,
scope: this,
});
}
},
onDisable: function () {
deluge.sidebar.un('filtercreate', this.onFilterCreate);
deluge.sidebar.un('afterfiltercreate', this.onAfterFilterCreate);
delete Deluge.FilterPanel.templates.label;
this.deregisterTorrentStatus('label');
deluge.menus.torrent.remove(this.tmSep);
deluge.menus.torrent.remove(this.tm);
deluge.preferences.removePage(this.prefsPage);
},
onEnable: function () {
this.prefsPage = deluge.preferences.addPage(
new Deluge.ux.preferences.LabelPage()
);
this.torrentMenu = new Ext.menu.Menu();
this.tmSep = deluge.menus.torrent.add({
xtype: 'menuseparator',
});
this.tm = deluge.menus.torrent.add({
text: _('Label'),
menu: this.torrentMenu,
});
var lbltpl =
'<div class="x-deluge-filter">' +
'<tpl if="filter">{filter}</tpl>' +
'<tpl if="!filter">No Label</tpl>' +
' ({count})' +
'</div>';
if (deluge.sidebar.hasFilter('label')) {
var filter = deluge.sidebar.getFilter('label');
filter.list.columns[0].tpl = new Ext.XTemplate(lbltpl);
this.setFilter(filter);
this.updateTorrentMenu(filter.getStates());
filter.list.refresh();
} else {
deluge.sidebar.on('filtercreate', this.onFilterCreate, this);
deluge.sidebar.on(
'afterfiltercreate',
this.onAfterFilterCreate,
this
);
Deluge.FilterPanel.templates.label = lbltpl;
}
this.registerTorrentStatus('label', _('Label'));
},
onAfterFilterCreate: function (sidebar, filter) {
if (filter.filter != 'label') return;
this.updateTorrentMenu(filter.getStates());
},
onFilterCreate: function (sidebar, filter) {
if (filter.filter != 'label') return;
this.setFilter(filter);
},
onLabelAddClick: function () {
if (!this.addWindow) {
this.addWindow = new Deluge.ux.AddLabelWindow();
this.addWindow.on('labeladded', this.onLabelAdded, this);
}
this.addWindow.show();
},
onLabelAdded: function (label) {
var filter = deluge.sidebar.getFilter('label');
var states = filter.getStates();
var statesArray = [];
for (state in states) {
if (!state || state == 'All') continue;
statesArray.push(state);
}
statesArray.push(label.toLowerCase());
statesArray.sort();
//console.log(states);
//console.log(statesArray);
states = {};
for (i = 0; i < statesArray.length; ++i) {
states[statesArray[i]] = 0;
}
this.updateTorrentMenu(states);
},
onLabelContextMenu: function (dv, i, node, e) {
e.preventDefault();
if (!this.labelMenu) this.createMenu();
var r = dv.getRecord(node).get('filter');
if (!r || r == 'All') {
this.labelMenu.items.get(1).setDisabled(true);
this.labelMenu.items.get(2).setDisabled(true);
} else {
this.labelMenu.items.get(1).setDisabled(false);
this.labelMenu.items.get(2).setDisabled(false);
}
dv.select(i);
this.labelMenu.showAt(e.getXY());
},
onLabelHeaderContextMenu: function (e, t) {
e.preventDefault();
if (!this.labelMenu) this.createMenu();
this.labelMenu.items.get(1).setDisabled(true);
this.labelMenu.items.get(2).setDisabled(true);
this.labelMenu.showAt(e.getXY());
},
onLabelOptionsClick: function () {
if (!this.labelOpts)
this.labelOpts = new Deluge.ux.LabelOptionsWindow();
this.labelOpts.show(this.filter.getState());
},
onLabelRemoveClick: function () {
var state = this.filter.getState();
deluge.client.label.remove(state, {
success: function () {
deluge.ui.update();
this.torrentMenu.items.each(function (item) {
if (item.text != state) return;
this.torrentMenu.remove(item);
var i = item;
}, this);
},
scope: this,
});
},
onTorrentMenuClick: function (item, e) {
var ids = deluge.torrents.getSelectedIds();
Ext.each(ids, function (id, i) {
if (ids.length == i + 1) {
deluge.client.label.set_torrent(id, item.label, {
success: function () {
deluge.ui.update();
},
});
} else {
deluge.client.label.set_torrent(id, item.label);
}
});
},
});
Deluge.registerPlugin('Label', Deluge.plugins.LabelPlugin);
@@ -0,0 +1,522 @@
/**
* notifications.js
*
* Copyright (c) Omar Alvarez 2014 <omar.alvarez@udc.es>
*
* This file is part of Deluge and is licensed under GNU General Public License 3.0, or later, with
* the additional special exception to link portions of this program with the OpenSSL library.
* See LICENSE for more details.
*
*/
Ext.ns('Deluge.ux.preferences');
/**
* @class Deluge.ux.preferences.NotificationsPage
* @extends Ext.Panel
*/
Deluge.ux.preferences.NotificationsPage = Ext.extend(Ext.Panel, {
title: _('Notifications'),
header: false,
layout: 'fit',
border: false,
initComponent: function () {
Deluge.ux.preferences.NotificationsPage.superclass.initComponent.call(
this
);
this.emailNotiFset = new Ext.form.FieldSet({
xtype: 'fieldset',
border: false,
title: _('Email Notifications'),
autoHeight: true,
defaultType: 'textfield',
style: 'margin-top: 3px; margin-bottom: 0px; padding-bottom: 0px;',
width: '85%',
labelWidth: 1,
});
this.chkEnableEmail = this.emailNotiFset.add({
fieldLabel: '',
labelSeparator: '',
name: 'enable_email',
xtype: 'checkbox',
boxLabel: _('Enabled'),
listeners: {
check: function (object, checked) {
this.setSmtpDisabled(!checked);
},
scope: this,
},
});
this.hBoxHost = this.emailNotiFset.add({
fieldLabel: '',
labelSeparator: '',
name: 'host',
xtype: 'container',
layout: 'hbox',
disabled: true,
items: [
{
xtype: 'label',
text: _('Hostname:'),
margins: '6 0 0 6',
},
{
xtype: 'textfield',
margins: '2 0 0 4',
},
],
});
this.hBoxPort = this.emailNotiFset.add({
fieldLabel: '',
labelSeparator: '',
name: 'port',
xtype: 'container',
layout: 'hbox',
disabled: true,
items: [
{
xtype: 'label',
text: _('Port:'),
margins: '6 0 0 6',
},
{
xtype: 'spinnerfield',
margins: '2 0 0 34',
width: 64,
decimalPrecision: 0,
minValue: 0,
maxValue: 65535,
},
],
});
this.hBoxUser = this.emailNotiFset.add({
fieldLabel: '',
labelSeparator: '',
name: 'username',
xtype: 'container',
layout: 'hbox',
disabled: true,
items: [
{
xtype: 'label',
text: _('Username:'),
margins: '6 0 0 6',
},
{
xtype: 'textfield',
margins: '2 0 0 3',
},
],
});
this.hBoxPassword = this.emailNotiFset.add({
fieldLabel: '',
labelSeparator: '',
name: 'password',
xtype: 'container',
layout: 'hbox',
disabled: true,
items: [
{
xtype: 'label',
text: _('Password:'),
margins: '6 0 0 6',
},
{
xtype: 'textfield',
inputType: 'password',
margins: '2 0 0 5',
},
],
});
this.hBoxFrom = this.emailNotiFset.add({
fieldLabel: '',
labelSeparator: '',
name: 'from',
xtype: 'container',
layout: 'hbox',
disabled: true,
items: [
{
xtype: 'label',
text: _('From:'),
margins: '6 0 0 6',
},
{
xtype: 'textfield',
margins: '2 0 0 28',
},
],
});
this.chkTLS = this.emailNotiFset.add({
fieldLabel: '',
labelSeparator: '',
name: 'enable_tls_ssl',
xtype: 'checkbox',
disabled: true,
boxLabel: _('Server requires TLS/SSL'),
});
this.recipientsFset = new Ext.form.FieldSet({
xtype: 'fieldset',
border: false,
title: _('Recipients'),
autoHeight: true,
defaultType: 'editorgrid',
style: 'margin-top: 3px; margin-bottom: 0px; padding-bottom: 0px;',
autoWidth: true,
items: [
{
fieldLabel: '',
name: 'recipients',
margins: '2 0 5 5',
height: 130,
hideHeaders: true,
width: 260,
disabled: true,
autoExpandColumn: 'recipient',
bbar: {
items: [
{
text: _('Add'),
iconCls: 'icon-add',
handler: this.onAddClick,
scope: this,
},
{
text: _('Remove'),
iconCls: 'icon-remove',
handler: this.onRemoveClick,
scope: this,
},
],
},
viewConfig: {
emptyText: _('Add an recipient...'),
deferEmptyText: false,
},
colModel: new Ext.grid.ColumnModel({
columns: [
{
id: 'recipient',
header: _('Recipient'),
dataIndex: 'recipient',
sortable: true,
hideable: false,
editable: true,
editor: {
xtype: 'textfield',
},
},
],
}),
selModel: new Ext.grid.RowSelectionModel({
singleSelect: false,
moveEditorOnEnter: false,
}),
store: new Ext.data.ArrayStore({
autoDestroy: true,
fields: [{ name: 'recipient' }],
}),
listeners: {
afteredit: function (e) {
e.record.commit();
},
},
setEmptyText: function (text) {
if (this.viewReady) {
this.getView().emptyText = text;
this.getView().refresh();
} else {
Ext.apply(this.viewConfig, { emptyText: text });
}
},
loadData: function (data) {
this.getStore().loadData(data);
if (this.viewReady) {
this.getView().updateHeaders();
}
},
},
],
});
this.edGridSubs = new Ext.grid.EditorGridPanel({
xtype: 'editorgrid',
autoHeight: true,
autoExpandColumn: 'event',
viewConfig: {
emptyText: _('Loading events...'),
deferEmptyText: false,
},
colModel: new Ext.grid.ColumnModel({
defaults: {
renderer: function (
value,
meta,
record,
rowIndex,
colIndex,
store
) {
if (Ext.isNumber(value) && parseInt(value) !== value) {
return value.toFixed(6);
} else if (Ext.isBoolean(value)) {
return (
'<div class="x-grid3-check-col' +
(value ? '-on' : '') +
'" style="width: 20px;">&#160;</div>'
);
}
return value;
},
},
columns: [
{
id: 'event',
header: 'Event',
dataIndex: 'event',
sortable: true,
hideable: false,
},
{
id: 'email',
header: _('Email'),
dataIndex: 'email',
sortable: true,
hideable: false,
menuDisabled: true,
width: 40,
},
],
}),
store: new Ext.data.ArrayStore({
autoDestroy: true,
fields: [
{
name: 'event',
},
{
name: 'email',
},
],
}),
listeners: {
cellclick: function (grid, rowIndex, colIndex, e) {
var record = grid.getStore().getAt(rowIndex);
var field = grid.getColumnModel().getDataIndex(colIndex);
var value = record.get(field);
if (colIndex == 1) {
if (Ext.isBoolean(value)) {
record.set(field, !value);
record.commit();
}
}
},
beforeedit: function (e) {
if (Ext.isBoolean(e.value)) {
return false;
}
return e.record.get('enabled');
},
afteredit: function (e) {
e.record.commit();
},
},
setEmptyText: function (text) {
if (this.viewReady) {
this.getView().emptyText = text;
this.getView().refresh();
} else {
Ext.apply(this.viewConfig, { emptyText: text });
}
},
setSub: function (eventName) {
var store = this.getStore();
var index = store.find('event', eventName);
store.getAt(index).set('email', true);
store.getAt(index).commit();
},
loadData: function (data) {
this.getStore().loadData(data);
if (this.viewReady) {
this.getView().updateHeaders();
}
},
});
this.tabPanSettings = this.add({
xtype: 'tabpanel',
activeTab: 0,
items: [
{
title: _('Settings'),
items: [this.emailNotiFset, this.recipientsFset],
autoScroll: true,
},
{
title: _('Subscriptions'),
items: this.edGridSubs,
},
],
});
this.on('show', this.updateConfig, this);
},
updateConfig: function () {
deluge.client.notifications.get_handled_events({
success: function (events) {
var data = [];
var keys = Ext.keys(events);
for (var i = 0; i < keys.length; i++) {
var key = keys[i];
data.push([events[key][0], false]);
}
this.edGridSubs.loadData(data);
},
scope: this,
});
deluge.client.notifications.get_config({
success: function (config) {
this.chkEnableEmail.setValue(config['smtp_enabled']);
this.setSmtpDisabled(!config['smtp_enabled']);
this.hBoxHost.getComponent(1).setValue(config['smtp_host']);
this.hBoxPort.getComponent(1).setValue(config['smtp_port']);
this.hBoxUser.getComponent(1).setValue(config['smtp_user']);
this.hBoxPassword.getComponent(1).setValue(config['smtp_pass']);
this.hBoxFrom.getComponent(1).setValue(config['smtp_from']);
this.chkTLS.setValue(config['smtp_tls']);
var data = [];
var keys = Ext.keys(config['smtp_recipients']);
for (var i = 0; i < keys.length; i++) {
var key = keys[i];
data.push([config['smtp_recipients'][key]]);
}
this.recipientsFset.getComponent(0).loadData(data);
data = [];
keys = Ext.keys(config['subscriptions']['email']);
for (var i = 0; i < keys.length; i++) {
var key = keys[i];
this.edGridSubs.setSub(
config['subscriptions']['email'][key]
);
}
},
scope: this,
});
},
onApply: function () {
var config = {};
config['smtp_enabled'] = this.chkEnableEmail.getValue();
config['smtp_host'] = this.hBoxHost.getComponent(1).getValue();
config['smtp_port'] = Number(this.hBoxPort.getComponent(1).getValue());
config['smtp_user'] = this.hBoxUser.getComponent(1).getValue();
config['smtp_pass'] = this.hBoxPassword.getComponent(1).getValue();
config['smtp_from'] = this.hBoxFrom.getComponent(1).getValue();
config['smtp_tls'] = this.chkTLS.getValue();
var recipientsList = [];
var store = this.recipientsFset.getComponent(0).getStore();
for (var i = 0; i < store.getCount(); i++) {
var record = store.getAt(i);
var recipient = record.get('recipient');
recipientsList.push(recipient);
}
config['smtp_recipients'] = recipientsList;
var subscriptions = {};
var eventList = [];
store = this.edGridSubs.getStore();
for (var i = 0; i < store.getCount(); i++) {
var record = store.getAt(i);
var ev = record.get('event');
var email = record.get('email');
if (email) {
eventList.push(ev);
}
}
subscriptions['email'] = eventList;
config['subscriptions'] = subscriptions;
deluge.client.notifications.set_config(config);
},
onOk: function () {
this.onApply();
},
onAddClick: function () {
var store = this.recipientsFset.getComponent(0).getStore();
var Recipient = store.recordType;
var i = new Recipient({
recipient: '',
});
this.recipientsFset.getComponent(0).stopEditing();
store.insert(0, i);
this.recipientsFset.getComponent(0).startEditing(0, 0);
},
onRemoveClick: function () {
var selections = this.recipientsFset
.getComponent(0)
.getSelectionModel()
.getSelections();
var store = this.recipientsFset.getComponent(0).getStore();
this.recipientsFset.getComponent(0).stopEditing();
for (var i = 0; i < selections.length; i++) store.remove(selections[i]);
store.commitChanges();
},
setSmtpDisabled: function (disable) {
this.hBoxHost.setDisabled(disable);
this.hBoxPort.setDisabled(disable);
this.hBoxUser.setDisabled(disable);
this.hBoxPassword.setDisabled(disable);
this.hBoxFrom.setDisabled(disable);
this.chkTLS.setDisabled(disable);
this.recipientsFset.getComponent(0).setDisabled(disable);
},
onDestroy: function () {
deluge.preferences.un('show', this.updateConfig, this);
Deluge.ux.preferences.NotificationsPage.superclass.onDestroy.call(this);
},
});
Deluge.plugins.NotificationsPlugin = Ext.extend(Deluge.Plugin, {
name: 'Notifications',
onDisable: function () {
deluge.preferences.removePage(this.prefsPage);
},
onEnable: function () {
this.prefsPage = deluge.preferences.addPage(
new Deluge.ux.preferences.NotificationsPage()
);
},
});
Deluge.registerPlugin('Notifications', Deluge.plugins.NotificationsPlugin);
@@ -0,0 +1,621 @@
/**
* scheduler.js
* The client-side javascript code for the Scheduler plugin.
*
* Copyright (C) samuel337 2011
*
* This file is part of Deluge and is licensed under GNU General Public License 3.0, or later, with
* the additional special exception to link portions of this program with the OpenSSL library.
* See LICENSE for more details.
*
*/
Ext.ns('Deluge.ux');
Deluge.ux.ScheduleSelector = Ext.extend(Ext.form.FieldSet, {
title: _('Schedule'),
autoHeight: true,
style: 'margin-bottom: 0px; padding-bottom: 0px;',
border: false,
states: [
{
name: 'Normal',
backgroundColor: 'LightGreen',
borderColor: 'DarkGreen',
value: 0,
},
{
name: 'Throttled',
backgroundColor: 'Yellow',
borderColor: 'Gold',
value: 1,
},
{
name: 'Paused',
backgroundColor: 'OrangeRed',
borderColor: 'FireBrick',
value: 2,
},
],
daysOfWeek: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'],
initComponent: function () {
Deluge.ux.ScheduleSelector.superclass.initComponent.call(this);
// ExtJS' radiogroup implementation is very broken for styling.
/*this.stateBrush = this.add({
xtype: 'radiogroup',
fieldLabel: _('State Brush'),
name: 'current_state_brush',
submitValue: false,
items: [
{ boxLabel: 'Normal', name: 'current_state_brush', inputValue: 0 },
{ boxLabel: 'Throttled', name: 'current_state_brush', inputValue: 1, checked: true },
{ boxLabel: 'Paused', name: 'current_state_brush', inputValue: 2 },
]
});*/
},
onRender: function (ct, position) {
Deluge.ux.ScheduleSelector.superclass.onRender.call(this, ct, position);
var dom = this.body.dom;
function createEl(parent, type) {
var el = document.createElement(type);
parent.appendChild(el);
return el;
}
// create state brushes
// tack a random number to the end to avoid clashes
this.stateBrushName =
'schedule-state-brush-' + Math.round(Math.random() * 10000);
var el1 = createEl(dom, 'div');
var el2 = createEl(el1, 'div');
this.stateBrush = el2;
el2.id = this.stateBrushName;
// for webkit
var floatAttr = 'float';
if (el2.style.float == undefined) {
// for firefox
if (el2.style.cssFloat != undefined) floatAttr = 'cssFloat';
// for IE
if (el2.style.styleFloat != undefined) floatAttr = 'styleFloat';
}
el2.style[floatAttr] = 'right';
for (var i = 0; i < this.states.length; i++) {
var el3 = createEl(el2, 'input');
el3.type = 'radio';
el3.value = this.states[i].value;
el3.name = this.stateBrushName;
el3.id = this.stateBrushName + '-' + this.states[i].name;
// isn't the first one
if (i > 0) el3.style.marginLeft = '7px';
// assume the first is the default state, so make the 2nd one the default brush
if (i == 1) el3.checked = true;
var el4 = createEl(el2, 'label');
el4.appendChild(document.createTextNode(this.states[i].name));
el4.htmlFor = el3.id;
el4.style.backgroundColor = this.states[i].backgroundColor;
el4.style.borderBottom = '2px solid ' + this.states[i].borderColor;
el4.style.padding = '2px 3px';
el4.style.marginLeft = '3px';
}
el1.appendChild(document.createTextNode('Select a state brush:'));
el1.style.marginBottom = '10px';
// keep the radio buttons separate from the time bars
createEl(dom, 'div').style.clear = 'both';
var table = createEl(dom, 'table');
table.cellSpacing = 0;
// cache access to cells for easier access later
this.scheduleCells = {};
Ext.each(
this.daysOfWeek,
function (day) {
var cells = [];
var row = createEl(table, 'tr');
var label = createEl(row, 'th');
label.setAttribute(
'style',
'font-weight: bold; padding-right: 5px;'
);
label.appendChild(document.createTextNode(day));
for (var hour = 0; hour < 24; hour++) {
var cell = createEl(row, 'td');
// assume the first state is the default state
cell.currentValue = cell.oldValue = this.states[0].value;
cell.day = day;
cell.hour = hour;
cell.width = '16px';
cell.height = '20px';
cell.style.border = '1px solid #999999';
// don't repeat borders in between cells
if (hour != 23)
// not the last cell
cell.style.borderRight = 'none';
this.updateCell(cell);
cells.push(cell);
cell = Ext.get(cell);
cell.on('click', this.onCellClick, this);
cell.on('mouseover', this.onCellMouseOver, this);
cell.on('mouseout', this.onCellMouseOut, this);
cell.on('mousedown', this.onCellMouseDown, this);
cell.on('mouseup', this.onCellMouseUp, this);
}
// insert gap row to provide visual separation
row = createEl(table, 'tr');
// blank cell to create gap
createEl(row, 'td').height = '3px';
this.scheduleCells[day] = cells;
},
this
);
},
updateCell: function (cell) {
// sanity check
if (cell.currentValue == undefined) return;
for (var i in this.states) {
var curState = this.states[i];
if (curState.value == cell.currentValue) {
cell.style.background = curState.backgroundColor;
break;
}
}
},
getCurrentBrushValue: function () {
var v = null;
var brushes = Ext.get(this.body.dom).findParent('form').elements[
this.stateBrushName
];
Ext.each(brushes, function (b) {
if (b.checked) v = b.value;
});
return v;
},
onCellClick: function (event, cell) {
cell.oldValue = cell.currentValue;
this.dragAnchor = null;
},
onCellMouseDown: function (event, cell) {
this.dragAnchor = cell;
},
onCellMouseUp: function (event, cell) {
// if we're dragging...
if (this.dragAnchor) {
// set all those between here and the anchor to the new values
if (cell.hour > this.dragAnchor.hour)
this.confirmCells(cell.day, this.dragAnchor.hour, cell.hour);
else if (cell.hour < this.dragAnchor.hour)
this.confirmCells(cell.day, cell.hour, this.dragAnchor.hour);
else this.confirmCells(cell.day, cell.hour, cell.hour);
this.hideCellLeftTooltip();
this.hideCellRightTooltip();
this.dragAnchor = null;
}
},
onCellMouseOver: function (event, cell) {
// LEFT TOOL TIP
// if it isn't showing and we're dragging, show it.
// otherwise if dragging, leave it alone unless we're dragging to the left.
// if we're not dragging, show it.
var leftTooltipCell = null;
if (!this.dragAnchor) leftTooltipCell = cell;
else if (
(this.dragAnchor && this.isCellLeftTooltipHidden()) ||
(this.dragAnchor && this.dragAnchor.hour > cell.hour)
)
leftTooltipCell = this.dragAnchor;
if (leftTooltipCell) {
var hour = leftTooltipCell.hour;
var pm = false;
// convert to 12-hour time
if (hour >= 12) {
pm = true;
if (hour > 12) hour -= 12;
} else if (hour == 0) {
// change 0 hour to 12am
hour = 12;
}
this.showCellLeftTooltip(
hour + ' ' + (pm ? 'pm' : 'am'),
leftTooltipCell
);
}
// RIGHT TOOL TIP
var rightTooltipCell = null;
if (this.dragAnchor) {
if (this.dragAnchor.hour == cell.hour) this.hideCellRightTooltip();
else if (
this.dragAnchor.hour > cell.hour &&
this.isCellRightTooltipHidden()
)
rightTooltipCell = this.dragAnchor;
// cell.hour > this.dragAnchor.hour
else rightTooltipCell = cell;
}
if (rightTooltipCell) {
var hour = rightTooltipCell.hour;
var pm = false;
// convert to 12-hour time
if (hour >= 12) {
pm = true;
if (hour > 12) hour -= 12;
} else if (hour == 0) {
// change 0 hour to 12am
hour = 12;
}
this.showCellRightTooltip(
hour + ' ' + (pm ? 'pm' : 'am'),
rightTooltipCell
);
}
// preview colour change and
// revert state for all those on the outer side of the drag if dragging
if (this.dragAnchor) {
if (cell.day != this.dragAnchor.day) {
// dragged into another day. Abort! Abort!
Ext.each(
this.daysOfWeek,
function (day) {
this.revertCells(day, 0, 23);
},
this
);
this.dragAnchor = null;
this.hideCellLeftTooltip();
this.hideCellRightTooltip();
} else if (cell.hour > this.dragAnchor.hour) {
// dragging right
this.revertCells(cell.day, cell.hour + 1, 23);
this.previewCells(cell.day, this.dragAnchor.hour, cell.hour);
} else if (cell.hour < this.dragAnchor.hour) {
// dragging left
this.revertCells(cell.day, 0, cell.hour - 1);
this.previewCells(cell.day, cell.hour, this.dragAnchor.hour);
} else {
// back to anchor cell
// don't know if it is from right or left, so revert all except this
this.revertCells(cell.day, cell.hour + 1, 23);
this.revertCells(cell.day, 0, cell.hour - 1);
}
} else {
// not dragging, just preview this cell
this.previewCells(cell.day, cell.hour, cell.hour);
}
},
onCellMouseOut: function (event, cell) {
if (!this.dragAnchor) this.hideCellLeftTooltip();
// revert state. If new state has been set, old and new will be equal.
// if dragging, this will be handled by the next mouse over
if (this.dragAnchor == null && cell.oldValue != cell.currentValue) {
this.revertCells(cell.day, cell.hour, cell.hour);
}
},
previewCells: function (day, fromHour, toHour) {
var cells = this.scheduleCells[day];
var curBrushValue = this.getCurrentBrushValue();
if (toHour > cells.length) toHour = cells.length;
for (var i = fromHour; i <= toHour; i++) {
if (cells[i].currentValue != curBrushValue) {
cells[i].oldValue = cells[i].currentValue;
cells[i].currentValue = curBrushValue;
this.updateCell(cells[i]);
}
}
},
revertCells: function (day, fromHour, toHour) {
var cells = this.scheduleCells[day];
if (toHour > cells.length) toHour = cells.length;
for (var i = fromHour; i <= toHour; i++) {
cells[i].currentValue = cells[i].oldValue;
this.updateCell(cells[i]);
}
},
confirmCells: function (day, fromHour, toHour) {
var cells = this.scheduleCells[day];
if (toHour > cells.length) toHour = cells.length;
for (var i = fromHour; i <= toHour; i++) {
if (cells[i].currentValue != cells[i].oldValue) {
cells[i].oldValue = cells[i].currentValue;
}
}
},
showCellLeftTooltip: function (text, cell) {
var tooltip = this.cellLeftTooltip;
if (!tooltip) {
// no cached left tooltip exists, create one
tooltip = document.createElement('div');
this.cellLeftTooltip = tooltip;
this.body.dom.appendChild(tooltip);
tooltip.style.position = 'absolute';
tooltip.style.backgroundColor = '#F2F2F2';
tooltip.style.border = '1px solid #333333';
tooltip.style.padding = '1px 3px';
tooltip.style.opacity = 0.8;
}
// remove all existing children
while (tooltip.childNodes.length > 0) {
tooltip.removeChild(tooltip.firstChild);
}
// add the requested text
tooltip.appendChild(document.createTextNode(text));
// place the tooltip
Ext.get(tooltip).alignTo(cell, 'br-tr');
// make it visible
tooltip.style.visibility = 'visible';
},
hideCellLeftTooltip: function () {
if (this.cellLeftTooltip) {
this.cellLeftTooltip.style.visibility = 'hidden';
}
},
isCellLeftTooltipHidden: function () {
if (this.cellLeftTooltip)
return this.cellLeftTooltip.style.visibility == 'hidden';
else return true;
},
showCellRightTooltip: function (text, cell) {
var tooltip = this.cellRightTooltip;
if (!tooltip) {
// no cached left tooltip exists, create one
tooltip = document.createElement('div');
this.cellRightTooltip = tooltip;
this.body.dom.appendChild(tooltip);
tooltip.style.position = 'absolute';
tooltip.style.backgroundColor = '#F2F2F2';
tooltip.style.border = '1px solid #333333';
tooltip.style.padding = '1px 3px';
tooltip.style.opacity = 0.8;
}
// remove all existing children
while (tooltip.childNodes.length > 0) {
tooltip.removeChild(tooltip.firstChild);
}
// add the requested text
tooltip.appendChild(document.createTextNode(text));
// place the tooltip
Ext.get(tooltip).alignTo(cell, 'bl-tl');
// make it visible
tooltip.style.visibility = 'visible';
},
hideCellRightTooltip: function () {
if (this.cellRightTooltip) {
this.cellRightTooltip.style.visibility = 'hidden';
}
},
isCellRightTooltipHidden: function () {
if (this.cellRightTooltip)
return this.cellRightTooltip.style.visibility == 'hidden';
else return true;
},
getConfig: function () {
var config = [];
for (var i = 0; i < 24; i++) {
var hourConfig = [0, 0, 0, 0, 0, 0, 0];
for (var j = 0; j < this.daysOfWeek.length; j++) {
hourConfig[j] = parseInt(
this.scheduleCells[this.daysOfWeek[j]][i].currentValue
);
}
config.push(hourConfig);
}
return config;
},
setConfig: function (config) {
for (var i = 0; i < 24; i++) {
var hourConfig = config[i];
for (var j = 0; j < this.daysOfWeek.length; j++) {
if (this.scheduleCells == undefined) {
var cell = hourConfig[j];
} else {
var cell = this.scheduleCells[this.daysOfWeek[j]][i];
}
cell.currentValue = cell.oldValue = hourConfig[j];
this.updateCell(cell);
}
}
},
});
Ext.ns('Deluge.ux.preferences');
Deluge.ux.preferences.SchedulerPage = Ext.extend(Ext.Panel, {
border: false,
title: _('Scheduler'),
header: false,
layout: 'fit',
initComponent: function () {
Deluge.ux.preferences.SchedulerPage.superclass.initComponent.call(this);
this.form = this.add({
xtype: 'form',
layout: 'form',
border: false,
autoHeight: true,
});
this.schedule = this.form.add(new Deluge.ux.ScheduleSelector());
this.slowSettings = this.form.add({
xtype: 'fieldset',
border: false,
title: _('Throttled Settings'),
autoHeight: true,
defaultType: 'spinnerfield',
defaults: {
minValue: -1,
maxValue: 99999,
},
style: 'margin-top: 5px; margin-bottom: 0px; padding-bottom: 0px;',
labelWidth: 200,
});
this.downloadLimit = this.slowSettings.add({
fieldLabel: _('Maximum Download Speed (KiB/s)'),
name: 'download_limit',
width: 80,
value: -1,
decimalPrecision: 0,
});
this.uploadLimit = this.slowSettings.add({
fieldLabel: _('Maximum Upload Speed (KiB/s)'),
name: 'upload_limit',
width: 80,
value: -1,
decimalPrecision: 0,
});
this.activeTorrents = this.slowSettings.add({
fieldLabel: _('Active Torrents'),
name: 'active_torrents',
width: 80,
value: -1,
decimalPrecision: 0,
});
this.activeDownloading = this.slowSettings.add({
fieldLabel: _('Active Downloading'),
name: 'active_downloading',
width: 80,
value: -1,
decimalPrecision: 0,
});
this.activeSeeding = this.slowSettings.add({
fieldLabel: _('Active Seeding'),
name: 'active_seeding',
width: 80,
value: -1,
decimalPrecision: 0,
});
this.on('show', this.updateConfig, this);
},
onRender: function (ct, position) {
Deluge.ux.preferences.SchedulerPage.superclass.onRender.call(
this,
ct,
position
);
this.form.layout = new Ext.layout.FormLayout();
this.form.layout.setContainer(this);
this.form.doLayout();
},
onApply: function () {
// build settings object
var config = {};
config['button_state'] = this.schedule.getConfig();
config['low_down'] = this.downloadLimit.getValue();
config['low_up'] = this.uploadLimit.getValue();
config['low_active'] = this.activeTorrents.getValue();
config['low_active_down'] = this.activeDownloading.getValue();
config['low_active_up'] = this.activeSeeding.getValue();
deluge.client.scheduler.set_config(config);
},
onOk: function () {
this.onApply();
},
updateConfig: function () {
deluge.client.scheduler.get_config({
success: function (config) {
this.schedule.setConfig(config['button_state']);
this.downloadLimit.setValue(config['low_down']);
this.uploadLimit.setValue(config['low_up']);
this.activeTorrents.setValue(config['low_active']);
this.activeDownloading.setValue(config['low_active_down']);
this.activeSeeding.setValue(config['low_active_up']);
},
scope: this,
});
},
});
Deluge.plugins.SchedulerPlugin = Ext.extend(Deluge.Plugin, {
name: 'Scheduler',
onDisable: function () {
deluge.preferences.removePage(this.prefsPage);
},
onEnable: function () {
this.prefsPage = deluge.preferences.addPage(
new Deluge.ux.preferences.SchedulerPage()
);
},
});
Deluge.registerPlugin('Scheduler', Deluge.plugins.SchedulerPlugin);
@@ -0,0 +1,27 @@
/**
* Script: stats.js
* The javascript client-side code for the Stats plugin.
*
* Copyright (c) Damien Churchill 2009-2010 <damoxc@gmail.com>
*
* This file is part of Deluge and is licensed under GNU General Public License 3.0, or later, with
* the additional special exception to link portions of this program with the OpenSSL library.
* See LICENSE for more details.
*/
StatsPlugin = Ext.extend(Deluge.Plugin, {
constructor: function (config) {
config = Ext.apply(
{
name: 'Stats',
},
config
);
StatsPlugin.superclass.constructor.call(this, config);
},
onDisable: function () {},
onEnable: function () {},
});
new StatsPlugin();
@@ -0,0 +1,27 @@
/**
* Script: toggle.js
* The client-side javascript code for the Toggle plugin.
*
* Copyright (C) John Garland 2010 <johnnybg+deluge@gmail.com>
*
* This file is part of Deluge and is licensed under GNU General Public License 3.0, or later, with
* the additional special exception to link portions of this program with the OpenSSL library.
* See LICENSE for more details.
*/
TogglePlugin = Ext.extend(Deluge.Plugin, {
constructor: function (config) {
config = Ext.apply(
{
name: 'Toggle',
},
config
);
TogglePlugin.superclass.constructor.call(this, config);
},
onDisable: function () {},
onEnable: function () {},
});
new TogglePlugin();
Binary file not shown.