Daniel Brötzmann pushed to branch master at gajim / gajim
Commits: bbafe882 by wurstsalat at 2022-01-14T10:08:12+01:00 Jingle file transfers: Typing
- - - - -
7 changed files:
- gajim/common/events.py - gajim/common/file_props.py - gajim/common/modules/iq.py - gajim/gtk/controls/base.py - gajim/gtk/conversation/rows/file_transfer_jingle.py - gajim/gtk/conversation/view.py - gajim/gtk/filetransfer.py
Changes:
===================================== gajim/common/events.py ===================================== @@ -12,6 +12,8 @@ # You should have received a copy of the GNU General Public License # along with Gajim. If not, see http://www.gnu.org/licenses/.
+from __future__ import annotations + import typing from typing import Any from typing import Union @@ -29,11 +31,13 @@ from nbxmpp.const import InviteType
from gajim.common import app +from gajim.common.file_props import FileProp
if typing.TYPE_CHECKING: from gajim.common.helpers import AdditionalDataDict from gajim.common.const import KindConstant from gajim.common.client import Client + from gajim.common.jingle_session import JingleSession
@dataclass @@ -167,14 +171,14 @@ class AdHocCommandActionResponse(ApplicationEvent): @dataclass class FileProgress(ApplicationEvent): name: str = field(init=False, default='file-progress') - file_props: Any + file_props: FileProp
@dataclass class FileCompleted(ApplicationEvent): name: str = field(init=False, default='file-completed') account: str - file_props: Any + file_props: FileProp jid: str
@@ -182,7 +186,7 @@ class FileCompleted(ApplicationEvent): class FileError(ApplicationEvent): name: str = field(init=False, default='file-error') account: str - file_props: Any + file_props: FileProp jid: str
@@ -190,7 +194,7 @@ class FileError(ApplicationEvent): class FileHashError(ApplicationEvent): name: str = field(init=False, default='file-hash-error') account: str - file_props: Any + file_props: FileProp jid: str
@@ -198,7 +202,7 @@ class FileHashError(ApplicationEvent): class FileRequestSent(ApplicationEvent): name: str = field(init=False, default='file-request-sent') account: str - file_props: Any + file_props: FileProp jid: str
@@ -206,7 +210,7 @@ class FileRequestSent(ApplicationEvent): class FileRequestError(ApplicationEvent): name: str = field(init=False, default='file-request-error') conn: 'Client' - file_props: Any + file_props: FileProp jid: str error_msg: str = ''
@@ -215,8 +219,9 @@ class FileRequestError(ApplicationEvent): class FileSendError(ApplicationEvent): name: str = field(init=False, default='file-send-error') account: str - file_props: Any + file_props: FileProp jid: str + error_msg: str = ''
@dataclass @@ -484,7 +489,7 @@ class JingleEvent(ApplicationEvent): jid: str sid: str resource: str - jingle_session: Any + jingle_session: JingleSession
@dataclass @@ -651,7 +656,7 @@ class FileRequestReceivedEvent(ApplicationEvent): fjid: str = field(init=False) account: str = field(init=False) jid: str = field(init=False) - file_props: Any = field(init=False) + file_props: FileProp = field(init=False)
def __post_init__(self): from gajim.common.jingle_transport import JingleTransportSocks5
===================================== gajim/common/file_props.py ===================================== @@ -112,7 +112,7 @@ def __init__(self, account: str, sid: str) -> None: # Do not instantiate this class directly! # Call FilesProp.getNeFileProp instead self.streamhosts = [] - self.transfered_size: list[int] = [] + self.transfered_size: list[tuple[float, int]] = [] self.started: bool = False self.completed: bool = False self.paused: bool = False
===================================== gajim/common/modules/iq.py ===================================== @@ -66,7 +66,8 @@ def _iq_error_received(self, _con, _stanza, properties): app.ged.raise_event( FileSendError(account=self._account, jid=str(properties.jid), - file_props=file_props)) + file_props=file_props, + error_msg='')) self._con.get_module('Bytestream').disconnect_transfer( file_props) raise nbxmpp.NodeProcessed
===================================== gajim/gtk/controls/base.py ===================================== @@ -29,6 +29,7 @@ from typing import Dict from typing import List from typing import Optional +from typing import Union
import os import logging @@ -54,7 +55,10 @@ from gajim.common.helpers import get_file_path_from_dnd_dropped_uri from gajim.common.i18n import _ from gajim.common.ged import EventHelper +from gajim.common.events import ApplicationEvent from gajim.common.events import JingleRequestReceived +from gajim.common.events import FileRequestReceivedEvent +from gajim.common.events import FileRequestSent from gajim.common.events import Notification from gajim.common.helpers import AdditionalDataDict from gajim.common.helpers import get_retraction_text @@ -293,7 +297,7 @@ def _connect_contact_signals(self) -> None: def _get_action(self, name: str) -> Gio.SimpleAction: return app.window.lookup_action(f'{name}{self.control_id}')
- def process_event(self, event): + def process_event(self, event: ApplicationEvent) -> None: if event.account != self.account: return
@@ -311,6 +315,7 @@ def process_event(self, event): if event.name in jingle_av_events: self._process_jingle_av_event(event) return + if event.name in ('file-request-received', 'file-request-sent'): self.add_jingle_file_transfer(event=event) return @@ -1173,7 +1178,12 @@ def add_info_message(self, text: str) -> None: def add_file_transfer(self, transfer: HTTPFileTransfer) -> None: self.conversation_view.add_file_transfer(transfer)
- def add_jingle_file_transfer(self, event): + def add_jingle_file_transfer(self, + event: Union[ + FileRequestReceivedEvent, + FileRequestSent, + None] + ) -> None: if self._allow_add_message(): self.conversation_view.add_jingle_file_transfer(event)
===================================== gajim/gtk/conversation/rows/file_transfer_jingle.py ===================================== @@ -12,11 +12,17 @@ # You should have received a copy of the GNU General Public License # along with Gajim. If not, see http://www.gnu.org/licenses/.
+from __future__ import annotations + +from typing import Union +from typing import Optional + import logging import os import time from datetime import datetime
+from gi.repository import GdkPixbuf from gi.repository import GLib from gi.repository import Gtk
@@ -24,27 +30,44 @@ from gajim.common import ged from gajim.common.const import AvatarSize from gajim.common.const import KindConstant +from gajim.common.events import FileRequestReceivedEvent +from gajim.common.events import FileRequestSent +from gajim.common.events import FileCompleted +from gajim.common.events import FileProgress +from gajim.common.events import FileError +from gajim.common.events import FileHashError +from gajim.common.events import FileSendError +from gajim.common.events import FileRequestError +from gajim.common.events import JingleErrorReceived +from gajim.common.events import JingleFtCancelledReceived from gajim.common.file_props import FileProp from gajim.common.file_props import FilesProp from gajim.common.helpers import open_file from gajim.common.i18n import _ +from gajim.common.modules.contacts import BareContact +from gajim.common.storage.archive import ConversationRow
from .base import BaseRow from ...builder import get_builder from ...util import format_eta
+TransferEventT = Union[FileRequestReceivedEvent, FileRequestSent] + log = logging.getLogger('gajim.gui.conversation.rows.file_transfer_jingle')
class FileTransferJingleRow(BaseRow): - def __init__(self, account, contact, event=None, db_message=None): + def __init__(self, + account: str, + contact: BareContact, + event: Optional[TransferEventT] = None, + db_message: Optional[ConversationRow] = None + ) -> None: BaseRow.__init__(self, account)
self.type = 'file-transfer'
- is_from_db = bool(db_message is not None) - - if is_from_db: + if db_message is not None: timestamp = db_message.time else: timestamp = time.time() @@ -53,12 +76,14 @@ def __init__(self, account, contact, event=None, db_message=None):
self._contact = contact
- if is_from_db: + if db_message is not None: sid = db_message.additional_data.get_value('gajim', 'sid') + assert sid is not None self._file_props = FilesProp.getFilePropBySid(sid) if self._file_props is None: - log.debug('File props not found for SID: %s', sid) + log.debug('File prop not found for SID: %s', sid) else: + assert event is not None self._file_props = event.file_props self._start_time = 0
@@ -72,7 +97,7 @@ def __init__(self, account, contact, event=None, db_message=None): avatar_placeholder.set_valign(Gtk.Align.START) self.grid.attach(avatar_placeholder, 0, 0, 1, 1)
- if is_from_db: + if db_message is not None: if db_message.kind == KindConstant.FILE_TRANSFER_INCOMING: contact = self._contact is_self = True @@ -81,7 +106,7 @@ def __init__(self, account, contact, event=None, db_message=None): str(self._client.get_own_jid().bare)) is_self = False else: - if event.name == 'file-request-sent': + if isinstance(event, FileRequestSent): contact = self._client.get_module('Contacts').get_contact( str(self._client.get_own_jid().bare)) is_self = False @@ -91,6 +116,7 @@ def __init__(self, account, contact, event=None, db_message=None):
scale = self.get_scale_factor() avatar = contact.get_avatar(AvatarSize.ROSTER, scale, add_show=False) + assert not isinstance(avatar, GdkPixbuf.Pixbuf) avatar_image = Gtk.Image.new_from_surface(avatar) avatar_placeholder.add(avatar_image)
@@ -112,9 +138,10 @@ def __init__(self, account, contact, event=None, db_message=None):
self.show_all()
- if is_from_db: + if db_message is not None: self._reconstruct_transfer() else: + assert event is not None self._display_transfer_info(event.name)
if self._file_props is None: @@ -170,7 +197,7 @@ def _show_file_infos(self) -> None: self._ui.file_size.hide() return
- file_name = GLib.markup_escape_text(self._file_props.name) + file_name = GLib.markup_escape_text(str(self._file_props.name)) if self._file_props.mime_type: file_name = f'{file_name} ({self._file_props.mime_type})' self._ui.file_name.set_text(file_name) @@ -186,8 +213,8 @@ def _show_file_infos(self) -> None: self._ui.file_size.set_text( GLib.format_size_full(self._file_props.size, self._units))
- def process_event(self, event): - if event.name == 'jingle-error-received': + def process_event(self, event: TransferEventT) -> None: + if isinstance(event, JingleErrorReceived): if event.sid != self._file_props.sid: return self._ui.action_stack.set_visible_child_name('error') @@ -195,7 +222,7 @@ def process_event(self, event): self._ui.error_label.set_text(event.reason) return
- if event.name == 'jingle-ft-cancelled-received': + if isinstance(event, JingleFtCancelledReceived): if event.sid != self._file_props.sid: return self._ui.action_stack.set_visible_child_name('error') @@ -209,14 +236,15 @@ def process_event(self, event): if event.file_props.sid != self._file_props.sid: return
- if event.name == 'file-completed': + if isinstance(event, FileCompleted): self._show_completed() - elif event.name == 'file-error': + elif isinstance(event, FileError): self._show_error(event.file_props) - elif event.name == 'file-hash-error': + elif isinstance(event, FileHashError): self._ui.action_stack.set_visible_child_name('hash-error') self._ui.transfer_action.set_text(_('File Verification Failed')) - elif event.name in ('file-request-error', 'file-send-error'): + elif (isinstance(event, FileRequestError) or + isinstance(event, FileSendError)): self._ui.action_stack.set_visible_child_name('error') self._ui.transfer_action.set_text(_('File Transfer Cancelled')) error_text = _('Connection with %s could not be ' @@ -225,7 +253,7 @@ def process_event(self, event): error_text = f'{error_text} ({event.error_msg})' self._ui.error_label.set_text(error_text)
- elif event.name == 'file-progress': + elif isinstance(event, FileProgress): self._update_progress(event.file_props)
def _update_progress(self, file_props: FileProp) -> None:
===================================== gajim/gtk/conversation/view.py ===================================== @@ -36,6 +36,8 @@ from gajim.common import app from gajim.common.client import Client from gajim.common.events import JingleRequestReceived +from gajim.common.events import FileRequestReceivedEvent +from gajim.common.events import FileRequestSent from gajim.common.helpers import AdditionalDataDict from gajim.common.helpers import to_user_string from gajim.common.helpers import get_start_of_day @@ -231,7 +233,14 @@ def add_file_transfer(self, transfer: HTTPFileTransfer) -> None: transfer_row = FileTransferRow(self._account, transfer) self._insert_message(transfer_row)
- def add_jingle_file_transfer(self, event=None, db_message=None): + def add_jingle_file_transfer(self, + event: Union[ + FileRequestReceivedEvent, + FileRequestSent, + None] = None, + db_message: Optional[ConversationRow] = None + ) -> None: + assert isinstance(self._contact, BareContact) jingle_transfer_row = FileTransferJingleRow( self._account, self._contact, event=event, db_message=db_message) self._insert_message(jingle_transfer_row)
===================================== gajim/gtk/filetransfer.py ===================================== @@ -30,6 +30,8 @@ from gi.repository import GLib from gi.repository import Pango
+from nbxmpp.protocol import JID + from gajim.common import app from gajim.common import ged from gajim.common import helpers @@ -38,12 +40,14 @@ from gajim.common.const import KindConstant from gajim.common.i18n import _ from gajim.common.file_props import FilesProp +from gajim.common.file_props import FileProp from gajim.common.helpers import open_file from gajim.common.helpers import file_is_locked from gajim.common.helpers import AdditionalDataDict from gajim.common.modules.bytestream import is_transfer_active from gajim.common.modules.bytestream import is_transfer_paused from gajim.common.modules.bytestream import is_transfer_stopped +from gajim.common.modules.contacts import BareContact
from .dialogs import DialogButton from .dialogs import ConfirmationDialog @@ -343,7 +347,11 @@ def show_stopped(self, jid, file_props, error_msg=''): ErrorDialog(_('File transfer stopped'), sectext) self._ui.transfers_list.get_selection().unselect_all()
- def show_hash_error(self, jid, file_props, account): + def show_hash_error(self, + jid: JID, + file_props: FileProp, + account: str + ) -> None: def _on_yes(): # Delete old file os.remove(file_props.file_name) @@ -436,7 +444,11 @@ def _start_receive(self, file_path, account, contact, file_props): client = app.get_client(account) client.get_module('Bytestream').send_file_approval(file_props)
- def on_file_request_accepted(self, account, contact, file_props): + def on_file_request_accepted(self, + account: str, + contact: BareContact, + file_props: FileProp + ) -> None: def _on_accepted(account, contact, file_props, file_path): if os.path.exists(file_path): app.settings.set('last_save_dir', os.path.dirname(file_path)) @@ -887,10 +899,10 @@ def _on_cancel_button_clicked(self, widget): file_props = FilesProp.getFilePropByType(sid[0], sid[1:]) self.cancel_transfer(file_props)
- def cancel_transfer(self, file_props): + def cancel_transfer(self, file_props: FileProp) -> None: # TODO: does not cancel transfer somehow account = file_props.tt_account - if account not in app.connections: + if account is None or account not in app.connections: return client = app.get_client(account) # Check if we are in a IBB transfer
View it on GitLab: https://dev.gajim.org/gajim/gajim/-/commit/bbafe882fa17592704f25cd2b3add6025...