Daniel Brötzmann pushed to branch mainwindow at gajim / gajim

Commits:

7 changed files:

Changes:

  • gajim/common/const.py
    ... ... @@ -186,6 +186,11 @@ class Trust(IntEnum):
    186 186
         VERIFIED = 3
    
    187 187
     
    
    188 188
     
    
    189
    +class Direction(IntEnum):
    
    190
    +    NEXT = 0
    
    191
    +    PREV = 1
    
    192
    +
    
    193
    +
    
    189 194
     class Display(Enum):
    
    190 195
         X11 = 'X11Display'
    
    191 196
         WAYLAND = 'GdkWaylandDisplay'
    

  • gajim/gtk/chat_list.py
    ... ... @@ -30,6 +30,7 @@
    30 30
     from gajim.common import app
    
    31 31
     from gajim.common import ged
    
    32 32
     from gajim.common.const import AvatarSize
    
    33
    +from gajim.common.const import Direction
    
    33 34
     from gajim.common.const import KindConstant
    
    34 35
     from gajim.common.const import RowHeaderType
    
    35 36
     from gajim.common.i18n import _
    
    ... ... @@ -224,10 +225,9 @@ def select_chat(self, account: str, jid: JID) -> None:
    224 225
             row = self._chats[(account, jid)]
    
    225 226
             self.select_row(row)
    
    226 227
     
    
    227
    -    def select_next_chat(self, forwards: bool,
    
    228
    +    def select_next_chat(self, direction: Direction,
    
    228 229
                              unread_first: bool = False) -> None:
    
    229 230
             # Selects the next chat, but prioritizes chats with unread messages.
    
    230
    -        # Direction is forwards (True) or backwards (False)
    
    231 231
             row = self.get_selected_chat()
    
    232 232
             if row is None:
    
    233 233
                 row = self.get_row_at_index(0)
    
    ... ... @@ -243,7 +243,7 @@ def select_next_chat(self, forwards: bool,
    243 243
     
    
    244 244
                 # Loop until finding a chat with unread count or completing a cycle
    
    245 245
                 while True:
    
    246
    -                if forwards:
    
    246
    +                if direction == Direction.NEXT:
    
    247 247
                         index += 1
    
    248 248
                         if index >= len(self.get_children()):
    
    249 249
                             index = 0
    
    ... ... @@ -266,12 +266,12 @@ def select_next_chat(self, forwards: bool,
    266 266
                 return
    
    267 267
     
    
    268 268
             index = row.get_index()
    
    269
    -        if forwards:
    
    269
    +        if direction == Direction.NEXT:
    
    270 270
                 next_row = self.get_row_at_index(index + 1)
    
    271 271
             else:
    
    272 272
                 next_row = self.get_row_at_index(index - 1)
    
    273 273
             if next_row is None:
    
    274
    -            if forwards:
    
    274
    +            if direction == Direction.NEXT:
    
    275 275
                     next_row = self.get_row_at_index(0)
    
    276 276
                 else:
    
    277 277
                     last = len(self.get_children()) - 1
    

  • gajim/gtk/controls/base.py
    ... ... @@ -23,6 +23,9 @@
    23 23
     # You should have received a copy of the GNU General Public License
    
    24 24
     # along with Gajim. If not, see <http://www.gnu.org/licenses/>.
    
    25 25
     
    
    26
    +from typing import Any
    
    27
    +from typing import Dict
    
    28
    +from typing import List
    
    26 29
     from typing import Optional
    
    27 30
     
    
    28 31
     import os
    
    ... ... @@ -31,13 +34,16 @@
    31 34
     import uuid
    
    32 35
     import tempfile
    
    33 36
     
    
    34
    -from nbxmpp.const import Chatstate
    
    35
    -
    
    36 37
     from gi.repository import Gtk
    
    37 38
     from gi.repository import Gdk
    
    39
    +from gi.repository import GdkPixbuf
    
    38 40
     from gi.repository import GLib
    
    39 41
     from gi.repository import Gio
    
    40 42
     
    
    43
    +from nbxmpp import JID
    
    44
    +from nbxmpp.const import Chatstate
    
    45
    +from nbxmpp.modules.security_labels import Displaymarking
    
    46
    +
    
    41 47
     from gajim.common import app
    
    42 48
     from gajim.common import helpers
    
    43 49
     from gajim.common import ged
    
    ... ... @@ -48,6 +54,7 @@
    48 54
     from gajim.common.helpers import AdditionalDataDict
    
    49 55
     from gajim.common.helpers import get_retraction_text
    
    50 56
     from gajim.common.const import KindConstant
    
    57
    +from gajim.common.modules.httpupload import HTTPFileTransfer
    
    51 58
     from gajim.common.preview_helpers import filename_from_uri
    
    52 59
     from gajim.common.preview_helpers import guess_simple_file_type
    
    53 60
     from gajim.common.structs import OutgoingMessage
    
    ... ... @@ -103,13 +110,13 @@ class BaseControl(ChatCommandProcessor, CommandTools, EventHelper):
    103 110
     
    
    104 111
         _type = None  # type: ControlType
    
    105 112
     
    
    106
    -    def __init__(self, widget_name, account, jid):
    
    113
    +    def __init__(self, widget_name: str, account: str, jid: JID) -> None:
    
    107 114
             EventHelper.__init__(self)
    
    108 115
             # Undo needs this variable to know if space has been pressed.
    
    109 116
             # Initialize it to True so empty textview is saved in undo list
    
    110
    -        self.space_pressed = True
    
    117
    +        self.space_pressed: bool = True
    
    111 118
     
    
    112
    -        self.handlers = {}
    
    119
    +        self.handlers: Dict[str, Any] = {}
    
    113 120
     
    
    114 121
             self.account = account
    
    115 122
     
    
    ... ... @@ -122,7 +129,7 @@ def __init__(self, widget_name, account, jid):
    122 129
     
    
    123 130
             # control_id is a unique id for the control,
    
    124 131
             # its used as action name for actions that belong to a control
    
    125
    -        self.control_id = str(uuid.uuid4())
    
    132
    +        self.control_id: str = str(uuid.uuid4())
    
    126 133
             self.session = None
    
    127 134
     
    
    128 135
             self.xml = get_builder(f'{widget_name}.ui')
    
    ... ... @@ -131,8 +138,8 @@ def __init__(self, widget_name, account, jid):
    131 138
     
    
    132 139
             self._account_badge = AccountBadge(self.account)
    
    133 140
             self.xml.account_badge_box.add(self._account_badge)
    
    134
    -        show = len(app.settings.get_active_accounts()) > 1
    
    135
    -        self.xml.account_badge_box.set_visible(show)
    
    141
    +        show_account_badge = len(app.settings.get_active_accounts()) > 1
    
    142
    +        self.xml.account_badge_box.set_visible(show_account_badge)
    
    136 143
     
    
    137 144
             # Drag and drop
    
    138 145
             self.xml.overlay.add_overlay(self.xml.drop_area)
    
    ... ... @@ -214,30 +221,32 @@ def __init__(self, widget_name, account, jid):
    214 221
             self.xml.hbox.pack_start(self.msg_scrolledwindow, True, True, 0)
    
    215 222
     
    
    216 223
             # the following vars are used to keep history of user's messages
    
    217
    -        self.sent_history = []
    
    218
    -        self.sent_history_pos = 0
    
    219
    -        self.received_history = []
    
    220
    -        self.received_history_pos = 0
    
    221
    -        self.orig_msg = None
    
    224
    +        self.sent_history: List[str] = []
    
    225
    +        self.sent_history_pos: int = 0
    
    226
    +        self.received_history: List[str] = []
    
    227
    +        self.received_history_pos: int = 0
    
    228
    +        self.orig_msg: Optional[str] = None
    
    222 229
     
    
    223
    -        # For XEP-0333
    
    224
    -        self.last_msg_id = None
    
    230
    +        # XEP-0333 Chat Markers
    
    231
    +        self.last_msg_id: Optional[str] = None
    
    225 232
     
    
    226
    -        self.correcting = False
    
    227
    -        self.last_sent_msg = None
    
    233
    +        # XEP-0308 Message Correction
    
    234
    +        self.correcting: bool = False
    
    235
    +        self.last_sent_msg: Optional[str] = None
    
    228 236
     
    
    229 237
             self.set_emoticon_popover()
    
    230 238
     
    
    231 239
             # Attach speller
    
    232 240
             self.set_speller()
    
    233 241
     
    
    234
    -        # For XEP-0172
    
    242
    +        # XEP-0172 User Nickname
    
    243
    +        # TODO:
    
    235 244
             self.user_nick = None
    
    236 245
     
    
    237
    -        self.command_hits = []
    
    238
    -        self.last_key_tabs = False
    
    246
    +        self.command_hits: List[str] = []
    
    247
    +        self.last_key_tabs: bool = False
    
    239 248
     
    
    240
    -        self.sendmessage = True
    
    249
    +        self.sendmessage: bool = True
    
    241 250
     
    
    242 251
             self._client.get_module('Chatstate').set_active(self.contact)
    
    243 252
     
    
    ... ... @@ -263,11 +272,17 @@ def __init__(self, widget_name, account, jid):
    263 272
         def _connect_contact_signals(self):
    
    264 273
             raise NotImplementedError
    
    265 274
     
    
    266
    -    def _process_jingle_av_event(self):
    
    275
    +    def _process_jingle_av_event(self, *args):
    
    267 276
             raise NotImplementedError
    
    268 277
     
    
    269
    -    def _get_action(self, name):
    
    270
    -        return app.window.lookup_action(name + self.control_id)
    
    278
    +    def get_our_nick(self):
    
    279
    +        raise NotImplementedError
    
    280
    +
    
    281
    +    def room_name(self):
    
    282
    +        raise NotImplementedError
    
    283
    +
    
    284
    +    def _get_action(self, name: str) -> Gio.Action:
    
    285
    +        return app.window.lookup_action(f'{name}{self.control_id}')
    
    271 286
     
    
    272 287
         def process_event(self, event):
    
    273 288
             if event.account != self.account:
    
    ... ... @@ -341,22 +356,22 @@ def _on_conversation_view_key_press(self, _listbox, event):
    341 356
             return Gdk.EVENT_STOP
    
    342 357
     
    
    343 358
         @property
    
    344
    -    def type(self):
    
    359
    +    def type(self) -> ControlType:
    
    345 360
             return self._type
    
    346 361
     
    
    347 362
         @property
    
    348
    -    def is_chat(self):
    
    363
    +    def is_chat(self) -> bool:
    
    349 364
             return self._type.is_chat
    
    350 365
     
    
    351 366
         @property
    
    352
    -    def is_privatechat(self):
    
    367
    +    def is_privatechat(self) -> bool:
    
    353 368
             return self._type.is_privatechat
    
    354 369
     
    
    355 370
         @property
    
    356
    -    def is_groupchat(self):
    
    371
    +    def is_groupchat(self) -> bool:
    
    357 372
             return self._type.is_groupchat
    
    358 373
     
    
    359
    -    def safe_shutdown(self):
    
    374
    +    def safe_shutdown(self) -> bool:
    
    360 375
             """
    
    361 376
             Called to check if control can be closed without losing data.
    
    362 377
             returns True if control can be closed safely else False
    
    ... ... @@ -378,7 +393,7 @@ def allow_shutdown(self, method, on_response_yes, on_response_no):
    378 393
         def focus(self):
    
    379 394
             raise NotImplementedError
    
    380 395
     
    
    381
    -    def draw_banner(self):
    
    396
    +    def draw_banner(self) -> None:
    
    382 397
             """
    
    383 398
             Draw the fat line at the top of the window
    
    384 399
             that houses the icon, jid, etc
    
    ... ... @@ -387,7 +402,7 @@ def draw_banner(self):
    387 402
             """
    
    388 403
             self.draw_banner_text()
    
    389 404
     
    
    390
    -    def update_toolbar(self):
    
    405
    +    def update_toolbar(self) -> None:
    
    391 406
             """
    
    392 407
             update state of buttons in toolbar
    
    393 408
             """
    
    ... ... @@ -395,18 +410,18 @@ def update_toolbar(self):
    395 410
             app.plugin_manager.gui_extension_point(
    
    396 411
                 'chat_control_base_update_toolbar', self)
    
    397 412
     
    
    398
    -    def draw_banner_text(self):
    
    413
    +    def draw_banner_text(self) -> None:
    
    399 414
             """
    
    400 415
             Derived types SHOULD implement this
    
    401 416
             """
    
    402 417
     
    
    403
    -    def update_ui(self):
    
    418
    +    def update_ui(self) -> None:
    
    404 419
             """
    
    405 420
             Derived types SHOULD implement this
    
    406 421
             """
    
    407 422
             self.draw_banner()
    
    408 423
     
    
    409
    -    def repaint_themed_widgets(self):
    
    424
    +    def repaint_themed_widgets(self) -> None:
    
    410 425
             """
    
    411 426
             Derived types MAY implement this
    
    412 427
             """
    
    ... ... @@ -453,7 +468,7 @@ def remove_session(self, session):
    453 468
         def _nec_ping(self, obj):
    
    454 469
             raise NotImplementedError
    
    455 470
     
    
    456
    -    def setup_seclabel(self):
    
    471
    +    def setup_seclabel(self) -> None:
    
    457 472
             self.xml.label_selector.hide()
    
    458 473
             self.xml.label_selector.set_no_show_all(True)
    
    459 474
             lb = Gtk.ListStore(str)
    
    ... ... @@ -502,7 +517,7 @@ def delegate_action(self, action):
    502 517
                 return Gdk.EVENT_STOP
    
    503 518
     
    
    504 519
             if action == 'delete-line':
    
    505
    -            self.clear(self.msg_textview)
    
    520
    +            self.msg_textview.clear()
    
    506 521
                 return Gdk.EVENT_STOP
    
    507 522
     
    
    508 523
             if action == 'show-emoji-chooser':
    
    ... ... @@ -514,7 +529,7 @@ def delegate_action(self, action):
    514 529
     
    
    515 530
             return Gdk.EVENT_PROPAGATE
    
    516 531
     
    
    517
    -    def add_actions(self):
    
    532
    +    def add_actions(self) -> None:
    
    518 533
             action = Gio.SimpleAction.new_stateful(
    
    519 534
                 f'set-encryption-{self.control_id}',
    
    520 535
                 GLib.VariantType.new('s'),
    
    ... ... @@ -535,7 +550,7 @@ def add_actions(self):
    535 550
                 action.set_enabled(False)
    
    536 551
                 app.window.add_action(action)
    
    537 552
     
    
    538
    -    def remove_actions(self):
    
    553
    +    def remove_actions(self) -> None:
    
    539 554
             actions = [
    
    540 555
                 'send-message-',
    
    541 556
                 'set-encryption-',
    
    ... ... @@ -547,7 +562,7 @@ def remove_actions(self):
    547 562
             for action in actions:
    
    548 563
                 app.window.remove_action(f'{action}{self.control_id}')
    
    549 564
     
    
    550
    -    def mark_as_read(self, send_marker=True):
    
    565
    +    def mark_as_read(self, send_marker: bool = True) -> None:
    
    551 566
             self._jump_to_end_button.reset_unread_count()
    
    552 567
     
    
    553 568
             if send_marker:
    
    ... ... @@ -576,7 +591,7 @@ def change_encryption(self, action, param):
    576 591
             self.set_encryption_menu_icon()
    
    577 592
             self.set_lock_image()
    
    578 593
     
    
    579
    -    def set_lock_image(self):
    
    594
    +    def set_lock_image(self) -> None:
    
    580 595
             encryption_state = {'visible': self.encryption is not None,
    
    581 596
                                 'enc_type': self.encryption,
    
    582 597
                                 'authenticated': False}
    
    ... ... @@ -621,7 +636,7 @@ def get_encryption_state(self):
    621 636
                 return None
    
    622 637
             return state
    
    623 638
     
    
    624
    -    def set_encryption_menu_icon(self):
    
    639
    +    def set_encryption_menu_icon(self) -> None:
    
    625 640
             image = self.xml.encryption_menu.get_image()
    
    626 641
             if image is None:
    
    627 642
                 image = Gtk.Image()
    
    ... ... @@ -633,7 +648,7 @@ def set_encryption_menu_icon(self):
    633 648
                 image.set_from_icon_name('channel-secure-symbolic',
    
    634 649
                                          Gtk.IconSize.MENU)
    
    635 650
     
    
    636
    -    def set_speller(self):
    
    651
    +    def set_speller(self) -> None:
    
    637 652
             if (not app.is_installed('GSPELL') or
    
    638 653
                     not app.settings.get('use_speller')):
    
    639 654
                 return
    
    ... ... @@ -649,7 +664,7 @@ def set_speller(self):
    649 664
     
    
    650 665
             spell_checker.connect('notify::language', self.on_language_changed)
    
    651 666
     
    
    652
    -    def get_speller_language(self):
    
    667
    +    def get_speller_language(self) -> Optional[Gspell.Language]:
    
    653 668
             lang = self.contact.settings.get('speller_language')
    
    654 669
             if not lang:
    
    655 670
                 # use the default one
    
    ... ... @@ -665,7 +680,7 @@ def on_language_changed(self, checker, _param):
    665 680
             gspell_lang = checker.get_language()
    
    666 681
             self.contact.settings.set('speller_language', gspell_lang.get_code())
    
    667 682
     
    
    668
    -    def shutdown(self):
    
    683
    +    def shutdown(self) -> None:
    
    669 684
             # remove_gui_extension_point() is called on shutdown, but also when
    
    670 685
             # a plugin is getting disabled. Plugins don’t know the difference.
    
    671 686
             # Plugins might want to remove their widgets on
    
    ... ... @@ -763,17 +778,24 @@ def _on_message_textview_paste_event(self, _texview):
    763 778
                                        callback=self._paste_event_confirmed,
    
    764 779
                                        args=[image])]).show()
    
    765 780
     
    
    766
    -    def _paste_event_confirmed(self, is_checked, image):
    
    781
    +    def _paste_event_confirmed(self,
    
    782
    +                               is_checked: bool,
    
    783
    +                               image: Optional[GdkPixbuf.Pixbuf]
    
    784
    +                               ) -> None:
    
    767 785
             if is_checked:
    
    768 786
                 app.settings.set('confirm_paste_image', False)
    
    769 787
     
    
    770 788
             dir_ = tempfile.gettempdir()
    
    771 789
             path = os.path.join(dir_, f'{uuid.uuid4()}.png')
    
    790
    +        if image is None:
    
    791
    +            self.add_info_message(_('Error: Could not process image'))
    
    792
    +            return
    
    793
    +
    
    772 794
             image.savev(path, 'png', [], [])
    
    773 795
     
    
    774 796
             self._start_filetransfer(path)
    
    775 797
     
    
    776
    -    def _get_pref_ft_method(self):
    
    798
    +    def _get_pref_ft_method(self) -> Optional[str]:
    
    777 799
             ft_pref = app.settings.get_account_setting(self.account,
    
    778 800
                                                        'filetransfer_preference')
    
    779 801
             httpupload = app.window.lookup_action(
    
    ... ... @@ -1006,12 +1028,13 @@ def _on_send_message(self, *args):
    1006 1028
             self.send_message(message, xhtml=xhtml)
    
    1007 1029
     
    
    1008 1030
         def send_message(self,
    
    1009
    -                     message,
    
    1010
    -                     type_='chat',
    
    1011
    -                     resource=None,
    
    1012
    -                     xhtml=None,
    
    1013
    -                     process_commands=True,
    
    1014
    -                     attention=False):
    
    1031
    +                     message: str,
    
    1032
    +                     type_: str = 'chat',
    
    1033
    +                     resource: Optional[str] = None,
    
    1034
    +                     xhtml: Optional[str] = None,
    
    1035
    +                     process_commands: bool = True,
    
    1036
    +                     attention: bool = False
    
    1037
    +                     ) -> None:
    
    1015 1038
             """
    
    1016 1039
             Send the given message to the active tab. Doesn't return None if error
    
    1017 1040
             """
    
    ... ... @@ -1023,6 +1046,7 @@ def send_message(self,
    1023 1046
     
    
    1024 1047
             label = self.get_seclabel()
    
    1025 1048
     
    
    1049
    +        correct_id: Optional[str] = None
    
    1026 1050
             if self.correcting and self.last_sent_msg:
    
    1027 1051
                 correct_id = self.last_sent_msg
    
    1028 1052
             else:
    
    ... ... @@ -1073,7 +1097,7 @@ def _on_message_tv_buffer_changed(self, textbuffer):
    1073 1097
             self._client.get_module('Chatstate').set_chatstate(
    
    1074 1098
                 self.contact, Chatstate.COMPOSING)
    
    1075 1099
     
    
    1076
    -    def save_message(self, message, msg_type):
    
    1100
    +    def save_message(self, message: str, msg_type: str) -> None:
    
    1077 1101
             # save the message, so user can scroll though the list with key up/down
    
    1078 1102
             if msg_type == 'sent':
    
    1079 1103
                 history = self.sent_history
    
    ... ... @@ -1099,10 +1123,10 @@ def save_message(self, message, msg_type):
    1099 1123
             else:
    
    1100 1124
                 self.received_history_pos = pos
    
    1101 1125
     
    
    1102
    -    def add_info_message(self, text):
    
    1126
    +    def add_info_message(self, text: str) -> None:
    
    1103 1127
             self.conversation_view.add_info_message(text)
    
    1104 1128
     
    
    1105
    -    def add_file_transfer(self, transfer):
    
    1129
    +    def add_file_transfer(self, transfer: HTTPFileTransfer) -> None:
    
    1106 1130
             self.conversation_view.add_file_transfer(transfer)
    
    1107 1131
     
    
    1108 1132
         def add_jingle_file_transfer(self, event):
    
    ... ... @@ -1118,16 +1142,17 @@ def add_call_message(self, event):
    1118 1142
                 self.conversation_view.add_call_message(event=event)
    
    1119 1143
     
    
    1120 1144
         def add_message(self,
    
    1121
    -                    text,
    
    1122
    -                    kind,
    
    1123
    -                    name,
    
    1124
    -                    tim,
    
    1125
    -                    notify,
    
    1126
    -                    displaymarking=None,
    
    1127
    -                    msg_log_id=None,
    
    1128
    -                    message_id=None,
    
    1129
    -                    stanza_id=None,
    
    1130
    -                    additional_data=None):
    
    1145
    +                    text: str,
    
    1146
    +                    kind: str,
    
    1147
    +                    name: str,
    
    1148
    +                    tim: float,
    
    1149
    +                    notify: bool,
    
    1150
    +                    displaymarking: Optional[Displaymarking] = None,
    
    1151
    +                    msg_log_id: Optional[str] = None,
    
    1152
    +                    message_id: Optional[str] = None,
    
    1153
    +                    stanza_id: Optional[str]  =None,
    
    1154
    +                    additional_data: Optional[AdditionalDataDict] = None
    
    1155
    +                    ) -> None:
    
    1131 1156
     
    
    1132 1157
             if additional_data is None:
    
    1133 1158
                 additional_data = AdditionalDataDict()
    
    ... ... @@ -1174,8 +1199,12 @@ def add_message(self,
    1174 1199
                 if chat_active and self._scrolled_view.get_autoscroll():
    
    1175 1200
                     app.window.mark_as_read(self.account, self.contact.jid)
    
    1176 1201
     
    
    1177
    -    def _notify(self, name: str, text: str, tim: Optional[int],
    
    1178
    -                additional_data: AdditionalDataDict) -> None:
    
    1202
    +    def _notify(self,
    
    1203
    +                name: str,
    
    1204
    +                text: str,
    
    1205
    +                tim: Optional[float],
    
    1206
    +                additional_data: AdditionalDataDict
    
    1207
    +                ) -> None:
    
    1179 1208
             if app.window.is_chat_active(self.account, self.contact.jid):
    
    1180 1209
                 if self._scrolled_view.get_autoscroll():
    
    1181 1210
                     return
    
    ... ... @@ -1192,6 +1221,7 @@ def _notify(self, name: str, text: str, tim: Optional[int],
    1192 1221
                     _icon, file_type = guess_simple_file_type(text)
    
    1193 1222
                     text = f'{file_type} ({file_name})'
    
    1194 1223
     
    
    1224
    +        sound: Optional[str] = None
    
    1195 1225
             if self.is_chat:
    
    1196 1226
                 msg_type = 'chat-message'
    
    1197 1227
                 sound = 'first_message_received'
    
    ... ... @@ -1205,6 +1235,7 @@ def _notify(self, name: str, text: str, tim: Optional[int],
    1205 1235
                     sound = 'muc_message_highlight'
    
    1206 1236
                 else:
    
    1207 1237
                     sound = 'muc_message_received'
    
    1238
    +
    
    1208 1239
                 if not self.contact.can_notify():
    
    1209 1240
                     sound = None
    
    1210 1241
     
    
    ... ... @@ -1234,7 +1265,7 @@ def _notify(self, name: str, text: str, tim: Optional[int],
    1234 1265
                              text=text,
    
    1235 1266
                              sound=sound))
    
    1236 1267
     
    
    1237
    -    def toggle_emoticons(self):
    
    1268
    +    def toggle_emoticons(self) -> None:
    
    1238 1269
             """
    
    1239 1270
             Hide show emoticons_button
    
    1240 1271
             """
    
    ... ... @@ -1245,7 +1276,7 @@ def toggle_emoticons(self):
    1245 1276
                 self.xml.emoticons_button.set_no_show_all(True)
    
    1246 1277
                 self.xml.emoticons_button.hide()
    
    1247 1278
     
    
    1248
    -    def set_emoticon_popover(self):
    
    1279
    +    def set_emoticon_popover(self) -> None:
    
    1249 1280
             if not app.settings.get('emoticons_theme'):
    
    1250 1281
                 return
    
    1251 1282
     
    
    ... ... @@ -1295,7 +1326,7 @@ def clear(tv):
    1295 1326
             start, end = buffer_.get_bounds()
    
    1296 1327
             buffer_.delete(start, end)
    
    1297 1328
     
    
    1298
    -    def set_control_active(self, state):
    
    1329
    +    def set_control_active(self, state: bool) -> None:
    
    1299 1330
             if state:
    
    1300 1331
                 self.set_emoticon_popover()
    
    1301 1332
     
    
    ... ... @@ -1309,19 +1340,19 @@ def set_control_active(self, state):
    1309 1340
                 self._client.get_module('Chatstate').set_chatstate(
    
    1310 1341
                     self.contact, Chatstate.INACTIVE)
    
    1311 1342
     
    
    1312
    -    def reset_view(self):
    
    1343
    +    def reset_view(self) -> None:
    
    1313 1344
             self.conversation_view.clear()
    
    1314 1345
     
    
    1315
    -    def get_autoscroll(self):
    
    1346
    +    def get_autoscroll(self) -> bool:
    
    1316 1347
             return self._scrolled_view.get_autoscroll()
    
    1317 1348
     
    
    1318
    -    def scroll_to_end(self, force=False):
    
    1349
    +    def scroll_to_end(self, force: bool = False) -> None:
    
    1319 1350
             # Clear view and reload conversation
    
    1320 1351
             self.conversation_view.clear()
    
    1321 1352
             self._scrolled_view.reset()
    
    1322 1353
             self.conversation_view.scroll_to_end(force)
    
    1323 1354
     
    
    1324
    -    def scroll_to_message(self, log_line_id, timestamp):
    
    1355
    +    def scroll_to_message(self, log_line_id: str, timestamp: float) -> None:
    
    1325 1356
             row = self.conversation_view.get_row_by_log_line_id(log_line_id)
    
    1326 1357
             if row is None:
    
    1327 1358
                 # Clear view and reload conversation around timestamp
    
    ... ... @@ -1338,7 +1369,11 @@ def scroll_to_message(self, log_line_id, timestamp):
    1338 1369
                 log_line_id)
    
    1339 1370
             GLib.idle_add(self.conversation_view.unlock)
    
    1340 1371
     
    
    1341
    -    def fetch_n_lines_history(self, _scrolled, before, n_lines):
    
    1372
    +    def fetch_n_lines_history(self,
    
    1373
    +                              _scrolled: Gtk.ScrolledWindow,
    
    1374
    +                              before: bool,
    
    1375
    +                              n_lines: int
    
    1376
    +                              ) -> None:
    
    1342 1377
             if self.conversation_view.locked:
    
    1343 1378
                 return
    
    1344 1379
     
    
    ... ... @@ -1436,13 +1471,17 @@ def add_messages(self, messages):
    1436 1471
                     marker=msg.marker,
    
    1437 1472
                     error=msg.error)
    
    1438 1473
     
    
    1439
    -    def has_focus(self):
    
    1474
    +    def has_focus(self) -> bool:
    
    1440 1475
             if app.window.get_property('has-toplevel-focus'):
    
    1441 1476
                 if self == app.window.get_active_control():
    
    1442 1477
                     return True
    
    1443 1478
             return False
    
    1444 1479
     
    
    1445
    -    def scroll_messages(self, direction, msg_buf, msg_type):
    
    1480
    +    def scroll_messages(self,
    
    1481
    +                        direction: str,
    
    1482
    +                        msg_buf: Gtk.TextBuffer,
    
    1483
    +                        msg_type: str,
    
    1484
    +                        ) -> None:
    
    1446 1485
             if msg_type == 'sent':
    
    1447 1486
                 history = self.sent_history
    
    1448 1487
                 pos = self.sent_history_pos
    
    ... ... @@ -1490,7 +1529,7 @@ def scroll_messages(self, direction, msg_buf, msg_type):
    1490 1529
                     message = '> %s\n' % message.replace('\n', '\n> ')
    
    1491 1530
             msg_buf.set_text(message)
    
    1492 1531
     
    
    1493
    -    def update_account_badge(self):
    
    1532
    +    def update_account_badge(self) -> None:
    
    1494 1533
             show = len(app.settings.get_active_accounts()) > 1
    
    1495 1534
             self.xml.account_badge_box.set_visible(show)
    
    1496 1535
     
    

  • gajim/gtk/controls/chat.py
    ... ... @@ -25,6 +25,7 @@
    25 25
     
    
    26 26
     from typing import ClassVar  # pylint: disable=unused-import
    
    27 27
     from typing import Type  # pylint: disable=unused-import
    
    28
    +from typing import Optional
    
    28 29
     
    
    29 30
     import time
    
    30 31
     import logging
    
    ... ... @@ -34,8 +35,10 @@
    34 35
     from gi.repository import GLib
    
    35 36
     from gi.repository import Gdk
    
    36 37
     
    
    37
    -from nbxmpp.namespaces import Namespace
    
    38
    +from nbxmpp import JID
    
    38 39
     from nbxmpp.const import Chatstate
    
    40
    +from nbxmpp.modules.security_labels import Displaymarking
    
    41
    +from nbxmpp.namespaces import Namespace
    
    39 42
     
    
    40 43
     from gajim.common import app
    
    41 44
     from gajim.common import helpers
    
    ... ... @@ -80,14 +83,17 @@ class ChatControl(BaseControl):
    80 83
         # processed with this command host.
    
    81 84
         COMMAND_HOST = ChatCommands  # type: ClassVar[Type[CommandHost]]
    
    82 85
     
    
    83
    -    def __init__(self, account, jid):
    
    86
    +    def __init__(self, account: str, jid: JID) -> None:
    
    84 87
             BaseControl.__init__(self,
    
    85 88
                                  'chat_control',
    
    86 89
                                  account,
    
    87 90
                                  jid)
    
    88 91
     
    
    89
    -        self.last_recv_message_id = None
    
    90
    -        self.last_recv_message_marks = None
    
    92
    +        self.sendmessage: bool = True
    
    93
    +
    
    94
    +        # XEP-0308 Message Correction
    
    95
    +        self.correcting: bool = False
    
    96
    +        self.last_sent_msg: Optional[str] = None
    
    91 97
     
    
    92 98
             self.toggle_emoticons()
    
    93 99
     
    
    ... ... @@ -147,7 +153,7 @@ def __init__(self, account, jid):
    147 153
             app.plugin_manager.gui_extension_point('chat_control', self)
    
    148 154
             self.update_actions()
    
    149 155
     
    
    150
    -    def _connect_contact_signals(self):
    
    156
    +    def _connect_contact_signals(self) -> None:
    
    151 157
             self.contact.multi_connect({
    
    152 158
                 'presence-update': self._on_presence_update,
    
    153 159
                 'chatstate-update': self._on_chatstate_update,
    
    ... ... @@ -157,10 +163,10 @@ def _connect_contact_signals(self):
    157 163
             })
    
    158 164
     
    
    159 165
         @property
    
    160
    -    def jid(self):
    
    166
    +    def jid(self) -> JID:
    
    161 167
             return self.contact.jid
    
    162 168
     
    
    163
    -    def add_actions(self):
    
    169
    +    def add_actions(self) -> None:
    
    164 170
             super().add_actions()
    
    165 171
             actions = [
    
    166 172
                 ('invite-contacts-', self._on_invite_contacts),
    
    ... ... @@ -194,7 +200,7 @@ def add_actions(self):
    194 200
             act.connect('change-state', self._on_send_marker)
    
    195 201
             app.window.add_action(act)
    
    196 202
     
    
    197
    -    def update_actions(self):
    
    203
    +    def update_actions(self) -> None:
    
    198 204
             online = app.account_is_connected(self.account)
    
    199 205
     
    
    200 206
             if self.type.is_chat:
    
    ... ... @@ -254,7 +260,7 @@ def update_actions(self):
    254 260
             # Information
    
    255 261
             self._get_action('information-').set_enabled(online)
    
    256 262
     
    
    257
    -    def remove_actions(self):
    
    263
    +    def remove_actions(self) -> None:
    
    258 264
             super().remove_actions()
    
    259 265
             actions = [
    
    260 266
                 'invite-contacts-',
    
    ... ... @@ -268,7 +274,7 @@ def remove_actions(self):
    268 274
             for action in actions:
    
    269 275
                 app.window.remove_action(f'{action}{self.control_id}')
    
    270 276
     
    
    271
    -    def focus(self):
    
    277
    +    def focus(self) -> None:
    
    272 278
             self.msg_textview.grab_focus()
    
    273 279
     
    
    274 280
         def delegate_action(self, action):
    
    ... ... @@ -307,7 +313,7 @@ def _on_send_marker(self, action, param):
    307 313
             action.set_state(param)
    
    308 314
             self.contact.settings.set('send_marker', param.get_boolean())
    
    309 315
     
    
    310
    -    def _update_toolbar(self):
    
    316
    +    def _update_toolbar(self) -> None:
    
    311 317
             # Formatting
    
    312 318
             # TODO: find out what encryption allows for xhtml and which not
    
    313 319
             if self.contact.supports(Namespace.XHTML_IM):
    
    ... ... @@ -319,13 +325,13 @@ def _update_toolbar(self):
    319 325
                 self.xml.formattings_button.set_tooltip_text(
    
    320 326
                     _('This contact does not support HTML'))
    
    321 327
     
    
    322
    -    def update_all_pep_types(self):
    
    328
    +    def update_all_pep_types(self) -> None:
    
    323 329
             self._update_pep(PEPEventType.LOCATION)
    
    324 330
             self._update_pep(PEPEventType.MOOD)
    
    325 331
             self._update_pep(PEPEventType.ACTIVITY)
    
    326 332
             self._update_pep(PEPEventType.TUNE)
    
    327 333
     
    
    328
    -    def _update_pep(self, type_):
    
    334
    +    def _update_pep(self, type_: PEPEventType) -> None:
    
    329 335
             return
    
    330 336
             # TODO
    
    331 337
             image = self._get_pep_widget(type_)
    
    ... ... @@ -351,7 +357,7 @@ def _update_pep(self, type_):
    351 357
             image.set_tooltip_markup(formated_text)
    
    352 358
             image.show()
    
    353 359
     
    
    354
    -    def _get_pep_widget(self, type_):
    
    360
    +    def _get_pep_widget(self, type_: PEPEventType) -> Optional[Gtk.Image]:
    
    355 361
             if type_ == PEPEventType.MOOD:
    
    356 362
                 return self.xml.mood_image
    
    357 363
             if type_ == PEPEventType.ACTIVITY:
    
    ... ... @@ -488,7 +494,7 @@ def _nec_ping(self, event):
    488 494
                 self.add_info_message(event.error)
    
    489 495
     
    
    490 496
         # Jingle AV calls
    
    491
    -    def _on_start_call(self):
    
    497
    +    def _on_start_call(self) -> None:
    
    492 498
             self._call_widget.start_call()
    
    493 499
     
    
    494 500
         def _process_jingle_av_event(self, event):
    
    ... ... @@ -527,14 +533,14 @@ def on_location_eventbox_enter_notify_event(self, _widget, _event):
    527 533
             cursor = get_cursor('pointer')
    
    528 534
             app.window.get_window().set_cursor(cursor)
    
    529 535
     
    
    530
    -    def update_ui(self):
    
    536
    +    def update_ui(self) -> None:
    
    531 537
             # The name banner is drawn here
    
    532 538
             BaseControl.update_ui(self)
    
    533 539
             self.update_toolbar()
    
    534 540
             self._update_avatar()
    
    535 541
             self.update_actions()
    
    536 542
     
    
    537
    -    def draw_banner_text(self):
    
    543
    +    def draw_banner_text(self) -> None:
    
    538 544
             """
    
    539 545
             Draws the chat banner's text (e.g. name, chat state) in the top of the
    
    540 546
             chat window
    
    ... ... @@ -572,10 +578,11 @@ def draw_banner_text(self):
    572 578
             self.xml.banner_name_label.set_tooltip_text(label_tooltip)
    
    573 579
     
    
    574 580
         def send_message(self,
    
    575
    -                     message,
    
    576
    -                     xhtml=None,
    
    577
    -                     process_commands=True,
    
    578
    -                     attention=False):
    
    581
    +                     message: str,
    
    582
    +                     xhtml: Optional[str] = None,
    
    583
    +                     process_commands: bool = True,
    
    584
    +                     attention: bool = False
    
    585
    +                     ) -> None:
    
    579 586
             """
    
    580 587
             Send a message to contact
    
    581 588
             """
    
    ... ... @@ -598,19 +605,20 @@ def send_message(self,
    598 605
                                      process_commands=process_commands,
    
    599 606
                                      attention=attention)
    
    600 607
     
    
    601
    -    def get_our_nick(self):
    
    608
    +    def get_our_nick(self) -> str:
    
    602 609
             return app.nicks[self.account]
    
    603 610
     
    
    604 611
         def add_message(self,
    
    605
    -                    text,
    
    606
    -                    kind,
    
    607
    -                    tim=None,
    
    608
    -                    displaymarking=None,
    
    609
    -                    msg_log_id=None,
    
    610
    -                    stanza_id=None,
    
    611
    -                    message_id=None,
    
    612
    -                    additional_data=None,
    
    613
    -                    notify=True):
    
    612
    +                    text: str,
    
    613
    +                    kind: str,
    
    614
    +                    tim: Optional[float] = None,
    
    615
    +                    displaymarking: Optional[Displaymarking] = None,
    
    616
    +                    msg_log_id: Optional[str] = None,
    
    617
    +                    stanza_id: Optional[str] = None,
    
    618
    +                    message_id: Optional[str] = None,
    
    619
    +                    additional_data: Optional[AdditionalDataDict] = None,
    
    620
    +                    notify: bool = True
    
    621
    +                    ) -> None:
    
    614 622
     
    
    615 623
             if additional_data is None:
    
    616 624
                 additional_data = AdditionalDataDict()
    
    ... ... @@ -632,7 +640,7 @@ def add_message(self,
    632 640
                                     stanza_id=stanza_id,
    
    633 641
                                     additional_data=additional_data)
    
    634 642
     
    
    635
    -    def shutdown(self):
    
    643
    +    def shutdown(self) -> None:
    
    636 644
             # PluginSystem: removing GUI extension points connected with ChatControl
    
    637 645
             # instance object
    
    638 646
             app.plugin_manager.remove_gui_extension_point('chat_control', self)
    
    ... ... @@ -682,7 +690,7 @@ def allow_shutdown(self, _method, on_yes, on_no):
    682 690
         def _on_avatar_update(self, _contact, _signal_name):
    
    683 691
             self._update_avatar()
    
    684 692
     
    
    685
    -    def _update_avatar(self):
    
    693
    +    def _update_avatar(self) -> None:
    
    686 694
             scale = app.window.get_scale_factor()
    
    687 695
             surface = self.contact.get_avatar(AvatarSize.CHAT, scale)
    
    688 696
             self.xml.avatar_image.set_from_surface(surface)
    

  • gajim/gtk/controls/groupchat.py
    ... ... @@ -24,15 +24,21 @@
    24 24
     # You should have received a copy of the GNU General Public License
    
    25 25
     # along with Gajim. If not, see <http://www.gnu.org/licenses/>.
    
    26 26
     
    
    27
    +from typing import Any
    
    28
    +from typing import List
    
    29
    +from typing import Optional
    
    30
    +
    
    27 31
     import time
    
    28 32
     import logging
    
    29 33
     
    
    34
    +from nbxmpp import JID
    
    30 35
     from nbxmpp.namespaces import Namespace
    
    31 36
     from nbxmpp.protocol import InvalidJid
    
    32 37
     from nbxmpp.protocol import validate_resourcepart
    
    33 38
     from nbxmpp.const import StatusCode
    
    34 39
     from nbxmpp.const import Affiliation
    
    35 40
     from nbxmpp.errors import StanzaError
    
    41
    +from nbxmpp.modules.security_labels import Displaymarking
    
    36 42
     from nbxmpp.modules.vcard_temp import VCard
    
    37 43
     
    
    38 44
     from gi.repository import Gtk
    
    ... ... @@ -46,6 +52,7 @@
    46 52
     from gajim.common import app
    
    47 53
     from gajim.common import ged
    
    48 54
     from gajim.common import helpers
    
    55
    +from gajim.common.helpers import AdditionalDataDict
    
    49 56
     from gajim.common.helpers import event_filter
    
    50 57
     from gajim.common.helpers import to_user_string
    
    51 58
     from gajim.common.const import AvatarSize
    
    ... ... @@ -86,7 +93,7 @@ class GroupchatControl(BaseControl):
    86 93
         # will be processed with this command host.
    
    87 94
         COMMAND_HOST = GroupChatCommands
    
    88 95
     
    
    89
    -    def __init__(self, account, jid):
    
    96
    +    def __init__(self, account: str, jid: JID) -> None:
    
    90 97
             BaseControl.__init__(self,
    
    91 98
                                  'groupchat_control',
    
    92 99
                                  account,
    
    ... ... @@ -95,23 +102,27 @@ def __init__(self, account, jid):
    95 102
             self._client.connect_signal('state-changed',
    
    96 103
                                         self._on_client_state_changed)
    
    97 104
     
    
    98
    -        self.is_anonymous = True
    
    105
    +        self.is_anonymous: bool = True
    
    99 106
     
    
    100 107
             self.toggle_emoticons()
    
    101 108
     
    
    102
    -        self.room_jid = str(self.contact.jid)
    
    109
    +        self.room_jid: str = str(self.contact.jid)
    
    103 110
     
    
    104 111
             # Stores nickname we want to kick
    
    105
    -        self._kick_nick = None
    
    112
    +        self._kick_nick: Optional[str] = None
    
    106 113
     
    
    107 114
             # Stores nickname we want to ban
    
    108
    -        self._ban_jid = None
    
    115
    +        self._ban_jid: Optional[str] = None
    
    109 116
     
    
    110 117
             # Last sent message text
    
    111
    -        self.last_sent_txt = ''
    
    118
    +        self.last_sent_txt: str = ''
    
    112 119
     
    
    113 120
             # Attribute, encryption plugins use to signal the message can be sent
    
    114
    -        self.sendmessage = False
    
    121
    +        self.sendmessage: bool = False
    
    122
    +
    
    123
    +        # XEP-0308 Message Correction
    
    124
    +        self.correcting: bool = False
    
    125
    +        self.last_sent_msg: Optional[str] = None
    
    115 126
     
    
    116 127
             self.roster = GroupchatRoster(self.account, self.room_jid, self)
    
    117 128
             self.xml.roster_revealer.add(self.roster)
    
    ... ... @@ -126,13 +137,13 @@ def __init__(self, account, jid):
    126 137
     
    
    127 138
             # muc attention flag (when we are mentioned in a muc)
    
    128 139
             # if True, the room has mentioned us
    
    129
    -        self.attention_flag = False
    
    140
    +        self.attention_flag: bool = False
    
    130 141
     
    
    131 142
             # sorted list of nicks who mentioned us (last at the end)
    
    132
    -        self.attention_list = []
    
    133
    -        self.nick_hits = []
    
    134
    -        self.__nick_completion = None
    
    135
    -        self.last_key_tabs = False
    
    143
    +        self.attention_list: List[str] = []
    
    144
    +        self.nick_hits: List[str] = []
    
    145
    +        self.__nick_completion: Optional[NickCompletionGenerator] = None
    
    146
    +        self.last_key_tabs: bool = False
    
    136 147
     
    
    137 148
             self.setup_seclabel()
    
    138 149
     
    
    ... ... @@ -158,7 +169,7 @@ def __init__(self, account, jid):
    158 169
             self._update_avatar()
    
    159 170
     
    
    160 171
             # Holds CaptchaRequest widget
    
    161
    -        self._captcha_request = None
    
    172
    +        self._captcha_request: Optional[DataFormWidget] = None
    
    162 173
     
    
    163 174
             # MUC Info
    
    164 175
             self._subject_data = None
    
    ... ... @@ -166,7 +177,7 @@ def __init__(self, account, jid):
    166 177
             self.xml.info_box.add(self._muc_info_box)
    
    167 178
     
    
    168 179
             # Groupchat settings
    
    169
    -        self._groupchat_settings_box = None
    
    180
    +        self._groupchat_settings_box: Optional[GroupChatSettings] = None
    
    170 181
     
    
    171 182
             # Groupchat invite
    
    172 183
             self.xml.quick_invite_button.set_action_name(
    
    ... ... @@ -211,7 +222,7 @@ def __init__(self, account, jid):
    211 222
             # instance object
    
    212 223
             app.plugin_manager.gui_extension_point('groupchat_control', self)
    
    213 224
     
    
    214
    -    def _connect_contact_signals(self):
    
    225
    +    def _connect_contact_signals(self) -> None:
    
    215 226
             self.contact.multi_connect({
    
    216 227
                 'state-changed': self._on_muc_state_changed,
    
    217 228
                 'avatar-update': self._on_avatar_update,
    
    ... ... @@ -260,7 +271,7 @@ def _nick_completion(self):
    260 271
             return self.__nick_completion
    
    261 272
     
    
    262 273
         @property
    
    263
    -    def subject(self):
    
    274
    +    def subject(self) -> str:
    
    264 275
             if self._subject_data is None:
    
    265 276
                 return ''
    
    266 277
             return self._subject_data.subject
    
    ... ... @@ -269,7 +280,7 @@ def subject(self):
    269 280
         def disco_info(self):
    
    270 281
             return app.storage.cache.get_last_disco_info(self.contact.jid)
    
    271 282
     
    
    272
    -    def add_actions(self):
    
    283
    +    def add_actions(self) -> None:
    
    273 284
             super().add_actions()
    
    274 285
             actions = [
    
    275 286
                 ('groupchat-settings-', None, self._on_groupchat_settings),
    
    ... ... @@ -368,7 +379,7 @@ def update_actions(self, *args):
    368 379
     
    
    369 380
             self._get_action('kick-').set_enabled(joined)
    
    370 381
     
    
    371
    -    def remove_actions(self):
    
    382
    +    def remove_actions(self) -> None:
    
    372 383
             super().remove_actions()
    
    373 384
             actions = [
    
    374 385
                 'groupchat-settings-',
    
    ... ... @@ -398,7 +409,7 @@ def is_irc(self) -> bool:
    398 409
                 return False
    
    399 410
             return self.disco_info.is_irc
    
    400 411
     
    
    401
    -    def _is_subject_change_allowed(self):
    
    412
    +    def _is_subject_change_allowed(self) -> Optional[Any]:
    
    402 413
             contact = self.contact.get_self()
    
    403 414
             if contact is None:
    
    404 415
                 return False
    
    ... ... @@ -410,7 +421,7 @@ def _is_subject_change_allowed(self):
    410 421
                 return False
    
    411 422
             return self.disco_info.muc_subjectmod or False
    
    412 423
     
    
    413
    -    def _show_page(self, name):
    
    424
    +    def _show_page(self, name: str) -> None:
    
    414 425
             transition = Gtk.StackTransitionType.SLIDE_DOWN
    
    415 426
             if name == 'groupchat':
    
    416 427
                 transition = Gtk.StackTransitionType.SLIDE_UP
    
    ... ... @@ -422,7 +433,7 @@ def _show_page(self, name):
    422 433
                 self.xml.info_close_button.grab_focus()
    
    423 434
             self.xml.stack.set_visible_child_full(name, transition)
    
    424 435
     
    
    425
    -    def _get_current_page(self):
    
    436
    +    def _get_current_page(self) -> str:
    
    426 437
             return self.xml.stack.get_visible_child_name()
    
    427 438
     
    
    428 439
         def _on_muc_disco_update(self, _event):
    
    ... ... @@ -624,11 +635,11 @@ def _on_roster_row_activated(self, _roster, nick):
    624 635
         def _on_avatar_update(self, _contact, _signal_name):
    
    625 636
             self._update_avatar()
    
    626 637
     
    
    627
    -    def _update_avatar(self):
    
    638
    +    def _update_avatar(self) -> None:
    
    628 639
             surface = self.contact.get_avatar(AvatarSize.CHAT, self.scale_factor)
    
    629 640
             self.xml.avatar_image.set_from_surface(surface)
    
    630 641
     
    
    631
    -    def draw_banner_text(self):
    
    642
    +    def draw_banner_text(self) -> None:
    
    632 643
             """
    
    633 644
             Draw the text in the fat line at the top of the window that houses the
    
    634 645
             room jid
    
    ... ... @@ -702,14 +713,15 @@ def _on_gc_message_received(self, event):
    702 713
                 self._client.get_own_jid().bare)
    
    703 714
     
    
    704 715
         def add_message(self,
    
    705
    -                    text,
    
    706
    -                    contact='',
    
    707
    -                    tim=None,
    
    708
    -                    displaymarking=None,
    
    709
    -                    message_id=None,
    
    710
    -                    stanza_id=None,
    
    711
    -                    additional_data=None,
    
    712
    -                    notify=True):
    
    716
    +                    text: str,
    
    717
    +                    contact: str = '',
    
    718
    +                    tim: Optional[float] = None,
    
    719
    +                    displaymarking: Optional[Displaymarking] = None,
    
    720
    +                    message_id: Optional[str] = None,
    
    721
    +                    stanza_id: Optional[str] = None,
    
    722
    +                    additional_data: Optional[AdditionalDataDict] = None,
    
    723
    +                    notify: bool = True
    
    724
    +                    ) -> None:
    
    713 725
     
    
    714 726
             if contact == self.contact.nickname:
    
    715 727
                 kind = 'outgoing'
    
    ... ... @@ -809,7 +821,7 @@ def _nec_ping(self, event):
    809 821
             elif event.name == 'ping-error':
    
    810 822
                 self.add_info_message(event.error)
    
    811 823
     
    
    812
    -    def _set_control_active(self):
    
    824
    +    def _set_control_active(self) -> None:
    
    813 825
             self.xml.formattings_button.set_sensitive(True)
    
    814 826
             self.msg_textview.set_sensitive(True)
    
    815 827
             self.msg_textview.set_editable(True)
    
    ... ... @@ -822,7 +834,7 @@ def _set_control_active(self):
    822 834
     
    
    823 835
             self.update_actions()
    
    824 836
     
    
    825
    -    def _set_control_inactive(self):
    
    837
    +    def _set_control_inactive(self) -> None:
    
    826 838
             self.xml.formattings_button.set_sensitive(False)
    
    827 839
             self.msg_textview.set_sensitive(False)
    
    828 840
             self.msg_textview.set_editable(False)
    
    ... ... @@ -834,7 +846,7 @@ def _set_control_inactive(self):
    834 846
     
    
    835 847
             self.update_actions()
    
    836 848
     
    
    837
    -    def rejoin(self):
    
    849
    +    def rejoin(self) -> None:
    
    838 850
             self._client.get_module('MUC').join(self.room_jid)
    
    839 851
     
    
    840 852
         # def send_pm(self, nick, message=None):
    
    ... ... @@ -1115,7 +1127,11 @@ def _on_message_sent(self, event):
    1115 1127
                 self.msg_textview.get_style_context().remove_class(
    
    1116 1128
                     'gajim-msg-correcting')
    
    1117 1129
     
    
    1118
    -    def send_message(self, message, xhtml=None, process_commands=True):
    
    1130
    +    def send_message(self,
    
    1131
    +                     message: str,
    
    1132
    +                     xhtml: Optional[str] = None,
    
    1133
    +                     process_commands: bool = True
    
    1134
    +                     ) -> None:
    
    1119 1135
             """
    
    1120 1136
             Call this function to send our message
    
    1121 1137
             """
    
    ... ... @@ -1182,7 +1198,7 @@ def shutdown(self, reason=None):
    1182 1198
             super(GroupchatControl, self).shutdown()
    
    1183 1199
             app.check_finalize(self)
    
    1184 1200
     
    
    1185
    -    def safe_shutdown(self):
    
    1201
    +    def safe_shutdown(self) -> bool:
    
    1186 1202
             # whether to ask for confirmation before closing muc
    
    1187 1203
             if app.settings.get('confirm_close_muc') and self.contact.is_joined:
    
    1188 1204
                 return False
    
    ... ... @@ -1219,12 +1235,12 @@ def on_cancel(is_checked):
    1219 1235
     
    
    1220 1236
             on_yes(self)
    
    1221 1237
     
    
    1222
    -    def _close_control(self):
    
    1238
    +    def _close_control(self) -> None:
    
    1223 1239
             app.window.activate_action(
    
    1224 1240
                 'remove-chat',
    
    1225 1241
                 GLib.Variant('as', [self.account, str(self.room_jid)]))
    
    1226 1242
     
    
    1227
    -    def set_control_active(self, state):
    
    1243
    +    def set_control_active(self, state: bool) -> None:
    
    1228 1244
             self.attention_flag = False
    
    1229 1245
             BaseControl.set_control_active(self, state)
    
    1230 1246
     
    
    ... ... @@ -1396,7 +1412,7 @@ def delegate_action(self, action):
    1396 1412
     
    
    1397 1413
             return Gdk.EVENT_PROPAGATE
    
    1398 1414
     
    
    1399
    -    def focus(self):
    
    1415
    +    def focus(self) -> None:
    
    1400 1416
             page_name = self._get_current_page()
    
    1401 1417
             if page_name == 'groupchat':
    
    1402 1418
                 self.msg_textview.grab_focus()
    
    ... ... @@ -1547,7 +1563,7 @@ def _on_room_captcha_error(self, _contact, _signal_name, error):
    1547 1563
             self.xml.captcha_error_label.set_text(error_text)
    
    1548 1564
             self._show_page('captcha-error')
    
    1549 1565
     
    
    1550
    -    def _remove_captcha_request(self):
    
    1566
    +    def _remove_captcha_request(self) -> None:
    
    1551 1567
             if self._captcha_request is None:
    
    1552 1568
                 return
    
    1553 1569
             if self._captcha_request in self.xml.captcha_box.get_children():
    

  • gajim/gtk/controls/private.py
    ... ... @@ -24,6 +24,10 @@
    24 24
     # You should have received a copy of the GNU General Public License
    
    25 25
     # along with Gajim. If not, see <http://www.gnu.org/licenses/>.
    
    26 26
     
    
    27
    +from typing import Optional
    
    28
    +
    
    29
    +from nbxmpp import JID
    
    30
    +
    
    27 31
     from gajim.common import app
    
    28 32
     from gajim.common import helpers
    
    29 33
     from gajim.common.i18n import _
    
    ... ... @@ -43,7 +47,7 @@ class PrivateChatControl(ChatControl):
    43 47
         # will be processed with this command host.
    
    44 48
         COMMAND_HOST = PrivateChatCommands
    
    45 49
     
    
    46
    -    def __init__(self, account, jid):
    
    50
    +    def __init__(self, account: str, jid: JID) -> None:
    
    47 51
             self._client = app.get_client(account)
    
    48 52
             self._room_contact = self._client.get_module('Contacts').get_contact(
    
    49 53
                 jid.bare)
    
    ... ... @@ -53,7 +57,7 @@ def __init__(self, account, jid):
    53 57
             # self.register_events([
    
    54 58
             #     ('update-gc-avatar', ged.GUI1, self._on_update_gc_avatar),
    
    55 59
     
    
    56
    -    def _connect_contact_signals(self):
    
    60
    +    def _connect_contact_signals(self) -> None:
    
    57 61
             self.contact.multi_connect({
    
    58 62
                 'user-avatar-update': self._on_user_avatar_update,
    
    59 63
                 'user-joined': self._on_user_joined,
    
    ... ... @@ -68,10 +72,10 @@ def _connect_contact_signals(self):
    68 72
             })
    
    69 73
     
    
    70 74
         @property
    
    71
    -    def room_name(self):
    
    75
    +    def room_name(self) -> str:
    
    72 76
             return self._room_contact.name
    
    73 77
     
    
    74
    -    def get_our_nick(self):
    
    78
    +    def get_our_nick(self) -> str:
    
    75 79
             muc_data = self._client.get_module('MUC').get_muc_data(
    
    76 80
                 self._room_contact.jid)
    
    77 81
             return muc_data.nick
    
    ... ... @@ -136,8 +140,12 @@ def _on_room_joined(self, *args):
    136 140
                 return
    
    137 141
             self.got_connected()
    
    138 142
     
    
    139
    -    def send_message(self, message, xhtml=None, process_commands=True,
    
    140
    -                     attention=False):
    
    143
    +    def send_message(self,
    
    144
    +                     message: str,
    
    145
    +                     xhtml: Optional[str] = None,
    
    146
    +                     process_commands: bool = True,
    
    147
    +                     attention: bool = False
    
    148
    +                     ) -> None:
    
    141 149
             """
    
    142 150
             Call this method to send the message
    
    143 151
             """
    
    ... ... @@ -161,7 +169,7 @@ def send_message(self, message, xhtml=None, process_commands=True,
    161 169
                                      process_commands=process_commands,
    
    162 170
                                      attention=attention)
    
    163 171
     
    
    164
    -    def update_ui(self):
    
    172
    +    def update_ui(self) -> None:
    
    165 173
             ChatControl.update_ui(self)
    
    166 174
     
    
    167 175
         def _on_user_avatar_update(self, *args):
    

  • gajim/gtk/main.py
    ... ... @@ -14,6 +14,7 @@
    14 14
     from gajim.common import app
    
    15 15
     from gajim.common import ged
    
    16 16
     from gajim.common.const import Display
    
    17
    +from gajim.common.const import Direction
    
    17 18
     from gajim.common.helpers import ask_for_status_message
    
    18 19
     from gajim.common.i18n import _
    
    19 20
     from gajim.common.nec import EventHelper
    
    ... ... @@ -260,19 +261,19 @@ def _on_action(self, action, _param):
    260 261
             #     return None
    
    261 262
     
    
    262 263
             if action == 'switch-next-tab':
    
    263
    -            self.select_next_chat(True)
    
    264
    +            self.select_next_chat(Direction.NEXT)
    
    264 265
                 return None
    
    265 266
     
    
    266 267
             if action == 'switch-prev-tab':
    
    267
    -            self.select_next_chat(False)
    
    268
    +            self.select_next_chat(Direction.PREV)
    
    268 269
                 return None
    
    269 270
     
    
    270 271
             if action == 'switch-next-unread-tab-right':
    
    271
    -            self.select_next_chat(True, unread_first=True)
    
    272
    +            self.select_next_chat(Direction.NEXT, unread_first=True)
    
    272 273
                 return None
    
    273 274
     
    
    274 275
             if action == 'switch-next-unread-tab-left':
    
    275
    -            self.select_next_chat(False, unread_first=True)
    
    276
    +            self.select_next_chat(Direction.PREV, unread_first=True)
    
    276 277
                 return None
    
    277 278
     
    
    278 279
             if action.startswith('switch-tab-'):
    
    ... ... @@ -443,12 +444,12 @@ def select_chat(self, account: str, jid: JID) -> None:
    443 444
             self._main_stack.show_chat_page()
    
    444 445
             self._chat_page.select_chat(account, jid)
    
    445 446
     
    
    446
    -    def select_next_chat(self, forwards: bool,
    
    447
    +    def select_next_chat(self, direction: Direction,
    
    447 448
                              unread_first: bool = False) -> None:
    
    448 449
             chat_list_stack = self._chat_page.get_chat_list_stack()
    
    449 450
             chat_list = chat_list_stack.get_current_chat_list()
    
    450 451
             if chat_list is not None:
    
    451
    -            chat_list.select_next_chat(forwards, unread_first)
    
    452
    +            chat_list.select_next_chat(direction, unread_first)
    
    452 453
     
    
    453 454
         def select_chat_number(self, number: int) -> None:
    
    454 455
             chat_list_stack = self._chat_page.get_chat_list_stack()