mirror of
https://github.com/codex-storage/deluge.git
synced 2025-02-22 08:08:17 +00:00
plugin work, search plugin
This commit is contained in:
parent
8cacacb3bb
commit
725ca07a25
@ -656,6 +656,7 @@ their share ratio reaches:</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="label" translatable="yes">gtk-preferences</property>
|
||||
<property name="use_stock">True</property>
|
||||
<signal name="clicked" handler="plugin_pref"/>
|
||||
</widget>
|
||||
</child>
|
||||
<child>
|
||||
|
@ -1,7 +1,8 @@
|
||||
#!/usr/bin/python
|
||||
|
||||
class plugin_Example:
|
||||
def __init__(self, deluge_core, deluge_interface):
|
||||
def __init__(self, path, deluge_core, deluge_interface):
|
||||
self.path = path
|
||||
self.core = deluge_core
|
||||
self.interface = deluge_interface
|
||||
print "Example Plugin loaded"
|
||||
|
166
plugins/TorrentSearch/plugin.py
Normal file
166
plugins/TorrentSearch/plugin.py
Normal file
@ -0,0 +1,166 @@
|
||||
#!/usr/bin/python
|
||||
|
||||
class plugin_Search:
|
||||
def __init__(self, path, deluge_core, deluge_interface):
|
||||
import dcommon, gtk, gtk.glade, dgtk
|
||||
self.core = deluge_core
|
||||
self.interface = deluge_interface
|
||||
self.conf_file = dcommon.CONFIG_DIR + "/search.conf"
|
||||
if not os.path.isfile(self.conf_file):
|
||||
f = open(self.conf_file, mode='w')
|
||||
f.flush()
|
||||
f.close()
|
||||
glade = gtk.glade.XML(path + "/searchdlg.glade")
|
||||
self.dlg = glade.get_widget("search_dialog")
|
||||
self.dlg.set_icon_from_file(dcommon.get_pixmap("deluge32.png"))
|
||||
self.view = glade.get_widget("search_view")
|
||||
model = gtk.ListStore(str, str)
|
||||
self.view.set_model(model)
|
||||
dgtk.add_text_column(self.view, "Name", 0)
|
||||
dgtk.add_text_column(self.view, "Search String", 1)
|
||||
self.field_name = glade.get_widget("field_name")
|
||||
self.field_search = glade.get_widget("field_search")
|
||||
self.button_add = glade.get_widget("button_addsearch")
|
||||
self.button_del = glade.get_widget("button_delsearch")
|
||||
dic = { "add_clicked" : self.add_clicked,
|
||||
"del_clicked" : self.del_clicked,
|
||||
"row_clicked" : self.row_clicked,
|
||||
"text_changed" : self.text_changed }
|
||||
glade.signal_autoconnect(dic)
|
||||
self.view.get_selection().set_select_function(self.row_clicked)
|
||||
|
||||
|
||||
### Note: All other plugins should use self.interface.toolbar
|
||||
### when adding items to the toolbar
|
||||
self.se = ''
|
||||
self.toolbar = self.interface.wtree.get_widget("tb_right")
|
||||
self.engines = dcommon.DelugePreferences()
|
||||
self.engines.load_from_file(self.conf_file)
|
||||
self.search_entry = gtk.Entry()
|
||||
self.search_item = gtk.ToolItem()
|
||||
self.search_item.add(self.search_entry)
|
||||
self.search_icon = gtk.Image()
|
||||
self.search_icon.set_from_stock(gtk.STOCK_FIND, gtk.ICON_SIZE_MENU)
|
||||
self.menu_button = gtk.MenuToolButton(self.search_icon, "Choose an Engine")
|
||||
self.menu_button.set_is_important(True)
|
||||
self.menu_button.connect("clicked", self.torrent_search)
|
||||
self.menu = gtk.Menu()
|
||||
self.manage_item = gtk.ImageMenuItem("Manage Engines")
|
||||
self.image = gtk.Image()
|
||||
self.image.set_from_stock(gtk.STOCK_PREFERENCES, gtk.ICON_SIZE_MENU)
|
||||
self.manage_item.set_image(self.image)
|
||||
self.manage_item.connect("activate", self.configure)
|
||||
self.menu.add(self.manage_item)
|
||||
self.menu_button.set_menu(self.menu)
|
||||
self.toolbar.insert(self.search_item, -1)
|
||||
self.toolbar.insert(self.menu_button, -1)
|
||||
self.populate_search_menu()
|
||||
self.toolbar.show_all()
|
||||
self.search_item.show_all()
|
||||
self.menu_button.show_all()
|
||||
self.menu.show_all()
|
||||
print "Torrent Search Initialized"
|
||||
|
||||
def unload(self):
|
||||
self.engines.save_to_file(self.conf_file)
|
||||
self.toolbar.remove(self.search_item)
|
||||
self.toolbar.remove(self.menu_button)
|
||||
|
||||
def text_changed(self, args):
|
||||
a = (self.field_name.get_text() != "")
|
||||
b = (self.field_search.get_text() != "")
|
||||
if(a and b):
|
||||
self.button_add.set_sensitive(1)
|
||||
else:
|
||||
self.button_add.set_sensitive(0)
|
||||
|
||||
def add_clicked(self, args):
|
||||
self.view.get_model().append([self.field_name.get_text(),
|
||||
self.field_search.get_text()])
|
||||
self.field_name.set_text("")
|
||||
self.field_search.set_text("")
|
||||
|
||||
def del_clicked(self, args):
|
||||
(model, selection) = self.view.get_selection().get_selected()
|
||||
model.remove(selection)
|
||||
self.button_del.set_sensitive(0)
|
||||
|
||||
def row_clicked(self, args):
|
||||
self.button_del.set_sensitive(1)
|
||||
return True
|
||||
|
||||
def configure(self, widget=None):
|
||||
import dcommon, gtk, gtk.glade
|
||||
|
||||
self.dlg.show_all()
|
||||
model = self.view.get_model()
|
||||
model.clear
|
||||
for name in self.engines.keys():
|
||||
self.view.get_model().append( (name, self.engines.get(name)) )
|
||||
self.button_add.set_sensitive(0)
|
||||
self.button_del.set_sensitive(0)
|
||||
result = self.dlg.run()
|
||||
self.dlg.hide_all()
|
||||
if result == 1:
|
||||
self.engines.clear()
|
||||
the_iter = model.get_iter_first()
|
||||
while the_iter is not None:
|
||||
self.engines.set(model.get_value(the_iter, 0), model.get_value(the_iter, 1))
|
||||
the_iter = model.iter_next(the_iter)
|
||||
else:
|
||||
pass
|
||||
|
||||
|
||||
|
||||
def update(self):
|
||||
pass
|
||||
|
||||
def torrent_search(self, widget=None):
|
||||
print "Searching with engine", self.se
|
||||
url = self.engines.get(self.se)
|
||||
entry = self.search_entry.get_text()
|
||||
print 'URL =', url
|
||||
print 'Entry =', entry
|
||||
entry = entry.replace(' ', '+')
|
||||
print 'URL =', url
|
||||
print 'Entry =', entry
|
||||
url = url.replace('${query}', entry)
|
||||
print 'URL =', url
|
||||
print 'Entry =', entry
|
||||
|
||||
def populate_search_menu(self):
|
||||
import gtk
|
||||
self.menu_button.set_label("Choose an Engine")
|
||||
for child in self.menu.get_children():
|
||||
self.menu.remove(child)
|
||||
group = None
|
||||
i = 0
|
||||
for engine in self.engines.keys():
|
||||
rmi = gtk.RadioMenuItem(None, engine)
|
||||
rmi.eng_name = engine
|
||||
rmi.connect("activate", self.select_search, rmi.eng_name)
|
||||
if (group != None):
|
||||
rmi.set_group(group)
|
||||
else:
|
||||
group = rmi
|
||||
rmi.set_active(1)
|
||||
self.menu.insert(rmi, i)
|
||||
i = i + 1
|
||||
rmi.show()
|
||||
self.menu.insert(self.manage_item, i)
|
||||
self.menu.show()
|
||||
|
||||
def select_search(self, menuitem, engine_string):
|
||||
self.menu_button.set_label("Search " + engine_string)
|
||||
self.se = engine_string
|
||||
|
||||
|
||||
register_plugin("Torrent Search",
|
||||
plugin_Search,
|
||||
"0.5",
|
||||
"A searchbar for torrent search engines",
|
||||
config=True,
|
||||
default=False,
|
||||
requires="0.5.0",
|
||||
interface="gtk",
|
||||
required_plugins=None)
|
183
plugins/TorrentSearch/searchdlg.glade
Normal file
183
plugins/TorrentSearch/searchdlg.glade
Normal file
@ -0,0 +1,183 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!DOCTYPE glade-interface SYSTEM "glade-2.0.dtd">
|
||||
<!--Generated with glade3 3.1.4 on Wed Feb 14 19:36:16 2007 by zach@notapowerbook-->
|
||||
<glade-interface>
|
||||
<widget class="GtkDialog" id="search_dialog">
|
||||
<property name="border_width">5</property>
|
||||
<property name="title" translatable="yes">Manage Search Plugins</property>
|
||||
<property name="has_separator">False</property>
|
||||
<child internal-child="vbox">
|
||||
<widget class="GtkVBox" id="dialog-vbox1">
|
||||
<property name="visible">True</property>
|
||||
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_ENTER_NOTIFY_MASK</property>
|
||||
<property name="spacing">2</property>
|
||||
<child>
|
||||
<widget class="GtkTable" id="table1">
|
||||
<property name="visible">True</property>
|
||||
<property name="n_rows">4</property>
|
||||
<property name="n_columns">4</property>
|
||||
<child>
|
||||
<widget class="GtkExpander" id="expander1">
|
||||
<property name="visible">True</property>
|
||||
<property name="expanded">True</property>
|
||||
<child>
|
||||
<widget class="GtkLabel" id="label3">
|
||||
<property name="visible">True</property>
|
||||
<property name="label" translatable="yes">Add a new search engine by entering a Name and a URL. For Name, enter the name of the search engine to be used. For URL, enter the url of the seach page. The user's search query will replace any instance of ${query} in the URL.
|
||||
For example, a Google search would be:
|
||||
Name: Google
|
||||
URL: http://www.google.com/search?q=${query}</property>
|
||||
<property name="wrap">True</property>
|
||||
</widget>
|
||||
</child>
|
||||
<child>
|
||||
<widget class="GtkLabel" id="label3">
|
||||
<property name="visible">True</property>
|
||||
<property name="label" translatable="yes">Help</property>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="type">label_item</property>
|
||||
</packing>
|
||||
</child>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="right_attach">4</property>
|
||||
<property name="top_attach">3</property>
|
||||
<property name="bottom_attach">4</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<widget class="GtkButton" id="button_delsearch">
|
||||
<property name="visible">True</property>
|
||||
<property name="label" translatable="yes">gtk-remove</property>
|
||||
<property name="use_stock">True</property>
|
||||
<signal name="clicked" handler="del_clicked"/>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="left_attach">3</property>
|
||||
<property name="right_attach">4</property>
|
||||
<property name="top_attach">1</property>
|
||||
<property name="bottom_attach">2</property>
|
||||
<property name="x_options">GTK_FILL</property>
|
||||
<property name="y_options">GTK_FILL</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<widget class="GtkLabel" id="label2">
|
||||
<property name="visible">True</property>
|
||||
<property name="label" translatable="yes">URL:</property>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="top_attach">2</property>
|
||||
<property name="bottom_attach">3</property>
|
||||
<property name="x_options">GTK_FILL</property>
|
||||
<property name="y_options">GTK_FILL</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<widget class="GtkLabel" id="label1">
|
||||
<property name="visible">True</property>
|
||||
<property name="label" translatable="yes">Name:</property>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="top_attach">1</property>
|
||||
<property name="bottom_attach">2</property>
|
||||
<property name="x_options">GTK_FILL</property>
|
||||
<property name="y_options">GTK_FILL</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<widget class="GtkEntry" id="field_search">
|
||||
<property name="visible">True</property>
|
||||
<signal name="changed" handler="text_changed"/>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="left_attach">1</property>
|
||||
<property name="right_attach">4</property>
|
||||
<property name="top_attach">2</property>
|
||||
<property name="bottom_attach">3</property>
|
||||
<property name="y_options">GTK_FILL</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<widget class="GtkEntry" id="field_name">
|
||||
<property name="visible">True</property>
|
||||
<signal name="changed" handler="text_changed"/>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="left_attach">1</property>
|
||||
<property name="right_attach">2</property>
|
||||
<property name="top_attach">1</property>
|
||||
<property name="bottom_attach">2</property>
|
||||
<property name="y_options">GTK_FILL</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<widget class="GtkScrolledWindow" id="scrolledwindow1">
|
||||
<property name="visible">True</property>
|
||||
<property name="hscrollbar_policy">GTK_POLICY_AUTOMATIC</property>
|
||||
<child>
|
||||
<widget class="GtkTreeView" id="search_view">
|
||||
<property name="visible">True</property>
|
||||
</widget>
|
||||
</child>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="right_attach">4</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<widget class="GtkButton" id="button_addsearch">
|
||||
<property name="visible">True</property>
|
||||
<property name="label" translatable="yes">gtk-add</property>
|
||||
<property name="use_stock">True</property>
|
||||
<signal name="pressed" handler="add_clicked"/>
|
||||
<signal name="activate" handler="add_clicked"/>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="left_attach">2</property>
|
||||
<property name="right_attach">3</property>
|
||||
<property name="top_attach">1</property>
|
||||
<property name="bottom_attach">2</property>
|
||||
<property name="x_options">GTK_FILL</property>
|
||||
<property name="y_options">GTK_FILL</property>
|
||||
</packing>
|
||||
</child>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child internal-child="action_area">
|
||||
<widget class="GtkHButtonBox" id="dialog-action_area1">
|
||||
<property name="visible">True</property>
|
||||
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_ENTER_NOTIFY_MASK</property>
|
||||
<property name="layout_style">GTK_BUTTONBOX_END</property>
|
||||
<child>
|
||||
<widget class="GtkButton" id="button3">
|
||||
<property name="visible">True</property>
|
||||
<property name="label" translatable="yes">gtk-cancel</property>
|
||||
<property name="use_stock">True</property>
|
||||
</widget>
|
||||
</child>
|
||||
<child>
|
||||
<widget class="GtkButton" id="button2">
|
||||
<property name="visible">True</property>
|
||||
<property name="label" translatable="yes">gtk-ok</property>
|
||||
<property name="use_stock">True</property>
|
||||
<property name="response_id">1</property>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="pack_type">GTK_PACK_END</property>
|
||||
</packing>
|
||||
</child>
|
||||
</widget>
|
||||
</child>
|
||||
</widget>
|
||||
</glade-interface>
|
@ -65,11 +65,14 @@ class DelugePreferences:
|
||||
def keys(self):
|
||||
return self.pref.keys()
|
||||
|
||||
def clear(self):
|
||||
self.pref.clear()
|
||||
|
||||
def load_from_file(self, filename):
|
||||
f = open(filename, mode='r')
|
||||
for line in f:
|
||||
try:
|
||||
(key, value) = line.split("=")
|
||||
(key, value) = line.split("=", 1)
|
||||
key = key.strip(" \n")
|
||||
value = value.strip(" \n")
|
||||
self.pref[key] = value
|
||||
|
@ -189,7 +189,23 @@ class DelugeGTK(dbus.service.Object):
|
||||
self.plugin_view.set_model(self.plugin_store)
|
||||
dgtk.add_text_column(self.plugin_view, "Name", 0)
|
||||
dgtk.add_toggle_column(self.plugin_view, "Enabled", 1, toggled_signal=self.plugin_toggled)
|
||||
|
||||
self.prf_glade.signal_autoconnect({'plugin_pref': self.plugin_pref})
|
||||
|
||||
def plugin_toggled(self, renderer, path):
|
||||
plugin_iter = self.plugin_store.get_iter_from_string(path)
|
||||
plugin_name = self.plugin_store.get_value(plugin_iter, 0)
|
||||
plugin_value = not self.plugin_store.get_value(plugin_iter, 1)
|
||||
self.plugin_store.set_value(plugin_iter, 1, plugin_value)
|
||||
if plugin_value:
|
||||
self.plugins.enable_plugin(plugin_name)
|
||||
else:
|
||||
self.plugins.disable_plugin(plugin_name)
|
||||
|
||||
def plugin_pref(self, widget=None):
|
||||
print "foobar"
|
||||
(model, plugin_iter) = self.plugin_view.get_selection().get_selected()
|
||||
plugin_name = self.plugin_store.get_value(plugin_iter, 0)
|
||||
self.plugins.configure_plugin(plugin_name)
|
||||
|
||||
def build_torrent_table(self):
|
||||
## Create the torrent listview
|
||||
@ -337,21 +353,15 @@ class DelugeGTK(dbus.service.Object):
|
||||
def show_plugin_dialog(self, arg=None):
|
||||
self.plugin_store.clear()
|
||||
for plugin in self.plugins.get_available_plugins():
|
||||
self.plugin_store.append( (plugin, False) )
|
||||
if plugin in self.plugins.get_enabled_plugins():
|
||||
self.plugin_store.append( (plugin, True) )
|
||||
else:
|
||||
self.plugin_store.append( (plugin, False) )
|
||||
self.plugin_dlg.show()
|
||||
self.plugin_dlg.run()
|
||||
self.plugin_dlg.hide()
|
||||
|
||||
def plugin_toggled(self, renderer, path):
|
||||
plugin_iter = self.plugin_store.get_iter_from_string(path)
|
||||
plugin_name = self.plugin_store.get_value(plugin_iter, 0)
|
||||
plugin_value = not self.plugin_store.get_value(plugin_iter, 1)
|
||||
self.plugin_store.set_value(plugin_iter, 1, plugin_value)
|
||||
print "Plugin:", plugin_name, renderer.get_active()
|
||||
if plugin_value:
|
||||
self.plugins.enable_plugin(plugin_name)
|
||||
else:
|
||||
self.plugins.disable_plugin(plugin_name)
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -39,6 +39,7 @@ class PluginManager:
|
||||
plugin_folders = os.listdir(folder)
|
||||
for plugin in plugin_folders:
|
||||
if os.path.isfile(folder + "/" + plugin + "/plugin.py"):
|
||||
self.path = folder + "/" + plugin
|
||||
execfile(folder + "/" + plugin + "/plugin.py")
|
||||
|
||||
def get_available_plugins(self):
|
||||
@ -48,7 +49,8 @@ class PluginManager:
|
||||
return self.available_plugins[name]
|
||||
|
||||
def enable_plugin(self, name):
|
||||
self.enabled_plugins[name] = self.available_plugins[name]['class'](self.core, self.interface)
|
||||
self.enabled_plugins[name] = self.available_plugins[name]['class'](
|
||||
self.available_plugins[name]['path'], self.core, self.interface)
|
||||
|
||||
def get_enabled_plugins(self):
|
||||
return self.enabled_plugins.keys()
|
||||
@ -56,6 +58,10 @@ class PluginManager:
|
||||
def disable_plugin(self, name):
|
||||
self.enabled_plugins[name].unload()
|
||||
self.enabled_plugins.pop(name)
|
||||
|
||||
def configure_plugin(self, name):
|
||||
print "configuring", name
|
||||
self.enabled_plugins[name].configure()
|
||||
|
||||
def update_active_plugins(self):
|
||||
for name in self.enabled_plugins.keys():
|
||||
@ -78,8 +84,8 @@ class PluginManager:
|
||||
'default': default,
|
||||
'requires': requires,
|
||||
'interface': interface,
|
||||
'req plugins': required_plugins
|
||||
}
|
||||
'req plugins': required_plugins,
|
||||
'path': self.path}
|
||||
|
||||
## Few lines of code to test functionality
|
||||
if __name__ == "__main__":
|
||||
|
Loading…
x
Reference in New Issue
Block a user