summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--deluge/tests/test_file_tree.py46
-rw-r--r--deluge/ui/common.py77
2 files changed, 123 insertions, 0 deletions
diff --git a/deluge/tests/test_file_tree.py b/deluge/tests/test_file_tree.py
new file mode 100644
index 000000000..34c018e68
--- /dev/null
+++ b/deluge/tests/test_file_tree.py
@@ -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": ""})
diff --git a/deluge/ui/common.py b/deluge/ui/common.py
index 239bb84c9..4ad0f12e4 100644
--- a/deluge/ui/common.py
+++ b/deluge/ui/common.py
@@ -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.