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

Commits:

6 changed files:

Changes:

  • gajim/common/modules/chatstates.py
    ... ... @@ -135,6 +135,7 @@ def _presence_received(self,
    135 135
             app.nec.push_outgoing_event(
    
    136 136
                 NetworkEvent('chatstate-received',
    
    137 137
                              account=self._account,
    
    138
    +                         jid=contact.jid,
    
    138 139
                              contact=contact))
    
    139 140
     
    
    140 141
         def _process_chatstate(self, _con, _stanza, properties):
    
    ... ... @@ -163,6 +164,7 @@ def _process_chatstate(self, _con, _stanza, properties):
    163 164
             app.nec.push_outgoing_event(
    
    164 165
                 NetworkEvent('chatstate-received',
    
    165 166
                              account=self._account,
    
    167
    +                         jid=contact.jid,
    
    166 168
                              contact=contact))
    
    167 169
     
    
    168 170
         @ensure_enabled
    

  • gajim/groupchat_control.py
    ... ... @@ -963,7 +963,7 @@ def check_focus_out_line(self):
    963 963
             - remove previous line first
    
    964 964
             """
    
    965 965
     
    
    966
    -        if app.window.is_chat_focused(self.account, self.room_jid):
    
    966
    +        if app.window.is_chat_active(self.account, self.room_jid):
    
    967 967
                 return
    
    968 968
     
    
    969 969
             self.conv_textview.show_focus_out_line()
    

  • gajim/gtk/chat_list.py
    ... ... @@ -37,6 +37,9 @@ def __init__(self, workspace_id):
    37 37
     
    
    38 38
             self.show_all()
    
    39 39
     
    
    40
    +    def is_visible(self):
    
    41
    +        return self.get_parent().get_property('child-widget') == self
    
    42
    +
    
    40 43
         def _on_destroy(self):
    
    41 44
             GLib.source_remove(self._timer_id)
    
    42 45
     
    
    ... ... @@ -101,12 +104,11 @@ def remove_chat(self, account, jid):
    101 104
             self.remove(row)
    
    102 105
             row.destroy()
    
    103 106
     
    
    104
    -    def get_active_chat(self):
    
    107
    +    def get_selected_chat(self):
    
    105 108
             row = self.get_selected_row()
    
    106 109
             if row is None:
    
    107 110
                 return None
    
    108
    -
    
    109
    -        return (row.account, row.jid)
    
    111
    +        return row
    
    110 112
     
    
    111 113
         def contains_chat(self, account, jid):
    
    112 114
             return self._chats.get((account, jid)) is not None
    
    ... ... @@ -132,9 +134,7 @@ def _on_message_received(self, event):
    132 134
                 return
    
    133 135
     
    
    134 136
             row = self._chats.get((event.account, event.jid))
    
    135
    -        if not (row.is_selected() and
    
    136
    -                self.get_toplevel().get_property('has-toplevel-focus')):
    
    137
    -            row.add_unread()
    
    137
    +        row.add_unread()
    
    138 138
             row.set_last_message_text('Me', event.msgtxt)
    
    139 139
     
    
    140 140
     
    
    ... ... @@ -218,6 +218,11 @@ def __init__(self, workspace_id, account, jid, type_):
    218 218
     
    
    219 219
             self.show_all()
    
    220 220
     
    
    221
    +    @property
    
    222
    +    def is_active(self):
    
    223
    +        return (self.is_selected() and
    
    224
    +                self.get_toplevel().get_property('is-active'))
    
    225
    +
    
    221 226
         def _on_state_flags_changed(self, _listboxrow, *args):
    
    222 227
             state = self.get_state_flags()
    
    223 228
             if (state & Gtk.StateFlags.PRELIGHT) != 0:
    
    ... ... @@ -233,10 +238,20 @@ def update_time(self):
    233 238
                 self._ui.timestamp_label.set_text(
    
    234 239
                     get_uf_relative_time(self._timestamp))
    
    235 240
     
    
    241
    +    def _update_unread(self):
    
    242
    +        print('Update unread', self.account, self.jid, self._unread_count)
    
    243
    +        self._ui.unread_label.set_text(str(self._unread_count))
    
    244
    +        self._ui.unread_label.set_visible(bool(self._unread_count))
    
    245
    +
    
    236 246
         def add_unread(self):
    
    247
    +        if self.is_active:
    
    248
    +            return
    
    237 249
             self._unread_count += 1
    
    238
    -        self._ui.unread_label.set_text(str(self._unread_count))
    
    239
    -        self._ui.unread_label.show()
    
    250
    +        self._update_unread()
    
    251
    +
    
    252
    +    def reset_unread(self):
    
    253
    +        self._unread_count = 0
    
    254
    +        self._update_unread()
    
    240 255
     
    
    241 256
         def set_last_message_text(self, nickname, text):
    
    242 257
             self._ui.message_label.set_text(text)
    

  • gajim/gtk/chat_list_stack.py
    ... ... @@ -12,7 +12,7 @@
    12 12
     
    
    13 13
     
    
    14 14
     class ChatListStack(Gtk.Stack):
    
    15
    -    def __init__(self, ui, chat_stack):
    
    15
    +    def __init__(self, main_window, ui, chat_stack):
    
    16 16
             Gtk.Stack.__init__(self)
    
    17 17
             self.set_hexpand(True)
    
    18 18
             self.set_vexpand(True)
    
    ... ... @@ -28,19 +28,30 @@ def __init__(self, ui, chat_stack):
    28 28
             self._ui.search_entry.connect(
    
    29 29
                 'search-changed', self._on_search_changed)
    
    30 30
     
    
    31
    -    def get_active_chat(self):
    
    31
    +        main_window.connect('notify::is-active', self._on_window_active)
    
    32
    +
    
    33
    +    def _on_window_active(self, window, _param):
    
    34
    +        is_active = window.get_property('is-active')
    
    35
    +        if is_active:
    
    36
    +            chat = self.get_selected_chat()
    
    37
    +            if chat is not None:
    
    38
    +                chat.reset_unread()
    
    39
    +
    
    40
    +    def get_selected_chat(self):
    
    32 41
             workspace_id = self.get_visible_child_name()
    
    33 42
             if workspace_id == 'empty':
    
    34 43
                 return None
    
    35 44
     
    
    36 45
             chat_list = self._chat_lists[workspace_id]
    
    37
    -        return chat_list.get_active_chat()
    
    46
    +        return chat_list.get_selected_chat()
    
    38 47
     
    
    39 48
         def is_chat_active(self, account, jid):
    
    40
    -        active = self.get_active_chat()
    
    41
    -        if active is None:
    
    49
    +        chat = self.get_selected_chat()
    
    50
    +        if chat is None:
    
    42 51
                 return False
    
    43
    -        return active == (account, jid)
    
    52
    +        if chat.account != account or chat.jid != jid:
    
    53
    +            return False
    
    54
    +        return chat.is_active
    
    44 55
     
    
    45 56
         def _on_search_changed(self, search_entry):
    
    46 57
             chat_list = self.get_visible_child()
    
    ... ... @@ -67,7 +78,10 @@ def _on_row_selected(self, _chat_list, row):
    67 78
             if row is None:
    
    68 79
                 self._chat_stack.clear()
    
    69 80
                 return
    
    81
    +
    
    70 82
             self._chat_stack.show_chat(row.account, row.jid)
    
    83
    +        if row.is_active:
    
    84
    +            row.reset_unread()
    
    71 85
     
    
    72 86
         def show_chat_list(self, workspace_id):
    
    73 87
             current_workspace_id = self.get_visible_child_name()
    

  • gajim/gtk/main.py
    ... ... @@ -45,7 +45,7 @@ def __init__(self):
    45 45
             self.add(self._ui.main_grid)
    
    46 46
     
    
    47 47
             self._chat_stack = ChatStack()
    
    48
    -        self._chat_list_stack = ChatListStack(self._ui, self._chat_stack)
    
    48
    +        self._chat_list_stack = ChatListStack(self, self._ui, self._chat_stack)
    
    49 49
             self._ui.chat_list_scrolled.add(self._chat_list_stack)
    
    50 50
     
    
    51 51
             self._account_side_bar = AccountSideBar()
    
    ... ... @@ -158,10 +158,7 @@ def get_workspace_bar(self):
    158 158
         def get_active_workspace(self):
    
    159 159
             return self._workspace_side_bar.get_active_workspace()
    
    160 160
     
    
    161
    -    def get_active_chat(self):
    
    162
    -        return self._chat_list_stack.get_active_chat()
    
    163
    -
    
    164
    -    def is_chat_focused(self, account, jid):
    
    161
    +    def is_chat_active(self, account, jid):
    
    165 162
             if not self.get_property('has-toplevel-focus'):
    
    166 163
                 return False
    
    167 164
             return self._chat_list_stack.is_chat_active(account, jid)
    

  • gajim/gtk/util.py
    ... ... @@ -856,3 +856,36 @@ def _destroy(*args):
    856 856
     
    
    857 857
     def check_finalize(obj, name):
    
    858 858
         weakref.finalize(obj, print, f'{name} has been finalized')
    
    859
    +
    
    860
    +
    
    861
    +def _connect_destroy(sender, func, detailed_signal, handler, *args, **kwargs):
    
    862
    +    """Connect a bound method to a foreign object signal and disconnect
    
    863
    +    if the object the method is bound to emits destroy (Gtk.Widget subclass).
    
    864
    +    Also works if the handler is a nested function in a method and
    
    865
    +    references the method's bound object.
    
    866
    +    This solves the problem that the sender holds a strong reference
    
    867
    +    to the bound method and the bound to object doesn't get GCed.
    
    868
    +    """
    
    869
    +
    
    870
    +    if hasattr(handler, "__self__"):
    
    871
    +        obj = handler.__self__
    
    872
    +    else:
    
    873
    +        # XXX: get the "self" var of the enclosing scope.
    
    874
    +        # Used for nested functions which ref the object but aren't methods.
    
    875
    +        # In case they don't ref "self" normal connect() should be used anyway.
    
    876
    +        index = handler.__code__.co_freevars.index("self")
    
    877
    +        obj = handler.__closure__[index].cell_contents
    
    878
    +
    
    879
    +    assert obj is not sender
    
    880
    +
    
    881
    +    handler_id = func(detailed_signal, handler, *args, **kwargs)
    
    882
    +
    
    883
    +    def disconnect_cb(*args):
    
    884
    +        sender.disconnect(handler_id)
    
    885
    +
    
    886
    +    obj.connect('destroy', disconnect_cb)
    
    887
    +    return handler_id
    
    888
    +
    
    889
    +
    
    890
    +def connect_destroy(sender, *args, **kwargs):
    
    891
    +    return _connect_destroy(sender, sender.connect, *args, **kwargs)