From 742d853b114c39642d0646cddc4f278fa2fd1033 Mon Sep 17 00:00:00 2001 From: ingvar1995 Date: Wed, 3 Aug 2016 23:32:11 +0300 Subject: [PATCH] threads fix and update --- toxygen/callbacks.py | 21 ++------- toxygen/file_transfers.py | 28 ++++++++---- toxygen/list_items.py | 2 +- toxygen/profile.py | 95 ++++++++++++++++++--------------------- 4 files changed, 67 insertions(+), 79 deletions(-) diff --git a/toxygen/callbacks.py b/toxygen/callbacks.py index f85d7a3..bcb4a1b 100644 --- a/toxygen/callbacks.py +++ b/toxygen/callbacks.py @@ -243,30 +243,15 @@ def file_recv_chunk(tox, friend_number, file_number, position, chunk, length, us """ Incoming chunk """ - if not length: - invoke_in_main_thread(Profile.get_instance().incoming_chunk, - friend_number, - file_number, - position, - None) - else: - _thread.execute(Profile.get_instance().incoming_chunk, friend_number, file_number, position, chunk[:length]) - #Profile.get_instance().incoming_chunk(friend_number, file_number, position, chunk[:length]) + _thread.execute(Profile.get_instance().incoming_chunk, friend_number, file_number, position, + chunk[:length] if length else None) def file_chunk_request(tox, friend_number, file_number, position, size, user_data): """ Outgoing chunk """ - if size: - #_thread.execute(Profile.get_instance().outgoing_chunk, friend_number, file_number, position, size) - Profile.get_instance().outgoing_chunk(friend_number, file_number, position, size) - else: - invoke_in_main_thread(Profile.get_instance().outgoing_chunk, - friend_number, - file_number, - position, - size) + Profile.get_instance().outgoing_chunk(friend_number, file_number, position, size) def file_recv_control(tox, friend_number, file_number, file_control, user_data): diff --git a/toxygen/file_transfers.py b/toxygen/file_transfers.py index c45485a..1794e63 100644 --- a/toxygen/file_transfers.py +++ b/toxygen/file_transfers.py @@ -10,8 +10,6 @@ except ImportError: from PyQt4 import QtCore QtCore.Signal = QtCore.pyqtSignal -# TODO: threads! - TOX_FILE_TRANSFER_STATE = { 'RUNNING': 0, @@ -36,7 +34,12 @@ ALLOWED_FILES = ('toxygen_inline.png', 'utox-inline.png', 'sticker.png') class StateSignal(QtCore.QObject): - signal = QtCore.Signal(int, float, int) # state and progress + signal = QtCore.Signal(int, float, int) # state, progress, time in sec + + +class TransferFinishedSignal(QtCore.QObject): + + signal = QtCore.Signal(int, int) # friend number, file number class FileTransfer(QtCore.QObject): @@ -55,6 +58,7 @@ class FileTransfer(QtCore.QObject): self._size = float(size) self._done = 0 self._state_changed = StateSignal() + self._finished = TransferFinishedSignal() self._file_id = None def set_tox(self, tox): @@ -63,6 +67,9 @@ class FileTransfer(QtCore.QObject): def set_state_changed_handler(self, handler): self._state_changed.signal.connect(handler) + def set_transfer_finished_handler(self, handler): + self._finished.signal.connect(handler) + def signal(self): percentage = self._done / self._size if self._size else 0 if self._creation_time is None or not percentage: @@ -71,6 +78,9 @@ class FileTransfer(QtCore.QObject): t = ((time() - self._creation_time) / percentage) * (1 - percentage) self._state_changed.signal.emit(self.state, percentage, int(t)) + def finished(self): + self._finished.signal.emit(self._friend_number, self._file_number) + def get_file_number(self): return self._file_number @@ -143,12 +153,12 @@ class SendTransfer(FileTransfer): data = self._file.read(size) self._tox.file_send_chunk(self._friend_number, self._file_number, position, data) self._done += size - self.signal() else: if hasattr(self, '_file'): self._file.close() self.state = TOX_FILE_TRANSFER_STATE['FINISHED'] - self.signal() + self.finished() + self.signal() class SendAvatar(SendTransfer): @@ -187,10 +197,10 @@ class SendFromBuffer(FileTransfer): data = self._data[position:position + size] self._tox.file_send_chunk(self._friend_number, self._file_number, position, data) self._done += size - self.signal() else: self.state = TOX_FILE_TRANSFER_STATE['FINISHED'] - self.signal() + self.finished() + self.signal() class SendFromFileBuffer(SendTransfer): @@ -213,7 +223,7 @@ class ReceiveTransfer(FileTransfer): def __init__(self, path, tox, friend_number, size, file_number, position=0): super(ReceiveTransfer, self).__init__(path, tox, friend_number, size, file_number) - self._file = open(self._path, 'wb') + self._file = open(self._path, 'wb', 1371 * 4) self._file_size = position self._file.truncate(position) self._missed = set() @@ -239,6 +249,7 @@ class ReceiveTransfer(FileTransfer): if data is None: self._file.close() self.state = TOX_FILE_TRANSFER_STATE['FINISHED'] + self.finished() else: data = bytearray(data) if self._file_size < position: @@ -274,6 +285,7 @@ class ReceiveToBuffer(FileTransfer): self._creation_time = time() if data is None: self.state = TOX_FILE_TRANSFER_STATE['FINISHED'] + self.finished() else: data = bytes(data) l = len(data) diff --git a/toxygen/list_items.py b/toxygen/list_items.py index d0301ca..81469f7 100644 --- a/toxygen/list_items.py +++ b/toxygen/list_items.py @@ -410,7 +410,7 @@ class FileTransferItem(QtGui.QListWidget): if time + 1: m, s = divmod(time, 60) self.time_left.setText('{0:02d}:{1:02d}'.format(m, s)) - if self.state != state: + if self.state != state and self.state in ACTIVE_FILE_TRANSFERS: if state == TOX_FILE_TRANSFER_STATE['CANCELLED']: self.setStyleSheet('QListWidget { border: 1px solid #B40404; }') self.cancel.setVisible(False) diff --git a/toxygen/profile.py b/toxygen/profile.py index 3f6fe42..a6d58b9 100644 --- a/toxygen/profile.py +++ b/toxygen/profile.py @@ -874,7 +874,9 @@ class Profile(contact.Contact, Singleton): if file_id in self._paused_file_transfers: data = self._paused_file_transfers[file_id] pos = data[-1] if os.path.exists(data[0]) else 0 - print(pos, os.path.getsize(data[0])) + if pos >= os.path.getsize(data[0]): + self._tox.file_control(friend_number, file_number, TOX_FILE_CONTROL['CANCEL']) + return self._tox.file_seek(friend_number, file_number, pos) self.accept_transfer(None, data[0], friend_number, file_number, size, False, pos) tm = TransferMessage(MESSAGE_OWNER['FRIEND'], @@ -969,7 +971,12 @@ class Profile(contact.Contact, Singleton): """ self.get_friend_by_number(friend_number).update_transfer_data(file_number, TOX_FILE_TRANSFER_STATE['RUNNING']) - tr = self._file_transfers[(friend_number, file_number)] + try: + tr = self._file_transfers[(friend_number, file_number)] + except: + print('Exception in resume:', self._file_transfers) + print(friend_number, file_number, by_friend) + return if by_friend: tr.state = TOX_FILE_TRANSFER_STATE['RUNNING'] tr.signal() @@ -1001,6 +1008,7 @@ class Profile(contact.Contact, Singleton): rt = ReceiveTransfer(path, self._tox, friend_number, size, file_number, from_position) else: rt = ReceiveToBuffer(self._tox, friend_number, size, file_number) + rt.set_transfer_finished_handler(self.transfer_finished) self._file_transfers[(friend_number, file_number)] = rt self._tox.file_control(friend_number, file_number, TOX_FILE_CONTROL['RESUME']) if item is not None: @@ -1032,6 +1040,7 @@ class Profile(contact.Contact, Singleton): elif friend.status is None and is_resend: raise RuntimeError() st = SendFromBuffer(self._tox, friend.number, data, file_name) + st.set_transfer_finished_handler(self.transfer_finished) self._file_transfers[(friend.number, st.get_file_number())] = st tm = TransferMessage(MESSAGE_OWNER['ME'], time.time(), @@ -1064,7 +1073,9 @@ class Profile(contact.Contact, Singleton): print('Error in sending') raise RuntimeError() st = SendTransfer(path, self._tox, friend_number, TOX_FILE_KIND['DATA'], file_id) + st.set_transfer_finished_handler(self.transfer_finished) self._file_transfers[(friend_number, st.get_file_number())] = st + print('In send file', self._file_transfers) tm = TransferMessage(MESSAGE_OWNER['ME'], time.time(), TOX_FILE_TRANSFER_STATE['OUTGOING_NOT_STARTED'], @@ -1075,67 +1086,47 @@ class Profile(contact.Contact, Singleton): if friend_number == self.get_active_number(): item = self.create_file_transfer_item(tm) st.set_state_changed_handler(item.update) - self._friends[self._active_friend].append_message(tm) self._messages.scrollToBottom() + self._friends[friend_number].append_message(tm) def incoming_chunk(self, friend_number, file_number, position, data): """ Incoming chunk """ - if (friend_number, file_number) in self._file_transfers: - transfer = self._file_transfers[(friend_number, file_number)] - transfer.write_chunk(position, data) - if transfer.state not in ACTIVE_FILE_TRANSFERS: # finished or cancelled - if type(transfer) is ReceiveAvatar: - self.get_friend_by_number(friend_number).load_avatar() - self.set_active(None) - elif type(transfer) is ReceiveToBuffer: # inline image - print('inline') - inline = InlineImage(transfer.get_data()) - i = self.get_friend_by_number(friend_number).update_transfer_data(file_number, - TOX_FILE_TRANSFER_STATE['FINISHED'], - inline) - if friend_number == self.get_active_number(): - count = self._messages.count() - if count + i + 1 >= 0: - elem = QtGui.QListWidgetItem() - item = InlineImageItem(transfer.get_data(), self._messages.width(), elem) - elem.setSizeHint(QtCore.QSize(self._messages.width(), item.height())) - self._messages.insertItem(count + i + 1, elem) - self._messages.setItemWidget(elem, item) - else: - self.get_friend_by_number(friend_number).update_transfer_data(file_number, - TOX_FILE_TRANSFER_STATE['FINISHED']) - del self._file_transfers[(friend_number, file_number)] + self._file_transfers[(friend_number, file_number)].write_chunk(position, data) def outgoing_chunk(self, friend_number, file_number, position, size): """ Outgoing chunk """ - if (friend_number, file_number) in self._file_transfers: - transfer = self._file_transfers[(friend_number, file_number)] - transfer.send_chunk(position, size) - if transfer.state not in ACTIVE_FILE_TRANSFERS: # finished or cancelled - del self._file_transfers[(friend_number, file_number)] - if type(transfer) is not SendAvatar: - if type(transfer) is SendFromBuffer and Settings.get_instance()['allow_inline']: # inline - inline = InlineImage(transfer.get_data()) - print('inline') - i = self.get_friend_by_number(friend_number).update_transfer_data(file_number, - TOX_FILE_TRANSFER_STATE[ - 'FINISHED'], - inline) - if friend_number == self.get_active_number(): - count = self._messages.count() - if count + i + 1 >= 0: - elem = QtGui.QListWidgetItem() - item = InlineImageItem(transfer.get_data(), self._messages.width(), elem) - elem.setSizeHint(QtCore.QSize(self._messages.width(), item.height())) - self._messages.insertItem(count + i + 1, elem) - self._messages.setItemWidget(elem, item) - else: - self.get_friend_by_number(friend_number).update_transfer_data(file_number, - TOX_FILE_TRANSFER_STATE['FINISHED']) + self._file_transfers[(friend_number, file_number)].send_chunk(position, size) + + @QtCore.Slot(int, int) + def transfer_finished(self, friend_number, file_number): + transfer = self._file_transfers[(friend_number, file_number)] + t = type(transfer) + if t is ReceiveAvatar: + self.get_friend_by_number(friend_number).load_avatar() + self.set_active(None) + elif t is ReceiveToBuffer or (t is SendFromBuffer and Settings.get_instance()['allow_inline']): # inline image + print('inline') + inline = InlineImage(transfer.get_data()) + i = self.get_friend_by_number(friend_number).update_transfer_data(file_number, + TOX_FILE_TRANSFER_STATE['FINISHED'], + inline) + if friend_number == self.get_active_number(): + count = self._messages.count() + if count + i + 1 >= 0: + elem = QtGui.QListWidgetItem() + item = InlineImageItem(transfer.get_data(), self._messages.width(), elem) + elem.setSizeHint(QtCore.QSize(self._messages.width(), item.height())) + self._messages.insertItem(count + i + 1, elem) + self._messages.setItemWidget(elem, item) + elif t is not SendAvatar: + self.get_friend_by_number(friend_number).update_transfer_data(file_number, + TOX_FILE_TRANSFER_STATE['FINISHED']) + del self._file_transfers[(friend_number, file_number)] + del transfer # ----------------------------------------------------------------------------------------------------------------- # Avatars support