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

Commits:

7 changed files:

Changes:

  • gajim/common/events.py
    ... ... @@ -12,6 +12,8 @@
    12 12
     # You should have received a copy of the GNU General Public License
    
    13 13
     # along with Gajim. If not, see <http://www.gnu.org/licenses/>.
    
    14 14
     
    
    15
    +from __future__ import annotations
    
    16
    +
    
    15 17
     import typing
    
    16 18
     from typing import Any
    
    17 19
     from typing import Union
    
    ... ... @@ -29,11 +31,13 @@
    29 31
     from nbxmpp.const import InviteType
    
    30 32
     
    
    31 33
     from gajim.common import app
    
    34
    +from gajim.common.file_props import FileProp
    
    32 35
     
    
    33 36
     if typing.TYPE_CHECKING:
    
    34 37
         from gajim.common.helpers import AdditionalDataDict
    
    35 38
         from gajim.common.const import KindConstant
    
    36 39
         from gajim.common.client import Client
    
    40
    +    from gajim.common.jingle_session import JingleSession
    
    37 41
     
    
    38 42
     
    
    39 43
     @dataclass
    
    ... ... @@ -167,14 +171,14 @@ class AdHocCommandActionResponse(ApplicationEvent):
    167 171
     @dataclass
    
    168 172
     class FileProgress(ApplicationEvent):
    
    169 173
         name: str = field(init=False, default='file-progress')
    
    170
    -    file_props: Any
    
    174
    +    file_props: FileProp
    
    171 175
     
    
    172 176
     
    
    173 177
     @dataclass
    
    174 178
     class FileCompleted(ApplicationEvent):
    
    175 179
         name: str = field(init=False, default='file-completed')
    
    176 180
         account: str
    
    177
    -    file_props: Any
    
    181
    +    file_props: FileProp
    
    178 182
         jid: str
    
    179 183
     
    
    180 184
     
    
    ... ... @@ -182,7 +186,7 @@ class FileCompleted(ApplicationEvent):
    182 186
     class FileError(ApplicationEvent):
    
    183 187
         name: str = field(init=False, default='file-error')
    
    184 188
         account: str
    
    185
    -    file_props: Any
    
    189
    +    file_props: FileProp
    
    186 190
         jid: str
    
    187 191
     
    
    188 192
     
    
    ... ... @@ -190,7 +194,7 @@ class FileError(ApplicationEvent):
    190 194
     class FileHashError(ApplicationEvent):
    
    191 195
         name: str = field(init=False, default='file-hash-error')
    
    192 196
         account: str
    
    193
    -    file_props: Any
    
    197
    +    file_props: FileProp
    
    194 198
         jid: str
    
    195 199
     
    
    196 200
     
    
    ... ... @@ -198,7 +202,7 @@ class FileHashError(ApplicationEvent):
    198 202
     class FileRequestSent(ApplicationEvent):
    
    199 203
         name: str = field(init=False, default='file-request-sent')
    
    200 204
         account: str
    
    201
    -    file_props: Any
    
    205
    +    file_props: FileProp
    
    202 206
         jid: str
    
    203 207
     
    
    204 208
     
    
    ... ... @@ -206,7 +210,7 @@ class FileRequestSent(ApplicationEvent):
    206 210
     class FileRequestError(ApplicationEvent):
    
    207 211
         name: str = field(init=False, default='file-request-error')
    
    208 212
         conn: 'Client'
    
    209
    -    file_props: Any
    
    213
    +    file_props: FileProp
    
    210 214
         jid: str
    
    211 215
         error_msg: str = ''
    
    212 216
     
    
    ... ... @@ -215,8 +219,9 @@ class FileRequestError(ApplicationEvent):
    215 219
     class FileSendError(ApplicationEvent):
    
    216 220
         name: str = field(init=False, default='file-send-error')
    
    217 221
         account: str
    
    218
    -    file_props: Any
    
    222
    +    file_props: FileProp
    
    219 223
         jid: str
    
    224
    +    error_msg: str = ''
    
    220 225
     
    
    221 226
     
    
    222 227
     @dataclass
    
    ... ... @@ -484,7 +489,7 @@ class JingleEvent(ApplicationEvent):
    484 489
         jid: str
    
    485 490
         sid: str
    
    486 491
         resource: str
    
    487
    -    jingle_session: Any
    
    492
    +    jingle_session: JingleSession
    
    488 493
     
    
    489 494
     
    
    490 495
     @dataclass
    
    ... ... @@ -651,7 +656,7 @@ class FileRequestReceivedEvent(ApplicationEvent):
    651 656
         fjid: str = field(init=False)
    
    652 657
         account: str = field(init=False)
    
    653 658
         jid: str = field(init=False)
    
    654
    -    file_props: Any = field(init=False)
    
    659
    +    file_props: FileProp = field(init=False)
    
    655 660
     
    
    656 661
         def __post_init__(self):
    
    657 662
             from gajim.common.jingle_transport import JingleTransportSocks5
    

  • gajim/common/file_props.py
    ... ... @@ -112,7 +112,7 @@ def __init__(self, account: str, sid: str) -> None:
    112 112
             # Do not instantiate this class directly!
    
    113 113
             # Call FilesProp.getNeFileProp instead
    
    114 114
             self.streamhosts = []
    
    115
    -        self.transfered_size: list[int] = []
    
    115
    +        self.transfered_size: list[tuple[float, int]] = []
    
    116 116
             self.started: bool = False
    
    117 117
             self.completed: bool = False
    
    118 118
             self.paused: bool = False
    

  • gajim/common/modules/iq.py
    ... ... @@ -66,7 +66,8 @@ def _iq_error_received(self, _con, _stanza, properties):
    66 66
                     app.ged.raise_event(
    
    67 67
                         FileSendError(account=self._account,
    
    68 68
                                       jid=str(properties.jid),
    
    69
    -                                  file_props=file_props))
    
    69
    +                                  file_props=file_props,
    
    70
    +                                  error_msg=''))
    
    70 71
                     self._con.get_module('Bytestream').disconnect_transfer(
    
    71 72
                         file_props)
    
    72 73
                     raise nbxmpp.NodeProcessed
    

  • gajim/gtk/controls/base.py
    ... ... @@ -29,6 +29,7 @@
    29 29
     from typing import Dict
    
    30 30
     from typing import List
    
    31 31
     from typing import Optional
    
    32
    +from typing import Union
    
    32 33
     
    
    33 34
     import os
    
    34 35
     import logging
    
    ... ... @@ -54,7 +55,10 @@
    54 55
     from gajim.common.helpers import get_file_path_from_dnd_dropped_uri
    
    55 56
     from gajim.common.i18n import _
    
    56 57
     from gajim.common.ged import EventHelper
    
    58
    +from gajim.common.events import ApplicationEvent
    
    57 59
     from gajim.common.events import JingleRequestReceived
    
    60
    +from gajim.common.events import FileRequestReceivedEvent
    
    61
    +from gajim.common.events import FileRequestSent
    
    58 62
     from gajim.common.events import Notification
    
    59 63
     from gajim.common.helpers import AdditionalDataDict
    
    60 64
     from gajim.common.helpers import get_retraction_text
    
    ... ... @@ -293,7 +297,7 @@ def _connect_contact_signals(self) -> None:
    293 297
         def _get_action(self, name: str) -> Gio.SimpleAction:
    
    294 298
             return app.window.lookup_action(f'{name}{self.control_id}')
    
    295 299
     
    
    296
    -    def process_event(self, event):
    
    300
    +    def process_event(self, event: ApplicationEvent) -> None:
    
    297 301
             if event.account != self.account:
    
    298 302
                 return
    
    299 303
     
    
    ... ... @@ -311,6 +315,7 @@ def process_event(self, event):
    311 315
                 if event.name in jingle_av_events:
    
    312 316
                     self._process_jingle_av_event(event)
    
    313 317
                     return
    
    318
    +
    
    314 319
                 if event.name in ('file-request-received', 'file-request-sent'):
    
    315 320
                     self.add_jingle_file_transfer(event=event)
    
    316 321
                     return
    
    ... ... @@ -1173,7 +1178,12 @@ def add_info_message(self, text: str) -> None:
    1173 1178
         def add_file_transfer(self, transfer: HTTPFileTransfer) -> None:
    
    1174 1179
             self.conversation_view.add_file_transfer(transfer)
    
    1175 1180
     
    
    1176
    -    def add_jingle_file_transfer(self, event):
    
    1181
    +    def add_jingle_file_transfer(self,
    
    1182
    +                                 event: Union[
    
    1183
    +                                     FileRequestReceivedEvent,
    
    1184
    +                                     FileRequestSent,
    
    1185
    +                                     None]
    
    1186
    +                                 ) -> None:
    
    1177 1187
             if self._allow_add_message():
    
    1178 1188
                 self.conversation_view.add_jingle_file_transfer(event)
    
    1179 1189
     
    

  • gajim/gtk/conversation/rows/file_transfer_jingle.py
    ... ... @@ -12,11 +12,17 @@
    12 12
     # You should have received a copy of the GNU General Public License
    
    13 13
     # along with Gajim. If not, see <http://www.gnu.org/licenses/>.
    
    14 14
     
    
    15
    +from __future__ import annotations
    
    16
    +
    
    17
    +from typing import Union
    
    18
    +from typing import Optional
    
    19
    +
    
    15 20
     import logging
    
    16 21
     import os
    
    17 22
     import time
    
    18 23
     from datetime import datetime
    
    19 24
     
    
    25
    +from gi.repository import GdkPixbuf
    
    20 26
     from gi.repository import GLib
    
    21 27
     from gi.repository import Gtk
    
    22 28
     
    
    ... ... @@ -24,27 +30,44 @@
    24 30
     from gajim.common import ged
    
    25 31
     from gajim.common.const import AvatarSize
    
    26 32
     from gajim.common.const import KindConstant
    
    33
    +from gajim.common.events import FileRequestReceivedEvent
    
    34
    +from gajim.common.events import FileRequestSent
    
    35
    +from gajim.common.events import FileCompleted
    
    36
    +from gajim.common.events import FileProgress
    
    37
    +from gajim.common.events import FileError
    
    38
    +from gajim.common.events import FileHashError
    
    39
    +from gajim.common.events import FileSendError
    
    40
    +from gajim.common.events import FileRequestError
    
    41
    +from gajim.common.events import JingleErrorReceived
    
    42
    +from gajim.common.events import JingleFtCancelledReceived
    
    27 43
     from gajim.common.file_props import FileProp
    
    28 44
     from gajim.common.file_props import FilesProp
    
    29 45
     from gajim.common.helpers import open_file
    
    30 46
     from gajim.common.i18n import _
    
    47
    +from gajim.common.modules.contacts import BareContact
    
    48
    +from gajim.common.storage.archive import ConversationRow
    
    31 49
     
    
    32 50
     from .base import BaseRow
    
    33 51
     from ...builder import get_builder
    
    34 52
     from ...util import format_eta
    
    35 53
     
    
    54
    +TransferEventT = Union[FileRequestReceivedEvent, FileRequestSent]
    
    55
    +
    
    36 56
     log = logging.getLogger('gajim.gui.conversation.rows.file_transfer_jingle')
    
    37 57
     
    
    38 58
     
    
    39 59
     class FileTransferJingleRow(BaseRow):
    
    40
    -    def __init__(self, account, contact, event=None, db_message=None):
    
    60
    +    def __init__(self,
    
    61
    +                 account: str,
    
    62
    +                 contact: BareContact,
    
    63
    +                 event: Optional[TransferEventT] = None,
    
    64
    +                 db_message: Optional[ConversationRow] = None
    
    65
    +                 ) -> None:
    
    41 66
             BaseRow.__init__(self, account)
    
    42 67
     
    
    43 68
             self.type = 'file-transfer'
    
    44 69
     
    
    45
    -        is_from_db = bool(db_message is not None)
    
    46
    -
    
    47
    -        if is_from_db:
    
    70
    +        if db_message is not None:
    
    48 71
                 timestamp = db_message.time
    
    49 72
             else:
    
    50 73
                 timestamp = time.time()
    
    ... ... @@ -53,12 +76,14 @@ def __init__(self, account, contact, event=None, db_message=None):
    53 76
     
    
    54 77
             self._contact = contact
    
    55 78
     
    
    56
    -        if is_from_db:
    
    79
    +        if db_message is not None:
    
    57 80
                 sid = db_message.additional_data.get_value('gajim', 'sid')
    
    81
    +            assert sid is not None
    
    58 82
                 self._file_props = FilesProp.getFilePropBySid(sid)
    
    59 83
                 if self._file_props is None:
    
    60
    -                log.debug('File props not found for SID: %s', sid)
    
    84
    +                log.debug('File prop not found for SID: %s', sid)
    
    61 85
             else:
    
    86
    +            assert event is not None
    
    62 87
                 self._file_props = event.file_props
    
    63 88
             self._start_time = 0
    
    64 89
     
    
    ... ... @@ -72,7 +97,7 @@ def __init__(self, account, contact, event=None, db_message=None):
    72 97
             avatar_placeholder.set_valign(Gtk.Align.START)
    
    73 98
             self.grid.attach(avatar_placeholder, 0, 0, 1, 1)
    
    74 99
     
    
    75
    -        if is_from_db:
    
    100
    +        if db_message is not None:
    
    76 101
                 if db_message.kind == KindConstant.FILE_TRANSFER_INCOMING:
    
    77 102
                     contact = self._contact
    
    78 103
                     is_self = True
    
    ... ... @@ -81,7 +106,7 @@ def __init__(self, account, contact, event=None, db_message=None):
    81 106
                         str(self._client.get_own_jid().bare))
    
    82 107
                     is_self = False
    
    83 108
             else:
    
    84
    -            if event.name == 'file-request-sent':
    
    109
    +            if isinstance(event, FileRequestSent):
    
    85 110
                     contact = self._client.get_module('Contacts').get_contact(
    
    86 111
                         str(self._client.get_own_jid().bare))
    
    87 112
                     is_self = False
    
    ... ... @@ -91,6 +116,7 @@ def __init__(self, account, contact, event=None, db_message=None):
    91 116
     
    
    92 117
             scale = self.get_scale_factor()
    
    93 118
             avatar = contact.get_avatar(AvatarSize.ROSTER, scale, add_show=False)
    
    119
    +        assert not isinstance(avatar, GdkPixbuf.Pixbuf)
    
    94 120
             avatar_image = Gtk.Image.new_from_surface(avatar)
    
    95 121
             avatar_placeholder.add(avatar_image)
    
    96 122
     
    
    ... ... @@ -112,9 +138,10 @@ def __init__(self, account, contact, event=None, db_message=None):
    112 138
     
    
    113 139
             self.show_all()
    
    114 140
     
    
    115
    -        if is_from_db:
    
    141
    +        if db_message is not None:
    
    116 142
                 self._reconstruct_transfer()
    
    117 143
             else:
    
    144
    +            assert event is not None
    
    118 145
                 self._display_transfer_info(event.name)
    
    119 146
     
    
    120 147
             if self._file_props is None:
    
    ... ... @@ -170,7 +197,7 @@ def _show_file_infos(self) -> None:
    170 197
                 self._ui.file_size.hide()
    
    171 198
                 return
    
    172 199
     
    
    173
    -        file_name = GLib.markup_escape_text(self._file_props.name)
    
    200
    +        file_name = GLib.markup_escape_text(str(self._file_props.name))
    
    174 201
             if self._file_props.mime_type:
    
    175 202
                 file_name = f'{file_name} ({self._file_props.mime_type})'
    
    176 203
             self._ui.file_name.set_text(file_name)
    
    ... ... @@ -186,8 +213,8 @@ def _show_file_infos(self) -> None:
    186 213
             self._ui.file_size.set_text(
    
    187 214
                 GLib.format_size_full(self._file_props.size, self._units))
    
    188 215
     
    
    189
    -    def process_event(self, event):
    
    190
    -        if event.name == 'jingle-error-received':
    
    216
    +    def process_event(self, event: TransferEventT) -> None:
    
    217
    +        if isinstance(event, JingleErrorReceived):
    
    191 218
                 if event.sid != self._file_props.sid:
    
    192 219
                     return
    
    193 220
                 self._ui.action_stack.set_visible_child_name('error')
    
    ... ... @@ -195,7 +222,7 @@ def process_event(self, event):
    195 222
                 self._ui.error_label.set_text(event.reason)
    
    196 223
                 return
    
    197 224
     
    
    198
    -        if event.name == 'jingle-ft-cancelled-received':
    
    225
    +        if isinstance(event, JingleFtCancelledReceived):
    
    199 226
                 if event.sid != self._file_props.sid:
    
    200 227
                     return
    
    201 228
                 self._ui.action_stack.set_visible_child_name('error')
    
    ... ... @@ -209,14 +236,15 @@ def process_event(self, event):
    209 236
             if event.file_props.sid != self._file_props.sid:
    
    210 237
                 return
    
    211 238
     
    
    212
    -        if event.name == 'file-completed':
    
    239
    +        if isinstance(event, FileCompleted):
    
    213 240
                 self._show_completed()
    
    214
    -        elif event.name == 'file-error':
    
    241
    +        elif isinstance(event, FileError):
    
    215 242
                 self._show_error(event.file_props)
    
    216
    -        elif event.name == 'file-hash-error':
    
    243
    +        elif isinstance(event, FileHashError):
    
    217 244
                 self._ui.action_stack.set_visible_child_name('hash-error')
    
    218 245
                 self._ui.transfer_action.set_text(_('File Verification Failed'))
    
    219
    -        elif event.name in ('file-request-error', 'file-send-error'):
    
    246
    +        elif (isinstance(event, FileRequestError) or
    
    247
    +                isinstance(event, FileSendError)):
    
    220 248
                 self._ui.action_stack.set_visible_child_name('error')
    
    221 249
                 self._ui.transfer_action.set_text(_('File Transfer Cancelled'))
    
    222 250
                 error_text = _('Connection with %s could not be '
    
    ... ... @@ -225,7 +253,7 @@ def process_event(self, event):
    225 253
                     error_text = f'{error_text} ({event.error_msg})'
    
    226 254
                 self._ui.error_label.set_text(error_text)
    
    227 255
     
    
    228
    -        elif event.name == 'file-progress':
    
    256
    +        elif isinstance(event, FileProgress):
    
    229 257
                 self._update_progress(event.file_props)
    
    230 258
     
    
    231 259
         def _update_progress(self, file_props: FileProp) -> None:
    

  • gajim/gtk/conversation/view.py
    ... ... @@ -36,6 +36,8 @@
    36 36
     from gajim.common import app
    
    37 37
     from gajim.common.client import Client
    
    38 38
     from gajim.common.events import JingleRequestReceived
    
    39
    +from gajim.common.events import FileRequestReceivedEvent
    
    40
    +from gajim.common.events import FileRequestSent
    
    39 41
     from gajim.common.helpers import AdditionalDataDict
    
    40 42
     from gajim.common.helpers import to_user_string
    
    41 43
     from gajim.common.helpers import get_start_of_day
    
    ... ... @@ -231,7 +233,14 @@ def add_file_transfer(self, transfer: HTTPFileTransfer) -> None:
    231 233
             transfer_row = FileTransferRow(self._account, transfer)
    
    232 234
             self._insert_message(transfer_row)
    
    233 235
     
    
    234
    -    def add_jingle_file_transfer(self, event=None, db_message=None):
    
    236
    +    def add_jingle_file_transfer(self,
    
    237
    +                                 event: Union[
    
    238
    +                                     FileRequestReceivedEvent,
    
    239
    +                                     FileRequestSent,
    
    240
    +                                     None] = None,
    
    241
    +                                 db_message: Optional[ConversationRow] = None
    
    242
    +                                 ) -> None:
    
    243
    +        assert isinstance(self._contact, BareContact)
    
    235 244
             jingle_transfer_row = FileTransferJingleRow(
    
    236 245
                 self._account, self._contact, event=event, db_message=db_message)
    
    237 246
             self._insert_message(jingle_transfer_row)
    

  • gajim/gtk/filetransfer.py
    ... ... @@ -30,6 +30,8 @@
    30 30
     from gi.repository import GLib
    
    31 31
     from gi.repository import Pango
    
    32 32
     
    
    33
    +from nbxmpp.protocol import JID
    
    34
    +
    
    33 35
     from gajim.common import app
    
    34 36
     from gajim.common import ged
    
    35 37
     from gajim.common import helpers
    
    ... ... @@ -38,12 +40,14 @@
    38 40
     from gajim.common.const import KindConstant
    
    39 41
     from gajim.common.i18n import _
    
    40 42
     from gajim.common.file_props import FilesProp
    
    43
    +from gajim.common.file_props import FileProp
    
    41 44
     from gajim.common.helpers import open_file
    
    42 45
     from gajim.common.helpers import file_is_locked
    
    43 46
     from gajim.common.helpers import AdditionalDataDict
    
    44 47
     from gajim.common.modules.bytestream import is_transfer_active
    
    45 48
     from gajim.common.modules.bytestream import is_transfer_paused
    
    46 49
     from gajim.common.modules.bytestream import is_transfer_stopped
    
    50
    +from gajim.common.modules.contacts import BareContact
    
    47 51
     
    
    48 52
     from .dialogs import DialogButton
    
    49 53
     from .dialogs import ConfirmationDialog
    
    ... ... @@ -343,7 +347,11 @@ def show_stopped(self, jid, file_props, error_msg=''):
    343 347
             ErrorDialog(_('File transfer stopped'), sectext)
    
    344 348
             self._ui.transfers_list.get_selection().unselect_all()
    
    345 349
     
    
    346
    -    def show_hash_error(self, jid, file_props, account):
    
    350
    +    def show_hash_error(self,
    
    351
    +                        jid: JID,
    
    352
    +                        file_props: FileProp,
    
    353
    +                        account: str
    
    354
    +                        ) -> None:
    
    347 355
             def _on_yes():
    
    348 356
                 # Delete old file
    
    349 357
                 os.remove(file_props.file_name)
    
    ... ... @@ -436,7 +444,11 @@ def _start_receive(self, file_path, account, contact, file_props):
    436 444
             client = app.get_client(account)
    
    437 445
             client.get_module('Bytestream').send_file_approval(file_props)
    
    438 446
     
    
    439
    -    def on_file_request_accepted(self, account, contact, file_props):
    
    447
    +    def on_file_request_accepted(self,
    
    448
    +                                 account: str,
    
    449
    +                                 contact: BareContact,
    
    450
    +                                 file_props: FileProp
    
    451
    +                                 ) -> None:
    
    440 452
             def _on_accepted(account, contact, file_props, file_path):
    
    441 453
                 if os.path.exists(file_path):
    
    442 454
                     app.settings.set('last_save_dir', os.path.dirname(file_path))
    
    ... ... @@ -887,10 +899,10 @@ def _on_cancel_button_clicked(self, widget):
    887 899
             file_props = FilesProp.getFilePropByType(sid[0], sid[1:])
    
    888 900
             self.cancel_transfer(file_props)
    
    889 901
     
    
    890
    -    def cancel_transfer(self, file_props):
    
    902
    +    def cancel_transfer(self, file_props: FileProp) -> None:
    
    891 903
             # TODO: does not cancel transfer somehow
    
    892 904
             account = file_props.tt_account
    
    893
    -        if account not in app.connections:
    
    905
    +        if account is None or account not in app.connections:
    
    894 906
                 return
    
    895 907
             client = app.get_client(account)
    
    896 908
             # Check if we are in a IBB transfer