Philipp Hörist pushed to branch chat_markers at gajim / gajim

Commits:

17 changed files:

Changes:

  • gajim/app_actions.py
    ... ... @@ -249,12 +249,8 @@ def on_server_info(action, param):
    249 249
     
    
    250 250
     
    
    251 251
     def on_xml_console(action, param):
    
    252
    -    account = param.get_string()
    
    253
    -    window = app.get_app_window(XMLConsoleWindow, account)
    
    254
    -    if window is None:
    
    255
    -        XMLConsoleWindow(account)
    
    256
    -    else:
    
    257
    -        window.present()
    
    252
    +    XMLConsoleWindow()
    
    253
    +
    
    258 254
     
    
    259 255
     
    
    260 256
     def on_manage_proxies(action, param):
    

  • gajim/application.py
    ... ... @@ -431,6 +431,7 @@ class GajimApplication(Gtk.Application):
    431 431
                 ('history-manager', app_actions.on_history_manager),
    
    432 432
                 ('preferences', app_actions.on_preferences),
    
    433 433
                 ('plugins', app_actions.on_plugins),
    
    434
    +            ('xml-console', app_actions.on_xml_console),
    
    434 435
                 ('file-transfer', app_actions.on_file_transfers),
    
    435 436
                 ('history', app_actions.on_history),
    
    436 437
                 ('shortcuts', app_actions.on_keyboard_shortcuts),
    
    ... ... @@ -496,9 +497,7 @@ class GajimApplication(Gtk.Application):
    496 497
             from gajim import app_actions as a
    
    497 498
     
    
    498 499
             if account == 'Local':
    
    499
    -            return [
    
    500
    -                ('-xml-console', a.on_xml_console, 'always', 's')
    
    501
    -            ]
    
    500
    +            return []
    
    502 501
     
    
    503 502
             return [
    
    504 503
                 ('-bookmarks', a.on_bookmarks, 'online', 's'),
    
    ... ... @@ -507,7 +506,6 @@ class GajimApplication(Gtk.Application):
    507 506
                 ('-add-contact', a.on_add_contact, 'online', 'as'),
    
    508 507
                 ('-services', a.on_service_disco, 'online', 's'),
    
    509 508
                 ('-profile', a.on_profile, 'feature', 's'),
    
    510
    -            ('-xml-console', a.on_xml_console, 'always', 's'),
    
    511 509
                 ('-server-info', a.on_server_info, 'online', 's'),
    
    512 510
                 ('-archive', a.on_mam_preferences, 'feature', 's'),
    
    513 511
                 ('-pep-config', a.on_pep_config, 'online', 's'),
    

  • gajim/chat_control.py
    ... ... @@ -1284,7 +1284,8 @@ class ChatControl(ChatControlBase):
    1284 1284
                 self.add_message(event.message, kind, tim=event.time,
    
    1285 1285
                     encrypted=event.encrypted, subject=event.subject,
    
    1286 1286
                     xhtml=event.xhtml, displaymarking=event.displaymarking,
    
    1287
    -                correct_id=event.correct_id, additional_data=event.additional_data)
    
    1287
    +                correct_id=event.correct_id, message_id=event.message_id,
    
    1288
    +                additional_data=event.additional_data)
    
    1288 1289
                 if isinstance(event.msg_log_id, int):
    
    1289 1290
                     message_ids.append(event.msg_log_id)
    
    1290 1291
     
    

  • gajim/chat_control_base.py
    ... ... @@ -322,6 +322,9 @@ class ChatControlBase(MessageControl, ChatCommandProcessor, CommandTools):
    322 322
             self.received_history_pos = 0
    
    323 323
             self.orig_msg = None
    
    324 324
     
    
    325
    +        # For XEP-0333
    
    326
    +        self.last_msg_id = None
    
    327
    +
    
    325 328
             self.set_emoticon_popover()
    
    326 329
     
    
    327 330
             # Attach speller
    
    ... ... @@ -1022,6 +1025,9 @@ class ChatControlBase(MessageControl, ChatCommandProcessor, CommandTools):
    1022 1025
             if restored:
    
    1023 1026
                 return
    
    1024 1027
     
    
    1028
    +        if message_id:
    
    1029
    +            self.last_msg_id = message_id
    
    1030
    +
    
    1025 1031
             if kind == 'incoming':
    
    1026 1032
                 if not self.type_id == message_control.TYPE_GC or \
    
    1027 1033
                 app.config.notify_for_muc(jid) or \
    
    ... ... @@ -1065,6 +1071,7 @@ class ChatControlBase(MessageControl, ChatCommandProcessor, CommandTools):
    1065 1071
                         event_type.type_, self.contact.jid)
    
    1066 1072
     
    
    1067 1073
                     event = event_type(text, subject, self, msg_log_id,
    
    1074
    +                    msg_id=message_id,
    
    1068 1075
                         show_in_roster=show_in_roster,
    
    1069 1076
                         show_in_systray=show_in_systray)
    
    1070 1077
                     app.events.add_event(self.account, full_jid, event)
    
    ... ... @@ -1220,6 +1227,11 @@ class ChatControlBase(MessageControl, ChatCommandProcessor, CommandTools):
    1220 1227
                     types=type_):
    
    1221 1228
                         # There were events to remove
    
    1222 1229
                         self.redraw_after_event_removed(jid)
    
    1230
    +                    # XEP-0333 Send <displayed> tag.
    
    1231
    +                    con.get_module('ChatMarkers').send_displayed_marker(
    
    1232
    +                        self.get_full_jid(), self.last_msg_id,
    
    1233
    +                        self.type_id == message_control.TYPE_GC)
    
    1234
    +                    self.last_msg_id = None
    
    1223 1235
                 # send chatstate inactive to the one we're leaving
    
    1224 1236
                 # and active to the one we visit
    
    1225 1237
                 if self.msg_textview.has_text():
    
    ... ... @@ -1262,8 +1274,14 @@ class ChatControlBase(MessageControl, ChatCommandProcessor, CommandTools):
    1262 1274
                 # we are at the end
    
    1263 1275
                 if not app.events.remove_events(
    
    1264 1276
                         self.account, jid, types=types_list):
    
    1277
    +                con = app.connections[self.account]
    
    1265 1278
                     # There were events to remove
    
    1266 1279
                     self.redraw_after_event_removed(jid)
    
    1280
    +                # XEP-0333 Send <displayed> tag.
    
    1281
    +                con.get_module('ChatMarkers').send_displayed_marker(
    
    1282
    +                    self.get_full_jid(), self.last_msg_id,
    
    1283
    +                    self.type_id == message_control.TYPE_GC)
    
    1284
    +                self.last_msg_id = None
    
    1267 1285
     
    
    1268 1286
         def _on_scrollbar_button_release(self, scrollbar, event):
    
    1269 1287
             if event.get_button()[1] != 1:
    
    ... ... @@ -1328,6 +1346,8 @@ class ChatControlBase(MessageControl, ChatCommandProcessor, CommandTools):
    1328 1346
             We just removed a 'printed_*' event, redraw contact in roster or
    
    1329 1347
             gc_roster and titles in roster and msg_win
    
    1330 1348
             """
    
    1349
    +        if not self.parent_win: # minimized groupchat
    
    1350
    +            return
    
    1331 1351
             self.parent_win.redraw_tab(self)
    
    1332 1352
             self.parent_win.show_title()
    
    1333 1353
             # TODO : get the contact and check get_show_in_roster()
    

  • gajim/common/app.py
    ... ... @@ -152,6 +152,7 @@ gajim_common_features = [
    152 152
         nbxmpp.NS_BYTESTREAM,
    
    153 153
         nbxmpp.NS_FILE,
    
    154 154
         nbxmpp.NS_MUC,
    
    155
    +    nbxmpp.NS_CHATMARKERS,
    
    155 156
         nbxmpp.NS_COMMANDS,
    
    156 157
         nbxmpp.NS_DISCO_INFO,
    
    157 158
         nbxmpp.NS_LAST,
    

  • gajim/common/connection.py
    ... ... @@ -308,6 +308,9 @@ class CommonConnection:
    308 308
                     obj.session.last_send = time.time()
    
    309 309
                     msg_iq.setThread(obj.session.thread_id)
    
    310 310
     
    
    311
    +        if obj.message:
    
    312
    +            msg_iq.setMarkable()
    
    313
    +
    
    311 314
             self._push_stanza_message_outgoing(obj, msg_iq)
    
    312 315
     
    
    313 316
         def _push_stanza_message_outgoing(self, obj, msg_iq):
    

  • gajim/common/events.py
    ... ... @@ -62,7 +62,7 @@ class Event:
    62 62
     class ChatEvent(Event):
    
    63 63
         type_ = 'chat'
    
    64 64
         def __init__(self, message, subject, kind, time_, encrypted, resource,
    
    65
    -    msg_log_id, correct_id=None, xhtml=None, session=None, form_node=None,
    
    65
    +    msg_log_id, correct_id=None, message_id=None, xhtml=None, session=None, form_node=None,
    
    66 66
         displaymarking=None, sent_forwarded=False, show_in_roster=False,
    
    67 67
         show_in_systray=True, additional_data=None):
    
    68 68
             Event.__init__(self, time_, show_in_roster=show_in_roster,
    
    ... ... @@ -74,6 +74,7 @@ class ChatEvent(Event):
    74 74
             self.encrypted = encrypted
    
    75 75
             self.resource = resource
    
    76 76
             self.msg_log_id = msg_log_id
    
    77
    +        self.message_id = message_id
    
    77 78
             self.correct_id = correct_id
    
    78 79
             self.xhtml = xhtml
    
    79 80
             self.session = session
    
    ... ... @@ -94,13 +95,14 @@ class PmEvent(ChatEvent):
    94 95
     class PrintedChatEvent(Event):
    
    95 96
         type_ = 'printed_chat'
    
    96 97
         def __init__(self, message, subject, control, msg_log_id, time_=None,
    
    97
    -    show_in_roster=False, show_in_systray=True):
    
    98
    +    message_id=None, show_in_roster=False, show_in_systray=True):
    
    98 99
             Event.__init__(self, time_, show_in_roster=show_in_roster,
    
    99 100
                 show_in_systray=show_in_systray)
    
    100 101
             self.message = message
    
    101 102
             self.subject = subject
    
    102 103
             self.control = control
    
    103 104
             self.msg_log_id = msg_log_id
    
    105
    +        self.message_id = message_id
    
    104 106
     
    
    105 107
     class PrintedGcMsgEvent(PrintedChatEvent):
    
    106 108
         type_ = 'printed_gc_msg'
    

  • gajim/common/modules/__init__.py
    ... ... @@ -40,6 +40,7 @@ MODULES = [
    40 40
         'bookmarks',
    
    41 41
         'caps',
    
    42 42
         'carbons',
    
    43
    +    'chat_markers',
    
    43 44
         'chatstates',
    
    44 45
         'delimiter',
    
    45 46
         'discovery',
    

  • gajim/common/modules/chat_markers.py
    1
    +# This file is part of Gajim.
    
    2
    +#
    
    3
    +# Gajim is free software; you can redistribute it and/or modify
    
    4
    +# it under the terms of the GNU General Public License as published
    
    5
    +# by the Free Software Foundation; version 3 only.
    
    6
    +#
    
    7
    +# Gajim is distributed in the hope that it will be useful,
    
    8
    +# but WITHOUT ANY WARRANTY; without even the implied warranty of
    
    9
    +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    
    10
    +# GNU General Public License for more details.
    
    11
    +#
    
    12
    +# You should have received a copy of the GNU General Public License
    
    13
    +# along with Gajim.  If not, see <http://www.gnu.org/licenses/>.
    
    14
    +
    
    15
    +# Chat Markers (XEP-0333)
    
    16
    +
    
    17
    +import nbxmpp
    
    18
    +from nbxmpp.structs import StanzaHandler
    
    19
    +
    
    20
    +from gajim.common import app
    
    21
    +from gajim.common.nec import NetworkEvent
    
    22
    +from gajim.common.modules.base import BaseModule
    
    23
    +
    
    24
    +
    
    25
    +class ChatMarkers(BaseModule):
    
    26
    +
    
    27
    +    _nbxmpp_extends = 'ChatMarkers'
    
    28
    +
    
    29
    +    def __init__(self, con):
    
    30
    +        BaseModule.__init__(self, con)
    
    31
    +
    
    32
    +        self.handlers = [
    
    33
    +            StanzaHandler(name='message',
    
    34
    +                          callback=self._process_message_marker,
    
    35
    +                          ns=nbxmpp.NS_CHATMARKERS,
    
    36
    +                          priority=48),
    
    37
    +        ]
    
    38
    +
    
    39
    +    def _process_message_marker(self, _con, stanza, properties):
    
    40
    +        if not properties.is_displayed_marker:
    
    41
    +            return
    
    42
    +
    
    43
    +        if properties.type.is_error:
    
    44
    +            return
    
    45
    +
    
    46
    +        self._log.info('Displayed: %s, id: %s',
    
    47
    +                       properties.jid, properties.marker.id)
    
    48
    +
    
    49
    +        app.nec.push_outgoing_event(
    
    50
    +            NetworkEvent('displayed-marker-received',
    
    51
    +                         account=self._account,
    
    52
    +                         jid=properties.jid,
    
    53
    +                         type=properties.type,
    
    54
    +                         marker_id=properties.marker.id))
    
    55
    +
    
    56
    +    def send_marker(self, jid, marker, id_, is_gc):
    
    57
    +        if is_gc:
    
    58
    +            message = nbxmpp.Message(to=jid, typ='groupchat')
    
    59
    +        else:
    
    60
    +            message = nbxmpp.Message(to=jid, typ='chat')
    
    61
    +        message.setTag(marker, namespace=nbxmpp.NS_CHATMARKERS,
    
    62
    +            attrs={'id': id_})
    
    63
    +        self._nbxmpp().send(message)
    
    64
    +
    
    65
    +    def send_displayed_marker(self, jid, id_, is_gc):
    
    66
    +        self.send_marker(jid, 'displayed', id_, is_gc)
    
    67
    +
    
    68
    +
    
    69
    +def get_instance(*args, **kwargs):
    
    70
    +    return ChatMarkers(*args, **kwargs), 'ChatMarkers'

  • gajim/common/modules/message.py
    ... ... @@ -173,7 +173,7 @@ class Message(BaseModule):
    173 173
                 'timestamp': properties.timestamp,
    
    174 174
                 'delayed': properties.user_timestamp is not None,
    
    175 175
                 'muc_pm': properties.is_muc_pm,
    
    176
    -            'gc_control': gc_control
    
    176
    +            'gc_control': gc_control,
    
    177 177
             }
    
    178 178
     
    
    179 179
             app.nec.push_incoming_event(NetworkEvent('update-client-info',
    

  • gajim/data/gui/application_menu.ui
    ... ... @@ -28,6 +28,11 @@
    28 28
             </item>
    
    29 29
           </section>
    
    30 30
           <section>
    
    31
    +        <item>
    
    32
    +          <attribute name="label" translatable="yes">XML Console</attribute>
    
    33
    +          <attribute name="action">app.xml-console</attribute>
    
    34
    +          <attribute name="accel">&lt;Primary&gt;&lt;Shift&gt;X</attribute>
    
    35
    +        </item>
    
    31 36
             <item>
    
    32 37
               <attribute name="label" translatable="yes">File Transfer</attribute>
    
    33 38
               <attribute name="action">app.file-transfer</attribute>
    

  • gajim/data/gui/xml_console_window.ui → gajim/data/gui/xml_console.ui
    ... ... @@ -75,16 +75,12 @@
    75 75
         <property name="visible">True</property>
    
    76 76
         <property name="can_focus">False</property>
    
    77 77
         <property name="title" translatable="yes">XML Console</property>
    
    78
    -    <property name="has_subtitle">False</property>
    
    79 78
         <property name="show_close_button">True</property>
    
    80 79
         <child>
    
    81
    -      <object class="GtkSwitch">
    
    80
    +      <object class="GtkImage">
    
    82 81
             <property name="visible">True</property>
    
    83
    -        <property name="can_focus">True</property>
    
    84
    -        <property name="halign">start</property>
    
    85
    -        <property name="valign">center</property>
    
    86
    -        <property name="active">True</property>
    
    87
    -        <signal name="notify::active" handler="_on_enable" swapped="no"/>
    
    82
    +        <property name="can_focus">False</property>
    
    83
    +        <property name="icon_name">utilities-terminal-symbolic</property>
    
    88 84
           </object>
    
    89 85
         </child>
    
    90 86
       </object>
    

  • gajim/groupchat_control.py
    ... ... @@ -847,7 +847,8 @@ class GroupchatControl(ChatControlBase):
    847 847
     
    
    848 848
         def on_private_message(self, nick, sent, msg, tim, xhtml, session,
    
    849 849
                                msg_log_id=None, encrypted=False,
    
    850
    -                           displaymarking=None):
    
    850
    +                           displaymarking=None, message_id=None):
    
    851
    +
    
    851 852
             # Do we have a queue?
    
    852 853
             fjid = self.room_jid + '/' + nick
    
    853 854
     
    
    ... ... @@ -862,7 +863,9 @@ class GroupchatControl(ChatControlBase):
    862 863
                                    session=session,
    
    863 864
                                    form_node=None,
    
    864 865
                                    displaymarking=displaymarking,
    
    865
    -                               sent_forwarded=sent)
    
    866
    +                               sent_forwarded=sent,
    
    867
    +                               message_id=message_id)
    
    868
    +
    
    866 869
             app.events.add_event(self.account, fjid, event)
    
    867 870
     
    
    868 871
             autopopup = app.config.get('autopopup')
    
    ... ... @@ -1106,7 +1109,8 @@ class GroupchatControl(ChatControlBase):
    1106 1109
                     self.on_private_message(
    
    1107 1110
                         nick, obj.sent, obj.msgtxt, obj.timestamp,
    
    1108 1111
                         obj.xhtml, self.session, msg_log_id=obj.msg_log_id,
    
    1109
    -                    encrypted=obj.encrypted, displaymarking=obj.displaymarking)
    
    1112
    +                    encrypted=obj.encrypted, displaymarking=obj.displaymarking,
    
    1113
    +                    message_id=obj.message_id)
    
    1110 1114
     
    
    1111 1115
         def _nec_ping(self, obj):
    
    1112 1116
             if self.contact.jid != obj.contact.room_jid:
    

  • gajim/gtk/xml_console.py
    ... ... @@ -35,7 +35,7 @@ from gajim.gtk.const import SettingType
    35 35
     
    
    36 36
     
    
    37 37
     class XMLConsoleWindow(Gtk.ApplicationWindow):
    
    38
    -    def __init__(self, account):
    
    38
    +    def __init__(self):
    
    39 39
             Gtk.ApplicationWindow.__init__(self)
    
    40 40
             self.set_application(app.app)
    
    41 41
             self.set_position(Gtk.WindowPosition.CENTER)
    
    ... ... @@ -44,8 +44,7 @@ class XMLConsoleWindow(Gtk.ApplicationWindow):
    44 44
             self.set_show_menubar(False)
    
    45 45
             self.set_name('XMLConsoleWindow')
    
    46 46
     
    
    47
    -        self.account = account
    
    48
    -        self.enabled = True
    
    47
    +        self.selected_account = None
    
    49 48
             self.presence = True
    
    50 49
             self.message = True
    
    51 50
             self.iq = True
    
    ... ... @@ -55,24 +54,21 @@ class XMLConsoleWindow(Gtk.ApplicationWindow):
    55 54
             self.filter_dialog = None
    
    56 55
             self.last_stanza = None
    
    57 56
     
    
    58
    -        self._ui = get_builder('xml_console_window.ui')
    
    59
    -
    
    60
    -        jid = app.get_jid_from_account(account)
    
    57
    +        self._ui = get_builder('xml_console.ui')
    
    61 58
             self.set_titlebar(self._ui.headerbar)
    
    62
    -        self._ui.headerbar.set_subtitle(jid)
    
    63
    -
    
    59
    +        self._set_titlebar()
    
    64 60
             self.add(self._ui.box)
    
    65 61
     
    
    66 62
             self._ui.paned.set_position(self._ui.paned.get_property('max-position'))
    
    67 63
     
    
    68 64
             button = get_image_button(
    
    69
    -            'edit-clear-all-symbolic', _('Clear'))
    
    70
    -        button.connect('clicked', self._on_clear)
    
    65
    +            'applications-system-symbolic', _('Filter'))
    
    66
    +        button.connect('clicked', self._on_filter_options)
    
    71 67
             self._ui.actionbar.pack_start(button)
    
    72 68
     
    
    73 69
             button = get_image_button(
    
    74
    -            'applications-system-symbolic', _('Filter'))
    
    75
    -        button.connect('clicked', self._on_filter_options)
    
    70
    +            'edit-clear-symbolic', _('Clear'))
    
    71
    +        button.connect('clicked', self._on_clear)
    
    76 72
             self._ui.actionbar.pack_start(button)
    
    77 73
     
    
    78 74
             button = get_image_button(
    
    ... ... @@ -84,7 +80,7 @@ class XMLConsoleWindow(Gtk.ApplicationWindow):
    84 80
             button.connect('clicked', self._on_paste_last)
    
    85 81
             self._ui.actionbar.pack_start(button)
    
    86 82
     
    
    87
    -        button = get_image_button('mail-send-symbolic', _('Send'))
    
    83
    +        button = Gtk.Button.new_with_mnemonic(_('_Send'))
    
    88 84
             button.connect('clicked', self._on_send)
    
    89 85
             self._ui.actionbar.pack_end(button)
    
    90 86
     
    
    ... ... @@ -105,6 +101,13 @@ class XMLConsoleWindow(Gtk.ApplicationWindow):
    105 101
             app.ged.register_event_handler(
    
    106 102
                 'stanza-sent', ged.GUI1, self._nec_stanza_sent)
    
    107 103
     
    
    104
    +    def _set_titlebar(self):
    
    105
    +        if self.selected_account is None:
    
    106
    +            title = _('All Accounts')
    
    107
    +        else:
    
    108
    +            title = app.get_jid_from_account(self.selected_account)
    
    109
    +        self._ui.headerbar.set_subtitle(title)
    
    110
    +
    
    108 111
         def _create_tags(self):
    
    109 112
             buffer_ = self._ui.textview.get_buffer()
    
    110 113
             in_color = app.css_config.get_value(
    
    ... ... @@ -160,12 +163,12 @@ class XMLConsoleWindow(Gtk.ApplicationWindow):
    160 163
                 self._ui.input_entry.grab_focus()
    
    161 164
     
    
    162 165
         def _on_send(self, *args):
    
    163
    -        if not app.account_is_connected(self.account):
    
    166
    +        if not app.account_is_connected(self.selected_account):
    
    164 167
                 # If offline or connecting
    
    165 168
                 ErrorDialog(
    
    166 169
                     _('Connection not available'),
    
    167 170
                     _('Please make sure you are connected with \'%s\'.') %
    
    168
    -                self.account)
    
    171
    +                self.selected_account)
    
    169 172
                 return
    
    170 173
             buffer_ = self._ui.input_entry.get_buffer()
    
    171 174
             begin_iter, end_iter = buffer_.get_bounds()
    
    ... ... @@ -184,7 +187,7 @@ class XMLConsoleWindow(Gtk.ApplicationWindow):
    184 187
                     # stream management
    
    185 188
                     node = nbxmpp.Protocol(node=stanza,
    
    186 189
                                            attrs={'xmlns': 'jabber:client'})
    
    187
    -            app.connections[self.account].connection.send(node)
    
    190
    +            app.connections[self.selected_account].connection.send(node)
    
    188 191
                 self.last_stanza = stanza
    
    189 192
                 buffer_.set_text('')
    
    190 193
     
    
    ... ... @@ -207,32 +210,46 @@ class XMLConsoleWindow(Gtk.ApplicationWindow):
    207 210
             if self.filter_dialog:
    
    208 211
                 self.filter_dialog.present()
    
    209 212
                 return
    
    210
    -        options = [
    
    213
    +
    
    214
    +        # Get all accounts for settings combobox
    
    215
    +        accounts = app.get_accounts_sorted()
    
    216
    +        combo_accounts = []
    
    217
    +        for account in accounts:
    
    218
    +            label = app.get_account_label(account)
    
    219
    +            combo_accounts.append((account, label))
    
    220
    +        combo_accounts.insert(0, (None, _('All Accounts')))
    
    221
    +
    
    222
    +        settings = [
    
    223
    +            Setting(SettingKind.COMBO, _('Account'),
    
    224
    +                    SettingType.VALUE, self.selected_account,
    
    225
    +                    callback=self._set_account,
    
    226
    +                    props={'combo_items': combo_accounts}),
    
    227
    +
    
    211 228
                 Setting(SettingKind.SWITCH, 'Presence',
    
    212 229
                         SettingType.VALUE, self.presence,
    
    213
    -                    callback=self._on_option, data='presence'),
    
    230
    +                    callback=self._on_setting, data='presence'),
    
    214 231
     
    
    215 232
                 Setting(SettingKind.SWITCH, 'Message',
    
    216 233
                         SettingType.VALUE, self.message,
    
    217
    -                    callback=self._on_option, data='message'),
    
    234
    +                    callback=self._on_setting, data='message'),
    
    218 235
     
    
    219 236
                 Setting(SettingKind.SWITCH, 'IQ', SettingType.VALUE, self.iq,
    
    220
    -                    callback=self._on_option, data='iq'),
    
    237
    +                    callback=self._on_setting, data='iq'),
    
    221 238
     
    
    222 239
                 Setting(SettingKind.SWITCH, 'Stream Management',
    
    223 240
                         SettingType.VALUE, self.stream,
    
    224
    -                    callback=self._on_option, data='stream'),
    
    241
    +                    callback=self._on_setting, data='stream'),
    
    225 242
     
    
    226 243
                 Setting(SettingKind.SWITCH, 'In', SettingType.VALUE, self.incoming,
    
    227
    -                    callback=self._on_option, data='incoming'),
    
    244
    +                    callback=self._on_setting, data='incoming'),
    
    228 245
     
    
    229 246
                 Setting(SettingKind.SWITCH, 'Out', SettingType.VALUE, self.outgoing,
    
    230
    -                    callback=self._on_option, data='outgoing'),
    
    247
    +                    callback=self._on_setting, data='outgoing'),
    
    231 248
             ]
    
    232 249
     
    
    233
    -        self.filter_dialog = SettingsDialog(self, 'Filter',
    
    250
    +        self.filter_dialog = SettingsDialog(self, _('Filter'),
    
    234 251
                                                 Gtk.DialogFlags.DESTROY_WITH_PARENT,
    
    235
    -                                            options, self.account)
    
    252
    +                                            settings, self.selected_account)
    
    236 253
             self.filter_dialog.connect('destroy', self._on_filter_destroyed)
    
    237 254
     
    
    238 255
         def _on_filter_destroyed(self, win):
    
    ... ... @@ -247,10 +264,11 @@ class XMLConsoleWindow(Gtk.ApplicationWindow):
    247 264
             app.ged.remove_event_handler(
    
    248 265
                 'stanza-sent', ged.GUI1, self._nec_stanza_sent)
    
    249 266
     
    
    250
    -    def _on_enable(self, switch, param):
    
    251
    -        self.enabled = switch.get_active()
    
    267
    +    def _set_account(self, value, data):
    
    268
    +        self.selected_account = value
    
    269
    +        self._set_titlebar()
    
    252 270
     
    
    253
    -    def _on_option(self, value, data):
    
    271
    +    def _on_setting(self, value, data):
    
    254 272
             setattr(self, data, value)
    
    255 273
             value = not value
    
    256 274
             table = self._ui.textview.get_buffer().get_tag_table()
    
    ... ... @@ -263,19 +281,21 @@ class XMLConsoleWindow(Gtk.ApplicationWindow):
    263 281
             tag.set_property('invisible', value)
    
    264 282
     
    
    265 283
         def _nec_stanza_received(self, obj):
    
    266
    -        if obj.conn.name != self.account:
    
    267
    -            return
    
    268
    -        self._print_stanza(obj.stanza_str, 'incoming')
    
    284
    +        if self.selected_account is not None:
    
    285
    +            if obj.conn.name != self.selected_account:
    
    286
    +                return
    
    287
    +        self._print_stanza(obj, 'incoming')
    
    269 288
     
    
    270 289
         def _nec_stanza_sent(self, obj):
    
    271
    -        if obj.conn.name != self.account:
    
    272
    -            return
    
    273
    -        self._print_stanza(obj.stanza_str, 'outgoing')
    
    290
    +        if self.selected_account is not None:
    
    291
    +            if obj.conn.name != self.selected_account:
    
    292
    +                return
    
    293
    +        self._print_stanza(obj, 'outgoing')
    
    274 294
     
    
    275
    -    def _print_stanza(self, stanza, kind):
    
    295
    +    def _print_stanza(self, obj, kind):
    
    296
    +        account = app.get_jid_from_account(obj.conn.name)
    
    297
    +        stanza = obj.stanza_str
    
    276 298
             # Kind must be 'incoming' or 'outgoing'
    
    277
    -        if not self.enabled:
    
    278
    -            return
    
    279 299
             if not stanza:
    
    280 300
                 return
    
    281 301
     
    
    ... ... @@ -294,9 +314,10 @@ class XMLConsoleWindow(Gtk.ApplicationWindow):
    294 314
             elif stanza.startswith('<r') or stanza.startswith('<a'):
    
    295 315
                 type_ = 'stream'
    
    296 316
     
    
    297
    -        stanza = '<!-- {kind} {time} -->\n{stanza}\n\n'.format(
    
    317
    +        stanza = '<!-- {kind} {time} ({account}) -->\n{stanza}\n\n'.format(
    
    298 318
                 kind=kind.capitalize(),
    
    299 319
                 time=time.strftime('%c'),
    
    320
    +            account=account,
    
    300 321
                 stanza=stanza.replace('><', '>\n<'))
    
    301 322
             buffer_.insert_with_tags_by_name(end_iter, stanza, type_, kind)
    
    302 323
     
    

  • gajim/gui_interface.py
    ... ... @@ -285,6 +285,44 @@ class Interface:
    285 285
             if ctrl and ctrl.session and len(obj.contact_list) > 1:
    
    286 286
                 ctrl.remove_session(ctrl.session)
    
    287 287
     
    
    288
    +    def handle_event_chat_marker_received(self, event):
    
    289
    +        if event.type.is_groupchat:
    
    290
    +            types = ['printed_gc_msg', 'printed_marked_gc_msg']
    
    291
    +            control = app.interface.msg_win_mgr.get_control(event.jid,
    
    292
    +                                                            event.account)
    
    293
    +            if not control:
    
    294
    +                if event.jid in app.interface.minimized_controls[event.account]:
    
    295
    +                    control = app.interface.minimized_controls[event.account][event.jid]
    
    296
    +            if not control:
    
    297
    +                return
    
    298
    +            if obj.resource != control.nick:
    
    299
    +                return
    
    300
    +            event_jid = event.jid
    
    301
    +
    
    302
    +        else:
    
    303
    +
    
    304
    +            types = ['chat', 'pm', 'printed_chat', 'printed_pm']
    
    305
    +            if event.properties.carbon_type != 'sent':
    
    306
    +                return
    
    307
    +
    
    308
    +            control = app.interface.msg_win_mgr.get_control(event.jid,
    
    309
    +                                                            event.account)
    
    310
    +            if not control:
    
    311
    +                control = app.interface.msg_win_mgr.get_gc_control(
    
    312
    +                    event.jid, event.account)
    
    313
    +            event_jid = event.jid
    
    314
    +
    
    315
    +        # Compare with control.last_msg_id.
    
    316
    +        events_ = app.events.get_events(event.account, event_jid, types)
    
    317
    +        if not events_:
    
    318
    +            return
    
    319
    +        if events_[-1].msg_id != event.marker_id:
    
    320
    +            return
    
    321
    +        if not app.events.remove_events(event.account, event_jid, types=types):
    
    322
    +            # There were events to remove
    
    323
    +            if control:
    
    324
    +                control.redraw_after_event_removed(event.jid)
    
    325
    +
    
    288 326
         def handle_event_msgerror(self, obj):
    
    289 327
             #'MSGERROR' (account, (jid, error_code, error_msg, msg, time[session]))
    
    290 328
             account = obj.conn.name
    
    ... ... @@ -1173,6 +1211,7 @@ class Interface:
    1173 1211
                 'unsubscribed-presence-received': [
    
    1174 1212
                     self.handle_event_unsubscribed_presence],
    
    1175 1213
                 'zeroconf-name-conflict': [self.handle_event_zc_name_conflict],
    
    1214
    +            'displayed-marker-received': [self.handle_event_chat_marker_received],
    
    1176 1215
             }
    
    1177 1216
     
    
    1178 1217
         def register_core_handlers(self):
    

  • gajim/gui_menu_builder.py
    ... ... @@ -678,8 +678,6 @@ def get_account_menu(account):
    678 678
                 ('-pep-config', _('PEP Configuration')),
    
    679 679
                 ('-sync-history', _('Synchronise History')),
    
    680 680
                 ('-privacylists', _('Privacy Lists')),
    
    681
    -
    
    682
    -            ('-xml-console', _('XML Console'))
    
    683 681
             ]),
    
    684 682
             (_('Admin'), [
    
    685 683
                 ('-send-server-message', _('Send Server Message…')),
    
    ... ... @@ -689,10 +687,6 @@ def get_account_menu(account):
    689 687
             ]),
    
    690 688
         ]
    
    691 689
     
    
    692
    -    zeroconf_menu = [
    
    693
    -        ('-xml-console', _('XML Console')),
    
    694
    -    ]
    
    695
    -
    
    696 690
         def build_menu(preset):
    
    697 691
             menu = Gio.Menu()
    
    698 692
             for item in preset:
    
    ... ... @@ -713,8 +707,6 @@ def get_account_menu(account):
    713 707
                     menu.append_submenu(label, submenu)
    
    714 708
             return menu
    
    715 709
     
    
    716
    -    if account == 'Local':
    
    717
    -        return build_menu(zeroconf_menu)
    
    718 710
         return build_menu(account_menu)
    
    719 711
     
    
    720 712
     
    
    ... ... @@ -741,8 +733,9 @@ def build_accounts_menu():
    741 733
             acc_menu.append_item(modify_account_item)
    
    742 734
             for acc in accounts_list:
    
    743 735
                 label = escape_mnemonic(app.get_account_label(acc))
    
    744
    -            acc_menu.append_submenu(
    
    745
    -                label, get_account_menu(acc))
    
    736
    +            if acc != 'Local':
    
    737
    +                acc_menu.append_submenu(
    
    738
    +                    label, get_account_menu(acc))
    
    746 739
         else:
    
    747 740
             acc_menu = get_account_menu(accounts_list[0])
    
    748 741
             modify_account_item = Gio.MenuItem.new(_('_Modify Account…'),
    

  • gajim/session.py
    ... ... @@ -253,7 +253,9 @@ class ChatControlSession:
    253 253
             if do_event:
    
    254 254
                 event = event_t(obj.msgtxt, obj.subject, obj.mtype, obj.timestamp,
    
    255 255
                     obj.encrypted, obj.resource, obj.msg_log_id,
    
    256
    -                correct_id=(obj.id_, obj.correct_id), xhtml=obj.xhtml,
    
    256
    +                correct_id=obj.correct_id,
    
    257
    +                message_id=obj.message_id,
    
    258
    +                xhtml=obj.xhtml,
    
    257 259
                     session=self, form_node=obj.form_node,
    
    258 260
                     displaymarking=obj.displaymarking,
    
    259 261
                     sent_forwarded=obj.forwarded and obj.sent,