Merge remote-tracking branch 'bro/master-torrentview-speedups'
This commit is contained in:
commit
b4f5e78a77
|
@ -74,11 +74,8 @@ class GtkUI(GtkPluginBase):
|
||||||
self.sidebar_menu.unload()
|
self.sidebar_menu.unload()
|
||||||
del self.sidebar_menu
|
del self.sidebar_menu
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
component.get("TorrentView").remove_column(_("Label"))
|
component.get("TorrentView").remove_column(_("Label"))
|
||||||
log.debug(1.1)
|
log.debug(1.1)
|
||||||
component.get("TorrentView").create_model_filter() #todo:improve.
|
|
||||||
|
|
||||||
except Exception, e:
|
except Exception, e:
|
||||||
log.debug(e)
|
log.debug(e)
|
||||||
|
|
|
@ -237,17 +237,30 @@ class ListView:
|
||||||
model_filter = self.liststore.filter_new()
|
model_filter = self.liststore.filter_new()
|
||||||
model_filter.set_visible_column(
|
model_filter.set_visible_column(
|
||||||
self.columns["filter"].column_indices[0])
|
self.columns["filter"].column_indices[0])
|
||||||
sort_info = None
|
|
||||||
if self.model_filter:
|
|
||||||
sort_info = self.model_filter.get_sort_column_id()
|
|
||||||
|
|
||||||
self.model_filter = gtk.TreeModelSort(model_filter)
|
self.model_filter = gtk.TreeModelSort(model_filter)
|
||||||
if sort_info and sort_info[0] and sort_info[1] > -1:
|
|
||||||
self.model_filter.set_sort_column_id(sort_info[0], sort_info[1])
|
|
||||||
self.set_sort_functions()
|
|
||||||
self.model_filter.connect("sort-column-changed", self.on_model_sort_changed)
|
self.model_filter.connect("sort-column-changed", self.on_model_sort_changed)
|
||||||
self.model_filter.connect("row-inserted", self.on_model_row_inserted)
|
self.model_filter.connect("row-inserted", self.on_model_row_inserted)
|
||||||
self.treeview.set_model(self.model_filter)
|
self.treeview.set_model(self.model_filter)
|
||||||
|
self.set_sort_functions()
|
||||||
|
self.set_model_sort()
|
||||||
|
|
||||||
|
def set_model_sort(self):
|
||||||
|
column_state = self.get_sort_column_from_state()
|
||||||
|
if column_state:
|
||||||
|
self.treeview.get_model().set_sort_column_id(column_state.sort, column_state.sort_order)
|
||||||
|
# Using the default sort column
|
||||||
|
elif self.default_sort_column_id:
|
||||||
|
self.model_filter.set_sort_column_id(self.default_sort_column_id, gtk.SORT_ASCENDING)
|
||||||
|
self.model_filter.set_default_sort_func(None)
|
||||||
|
|
||||||
|
def get_sort_column_from_state(self):
|
||||||
|
"""Find the first (should only be one) state with sort enabled"""
|
||||||
|
if self.state is None:
|
||||||
|
return None
|
||||||
|
for column_state in self.state:
|
||||||
|
if column_state.sort is not None and column_state.sort > -1:
|
||||||
|
return column_state
|
||||||
|
return None
|
||||||
|
|
||||||
def on_model_sort_changed(self, model):
|
def on_model_sort_changed(self, model):
|
||||||
if self.unique_column_id:
|
if self.unique_column_id:
|
||||||
|
@ -281,7 +294,6 @@ class ListView:
|
||||||
return cmp(model[iter1][data], model[iter2][data])
|
return cmp(model[iter1][data], model[iter2][data])
|
||||||
|
|
||||||
def set_sort_functions(self):
|
def set_sort_functions(self):
|
||||||
self.model_filter.set_default_sort_func(None)
|
|
||||||
for column in self.columns.values():
|
for column in self.columns.values():
|
||||||
sort_func = column.sort_func or self.generic_sort_func
|
sort_func = column.sort_func or self.generic_sort_func
|
||||||
self.model_filter.set_sort_func(
|
self.model_filter.set_sort_func(
|
||||||
|
@ -297,6 +309,7 @@ class ListView:
|
||||||
position = index
|
position = index
|
||||||
break
|
break
|
||||||
sort = None
|
sort = None
|
||||||
|
if self.model_filter:
|
||||||
sort_id, order = self.model_filter.get_sort_column_id()
|
sort_id, order = self.model_filter.get_sort_column_id()
|
||||||
if self.get_column_name(sort_id) == column.get_title():
|
if self.get_column_name(sort_id) == column.get_title():
|
||||||
sort = sort_id
|
sort = sort_id
|
||||||
|
@ -449,10 +462,6 @@ class ListView:
|
||||||
self.liststore.foreach(copy_row, (new_list, self.columns))
|
self.liststore.foreach(copy_row, (new_list, self.columns))
|
||||||
|
|
||||||
self.liststore = new_list
|
self.liststore = new_list
|
||||||
# Create the model
|
|
||||||
self.create_model_filter()
|
|
||||||
|
|
||||||
return
|
|
||||||
|
|
||||||
def remove_column(self, header):
|
def remove_column(self, header):
|
||||||
"""Removes the column with the name 'header' from the listview"""
|
"""Removes the column with the name 'header' from the listview"""
|
||||||
|
@ -481,10 +490,11 @@ class ListView:
|
||||||
|
|
||||||
# Create a new liststore
|
# Create a new liststore
|
||||||
self.create_new_liststore()
|
self.create_new_liststore()
|
||||||
|
# Create new model for the treeview
|
||||||
|
self.create_model_filter()
|
||||||
|
|
||||||
# Re-create the menu
|
# Re-create the menu
|
||||||
self.create_checklist_menu()
|
self.create_checklist_menu()
|
||||||
|
|
||||||
return
|
return
|
||||||
|
|
||||||
def add_column(self, header, render, col_types, hidden, position,
|
def add_column(self, header, render, col_types, hidden, position,
|
||||||
|
@ -523,6 +533,10 @@ class ListView:
|
||||||
# Create a new list with the added column
|
# Create a new list with the added column
|
||||||
self.create_new_liststore()
|
self.create_new_liststore()
|
||||||
|
|
||||||
|
# Happens only on columns added after the torrent list has been loaded
|
||||||
|
if self.model_filter:
|
||||||
|
self.create_model_filter()
|
||||||
|
|
||||||
column = self.TreeviewColumn(header)
|
column = self.TreeviewColumn(header)
|
||||||
|
|
||||||
if column_type == "text":
|
if column_type == "text":
|
||||||
|
@ -575,11 +589,6 @@ class ListView:
|
||||||
if tooltip:
|
if tooltip:
|
||||||
column.get_widget().set_tooltip_markup(tooltip)
|
column.get_widget().set_tooltip_markup(tooltip)
|
||||||
|
|
||||||
if default_sort:
|
|
||||||
if self.model_filter.get_sort_column_id()[0] is None:
|
|
||||||
self.model_filter.set_sort_column_id(column_indices[sortid],
|
|
||||||
gtk.SORT_ASCENDING)
|
|
||||||
|
|
||||||
# Check for loaded state and apply
|
# Check for loaded state and apply
|
||||||
column_in_state = False
|
column_in_state = False
|
||||||
if self.state != None:
|
if self.state != None:
|
||||||
|
@ -591,10 +600,6 @@ class ListView:
|
||||||
column.set_sizing(gtk.TREE_VIEW_COLUMN_FIXED)
|
column.set_sizing(gtk.TREE_VIEW_COLUMN_FIXED)
|
||||||
column.set_fixed_width(column_state.width)
|
column.set_fixed_width(column_state.width)
|
||||||
|
|
||||||
if column_state.sort is not None and column_state.sort > -1:
|
|
||||||
self.model_filter.set_sort_column_id(
|
|
||||||
column_state.sort, column_state.sort_order
|
|
||||||
)
|
|
||||||
column.set_visible(column_state.visible)
|
column.set_visible(column_state.visible)
|
||||||
position = column_state.position
|
position = column_state.position
|
||||||
break
|
break
|
||||||
|
|
|
@ -452,18 +452,12 @@ class TorrentView(listview.ListView, component.Component):
|
||||||
{}, status_fields).addCallback(self._on_session_state)
|
{}, status_fields).addCallback(self._on_session_state)
|
||||||
|
|
||||||
def _on_session_state(self, state):
|
def _on_session_state(self, state):
|
||||||
self.treeview.freeze_child_notify()
|
self.add_rows(state)
|
||||||
model = self.treeview.get_model()
|
|
||||||
for torrent_id in state:
|
|
||||||
self.add_row(torrent_id, update=False)
|
|
||||||
self.mark_dirty(torrent_id)
|
|
||||||
self.treeview.set_model(model)
|
|
||||||
self.treeview.thaw_child_notify()
|
|
||||||
self.got_state = True
|
self.got_state = True
|
||||||
# Update the view right away with our status
|
# Update the view right away with our status
|
||||||
self.status = state
|
self.status = state
|
||||||
self.set_columns_to_update()
|
self.set_columns_to_update()
|
||||||
self.update_view()
|
self.update_view(load_new_list=True)
|
||||||
|
|
||||||
def stop(self):
|
def stop(self):
|
||||||
"""Stops the torrentview"""
|
"""Stops the torrentview"""
|
||||||
|
@ -551,43 +545,66 @@ class TorrentView(listview.ListView, component.Component):
|
||||||
# Send a status request
|
# Send a status request
|
||||||
gobject.idle_add(self.send_status_request)
|
gobject.idle_add(self.send_status_request)
|
||||||
|
|
||||||
def update_view(self, columns=None):
|
def update_view(self, load_new_list=False):
|
||||||
"""Update the view. If columns is not None, it will attempt to only
|
"""Update the torrent view model with data we've received."""
|
||||||
update those columns selected.
|
|
||||||
"""
|
|
||||||
filter_column = self.columns["filter"].column_indices[0]
|
filter_column = self.columns["filter"].column_indices[0]
|
||||||
# Update the torrent view model with data we've received
|
|
||||||
status = self.status
|
status = self.status
|
||||||
|
|
||||||
for row in self.liststore:
|
if not load_new_list:
|
||||||
torrent_id = row[self.columns["torrent_id"].column_indices[0]]
|
# Freeze notications while updating
|
||||||
|
self.treeview.freeze_child_notify()
|
||||||
|
|
||||||
if not torrent_id in status.keys():
|
# Get the columns to update from one of the torrents
|
||||||
row[filter_column] = False
|
if status:
|
||||||
else:
|
torrent_id = status.keys()[0]
|
||||||
row[filter_column] = True
|
fields_to_update = []
|
||||||
if torrent_id in self.prev_status and status[torrent_id] == self.prev_status[torrent_id]:
|
|
||||||
# The status dict is the same, so do not update
|
|
||||||
continue
|
|
||||||
|
|
||||||
# Set values for each column in the row
|
|
||||||
for column in self.columns_to_update:
|
for column in self.columns_to_update:
|
||||||
column_index = self.get_column_index(column)
|
column_index = self.get_column_index(column)
|
||||||
for i, status_field in enumerate(self.columns[column].status_field):
|
for i, status_field in enumerate(self.columns[column].status_field):
|
||||||
|
# Only use columns that the torrent has in the state
|
||||||
if status_field in status[torrent_id]:
|
if status_field in status[torrent_id]:
|
||||||
|
fields_to_update.append((column_index[i], status_field))
|
||||||
|
|
||||||
|
for row in self.liststore:
|
||||||
|
torrent_id = row[self.columns["torrent_id"].column_indices[0]]
|
||||||
|
# We expect the torrent_id to be in status and prev_status,
|
||||||
|
# as it will be as long as the list isn't changed by the user
|
||||||
|
|
||||||
|
torrent_id_in_status = False
|
||||||
try:
|
try:
|
||||||
# Only update if different
|
torrent_status = status[torrent_id]
|
||||||
|
torrent_id_in_status = True
|
||||||
|
if torrent_status == self.prev_status[torrent_id]:
|
||||||
|
# The status dict is the same, so do nothing to update for this torrent
|
||||||
|
continue
|
||||||
|
except KeyError, e:
|
||||||
|
pass
|
||||||
|
|
||||||
|
if not torrent_id_in_status:
|
||||||
|
if row[filter_column] is True:
|
||||||
|
row[filter_column] = False
|
||||||
|
else:
|
||||||
|
if row[filter_column] is False:
|
||||||
|
row[filter_column] = True
|
||||||
|
|
||||||
|
# Find the fields to update
|
||||||
|
to_update = []
|
||||||
|
for i, status_field in fields_to_update:
|
||||||
row_value = status[torrent_id][status_field]
|
row_value = status[torrent_id][status_field]
|
||||||
if row[column_index[i]] != row_value:
|
if row[i] != row_value:
|
||||||
row[column_index[i]] = row_value
|
to_update.append(i)
|
||||||
except Exception, e:
|
to_update.append(row_value)
|
||||||
log.debug("Error while updating row for column "
|
# Update fields in the liststore
|
||||||
"index %d, status field %r, value %r:"
|
if to_update:
|
||||||
" %s", column_index[0], status_field,
|
self.liststore.set(row.iter, *to_update)
|
||||||
row_value, e)
|
|
||||||
|
if load_new_list:
|
||||||
|
# Create the model filter. This sets the model for the treeview and enables sorting.
|
||||||
|
self.create_model_filter()
|
||||||
|
else:
|
||||||
|
self.treeview.thaw_child_notify()
|
||||||
|
|
||||||
component.get("MenuBar").update_menu()
|
component.get("MenuBar").update_menu()
|
||||||
|
|
||||||
self.prev_status = status
|
self.prev_status = status
|
||||||
|
|
||||||
def _on_get_torrents_status(self, status):
|
def _on_get_torrents_status(self, status):
|
||||||
|
@ -602,6 +619,16 @@ class TorrentView(listview.ListView, component.Component):
|
||||||
return
|
return
|
||||||
gobject.idle_add(self.update_view)
|
gobject.idle_add(self.update_view)
|
||||||
|
|
||||||
|
def add_rows(self, state):
|
||||||
|
"""Adds all the torrents from state to self.liststore"""
|
||||||
|
torrent_id_column = self.columns["torrent_id"].column_indices[0]
|
||||||
|
dirty_column = self.columns["dirty"].column_indices[0]
|
||||||
|
filter_column = self.columns["filter"].column_indices[0]
|
||||||
|
for i, torrent_id in enumerate(state):
|
||||||
|
# Insert a new row to the liststore
|
||||||
|
row = self.liststore.append()
|
||||||
|
self.liststore.set(row, torrent_id_column, torrent_id, dirty_column, True, filter_column, True)
|
||||||
|
|
||||||
def add_row(self, torrent_id, update=True):
|
def add_row(self, torrent_id, update=True):
|
||||||
"""Adds a new torrent row to the treeview"""
|
"""Adds a new torrent row to the treeview"""
|
||||||
# Make sure this torrent isn't already in the list
|
# Make sure this torrent isn't already in the list
|
||||||
|
|
Loading…
Reference in New Issue