merge branches
This commit is contained in:
commit
e21cc8accf
|
@ -51,33 +51,12 @@
|
|||
<property name="orientation">vertical</property>
|
||||
<property name="spacing">6</property>
|
||||
<child>
|
||||
<object class="GtkHBox" id="hbox4">
|
||||
<object class="GtkLabel" id="plugin_name_label">
|
||||
<property name="visible">True</property>
|
||||
<property name="spacing">6</property>
|
||||
<child>
|
||||
<object class="GtkLabel" id="plugin_name_label">
|
||||
<property name="visible">True</property>
|
||||
<property name="xalign">0</property>
|
||||
<property name="label" translatable="yes">&lt;empty&gt;</property>
|
||||
<property name="use_markup">True</property>
|
||||
<property name="wrap">True</property>
|
||||
<property name="selectable">True</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkAlignment" id="alignment1">
|
||||
<property name="visible">True</property>
|
||||
<child>
|
||||
<placeholder/>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
<property name="xalign">0</property>
|
||||
<property name="label" translatable="yes">&lt;empty&gt;</property>
|
||||
<property name="use_markup">True</property>
|
||||
<property name="selectable">True</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
from ftp_manager import FtpManager
|
|
@ -0,0 +1,281 @@
|
|||
<?xml version="1.0"?>
|
||||
<interface>
|
||||
<requires lib="gtk+" version="2.16"/>
|
||||
<!-- interface-naming-policy toplevel-contextual -->
|
||||
<object class="GtkTextBuffer" id="textbuffer1">
|
||||
<property name="text" translatable="yes">Plug-in decription should be displayed here. This text will be erased during PluginsWindow initialization.</property>
|
||||
</object>
|
||||
<object class="GtkWindow" id="window1">
|
||||
<child>
|
||||
<object class="GtkHPaned" id="hpaned2">
|
||||
<property name="width_request">600</property>
|
||||
<property name="height_request">350</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="position">340</property>
|
||||
<property name="position_set">True</property>
|
||||
<child>
|
||||
<object class="GtkScrolledWindow" id="scrolledwindow2">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="border_width">6</property>
|
||||
<property name="hscrollbar_policy">automatic</property>
|
||||
<property name="vscrollbar_policy">automatic</property>
|
||||
<child>
|
||||
<object class="GtkTreeView" id="available_treeview">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="search_column">1</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="resize">False</property>
|
||||
<property name="shrink">True</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkVBox" id="vbox4">
|
||||
<property name="visible">True</property>
|
||||
<property name="border_width">5</property>
|
||||
<property name="orientation">vertical</property>
|
||||
<property name="spacing">6</property>
|
||||
<child>
|
||||
<object class="GtkLabel" id="plugin_name_label1">
|
||||
<property name="visible">True</property>
|
||||
<property name="xalign">0</property>
|
||||
<property name="label" translatable="yes"><empty></property>
|
||||
<property name="selectable">True</property>
|
||||
<property name="ellipsize">end</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkHBox" id="hbox8">
|
||||
<property name="visible">True</property>
|
||||
<property name="spacing">6</property>
|
||||
<child>
|
||||
<object class="GtkLabel" id="label8">
|
||||
<property name="visible">True</property>
|
||||
<property name="label" translatable="yes">Authors:</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel" id="plugin_authors_label1">
|
||||
<property name="visible">True</property>
|
||||
<property name="xalign">0</property>
|
||||
<property name="xpad">6</property>
|
||||
<property name="label" translatable="yes"><empty></property>
|
||||
<property name="selectable">True</property>
|
||||
<property name="ellipsize">end</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkHBox" id="hbox9">
|
||||
<property name="visible">True</property>
|
||||
<child>
|
||||
<object class="GtkLabel" id="label9">
|
||||
<property name="visible">True</property>
|
||||
<property name="label" translatable="yes">Homepage:</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLinkButton" id="plugin_homepage_linkbutton1">
|
||||
<property name="label" translatable="yes">button</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">True</property>
|
||||
<property name="relief">none</property>
|
||||
<property name="focus_on_click">False</property>
|
||||
<property name="xalign">0</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="position">2</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkVBox" id="vbox5">
|
||||
<property name="visible">True</property>
|
||||
<property name="orientation">vertical</property>
|
||||
<child>
|
||||
<object class="GtkHBox" id="hbox10">
|
||||
<property name="visible">True</property>
|
||||
<child>
|
||||
<object class="GtkLabel" id="label10">
|
||||
<property name="visible">True</property>
|
||||
<property name="label" translatable="yes">Descrition:</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkAlignment" id="alignment4">
|
||||
<property name="visible">True</property>
|
||||
<child>
|
||||
<placeholder/>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkTextView" id="plugin_description_textview1">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="pixels_above_lines">6</property>
|
||||
<property name="wrap_mode">word</property>
|
||||
<property name="left_margin">6</property>
|
||||
<property name="right_margin">6</property>
|
||||
<property name="indent">1</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="position">3</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkHBox" id="hbox15">
|
||||
<property name="visible">True</property>
|
||||
<child>
|
||||
<object class="GtkProgressBar" id="progressbar">
|
||||
<property name="ellipsize">end</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkHButtonBox" id="hbuttonbox3">
|
||||
<property name="visible">True</property>
|
||||
<property name="layout_style">end</property>
|
||||
<child>
|
||||
<object class="GtkButton" id="inslall_upgrade_button">
|
||||
<property name="visible">True</property>
|
||||
<property name="sensitive">False</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="receives_default">True</property>
|
||||
<signal name="clicked" handler="on_inslall_upgrade_clicked"/>
|
||||
<child>
|
||||
<object class="GtkHBox" id="hbox1">
|
||||
<property name="visible">True</property>
|
||||
<child>
|
||||
<object class="GtkImage" id="image1">
|
||||
<property name="visible">True</property>
|
||||
<property name="stock">gtk-refresh</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel" id="label1">
|
||||
<property name="visible">True</property>
|
||||
<property name="xalign">0</property>
|
||||
<property name="label" translatable="yes">Install/Upgrade</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">False</property>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">False</property>
|
||||
<property name="pack_type">end</property>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">False</property>
|
||||
<property name="position">4</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="resize">True</property>
|
||||
<property name="shrink">True</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
<object class="GtkWindow" id="window2">
|
||||
<child>
|
||||
<object class="GtkHBox" id="hbox111">
|
||||
<property name="visible">True</property>
|
||||
<child>
|
||||
<object class="GtkLabel" id="label1">
|
||||
<property name="visible">True</property>
|
||||
<property name="xalign">0</property>
|
||||
<property name="label" translatable="yes">Ftp server:</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">False</property>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkEntry" id="ftp_server">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="invisible_char">●</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</interface>
|
|
@ -0,0 +1,459 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
## plugins/ftp_manager/ftp_manager.py
|
||||
##
|
||||
## Copyright (C) 2010 Denis Fomin <fominde AT gmail.com>
|
||||
##
|
||||
## This file is part of Gajim.
|
||||
##
|
||||
## Gajim 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; version 3 only.
|
||||
##
|
||||
## Gajim 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 Gajim. If not, see <http://www.gnu.org/licenses/>.
|
||||
##
|
||||
import gtk
|
||||
import pango
|
||||
import gobject
|
||||
import ftplib
|
||||
import io
|
||||
import threading
|
||||
import ConfigParser
|
||||
import os
|
||||
import fnmatch
|
||||
import sys
|
||||
|
||||
from common import gajim
|
||||
from plugins import GajimPlugin
|
||||
from plugins.helpers import log_calls, log
|
||||
from dialogs import WarningDialog, HigDialog
|
||||
from plugins.gui import GajimPluginConfigDialog
|
||||
from common import i18n
|
||||
|
||||
class FtpManager(GajimPlugin):
|
||||
|
||||
@log_calls('FtpManagerPlugin')
|
||||
def init(self):
|
||||
self.config_dialog = FtpManagerPluginConfigDialog(self)
|
||||
self.config_default_values = {'ftp_server': ('ftp.gajim.org','')}
|
||||
|
||||
@log_calls('FtpManagerPlugin')
|
||||
def activate(self):
|
||||
self.pl_menuitem = gajim.interface.roster.xml.get_object(
|
||||
'plugins_menuitem')
|
||||
self.id_ = self.pl_menuitem.connect_after('activate', self.on_activate)
|
||||
if gajim.interface.instances.has_key('plugins'):
|
||||
self.on_activate(None)
|
||||
|
||||
@log_calls('FtpManagerPlugin')
|
||||
def deactivate(self):
|
||||
self.pl_menuitem.disconnect(self.id_)
|
||||
if hasattr(self, 'page_num'):
|
||||
self.notebook.remove_page(self.page_num)
|
||||
self.notebook.set_current_page(0)
|
||||
if hasattr(self, 'ftp'):
|
||||
del self.ftp
|
||||
|
||||
def on_activate(self, widget):
|
||||
if not gajim.interface.instances.has_key('plugins'):
|
||||
return
|
||||
self.installed_plugins_model = gajim.interface.instances[
|
||||
'plugins'].installed_plugins_model
|
||||
self.notebook = gajim.interface.instances['plugins'].plugins_notebook
|
||||
self.id_n = self.notebook.connect('switch-page',
|
||||
self.on_notebook_switch_page)
|
||||
self.window = gajim.interface.instances['plugins'].window
|
||||
self.window.connect('destroy', self.on_win_destroy)
|
||||
self.GTK_BUILDER_FILE_PATH = self.local_file_path(
|
||||
'config_dialog.ui')
|
||||
self.xml = gtk.Builder()
|
||||
self.xml.set_translation_domain(i18n.APP)
|
||||
self.xml.add_objects_from_file(self.GTK_BUILDER_FILE_PATH,
|
||||
['hpaned2'])
|
||||
hpaned = self.xml.get_object('hpaned2')
|
||||
self.page_num = self.notebook.append_page(hpaned,
|
||||
gtk.Label('Ftp Manager'))
|
||||
|
||||
widgets_to_extract = ('plugin_name_label1',
|
||||
'available_treeview', 'progressbar', 'inslall_upgrade_button',
|
||||
'plugin_authors_label1', 'plugin_authors_label1',
|
||||
'plugin_homepage_linkbutton1', 'plugin_description_textview1')
|
||||
|
||||
for widget_name in widgets_to_extract:
|
||||
setattr(self, widget_name, self.xml.get_object(widget_name))
|
||||
|
||||
attr_list = pango.AttrList()
|
||||
attr_list.insert(pango.AttrWeight(pango.WEIGHT_BOLD, 0, -1))
|
||||
self.plugin_name_label1.set_attributes(attr_list)
|
||||
|
||||
self.available_plugins_model = gtk.ListStore(gobject.TYPE_PYOBJECT,
|
||||
gobject.TYPE_STRING, gobject.TYPE_STRING, gobject.TYPE_STRING,
|
||||
gobject.TYPE_BOOLEAN, gobject.TYPE_PYOBJECT, gobject.TYPE_PYOBJECT,
|
||||
gobject.TYPE_PYOBJECT)
|
||||
self.available_treeview.set_model(self.available_plugins_model)
|
||||
|
||||
self.progressbar.set_property('no-show-all', True)
|
||||
renderer = gtk.CellRendererText()
|
||||
col = gtk.TreeViewColumn(_('Plugin'), renderer, text=1)
|
||||
col.set_resizable(True)
|
||||
col.set_property('expand', True)
|
||||
col.set_sizing(gtk.TREE_VIEW_COLUMN_GROW_ONLY)
|
||||
self.available_treeview.append_column(col)
|
||||
col = gtk.TreeViewColumn(_('Installed\nversion'), renderer, text=2)
|
||||
self.available_treeview.append_column(col)
|
||||
col = gtk.TreeViewColumn(_('Available\nversion'), renderer, text=3)
|
||||
col.set_property('expand', False)
|
||||
self.available_treeview.append_column(col)
|
||||
|
||||
renderer = gtk.CellRendererToggle()
|
||||
renderer.set_property('activatable', True)
|
||||
renderer.connect('toggled', self.available_plugins_toggled_cb)
|
||||
col = gtk.TreeViewColumn(_('Install /\nUpgrade'), renderer, active=4)
|
||||
self.available_treeview.append_column(col)
|
||||
|
||||
if gobject.signal_lookup('error_signal', self.window) is 0:
|
||||
gobject.signal_new('error_signal', self.window,
|
||||
gobject.SIGNAL_RUN_LAST, gobject.TYPE_STRING,
|
||||
(gobject.TYPE_STRING,))
|
||||
gobject.signal_new('plugin_downloaded', self.window,
|
||||
gobject.SIGNAL_RUN_LAST, gobject.TYPE_STRING,
|
||||
(gobject.TYPE_PYOBJECT,))
|
||||
self.window.connect('error_signal', self.on_some_ftp_error)
|
||||
self.window.connect('plugin_downloaded', self.on_plugin_downloaded)
|
||||
|
||||
selection = self.available_treeview.get_selection()
|
||||
selection.connect('changed',
|
||||
self.available_plugins_treeview_selection_changed)
|
||||
selection.set_mode(gtk.SELECTION_SINGLE)
|
||||
|
||||
self._clear_available_plugin_info()
|
||||
self.xml.connect_signals(self)
|
||||
self.window.show_all()
|
||||
|
||||
def on_win_destroy(self, widget):
|
||||
if hasattr(self, 'ftp'):
|
||||
del self.ftp
|
||||
|
||||
def available_plugins_toggled_cb(self, cell, path):
|
||||
is_active = self.available_plugins_model[path][4]
|
||||
self.available_plugins_model[path][4] = not is_active
|
||||
dir_list = []
|
||||
for i in xrange(len(self.available_plugins_model)):
|
||||
if self.available_plugins_model[i][4]:
|
||||
dir_list.append(self.available_plugins_model[i][0])
|
||||
if not dir_list:
|
||||
self.inslall_upgrade_button.set_property('sensitive', False)
|
||||
else:
|
||||
self.inslall_upgrade_button.set_property('sensitive', True)
|
||||
|
||||
def on_notebook_switch_page(self, widget, page, page_num,):
|
||||
if not hasattr(self, 'ftp') and self.page_num == page_num:
|
||||
self.available_plugins_model.clear()
|
||||
self.progressbar.show()
|
||||
self.ftp = Ftp(self)
|
||||
self.ftp.remote_dirs = None
|
||||
self.ftp.start()
|
||||
|
||||
def on_inslall_upgrade_clicked(self, widget):
|
||||
self.inslall_upgrade_button.set_property('sensitive', False)
|
||||
dir_list = []
|
||||
for i in xrange(len(self.available_plugins_model)):
|
||||
if self.available_plugins_model[i][4]:
|
||||
dir_list.append(self.available_plugins_model[i][0])
|
||||
|
||||
ftp = Ftp(self)
|
||||
ftp.remote_dirs = dir_list
|
||||
ftp.start()
|
||||
|
||||
def on_some_ftp_error(self, widget, error_text):
|
||||
for i in xrange(len(self.available_plugins_model)):
|
||||
self.available_plugins_model[i][4] = False
|
||||
self.progressbar.hide()
|
||||
WarningDialog('Ftp error', error_text, self.window)
|
||||
|
||||
def on_plugin_downloaded(self, widget, plugin_dirs):
|
||||
for _dir in plugin_dirs:
|
||||
is_active = False
|
||||
plugins = None
|
||||
plugin_dir = os.path.join(gajim.PLUGINS_DIRS[1], _dir)
|
||||
plugin = gajim.plugin_manager.get_plugin_by_path(plugin_dir)
|
||||
if plugin:
|
||||
if plugin.active and plugin.name != self.name:
|
||||
is_active = True
|
||||
gobject.idle_add(gajim.plugin_manager.deactivate_plugin ,plugin)
|
||||
gajim.plugin_manager.plugins.remove(plugin)
|
||||
|
||||
model = self.installed_plugins_model
|
||||
for row in xrange(len(model)):
|
||||
if plugin == model[row][0]:
|
||||
model.remove(model.get_iter((row, 0)))
|
||||
break
|
||||
|
||||
plugins = self.scan_dir_for_plugin(plugin_dir)
|
||||
if not plugins:
|
||||
continue
|
||||
gajim.plugin_manager.add_plugin(plugins[0])
|
||||
plugin = gajim.plugin_manager.plugins[-1]
|
||||
for row in xrange(len(self.available_plugins_model)):
|
||||
if plugin.name == self.available_plugins_model[row][1]:
|
||||
self.available_plugins_model[row][2] = plugin.version
|
||||
self.available_plugins_model[row][4] = False
|
||||
continue
|
||||
if is_active and plugin.name != self.name:
|
||||
gobject.idle_add(gajim.plugin_manager.activate_plugin ,plugin)
|
||||
if plugin.name != 'Ftp Manager':
|
||||
self.installed_plugins_model.append([plugin, plugin.name,
|
||||
is_active])
|
||||
dialog = HigDialog(None, gtk.MESSAGE_INFO, gtk.BUTTONS_OK,
|
||||
'', 'All selected plugins downloaded')
|
||||
dialog.set_modal(False)
|
||||
dialog.set_transient_for(self.window)
|
||||
dialog.popup()
|
||||
|
||||
def available_plugins_treeview_selection_changed(self, treeview_selection):
|
||||
model, iter = treeview_selection.get_selected()
|
||||
if iter:
|
||||
self.plugin_name_label1.set_text(model.get_value(iter, 1))
|
||||
self.plugin_authors_label1.set_text(model.get_value(iter, 6))
|
||||
self.plugin_homepage_linkbutton1.set_uri(model.get_value(iter, 7))
|
||||
self.plugin_homepage_linkbutton1.set_label(model.get_value(iter, 7))
|
||||
label = self.plugin_homepage_linkbutton1.get_children()[0]
|
||||
label.set_ellipsize(pango.ELLIPSIZE_END)
|
||||
self.plugin_homepage_linkbutton1.set_property('sensitive', True)
|
||||
desc_textbuffer = self.plugin_description_textview1.get_buffer()
|
||||
desc_textbuffer.set_text(model.get_value(iter, 5))
|
||||
self.plugin_description_textview1.set_property('sensitive', True)
|
||||
else:
|
||||
self._clear_available_plugin_info()
|
||||
|
||||
def _clear_available_plugin_info(self):
|
||||
self.plugin_name_label1.set_text('')
|
||||
self.plugin_authors_label1.set_text('')
|
||||
self.plugin_homepage_linkbutton1.set_uri('')
|
||||
self.plugin_homepage_linkbutton1.set_label('')
|
||||
self.plugin_homepage_linkbutton1.set_property('sensitive', False)
|
||||
|
||||
desc_textbuffer = self.plugin_description_textview1.get_buffer()
|
||||
desc_textbuffer.set_text('')
|
||||
self.plugin_description_textview1.set_property('sensitive', False)
|
||||
|
||||
def scan_dir_for_plugin(self, path):
|
||||
plugins_found = []
|
||||
conf = ConfigParser.ConfigParser()
|
||||
fields = ('name', 'short_name', 'version', 'description', 'authors',
|
||||
'homepage')
|
||||
if not os.path.isdir(path):
|
||||
return plugins_found
|
||||
|
||||
dir_list = os.listdir(path)
|
||||
dir_, mod = os.path.split(path)
|
||||
sys.path.insert(0, dir_)
|
||||
|
||||
manifest_path = os.path.join(path, 'manifest.ini')
|
||||
if not os.path.isfile(manifest_path):
|
||||
return plugins_found
|
||||
|
||||
for elem_name in dir_list:
|
||||
file_path = os.path.join(path, elem_name)
|
||||
module = None
|
||||
|
||||
if os.path.isfile(file_path) and fnmatch.fnmatch(file_path, '*.py'):
|
||||
module_name = os.path.splitext(elem_name)[0]
|
||||
if module_name == '__init__':
|
||||
continue
|
||||
try:
|
||||
module = __import__('%s.%s' %(mod, module_name))
|
||||
except ValueError, value_error:
|
||||
pass
|
||||
except ImportError, import_error:
|
||||
pass
|
||||
except AttributeError, attribute_error:
|
||||
pass
|
||||
if module is None:
|
||||
continue
|
||||
|
||||
for module_attr_name in [attr_name for attr_name in dir(module)
|
||||
if not (attr_name.startswith('__') or attr_name.endswith('__'))]:
|
||||
module_attr = getattr(module, module_attr_name)
|
||||
try:
|
||||
if not issubclass(module_attr, GajimPlugin) or \
|
||||
module_attr is GajimPlugin:
|
||||
continue
|
||||
module_attr.__path__ = os.path.abspath(os.path.dirname(
|
||||
file_path))
|
||||
|
||||
# read metadata from manifest.ini
|
||||
conf.readfp(open(manifest_path, 'r'))
|
||||
for option in fields:
|
||||
if conf.get('info', option) is '':
|
||||
raise ConfigParser.NoOptionError, 'field empty'
|
||||
setattr(module_attr, option, conf.get('info', option))
|
||||
conf.remove_section('info')
|
||||
plugins_found.append(module_attr)
|
||||
|
||||
except TypeError, type_error:
|
||||
pass
|
||||
except ConfigParser.NoOptionError, type_error:
|
||||
# all fields are required
|
||||
pass
|
||||
return plugins_found
|
||||
|
||||
|
||||
class Ftp(threading.Thread):
|
||||
def __init__(self, plugin):
|
||||
super(Ftp, self).__init__()
|
||||
self.window = plugin.window
|
||||
self.server = plugin.config['ftp_server']
|
||||
self.progressbar = plugin.progressbar
|
||||
self.model = plugin.available_plugins_model
|
||||
self.config = ConfigParser.ConfigParser()
|
||||
self.buffer_ = io.BytesIO()
|
||||
self.remote_dirs = None
|
||||
self.append_to_model = True
|
||||
|
||||
def model_append(self, row):
|
||||
self.model.append(row)
|
||||
return False
|
||||
|
||||
def progressbar_pulse(self):
|
||||
self.progressbar.pulse()
|
||||
return True
|
||||
|
||||
def get_plugin_version(self, plugin_name):
|
||||
for plugin in gajim.plugin_manager.plugins:
|
||||
if plugin.name == plugin_name:
|
||||
return plugin.version
|
||||
|
||||
def run(self):
|
||||
try:
|
||||
gobject.idle_add(self.progressbar.set_text,
|
||||
'Connecting to server')
|
||||
self.ftp = ftplib.FTP(self.server)
|
||||
self.ftp.login()
|
||||
self.ftp.cwd('plugins')
|
||||
if not self.remote_dirs:
|
||||
self.plugins_dirs = self.ftp.nlst()
|
||||
progress_step = 1.0 / len(self.plugins_dirs)
|
||||
gobject.idle_add(self.progressbar.set_text,
|
||||
'Scan files on the server')
|
||||
for dir_ in self.plugins_dirs:
|
||||
fract = self.progressbar.get_fraction() + progress_step
|
||||
gobject.idle_add(self.progressbar.set_fraction, fract)
|
||||
gobject.idle_add(self.progressbar.set_text,
|
||||
'Read "%s"' % dir_)
|
||||
try:
|
||||
self.ftp.retrbinary('RETR %s/manifest.ini' %dir_,
|
||||
self.handleDownload)
|
||||
except Exception, error:
|
||||
if str(error).startswith('550'):
|
||||
continue
|
||||
self.config.readfp(io.BytesIO(self.buffer_.getvalue()))
|
||||
local_version = self.get_plugin_version(
|
||||
self.config.get('info', 'name'))
|
||||
gobject.idle_add(self.model_append,[dir_,
|
||||
self.config.get('info', 'name'), local_version,
|
||||
self.config.get('info', 'version'), False,
|
||||
self.config.get('info', 'description'),
|
||||
self.config.get('info', 'authors'),
|
||||
self.config.get('info', 'homepage'),])
|
||||
self.plugins_dirs = None
|
||||
self.ftp.quit()
|
||||
gobject.idle_add(self.progressbar.set_fraction, 0)
|
||||
if self.remote_dirs:
|
||||
self.download_plugin()
|
||||
gobject.idle_add(self.progressbar.hide)
|
||||
except Exception, e:
|
||||
self.window.emit('error_signal', str(e))
|
||||
|
||||
|
||||
def handleDownload(self, block):
|
||||
self.buffer_.write(block)
|
||||
|
||||
def download_plugin(self):
|
||||
gobject.idle_add(self.progressbar.show)
|
||||
self.pulse = gobject.timeout_add(150, self.progressbar_pulse)
|
||||
gobject.idle_add(self.progressbar.set_text,
|
||||
'Create a list of files')
|
||||
for remote_dir in self.remote_dirs:
|
||||
|
||||
def nlstr(dir_, subdir=None):
|
||||
if subdir:
|
||||
dir_ = dir_ + '/' + subdir
|
||||
list_ = self.ftp.nlst(dir_)
|
||||
for i in list_:
|
||||
name = i.split('/')[-1]
|
||||
if '.' not in name:
|
||||
try:
|
||||
if i == self.ftp.nlst(i)[0]:
|
||||
files.append(i[1:])
|
||||
del dirs[i[1:]]
|
||||
except Exception,e:
|
||||
# empty dir or file
|
||||
continue
|
||||
dirs.append(i[1:])
|
||||
subdirs = name
|
||||
nlstr(dir_, subdirs)
|
||||
else:
|
||||
files.append(i[1:])
|
||||
dirs,files = [], []
|
||||
nlstr('/plugins/' + remote_dir)
|
||||
|
||||
if not os.path.isdir(gajim.PLUGINS_DIRS[1]):
|
||||
os.mkdir(gajim.PLUGINS_DIRS[1])
|
||||
local_dir = ld = os.path.join(gajim.PLUGINS_DIRS[1], remote_dir)
|
||||
if not os.path.isdir(local_dir):
|
||||
os.mkdir(local_dir)
|
||||
local_dir = os.path.split(gajim.PLUGINS_DIRS[1])[0]
|
||||
|
||||
# creating dirs
|
||||
for dir_ in dirs:
|
||||
try:
|
||||
os.mkdir(os.path.join(local_dir, dir_))
|
||||
except OSError, e:
|
||||
if str(e).startswith('[Errno 17]'):
|
||||
continue
|
||||
raise
|
||||
|
||||
# downloading files
|
||||
for filename in files:
|
||||
gobject.idle_add(self.progressbar.set_text,
|
||||
'Downloading "%s"' % filename)
|
||||
full_filename = os.path.join(local_dir, filename)
|
||||
try:
|
||||
self.ftp.retrbinary('RETR /%s' % filename,
|
||||
open(full_filename, 'wb').write)
|
||||
#full_filename.close()
|
||||
except ftplib.error_perm:
|
||||
print 'ERROR: cannot read file "%s"' % filename
|
||||
os.unlink(filename)
|
||||
self.ftp.quit()
|
||||
self.window.emit('plugin_downloaded', self.remote_dirs)
|
||||
gobject.source_remove(self.pulse)
|
||||
|
||||
|
||||
class FtpManagerPluginConfigDialog(GajimPluginConfigDialog):
|
||||
def init(self):
|
||||
self.GTK_BUILDER_FILE_PATH = self.plugin.local_file_path(
|
||||
'config_dialog.ui')
|
||||
self.xml = gtk.Builder()
|
||||
self.xml.add_objects_from_file(self.GTK_BUILDER_FILE_PATH,
|
||||
['hbox111'])
|
||||
hbox = self.xml.get_object('hbox111')
|
||||
self.child.pack_start(hbox)
|
||||
|
||||
self.xml.connect_signals(self)
|
||||
self.connect('hide', self.on_hide)
|
||||
|
||||
def on_run(self):
|
||||
widget = self.xml.get_object('ftp_server')
|
||||
widget.set_text(str(self.plugin.config['ftp_server']))
|
||||
|
||||
def on_hide(self, widget):
|
||||
widget = self.xml.get_object('ftp_server')
|
||||
self.plugin.config['ftp_server'] = widget.get_text()
|
|
@ -0,0 +1,7 @@
|
|||
[info]
|
||||
name: Ftp Manager
|
||||
short_name: ftp_manager
|
||||
version: 0.3
|
||||
description: Install and upgrade plugins from ftp
|
||||
authors: Denis Fomin <fominde@gmail.com>
|
||||
homepage: http://trac-plugins.gajim.org/wiki/
|
|
@ -539,6 +539,9 @@ class PluginManager(object):
|
|||
self.plugins.remove(plugin)
|
||||
if self._plugin_has_entry_in_global_config(plugin):
|
||||
self._remove_plugin_entry_in_global_config(plugin)
|
||||
del sys.modules[plugin.__module__.split('.')[-1]]
|
||||
del plugin.__module__.split('.')[-1]
|
||||
del plugin
|
||||
|
||||
def get_plugin_by_path(self, plugin_dir):
|
||||
for plugin in self.plugins:
|
||||
|
|
Loading…
Reference in New Issue