Improvements to GUI extension points handling - added method to remove these from PluginManager (memory optimization).
Removed logging from most of the code.
This commit is contained in:
		
							parent
							
								
									5cce0a8ca9
								
							
						
					
					
						commit
						16ac65e58b
					
				
					 12 changed files with 226 additions and 131 deletions
				
			
		| 
						 | 
					@ -39,10 +39,7 @@ class AcronymsExpanderPlugin(GajimPlugin):
 | 
				
			||||||
	authors = [u'Mateusz Biliński <mateusz@bilinski.it>']
 | 
						authors = [u'Mateusz Biliński <mateusz@bilinski.it>']
 | 
				
			||||||
	homepage = u'http://blog.bilinski.it'
 | 
						homepage = u'http://blog.bilinski.it'
 | 
				
			||||||
		
 | 
							
 | 
				
			||||||
	#@log_calls('AcronymsExpanderPlugin')
 | 
						@log_calls('AcronymsExpanderPlugin')
 | 
				
			||||||
	#def __init__(self):
 | 
					 | 
				
			||||||
		#super(AcronymsExpanderPlugin, self).__init__()
 | 
					 | 
				
			||||||
		
 | 
					 | 
				
			||||||
	def init(self):
 | 
						def init(self):
 | 
				
			||||||
		self.config_dialog = None
 | 
							self.config_dialog = None
 | 
				
			||||||
		
 | 
							
 | 
				
			||||||
| 
						 | 
					@ -71,20 +68,20 @@ class AcronymsExpanderPlugin(GajimPlugin):
 | 
				
			||||||
		ACRONYMS = self.config['ACRONYMS']
 | 
							ACRONYMS = self.config['ACRONYMS']
 | 
				
			||||||
		INVOKER = self.config['INVOKER']
 | 
							INVOKER = self.config['INVOKER']
 | 
				
			||||||
		t = tb.get_text(tb.get_start_iter(), tb.get_end_iter())
 | 
							t = tb.get_text(tb.get_start_iter(), tb.get_end_iter())
 | 
				
			||||||
		log.debug('%s %d'%(t, len(t)))
 | 
							#log.debug('%s %d'%(t, len(t)))
 | 
				
			||||||
		if t and t[-1] == INVOKER:
 | 
							if t and t[-1] == INVOKER:
 | 
				
			||||||
			log.debug("changing msg text")
 | 
								#log.debug("changing msg text")
 | 
				
			||||||
			base,sep,head=t[:-1].rpartition(INVOKER)
 | 
								base,sep,head=t[:-1].rpartition(INVOKER)
 | 
				
			||||||
			log.debug('%s | %s | %s'%(base, sep, head))
 | 
								#log.debug('%s | %s | %s'%(base, sep, head))
 | 
				
			||||||
			if head in ACRONYMS:
 | 
								if head in ACRONYMS:
 | 
				
			||||||
				head = ACRONYMS[head]
 | 
									head = ACRONYMS[head]
 | 
				
			||||||
				log.debug("head: %s"%(head))
 | 
									log.debug("head: %s"%(head))
 | 
				
			||||||
				t = "".join((base, sep, head, INVOKER))
 | 
									t = "".join((base, sep, head, INVOKER))
 | 
				
			||||||
				log.debug("turning off notify")
 | 
									#log.debug("turning off notify")
 | 
				
			||||||
				tb.freeze_notify()
 | 
									tb.freeze_notify()
 | 
				
			||||||
				log.debug("setting text: '%s'"%(t))
 | 
									#log.debug("setting text: '%s'"%(t))
 | 
				
			||||||
				tb.set_text(t)
 | 
									tb.set_text(t)
 | 
				
			||||||
				log.debug("turning on notify")
 | 
									#log.debug("turning on notify")
 | 
				
			||||||
				tb.thaw_notify()
 | 
									tb.thaw_notify()
 | 
				
			||||||
		
 | 
							
 | 
				
			||||||
	@log_calls('AcronymsExpanderPlugin')
 | 
						@log_calls('AcronymsExpanderPlugin')
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -94,7 +94,6 @@ http://trac.gajim.org/attachment/ticket/4133'''
 | 
				
			||||||
		if self.config['show_banner_resource'] or self.config['banner_small_fonts']:
 | 
							if self.config['show_banner_resource'] or self.config['banner_small_fonts']:
 | 
				
			||||||
			banner_name_label = chat_control.xml.get_widget('banner_name_label')
 | 
								banner_name_label = chat_control.xml.get_widget('banner_name_label')
 | 
				
			||||||
			label_text = banner_name_label.get_label()
 | 
								label_text = banner_name_label.get_label()
 | 
				
			||||||
			log.debug('label_text = "%s"'%(label_text))
 | 
					 | 
				
			||||||
						
 | 
											
 | 
				
			||||||
			contact = chat_control.contact
 | 
								contact = chat_control.contact
 | 
				
			||||||
			jid = contact.jid
 | 
								jid = contact.jid
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,6 +1,6 @@
 | 
				
			||||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
 | 
					<?xml version="1.0" encoding="UTF-8" standalone="no"?>
 | 
				
			||||||
<!DOCTYPE glade-interface SYSTEM "glade-2.0.dtd">
 | 
					<!DOCTYPE glade-interface SYSTEM "glade-2.0.dtd">
 | 
				
			||||||
<!--Generated with glade3 3.4.5 on Tue Jul 29 19:58:18 2008 -->
 | 
					<!--Generated with glade3 3.4.5 on Sun Aug  3 13:57:25 2008 -->
 | 
				
			||||||
<glade-interface>
 | 
					<glade-interface>
 | 
				
			||||||
  <widget class="GtkWindow" id="window1">
 | 
					  <widget class="GtkWindow" id="window1">
 | 
				
			||||||
    <child>
 | 
					    <child>
 | 
				
			||||||
| 
						 | 
					@ -12,40 +12,58 @@
 | 
				
			||||||
        <property name="column_spacing">7</property>
 | 
					        <property name="column_spacing">7</property>
 | 
				
			||||||
        <property name="row_spacing">5</property>
 | 
					        <property name="row_spacing">5</property>
 | 
				
			||||||
        <child>
 | 
					        <child>
 | 
				
			||||||
          <widget class="GtkHBox" id="hbox2">
 | 
					          <widget class="GtkLabel" id="label1">
 | 
				
			||||||
            <property name="visible">True</property>
 | 
					            <property name="visible">True</property>
 | 
				
			||||||
            <child>
 | 
					            <property name="tooltip" translatable="yes">Message length at which notification is invoked.</property>
 | 
				
			||||||
              <widget class="GtkSpinButton" id="message_length_spinbutton">
 | 
					            <property name="xalign">0</property>
 | 
				
			||||||
                <property name="visible">True</property>
 | 
					            <property name="label" translatable="yes">Message length:</property>
 | 
				
			||||||
                <property name="can_focus">True</property>
 | 
					          </widget>
 | 
				
			||||||
                <property name="tooltip" translatable="yes">Message length at which notification is invoked.</property>
 | 
					          <packing>
 | 
				
			||||||
                <property name="width_chars">6</property>
 | 
					            <property name="x_options">GTK_FILL</property>
 | 
				
			||||||
                <property name="adjustment">0 0 999999 1 10 10</property>
 | 
					            <property name="y_options">GTK_FILL</property>
 | 
				
			||||||
                <property name="snap_to_ticks">True</property>
 | 
					          </packing>
 | 
				
			||||||
                <property name="numeric">True</property>
 | 
					        </child>
 | 
				
			||||||
                <signal name="value_changed" handler="on_message_length_spinbutton_value_changed"/>
 | 
					        <child>
 | 
				
			||||||
              </widget>
 | 
					          <widget class="GtkLabel" id="label2">
 | 
				
			||||||
              <packing>
 | 
					            <property name="visible">True</property>
 | 
				
			||||||
                <property name="expand">False</property>
 | 
					            <property name="tooltip" translatable="yes">Background color of text entry field in chat window when notification is invoked.</property>
 | 
				
			||||||
                <property name="fill">False</property>
 | 
					            <property name="xalign">0</property>
 | 
				
			||||||
              </packing>
 | 
					            <property name="label" translatable="yes">Notification color:</property>
 | 
				
			||||||
            </child>
 | 
					          </widget>
 | 
				
			||||||
            <child>
 | 
					          <packing>
 | 
				
			||||||
              <widget class="GtkAlignment" id="alignment2">
 | 
					            <property name="top_attach">1</property>
 | 
				
			||||||
                <property name="visible">True</property>
 | 
					            <property name="bottom_attach">2</property>
 | 
				
			||||||
                <child>
 | 
					            <property name="x_options">GTK_FILL</property>
 | 
				
			||||||
                  <placeholder/>
 | 
					            <property name="y_options">GTK_FILL</property>
 | 
				
			||||||
                </child>
 | 
					          </packing>
 | 
				
			||||||
              </widget>
 | 
					        </child>
 | 
				
			||||||
              <packing>
 | 
					        <child>
 | 
				
			||||||
                <property name="position">1</property>
 | 
					          <widget class="GtkLabel" id="label3">
 | 
				
			||||||
              </packing>
 | 
					            <property name="visible">True</property>
 | 
				
			||||||
            </child>
 | 
					            <property name="tooltip" translatable="yes">JabberIDs that plugin should be used with (eg. restrict only to one microblogging bot). Use comma (without space) as separator. If empty plugin is used with every JID. </property>
 | 
				
			||||||
 | 
					            <property name="xalign">0</property>
 | 
				
			||||||
 | 
					            <property name="label" translatable="yes">JabberIDs to include:</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="GtkEntry" id="jids_entry">
 | 
				
			||||||
 | 
					            <property name="visible">True</property>
 | 
				
			||||||
 | 
					            <property name="can_focus">True</property>
 | 
				
			||||||
 | 
					            <property name="tooltip" translatable="yes">JabberIDs that plugin should be used with (eg. restrict only to one microblogging bot). Use comma (without space) as separator. If empty plugin is used with every JID. </property>
 | 
				
			||||||
 | 
					            <signal name="changed" handler="on_jids_entry_changed"/>
 | 
				
			||||||
 | 
					            <signal name="editing_done" handler="on_jids_entry_editing_done"/>
 | 
				
			||||||
          </widget>
 | 
					          </widget>
 | 
				
			||||||
          <packing>
 | 
					          <packing>
 | 
				
			||||||
            <property name="left_attach">1</property>
 | 
					            <property name="left_attach">1</property>
 | 
				
			||||||
            <property name="right_attach">2</property>
 | 
					            <property name="right_attach">2</property>
 | 
				
			||||||
            <property name="x_options">GTK_FILL</property>
 | 
					            <property name="top_attach">2</property>
 | 
				
			||||||
 | 
					            <property name="bottom_attach">3</property>
 | 
				
			||||||
            <property name="y_options">GTK_FILL</property>
 | 
					            <property name="y_options">GTK_FILL</property>
 | 
				
			||||||
          </packing>
 | 
					          </packing>
 | 
				
			||||||
        </child>
 | 
					        </child>
 | 
				
			||||||
| 
						 | 
					@ -91,57 +109,39 @@
 | 
				
			||||||
          </packing>
 | 
					          </packing>
 | 
				
			||||||
        </child>
 | 
					        </child>
 | 
				
			||||||
        <child>
 | 
					        <child>
 | 
				
			||||||
          <widget class="GtkEntry" id="jids_entry">
 | 
					          <widget class="GtkHBox" id="hbox2">
 | 
				
			||||||
            <property name="visible">True</property>
 | 
					            <property name="visible">True</property>
 | 
				
			||||||
            <property name="can_focus">True</property>
 | 
					            <child>
 | 
				
			||||||
            <property name="tooltip" translatable="yes">JabberIDs that plugin should be used with (eg. restrict only to one microblogging bot). If empty plugin is used with every JID. [not implemented]</property>
 | 
					              <widget class="GtkSpinButton" id="message_length_spinbutton">
 | 
				
			||||||
            <signal name="changed" handler="on_jids_entry_changed"/>
 | 
					                <property name="visible">True</property>
 | 
				
			||||||
            <signal name="editing_done" handler="on_jids_entry_editing_done"/>
 | 
					                <property name="can_focus">True</property>
 | 
				
			||||||
 | 
					                <property name="tooltip" translatable="yes">Message length at which notification is invoked.</property>
 | 
				
			||||||
 | 
					                <property name="width_chars">6</property>
 | 
				
			||||||
 | 
					                <property name="adjustment">0 0 999999 1 10 10</property>
 | 
				
			||||||
 | 
					                <property name="snap_to_ticks">True</property>
 | 
				
			||||||
 | 
					                <property name="numeric">True</property>
 | 
				
			||||||
 | 
					                <signal name="value_changed" handler="on_message_length_spinbutton_value_changed"/>
 | 
				
			||||||
 | 
					              </widget>
 | 
				
			||||||
 | 
					              <packing>
 | 
				
			||||||
 | 
					                <property name="expand">False</property>
 | 
				
			||||||
 | 
					                <property name="fill">False</property>
 | 
				
			||||||
 | 
					              </packing>
 | 
				
			||||||
 | 
					            </child>
 | 
				
			||||||
 | 
					            <child>
 | 
				
			||||||
 | 
					              <widget class="GtkAlignment" id="alignment2">
 | 
				
			||||||
 | 
					                <property name="visible">True</property>
 | 
				
			||||||
 | 
					                <child>
 | 
				
			||||||
 | 
					                  <placeholder/>
 | 
				
			||||||
 | 
					                </child>
 | 
				
			||||||
 | 
					              </widget>
 | 
				
			||||||
 | 
					              <packing>
 | 
				
			||||||
 | 
					                <property name="position">1</property>
 | 
				
			||||||
 | 
					              </packing>
 | 
				
			||||||
 | 
					            </child>
 | 
				
			||||||
          </widget>
 | 
					          </widget>
 | 
				
			||||||
          <packing>
 | 
					          <packing>
 | 
				
			||||||
            <property name="left_attach">1</property>
 | 
					            <property name="left_attach">1</property>
 | 
				
			||||||
            <property name="right_attach">2</property>
 | 
					            <property name="right_attach">2</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="GtkLabel" id="label3">
 | 
					 | 
				
			||||||
            <property name="visible">True</property>
 | 
					 | 
				
			||||||
            <property name="tooltip" translatable="yes">JabberIDs that plugin should be used with (eg. restrict only to one microblogging bot). If empty plugin is used with every JID. [not implemented]</property>
 | 
					 | 
				
			||||||
            <property name="xalign">0</property>
 | 
					 | 
				
			||||||
            <property name="label" translatable="yes">JabberIDs to include:</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="label2">
 | 
					 | 
				
			||||||
            <property name="visible">True</property>
 | 
					 | 
				
			||||||
            <property name="tooltip" translatable="yes">Background color of text entry field in chat window when notification is invoked.</property>
 | 
					 | 
				
			||||||
            <property name="xalign">0</property>
 | 
					 | 
				
			||||||
            <property name="label" translatable="yes">Notification color:</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="GtkLabel" id="label1">
 | 
					 | 
				
			||||||
            <property name="visible">True</property>
 | 
					 | 
				
			||||||
            <property name="tooltip" translatable="yes">Message length at which notification is invoked.</property>
 | 
					 | 
				
			||||||
            <property name="xalign">0</property>
 | 
					 | 
				
			||||||
            <property name="label" translatable="yes">Message length:</property>
 | 
					 | 
				
			||||||
          </widget>
 | 
					 | 
				
			||||||
          <packing>
 | 
					 | 
				
			||||||
            <property name="x_options">GTK_FILL</property>
 | 
					            <property name="x_options">GTK_FILL</property>
 | 
				
			||||||
            <property name="y_options">GTK_FILL</property>
 | 
					            <property name="y_options">GTK_FILL</property>
 | 
				
			||||||
          </packing>
 | 
					          </packing>
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -41,10 +41,6 @@ class LengthNotifierPlugin(GajimPlugin):
 | 
				
			||||||
	authors = [u'Mateusz Biliński <mateusz@bilinski.it>']
 | 
						authors = [u'Mateusz Biliński <mateusz@bilinski.it>']
 | 
				
			||||||
	homepage = u'http://blog.bilinski.it'
 | 
						homepage = u'http://blog.bilinski.it'
 | 
				
			||||||
	
 | 
						
 | 
				
			||||||
	#@log_calls('LengthNotifierPlugin')
 | 
					 | 
				
			||||||
	#def __init__(self):
 | 
					 | 
				
			||||||
		#super(LengthNotifierPlugin, self).__init__()
 | 
					 | 
				
			||||||
	
 | 
					 | 
				
			||||||
	@log_calls('LengthNotifierPlugin')
 | 
						@log_calls('LengthNotifierPlugin')
 | 
				
			||||||
	def init(self):
 | 
						def init(self):
 | 
				
			||||||
		self.config_dialog = LengthNotifierPluginConfigDialog(self)
 | 
							self.config_dialog = LengthNotifierPluginConfigDialog(self)
 | 
				
			||||||
| 
						 | 
					@ -107,7 +103,8 @@ class LengthNotifierPlugin(GajimPlugin):
 | 
				
			||||||
			if d['prev_color']:
 | 
								if d['prev_color']:
 | 
				
			||||||
				tv.modify_base(gtk.STATE_NORMAL, d['prev_color'])
 | 
									tv.modify_base(gtk.STATE_NORMAL, d['prev_color'])
 | 
				
			||||||
		except AttributeError, error:
 | 
							except AttributeError, error:
 | 
				
			||||||
			log.debug('Length Notifier Plugin was (probably) never connected with this chat window.\n Error: %s' % (error))
 | 
								pass
 | 
				
			||||||
 | 
								#log.debug('Length Notifier Plugin was (probably) never connected with this chat window.\n Error: %s' % (error))
 | 
				
			||||||
	
 | 
						
 | 
				
			||||||
	@log_calls('LengthNotifierPlugin')
 | 
						@log_calls('LengthNotifierPlugin')
 | 
				
			||||||
	def jid_is_ok(self, jid):
 | 
						def jid_is_ok(self, jid):
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -41,13 +41,8 @@ class RosterButtonsPlugin(GajimPlugin):
 | 
				
			||||||
	authors = [u'Mateusz Biliński <mateusz@bilinski.it>']
 | 
						authors = [u'Mateusz Biliński <mateusz@bilinski.it>']
 | 
				
			||||||
	homepage = u'http://blog.bilinski.it'
 | 
						homepage = u'http://blog.bilinski.it'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	#@log_calls('RosterButtonsPlugin')
 | 
					 | 
				
			||||||
	#def __init__(self):
 | 
					 | 
				
			||||||
		#super(RosterButtonsPlugin, self).__init__()
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	@log_calls('RosterButtonsPlugin')	
 | 
						@log_calls('RosterButtonsPlugin')	
 | 
				
			||||||
	def init(self):
 | 
						def init(self):
 | 
				
			||||||
		#log.debug('self.__path__==%s'%(self.__path__))
 | 
					 | 
				
			||||||
		self.GLADE_FILE_PATH = self.local_file_path('roster_buttons.glade')
 | 
							self.GLADE_FILE_PATH = self.local_file_path('roster_buttons.glade')
 | 
				
			||||||
		
 | 
							
 | 
				
			||||||
		self.roster_vbox = gajim.interface.roster.xml.get_widget('roster_vbox2')
 | 
							self.roster_vbox = gajim.interface.roster.xml.get_widget('roster_vbox2')
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -294,8 +294,16 @@ class ChatControlBase(MessageControl):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		self.smooth = True
 | 
							self.smooth = True
 | 
				
			||||||
		
 | 
							
 | 
				
			||||||
 | 
							# PluginSystem: adding GUI extension point for ChatControlBase
 | 
				
			||||||
 | 
							# instance object (also subclasses, eg. ChatControl or GroupchatControl)
 | 
				
			||||||
		gajim.plugin_manager.gui_extension_point('chat_control_base', self)
 | 
							gajim.plugin_manager.gui_extension_point('chat_control_base', self)
 | 
				
			||||||
		
 | 
							
 | 
				
			||||||
 | 
						def shutdown(self):
 | 
				
			||||||
 | 
							# PluginSystem: removing GUI extension points connected with ChatControlBase
 | 
				
			||||||
 | 
							# instance object
 | 
				
			||||||
 | 
							gajim.plugin_manager.remove_gui_extension_point('chat_control_base', self)
 | 
				
			||||||
 | 
							gajim.plugin_manager.remove_gui_extension_point('chat_control_base_draw_banner', self)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	def on_msg_textview_populate_popup(self, textview, menu):
 | 
						def on_msg_textview_populate_popup(self, textview, menu):
 | 
				
			||||||
		'''we override the default context menu and we prepend an option to switch languages'''
 | 
							'''we override the default context menu and we prepend an option to switch languages'''
 | 
				
			||||||
		def _on_select_dictionary(widget, lang):
 | 
							def _on_select_dictionary(widget, lang):
 | 
				
			||||||
| 
						 | 
					@ -1144,6 +1152,8 @@ class ChatControl(ChatControlBase):
 | 
				
			||||||
		# restore previous conversation
 | 
							# restore previous conversation
 | 
				
			||||||
		self.restore_conversation()
 | 
							self.restore_conversation()
 | 
				
			||||||
		
 | 
							
 | 
				
			||||||
 | 
							# PluginSystem: adding GUI extension point for this ChatControl 
 | 
				
			||||||
 | 
							# instance object
 | 
				
			||||||
		gajim.plugin_manager.gui_extension_point('chat_control', self)
 | 
							gajim.plugin_manager.gui_extension_point('chat_control', self)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	def on_avatar_eventbox_enter_notify_event(self, widget, event):
 | 
						def on_avatar_eventbox_enter_notify_event(self, widget, event):
 | 
				
			||||||
| 
						 | 
					@ -2022,6 +2032,13 @@ class ChatControl(ChatControlBase):
 | 
				
			||||||
			self.reset_kbd_mouse_timeout_vars()
 | 
								self.reset_kbd_mouse_timeout_vars()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	def shutdown(self):
 | 
						def shutdown(self):
 | 
				
			||||||
 | 
							# PluginSystem: calling shutdown of super class (ChatControlBase) to let it remove
 | 
				
			||||||
 | 
							# it's GUI extension points
 | 
				
			||||||
 | 
							super(ChatControl, self).shutdown()
 | 
				
			||||||
 | 
							# PluginSystem: removing GUI extension points connected with ChatControl
 | 
				
			||||||
 | 
							# instance object
 | 
				
			||||||
 | 
							gajim.plugin_manager.remove_gui_extension_point('chat_control', self)
 | 
				
			||||||
 | 
							
 | 
				
			||||||
		# destroy banner tooltip - bug #pygtk for that!
 | 
							# destroy banner tooltip - bug #pygtk for that!
 | 
				
			||||||
		self.status_tooltip.destroy()
 | 
							self.status_tooltip.destroy()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1636,6 +1636,11 @@ class GroupchatControl(ChatControlBase):
 | 
				
			||||||
			status = self.subject)
 | 
								status = self.subject)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	def shutdown(self, status='offline'):
 | 
						def shutdown(self, status='offline'):
 | 
				
			||||||
 | 
							# PluginSystem: calling shutdown of super class (ChatControlBase) 
 | 
				
			||||||
 | 
							# to let it remove it's GUI extension points
 | 
				
			||||||
 | 
							super(GroupchatControl, self).shutdown()
 | 
				
			||||||
 | 
							
 | 
				
			||||||
 | 
							
 | 
				
			||||||
		# destroy banner tooltip - bug #pygtk for that!
 | 
							# destroy banner tooltip - bug #pygtk for that!
 | 
				
			||||||
		self.subject_tooltip.destroy()
 | 
							self.subject_tooltip.destroy()
 | 
				
			||||||
		gajim.connections[self.account].send_gc_status(self.nick, self.room_jid,
 | 
							gajim.connections[self.account].send_gc_status(self.nick, self.room_jid,
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -28,7 +28,7 @@ TYPE_PM = 'pm'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
####################
 | 
					####################
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class MessageControl:
 | 
					class MessageControl(object):
 | 
				
			||||||
	'''An abstract base widget that can embed in the gtk.Notebook of a MessageWindow'''
 | 
						'''An abstract base widget that can embed in the gtk.Notebook of a MessageWindow'''
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	def __init__(self, type_id, parent_win, widget_name, contact, account, resource = None):
 | 
						def __init__(self, type_id, parent_win, widget_name, contact, account, resource = None):
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -170,7 +170,7 @@ class PluginsWindow(object):
 | 
				
			||||||
	
 | 
						
 | 
				
			||||||
	@log_calls('PluginsWindow')
 | 
						@log_calls('PluginsWindow')
 | 
				
			||||||
	def on_configure_plugin_button_clicked(self, widget):
 | 
						def on_configure_plugin_button_clicked(self, widget):
 | 
				
			||||||
		log.debug('widget: %s'%(widget))
 | 
							#log.debug('widget: %s'%(widget))
 | 
				
			||||||
		selection = self.installed_plugins_treeview.get_selection()
 | 
							selection = self.installed_plugins_treeview.get_selection()
 | 
				
			||||||
		model, iter = selection.get_selected()
 | 
							model, iter = selection.get_selected()
 | 
				
			||||||
		if iter:
 | 
							if iter:
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -50,7 +50,8 @@ class log_calls(object):
 | 
				
			||||||
    Decorator class for functions to easily log when they are entered and left.
 | 
					    Decorator class for functions to easily log when they are entered and left.
 | 
				
			||||||
    '''
 | 
					    '''
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    filter_out_classes = ['PluginManager']
 | 
					    filter_out_classes = ['GajimPlugin', 'GajimPluginConfig',
 | 
				
			||||||
 | 
					                          'GajimPluginConfigDialog', 'PluginsWindow']
 | 
				
			||||||
    '''
 | 
					    '''
 | 
				
			||||||
    List of classes from which no logs should be emited when methods are called,
 | 
					    List of classes from which no logs should be emited when methods are called,
 | 
				
			||||||
    eventhough `log_calls` decorator is used.
 | 
					    eventhough `log_calls` decorator is used.
 | 
				
			||||||
| 
						 | 
					@ -129,10 +130,11 @@ class Singleton(type):
 | 
				
			||||||
    def __call__(cls,*args,**kw):
 | 
					    def __call__(cls,*args,**kw):
 | 
				
			||||||
        if cls.instance is None:
 | 
					        if cls.instance is None:
 | 
				
			||||||
            cls.instance=super(Singleton,cls).__call__(*args,**kw)
 | 
					            cls.instance=super(Singleton,cls).__call__(*args,**kw)
 | 
				
			||||||
            log.debug('%(classname)s - new instance created'%{
 | 
					            #log.debug('%(classname)s - new instance created'%{
 | 
				
			||||||
                'classname' : cls.__name__})
 | 
					                #'classname' : cls.__name__})
 | 
				
			||||||
        else:
 | 
					        else:
 | 
				
			||||||
            log.debug('%(classname)s - returning already existing instance'%{
 | 
					            pass
 | 
				
			||||||
                'classname' : cls.__name__})
 | 
					            #log.debug('%(classname)s - returning already existing instance'%{
 | 
				
			||||||
 | 
					                #'classname' : cls.__name__})
 | 
				
			||||||
            
 | 
					            
 | 
				
			||||||
        return cls.instance
 | 
					        return cls.instance
 | 
				
			||||||
| 
						 | 
					@ -134,6 +134,18 @@ class GajimPlugin(object):
 | 
				
			||||||
	def load_config(self):
 | 
						def load_config(self):
 | 
				
			||||||
		self.config.load()
 | 
							self.config.load()
 | 
				
			||||||
		
 | 
							
 | 
				
			||||||
 | 
						def __eq__(self, plugin):
 | 
				
			||||||
 | 
							if self.short_name == plugin.short_name:
 | 
				
			||||||
 | 
								return True
 | 
				
			||||||
 | 
							
 | 
				
			||||||
 | 
							return False
 | 
				
			||||||
 | 
						
 | 
				
			||||||
 | 
						def __ne__(self, plugin):
 | 
				
			||||||
 | 
							if self.short_name != plugin.short_name:
 | 
				
			||||||
 | 
								return True
 | 
				
			||||||
 | 
							
 | 
				
			||||||
 | 
							return False
 | 
				
			||||||
 | 
							
 | 
				
			||||||
	@log_calls('GajimPlugin')
 | 
						@log_calls('GajimPlugin')
 | 
				
			||||||
	def local_file_path(self, file_name):
 | 
						def local_file_path(self, file_name):
 | 
				
			||||||
		return os.path.join(self.__path__, file_name)
 | 
							return os.path.join(self.__path__, file_name)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -96,11 +96,11 @@ class PluginManager(object):
 | 
				
			||||||
		for path in gajim.PLUGINS_DIRS:
 | 
							for path in gajim.PLUGINS_DIRS:
 | 
				
			||||||
			self.add_plugins(PluginManager.scan_dir_for_plugins(path))
 | 
								self.add_plugins(PluginManager.scan_dir_for_plugins(path))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		log.debug('plugins: %s'%(self.plugins))
 | 
							#log.debug('plugins: %s'%(self.plugins))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		self._activate_all_plugins_from_global_config()
 | 
							self._activate_all_plugins_from_global_config()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		log.debug('active: %s'%(self.active_plugins))
 | 
							#log.debug('active: %s'%(self.active_plugins))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	@log_calls('PluginManager')
 | 
						@log_calls('PluginManager')
 | 
				
			||||||
	def _plugin_has_entry_in_global_config(self, plugin):
 | 
						def _plugin_has_entry_in_global_config(self, plugin):
 | 
				
			||||||
| 
						 | 
					@ -120,11 +120,16 @@ class PluginManager(object):
 | 
				
			||||||
		and adding class from reloaded module or ignoring adding plug-in?
 | 
							and adding class from reloaded module or ignoring adding plug-in?
 | 
				
			||||||
		'''
 | 
							'''
 | 
				
			||||||
		plugin = plugin_class()
 | 
							plugin = plugin_class()
 | 
				
			||||||
		if not self._plugin_has_entry_in_global_config(plugin):
 | 
					 | 
				
			||||||
			self._create_plugin_entry_in_global_config(plugin)
 | 
					 | 
				
			||||||
		
 | 
							
 | 
				
			||||||
		self.plugins.append(plugin)
 | 
							if plugin not in self.plugins:
 | 
				
			||||||
		plugin.active = False
 | 
								if not self._plugin_has_entry_in_global_config(plugin):
 | 
				
			||||||
 | 
									self._create_plugin_entry_in_global_config(plugin)
 | 
				
			||||||
 | 
									
 | 
				
			||||||
 | 
								self.plugins.append(plugin)
 | 
				
			||||||
 | 
								plugin.active = False
 | 
				
			||||||
 | 
							else:
 | 
				
			||||||
 | 
								log.info('Not loading plugin %s v%s from module %s (identified by short name: %s). Plugin already loaded.'%(
 | 
				
			||||||
 | 
									plugin.name, plugin.version, plugin.__module__, plugin.short_name))
 | 
				
			||||||
	
 | 
						
 | 
				
			||||||
	@log_calls('PluginManager')
 | 
						@log_calls('PluginManager')
 | 
				
			||||||
	def add_plugins(self, plugin_classes):
 | 
						def add_plugins(self, plugin_classes):
 | 
				
			||||||
| 
						 | 
					@ -134,7 +139,9 @@ class PluginManager(object):
 | 
				
			||||||
	@log_calls('PluginManager')
 | 
						@log_calls('PluginManager')
 | 
				
			||||||
	def gui_extension_point(self, gui_extpoint_name, *args):
 | 
						def gui_extension_point(self, gui_extpoint_name, *args):
 | 
				
			||||||
		'''
 | 
							'''
 | 
				
			||||||
		Invokes all handlers (from plugins) for particular GUI extension point.
 | 
							Invokes all handlers (from plugins) for particular GUI extension point
 | 
				
			||||||
 | 
							and adds it to collection for further processing (eg. by plugins not active
 | 
				
			||||||
 | 
							yet).
 | 
				
			||||||
		
 | 
							
 | 
				
			||||||
		:param gui_extpoint_name: name of GUI extension point.
 | 
							:param gui_extpoint_name: name of GUI extension point.
 | 
				
			||||||
		:type gui_extpoint_name: unicode
 | 
							:type gui_extpoint_name: unicode
 | 
				
			||||||
| 
						 | 
					@ -158,9 +165,68 @@ class PluginManager(object):
 | 
				
			||||||
		self._add_gui_extension_point_call_to_list(gui_extpoint_name, *args)
 | 
							self._add_gui_extension_point_call_to_list(gui_extpoint_name, *args)
 | 
				
			||||||
		self._execute_all_handlers_of_gui_extension_point(gui_extpoint_name, *args)
 | 
							self._execute_all_handlers_of_gui_extension_point(gui_extpoint_name, *args)
 | 
				
			||||||
	
 | 
						
 | 
				
			||||||
 | 
						@log_calls('PluginManager')
 | 
				
			||||||
 | 
						def remove_gui_extension_point(self, gui_extpoint_name, *args):
 | 
				
			||||||
 | 
							'''
 | 
				
			||||||
 | 
							Removes GUI extension point from collection held by `PluginManager`.
 | 
				
			||||||
 | 
							
 | 
				
			||||||
 | 
							From this point this particular extension point won't be visible
 | 
				
			||||||
 | 
							to plugins (eg. it won't invoke any handlers when plugin is activated).
 | 
				
			||||||
 | 
							
 | 
				
			||||||
 | 
							GUI extension point is removed completely (there is no way to recover it
 | 
				
			||||||
 | 
							from inside `PluginManager`).
 | 
				
			||||||
 | 
							
 | 
				
			||||||
 | 
							Removal is needed when instance object that given extension point was
 | 
				
			||||||
 | 
							connect with is destroyed (eg. ChatControl is closed or context menu
 | 
				
			||||||
 | 
							is hidden).
 | 
				
			||||||
 | 
							
 | 
				
			||||||
 | 
							Each `PluginManager.gui_extension_point` call should have a call of 
 | 
				
			||||||
 | 
							`PluginManager.remove_gui_extension_point` related to it.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							:note: in current implementation different arguments mean different
 | 
				
			||||||
 | 
								extension points. The same arguments and the same name mean
 | 
				
			||||||
 | 
								the same extension point.
 | 
				
			||||||
 | 
							:todo: instead of using argument to identify which extpoint should be
 | 
				
			||||||
 | 
								removed, maybe add additional 'id' argument - this would work similar
 | 
				
			||||||
 | 
								hash in Python objects. 'id' would be calculated based on arguments
 | 
				
			||||||
 | 
								passed or on anything else (even could be constant). This would give
 | 
				
			||||||
 | 
								core developers (that add new extpoints) more freedom, but is this 
 | 
				
			||||||
 | 
								necessary?
 | 
				
			||||||
 | 
							
 | 
				
			||||||
 | 
							:param gui_extpoint_name: name of GUI extension point.
 | 
				
			||||||
 | 
							:type gui_extpoint_name: unicode
 | 
				
			||||||
 | 
							:param args: arguments that `PluginManager.gui_extension_point` was
 | 
				
			||||||
 | 
								called with for this extension point. This is used (along with
 | 
				
			||||||
 | 
								extension point name) to identify element to be removed.
 | 
				
			||||||
 | 
							:type args: tuple
 | 
				
			||||||
 | 
							'''
 | 
				
			||||||
 | 
							log.debug('name: %s\n args: %s'%(gui_extpoint_name, args))
 | 
				
			||||||
 | 
							
 | 
				
			||||||
 | 
									
 | 
				
			||||||
	@log_calls('PluginManager')
 | 
						@log_calls('PluginManager')
 | 
				
			||||||
	def _add_gui_extension_point_call_to_list(self, gui_extpoint_name, *args):
 | 
						def _add_gui_extension_point_call_to_list(self, gui_extpoint_name, *args):
 | 
				
			||||||
		self.gui_extension_points.setdefault(gui_extpoint_name, []).append(args)
 | 
							'''
 | 
				
			||||||
 | 
							Adds GUI extension point call to list of calls.
 | 
				
			||||||
 | 
							
 | 
				
			||||||
 | 
							This is done only if such call hasn't been added already
 | 
				
			||||||
 | 
							(same extension point name and same arguments).
 | 
				
			||||||
 | 
							
 | 
				
			||||||
 | 
							:note: This is assumption that GUI extension points are different only
 | 
				
			||||||
 | 
							if they have different name or different arguments. 
 | 
				
			||||||
 | 
							
 | 
				
			||||||
 | 
							:param gui_extpoint_name: GUI extension point name used to identify it
 | 
				
			||||||
 | 
								by plugins.
 | 
				
			||||||
 | 
							:type gui_extpoint_name: str
 | 
				
			||||||
 | 
							
 | 
				
			||||||
 | 
							:param args: parameters to be passed to extension point handlers 
 | 
				
			||||||
 | 
								(typically and object that invokes `gui_extension_point`; however, 
 | 
				
			||||||
 | 
								this can be practically anything)
 | 
				
			||||||
 | 
							:type args: tuple
 | 
				
			||||||
 | 
							
 | 
				
			||||||
 | 
							'''
 | 
				
			||||||
 | 
							if ((gui_extpoint_name not in self.gui_extension_points)
 | 
				
			||||||
 | 
								or (args not in self.gui_extension_points[gui_extpoint_name])):
 | 
				
			||||||
 | 
								self.gui_extension_points.setdefault(gui_extpoint_name, []).append(args)
 | 
				
			||||||
	
 | 
						
 | 
				
			||||||
	@log_calls('PluginManager')
 | 
						@log_calls('PluginManager')
 | 
				
			||||||
	def _execute_all_handlers_of_gui_extension_point(self, gui_extpoint_name, *args):
 | 
						def _execute_all_handlers_of_gui_extension_point(self, gui_extpoint_name, *args):
 | 
				
			||||||
| 
						 | 
					@ -287,57 +353,62 @@ class PluginManager(object):
 | 
				
			||||||
			#log.debug(sys.path)
 | 
								#log.debug(sys.path)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			for elem_name in dir_list:
 | 
								for elem_name in dir_list:
 | 
				
			||||||
				log.debug('- "%s"'%(elem_name))
 | 
									#log.debug('- "%s"'%(elem_name))
 | 
				
			||||||
				file_path = os.path.join(path, elem_name)
 | 
									file_path = os.path.join(path, elem_name)
 | 
				
			||||||
				log.debug('  "%s"'%(file_path))
 | 
									#log.debug('  "%s"'%(file_path))
 | 
				
			||||||
				
 | 
									
 | 
				
			||||||
				module = None
 | 
									module = None
 | 
				
			||||||
				
 | 
									
 | 
				
			||||||
				if os.path.isfile(file_path) and fnmatch.fnmatch(file_path,'*.py'):
 | 
									if os.path.isfile(file_path) and fnmatch.fnmatch(file_path,'*.py'):
 | 
				
			||||||
					module_name = os.path.splitext(elem_name)[0]
 | 
										module_name = os.path.splitext(elem_name)[0]
 | 
				
			||||||
					log.debug('Possible module detected.')
 | 
										#log.debug('Possible module detected.')
 | 
				
			||||||
					try:
 | 
										try:
 | 
				
			||||||
						module = __import__(module_name)
 | 
											module = __import__(module_name)
 | 
				
			||||||
						log.debug('Module imported.')
 | 
											#log.debug('Module imported.')
 | 
				
			||||||
					except ValueError, value_error:
 | 
										except ValueError, value_error:
 | 
				
			||||||
						log.debug('Module not imported successfully. ValueError: %s'%(value_error))
 | 
											pass
 | 
				
			||||||
 | 
											#log.debug('Module not imported successfully. ValueError: %s'%(value_error))
 | 
				
			||||||
					except ImportError, import_error:
 | 
										except ImportError, import_error:
 | 
				
			||||||
						log.debug('Module not imported successfully. ImportError: %s'%(import_error))
 | 
											pass
 | 
				
			||||||
 | 
											#log.debug('Module not imported successfully. ImportError: %s'%(import_error))
 | 
				
			||||||
					
 | 
										
 | 
				
			||||||
				elif os.path.isdir(file_path):
 | 
									elif os.path.isdir(file_path):
 | 
				
			||||||
					module_name = elem_name
 | 
										module_name = elem_name
 | 
				
			||||||
					file_path += os.path.sep
 | 
										file_path += os.path.sep
 | 
				
			||||||
					log.debug('Possible package detected.')
 | 
										#log.debug('Possible package detected.')
 | 
				
			||||||
					try:
 | 
										try:
 | 
				
			||||||
						module = __import__(module_name)
 | 
											module = __import__(module_name)
 | 
				
			||||||
						log.debug('Package imported.')
 | 
											#log.debug('Package imported.')
 | 
				
			||||||
					except ValueError, value_error:
 | 
										except ValueError, value_error:
 | 
				
			||||||
						log.debug('Package not imported successfully. ValueError: %s'%(value_error))
 | 
											pass
 | 
				
			||||||
 | 
											#log.debug('Package not imported successfully. ValueError: %s'%(value_error))
 | 
				
			||||||
					except ImportError, import_error:
 | 
										except ImportError, import_error:
 | 
				
			||||||
						log.debug('Package not imported successfully. ImportError: %s'%(import_error))
 | 
											pass
 | 
				
			||||||
 | 
											#log.debug('Package not imported successfully. ImportError: %s'%(import_error))
 | 
				
			||||||
					
 | 
										
 | 
				
			||||||
					
 | 
										
 | 
				
			||||||
				if module:
 | 
									if module:
 | 
				
			||||||
					log.debug('Attributes processing started')
 | 
										#log.debug('Attributes processing started')
 | 
				
			||||||
					for module_attr_name in [attr_name for attr_name in dir(module) 
 | 
										for module_attr_name in [attr_name for attr_name in dir(module) 
 | 
				
			||||||
											 if not (attr_name.startswith('__') or 
 | 
																 if not (attr_name.startswith('__') or 
 | 
				
			||||||
													 attr_name.endswith('__'))]:
 | 
																		 attr_name.endswith('__'))]:
 | 
				
			||||||
						module_attr = getattr(module, module_attr_name)
 | 
											module_attr = getattr(module, module_attr_name)
 | 
				
			||||||
						log.debug('%s : %s'%(module_attr_name, module_attr))
 | 
											#log.debug('%s : %s'%(module_attr_name, module_attr))
 | 
				
			||||||
						
 | 
											
 | 
				
			||||||
						try:
 | 
											try:
 | 
				
			||||||
							if issubclass(module_attr, GajimPlugin) and \
 | 
												if issubclass(module_attr, GajimPlugin) and \
 | 
				
			||||||
							   not module_attr is GajimPlugin:
 | 
												   not module_attr is GajimPlugin:
 | 
				
			||||||
								log.debug('is subclass of GajimPlugin')
 | 
													#log.debug('is subclass of GajimPlugin')
 | 
				
			||||||
								#log.debug('file_path: %s\nabspath: %s\ndirname: %s'%(file_path, os.path.abspath(file_path), os.path.dirname(os.path.abspath(file_path))))
 | 
													#log.debug('file_path: %s\nabspath: %s\ndirname: %s'%(file_path, os.path.abspath(file_path), os.path.dirname(os.path.abspath(file_path))))
 | 
				
			||||||
								#log.debug('file_path: %s\ndirname: %s\nabspath: %s'%(file_path, os.path.dirname(file_path), os.path.abspath(os.path.dirname(file_path))))
 | 
													#log.debug('file_path: %s\ndirname: %s\nabspath: %s'%(file_path, os.path.dirname(file_path), os.path.abspath(os.path.dirname(file_path))))
 | 
				
			||||||
								module_attr.__path__ = os.path.abspath(os.path.dirname(file_path))
 | 
													module_attr.__path__ = os.path.abspath(os.path.dirname(file_path))
 | 
				
			||||||
								plugins_found.append(module_attr)
 | 
													plugins_found.append(module_attr)
 | 
				
			||||||
						except TypeError, type_error:
 | 
											except TypeError, type_error:
 | 
				
			||||||
							log.debug('module_attr: %s, error : %s'%(
 | 
												pass
 | 
				
			||||||
								module_name+'.'+module_attr_name,
 | 
												#log.debug('module_attr: %s, error : %s'%(
 | 
				
			||||||
								type_error))
 | 
													#module_name+'.'+module_attr_name,
 | 
				
			||||||
 | 
													#type_error))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
					log.debug(module)
 | 
										#log.debug(module)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		return plugins_found
 | 
							return plugins_found
 | 
				
			||||||
		Loading…
	
	Add table
		
		Reference in a new issue