mirror of
https://git.deluge-torrent.org/deluge
synced 2025-04-20 19:44:52 +00:00
* Added dump_torrent_info_file() to core to just list files in torrent by its
filename. * Replaced all file filters in torrents with priorities. Nothing to see in UI yet. Based on patch from eternalswd.
This commit is contained in:
parent
89972e1e54
commit
6a22d12975
5 changed files with 233 additions and 170 deletions
113
src/core.py
113
src/core.py
|
@ -47,14 +47,13 @@
|
|||
# time to calculate, so we do if efficiently
|
||||
# 3. supp_torrent_state - supplementary torrent data, from Deluge
|
||||
|
||||
import deluge_core
|
||||
import pickle
|
||||
import os
|
||||
import os.path
|
||||
import shutil
|
||||
import statvfs
|
||||
import pickle
|
||||
import time
|
||||
import gettext
|
||||
|
||||
import deluge_core
|
||||
import pref
|
||||
|
||||
# Constants
|
||||
|
@ -167,8 +166,8 @@ class persistent_state:
|
|||
self.torrents = []
|
||||
|
||||
# Prepare queue (queue is pickled, just like everything else)
|
||||
self.queue = [] # queue[x] is the unique_ID of the x-th queue position. Simple.
|
||||
|
||||
# queue[x] is the unique_ID of the x-th queue position. Simple.
|
||||
self.queue = []
|
||||
|
||||
# The manager for the torrent system
|
||||
|
||||
|
@ -236,15 +235,18 @@ class Manager:
|
|||
# Unpickle the state, or create a new one
|
||||
if not blank_slate:
|
||||
try:
|
||||
pkl_file = open(os.path.join(self.base_dir, STATE_FILENAME), 'rb')
|
||||
pkl_file = open(os.path.join(self.base_dir, STATE_FILENAME),
|
||||
'rb')
|
||||
self.state = pickle.load(pkl_file)
|
||||
pkl_file.close()
|
||||
|
||||
# Sync with the core: tell core about torrents, and get unique_IDs
|
||||
# Sync with the core: tell core about torrents, and get
|
||||
# unique_IDs
|
||||
self.sync()
|
||||
|
||||
# Apply all the file filters, right after adding the torrents
|
||||
self.apply_all_file_filters()
|
||||
# Apply all the file priorities, right after adding the
|
||||
# torrents
|
||||
self.apply_all_file_priorities()
|
||||
|
||||
# Apply the queue at this time, after all is loaded and ready
|
||||
self.apply_queue()
|
||||
|
@ -262,10 +264,7 @@ class Manager:
|
|||
self.config.save()
|
||||
|
||||
# Pickle the state
|
||||
print "Pickling state..."
|
||||
output = open(os.path.join(self.base_dir, STATE_FILENAME), 'wb')
|
||||
pickle.dump(self.state, output)
|
||||
output.close()
|
||||
self.pickle_state()
|
||||
|
||||
# Stop DHT, if needed
|
||||
self.set_DHT(False)
|
||||
|
@ -278,6 +277,18 @@ class Manager:
|
|||
print "Quitting the core..."
|
||||
deluge_core.quit()
|
||||
|
||||
def pickle_state(self):
|
||||
# Pickle the state so if we experience a crash, the latest state is
|
||||
# available
|
||||
print "Pickling state..."
|
||||
|
||||
#print self.state.torrents
|
||||
#print self.state.queue
|
||||
|
||||
output = open(os.path.join(self.base_dir, STATE_FILENAME), 'wb')
|
||||
pickle.dump(self.state, output)
|
||||
output.close()
|
||||
|
||||
def pre_quitting(self):
|
||||
# Save the uploaded data from this session to the existing upload memory
|
||||
for unique_ID in self.unique_IDs.keys():
|
||||
|
@ -306,6 +317,10 @@ class Manager:
|
|||
if PREF_FUNCTIONS[key] is not None:
|
||||
PREF_FUNCTIONS[key](value)
|
||||
|
||||
# Dump torrent info without adding
|
||||
def dump_torrent_file_info(self, torrent):
|
||||
return deluge_core.dump_file_info(torrent)
|
||||
|
||||
# Torrent addition and removal functions
|
||||
|
||||
def add_torrent(self, filename, save_dir, compact):
|
||||
|
@ -393,14 +408,13 @@ class Manager:
|
|||
# This is the EXTERNAL function, for the GUI. It returns the core_state + supp_state
|
||||
def get_torrent_state(self, unique_ID):
|
||||
# Check to see if unique_ID exists:
|
||||
if self.state.queue.count(unique_ID) == 0:
|
||||
if unique_ID not in self.state.queue:
|
||||
raise InvalidUniqueIDError(_("Asked for a torrent that doesn't exist"))
|
||||
|
||||
ret = self.get_core_torrent_state(unique_ID, True).copy()
|
||||
|
||||
# Add the deluge-level things to the deluge_core data
|
||||
if self.get_supp_torrent_state(unique_ID) is not None:
|
||||
ret.update(self.get_supp_torrent_state(unique_ID))
|
||||
ret.update(self.get_supp_torrent_state(unique_ID))
|
||||
|
||||
# Get queue position
|
||||
ret['queue_pos'] = self.state.queue.index(unique_ID)
|
||||
|
@ -604,30 +618,30 @@ class Manager:
|
|||
|
||||
return ret
|
||||
|
||||
# Filtering functions
|
||||
|
||||
def set_file_filter(self, unique_ID, file_filter):
|
||||
assert(len(file_filter) == self.get_core_torrent_state(unique_ID, True)['num_files'])
|
||||
|
||||
self.unique_IDs[unique_ID].file_filter = file_filter[:]
|
||||
|
||||
deluge_core.set_filter_out(unique_ID, file_filter)
|
||||
|
||||
def get_file_filter(self, unique_ID):
|
||||
try:
|
||||
return self.unique_IDs[unique_ID].file_filter[:]
|
||||
except AttributeError:
|
||||
return None
|
||||
|
||||
# Priorities functions
|
||||
def prioritize_files(self, unique_ID, priorities):
|
||||
assert(len(priorities) == self.get_core_torrent_state(unique_ID,
|
||||
True)['num_files'])
|
||||
|
||||
self.unique_IDs[unique_ID].priorities = priorities[:]
|
||||
deluge_core.prioritize_files(unique_ID, priorities)
|
||||
|
||||
# Called when a session starts, to apply existing filters
|
||||
def apply_all_file_filters(self):
|
||||
def get_priorities(self, unique_ID):
|
||||
try:
|
||||
return self.unique_IDs[unique_ID].priorities[:]
|
||||
except AttributeError:
|
||||
# return normal priority for all files by default
|
||||
|
||||
num_files = self.get_core_torrent_state(unique_ID,
|
||||
True)['num_files']
|
||||
return [1] * num_files
|
||||
|
||||
# Called when a session starts, to apply existing priorities
|
||||
def apply_all_file_priorities(self):
|
||||
for unique_ID in self.unique_IDs.keys():
|
||||
try:
|
||||
self.set_file_filter(unique_ID, self.unique_IDs[unique_ID].file_filter)
|
||||
self.prioritize_files(unique_ID,
|
||||
self.get_priorities(unique_ID))
|
||||
except AttributeError:
|
||||
pass
|
||||
|
||||
|
@ -673,8 +687,9 @@ class Manager:
|
|||
|
||||
# Efficient: use a saved state, if it hasn't expired yet
|
||||
def get_core_torrent_state(self, unique_ID, efficiently=True):
|
||||
if unique_ID not in self.saved_core_torrent_states.keys():
|
||||
self.saved_core_torrent_states[unique_ID] = cached_data(deluge_core.get_torrent_state, unique_ID)
|
||||
if unique_ID not in self.saved_core_torrent_states:
|
||||
self.saved_core_torrent_states[unique_ID] = \
|
||||
cached_data(deluge_core.get_torrent_state, unique_ID)
|
||||
|
||||
return self.saved_core_torrent_states[unique_ID].get(efficiently)
|
||||
|
||||
|
@ -682,7 +697,7 @@ class Manager:
|
|||
try:
|
||||
return self.supp_torrent_states[unique_ID]
|
||||
except KeyError:
|
||||
return None
|
||||
return {}
|
||||
|
||||
def set_supp_torrent_state_val(self, unique_ID, key, val):
|
||||
try:
|
||||
|
@ -754,19 +769,17 @@ class Manager:
|
|||
no_space = False
|
||||
|
||||
# Add torrents to core and unique_IDs
|
||||
torrents_with_unique_ID = self.unique_IDs.values()
|
||||
|
||||
for torrent in self.state.torrents:
|
||||
if not os.path.exists(torrent.filename):
|
||||
print "Missing file: %s" % torrent.filename
|
||||
self.state.torrents.remove(torrent)
|
||||
continue
|
||||
if torrent not in torrents_with_unique_ID:
|
||||
if torrent not in self.unique_IDs.values():
|
||||
# print "Adding torrent to core:", torrent.filename, torrent.save_dir, torrent.compact
|
||||
try:
|
||||
unique_ID = deluge_core.add_torrent(torrent.filename,
|
||||
torrent.save_dir,
|
||||
torrent.compact)
|
||||
torrent.save_dir,
|
||||
torrent.compact)
|
||||
except DelugeError, e:
|
||||
print "Error:", e
|
||||
self.state.torrents.remove(torrent)
|
||||
|
@ -775,9 +788,7 @@ class Manager:
|
|||
|
||||
ret = unique_ID
|
||||
self.unique_IDs[unique_ID] = torrent
|
||||
|
||||
|
||||
# print torrents_with_unique_ID
|
||||
# Remove torrents from core, unique_IDs and queue
|
||||
to_delete = []
|
||||
for unique_ID in self.unique_IDs.keys():
|
||||
|
@ -800,8 +811,9 @@ class Manager:
|
|||
# Add torrents to queue - at the end, of course
|
||||
for unique_ID in self.unique_IDs.keys():
|
||||
if unique_ID not in self.state.queue:
|
||||
if (self.get_pref('queue_above_completed')) and len(self.state.queue) > 0:
|
||||
for index in range(len(self.state.queue)):
|
||||
if self.get_pref('queue_above_completed') and \
|
||||
len(self.state.queue) > 0:
|
||||
for index in xrange(len(self.state.queue)):
|
||||
torrent_state = self.get_core_torrent_state(self.state.queue[index])
|
||||
if torrent_state['progress'] == 1.0:
|
||||
break
|
||||
|
@ -827,11 +839,8 @@ class Manager:
|
|||
|
||||
#if no_space:
|
||||
#self.apply_queue()
|
||||
# Pickle the state so if we experience a crash, the latest state is available
|
||||
print "Pickling state..."
|
||||
output = open(os.path.join(self.base_dir, STATE_FILENAME), 'wb')
|
||||
pickle.dump(self.state, output)
|
||||
output.close()
|
||||
|
||||
self.pickle_state()
|
||||
|
||||
return ret
|
||||
|
||||
|
|
|
@ -97,7 +97,6 @@ using namespace libtorrent;
|
|||
//-----------------
|
||||
|
||||
typedef long unique_ID_t;
|
||||
typedef std::vector<bool> filter_out_t;
|
||||
typedef std::string torrent_name_t;
|
||||
|
||||
struct torrent_t
|
||||
|
@ -179,6 +178,17 @@ long get_index_from_unique_ID(long unique_ID)
|
|||
RAISE_INT(DelugeError, "No such unique_ID.");
|
||||
}
|
||||
|
||||
torrent_info internal_dump_file_info(std::string const& torrent_name)
|
||||
{
|
||||
std::ifstream in(torrent_name.c_str(), std::ios_base::binary);
|
||||
in.unsetf(std::ios_base::skipws);
|
||||
entry e;
|
||||
e = bdecode(std::istream_iterator<char>(in), std::istream_iterator<char>());
|
||||
|
||||
torrent_info t(e);
|
||||
|
||||
return t;
|
||||
}
|
||||
|
||||
long internal_add_torrent(std::string const& torrent_name,
|
||||
float preferred_ratio,
|
||||
|
@ -512,6 +522,34 @@ static PyObject *torrent_set_max_connections(PyObject *self, PyObject *args)
|
|||
Py_INCREF(Py_None); return Py_None;
|
||||
}
|
||||
|
||||
static PyObject *torrent_dump_file_info(PyObject *self, PyObject *args)
|
||||
{
|
||||
const char *name;
|
||||
if (!PyArg_ParseTuple(args, "s", &name))
|
||||
return NULL;
|
||||
|
||||
torrent_info t = internal_dump_file_info(name);
|
||||
|
||||
PyObject *file_info;
|
||||
long file_index = 0;
|
||||
PyObject *ret = PyTuple_New(t.num_files());
|
||||
|
||||
for(torrent_info::file_iterator i = t.begin_files(); i != t.end_files(); ++i)
|
||||
{
|
||||
file_entry const &currFile = (*i);
|
||||
|
||||
file_info = Py_BuildValue(
|
||||
"{s:s,s:L}",
|
||||
"path", currFile.path.string().c_str(),
|
||||
"size", currFile.size
|
||||
);
|
||||
|
||||
PyTuple_SetItem(ret, file_index, file_info);
|
||||
file_index++;
|
||||
};
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static PyObject *torrent_add_torrent(PyObject *self, PyObject *args)
|
||||
{
|
||||
|
@ -1011,35 +1049,6 @@ static PyObject *torrent_get_file_info(PyObject *self, PyObject *args)
|
|||
return ret;
|
||||
};
|
||||
|
||||
static PyObject *torrent_set_filter_out(PyObject *self, PyObject *args)
|
||||
{
|
||||
python_long unique_ID;
|
||||
PyObject *filter_out_object;
|
||||
if (!PyArg_ParseTuple(args, "iO", &unique_ID, &filter_out_object))
|
||||
return NULL;
|
||||
|
||||
long index = get_index_from_unique_ID(unique_ID);
|
||||
if (PyErr_Occurred())
|
||||
return NULL;
|
||||
|
||||
torrent_t &t = M_torrents->at(index);
|
||||
long num_files = t.handle.get_torrent_info().num_files();
|
||||
assert(PyList_Size(filter_out_object) == num_files);
|
||||
|
||||
filter_out_t filter_out(num_files);
|
||||
|
||||
for (long i = 0; i < num_files; i++)
|
||||
{
|
||||
filter_out.at(i) =
|
||||
PyInt_AsLong(PyList_GetItem(filter_out_object, i));
|
||||
};
|
||||
|
||||
t.handle.filter_files(filter_out);
|
||||
|
||||
Py_INCREF(Py_None); return Py_None;
|
||||
}
|
||||
|
||||
|
||||
/*static PyObject *torrent_get_unique_IDs(PyObject *self, PyObject *args)
|
||||
{
|
||||
PyObject *ret = PyTuple_New(M_torrents.size());
|
||||
|
@ -1521,7 +1530,7 @@ static PyMethodDef deluge_core_methods[] =
|
|||
{"get_session_info", torrent_get_session_info, METH_VARARGS, "."},
|
||||
{"get_peer_info", torrent_get_peer_info, METH_VARARGS, "."},
|
||||
{"get_file_info", torrent_get_file_info, METH_VARARGS, "."},
|
||||
{"set_filter_out", torrent_set_filter_out, METH_VARARGS, "."},
|
||||
{"dump_file_info", torrent_dump_file_info, METH_VARARGS, "."},
|
||||
{"constants", torrent_constants, METH_VARARGS, "."},
|
||||
{"start_DHT", torrent_start_DHT, METH_VARARGS, "."},
|
||||
{"stop_DHT", torrent_stop_DHT, METH_VARARGS, "."},
|
||||
|
|
|
@ -202,22 +202,18 @@ class PreferencesDlg:
|
|||
self.glade.get_widget('txt_tray_passwd').set_sensitive(value)
|
||||
|
||||
class FilesDlg:
|
||||
def __init__(self, manager, unique_id):
|
||||
def __init__(self, dumped_torrent):
|
||||
self.glade = gtk.glade.XML(common.get_glade_file("files_dialog.glade"),
|
||||
domain='deluge')
|
||||
self.dialog = self.glade.get_widget("file_dialog")
|
||||
self.dialog.set_icon_from_file(common.get_pixmap("deluge32.png"))
|
||||
self.file_view = self.glade.get_widget("file_view")
|
||||
|
||||
self.manager = manager
|
||||
self.unique_id = unique_id
|
||||
self.files_manager = files.FilesManager(manager, False)
|
||||
self.files_manager = files.FilesDialogManager(dumped_torrent)
|
||||
self.files_manager.build_file_view(self.file_view)
|
||||
self.files_manager.prepare_file_store()
|
||||
|
||||
def show(self):
|
||||
self.files_manager.use_unique_id(self.unique_id)
|
||||
self.files_manager.prepare_store()
|
||||
|
||||
#clear private setting
|
||||
self.glade.get_widget("chk_setpriv").set_active(False)
|
||||
|
||||
|
@ -229,6 +225,9 @@ class FilesDlg:
|
|||
self.manager.set_priv(self.unique_id, True)
|
||||
|
||||
return r
|
||||
|
||||
def get_priorities(self):
|
||||
return self.files_manager.get_priorities()
|
||||
|
||||
class PluginDlg:
|
||||
def __init__(self, plugins):
|
||||
|
|
164
src/files.py
164
src/files.py
|
@ -36,10 +36,10 @@ import common
|
|||
from itertools import izip
|
||||
import gobject
|
||||
|
||||
class FilesManager:
|
||||
def __init__(self, manager, is_file_tab):
|
||||
self.manager = manager
|
||||
self.file_glade = gtk.glade.XML(common.get_glade_file("file_tab_menu.glade"), domain='deluge')
|
||||
class FilesBaseManager(object):
|
||||
def __init__(self, file_store):
|
||||
self.file_glade = gtk.glade.XML(common.get_glade_file("file_tab_menu.glade"),
|
||||
domain='deluge')
|
||||
self.file_menu = self.file_glade.get_widget("file_tab_menu")
|
||||
self.file_glade.signal_autoconnect({
|
||||
"select_all": self.file_select_all,
|
||||
|
@ -47,33 +47,25 @@ class FilesManager:
|
|||
"check_selected": self.file_check_selected,
|
||||
"uncheck_selected": self.file_uncheck_selected,
|
||||
})
|
||||
self.file_unique_id = -1
|
||||
self.is_file_tab = is_file_tab
|
||||
# Stores file path -> gtk.TreeIter's iter mapping for quick look up
|
||||
# in self.update_torrent_info_widget
|
||||
self.file_store_dict = {}
|
||||
if self.is_file_tab:
|
||||
self.file_store = gtk.ListStore(bool, str, gobject.TYPE_UINT64, float)
|
||||
else:
|
||||
self.file_store = gtk.ListStore(bool, str, gobject.TYPE_UINT64)
|
||||
|
||||
self.file_store = file_store
|
||||
# We need file_store_sorted so original file_store keeps unchanged
|
||||
# when file_view is sorted. And from file_store we have to pass
|
||||
# files priorities to manager.prioritize_files() in the exact same
|
||||
# order as we get files from manager.get_torrent_file_info()
|
||||
self.file_store_sorted = gtk.TreeModelSort(self.file_store)
|
||||
|
||||
def use_unique_id(self, unique_id):
|
||||
self.file_unique_id = unique_id
|
||||
|
||||
def build_file_view(self, file_view):
|
||||
self.file_view = file_view
|
||||
def percent(column, cell, model, iter, data):
|
||||
percent = float(model.get_value(iter, data))
|
||||
percent_str = "%.2f%%"%percent
|
||||
cell.set_property("text", percent_str)
|
||||
self.file_selected = []
|
||||
self.toggle_column = dgtk.add_toggle_column(self.file_view, _("Download"), 0, toggled_signal=self.file_toggled)
|
||||
|
||||
self.toggle_column = dgtk.add_toggle_column(self.file_view,
|
||||
_("Priority"), 0,
|
||||
toggled_signal=self.file_toggled)
|
||||
self.filename_column = dgtk.add_text_column(self.file_view, _("Filename"), 1)
|
||||
self.filename_column.set_expand(True)
|
||||
self.size_column = dgtk.add_func_column(self.file_view, _("Size"), dgtk.cell_data_size, 2)
|
||||
if self.is_file_tab:
|
||||
dgtk.add_func_column(self.file_view, _("Progress"), percent, 3)
|
||||
|
||||
self.file_view.set_model(self.file_store_sorted)
|
||||
self.file_view.get_selection().set_mode(gtk.SELECTION_MULTIPLE)
|
||||
self.file_view.get_selection().set_select_function(self.file_clicked)
|
||||
|
@ -82,33 +74,10 @@ class FilesManager:
|
|||
def clear_file_store(self):
|
||||
self.file_store.clear()
|
||||
self.file_store_dict = {}
|
||||
|
||||
def prepare_store(self):
|
||||
if not self.file_store_dict:
|
||||
all_files = self.manager.get_torrent_file_info(self.file_unique_id)
|
||||
file_filter = self.manager.get_file_filter(self.file_unique_id)
|
||||
if file_filter is None:
|
||||
file_filter = [False] * len(all_files)
|
||||
if self.is_file_tab:
|
||||
for file, filt in izip(all_files, file_filter):
|
||||
iter = self.file_store.append([not filt, file['path'],
|
||||
file['size'],
|
||||
round(file['progress'], 2)])
|
||||
self.file_store_dict[file['path']] = iter
|
||||
else:
|
||||
for file, filt in izip(all_files, file_filter):
|
||||
iter = self.file_store.append([not filt, file['path'],
|
||||
file['size']])
|
||||
self.file_store_dict[file['path']] = iter
|
||||
|
||||
|
||||
def update_store(self):
|
||||
new_file_info = self.manager.get_torrent_file_info(self.file_unique_id)
|
||||
for file in new_file_info:
|
||||
iter = self.file_store_dict[file['path']]
|
||||
if self.file_store.get_value(iter, 3) != round(file['progress'], 2):
|
||||
self.file_store.set(iter, 3, file['progress'])
|
||||
|
||||
|
||||
def prepare_file_store(self):
|
||||
pass
|
||||
|
||||
def file_select_all(self, widget):
|
||||
self.file_view.get_selection().select_all()
|
||||
|
||||
|
@ -117,11 +86,11 @@ class FilesManager:
|
|||
|
||||
def file_check_selected(self, widget):
|
||||
self.file_view.get_selection().selected_foreach(self.file_toggle_selected, True)
|
||||
self.file_toggled_update_filter()
|
||||
self.file_toggled_update_priorities()
|
||||
|
||||
def file_uncheck_selected(self, widget):
|
||||
self.file_view.get_selection().selected_foreach(self.file_toggle_selected, False)
|
||||
self.file_toggled_update_filter()
|
||||
self.file_toggled_update_priorities()
|
||||
|
||||
def file_clicked(self, path):
|
||||
return not self.file_selected
|
||||
|
@ -137,22 +106,97 @@ class FilesManager:
|
|||
def file_toggle_selected(self, treemodel, path, selected_iter, value):
|
||||
child_iter = self.file_store_sorted.convert_iter_to_child_iter(None,
|
||||
selected_iter)
|
||||
self.file_store_sorted.get_model().set_value(child_iter, 0, value)
|
||||
|
||||
if value:
|
||||
new_value = 1
|
||||
else:
|
||||
new_value = 0
|
||||
self.file_store_sorted.get_model().set_value(child_iter, 0, new_value)
|
||||
|
||||
def file_toggled(self, renderer, path):
|
||||
self.file_selected = True
|
||||
file_iter = self.file_store_sorted.get_iter_from_string(path)
|
||||
|
||||
value = not renderer.get_active()
|
||||
if value:
|
||||
new_value = 1
|
||||
else:
|
||||
new_value = 0
|
||||
|
||||
file_iter = self.file_store_sorted.get_iter_from_string(path)
|
||||
selection = self.file_view.get_selection()
|
||||
if selection.iter_is_selected(file_iter):
|
||||
selection.selected_foreach(self.file_toggle_selected, value)
|
||||
else:
|
||||
child_iter = self.file_store_sorted.convert_iter_to_child_iter(
|
||||
None, file_iter)
|
||||
self.file_store_sorted.get_model().set_value(child_iter, 0, value)
|
||||
self.file_store_sorted.get_model().set_value(child_iter, 0,
|
||||
new_value)
|
||||
self.file_toggled_update_priorities()
|
||||
|
||||
def file_toggled_update_priorities(self):
|
||||
pass
|
||||
|
||||
class FilesTabManager(FilesBaseManager):
|
||||
def __init__(self, manager):
|
||||
file_store = gtk.ListStore(int, str, gobject.TYPE_UINT64, float)
|
||||
|
||||
self.file_toggled_update_filter()
|
||||
super(FilesTabManager, self).__init__(file_store)
|
||||
|
||||
self.manager = manager
|
||||
self.file_unique_id = None
|
||||
|
||||
def file_toggled_update_filter(self):
|
||||
file_filter = [not x[0] for x in self.file_store]
|
||||
self.manager.set_file_filter(self.file_unique_id, file_filter)
|
||||
# Stores file path -> gtk.TreeIter's iter mapping for quick look up
|
||||
# in self.update_file_store()
|
||||
self.file_store_dict = {}
|
||||
|
||||
def build_file_view(self, file_view):
|
||||
super(FilesTabManager, self).build_file_view(file_view)
|
||||
|
||||
def percent(column, cell, model, iter, data):
|
||||
percent = float(model.get_value(iter, data))
|
||||
percent_str = "%.2f%%"%percent
|
||||
cell.set_property("text", percent_str)
|
||||
dgtk.add_func_column(file_view, _("Progress"), percent, 3)
|
||||
|
||||
def set_unique_id(self, unique_id):
|
||||
self.file_unique_id = unique_id
|
||||
|
||||
def prepare_file_store(self):
|
||||
if not self.file_store_dict:
|
||||
all_files = self.manager.get_torrent_file_info(self.file_unique_id)
|
||||
file_priorities = self.manager.get_priorities(self.file_unique_id)
|
||||
for file, priority in izip(all_files, file_priorities):
|
||||
iter = self.file_store.append([priority, file['path'],
|
||||
file['size'],
|
||||
round(file['progress'], 2)])
|
||||
self.file_store_dict[file['path']] = iter
|
||||
|
||||
def update_file_store(self):
|
||||
new_file_info = self.manager.get_torrent_file_info(self.file_unique_id)
|
||||
for file in new_file_info:
|
||||
iter = self.file_store_dict[file['path']]
|
||||
if self.file_store.get_value(iter, 3) != round(file['progress'], 2):
|
||||
self.file_store.set(iter, 3, file['progress'])
|
||||
|
||||
def file_toggled_update_priorities(self):
|
||||
file_priorities = []
|
||||
for x in self.file_store:
|
||||
file_priorities.append(x[0])
|
||||
self.manager.prioritize_files(self.file_unique_id, file_priorities)
|
||||
|
||||
class FilesDialogManager(FilesBaseManager):
|
||||
def __init__(self, dumped_torrent):
|
||||
file_store = gtk.ListStore(int, str, gobject.TYPE_UINT64)
|
||||
super(FilesDialogManager, self).__init__(file_store)
|
||||
|
||||
self.dumped_torrent = dumped_torrent
|
||||
|
||||
def prepare_file_store(self):
|
||||
for file in self.dumped_torrent:
|
||||
self.file_store.append([1, file['path'], file['size']])
|
||||
|
||||
def get_priorities(self):
|
||||
file_priorities = []
|
||||
for x in self.file_store:
|
||||
file_priorities.append(x[0])
|
||||
|
||||
return file_priorities
|
||||
|
|
|
@ -63,7 +63,7 @@ class DelugeGTK:
|
|||
#Start the Deluge Manager:
|
||||
self.manager = core.Manager(common.CLIENT_CODE, common.CLIENT_VERSION,
|
||||
'%s %s'%(common.PROGRAM_NAME, common.PROGRAM_VERSION), common.CONFIG_DIR)
|
||||
self.files_for_tab = files.FilesManager(self.manager, True)
|
||||
self.files_tab = files.FilesTabManager(self.manager)
|
||||
self.plugins = plugins.PluginManager(self.manager, self)
|
||||
self.plugins.add_plugin_dir(common.PLUGIN_DIR)
|
||||
if os.path.isdir(os.path.join(common.CONFIG_DIR , 'plugins')):
|
||||
|
@ -636,10 +636,10 @@ class DelugeGTK:
|
|||
self.peer_store_dict = {}
|
||||
|
||||
def build_file_tab(self):
|
||||
self.files_for_tab.build_file_view(self.wtree.get_widget("file_view"))
|
||||
self.files_tab.build_file_view(self.wtree.get_widget("file_view"))
|
||||
|
||||
def clear_file_store(self):
|
||||
self.files_for_tab.clear_file_store()
|
||||
self.files_tab.clear_file_store()
|
||||
|
||||
def show_about_dialog(self, arg=None):
|
||||
dialogs.show_about_dialog()
|
||||
|
@ -1019,9 +1019,9 @@ class DelugeGTK:
|
|||
elif page_num == 2: # Files
|
||||
# Fill self.file_store with files only once and only when we click to
|
||||
# Files tab or it's already open
|
||||
self.files_for_tab.use_unique_id(unique_id)
|
||||
self.files_for_tab.prepare_store()
|
||||
self.files_for_tab.update_store()
|
||||
self.files_tab.set_unique_id(unique_id)
|
||||
self.files_tab.prepare_file_store()
|
||||
self.files_tab.update_file_store()
|
||||
|
||||
|
||||
def calc_share_ratio(self, unique_id, torrent_state):
|
||||
|
@ -1083,7 +1083,20 @@ class DelugeGTK:
|
|||
return
|
||||
|
||||
try:
|
||||
unique_id = self.manager.add_torrent(torrent, path, self.config.get('use_compact_storage'))
|
||||
dumped_torrent = self.manager.dump_torrent_file_info(torrent)
|
||||
if self.config.get('enable_files_dialog') and \
|
||||
len(dumped_torrent) > 1:
|
||||
files_dialog = dialogs.FilesDlg(dumped_torrent)
|
||||
if files_dialog.show() == 1:
|
||||
unique_id = self.manager.add_torrent(torrent, path,
|
||||
self.config.get('use_compact_storage'))
|
||||
self.manager.prioritize_files(unique_id,
|
||||
files_dialog.get_priorities())
|
||||
else:
|
||||
return
|
||||
else:
|
||||
unique_id = self.manager.add_torrent(torrent, path,
|
||||
self.config.get('use_compact_storage'))
|
||||
except core.InvalidEncodingError, e:
|
||||
print "InvalidEncodingError", e
|
||||
dialogs.show_popup_warning(self.window, _("An error occured while trying to add the torrent. It's possible your .torrent file is corrupted."))
|
||||
|
@ -1095,19 +1108,8 @@ class DelugeGTK:
|
|||
dialogs.show_popup_warning(self.window, _("There is not enough free disk space to complete your download.") + "\n" + \
|
||||
_("Space Needed:") + " " + nice_need + "\n" + \
|
||||
_("Available Space:") + " " + nice_free)
|
||||
else:
|
||||
num_files = len(self.manager.get_torrent_file_info(unique_id))
|
||||
if self.config.get('enable_files_dialog') and num_files > 1:
|
||||
self.manager.set_user_pause(unique_id, True)
|
||||
|
||||
files_dialog = dialogs.FilesDlg(self.manager, unique_id)
|
||||
if files_dialog.show() == 1:
|
||||
self.manager.set_user_pause(unique_id, False)
|
||||
self.torrent_model_append(unique_id)
|
||||
else:
|
||||
self.manager.remove_torrent(unique_id, True, True)
|
||||
else:
|
||||
self.torrent_model_append(unique_id)
|
||||
|
||||
self.torrent_model_append(unique_id)
|
||||
|
||||
def launchpad(self, obj=None):
|
||||
common.open_url_in_browser('https://translations.launchpad.net/deluge/trunk/+pots/deluge')
|
||||
|
|
Loading…
Add table
Reference in a new issue