Merge branch 'xmlconsole' into 'master'
Redesign XML Console See merge request !115
This commit is contained in:
		
						commit
						174e88024d
					
				
					 3 changed files with 313 additions and 134 deletions
				
			
		|  | @ -29,3 +29,14 @@ popover#EmoticonPopover flowboxchild { padding-top: 5px; padding-bottom: 5px; } | |||
| #ServerInfoGrid > list > row { padding: 10px 20px 10px 10px; } | ||||
| #ServerInfoGrid > list > label { padding:10px; color: @insensitive_fg_color; font-weight: bold; } | ||||
| #ServerInfoGrid > list > row.activatable:active { box-shadow: none; } | ||||
| 
 | ||||
| /* Generic Options Dialog */ | ||||
| #OptionsDialog list > row { border-bottom: 1px solid; border-color: @theme_unfocused_bg_color; } | ||||
| #OptionsDialog list > row:last-child { border-bottom: 0px} | ||||
| #OptionsDialog list > row { padding: 10px; } | ||||
| #OptionsDialog list > row.activatable:active { box-shadow: none; } | ||||
| 
 | ||||
| /* Generic Popover Menu with Buttons */ | ||||
| .PopoverButtonListbox { margin-top: 10px; margin-bottom: 10px; } | ||||
| .PopoverButtonListbox > row { padding: 10px 20px 10px 20px; } | ||||
| .PopoverButtonListbox row.activatable:active { box-shadow: none; background-color: @theme_selected_bg_color } | ||||
|  |  | |||
|  | @ -175,7 +175,7 @@ class AppActions(): | |||
|     def on_xml_console(self, action, param): | ||||
|         account = param.get_string() | ||||
|         if 'xml_console' in gajim.interface.instances[account]: | ||||
|             gajim.interface.instances[account]['xml_console'].window.present() | ||||
|             gajim.interface.instances[account]['xml_console'].present() | ||||
|         else: | ||||
|             gajim.interface.instances[account]['xml_console'] = \ | ||||
|                 dialogs.XMLConsoleWindow(account) | ||||
|  |  | |||
							
								
								
									
										434
									
								
								gajim/dialogs.py
									
										
									
									
									
								
							
							
						
						
									
										434
									
								
								gajim/dialogs.py
									
										
									
									
									
								
							|  | @ -3347,139 +3347,256 @@ class SingleMessageWindow: | |||
|             self.save_pos() | ||||
|             self.window.destroy() | ||||
| 
 | ||||
| class XMLConsoleWindow: | ||||
| 
 | ||||
| class XMLConsoleWindow(Gtk.Window): | ||||
|     def __init__(self, account): | ||||
|         Gtk.Window.__init__(self) | ||||
|         self.account = account | ||||
|         self.set_default_size(600, 600) | ||||
|         self.connect("destroy", self.on_destroy) | ||||
| 
 | ||||
|         self.xml = gtkgui_helpers.get_gtk_builder('xml_console_window.ui') | ||||
|         self.window = self.xml.get_object('xml_console_window') | ||||
|         self.input_textview = self.xml.get_object('input_textview') | ||||
|         self.stanzas_log_textview = self.xml.get_object('stanzas_log_textview') | ||||
|         self.input_tv_buffer = self.input_textview.get_buffer() | ||||
|         self.parent = self.stanzas_log_textview.get_parent() | ||||
|         buffer_ = self.stanzas_log_textview.get_buffer() | ||||
|         headerbar = Gtk.HeaderBar() | ||||
|         headerbar.set_title(_('XML Console')) | ||||
|         headerbar.set_show_close_button(True) | ||||
|         self.set_titlebar(headerbar) | ||||
| 
 | ||||
|         self.tagIn = buffer_.create_tag('incoming') | ||||
|         color = gajim.config.get('inmsgcolor') | ||||
|         self.tagIn.set_property('foreground', color) | ||||
|         self.tagInPresence = buffer_.create_tag('incoming_presence') | ||||
|         self.tagInPresence.set_property('foreground', color) | ||||
|         self.tagInMessage = buffer_.create_tag('incoming_message') | ||||
|         self.tagInMessage.set_property('foreground', color) | ||||
|         self.tagInIq = buffer_.create_tag('incoming_iq') | ||||
|         self.tagInIq.set_property('foreground', color) | ||||
|         switch = Gtk.Switch() | ||||
|         switch.set_active(True) | ||||
|         switch.connect("notify::active", self.on_enable) | ||||
|         headerbar.pack_start(switch) | ||||
| 
 | ||||
|         self.tagOut = buffer_.create_tag('outgoing') | ||||
|         color = gajim.config.get('outmsgcolor') | ||||
|         self.tagOut.set_property('foreground', color) | ||||
|         self.tagOutPresence = buffer_.create_tag('outgoing_presence') | ||||
|         self.tagOutPresence.set_property('foreground', color) | ||||
|         self.tagOutMessage = buffer_.create_tag('outgoing_message') | ||||
|         self.tagOutMessage.set_property('foreground', color) | ||||
|         self.tagOutIq = buffer_.create_tag('outgoing_iq') | ||||
|         self.tagOutIq.set_property('foreground', color) | ||||
|         buffer_.create_tag('') # Default tag | ||||
|         headerbar.set_decoration_layout(':minimize,close') | ||||
| 
 | ||||
|         self.enabled = True | ||||
|         self.xml.get_object('enable_checkbutton').set_active(True) | ||||
|         self.presence = True | ||||
|         self.message = True | ||||
|         self.iq = True | ||||
|         self.stream = True | ||||
|         self.incoming = True | ||||
|         self.outgoing = True | ||||
| 
 | ||||
|         if len(gajim.connections) > 1: | ||||
|             title = _('XML Console for %s') % self.account | ||||
|         else: | ||||
|             title = _('XML Console') | ||||
|         self.textview = Gtk.TextView() | ||||
|         self.textview.set_size_request(-1, 400) | ||||
|         self.textview.set_editable(False) | ||||
|         self.textview.set_cursor_visible(False) | ||||
|         self.textview.set_hexpand(True) | ||||
| 
 | ||||
|         self.scrolled = Gtk.ScrolledWindow() | ||||
|         self.scrolled.add(self.textview) | ||||
| 
 | ||||
|         self.input = Gtk.TextView() | ||||
|         self.input.show() | ||||
|         self.input.set_vexpand(True) | ||||
| 
 | ||||
|         self.scrolled_input = Gtk.ScrolledWindow() | ||||
|         self.scrolled_input.set_size_request(-1, 150) | ||||
|         self.scrolled_input.add(self.input) | ||||
|         self.scrolled_input.set_no_show_all(True) | ||||
| 
 | ||||
|         self.paned = Gtk.VPaned() | ||||
|         self.paned.set_vexpand(True) | ||||
|         self.paned.pack1(self.scrolled, True, False) | ||||
|         self.paned.pack2(self.scrolled_input, False, False) | ||||
|         self.paned.set_position(self.paned.get_property('max-position')) | ||||
| 
 | ||||
|         self.actionbar = Gtk.ActionBar() | ||||
| 
 | ||||
|         icon = gtkgui_helpers.get_icon_pixmap('edit-clear-all-symbolic') | ||||
|         image = Gtk.Image() | ||||
|         image.set_from_pixbuf(icon) | ||||
|         button = Gtk.Button() | ||||
|         button.set_tooltip_text(_('Clear')) | ||||
|         button.connect('clicked', self.on_clear) | ||||
|         button.set_image(image) | ||||
|         self.actionbar.pack_start(button) | ||||
| 
 | ||||
|         icon = gtkgui_helpers.get_icon_pixmap('applications-system-symbolic') | ||||
|         image = Gtk.Image() | ||||
|         image.set_from_pixbuf(icon) | ||||
|         button = Gtk.Button() | ||||
|         button.set_tooltip_text(_('Filter')) | ||||
|         button.connect('clicked', self.on_filter_options) | ||||
|         button.set_image(image) | ||||
|         self.actionbar.pack_start(button) | ||||
| 
 | ||||
|         icon = gtkgui_helpers.get_icon_pixmap('document-edit-symbolic') | ||||
|         image = Gtk.Image() | ||||
|         image.set_from_pixbuf(icon) | ||||
|         button = Gtk.ToggleButton() | ||||
|         button.set_tooltip_text(_('XML Input')) | ||||
|         button.set_active(False) | ||||
|         button.connect('toggled', self.on_input) | ||||
|         button.set_image(image) | ||||
|         self.actionbar.pack_start(button) | ||||
| 
 | ||||
|         icon = gtkgui_helpers.get_icon_pixmap('emblem-ok-symbolic') | ||||
|         image = Gtk.Image() | ||||
|         image.set_from_pixbuf(icon) | ||||
|         button = Gtk.Button() | ||||
|         button.set_tooltip_text(_('Send')) | ||||
|         button.connect('clicked', self.on_send) | ||||
|         button.set_image(image) | ||||
|         self.actionbar.pack_end(button) | ||||
| 
 | ||||
|         listbox = Gtk.ListBox() | ||||
|         context = listbox.get_style_context() | ||||
|         context.add_class('PopoverButtonListbox') | ||||
| 
 | ||||
|         label = Gtk.Label(label='Message') | ||||
|         listbox.add(label) | ||||
| 
 | ||||
|         label = Gtk.Label(label='Presence') | ||||
|         listbox.add(label) | ||||
| 
 | ||||
|         label = Gtk.Label(label='Iq') | ||||
|         listbox.add(label) | ||||
|         listbox.show_all() | ||||
|         listbox.set_selection_mode(Gtk.SelectionMode.NONE) | ||||
|         listbox.connect('row-activated', self.on_row_activated) | ||||
| 
 | ||||
|         popover = Gtk.Popover() | ||||
|         popover.add(listbox) | ||||
| 
 | ||||
|         self.menubutton = Gtk.MenuButton() | ||||
|         self.menubutton.set_direction(Gtk.ArrowType.UP) | ||||
|         self.menubutton.set_popover(popover) | ||||
|         self.menubutton.set_tooltip_text(_('Presets')) | ||||
|         self.menubutton.set_no_show_all(True) | ||||
| 
 | ||||
|         self.actionbar.pack_start(self.menubutton) | ||||
| 
 | ||||
|         box = Gtk.Box.new(Gtk.Orientation.VERTICAL, 0) | ||||
|         box.add(self.paned) | ||||
|         box.add(self.actionbar) | ||||
| 
 | ||||
|         self.add(box) | ||||
| 
 | ||||
|         self.connect('key_press_event', self.on_key_press_event) | ||||
| 
 | ||||
|         self.create_tags() | ||||
|         self.show_all() | ||||
| 
 | ||||
|         self.window.set_title(title) | ||||
|         self.window.show_all() | ||||
|         gajim.ged.register_event_handler('stanza-received', ged.GUI1, | ||||
|             self._nec_stanza_received) | ||||
|         gajim.ged.register_event_handler('stanza-sent', ged.GUI1, | ||||
|             self._nec_stanza_sent) | ||||
| 
 | ||||
|         self.xml.connect_signals(self) | ||||
|     def create_tags(self): | ||||
|         buffer_ = self.textview.get_buffer() | ||||
|         in_color = gajim.config.get('inmsgcolor') | ||||
|         out_color = gajim.config.get('outmsgcolor') | ||||
| 
 | ||||
|         tags = ['presence', 'message', 'stream', 'iq'] | ||||
| 
 | ||||
|         tag = buffer_.create_tag('incoming') | ||||
|         tag.set_property('foreground', in_color) | ||||
|         tag = buffer_.create_tag('outgoing') | ||||
|         tag.set_property('foreground', out_color) | ||||
| 
 | ||||
|         for tag_name in tags: | ||||
|             buffer_.create_tag(tag_name) | ||||
| 
 | ||||
|     def on_key_press_event(self, widget, event): | ||||
|         if event.keyval == Gdk.KEY_Escape: | ||||
|             self.window.destroy() | ||||
|             self.destroy() | ||||
| 
 | ||||
|     def on_xml_console_window_destroy(self, widget): | ||||
|     def on_row_activated(self, listbox, row): | ||||
|         text = row.get_child().get_text() | ||||
|         input_text = None | ||||
|         if text == 'Presence': | ||||
|             input_text = ( | ||||
|                 '<presence>\n' | ||||
|                 '<show></show>\n' | ||||
|                 '<status></status>\n' | ||||
|                 '<priority></priority>\n' | ||||
|                 '</presence>') | ||||
|         elif text == 'Message': | ||||
|             input_text = ( | ||||
|                 '<message to="" type="">\n' | ||||
|                 '<body></body>\n' | ||||
|                 '</message>') | ||||
|         elif text == 'Iq': | ||||
|             input_text = ( | ||||
|                 '<iq to="" type="">\n' | ||||
|                 '<query xmlns=""></query>\n' | ||||
|                 '</iq>') | ||||
| 
 | ||||
|         if input_text is not None: | ||||
|             buffer_ = self.input.get_buffer() | ||||
|             buffer_.set_text(input_text) | ||||
|             self.input.grab_focus() | ||||
| 
 | ||||
|     def on_send(self, *args): | ||||
|         if gajim.connections[self.account].connected <= 1: | ||||
|             # if offline or connecting | ||||
|             ErrorDialog(_('Connection not available'), | ||||
|                 _('Please make sure you are connected with "%s".') % \ | ||||
|                 self.account) | ||||
|             return | ||||
|         buffer_ = self.input.get_buffer() | ||||
|         begin_iter, end_iter = buffer_.get_bounds() | ||||
|         stanza = buffer_.get_text(begin_iter, end_iter, True) | ||||
|         if stanza: | ||||
|             gajim.connections[self.account].send_stanza(stanza) | ||||
|             buffer_.set_text('') | ||||
| 
 | ||||
|     def on_input(self, button, *args): | ||||
|         if button.get_active(): | ||||
|             self.paned.get_child2().show() | ||||
|             self.menubutton.show() | ||||
|             self.input.grab_focus() | ||||
|         else: | ||||
|             self.paned.get_child2().hide() | ||||
|             self.menubutton.hide() | ||||
| 
 | ||||
|     def on_filter_options(self, *args): | ||||
|         options = [ | ||||
|             SwitchOption('Presence', self.presence, | ||||
|                          self.on_option, | ||||
|                          'presence'), | ||||
|             SwitchOption('Message', self.message, | ||||
|                          self.on_option, | ||||
|                          'message'), | ||||
|             SwitchOption('Iq', self.iq, | ||||
|                          self.on_option, | ||||
|                          'iq'), | ||||
|             SwitchOption('Stream\nManagement', self.stream, | ||||
|                          self.on_option, | ||||
|                          'stream'), | ||||
|             SwitchOption('In', self.incoming, | ||||
|                          self.on_option, | ||||
|                          'incoming'), | ||||
|             SwitchOption('Out', self.outgoing, | ||||
|                          self.on_option, | ||||
|                          'outgoing')] | ||||
| 
 | ||||
|         OptionsDialog(self, 'Filter', options) | ||||
| 
 | ||||
|     def on_clear(self, *args): | ||||
|         buffer_ = self.textview.get_buffer().set_text('') | ||||
| 
 | ||||
|     def on_destroy(self, *args): | ||||
|         del gajim.interface.instances[self.account]['xml_console'] | ||||
|         gajim.ged.remove_event_handler('stanza-received', ged.GUI1, | ||||
|             self._nec_stanza_received) | ||||
|         gajim.ged.remove_event_handler('stanza-sent', ged.GUI1, | ||||
|             self._nec_stanza_sent) | ||||
| 
 | ||||
|     def on_clear_button_clicked(self, widget): | ||||
|         buffer_ = self.stanzas_log_textview.get_buffer() | ||||
|         buffer_.set_text('') | ||||
|     def on_enable(self, switch, param): | ||||
|         self.enabled = switch.get_active() | ||||
| 
 | ||||
|     def on_enable_checkbutton_toggled(self, widget): | ||||
|         self.enabled = widget.get_active() | ||||
| 
 | ||||
|     def on_in_stanza_checkbutton_toggled(self, widget): | ||||
|         active = widget.get_active() | ||||
|         self.tagIn.set_property('invisible', active) | ||||
|         self.tagInPresence.set_property('invisible', active) | ||||
|         self.tagInMessage.set_property('invisible', active) | ||||
|         self.tagInIq.set_property('invisible', active) | ||||
| 
 | ||||
|     def on_presence_stanza_checkbutton_toggled(self, widget): | ||||
|         active = widget.get_active() | ||||
|         self.tagInPresence.set_property('invisible', active) | ||||
|         self.tagOutPresence.set_property('invisible', active) | ||||
| 
 | ||||
|     def on_out_stanza_checkbutton_toggled(self, widget): | ||||
|         active = widget.get_active() | ||||
|         self.tagOut.set_property('invisible', active) | ||||
|         self.tagOutPresence.set_property('invisible', active) | ||||
|         self.tagOutMessage.set_property('invisible', active) | ||||
|         self.tagOutIq.set_property('invisible', active) | ||||
| 
 | ||||
|     def on_message_stanza_checkbutton_toggled(self, widget): | ||||
|         active = widget.get_active() | ||||
|         self.tagInMessage.set_property('invisible', active) | ||||
|         self.tagOutMessage.set_property('invisible', active) | ||||
| 
 | ||||
|     def on_iq_stanza_checkbutton_toggled(self, widget): | ||||
|         active = widget.get_active() | ||||
|         self.tagInIq.set_property('invisible', active) | ||||
|         self.tagOutIq.set_property('invisible', active) | ||||
| 
 | ||||
|     def print_stanza(self, stanza, kind): | ||||
|         # kind must be 'incoming' or 'outgoing' | ||||
|         if not self.enabled: | ||||
|             return | ||||
|         if not stanza: | ||||
|             return | ||||
| 
 | ||||
|         at_the_end = gtkgui_helpers.at_the_end(self.parent) | ||||
| 
 | ||||
|         buffer = self.stanzas_log_textview.get_buffer() | ||||
|         end_iter = buffer.get_end_iter() | ||||
| 
 | ||||
|         type_ = '' | ||||
|         if stanza[1:9] == 'presence': | ||||
|             type_ = 'presence' | ||||
|         elif stanza[1:8] == 'message': | ||||
|             type_ = 'message' | ||||
|         elif stanza[1:3] == 'iq': | ||||
|             type_ = 'iq' | ||||
| 
 | ||||
|         if type_: | ||||
|             type_ = kind + '_' + type_ | ||||
|         else: | ||||
|             type_ = kind # 'incoming' or 'outgoing' | ||||
| 
 | ||||
|         if kind == 'incoming': | ||||
|             buffer.insert_with_tags_by_name(end_iter, '<!-- In %s -->\n' % \ | ||||
|                 time.strftime('%c'), type_) | ||||
|         elif kind == 'outgoing': | ||||
|             buffer.insert_with_tags_by_name(end_iter, '<!-- Out %s -->\n' % \ | ||||
|                 time.strftime('%c'), type_) | ||||
|         end_iter = buffer.get_end_iter() | ||||
|         buffer.insert_with_tags_by_name(end_iter, stanza.replace('><', '>\n<') \ | ||||
|             + '\n\n', type_) | ||||
|         if at_the_end: | ||||
|             GLib.idle_add(gtkgui_helpers.scroll_to_end, self.parent) | ||||
|     def on_option(self, switch, param, *user_data): | ||||
|         kind = user_data[0] | ||||
|         setattr(self, kind, switch.get_active()) | ||||
|         value = not switch.get_active() | ||||
|         table = self.textview.get_buffer().get_tag_table() | ||||
|         tag = table.lookup(kind) | ||||
|         if kind in ('incoming', 'outgoing'): | ||||
|             if value: | ||||
|                 tag.set_priority(table.get_size() - 1) | ||||
|             else: | ||||
|                 tag.set_priority(0) | ||||
|         tag.set_property('invisible', value) | ||||
| 
 | ||||
|     def _nec_stanza_received(self, obj): | ||||
|         if obj.conn.name != self.account: | ||||
|  | @ -3491,36 +3608,87 @@ class XMLConsoleWindow: | |||
|             return | ||||
|         self.print_stanza(obj.stanza_str, 'outgoing') | ||||
| 
 | ||||
|     def on_send_button_clicked(self, widget): | ||||
|         if gajim.connections[self.account].connected <= 1: | ||||
|             # if offline or connecting | ||||
|             ErrorDialog(_('Connection not available'), | ||||
|                 _('Please make sure you are connected with "%s".') % \ | ||||
|                 self.account) | ||||
|     def print_stanza(self, stanza, kind): | ||||
|         # kind must be 'incoming' or 'outgoing' | ||||
|         if not self.enabled: | ||||
|             return | ||||
|         if not stanza: | ||||
|             return | ||||
|         begin_iter, end_iter = self.input_tv_buffer.get_bounds() | ||||
|         stanza = self.input_tv_buffer.get_text(begin_iter, end_iter, True) | ||||
|         if stanza: | ||||
|             gajim.connections[self.account].send_stanza(stanza) | ||||
|             self.input_tv_buffer.set_text('') # we sent ok, clear the textview | ||||
| 
 | ||||
|     def on_presence_button_clicked(self, widget): | ||||
|         self.input_tv_buffer.set_text( | ||||
|             '<presence><show></show><status></status><priority></priority>' | ||||
|             '</presence>') | ||||
|         at_the_end = gtkgui_helpers.at_the_end(self.scrolled) | ||||
| 
 | ||||
|     def on_iq_button_clicked(self, widget): | ||||
|         self.input_tv_buffer.set_text( | ||||
|             '<iq to="" type=""><query xmlns=""></query></iq>') | ||||
|         buffer_ = self.textview.get_buffer() | ||||
|         end_iter = buffer_.get_end_iter() | ||||
| 
 | ||||
|     def on_message_button_clicked(self, widget): | ||||
|         self.input_tv_buffer.set_text( | ||||
|             '<message to="" type=""><body></body></message>') | ||||
|         type_ = kind | ||||
|         if stanza.startswith('<presence'): | ||||
|             type_ = 'presence' | ||||
|         elif stanza.startswith('<message'): | ||||
|             type_ = 'message' | ||||
|         elif stanza.startswith('<iq'): | ||||
|             type_ = 'iq' | ||||
|         elif stanza.startswith('<r') or stanza.startswith('<a'): | ||||
|             type_ = 'stream' | ||||
| 
 | ||||
|     def on_expander_activate(self, widget): | ||||
|         if not widget.get_expanded(): # it's the opposite! | ||||
|             # it's expanded!! | ||||
|             self.input_textview.grab_focus() | ||||
|         stanza = '<!-- {kind} {time} -->\n{stanza}\n\n'.format( | ||||
|             kind=kind.capitalize(), | ||||
|             time=time.strftime('%c'), | ||||
|             stanza=stanza.replace('><', '>\n<')) | ||||
|         buffer_.insert_with_tags_by_name(end_iter, stanza, type_, kind) | ||||
| 
 | ||||
|         if at_the_end: | ||||
|             GLib.idle_add(gtkgui_helpers.scroll_to_end, self.scrolled) | ||||
| 
 | ||||
| 
 | ||||
| class OptionsDialog(Gtk.Dialog): | ||||
|     def __init__(self, parent, title, options): | ||||
|         Gtk.Dialog.__init__(self, title, parent, | ||||
|                             Gtk.DialogFlags.DESTROY_WITH_PARENT) | ||||
|         self.set_name('OptionsDialog') | ||||
|         self.set_resizable(False) | ||||
|         self.set_default_size(250, -1) | ||||
| 
 | ||||
|         self.remove(self.get_content_area()) | ||||
| 
 | ||||
|         listbox = Gtk.ListBox() | ||||
|         listbox.set_hexpand(True) | ||||
|         listbox.set_selection_mode(Gtk.SelectionMode.NONE) | ||||
| 
 | ||||
|         for option in options: | ||||
|             listbox.add(option) | ||||
| 
 | ||||
|         self.add(listbox) | ||||
| 
 | ||||
|         self.show_all() | ||||
|         listbox.connect('row-activated', self.on_row_activated) | ||||
| 
 | ||||
|     def on_row_activated(self, listbox, row): | ||||
|         row.get_child().set_switch_state() | ||||
| 
 | ||||
| 
 | ||||
| class SwitchOption(Gtk.Grid): | ||||
|     def __init__(self, label, state, callback, *user_data): | ||||
|         Gtk.Grid.__init__(self) | ||||
|         self.set_column_spacing(6) | ||||
| 
 | ||||
|         label = Gtk.Label(label=label) | ||||
|         label.set_hexpand(True) | ||||
|         label.set_halign(Gtk.Align.START) | ||||
| 
 | ||||
|         self.switch = Gtk.Switch() | ||||
|         self.switch.set_active(state) | ||||
|         self.switch.connect("notify::active", callback, *user_data) | ||||
|         self.switch.set_hexpand(True) | ||||
|         self.switch.set_halign(Gtk.Align.END) | ||||
| 
 | ||||
|         self.add(label) | ||||
|         self.add(self.switch) | ||||
|         self.show_all() | ||||
| 
 | ||||
|     def set_switch_state(self): | ||||
|         state = self.switch.get_active() | ||||
|         self.switch.set_active(not state) | ||||
|        | ||||
| 
 | ||||
| #Action that can be done with an incoming list of contacts | ||||
| TRANSLATED_ACTION = {'add': _('add'), 'modify': _('modify'), | ||||
|  |  | |||
		Loading…
	
	Add table
		
		Reference in a new issue