Compare commits
51 Commits
master
...
extjs4-por
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6892834d4d | ||
|
|
609f54a704 | ||
|
|
fa08f7de43 | ||
|
|
a91037843b | ||
|
|
4a43d6a635 | ||
|
|
1837d833c2 | ||
|
|
e3e20aa14f | ||
|
|
c865486f82 | ||
|
|
c06d4dfea5 | ||
|
|
c405425993 | ||
|
|
d10752fc1a | ||
|
|
ab665384d4 | ||
|
|
f5e6eabee4 | ||
|
|
717e66b836 | ||
|
|
fea0b41425 | ||
|
|
d37c3e0213 | ||
|
|
b724f74700 | ||
|
|
d44a357284 | ||
|
|
d6715fcbb9 | ||
|
|
2853d028fd | ||
|
|
4ab5c6d9de | ||
|
|
f53dc5faaf | ||
|
|
c46bc049d1 | ||
|
|
39d19b5afd | ||
|
|
e8506b925f | ||
|
|
eb9071fcb0 | ||
|
|
9362ec0103 | ||
|
|
fe0332bccf | ||
|
|
64bacbfbf4 | ||
|
|
280377ad6f | ||
|
|
0c3d2322cc | ||
|
|
07b6db0c98 | ||
|
|
713953ec03 | ||
|
|
6324737031 | ||
|
|
428681aca3 | ||
|
|
317e9ee423 | ||
|
|
08e774bbda | ||
|
|
43cb787b44 | ||
|
|
fb8f1e7ebc | ||
|
|
881bcee160 | ||
|
|
42b8af25aa | ||
|
|
bf4b826809 | ||
|
|
8ae14de208 | ||
|
|
5b45670a85 | ||
|
|
6cdf9940d3 | ||
|
|
8b69d66bae | ||
|
|
3ee434975c | ||
|
|
dda4620d98 | ||
|
|
7ac0083239 | ||
|
|
6ae58248a1 | ||
|
|
1c78bcbb29 |
46
deluge/tests/test_file_tree.py
Normal file
46
deluge/tests/test_file_tree.py
Normal file
@ -0,0 +1,46 @@
|
||||
from twisted.trial import unittest
|
||||
from deluge.ui.common import ExtFileTree
|
||||
|
||||
class ExtFileTreeTestCase(unittest.TestCase):
|
||||
|
||||
def test_simple_tree(self):
|
||||
paths = [
|
||||
"SomeRootFolder/file1",
|
||||
"SomeRootFolder/file2",
|
||||
"SomeRootFolder/subfolder1/subfile1",
|
||||
"SomeRootFolder/subfolder1/subfile2"
|
||||
]
|
||||
tree = ExtFileTree(paths)
|
||||
self.assertEqual(tree.tree, {"children": [
|
||||
{"text": "SomeRootFolder", "children": [
|
||||
{"text": "file1"},
|
||||
{"text": "file2"},
|
||||
{"text": "subfolder1", "children": [
|
||||
{"text": "subfile1"},
|
||||
{"text": "subfile2"}
|
||||
]}
|
||||
]}
|
||||
], "text": ""})
|
||||
|
||||
def test_tree_walk(self):
|
||||
paths = [
|
||||
"SomeRootFolder/file1",
|
||||
"SomeRootFolder/file2",
|
||||
"SomeRootFolder/subfolder1/subfile1",
|
||||
"SomeRootFolder/subfolder1/subfile2"
|
||||
]
|
||||
tree = ExtFileTree(paths)
|
||||
for path, obj in tree.walk():
|
||||
if path == "SomeRootFolder/file1":
|
||||
obj["size"] = 1024
|
||||
|
||||
self.assertEqual(tree.tree, {"children": [
|
||||
{"text": "SomeRootFolder", "children": [
|
||||
{"text": "file1", "size": 1024},
|
||||
{"text": "file2"},
|
||||
{"text": "subfolder1", "children": [
|
||||
{"text": "subfile1"},
|
||||
{"text": "subfile2"}
|
||||
]}
|
||||
]}
|
||||
], "text": ""})
|
||||
@ -244,6 +244,83 @@ class TorrentInfo(object):
|
||||
"""
|
||||
return self.__m_filedata
|
||||
|
||||
class ExtFileTree(object):
|
||||
"""
|
||||
Convert a list of paths into a compatible file tree format for Ext.
|
||||
|
||||
:param paths: The paths to be converted
|
||||
:type paths: list
|
||||
"""
|
||||
|
||||
def __init__(self, paths):
|
||||
self.tree = {"children": [], "text": ""}
|
||||
|
||||
def get_parent(path):
|
||||
parent = self.tree
|
||||
while "/" in path:
|
||||
directory, sep, path = path.partition("/")
|
||||
new_parent = None
|
||||
for child in parent["children"]:
|
||||
if child["text"] == directory:
|
||||
new_parent = child
|
||||
if not new_parent:
|
||||
new_parent = {"children": [], "text": directory}
|
||||
parent["children"].append(new_parent)
|
||||
parent = new_parent
|
||||
return parent, path
|
||||
|
||||
for path in paths:
|
||||
if path[-1] == "/":
|
||||
path = path[:-1]
|
||||
parent, path = get_parent(path)
|
||||
parent["children"].append({
|
||||
"text": path,
|
||||
"children": []
|
||||
})
|
||||
else:
|
||||
parent, path = get_parent(path)
|
||||
parent["children"].append({"text": path})
|
||||
|
||||
def get_tree(self):
|
||||
"""
|
||||
Return the tree.
|
||||
|
||||
:returns: the file tree.
|
||||
:rtype: dictionary
|
||||
"""
|
||||
return self.tree
|
||||
|
||||
def walk(self):
|
||||
"""
|
||||
Walk through the file tree calling the callback function on each item
|
||||
contained.
|
||||
|
||||
:param callback: The function to be used as a callback, it should have
|
||||
the signature func(item, path) where item is a `tuple` for a file
|
||||
and `dict` for a directory.
|
||||
:type callback: function
|
||||
"""
|
||||
for path, child in self.__walk(self.tree, ""):
|
||||
yield path, child
|
||||
|
||||
def __walk(self, directory, parent_path):
|
||||
for item in directory["children"]:
|
||||
path = path_join(parent_path, item["text"])
|
||||
if "children" in item:
|
||||
for path, child in self.__walk(item, path):
|
||||
yield path, child
|
||||
yield path, item
|
||||
|
||||
def __str__(self):
|
||||
lines = []
|
||||
def write(path, item):
|
||||
depth = path.count("/")
|
||||
path = os.path.basename(path)
|
||||
path = path + "/" if item["type"] == "dir" else path
|
||||
lines.append(" " * depth + path)
|
||||
self.walk(write)
|
||||
return "\n".join(lines)
|
||||
|
||||
class FileTree2(object):
|
||||
"""
|
||||
Converts a list of paths in to a file tree.
|
||||
|
||||
@ -51,11 +51,14 @@ import time
|
||||
import random
|
||||
import hashlib
|
||||
import logging
|
||||
|
||||
from datetime import datetime, timedelta
|
||||
from email.utils import formatdate
|
||||
from types import FunctionType
|
||||
|
||||
from twisted.internet.defer import Deferred
|
||||
from twisted.internet.task import LoopingCall
|
||||
from twisted.web.http import FORBIDDEN
|
||||
|
||||
from deluge import component
|
||||
from deluge.ui.web.json_api import JSONComponent, export
|
||||
@ -89,6 +92,29 @@ def make_expires(timeout):
|
||||
expires_str = formatdate(timeval=expires, localtime=False, usegmt=True)
|
||||
return expires, expires_str
|
||||
|
||||
def secure(auth_level=AUTH_LEVEL_DEFAULT):
|
||||
"""
|
||||
Decorator function to secure a Twisted resource ensuring that the
|
||||
user is authenticated with the web interface.
|
||||
"""
|
||||
def wrap(func, *args, **kwargs):
|
||||
def secure_render(self, request):
|
||||
try:
|
||||
component.get("Auth").check_request(request,
|
||||
level=auth_level)
|
||||
except AuthError:
|
||||
request.setResponseCode(FORBIDDEN)
|
||||
return "<h1>Forbidden</h1>"
|
||||
return func(self, request)
|
||||
return secure_render
|
||||
|
||||
if type(auth_level) is FunctionType:
|
||||
func = auth_level
|
||||
auth_level = AUTH_LEVEL_DEFAULT
|
||||
return wrap(func)
|
||||
else:
|
||||
return wrap
|
||||
|
||||
class Auth(JSONComponent):
|
||||
"""
|
||||
The component that implements authentification into the JSON interface.
|
||||
@ -136,7 +162,7 @@ class Auth(JSONComponent):
|
||||
checksum = str(make_checksum(session_id))
|
||||
|
||||
request.addCookie('_session_id', session_id + checksum,
|
||||
path=request.base+"json", expires=expires_str)
|
||||
path=request.base, expires=expires_str)
|
||||
|
||||
log.debug("Creating session for %s", login)
|
||||
config = component.get("DelugeWeb").config
|
||||
@ -233,7 +259,7 @@ class Auth(JSONComponent):
|
||||
|
||||
_session_id = request.getCookie("_session_id")
|
||||
request.addCookie('_session_id', _session_id,
|
||||
path=request.base+"json", expires=expires_str)
|
||||
path=request.base, expires=expires_str)
|
||||
|
||||
if method:
|
||||
if not hasattr(method, "_json_export"):
|
||||
|
||||
@ -37,6 +37,8 @@ import zlib
|
||||
import gettext
|
||||
from deluge import common
|
||||
|
||||
from twisted.web.resource import Resource as _Resource
|
||||
|
||||
_ = lambda x: gettext.gettext(x).decode("utf-8")
|
||||
|
||||
def escape(text):
|
||||
@ -86,3 +88,10 @@ except ImportError:
|
||||
raise RuntimeError(
|
||||
"The Mako library is required to run deluge.ui.web"
|
||||
)
|
||||
|
||||
class Resource(_Resource):
|
||||
|
||||
def render(self, request):
|
||||
request.setHeader("x-powered-by", "Rum")
|
||||
request.setHeader("x-accept-rum",
|
||||
"Morgans Spiced, Sailor Jerry, Bundaberg")
|
||||
|
||||
@ -11,13 +11,55 @@ input {
|
||||
color: Black;
|
||||
}
|
||||
|
||||
#loading-mask {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
z-index: 20000;
|
||||
background-color: white;
|
||||
}
|
||||
|
||||
#loading {
|
||||
position: absolute;
|
||||
left: 50%;
|
||||
top: 50%;
|
||||
padding: 2px;
|
||||
z-index: 20001;
|
||||
height: auto;
|
||||
margin: -35px 0 0 -30px;
|
||||
}
|
||||
|
||||
#loading .loading-indicator {
|
||||
background: url('../images/loading.gif') no-repeat;
|
||||
color: #555;
|
||||
font: 24px "UbuntuBeta Regular",Ubuntu,"Bitstream Vera Sans","DejaVu Sans",Tahoma,sans-serif;
|
||||
padding: 2px 42px;
|
||||
margin: 0;
|
||||
text-align: center;
|
||||
height: auto;
|
||||
}
|
||||
|
||||
.x-deluge-dropzone {
|
||||
position: absolute;
|
||||
z-index: 1;
|
||||
margin: 10px;
|
||||
border: 2px dashed black;
|
||||
width: 420px;
|
||||
height: 110px;
|
||||
line-height: 110px;
|
||||
text-align: center;
|
||||
font-size: 2em;
|
||||
}
|
||||
|
||||
.x-deluge-main-panel {
|
||||
background-image: url('../icons/deluge.png');
|
||||
}
|
||||
|
||||
.deluge-torrents td, .x-deluge-peers td {
|
||||
height: 16px;
|
||||
line-height: 16px;
|
||||
line-height: 16px !important;
|
||||
}
|
||||
|
||||
.deluge-torrents .torrent-name, .x-deluge-peer, .x-deluge-seed {
|
||||
@ -49,6 +91,18 @@ input {
|
||||
.x-deluge-install-plugin, .x-btn .x-deluge-install-plugin {background-image: url('../icons/install_plugin.png'); }
|
||||
.x-deluge-find-more, .x-btn .x-deluge-find-more {background-image: url('../icons/find_more.png'); }
|
||||
|
||||
.x-status-item {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.x-status-label {
|
||||
font-weight: bold;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.x-status-text {
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
/* Torrent Details */
|
||||
#torrentDetails dl, dl.singleline {
|
||||
@ -81,41 +135,6 @@ dl.singleline dd {
|
||||
background: White;
|
||||
}
|
||||
|
||||
/* Torrent Details - Status Tab */
|
||||
.x-deluge-status-progressbar {
|
||||
margin: 5px;
|
||||
}
|
||||
|
||||
.x-deluge-status {
|
||||
margin: 10px;
|
||||
}
|
||||
|
||||
.x-deluge-status dd.downloaded,
|
||||
.x-deluge-status dd.uploaded,
|
||||
.x-deluge-status dd.share,
|
||||
.x-deluge-status dd.announce,
|
||||
.x-deluge-status dd.tracker_status {
|
||||
width: 200px;
|
||||
margin-left: 100px;
|
||||
}
|
||||
|
||||
.x-deluge-status dd.downspeed,
|
||||
.x-deluge-status dd.upspeed,
|
||||
.x-deluge-status dd.eta,
|
||||
.x-deluge-status dd.pieces {
|
||||
margin-left: 100px;
|
||||
}
|
||||
|
||||
.x-deluge-status dd.active_time,
|
||||
.x-deluge-status dd.seeding_time,
|
||||
.x-deluge-status dd.seed_rank,
|
||||
.x-deluge-status dd.time_added {
|
||||
width: 100px;
|
||||
}
|
||||
.x-deluge-status dd.last_seen_complete {
|
||||
width: 100px;
|
||||
}
|
||||
|
||||
/* Torrent Details - Details Tab */
|
||||
#torrentDetails dd.torrent_name,
|
||||
#torrentDetails dd.status,
|
||||
@ -147,7 +166,7 @@ dl.singleline dd {
|
||||
.x-deluge-add-torrent-name-loading {
|
||||
padding-left: 20px;
|
||||
line-height: 20px;
|
||||
background: url('/themes/default/tree/loading.gif') no-repeat 2px;
|
||||
background: url('/resources/themes/images/default/tree/loading.gif') no-repeat 2px;
|
||||
}
|
||||
|
||||
/* Add Url Window */
|
||||
@ -290,130 +309,3 @@ dl.singleline dd {
|
||||
.x-mixed-download {
|
||||
/*background-image: url(../icons/mixed.png);*/
|
||||
}
|
||||
|
||||
/**
|
||||
* Deluge Default Icon Set
|
||||
* n.b. this needs to be forked out at some point
|
||||
*/
|
||||
|
||||
.icon-create {
|
||||
background-image: url('../icons/create.png') !important;
|
||||
}
|
||||
|
||||
.icon-add {
|
||||
background-image: url('../icons/add.png') !important;
|
||||
}
|
||||
|
||||
.icon-add-url {
|
||||
background-image: url('../icons/add_url.png') !important;
|
||||
}
|
||||
|
||||
.icon-add-magnet {
|
||||
background-image: url('../icons/add_magnet.png') !important;
|
||||
}
|
||||
|
||||
|
||||
|
||||
.icon-pause {
|
||||
background-image: url('../icons/pause.png') !important;
|
||||
}
|
||||
|
||||
.icon-resume {
|
||||
background-image: url('../icons/start.png') !important;
|
||||
}
|
||||
|
||||
.icon-options {
|
||||
background-image: url('../icons/preferences.png') !important;
|
||||
}
|
||||
|
||||
.icon-queue {
|
||||
background-image: url('../icons/queue.png') !important;
|
||||
}
|
||||
|
||||
.icon-top {
|
||||
background-image: url('../icons/top.png') !important;
|
||||
}
|
||||
|
||||
.icon-up {
|
||||
background-image: url('../icons/up.png') !important;
|
||||
}
|
||||
|
||||
.icon-down {
|
||||
background-image: url('../icons/down.png') !important;
|
||||
}
|
||||
|
||||
.icon-bottom {
|
||||
background-image: url('../icons/bottom.png') !important;
|
||||
}
|
||||
|
||||
.icon-update-tracker {
|
||||
background-image: url('../icons/update.png') !important;
|
||||
}
|
||||
|
||||
.icon-edit-trackers, .icon-edit {
|
||||
background-image: url('../icons/edit_trackers.png') !important;
|
||||
}
|
||||
|
||||
.icon-remove {
|
||||
background-image: url('../icons/remove.png') !important;
|
||||
}
|
||||
|
||||
.icon-recheck {
|
||||
background-image: url('../icons/recheck.png') !important;
|
||||
}
|
||||
|
||||
.icon-move {
|
||||
background-image: url('../icons/move.png') !important;
|
||||
}
|
||||
|
||||
.icon-help {
|
||||
background-image: url('../icons/help.png') !important;
|
||||
}
|
||||
|
||||
.icon-logout {
|
||||
background-image: url('../icons/logout.png') !important;
|
||||
}
|
||||
|
||||
.icon-back {
|
||||
background-image: url('../icons/back.png') !important;
|
||||
}
|
||||
|
||||
.icon-forward {
|
||||
background-image: url('../icons/forward.png') !important;
|
||||
}
|
||||
|
||||
.icon-home {
|
||||
background-image: url('../icons/home.png') !important;
|
||||
}
|
||||
|
||||
.icon-ok {
|
||||
background-image: url('../icons/ok.png') !important;
|
||||
}
|
||||
|
||||
.icon-error {
|
||||
background-image: url('../icons/error.png') !important;
|
||||
}
|
||||
|
||||
.icon-upload-slots {
|
||||
background-image: url('../icons/upload_slots.png') !important;
|
||||
}
|
||||
|
||||
.icon-expand-all {
|
||||
background-image: url('../icons/expand_all.png') !important;
|
||||
}
|
||||
|
||||
.icon-do-not-download {
|
||||
background-image: url('../icons/no_download.png') !important;
|
||||
}
|
||||
|
||||
.icon-normal {
|
||||
background-image: url('../icons/normal.png') !important;
|
||||
}
|
||||
|
||||
.icon-high {
|
||||
background-image: url('../icons/high.png') !important;
|
||||
}
|
||||
|
||||
.icon-highest {
|
||||
background-image: url('../icons/highest.png') !important;
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
111
deluge/ui/web/css/icons.css
Normal file
111
deluge/ui/web/css/icons.css
Normal file
@ -0,0 +1,111 @@
|
||||
.icon-create {
|
||||
background-image: url('../icons/create.png') !important;
|
||||
}
|
||||
|
||||
.icon-add {
|
||||
background-image: url('../icons/add.png') !important;
|
||||
}
|
||||
|
||||
.icon-add-url {
|
||||
background-image: url('../icons/add_url.png') !important;
|
||||
}
|
||||
|
||||
.icon-add-magnet {
|
||||
background-image: url('../icons/add_magnet.png') !important;
|
||||
}
|
||||
|
||||
.icon-options {
|
||||
background-image: url('../icons/preferences.png') !important;
|
||||
}
|
||||
|
||||
.icon-queue {
|
||||
background-image: url('../icons/queue.png') !important;
|
||||
}
|
||||
|
||||
.icon-top {
|
||||
background-image: url('../icons/top.png') !important;
|
||||
}
|
||||
|
||||
.icon-up {
|
||||
background-image: url('../icons/up.png') !important;
|
||||
}
|
||||
|
||||
.icon-down {
|
||||
background-image: url('../icons/down.png') !important;
|
||||
}
|
||||
|
||||
.icon-bottom {
|
||||
background-image: url('../icons/bottom.png') !important;
|
||||
}
|
||||
|
||||
.icon-update-tracker {
|
||||
background-image: url('../icons/update.png') !important;
|
||||
}
|
||||
|
||||
.icon-edit-trackers, .icon-edit {
|
||||
background-image: url('../icons/edit_trackers.png') !important;
|
||||
}
|
||||
|
||||
.icon-remove {
|
||||
background-image: url('../icons/remove.png') !important;
|
||||
}
|
||||
|
||||
.icon-recheck {
|
||||
background-image: url('../icons/recheck.png') !important;
|
||||
}
|
||||
|
||||
.icon-move {
|
||||
background-image: url('../icons/move.png') !important;
|
||||
}
|
||||
|
||||
.icon-help {
|
||||
background-image: url('../icons/help.png') !important;
|
||||
}
|
||||
|
||||
.icon-logout {
|
||||
background-image: url('../icons/logout.png') !important;
|
||||
}
|
||||
|
||||
.icon-back {
|
||||
background-image: url('../icons/back.png') !important;
|
||||
}
|
||||
|
||||
.icon-forward {
|
||||
background-image: url('../icons/forward.png') !important;
|
||||
}
|
||||
|
||||
.icon-home {
|
||||
background-image: url('../icons/home.png') !important;
|
||||
}
|
||||
|
||||
.icon-ok {
|
||||
background-image: url('../icons/ok.png') !important;
|
||||
}
|
||||
|
||||
.icon-error {
|
||||
background-image: url('../icons/error.png') !important;
|
||||
}
|
||||
|
||||
.icon-upload-slots {
|
||||
background-image: url('../icons/upload_slots.png') !important;
|
||||
}
|
||||
|
||||
.icon-expand-all {
|
||||
background-image: url('../icons/expand_all.png') !important;
|
||||
}
|
||||
|
||||
.icon-do-not-download {
|
||||
background-image: url('../icons/no_download.png') !important;
|
||||
}
|
||||
|
||||
.icon-normal {
|
||||
background-image: url('../icons/normal.png') !important;
|
||||
}
|
||||
|
||||
.icon-high {
|
||||
background-image: url('../icons/high.png') !important;
|
||||
}
|
||||
|
||||
.icon-highest {
|
||||
background-image: url('../icons/highest.png') !important;
|
||||
}
|
||||
@ -22,7 +22,7 @@ GetText = {
|
||||
}
|
||||
}
|
||||
|
||||
function _(string) {
|
||||
window._ = function(string) {
|
||||
return GetText.get(string);
|
||||
}
|
||||
|
||||
|
||||
BIN
deluge/ui/web/images/loading.gif
Normal file
BIN
deluge/ui/web/images/loading.gif
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 3.1 KiB |
@ -19,7 +19,7 @@
|
||||
author: 'Damien Churchill <damoxc@gmail.com>',
|
||||
version: '${version}',
|
||||
config: ${js_config}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<!-- Javascript -->
|
||||
@ -31,7 +31,12 @@
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
<div style="background-image: url('${base}themes/images/default/tree/loading.gif');"></div>
|
||||
<div id="loading-mask"></div>
|
||||
<div id="loading">
|
||||
<div class="loading-indicator">
|
||||
Loading...
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Preload icon classes -->
|
||||
<div class="ext-mb-error"></div>
|
||||
|
||||
@ -1,2 +1,3 @@
|
||||
+ OptionsManager.js
|
||||
+ StatusbarMenu.js
|
||||
+ Formatters.js
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
/*!
|
||||
* Deluge.AddConnectionWindow.js
|
||||
*
|
||||
* Copyright (c) Damien Churchill 2009-2010 <damoxc@gmail.com>
|
||||
*
|
||||
* Copyright (c) Damien Churchill 2009-2011 <damoxc@gmail.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@ -29,13 +29,13 @@
|
||||
* this exception statement from your version. If you delete this exception
|
||||
* statement from all source files in the program, then also delete it here.
|
||||
*/
|
||||
Ext.ns('Deluge');
|
||||
|
||||
/**
|
||||
* @class Deluge.AddConnectionWindow
|
||||
* @extends Ext.Window
|
||||
*/
|
||||
Deluge.AddConnectionWindow = Ext.extend(Ext.Window, {
|
||||
Ext.define('Deluge.AddConnectionWindow', {
|
||||
extend: 'Ext.Window',
|
||||
|
||||
title: _('Add Connection'),
|
||||
iconCls: 'x-deluge-add-window-icon',
|
||||
@ -48,15 +48,27 @@ Deluge.AddConnectionWindow = Ext.extend(Ext.Window, {
|
||||
closeAction: 'hide',
|
||||
|
||||
initComponent: function() {
|
||||
Deluge.AddConnectionWindow.superclass.initComponent.call(this);
|
||||
this.callParent(arguments);
|
||||
|
||||
this.addEvents('hostadded');
|
||||
|
||||
this.addButton(_('Close'), this.hide, this);
|
||||
this.addButton(_('Add'), this.onAddClick, this);
|
||||
|
||||
this.on('hide', this.onHide, this);
|
||||
|
||||
|
||||
this.addDocked({
|
||||
xtype: 'toolbar',
|
||||
dock: 'bottom',
|
||||
defaultType: 'button',
|
||||
items: [
|
||||
'->',
|
||||
{text: _('Close'), handler: function() {
|
||||
this.setVisible(false);
|
||||
}, scope: this},
|
||||
{text: _('Add'), handler: this.onAddClick, scope: this}
|
||||
]
|
||||
});
|
||||
|
||||
this.on('hide', function() {
|
||||
this.form.getForm().reset();
|
||||
}, this);
|
||||
|
||||
this.form = this.add({
|
||||
xtype: 'form',
|
||||
defaultType: 'textfield',
|
||||
@ -65,28 +77,22 @@ Deluge.AddConnectionWindow = Ext.extend(Ext.Window, {
|
||||
items: [{
|
||||
fieldLabel: _('Host'),
|
||||
name: 'host',
|
||||
anchor: '75%',
|
||||
value: ''
|
||||
}, {
|
||||
xtype: 'spinnerfield',
|
||||
xtype: 'numberfield',
|
||||
fieldLabel: _('Port'),
|
||||
name: 'port',
|
||||
strategy: {
|
||||
xtype: 'number',
|
||||
decimalPrecision: 0,
|
||||
minValue: -1,
|
||||
maxValue: 65535
|
||||
},
|
||||
value: '58846',
|
||||
anchor: '40%'
|
||||
width: 175,
|
||||
value: 58846,
|
||||
minValue: -1,
|
||||
maxValue: 65535,
|
||||
decimalPrecision: 0,
|
||||
}, {
|
||||
fieldLabel: _('Username'),
|
||||
name: 'username',
|
||||
anchor: '75%',
|
||||
value: ''
|
||||
}, {
|
||||
fieldLabel: _('Password'),
|
||||
anchor: '75%',
|
||||
name: 'password',
|
||||
inputType: 'password',
|
||||
value: ''
|
||||
@ -114,9 +120,5 @@ Deluge.AddConnectionWindow = Ext.extend(Ext.Window, {
|
||||
},
|
||||
scope: this
|
||||
});
|
||||
},
|
||||
|
||||
onHide: function() {
|
||||
this.form.getForm().reset();
|
||||
}
|
||||
});
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
/*!
|
||||
* Deluge.AddTrackerWindow.js
|
||||
*
|
||||
* Copyright (c) Damien Churchill 2009-2010 <damoxc@gmail.com>
|
||||
*
|
||||
* Copyright (c) Damien Churchill 2009-2011 <damoxc@gmail.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@ -29,14 +29,14 @@
|
||||
* this exception statement from your version. If you delete this exception
|
||||
* statement from all source files in the program, then also delete it here.
|
||||
*/
|
||||
Ext.ns('Deluge');
|
||||
|
||||
/**
|
||||
* @class Deluge.AddTrackerWindow
|
||||
* @extends Ext.Window
|
||||
*/
|
||||
Deluge.AddTrackerWindow = Ext.extend(Ext.Window, {
|
||||
|
||||
Ext.define('Deluge.AddTrackerWindow', {
|
||||
extend: 'Ext.Window',
|
||||
|
||||
title: _('Add Tracker'),
|
||||
layout: 'fit',
|
||||
width: 375,
|
||||
@ -51,12 +51,12 @@ Deluge.AddTrackerWindow = Ext.extend(Ext.Window, {
|
||||
iconCls: 'x-deluge-edit-trackers',
|
||||
|
||||
initComponent: function() {
|
||||
Deluge.AddTrackerWindow.superclass.initComponent.call(this);
|
||||
|
||||
this.addButton(_('Cancel'), this.onCancelClick, this);
|
||||
this.addButton(_('Add'), this.onAddClick, this);
|
||||
this.callParent(arguments);
|
||||
|
||||
//this.addButton(_('Cancel'), this.onCancelClick, this);
|
||||
//this.addButton(_('Add'), this.onAddClick, this);
|
||||
this.addEvents('add');
|
||||
|
||||
|
||||
this.form = this.add({
|
||||
xtype: 'form',
|
||||
defaultType: 'textarea',
|
||||
@ -73,7 +73,7 @@ Deluge.AddTrackerWindow = Ext.extend(Ext.Window, {
|
||||
onAddClick: function() {
|
||||
var trackers = this.form.getForm().findField('trackers').getValue();
|
||||
trackers = trackers.split('\n');
|
||||
|
||||
|
||||
var cleaned = [];
|
||||
Ext.each(trackers, function(tracker) {
|
||||
if (Ext.form.VTypes.url(tracker)) {
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
/*!
|
||||
* Deluge.Client.js
|
||||
*
|
||||
* Copyright (c) Damien Churchill 2009-2010 <damoxc@gmail.com>
|
||||
*
|
||||
* Copyright (c) Damien Churchill 2009-2011 <damoxc@gmail.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@ -29,7 +29,6 @@
|
||||
* this exception statement from your version. If you delete this exception
|
||||
* statement from all source files in the program, then also delete it here.
|
||||
*/
|
||||
Ext.namespace('Ext.ux.util');
|
||||
|
||||
/**
|
||||
* A class that connects to a json-rpc resource and adds the available
|
||||
@ -37,23 +36,24 @@ Ext.namespace('Ext.ux.util');
|
||||
* @class Ext.ux.util.RpcClient
|
||||
* @namespace Ext.ux.util
|
||||
*/
|
||||
Ext.ux.util.RpcClient = Ext.extend(Ext.util.Observable, {
|
||||
Ext.define('Ext.ux.util.RpcClient', {
|
||||
extend: 'Ext.util.Observable',
|
||||
|
||||
_components: [],
|
||||
|
||||
|
||||
_methods: [],
|
||||
|
||||
|
||||
_requests: {},
|
||||
|
||||
|
||||
_url: null,
|
||||
|
||||
|
||||
_optionKeys: ['scope', 'success', 'failure'],
|
||||
|
||||
|
||||
constructor: function(config) {
|
||||
Ext.ux.util.RpcClient.superclass.constructor.call(this, config);
|
||||
this._url = config.url || null;
|
||||
this._id = 0;
|
||||
|
||||
|
||||
this.addEvents(
|
||||
// raw events
|
||||
/**
|
||||
@ -62,12 +62,12 @@ Ext.ux.util.RpcClient = Ext.extend(Ext.util.Observable, {
|
||||
* @param {Ext.ux.util.RpcClient} this
|
||||
*/
|
||||
'connected',
|
||||
|
||||
|
||||
'error'
|
||||
);
|
||||
this.reloadMethods();
|
||||
},
|
||||
|
||||
|
||||
reloadMethods: function() {
|
||||
Ext.each(this._components, function(component) {
|
||||
delete this[component];
|
||||
@ -82,14 +82,14 @@ Ext.ux.util.RpcClient = Ext.extend(Ext.util.Observable, {
|
||||
options = options || {};
|
||||
options.params = options.params || [];
|
||||
options.id = this._id;
|
||||
|
||||
|
||||
var request = Ext.encode({
|
||||
method: method,
|
||||
params: options.params,
|
||||
id: options.id
|
||||
});
|
||||
this._id++;
|
||||
|
||||
|
||||
return Ext.Ajax.request({
|
||||
url: this._url,
|
||||
method: 'POST',
|
||||
@ -100,7 +100,7 @@ Ext.ux.util.RpcClient = Ext.extend(Ext.util.Observable, {
|
||||
options: options
|
||||
});
|
||||
},
|
||||
|
||||
|
||||
_onFailure: function(response, requestOptions) {
|
||||
var options = requestOptions.options;
|
||||
errorObj = {
|
||||
@ -111,23 +111,23 @@ Ext.ux.util.RpcClient = Ext.extend(Ext.util.Observable, {
|
||||
code: 255
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
this.fireEvent('error', errorObj, response, requestOptions)
|
||||
|
||||
|
||||
if (Ext.type(options.failure) != 'function') return;
|
||||
if (options.scope) {
|
||||
options.failure.call(options.scope, errorObj, response, requestOptions);
|
||||
} else {
|
||||
options.failure(errorObj, response, requestOptions);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
_onSuccess: function(response, requestOptions) {
|
||||
var responseObj = Ext.decode(response.responseText);
|
||||
var options = requestOptions.options;
|
||||
if (responseObj.error) {
|
||||
this.fireEvent('error', responseObj, response, requestOptions);
|
||||
|
||||
|
||||
if (Ext.type(options.failure) != 'function') return;
|
||||
if (options.scope) {
|
||||
options.failure.call(options.scope, responseObj, response, requestOptions);
|
||||
@ -143,23 +143,23 @@ Ext.ux.util.RpcClient = Ext.extend(Ext.util.Observable, {
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
_parseArgs: function(args) {
|
||||
var params = [];
|
||||
Ext.each(args, function(arg) {
|
||||
params.push(arg);
|
||||
});
|
||||
|
||||
|
||||
var options = params[params.length - 1];
|
||||
if (Ext.type(options) == 'object') {
|
||||
var keys = Ext.keys(options), isOption = false;
|
||||
|
||||
|
||||
Ext.each(this._optionKeys, function(key) {
|
||||
if (keys.indexOf(key) > -1) isOption = true;
|
||||
});
|
||||
|
||||
|
||||
if (isOption) {
|
||||
params.remove(options)
|
||||
params.pop(-1)
|
||||
} else {
|
||||
options = {}
|
||||
}
|
||||
@ -172,11 +172,11 @@ Ext.ux.util.RpcClient = Ext.extend(Ext.util.Observable, {
|
||||
|
||||
_setMethods: function(methods) {
|
||||
var components = {}, self = this;
|
||||
|
||||
|
||||
Ext.each(methods, function(method) {
|
||||
var parts = method.split('.');
|
||||
var component = components[parts[0]] || {};
|
||||
|
||||
|
||||
var fn = function() {
|
||||
var options = self._parseArgs(arguments);
|
||||
return self._execute(method, options);
|
||||
@ -184,11 +184,11 @@ Ext.ux.util.RpcClient = Ext.extend(Ext.util.Observable, {
|
||||
component[parts[1]] = fn;
|
||||
components[parts[0]] = component;
|
||||
});
|
||||
|
||||
|
||||
for (var name in components) {
|
||||
self[name] = components[name];
|
||||
}
|
||||
|
||||
|
||||
this._components = Ext.keys(components);
|
||||
this.fireEvent('connected', this);
|
||||
}
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
/*!
|
||||
* Deluge.ConnectionManager.js
|
||||
*
|
||||
* Copyright (c) Damien Churchill 2009-2010 <damoxc@gmail.com>
|
||||
* Copyright (c) Damien Churchill 2009-2011 <damoxc@gmail.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@ -30,7 +30,8 @@
|
||||
* statement from all source files in the program, then also delete it here.
|
||||
*/
|
||||
|
||||
Deluge.ConnectionManager = Ext.extend(Ext.Window, {
|
||||
Ext.define('Deluge.ConnectionManager', {
|
||||
extend: 'Ext.Window',
|
||||
|
||||
layout: 'fit',
|
||||
width: 300,
|
||||
@ -44,84 +45,69 @@ Deluge.ConnectionManager = Ext.extend(Ext.Window, {
|
||||
iconCls: 'x-deluge-connect-window-icon',
|
||||
|
||||
initComponent: function() {
|
||||
Deluge.ConnectionManager.superclass.initComponent.call(this);
|
||||
this.on('hide', this.onHide, this);
|
||||
this.on('show', this.onShow, this);
|
||||
this.callParent(arguments);
|
||||
this.afterMethod('onHide', this.afterHidden, this);
|
||||
this.afterMethod('onShow', this.afterShown, this);
|
||||
|
||||
deluge.events.on('login', this.onLogin, this);
|
||||
deluge.events.on('logout', this.onLogout, this);
|
||||
|
||||
this.addButton(_('Close'), this.onClose, this);
|
||||
this.addButton(_('Connect'), this.onConnect, this);
|
||||
this.addDocked({
|
||||
xtype: 'toolbar',
|
||||
dock: 'bottom',
|
||||
defaultType: 'button',
|
||||
items: [
|
||||
'->',
|
||||
{text: _('Close'), handler: this.onClose, scope: this},
|
||||
{text: _('Connect'), handler: this.onConnect, scope: this}
|
||||
]
|
||||
});
|
||||
|
||||
this.list = new Ext.list.ListView({
|
||||
store: new Ext.data.ArrayStore({
|
||||
fields: [
|
||||
{name: 'status', mapping: 3},
|
||||
{name: 'host', mapping: 1},
|
||||
{name: 'port', mapping: 2},
|
||||
{name: 'version', mapping: 4}
|
||||
],
|
||||
id: 0
|
||||
this.grid = this.add({
|
||||
xtype: 'grid',
|
||||
autoScroll: true,
|
||||
store: Ext.create('Ext.data.Store', {
|
||||
model: 'Deluge.data.Host',
|
||||
proxy: {
|
||||
type: 'memory',
|
||||
reader: {
|
||||
type: 'json',
|
||||
root: 'hosts',
|
||||
idProperty: 'id'
|
||||
}
|
||||
}
|
||||
}),
|
||||
columns: [{
|
||||
header: _('Status'),
|
||||
width: .24,
|
||||
width: 70,
|
||||
sortable: true,
|
||||
dataIndex: 'status'
|
||||
}, {
|
||||
id:'host',
|
||||
xtype: 'templatecolumn',
|
||||
flex: 1,
|
||||
header: _('Host'),
|
||||
width: .51,
|
||||
sortable: true,
|
||||
tpl: '{host}:{port}',
|
||||
dataIndex: 'host'
|
||||
tpl: '{host}:{port}'
|
||||
}, {
|
||||
xtype: 'templatecolumn',
|
||||
header: _('Version'),
|
||||
width: .25,
|
||||
width: 70,
|
||||
sortable: true,
|
||||
tpl: '<tpl if="version">{version}</tpl>',
|
||||
dataIndex: 'version'
|
||||
tpl: '<tpl if="version">{version}</tpl>'
|
||||
}],
|
||||
singleSelect: true,
|
||||
listeners: {
|
||||
'selectionchange': {fn: this.onSelectionChanged, scope: this}
|
||||
}
|
||||
},
|
||||
bbar: [
|
||||
{xtype: 'button', text: _('Add'), iconCls: 'icon-add', handler: this.onAddClick, scope: this},
|
||||
{xtype: 'button', text: _('Remove'), iconCls: 'icon-remove', handler: this.onRemoveClick, scope: this},
|
||||
'->',
|
||||
{xtype: 'button', text: _('Stop Daemon'), iconCls: 'icon-error', handler: this.onStopClick, scope: this, disabled: true}
|
||||
]
|
||||
});
|
||||
|
||||
this.panel = this.add({
|
||||
autoScroll: true,
|
||||
items: [this.list],
|
||||
bbar: new Ext.Toolbar({
|
||||
buttons: [
|
||||
{
|
||||
id: 'cm-add',
|
||||
cls: 'x-btn-text-icon',
|
||||
text: _('Add'),
|
||||
iconCls: 'icon-add',
|
||||
handler: this.onAddClick,
|
||||
scope: this
|
||||
}, {
|
||||
id: 'cm-remove',
|
||||
cls: 'x-btn-text-icon',
|
||||
text: _('Remove'),
|
||||
iconCls: 'icon-remove',
|
||||
handler: this.onRemoveClick,
|
||||
disabled: true,
|
||||
scope: this
|
||||
}, '->', {
|
||||
id: 'cm-stop',
|
||||
cls: 'x-btn-text-icon',
|
||||
text: _('Stop Daemon'),
|
||||
iconCls: 'icon-error',
|
||||
handler: this.onStopClick,
|
||||
disabled: true,
|
||||
scope: this
|
||||
}
|
||||
]
|
||||
})
|
||||
});
|
||||
this.update = this.update.createDelegate(this);
|
||||
this.update = Ext.Function.bind(this.update, this);
|
||||
},
|
||||
|
||||
/**
|
||||
@ -157,8 +143,8 @@ Deluge.ConnectionManager = Ext.extend(Ext.Window, {
|
||||
},
|
||||
|
||||
update: function() {
|
||||
this.list.getStore().each(function(r) {
|
||||
deluge.client.web.get_host_status(r.id, {
|
||||
this.grid.getStore().each(function(r) {
|
||||
deluge.client.web.get_host_status(r.getId(), {
|
||||
success: this.onGetHostStatus,
|
||||
scope: this
|
||||
});
|
||||
@ -171,21 +157,23 @@ Deluge.ConnectionManager = Ext.extend(Ext.Window, {
|
||||
* @param {Ext.data.Record} record The hosts record to update the UI for
|
||||
*/
|
||||
updateButtons: function(record) {
|
||||
var button = this.buttons[1], status = record.get('status');
|
||||
var btns = this.query('toolbar[dock=bottom] button'),
|
||||
btn = btns[4],
|
||||
s = record.get('status');
|
||||
|
||||
// Update the Connect/Disconnect button
|
||||
if (status == _('Connected')) {
|
||||
button.enable();
|
||||
button.setText(_('Disconnect'));
|
||||
} else if (status == _('Offline')) {
|
||||
button.disable();
|
||||
if (s == _('Connected')) {
|
||||
btn.enable();
|
||||
btn.setText(_('Disconnect'));
|
||||
} else if (s == _('Offline')) {
|
||||
btn.disable();
|
||||
} else {
|
||||
button.enable();
|
||||
button.setText(_('Connect'));
|
||||
btn.enable();
|
||||
btn.setText(_('Connect'));
|
||||
}
|
||||
|
||||
// Update the Stop/Start Daemon button
|
||||
if (status == _('Offline')) {
|
||||
if (s == _('Offline')) {
|
||||
if (record.get('host') == '127.0.0.1' || record.get('host') == 'localhost') {
|
||||
this.stopHostButton.enable();
|
||||
this.stopHostButton.setText(_('Start Daemon'));
|
||||
@ -201,7 +189,7 @@ Deluge.ConnectionManager = Ext.extend(Ext.Window, {
|
||||
// private
|
||||
onAddClick: function(button, e) {
|
||||
if (!this.addWindow) {
|
||||
this.addWindow = new Deluge.AddConnectionWindow();
|
||||
this.addWindow = Ext.create('Deluge.AddConnectionWindow');
|
||||
this.addWindow.on('hostadded', this.onHostAdded, this);
|
||||
}
|
||||
this.addWindow.show();
|
||||
@ -219,7 +207,9 @@ Deluge.ConnectionManager = Ext.extend(Ext.Window, {
|
||||
|
||||
// private
|
||||
onConnect: function(e) {
|
||||
var selected = this.list.getSelectedRecords()[0];
|
||||
var sm = this.grid.getSelectionModel(),
|
||||
selected = sm.getLastSelected();
|
||||
|
||||
if (!selected) return;
|
||||
|
||||
if (selected.get('status') == _('Connected')) {
|
||||
@ -231,8 +221,7 @@ Deluge.ConnectionManager = Ext.extend(Ext.Window, {
|
||||
scope: this
|
||||
});
|
||||
} else {
|
||||
var id = selected.id;
|
||||
deluge.client.web.connect(id, {
|
||||
deluge.client.web.connect(selected.getId(), {
|
||||
success: function(methods) {
|
||||
deluge.client.reloadMethods();
|
||||
deluge.client.on('connected', function(e) {
|
||||
@ -246,9 +235,13 @@ Deluge.ConnectionManager = Ext.extend(Ext.Window, {
|
||||
|
||||
// private
|
||||
onGetHosts: function(hosts) {
|
||||
this.list.getStore().loadData(hosts);
|
||||
// FIXME: Why on earth do I need to do it like this?!
|
||||
var store = this.grid.getStore(),
|
||||
results = store.proxy.reader.readRecords(hosts);
|
||||
store.loadRecords(results.records);
|
||||
|
||||
Ext.each(hosts, function(host) {
|
||||
deluge.client.web.get_host_status(host[0], {
|
||||
deluge.client.web.get_host_status(host['id'], {
|
||||
success: this.onGetHostStatus,
|
||||
scope: this
|
||||
});
|
||||
@ -257,15 +250,18 @@ Deluge.ConnectionManager = Ext.extend(Ext.Window, {
|
||||
|
||||
// private
|
||||
onGetHostStatus: function(host) {
|
||||
var record = this.list.getStore().getById(host[0]);
|
||||
record.set('status', host[3])
|
||||
record.set('version', host[4])
|
||||
var record = this.grid.getStore().getById(host['id']);
|
||||
record.set('status', host['status'])
|
||||
record.set('version', host['version'])
|
||||
record.commit();
|
||||
if (this.list.getSelectedRecords()[0] == record) this.updateButtons(record);
|
||||
|
||||
if (this.grid.getSelectionModel().isSelected(record)) {
|
||||
this.updateButtons(record);
|
||||
}
|
||||
},
|
||||
|
||||
// private
|
||||
onHide: function() {
|
||||
afterHidden: function() {
|
||||
if (this.running) window.clearInterval(this.running);
|
||||
},
|
||||
|
||||
@ -298,10 +294,12 @@ Deluge.ConnectionManager = Ext.extend(Ext.Window, {
|
||||
|
||||
// private
|
||||
onRemoveClick: function(button) {
|
||||
var connection = this.list.getSelectedRecords()[0];
|
||||
if (!connection) return;
|
||||
var sm = this.grid.getSelectionModel(),
|
||||
selected = sm.getLastSelected();
|
||||
|
||||
deluge.client.web.remove_host(connection.id, {
|
||||
if (!selected) return;
|
||||
|
||||
deluge.client.web.remove_host(selected.getId(), {
|
||||
success: function(result) {
|
||||
if (!result) {
|
||||
Ext.MessageBox.show({
|
||||
@ -313,7 +311,7 @@ Deluge.ConnectionManager = Ext.extend(Ext.Window, {
|
||||
iconCls: 'x-deluge-icon-error'
|
||||
});
|
||||
} else {
|
||||
this.list.getStore().remove(connection);
|
||||
this.grid.getStore().remove(selected);
|
||||
}
|
||||
},
|
||||
scope: this
|
||||
@ -321,12 +319,12 @@ Deluge.ConnectionManager = Ext.extend(Ext.Window, {
|
||||
},
|
||||
|
||||
// private
|
||||
onSelectionChanged: function(list, selections) {
|
||||
onSelectionChanged: function(grid, selections) {
|
||||
if (selections[0]) {
|
||||
this.removeHostButton.enable();
|
||||
this.stopHostButton.enable();
|
||||
this.stopHostButton.setText(_('Stop Daemon'));
|
||||
this.updateButtons(this.list.getRecord(selections[0]));
|
||||
this.updateButtons(selections[0]);
|
||||
} else {
|
||||
this.removeHostButton.disable();
|
||||
this.stopHostButton.disable();
|
||||
@ -335,12 +333,12 @@ Deluge.ConnectionManager = Ext.extend(Ext.Window, {
|
||||
|
||||
// FIXME: Find out why this is being fired twice
|
||||
// private
|
||||
onShow: function() {
|
||||
afterShown: function() {
|
||||
if (!this.addHostButton) {
|
||||
var bbar = this.panel.getBottomToolbar();
|
||||
this.addHostButton = bbar.items.get('cm-add');
|
||||
this.removeHostButton = bbar.items.get('cm-remove');
|
||||
this.stopHostButton = bbar.items.get('cm-stop');
|
||||
var buttons = this.grid.query('button');
|
||||
this.addHostButton = buttons[0];
|
||||
this.removeHostButton = buttons[1];
|
||||
this.stopHostButton = buttons[2];
|
||||
}
|
||||
this.loadHosts();
|
||||
if (this.running) return;
|
||||
@ -349,15 +347,16 @@ Deluge.ConnectionManager = Ext.extend(Ext.Window, {
|
||||
|
||||
// private
|
||||
onStopClick: function(button, e) {
|
||||
var connection = this.list.getSelectedRecords()[0];
|
||||
if (!connection) return;
|
||||
var sm = this.grid.getSelectionModel(),
|
||||
selected = sm.getLastSelected();
|
||||
if (!selected) return;
|
||||
|
||||
if (connection.get('status') == 'Offline') {
|
||||
if (selected.get('status') == 'Offline') {
|
||||
// This means we need to start the daemon
|
||||
deluge.client.web.start_daemon(connection.get('port'));
|
||||
deluge.client.web.start_daemon(selected.get('port'));
|
||||
} else {
|
||||
// This means we need to stop the daemon
|
||||
deluge.client.web.stop_daemon(connection.id, {
|
||||
deluge.client.web.stop_daemon(selected.getId(), {
|
||||
success: function(result) {
|
||||
if (!result[0]) {
|
||||
Ext.MessageBox.show({
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
/*!
|
||||
* Deluge.js
|
||||
*
|
||||
*
|
||||
* Copyright (c) Damien Churchill 2009-2010 <damoxc@gmail.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
@ -31,7 +31,14 @@
|
||||
*/
|
||||
|
||||
// Setup the state manager
|
||||
Ext.state.Manager.setProvider(new Ext.state.CookieProvider());
|
||||
var provider = Ext.state.CookieProvider;
|
||||
try {
|
||||
if ('localStorage' in window && window['localStorage'] !== null) {
|
||||
provider = Ext.state.LocalStorageProvider;
|
||||
}
|
||||
} catch (e) {
|
||||
}
|
||||
Ext.state.Manager.setProvider(new provider());
|
||||
|
||||
// Add some additional functions to ext and setup some of the
|
||||
// configurable parameters
|
||||
@ -56,7 +63,7 @@ Ext.apply(Ext, {
|
||||
}
|
||||
return equal;
|
||||
},
|
||||
|
||||
|
||||
keys: function(obj) {
|
||||
var keys = [];
|
||||
for (var i in obj) if (obj.hasOwnProperty(i))
|
||||
@ -75,7 +82,7 @@ Ext.apply(Ext, {
|
||||
}
|
||||
return values;
|
||||
},
|
||||
|
||||
|
||||
splat: function(obj) {
|
||||
var type = Ext.type(obj);
|
||||
return (type) ? ((type != 'array') ? [obj] : obj) : [];
|
||||
@ -90,22 +97,16 @@ Ext.apply(Deluge, {
|
||||
|
||||
// private
|
||||
pluginStore: {},
|
||||
|
||||
|
||||
// private
|
||||
progressTpl: '<div class="x-progress-wrap x-progress-renderered">' +
|
||||
'<div class="x-progress-inner">' +
|
||||
'<div style="width: {2}px" class="x-progress-bar">' +
|
||||
'<div style="z-index: 99; width: {3}px" class="x-progress-text">' +
|
||||
'<div style="width: {1}px;">{0}</div>' +
|
||||
'</div>' +
|
||||
'</div>' +
|
||||
'<div class="x-progress-text x-progress-text-back">' +
|
||||
'<div style="width: {1}px;">{0}</div>' +
|
||||
'</div>' +
|
||||
progressTpl: '<div class="x-progress x-progress-default">' +
|
||||
'<div class="x-progress-text x-progress-text-back" style="width: {1}px;">{0}</div>' +
|
||||
'<div class="x-progress-bar" style="width: {3}px;">' +
|
||||
'<div class="x-progress-text" style="width: {1}px;">{0}</div>' +
|
||||
'</div>' +
|
||||
'</div>',
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* A method to create a progress bar that can be used by renderers
|
||||
* to display a bar within a grid or tree.
|
||||
@ -115,11 +116,11 @@ Ext.apply(Deluge, {
|
||||
* @param {Number} modified Amount to subtract from the width allowing for fixes
|
||||
*/
|
||||
progressBar: function(progress, width, text, modifier) {
|
||||
modifier = Ext.value(modifier, 10);
|
||||
modifier = Ext.value(modifier, 5);
|
||||
var progressWidth = ((width / 100.0) * progress).toFixed(0);
|
||||
var barWidth = progressWidth - 1;
|
||||
var textWidth = ((progressWidth - modifier) > 0 ? progressWidth - modifier : 0);
|
||||
return String.format(Deluge.progressTpl, text, width, barWidth, textWidth);
|
||||
return Ext.String.format(Deluge.progressTpl, text, width, barWidth, textWidth);
|
||||
},
|
||||
|
||||
/**
|
||||
@ -146,12 +147,19 @@ Ext.apply(Deluge, {
|
||||
registerPlugin: function(name, plugin) {
|
||||
Deluge.pluginStore[name] = plugin;
|
||||
}
|
||||
|
||||
|
||||
});
|
||||
|
||||
// Setup a space for plugins to insert themselves
|
||||
deluge.plugins = {};
|
||||
|
||||
deluge.logDateFormat = 'd/m/Y H:i:s,u';
|
||||
|
||||
deluge.log = function(msg) {
|
||||
var date = new Date()
|
||||
console.log(Ext.Date.format(date, deluge.logDateFormat) + ' - ' + msg);
|
||||
}
|
||||
|
||||
// Hinting for gettext_gen.py
|
||||
// _('Do Not Download')
|
||||
// _('Normal Priority')
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
/*!
|
||||
* Deluge.EditTrackerWindow.js
|
||||
*
|
||||
* Copyright (c) Damien Churchill 2009-2010 <damoxc@gmail.com>
|
||||
*
|
||||
* Copyright (c) Damien Churchill 2009-2011 <damoxc@gmail.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@ -29,13 +29,13 @@
|
||||
* this exception statement from your version. If you delete this exception
|
||||
* statement from all source files in the program, then also delete it here.
|
||||
*/
|
||||
Ext.ns('Deluge');
|
||||
|
||||
/**
|
||||
* @class Deluge.EditTrackerWindow
|
||||
* @extends Ext.Window
|
||||
*/
|
||||
Deluge.EditTrackerWindow = Ext.extend(Ext.Window, {
|
||||
Ext.define('Deluge.EditTrackerWindow', {
|
||||
extend: 'Ext.Window',
|
||||
|
||||
title: _('Edit Tracker'),
|
||||
layout: 'fit',
|
||||
@ -49,14 +49,14 @@ Deluge.EditTrackerWindow = Ext.extend(Ext.Window, {
|
||||
buttonAlign: 'right',
|
||||
closeAction: 'hide',
|
||||
iconCls: 'x-deluge-edit-trackers',
|
||||
|
||||
|
||||
initComponent: function() {
|
||||
Deluge.EditTrackerWindow.superclass.initComponent.call(this);
|
||||
|
||||
this.addButton(_('Cancel'), this.onCancelClick, this);
|
||||
this.addButton(_('Save'), this.onSaveClick, this);
|
||||
this.callParent(arguments);
|
||||
|
||||
//this.addButton(_('Cancel'), this.onCancelClick, this);
|
||||
//this.addButton(_('Save'), this.onSaveClick, this);
|
||||
this.on('hide', this.onHide, this);
|
||||
|
||||
|
||||
this.form = this.add({
|
||||
xtype: 'form',
|
||||
defaultType: 'textfield',
|
||||
@ -69,22 +69,22 @@ Deluge.EditTrackerWindow = Ext.extend(Ext.Window, {
|
||||
}]
|
||||
});
|
||||
},
|
||||
|
||||
|
||||
show: function(record) {
|
||||
Deluge.EditTrackerWindow.superclass.show.call(this);
|
||||
|
||||
this.callParent(arguments);
|
||||
|
||||
this.record = record;
|
||||
this.form.getForm().findField('tracker').setValue(record.data['url']);
|
||||
},
|
||||
|
||||
|
||||
onCancelClick: function() {
|
||||
this.hide();
|
||||
},
|
||||
|
||||
|
||||
onHide: function() {
|
||||
this.form.getForm().findField('tracker').setValue('');
|
||||
},
|
||||
|
||||
|
||||
onSaveClick: function() {
|
||||
var url = this.form.getForm().findField('tracker').getValue();
|
||||
this.record.set('url', url);
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
/*!
|
||||
* Deluge.EditTrackers.js
|
||||
*
|
||||
* Copyright (c) Damien Churchill 2009-2010 <damoxc@gmail.com>
|
||||
* Copyright (c) Damien Churchill 2009-2011 <damoxc@gmail.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@ -29,13 +29,13 @@
|
||||
* this exception statement from your version. If you delete this exception
|
||||
* statement from all source files in the program, then also delete it here.
|
||||
*/
|
||||
Ext.ns('Deluge');
|
||||
|
||||
/**
|
||||
* @class Deluge.EditTrackerWindow
|
||||
* @extends Ext.Window
|
||||
*/
|
||||
Deluge.EditTrackersWindow = Ext.extend(Ext.Window, {
|
||||
Ext.define('Deluge.EditTrackersWindow', {
|
||||
extend: 'Ext.Window',
|
||||
|
||||
title: _('Edit Trackers'),
|
||||
layout: 'fit',
|
||||
@ -51,21 +51,20 @@ Deluge.EditTrackersWindow = Ext.extend(Ext.Window, {
|
||||
iconCls: 'x-deluge-edit-trackers',
|
||||
|
||||
initComponent: function() {
|
||||
Deluge.EditTrackersWindow.superclass.initComponent.call(this);
|
||||
this.callParent(arguments);
|
||||
|
||||
this.addButton(_('Cancel'), this.onCancelClick, this);
|
||||
this.addButton(_('Ok'), this.onOkClick, this);
|
||||
//this.addButton(_('Cancel'), this.onCancelClick, this);
|
||||
//this.addButton(_('Ok'), this.onOkClick, this);
|
||||
this.addEvents('save');
|
||||
|
||||
this.on('show', this.onShow, this);
|
||||
this.on('save', this.onSave, this);
|
||||
|
||||
this.addWindow = new Deluge.AddTrackerWindow();
|
||||
this.addWindow = Ext.create('Deluge.AddTrackerWindow');
|
||||
this.addWindow.on('add', this.onAddTrackers, this);
|
||||
this.editWindow = new Deluge.EditTrackerWindow();
|
||||
this.editWindow = Ext.create('Deluge.EditTrackerWindow');
|
||||
|
||||
this.list = new Ext.list.ListView({
|
||||
store: new Ext.data.JsonStore({
|
||||
this.list = Ext.create('Ext.list.ListView', {
|
||||
store: Ext.create('Ext.data.Store', {
|
||||
root: 'trackers',
|
||||
fields: [
|
||||
'tier',
|
||||
@ -96,7 +95,7 @@ Deluge.EditTrackersWindow = Ext.extend(Ext.Window, {
|
||||
margins: '0 0 0 0',
|
||||
items: [this.list],
|
||||
autoScroll: true,
|
||||
bbar: new Ext.Toolbar({
|
||||
bbar: {
|
||||
items: [
|
||||
{
|
||||
text: _('Up'),
|
||||
@ -125,7 +124,7 @@ Deluge.EditTrackersWindow = Ext.extend(Ext.Window, {
|
||||
scope: this
|
||||
}
|
||||
]
|
||||
})
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
@ -147,7 +146,7 @@ Deluge.EditTrackersWindow = Ext.extend(Ext.Window, {
|
||||
}
|
||||
}, this);
|
||||
if (duplicate) return;
|
||||
store.add(new store.recordType({'tier': heightestTier + 1, 'url': tracker}));
|
||||
store.add({'tier': heightestTier + 1, 'url': tracker});
|
||||
}, this);
|
||||
},
|
||||
|
||||
@ -194,6 +193,10 @@ Deluge.EditTrackersWindow = Ext.extend(Ext.Window, {
|
||||
this.list.getStore().sort('tier', 'ASC');
|
||||
},
|
||||
|
||||
onSave: function() {
|
||||
// What am I meant to do here?
|
||||
},
|
||||
|
||||
onSaveFail: function() {
|
||||
|
||||
},
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
/*!
|
||||
* Deluge.EventsManager.js
|
||||
*
|
||||
* Copyright (c) Damien Churchill 2009-2010 <damoxc@gmail.com>
|
||||
*
|
||||
* Copyright (c) Damien Churchill 2009-2011 <damoxc@gmail.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@ -36,13 +36,15 @@
|
||||
* <p>Deluge.EventsManager is instantated as <tt>deluge.events</tt> and can be used by components of the UI to fire global events</p>
|
||||
* Class for holding global events that occur within the UI.
|
||||
*/
|
||||
Deluge.EventsManager = Ext.extend(Ext.util.Observable, {
|
||||
Ext.define('Deluge.EventsManager', {
|
||||
extend: 'Ext.util.Observable',
|
||||
toRegister: [],
|
||||
|
||||
constructor: function() {
|
||||
this.toRegister = [];
|
||||
this.on('login', this.onLogin, this);
|
||||
Deluge.EventsManager.superclass.constructor.call(this);
|
||||
this.callParent(arguments);
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Append an event handler to this object.
|
||||
*/
|
||||
@ -54,8 +56,9 @@ Deluge.EventsManager = Ext.extend(Ext.util.Observable, {
|
||||
} else {
|
||||
deluge.client.web.register_event_listener(eventName);
|
||||
}
|
||||
} else {
|
||||
this.callParent(arguments);
|
||||
}
|
||||
Deluge.EventsManager.superclass.addListener.call(this, eventName, fn, scope, o);
|
||||
},
|
||||
|
||||
getEvents: function() {
|
||||
@ -114,14 +117,13 @@ Deluge.EventsManager = Ext.extend(Ext.util.Observable, {
|
||||
|
||||
/**
|
||||
* Appends an event handler to this object (shorthand for {@link #addListener})
|
||||
* @method
|
||||
* @method
|
||||
*/
|
||||
Deluge.EventsManager.prototype.on = Deluge.EventsManager.prototype.addListener
|
||||
|
||||
/**
|
||||
* Fires the specified event with the passed parameters (minus the
|
||||
* event name).
|
||||
* @method
|
||||
* @method
|
||||
*/
|
||||
Deluge.EventsManager.prototype.fire = Deluge.EventsManager.prototype.fireEvent
|
||||
deluge.events = new Deluge.EventsManager();
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
/*!
|
||||
* Deluge.FilterPanel.js
|
||||
*
|
||||
* Copyright (c) Damien Churchill 2009-2010 <damoxc@gmail.com>
|
||||
* Copyright (c) Damien Churchill 2009-2011 <damoxc@gmail.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@ -29,24 +29,35 @@
|
||||
* this exception statement from your version. If you delete this exception
|
||||
* statement from all source files in the program, then also delete it here.
|
||||
*/
|
||||
Ext.ns('Deluge');
|
||||
|
||||
/**
|
||||
* @class Deluge.FilterPanel
|
||||
* @extends Ext.list.ListView
|
||||
* @extends Ext.panel.Panel
|
||||
*/
|
||||
Deluge.FilterPanel = Ext.extend(Ext.Panel, {
|
||||
Ext.define('Deluge.FilterPanel', {
|
||||
extend: 'Ext.panel.Panel',
|
||||
|
||||
autoScroll: true,
|
||||
|
||||
border: false,
|
||||
|
||||
show_zero: null,
|
||||
title: ' ',
|
||||
|
||||
initComponent: function() {
|
||||
Deluge.FilterPanel.superclass.initComponent.call(this);
|
||||
this.callParent(arguments);
|
||||
this.filterType = this.initialConfig.filter;
|
||||
|
||||
this.on('activate', function() {
|
||||
console.log('activate');
|
||||
});
|
||||
|
||||
this.on('show', function() {
|
||||
console.log('show');
|
||||
});
|
||||
|
||||
this.on('render', function() {
|
||||
console.log('render');
|
||||
});
|
||||
|
||||
var title = this.filterType.replace('_', ' '),
|
||||
parts = title.split(' '),
|
||||
title = '';
|
||||
@ -54,7 +65,7 @@ Deluge.FilterPanel = Ext.extend(Ext.Panel, {
|
||||
fl = p.substring(0, 1).toUpperCase();
|
||||
title += fl + p.substring(1) + ' ';
|
||||
});
|
||||
this.setTitle(_(title));
|
||||
this.title = _(title);
|
||||
|
||||
if (Deluge.FilterPanel.templates[this.filterType]) {
|
||||
var tpl = Deluge.FilterPanel.templates[this.filterType];
|
||||
@ -62,23 +73,31 @@ Deluge.FilterPanel = Ext.extend(Ext.Panel, {
|
||||
var tpl = '<div class="x-deluge-filter x-deluge-{filter:lowercase}">{filter} ({count})</div>';
|
||||
}
|
||||
|
||||
this.list = this.add({
|
||||
xtype: 'listview',
|
||||
this.grid = this.add({
|
||||
xtype: 'grid',
|
||||
border: false,
|
||||
singleSelect: true,
|
||||
hideHeaders: true,
|
||||
reserveScrollOffset: true,
|
||||
store: new Ext.data.ArrayStore({
|
||||
idIndex: 0,
|
||||
fields: ['filter', 'count']
|
||||
store: Ext.create('Ext.data.Store', {
|
||||
model: 'Deluge.data.Filter',
|
||||
proxy: {
|
||||
type: 'memory'
|
||||
}
|
||||
}),
|
||||
columns: [{
|
||||
id: 'filter',
|
||||
xtype: 'templatecolumn',
|
||||
sortable: false,
|
||||
tpl: tpl,
|
||||
dataIndex: 'filter'
|
||||
dataIndex: 'filter',
|
||||
flex: 1
|
||||
}]
|
||||
});
|
||||
this.relayEvents(this.list, ['selectionchange']);
|
||||
this.relayEvents(this.grid, ['selectionchange']);
|
||||
},
|
||||
|
||||
getSelectionModel: function() {
|
||||
return this.grid.getSelectionModel();
|
||||
},
|
||||
|
||||
/**
|
||||
@ -86,11 +105,13 @@ Deluge.FilterPanel = Ext.extend(Ext.Panel, {
|
||||
* @returns {String} the current filter state
|
||||
*/
|
||||
getState: function() {
|
||||
if (!this.list.getSelectionCount()) return;
|
||||
var sm = this.grid.getSelectionModel()
|
||||
if (!sm.hasSelection()) return;
|
||||
|
||||
var state = this.list.getSelectedRecords()[0];
|
||||
if (state.id == 'All') return;
|
||||
return state.id;
|
||||
var state = sm.getLastSelected(),
|
||||
stateId = state.getId();
|
||||
if (stateId == 'All') return;
|
||||
return stateId;
|
||||
},
|
||||
|
||||
/**
|
||||
@ -105,7 +126,7 @@ Deluge.FilterPanel = Ext.extend(Ext.Panel, {
|
||||
* @returns {Ext.data.Store} the ListView store
|
||||
*/
|
||||
getStore: function() {
|
||||
return this.list.getStore();
|
||||
return this.grid.getStore();
|
||||
},
|
||||
|
||||
/**
|
||||
@ -128,41 +149,44 @@ Deluge.FilterPanel = Ext.extend(Ext.Panel, {
|
||||
states = newStates;
|
||||
}
|
||||
|
||||
var store = this.getStore();
|
||||
var filters = {};
|
||||
var store = this.getStore(),
|
||||
sm = this.grid.getSelectionModel(),
|
||||
filters = {};
|
||||
Ext.each(states, function(s, i) {
|
||||
var record = store.getById(s[0]);
|
||||
if (!record) {
|
||||
record = new store.recordType({
|
||||
record = Ext.create('Deluge.data.Filter', {
|
||||
filter: s[0],
|
||||
count: s[1]
|
||||
count: [1]
|
||||
});
|
||||
record.id = s[0];
|
||||
store.insert(i, record);
|
||||
record.setId(s[0]);
|
||||
store.insert(i, [record]);
|
||||
} else {
|
||||
record.beginEdit();
|
||||
record.set('filter', s[0]);
|
||||
record.set('count', s[1]);
|
||||
record.endEdit();
|
||||
}
|
||||
record.beginEdit();
|
||||
record.set('filter', s[0]);
|
||||
record.set('count', s[1]);
|
||||
record.endEdit();
|
||||
filters[s[0]] = true;
|
||||
}, this);
|
||||
|
||||
store.each(function(record) {
|
||||
if (filters[record.id]) return;
|
||||
var r = this.list.getSelectedRecords()[0];
|
||||
if (filters[record.getId()]) return;
|
||||
var r = sm.getLastSelected();
|
||||
store.remove(record);
|
||||
if (r.id == record.id) {
|
||||
this.list.select(0);
|
||||
if (r === undefined)
|
||||
return;
|
||||
if (r.getId() == record.getId()) {
|
||||
sm.select(0);
|
||||
}
|
||||
}, this);
|
||||
|
||||
store.commitChanges();
|
||||
store.sync();
|
||||
|
||||
if (!this.list.getSelectionCount()) {
|
||||
this.list.select(0);
|
||||
if (!sm.hasSelection()) {
|
||||
//sm.select(0);
|
||||
}
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
Deluge.FilterPanel.templates = {
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
/*!
|
||||
* Deluge.Formatters.js
|
||||
*
|
||||
*
|
||||
* Copyright (c) Damien Churchill 2009-2010 <damoxc@gmail.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
@ -56,11 +56,11 @@ Deluge.Formatters = {
|
||||
}
|
||||
timestamp = timestamp * 1000;
|
||||
var date = new Date(timestamp);
|
||||
return String.format('{0}/{1}/{2} {3}:{4}:{5}',
|
||||
return Ext.String.format('{0}/{1}/{2} {3}:{4}:{5}',
|
||||
zeroPad(date.getDate(), 2), zeroPad(date.getMonth() + 1, 2), date.getFullYear(),
|
||||
zeroPad(date.getHours(), 2), zeroPad(date.getMinutes(), 2), zeroPad(date.getSeconds(), 2));
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Formats the bytes value into a string with KiB, MiB or GiB units.
|
||||
*
|
||||
@ -71,16 +71,16 @@ Deluge.Formatters = {
|
||||
size: function(bytes, showZero) {
|
||||
if (!bytes && !showZero) return '';
|
||||
bytes = bytes / 1024.0;
|
||||
|
||||
|
||||
if (bytes < 1024) { return bytes.toFixed(1) + ' KiB'; }
|
||||
else { bytes = bytes / 1024; }
|
||||
|
||||
|
||||
if (bytes < 1024) { return bytes.toFixed(1) + ' MiB'; }
|
||||
else { bytes = bytes / 1024; }
|
||||
|
||||
|
||||
return bytes.toFixed(1) + ' GiB'
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Formats a string to display a transfer speed utilizing {@link #size}
|
||||
*
|
||||
@ -91,7 +91,7 @@ Deluge.Formatters = {
|
||||
speed: function(bytes, showZero) {
|
||||
return (!bytes && !showZero) ? '' : fsize(bytes, showZero) + '/s';
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Formats a string to show time in a human readable form.
|
||||
*
|
||||
@ -103,7 +103,7 @@ Deluge.Formatters = {
|
||||
time = time.toFixed(0);
|
||||
if (time < 60) { return time + 's'; }
|
||||
else { time = time / 60; }
|
||||
|
||||
|
||||
if (time < 60) {
|
||||
var minutes = Math.floor(time)
|
||||
var seconds = Math.round(60 * (time - minutes))
|
||||
@ -113,18 +113,18 @@ Deluge.Formatters = {
|
||||
return minutes + 'm'; }
|
||||
}
|
||||
else { time = time / 60; }
|
||||
|
||||
if (time < 24) {
|
||||
|
||||
if (time < 24) {
|
||||
var hours = Math.floor(time)
|
||||
var minutes = Math.round(60 * (time - hours))
|
||||
if (minutes > 0) {
|
||||
return hours + 'h ' + minutes + 'm';
|
||||
} else {
|
||||
return hours + 'h';
|
||||
}
|
||||
}
|
||||
}
|
||||
else { time = time / 24; }
|
||||
|
||||
|
||||
var days = Math.floor(time)
|
||||
var hours = Math.round(24 * (time - days))
|
||||
if (hours > 0) {
|
||||
@ -133,7 +133,7 @@ Deluge.Formatters = {
|
||||
return days + 'd';
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Simply returns the value untouched, for when no formatting is required.
|
||||
*
|
||||
@ -148,9 +148,9 @@ Deluge.Formatters = {
|
||||
return value.toLowerCase().replace('.', '_');
|
||||
}
|
||||
}
|
||||
var fsize = Deluge.Formatters.size;
|
||||
var fspeed = Deluge.Formatters.speed;
|
||||
var ftime = Deluge.Formatters.timeRemaining;
|
||||
var fdate = Deluge.Formatters.date;
|
||||
var fplain = Deluge.Formatters.plain;
|
||||
window.fsize = Deluge.Formatters.size;
|
||||
window.fspeed = Deluge.Formatters.speed;
|
||||
window.ftime = Deluge.Formatters.timeRemaining;
|
||||
window.fdate = Deluge.Formatters.date;
|
||||
window.fplain = Deluge.Formatters.plain;
|
||||
Ext.util.Format.cssClassEscape = Deluge.Formatters.cssClassEscape;
|
||||
|
||||
@ -48,7 +48,8 @@ Deluge.Keys = {
|
||||
'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', 'last_seen_complete'
|
||||
'is_auto_managed', 'time_added', 'tracker_host', 'save_path',
|
||||
'last_seen_complete', 'owner', 'public', 'shared'
|
||||
],
|
||||
|
||||
/**
|
||||
@ -63,7 +64,7 @@ Deluge.Keys = {
|
||||
'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', 'last_seen_complete', 'owner', 'public', 'shared'
|
||||
'seed_rank'
|
||||
],
|
||||
|
||||
/**
|
||||
@ -87,7 +88,7 @@ Deluge.Keys = {
|
||||
*/
|
||||
Details: [
|
||||
'name', 'save_path', 'total_size', 'num_files', 'message',
|
||||
'tracker', 'comment'
|
||||
'tracker', 'comment', 'owner', 'shared'
|
||||
],
|
||||
|
||||
/**
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
/*!
|
||||
* Deluge.LoginWindow.js
|
||||
*
|
||||
* Copyright (c) Damien Churchill 2009-2010 <damoxc@gmail.com>
|
||||
*
|
||||
* Copyright (c) Damien Churchill 2009-2011 <damoxc@gmail.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@ -30,8 +30,10 @@
|
||||
* statement from all source files in the program, then also delete it here.
|
||||
*/
|
||||
|
||||
Deluge.LoginWindow = Ext.extend(Ext.Window, {
|
||||
|
||||
Ext.define('Deluge.LoginWindow', {
|
||||
|
||||
extend: 'Ext.Window',
|
||||
|
||||
firstShow: true,
|
||||
bodyStyle: 'padding: 10px 5px;',
|
||||
buttonAlign: 'center',
|
||||
@ -44,37 +46,43 @@ Deluge.LoginWindow = Ext.extend(Ext.Window, {
|
||||
resizable: false,
|
||||
title: _('Login'),
|
||||
width: 300,
|
||||
height: 120,
|
||||
|
||||
height: 105,
|
||||
|
||||
initComponent: function() {
|
||||
Deluge.LoginWindow.superclass.initComponent.call(this);
|
||||
this.callParent(arguments);
|
||||
this.on('show', this.onShow, this);
|
||||
|
||||
this.addButton({
|
||||
text: _('Login'),
|
||||
handler: this.onLogin,
|
||||
scope: this
|
||||
|
||||
this.addDocked({
|
||||
xtype: 'toolbar',
|
||||
dock: 'bottom',
|
||||
defaultType: 'button',
|
||||
items: [
|
||||
'->',
|
||||
{text: _('Login'), handler: this.onLogin, scope: this}
|
||||
]
|
||||
});
|
||||
|
||||
|
||||
this.form = this.add({
|
||||
xtype: 'form',
|
||||
baseCls: 'x-plain',
|
||||
labelWidth: 55,
|
||||
width: 300,
|
||||
defaults: {width: 200},
|
||||
defaultType: 'textfield'
|
||||
items: [{
|
||||
xtype: 'textfield',
|
||||
fieldLabel: _('Password'),
|
||||
name: 'password',
|
||||
inputType: 'password',
|
||||
labelWidth: 60,
|
||||
width: 275,
|
||||
listeners: {
|
||||
specialkey: {
|
||||
scope: this,
|
||||
fn: this.onSpecialKey
|
||||
}
|
||||
}
|
||||
}]
|
||||
});
|
||||
|
||||
this.passwordField = this.form.add({
|
||||
xtype: 'textfield',
|
||||
fieldLabel: _('Password'),
|
||||
id: '_password',
|
||||
name: 'password',
|
||||
inputType: 'password'
|
||||
});
|
||||
this.passwordField.on('specialkey', this.onSpecialKey, this);
|
||||
},
|
||||
|
||||
|
||||
logout: function() {
|
||||
deluge.events.fire('logout');
|
||||
deluge.client.auth.delete_session({
|
||||
@ -84,17 +92,17 @@ Deluge.LoginWindow = Ext.extend(Ext.Window, {
|
||||
scope: this
|
||||
});
|
||||
},
|
||||
|
||||
|
||||
show: function(skipCheck) {
|
||||
if (this.firstShow) {
|
||||
deluge.client.on('error', this.onClientError, this);
|
||||
this.firstShow = false;
|
||||
}
|
||||
|
||||
|
||||
if (skipCheck) {
|
||||
return Deluge.LoginWindow.superclass.show.call(this);
|
||||
return this.callParent();
|
||||
}
|
||||
|
||||
|
||||
deluge.client.auth.check_session({
|
||||
success: function(result) {
|
||||
if (result) {
|
||||
@ -109,19 +117,20 @@ Deluge.LoginWindow = Ext.extend(Ext.Window, {
|
||||
scope: this
|
||||
});
|
||||
},
|
||||
|
||||
|
||||
onSpecialKey: function(field, e) {
|
||||
if (e.getKey() == 13) this.onLogin();
|
||||
},
|
||||
|
||||
|
||||
onLogin: function() {
|
||||
var passwordField = this.passwordField;
|
||||
deluge.client.auth.login(passwordField.getValue(), {
|
||||
var f = this.form.getForm(),
|
||||
p = f.getValues().password;;
|
||||
deluge.client.auth.login(p, {
|
||||
success: function(result) {
|
||||
if (result) {
|
||||
deluge.events.fire('login');
|
||||
this.hide();
|
||||
passwordField.setRawValue('');
|
||||
f.setValues({password: ''});
|
||||
} else {
|
||||
Ext.MessageBox.show({
|
||||
title: _('Login Failed'),
|
||||
@ -129,7 +138,7 @@ Deluge.LoginWindow = Ext.extend(Ext.Window, {
|
||||
buttons: Ext.MessageBox.OK,
|
||||
modal: false,
|
||||
fn: function() {
|
||||
passwordField.focus(true, 10);
|
||||
f.findField('password').focus(true, 10);
|
||||
},
|
||||
icon: Ext.MessageBox.WARNING,
|
||||
iconCls: 'x-deluge-icon-warning'
|
||||
@ -139,15 +148,15 @@ Deluge.LoginWindow = Ext.extend(Ext.Window, {
|
||||
scope: this
|
||||
});
|
||||
},
|
||||
|
||||
|
||||
onClientError: function(errorObj, response, requestOptions) {
|
||||
if (errorObj.error.code == 1) {
|
||||
deluge.events.fire('logout');
|
||||
this.show(true);
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
onShow: function() {
|
||||
this.passwordField.focus(true, true);
|
||||
this.form.getForm().findField('password').focus(true, 10);
|
||||
}
|
||||
});
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
/*!
|
||||
* Deluge.Menus.js
|
||||
*
|
||||
*
|
||||
* Copyright (c) Damien Churchill 2009-2010 <damoxc@gmail.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
@ -34,7 +34,7 @@ deluge.menus = {
|
||||
onTorrentAction: function(item, e) {
|
||||
var ids = deluge.torrents.getSelectedIds();
|
||||
var action = item.initialConfig.torrentAction;
|
||||
|
||||
|
||||
switch (action) {
|
||||
case 'pause':
|
||||
case 'resume':
|
||||
@ -69,7 +69,7 @@ deluge.menus = {
|
||||
break;
|
||||
case 'recheck':
|
||||
deluge.client.core.force_recheck(ids, {
|
||||
success: function() {
|
||||
success: function() {
|
||||
deluge.ui.update();
|
||||
}
|
||||
});
|
||||
@ -81,7 +81,7 @@ deluge.menus = {
|
||||
}
|
||||
}
|
||||
|
||||
deluge.menus.torrent = new Ext.menu.Menu({
|
||||
deluge.menus.torrent = Ext.create('Ext.menu.Menu', {
|
||||
id: 'torrentMenu',
|
||||
items: [{
|
||||
torrentAction: 'pause',
|
||||
@ -98,11 +98,11 @@ deluge.menus.torrent = new Ext.menu.Menu({
|
||||
}, '-', {
|
||||
text: _('Options'),
|
||||
iconCls: 'icon-options',
|
||||
menu: new Ext.menu.Menu({
|
||||
menu: {
|
||||
items: [{
|
||||
text: _('D/L Speed Limit'),
|
||||
iconCls: 'x-deluge-downloading',
|
||||
menu: new Ext.menu.Menu({
|
||||
menu: {
|
||||
items: [{
|
||||
text: _('5 KiB/s')
|
||||
}, {
|
||||
@ -116,11 +116,11 @@ deluge.menus.torrent = new Ext.menu.Menu({
|
||||
},{
|
||||
text: _('Unlimited')
|
||||
}]
|
||||
})
|
||||
}
|
||||
}, {
|
||||
text: _('U/L Speed Limit'),
|
||||
iconCls: 'x-deluge-seeding',
|
||||
menu: new Ext.menu.Menu({
|
||||
menu: {
|
||||
items: [{
|
||||
text: _('5 KiB/s')
|
||||
}, {
|
||||
@ -134,11 +134,11 @@ deluge.menus.torrent = new Ext.menu.Menu({
|
||||
},{
|
||||
text: _('Unlimited')
|
||||
}]
|
||||
})
|
||||
}
|
||||
}, {
|
||||
text: _('Connection Limit'),
|
||||
iconCls: 'x-deluge-connections',
|
||||
menu: new Ext.menu.Menu({
|
||||
menu: {
|
||||
items: [{
|
||||
text: _('50')
|
||||
}, {
|
||||
@ -152,11 +152,11 @@ deluge.menus.torrent = new Ext.menu.Menu({
|
||||
},{
|
||||
text: _('Unlimited')
|
||||
}]
|
||||
})
|
||||
}
|
||||
}, {
|
||||
text: _('Upload Slot Limit'),
|
||||
iconCls: 'icon-upload-slots',
|
||||
menu: new Ext.menu.Menu({
|
||||
menu: {
|
||||
items: [{
|
||||
text: _('0')
|
||||
}, {
|
||||
@ -170,17 +170,17 @@ deluge.menus.torrent = new Ext.menu.Menu({
|
||||
},{
|
||||
text: _('Unlimited')
|
||||
}]
|
||||
})
|
||||
}
|
||||
}, {
|
||||
id: 'auto_managed',
|
||||
text: _('Auto Managed'),
|
||||
checked: false
|
||||
}]
|
||||
})
|
||||
}
|
||||
}, '-', {
|
||||
text: _('Queue'),
|
||||
iconCls: 'icon-queue',
|
||||
menu: new Ext.menu.Menu({
|
||||
menu: {
|
||||
items: [{
|
||||
torrentAction: 'top',
|
||||
text: _('Top'),
|
||||
@ -206,7 +206,7 @@ deluge.menus.torrent = new Ext.menu.Menu({
|
||||
handler: deluge.menus.onTorrentAction,
|
||||
scope: deluge.menus
|
||||
}]
|
||||
})
|
||||
}
|
||||
}, '-', {
|
||||
torrentAction: 'update',
|
||||
text: _('Update Tracker'),
|
||||
@ -240,7 +240,7 @@ deluge.menus.torrent = new Ext.menu.Menu({
|
||||
}]
|
||||
});
|
||||
|
||||
deluge.menus.filePriorities = new Ext.menu.Menu({
|
||||
deluge.menus.filePriorities = Ext.create('Ext.menu.Menu', {
|
||||
id: 'filePrioritiesMenu',
|
||||
items: [{
|
||||
id: 'expandAll',
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
/*!
|
||||
* Deluge.MoveStorage.js
|
||||
*
|
||||
* Copyright (c) Damien Churchill 2009-2010 <damoxc@gmail.com>
|
||||
*
|
||||
* Copyright (c) Damien Churchill 2009-2011 <damoxc@gmail.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@ -30,30 +30,26 @@
|
||||
* statement from all source files in the program, then also delete it here.
|
||||
*/
|
||||
|
||||
Ext.namespace('Deluge');
|
||||
Deluge.MoveStorage = Ext.extend(Ext.Window, {
|
||||
|
||||
constructor: function(config) {
|
||||
config = Ext.apply({
|
||||
title: _('Move Storage'),
|
||||
width: 375,
|
||||
height: 110,
|
||||
layout: 'fit',
|
||||
buttonAlign: 'right',
|
||||
closeAction: 'hide',
|
||||
closable: true,
|
||||
iconCls: 'x-deluge-move-storage',
|
||||
plain: true,
|
||||
resizable: false
|
||||
}, config);
|
||||
Deluge.MoveStorage.superclass.constructor.call(this, config);
|
||||
},
|
||||
Ext.define('Deluge.MoveStorage', {
|
||||
extend: 'Ext.Window',
|
||||
|
||||
title: _('Move Storage'),
|
||||
width: 375,
|
||||
height: 110,
|
||||
layout: 'fit',
|
||||
buttonAlign: 'right',
|
||||
closeAction: 'hide',
|
||||
closable: true,
|
||||
iconCls: 'x-deluge-move-storage',
|
||||
plain: true,
|
||||
resizable: false,
|
||||
|
||||
initComponent: function() {
|
||||
Deluge.MoveStorage.superclass.initComponent.call(this);
|
||||
this.callParent(arguments);
|
||||
|
||||
this.addButton(_('Cancel'), this.onCancel, this);
|
||||
this.addButton(_('Move'), this.onMove, this);
|
||||
// FIXME: Replace the buttons
|
||||
//this.addButton(_('Cancel'), this.onCancel, this);
|
||||
//this.addButton(_('Move'), this.onMove, this);
|
||||
|
||||
this.form = this.add({
|
||||
xtype: 'form',
|
||||
@ -82,12 +78,12 @@ Deluge.MoveStorage = Ext.extend(Ext.Window, {
|
||||
},
|
||||
|
||||
hide: function() {
|
||||
Deluge.MoveStorage.superclass.hide.call(this);
|
||||
this.callParent(arguments);
|
||||
this.torrentIds = null;
|
||||
},
|
||||
|
||||
show: function(torrentIds) {
|
||||
Deluge.MoveStorage.superclass.show.call(this);
|
||||
this.callParent(arguments);
|
||||
this.torrentIds = torrentIds;
|
||||
},
|
||||
|
||||
@ -101,4 +97,3 @@ Deluge.MoveStorage = Ext.extend(Ext.Window, {
|
||||
this.hide();
|
||||
}
|
||||
});
|
||||
deluge.moveStorage = new Deluge.MoveStorage();
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
/*!
|
||||
* Deluge.OtherLimitWindow.js
|
||||
*
|
||||
* Copyright (c) Damien Churchill 2009-2010 <damoxc@gmail.com>
|
||||
*
|
||||
* Copyright (c) Damien Churchill 2009-2011 <damoxc@gmail.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@ -29,14 +29,14 @@
|
||||
* this exception statement from your version. If you delete this exception
|
||||
* statement from all source files in the program, then also delete it here.
|
||||
*/
|
||||
Ext.ns('Deluge');
|
||||
|
||||
/**
|
||||
* @class Deluge.OtherLimitWindow
|
||||
* @extends Ext.Window
|
||||
*/
|
||||
Deluge.OtherLimitWindow = Ext.extend(Ext.Window, {
|
||||
|
||||
Ext.define('Deluge.OtherLimitWindow', {
|
||||
extend: 'Ext.Window',
|
||||
|
||||
layout: 'fit',
|
||||
width: 210,
|
||||
height: 100,
|
||||
@ -44,7 +44,7 @@ Deluge.OtherLimitWindow = Ext.extend(Ext.Window, {
|
||||
closeAction: 'hide',
|
||||
|
||||
initComponent: function() {
|
||||
Deluge.OtherLimitWindow.superclass.initComponent.call(this);
|
||||
this.callParent(arguments);
|
||||
this.form = this.add({
|
||||
xtype: 'form',
|
||||
baseCls: 'x-plain',
|
||||
@ -69,8 +69,17 @@ Deluge.OtherLimitWindow = Ext.extend(Ext.Window, {
|
||||
this.setSize(180, 100);
|
||||
}
|
||||
|
||||
this.addButton(_('Cancel'), this.onCancelClick, this);
|
||||
this.addButton(_('Ok'), this.onOkClick, this);
|
||||
this.addDocked({
|
||||
xtype: 'toolbar',
|
||||
dock: 'bottom',
|
||||
defaultType: 'button',
|
||||
items: [
|
||||
'->',
|
||||
{text: _('Cancel'), handler: this.onCancelClick, scope: this},
|
||||
{text: _('Ok'), handler: this.onOkClick, scope: this}
|
||||
]
|
||||
});
|
||||
|
||||
this.afterMethod('show', this.doFocusField, this);
|
||||
},
|
||||
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
/*!
|
||||
* Deluge.Plugin.js
|
||||
*
|
||||
* Copyright (c) Damien Churchill 2009-2010 <damoxc@gmail.com>
|
||||
*
|
||||
* Copyright (c) Damien Churchill 2009-2011 <damoxc@gmail.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@ -29,13 +29,13 @@
|
||||
* this exception statement from your version. If you delete this exception
|
||||
* statement from all source files in the program, then also delete it here.
|
||||
*/
|
||||
Ext.ns('Deluge');
|
||||
|
||||
/**
|
||||
* @class Deluge.Plugin
|
||||
* @extends Ext.util.Observable
|
||||
*/
|
||||
Deluge.Plugin = Ext.extend(Ext.util.Observable, {
|
||||
Ext.define('Deluge.Plugin', {
|
||||
extend: 'Ext.util.Observable',
|
||||
|
||||
/**
|
||||
* The plugins name
|
||||
@ -59,9 +59,9 @@ Deluge.Plugin = Ext.extend(Ext.util.Observable, {
|
||||
*/
|
||||
"disabled": true
|
||||
});
|
||||
Deluge.Plugin.superclass.constructor.call(this, config);
|
||||
this.callParent(arguments);
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Disables the plugin, firing the "{@link #disabled}" event and
|
||||
* then executing the plugins clean up method onDisabled.
|
||||
@ -70,7 +70,7 @@ Deluge.Plugin = Ext.extend(Ext.util.Observable, {
|
||||
this.fireEvent("disabled", this);
|
||||
if (this.onDisable) this.onDisable();
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Enables the plugin, firing the "{@link #enabled}" event and
|
||||
* then executes the plugins setup method, onEnabled.
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
/*!
|
||||
* Deluge.RemoveWindow.js
|
||||
*
|
||||
* Copyright (c) Damien Churchill 2009-2010 <damoxc@gmail.com>
|
||||
*
|
||||
* Copyright (c) Damien Churchill 2009-2011 <damoxc@gmail.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@ -34,29 +34,39 @@
|
||||
* @class Deluge.RemoveWindow
|
||||
* @extends Ext.Window
|
||||
*/
|
||||
Deluge.RemoveWindow = Ext.extend(Ext.Window, {
|
||||
|
||||
Ext.define('Deluge.RemoveWindow', {
|
||||
extend: 'Ext.Window',
|
||||
|
||||
title: _('Remove Torrent'),
|
||||
layout: 'fit',
|
||||
width: 350,
|
||||
height: 100,
|
||||
|
||||
|
||||
buttonAlign: 'right',
|
||||
closeAction: 'hide',
|
||||
closable: true,
|
||||
iconCls: 'x-deluge-remove-window-icon',
|
||||
plain: true,
|
||||
|
||||
bodyStyle: 'padding: 5px; padding-left: 10px;',
|
||||
html: 'Are you sure you wish to remove the torrent (s)?',
|
||||
|
||||
|
||||
initComponent: function() {
|
||||
Deluge.RemoveWindow.superclass.initComponent.call(this);
|
||||
this.addButton(_('Cancel'), this.onCancel, this);
|
||||
this.addButton(_('Remove With Data'), this.onRemoveData, this);
|
||||
this.addButton(_('Remove Torrent'), this.onRemove, this);
|
||||
this.callParent(arguments);
|
||||
this.addDocked({
|
||||
xtype: 'toolbar',
|
||||
dock: 'bottom',
|
||||
defaultType: 'button',
|
||||
items: [
|
||||
'->',
|
||||
{text: _('Cancel'), handler: this.onCancel, scope: this},
|
||||
{text: _('Remove With Data'), handler: this.onRemoveData, scope: this},
|
||||
{text: _('Remove Torrent'), handler: this.onRemove, scope: this}
|
||||
]
|
||||
});
|
||||
this.add({
|
||||
bodyStyle: 'padding: 10px;',
|
||||
border: false,
|
||||
html: 'Are you sure you wish to remove the torrent (s)?',
|
||||
});
|
||||
},
|
||||
|
||||
|
||||
remove: function(removeData) {
|
||||
Ext.each(this.torrentIds, function(torrentId) {
|
||||
deluge.client.core.remove_torrent(torrentId, removeData, {
|
||||
@ -67,32 +77,30 @@ Deluge.RemoveWindow = Ext.extend(Ext.Window, {
|
||||
torrentId: torrentId
|
||||
});
|
||||
}, this);
|
||||
|
||||
|
||||
},
|
||||
|
||||
|
||||
show: function(ids) {
|
||||
Deluge.RemoveWindow.superclass.show.call(this);
|
||||
this.callParent(arguments);
|
||||
this.torrentIds = ids;
|
||||
},
|
||||
|
||||
|
||||
onCancel: function() {
|
||||
this.hide();
|
||||
this.torrentIds = null;
|
||||
},
|
||||
|
||||
|
||||
onRemove: function() {
|
||||
this.remove(false);
|
||||
},
|
||||
|
||||
|
||||
onRemoveData: function() {
|
||||
this.remove(true);
|
||||
},
|
||||
|
||||
|
||||
onRemoved: function(torrentId) {
|
||||
deluge.events.fire('torrentRemoved', torrentId);
|
||||
this.hide();
|
||||
deluge.ui.update();
|
||||
}
|
||||
});
|
||||
|
||||
deluge.removeWindow = new Deluge.RemoveWindow();
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
/*!
|
||||
* Deluge.Sidebar.js
|
||||
*
|
||||
* Copyright (c) Damien Churchill 2009-2010 <damoxc@gmail.com>
|
||||
*
|
||||
* Copyright (c) Damien Churchill 2009-2011 <damoxc@gmail.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@ -39,7 +39,24 @@
|
||||
* @author Damien Churchill <damoxc@gmail.com>
|
||||
* @version 1.3
|
||||
*/
|
||||
Deluge.Sidebar = Ext.extend(Ext.Panel, {
|
||||
Ext.define('Deluge.Sidebar', {
|
||||
extend: 'Ext.panel.Panel',
|
||||
|
||||
id: 'sidebar',
|
||||
region: 'west',
|
||||
cls: 'deluge-sidebar',
|
||||
title: _('Filters'),
|
||||
layout: 'accordion',
|
||||
layoutCfg: {
|
||||
multi: true,
|
||||
collapseFirst: true
|
||||
},
|
||||
split: true,
|
||||
width: 200,
|
||||
minSize: 175,
|
||||
collapsible: true,
|
||||
margins: '5 0 0 5',
|
||||
cmargins: '5 0 0 5',
|
||||
|
||||
// private
|
||||
panels: {},
|
||||
@ -47,47 +64,34 @@ Deluge.Sidebar = Ext.extend(Ext.Panel, {
|
||||
// private
|
||||
selected: null,
|
||||
|
||||
constructor: function(config) {
|
||||
config = Ext.apply({
|
||||
id: 'sidebar',
|
||||
region: 'west',
|
||||
cls: 'deluge-sidebar',
|
||||
title: _('Filters'),
|
||||
layout: 'accordion',
|
||||
split: true,
|
||||
width: 200,
|
||||
minSize: 175,
|
||||
collapsible: true,
|
||||
margins: '5 0 0 5',
|
||||
cmargins: '5 0 0 5'
|
||||
}, config);
|
||||
Deluge.Sidebar.superclass.constructor.call(this, config);
|
||||
},
|
||||
|
||||
// private
|
||||
initComponent: function() {
|
||||
Deluge.Sidebar.superclass.initComponent.call(this);
|
||||
this.callParent(arguments);
|
||||
deluge.events.on("disconnect", this.onDisconnect, this);
|
||||
},
|
||||
|
||||
createFilter: function(filter, states) {
|
||||
var panel = new Deluge.FilterPanel({
|
||||
var panel = Ext.create('Deluge.FilterPanel', {
|
||||
filter: filter
|
||||
});
|
||||
panel.on('selectionchange', function(view, nodes) {
|
||||
deluge.ui.update();
|
||||
});
|
||||
this.add(panel);
|
||||
|
||||
|
||||
this.doLayout();
|
||||
this.panels[filter] = panel;
|
||||
|
||||
panel.header.on('click', function(header) {
|
||||
var s = panel.getStore(),
|
||||
sm = panel.getSelectionModel();
|
||||
|
||||
if (!deluge.config.sidebar_multiple_filters) {
|
||||
deluge.ui.update();
|
||||
}
|
||||
if (!panel.list.getSelectionCount()) {
|
||||
panel.list.select(0);
|
||||
|
||||
if (!sm.hasSelection() && s.count() > 0) {
|
||||
sm.select([s.first()]);
|
||||
}
|
||||
});
|
||||
this.fireEvent('filtercreate', this, panel);
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
/*!
|
||||
* Deluge.Statusbar.js
|
||||
*
|
||||
* Copyright (c) Damien Churchill 2009-2010 <damoxc@gmail.com>
|
||||
*
|
||||
* Copyright (c) Damien Churchill 2009-2011 <damoxc@gmail.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@ -29,25 +29,21 @@
|
||||
* this exception statement from your version. If you delete this exception
|
||||
* statement from all source files in the program, then also delete it here.
|
||||
*/
|
||||
Ext.namespace('Deluge');
|
||||
|
||||
Deluge.Statusbar = Ext.extend(Ext.ux.StatusBar, {
|
||||
constructor: function(config) {
|
||||
config = Ext.apply({
|
||||
id: 'deluge-statusbar',
|
||||
defaultIconCls: 'x-deluge-statusbar x-not-connected',
|
||||
defaultText: _('Not Connected')
|
||||
}, config);
|
||||
Deluge.Statusbar.superclass.constructor.call(this, config);
|
||||
},
|
||||
|
||||
Ext.define('Deluge.StatusBar', {
|
||||
extend: 'Ext.ux.statusbar.StatusBar',
|
||||
|
||||
id: 'deluge-statusbar',
|
||||
defaultIconCls: 'x-deluge-statusbar x-not-connected',
|
||||
defaultText: _('Not Connected'),
|
||||
|
||||
initComponent: function() {
|
||||
Deluge.Statusbar.superclass.initComponent.call(this);
|
||||
|
||||
this.callParent(arguments);
|
||||
|
||||
deluge.events.on('connect', this.onConnect, this);
|
||||
deluge.events.on('disconnect', this.onDisconnect, this);
|
||||
},
|
||||
|
||||
|
||||
createButtons: function() {
|
||||
this.buttons = this.add({
|
||||
id: 'statusbar-connections',
|
||||
@ -55,7 +51,7 @@ Deluge.Statusbar = Ext.extend(Ext.ux.StatusBar, {
|
||||
cls: 'x-btn-text-icon',
|
||||
iconCls: 'x-deluge-connections',
|
||||
tooltip: _('Connections'),
|
||||
menu: new Deluge.StatusbarMenu({
|
||||
menu: Ext.create('Deluge.StatusbarMenu', {
|
||||
items: [{
|
||||
text: '50',
|
||||
value: '50',
|
||||
@ -102,7 +98,7 @@ Deluge.Statusbar = Ext.extend(Ext.ux.StatusBar, {
|
||||
cls: 'x-btn-text-icon',
|
||||
iconCls: 'x-deluge-downloading',
|
||||
tooltip: _('Download Speed'),
|
||||
menu: new Deluge.StatusbarMenu({
|
||||
menu: Ext.create('Deluge.StatusbarMenu', {
|
||||
items: [{
|
||||
value: '5',
|
||||
text: '5 KiB/s',
|
||||
@ -150,7 +146,7 @@ Deluge.Statusbar = Ext.extend(Ext.ux.StatusBar, {
|
||||
cls: 'x-btn-text-icon',
|
||||
iconCls: 'x-deluge-seeding',
|
||||
tooltip: _('Upload Speed'),
|
||||
menu: new Deluge.StatusbarMenu({
|
||||
menu: Ext.create('Deluge.StatusbarMenu', {
|
||||
items: [{
|
||||
value: '5',
|
||||
text: '5 KiB/s',
|
||||
@ -221,7 +217,7 @@ Deluge.Statusbar = Ext.extend(Ext.ux.StatusBar, {
|
||||
});
|
||||
this.created = true;
|
||||
},
|
||||
|
||||
|
||||
onConnect: function() {
|
||||
this.setStatus({
|
||||
iconCls: 'x-connected',
|
||||
@ -246,18 +242,18 @@ Deluge.Statusbar = Ext.extend(Ext.ux.StatusBar, {
|
||||
});
|
||||
this.doLayout();
|
||||
},
|
||||
|
||||
|
||||
update: function(stats) {
|
||||
if (!stats) return;
|
||||
|
||||
|
||||
function addSpeed(val) {return val + ' KiB/s'}
|
||||
|
||||
var updateStat = function(name, config) {
|
||||
|
||||
var updateStat = Ext.bind(function(name, config) {
|
||||
var item = this.items.get('statusbar-' + name);
|
||||
if (config.limit.value > 0) {
|
||||
var value = (config.value.formatter) ? config.value.formatter(config.value.value, true) : config.value.value;
|
||||
var limit = (config.limit.formatter) ? config.limit.formatter(config.limit.value, true) : config.limit.value;
|
||||
var str = String.format(config.format, value, limit);
|
||||
var str = Ext.String.format(config.format, value, limit);
|
||||
} else {
|
||||
var str = (config.value.formatter) ? config.value.formatter(config.value.value, true) : config.value.value;
|
||||
}
|
||||
@ -265,8 +261,8 @@ Deluge.Statusbar = Ext.extend(Ext.ux.StatusBar, {
|
||||
|
||||
if (!item.menu) return;
|
||||
item.menu.setValue(config.limit.value);
|
||||
}.createDelegate(this);
|
||||
|
||||
}, this);
|
||||
|
||||
updateStat('connections', {
|
||||
value: {value: stats.num_connections},
|
||||
limit: {value: stats.max_num_connections},
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
/*!
|
||||
* Deluge.StatusbarMenu.js
|
||||
*
|
||||
*
|
||||
* Copyright (c) Damien Churchill 2009-2010 <damoxc@gmail.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
@ -37,10 +37,10 @@ Ext.ns('Deluge');
|
||||
* @extends Ext.menu.Menu
|
||||
*/
|
||||
Deluge.StatusbarMenu = Ext.extend(Ext.menu.Menu, {
|
||||
|
||||
|
||||
initComponent: function() {
|
||||
Deluge.StatusbarMenu.superclass.initComponent.call(this);
|
||||
this.otherWin = new Deluge.OtherLimitWindow(this.initialConfig.otherWin || {});
|
||||
this.otherWin = Ext.create('Deluge.OtherLimitWindow', this.initialConfig.otherWin || {});
|
||||
|
||||
this.items.each(function(item) {
|
||||
if (item.getXType() != 'menucheckitem') return;
|
||||
@ -51,7 +51,7 @@ Deluge.StatusbarMenu = Ext.extend(Ext.menu.Menu, {
|
||||
}
|
||||
}, this);
|
||||
},
|
||||
|
||||
|
||||
setValue: function(value) {
|
||||
var beenSet = false;
|
||||
// set the new value
|
||||
@ -67,12 +67,12 @@ Deluge.StatusbarMenu = Ext.extend(Ext.menu.Menu, {
|
||||
beenSet = true;
|
||||
} else {
|
||||
item.setChecked(false);
|
||||
}
|
||||
}
|
||||
item.resumeEvents();
|
||||
}
|
||||
}
|
||||
|
||||
if (item.value == 'other') other = item;
|
||||
});
|
||||
});
|
||||
|
||||
if (beenSet) return;
|
||||
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
/*!
|
||||
* Deluge.Toolbar.js
|
||||
*
|
||||
*
|
||||
* Copyright (c) Damien Churchill 2009-2010 <damoxc@gmail.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
@ -116,53 +116,49 @@ Deluge.Toolbar = Ext.extend(Ext.Toolbar, {
|
||||
connectedButtons: [
|
||||
'add', 'remove', 'pause', 'resume', 'up', 'down'
|
||||
],
|
||||
|
||||
|
||||
initComponent: function() {
|
||||
Deluge.Toolbar.superclass.initComponent.call(this);
|
||||
deluge.events.on('connect', this.onConnect, this);
|
||||
deluge.events.on('login', this.onLogin, this);
|
||||
},
|
||||
|
||||
|
||||
onConnect: function() {
|
||||
Ext.each(this.connectedButtons, function(buttonId) {
|
||||
this.items.get(buttonId).enable();
|
||||
}, this);
|
||||
},
|
||||
|
||||
|
||||
onDisconnect: function() {
|
||||
Ext.each(this.connectedButtons, function(buttonId) {
|
||||
this.items.get(buttonId).disable();
|
||||
}, this);
|
||||
},
|
||||
|
||||
|
||||
onLogin: function() {
|
||||
this.items.get('logout').enable();
|
||||
},
|
||||
|
||||
|
||||
onLogout: function() {
|
||||
this.items.get('logout').disable();
|
||||
deluge.login.logout();
|
||||
},
|
||||
|
||||
|
||||
onConnectionManagerClick: function() {
|
||||
deluge.connectionManager.show();
|
||||
},
|
||||
|
||||
|
||||
onHelpClick: function() {
|
||||
window.open('http://dev.deluge-torrent.org/wiki/UserGuide');
|
||||
},
|
||||
|
||||
|
||||
onPreferencesClick: function() {
|
||||
deluge.preferences.show();
|
||||
},
|
||||
|
||||
|
||||
onTorrentAction: function(item) {
|
||||
var selection = deluge.torrents.getSelections();
|
||||
var ids = [];
|
||||
Ext.each(selection, function(record) {
|
||||
ids.push(record.id);
|
||||
});
|
||||
|
||||
var ids = deluge.torrents.getSelectedIds();
|
||||
|
||||
switch (item.id) {
|
||||
case 'remove':
|
||||
deluge.removeWindow.show(ids);
|
||||
@ -185,7 +181,7 @@ Deluge.Toolbar = Ext.extend(Ext.Toolbar, {
|
||||
break;
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
onTorrentAdd: function() {
|
||||
deluge.add.show();
|
||||
}
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
/*!
|
||||
* Deluge.TorrentGrid.js
|
||||
*
|
||||
* Copyright (c) Damien Churchill 2009-2010 <damoxc@gmail.com>
|
||||
* Copyright (c) Damien Churchill 2009-2011 <damoxc@gmail.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@ -30,240 +30,257 @@
|
||||
* statement from all source files in the program, then also delete it here.
|
||||
*/
|
||||
|
||||
(function() {
|
||||
/* Renderers for the Torrent Grid */
|
||||
function queueRenderer(value) {
|
||||
return (value == -1) ? '' : value + 1;
|
||||
}
|
||||
function torrentNameRenderer(value, p, r) {
|
||||
return Ext.String.format('<div class="torrent-name x-deluge-{0}">{1}</div>', r.data['state'].toLowerCase(), value);
|
||||
}
|
||||
function torrentSpeedRenderer(value) {
|
||||
if (!value) return;
|
||||
return fspeed(value);
|
||||
}
|
||||
function torrentProgressRenderer(value, md, r) {
|
||||
value = Number(value);
|
||||
var width = this.query('gridcolumn[dataIndex=progress]')[0].getWidth(),
|
||||
progress = value,
|
||||
text = r.data['state'] + ' ' + value.toFixed(2) + '%';
|
||||
return Deluge.progressBar(value, width - 8, text);
|
||||
}
|
||||
function seedsRenderer(value, p, r) {
|
||||
if (r.data['total_seeds'] > -1) {
|
||||
return Ext.String.format('{0} ({1})', value, r.data['total_seeds']);
|
||||
} else {
|
||||
return value;
|
||||
}
|
||||
}
|
||||
function peersRenderer(value, p, r) {
|
||||
if (r.data['total_peers'] > -1) {
|
||||
return Ext.String.format('{0} ({1})', value, r.data['total_peers']);
|
||||
} else {
|
||||
return value;
|
||||
}
|
||||
}
|
||||
function availRenderer(value, p, r) {
|
||||
return (value < 0) ? '∞' : Number(value).toFixed(3);
|
||||
}
|
||||
function trackerRenderer(value, p, r) {
|
||||
return Ext.String.format('<div style="background: url(' + deluge.config.base + 'tracker/{0}) no-repeat; padding-left: 20px;">{0}</div>', value);
|
||||
}
|
||||
|
||||
/* Renderers for the Torrent Grid */
|
||||
function queueRenderer(value) {
|
||||
return (value == -1) ? '' : value + 1;
|
||||
}
|
||||
function torrentNameRenderer(value, p, r) {
|
||||
return String.format('<div class="torrent-name x-deluge-{0}">{1}</div>', r.data['state'].toLowerCase(), value);
|
||||
}
|
||||
function torrentSpeedRenderer(value) {
|
||||
if (!value) return;
|
||||
return fspeed(value);
|
||||
}
|
||||
function torrentProgressRenderer(value, p, r) {
|
||||
value = new Number(value);
|
||||
var progress = value;
|
||||
var text = r.data['state'] + ' ' + value.toFixed(2) + '%';
|
||||
var width = new Number(this.style.match(/\w+:\s*(\d+)\w+/)[1]);
|
||||
return Deluge.progressBar(value, width - 8, text);
|
||||
}
|
||||
function seedsRenderer(value, p, r) {
|
||||
if (r.data['total_seeds'] > -1) {
|
||||
return String.format('{0} ({1})', value, r.data['total_seeds']);
|
||||
} else {
|
||||
return value;
|
||||
function etaSorter(eta) {
|
||||
return eta * -1;
|
||||
}
|
||||
|
||||
function dateOrNever(date) {
|
||||
return date > 0.0 ? fdate(date) : "Never"
|
||||
}
|
||||
|
||||
/**
|
||||
* Deluge.TorrentGrid Class
|
||||
*
|
||||
* @author Damien Churchill <damoxc@gmail.com>
|
||||
* @version 1.3
|
||||
*
|
||||
* @class Deluge.TorrentGrid
|
||||
* @extends Ext.grid.Panel
|
||||
* @constructor
|
||||
* @param {Object} config Configuration options
|
||||
*/
|
||||
Ext.define('Deluge.TorrentGrid', {
|
||||
extend: 'Ext.grid.Panel',
|
||||
|
||||
// object to store contained torrent ids
|
||||
torrents: {},
|
||||
|
||||
columns: [{
|
||||
header: _('#'),
|
||||
width: 30,
|
||||
sortable: true,
|
||||
renderer: queueRenderer,
|
||||
dataIndex: 'queue'
|
||||
}, {
|
||||
flex: 1,
|
||||
header: _('Name'),
|
||||
width: 150,
|
||||
sortable: true,
|
||||
renderer: torrentNameRenderer,
|
||||
dataIndex: 'name'
|
||||
}, {
|
||||
header: _('Size'),
|
||||
width: 75,
|
||||
sortable: true,
|
||||
renderer: fsize,
|
||||
dataIndex: 'total_size'
|
||||
}, {
|
||||
header: _('Progress'),
|
||||
width: 150,
|
||||
sortable: true,
|
||||
renderer: torrentProgressRenderer,
|
||||
dataIndex: 'progress'
|
||||
}, {
|
||||
header: _('Seeders'),
|
||||
width: 60,
|
||||
sortable: true,
|
||||
renderer: seedsRenderer,
|
||||
dataIndex: 'num_seeds'
|
||||
}, {
|
||||
header: _('Peers'),
|
||||
width: 60,
|
||||
sortable: true,
|
||||
renderer: peersRenderer,
|
||||
dataIndex: 'num_peers'
|
||||
}, {
|
||||
header: _('Down Speed'),
|
||||
width: 80,
|
||||
sortable: true,
|
||||
renderer: torrentSpeedRenderer,
|
||||
dataIndex: 'download_payload_rate'
|
||||
}, {
|
||||
header: _('Up Speed'),
|
||||
width: 80,
|
||||
sortable: true,
|
||||
renderer: torrentSpeedRenderer,
|
||||
dataIndex: 'upload_payload_rate'
|
||||
}, {
|
||||
header: _('ETA'),
|
||||
width: 60,
|
||||
sortable: true,
|
||||
renderer: ftime,
|
||||
dataIndex: 'eta'
|
||||
}, {
|
||||
header: _('Ratio'),
|
||||
width: 60,
|
||||
sortable: true,
|
||||
renderer: availRenderer,
|
||||
dataIndex: 'ratio'
|
||||
}, {
|
||||
header: _('Avail'),
|
||||
width: 60,
|
||||
sortable: true,
|
||||
renderer: availRenderer,
|
||||
dataIndex: 'distributed_copies'
|
||||
}, {
|
||||
header: _('Added'),
|
||||
width: 80,
|
||||
sortable: true,
|
||||
renderer: fdate,
|
||||
dataIndex: 'time_added'
|
||||
}, {
|
||||
header: _('Last Seen Complete'),
|
||||
width: 80,
|
||||
sortable: true,
|
||||
renderer: dateOrNever,
|
||||
dataIndex: 'last_seen_complete'
|
||||
}, {
|
||||
header: _('Tracker'),
|
||||
width: 120,
|
||||
sortable: true,
|
||||
renderer: trackerRenderer,
|
||||
dataIndex: 'tracker_host'
|
||||
}, {
|
||||
header: _('Save Path'),
|
||||
width: 120,
|
||||
sortable: true,
|
||||
renderer: fplain,
|
||||
dataIndex: 'save_path'
|
||||
}, {
|
||||
header: _('Owner'),
|
||||
width: 80,
|
||||
sortable: true,
|
||||
renderer: fplain,
|
||||
dataIndex: 'owner'
|
||||
}, {
|
||||
header: _('Public'),
|
||||
width: 80,
|
||||
sortable: true,
|
||||
renderer: fplain,
|
||||
dataIndex: 'public'
|
||||
}, {
|
||||
header: _('Shared'),
|
||||
width: 80,
|
||||
sortable: true,
|
||||
renderer: fplain,
|
||||
dataIndex: 'shared'
|
||||
}],
|
||||
|
||||
meta: {
|
||||
root: 'torrents',
|
||||
idProperty: 'id',
|
||||
fields: [
|
||||
{name: 'queue', sortType: Deluge.data.SortTypes.asQueuePosition},
|
||||
{name: 'name'},
|
||||
{name: 'total_size', type: 'int'},
|
||||
{name: 'state'},
|
||||
{name: 'progress', type: 'float'},
|
||||
{name: 'num_seeds', type: 'int'},
|
||||
{name: 'total_seeds', type: 'int'},
|
||||
{name: 'num_peers', type: 'int'},
|
||||
{name: 'total_peers', type: 'int'},
|
||||
{name: 'download_payload_rate', type: 'int'},
|
||||
{name: 'upload_payload_speed', type: 'int'},
|
||||
{name: 'eta', type: 'int', sortType: etaSorter},
|
||||
{name: 'ratio', type: 'float'},
|
||||
{name: 'distributed_copies', type: 'float'},
|
||||
{name: 'time_added', type: 'int'},
|
||||
{name: 'tracker_host'},
|
||||
{name: 'save_path'}
|
||||
]
|
||||
},
|
||||
|
||||
store: Ext.create('Ext.data.Store', {
|
||||
model: 'Deluge.data.Torrent',
|
||||
proxy: {
|
||||
type: 'memory',
|
||||
reader: {
|
||||
type: 'json',
|
||||
root: 'torrents'
|
||||
}
|
||||
}
|
||||
}
|
||||
function peersRenderer(value, p, r) {
|
||||
if (r.data['total_peers'] > -1) {
|
||||
return String.format('{0} ({1})', value, r.data['total_peers']);
|
||||
} else {
|
||||
return value;
|
||||
}
|
||||
}
|
||||
function availRenderer(value, p, r) {
|
||||
return (value < 0) ? '∞' : new Number(value).toFixed(3);
|
||||
}
|
||||
function trackerRenderer(value, p, r) {
|
||||
return String.format('<div style="background: url(' + deluge.config.base + 'tracker/{0}) no-repeat; padding-left: 20px;">{0}</div>', value);
|
||||
}
|
||||
}),
|
||||
|
||||
function etaSorter(eta) {
|
||||
return eta * -1;
|
||||
}
|
||||
viewConfig: {
|
||||
stateId: 'torrentGridView',
|
||||
stateful: true
|
||||
},
|
||||
|
||||
function dateOrNever(date) {
|
||||
return date > 0.0 ? fdate(date) : "Never"
|
||||
}
|
||||
|
||||
/**
|
||||
* Deluge.TorrentGrid Class
|
||||
*
|
||||
* @author Damien Churchill <damoxc@gmail.com>
|
||||
* @version 1.3
|
||||
*
|
||||
* @class Deluge.TorrentGrid
|
||||
* @extends Ext.grid.GridPanel
|
||||
* @constructor
|
||||
* @param {Object} config Configuration options
|
||||
*/
|
||||
Deluge.TorrentGrid = Ext.extend(Ext.grid.GridPanel, {
|
||||
|
||||
// object to store contained torrent ids
|
||||
torrents: {},
|
||||
|
||||
columns: [{
|
||||
id:'queue',
|
||||
header: _('#'),
|
||||
width: 30,
|
||||
sortable: true,
|
||||
renderer: queueRenderer,
|
||||
dataIndex: 'queue'
|
||||
}, {
|
||||
id:'name',
|
||||
header: _('Name'),
|
||||
width: 150,
|
||||
sortable: true,
|
||||
renderer: torrentNameRenderer,
|
||||
dataIndex: 'name'
|
||||
}, {
|
||||
header: _('Size'),
|
||||
width: 75,
|
||||
sortable: true,
|
||||
renderer: fsize,
|
||||
dataIndex: 'total_size'
|
||||
}, {
|
||||
header: _('Progress'),
|
||||
width: 150,
|
||||
sortable: true,
|
||||
renderer: torrentProgressRenderer,
|
||||
dataIndex: 'progress'
|
||||
}, {
|
||||
header: _('Seeders'),
|
||||
width: 60,
|
||||
sortable: true,
|
||||
renderer: seedsRenderer,
|
||||
dataIndex: 'num_seeds'
|
||||
}, {
|
||||
header: _('Peers'),
|
||||
width: 60,
|
||||
sortable: true,
|
||||
renderer: peersRenderer,
|
||||
dataIndex: 'num_peers'
|
||||
}, {
|
||||
header: _('Down Speed'),
|
||||
width: 80,
|
||||
sortable: true,
|
||||
renderer: torrentSpeedRenderer,
|
||||
dataIndex: 'download_payload_rate'
|
||||
}, {
|
||||
header: _('Up Speed'),
|
||||
width: 80,
|
||||
sortable: true,
|
||||
renderer: torrentSpeedRenderer,
|
||||
dataIndex: 'upload_payload_rate'
|
||||
}, {
|
||||
header: _('ETA'),
|
||||
width: 60,
|
||||
sortable: true,
|
||||
renderer: ftime,
|
||||
dataIndex: 'eta'
|
||||
}, {
|
||||
header: _('Ratio'),
|
||||
width: 60,
|
||||
sortable: true,
|
||||
renderer: availRenderer,
|
||||
dataIndex: 'ratio'
|
||||
}, {
|
||||
header: _('Avail'),
|
||||
width: 60,
|
||||
sortable: true,
|
||||
renderer: availRenderer,
|
||||
dataIndex: 'distributed_copies'
|
||||
}, {
|
||||
header: _('Added'),
|
||||
width: 80,
|
||||
sortable: true,
|
||||
renderer: fdate,
|
||||
dataIndex: 'time_added'
|
||||
}, {
|
||||
header: _('Last Seen Complete'),
|
||||
width: 80,
|
||||
sortable: true,
|
||||
renderer: dateOrNever,
|
||||
dataIndex: 'last_seen_complete'
|
||||
}, {
|
||||
header: _('Tracker'),
|
||||
width: 120,
|
||||
sortable: true,
|
||||
renderer: trackerRenderer,
|
||||
dataIndex: 'tracker_host'
|
||||
}, {
|
||||
header: _('Save Path'),
|
||||
width: 120,
|
||||
sortable: true,
|
||||
renderer: fplain,
|
||||
dataIndex: 'save_path'
|
||||
}, {
|
||||
header: _('Owner'),
|
||||
width: 80,
|
||||
sortable: true,
|
||||
renderer: fplain,
|
||||
dataIndex: 'owner'
|
||||
}, {
|
||||
header: _('Public'),
|
||||
width: 80,
|
||||
sortable: true,
|
||||
renderer: fplain,
|
||||
dataIndex: 'public'
|
||||
}, {
|
||||
header: _('Shared'),
|
||||
width: 80,
|
||||
sortable: true,
|
||||
renderer: fplain,
|
||||
dataIndex: 'shared'
|
||||
}],
|
||||
|
||||
meta: {
|
||||
root: 'torrents',
|
||||
idProperty: 'id',
|
||||
fields: [
|
||||
{name: 'queue', sortType: Deluge.data.SortTypes.asQueuePosition},
|
||||
{name: 'name'},
|
||||
{name: 'total_size', type: 'int'},
|
||||
{name: 'state'},
|
||||
{name: 'progress', type: 'float'},
|
||||
{name: 'num_seeds', type: 'int'},
|
||||
{name: 'total_seeds', type: 'int'},
|
||||
{name: 'num_peers', type: 'int'},
|
||||
{name: 'total_peers', type: 'int'},
|
||||
{name: 'download_payload_rate', type: 'int'},
|
||||
{name: 'upload_payload_speed', type: 'int'},
|
||||
{name: 'eta', type: 'int', sortType: etaSorter},
|
||||
{name: 'ratio', type: 'float'},
|
||||
{name: 'distributed_copies', type: 'float'},
|
||||
{name: 'time_added', type: 'int'},
|
||||
{name: 'tracker_host'},
|
||||
{name: 'save_path'}
|
||||
]
|
||||
},
|
||||
|
||||
constructor: function(config) {
|
||||
config = Ext.apply({
|
||||
id: 'torrentGrid',
|
||||
store: new Ext.data.JsonStore(this.meta),
|
||||
columns: this.columns,
|
||||
region: 'center',
|
||||
cls: 'deluge-torrents',
|
||||
stripeRows: true,
|
||||
autoExpandColumn: 'name',
|
||||
deferredRender:false,
|
||||
autoScroll:true,
|
||||
margins: '5 5 0 0',
|
||||
stateful: true,
|
||||
view: new Ext.ux.grid.BufferView({
|
||||
rowHeight: 26,
|
||||
scrollDelay: false
|
||||
})
|
||||
}, config);
|
||||
Deluge.TorrentGrid.superclass.constructor.call(this, config);
|
||||
},
|
||||
id: 'torrentGrid',
|
||||
region: 'center',
|
||||
cls: 'deluge-torrents',
|
||||
stripeRows: true,
|
||||
deferredRender:false,
|
||||
invalidateScrollOnRefresh: false,
|
||||
margins: '5 5 0 0',
|
||||
|
||||
initComponent: function() {
|
||||
Deluge.TorrentGrid.superclass.initComponent.call(this);
|
||||
this.callParent(arguments);
|
||||
deluge.events.on('torrentRemoved', this.onTorrentRemoved, this);
|
||||
deluge.events.on('disconnect', this.onDisconnect, this);
|
||||
|
||||
this.on('rowcontextmenu', function(grid, rowIndex, e) {
|
||||
e.stopEvent();
|
||||
var selection = grid.getSelectionModel();
|
||||
if (!selection.hasSelection()) {
|
||||
selection.selectRow(rowIndex);
|
||||
}
|
||||
deluge.menus.torrent.showAt(e.getPoint());
|
||||
this.on('itemcontextmenu', this.onTorrentSelected, this);
|
||||
|
||||
this.on('staterestore', function(stateful, state, eopts) {
|
||||
deluge.log('grid restoring state');
|
||||
});
|
||||
|
||||
this.on('selectionchange', function(grid, selected) {
|
||||
if (selected.length)
|
||||
deluge.details.update();
|
||||
else
|
||||
deluge.details.clear();
|
||||
});
|
||||
|
||||
this.on('statesave', function() {
|
||||
deluge.log('grid saving state');
|
||||
});
|
||||
|
||||
this.getView().on('statesave', function() {
|
||||
deluge.log('view saving state');
|
||||
});
|
||||
|
||||
this.getView().on('staterestore', function(stateful, state, eopts) {
|
||||
deluge.log('view restoring state');
|
||||
});
|
||||
},
|
||||
|
||||
@ -282,14 +299,14 @@
|
||||
* @ return {Array/Ext.data.Record} The record(s) representing the rows
|
||||
*/
|
||||
getSelected: function() {
|
||||
return this.getSelectionModel().getSelected();
|
||||
return this.getSelectionModel().getLastSelected();
|
||||
},
|
||||
|
||||
/**
|
||||
* Returns the currently selected records.
|
||||
*/
|
||||
getSelections: function() {
|
||||
return this.getSelectionModel().getSelections();
|
||||
return this.getSelectionModel().getSelection();
|
||||
},
|
||||
|
||||
/**
|
||||
@ -297,7 +314,7 @@
|
||||
* @return {String} The currently selected id.
|
||||
*/
|
||||
getSelectedId: function() {
|
||||
return this.getSelectionModel().getSelected().id
|
||||
return this.getSelected().getId()
|
||||
},
|
||||
|
||||
/**
|
||||
@ -306,8 +323,8 @@
|
||||
*/
|
||||
getSelectedIds: function() {
|
||||
var ids = [];
|
||||
Ext.each(this.getSelectionModel().getSelections(), function(r) {
|
||||
ids.push(r.id);
|
||||
Ext.each(this.getSelections(), function(r) {
|
||||
ids.push(r.getId());
|
||||
});
|
||||
return ids;
|
||||
},
|
||||
@ -336,9 +353,10 @@
|
||||
}
|
||||
}
|
||||
record.endEdit();
|
||||
record.commit();
|
||||
} else {
|
||||
var record = new Deluge.data.Torrent(torrent);
|
||||
record.id = t;
|
||||
var record = Ext.create('Deluge.data.Torrent', torrent);
|
||||
record.setId(t);
|
||||
this.torrents[t] = 1;
|
||||
newTorrents.push(record);
|
||||
}
|
||||
@ -347,16 +365,15 @@
|
||||
|
||||
// Remove any torrents that should not be in the store.
|
||||
store.each(function(record) {
|
||||
if (!torrents[record.id]) {
|
||||
if (!torrents[record.getId()]) {
|
||||
store.remove(record);
|
||||
delete this.torrents[record.id];
|
||||
delete this.torrents[record.getId()];
|
||||
}
|
||||
}, this);
|
||||
store.commitChanges();
|
||||
store.sync();
|
||||
|
||||
var sortState = store.getSortState()
|
||||
if (!sortState) return;
|
||||
store.sort(sortState.field, sortState.direction);
|
||||
// TODO: re-enable this is it's required.
|
||||
//store.sort(store.sorters);
|
||||
},
|
||||
|
||||
// private
|
||||
@ -376,7 +393,15 @@
|
||||
this.getStore().remove(record);
|
||||
delete this.torrents[torrentId];
|
||||
}, this);
|
||||
},
|
||||
|
||||
onTorrentSelected: function(grid, record, item, i, e, opts) {
|
||||
e.stopEvent();
|
||||
var sm = grid.getSelectionModel();
|
||||
if (!sm.hasSelection()) {
|
||||
sm.select(record);
|
||||
}
|
||||
var point = e.getPoint();
|
||||
deluge.menus.torrent.showAt(point.x, point.y);
|
||||
}
|
||||
});
|
||||
deluge.torrents = new Deluge.TorrentGrid();
|
||||
})();
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
/*!
|
||||
* Deluge.UI.js
|
||||
*
|
||||
* Copyright (c) Damien Churchill 2009-2010 <damoxc@gmail.com>
|
||||
* Copyright (c) Damien Churchill 2009-2011 <damoxc@gmail.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@ -47,17 +47,21 @@ deluge.ui = {
|
||||
* and set up various events that the UI will utilise.
|
||||
*/
|
||||
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();
|
||||
deluge.toolbar = new Deluge.Toolbar();
|
||||
|
||||
this.MainPanel = new Ext.Panel({
|
||||
deluge.events = Ext.create('Deluge.EventsManager');
|
||||
deluge.add = Ext.create('Deluge.add.AddWindow');
|
||||
deluge.details = Ext.create('Deluge.details.DetailsPanel');
|
||||
deluge.connectionManager = Ext.create('Deluge.ConnectionManager');
|
||||
deluge.editTrackers = Ext.create('Deluge.EditTrackersWindow');
|
||||
deluge.login = Ext.create('Deluge.LoginWindow');
|
||||
deluge.preferences = Ext.create('Deluge.preferences.PreferencesWindow');
|
||||
deluge.removeWindow = Ext.create('Deluge.RemoveWindow');
|
||||
deluge.sidebar = Ext.create('Deluge.Sidebar');
|
||||
deluge.statusbar = Ext.create('Deluge.StatusBar');
|
||||
deluge.toolbar = Ext.create('Deluge.Toolbar');
|
||||
deluge.torrents = Ext.create('Deluge.TorrentGrid');
|
||||
|
||||
this.MainPanel = Ext.create('Ext.Panel', {
|
||||
id: 'mainPanel',
|
||||
iconCls: 'x-deluge-main-panel',
|
||||
title: 'Deluge',
|
||||
@ -71,7 +75,7 @@ deluge.ui = {
|
||||
bbar: deluge.statusbar
|
||||
});
|
||||
|
||||
this.Viewport = new Ext.Viewport({
|
||||
this.Viewport = Ext.create('Ext.Viewport', {
|
||||
layout: 'fit',
|
||||
items: [this.MainPanel]
|
||||
});
|
||||
@ -80,7 +84,7 @@ deluge.ui = {
|
||||
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({
|
||||
deluge.client = Ext.create('Ext.ux.util.RpcClient', {
|
||||
url: deluge.config.base + 'json'
|
||||
});
|
||||
|
||||
@ -96,10 +100,12 @@ deluge.ui = {
|
||||
|
||||
deluge.client.on('connected', function(e) {
|
||||
deluge.login.show();
|
||||
Ext.get('loading').remove();
|
||||
Ext.get('loading-mask').fadeOut({remove:true});
|
||||
}, this, {single: true});
|
||||
|
||||
this.update = this.update.createDelegate(this);
|
||||
this.checkConnection = this.checkConnection.createDelegate(this);
|
||||
this.update = Ext.bind(this.update, this);
|
||||
this.checkConnection = Ext.bind(this.checkConnection, this);
|
||||
|
||||
this.originalTitle = document.title;
|
||||
},
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
/*!
|
||||
* Deluge.add.AddWindow.js
|
||||
*
|
||||
* Copyright (c) Damien Churchill 2009-2010 <damoxc@gmail.com>
|
||||
*
|
||||
* Copyright (c) Damien Churchill 2009-2011 <damoxc@gmail.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@ -30,9 +30,8 @@
|
||||
* statement from all source files in the program, then also delete it here.
|
||||
*/
|
||||
|
||||
Ext.namespace('Deluge.add');
|
||||
|
||||
Deluge.add.AddWindow = Ext.extend(Deluge.add.Window, {
|
||||
Ext.define('Deluge.add.AddWindow', {
|
||||
extend: 'Deluge.add.Window',
|
||||
|
||||
title: _('Add Torrents'),
|
||||
layout: 'border',
|
||||
@ -46,52 +45,68 @@ Deluge.add.AddWindow = Ext.extend(Deluge.add.Window, {
|
||||
iconCls: 'x-deluge-add-window-icon',
|
||||
|
||||
initComponent: function() {
|
||||
Deluge.add.AddWindow.superclass.initComponent.call(this);
|
||||
this.callParent(arguments);
|
||||
this.afterMethod('onHide', this.afterHidden, this);
|
||||
this.afterMethod('onShow', this.afterShown, this);
|
||||
|
||||
this.addDocked({
|
||||
xtype: 'toolbar',
|
||||
dock: 'bottom',
|
||||
defaultType: 'button',
|
||||
items: [
|
||||
'->',
|
||||
{text: _('Cancel'), handler: this.onCancelClick, scope: this},
|
||||
{text: _('Add'), handler: this.onAddClick, scope: this}
|
||||
]
|
||||
});
|
||||
|
||||
this.addButton(_('Cancel'), this.onCancelClick, this);
|
||||
this.addButton(_('Add'), this.onAddClick, this);
|
||||
|
||||
function torrentRenderer(value, p, r) {
|
||||
if (r.data['info_hash']) {
|
||||
return String.format('<div class="x-deluge-add-torrent-name">{0}</div>', value);
|
||||
return Ext.String.format('<div class="x-deluge-add-torrent-name">{0}</div>', value);
|
||||
} else {
|
||||
return String.format('<div class="x-deluge-add-torrent-name-loading">{0}</div>', value);
|
||||
return Ext.String.format('<div class="x-deluge-add-torrent-name-loading">{0}</div>', value);
|
||||
}
|
||||
}
|
||||
|
||||
this.list = new Ext.list.ListView({
|
||||
store: new Ext.data.SimpleStore({
|
||||
fields: [
|
||||
{name: 'info_hash', mapping: 1},
|
||||
{name: 'text', mapping: 2}
|
||||
],
|
||||
id: 0
|
||||
this.grid = this.add({
|
||||
xtype: 'grid',
|
||||
autoScroll: true,
|
||||
store: Ext.create('Ext.data.Store', {
|
||||
model: 'Deluge.data.AddTorrent'
|
||||
}),
|
||||
columns: [{
|
||||
id: 'torrent',
|
||||
width: 150,
|
||||
sortable: true,
|
||||
renderer: torrentRenderer,
|
||||
dataIndex: 'text'
|
||||
}],
|
||||
stripeRows: true,
|
||||
dataIndex: 'text',
|
||||
flex: 1
|
||||
}],
|
||||
hideHeaders: true,
|
||||
margins: '5 5 5 5',
|
||||
region: 'center',
|
||||
singleSelect: true,
|
||||
listeners: {
|
||||
'selectionchange': {
|
||||
fn: this.onSelect,
|
||||
scope: this
|
||||
},
|
||||
'render': {
|
||||
fn: function(list) {
|
||||
var el = list.getEl(),
|
||||
dh = Ext.core.DomHelper,
|
||||
dropEl = {
|
||||
tag: 'div',
|
||||
cls: 'x-deluge-dropzone',
|
||||
style: 'display: none',
|
||||
html: 'Drop torrent file here'
|
||||
};
|
||||
this.dropEl = Ext.get(dh.insertFirst(el, dropEl));
|
||||
},
|
||||
scope: this
|
||||
}
|
||||
},
|
||||
hideHeaders: true,
|
||||
autoExpandColumn: 'torrent',
|
||||
autoScroll: true
|
||||
});
|
||||
|
||||
this.add({
|
||||
region: 'center',
|
||||
items: [this.list],
|
||||
margins: '5 5 5 5',
|
||||
bbar: new Ext.Toolbar({
|
||||
bbar: {
|
||||
items: [{
|
||||
iconCls: 'x-deluge-add-file',
|
||||
text: _('File'),
|
||||
@ -112,23 +127,25 @@ Deluge.add.AddWindow = Ext.extend(Deluge.add.Window, {
|
||||
handler: this.onRemove,
|
||||
scope: this
|
||||
}]
|
||||
})
|
||||
}
|
||||
});
|
||||
|
||||
this.optionsPanel = this.add(new Deluge.add.OptionsPanel());
|
||||
this.on('hide', this.onHide, this);
|
||||
this.on('show', this.onShow, this);
|
||||
|
||||
this.optionsPanel = this.add(Ext.create('Deluge.add.OptionsPanel'));
|
||||
},
|
||||
|
||||
clear: function() {
|
||||
this.list.getStore().removeAll();
|
||||
this.grid.getStore().removeAll();
|
||||
this.optionsPanel.clear();
|
||||
},
|
||||
|
||||
processDnDFileUpload: function(file) {
|
||||
console.log(file.size);
|
||||
},
|
||||
|
||||
onAddClick: function() {
|
||||
var torrents = [];
|
||||
if (!this.list) return;
|
||||
this.list.getStore().each(function(r) {
|
||||
if (!this.grid) return;
|
||||
this.grid.getStore().each(function(r) {
|
||||
var id = r.get('info_hash');
|
||||
torrents.push({
|
||||
path: this.optionsPanel.getFilename(id),
|
||||
@ -150,28 +167,22 @@ Deluge.add.AddWindow = Ext.extend(Deluge.add.Window, {
|
||||
},
|
||||
|
||||
onFile: function() {
|
||||
if (!this.file) this.file = new Deluge.add.FileWindow();
|
||||
if (!this.file) this.file = Ext.create('Deluge.add.FileWindow');
|
||||
this.file.show();
|
||||
},
|
||||
|
||||
onHide: function() {
|
||||
this.optionsPanel.setActiveTab(0);
|
||||
this.optionsPanel.files.setDisabled(true);
|
||||
this.optionsPanel.form.setDisabled(true);
|
||||
},
|
||||
|
||||
onRemove: function() {
|
||||
if (!this.list.getSelectionCount()) return;
|
||||
var torrent = this.list.getSelectedRecords()[0];
|
||||
this.list.getStore().remove(torrent);
|
||||
var torrent = this.grid.getSelectedRecords()[0];
|
||||
this.grid.getStore().remove(torrent);
|
||||
this.optionsPanel.clear();
|
||||
|
||||
|
||||
if (this.torrents && this.torrents[torrent.id]) delete this.torrents[torrent.id];
|
||||
},
|
||||
|
||||
onSelect: function(list, selections) {
|
||||
if (selections.length) {
|
||||
var record = this.list.getRecord(selections[0]);
|
||||
onSelect: function(grid, selections) {
|
||||
if (selections.length) {
|
||||
var record = selections[0];
|
||||
this.optionsPanel.setTorrent(record.get('info_hash'));
|
||||
this.optionsPanel.files.setDisabled(false);
|
||||
this.optionsPanel.form.setDisabled(false);
|
||||
@ -181,29 +192,95 @@ Deluge.add.AddWindow = Ext.extend(Deluge.add.Window, {
|
||||
}
|
||||
},
|
||||
|
||||
onShow: function() {
|
||||
afterHidden: function() {
|
||||
this.optionsPanel.setActiveTab(0);
|
||||
this.optionsPanel.files.setDisabled(true);
|
||||
this.optionsPanel.form.setDisabled(true);
|
||||
},
|
||||
|
||||
afterShown: function() {
|
||||
if (!this.url) {
|
||||
this.url = new Deluge.add.UrlWindow();
|
||||
this.url = Ext.create('Deluge.add.UrlWindow');
|
||||
this.url.on('beforeadd', this.onTorrentBeforeAdd, this);
|
||||
this.url.on('add', this.onTorrentAdd, this);
|
||||
}
|
||||
|
||||
if (!this.file) {
|
||||
this.file = new Deluge.add.FileWindow();
|
||||
this.file = Ext.create('Deluge.add.FileWindow');
|
||||
this.file.on('beforeadd', this.onTorrentBeforeAdd, this);
|
||||
this.file.on('add', this.onTorrentAdd, this);
|
||||
}
|
||||
|
||||
|
||||
this.optionsPanel.form.getDefaults();
|
||||
|
||||
var body = Ext.getBody(),
|
||||
dropEl = this.dropEl;
|
||||
|
||||
body.on({
|
||||
dragenter: function(evt) {
|
||||
dropEl.setStyle('display', 'block');
|
||||
return true;
|
||||
},
|
||||
dragleave: function(evt) {
|
||||
var viewSize = body.getViewSize(),
|
||||
pageX = evt.getPageX(),
|
||||
pageY = evt.getPageY();
|
||||
if (pageX < 10 || pageY < 10 || viewSize.width - pageX < 10 || viewSize.height - pageY < 10) {
|
||||
dropEl.setStyle('display', 'none');
|
||||
}
|
||||
return true;
|
||||
},
|
||||
dragover: function(evt) {
|
||||
evt.stopEvent();
|
||||
return true;
|
||||
},
|
||||
drop: function(evt) {
|
||||
evt.stopEvent();
|
||||
return true;
|
||||
}
|
||||
});
|
||||
|
||||
this.dropEl.on({
|
||||
dragenter: function(evt) {
|
||||
evt.browserEvent.dataTransfer.dropEffect = 'move';
|
||||
return true;
|
||||
},
|
||||
dragover: function(evt) {
|
||||
evt.browserEvent.dataTransfer.dropEffect = 'move';
|
||||
evt.stopEvent();
|
||||
return true;
|
||||
},
|
||||
drop: {
|
||||
fn: function(evt) {
|
||||
evt.stopEvent();
|
||||
var files = evt.browserEvent.dataTransfer.files;
|
||||
|
||||
if (files === undefined) {
|
||||
return true;
|
||||
}
|
||||
var len = files.length;
|
||||
while (--len >= 0) {
|
||||
this.processDnDFileUpload(files[len]);
|
||||
}
|
||||
this.dropEl.setStyle('display', 'none');
|
||||
},
|
||||
scope: this
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
onTorrentBeforeAdd: function(torrentId, text) {
|
||||
var store = this.list.getStore();
|
||||
store.loadData([[torrentId, null, text]], true);
|
||||
var rec = Ext.create('Deluge.data.AddTorrent', {
|
||||
'id': torrentId,
|
||||
'info_hash': null,
|
||||
'text': text
|
||||
|
||||
}, torrentId);
|
||||
this.grid.getStore().add(rec);
|
||||
},
|
||||
|
||||
onTorrentAdd: function(torrentId, info) {
|
||||
var r = this.list.getStore().getById(torrentId);
|
||||
var r = this.grid.getStore().getById(String(torrentId));
|
||||
if (!info) {
|
||||
Ext.MessageBox.show({
|
||||
title: _('Error'),
|
||||
@ -213,11 +290,11 @@ Deluge.add.AddWindow = Ext.extend(Deluge.add.Window, {
|
||||
icon: Ext.MessageBox.ERROR,
|
||||
iconCls: 'x-deluge-icon-error'
|
||||
});
|
||||
this.list.getStore().remove(r);
|
||||
this.grid.getStore().remove(r);
|
||||
} else {
|
||||
r.set('info_hash', info['info_hash']);
|
||||
r.set('text', info['name']);
|
||||
this.list.getStore().commitChanges();
|
||||
r.commit();;
|
||||
this.optionsPanel.addTorrent(info);
|
||||
}
|
||||
},
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
/*!
|
||||
* Deluge.add.File.js
|
||||
*
|
||||
* Copyright (c) Damien Churchill 2009-2010 <damoxc@gmail.com>
|
||||
*
|
||||
* Copyright (c) Damien Churchill 2009-2011 <damoxc@gmail.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@ -29,13 +29,13 @@
|
||||
* this exception statement from your version. If you delete this exception
|
||||
* statement from all source files in the program, then also delete it here.
|
||||
*/
|
||||
Ext.ns('Deluge.add');
|
||||
|
||||
/**
|
||||
* @class Deluge.add.FileWindow
|
||||
* @extends Deluge.add.Window
|
||||
*/
|
||||
Deluge.add.FileWindow = Ext.extend(Deluge.add.Window, {
|
||||
Ext.define('Deluge.add.FileWindow', {
|
||||
extend: 'Deluge.add.Window',
|
||||
|
||||
title: _('Add from File'),
|
||||
layout: 'fit',
|
||||
@ -49,29 +49,36 @@ Deluge.add.FileWindow = Ext.extend(Deluge.add.Window, {
|
||||
iconCls: 'x-deluge-add-file',
|
||||
|
||||
initComponent: function() {
|
||||
Deluge.add.FileWindow.superclass.initComponent.call(this);
|
||||
this.addButton(_('Add'), this.onAddClick, this);
|
||||
|
||||
this.callParent(arguments);
|
||||
this.addDocked({
|
||||
xtype: 'toolbar',
|
||||
dock: 'bottom',
|
||||
defaultType: 'button',
|
||||
items: [
|
||||
'->',
|
||||
{text: _('Add'), handler: this.onAddClick, scope: this}
|
||||
]
|
||||
});
|
||||
|
||||
this.form = this.add({
|
||||
xtype: 'form',
|
||||
width: 300,
|
||||
baseCls: 'x-plain',
|
||||
labelWidth: 35,
|
||||
autoHeight: true,
|
||||
fileUpload: true,
|
||||
|
||||
items: [{
|
||||
xtype: 'fileuploadfield',
|
||||
xtype: 'filefield',
|
||||
id: 'torrentFile',
|
||||
width: 280,
|
||||
anchor: '100%',
|
||||
emptyText: _('Select a torrent'),
|
||||
labelWidth: 35,
|
||||
fieldLabel: _('File'),
|
||||
name: 'file',
|
||||
buttonCfg: {
|
||||
text: _('Browse') + '...'
|
||||
}
|
||||
buttonText: _('Browse') + '...'
|
||||
}]
|
||||
});
|
||||
},
|
||||
|
||||
|
||||
// private
|
||||
onAddClick: function(field, e) {
|
||||
if (this.form.getForm().isValid()) {
|
||||
@ -88,7 +95,7 @@ Deluge.add.FileWindow = Ext.extend(Deluge.add.Window, {
|
||||
this.fireEvent('beforeadd', this.torrentId, name);
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
// private
|
||||
onGotInfo: function(info, obj, response, request) {
|
||||
info['filename'] = request.options.filename;
|
||||
@ -99,7 +106,7 @@ Deluge.add.FileWindow = Ext.extend(Deluge.add.Window, {
|
||||
onUploadFailure: function(form, action) {
|
||||
this.hide();
|
||||
},
|
||||
|
||||
|
||||
// private
|
||||
onUploadSuccess: function(fp, upload) {
|
||||
this.hide();
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
/*!
|
||||
* Deluge.add.FilesTab.js
|
||||
*
|
||||
* Copyright (c) Damien Churchill 2009-2010 <damoxc@gmail.com>
|
||||
*
|
||||
* Copyright (c) Damien Churchill 2009-2011 <damoxc@gmail.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@ -29,13 +29,13 @@
|
||||
* this exception statement from your version. If you delete this exception
|
||||
* statement from all source files in the program, then also delete it here.
|
||||
*/
|
||||
Ext.ns('Deluge.add');
|
||||
|
||||
/**
|
||||
* @class Deluge.add.FilesTab
|
||||
* @extends Ext.ux.tree.TreeGrid
|
||||
*/
|
||||
Deluge.add.FilesTab = Ext.extend(Ext.ux.tree.TreeGrid, {
|
||||
Ext.define('Deluge.add.FilesTab', {
|
||||
extend: 'Ext.tree.Panel',
|
||||
|
||||
layout: 'fit',
|
||||
title: _('Files'),
|
||||
@ -47,41 +47,46 @@ Deluge.add.FilesTab = Ext.extend(Ext.ux.tree.TreeGrid, {
|
||||
rootVisible: false,
|
||||
|
||||
columns: [{
|
||||
xtype: 'treecolumn',
|
||||
header: _('Filename'),
|
||||
width: 295,
|
||||
dataIndex: 'filename'
|
||||
},{
|
||||
xtype: 'templatecolumn',
|
||||
header: _('Size'),
|
||||
width: 60,
|
||||
dataIndex: 'size',
|
||||
tpl: new Ext.XTemplate('{size:this.fsize}', {
|
||||
tpl: Ext.create('Ext.XTemplate', '{size:this.fsize}', {
|
||||
fsize: function(v) {
|
||||
return fsize(v);
|
||||
}
|
||||
})
|
||||
},{
|
||||
xtype: 'templatecolumn',
|
||||
header: _('Download'),
|
||||
width: 65,
|
||||
dataIndex: 'download',
|
||||
tpl: new Ext.XTemplate('{download:this.format}', {
|
||||
tpl: Ext.create('Ext.XTemplate', '{download:this.format}', {
|
||||
format: function(v) {
|
||||
return '<div rel="chkbox" class="x-grid3-check-col'+(v?'-on':'')+'"> </div>';
|
||||
}
|
||||
})
|
||||
}],
|
||||
|
||||
store: Ext.create('Ext.data.TreeStore', {
|
||||
model: 'Deluge.data.AddTorrentFile',
|
||||
proxy: {
|
||||
type: 'memory'
|
||||
}
|
||||
}),
|
||||
|
||||
initComponent: function() {
|
||||
Deluge.add.FilesTab.superclass.initComponent.call(this);
|
||||
this.callParent(arguments);
|
||||
this.on('click', this.onNodeClick, this);
|
||||
},
|
||||
|
||||
clearFiles: function() {
|
||||
var root = this.getRootNode();
|
||||
if (!root.hasChildNodes()) return;
|
||||
root.cascade(function(node) {
|
||||
if (!node.parentNode || !node.getOwnerTree()) return;
|
||||
node.remove();
|
||||
});
|
||||
this.getStore().removeAll();
|
||||
},
|
||||
|
||||
setDownload: function(node, value, suppress) {
|
||||
@ -106,7 +111,7 @@ Deluge.add.FilesTab = Ext.extend(Ext.ux.tree.TreeGrid, {
|
||||
},
|
||||
|
||||
onNodeClick: function(node, e) {
|
||||
var el = new Ext.Element(e.target);
|
||||
var el = Ext.fly(e.target);
|
||||
if (el.getAttribute('rel') == 'chkbox') {
|
||||
this.setDownload(node, !node.attributes.download);
|
||||
}
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
/*!
|
||||
* Deluge.add.Infohash.js
|
||||
*
|
||||
* Copyright (c) Damien Churchill 2009-2010 <damoxc@gmail.com>
|
||||
*
|
||||
* Copyright (c) Damien Churchill 2009-2011 <damoxc@gmail.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@ -29,4 +29,3 @@
|
||||
* this exception statement from your version. If you delete this exception
|
||||
* statement from all source files in the program, then also delete it here.
|
||||
*/
|
||||
Ext.namespace('Ext.deluge.add');
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
/*!
|
||||
* Deluge.add.OptionsPanel.js
|
||||
*
|
||||
* Copyright (c) Damien Churchill 2009-2010 <damoxc@gmail.com>
|
||||
*
|
||||
* Copyright (c) Damien Churchill 2009-2011 <damoxc@gmail.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@ -29,9 +29,9 @@
|
||||
* this exception statement from your version. If you delete this exception
|
||||
* statement from all source files in the program, then also delete it here.
|
||||
*/
|
||||
Ext.ns('Deluge.add');
|
||||
|
||||
Deluge.add.OptionsPanel = Ext.extend(Ext.TabPanel, {
|
||||
Ext.define('Deluge.add.OptionsPanel', {
|
||||
extend: 'Ext.TabPanel',
|
||||
|
||||
torrents: {},
|
||||
|
||||
@ -42,9 +42,9 @@ Deluge.add.OptionsPanel = Ext.extend(Ext.TabPanel, {
|
||||
height: 220,
|
||||
|
||||
initComponent: function() {
|
||||
Deluge.add.OptionsPanel.superclass.initComponent.call(this);
|
||||
this.files = this.add(new Deluge.add.FilesTab());
|
||||
this.form = this.add(new Deluge.add.OptionsTab());
|
||||
this.callParent(arguments);
|
||||
this.files = this.add(Ext.create('Deluge.add.FilesTab'));
|
||||
this.form = this.add(Ext.create('Deluge.add.OptionsTab'));
|
||||
|
||||
this.files.on('fileschecked', this.onFilesChecked, this);
|
||||
},
|
||||
@ -61,7 +61,7 @@ Deluge.add.OptionsPanel = Ext.extend(Ext.TabPanel, {
|
||||
Ext.each(Ext.keys(fileIndexes), function(index) {
|
||||
priorities[index] = fileIndexes[index];
|
||||
});
|
||||
|
||||
|
||||
var oldId = this.form.optionsManager.changeId(torrent['info_hash'], true);
|
||||
this.form.optionsManager.setDefault('file_priorities', priorities);
|
||||
this.form.optionsManager.changeId(oldId, true);
|
||||
@ -91,7 +91,7 @@ Deluge.add.OptionsPanel = Ext.extend(Ext.TabPanel, {
|
||||
|
||||
this.torrentId = torrentId;
|
||||
this.form.optionsManager.changeId(torrentId);
|
||||
|
||||
|
||||
this.files.clearFiles();
|
||||
var root = this.files.getRootNode();
|
||||
var priorities = this.form.optionsManager.get('file_priorities');
|
||||
@ -120,7 +120,7 @@ Deluge.add.OptionsPanel = Ext.extend(Ext.TabPanel, {
|
||||
} else {
|
||||
var ret = callback(filename, type, entry, parentNode);
|
||||
}
|
||||
|
||||
|
||||
if (type == 'dir') this.walkFileTree(entry, callback, scope, ret);
|
||||
}
|
||||
},
|
||||
@ -142,7 +142,7 @@ Deluge.add.OptionsPanel = Ext.extend(Ext.TabPanel, {
|
||||
}, this);
|
||||
} else {
|
||||
this.files.setDownload(nodes[0], oldValue, true);
|
||||
}
|
||||
}
|
||||
},
|
||||
scope: this,
|
||||
icon: Ext.MessageBox.QUESTION
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
/*!
|
||||
* Deluge.add.OptionsPanel.js
|
||||
*
|
||||
* Copyright (c) Damien Churchill 2009-2010 <damoxc@gmail.com>
|
||||
*
|
||||
* Copyright (c) Damien Churchill 2009-2011 <damoxc@gmail.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@ -29,13 +29,13 @@
|
||||
* this exception statement from your version. If you delete this exception
|
||||
* statement from all source files in the program, then also delete it here.
|
||||
*/
|
||||
Ext.ns('Deluge.add');
|
||||
|
||||
/**
|
||||
* @class Deluge.add.OptionsTab
|
||||
* @extends Ext.form.FormPanel
|
||||
*/
|
||||
Deluge.add.OptionsTab = Ext.extend(Ext.form.FormPanel, {
|
||||
Ext.define('Deluge.add.OptionsTab', {
|
||||
extend: 'Ext.form.Panel',
|
||||
|
||||
title: _('Options'),
|
||||
height: 170,
|
||||
@ -46,7 +46,7 @@ Deluge.add.OptionsTab = Ext.extend(Ext.form.FormPanel, {
|
||||
labelWidth: 1,
|
||||
|
||||
initComponent: function() {
|
||||
Deluge.add.OptionsTab.superclass.initComponent.call(this);
|
||||
this.callParent(arguments);
|
||||
|
||||
this.optionsManager = new Deluge.MultiOptionsManager();
|
||||
|
||||
@ -67,7 +67,7 @@ Deluge.add.OptionsTab = Ext.extend(Ext.form.FormPanel, {
|
||||
width: 400,
|
||||
labelSeparator: ''
|
||||
}));
|
||||
|
||||
|
||||
var panel = this.add({
|
||||
border: false,
|
||||
layout: 'column',
|
||||
@ -135,7 +135,7 @@ Deluge.add.OptionsTab = Ext.extend(Ext.form.FormPanel, {
|
||||
name: 'max_upload_slots',
|
||||
width: 60
|
||||
}));
|
||||
|
||||
|
||||
fieldset = panel.add({
|
||||
title: _('General'),
|
||||
border: false,
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
/*!
|
||||
* Deluge.add.UrlWindow.js
|
||||
*
|
||||
* Copyright (c) Damien Churchill 2009-2010 <damoxc@gmail.com>
|
||||
* Copyright (c) Damien Churchill 2009-2011 <damoxc@gmail.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@ -30,15 +30,15 @@
|
||||
* statement from all source files in the program, then also delete it here.
|
||||
*/
|
||||
|
||||
Ext.namespace('Deluge.add');
|
||||
Deluge.add.UrlWindow = Ext.extend(Deluge.add.Window, {
|
||||
Ext.define('Deluge.add.UrlWindow', {
|
||||
extend: 'Deluge.add.Window',
|
||||
|
||||
title: _('Add from Url'),
|
||||
modal: true,
|
||||
plain: true,
|
||||
layout: 'fit',
|
||||
width: 350,
|
||||
height: 155,
|
||||
height: 130,
|
||||
|
||||
buttonAlign: 'center',
|
||||
closeAction: 'hide',
|
||||
@ -46,29 +46,39 @@ Deluge.add.UrlWindow = Ext.extend(Deluge.add.Window, {
|
||||
iconCls: 'x-deluge-add-url-window-icon',
|
||||
|
||||
initComponent: function() {
|
||||
Deluge.add.UrlWindow.superclass.initComponent.call(this);
|
||||
this.addButton(_('Add'), this.onAddClick, this);
|
||||
this.callParent(arguments);
|
||||
|
||||
this.addDocked({
|
||||
xtype: 'toolbar',
|
||||
dock: 'bottom',
|
||||
defaultType: 'button',
|
||||
items: [
|
||||
'->',
|
||||
{text: _('Add'), handler: this.onAddClick, scope: this}
|
||||
]
|
||||
});
|
||||
|
||||
var form = this.add({
|
||||
xtype: 'form',
|
||||
defaultType: 'textfield',
|
||||
baseCls: 'x-plain',
|
||||
labelWidth: 55
|
||||
defaults: {
|
||||
labelWidth: 55,
|
||||
anchor: '100%'
|
||||
}
|
||||
});
|
||||
|
||||
this.urlField = form.add({
|
||||
fieldLabel: _('Url'),
|
||||
id: 'url',
|
||||
name: 'url',
|
||||
width: '97%'
|
||||
name: 'url'
|
||||
});
|
||||
this.urlField.on('specialkey', this.onAdd, this);
|
||||
|
||||
this.cookieField = form.add({
|
||||
fieldLabel: _('Cookies'),
|
||||
id: 'cookies',
|
||||
name: 'cookies',
|
||||
width: '97%'
|
||||
name: 'cookies'
|
||||
});
|
||||
this.cookieField.on('specialkey', this.onAdd, this);
|
||||
},
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
/*!
|
||||
* Deluge.add.Window.js
|
||||
*
|
||||
* Copyright (c) Damien Churchill 2009-2010 <damoxc@gmail.com>
|
||||
*
|
||||
* Copyright (c) Damien Churchill 2009-2011 <damoxc@gmail.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@ -29,16 +29,17 @@
|
||||
* this exception statement from your version. If you delete this exception
|
||||
* statement from all source files in the program, then also delete it here.
|
||||
*/
|
||||
Ext.ns('Deluge.add');
|
||||
|
||||
/**
|
||||
* @class Deluge.add.Window
|
||||
* @extends Ext.Window
|
||||
* Base class for an add Window
|
||||
*/
|
||||
Deluge.add.Window = Ext.extend(Ext.Window, {
|
||||
Ext.define('Deluge.add.Window', {
|
||||
extend: 'Ext.Window',
|
||||
|
||||
initComponent: function() {
|
||||
Deluge.add.Window.superclass.initComponent.call(this);
|
||||
this.callParent(arguments);
|
||||
this.addEvents(
|
||||
'beforeadd',
|
||||
'add'
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
/*!
|
||||
* Ext.ux.tree.TreeGridNodeUIFix.js
|
||||
*
|
||||
* Copyright (c) Damien Churchill 2009-2010 <damoxc@gmail.com>
|
||||
* Deluge.data.AddTorrent.js
|
||||
*
|
||||
* Copyright (c) Damien Churchill 2011 <damoxc@gmail.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@ -30,24 +30,11 @@
|
||||
* statement from all source files in the program, then also delete it here.
|
||||
*/
|
||||
|
||||
Ext.override(Ext.ux.tree.TreeGridNodeUI, {
|
||||
|
||||
updateColumns: function() {
|
||||
if (!this.rendered) return;
|
||||
|
||||
var a = this.node.attributes,
|
||||
t = this.node.getOwnerTree(),
|
||||
cols = t.columns,
|
||||
c = cols[0];
|
||||
|
||||
// Update the first column
|
||||
this.anchor.firstChild.innerHTML = (c.tpl ? c.tpl.apply(a) : a[c.dataIndex] || c.text);
|
||||
|
||||
// Update the remaining columns
|
||||
for(i = 1, len = cols.length; i < len; i++) {
|
||||
c = cols[i];
|
||||
this.elNode.childNodes[i].firstChild.innerHTML = (c.tpl ? c.tpl.apply(a) : a[c.dataIndex] || c.text);
|
||||
}
|
||||
}
|
||||
|
||||
Ext.define('Deluge.data.AddTorrent', {
|
||||
extend: 'Ext.data.Model',
|
||||
fields: [
|
||||
{name: 'id', type: 'string'},
|
||||
{name: 'info_hash', type: 'string'},
|
||||
{name: 'text', type: 'string'}
|
||||
]
|
||||
});
|
||||
@ -1,7 +1,7 @@
|
||||
/*!
|
||||
* Ext.ux.form.RadioGroup.js
|
||||
*
|
||||
* Copyright (c) Damien Churchill 2009-2010 <damoxc@gmail.com>
|
||||
* Deluge.data.AddTorrentFile.js
|
||||
*
|
||||
* Copyright (c) Damien Churchill 2011 <damoxc@gmail.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@ -30,42 +30,11 @@
|
||||
* statement from all source files in the program, then also delete it here.
|
||||
*/
|
||||
|
||||
// Allow radiogroups to be treated as a single form element.
|
||||
Ext.override(Ext.form.RadioGroup, {
|
||||
|
||||
afterRender: function() {
|
||||
this.items.each(function(i) {
|
||||
this.relayEvents(i, ['check']);
|
||||
}, this);
|
||||
if (this.lazyValue) {
|
||||
this.setValue(this.value);
|
||||
delete this.value;
|
||||
delete this.lazyValue;
|
||||
}
|
||||
Ext.form.RadioGroup.superclass.afterRender.call(this)
|
||||
},
|
||||
|
||||
getName: function() {
|
||||
return this.items.first().getName();
|
||||
},
|
||||
|
||||
getValue: function() {
|
||||
return this.items.first().getGroupValue();
|
||||
},
|
||||
|
||||
setValue: function(v) {
|
||||
if (!this.items.each) {
|
||||
this.value = v;
|
||||
this.lazyValue = true;
|
||||
return;
|
||||
}
|
||||
this.items.each(function(item) {
|
||||
if (item.rendered) {
|
||||
var checked = (item.el.getValue() == String(v));
|
||||
item.el.dom.checked = checked;
|
||||
item.el.dom.defaultChecked = checked;
|
||||
item.wrap[checked ? 'addClass' : 'removeClass'](item.checkedCls);
|
||||
}
|
||||
});
|
||||
}
|
||||
Ext.define('Deluge.data.AddTorrentFile', {
|
||||
extend: 'Ext.data.Model',
|
||||
fields: [
|
||||
{name: 'filename', type: 'string'},
|
||||
{name: 'size', type: 'number'},
|
||||
{name: 'download', type: 'boolean'}
|
||||
]
|
||||
});
|
||||
50
deluge/ui/web/js/deluge-all/data/FilterRecord.js
Normal file
50
deluge/ui/web/js/deluge-all/data/FilterRecord.js
Normal file
@ -0,0 +1,50 @@
|
||||
/*!
|
||||
* Deluge.data.FilterRecord.js
|
||||
*
|
||||
* Copyright (c) Damien Churchill 2011 <damoxc@gmail.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, write to:
|
||||
* The Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor
|
||||
* Boston, MA 02110-1301, USA.
|
||||
*
|
||||
* In addition, as a special exception, the copyright holders give
|
||||
* permission to link the code of portions of this program with the OpenSSL
|
||||
* library.
|
||||
* You must obey the GNU General Public License in all respects for all of
|
||||
* the code used other than OpenSSL. If you modify file(s) with this
|
||||
* exception, you may extend this exception to your version of the file(s),
|
||||
* but you are not obligated to do so. If you do not wish to do so, delete
|
||||
* this exception statement from your version. If you delete this exception
|
||||
* statement from all source files in the program, then also delete it here.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Deluge.data.Filter record
|
||||
*
|
||||
* @author Damien Churchill <damoxc@gmail.com>
|
||||
* @version 1.4
|
||||
*
|
||||
* @class Deluge.data.Filter
|
||||
* @extends Ext.data.Model
|
||||
* @constructor
|
||||
* @param {Object} data The Filter data
|
||||
*/
|
||||
Ext.define('Deluge.data.Filter', {
|
||||
extend: 'Ext.data.Model',
|
||||
fields: [
|
||||
{name: 'filter', type: 'string'},
|
||||
{name: 'count', type: 'number'}
|
||||
]
|
||||
});
|
||||
53
deluge/ui/web/js/deluge-all/data/HostRecord.js
Normal file
53
deluge/ui/web/js/deluge-all/data/HostRecord.js
Normal file
@ -0,0 +1,53 @@
|
||||
/*!
|
||||
* Deluge.data.Host.js
|
||||
*
|
||||
* Copyright (c) Damien Churchill 2011 <damoxc@gmail.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, write to:
|
||||
* The Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor
|
||||
* Boston, MA 02110-1301, USA.
|
||||
*
|
||||
* In addition, as a special exception, the copyright holders give
|
||||
* permission to link the code of portions of this program with the OpenSSL
|
||||
* library.
|
||||
* You must obey the GNU General Public License in all respects for all of
|
||||
* the code used other than OpenSSL. If you modify file(s) with this
|
||||
* exception, you may extend this exception to your version of the file(s),
|
||||
* but you are not obligated to do so. If you do not wish to do so, delete
|
||||
* this exception statement from your version. If you delete this exception
|
||||
* statement from all source files in the program, then also delete it here.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Deluge.data.Host
|
||||
*
|
||||
* @author Damien Churchill <damoxc@gmail.com>
|
||||
* @version 1.4
|
||||
*
|
||||
* @class Deluge.data.Host
|
||||
* @extends Ext.data.Model
|
||||
* @constructor
|
||||
* @param {Object} data The peer data
|
||||
*/
|
||||
Ext.define('Deluge.data.Host', {
|
||||
extend: 'Ext.data.Model',
|
||||
fields: [
|
||||
{name: 'id', type: 'string'},
|
||||
{name: 'host', type: 'string'},
|
||||
{name: 'port', type: 'int'},
|
||||
{name: 'status', type: 'string'},
|
||||
{name: 'version', type: 'string'}
|
||||
]
|
||||
});
|
||||
@ -1,7 +1,7 @@
|
||||
/*!
|
||||
* Deluge.data.PeerRecord.js
|
||||
*
|
||||
* Copyright (c) Damien Churchill 2009-2010 <damoxc@gmail.com>
|
||||
* Deluge.data.Peer.js
|
||||
*
|
||||
* Copyright (c) Damien Churchill 2009-2011 <damoxc@gmail.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@ -29,7 +29,6 @@
|
||||
* this exception statement from your version. If you delete this exception
|
||||
* statement from all source files in the program, then also delete it here.
|
||||
*/
|
||||
Ext.namespace('Deluge.data');
|
||||
|
||||
/**
|
||||
* Deluge.data.Peer record
|
||||
@ -38,32 +37,19 @@ Ext.namespace('Deluge.data');
|
||||
* @version 1.3
|
||||
*
|
||||
* @class Deluge.data.Peer
|
||||
* @extends Ext.data.Record
|
||||
* @extends Ext.data.Model
|
||||
* @constructor
|
||||
* @param {Object} data The peer data
|
||||
*/
|
||||
Deluge.data.Peer = Ext.data.Record.create([
|
||||
{
|
||||
name: 'country',
|
||||
type: 'string'
|
||||
}, {
|
||||
name: 'ip',
|
||||
type: 'string',
|
||||
sortType: Deluge.data.SortTypes.asIPAddress
|
||||
}, {
|
||||
name: 'client',
|
||||
type: 'string'
|
||||
}, {
|
||||
name: 'progress',
|
||||
type: 'float'
|
||||
}, {
|
||||
name: 'down_speed',
|
||||
type: 'int'
|
||||
}, {
|
||||
name: 'up_speed',
|
||||
type: 'int'
|
||||
}, {
|
||||
name: 'seed',
|
||||
type: 'int'
|
||||
}
|
||||
]);
|
||||
Ext.define('Deluge.data.Peer', {
|
||||
extend: 'Ext.data.Model',
|
||||
fields: [
|
||||
{name: 'country', type: 'string'},
|
||||
{name: 'ip', type: 'string', sortType: Deluge.data.SortTypes.asIPAddress},
|
||||
{name: 'client', type: 'string'},
|
||||
{name: 'progress', type: 'float'},
|
||||
{name: 'down_speed', type: 'int'},
|
||||
{name: 'up_speed', type: 'int'},
|
||||
{name: 'seed', type: 'int'}
|
||||
]
|
||||
});
|
||||
|
||||
50
deluge/ui/web/js/deluge-all/data/Plugin.js
Normal file
50
deluge/ui/web/js/deluge-all/data/Plugin.js
Normal file
@ -0,0 +1,50 @@
|
||||
/*!
|
||||
* Deluge.data.Plugin.js
|
||||
*
|
||||
* Copyright (c) Damien Churchill 2011 <damoxc@gmail.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, write to:
|
||||
* The Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor
|
||||
* Boston, MA 02110-1301, USA.
|
||||
*
|
||||
* In addition, as a special exception, the copyright holders give
|
||||
* permission to link the code of portions of this program with the OpenSSL
|
||||
* library.
|
||||
* You must obey the GNU General Public License in all respects for all of
|
||||
* the code used other than OpenSSL. If you modify file(s) with this
|
||||
* exception, you may extend this exception to your version of the file(s),
|
||||
* but you are not obligated to do so. If you do not wish to do so, delete
|
||||
* this exception statement from your version. If you delete this exception
|
||||
* statement from all source files in the program, then also delete it here.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Deluge.data.Plugin record
|
||||
*
|
||||
* @author Damien Churchill <damoxc@gmail.com>
|
||||
* @version 1.4
|
||||
*
|
||||
* @class Deluge.data.Plugin
|
||||
* @extends Ext.data.Model
|
||||
* @constructor
|
||||
* @param {Object} data The plugin data
|
||||
*/
|
||||
Ext.define('Deluge.data.Plugin', {
|
||||
extend: 'Ext.data.Model',
|
||||
fields: [
|
||||
{name: 'enabled', type: 'boolean'},
|
||||
{name: 'plugin', type: 'string'}
|
||||
]
|
||||
});
|
||||
@ -1,7 +1,7 @@
|
||||
/*!
|
||||
* Ext.ux.form.SpinnerField.js
|
||||
*
|
||||
* Copyright (c) Damien Churchill 2010 <damoxc@gmail.com>
|
||||
* Deluge.data.Preference.js
|
||||
*
|
||||
* Copyright (c) Damien Churchill 2011 <damoxc@gmail.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@ -30,6 +30,9 @@
|
||||
* statement from all source files in the program, then also delete it here.
|
||||
*/
|
||||
|
||||
Ext.override(Ext.ux.form.SpinnerField, {
|
||||
onBlur: Ext.form.Field.prototype.onBlur
|
||||
Ext.define('Deluge.data.Preferences', {
|
||||
extend: 'Ext.data.Model',
|
||||
fields: [
|
||||
{name: 'name', type: 'string'}
|
||||
]
|
||||
});
|
||||
@ -1,7 +1,7 @@
|
||||
/*!
|
||||
* Deluge.data.SortTypes.js
|
||||
*
|
||||
* Copyright (c) Damien Churchill 2009-2010 <damoxc@gmail.com>
|
||||
*
|
||||
* Copyright (c) Damien Churchill 2009-2011 <damoxc@gmail.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@ -39,7 +39,7 @@ Ext.namespace('Deluge.data');
|
||||
*
|
||||
* @class Deluge.data.SortTypes
|
||||
* @singleton
|
||||
*/
|
||||
*/
|
||||
Deluge.data.SortTypes = {
|
||||
asIPAddress: function(value) {
|
||||
var d = value.match(/(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})\:(\d+)/);
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
/*!
|
||||
* Deluge.data.TorrentRecord.js
|
||||
*
|
||||
* Copyright (c) Damien Churchill 2009-2010 <damoxc@gmail.com>
|
||||
*
|
||||
* Copyright (c) Damien Churchill 2009-2011 <damoxc@gmail.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@ -29,7 +29,6 @@
|
||||
* this exception statement from your version. If you delete this exception
|
||||
* statement from all source files in the program, then also delete it here.
|
||||
*/
|
||||
Ext.namespace('Deluge.data');
|
||||
|
||||
/**
|
||||
* Deluge.data.Torrent record
|
||||
@ -38,57 +37,28 @@ Ext.namespace('Deluge.data');
|
||||
* @version 1.3
|
||||
*
|
||||
* @class Deluge.data.Torrent
|
||||
* @extends Ext.data.Record
|
||||
* @extends Ext.data.Model
|
||||
* @constructor
|
||||
* @param {Object} data The torrents data
|
||||
*/
|
||||
Deluge.data.Torrent = Ext.data.Record.create([{
|
||||
name: 'queue',
|
||||
type: 'int'
|
||||
}, {
|
||||
name: 'name',
|
||||
type: 'string'
|
||||
}, {
|
||||
name: 'total_size',
|
||||
type: 'int'
|
||||
}, {
|
||||
name: 'state',
|
||||
type: 'string'
|
||||
}, {
|
||||
name: 'progress',
|
||||
type: 'int'
|
||||
}, {
|
||||
name: 'num_seeds',
|
||||
type: 'int'
|
||||
}, {
|
||||
name: 'total_seeds',
|
||||
type: 'int'
|
||||
}, {
|
||||
name: 'num_peers',
|
||||
type: 'int'
|
||||
}, {
|
||||
name: 'total_peers',
|
||||
type: 'int'
|
||||
}, {
|
||||
name: 'download_payload_rate',
|
||||
type: 'int'
|
||||
}, {
|
||||
name: 'upload_payload_rate',
|
||||
type: 'int'
|
||||
}, {
|
||||
name: 'eta',
|
||||
type: 'int'
|
||||
}, {
|
||||
name: 'ratio',
|
||||
type: 'float'
|
||||
}, {
|
||||
name: 'distributed_copies',
|
||||
type: 'float'
|
||||
}, {
|
||||
name: 'time_added',
|
||||
type: 'int'
|
||||
}, {
|
||||
name: 'tracker_host',
|
||||
type: 'string'
|
||||
}
|
||||
]);
|
||||
Ext.define('Deluge.data.Torrent', {
|
||||
extend: 'Ext.data.Model',
|
||||
fields: [
|
||||
{name: 'queue', type: 'int', sortType: Deluge.data.SortTypes.asQueuePosition},
|
||||
{name: 'name', type: 'string'},
|
||||
{name: 'total_size', type: 'int'},
|
||||
{name: 'state', type: 'string'},
|
||||
{name: 'progress', type: 'float'},
|
||||
{name: 'num_seeds', type: 'int'},
|
||||
{name: 'total_seeds', type: 'int'},
|
||||
{name: 'num_peers', type: 'int'},
|
||||
{name: 'total_peers', type: 'int'},
|
||||
{name: 'download_payload_rate', type: 'int'},
|
||||
{name: 'upload_payload_rate', type: 'int'},
|
||||
{name: 'eta', type: 'int'},
|
||||
{name: 'ratio', type: 'float'},
|
||||
{name: 'distributed_copies', type: 'float'},
|
||||
{name: 'time_added', type: 'int'},
|
||||
{name: 'tracker_host', type: 'string'}
|
||||
]
|
||||
});
|
||||
@ -1,7 +1,7 @@
|
||||
/*!
|
||||
* Deluge.details.DetailsPanel.js
|
||||
*
|
||||
* Copyright (c) Damien Churchill 2009-2010 <damoxc@gmail.com>
|
||||
*
|
||||
* Copyright (c) Damien Churchill 2009-2011 <damoxc@gmail.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@ -29,12 +29,12 @@
|
||||
* this exception statement from your version. If you delete this exception
|
||||
* statement from all source files in the program, then also delete it here.
|
||||
*/
|
||||
Ext.namespace('Deluge.details');
|
||||
|
||||
/**
|
||||
* @class Deluge.details.DetailsPanel
|
||||
*/
|
||||
Deluge.details.DetailsPanel = Ext.extend(Ext.TabPanel, {
|
||||
Ext.define('Deluge.details.DetailsPanel', {
|
||||
extend: 'Ext.tab.Panel',
|
||||
|
||||
region: 'south',
|
||||
id: 'torrentDetails',
|
||||
@ -43,61 +43,61 @@ Deluge.details.DetailsPanel = Ext.extend(Ext.TabPanel, {
|
||||
minSize: 100,
|
||||
collapsible: true,
|
||||
margins: '0 5 5 5',
|
||||
activeTab: 0,
|
||||
|
||||
|
||||
initComponent: function() {
|
||||
Deluge.details.DetailsPanel.superclass.initComponent.call(this);
|
||||
this.add(new Deluge.details.StatusTab());
|
||||
this.add(new Deluge.details.DetailsTab());
|
||||
this.add(new Deluge.details.FilesTab());
|
||||
this.add(new Deluge.details.PeersTab());
|
||||
this.add(new Deluge.details.OptionsTab());
|
||||
this.callParent(arguments);
|
||||
this.add(Ext.create('Deluge.details.StatusTab'));
|
||||
this.add(Ext.create('Deluge.details.DetailsTab'));
|
||||
this.add(Ext.create('Deluge.details.FilesTab'));
|
||||
this.add(Ext.create('Deluge.details.PeersTab'));
|
||||
this.add(Ext.create('Deluge.details.OptionsTab'));
|
||||
this.setActiveTab(0);
|
||||
},
|
||||
|
||||
|
||||
clear: function() {
|
||||
this.items.each(function(panel) {
|
||||
if (panel.clear) {
|
||||
panel.clear.defer(100, panel);
|
||||
Ext.defer(panel.clear, 100, panel);
|
||||
panel.disable();
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
|
||||
|
||||
|
||||
update: function(tab) {
|
||||
var torrent = deluge.torrents.getSelected();
|
||||
if (!torrent) {
|
||||
this.clear();
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
this.items.each(function(tab) {
|
||||
if (tab.disabled) tab.enable();
|
||||
});
|
||||
|
||||
|
||||
tab = tab || this.getActiveTab();
|
||||
if (tab.update) tab.update(torrent.id);
|
||||
if (tab.update) tab.update(torrent.getId());
|
||||
},
|
||||
|
||||
|
||||
/* Event Handlers */
|
||||
|
||||
|
||||
// We need to add the events in onRender since Deluge.Torrents hasn't
|
||||
// been created yet.
|
||||
onRender: function(ct, position) {
|
||||
Deluge.details.DetailsPanel.superclass.onRender.call(this, ct, position);
|
||||
this.callParent(arguments);
|
||||
deluge.events.on('disconnect', this.clear, this);
|
||||
deluge.torrents.on('rowclick', this.onTorrentsClick, this);
|
||||
this.on('tabchange', this.onTabChange, this);
|
||||
|
||||
|
||||
deluge.torrents.getSelectionModel().on('selectionchange', function(selModel) {
|
||||
if (!selModel.hasSelection()) this.clear();
|
||||
}, this);
|
||||
},
|
||||
|
||||
|
||||
onTabChange: function(panel, tab) {
|
||||
this.update(tab);
|
||||
},
|
||||
|
||||
|
||||
onTorrentsClick: function(grid, rowIndex, e) {
|
||||
this.update();
|
||||
}
|
||||
|
||||
@ -1,48 +1,47 @@
|
||||
/*
|
||||
Script: Deluge.Details.Details.js
|
||||
The details tab displayed in the details panel.
|
||||
/*!
|
||||
* Deluge.details.DetailsTab.js
|
||||
*
|
||||
* Copyright (c) Damien Churchill 2009-2011 <damoxc@gmail.com>
|
||||
*
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, write to:
|
||||
* The Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor
|
||||
* Boston, MA 02110-1301, USA.
|
||||
*
|
||||
* In addition, as a special exception, the copyright holders give
|
||||
* permission to link the code of portions of this program with the OpenSSL
|
||||
* library.
|
||||
* You must obey the GNU General Public License in all respects for all of
|
||||
* the code used other than OpenSSL. If you modify file(s) with this
|
||||
* exception, you may extend this exception to your version of the file(s),
|
||||
* but you are not obligated to do so. If you do not wish to do so, delete
|
||||
* this exception statement from your version. If you delete this exception
|
||||
* statement from all source files in the program, then also delete it here.
|
||||
*/
|
||||
|
||||
Copyright:
|
||||
(C) Damien Churchill 2009-2010 <damoxc@gmail.com>
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 3, or (at your option)
|
||||
any later version.
|
||||
Ext.define('Deluge.details.DetailsTab', {
|
||||
extend: 'Ext.Panel',
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, write to:
|
||||
The Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor
|
||||
Boston, MA 02110-1301, USA.
|
||||
|
||||
In addition, as a special exception, the copyright holders give
|
||||
permission to link the code of portions of this program with the OpenSSL
|
||||
library.
|
||||
You must obey the GNU General Public License in all respects for all of
|
||||
the code used other than OpenSSL. If you modify file(s) with this
|
||||
exception, you may extend this exception to your version of the file(s),
|
||||
but you are not obligated to do so. If you do not wish to do so, delete
|
||||
this exception statement from your version. If you delete this exception
|
||||
statement from all source files in the program, then also delete it here.
|
||||
|
||||
*/
|
||||
|
||||
Deluge.details.DetailsTab = Ext.extend(Ext.Panel, {
|
||||
title: _('Details'),
|
||||
|
||||
autoScroll: true,
|
||||
fields: {},
|
||||
|
||||
queuedItems: {},
|
||||
|
||||
oldData: {},
|
||||
|
||||
initComponent: function() {
|
||||
Deluge.details.DetailsTab.superclass.initComponent.call(this);
|
||||
this.callParent(arguments);
|
||||
this.addItem('torrent_name', _('Name'));
|
||||
this.addItem('hash', _('Hash'));
|
||||
this.addItem('path', _('Path'));
|
||||
@ -51,12 +50,14 @@ Deluge.details.DetailsTab = Ext.extend(Ext.Panel, {
|
||||
this.addItem('comment', _('Comment'));
|
||||
this.addItem('status', _('Status'));
|
||||
this.addItem('tracker', _('Tracker'));
|
||||
this.addItem('owner', _('Owner'));
|
||||
this.addItem('shared', _('Shared'));
|
||||
},
|
||||
|
||||
onRender: function(ct, position) {
|
||||
Deluge.details.DetailsTab.superclass.onRender.call(this, ct, position);
|
||||
this.callParent(arguments);
|
||||
this.body.setStyle('padding', '10px');
|
||||
this.dl = Ext.DomHelper.append(this.body, {tag: 'dl'}, true);
|
||||
this.dl = Ext.core.DomHelper.append(this.body, {tag: 'dl'}, true);
|
||||
|
||||
for (var id in this.queuedItems) {
|
||||
this.doAddItem(id, this.queuedItems[id]);
|
||||
@ -73,8 +74,8 @@ Deluge.details.DetailsTab = Ext.extend(Ext.Panel, {
|
||||
|
||||
// private
|
||||
doAddItem: function(id, label) {
|
||||
Ext.DomHelper.append(this.dl, {tag: 'dt', cls: id, html: label + ':'});
|
||||
this.fields[id] = Ext.DomHelper.append(this.dl, {tag: 'dd', cls: id, html: ''}, true);
|
||||
Ext.core.DomHelper.append(this.dl, {tag: 'dt', cls: id, html: label + ':'});
|
||||
this.fields[id] = Ext.core.DomHelper.append(this.dl, {tag: 'dd', cls: id, html: ''}, true);
|
||||
},
|
||||
|
||||
clear: function() {
|
||||
@ -102,11 +103,14 @@ Deluge.details.DetailsTab = Ext.extend(Ext.Panel, {
|
||||
files: torrent.num_files,
|
||||
status: torrent.message,
|
||||
tracker: torrent.tracker,
|
||||
comment: torrent.comment
|
||||
comment: torrent.comment,
|
||||
owner: torrent.owner,
|
||||
shared: torrent.shared
|
||||
};
|
||||
|
||||
for (var field in this.fields) {
|
||||
if (!Ext.isDefined(data[field])) continue; // this is a field we aren't responsible for.
|
||||
// this is a field we aren't responsible for.
|
||||
if (!Ext.isDefined(data[field])) continue;
|
||||
if (data[field] == this.oldData[field]) continue;
|
||||
this.fields[field].dom.innerHTML = Ext.escapeHTML(data[field]);
|
||||
}
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
/*!
|
||||
* Deluge.details.FilesTab.js
|
||||
*
|
||||
* Copyright (c) Damien Churchill 2009-2010 <damoxc@gmail.com>
|
||||
*
|
||||
* Copyright (c) Damien Churchill 2009-2011 <damoxc@gmail.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@ -29,39 +29,52 @@
|
||||
* this exception statement from your version. If you delete this exception
|
||||
* statement from all source files in the program, then also delete it here.
|
||||
*/
|
||||
|
||||
Deluge.details.FilesTab = Ext.extend(Ext.ux.tree.TreeGrid, {
|
||||
|
||||
Ext.define('Deluge.data.File', {
|
||||
extend: 'Ext.data.Model',
|
||||
fields: [
|
||||
{name: 'filename', type: 'string'},
|
||||
{name: 'size', type: 'int'},
|
||||
{name: 'progress', type: 'float'}
|
||||
]
|
||||
});
|
||||
|
||||
Ext.define('Deluge.details.FilesTab', {
|
||||
|
||||
extend: 'Ext.tree.Panel',
|
||||
|
||||
title: _('Files'),
|
||||
|
||||
autoScroll: true,
|
||||
rootVisible: false,
|
||||
|
||||
columns: [{
|
||||
header: _('Filename'),
|
||||
xtype: 'treecolumn',
|
||||
text: _('Filename'),
|
||||
width: 330,
|
||||
dataIndex: 'filename'
|
||||
}, {
|
||||
header: _('Size'),
|
||||
xtype: 'templatecolumn',
|
||||
text: _('Size'),
|
||||
width: 150,
|
||||
dataIndex: 'size',
|
||||
tpl: new Ext.XTemplate('{size:this.fsize}', {
|
||||
tpl: Ext.create('Ext.XTemplate', '{size:this.fsize}', {
|
||||
fsize: function(v) { return fsize(v); }
|
||||
})
|
||||
}, {
|
||||
xtype: 'tgrendercolumn',
|
||||
header: _('Progress'),
|
||||
xtype: 'templatecolumn',
|
||||
text: _('Progress'),
|
||||
width: 150,
|
||||
dataIndex: 'progress',
|
||||
renderer: function(v) {
|
||||
var progress = v * 100;
|
||||
return Deluge.progressBar(progress, this.col.width, progress.toFixed(2) + '%', 0);
|
||||
}
|
||||
tpl: Ext.create('Ext.XTemplate', '{progress:this.progress}', {
|
||||
progress: function(v) {
|
||||
var progress = v * 100;
|
||||
return Deluge.progressBar(progress, this.col.width, progress.toFixed(2) + '%', 0);
|
||||
}
|
||||
})
|
||||
}, {
|
||||
header: _('Priority'),
|
||||
xtype: 'templatecolumn',
|
||||
text: _('Priority'),
|
||||
width: 150,
|
||||
dataIndex: 'priority',
|
||||
tpl: new Ext.XTemplate('<tpl if="!isNaN(priority)">' +
|
||||
tpl: Ext.create('Ext.XTemplate', '<tpl if="!isNaN(priority)">' +
|
||||
'<div class="{priority:this.getClass}">' +
|
||||
'{priority:this.getName}' +
|
||||
'</div></tpl>', {
|
||||
@ -74,96 +87,48 @@ Deluge.details.FilesTab = Ext.extend(Ext.ux.tree.TreeGrid, {
|
||||
}
|
||||
})
|
||||
}],
|
||||
|
||||
selModel: new Ext.tree.MultiSelectionModel(),
|
||||
|
||||
initComponent: function() {
|
||||
Deluge.details.FilesTab.superclass.initComponent.call(this);
|
||||
this.setRootNode(new Ext.tree.TreeNode({text: 'Files'}));
|
||||
},
|
||||
store: Ext.create('Ext.data.TreeStore', {
|
||||
model: 'Deluge.data.File',
|
||||
proxy: {
|
||||
type: 'memory'
|
||||
}
|
||||
}),
|
||||
|
||||
autoScroll: true,
|
||||
multiSelect: true,
|
||||
rootVisible: false,
|
||||
useArrows: true,
|
||||
|
||||
clear: function() {
|
||||
var root = this.getRootNode();
|
||||
if (!root.hasChildNodes()) return;
|
||||
root.cascade(function(node) {
|
||||
var parentNode = node.parentNode;
|
||||
if (!parentNode) return;
|
||||
if (!parentNode.ownerTree) return;
|
||||
parentNode.removeChild(node);
|
||||
});
|
||||
},
|
||||
|
||||
createFileTree: function(files) {
|
||||
function walk(files, parentNode) {
|
||||
for (var file in files.contents) {
|
||||
var item = files.contents[file];
|
||||
if (item.type == 'dir') {
|
||||
walk(item, parentNode.appendChild(new Ext.tree.TreeNode({
|
||||
text: file,
|
||||
filename: file,
|
||||
size: item.size,
|
||||
progress: item.progress,
|
||||
priority: item.priority
|
||||
})));
|
||||
} else {
|
||||
parentNode.appendChild(new Ext.tree.TreeNode({
|
||||
text: file,
|
||||
filename: file,
|
||||
fileIndex: item.index,
|
||||
size: item.size,
|
||||
progress: item.progress,
|
||||
priority: item.priority,
|
||||
leaf: true,
|
||||
iconCls: 'x-deluge-file',
|
||||
uiProvider: Ext.ux.tree.TreeGridNodeUI
|
||||
}));
|
||||
}
|
||||
}
|
||||
}
|
||||
var root = this.getRootNode();
|
||||
walk(files, root);
|
||||
root.firstChild.expand();
|
||||
this.getStore().removeAll();
|
||||
},
|
||||
|
||||
update: function(torrentId) {
|
||||
var store = this.getStore(),
|
||||
view = this.getView();
|
||||
|
||||
if (this.torrentId != torrentId) {
|
||||
this.clear();
|
||||
//store.removeAll();
|
||||
store.setProxy({
|
||||
type: 'ajax',
|
||||
url: 'files/' + torrentId
|
||||
})
|
||||
this.torrentId = torrentId;
|
||||
}
|
||||
|
||||
deluge.client.web.get_torrent_files(torrentId, {
|
||||
success: this.onRequestComplete,
|
||||
scope: this,
|
||||
torrentId: torrentId
|
||||
});
|
||||
},
|
||||
|
||||
updateFileTree: function(files) {
|
||||
function walk(files, parentNode) {
|
||||
for (var file in files.contents) {
|
||||
var item = files.contents[file];
|
||||
var node = parentNode.findChild('filename', file);
|
||||
node.attributes.size = item.size;
|
||||
node.attributes.progress = item.progress;
|
||||
node.attributes.priority = item.priority;
|
||||
node.ui.updateColumns();
|
||||
if (item.type == 'dir') {
|
||||
walk(item, node);
|
||||
}
|
||||
}
|
||||
}
|
||||
walk(files, this.getRootNode());
|
||||
store.load();
|
||||
},
|
||||
|
||||
onRender: function(ct, position) {
|
||||
Deluge.details.FilesTab.superclass.onRender.call(this, ct, position);
|
||||
deluge.menus.filePriorities.on('itemclick', this.onItemClick, this);
|
||||
this.on('contextmenu', this.onContextMenu, this);
|
||||
this.sorter = new Ext.tree.TreeSorter(this, {
|
||||
folderSort: true
|
||||
});
|
||||
//this.sorter = new Ext.tree.TreeSorter(this, {
|
||||
// folderSort: true
|
||||
//});
|
||||
},
|
||||
|
||||
|
||||
onContextMenu: function(node, e) {
|
||||
e.stopEvent();
|
||||
var selModel = this.getSelectionModel();
|
||||
@ -173,7 +138,7 @@ Deluge.details.FilesTab = Ext.extend(Ext.ux.tree.TreeGrid, {
|
||||
}
|
||||
deluge.menus.filePriorities.showAt(e.getPoint());
|
||||
},
|
||||
|
||||
|
||||
onItemClick: function(baseItem, e) {
|
||||
switch (baseItem.id) {
|
||||
case 'expandAll':
|
||||
@ -200,7 +165,7 @@ Deluge.details.FilesTab = Ext.extend(Ext.ux.tree.TreeGrid, {
|
||||
return;
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
var priorities = new Array(Ext.keys(indexes).length);
|
||||
for (var index in indexes) {
|
||||
priorities[index] = indexes[index];
|
||||
@ -216,13 +181,5 @@ Deluge.details.FilesTab = Ext.extend(Ext.ux.tree.TreeGrid, {
|
||||
});
|
||||
break;
|
||||
}
|
||||
},
|
||||
|
||||
onRequestComplete: function(files, options) {
|
||||
if (!this.getRootNode().hasChildNodes()) {
|
||||
this.createFileTree(files);
|
||||
} else {
|
||||
this.updateFileTree(files);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
/*!
|
||||
* Deluge.details.OptionsTab.js
|
||||
*
|
||||
* Copyright (c) Damien Churchill 2009-2010 <damoxc@gmail.com>
|
||||
* Copyright (c) Damien Churchill 2009-2011 <damoxc@gmail.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@ -30,32 +30,27 @@
|
||||
* statement from all source files in the program, then also delete it here.
|
||||
*/
|
||||
|
||||
Ext.define('Deluge.details.OptionsTab', {
|
||||
extend: 'Ext.form.Panel',
|
||||
|
||||
Deluge.details.OptionsTab = Ext.extend(Ext.form.FormPanel, {
|
||||
|
||||
constructor: function(config) {
|
||||
config = Ext.apply({
|
||||
autoScroll: true,
|
||||
bodyStyle: 'padding: 5px;',
|
||||
border: false,
|
||||
cls: 'x-deluge-options',
|
||||
defaults: {
|
||||
autoHeight: true,
|
||||
labelWidth: 1,
|
||||
defaultType: 'checkbox'
|
||||
},
|
||||
deferredRender: false,
|
||||
layout: 'column',
|
||||
title: _('Options')
|
||||
}, config);
|
||||
Deluge.details.OptionsTab.superclass.constructor.call(this, config);
|
||||
title: _('Options'),
|
||||
autoScroll: true,
|
||||
bodyStyle: 'padding: 5px;',
|
||||
border: false,
|
||||
cls: 'x-deluge-options',
|
||||
defaults: {
|
||||
autoHeight: true,
|
||||
labelWidth: 1,
|
||||
defaultType: 'checkbox'
|
||||
},
|
||||
deferredRender: false,
|
||||
layout: 'column',
|
||||
|
||||
initComponent: function() {
|
||||
Deluge.details.OptionsTab.superclass.initComponent.call(this);
|
||||
this.callParent(arguments);
|
||||
|
||||
this.fieldsets = {}, this.fields = {};
|
||||
this.optionsManager = new Deluge.MultiOptionsManager({
|
||||
this.optionsManager = Ext.create('Deluge.MultiOptionsManager', {
|
||||
options: {
|
||||
'max_download_speed': -1,
|
||||
'max_upload_speed': -1,
|
||||
@ -291,7 +286,7 @@ Deluge.details.OptionsTab = Ext.extend(Ext.form.FormPanel, {
|
||||
autoHeight: true,
|
||||
defaultType: 'checkbox',
|
||||
title: _('General'),
|
||||
layout: 'form'
|
||||
layout: 'anchor'
|
||||
});
|
||||
|
||||
this.fields['private'] = this.fieldsets.general.add({
|
||||
@ -354,12 +349,12 @@ Deluge.details.OptionsTab = Ext.extend(Ext.form.FormPanel, {
|
||||
},
|
||||
|
||||
onRender: function(ct, position) {
|
||||
Deluge.details.OptionsTab.superclass.onRender.call(this, ct, position);
|
||||
this.callParent(arguments);
|
||||
|
||||
// This is another hack I think, so keep an eye out here when upgrading.
|
||||
this.layout = new Ext.layout.ColumnLayout();
|
||||
this.layout.setContainer(this);
|
||||
this.doLayout();
|
||||
//this.layout = new Ext.layout.ColumnLayout();
|
||||
//this.layout.setContainer(this);
|
||||
//this.doLayout();
|
||||
},
|
||||
|
||||
clear: function() {
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
/*!
|
||||
* Deluge.details.PeersTab.js
|
||||
*
|
||||
* Copyright (c) Damien Churchill 2009-2010 <damoxc@gmail.com>
|
||||
* Copyright (c) Damien Churchill 2009-2011 <damoxc@gmail.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@ -30,136 +30,95 @@
|
||||
* statement from all source files in the program, then also delete it here.
|
||||
*/
|
||||
|
||||
(function() {
|
||||
function flagRenderer(value) {
|
||||
if (!value.replace(' ', '').replace(' ', '')){
|
||||
return '';
|
||||
Ext.define('Deluge.details.PeersTab', {
|
||||
extend: 'Ext.grid.Panel',
|
||||
id: 'peersGrid',
|
||||
title: _('Peers'),
|
||||
cls: 'x-deluge-peers',
|
||||
viewConfig: {
|
||||
loadMask: false
|
||||
},
|
||||
invalidateScrollerOnRefresh: false,
|
||||
|
||||
store: {
|
||||
model: 'Deluge.data.Peer',
|
||||
proxy: {
|
||||
type: 'ajax',
|
||||
url: 'peers/',
|
||||
reader: {
|
||||
type: 'json',
|
||||
root: 'peers'
|
||||
}
|
||||
}
|
||||
return String.format('<img src="flag/{0}" />', value);
|
||||
}
|
||||
function peerAddressRenderer(value, p, record) {
|
||||
var seed = (record.data['seed'] == 1024) ? 'x-deluge-seed' : 'x-deluge-peer';
|
||||
if (peer_ip.length > 2) {
|
||||
var port = peer_ip.pop();
|
||||
var ip = peer_ip.join(":");
|
||||
value = "[" + ip + "]:" + port;
|
||||
},
|
||||
|
||||
columns: [{
|
||||
text: ' ',
|
||||
dataIndex: 'country',
|
||||
width: 30,
|
||||
sortable: true,
|
||||
renderer: function(v) {
|
||||
if (!v.replace(' ', '').replace(' ', '')) {
|
||||
return '';
|
||||
}
|
||||
return Ext.String.format('<img src="flag/{0}" />', v);
|
||||
}
|
||||
return String.format('<div class="{0}">{1}</div>', seed, value);
|
||||
}
|
||||
function peerProgressRenderer(value) {
|
||||
var progress = (value * 100).toFixed(0);
|
||||
return Deluge.progressBar(progress, this.width - 8, progress + '%');
|
||||
}
|
||||
|
||||
Deluge.details.PeersTab = Ext.extend(Ext.grid.GridPanel, {
|
||||
|
||||
// fast way to figure out if we have a peer already.
|
||||
peers: {},
|
||||
|
||||
constructor: function(config) {
|
||||
config = Ext.apply({
|
||||
title: _('Peers'),
|
||||
cls: 'x-deluge-peers',
|
||||
store: new Ext.data.Store({
|
||||
reader: new Ext.data.JsonReader({
|
||||
idProperty: 'ip',
|
||||
root: 'peers'
|
||||
}, Deluge.data.Peer)
|
||||
}),
|
||||
columns: [{
|
||||
header: ' ',
|
||||
width: 30,
|
||||
sortable: true,
|
||||
renderer: flagRenderer,
|
||||
dataIndex: 'country'
|
||||
}, {
|
||||
header: 'Address',
|
||||
width: 125,
|
||||
sortable: true,
|
||||
renderer: peerAddressRenderer,
|
||||
dataIndex: 'ip'
|
||||
}, {
|
||||
header: 'Client',
|
||||
width: 125,
|
||||
sortable: true,
|
||||
renderer: fplain,
|
||||
dataIndex: 'client'
|
||||
}, {
|
||||
header: 'Progress',
|
||||
width: 150,
|
||||
sortable: true,
|
||||
renderer: peerProgressRenderer,
|
||||
dataIndex: 'progress'
|
||||
}, {
|
||||
header: 'Down Speed',
|
||||
width: 100,
|
||||
sortable: true,
|
||||
renderer: fspeed,
|
||||
dataIndex: 'down_speed'
|
||||
}, {
|
||||
header: 'Up Speed',
|
||||
width: 100,
|
||||
sortable: true,
|
||||
renderer: fspeed,
|
||||
dataIndex: 'up_speed'
|
||||
}],
|
||||
stripeRows: true,
|
||||
deferredRender:false,
|
||||
autoScroll:true
|
||||
}, config);
|
||||
Deluge.details.PeersTab.superclass.constructor.call(this, config);
|
||||
},
|
||||
|
||||
clear: function() {
|
||||
this.getStore().removeAll();
|
||||
this.peers = {};
|
||||
},
|
||||
|
||||
update: function(torrentId) {
|
||||
deluge.client.web.get_torrent_status(torrentId, Deluge.Keys.Peers, {
|
||||
success: this.onRequestComplete,
|
||||
scope: this
|
||||
});
|
||||
},
|
||||
|
||||
onRequestComplete: function(torrent, options) {
|
||||
if (!torrent) return;
|
||||
|
||||
var store = this.getStore();
|
||||
var newPeers = [];
|
||||
var addresses = {};
|
||||
|
||||
// Go through the peers updating and creating peer records
|
||||
Ext.each(torrent.peers, function(peer) {
|
||||
if (this.peers[peer.ip]) {
|
||||
var record = store.getById(peer.ip);
|
||||
record.beginEdit();
|
||||
for (var k in peer) {
|
||||
if (record.get(k) != peer[k]) {
|
||||
record.set(k, peer[k]);
|
||||
}
|
||||
}
|
||||
record.endEdit();
|
||||
} else {
|
||||
this.peers[peer.ip] = 1;
|
||||
newPeers.push(new Deluge.data.Peer(peer, peer.ip));
|
||||
}
|
||||
addresses[peer.ip] = 1;
|
||||
}, this);
|
||||
store.add(newPeers);
|
||||
|
||||
// Remove any peers that shouldn't be left in the store
|
||||
store.each(function(record) {
|
||||
if (!addresses[record.id]) {
|
||||
store.remove(record);
|
||||
delete this.peers[record.id];
|
||||
}
|
||||
}, this);
|
||||
store.commitChanges();
|
||||
|
||||
var sortState = store.getSortState();
|
||||
if (!sortState) return;
|
||||
store.sort(sortState.field, sortState.direction);
|
||||
}, {
|
||||
text: 'Address',
|
||||
dataIndex: 'ip',
|
||||
width: 125,
|
||||
sortable: true,
|
||||
renderer: function(v, p, r) {
|
||||
var cls = (r.data['seed'] == 1024) ? 'x-deluge-seed': 'x-deluge-peer';
|
||||
return Ext.String.format('<div class="{0}">{1}</div>', cls, v);
|
||||
}
|
||||
});
|
||||
})();
|
||||
}, {
|
||||
text: 'Client',
|
||||
dataIndex: 'client',
|
||||
width: 125,
|
||||
sortable: true,
|
||||
renderer: function(v) { return fplain(v) }
|
||||
}, {
|
||||
text: 'Progress',
|
||||
dataIndex: 'progress',
|
||||
width: 150,
|
||||
sortable: true,
|
||||
renderer: function(v) {
|
||||
var progress = (v * 100).toFixed(0),
|
||||
width = this.query('gridcolumn[dataIndex=progress]')[0].getWidth();
|
||||
return Deluge.progressBar(progress, width - 8, progress + '%');
|
||||
}
|
||||
}, {
|
||||
text: 'Down Speed',
|
||||
dataIndex: 'down_speed',
|
||||
width: 100,
|
||||
sortable: true,
|
||||
renderer: function(v) { return fspeed(v) }
|
||||
}, {
|
||||
text: 'Up Speed',
|
||||
dataIndex: 'up_speed',
|
||||
width: 100,
|
||||
sortable: true,
|
||||
renderer: function(v) { return fspeed(v) }
|
||||
}],
|
||||
|
||||
autoScroll: true,
|
||||
deferredRender: false,
|
||||
stripeRows: true,
|
||||
|
||||
clear: function() {
|
||||
this.getStore().removeAll();
|
||||
},
|
||||
|
||||
update: function(torrentId) {
|
||||
var store = this.getStore(),
|
||||
view = this.getView();
|
||||
|
||||
if (torrentId != this.torrentId) {
|
||||
store.removeAll();
|
||||
store.getProxy().url = 'peers/' + torrentId;
|
||||
this.torrentId = torrentId;
|
||||
}
|
||||
store.load();
|
||||
}
|
||||
});
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
/*!
|
||||
* Ext.ux.layout.FormLayoutFix.js
|
||||
*
|
||||
* Copyright (c) Damien Churchill 2009-2010 <damoxc@gmail.com>
|
||||
* Deluge.details.StatusItem.js
|
||||
*
|
||||
* Copyright (c) Damien Churchill 2011 <damoxc@gmail.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@ -30,27 +30,46 @@
|
||||
* statement from all source files in the program, then also delete it here.
|
||||
*/
|
||||
|
||||
// Taken from http://extjs.com/forum/showthread.php?t=75273
|
||||
// remove spaces for hidden elements and make show(), hide(), enable() and disable() act on
|
||||
// the label. don't use hideLabel with this.
|
||||
Ext.override(Ext.layout.FormLayout, {
|
||||
renderItem : function(c, position, target){
|
||||
if(c && !c.rendered && (c.isFormField || c.fieldLabel) && c.inputType != 'hidden'){
|
||||
var args = this.getTemplateArgs(c);
|
||||
if(typeof position == 'number'){
|
||||
position = target.dom.childNodes[position] || null;
|
||||
}
|
||||
if(position){
|
||||
c.formItem = this.fieldTpl.insertBefore(position, args, true);
|
||||
}else{
|
||||
c.formItem = this.fieldTpl.append(target, args, true);
|
||||
}
|
||||
c.actionMode = 'formItem';
|
||||
c.render('x-form-el-'+c.id);
|
||||
c.container = c.formItem;
|
||||
c.actionMode = 'container';
|
||||
}else {
|
||||
Ext.layout.FormLayout.superclass.renderItem.apply(this, arguments);
|
||||
}
|
||||
/**
|
||||
* @class Deluge.details.StatusItem
|
||||
* @extends Ext.Component
|
||||
*/
|
||||
Ext.define('Deluge.details.StatusItem', {
|
||||
extend: 'Ext.Component',
|
||||
alias: 'widget.statusitem',
|
||||
|
||||
renderTpl:
|
||||
'<div class="x-status-item">' +
|
||||
'<span class="x-status-label" style="width: {labelWidth}px;">{label}:</span>' +
|
||||
'<span class="x-status-text">{text}</span>' +
|
||||
'</div>',
|
||||
|
||||
renderSelectors: {
|
||||
labelEl: 'span.x-status-label',
|
||||
textEl: 'span.x-status-text'
|
||||
},
|
||||
|
||||
|
||||
initComponent: function() {
|
||||
var me = this;
|
||||
me.callParent(arguments);
|
||||
},
|
||||
|
||||
setText: function(text) {
|
||||
var me = this;
|
||||
me.textEl.dom.innerHTML = text;
|
||||
},
|
||||
|
||||
// private
|
||||
onRender: function(ct, position) {
|
||||
var me = this;
|
||||
|
||||
Ext.applyIf(me.renderData, {
|
||||
label: me.label,
|
||||
labelWidth: me.labelWidth || 0,
|
||||
text: me.text
|
||||
});
|
||||
|
||||
me.callParent(arguments);
|
||||
}
|
||||
});
|
||||
@ -1,7 +1,7 @@
|
||||
/*!
|
||||
* Deluge.details.StatusTab.js
|
||||
*
|
||||
* Copyright (c) Damien Churchill 2009-2010 <damoxc@gmail.com>
|
||||
*
|
||||
* Copyright (c) Damien Churchill 2009-2011 <damoxc@gmail.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@ -29,99 +29,180 @@
|
||||
* this exception statement from your version. If you delete this exception
|
||||
* statement from all source files in the program, then also delete it here.
|
||||
*/
|
||||
Ext.ns('Deluge.details');
|
||||
|
||||
/**
|
||||
* @class Deluge.details.StatusTab
|
||||
* @extends Ext.Panel
|
||||
* @extends Ext.panel.Panel
|
||||
*/
|
||||
Deluge.details.StatusTab = Ext.extend(Ext.Panel, {
|
||||
Ext.define('Deluge.details.StatusTab', {
|
||||
extend: 'Ext.panel.Panel',
|
||||
|
||||
title: _('Status'),
|
||||
autoScroll: true,
|
||||
|
||||
onRender: function(ct, position) {
|
||||
Deluge.details.StatusTab.superclass.onRender.call(this, ct, position);
|
||||
|
||||
bodyPadding: 10,
|
||||
layout: {
|
||||
type: 'vbox',
|
||||
align: 'stretch'
|
||||
},
|
||||
|
||||
initComponent: function() {
|
||||
this.callParent(arguments);
|
||||
|
||||
this.fields = {};
|
||||
this.progressBar = this.add({
|
||||
xtype: 'progress',
|
||||
cls: 'x-deluge-status-progressbar'
|
||||
xtype: 'progressbar',
|
||||
cls: 'x-deluge-torrent-progressbar'
|
||||
});
|
||||
|
||||
this.status = this.add({
|
||||
cls: 'x-deluge-status',
|
||||
id: 'deluge-details-status',
|
||||
|
||||
this.add({
|
||||
xtype: 'container',
|
||||
margins: 10,
|
||||
border: false,
|
||||
width: 1000,
|
||||
listeners: {
|
||||
'render': {
|
||||
fn: function(panel) {
|
||||
panel.load({
|
||||
url: deluge.config.base + 'render/tab_status.html',
|
||||
text: _('Loading') + '...'
|
||||
});
|
||||
panel.getUpdater().on('update', this.onPanelUpdate, this);
|
||||
},
|
||||
scope: this
|
||||
}
|
||||
}
|
||||
flex: 1,
|
||||
layout: {
|
||||
type: 'hbox',
|
||||
align: 'stretch'
|
||||
},
|
||||
defaultType: 'container',
|
||||
defaults: {
|
||||
flex: 1,
|
||||
layout: 'vbox',
|
||||
border: false,
|
||||
defaultType: 'statusitem'
|
||||
},
|
||||
|
||||
items: [{
|
||||
defaults: {
|
||||
labelWidth: 100,
|
||||
width: 300,
|
||||
margins: '2 0 2 0'
|
||||
},
|
||||
items: [{
|
||||
label: _('Downloaded'),
|
||||
dataIndex: 'downloaded'
|
||||
}, {
|
||||
label: _('Uploaded'),
|
||||
dataIndex: 'uploaded'
|
||||
}, {
|
||||
label: _('Share Ratio'),
|
||||
dataIndex: 'share'
|
||||
}, {
|
||||
label: _('Next Announce'),
|
||||
dataIndex: 'announce'
|
||||
}, {
|
||||
label: _('Tracker Status'),
|
||||
dataIndex: 'tracker_status'
|
||||
}]
|
||||
}, {
|
||||
defaults: {
|
||||
labelWidth: 55,
|
||||
width: 300
|
||||
},
|
||||
items: [{
|
||||
label: _('Speed'),
|
||||
dataIndex: 'downspeed'
|
||||
}, {
|
||||
label: _('Speed'),
|
||||
dataIndex: 'upspeed'
|
||||
}, {
|
||||
label: _('ETA'),
|
||||
dataIndex: 'eta'
|
||||
}, {
|
||||
label: _('Pieces'),
|
||||
dataIndex: 'pieces'
|
||||
}]
|
||||
}, {
|
||||
defaults: {
|
||||
labelWidth: 130,
|
||||
width: 300
|
||||
},
|
||||
items: [{
|
||||
label: _('Seeders'),
|
||||
dataIndex: 'seeders'
|
||||
}, {
|
||||
label: _('Peers'),
|
||||
dataIndex: 'peers'
|
||||
}, {
|
||||
label: _('Availability'),
|
||||
dataIndex: 'avail'
|
||||
}, {
|
||||
label: _('Auto Managed'),
|
||||
dataIndex: 'auto_managed'
|
||||
}, {
|
||||
label: _('Last Seen Complete'),
|
||||
dataIndex: 'last_seen_complete'
|
||||
}]
|
||||
}, {
|
||||
defaults: {
|
||||
labelWidth: 100,
|
||||
width: 300
|
||||
},
|
||||
items: [{
|
||||
label: _('Active Time'),
|
||||
dataIndex: 'active_time'
|
||||
}, {
|
||||
label: _('Seeding Time'),
|
||||
dataIndex: 'seeding_time'
|
||||
}, {
|
||||
label: _('Seed Rank'),
|
||||
dataIndex: 'seed_rank'
|
||||
}, {
|
||||
label: _('Date Added'),
|
||||
dataIndex: 'time_added'
|
||||
}]
|
||||
}]
|
||||
});
|
||||
},
|
||||
|
||||
|
||||
update: function(torrentId) {
|
||||
deluge.client.web.get_torrent_status(torrentId, Deluge.Keys.Status, {
|
||||
success: this.onRequestComplete,
|
||||
scope: this
|
||||
});
|
||||
},
|
||||
|
||||
clear: function() {
|
||||
this.progressBar.updateProgress(0, ' ');
|
||||
for (var k in this.fields) {
|
||||
this.fields[k].innerHTML = '';
|
||||
}
|
||||
},
|
||||
|
||||
update: function(torrentId) {
|
||||
if (!this.fields) this.getFields();
|
||||
deluge.client.web.get_torrent_status(torrentId, Deluge.Keys.Status, {
|
||||
success: this.onRequestComplete,
|
||||
scope: this
|
||||
});
|
||||
},
|
||||
|
||||
onPanelUpdate: function(el, response) {
|
||||
this.fields = {};
|
||||
Ext.each(Ext.query('dd', this.status.body.dom), function(field) {
|
||||
this.fields[field.className] = field;
|
||||
}, this);
|
||||
},
|
||||
|
||||
onRequestComplete: function(status) {
|
||||
seeders = status.total_seeds > -1 ? status.num_seeds + ' (' + status.total_seeds + ')' : status.num_seeds;
|
||||
peers = status.total_peers > -1 ? status.num_peers + ' (' + status.total_peers + ')' : status.num_peers;
|
||||
last_seen_complete = status.last_seen_complete > 0.0 ? fdate(status.last_seen_complete) : "Never";
|
||||
|
||||
onRequestComplete: function(torrent) {
|
||||
var me = this;
|
||||
|
||||
var text = torrent.state + ' ' + torrent.progress.toFixed(2) + '%';
|
||||
me.progressBar.updateProgress(torrent.progress / 100.0, text);
|
||||
|
||||
seeders = torrent.total_seeds > -1 ? torrent.num_seeds + ' (' + torrent.total_seeds + ')' : torrent.num_seeds;
|
||||
peers = torrent.total_peers > -1 ? torrent.num_peers + ' (' + torrent.total_peers + ')' : torrent.num_peers;
|
||||
last_seen_complete = torrent.last_seen_complete > 0.0 ? fdate(torrent.last_seen_complete) : "Never";
|
||||
var data = {
|
||||
downloaded: fsize(status.total_done, true),
|
||||
uploaded: fsize(status.total_uploaded, true),
|
||||
share: (status.ratio == -1) ? '∞' : status.ratio.toFixed(3),
|
||||
announce: ftime(status.next_announce),
|
||||
tracker_status: status.tracker_status,
|
||||
downspeed: (status.download_payload_rate) ? fspeed(status.download_payload_rate) : '0.0 KiB/s',
|
||||
upspeed: (status.upload_payload_rate) ? fspeed(status.upload_payload_rate) : '0.0 KiB/s',
|
||||
eta: ftime(status.eta),
|
||||
pieces: status.num_pieces + ' (' + fsize(status.piece_length) + ')',
|
||||
downloaded: fsize(torrent.total_done, true),
|
||||
uploaded: fsize(torrent.total_uploaded, true),
|
||||
share: (torrent.ratio == -1) ? '∞' : torrent.ratio.toFixed(3),
|
||||
announce: ftime(torrent.next_announce),
|
||||
tracker_status: torrent.tracker_status,
|
||||
tracker_torrent: torrent.tracker_torrent,
|
||||
downspeed: (torrent.download_payload_rate) ? fspeed(torrent.download_payload_rate) : '0.0 KiB/s',
|
||||
upspeed: (torrent.upload_payload_rate) ? fspeed(torrent.upload_payload_rate) : '0.0 KiB/s',
|
||||
eta: ftime(torrent.eta),
|
||||
pieces: torrent.num_pieces + ' (' + fsize(torrent.piece_length) + ')',
|
||||
seeders: seeders,
|
||||
peers: peers,
|
||||
avail: status.distributed_copies.toFixed(3),
|
||||
active_time: ftime(status.active_time),
|
||||
seeding_time: ftime(status.seeding_time),
|
||||
seed_rank: status.seed_rank,
|
||||
time_added: fdate(status.time_added),
|
||||
avail: torrent.distributed_copies.toFixed(3),
|
||||
active_time: ftime(torrent.active_time),
|
||||
seeding_time: ftime(torrent.seeding_time),
|
||||
seed_rank: torrent.seed_rank,
|
||||
time_added: fdate(torrent.time_added),
|
||||
last_seen_complete: last_seen_complete
|
||||
}
|
||||
data.auto_managed = _((status.is_auto_managed) ? 'True' : 'False');
|
||||
data.auto_managed = _((torrent.is_auto_managed) ? 'True' : 'False');
|
||||
|
||||
data.downloaded += ' (' + ((status.total_payload_download) ? fsize(status.total_payload_download) : '0.0 KiB') + ')';
|
||||
data.uploaded += ' (' + ((status.total_payload_download) ? fsize(status.total_payload_download): '0.0 KiB') + ')';
|
||||
|
||||
for (var field in this.fields) {
|
||||
this.fields[field].innerHTML = data[field];
|
||||
}
|
||||
var text = status.state + ' ' + status.progress.toFixed(2) + '%';
|
||||
this.progressBar.updateProgress(status.progress / 100.0, text);
|
||||
data.downloaded += ' (' + ((torrent.total_payload_download) ? fsize(torrent.total_payload_download) : '0.0 KiB') + ')';
|
||||
data.uploaded += ' (' + ((torrent.total_payload_download) ? fsize(torrent.total_payload_download): '0.0 KiB') + ')';
|
||||
|
||||
Ext.Array.each(me.query('statusitem'), function(item) {
|
||||
item.setText(data[item.dataIndex]);
|
||||
}, me);
|
||||
}
|
||||
});
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
/*!
|
||||
* Deluge.preferences.BandwidthPage.js
|
||||
*
|
||||
* Copyright (c) Damien Churchill 2009-2010 <damoxc@gmail.com>
|
||||
*
|
||||
* Copyright (c) Damien Churchill 2009-2011 <damoxc@gmail.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@ -29,26 +29,21 @@
|
||||
* this exception statement from your version. If you delete this exception
|
||||
* statement from all source files in the program, then also delete it here.
|
||||
*/
|
||||
Ext.namespace('Deluge.preferences');
|
||||
|
||||
/**
|
||||
* @class Deluge.preferences.Bandwidth
|
||||
* @extends Ext.form.FormPanel
|
||||
*/
|
||||
Deluge.preferences.Bandwidth = Ext.extend(Ext.form.FormPanel, {
|
||||
constructor: function(config) {
|
||||
config = Ext.apply({
|
||||
border: false,
|
||||
title: _('Bandwidth'),
|
||||
layout: 'form',
|
||||
labelWidth: 10
|
||||
}, config);
|
||||
Deluge.preferences.Bandwidth.superclass.constructor.call(this, config);
|
||||
},
|
||||
|
||||
Ext.define('Deluge.preferences.Bandwidth', {
|
||||
extend: 'Ext.form.Panel',
|
||||
|
||||
border: false,
|
||||
title: _('Bandwidth'),
|
||||
labelWidth: 10,
|
||||
|
||||
initComponent: function() {
|
||||
Deluge.preferences.Bandwidth.superclass.initComponent.call(this);
|
||||
|
||||
this.callParent(arguments);
|
||||
|
||||
var om = deluge.preferences.getOptionsManager();
|
||||
var fieldset = this.add({
|
||||
xtype: 'fieldset',
|
||||
@ -105,7 +100,7 @@ Deluge.preferences.Bandwidth = Ext.extend(Ext.form.FormPanel, {
|
||||
value: -1,
|
||||
decimalPrecision: 0
|
||||
}));
|
||||
|
||||
|
||||
fieldset = this.add({
|
||||
xtype: 'fieldset',
|
||||
border: false,
|
||||
@ -128,7 +123,7 @@ Deluge.preferences.Bandwidth = Ext.extend(Ext.form.FormPanel, {
|
||||
labelSeparator: '',
|
||||
boxLabel: _('Rate limit IP overhead')
|
||||
}));
|
||||
|
||||
|
||||
fieldset = this.add({
|
||||
xtype: 'fieldset',
|
||||
border: false,
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
/*!
|
||||
* Deluge.preferences.CachePage.js
|
||||
*
|
||||
* Copyright (c) Damien Churchill 2009-2010 <damoxc@gmail.com>
|
||||
*
|
||||
* Copyright (c) Damien Churchill 2009-2011 <damoxc@gmail.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@ -29,23 +29,22 @@
|
||||
* this exception statement from your version. If you delete this exception
|
||||
* statement from all source files in the program, then also delete it here.
|
||||
*/
|
||||
Ext.namespace('Deluge.preferences');
|
||||
|
||||
/**
|
||||
* @class Deluge.preferences.Cache
|
||||
* @extends Ext.form.FormPanel
|
||||
*/
|
||||
Deluge.preferences.Cache = Ext.extend(Ext.form.FormPanel, {
|
||||
Ext.define('Deluge.preferences.Cache', {
|
||||
extend: 'Ext.form.Panel',
|
||||
|
||||
border: false,
|
||||
title: _('Cache'),
|
||||
layout: 'form',
|
||||
|
||||
|
||||
initComponent: function() {
|
||||
Deluge.preferences.Cache.superclass.initComponent.call(this);
|
||||
this.callParent(arguments);
|
||||
|
||||
var om = deluge.preferences.getOptionsManager();
|
||||
|
||||
|
||||
var fieldset = this.add({
|
||||
xtype: 'fieldset',
|
||||
border: false,
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
/*!
|
||||
* Deluge.preferences.DaemonPage.js
|
||||
*
|
||||
* Copyright (c) Damien Churchill 2009-2010 <damoxc@gmail.com>
|
||||
*
|
||||
* Copyright (c) Damien Churchill 2009-2011 <damoxc@gmail.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@ -29,23 +29,22 @@
|
||||
* this exception statement from your version. If you delete this exception
|
||||
* statement from all source files in the program, then also delete it here.
|
||||
*/
|
||||
Ext.namespace('Deluge.preferences');
|
||||
|
||||
/**
|
||||
* @class Deluge.preferences.Daemon
|
||||
* @extends Ext.form.FormPanel
|
||||
*/
|
||||
Deluge.preferences.Daemon = Ext.extend(Ext.form.FormPanel, {
|
||||
Ext.define('Deluge.preferences.Daemon', {
|
||||
extend: 'Ext.form.Panel',
|
||||
|
||||
border: false,
|
||||
title: _('Daemon'),
|
||||
layout: 'form',
|
||||
|
||||
|
||||
initComponent: function() {
|
||||
Deluge.preferences.Daemon.superclass.initComponent.call(this);
|
||||
this.callParent(arguments);
|
||||
|
||||
var om = deluge.preferences.getOptionsManager();
|
||||
|
||||
|
||||
var fieldset = this.add({
|
||||
xtype: 'fieldset',
|
||||
border: false,
|
||||
@ -61,7 +60,7 @@ Deluge.preferences.Daemon = Ext.extend(Ext.form.FormPanel, {
|
||||
minValue: -1,
|
||||
maxValue: 99999
|
||||
}));
|
||||
|
||||
|
||||
fieldset = this.add({
|
||||
xtype: 'fieldset',
|
||||
border: false,
|
||||
@ -77,7 +76,7 @@ Deluge.preferences.Daemon = Ext.extend(Ext.form.FormPanel, {
|
||||
boxLabel: _('Allow Remote Connections'),
|
||||
name: 'allow_remote'
|
||||
}));
|
||||
|
||||
|
||||
fieldset = this.add({
|
||||
xtype: 'fieldset',
|
||||
border: false,
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
/*!
|
||||
* Deluge.preferences.DownloadsPage.js
|
||||
*
|
||||
* Copyright (c) Damien Churchill 2009-2010 <damoxc@gmail.com>
|
||||
*
|
||||
* Copyright (c) Damien Churchill 2009-2011 <damoxc@gmail.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@ -29,26 +29,21 @@
|
||||
* this exception statement from your version. If you delete this exception
|
||||
* statement from all source files in the program, then also delete it here.
|
||||
*/
|
||||
Ext.namespace('Deluge.preferences');
|
||||
|
||||
/**
|
||||
* @class Deluge.preferences.Downloads
|
||||
* @extends Ext.form.FormPanel
|
||||
*/
|
||||
Deluge.preferences.Downloads = Ext.extend(Ext.FormPanel, {
|
||||
constructor: function(config) {
|
||||
config = Ext.apply({
|
||||
border: false,
|
||||
title: _('Downloads'),
|
||||
layout: 'form',
|
||||
autoHeight: true,
|
||||
width: 320
|
||||
}, config);
|
||||
Deluge.preferences.Downloads.superclass.constructor.call(this, config);
|
||||
},
|
||||
Ext.define('Deluge.preferences.Downloads', {
|
||||
extend: 'Ext.form.Panel',
|
||||
border: false,
|
||||
title: _('Downloads'),
|
||||
layout: 'anchor',
|
||||
autoHeight: true,
|
||||
width: 320,
|
||||
|
||||
initComponent: function() {
|
||||
Deluge.preferences.Downloads.superclass.initComponent.call(this);
|
||||
this.callParent(arguments);
|
||||
|
||||
var optMan = deluge.preferences.getOptionsManager();
|
||||
var fieldset = this.add({
|
||||
@ -93,7 +88,7 @@ Deluge.preferences.Downloads = Ext.extend(Ext.FormPanel, {
|
||||
});
|
||||
optMan.bind('autoadd_enable', field.toggle);
|
||||
optMan.bind('autoadd_location', field.input);
|
||||
|
||||
|
||||
fieldset = this.add({
|
||||
xtype: 'fieldset',
|
||||
border: false,
|
||||
@ -122,7 +117,7 @@ Deluge.preferences.Downloads = Ext.extend(Ext.FormPanel, {
|
||||
inputValue: true
|
||||
}]
|
||||
}));
|
||||
|
||||
|
||||
fieldset = this.add({
|
||||
xtype: 'fieldset',
|
||||
border: false,
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
/*!
|
||||
* Deluge.preferences.EncryptionPage.js
|
||||
*
|
||||
*
|
||||
* Copyright (c) Damien Churchill 2009-2010 <damoxc@gmail.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
@ -39,12 +39,12 @@ Deluge.preferences.Encryption = Ext.extend(Ext.form.FormPanel, {
|
||||
|
||||
border: false,
|
||||
title: _('Encryption'),
|
||||
|
||||
|
||||
initComponent: function() {
|
||||
Deluge.preferences.Encryption.superclass.initComponent.call(this);
|
||||
|
||||
var optMan = deluge.preferences.getOptionsManager();
|
||||
|
||||
|
||||
var fieldset = this.add({
|
||||
xtype: 'fieldset',
|
||||
border: false,
|
||||
@ -57,7 +57,7 @@ Deluge.preferences.Encryption = Ext.extend(Ext.form.FormPanel, {
|
||||
fieldLabel: _('Inbound'),
|
||||
mode: 'local',
|
||||
width: 150,
|
||||
store: new Ext.data.ArrayStore({
|
||||
store: Ext.create('Ext.data.Store', {
|
||||
fields: ['id', 'text'],
|
||||
data: [
|
||||
[0, _('Forced')],
|
||||
@ -74,7 +74,7 @@ Deluge.preferences.Encryption = Ext.extend(Ext.form.FormPanel, {
|
||||
fieldLabel: _('Outbound'),
|
||||
mode: 'local',
|
||||
width: 150,
|
||||
store: new Ext.data.SimpleStore({
|
||||
store: Ext.create('Ext.data.Store', {
|
||||
fields: ['id', 'text'],
|
||||
data: [
|
||||
[0, _('Forced')],
|
||||
@ -91,7 +91,7 @@ Deluge.preferences.Encryption = Ext.extend(Ext.form.FormPanel, {
|
||||
fieldLabel: _('Level'),
|
||||
mode: 'local',
|
||||
width: 150,
|
||||
store: new Ext.data.SimpleStore({
|
||||
store: Ext.create('Ext.data.Store', {
|
||||
fields: ['id', 'text'],
|
||||
data: [
|
||||
[0, _('Handshake')],
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
/*!
|
||||
* Deluge.preferences.InterfacePage.js
|
||||
*
|
||||
* Copyright (c) Damien Churchill 2009-2010 <damoxc@gmail.com>
|
||||
*
|
||||
* Copyright (c) Damien Churchill 2009-2011 <damoxc@gmail.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@ -29,24 +29,23 @@
|
||||
* this exception statement from your version. If you delete this exception
|
||||
* statement from all source files in the program, then also delete it here.
|
||||
*/
|
||||
Ext.namespace('Deluge.preferences');
|
||||
|
||||
/**
|
||||
* @class Deluge.preferences.Interface
|
||||
* @extends Ext.form.FormPanel
|
||||
*/
|
||||
Deluge.preferences.Interface = Ext.extend(Ext.form.FormPanel, {
|
||||
Ext.define('Deluge.preferences.Interface', {
|
||||
extend: 'Ext.form.Panel',
|
||||
|
||||
border: false,
|
||||
title: _('Interface'),
|
||||
layout: 'form',
|
||||
|
||||
|
||||
initComponent: function() {
|
||||
Deluge.preferences.Interface.superclass.initComponent.call(this);
|
||||
|
||||
this.callParent(arguments);
|
||||
|
||||
var om = this.optionsManager = new Deluge.OptionsManager();
|
||||
this.on('show', this.onPageShow, this);
|
||||
|
||||
|
||||
var fieldset = this.add({
|
||||
xtype: 'fieldset',
|
||||
border: false,
|
||||
@ -77,7 +76,7 @@ Deluge.preferences.Interface = Ext.extend(Ext.form.FormPanel, {
|
||||
labelSeparator: '',
|
||||
boxLabel: _('Allow the use of multiple filters at once')
|
||||
}));
|
||||
|
||||
|
||||
fieldset = this.add({
|
||||
xtype: 'fieldset',
|
||||
border: false,
|
||||
@ -91,7 +90,7 @@ Deluge.preferences.Interface = Ext.extend(Ext.form.FormPanel, {
|
||||
inputType: 'password'
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
this.oldPassword = fieldset.add({
|
||||
name: 'old_password',
|
||||
fieldLabel: _('Old Password')
|
||||
@ -104,7 +103,7 @@ Deluge.preferences.Interface = Ext.extend(Ext.form.FormPanel, {
|
||||
name: 'confirm_password',
|
||||
fieldLabel: _('Confirm Password')
|
||||
});
|
||||
|
||||
|
||||
var panel = fieldset.add({
|
||||
xtype: 'panel',
|
||||
autoHeight: true,
|
||||
@ -122,7 +121,7 @@ Deluge.preferences.Interface = Ext.extend(Ext.form.FormPanel, {
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
fieldset = this.add({
|
||||
xtype: 'fieldset',
|
||||
border: false,
|
||||
@ -173,7 +172,7 @@ Deluge.preferences.Interface = Ext.extend(Ext.form.FormPanel, {
|
||||
fieldLabel: _('Certificate')
|
||||
}));
|
||||
},
|
||||
|
||||
|
||||
onApply: function() {
|
||||
var changed = this.optionsManager.getDirty();
|
||||
if (!Ext.isObjectEmpty(changed)) {
|
||||
@ -187,11 +186,11 @@ Deluge.preferences.Interface = Ext.extend(Ext.form.FormPanel, {
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
onGotConfig: function(config) {
|
||||
this.optionsManager.set(config);
|
||||
},
|
||||
|
||||
|
||||
onPasswordChange: function() {
|
||||
var newPassword = this.newPassword.getValue();
|
||||
if (newPassword != this.confirmPassword.getValue()) {
|
||||
@ -205,7 +204,7 @@ Deluge.preferences.Interface = Ext.extend(Ext.form.FormPanel, {
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
var oldPassword = this.oldPassword.getValue();
|
||||
deluge.client.auth.change_password(oldPassword, newPassword, {
|
||||
success: function(result) {
|
||||
@ -236,18 +235,18 @@ Deluge.preferences.Interface = Ext.extend(Ext.form.FormPanel, {
|
||||
scope: this
|
||||
});
|
||||
},
|
||||
|
||||
|
||||
onSetConfig: function() {
|
||||
this.optionsManager.commit();
|
||||
},
|
||||
|
||||
|
||||
onPageShow: function() {
|
||||
deluge.client.web.get_config({
|
||||
success: this.onGotConfig,
|
||||
scope: this
|
||||
})
|
||||
},
|
||||
|
||||
|
||||
onSSLCheck: function(e, checked) {
|
||||
this.pkeyField.setDisabled(!checked);
|
||||
this.certField.setDisabled(!checked);
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
/*!
|
||||
* Deluge.preferences.NetworkPage.js
|
||||
*
|
||||
* Copyright (c) Damien Churchill 2009-2010 <damoxc@gmail.com>
|
||||
*
|
||||
* Copyright (c) Damien Churchill 2009-2011 <damoxc@gmail.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@ -29,22 +29,21 @@
|
||||
* this exception statement from your version. If you delete this exception
|
||||
* statement from all source files in the program, then also delete it here.
|
||||
*/
|
||||
Ext.namespace('Deluge.preferences');
|
||||
|
||||
/**
|
||||
* @class Deluge.preferences.Network
|
||||
* @extends Ext.form.FormPanel
|
||||
*/
|
||||
Deluge.preferences.Network = Ext.extend(Ext.form.FormPanel, {
|
||||
|
||||
Ext.define('Deluge.preferences.Network', {
|
||||
extend: 'Ext.form.Panel',
|
||||
|
||||
border: false,
|
||||
layout: 'form',
|
||||
title: _('Network'),
|
||||
|
||||
initComponent: function() {
|
||||
Deluge.preferences.Network.superclass.initComponent.call(this);
|
||||
this.callParent(arguments);
|
||||
var optMan = deluge.preferences.getOptionsManager();
|
||||
|
||||
|
||||
var fieldset = this.add({
|
||||
xtype: 'fieldset',
|
||||
border: false,
|
||||
@ -97,7 +96,7 @@ Deluge.preferences.Network = Ext.extend(Ext.form.FormPanel, {
|
||||
}]
|
||||
});
|
||||
optMan.bind('listen_ports', this.listenPorts);
|
||||
|
||||
|
||||
fieldset = this.add({
|
||||
xtype: 'fieldset',
|
||||
border: false,
|
||||
@ -150,7 +149,7 @@ Deluge.preferences.Network = Ext.extend(Ext.form.FormPanel, {
|
||||
}]
|
||||
});
|
||||
optMan.bind('outgoing_ports', this.outgoingPorts);
|
||||
|
||||
|
||||
fieldset = this.add({
|
||||
xtype: 'fieldset',
|
||||
border: false,
|
||||
@ -166,7 +165,7 @@ Deluge.preferences.Network = Ext.extend(Ext.form.FormPanel, {
|
||||
labelSeparator: '',
|
||||
width: 200
|
||||
}));
|
||||
|
||||
|
||||
fieldset = this.add({
|
||||
xtype: 'fieldset',
|
||||
border: false,
|
||||
@ -181,7 +180,7 @@ Deluge.preferences.Network = Ext.extend(Ext.form.FormPanel, {
|
||||
fieldLabel: _('Peer TOS Byte'),
|
||||
width: 80
|
||||
}));
|
||||
|
||||
|
||||
fieldset = this.add({
|
||||
xtype: 'fieldset',
|
||||
border: false,
|
||||
@ -190,7 +189,7 @@ Deluge.preferences.Network = Ext.extend(Ext.form.FormPanel, {
|
||||
layout: 'table',
|
||||
layoutConfig: {
|
||||
columns: 3
|
||||
},
|
||||
},
|
||||
defaultType: 'checkbox'
|
||||
});
|
||||
optMan.bind('upnp', fieldset.add({
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
/*!
|
||||
* Deluge.preferences.OtherPage.js
|
||||
*
|
||||
* Copyright (c) Damien Churchill 2009-2010 <damoxc@gmail.com>
|
||||
*
|
||||
* Copyright (c) Damien Churchill 2009-2011 <damoxc@gmail.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@ -29,27 +29,21 @@
|
||||
* this exception statement from your version. If you delete this exception
|
||||
* statement from all source files in the program, then also delete it here.
|
||||
*/
|
||||
Ext.namespace('Deluge.preferences');
|
||||
|
||||
/**
|
||||
* @class Deluge.preferences.Other
|
||||
* @extends Ext.form.FormPanel
|
||||
*/
|
||||
Deluge.preferences.Other = Ext.extend(Ext.form.FormPanel, {
|
||||
constructor: function(config) {
|
||||
config = Ext.apply({
|
||||
border: false,
|
||||
title: _('Other'),
|
||||
layout: 'form'
|
||||
}, config);
|
||||
Deluge.preferences.Other.superclass.constructor.call(this, config);
|
||||
},
|
||||
|
||||
Ext.define('Deluge.preferences.Other', {
|
||||
extend: 'Ext.form.Panel',
|
||||
border: false,
|
||||
title: _('Other'),
|
||||
|
||||
initComponent: function() {
|
||||
Deluge.preferences.Other.superclass.initComponent.call(this);
|
||||
|
||||
this.callParent(arguments);
|
||||
|
||||
var optMan = deluge.preferences.getOptionsManager();
|
||||
|
||||
|
||||
var fieldset = this.add({
|
||||
xtype: 'fieldset',
|
||||
border: false,
|
||||
@ -65,7 +59,7 @@ Deluge.preferences.Other = Ext.extend(Ext.form.FormPanel, {
|
||||
name: 'new_release_check',
|
||||
boxLabel: _('Be alerted about new releases')
|
||||
}));
|
||||
|
||||
|
||||
fieldset = this.add({
|
||||
xtype: 'fieldset',
|
||||
border: false,
|
||||
@ -90,7 +84,7 @@ Deluge.preferences.Other = Ext.extend(Ext.form.FormPanel, {
|
||||
boxLabel: _('Yes, please send anonymous statistics'),
|
||||
name: 'send_info'
|
||||
}));
|
||||
|
||||
|
||||
fieldset = this.add({
|
||||
xtype: 'fieldset',
|
||||
border: false,
|
||||
|
||||
@ -29,7 +29,6 @@
|
||||
* this exception statement from your version. If you delete this exception
|
||||
* statement from all source files in the program, then also delete it here.
|
||||
*/
|
||||
Ext.namespace('Deluge.preferences');
|
||||
|
||||
/**
|
||||
* @class Deluge.preferences.Plugins
|
||||
@ -43,7 +42,7 @@ Deluge.preferences.Plugins = Ext.extend(Ext.Panel, {
|
||||
height: 400,
|
||||
cls: 'x-deluge-plugins',
|
||||
|
||||
pluginTemplate: new Ext.Template(
|
||||
pluginTemplate: Ext.create('Ext.Template',
|
||||
'<dl class="singleline">' +
|
||||
'<dt>Author:</dt><dd>{author}</dd>' +
|
||||
'<dt>Version:</dt><dd>{version}</dd>' +
|
||||
@ -54,7 +53,8 @@ Deluge.preferences.Plugins = Ext.extend(Ext.Panel, {
|
||||
),
|
||||
|
||||
initComponent: function() {
|
||||
Deluge.preferences.Plugins.superclass.initComponent.call(this);
|
||||
console.log('Plugins preferences page created');
|
||||
this.callParent(arguments);
|
||||
this.defaultValues = {
|
||||
'version': '',
|
||||
'email': '',
|
||||
@ -68,20 +68,23 @@ Deluge.preferences.Plugins = Ext.extend(Ext.Panel, {
|
||||
return '<div class="x-grid3-check-col'+(v?'-on':'')+'"> </div>';
|
||||
}
|
||||
|
||||
this.list = this.add({
|
||||
xtype: 'listview',
|
||||
store: new Ext.data.ArrayStore({
|
||||
fields: [
|
||||
{name: 'enabled', mapping: 0},
|
||||
{name: 'plugin', mapping: 1}
|
||||
]
|
||||
|
||||
|
||||
this.grid = this.add({
|
||||
xtype: 'grid',
|
||||
store: Ext.create('Ext.data.Store', {
|
||||
model: 'Deluge.data.Plugin',
|
||||
proxy: {
|
||||
type: 'memory'
|
||||
}
|
||||
}),
|
||||
singleSelect: true,
|
||||
columns: [{
|
||||
id: 'enabled',
|
||||
header: _('Enabled'),
|
||||
width: .2,
|
||||
sortable: true,
|
||||
tpl: new Ext.XTemplate('{enabled:this.getCheckbox}', {
|
||||
tpl: Ext.create('Ext.XTemplate', '{enabled:this.getCheckbox}', {
|
||||
getCheckbox: function(v) {
|
||||
return '<div class="x-grid3-check-col'+(v?'-on':'')+'" rel="chkbox"> </div>';
|
||||
}
|
||||
@ -94,8 +97,6 @@ Deluge.preferences.Plugins = Ext.extend(Ext.Panel, {
|
||||
sortable: true,
|
||||
dataIndex: 'plugin'
|
||||
}],
|
||||
singleSelect: true,
|
||||
autoExpandColumn: 'plugin',
|
||||
listeners: {
|
||||
selectionchange: {fn: this.onPluginSelect, scope: this}
|
||||
}
|
||||
@ -105,8 +106,8 @@ Deluge.preferences.Plugins = Ext.extend(Ext.Panel, {
|
||||
region: 'center',
|
||||
autoScroll: true,
|
||||
margins: '5 5 5 5',
|
||||
items: [this.list],
|
||||
bbar: new Ext.Toolbar({
|
||||
items: [this.grid],
|
||||
bbar: {
|
||||
items: [{
|
||||
cls: 'x-btn-text-icon',
|
||||
iconCls: 'x-deluge-install-plugin',
|
||||
@ -120,7 +121,7 @@ Deluge.preferences.Plugins = Ext.extend(Ext.Panel, {
|
||||
handler: this.onFindMorePlugins,
|
||||
scope: this
|
||||
}]
|
||||
})
|
||||
}
|
||||
});
|
||||
|
||||
var pp = this.pluginInfo = this.add({
|
||||
@ -147,7 +148,7 @@ Deluge.preferences.Plugins = Ext.extend(Ext.Panel, {
|
||||
});
|
||||
|
||||
this.pluginInfo.on('render', this.onPluginInfoRender, this);
|
||||
this.list.on('click', this.onNodeClick, this);
|
||||
this.grid.on('click', this.onNodeClick, this);
|
||||
deluge.preferences.on('show', this.onPreferencesShow, this);
|
||||
deluge.events.on('PluginDisabledEvent', this.onPluginDisabled, this);
|
||||
deluge.events.on('PluginEnabledEvent', this.onPluginEnabled, this);
|
||||
@ -187,7 +188,7 @@ Deluge.preferences.Plugins = Ext.extend(Ext.Panel, {
|
||||
},
|
||||
|
||||
onNodeClick: function(dv, index, node, e) {
|
||||
var el = new Ext.Element(e.target);
|
||||
var el = Ext.fly(e.target);
|
||||
if (el.getAttribute('rel') != 'chkbox') return;
|
||||
|
||||
var r = dv.getStore().getAt(index);
|
||||
@ -225,7 +226,7 @@ Deluge.preferences.Plugins = Ext.extend(Ext.Panel, {
|
||||
|
||||
onInstallPluginWindow: function() {
|
||||
if (!this.installWindow) {
|
||||
this.installWindow = new Deluge.preferences.InstallPluginWindow();
|
||||
this.installWindow = Ext.create('Deluge.preferences.InstallPluginWindow');
|
||||
this.installWindow.on('pluginadded', this.onPluginInstall, this);
|
||||
}
|
||||
this.installWindow.show();
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
/*!
|
||||
* Deluge.preferences.PreferencesWindow.js
|
||||
*
|
||||
* Copyright (c) Damien Churchill 2009-2010 <damoxc@gmail.com>
|
||||
*
|
||||
* Copyright (c) Damien Churchill 2009-2011 <damoxc@gmail.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@ -29,15 +29,13 @@
|
||||
* this exception statement from your version. If you delete this exception
|
||||
* statement from all source files in the program, then also delete it here.
|
||||
*/
|
||||
Ext.namespace('Deluge.preferences');
|
||||
|
||||
PreferencesRecord = Ext.data.Record.create([{name:'name', type:'string'}]);
|
||||
|
||||
/**
|
||||
* @class Deluge.preferences.PreferencesWindow
|
||||
* @extends Ext.Window
|
||||
*/
|
||||
Deluge.preferences.PreferencesWindow = Ext.extend(Ext.Window, {
|
||||
Ext.define('Deluge.preferences.PreferencesWindow', {
|
||||
extend: 'Ext.Window',
|
||||
|
||||
/**
|
||||
* @property {String} currentPage The currently selected page.
|
||||
@ -59,14 +57,16 @@ Deluge.preferences.PreferencesWindow = Ext.extend(Ext.Window, {
|
||||
pages: {},
|
||||
|
||||
initComponent: function() {
|
||||
Deluge.preferences.PreferencesWindow.superclass.initComponent.call(this);
|
||||
this.callParent(arguments);
|
||||
|
||||
this.list = new Ext.list.ListView({
|
||||
store: new Ext.data.Store(),
|
||||
this.list = Ext.create('Ext.list.ListView', {
|
||||
store: Ext.create('Ext.data.Store', {
|
||||
model: 'Deluge.data.Preferences'
|
||||
}),
|
||||
columns: [{
|
||||
id: 'name',
|
||||
renderer: fplain,
|
||||
dataIndex: 'name'
|
||||
dataIndex: 'name',
|
||||
flex: 1
|
||||
}],
|
||||
singleSelect: true,
|
||||
listeners: {
|
||||
@ -75,7 +75,6 @@ Deluge.preferences.PreferencesWindow = Ext.extend(Ext.Window, {
|
||||
}
|
||||
},
|
||||
hideHeaders: true,
|
||||
autoExpandColumn: 'name',
|
||||
deferredRender: false,
|
||||
autoScroll: true,
|
||||
collapsible: true
|
||||
@ -103,32 +102,32 @@ Deluge.preferences.PreferencesWindow = Ext.extend(Ext.Window, {
|
||||
cmargins: '5 5 5 5'
|
||||
});
|
||||
|
||||
this.addButton(_('Close'), this.onClose, this);
|
||||
this.addButton(_('Apply'), this.onApply, this);
|
||||
this.addButton(_('Ok'), this.onOk, this);
|
||||
|
||||
this.optionsManager = new Deluge.OptionsManager();
|
||||
this.on('afterrender', this.onAfterRender, this);
|
||||
this.on('show', this.onShow, this);
|
||||
//this.addButton(_('Close'), this.onClose, this);
|
||||
//this.addButton(_('Apply'), this.onApply, this);
|
||||
//this.addButton(_('Ok'), this.onOk, this);
|
||||
|
||||
this.optionsManager = Ext.create('Deluge.OptionsManager');
|
||||
this.on('afterrender', this.onAfterRender, this);
|
||||
|
||||
this.afterMethod('onShow', this.afterShown, this);
|
||||
this.initPages();
|
||||
},
|
||||
|
||||
initPages: function() {
|
||||
deluge.preferences = this;
|
||||
this.addPage(new Deluge.preferences.Downloads());
|
||||
this.addPage(new Deluge.preferences.Network());
|
||||
this.addPage(new Deluge.preferences.Encryption());
|
||||
this.addPage(new Deluge.preferences.Bandwidth());
|
||||
this.addPage(new Deluge.preferences.Interface());
|
||||
this.addPage(new Deluge.preferences.Other());
|
||||
this.addPage(new Deluge.preferences.Daemon());
|
||||
this.addPage(new Deluge.preferences.Queue());
|
||||
this.addPage(new Deluge.preferences.Proxy());
|
||||
this.addPage(new Deluge.preferences.Cache());
|
||||
this.addPage(new Deluge.preferences.Plugins());
|
||||
this.addPage(Ext.create('Deluge.preferences.Downloads'));
|
||||
//this.addPage(Ext.create('Deluge.preferences.Network'));
|
||||
this.addPage(Ext.create('Deluge.preferences.Encryption'));
|
||||
this.addPage(Ext.create('Deluge.preferences.Bandwidth'));
|
||||
this.addPage(Ext.create('Deluge.preferences.Interface'));
|
||||
this.addPage(Ext.create('Deluge.preferences.Other'));
|
||||
this.addPage(Ext.create('Deluge.preferences.Daemon'));
|
||||
this.addPage(Ext.create('Deluge.preferences.Queue'));
|
||||
this.addPage(Ext.create('Deluge.preferences.Proxy'));
|
||||
this.addPage(Ext.create('Deluge.preferences.Cache'));
|
||||
this.addPage(Ext.create('Deluge.preferences.Plugins'));
|
||||
},
|
||||
|
||||
|
||||
onApply: function(e) {
|
||||
var changed = this.optionsManager.getDirty();
|
||||
if (!Ext.isObjectEmpty(changed)) {
|
||||
@ -137,13 +136,13 @@ Deluge.preferences.PreferencesWindow = Ext.extend(Ext.Window, {
|
||||
scope: this
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
for (var page in this.pages) {
|
||||
if (this.pages[page].onApply) this.pages[page].onApply();
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Return the options manager for the preferences window.
|
||||
* @returns {Deluge.OptionsManager} the options manager
|
||||
@ -151,7 +150,7 @@ Deluge.preferences.PreferencesWindow = Ext.extend(Ext.Window, {
|
||||
getOptionsManager: function() {
|
||||
return this.optionsManager;
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Adds a page to the preferences window.
|
||||
* @param {Mixed} page
|
||||
@ -159,14 +158,14 @@ Deluge.preferences.PreferencesWindow = Ext.extend(Ext.Window, {
|
||||
addPage: function(page) {
|
||||
var store = this.list.getStore();
|
||||
var name = page.title;
|
||||
store.add([new PreferencesRecord({name: name})]);
|
||||
store.add({name: name});
|
||||
page['bodyStyle'] = 'padding: 5px';
|
||||
page.preferences = this;
|
||||
this.pages[name] = this.configPanel.add(page);
|
||||
this.pages[name].index = -1;
|
||||
return this.pages[name];
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Removes a preferences page from the window.
|
||||
* @param {mixed} name
|
||||
@ -179,12 +178,12 @@ Deluge.preferences.PreferencesWindow = Ext.extend(Ext.Window, {
|
||||
delete this.pages[page.title];
|
||||
},
|
||||
|
||||
/**
|
||||
/**
|
||||
* Select which preferences page is displayed.
|
||||
* @param {String} page The page name to change to
|
||||
*/
|
||||
selectPage: function(page) {
|
||||
if (this.pages[page].index < 0) {
|
||||
if (this.pages[page].index < 0) {
|
||||
this.pages[page].index = this.configPanel.items.indexOf(this.pages[page]);
|
||||
}
|
||||
this.list.select(this.pages[page].index);
|
||||
@ -192,24 +191,24 @@ Deluge.preferences.PreferencesWindow = Ext.extend(Ext.Window, {
|
||||
|
||||
// private
|
||||
doSelectPage: function(page) {
|
||||
if (this.pages[page].index < 0) {
|
||||
if (this.pages[page].index < 0) {
|
||||
this.pages[page].index = this.configPanel.items.indexOf(this.pages[page]);
|
||||
}
|
||||
this.configPanel.getLayout().setActiveItem(this.pages[page].index);
|
||||
this.currentPage = page;
|
||||
},
|
||||
|
||||
|
||||
// private
|
||||
onGotConfig: function(config) {
|
||||
this.getOptionsManager().set(config);
|
||||
},
|
||||
|
||||
|
||||
// private
|
||||
onPageSelect: function(list, selections) {
|
||||
var r = list.getRecord(selections[0]);
|
||||
this.doSelectPage(r.get('name'));
|
||||
},
|
||||
|
||||
|
||||
// private
|
||||
onSetConfig: function() {
|
||||
this.getOptionsManager().commit();
|
||||
@ -222,9 +221,9 @@ Deluge.preferences.PreferencesWindow = Ext.extend(Ext.Window, {
|
||||
}
|
||||
this.configPanel.getLayout().setActiveItem(0);
|
||||
},
|
||||
|
||||
|
||||
// private
|
||||
onShow: function() {
|
||||
afterShown: function() {
|
||||
if (!deluge.client.core) return;
|
||||
deluge.client.core.get_config({
|
||||
success: this.onGotConfig,
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
/*!
|
||||
* Deluge.preferences.ProxyField.js
|
||||
*
|
||||
*
|
||||
* Copyright (c) Damien Churchill 2009-2010 <damoxc@gmail.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
@ -49,7 +49,7 @@ Deluge.preferences.ProxyField = Ext.extend(Ext.form.FieldSet, {
|
||||
name: 'proxytype',
|
||||
mode: 'local',
|
||||
width: 150,
|
||||
store: new Ext.data.ArrayStore({
|
||||
store: Ext.create('Ext.data.Store', {
|
||||
fields: ['id', 'text'],
|
||||
data: [
|
||||
[0, _('None')],
|
||||
@ -58,8 +58,8 @@ Deluge.preferences.ProxyField = Ext.extend(Ext.form.FieldSet, {
|
||||
[3, _('Socksv5 with Auth')],
|
||||
[4, _('HTTP')],
|
||||
[5, _('HTTP with Auth')]
|
||||
]
|
||||
}),
|
||||
]
|
||||
}),
|
||||
editable: false,
|
||||
triggerAction: 'all',
|
||||
valueField: 'id',
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
/*!
|
||||
* Deluge.preferences.ProxyPage.js
|
||||
*
|
||||
* Copyright (c) Damien Churchill 2009-2010 <damoxc@gmail.com>
|
||||
*
|
||||
* Copyright (c) Damien Churchill 2009-2011 <damoxc@gmail.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@ -29,51 +29,46 @@
|
||||
* this exception statement from your version. If you delete this exception
|
||||
* statement from all source files in the program, then also delete it here.
|
||||
*/
|
||||
Ext.namespace('Deluge.preferences');
|
||||
|
||||
/**
|
||||
* @class Deluge.preferences.Proxy
|
||||
* @extends Ext.form.FormPanel
|
||||
*/
|
||||
Deluge.preferences.Proxy = Ext.extend(Ext.form.FormPanel, {
|
||||
constructor: function(config) {
|
||||
config = Ext.apply({
|
||||
border: false,
|
||||
title: _('Proxy'),
|
||||
layout: 'form'
|
||||
}, config);
|
||||
Deluge.preferences.Proxy.superclass.constructor.call(this, config);
|
||||
},
|
||||
|
||||
Ext.define('Deluge.preferences.Proxy', {
|
||||
extend: 'Ext.form.Panel',
|
||||
|
||||
border: false,
|
||||
title: _('Proxy'),
|
||||
|
||||
initComponent: function() {
|
||||
Deluge.preferences.Proxy.superclass.initComponent.call(this);
|
||||
this.peer = this.add(new Deluge.preferences.ProxyField({
|
||||
this.callParent(arguments);
|
||||
this.peer = this.add(Ext.create('Deluge.preferences.ProxyField', {
|
||||
title: _('Peer'),
|
||||
name: 'peer'
|
||||
}));
|
||||
this.peer.on('change', this.onProxyChange, this);
|
||||
|
||||
this.web_seed = this.add(new Deluge.preferences.ProxyField({
|
||||
|
||||
this.web_seed = this.add(Ext.create('Deluge.preferences.ProxyField',{
|
||||
title: _('Web Seed'),
|
||||
name: 'web_seed'
|
||||
}));
|
||||
this.web_seed.on('change', this.onProxyChange, this);
|
||||
|
||||
this.tracker = this.add(new Deluge.preferences.ProxyField({
|
||||
|
||||
this.tracker = this.add(Ext.create('Deluge.preferences.ProxyField', {
|
||||
title: _('Tracker'),
|
||||
name: 'tracker'
|
||||
}));
|
||||
this.tracker.on('change', this.onProxyChange, this);
|
||||
|
||||
this.dht = this.add(new Deluge.preferences.ProxyField({
|
||||
|
||||
this.dht = this.add(Ext.create('Deluge.preferences.ProxyField', {
|
||||
title: _('DHT'),
|
||||
name: 'dht'
|
||||
}));
|
||||
this.dht.on('change', this.onProxyChange, this);
|
||||
|
||||
|
||||
deluge.preferences.getOptionsManager().bind('proxies', this);
|
||||
},
|
||||
|
||||
|
||||
getValue: function() {
|
||||
return {
|
||||
'dht': this.dht.getValue(),
|
||||
@ -82,18 +77,18 @@ Deluge.preferences.Proxy = Ext.extend(Ext.form.FormPanel, {
|
||||
'web_seed': this.web_seed.getValue()
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
setValue: function(value) {
|
||||
for (var proxy in value) {
|
||||
this[proxy].setValue(value[proxy]);
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
onProxyChange: function(field, newValue, oldValue) {
|
||||
var newValues = this.getValue();
|
||||
var oldValues = Ext.apply({}, newValues);
|
||||
oldValues[field.getName()] = oldValue;
|
||||
|
||||
|
||||
this.fireEvent('change', this, newValues, oldValues);
|
||||
}
|
||||
});
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
/*!
|
||||
* Deluge.preferences.QueuePage.js
|
||||
*
|
||||
* Copyright (c) Damien Churchill 2009-2010 <damoxc@gmail.com>
|
||||
*
|
||||
* Copyright (c) Damien Churchill 2009-2011 <damoxc@gmail.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@ -29,23 +29,22 @@
|
||||
* this exception statement from your version. If you delete this exception
|
||||
* statement from all source files in the program, then also delete it here.
|
||||
*/
|
||||
Ext.namespace('Deluge.preferences');
|
||||
|
||||
/**
|
||||
* @class Deluge.preferences.Queue
|
||||
* @extends Ext.form.FormPanel
|
||||
*/
|
||||
Deluge.preferences.Queue = Ext.extend(Ext.form.FormPanel, {
|
||||
Ext.define('Deluge.preferences.Queue', {
|
||||
extend: 'Ext.form.Panel',
|
||||
|
||||
border: false,
|
||||
title: _('Queue'),
|
||||
layout: 'form',
|
||||
|
||||
|
||||
initComponent: function() {
|
||||
Deluge.preferences.Queue.superclass.initComponent.call(this);
|
||||
|
||||
this.callParent(arguments);
|
||||
|
||||
var om = deluge.preferences.getOptionsManager();
|
||||
|
||||
|
||||
var fieldset = this.add({
|
||||
xtype: 'fieldset',
|
||||
border: false,
|
||||
@ -62,7 +61,7 @@ Deluge.preferences.Queue = Ext.extend(Ext.form.FormPanel, {
|
||||
boxLabel: _('Queue new torrents to top'),
|
||||
name: 'queue_new_to_top'
|
||||
}));
|
||||
|
||||
|
||||
fieldset = this.add({
|
||||
xtype: 'fieldset',
|
||||
border: false,
|
||||
@ -113,7 +112,7 @@ Deluge.preferences.Queue = Ext.extend(Ext.form.FormPanel, {
|
||||
hideLabel: true,
|
||||
boxLabel: _('Prefer Seeding over Downloading')
|
||||
}));
|
||||
|
||||
|
||||
fieldset = this.add({
|
||||
xtype: 'fieldset',
|
||||
border: false,
|
||||
@ -154,17 +153,17 @@ Deluge.preferences.Queue = Ext.extend(Ext.form.FormPanel, {
|
||||
minValue: -1,
|
||||
maxValue: 99999
|
||||
}));
|
||||
|
||||
|
||||
fieldset = this.add({
|
||||
xtype: 'fieldset',
|
||||
border: false,
|
||||
autoHeight: true,
|
||||
|
||||
|
||||
layout: 'table',
|
||||
layoutConfig: {columns: 2},
|
||||
labelWidth: 0,
|
||||
defaultType: 'checkbox',
|
||||
|
||||
|
||||
defaults: {
|
||||
fieldLabel: '',
|
||||
labelSeparator: ''
|
||||
@ -176,7 +175,7 @@ Deluge.preferences.Queue = Ext.extend(Ext.form.FormPanel, {
|
||||
});
|
||||
this.stopAtRatio.on('check', this.onStopRatioCheck, this);
|
||||
om.bind('stop_seed_at_ratio', this.stopAtRatio);
|
||||
|
||||
|
||||
this.stopRatio = fieldset.add({
|
||||
xtype: 'spinnerfield',
|
||||
name: 'stop_seed_ratio',
|
||||
@ -191,7 +190,7 @@ Deluge.preferences.Queue = Ext.extend(Ext.form.FormPanel, {
|
||||
decimalPrecision: 2
|
||||
});
|
||||
om.bind('stop_seed_ratio', this.stopRatio);
|
||||
|
||||
|
||||
this.removeAtRatio = fieldset.add({
|
||||
name: 'remove_seed_at_ratio',
|
||||
ctCls: 'x-deluge-indent-checkbox',
|
||||
@ -201,7 +200,7 @@ Deluge.preferences.Queue = Ext.extend(Ext.form.FormPanel, {
|
||||
});
|
||||
om.bind('remove_seed_at_ratio', this.removeAtRatio);
|
||||
},
|
||||
|
||||
|
||||
onStopRatioCheck: function(e, checked) {
|
||||
this.stopRatio.setDisabled(!checked);
|
||||
this.removeAtRatio.setDisabled(!checked);
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
134730
deluge/ui/web/js/ext-all-dev.js
Normal file
134730
deluge/ui/web/js/ext-all-dev.js
Normal file
File diff suppressed because it is too large
Load Diff
File diff suppressed because one or more lines are too long
File diff suppressed because it is too large
Load Diff
File diff suppressed because one or more lines are too long
21851
deluge/ui/web/js/ext-debug.js
Normal file
21851
deluge/ui/web/js/ext-debug.js
Normal file
File diff suppressed because it is too large
Load Diff
22381
deluge/ui/web/js/ext-dev.js
Normal file
22381
deluge/ui/web/js/ext-dev.js
Normal file
File diff suppressed because it is too large
Load Diff
@ -1,38 +0,0 @@
|
||||
Ext.ux.JSLoader = function(options) {
|
||||
Ext.ux.JSLoader.scripts[++Ext.ux.JSLoader.index] = {
|
||||
url: options.url,
|
||||
success: true,
|
||||
jsLoadObj: null,
|
||||
options: options,
|
||||
onLoad: options.onLoad || Ext.emptyFn,
|
||||
onError: options.onError || Ext.ux.JSLoader.stdError,
|
||||
scope: options.scope || this
|
||||
};
|
||||
|
||||
Ext.Ajax.request({
|
||||
url: options.url,
|
||||
scriptIndex: Ext.ux.JSLoader.index,
|
||||
success: function(response, options) {
|
||||
var script = Ext.ux.JSLoader.scripts[options.scriptIndex];
|
||||
try {
|
||||
eval(response.responseText);
|
||||
} catch(e) {
|
||||
script.success = false;
|
||||
script.onError(script.options, e);
|
||||
}
|
||||
if (script.success) {
|
||||
script.onLoad.call(script.scope, script.options);
|
||||
}
|
||||
},
|
||||
failure: function(response, options) {
|
||||
var script = Ext.ux.JSLoader.scripts[options.scriptIndex];
|
||||
script.success = false;
|
||||
script.onError(script.options, response.status);
|
||||
}
|
||||
});
|
||||
}
|
||||
Ext.ux.JSLoader.index = 0;
|
||||
Ext.ux.JSLoader.scripts = [];
|
||||
Ext.ux.JSLoader.stdError = function(options, e) {
|
||||
window.alert('Error loading script:\n\n' + options.url + '\n\nstatus: ' + e);
|
||||
}
|
||||
@ -1,438 +0,0 @@
|
||||
/*!
|
||||
* Ext JS Library 3.1.0
|
||||
* Copyright(c) 2006-2009 Ext JS, LLC
|
||||
* licensing@extjs.com
|
||||
* http://www.extjs.com/license
|
||||
*/
|
||||
/**
|
||||
* @class Ext.ux.Spinner
|
||||
* @extends Ext.util.Observable
|
||||
* Creates a Spinner control utilized by Ext.ux.form.SpinnerField
|
||||
*/
|
||||
Ext.ux.Spinner = Ext.extend(Ext.util.Observable, {
|
||||
incrementValue: 1,
|
||||
alternateIncrementValue: 5,
|
||||
triggerClass: 'x-form-spinner-trigger',
|
||||
splitterClass: 'x-form-spinner-splitter',
|
||||
alternateKey: Ext.EventObject.shiftKey,
|
||||
defaultValue: 0,
|
||||
accelerate: false,
|
||||
|
||||
constructor: function(config){
|
||||
Ext.ux.Spinner.superclass.constructor.call(this, config);
|
||||
Ext.apply(this, config);
|
||||
this.mimicing = false;
|
||||
},
|
||||
|
||||
init: function(field){
|
||||
this.field = field;
|
||||
|
||||
field.afterMethod('onRender', this.doRender, this);
|
||||
field.afterMethod('onEnable', this.doEnable, this);
|
||||
field.afterMethod('onDisable', this.doDisable, this);
|
||||
field.afterMethod('afterRender', this.doAfterRender, this);
|
||||
field.afterMethod('onResize', this.doResize, this);
|
||||
field.afterMethod('onFocus', this.doFocus, this);
|
||||
field.beforeMethod('onDestroy', this.doDestroy, this);
|
||||
},
|
||||
|
||||
doRender: function(ct, position){
|
||||
var el = this.el = this.field.getEl();
|
||||
var f = this.field;
|
||||
|
||||
if (!f.wrap) {
|
||||
f.wrap = this.wrap = el.wrap({
|
||||
cls: "x-form-field-wrap"
|
||||
});
|
||||
}
|
||||
else {
|
||||
this.wrap = f.wrap.addClass('x-form-field-wrap');
|
||||
}
|
||||
|
||||
this.trigger = this.wrap.createChild({
|
||||
tag: "img",
|
||||
src: Ext.BLANK_IMAGE_URL,
|
||||
cls: "x-form-trigger " + this.triggerClass
|
||||
});
|
||||
|
||||
if (!f.width) {
|
||||
this.wrap.setWidth(el.getWidth() + this.trigger.getWidth());
|
||||
}
|
||||
|
||||
this.splitter = this.wrap.createChild({
|
||||
tag: 'div',
|
||||
cls: this.splitterClass,
|
||||
style: 'width:13px; height:2px;'
|
||||
});
|
||||
this.splitter.setRight((Ext.isIE) ? 1 : 2).setTop(10).show();
|
||||
|
||||
this.proxy = this.trigger.createProxy('', this.splitter, true);
|
||||
this.proxy.addClass("x-form-spinner-proxy");
|
||||
this.proxy.setStyle('left', '0px');
|
||||
this.proxy.setSize(14, 1);
|
||||
this.proxy.hide();
|
||||
this.dd = new Ext.dd.DDProxy(this.splitter.dom.id, "SpinnerDrag", {
|
||||
dragElId: this.proxy.id
|
||||
});
|
||||
|
||||
this.initTrigger();
|
||||
this.initSpinner();
|
||||
},
|
||||
|
||||
doAfterRender: function(){
|
||||
var y;
|
||||
if (Ext.isIE && this.el.getY() != (y = this.trigger.getY())) {
|
||||
this.el.position();
|
||||
this.el.setY(y);
|
||||
}
|
||||
},
|
||||
|
||||
doEnable: function(){
|
||||
if (this.wrap) {
|
||||
this.wrap.removeClass(this.field.disabledClass);
|
||||
}
|
||||
},
|
||||
|
||||
doDisable: function(){
|
||||
if (this.wrap) {
|
||||
this.wrap.addClass(this.field.disabledClass);
|
||||
this.el.removeClass(this.field.disabledClass);
|
||||
}
|
||||
},
|
||||
|
||||
doResize: function(w, h){
|
||||
if (typeof w == 'number') {
|
||||
this.el.setWidth(w - this.trigger.getWidth());
|
||||
}
|
||||
this.wrap.setWidth(this.el.getWidth() + this.trigger.getWidth());
|
||||
},
|
||||
|
||||
doFocus: function(){
|
||||
if (!this.mimicing) {
|
||||
this.wrap.addClass('x-trigger-wrap-focus');
|
||||
this.mimicing = true;
|
||||
Ext.get(Ext.isIE ? document.body : document).on("mousedown", this.mimicBlur, this, {
|
||||
delay: 10
|
||||
});
|
||||
this.el.on('keydown', this.checkTab, this);
|
||||
}
|
||||
},
|
||||
|
||||
// private
|
||||
checkTab: function(e){
|
||||
if (e.getKey() == e.TAB) {
|
||||
this.triggerBlur();
|
||||
}
|
||||
},
|
||||
|
||||
// private
|
||||
mimicBlur: function(e){
|
||||
if (!this.wrap.contains(e.target) && this.field.validateBlur(e)) {
|
||||
this.triggerBlur();
|
||||
}
|
||||
},
|
||||
|
||||
// private
|
||||
triggerBlur: function(){
|
||||
this.mimicing = false;
|
||||
Ext.get(Ext.isIE ? document.body : document).un("mousedown", this.mimicBlur, this);
|
||||
this.el.un("keydown", this.checkTab, this);
|
||||
this.field.beforeBlur();
|
||||
this.wrap.removeClass('x-trigger-wrap-focus');
|
||||
this.field.onBlur.call(this.field);
|
||||
},
|
||||
|
||||
initTrigger: function(){
|
||||
this.trigger.addClassOnOver('x-form-trigger-over');
|
||||
this.trigger.addClassOnClick('x-form-trigger-click');
|
||||
},
|
||||
|
||||
initSpinner: function(){
|
||||
this.field.addEvents({
|
||||
'spin': true,
|
||||
'spinup': true,
|
||||
'spindown': true
|
||||
});
|
||||
|
||||
this.keyNav = new Ext.KeyNav(this.el, {
|
||||
"up": function(e){
|
||||
e.preventDefault();
|
||||
this.onSpinUp();
|
||||
},
|
||||
|
||||
"down": function(e){
|
||||
e.preventDefault();
|
||||
this.onSpinDown();
|
||||
},
|
||||
|
||||
"pageUp": function(e){
|
||||
e.preventDefault();
|
||||
this.onSpinUpAlternate();
|
||||
},
|
||||
|
||||
"pageDown": function(e){
|
||||
e.preventDefault();
|
||||
this.onSpinDownAlternate();
|
||||
},
|
||||
|
||||
scope: this
|
||||
});
|
||||
|
||||
this.repeater = new Ext.util.ClickRepeater(this.trigger, {
|
||||
accelerate: this.accelerate
|
||||
});
|
||||
this.field.mon(this.repeater, "click", this.onTriggerClick, this, {
|
||||
preventDefault: true
|
||||
});
|
||||
|
||||
this.field.mon(this.trigger, {
|
||||
mouseover: this.onMouseOver,
|
||||
mouseout: this.onMouseOut,
|
||||
mousemove: this.onMouseMove,
|
||||
mousedown: this.onMouseDown,
|
||||
mouseup: this.onMouseUp,
|
||||
scope: this,
|
||||
preventDefault: true
|
||||
});
|
||||
|
||||
this.field.mon(this.wrap, "mousewheel", this.handleMouseWheel, this);
|
||||
|
||||
this.dd.setXConstraint(0, 0, 10)
|
||||
this.dd.setYConstraint(1500, 1500, 10);
|
||||
this.dd.endDrag = this.endDrag.createDelegate(this);
|
||||
this.dd.startDrag = this.startDrag.createDelegate(this);
|
||||
this.dd.onDrag = this.onDrag.createDelegate(this);
|
||||
},
|
||||
|
||||
onMouseOver: function(){
|
||||
if (this.disabled) {
|
||||
return;
|
||||
}
|
||||
var middle = this.getMiddle();
|
||||
this.tmpHoverClass = (Ext.EventObject.getPageY() < middle) ? 'x-form-spinner-overup' : 'x-form-spinner-overdown';
|
||||
this.trigger.addClass(this.tmpHoverClass);
|
||||
},
|
||||
|
||||
//private
|
||||
onMouseOut: function(){
|
||||
this.trigger.removeClass(this.tmpHoverClass);
|
||||
},
|
||||
|
||||
//private
|
||||
onMouseMove: function(){
|
||||
if (this.disabled) {
|
||||
return;
|
||||
}
|
||||
var middle = this.getMiddle();
|
||||
if (((Ext.EventObject.getPageY() > middle) && this.tmpHoverClass == "x-form-spinner-overup") ||
|
||||
((Ext.EventObject.getPageY() < middle) && this.tmpHoverClass == "x-form-spinner-overdown")) {
|
||||
}
|
||||
},
|
||||
|
||||
//private
|
||||
onMouseDown: function(){
|
||||
if (this.disabled) {
|
||||
return;
|
||||
}
|
||||
var middle = this.getMiddle();
|
||||
this.tmpClickClass = (Ext.EventObject.getPageY() < middle) ? 'x-form-spinner-clickup' : 'x-form-spinner-clickdown';
|
||||
this.trigger.addClass(this.tmpClickClass);
|
||||
},
|
||||
|
||||
//private
|
||||
onMouseUp: function(){
|
||||
this.trigger.removeClass(this.tmpClickClass);
|
||||
},
|
||||
|
||||
//private
|
||||
onTriggerClick: function(){
|
||||
if (this.disabled || this.el.dom.readOnly) {
|
||||
return;
|
||||
}
|
||||
var middle = this.getMiddle();
|
||||
var ud = (Ext.EventObject.getPageY() < middle) ? 'Up' : 'Down';
|
||||
this['onSpin' + ud]();
|
||||
},
|
||||
|
||||
//private
|
||||
getMiddle: function(){
|
||||
var t = this.trigger.getTop();
|
||||
var h = this.trigger.getHeight();
|
||||
var middle = t + (h / 2);
|
||||
return middle;
|
||||
},
|
||||
|
||||
//private
|
||||
//checks if control is allowed to spin
|
||||
isSpinnable: function(){
|
||||
if (this.disabled || this.el.dom.readOnly) {
|
||||
Ext.EventObject.preventDefault(); //prevent scrolling when disabled/readonly
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
},
|
||||
|
||||
handleMouseWheel: function(e){
|
||||
//disable scrolling when not focused
|
||||
if (this.wrap.hasClass('x-trigger-wrap-focus') == false) {
|
||||
return;
|
||||
}
|
||||
|
||||
var delta = e.getWheelDelta();
|
||||
if (delta > 0) {
|
||||
this.onSpinUp();
|
||||
e.stopEvent();
|
||||
}
|
||||
else
|
||||
if (delta < 0) {
|
||||
this.onSpinDown();
|
||||
e.stopEvent();
|
||||
}
|
||||
},
|
||||
|
||||
//private
|
||||
startDrag: function(){
|
||||
this.proxy.show();
|
||||
this._previousY = Ext.fly(this.dd.getDragEl()).getTop();
|
||||
},
|
||||
|
||||
//private
|
||||
endDrag: function(){
|
||||
this.proxy.hide();
|
||||
},
|
||||
|
||||
//private
|
||||
onDrag: function(){
|
||||
if (this.disabled) {
|
||||
return;
|
||||
}
|
||||
var y = Ext.fly(this.dd.getDragEl()).getTop();
|
||||
var ud = '';
|
||||
|
||||
if (this._previousY > y) {
|
||||
ud = 'Up';
|
||||
} //up
|
||||
if (this._previousY < y) {
|
||||
ud = 'Down';
|
||||
} //down
|
||||
if (ud != '') {
|
||||
this['onSpin' + ud]();
|
||||
}
|
||||
|
||||
this._previousY = y;
|
||||
},
|
||||
|
||||
//private
|
||||
onSpinUp: function(){
|
||||
if (this.isSpinnable() == false) {
|
||||
return;
|
||||
}
|
||||
if (Ext.EventObject.shiftKey == true) {
|
||||
this.onSpinUpAlternate();
|
||||
return;
|
||||
}
|
||||
else {
|
||||
this.spin(false, false);
|
||||
}
|
||||
this.field.fireEvent("spin", this);
|
||||
this.field.fireEvent("spinup", this);
|
||||
},
|
||||
|
||||
//private
|
||||
onSpinDown: function(){
|
||||
if (this.isSpinnable() == false) {
|
||||
return;
|
||||
}
|
||||
if (Ext.EventObject.shiftKey == true) {
|
||||
this.onSpinDownAlternate();
|
||||
return;
|
||||
}
|
||||
else {
|
||||
this.spin(true, false);
|
||||
}
|
||||
this.field.fireEvent("spin", this);
|
||||
this.field.fireEvent("spindown", this);
|
||||
},
|
||||
|
||||
//private
|
||||
onSpinUpAlternate: function(){
|
||||
if (this.isSpinnable() == false) {
|
||||
return;
|
||||
}
|
||||
this.spin(false, true);
|
||||
this.field.fireEvent("spin", this);
|
||||
this.field.fireEvent("spinup", this);
|
||||
},
|
||||
|
||||
//private
|
||||
onSpinDownAlternate: function(){
|
||||
if (this.isSpinnable() == false) {
|
||||
return;
|
||||
}
|
||||
this.spin(true, true);
|
||||
this.field.fireEvent("spin", this);
|
||||
this.field.fireEvent("spindown", this);
|
||||
},
|
||||
|
||||
spin: function(down, alternate){
|
||||
var v = parseFloat(this.field.getValue());
|
||||
var incr = (alternate == true) ? this.alternateIncrementValue : this.incrementValue;
|
||||
(down == true) ? v -= incr : v += incr;
|
||||
|
||||
v = (isNaN(v)) ? this.defaultValue : v;
|
||||
v = this.fixBoundries(v);
|
||||
this.field.setRawValue(v);
|
||||
},
|
||||
|
||||
fixBoundries: function(value){
|
||||
var v = value;
|
||||
|
||||
if (this.field.minValue != undefined && v < this.field.minValue) {
|
||||
v = this.field.minValue;
|
||||
}
|
||||
if (this.field.maxValue != undefined && v > this.field.maxValue) {
|
||||
v = this.field.maxValue;
|
||||
}
|
||||
|
||||
return this.fixPrecision(v);
|
||||
},
|
||||
|
||||
// private
|
||||
fixPrecision: function(value){
|
||||
var nan = isNaN(value);
|
||||
if (!this.field.allowDecimals || this.field.decimalPrecision == -1 || nan || !value) {
|
||||
return nan ? '' : value;
|
||||
}
|
||||
return parseFloat(parseFloat(value).toFixed(this.field.decimalPrecision));
|
||||
},
|
||||
|
||||
doDestroy: function(){
|
||||
if (this.trigger) {
|
||||
this.trigger.remove();
|
||||
}
|
||||
if (this.wrap) {
|
||||
this.wrap.remove();
|
||||
delete this.field.wrap;
|
||||
}
|
||||
|
||||
if (this.splitter) {
|
||||
this.splitter.remove();
|
||||
}
|
||||
|
||||
if (this.dd) {
|
||||
this.dd.unreg();
|
||||
this.dd = null;
|
||||
}
|
||||
|
||||
if (this.proxy) {
|
||||
this.proxy.remove();
|
||||
}
|
||||
|
||||
if (this.repeater) {
|
||||
this.repeater.purgeListeners();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
//backwards compat
|
||||
Ext.form.Spinner = Ext.ux.Spinner;
|
||||
@ -1,20 +1,28 @@
|
||||
/*!
|
||||
* Ext JS Library 3.1.0
|
||||
* Copyright(c) 2006-2009 Ext JS, LLC
|
||||
* licensing@extjs.com
|
||||
* http://www.extjs.com/license
|
||||
*/
|
||||
/*
|
||||
|
||||
This file is part of Ext JS 4
|
||||
|
||||
Copyright (c) 2011 Sencha Inc
|
||||
|
||||
Contact: http://www.sencha.com/contact
|
||||
|
||||
GNU General Public License Usage
|
||||
This file may be used under the terms of the GNU General Public License version 3.0 as published by the Free Software Foundation and appearing in the file LICENSE included in the packaging of this file. Please review the following information to ensure the GNU General Public License version 3.0 requirements will be met: http://www.gnu.org/copyleft/gpl.html.
|
||||
|
||||
If you are unsure which license is appropriate for your use, please contact the sales department at http://www.sencha.com/contact.
|
||||
|
||||
*/
|
||||
/**
|
||||
* @class Ext.ux.StatusBar
|
||||
* <p>Basic status bar component that can be used as the bottom toolbar of any {@link Ext.Panel}. In addition to
|
||||
* supporting the standard {@link Ext.Toolbar} interface for adding buttons, menus and other items, the StatusBar
|
||||
* supporting the standard {@link Ext.toolbar.Toolbar} interface for adding buttons, menus and other items, the StatusBar
|
||||
* provides a greedy status element that can be aligned to either side and has convenient methods for setting the
|
||||
* status text and icon. You can also indicate that something is processing using the {@link #showBusy} method.</p>
|
||||
* <pre><code>
|
||||
new Ext.Panel({
|
||||
Ext.create('Ext.Panel', {
|
||||
title: 'StatusBar',
|
||||
// etc.
|
||||
bbar: new Ext.ux.StatusBar({
|
||||
bbar: Ext.create('Ext.ux.StatusBar', {
|
||||
id: 'my-status',
|
||||
|
||||
// defaults to use when the status is cleared:
|
||||
@ -47,12 +55,16 @@ sb.showBusy();
|
||||
|
||||
sb.clearStatus(); // once completeed
|
||||
</code></pre>
|
||||
* @extends Ext.Toolbar
|
||||
* @extends Ext.toolbar.Toolbar
|
||||
* @constructor
|
||||
* Creates a new StatusBar
|
||||
* @param {Object/Array} config A config object
|
||||
*/
|
||||
Ext.ux.StatusBar = Ext.extend(Ext.Toolbar, {
|
||||
Ext.define('Ext.ux.statusbar.StatusBar', {
|
||||
extend: 'Ext.toolbar.Toolbar',
|
||||
alternateClassName: 'Ext.ux.StatusBar',
|
||||
alias: 'widget.statusbar',
|
||||
requires: ['Ext.toolbar.TextItem'],
|
||||
/**
|
||||
* @cfg {String} statusAlign
|
||||
* The alignment of the status element within the overall StatusBar layout. When the StatusBar is rendered,
|
||||
@ -63,10 +75,10 @@ Ext.ux.StatusBar = Ext.extend(Ext.Toolbar, {
|
||||
* <pre><code>
|
||||
// Create a left-aligned status bar containing a button,
|
||||
// separator and text item that will be right-aligned (default):
|
||||
new Ext.Panel({
|
||||
Ext.create('Ext.Panel', {
|
||||
title: 'StatusBar',
|
||||
// etc.
|
||||
bbar: new Ext.ux.StatusBar({
|
||||
bbar: Ext.create('Ext.ux.StatusBar', {
|
||||
defaultText: 'Default status text',
|
||||
id: 'status-id',
|
||||
items: [{
|
||||
@ -78,10 +90,10 @@ new Ext.Panel({
|
||||
// By adding the statusAlign config, this will create the
|
||||
// exact same toolbar, except the status and toolbar item
|
||||
// layout will be reversed from the previous example:
|
||||
new Ext.Panel({
|
||||
Ext.create('Ext.Panel', {
|
||||
title: 'StatusBar',
|
||||
// etc.
|
||||
bbar: new Ext.ux.StatusBar({
|
||||
bbar: Ext.create('Ext.ux.StatusBar', {
|
||||
defaultText: 'Default status text',
|
||||
id: 'status-id',
|
||||
statusAlign: 'right',
|
||||
@ -121,7 +133,7 @@ new Ext.Panel({
|
||||
}
|
||||
|
||||
// Setting a default icon:
|
||||
var sb = new Ext.ux.StatusBar({
|
||||
var sb = Ext.create('Ext.ux.StatusBar', {
|
||||
defaultIconCls: 'x-status-custom'
|
||||
});
|
||||
|
||||
@ -184,42 +196,32 @@ sb.setStatus({
|
||||
|
||||
// private
|
||||
initComponent : function(){
|
||||
if(this.statusAlign=='right'){
|
||||
if (this.statusAlign === 'right') {
|
||||
this.cls += ' x-status-right';
|
||||
}
|
||||
Ext.ux.StatusBar.superclass.initComponent.call(this);
|
||||
this.callParent(arguments);
|
||||
},
|
||||
|
||||
// private
|
||||
afterRender : function(){
|
||||
Ext.ux.StatusBar.superclass.afterRender.call(this);
|
||||
this.callParent(arguments);
|
||||
|
||||
var right = this.statusAlign == 'right';
|
||||
var right = this.statusAlign === 'right';
|
||||
this.currIconCls = this.iconCls || this.defaultIconCls;
|
||||
this.statusEl = new Ext.Toolbar.TextItem({
|
||||
this.statusEl = Ext.create('Ext.toolbar.TextItem', {
|
||||
cls: 'x-status-text ' + (this.currIconCls || ''),
|
||||
text: this.text || this.defaultText || ''
|
||||
});
|
||||
|
||||
if(right){
|
||||
if (right) {
|
||||
this.add('->');
|
||||
this.add(this.statusEl);
|
||||
}else{
|
||||
} else {
|
||||
this.insert(0, this.statusEl);
|
||||
this.insert(1, '->');
|
||||
}
|
||||
|
||||
// this.statusEl = td.createChild({
|
||||
// cls: 'x-status-text ' + (this.iconCls || this.defaultIconCls || ''),
|
||||
// html: this.text || this.defaultText || ''
|
||||
// });
|
||||
// this.statusEl.unselectable();
|
||||
|
||||
// this.spacerEl = td.insertSibling({
|
||||
// tag: 'td',
|
||||
// style: 'width:100%',
|
||||
// cn: [{cls:'ytb-spacer'}]
|
||||
// }, right ? 'before' : 'after');
|
||||
this.height = 27;
|
||||
this.doLayout();
|
||||
},
|
||||
|
||||
/**
|
||||
@ -271,39 +273,40 @@ statusBar.setStatus({
|
||||
</code></pre>
|
||||
* @return {Ext.ux.StatusBar} this
|
||||
*/
|
||||
setStatus : function(o){
|
||||
setStatus : function(o) {
|
||||
o = o || {};
|
||||
|
||||
if(typeof o == 'string'){
|
||||
if (Ext.isString(o)) {
|
||||
o = {text:o};
|
||||
}
|
||||
if(o.text !== undefined){
|
||||
if (o.text !== undefined) {
|
||||
this.setText(o.text);
|
||||
}
|
||||
if(o.iconCls !== undefined){
|
||||
if (o.iconCls !== undefined) {
|
||||
this.setIcon(o.iconCls);
|
||||
}
|
||||
|
||||
if(o.clear){
|
||||
if (o.clear) {
|
||||
var c = o.clear,
|
||||
wait = this.autoClear,
|
||||
defaults = {useDefaults: true, anim: true};
|
||||
|
||||
if(typeof c == 'object'){
|
||||
if (Ext.isObject(c)) {
|
||||
c = Ext.applyIf(c, defaults);
|
||||
if(c.wait){
|
||||
if (c.wait) {
|
||||
wait = c.wait;
|
||||
}
|
||||
}else if(typeof c == 'number'){
|
||||
} else if (Ext.isNumber(c)) {
|
||||
wait = c;
|
||||
c = defaults;
|
||||
}else if(typeof c == 'boolean'){
|
||||
} else if (Ext.isBoolean(c)) {
|
||||
c = defaults;
|
||||
}
|
||||
|
||||
c.threadId = this.activeThreadId;
|
||||
this.clearStatus.defer(wait, this, [c]);
|
||||
Ext.defer(this.clearStatus, wait, this, [c]);
|
||||
}
|
||||
this.doLayout();
|
||||
return this;
|
||||
},
|
||||
|
||||
@ -318,10 +321,10 @@ statusBar.setStatus({
|
||||
* </ul>
|
||||
* @return {Ext.ux.StatusBar} this
|
||||
*/
|
||||
clearStatus : function(o){
|
||||
clearStatus : function(o) {
|
||||
o = o || {};
|
||||
|
||||
if(o.threadId && o.threadId !== this.activeThreadId){
|
||||
if (o.threadId && o.threadId !== this.activeThreadId) {
|
||||
// this means the current call was made internally, but a newer
|
||||
// thread has set a message since this call was deferred. Since
|
||||
// we don't want to overwrite a newer message just ignore.
|
||||
@ -331,30 +334,31 @@ statusBar.setStatus({
|
||||
var text = o.useDefaults ? this.defaultText : this.emptyText,
|
||||
iconCls = o.useDefaults ? (this.defaultIconCls ? this.defaultIconCls : '') : '';
|
||||
|
||||
if(o.anim){
|
||||
// animate the statusEl Ext.Element
|
||||
this.statusEl.el.fadeOut({
|
||||
if (o.anim) {
|
||||
// animate the statusEl Ext.core.Element
|
||||
this.statusEl.el.puff({
|
||||
remove: false,
|
||||
useDisplay: true,
|
||||
scope: this,
|
||||
callback: function(){
|
||||
this.setStatus({
|
||||
text: text,
|
||||
iconCls: iconCls
|
||||
});
|
||||
text: text,
|
||||
iconCls: iconCls
|
||||
});
|
||||
|
||||
this.statusEl.el.show();
|
||||
}
|
||||
});
|
||||
}else{
|
||||
} else {
|
||||
// hide/show the el to avoid jumpy text or icon
|
||||
this.statusEl.hide();
|
||||
this.setStatus({
|
||||
text: text,
|
||||
iconCls: iconCls
|
||||
});
|
||||
this.statusEl.show();
|
||||
this.statusEl.hide();
|
||||
this.setStatus({
|
||||
text: text,
|
||||
iconCls: iconCls
|
||||
});
|
||||
this.statusEl.show();
|
||||
}
|
||||
this.doLayout();
|
||||
return this;
|
||||
},
|
||||
|
||||
@ -366,7 +370,7 @@ statusBar.setStatus({
|
||||
setText : function(text){
|
||||
this.activeThreadId++;
|
||||
this.text = text || '';
|
||||
if(this.rendered){
|
||||
if (this.rendered) {
|
||||
this.statusEl.setText(this.text);
|
||||
}
|
||||
return this;
|
||||
@ -390,16 +394,16 @@ statusBar.setStatus({
|
||||
this.activeThreadId++;
|
||||
cls = cls || '';
|
||||
|
||||
if(this.rendered){
|
||||
if(this.currIconCls){
|
||||
this.statusEl.removeClass(this.currIconCls);
|
||||
this.currIconCls = null;
|
||||
}
|
||||
if(cls.length > 0){
|
||||
this.statusEl.addClass(cls);
|
||||
this.currIconCls = cls;
|
||||
}
|
||||
}else{
|
||||
if (this.rendered) {
|
||||
if (this.currIconCls) {
|
||||
this.statusEl.removeCls(this.currIconCls);
|
||||
this.currIconCls = null;
|
||||
}
|
||||
if (cls.length > 0) {
|
||||
this.statusEl.addCls(cls);
|
||||
this.currIconCls = cls;
|
||||
}
|
||||
} else {
|
||||
this.currIconCls = cls;
|
||||
}
|
||||
return this;
|
||||
@ -416,8 +420,8 @@ statusBar.setStatus({
|
||||
* @return {Ext.ux.StatusBar} this
|
||||
*/
|
||||
showBusy : function(o){
|
||||
if(typeof o == 'string'){
|
||||
o = {text:o};
|
||||
if (Ext.isString(o)) {
|
||||
o = { text: o };
|
||||
}
|
||||
o = Ext.applyIf(o || {}, {
|
||||
text: this.busyText,
|
||||
@ -426,4 +430,4 @@ statusBar.setStatus({
|
||||
return this.setStatus(o);
|
||||
}
|
||||
});
|
||||
Ext.reg('statusbar', Ext.ux.StatusBar);
|
||||
|
||||
|
||||
@ -1,182 +0,0 @@
|
||||
/*!
|
||||
* Ext JS Library 3.1.0
|
||||
* Copyright(c) 2006-2009 Ext JS, LLC
|
||||
* licensing@extjs.com
|
||||
* http://www.extjs.com/license
|
||||
*/
|
||||
Ext.ns('Ext.ux.form');
|
||||
|
||||
/**
|
||||
* @class Ext.ux.form.FileUploadField
|
||||
* @extends Ext.form.TextField
|
||||
* Creates a file upload field.
|
||||
* @xtype fileuploadfield
|
||||
*/
|
||||
Ext.ux.form.FileUploadField = Ext.extend(Ext.form.TextField, {
|
||||
/**
|
||||
* @cfg {String} buttonText The button text to display on the upload button (defaults to
|
||||
* 'Browse...'). Note that if you supply a value for {@link #buttonCfg}, the buttonCfg.text
|
||||
* value will be used instead if available.
|
||||
*/
|
||||
buttonText: 'Browse...',
|
||||
/**
|
||||
* @cfg {Boolean} buttonOnly True to display the file upload field as a button with no visible
|
||||
* text field (defaults to false). If true, all inherited TextField members will still be available.
|
||||
*/
|
||||
buttonOnly: false,
|
||||
/**
|
||||
* @cfg {Number} buttonOffset The number of pixels of space reserved between the button and the text field
|
||||
* (defaults to 3). Note that this only applies if {@link #buttonOnly} = false.
|
||||
*/
|
||||
buttonOffset: 3,
|
||||
/**
|
||||
* @cfg {Object} buttonCfg A standard {@link Ext.Button} config object.
|
||||
*/
|
||||
|
||||
// private
|
||||
readOnly: true,
|
||||
|
||||
/**
|
||||
* @hide
|
||||
* @method autoSize
|
||||
*/
|
||||
autoSize: Ext.emptyFn,
|
||||
|
||||
// private
|
||||
initComponent: function(){
|
||||
Ext.ux.form.FileUploadField.superclass.initComponent.call(this);
|
||||
|
||||
this.addEvents(
|
||||
/**
|
||||
* @event fileselected
|
||||
* Fires when the underlying file input field's value has changed from the user
|
||||
* selecting a new file from the system file selection dialog.
|
||||
* @param {Ext.ux.form.FileUploadField} this
|
||||
* @param {String} value The file value returned by the underlying file input field
|
||||
*/
|
||||
'fileselected'
|
||||
);
|
||||
},
|
||||
|
||||
// private
|
||||
onRender : function(ct, position){
|
||||
Ext.ux.form.FileUploadField.superclass.onRender.call(this, ct, position);
|
||||
|
||||
this.wrap = this.el.wrap({cls:'x-form-field-wrap x-form-file-wrap'});
|
||||
this.el.addClass('x-form-file-text');
|
||||
this.el.dom.removeAttribute('name');
|
||||
this.createFileInput();
|
||||
|
||||
var btnCfg = Ext.applyIf(this.buttonCfg || {}, {
|
||||
text: this.buttonText
|
||||
});
|
||||
this.button = new Ext.Button(Ext.apply(btnCfg, {
|
||||
renderTo: this.wrap,
|
||||
cls: 'x-form-file-btn' + (btnCfg.iconCls ? ' x-btn-icon' : '')
|
||||
}));
|
||||
|
||||
if(this.buttonOnly){
|
||||
this.el.hide();
|
||||
this.wrap.setWidth(this.button.getEl().getWidth());
|
||||
}
|
||||
|
||||
this.bindListeners();
|
||||
this.resizeEl = this.positionEl = this.wrap;
|
||||
},
|
||||
|
||||
bindListeners: function(){
|
||||
this.fileInput.on({
|
||||
scope: this,
|
||||
mouseenter: function() {
|
||||
this.button.addClass(['x-btn-over','x-btn-focus'])
|
||||
},
|
||||
mouseleave: function(){
|
||||
this.button.removeClass(['x-btn-over','x-btn-focus','x-btn-click'])
|
||||
},
|
||||
mousedown: function(){
|
||||
this.button.addClass('x-btn-click')
|
||||
},
|
||||
mouseup: function(){
|
||||
this.button.removeClass(['x-btn-over','x-btn-focus','x-btn-click'])
|
||||
},
|
||||
change: function(){
|
||||
var v = this.fileInput.dom.value;
|
||||
this.setValue(v);
|
||||
this.fireEvent('fileselected', this, v);
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
createFileInput : function() {
|
||||
this.fileInput = this.wrap.createChild({
|
||||
id: this.getFileInputId(),
|
||||
name: this.name||this.getId(),
|
||||
cls: 'x-form-file',
|
||||
tag: 'input',
|
||||
type: 'file',
|
||||
size: 1
|
||||
});
|
||||
},
|
||||
|
||||
reset : function(){
|
||||
this.fileInput.remove();
|
||||
this.createFileInput();
|
||||
this.bindListeners();
|
||||
Ext.ux.form.FileUploadField.superclass.reset.call(this);
|
||||
},
|
||||
|
||||
// private
|
||||
getFileInputId: function(){
|
||||
return this.id + '-file';
|
||||
},
|
||||
|
||||
// private
|
||||
onResize : function(w, h){
|
||||
Ext.ux.form.FileUploadField.superclass.onResize.call(this, w, h);
|
||||
|
||||
this.wrap.setWidth(w);
|
||||
|
||||
if(!this.buttonOnly){
|
||||
var w = this.wrap.getWidth() - this.button.getEl().getWidth() - this.buttonOffset;
|
||||
this.el.setWidth(w);
|
||||
}
|
||||
},
|
||||
|
||||
// private
|
||||
onDestroy: function(){
|
||||
Ext.ux.form.FileUploadField.superclass.onDestroy.call(this);
|
||||
Ext.destroy(this.fileInput, this.button, this.wrap);
|
||||
},
|
||||
|
||||
onDisable: function(){
|
||||
Ext.ux.form.FileUploadField.superclass.onDisable.call(this);
|
||||
this.doDisable(true);
|
||||
},
|
||||
|
||||
onEnable: function(){
|
||||
Ext.ux.form.FileUploadField.superclass.onEnable.call(this);
|
||||
this.doDisable(false);
|
||||
|
||||
},
|
||||
|
||||
// private
|
||||
doDisable: function(disabled){
|
||||
this.fileInput.dom.disabled = disabled;
|
||||
this.button.setDisabled(disabled);
|
||||
},
|
||||
|
||||
|
||||
// private
|
||||
preFocus : Ext.emptyFn,
|
||||
|
||||
// private
|
||||
alignErrorIcon : function(){
|
||||
this.errorIcon.alignTo(this.wrap, 'tl-tr', [2, 0]);
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
Ext.reg('fileuploadfield', Ext.ux.form.FileUploadField);
|
||||
|
||||
// backwards compat
|
||||
Ext.form.FileUploadField = Ext.ux.form.FileUploadField;
|
||||
@ -1,61 +0,0 @@
|
||||
/*!
|
||||
* Ext JS Library 3.1.0
|
||||
* Copyright(c) 2006-2009 Ext JS, LLC
|
||||
* licensing@extjs.com
|
||||
* http://www.extjs.com/license
|
||||
*/
|
||||
Ext.ns('Ext.ux.form');
|
||||
|
||||
/**
|
||||
* @class Ext.ux.form.SpinnerField
|
||||
* @extends Ext.form.NumberField
|
||||
* Creates a field utilizing Ext.ux.Spinner
|
||||
* @xtype spinnerfield
|
||||
*/
|
||||
Ext.ux.form.SpinnerField = Ext.extend(Ext.form.NumberField, {
|
||||
actionMode: 'wrap',
|
||||
deferHeight: true,
|
||||
autoSize: Ext.emptyFn,
|
||||
onBlur: Ext.emptyFn,
|
||||
adjustSize: Ext.BoxComponent.prototype.adjustSize,
|
||||
|
||||
constructor: function(config) {
|
||||
var spinnerConfig = Ext.copyTo({}, config, 'incrementValue,alternateIncrementValue,accelerate,defaultValue,triggerClass,splitterClass');
|
||||
|
||||
var spl = this.spinner = new Ext.ux.Spinner(spinnerConfig);
|
||||
|
||||
var plugins = config.plugins
|
||||
? (Ext.isArray(config.plugins)
|
||||
? config.plugins.push(spl)
|
||||
: [config.plugins, spl])
|
||||
: spl;
|
||||
|
||||
Ext.ux.form.SpinnerField.superclass.constructor.call(this, Ext.apply(config, {plugins: plugins}));
|
||||
},
|
||||
|
||||
// private
|
||||
getResizeEl: function(){
|
||||
return this.wrap;
|
||||
},
|
||||
|
||||
// private
|
||||
getPositionEl: function(){
|
||||
return this.wrap;
|
||||
},
|
||||
|
||||
// private
|
||||
alignErrorIcon: function(){
|
||||
if (this.wrap) {
|
||||
this.errorIcon.alignTo(this.wrap, 'tl-tr', [2, 0]);
|
||||
}
|
||||
},
|
||||
|
||||
validateBlur: function(){
|
||||
return true;
|
||||
}
|
||||
});
|
||||
|
||||
Ext.reg('spinnerfield', Ext.ux.form.SpinnerField);
|
||||
|
||||
//backwards compat
|
||||
Ext.form.SpinnerField = Ext.ux.form.SpinnerField;
|
||||
@ -1,6 +1,6 @@
|
||||
/*!
|
||||
* Ext.ux.form.SpinnerGroup.js
|
||||
*
|
||||
*
|
||||
* Copyright (c) Damien Churchill 2009-2010 <damoxc@gmail.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
@ -29,12 +29,20 @@
|
||||
* this exception statement from your version. If you delete this exception
|
||||
* statement from all source files in the program, then also delete it here.
|
||||
*/
|
||||
Ext.ns('Ext.ux.form');
|
||||
|
||||
/**
|
||||
* Ext.ux.form.SpinnerGroup class
|
||||
*
|
||||
* @author Damien Churchill
|
||||
* @version v0.1
|
||||
*
|
||||
* @class Ext.ux.form.SpinnerGroup
|
||||
* @extends Ext.form.CheckboxGroup
|
||||
*/
|
||||
Ext.ux.form.SpinnerGroup = Ext.extend(Ext.form.CheckboxGroup, {
|
||||
Ext.define('Ext.ux.form.SpinnerGroup', {
|
||||
|
||||
extend: 'Ext.form.CheckboxGroup',
|
||||
alias: 'widget.spinnergroup',
|
||||
|
||||
// private
|
||||
defaultType: 'spinnerfield',
|
||||
@ -169,7 +177,7 @@ Ext.ux.form.SpinnerGroup = Ext.extend(Ext.form.CheckboxGroup, {
|
||||
}
|
||||
}
|
||||
|
||||
Ext.ux.form.SpinnerGroup.superclass.onRender.call(this, ct, position);
|
||||
this.callParent(arguments);
|
||||
},
|
||||
|
||||
onFieldChange: function(spinner) {
|
||||
@ -216,4 +224,3 @@ Ext.ux.form.SpinnerGroup = Ext.extend(Ext.form.CheckboxGroup, {
|
||||
}
|
||||
}
|
||||
});
|
||||
Ext.reg('spinnergroup', Ext.ux.form.SpinnerGroup);
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
/*!
|
||||
* Ext.ux.form.ToggleField.js
|
||||
*
|
||||
* Copyright (c) Damien Churchill 2009-2010 <damoxc@gmail.com>
|
||||
*
|
||||
* Copyright (c) Damien Churchill 2009-2011 <damoxc@gmail.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@ -29,7 +29,6 @@
|
||||
* this exception statement from your version. If you delete this exception
|
||||
* statement from all source files in the program, then also delete it here.
|
||||
*/
|
||||
Ext.namespace("Ext.ux.form");
|
||||
|
||||
/**
|
||||
* Ext.ux.form.ToggleField class
|
||||
@ -40,12 +39,15 @@ Ext.namespace("Ext.ux.form");
|
||||
* @class Ext.ux.form.ToggleField
|
||||
* @extends Ext.form.TriggerField
|
||||
*/
|
||||
Ext.ux.form.ToggleField = Ext.extend(Ext.form.Field, {
|
||||
Ext.define('Ext.ux.form.ToggleField', {
|
||||
|
||||
extend: 'Ext.form.Field',
|
||||
alias: 'widget.togglefield',
|
||||
|
||||
cls: 'x-toggle-field',
|
||||
|
||||
initComponent: function() {
|
||||
Ext.ux.form.ToggleField.superclass.initComponent.call(this);
|
||||
this.callParent(arguments);
|
||||
|
||||
this.toggle = new Ext.form.Checkbox();
|
||||
this.toggle.on('check', this.onToggleCheck, this);
|
||||
@ -75,7 +77,7 @@ Ext.ux.form.ToggleField = Ext.extend(Ext.form.Field, {
|
||||
|
||||
this.toggle.getEl().parent().setStyle('padding-right', '10px');
|
||||
}
|
||||
Ext.ux.form.ToggleField.superclass.onRender.call(this, ct, position);
|
||||
this.callParent(arguments);
|
||||
},
|
||||
|
||||
// private
|
||||
@ -92,4 +94,3 @@ Ext.ux.form.ToggleField = Ext.extend(Ext.form.Field, {
|
||||
this.input.setDisabled(!checked);
|
||||
}
|
||||
});
|
||||
Ext.reg('togglefield', Ext.ux.form.ToggleField);
|
||||
|
||||
@ -1,219 +0,0 @@
|
||||
/*!
|
||||
* Ext JS Library 3.1.0
|
||||
* Copyright(c) 2006-2009 Ext JS, LLC
|
||||
* licensing@extjs.com
|
||||
* http://www.extjs.com/license
|
||||
*/
|
||||
Ext.ns('Ext.ux.grid');
|
||||
|
||||
/**
|
||||
* @class Ext.ux.grid.BufferView
|
||||
* @extends Ext.grid.GridView
|
||||
* A custom GridView which renders rows on an as-needed basis.
|
||||
*/
|
||||
Ext.ux.grid.BufferView = Ext.extend(Ext.grid.GridView, {
|
||||
/**
|
||||
* @cfg {Number} rowHeight
|
||||
* The height of a row in the grid.
|
||||
*/
|
||||
rowHeight: 19,
|
||||
|
||||
/**
|
||||
* @cfg {Number} borderHeight
|
||||
* The combined height of border-top and border-bottom of a row.
|
||||
*/
|
||||
borderHeight: 2,
|
||||
|
||||
/**
|
||||
* @cfg {Boolean/Number} scrollDelay
|
||||
* The number of milliseconds before rendering rows out of the visible
|
||||
* viewing area. Defaults to 100. Rows will render immediately with a config
|
||||
* of false.
|
||||
*/
|
||||
scrollDelay: 100,
|
||||
|
||||
/**
|
||||
* @cfg {Number} cacheSize
|
||||
* The number of rows to look forward and backwards from the currently viewable
|
||||
* area. The cache applies only to rows that have been rendered already.
|
||||
*/
|
||||
cacheSize: 20,
|
||||
|
||||
/**
|
||||
* @cfg {Number} cleanDelay
|
||||
* The number of milliseconds to buffer cleaning of extra rows not in the
|
||||
* cache.
|
||||
*/
|
||||
cleanDelay: 500,
|
||||
|
||||
initTemplates : function(){
|
||||
Ext.ux.grid.BufferView.superclass.initTemplates.call(this);
|
||||
var ts = this.templates;
|
||||
// empty div to act as a place holder for a row
|
||||
ts.rowHolder = new Ext.Template(
|
||||
'<div class="x-grid3-row {alt}" style="{tstyle}"></div>'
|
||||
);
|
||||
ts.rowHolder.disableFormats = true;
|
||||
ts.rowHolder.compile();
|
||||
|
||||
ts.rowBody = new Ext.Template(
|
||||
'<table class="x-grid3-row-table" border="0" cellspacing="0" cellpadding="0" style="{tstyle}">',
|
||||
'<tbody><tr>{cells}</tr>',
|
||||
(this.enableRowBody ? '<tr class="x-grid3-row-body-tr" style="{bodyStyle}"><td colspan="{cols}" class="x-grid3-body-cell" tabIndex="0" hidefocus="on"><div class="x-grid3-row-body">{body}</div></td></tr>' : ''),
|
||||
'</tbody></table>'
|
||||
);
|
||||
ts.rowBody.disableFormats = true;
|
||||
ts.rowBody.compile();
|
||||
},
|
||||
|
||||
getStyleRowHeight : function(){
|
||||
return Ext.isBorderBox ? (this.rowHeight + this.borderHeight) : this.rowHeight;
|
||||
},
|
||||
|
||||
getCalculatedRowHeight : function(){
|
||||
return this.rowHeight + this.borderHeight;
|
||||
},
|
||||
|
||||
getVisibleRowCount : function(){
|
||||
var rh = this.getCalculatedRowHeight();
|
||||
var visibleHeight = this.scroller.dom.clientHeight;
|
||||
return (visibleHeight < 1) ? 0 : Math.ceil(visibleHeight / rh);
|
||||
},
|
||||
|
||||
getVisibleRows: function(){
|
||||
var count = this.getVisibleRowCount();
|
||||
var sc = this.scroller.dom.scrollTop;
|
||||
var start = (sc == 0 ? 0 : Math.floor(sc/this.getCalculatedRowHeight())-1);
|
||||
return {
|
||||
first: Math.max(start, 0),
|
||||
last: Math.min(start + count + 2, this.ds.getCount()-1)
|
||||
};
|
||||
},
|
||||
|
||||
doRender : function(cs, rs, ds, startRow, colCount, stripe, onlyBody){
|
||||
var ts = this.templates, ct = ts.cell, rt = ts.row, rb = ts.rowBody, last = colCount-1;
|
||||
var rh = this.getStyleRowHeight();
|
||||
var vr = this.getVisibleRows();
|
||||
var tstyle = 'width:'+this.getTotalWidth()+';height:'+rh+'px;';
|
||||
// buffers
|
||||
var buf = [], cb, c, p = {}, rp = {tstyle: tstyle}, r;
|
||||
for (var j = 0, len = rs.length; j < len; j++) {
|
||||
r = rs[j]; cb = [];
|
||||
var rowIndex = (j+startRow);
|
||||
var visible = rowIndex >= vr.first && rowIndex <= vr.last;
|
||||
if (visible) {
|
||||
for (var i = 0; i < colCount; i++) {
|
||||
c = cs[i];
|
||||
p.id = c.id;
|
||||
p.css = i == 0 ? 'x-grid3-cell-first ' : (i == last ? 'x-grid3-cell-last ' : '');
|
||||
p.attr = p.cellAttr = "";
|
||||
p.value = c.renderer(r.data[c.name], p, r, rowIndex, i, ds);
|
||||
p.style = c.style;
|
||||
if (p.value == undefined || p.value === "") {
|
||||
p.value = " ";
|
||||
}
|
||||
if (r.dirty && typeof r.modified[c.name] !== 'undefined') {
|
||||
p.css += ' x-grid3-dirty-cell';
|
||||
}
|
||||
cb[cb.length] = ct.apply(p);
|
||||
}
|
||||
}
|
||||
var alt = [];
|
||||
if(stripe && ((rowIndex+1) % 2 == 0)){
|
||||
alt[0] = "x-grid3-row-alt";
|
||||
}
|
||||
if(r.dirty){
|
||||
alt[1] = " x-grid3-dirty-row";
|
||||
}
|
||||
rp.cols = colCount;
|
||||
if(this.getRowClass){
|
||||
alt[2] = this.getRowClass(r, rowIndex, rp, ds);
|
||||
}
|
||||
rp.alt = alt.join(" ");
|
||||
rp.cells = cb.join("");
|
||||
buf[buf.length] = !visible ? ts.rowHolder.apply(rp) : (onlyBody ? rb.apply(rp) : rt.apply(rp));
|
||||
}
|
||||
return buf.join("");
|
||||
},
|
||||
|
||||
isRowRendered: function(index){
|
||||
var row = this.getRow(index);
|
||||
return row && row.childNodes.length > 0;
|
||||
},
|
||||
|
||||
syncScroll: function(){
|
||||
Ext.ux.grid.BufferView.superclass.syncScroll.apply(this, arguments);
|
||||
this.update();
|
||||
},
|
||||
|
||||
// a (optionally) buffered method to update contents of gridview
|
||||
update: function(){
|
||||
if (this.scrollDelay) {
|
||||
if (!this.renderTask) {
|
||||
this.renderTask = new Ext.util.DelayedTask(this.doUpdate, this);
|
||||
}
|
||||
this.renderTask.delay(this.scrollDelay);
|
||||
}else{
|
||||
this.doUpdate();
|
||||
}
|
||||
},
|
||||
|
||||
onRemove : function(ds, record, index, isUpdate){
|
||||
Ext.ux.grid.BufferView.superclass.onRemove.apply(this, arguments);
|
||||
if(isUpdate !== true){
|
||||
this.update();
|
||||
}
|
||||
},
|
||||
|
||||
doUpdate: function(){
|
||||
if (this.getVisibleRowCount() > 0) {
|
||||
var g = this.grid, cm = g.colModel, ds = g.store;
|
||||
var cs = this.getColumnData();
|
||||
|
||||
var vr = this.getVisibleRows();
|
||||
for (var i = vr.first; i <= vr.last; i++) {
|
||||
// if row is NOT rendered and is visible, render it
|
||||
if(!this.isRowRendered(i)){
|
||||
var html = this.doRender(cs, [ds.getAt(i)], ds, i, cm.getColumnCount(), g.stripeRows, true);
|
||||
this.getRow(i).innerHTML = html;
|
||||
}
|
||||
}
|
||||
this.clean();
|
||||
}
|
||||
},
|
||||
|
||||
// a buffered method to clean rows
|
||||
clean : function(){
|
||||
if(!this.cleanTask){
|
||||
this.cleanTask = new Ext.util.DelayedTask(this.doClean, this);
|
||||
}
|
||||
this.cleanTask.delay(this.cleanDelay);
|
||||
},
|
||||
|
||||
doClean: function(){
|
||||
if (this.getVisibleRowCount() > 0) {
|
||||
var vr = this.getVisibleRows();
|
||||
vr.first -= this.cacheSize;
|
||||
vr.last += this.cacheSize;
|
||||
|
||||
var i = 0, rows = this.getRows();
|
||||
// if first is less than 0, all rows have been rendered
|
||||
// so lets clean the end...
|
||||
if(vr.first <= 0){
|
||||
i = vr.last + 1;
|
||||
}
|
||||
for(var len = this.ds.getCount(); i < len; i++){
|
||||
// if current row is outside of first and last and
|
||||
// has content, update the innerHTML to nothing
|
||||
if ((i < vr.first || i > vr.last) && rows[i].innerHTML) {
|
||||
rows[i].innerHTML = '';
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
layout: function(){
|
||||
Ext.ux.grid.BufferView.superclass.layout.call(this);
|
||||
this.update();
|
||||
}
|
||||
});
|
||||
@ -1,92 +0,0 @@
|
||||
/*!
|
||||
* Ext.ux.tree.MultiSelectionModelFix.js
|
||||
*
|
||||
* Copyright (c) Damien Churchill 2009-2010 <damoxc@gmail.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, write to:
|
||||
* The Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor
|
||||
* Boston, MA 02110-1301, USA.
|
||||
*
|
||||
* In addition, as a special exception, the copyright holders give
|
||||
* permission to link the code of portions of this program with the OpenSSL
|
||||
* library.
|
||||
* You must obey the GNU General Public License in all respects for all of
|
||||
* the code used other than OpenSSL. If you modify file(s) with this
|
||||
* exception, you may extend this exception to your version of the file(s),
|
||||
* but you are not obligated to do so. If you do not wish to do so, delete
|
||||
* this exception statement from your version. If you delete this exception
|
||||
* statement from all source files in the program, then also delete it here.
|
||||
*/
|
||||
|
||||
/**
|
||||
* This enhances the MSM to allow for shift selecting in tree grids etc.
|
||||
* @author Damien Churchill <damoxc@gmail.com>
|
||||
*/
|
||||
Ext.override(Ext.tree.MultiSelectionModel, {
|
||||
|
||||
onNodeClick: function (node, e) {
|
||||
if (e.ctrlKey && this.isSelected(node)) {
|
||||
this.unselect(node);
|
||||
} else if (e.shiftKey && !this.isSelected(node)) {
|
||||
var parentNode = node.parentNode;
|
||||
// We can only shift select files in the same node
|
||||
if (this.lastSelNode.parentNode.id != parentNode.id) return;
|
||||
|
||||
// Get the node indexes
|
||||
var fi = parentNode.indexOf(node),
|
||||
li = parentNode.indexOf(this.lastSelNode);
|
||||
|
||||
// Select the last clicked node and wipe old selections
|
||||
this.select(this.lastSelNode, e, false, true);
|
||||
|
||||
// Swap the values if required
|
||||
if (fi > li) {
|
||||
fi = fi + li, li = fi - li, fi = fi - li;
|
||||
}
|
||||
|
||||
// Select all the nodes
|
||||
parentNode.eachChild(function(n) {
|
||||
var i = parentNode.indexOf(n);
|
||||
if (fi < i && i < li) {
|
||||
this.select(n, e, true, true);
|
||||
}
|
||||
}, this);
|
||||
|
||||
// Select the clicked node
|
||||
this.select(node, e, true);
|
||||
} else {
|
||||
this.select(node, e, e.ctrlKey);
|
||||
}
|
||||
},
|
||||
|
||||
select: function(node, e, keepExisting, suppressEvent) {
|
||||
if(keepExisting !== true){
|
||||
this.clearSelections(true);
|
||||
}
|
||||
if(this.isSelected(node)){
|
||||
this.lastSelNode = node;
|
||||
return node;
|
||||
}
|
||||
this.selNodes.push(node);
|
||||
this.selMap[node.id] = node;
|
||||
this.lastSelNode = node;
|
||||
node.ui.onSelectedChange(true);
|
||||
if (suppressEvent !== true) {
|
||||
this.fireEvent('selectionchange', this, this.selNodes);
|
||||
}
|
||||
return node;
|
||||
}
|
||||
|
||||
})
|
||||
@ -1,409 +0,0 @@
|
||||
/*!
|
||||
* Ext JS Library 3.1.0
|
||||
* Copyright(c) 2006-2009 Ext JS, LLC
|
||||
* licensing@extjs.com
|
||||
* http://www.extjs.com/license
|
||||
*/
|
||||
Ext.ns('Ext.ux.tree');
|
||||
|
||||
/**
|
||||
* @class Ext.ux.tree.TreeGrid
|
||||
* @extends Ext.tree.TreePanel
|
||||
*
|
||||
* @xtype treegrid
|
||||
*/
|
||||
Ext.ux.tree.TreeGrid = Ext.extend(Ext.tree.TreePanel, {
|
||||
rootVisible : false,
|
||||
useArrows : true,
|
||||
lines : false,
|
||||
borderWidth : Ext.isBorderBox ? 0 : 2, // the combined left/right border for each cell
|
||||
cls : 'x-treegrid',
|
||||
|
||||
columnResize : true,
|
||||
enableSort : true,
|
||||
reserveScrollOffset : true,
|
||||
enableHdMenu : true,
|
||||
|
||||
columnsText : 'Columns',
|
||||
|
||||
initComponent : function() {
|
||||
if(!this.root) {
|
||||
this.root = new Ext.tree.AsyncTreeNode({text: 'Root'});
|
||||
}
|
||||
|
||||
// initialize the loader
|
||||
var l = this.loader;
|
||||
if(!l){
|
||||
l = new Ext.ux.tree.TreeGridLoader({
|
||||
dataUrl: this.dataUrl,
|
||||
requestMethod: this.requestMethod,
|
||||
store: this.store
|
||||
});
|
||||
}else if(Ext.isObject(l) && !l.load){
|
||||
l = new Ext.ux.tree.TreeGridLoader(l);
|
||||
}
|
||||
else if(l) {
|
||||
l.createNode = function(attr) {
|
||||
if (!attr.uiProvider) {
|
||||
attr.uiProvider = Ext.ux.tree.TreeGridNodeUI;
|
||||
}
|
||||
return Ext.tree.TreeLoader.prototype.createNode.call(this, attr);
|
||||
}
|
||||
}
|
||||
this.loader = l;
|
||||
|
||||
Ext.ux.tree.TreeGrid.superclass.initComponent.call(this);
|
||||
|
||||
this.initColumns();
|
||||
|
||||
if(this.enableSort) {
|
||||
this.treeGridSorter = new Ext.ux.tree.TreeGridSorter(this, this.enableSort);
|
||||
}
|
||||
|
||||
if(this.columnResize){
|
||||
this.colResizer = new Ext.tree.ColumnResizer(this.columnResize);
|
||||
this.colResizer.init(this);
|
||||
}
|
||||
|
||||
var c = this.columns;
|
||||
if(!this.internalTpl){
|
||||
this.internalTpl = new Ext.XTemplate(
|
||||
'<div class="x-grid3-header">',
|
||||
'<div class="x-treegrid-header-inner">',
|
||||
'<div class="x-grid3-header-offset">',
|
||||
'<table cellspacing="0" cellpadding="0" border="0"><colgroup><tpl for="columns"><col /></tpl></colgroup>',
|
||||
'<thead><tr class="x-grid3-hd-row">',
|
||||
'<tpl for="columns">',
|
||||
'<td class="x-grid3-hd x-grid3-cell x-treegrid-hd" style="text-align: {align};" id="', this.id, '-xlhd-{#}">',
|
||||
'<div class="x-grid3-hd-inner x-treegrid-hd-inner" unselectable="on">',
|
||||
this.enableHdMenu ? '<a class="x-grid3-hd-btn" href="#"></a>' : '',
|
||||
'{header}<img class="x-grid3-sort-icon" src="', Ext.BLANK_IMAGE_URL, '" />',
|
||||
'</div>',
|
||||
'</td></tpl>',
|
||||
'</tr></thead>',
|
||||
'</div></table>',
|
||||
'</div></div>',
|
||||
'</div>',
|
||||
'<div class="x-treegrid-root-node">',
|
||||
'<table class="x-treegrid-root-table" cellpadding="0" cellspacing="0" style="table-layout: fixed;"></table>',
|
||||
'</div>'
|
||||
);
|
||||
}
|
||||
|
||||
if(!this.colgroupTpl) {
|
||||
this.colgroupTpl = new Ext.XTemplate(
|
||||
'<colgroup><tpl for="columns"><col style="width: {width}px"/></tpl></colgroup>'
|
||||
);
|
||||
}
|
||||
},
|
||||
|
||||
initColumns : function() {
|
||||
var cs = this.columns,
|
||||
len = cs.length,
|
||||
columns = [],
|
||||
i, c;
|
||||
|
||||
for(i = 0; i < len; i++){
|
||||
c = cs[i];
|
||||
if(!c.isColumn) {
|
||||
c.xtype = c.xtype ? (/^tg/.test(c.xtype) ? c.xtype : 'tg' + c.xtype) : 'tgcolumn';
|
||||
c = Ext.create(c);
|
||||
}
|
||||
c.init(this);
|
||||
columns.push(c);
|
||||
|
||||
if(this.enableSort !== false && c.sortable !== false) {
|
||||
c.sortable = true;
|
||||
this.enableSort = true;
|
||||
}
|
||||
}
|
||||
|
||||
this.columns = columns;
|
||||
},
|
||||
|
||||
onRender : function(){
|
||||
Ext.tree.TreePanel.superclass.onRender.apply(this, arguments);
|
||||
|
||||
this.el.addClass('x-treegrid');
|
||||
|
||||
this.outerCt = this.body.createChild({
|
||||
cls:'x-tree-root-ct x-treegrid-ct ' + (this.useArrows ? 'x-tree-arrows' : this.lines ? 'x-tree-lines' : 'x-tree-no-lines')
|
||||
});
|
||||
|
||||
this.internalTpl.overwrite(this.outerCt, {columns: this.columns});
|
||||
|
||||
this.mainHd = Ext.get(this.outerCt.dom.firstChild);
|
||||
this.innerHd = Ext.get(this.mainHd.dom.firstChild);
|
||||
this.innerBody = Ext.get(this.outerCt.dom.lastChild);
|
||||
this.innerCt = Ext.get(this.innerBody.dom.firstChild);
|
||||
|
||||
this.colgroupTpl.insertFirst(this.innerCt, {columns: this.columns});
|
||||
|
||||
if(this.hideHeaders){
|
||||
this.header.dom.style.display = 'none';
|
||||
}
|
||||
else if(this.enableHdMenu !== false){
|
||||
this.hmenu = new Ext.menu.Menu({id: this.id + '-hctx'});
|
||||
if(this.enableColumnHide !== false){
|
||||
this.colMenu = new Ext.menu.Menu({id: this.id + '-hcols-menu'});
|
||||
this.colMenu.on({
|
||||
scope: this,
|
||||
beforeshow: this.beforeColMenuShow,
|
||||
itemclick: this.handleHdMenuClick
|
||||
});
|
||||
this.hmenu.add({
|
||||
itemId:'columns',
|
||||
hideOnClick: false,
|
||||
text: this.columnsText,
|
||||
menu: this.colMenu,
|
||||
iconCls: 'x-cols-icon'
|
||||
});
|
||||
}
|
||||
this.hmenu.on('itemclick', this.handleHdMenuClick, this);
|
||||
}
|
||||
},
|
||||
|
||||
setRootNode : function(node){
|
||||
node.attributes.uiProvider = Ext.ux.tree.TreeGridRootNodeUI;
|
||||
node = Ext.ux.tree.TreeGrid.superclass.setRootNode.call(this, node);
|
||||
if(this.innerCt) {
|
||||
this.colgroupTpl.insertFirst(this.innerCt, {columns: this.columns});
|
||||
}
|
||||
return node;
|
||||
},
|
||||
|
||||
initEvents : function() {
|
||||
Ext.ux.tree.TreeGrid.superclass.initEvents.apply(this, arguments);
|
||||
|
||||
this.mon(this.innerBody, 'scroll', this.syncScroll, this);
|
||||
this.mon(this.innerHd, 'click', this.handleHdDown, this);
|
||||
this.mon(this.mainHd, {
|
||||
scope: this,
|
||||
mouseover: this.handleHdOver,
|
||||
mouseout: this.handleHdOut
|
||||
});
|
||||
},
|
||||
|
||||
onResize : function(w, h) {
|
||||
Ext.ux.tree.TreeGrid.superclass.onResize.apply(this, arguments);
|
||||
|
||||
var bd = this.innerBody.dom;
|
||||
var hd = this.innerHd.dom;
|
||||
|
||||
if(!bd){
|
||||
return;
|
||||
}
|
||||
|
||||
if(Ext.isNumber(h)){
|
||||
bd.style.height = this.body.getHeight(true) - hd.offsetHeight + 'px';
|
||||
}
|
||||
|
||||
if(Ext.isNumber(w)){
|
||||
var sw = Ext.num(this.scrollOffset, Ext.getScrollBarWidth());
|
||||
if(this.reserveScrollOffset || ((bd.offsetWidth - bd.clientWidth) > 10)){
|
||||
this.setScrollOffset(sw);
|
||||
}else{
|
||||
var me = this;
|
||||
setTimeout(function(){
|
||||
me.setScrollOffset(bd.offsetWidth - bd.clientWidth > 10 ? sw : 0);
|
||||
}, 10);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
updateColumnWidths : function() {
|
||||
var cols = this.columns,
|
||||
colCount = cols.length,
|
||||
groups = this.outerCt.query('colgroup'),
|
||||
groupCount = groups.length,
|
||||
c, g, i, j;
|
||||
|
||||
for(i = 0; i<colCount; i++) {
|
||||
c = cols[i];
|
||||
for(j = 0; j<groupCount; j++) {
|
||||
g = groups[j];
|
||||
g.childNodes[i].style.width = (c.hidden ? 0 : c.width) + 'px';
|
||||
}
|
||||
}
|
||||
|
||||
for(i = 0, groups = this.innerHd.query('td'), len = groups.length; i<len; i++) {
|
||||
c = Ext.fly(groups[i]);
|
||||
if(cols[i] && cols[i].hidden) {
|
||||
c.addClass('x-treegrid-hd-hidden');
|
||||
}
|
||||
else {
|
||||
c.removeClass('x-treegrid-hd-hidden');
|
||||
}
|
||||
}
|
||||
|
||||
var tcw = this.getTotalColumnWidth();
|
||||
Ext.fly(this.innerHd.dom.firstChild).setWidth(tcw + (this.scrollOffset || 0));
|
||||
this.outerCt.select('table').setWidth(tcw);
|
||||
this.syncHeaderScroll();
|
||||
},
|
||||
|
||||
getVisibleColumns : function() {
|
||||
var columns = [],
|
||||
cs = this.columns,
|
||||
len = cs.length,
|
||||
i;
|
||||
|
||||
for(i = 0; i<len; i++) {
|
||||
if(!cs[i].hidden) {
|
||||
columns.push(cs[i]);
|
||||
}
|
||||
}
|
||||
return columns;
|
||||
},
|
||||
|
||||
getTotalColumnWidth : function() {
|
||||
var total = 0;
|
||||
for(var i = 0, cs = this.getVisibleColumns(), len = cs.length; i<len; i++) {
|
||||
total += cs[i].width;
|
||||
}
|
||||
return total;
|
||||
},
|
||||
|
||||
setScrollOffset : function(scrollOffset) {
|
||||
this.scrollOffset = scrollOffset;
|
||||
this.updateColumnWidths();
|
||||
},
|
||||
|
||||
// private
|
||||
handleHdDown : function(e, t){
|
||||
var hd = e.getTarget('.x-treegrid-hd');
|
||||
|
||||
if(hd && Ext.fly(t).hasClass('x-grid3-hd-btn')){
|
||||
var ms = this.hmenu.items,
|
||||
cs = this.columns,
|
||||
index = this.findHeaderIndex(hd),
|
||||
c = cs[index],
|
||||
sort = c.sortable;
|
||||
|
||||
e.stopEvent();
|
||||
Ext.fly(hd).addClass('x-grid3-hd-menu-open');
|
||||
this.hdCtxIndex = index;
|
||||
|
||||
this.fireEvent('headerbuttonclick', ms, c, hd, index);
|
||||
|
||||
this.hmenu.on('hide', function(){
|
||||
Ext.fly(hd).removeClass('x-grid3-hd-menu-open');
|
||||
}, this, {single:true});
|
||||
|
||||
this.hmenu.show(t, 'tl-bl?');
|
||||
}
|
||||
else if(hd) {
|
||||
var index = this.findHeaderIndex(hd);
|
||||
this.fireEvent('headerclick', this.columns[index], hd, index);
|
||||
}
|
||||
},
|
||||
|
||||
// private
|
||||
handleHdOver : function(e, t){
|
||||
var hd = e.getTarget('.x-treegrid-hd');
|
||||
if(hd && !this.headersDisabled){
|
||||
index = this.findHeaderIndex(hd);
|
||||
this.activeHdRef = t;
|
||||
this.activeHdIndex = index;
|
||||
var el = Ext.get(hd);
|
||||
this.activeHdRegion = el.getRegion();
|
||||
el.addClass('x-grid3-hd-over');
|
||||
this.activeHdBtn = el.child('.x-grid3-hd-btn');
|
||||
if(this.activeHdBtn){
|
||||
this.activeHdBtn.dom.style.height = (hd.firstChild.offsetHeight-1)+'px';
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
// private
|
||||
handleHdOut : function(e, t){
|
||||
var hd = e.getTarget('.x-treegrid-hd');
|
||||
if(hd && (!Ext.isIE || !e.within(hd, true))){
|
||||
this.activeHdRef = null;
|
||||
Ext.fly(hd).removeClass('x-grid3-hd-over');
|
||||
hd.style.cursor = '';
|
||||
}
|
||||
},
|
||||
|
||||
findHeaderIndex : function(hd){
|
||||
hd = hd.dom || hd;
|
||||
var cs = hd.parentNode.childNodes;
|
||||
for(var i = 0, c; c = cs[i]; i++){
|
||||
if(c == hd){
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
},
|
||||
|
||||
// private
|
||||
beforeColMenuShow : function(){
|
||||
var cols = this.columns,
|
||||
colCount = cols.length,
|
||||
i, c;
|
||||
this.colMenu.removeAll();
|
||||
for(i = 1; i < colCount; i++){
|
||||
c = cols[i];
|
||||
if(c.hideable !== false){
|
||||
this.colMenu.add(new Ext.menu.CheckItem({
|
||||
itemId: 'col-' + i,
|
||||
text: c.header,
|
||||
checked: !c.hidden,
|
||||
hideOnClick:false,
|
||||
disabled: c.hideable === false
|
||||
}));
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
// private
|
||||
handleHdMenuClick : function(item){
|
||||
var index = this.hdCtxIndex,
|
||||
id = item.getItemId();
|
||||
|
||||
if(this.fireEvent('headermenuclick', this.columns[index], id, index) !== false) {
|
||||
index = id.substr(4);
|
||||
if(index > 0 && this.columns[index]) {
|
||||
this.setColumnVisible(index, !item.checked);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
},
|
||||
|
||||
setColumnVisible : function(index, visible) {
|
||||
this.columns[index].hidden = !visible;
|
||||
this.updateColumnWidths();
|
||||
},
|
||||
|
||||
/**
|
||||
* Scrolls the grid to the top
|
||||
*/
|
||||
scrollToTop : function(){
|
||||
this.innerBody.dom.scrollTop = 0;
|
||||
this.innerBody.dom.scrollLeft = 0;
|
||||
},
|
||||
|
||||
// private
|
||||
syncScroll : function(){
|
||||
this.syncHeaderScroll();
|
||||
var mb = this.innerBody.dom;
|
||||
this.fireEvent('bodyscroll', mb.scrollLeft, mb.scrollTop);
|
||||
},
|
||||
|
||||
// private
|
||||
syncHeaderScroll : function(){
|
||||
var mb = this.innerBody.dom;
|
||||
this.innerHd.dom.scrollLeft = mb.scrollLeft;
|
||||
this.innerHd.dom.scrollLeft = mb.scrollLeft; // second time for IE (1/2 time first fails, other browsers ignore)
|
||||
},
|
||||
|
||||
registerNode : function(n) {
|
||||
Ext.ux.tree.TreeGrid.superclass.registerNode.call(this, n);
|
||||
if(!n.uiProvider && !n.isRoot && !n.ui.isTreeGridNodeUI) {
|
||||
n.ui = new Ext.ux.tree.TreeGridNodeUI(n);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
Ext.reg('treegrid', Ext.ux.tree.TreeGrid);
|
||||
@ -1,117 +0,0 @@
|
||||
/*!
|
||||
* Ext JS Library 3.1.0
|
||||
* Copyright(c) 2006-2009 Ext JS, LLC
|
||||
* licensing@extjs.com
|
||||
* http://www.extjs.com/license
|
||||
*/
|
||||
/**
|
||||
* @class Ext.tree.ColumnResizer
|
||||
* @extends Ext.util.Observable
|
||||
*/
|
||||
Ext.tree.ColumnResizer = Ext.extend(Ext.util.Observable, {
|
||||
/**
|
||||
* @cfg {Number} minWidth The minimum width the column can be dragged to.
|
||||
* Defaults to <tt>14</tt>.
|
||||
*/
|
||||
minWidth: 14,
|
||||
|
||||
constructor: function(config){
|
||||
Ext.apply(this, config);
|
||||
Ext.tree.ColumnResizer.superclass.constructor.call(this);
|
||||
},
|
||||
|
||||
init : function(tree){
|
||||
this.tree = tree;
|
||||
tree.on('render', this.initEvents, this);
|
||||
},
|
||||
|
||||
initEvents : function(tree){
|
||||
tree.mon(tree.innerHd, 'mousemove', this.handleHdMove, this);
|
||||
this.tracker = new Ext.dd.DragTracker({
|
||||
onBeforeStart: this.onBeforeStart.createDelegate(this),
|
||||
onStart: this.onStart.createDelegate(this),
|
||||
onDrag: this.onDrag.createDelegate(this),
|
||||
onEnd: this.onEnd.createDelegate(this),
|
||||
tolerance: 3,
|
||||
autoStart: 300
|
||||
});
|
||||
this.tracker.initEl(tree.innerHd);
|
||||
tree.on('beforedestroy', this.tracker.destroy, this.tracker);
|
||||
},
|
||||
|
||||
handleHdMove : function(e, t){
|
||||
var hw = 5,
|
||||
x = e.getPageX(),
|
||||
hd = e.getTarget('.x-treegrid-hd', 3, true);
|
||||
|
||||
if(hd){
|
||||
var r = hd.getRegion(),
|
||||
ss = hd.dom.style,
|
||||
pn = hd.dom.parentNode;
|
||||
|
||||
if(x - r.left <= hw && hd.dom !== pn.firstChild) {
|
||||
var ps = hd.dom.previousSibling;
|
||||
while(ps && Ext.fly(ps).hasClass('x-treegrid-hd-hidden')) {
|
||||
ps = ps.previousSibling;
|
||||
}
|
||||
if(ps) {
|
||||
this.activeHd = Ext.get(ps);
|
||||
ss.cursor = Ext.isWebKit ? 'e-resize' : 'col-resize';
|
||||
}
|
||||
} else if(r.right - x <= hw) {
|
||||
var ns = hd.dom;
|
||||
while(ns && Ext.fly(ns).hasClass('x-treegrid-hd-hidden')) {
|
||||
ns = ns.previousSibling;
|
||||
}
|
||||
if(ns) {
|
||||
this.activeHd = Ext.get(ns);
|
||||
ss.cursor = Ext.isWebKit ? 'w-resize' : 'col-resize';
|
||||
}
|
||||
} else{
|
||||
delete this.activeHd;
|
||||
ss.cursor = '';
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
onBeforeStart : function(e){
|
||||
this.dragHd = this.activeHd;
|
||||
return !!this.dragHd;
|
||||
},
|
||||
|
||||
onStart : function(e){
|
||||
this.tree.headersDisabled = true;
|
||||
this.proxy = this.tree.body.createChild({cls:'x-treegrid-resizer'});
|
||||
this.proxy.setHeight(this.tree.body.getHeight());
|
||||
|
||||
var x = this.tracker.getXY()[0];
|
||||
|
||||
this.hdX = this.dragHd.getX();
|
||||
this.hdIndex = this.tree.findHeaderIndex(this.dragHd);
|
||||
|
||||
this.proxy.setX(this.hdX);
|
||||
this.proxy.setWidth(x-this.hdX);
|
||||
|
||||
this.maxWidth = this.tree.outerCt.getWidth() - this.tree.innerBody.translatePoints(this.hdX).left;
|
||||
},
|
||||
|
||||
onDrag : function(e){
|
||||
var cursorX = this.tracker.getXY()[0];
|
||||
this.proxy.setWidth((cursorX-this.hdX).constrain(this.minWidth, this.maxWidth));
|
||||
},
|
||||
|
||||
onEnd : function(e){
|
||||
var nw = this.proxy.getWidth(),
|
||||
tree = this.tree;
|
||||
|
||||
this.proxy.remove();
|
||||
delete this.dragHd;
|
||||
|
||||
tree.columns[this.hdIndex].width = nw;
|
||||
tree.updateColumnWidths();
|
||||
|
||||
setTimeout(function(){
|
||||
tree.headersDisabled = false;
|
||||
}, 100);
|
||||
}
|
||||
});
|
||||
@ -1,45 +0,0 @@
|
||||
/*!
|
||||
* Ext JS Library 3.1.0
|
||||
* Copyright(c) 2006-2009 Ext JS, LLC
|
||||
* licensing@extjs.com
|
||||
* http://www.extjs.com/license
|
||||
*/
|
||||
(function() {
|
||||
Ext.override(Ext.list.Column, {
|
||||
init : function() {
|
||||
if(!this.type){
|
||||
this.type = "auto";
|
||||
}
|
||||
|
||||
var st = Ext.data.SortTypes;
|
||||
// named sortTypes are supported, here we look them up
|
||||
if(typeof this.sortType == "string"){
|
||||
this.sortType = st[this.sortType];
|
||||
}
|
||||
|
||||
// set default sortType for strings and dates
|
||||
if(!this.sortType){
|
||||
switch(this.type){
|
||||
case "string":
|
||||
this.sortType = st.asUCString;
|
||||
break;
|
||||
case "date":
|
||||
this.sortType = st.asDate;
|
||||
break;
|
||||
default:
|
||||
this.sortType = st.none;
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
Ext.tree.Column = Ext.extend(Ext.list.Column, {});
|
||||
Ext.tree.NumberColumn = Ext.extend(Ext.list.NumberColumn, {});
|
||||
Ext.tree.DateColumn = Ext.extend(Ext.list.DateColumn, {});
|
||||
Ext.tree.BooleanColumn = Ext.extend(Ext.list.BooleanColumn, {});
|
||||
|
||||
Ext.reg('tgcolumn', Ext.tree.Column);
|
||||
Ext.reg('tgnumbercolumn', Ext.tree.NumberColumn);
|
||||
Ext.reg('tgdatecolumn', Ext.tree.DateColumn);
|
||||
Ext.reg('tgbooleancolumn', Ext.tree.BooleanColumn);
|
||||
})();
|
||||
@ -1,18 +0,0 @@
|
||||
/*!
|
||||
* Ext JS Library 3.1.0
|
||||
* Copyright(c) 2006-2009 Ext JS, LLC
|
||||
* licensing@extjs.com
|
||||
* http://www.extjs.com/license
|
||||
*/
|
||||
/**
|
||||
* @class Ext.ux.tree.TreeGridLoader
|
||||
* @extends Ext.tree.TreeLoader
|
||||
*/
|
||||
Ext.ux.tree.TreeGridLoader = Ext.extend(Ext.tree.TreeLoader, {
|
||||
createNode : function(attr) {
|
||||
if (!attr.uiProvider) {
|
||||
attr.uiProvider = Ext.ux.tree.TreeGridNodeUI;
|
||||
}
|
||||
return Ext.tree.TreeLoader.prototype.createNode.call(this, attr);
|
||||
}
|
||||
});
|
||||
@ -1,107 +0,0 @@
|
||||
/*!
|
||||
* Ext JS Library 3.1.0
|
||||
* Copyright(c) 2006-2009 Ext JS, LLC
|
||||
* licensing@extjs.com
|
||||
* http://www.extjs.com/license
|
||||
*/
|
||||
/**
|
||||
* @class Ext.ux.tree.TreeGridNodeUI
|
||||
* @extends Ext.tree.TreeNodeUI
|
||||
*/
|
||||
Ext.ux.tree.TreeGridNodeUI = Ext.extend(Ext.tree.TreeNodeUI, {
|
||||
isTreeGridNodeUI: true,
|
||||
|
||||
renderElements : function(n, a, targetNode, bulkRender){
|
||||
var t = n.getOwnerTree(),
|
||||
cols = t.columns,
|
||||
c = cols[0],
|
||||
i, buf, len;
|
||||
|
||||
this.indentMarkup = n.parentNode ? n.parentNode.ui.getChildIndent() : '';
|
||||
|
||||
buf = [
|
||||
'<tbody class="x-tree-node">',
|
||||
'<tr ext:tree-node-id="', n.id ,'" class="x-tree-node-el ', a.cls, '">',
|
||||
'<td class="x-treegrid-col">',
|
||||
'<span class="x-tree-node-indent">', this.indentMarkup, "</span>",
|
||||
'<img src="', this.emptyIcon, '" class="x-tree-ec-icon x-tree-elbow">',
|
||||
'<img src="', a.icon || this.emptyIcon, '" class="x-tree-node-icon', (a.icon ? " x-tree-node-inline-icon" : ""), (a.iconCls ? " "+a.iconCls : ""), '" unselectable="on">',
|
||||
'<a hidefocus="on" class="x-tree-node-anchor" href="', a.href ? a.href : '#', '" tabIndex="1" ',
|
||||
a.hrefTarget ? ' target="'+a.hrefTarget+'"' : '', '>',
|
||||
'<span unselectable="on">', (c.tpl ? c.tpl.apply(a) : a[c.dataIndex] || c.text), '</span></a>',
|
||||
'</td>'
|
||||
];
|
||||
|
||||
for(i = 1, len = cols.length; i < len; i++){
|
||||
c = cols[i];
|
||||
buf.push(
|
||||
'<td class="x-treegrid-col ', (c.cls ? c.cls : ''), '">',
|
||||
'<div unselectable="on" class="x-treegrid-text"', (c.align ? ' style="text-align: ' + c.align + ';"' : ''), '>',
|
||||
(c.tpl ? c.tpl.apply(a) : a[c.dataIndex]),
|
||||
'</div>',
|
||||
'</td>'
|
||||
);
|
||||
}
|
||||
|
||||
buf.push(
|
||||
'</tr><tr class="x-tree-node-ct"><td colspan="', cols.length, '">',
|
||||
'<table class="x-treegrid-node-ct-table" cellpadding="0" cellspacing="0" style="table-layout: fixed; display: none; width: ', t.innerCt.getWidth() ,'px;"><colgroup>'
|
||||
);
|
||||
for(i = 0, len = cols.length; i<len; i++) {
|
||||
buf.push('<col style="width: ', (cols[i].hidden ? 0 : cols[i].width) ,'px;" />');
|
||||
}
|
||||
buf.push('</colgroup></table></td></tr></tbody>');
|
||||
|
||||
if(bulkRender !== true && n.nextSibling && n.nextSibling.ui.getEl()){
|
||||
this.wrap = Ext.DomHelper.insertHtml("beforeBegin", n.nextSibling.ui.getEl(), buf.join(''));
|
||||
}else{
|
||||
this.wrap = Ext.DomHelper.insertHtml("beforeEnd", targetNode, buf.join(''));
|
||||
}
|
||||
|
||||
this.elNode = this.wrap.childNodes[0];
|
||||
this.ctNode = this.wrap.childNodes[1].firstChild.firstChild;
|
||||
var cs = this.elNode.firstChild.childNodes;
|
||||
this.indentNode = cs[0];
|
||||
this.ecNode = cs[1];
|
||||
this.iconNode = cs[2];
|
||||
this.anchor = cs[3];
|
||||
this.textNode = cs[3].firstChild;
|
||||
},
|
||||
|
||||
// private
|
||||
animExpand : function(cb){
|
||||
this.ctNode.style.display = "";
|
||||
Ext.ux.tree.TreeGridNodeUI.superclass.animExpand.call(this, cb);
|
||||
}
|
||||
});
|
||||
|
||||
Ext.ux.tree.TreeGridRootNodeUI = Ext.extend(Ext.tree.TreeNodeUI, {
|
||||
isTreeGridNodeUI: true,
|
||||
|
||||
// private
|
||||
render : function(){
|
||||
if(!this.rendered){
|
||||
this.wrap = this.ctNode = this.node.ownerTree.innerCt.dom;
|
||||
this.node.expanded = true;
|
||||
}
|
||||
|
||||
if(Ext.isWebKit) {
|
||||
// weird table-layout: fixed issue in webkit
|
||||
var ct = this.ctNode;
|
||||
ct.style.tableLayout = null;
|
||||
(function() {
|
||||
ct.style.tableLayout = 'fixed';
|
||||
}).defer(1);
|
||||
}
|
||||
},
|
||||
|
||||
destroy : function(){
|
||||
if(this.elNode){
|
||||
Ext.dd.Registry.unregister(this.elNode.id);
|
||||
}
|
||||
delete this.node;
|
||||
},
|
||||
|
||||
collapse : Ext.emptyFn,
|
||||
expand : Ext.emptyFn
|
||||
});
|
||||
@ -1,10 +0,0 @@
|
||||
Ext.tree.RenderColumn = Ext.extend(Ext.tree.Column, {
|
||||
|
||||
constructor: function(c) {
|
||||
c.tpl = c.tpl || new Ext.XTemplate('{' + c.dataIndex + ':this.format}');
|
||||
c.tpl.format = c.renderer;
|
||||
c.tpl.col = this;
|
||||
Ext.tree.RenderColumn.superclass.constructor.call(this, c);
|
||||
}
|
||||
});
|
||||
Ext.reg('tgrendercolumn', Ext.tree.RenderColumn);
|
||||
@ -1,116 +0,0 @@
|
||||
/*!
|
||||
* Ext JS Library 3.1.0
|
||||
* Copyright(c) 2006-2009 Ext JS, LLC
|
||||
* licensing@extjs.com
|
||||
* http://www.extjs.com/license
|
||||
*/
|
||||
Ext.ns('Ext.ux.tree');
|
||||
|
||||
/**
|
||||
* @class Ext.ux.tree.TreeGridSorter
|
||||
* @extends Ext.tree.TreeSorter
|
||||
*/
|
||||
Ext.ux.tree.TreeGridSorter = Ext.extend(Ext.tree.TreeSorter, {
|
||||
/**
|
||||
* @cfg {Array} sortClasses The CSS classes applied to a header when it is sorted. (defaults to <tt>['sort-asc', 'sort-desc']</tt>)
|
||||
*/
|
||||
sortClasses : ['sort-asc', 'sort-desc'],
|
||||
/**
|
||||
* @cfg {String} sortAscText The text displayed in the 'Sort Ascending' menu item (defaults to <tt>'Sort Ascending'</tt>)
|
||||
*/
|
||||
sortAscText : 'Sort Ascending',
|
||||
/**
|
||||
* @cfg {String} sortDescText The text displayed in the 'Sort Descending' menu item (defaults to <tt>'Sort Descending'</tt>)
|
||||
*/
|
||||
sortDescText : 'Sort Descending',
|
||||
|
||||
constructor : function(tree, config) {
|
||||
if(!Ext.isObject(config)) {
|
||||
config = {
|
||||
property: tree.columns[0].dataIndex || 'text',
|
||||
folderSort: true
|
||||
}
|
||||
}
|
||||
|
||||
Ext.ux.tree.TreeGridSorter.superclass.constructor.apply(this, arguments);
|
||||
|
||||
this.tree = tree;
|
||||
tree.on('headerclick', this.onHeaderClick, this);
|
||||
tree.ddAppendOnly = true;
|
||||
|
||||
me = this;
|
||||
this.defaultSortFn = function(n1, n2){
|
||||
|
||||
var dsc = me.dir && me.dir.toLowerCase() == 'desc';
|
||||
var p = me.property || 'text';
|
||||
var sortType = me.sortType;
|
||||
var fs = me.folderSort;
|
||||
var cs = me.caseSensitive === true;
|
||||
var leafAttr = me.leafAttr || 'leaf';
|
||||
|
||||
if(fs){
|
||||
if(n1.attributes[leafAttr] && !n2.attributes[leafAttr]){
|
||||
return 1;
|
||||
}
|
||||
if(!n1.attributes[leafAttr] && n2.attributes[leafAttr]){
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
var v1 = sortType ? sortType(n1.attributes[p]) : (cs ? n1.attributes[p] : n1.attributes[p].toUpperCase());
|
||||
var v2 = sortType ? sortType(n2.attributes[p]) : (cs ? n2.attributes[p] : n2.attributes[p].toUpperCase());
|
||||
if(v1 < v2){
|
||||
return dsc ? +1 : -1;
|
||||
}else if(v1 > v2){
|
||||
return dsc ? -1 : +1;
|
||||
}else{
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
|
||||
tree.on('afterrender', this.onAfterTreeRender, this, {single: true});
|
||||
tree.on('headermenuclick', this.onHeaderMenuClick, this);
|
||||
},
|
||||
|
||||
onAfterTreeRender : function() {
|
||||
var hmenu = this.tree.hmenu;
|
||||
hmenu.insert(0,
|
||||
{itemId:'asc', text: this.sortAscText, cls: 'xg-hmenu-sort-asc'},
|
||||
{itemId:'desc', text: this.sortDescText, cls: 'xg-hmenu-sort-desc'}
|
||||
);
|
||||
this.updateSortIcon(0, 'asc');
|
||||
},
|
||||
|
||||
onHeaderMenuClick : function(c, id, index) {
|
||||
if(id === 'asc' || id === 'desc') {
|
||||
this.onHeaderClick(c, null, index);
|
||||
return false;
|
||||
}
|
||||
},
|
||||
|
||||
onHeaderClick : function(c, el, i) {
|
||||
if(c && !this.tree.headersDisabled){
|
||||
var me = this;
|
||||
|
||||
me.property = c.dataIndex;
|
||||
me.dir = c.dir = (c.dir === 'desc' ? 'asc' : 'desc');
|
||||
me.sortType = c.sortType;
|
||||
me.caseSensitive === Ext.isBoolean(c.caseSensitive) ? c.caseSensitive : this.caseSensitive;
|
||||
me.sortFn = c.sortFn || this.defaultSortFn;
|
||||
|
||||
this.tree.root.cascade(function(n) {
|
||||
if(!n.isLeaf()) {
|
||||
me.updateSort(me.tree, n);
|
||||
}
|
||||
});
|
||||
|
||||
this.updateSortIcon(i, c.dir);
|
||||
}
|
||||
},
|
||||
|
||||
// private
|
||||
updateSortIcon : function(col, dir){
|
||||
var sc = this.sortClasses;
|
||||
var hds = this.tree.innerHd.select('td').removeClass(sc);
|
||||
hds.item(col).addClass(sc[dir == 'desc' ? 1 : 0]);
|
||||
}
|
||||
});
|
||||
15
deluge/ui/web/js/ext.js
Normal file
15
deluge/ui/web/js/ext.js
Normal file
File diff suppressed because one or more lines are too long
@ -56,7 +56,7 @@ from deluge.ui.client import client, Client
|
||||
from deluge.ui.coreconfig import CoreConfig
|
||||
from deluge.ui.sessionproxy import SessionProxy
|
||||
|
||||
from deluge.ui.web.common import _, compress
|
||||
from deluge.ui.web.common import Resource, _, compress
|
||||
json = common.json
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
@ -102,14 +102,14 @@ class JSONException(Exception):
|
||||
self.inner_exception = inner_exception
|
||||
Exception.__init__(self, str(inner_exception))
|
||||
|
||||
class JSON(resource.Resource, component.Component):
|
||||
class JSON(Resource, component.Component):
|
||||
"""
|
||||
A Twisted Web resource that exposes a JSON-RPC interface for web clients \
|
||||
to use.
|
||||
"""
|
||||
|
||||
def __init__(self):
|
||||
resource.Resource.__init__(self)
|
||||
Resource.__init__(self)
|
||||
component.Component.__init__(self, "JSON")
|
||||
self._remote_methods = []
|
||||
self._local_methods = {}
|
||||
@ -280,6 +280,7 @@ class JSON(resource.Resource, component.Component):
|
||||
"""
|
||||
Handles all the POST requests made to the /json controller.
|
||||
"""
|
||||
Resource.render(self, request)
|
||||
|
||||
if request.method != "POST":
|
||||
request.setResponseCode(http.NOT_ALLOWED)
|
||||
@ -505,11 +506,11 @@ class WebApi(JSONComponent):
|
||||
d = Deferred()
|
||||
ui_info = {
|
||||
"connected": client.connected(),
|
||||
"torrents": None,
|
||||
"filters": None,
|
||||
"torrents": None,
|
||||
"filters": None,
|
||||
"stats": {
|
||||
"max_download": self.core_config.get("max_download_speed"),
|
||||
"max_upload": self.core_config.get("max_upload_speed"),
|
||||
"max_download": self.core_config.get("max_download_speed"),
|
||||
"max_upload": self.core_config.get("max_upload_speed"),
|
||||
"max_num_connections": self.core_config.get("max_connections_global")
|
||||
}
|
||||
}
|
||||
@ -567,7 +568,7 @@ class WebApi(JSONComponent):
|
||||
dl.addCallback(on_complete)
|
||||
return d
|
||||
|
||||
def _on_got_files(self, torrent, d):
|
||||
def _on_got_files(self, torrent):
|
||||
files = torrent.get("files")
|
||||
file_progress = torrent.get("file_progress")
|
||||
file_priorities = torrent.get("file_priorities")
|
||||
@ -610,11 +611,11 @@ class WebApi(JSONComponent):
|
||||
|
||||
file_tree = uicommon.FileTree2(paths)
|
||||
file_tree.walk(walk)
|
||||
d.callback(file_tree.get_tree())
|
||||
return file_tree.get_tree()
|
||||
|
||||
@export
|
||||
def get_torrent_status(self, torrent_id, keys):
|
||||
return component.get("SessionProxy").get_torrent_status(torrent_id, keys)
|
||||
return component.get("SessionProxy").get_torrent_status(torrent_id, map(str, keys))
|
||||
|
||||
@export
|
||||
def get_torrent_files(self, torrent_id):
|
||||
@ -626,10 +627,8 @@ class WebApi(JSONComponent):
|
||||
:returns: The torrents files in a tree
|
||||
:rtype: dictionary
|
||||
"""
|
||||
main_deferred = Deferred()
|
||||
d = component.get("SessionProxy").get_torrent_status(torrent_id, FILES_KEYS)
|
||||
d.addCallback(self._on_got_files, main_deferred)
|
||||
return main_deferred
|
||||
return component.get("SessionProxy").get_torrent_status(torrent_id, FILES_KEYS
|
||||
).addCallback(self._on_got_files)
|
||||
|
||||
@export
|
||||
def download_torrent_from_url(self, url, cookie=None):
|
||||
@ -729,8 +728,7 @@ class WebApi(JSONComponent):
|
||||
"""
|
||||
Return the hosts in the hostlist.
|
||||
"""
|
||||
log.debug("get_hosts called")
|
||||
return [(tuple(host[HOSTS_ID:HOSTS_PORT+1]) + (_("Offline"),)) for host in self.host_list["hosts"]]
|
||||
return [dict(zip(('id', 'host', 'port', 'status'), tuple(host[HOSTS_ID:HOSTS_PORT+1]) + (_("Offline"),))) for host in self.host_list["hosts"]]
|
||||
|
||||
@export
|
||||
def get_host_status(self, host_id):
|
||||
@ -742,12 +740,18 @@ class WebApi(JSONComponent):
|
||||
"""
|
||||
|
||||
def response(status, info=None):
|
||||
return host_id, host, port, status, info
|
||||
return dict (
|
||||
id = host_id,
|
||||
host = host,
|
||||
port = port,
|
||||
status = status,
|
||||
version = info
|
||||
)
|
||||
|
||||
try:
|
||||
host_id, host, port, user, password = self.get_host(host_id)
|
||||
except TypeError, e:
|
||||
return response(_("Offline"))
|
||||
return None
|
||||
|
||||
def on_connect(connected, c, host_id):
|
||||
def on_info(info, c):
|
||||
|
||||
1
deluge/ui/web/resources/css/ext-all-access.css
Normal file
1
deluge/ui/web/resources/css/ext-all-access.css
Normal file
File diff suppressed because one or more lines are too long
1
deluge/ui/web/resources/css/ext-all-gray.css
Normal file
1
deluge/ui/web/resources/css/ext-all-gray.css
Normal file
File diff suppressed because one or more lines are too long
1
deluge/ui/web/resources/css/ext-all-scoped.css
Normal file
1
deluge/ui/web/resources/css/ext-all-scoped.css
Normal file
File diff suppressed because one or more lines are too long
1
deluge/ui/web/resources/css/ext-all.css
Normal file
1
deluge/ui/web/resources/css/ext-all.css
Normal file
File diff suppressed because one or more lines are too long
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user