示例#1
0
    def _on_filter_options(self, *args):
        if self.filter_dialog:
            self.filter_dialog.present()
            return
        options = [
            Setting(SettingKind.SWITCH, 'Presence',
                    SettingType.VALUE, self.presence,
                    callback=self._on_option, data='presence'),

            Setting(SettingKind.SWITCH, 'Message',
                    SettingType.VALUE, self.message,
                    callback=self._on_option, data='message'),

            Setting(SettingKind.SWITCH, 'IQ', SettingType.VALUE, self.iq,
                    callback=self._on_option, data='iq'),

            Setting(SettingKind.SWITCH, 'Stream Management',
                    SettingType.VALUE, self.stream,
                    callback=self._on_option, data='stream'),

            Setting(SettingKind.SWITCH, 'In', SettingType.VALUE, self.incoming,
                    callback=self._on_option, data='incoming'),

            Setting(SettingKind.SWITCH, 'Out', SettingType.VALUE, self.outgoing,
                    callback=self._on_option, data='outgoing'),
        ]

        self.filter_dialog = SettingsDialog(self, 'Filter',
                                            Gtk.DialogFlags.DESTROY_WITH_PARENT,
                                            options, self.account)
        self.filter_dialog.connect('destroy', self._on_filter_destroyed)
示例#2
0
    def __init__(self, account, parent):

        settings = [
            Setting(SettingKind.ENTRY,
                    _('Password'),
                    SettingType.ACCOUNT_CONFIG,
                    'password',
                    name='password',
                    enabledif=('savepass', True)),
            Setting(SettingKind.SWITCH,
                    _('Save Password'),
                    SettingType.ACCOUNT_CONFIG,
                    'savepass',
                    name='savepass'),
            Setting(SettingKind.CHANGEPASSWORD,
                    _('Change Password'),
                    SettingType.DIALOG,
                    callback=self.on_password_change,
                    props={'dialog': None}),
        ]

        SettingsDialog.__init__(self, parent, _('Login Settings'),
                                Gtk.DialogFlags.MODAL, settings, account)

        self.connect('destroy', self.on_destroy)
示例#3
0
    def _on_filter_options(self, *args):
        if self.filter_dialog:
            self.filter_dialog.present()
            return

        combo_accounts = self._get_accounts()
        combo_accounts.insert(0, (None, _('All Accounts')))

        settings = [
            Setting(SettingKind.COMBO,
                    _('Account'),
                    SettingType.VALUE,
                    self.selected_account,
                    callback=self._set_account,
                    props={'combo_items': combo_accounts}),
            Setting(SettingKind.SWITCH,
                    'Presence',
                    SettingType.VALUE,
                    self.presence,
                    callback=self._on_setting,
                    data='presence'),
            Setting(SettingKind.SWITCH,
                    'Message',
                    SettingType.VALUE,
                    self.message,
                    callback=self._on_setting,
                    data='message'),
            Setting(SettingKind.SWITCH,
                    'IQ',
                    SettingType.VALUE,
                    self.iq,
                    callback=self._on_setting,
                    data='iq'),
            Setting(SettingKind.SWITCH,
                    'Stream Management',
                    SettingType.VALUE,
                    self.stream,
                    callback=self._on_setting,
                    data='stream'),
            Setting(SettingKind.SWITCH,
                    'In',
                    SettingType.VALUE,
                    self.incoming,
                    callback=self._on_setting,
                    data='incoming'),
            Setting(SettingKind.SWITCH,
                    'Out',
                    SettingType.VALUE,
                    self.outgoing,
                    callback=self._on_setting,
                    data='outgoing'),
        ]

        self.filter_dialog = SettingsDialog(
            self, _('Filter'), Gtk.DialogFlags.DESTROY_WITH_PARENT, settings,
            self.selected_account)
        self.filter_dialog.connect('destroy', self._on_filter_destroyed)
示例#4
0
    def __init__(self, account, parent):

        settings = [
            Setting(SettingKind.FILECHOOSER,
                    _('Client Certificate'),
                    SettingType.ACCOUNT_CONFIG,
                    'client_cert',
                    props={'filefilter': (_('PKCS12 Files'), '*.p12')}),
            Setting(SettingKind.SWITCH, _('Encrypted Certificate'),
                    SettingType.ACCOUNT_CONFIG, 'client_cert_encrypted'),
        ]

        SettingsDialog.__init__(self, parent, _('Certificate Settings'),
                                Gtk.DialogFlags.MODAL, settings, account)
示例#5
0
    def __init__(self, account, parent):

        settings = [
            Setting(SettingKind.ENTRY, _('First Name'),
                    SettingType.ACCOUNT_CONFIG, 'zeroconf_first_name'),
            Setting(SettingKind.ENTRY, _('Last Name'),
                    SettingType.ACCOUNT_CONFIG, 'zeroconf_last_name'),
            Setting(SettingKind.ENTRY, _('XMPP Address'),
                    SettingType.ACCOUNT_CONFIG, 'zeroconf_jabber_id'),
            Setting(SettingKind.ENTRY, _('Email'), SettingType.ACCOUNT_CONFIG,
                    'zeroconf_email'),
        ]

        SettingsDialog.__init__(self, parent, _('Profile'),
                                Gtk.DialogFlags.MODAL, settings, account)
示例#6
0
    def __init__(self, plugin, parent):

        icon_position = [('0', _('Before Avatar')),
                         ('1', _('After Status Icon'))]

        self.plugin = plugin
        settings = [
            Setting(SettingKind.SWITCH,
                    _('Show Icons in Contact List'),
                    SettingType.VALUE,
                    self.plugin.config['show_in_roster'],
                    callback=self._on_setting,
                    data='show_in_roster'),
            Setting(SettingKind.SWITCH,
                    _('Show Icons in Tooltip'),
                    SettingType.VALUE,
                    self.plugin.config['show_in_tooltip'],
                    callback=self._on_setting,
                    data='show_in_tooltip'),
            Setting(SettingKind.SWITCH,
                    _('Show Icon for Unknown Clients'),
                    SettingType.VALUE,
                    self.plugin.config['show_unknown_icon'],
                    callback=self._on_setting,
                    data='show_unknown_icon'),
            Setting(SettingKind.SWITCH,
                    _('Show Icon for Transports'),
                    SettingType.VALUE,
                    self.plugin.config['show_facebook'],
                    desc=_('Icons for facebook.com and vk.com'),
                    callback=self._on_setting,
                    data='show_facebook'),
            Setting(SettingKind.COMBO,
                    _('Icon Position'),
                    SettingType.VALUE,
                    self.plugin.config['pos_in_list'],
                    callback=self._on_setting,
                    data='pos_in_list',
                    props={'combo_items': icon_position}),
        ]

        SettingsDialog.__init__(self, parent, _('Clients Icons Configuration'),
                                Gtk.DialogFlags.MODAL, settings, None)
示例#7
0
    def __init__(self, plugin, parent):

        self.plugin = plugin
        settings = [
            Setting('BoardSizeSpinSetting',
                    _('Board Size'),
                    SettingType.VALUE,
                    self.plugin.config['board_size'],
                    callback=self.on_setting,
                    data='board_size',
                    desc=_('Size of the board'),
                    props={'range_': (3, 10)})
        ]

        SettingsDialog.__init__(self,
                                parent,
                                _('TicTacToe Configuration'),
                                Gtk.DialogFlags.MODAL,
                                settings,
                                None,
                                extend=[('BoardSizeSpinSetting',
                                         SizeSpinSetting)])
示例#8
0
    def __init__(self, account, parent):

        settings = [
            Setting(SettingKind.SWITCH,
                    _('Enable'),
                    SettingType.ACCOUNT_CONFIG,
                    'use_custom_host',
                    name='custom'),
            Setting(SettingKind.ENTRY,
                    _('Hostname'),
                    SettingType.ACCOUNT_CONFIG,
                    'custom_host',
                    enabledif=('custom', True)),
            Setting(SettingKind.ENTRY,
                    _('Port'),
                    SettingType.ACCOUNT_CONFIG,
                    'custom_port',
                    enabledif=('custom', True)),
        ]

        SettingsDialog.__init__(self, parent, _('Connection Settings'),
                                Gtk.DialogFlags.MODAL, settings, account)
示例#9
0
    def __init__(self, account, parent):

        neg_priority = app.config.get('enable_negative_priority')
        if neg_priority:
            range_ = (-128, 127)
        else:
            range_ = (0, 127)

        settings = [
            Setting(SettingKind.SWITCH, _('Adjust to status'),
                    SettingType.ACCOUNT_CONFIG, 'adjust_priority_with_status',
                    'adjust'),
            Setting(SettingKind.SPIN,
                    _('Priority'),
                    SettingType.ACCOUNT_CONFIG,
                    'priority',
                    enabledif=('adjust', False),
                    props={'range_': range_}),
        ]

        SettingsDialog.__init__(self, parent, _('Priority'),
                                Gtk.DialogFlags.MODAL, settings, account)

        self.connect('destroy', self.on_destroy)
示例#10
0
    def __init__(self, plugin, parent):
        self.plugin = plugin

        qualities = [
            ('best', _('Best')),
            ('1080p', '1080p'),
            ('720p', '720p'),
            ('480p', '480p'),
            ('240p', '240p'),
            ('144p', '144p'),
        ]

        settings = [
            Setting(
                SettingKind.SWITCH,
                _('Enable database'),
                SettingType.VALUE,
                self.plugin.config['DB_ENABLED'],
                callback=self._on_setting,
                data='DB_ENABLED',
            ),
            Setting(
                'DirectoryChooserSetting',
                _('Video directory'),
                SettingType.VALUE,
                self.plugin.config['VIDEO_DIR'],
                callback=self._on_setting,
                data='VIDEO_DIR',
                desc=_('Directory for local video search')
            ),
            Setting(
                SettingKind.COMBO,
                _('Preferred maximum stream quality'),
                SettingType.VALUE,
                self.plugin.config['preferred_maximum_stream_quality'],
                callback=self._on_setting,
                data='preferred_maximum_stream_quality',
                desc=_('Preferred maximum quality for internet videos'),
                props={'combo_items': qualities},
            ),
            Setting('AlphaColorSetting',
                    _('User message foreground color'),
                    SettingType.VALUE,
                    self.plugin.config['USER_FG_COLOR'],
                    callback=self._on_setting,
                    data='USER_FG_COLOR',
                    desc=_('Foreground color for your messages'),
            ),
            Setting('AlphaColorSetting',
                    _('User message background color'),
                    SettingType.VALUE,
                    self.plugin.config['USER_BG_COLOR'],
                    callback=self._on_setting,
                    data='USER_BG_COLOR',
                    desc=_('Background color for your messages'),
            ),
            Setting('AlphaColorSetting',
                    _('Partner message foreground color'),
                    SettingType.VALUE,
                    self.plugin.config['PARTNER_FG_COLOR'],
                    callback=self._on_setting,
                    data='PARTNER_FG_COLOR',
                    desc=_('Foreground color for your partner\'s messages'),
            ),
            Setting('AlphaColorSetting',
                    _('Partner message background color'),
                    SettingType.VALUE,
                    self.plugin.config['PARTNER_BG_COLOR'],
                    callback=self._on_setting,
                    data='PARTNER_BG_COLOR',
                    desc=_('Background color for your partner\'s messages'),
            ),
        ]

        for p in color_properties:
            settings.append(Setting(
                'AlphaColorSetting',
                color_properties[p][1],
                SettingType.VALUE,
                self.plugin.config[p],
                callback=self._on_setting,
                data=p,
                desc=color_properties[p][2]
            ))

        extensions = [
            ('DirectoryChooserSetting', DirectoryChooserSetting),
            ('AlphaColorSetting', AlphaColorSetting),
        ]

        SettingsDialog.__init__(self, parent,
                                _('Moov Configuration'),
                                Gtk.DialogFlags.MODAL, settings, None,
                                extend=extensions)
示例#11
0
    def __init__(self, plugin, parent):

        sizes = [('262144', '256 KiB'), ('524288', '512 KiB'),
                 ('1048576', '1 MiB'), ('5242880', '5 MiB'),
                 ('10485760', '10 MiB')]

        actions = [('open_menuitem', _('Open')),
                   ('save_as_menuitem', _('Save as')),
                   ('open_folder_menuitem', _('Open Folder')),
                   ('copy_link_location_menuitem', _('Copy Link Location')),
                   ('open_link_in_browser_menuitem', _('Open Link in Browser'))
                   ]

        geo_providers = [('no_preview', _('No map preview')),
                         ('Google', _('Google Maps')),
                         ('OSM', _('OpenStreetMap'))]

        self.plugin = plugin
        settings = [
            Setting('PreviewSizeSpinSetting',
                    _('Preview Size'),
                    SettingType.VALUE,
                    self.plugin.config['PREVIEW_SIZE'],
                    callback=self.on_setting,
                    data='PREVIEW_SIZE',
                    desc=_('Size of preview image'),
                    props={'range_': (100, 1000)}),
            Setting(SettingKind.COMBO,
                    _('File Size'),
                    SettingType.VALUE,
                    self.plugin.config['MAX_FILE_SIZE'],
                    callback=self.on_setting,
                    data='MAX_FILE_SIZE',
                    desc=_('Maximum file size for preview generation'),
                    props={'combo_items': sizes}),
            Setting(SettingKind.SWITCH,
                    _('Preview all Image URLs'),
                    SettingType.VALUE,
                    self.plugin.config['ALLOW_ALL_IMAGES'],
                    callback=self.on_setting,
                    data='ALLOW_ALL_IMAGES',
                    desc=_('Generate preview for any URL containing images '
                           '(may be unsafe)')),
            Setting(SettingKind.COMBO,
                    _('Left Click'),
                    SettingType.VALUE,
                    self.plugin.config['LEFTCLICK_ACTION'],
                    callback=self.on_setting,
                    data='LEFTCLICK_ACTION',
                    desc=_('Action when left clicking a preview'),
                    props={'combo_items': actions}),
            Setting(SettingKind.COMBO,
                    _('Map Service'),
                    SettingType.VALUE,
                    self.plugin.config['GEO_PREVIEW_PROVIDER'],
                    callback=self.on_setting,
                    data='GEO_PREVIEW_PROVIDER',
                    desc=_('Service used for map previews'),
                    props={'combo_items': geo_providers}),
            Setting(SettingKind.SWITCH,
                    _('HTTPS Verification'),
                    SettingType.VALUE,
                    self.plugin.config['VERIFY'],
                    desc=_('Whether to check for a valid certificate'),
                    callback=self.on_setting,
                    data='VERIFY'),
        ]

        SettingsDialog.__init__(self,
                                parent,
                                _('UrlImagePreview Configuration'),
                                Gtk.DialogFlags.MODAL,
                                settings,
                                None,
                                extend=[('PreviewSizeSpinSetting',
                                         SizeSpinSetting)])
示例#12
0
class XMLConsoleWindow(Gtk.ApplicationWindow):
    def __init__(self, account):
        Gtk.ApplicationWindow.__init__(self)
        self.set_application(app.app)
        self.set_position(Gtk.WindowPosition.CENTER)
        self.set_default_size(600, 600)
        self.set_resizable(True)
        self.set_show_menubar(False)
        self.set_name('XMLConsoleWindow')

        self.account = account
        self.enabled = True
        self.presence = True
        self.message = True
        self.iq = True
        self.stream = True
        self.incoming = True
        self.outgoing = True
        self.filter_dialog = None
        self.last_stanza = None

        self._ui = get_builder('xml_console_window.ui')

        jid = app.get_jid_from_account(account)
        self.set_titlebar(self._ui.headerbar)
        self._ui.headerbar.set_subtitle(jid)

        self.add(self._ui.box)

        self._ui.paned.set_position(self._ui.paned.get_property('max-position'))

        button = get_image_button(
            'edit-clear-all-symbolic', _('Clear'))
        button.connect('clicked', self._on_clear)
        self._ui.actionbar.pack_start(button)

        button = get_image_button(
            'applications-system-symbolic', _('Filter'))
        button.connect('clicked', self._on_filter_options)
        self._ui.actionbar.pack_start(button)

        button = get_image_button(
            'document-edit-symbolic', _('XML Input'), toggle=True)
        button.connect('toggled', self._on_input)
        self._ui.actionbar.pack_start(button)

        button = get_image_button('insert-text-symbolic', _('Paste Last Input'))
        button.connect('clicked', self._on_paste_last)
        self._ui.actionbar.pack_start(button)

        button = get_image_button('mail-send-symbolic', _('Send'))
        button.connect('clicked', self._on_send)
        self._ui.actionbar.pack_end(button)

        self._ui.actionbar.pack_start(self._ui.menubutton)

        self._create_tags()
        self.show_all()

        self._ui.scrolled_input.hide()
        self._ui.menubutton.hide()

        self.connect('destroy', self._on_destroy)
        self.connect('key_press_event', self._on_key_press_event)
        self._ui.connect_signals(self)

        app.ged.register_event_handler(
            'stanza-received', ged.GUI1, self._nec_stanza_received)
        app.ged.register_event_handler(
            'stanza-sent', ged.GUI1, self._nec_stanza_sent)

    def _create_tags(self):
        buffer_ = self._ui.textview.get_buffer()
        in_color = app.css_config.get_value(
            '.gajim-incoming-nickname', StyleAttr.COLOR)
        out_color = app.css_config.get_value(
            '.gajim-outgoing-nickname', StyleAttr.COLOR)

        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.destroy()
        if (event.get_state() & Gdk.ModifierType.CONTROL_MASK and
                event.keyval == Gdk.KEY_Return or
                event.keyval == Gdk.KEY_KP_Enter):
            self._on_send()
        if (event.get_state() & Gdk.ModifierType.CONTROL_MASK and
                event.keyval == Gdk.KEY_Up):
            self._on_paste_last()

    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._ui.input_entry.get_buffer()
            buffer_.set_text(input_text)
            self._ui.input_entry.grab_focus()

    def _on_send(self, *args):
        if not app.account_is_connected(self.account):
            # If offline or connecting
            ErrorDialog(
                _('Connection not available'),
                _('Please make sure you are connected with \'%s\'.') %
                self.account)
            return
        buffer_ = self._ui.input_entry.get_buffer()
        begin_iter, end_iter = buffer_.get_bounds()
        stanza = buffer_.get_text(begin_iter, end_iter, True)
        if stanza:
            try:
                node = nbxmpp.Protocol(node=stanza)
                if node.getNamespace() == UNDECLARED:
                    node.setNamespace(nbxmpp.NS_CLIENT)
            except Exception as error:
                ErrorDialog(_('Invalid Node'), str(error))
                return
            app.connections[self.account].connection.send(node)
            self.last_stanza = stanza
            buffer_.set_text('')

    def _on_paste_last(self, *args):
        buffer_ = self._ui.input_entry.get_buffer()
        if buffer_ is not None and self.last_stanza is not None:
            buffer_.set_text(self.last_stanza)
        self._ui.input_entry.grab_focus()

    def _on_input(self, button, *args):
        if button.get_active():
            self._ui.paned.get_child2().show()
            self._ui.menubutton.show()
            self._ui.input_entry.grab_focus()
        else:
            self._ui.paned.get_child2().hide()
            self._ui.menubutton.hide()

    def _on_filter_options(self, *args):
        if self.filter_dialog:
            self.filter_dialog.present()
            return
        options = [
            Setting(SettingKind.SWITCH, 'Presence',
                    SettingType.VALUE, self.presence,
                    callback=self._on_option, data='presence'),

            Setting(SettingKind.SWITCH, 'Message',
                    SettingType.VALUE, self.message,
                    callback=self._on_option, data='message'),

            Setting(SettingKind.SWITCH, 'IQ', SettingType.VALUE, self.iq,
                    callback=self._on_option, data='iq'),

            Setting(SettingKind.SWITCH, 'Stream Management',
                    SettingType.VALUE, self.stream,
                    callback=self._on_option, data='stream'),

            Setting(SettingKind.SWITCH, 'In', SettingType.VALUE, self.incoming,
                    callback=self._on_option, data='incoming'),

            Setting(SettingKind.SWITCH, 'Out', SettingType.VALUE, self.outgoing,
                    callback=self._on_option, data='outgoing'),
        ]

        self.filter_dialog = SettingsDialog(self, 'Filter',
                                            Gtk.DialogFlags.DESTROY_WITH_PARENT,
                                            options, self.account)
        self.filter_dialog.connect('destroy', self._on_filter_destroyed)

    def _on_filter_destroyed(self, win):
        self.filter_dialog = None

    def _on_clear(self, *args):
        self._ui.textview.get_buffer().set_text('')

    def _on_destroy(self, *args):
        app.ged.remove_event_handler(
            'stanza-received', ged.GUI1, self._nec_stanza_received)
        app.ged.remove_event_handler(
            'stanza-sent', ged.GUI1, self._nec_stanza_sent)

    def _on_enable(self, switch, param):
        self.enabled = switch.get_active()

    def _on_option(self, value, data):
        setattr(self, data, value)
        value = not value
        table = self._ui.textview.get_buffer().get_tag_table()
        tag = table.lookup(data)
        if data 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:
            return
        self._print_stanza(obj.stanza_str, 'incoming')

    def _nec_stanza_sent(self, obj):
        if obj.conn.name != self.account:
            return
        self._print_stanza(obj.stanza_str, 'outgoing')

    def _print_stanza(self, stanza, kind):
        # Kind must be 'incoming' or 'outgoing'
        if not self.enabled:
            return
        if not stanza:
            return

        at_the_end = util.at_the_end(self._ui.scrolled)

        buffer_ = self._ui.textview.get_buffer()
        end_iter = buffer_.get_end_iter()

        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'

        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(util.scroll_to_end, self._ui.scrolled)
示例#13
0
class XMLConsoleWindow(Gtk.ApplicationWindow, EventHelper):
    def __init__(self):
        Gtk.ApplicationWindow.__init__(self)
        EventHelper.__init__(self)
        self.set_application(app.app)
        self.set_position(Gtk.WindowPosition.CENTER)
        self.set_default_size(600, 600)
        self.set_resizable(True)
        self.set_show_menubar(False)
        self.set_name('XMLConsoleWindow')

        self.selected_account = None
        self._selected_send_account = None
        self.presence = True
        self.message = True
        self.iq = True
        self.stream = True
        self.incoming = True
        self.outgoing = True
        self.filter_dialog = None
        self.last_stanza = None
        self.last_search = ''

        self._ui = get_builder('xml_console.ui')
        self.set_titlebar(self._ui.headerbar)
        self._set_titlebar()
        self.add(self._ui.box)

        self._ui.paned.set_position(
            self._ui.paned.get_property('max-position'))

        self._combo = MaxWidthComboBoxText()
        self._combo.set_max_size(200)
        self._combo.set_hexpand(False)
        self._combo.set_halign(Gtk.Align.END)
        self._combo.set_no_show_all(True)
        self._combo.set_visible(False)
        self._combo.connect('changed', self._on_value_change)
        for account, label in self._get_accounts():
            self._combo.append(account, label)
        self._ui.actionbar.pack_end(self._combo)

        self._create_tags()
        self.show_all()

        self.connect('key_press_event', self._on_key_press_event)
        self._ui.connect_signals(self)

        self.register_events([
            ('stanza-received', ged.GUI1, self._nec_stanza_received),
            ('stanza-sent', ged.GUI1, self._nec_stanza_sent),
        ])

    def _on_value_change(self, combo):
        self._selected_send_account = combo.get_active_id()

    def _set_titlebar(self):
        if self.selected_account is None:
            title = _('All Accounts')
        else:
            title = app.get_jid_from_account(self.selected_account)
        self._ui.headerbar.set_subtitle(title)

    def _create_tags(self):
        buffer_ = self._ui.textview.get_buffer()
        in_color = app.css_config.get_value('.gajim-incoming-nickname',
                                            StyleAttr.COLOR)
        out_color = app.css_config.get_value('.gajim-outgoing-nickname',
                                             StyleAttr.COLOR)

        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:
            if self._ui.search_revealer.get_child_revealed():
                self._ui.search_revealer.set_reveal_child(False)
                return
            self.destroy()
        if (event.get_state() & Gdk.ModifierType.CONTROL_MASK
                and event.keyval == Gdk.KEY_Return
                or event.keyval == Gdk.KEY_KP_Enter):
            self._on_send()
        if (event.get_state() & Gdk.ModifierType.CONTROL_MASK
                and event.keyval == Gdk.KEY_Up):
            self._on_paste_last()
        if (event.get_state() & Gdk.ModifierType.CONTROL_MASK
                and event.keyval == Gdk.KEY_f):
            self._ui.search_toggle.set_active(
                not self._ui.search_revealer.get_child_revealed())
        if event.keyval == Gdk.KEY_F3:
            self._find(True)

    def _on_row_activated(self, _listbox, row):
        text = row.get_child().get_text()
        input_text = None
        if text == 'Presence':
            input_text = ('<presence xmlns="jabber:client">\n'
                          '<show></show>\n'
                          '<status></status>\n'
                          '<priority></priority>\n'
                          '</presence>')
        elif text == 'Message':
            input_text = ('<message to="" type="" xmlns="jabber:client">\n'
                          '<body></body>\n'
                          '</message>')
        elif text == 'Iq':
            input_text = ('<iq to="" type="" xmlns="jabber:client">\n'
                          '<query xmlns=""></query>\n'
                          '</iq>')

        if input_text is not None:
            buffer_ = self._ui.input_entry.get_buffer()
            buffer_.set_text(input_text)
            self._ui.input_entry.grab_focus()

    def _on_send(self, *args):
        if not self._selected_send_account:
            return
        if not app.account_is_connected(self._selected_send_account):
            # If offline or connecting
            ErrorDialog(
                _('Connection not available'),
                _('Please make sure you are connected with \'%s\'.') %
                self._selected_send_account)
            return
        buffer_ = self._ui.input_entry.get_buffer()
        begin_iter, end_iter = buffer_.get_bounds()
        stanza = buffer_.get_text(begin_iter, end_iter, True)
        if stanza:
            try:
                node = nbxmpp.Node(node=stanza)
            except Exception as error:
                ErrorDialog(_('Invalid Node'), str(error))
                return

            if node.getName() in ('message', 'presence', 'iq'):
                # Parse stanza again if its a message, presence or iq and
                # set jabber:client as toplevel namespace
                # Use type Protocol so nbxmpp counts the stanza for
                # stream management
                node = nbxmpp.Protocol(node=stanza,
                                       attrs={'xmlns': 'jabber:client'})
            app.connections[self._selected_send_account].connection.send(node)
            self.last_stanza = stanza
            buffer_.set_text('')

    def _on_paste_last(self, *args):
        buffer_ = self._ui.input_entry.get_buffer()
        if buffer_ is not None and self.last_stanza is not None:
            buffer_.set_text(self.last_stanza)
        self._ui.input_entry.grab_focus()

    def _on_input(self, button, *args):
        if button.get_active():
            self._ui.paned.get_child2().show()
            self._ui.send.show()
            self._ui.paste.show()
            self._combo.show()
            self._ui.menubutton.show()
            self._ui.input_entry.grab_focus()
        else:
            self._ui.paned.get_child2().hide()
            self._ui.send.hide()
            self._ui.paste.hide()
            self._combo.hide()
            self._ui.menubutton.hide()

    def _on_search_toggled(self, button):
        self._ui.search_revealer.set_reveal_child(button.get_active())
        self._ui.search_entry.grab_focus()

    def _on_search_activate(self, _widget):
        self._find(True)

    def _on_search_clicked(self, button):
        forward = bool(button is self._ui.search_forward)
        self._find(forward)

    def _find(self, forward):
        search_str = self._ui.search_entry.get_text()
        textbuffer = self._ui.textview.get_buffer()
        cursor_mark = textbuffer.get_insert()
        current_pos = textbuffer.get_iter_at_mark(cursor_mark)

        if current_pos.get_offset() == textbuffer.get_char_count():
            current_pos = textbuffer.get_start_iter()

        last_pos_mark = textbuffer.get_mark('last_pos')
        if last_pos_mark is not None:
            current_pos = textbuffer.get_iter_at_mark(last_pos_mark)

        if search_str != self.last_search:
            current_pos = textbuffer.get_start_iter()

        if forward:
            match = current_pos.forward_search(
                search_str, Gtk.TextSearchFlags.VISIBLE_ONLY
                | Gtk.TextSearchFlags.CASE_INSENSITIVE, None)
        else:
            current_pos.backward_cursor_position()
            match = current_pos.backward_search(
                search_str, Gtk.TextSearchFlags.VISIBLE_ONLY
                | Gtk.TextSearchFlags.CASE_INSENSITIVE, None)

        if match is not None:
            match_start, match_end = match
            textbuffer.select_range(match_start, match_end)
            mark = textbuffer.create_mark('last_pos', match_end, True)
            self._ui.textview.scroll_to_mark(mark, 0, True, 0.5, 0.5)
        self.last_search = search_str

    @staticmethod
    def _get_accounts():
        accounts = app.get_accounts_sorted()
        combo_accounts = []
        for account in accounts:
            label = app.get_account_label(account)
            combo_accounts.append((account, label))
        return combo_accounts

    def _on_filter_options(self, *args):
        if self.filter_dialog:
            self.filter_dialog.present()
            return

        combo_accounts = self._get_accounts()
        combo_accounts.insert(0, (None, _('All Accounts')))

        settings = [
            Setting(SettingKind.COMBO,
                    _('Account'),
                    SettingType.VALUE,
                    self.selected_account,
                    callback=self._set_account,
                    props={'combo_items': combo_accounts}),
            Setting(SettingKind.SWITCH,
                    'Presence',
                    SettingType.VALUE,
                    self.presence,
                    callback=self._on_setting,
                    data='presence'),
            Setting(SettingKind.SWITCH,
                    'Message',
                    SettingType.VALUE,
                    self.message,
                    callback=self._on_setting,
                    data='message'),
            Setting(SettingKind.SWITCH,
                    'IQ',
                    SettingType.VALUE,
                    self.iq,
                    callback=self._on_setting,
                    data='iq'),
            Setting(SettingKind.SWITCH,
                    'Stream Management',
                    SettingType.VALUE,
                    self.stream,
                    callback=self._on_setting,
                    data='stream'),
            Setting(SettingKind.SWITCH,
                    'In',
                    SettingType.VALUE,
                    self.incoming,
                    callback=self._on_setting,
                    data='incoming'),
            Setting(SettingKind.SWITCH,
                    'Out',
                    SettingType.VALUE,
                    self.outgoing,
                    callback=self._on_setting,
                    data='outgoing'),
        ]

        self.filter_dialog = SettingsDialog(
            self, _('Filter'), Gtk.DialogFlags.DESTROY_WITH_PARENT, settings,
            self.selected_account)
        self.filter_dialog.connect('destroy', self._on_filter_destroyed)

    def _on_filter_destroyed(self, _win):
        self.filter_dialog = None

    def _on_clear(self, *args):
        self._ui.textview.get_buffer().set_text('')

    def _set_account(self, value, _data):
        self.selected_account = value
        self._set_titlebar()

    def _on_setting(self, value, data):
        setattr(self, data, value)
        value = not value
        table = self._ui.textview.get_buffer().get_tag_table()
        tag = table.lookup(data)
        if data 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 self.selected_account is not None:
            if obj.conn.name != self.selected_account:
                return
        self._print_stanza(obj, 'incoming')

    def _nec_stanza_sent(self, obj):
        if self.selected_account is not None:
            if obj.conn.name != self.selected_account:
                return
        self._print_stanza(obj, 'outgoing')

    def _print_stanza(self, obj, kind):
        account = app.get_jid_from_account(obj.conn.name)
        stanza = obj.stanza_str
        # Kind must be 'incoming' or 'outgoing'
        if not stanza:
            return

        at_the_end = util.at_the_end(self._ui.scrolled)

        buffer_ = self._ui.textview.get_buffer()
        end_iter = buffer_.get_end_iter()

        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'

        stanza = '<!-- {kind} {time} ({account}) -->\n{stanza}\n\n'.format(
            kind=kind.capitalize(),
            time=time.strftime('%c'),
            account=account,
            stanza=stanza.replace('><', '>\n<'))
        buffer_.insert_with_tags_by_name(end_iter, stanza, type_, kind)

        if at_the_end:
            GLib.idle_add(util.scroll_to_end, self._ui.scrolled)