mirror of
https://git.deluge-torrent.org/deluge
synced 2025-04-20 11:35:49 +00:00
files tab and peers tab made into plugins - micah
This commit is contained in:
parent
bf695f9cfa
commit
eff70a1c2c
16 changed files with 1244 additions and 1265 deletions
File diff suppressed because it is too large
Load diff
|
@ -52,7 +52,7 @@ def enable(core, interface):
|
|||
### The Plugin ###
|
||||
import deluge
|
||||
import gtk
|
||||
from EventLogging.tab_log import LogManager
|
||||
from EventLogging.tab_log import LogTabManager
|
||||
|
||||
class EventLogging:
|
||||
|
||||
|
@ -86,8 +86,8 @@ class EventLogging:
|
|||
self.parentNotebook.append_page(self.topWidget, gtk.Label(_("Event Log")))
|
||||
self.viewport.show()
|
||||
self.scrolledWindow.show()
|
||||
self.tab_log = LogManager(self.viewport, self.manager)
|
||||
self.tab_log.prepare_log_store()
|
||||
self.tab_log = LogTabManager(self.viewport, self.manager)
|
||||
self.tab_log.build_log_view()
|
||||
if self.config.get("enable_finished"):
|
||||
self.manager.connect_event(self.manager.constants['EVENT_FINISHED'], self.tab_log.handle_event)
|
||||
if self.config.get("enable_peer_error"):
|
||||
|
|
|
@ -5,7 +5,7 @@ import time
|
|||
|
||||
CONFIG_DIR = xdg.BaseDirectory.save_config_path('deluge')
|
||||
|
||||
class LogManager(object):
|
||||
class LogTabManager(object):
|
||||
def __init__(self, viewport, manager):
|
||||
self.log_files = False
|
||||
self.viewport = viewport
|
||||
|
@ -21,7 +21,7 @@ class LogManager(object):
|
|||
self.vbox.destroy()
|
||||
self.vbox = None
|
||||
|
||||
def prepare_log_store(self):
|
||||
def build_log_view(self):
|
||||
self.vbox = gtk.VBox()
|
||||
self.viewport.add(self.vbox)
|
||||
self.vbox.show_all()
|
||||
|
|
|
@ -8,8 +8,55 @@ def deluge_init(deluge_path):
|
|||
global path
|
||||
path = deluge_path
|
||||
|
||||
from NetworkGraph.plugin import plugin_NetGraph
|
||||
|
||||
def enable(core, interface):
|
||||
global path
|
||||
return plugin_NetGraph(path, core, interface)
|
||||
return NetworkGraph(path, core, interface)
|
||||
|
||||
from NetworkGraph.tab_graph import GraphTabManager
|
||||
|
||||
class NetworkGraph:
|
||||
def __init__(self, path, core, interface):
|
||||
import gtk
|
||||
self.parent = interface
|
||||
self.location = path
|
||||
self.manager = core
|
||||
scrolledWindow = gtk.ScrolledWindow()
|
||||
scrolledWindow.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
|
||||
image = gtk.Image()
|
||||
|
||||
viewport = gtk.Viewport()
|
||||
viewport.add(image)
|
||||
scrolledWindow.add(viewport)
|
||||
|
||||
image.show()
|
||||
viewport.show()
|
||||
self.topWidget = scrolledWindow
|
||||
|
||||
self.parentNotebook = self.parent.notebook
|
||||
# print "Parent NOTEBOOK:", self.parentNotebook
|
||||
self.parentNotebook.append_page(self.topWidget, gtk.Label(_("Graph")))
|
||||
# print "My INDEX in parentNoteBook:", self.index
|
||||
self.bootupRuns = 3 # This ensures that we pass the resizing phase, with scrollbars, etc.
|
||||
# So the first time it is viewed, we are all ready
|
||||
scrolledWindow.show()
|
||||
import pango
|
||||
pangoContext = self.parent.window.get_pango_context()
|
||||
pangoLayout = pango.Layout(pangoContext)
|
||||
self.tab_graph = GraphTabManager(scrolledWindow, image, pangoLayout, self.manager)
|
||||
|
||||
def unload(self): # Shutdown is called when the plugin is deactivated
|
||||
numPages = self.parentNotebook.get_n_pages()
|
||||
for page in range(numPages):
|
||||
if self.parentNotebook.get_nth_page(page) == self.topWidget:
|
||||
self.parentNotebook.remove_page(page)
|
||||
break
|
||||
|
||||
def update(self):
|
||||
if (not self.parentNotebook.get_nth_page(self.parentNotebook.get_current_page()) == \
|
||||
self.topWidget\
|
||||
or not self.parent.update_interface)\
|
||||
and not self.bootupRuns > 0:
|
||||
return
|
||||
self.bootupRuns = max(self.bootupRuns - 1, 0)
|
||||
self.tab_graph.update_graph_store()
|
||||
self.tab_graph.update_graph_view()
|
||||
|
|
|
@ -1,159 +0,0 @@
|
|||
# netgraph plugin
|
||||
|
||||
class plugin_NetGraph:
|
||||
def __init__(self, path, deluge_core, deluge_interface):
|
||||
import gtk
|
||||
self.parent = deluge_interface
|
||||
self.location = path
|
||||
self.core = deluge_core
|
||||
|
||||
self.image = gtk.Image()
|
||||
|
||||
self.viewPort = gtk.Viewport()
|
||||
self.viewPort.add(self.image)
|
||||
|
||||
self.scrolledWindow = gtk.ScrolledWindow()
|
||||
self.scrolledWindow.add(self.viewPort)
|
||||
self.scrolledWindow.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
|
||||
|
||||
self.topWidget = self.scrolledWindow
|
||||
|
||||
self.parentNotebook = self.parent.notebook
|
||||
# print "Parent NOTEBOOK:", self.parentNotebook
|
||||
self.parentNotebook.append_page(self.topWidget, gtk.Label(_("Graph")))
|
||||
# print "My INDEX in parentNoteBook:", self.index
|
||||
|
||||
self.image.show()
|
||||
self.viewPort.show()
|
||||
self.scrolledWindow.show()
|
||||
|
||||
self.length = 60
|
||||
|
||||
self.width = -1
|
||||
self.height = -1
|
||||
|
||||
import pango
|
||||
|
||||
self.pangoContext = self.parent.window.get_pango_context()
|
||||
self.pangoLayout = pango.Layout(self.pangoContext)
|
||||
|
||||
self.savedUpSpeeds = []
|
||||
self.savedDownSpeeds = []
|
||||
|
||||
self.bootupRuns = 3 # This ensures that we pass the resizing phase, with scrollbars, etc.
|
||||
# So the first time it is viewed, we are all ready
|
||||
|
||||
def unload(self): # Shutdown is called when the plugin is deactivated
|
||||
numPages = self.parentNotebook.get_n_pages()
|
||||
for page in range(numPages):
|
||||
if self.parentNotebook.get_nth_page(page) == self.topWidget:
|
||||
self.parentNotebook.remove_page(page)
|
||||
break
|
||||
|
||||
def update(self):
|
||||
if self.parent.update_interface:
|
||||
import gtk
|
||||
session_info = self.core.get_state()
|
||||
self.savedUpSpeeds.insert(0, session_info['upload_rate'])
|
||||
if len(self.savedUpSpeeds) > self.length:
|
||||
self.savedUpSpeeds.pop()
|
||||
self.savedDownSpeeds.insert(0, session_info['download_rate'])
|
||||
if len(self.savedDownSpeeds) > self.length:
|
||||
self.savedDownSpeeds.pop()
|
||||
|
||||
if not self.parentNotebook.get_nth_page(self.parentNotebook.get_current_page()) == \
|
||||
self.topWidget and not self.bootupRuns > 0:
|
||||
return
|
||||
|
||||
self.bootupRuns = max(self.bootupRuns - 1, 0)
|
||||
|
||||
extraWidth = self.scrolledWindow.get_vscrollbar().get_allocation().width * 1.5
|
||||
extraHeight = self.scrolledWindow.get_hscrollbar().get_allocation().height * 1.5
|
||||
allocation = self.scrolledWindow.get_allocation()
|
||||
allocation.width = int(allocation.width) - extraWidth
|
||||
allocation.height = int(allocation.height) - extraHeight
|
||||
|
||||
# Don't try to allocate a size too small, or you might crash
|
||||
if allocation.width < 2 or allocation.height < 2:
|
||||
return
|
||||
|
||||
# savedDownSpeeds = [1,2,3,2,1]
|
||||
# savedUpSpeeds = [5,8,0,0,1,2]
|
||||
|
||||
# allocation = self.image.get_allocation()
|
||||
# allocation.width = 300
|
||||
# allocation.height = 200
|
||||
|
||||
if not allocation.width == self.width or not allocation.height == self.height:
|
||||
# print "New Pixmap!"
|
||||
self.width = allocation.width
|
||||
self.height = allocation.height
|
||||
|
||||
self.networkPixmap = gtk.gdk.Pixmap(None, self.width,
|
||||
self.height, gtk.gdk.visual_get_system().depth)
|
||||
self.image.set_from_pixmap(self.networkPixmap, None)
|
||||
self.ctx = self.networkPixmap.cairo_create()
|
||||
|
||||
self.networkPixmap.draw_rectangle(self.image.get_style().white_gc,True, 0, 0, self.width, self.height)
|
||||
|
||||
maxSpeed = max(max(self.savedDownSpeeds),max(self.savedUpSpeeds))
|
||||
|
||||
if maxSpeed == 0:
|
||||
return
|
||||
|
||||
maxSpeed = maxSpeed*1.1 # Give some extra room on top
|
||||
|
||||
self.drawSpeedPoly(self.savedDownSpeeds, (0.5,1, 0.5, 1.0), maxSpeed, True)
|
||||
self.drawSpeedPoly(self.savedDownSpeeds, (0, 0.75,0, 1.0), maxSpeed, False)
|
||||
|
||||
self.drawSpeedPoly(self.savedUpSpeeds, (0.33,0.33,1.0, 0.5), maxSpeed, True)
|
||||
self.drawSpeedPoly(self.savedUpSpeeds, (0, 0, 1.0, 0.75), maxSpeed, False)
|
||||
|
||||
meanUpSpeed = sum(self.savedUpSpeeds) /len(self.savedUpSpeeds)
|
||||
meanDownSpeed = sum(self.savedDownSpeeds)/len(self.savedDownSpeeds)
|
||||
shownSpeed = max(meanUpSpeed, meanDownSpeed)
|
||||
|
||||
import deluge.common
|
||||
|
||||
self.pangoLayout.set_text(deluge.common.fspeed(shownSpeed))
|
||||
self.networkPixmap.draw_layout(self.image.get_style().black_gc,
|
||||
4,
|
||||
int(self.height - 1 - (self.height*shownSpeed/maxSpeed)),
|
||||
self.pangoLayout)
|
||||
|
||||
self.networkPixmap.draw_line(self.image.get_style().black_gc,
|
||||
0,
|
||||
int(self.height - (self.height*shownSpeed/maxSpeed)),
|
||||
self.width,
|
||||
int(self.height - (self.height*shownSpeed/maxSpeed)))
|
||||
|
||||
self.networkPixmap.draw_rectangle(self.image.get_style().black_gc,False, 0, 0, self.width-1, self.height-1)
|
||||
|
||||
self.image.queue_draw()
|
||||
|
||||
def tracePath(self, speeds, maxSpeed):
|
||||
lineWidth = 4
|
||||
|
||||
self.ctx.set_line_width(lineWidth)
|
||||
|
||||
self.ctx.move_to(self.width + lineWidth,self.height + lineWidth)
|
||||
self.ctx.line_to(self.width + lineWidth,int(self.height-(self.height*speeds[0]/maxSpeed)))
|
||||
|
||||
for i in range(len(speeds)):
|
||||
self.ctx.line_to(int(self.width-1-((i*self.width)/(self.length-1))),
|
||||
int(self.height-1-(self.height*speeds[i]/maxSpeed)))
|
||||
|
||||
self.ctx.line_to(int(self.width-1-(((len(speeds)-1)*self.width)/(self.length-1))),
|
||||
int(self.height)-1 + lineWidth)
|
||||
|
||||
self.ctx.close_path()
|
||||
|
||||
def drawSpeedPoly(self, speeds, color, maxSpeed, fill):
|
||||
|
||||
self.tracePath(speeds, maxSpeed)
|
||||
self.ctx.set_source_rgba(color[0],color[1],color[2], color[3])
|
||||
|
||||
if fill:
|
||||
self.ctx.fill()
|
||||
else:
|
||||
self.ctx.stroke()
|
85
plugins/TorrentFiles/__init__.py
Normal file
85
plugins/TorrentFiles/__init__.py
Normal file
|
@ -0,0 +1,85 @@
|
|||
# Copyright (C) 2007
|
||||
#
|
||||
# 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 2, 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 St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
|
||||
### Initialization ###
|
||||
|
||||
plugin_name = _("Torrent Files")
|
||||
plugin_author = "Deluge"
|
||||
plugin_version = "0.2"
|
||||
plugin_description = _("""
|
||||
This is just the files tab as a plugin.
|
||||
""")
|
||||
|
||||
def deluge_init(deluge_path):
|
||||
global path
|
||||
path = deluge_path
|
||||
|
||||
def enable(core, interface):
|
||||
global path
|
||||
return TorrentFiles(path, core, interface)
|
||||
|
||||
### The Plugin ###
|
||||
import deluge
|
||||
import gtk
|
||||
from TorrentFiles.tab_files import FilesTabManager
|
||||
|
||||
class TorrentFiles:
|
||||
|
||||
def __init__(self, path, core, interface):
|
||||
print "Loading TorrentFiles plugin..."
|
||||
self.manager = core
|
||||
self.parent = interface
|
||||
self.treeView = gtk.TreeView()
|
||||
self.scrolledWindow = gtk.ScrolledWindow()
|
||||
self.scrolledWindow.add(self.treeView)
|
||||
self.scrolledWindow.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
|
||||
|
||||
self.topWidget = self.scrolledWindow
|
||||
|
||||
self.parentNotebook = self.parent.notebook
|
||||
|
||||
self.parentNotebook.append_page(self.topWidget, gtk.Label(_("Files")))
|
||||
self.treeView.show()
|
||||
self.scrolledWindow.show()
|
||||
self.tab_files = FilesTabManager(self.treeView, self.manager)
|
||||
self.tab_files.build_file_view()
|
||||
|
||||
def unload(self):
|
||||
self.tab_files.clear_file_store()
|
||||
numPages = self.parentNotebook.get_n_pages()
|
||||
for page in xrange(numPages):
|
||||
if self.parentNotebook.get_nth_page(page) == self.topWidget:
|
||||
self.parentNotebook.remove_page(page)
|
||||
break
|
||||
|
||||
def update(self):
|
||||
if not self.parent.update_interface:
|
||||
return
|
||||
numPages = self.parentNotebook.get_n_pages()
|
||||
for page in xrange(numPages):
|
||||
if self.parentNotebook.get_nth_page(page) == self.topWidget:
|
||||
unique_id = self.parent.get_selected_torrent()
|
||||
if unique_id is None:
|
||||
#if no torrents added or more than one torrent selected
|
||||
self.tab_files.clear_file_store()
|
||||
return
|
||||
if self.tab_files.file_unique_id != unique_id:
|
||||
self.tab_files.clear_file_store()
|
||||
self.tab_files.set_unique_id(unique_id)
|
||||
self.tab_files.prepare_file_store()
|
||||
else:
|
||||
self.tab_files.update_file_store()
|
||||
break
|
68
plugins/TorrentFiles/tab_files.py
Normal file
68
plugins/TorrentFiles/tab_files.py
Normal file
|
@ -0,0 +1,68 @@
|
|||
from itertools import izip
|
||||
from deluge.files import FilesBaseManager
|
||||
from deluge import dgtk
|
||||
import gobject
|
||||
import gtk
|
||||
class FilesTabManager(FilesBaseManager):
|
||||
def __init__(self, file_view, manager):
|
||||
file_store = gtk.ListStore(str, gobject.TYPE_UINT64,
|
||||
gobject.TYPE_UINT, float)
|
||||
|
||||
super(FilesTabManager, self).__init__(file_view, file_store)
|
||||
|
||||
self.manager = manager
|
||||
self.file_unique_id = None
|
||||
|
||||
# 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):
|
||||
super(FilesTabManager, self).build_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(self.file_view, _("Progress"), percent, 3)
|
||||
|
||||
def set_unique_id(self, unique_id):
|
||||
self.file_unique_id = unique_id
|
||||
|
||||
def priority_clicked(self, widget):
|
||||
state = self.manager.get_torrent_state(self.file_unique_id)
|
||||
if state["compact_mode"]:
|
||||
self.compact_allocation_warning()
|
||||
else:
|
||||
super(FilesTabManager, self).priority_clicked(widget)
|
||||
|
||||
# From core to UI
|
||||
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([file['path'], file['size'],
|
||||
priority, round(file['progress'], 2)])
|
||||
self.file_store_dict[file['path']] = iter
|
||||
|
||||
# From core to UI
|
||||
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']]
|
||||
dgtk.update_store(self.file_store, iter, (3,),
|
||||
(round(file['progress'], 2),))
|
||||
|
||||
# From UI to core
|
||||
def update_priorities(self):
|
||||
prev_file_priorities = self.manager.get_priorities(self.file_unique_id)
|
||||
file_priorities = []
|
||||
update = False
|
||||
for x, priority in izip(self.file_store, prev_file_priorities):
|
||||
file_priorities.append(x[2])
|
||||
if x[2] > 0 and priority == 0:
|
||||
update = True
|
||||
if x[2] == 0:
|
||||
update = True
|
||||
self.manager.prioritize_files(self.file_unique_id, file_priorities, update_files_removed=update)
|
85
plugins/TorrentPeers/__init__.py
Normal file
85
plugins/TorrentPeers/__init__.py
Normal file
|
@ -0,0 +1,85 @@
|
|||
# Copyright (C) 2007
|
||||
#
|
||||
# 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 2, 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 St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
|
||||
### Initialization ###
|
||||
|
||||
plugin_name = _("Torrent Peers")
|
||||
plugin_author = "Deluge"
|
||||
plugin_version = "0.2"
|
||||
plugin_description = _("""
|
||||
This is just the peers tab as a plugin.
|
||||
""")
|
||||
|
||||
def deluge_init(deluge_path):
|
||||
global path
|
||||
path = deluge_path
|
||||
|
||||
def enable(core, interface):
|
||||
global path
|
||||
return TorrentPeers(path, core, interface)
|
||||
|
||||
### The Plugin ###
|
||||
import deluge
|
||||
import gtk
|
||||
from TorrentPeers.tab_peers import PeersTabManager
|
||||
|
||||
class TorrentPeers:
|
||||
|
||||
def __init__(self, path, core, interface):
|
||||
print "Loading TorrentPeers plugin..."
|
||||
self.manager = core
|
||||
self.parent = interface
|
||||
treeView = gtk.TreeView()
|
||||
scrolledWindow = gtk.ScrolledWindow()
|
||||
scrolledWindow.add(treeView)
|
||||
scrolledWindow.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
|
||||
|
||||
self.topWidget = scrolledWindow
|
||||
|
||||
self.parentNotebook = self.parent.notebook
|
||||
|
||||
self.parentNotebook.append_page(self.topWidget, gtk.Label(_("Peers")))
|
||||
treeView.show()
|
||||
scrolledWindow.show()
|
||||
self.tab_peers = PeersTabManager(treeView, self.manager)
|
||||
self.tab_peers.build_peers_view()
|
||||
|
||||
def unload(self):
|
||||
self.tab_peers.clear_peer_store()
|
||||
numPages = self.parentNotebook.get_n_pages()
|
||||
for page in xrange(numPages):
|
||||
if self.parentNotebook.get_nth_page(page) == self.topWidget:
|
||||
self.parentNotebook.remove_page(page)
|
||||
break
|
||||
|
||||
def update(self):
|
||||
if not self.parent.update_interface:
|
||||
return
|
||||
numPages = self.parentNotebook.get_n_pages()
|
||||
for page in xrange(numPages):
|
||||
if self.parentNotebook.get_nth_page(page) == self.topWidget:
|
||||
unique_id = self.parent.get_selected_torrent()
|
||||
if unique_id is None:
|
||||
#if no torrents added or more than one torrent selected
|
||||
self.tab_peers.clear_peer_store()
|
||||
return
|
||||
if self.tab_peers.peer_unique_id != unique_id:
|
||||
self.tab_peers.clear_peer_store()
|
||||
self.tab_peers.set_unique_id(unique_id)
|
||||
self.tab_peers.update_peer_store()
|
||||
else:
|
||||
self.tab_peers.update_peer_store()
|
||||
break
|
|
@ -1,31 +1,30 @@
|
|||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# tab_details.py
|
||||
|
||||
from itertools import izip
|
||||
|
||||
from deluge import dgtk
|
||||
from deluge import common
|
||||
import gobject
|
||||
import gtk
|
||||
|
||||
import common
|
||||
import dgtk
|
||||
|
||||
class PeersTabManager(object):
|
||||
def __init__(self, peer_view, manager):
|
||||
self.peer_view = peer_view
|
||||
self.manager = manager
|
||||
|
||||
self.peer_unique_id = None
|
||||
# IP int, IP string, Client, Percent Complete, Down Speed, Up Speed
|
||||
# IP int is for faster sorting
|
||||
self.peer_store = gtk.ListStore(gobject.TYPE_UINT, gtk.gdk.Pixbuf,
|
||||
str, str, float, int, int)
|
||||
# Stores IP -> gtk.TreeIter's iter mapping for quick look up
|
||||
# in update_torrent_info_widget
|
||||
self.peer_store_dict = {}
|
||||
|
||||
self.peer_store_dict = {}
|
||||
self._cached_flags = {}
|
||||
|
||||
|
||||
def clear_peer_store(self):
|
||||
self.peer_store.clear()
|
||||
self.peer_store_dict = {}
|
||||
self.peer_unique_id = None
|
||||
|
||||
def set_unique_id(self, unique_id):
|
||||
self.peer_unique_id = unique_id
|
||||
|
||||
def build_peers_view(self):
|
||||
def percent(column, cell, model, iter, data):
|
||||
percent = float(model.get_value(iter, data))
|
||||
|
@ -44,11 +43,7 @@ class PeersTabManager(object):
|
|||
dgtk.cell_data_speed, 5)
|
||||
dgtk.add_func_column(self.peer_view, _("Up Speed"),
|
||||
dgtk.cell_data_speed, 6)
|
||||
|
||||
def clear_store(self):
|
||||
self.peer_store.clear()
|
||||
self.peer_store_dict = {}
|
||||
|
||||
|
||||
def get_country_flag_image(self, country):
|
||||
flag_image = None
|
||||
if country.isalpha():
|
||||
|
@ -65,9 +60,9 @@ class PeersTabManager(object):
|
|||
self._cached_flags[country] = flag_image
|
||||
|
||||
return flag_image
|
||||
|
||||
def update(self, unique_id):
|
||||
new_peer_info = self.manager.get_torrent_peer_info(unique_id)
|
||||
|
||||
def update_peer_store(self):
|
||||
new_peer_info = self.manager.get_torrent_peer_info(self.peer_unique_id)
|
||||
new_ips = set()
|
||||
|
||||
for peer in new_peer_info:
|
|
@ -50,7 +50,7 @@ def enable(core, interface):
|
|||
### The Plugin ###
|
||||
import deluge
|
||||
import gtk
|
||||
from TorrentPieces.tab_pieces import PiecesManager
|
||||
from TorrentPieces.tab_pieces import PiecesTabManager
|
||||
|
||||
class TorrentPieces:
|
||||
|
||||
|
@ -66,7 +66,7 @@ class TorrentPieces:
|
|||
|
||||
self.parentNotebook.append_page(self.topWidget, gtk.Label(_("Pieces")))
|
||||
self.topWidget.show_all()
|
||||
self.tab_pieces = PiecesManager(self.manager)
|
||||
self.tab_pieces = PiecesTabManager(self.manager)
|
||||
|
||||
def unload(self):
|
||||
self.manager.disconnect_event(self.manager.constants['EVENT_PIECE_FINISHED'], self.tab_pieces.handle_event)
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import gtk
|
||||
import math
|
||||
|
||||
class PiecesManager(object):
|
||||
class PiecesTabManager(object):
|
||||
def __init__(self, manager):
|
||||
self.vbox = None
|
||||
self.manager = manager
|
||||
|
@ -15,8 +15,6 @@ class PiecesManager(object):
|
|||
self.unique_id = -1
|
||||
self.peer_speed = []
|
||||
self.piece_info = []
|
||||
self.first_indexes = []
|
||||
self.last_indexes = []
|
||||
self.all_files = None
|
||||
self.file_priorities = None
|
||||
self.index = 0
|
||||
|
@ -24,6 +22,8 @@ class PiecesManager(object):
|
|||
self.file_index = 0
|
||||
self.next_file_index = 1
|
||||
self.num_files = 0
|
||||
self.current_first_index = None
|
||||
self.current_last_index = None
|
||||
|
||||
def set_unique_id(self, unique_id):
|
||||
self.unique_id = unique_id
|
||||
|
@ -36,10 +36,10 @@ class PiecesManager(object):
|
|||
self.progress = []
|
||||
self.piece_info = []
|
||||
self.tooltips = []
|
||||
self.first_indexes = []
|
||||
self.last_indexes = []
|
||||
self.all_files = None
|
||||
self.file_priorities = None
|
||||
self.current_first_index = None
|
||||
self.current_last_index = None
|
||||
self.index = 0
|
||||
self.num_files = 0
|
||||
self.prev_file_index = -1
|
||||
|
@ -57,16 +57,13 @@ class PiecesManager(object):
|
|||
scrolledWindow.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
|
||||
self.vbox = gtk.VBox()
|
||||
viewport.add(self.vbox)
|
||||
self.all_files = self.manager.get_torrent_file_info(self.unique_id)
|
||||
self.all_files = self.manager.get_file_piece_range(self.unique_id)
|
||||
self.file_priorities = self.manager.get_priorities(self.unique_id)
|
||||
state = self.manager.get_torrent_state(self.unique_id)
|
||||
self.num_pieces = state["num_pieces"]
|
||||
for priority in self.file_priorities:
|
||||
if self.file_index == 0:
|
||||
file_piece_range = self.manager.get_file_piece_range(self.unique_id,\
|
||||
self.file_index, self.all_files[self.file_index]['size'])
|
||||
self.first_indexes.append(file_piece_range['first_index'])
|
||||
self.last_indexes.append(file_piece_range['last_index'])
|
||||
self.current_first_index = self.all_files[self.file_index]['first_index']
|
||||
self.current_last_index = self.all_files[self.file_index]['last_index']
|
||||
if priority > 0:
|
||||
#if file is being downloaded build the file pieces information
|
||||
self.build_file_pieces()
|
||||
|
@ -87,11 +84,11 @@ class PiecesManager(object):
|
|||
label.set_text(self.all_files[self.file_index]['path'])
|
||||
self.vbox.pack_start(label, expand=False)
|
||||
table = gtk.Table()
|
||||
self.rows = int(math.ceil((self.last_indexes[self.file_index]-self.first_indexes[self.file_index])/self.columns)+1)
|
||||
self.rows = int(math.ceil((self.current_last_index-self.current_first_index)/self.columns)+1)
|
||||
self.vbox.pack_start(table, expand=False)
|
||||
table.resize(self.rows, self.columns)
|
||||
table.set_size_request((self.columns+1)*self.piece_width, (self.rows+1)*self.piece_height)
|
||||
if self.last_indexes[self.file_index] != self.first_indexes[self.file_index]:
|
||||
if self.current_last_index != self.current_first_index:
|
||||
#if there is more than one piece
|
||||
self.build_pieces_table(table)
|
||||
only_one_piece = False
|
||||
|
@ -99,14 +96,12 @@ class PiecesManager(object):
|
|||
#if file only has one piece
|
||||
self.index = 0
|
||||
only_one_piece = True
|
||||
main_index = self.last_indexes[self.file_index]
|
||||
# do the following even if file has only one piece and that piece has already been created
|
||||
if self.next_file_index < len(self.all_files):
|
||||
#if there is another file
|
||||
file_piece_range = self.manager.get_file_piece_range(self.unique_id,\
|
||||
self.next_file_index, self.all_files[self.next_file_index]['size'])
|
||||
self.first_indexes.append(file_piece_range['first_index'])
|
||||
self.last_indexes.append(file_piece_range['last_index'])
|
||||
self.piece_info.append({'blocks_total':0, 'blocks_finished':0, 'blocks_requested':0})
|
||||
self.progress.append(gtk.ProgressBar())
|
||||
self.tooltips.append(gtk.Tooltips())
|
||||
self.eventboxes.append(gtk.EventBox())
|
||||
self.peer_speed.append("unknown")
|
||||
main_index = self.current_last_index
|
||||
if self.file_index > 0 and not self.piece_info[main_index] is None and only_one_piece:
|
||||
#if file has only one piece and it is shared destroy the table
|
||||
table.destroy()
|
||||
|
@ -117,10 +112,11 @@ class PiecesManager(object):
|
|||
|
||||
def build_pieces_table(self, table):
|
||||
temp_prev_priority = 1
|
||||
if self.first_indexes[self.file_index] == 0\
|
||||
or self.first_indexes[self.file_index] != self.last_indexes[self.prev_file_index]:
|
||||
if self.current_first_index == 0\
|
||||
or self.current_first_index !=\
|
||||
self.all_files[self.prev_file_index]['last_index']:
|
||||
#if first piece is not a shared piece
|
||||
temp_range = self.last_indexes[self.file_index]-self.first_indexes[self.file_index]
|
||||
temp_range = self.current_last_index-self.current_first_index
|
||||
diff = 0
|
||||
else:
|
||||
#if first piece is shared
|
||||
|
@ -128,15 +124,16 @@ class PiecesManager(object):
|
|||
if temp_prev_priority > 0:
|
||||
#if last file was not skipped, skip the first piece
|
||||
diff = 1
|
||||
temp_range = self.last_indexes[self.file_index]-(self.first_indexes[self.file_index]+1)
|
||||
temp_range = self.current_last_index-(self.current_first_index+1)
|
||||
#otherwise keep the first piece
|
||||
else:
|
||||
diff = 0
|
||||
temp_range = self.last_indexes[self.file_index]-self.first_indexes[self.file_index]
|
||||
temp_range = self.current_last_index-self.current_first_index
|
||||
#last piece handled outside of loop, skip it from range
|
||||
temp_first_index = self.current_first_index
|
||||
for index in xrange(temp_range):
|
||||
gtk.main_iteration_do(False)
|
||||
main_index = diff+self.first_indexes[self.file_index]+index
|
||||
main_index = diff+temp_first_index+index
|
||||
if temp_prev_priority > 0:
|
||||
#normal behavior
|
||||
self.piece_info.append({'blocks_total':0, 'blocks_finished':0, 'blocks_requested':0})
|
||||
|
@ -161,23 +158,18 @@ class PiecesManager(object):
|
|||
else:
|
||||
#if piece is not already finished
|
||||
self.tooltips[main_index].set_tip(self.eventboxes[main_index], _("Piece not started"))
|
||||
self.piece_info.append({'blocks_total':0, 'blocks_finished':0, 'blocks_requested':0})
|
||||
self.progress.append(gtk.ProgressBar())
|
||||
self.tooltips.append(gtk.Tooltips())
|
||||
self.eventboxes.append(gtk.EventBox())
|
||||
self.peer_speed.append("unknown")
|
||||
self.index = index+1
|
||||
self.index = temp_range
|
||||
|
||||
def build_last_file_piece(self, table, main_index, only_one_piece):
|
||||
gtk.main_iteration_do(False)
|
||||
if only_one_piece:
|
||||
if only_one_piece and self.file_index > 0:
|
||||
#if piece is shared with a skipped file
|
||||
self.share_skipped_piece(main_index)
|
||||
self.progress[main_index].set_size_request(self.piece_width, self.piece_height)
|
||||
if self.next_file_index < len(self.all_files):
|
||||
# if there is another file
|
||||
if self.file_priorities[self.next_file_index]==0\
|
||||
or self.last_indexes[self.file_index] != self.first_indexes[self.next_file_index]:
|
||||
or self.current_last_index != self.all_files[self.next_file_index]['first_index']:
|
||||
#if next file is skipped or there is no shared piece, keep last piece
|
||||
row=self.index/self.columns
|
||||
column=self.index%self.columns
|
||||
|
@ -185,7 +177,7 @@ class PiecesManager(object):
|
|||
xoptions=0, yoptions=0, xpadding=0, ypadding=0)
|
||||
self.eventboxes[main_index].add(self.progress[main_index])
|
||||
if self.file_priorities[self.next_file_index]>0\
|
||||
and self.last_indexes[self.file_index] == self.first_indexes[self.next_file_index]:
|
||||
and self.current_last_index == self.all_files[self.next_file_index]['first_index']:
|
||||
#if next file is not skipped and there is a shared piece, do not keep last piece
|
||||
if only_one_piece:
|
||||
#only piece in file is shared, destroy table for file
|
||||
|
@ -224,26 +216,20 @@ class PiecesManager(object):
|
|||
self.peer_speed[main_index] = "unknown"
|
||||
|
||||
def skip_current_file(self):
|
||||
if self.first_indexes[self.file_index] == 0 or self.first_indexes[self.file_index] != self.last_indexes[self.prev_file_index]:
|
||||
if self.current_first_index == 0\
|
||||
or self.current_first_index !=\
|
||||
self.all_files[self.prev_file_index]['last_index']:
|
||||
#if first piece is not shared
|
||||
temp_range = 1+self.last_indexes[self.file_index]-self.first_indexes[self.file_index]
|
||||
temp_range = 1+self.current_last_index-self.current_first_index
|
||||
else:
|
||||
#if first piece is shared
|
||||
temp_range = self.last_indexes[self.file_index]-self.first_indexes[self.file_index]
|
||||
temp_range = self.current_last_index-self.current_first_index
|
||||
for index in xrange(temp_range):
|
||||
self.piece_info.append(None)
|
||||
self.progress.append(None)
|
||||
self.eventboxes.append(None)
|
||||
self.tooltips.append(None)
|
||||
self.peer_speed.append(None)
|
||||
if self.next_file_index < len(self.all_files):
|
||||
#if there is another file
|
||||
file_piece_range = self.manager.get_file_piece_range(self.unique_id,\
|
||||
self.next_file_index, self.all_files[self.next_file_index]['size'])
|
||||
self.first_indexes.append(file_piece_range['first_index'])
|
||||
self.last_indexes.append(file_piece_range['last_index'])
|
||||
if self.last_indexes[self.next_file_index] >= self.num_pieces:
|
||||
self.last_indexes[self.next_file_index] = self.num_pieces-1
|
||||
|
||||
def handle_event(self, event):
|
||||
#protect against pieces trying to display after file priority changed
|
||||
|
|
|
@ -322,10 +322,8 @@ class Manager:
|
|||
return self.config.get(key)
|
||||
|
||||
# Get file piece range
|
||||
def get_file_piece_range(self, unique_id,\
|
||||
file_index, file_size):
|
||||
return deluge_core.get_file_piece_range(unique_id,\
|
||||
file_index, file_size)
|
||||
def get_file_piece_range(self, unique_id):
|
||||
return deluge_core.get_file_piece_range(unique_id)
|
||||
|
||||
# Check if piece is finished
|
||||
def has_piece(self, unique_id, piece_index):
|
||||
|
|
|
@ -1269,21 +1269,40 @@ static PyObject *torrent_get_file_info(PyObject *self, PyObject *args)
|
|||
static PyObject *torrent_get_file_piece_range(PyObject *self, PyObject *args)
|
||||
{
|
||||
python_long unique_ID;
|
||||
int file_index, file_size;
|
||||
if (!PyArg_ParseTuple(args, "iii", &unique_ID, &file_index, &file_size))
|
||||
if (!PyArg_ParseTuple(args, "i", &unique_ID))
|
||||
return NULL;
|
||||
|
||||
long index = get_index_from_unique_ID(unique_ID);
|
||||
if (PyErr_Occurred())
|
||||
return NULL;
|
||||
|
||||
std::vector<PyObject *> temp_files;
|
||||
|
||||
torrent_info const &info = M_torrents->at(index).handle.get_torrent_info();
|
||||
peer_request first_index = info.map_file(file_index, 0, 1);
|
||||
peer_request last_index = info.map_file(file_index, file_size-1, 1);
|
||||
return Py_BuildValue(
|
||||
"{s:i,s:i}",
|
||||
"first_index", first_index.piece,
|
||||
"last_index", last_index.piece
|
||||
);
|
||||
int file_index = 0;
|
||||
PyObject *file_info;
|
||||
|
||||
for(torrent_info::file_iterator i = info.begin_files(); i != info.end_files(); ++i)
|
||||
{
|
||||
file_entry const &currFile = (*i);
|
||||
peer_request first_index = info.map_file(file_index, 0, 1);
|
||||
peer_request last_index = info.map_file(file_index, currFile.size-1, 1);
|
||||
file_info = Py_BuildValue(
|
||||
"{s:i,s:i,s:s}",
|
||||
"first_index", first_index.piece,
|
||||
"last_index", last_index.piece,
|
||||
"path", currFile.path.string().c_str()
|
||||
);
|
||||
file_index++;
|
||||
temp_files.push_back(file_info);
|
||||
};
|
||||
|
||||
PyObject *ret = PyTuple_New(temp_files.size());
|
||||
|
||||
for (unsigned long i = 0; i < temp_files.size(); i++)
|
||||
PyTuple_SetItem(ret, i, temp_files[i]);
|
||||
|
||||
return ret;
|
||||
};
|
||||
|
||||
/*static PyObject *torrent_get_unique_IDs(PyObject *self, PyObject *args)
|
||||
|
|
|
@ -34,7 +34,7 @@ import gtk
|
|||
|
||||
import common
|
||||
import dgtk
|
||||
import tab_files
|
||||
import files
|
||||
import pref
|
||||
|
||||
PREFS_FILENAME = "prefs.state"
|
||||
|
@ -284,7 +284,7 @@ class FilesDlg:
|
|||
self.dialog = self.glade.get_widget("file_dialog")
|
||||
self.dialog.set_icon_from_file(common.get_pixmap("deluge32.png"))
|
||||
|
||||
self.files_manager = tab_files.FilesDialogManager(
|
||||
self.files_manager = files.FilesDialogManager(
|
||||
self.glade.get_widget("file_view"),
|
||||
dumped_torrent)
|
||||
self.files_manager.build_file_view()
|
||||
|
|
|
@ -137,70 +137,6 @@ class FilesBaseManager(object):
|
|||
def update_priorities(self):
|
||||
pass
|
||||
|
||||
class FilesTabManager(FilesBaseManager):
|
||||
def __init__(self, file_view, manager):
|
||||
file_store = gtk.ListStore(str, gobject.TYPE_UINT64,
|
||||
gobject.TYPE_UINT, float)
|
||||
|
||||
super(FilesTabManager, self).__init__(file_view, file_store)
|
||||
|
||||
self.manager = manager
|
||||
self.file_unique_id = None
|
||||
|
||||
# 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):
|
||||
super(FilesTabManager, self).build_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(self.file_view, _("Progress"), percent, 3)
|
||||
|
||||
def set_unique_id(self, unique_id):
|
||||
self.file_unique_id = unique_id
|
||||
|
||||
def priority_clicked(self, widget):
|
||||
state = self.manager.get_torrent_state(self.file_unique_id)
|
||||
if state["compact_mode"]:
|
||||
self.compact_allocation_warning()
|
||||
else:
|
||||
super(FilesTabManager, self).priority_clicked(widget)
|
||||
|
||||
# From core to UI
|
||||
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([file['path'], file['size'],
|
||||
priority, round(file['progress'], 2)])
|
||||
self.file_store_dict[file['path']] = iter
|
||||
|
||||
# From core to UI
|
||||
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']]
|
||||
dgtk.update_store(self.file_store, iter, (3,),
|
||||
(round(file['progress'], 2),))
|
||||
|
||||
# From UI to core
|
||||
def update_priorities(self):
|
||||
prev_file_priorities = self.manager.get_priorities(self.file_unique_id)
|
||||
file_priorities = []
|
||||
update = False
|
||||
for x, priority in izip(self.file_store, prev_file_priorities):
|
||||
file_priorities.append(x[2])
|
||||
if x[2] > 0 and priority == 0:
|
||||
update = True
|
||||
if x[2] == 0:
|
||||
update = True
|
||||
self.manager.prioritize_files(self.file_unique_id, file_priorities, update_files_removed=update)
|
||||
|
||||
class FilesDialogManager(FilesBaseManager):
|
||||
def __init__(self, file_view, dumped_torrent):
|
||||
file_store = gtk.ListStore(str, gobject.TYPE_UINT64,
|
|
@ -47,8 +47,7 @@ import dgtk
|
|||
import ipc_manager
|
||||
import plugins
|
||||
import tab_details
|
||||
import tab_files
|
||||
import tab_peers
|
||||
import files
|
||||
|
||||
class DelugeGTK:
|
||||
def __init__(self):
|
||||
|
@ -81,12 +80,6 @@ class DelugeGTK:
|
|||
# Tabs
|
||||
self.tab_details = tab_details.DetailsTabManager(self.wtree,
|
||||
self.manager)
|
||||
self.tab_peers = tab_peers.PeersTabManager(
|
||||
self.wtree.get_widget("peer_view"), self.manager)
|
||||
self.tab_peers.build_peers_view()
|
||||
self.tab_files = tab_files.FilesTabManager(
|
||||
self.wtree.get_widget("file_view"), self.manager)
|
||||
self.tab_files.build_file_view()
|
||||
|
||||
self.statusbar = self.wtree.get_widget("statusbar")
|
||||
|
||||
|
@ -579,9 +572,6 @@ class DelugeGTK:
|
|||
# Torrent is already selected, we don't need to do anything
|
||||
return True
|
||||
|
||||
self.tab_peers.clear_store()
|
||||
self.tab_files.clear_file_store()
|
||||
|
||||
unique_id = model.get_value(model.get_iter(path), 0)
|
||||
self.update_torrent_info_widget(unique_id)
|
||||
|
||||
|
@ -982,14 +972,6 @@ class DelugeGTK:
|
|||
|
||||
if page_num == 0: # Details
|
||||
self.tab_details.update(unique_id)
|
||||
elif page_num == 1: # Peers
|
||||
self.tab_peers.update(unique_id)
|
||||
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.tab_files.set_unique_id(unique_id)
|
||||
self.tab_files.prepare_file_store()
|
||||
self.tab_files.update_file_store()
|
||||
|
||||
# Return the id of the last single selected torrent
|
||||
def get_selected_torrent(self):
|
||||
|
@ -1152,8 +1134,6 @@ class DelugeGTK:
|
|||
|
||||
def clear_details_pane(self):
|
||||
self.tab_details.clear()
|
||||
self.tab_peers.clear_store()
|
||||
self.tab_files.clear_file_store()
|
||||
|
||||
def remove_toggle_warning(self, args, warning):
|
||||
if not args.get_active():
|
||||
|
|
Loading…
Add table
Reference in a new issue