threads fix and update

This commit is contained in:
ingvar1995 2016-08-03 23:32:11 +03:00
parent 39fe859fe5
commit 742d853b11
4 changed files with 67 additions and 79 deletions

View File

@ -243,30 +243,15 @@ def file_recv_chunk(tox, friend_number, file_number, position, chunk, length, us
""" """
Incoming chunk Incoming chunk
""" """
if not length: _thread.execute(Profile.get_instance().incoming_chunk, friend_number, file_number, position,
invoke_in_main_thread(Profile.get_instance().incoming_chunk, chunk[:length] if length else None)
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])
def file_chunk_request(tox, friend_number, file_number, position, size, user_data): def file_chunk_request(tox, friend_number, file_number, position, size, user_data):
""" """
Outgoing chunk 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) 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)
def file_recv_control(tox, friend_number, file_number, file_control, user_data): def file_recv_control(tox, friend_number, file_number, file_control, user_data):

View File

@ -10,8 +10,6 @@ except ImportError:
from PyQt4 import QtCore from PyQt4 import QtCore
QtCore.Signal = QtCore.pyqtSignal QtCore.Signal = QtCore.pyqtSignal
# TODO: threads!
TOX_FILE_TRANSFER_STATE = { TOX_FILE_TRANSFER_STATE = {
'RUNNING': 0, 'RUNNING': 0,
@ -36,7 +34,12 @@ ALLOWED_FILES = ('toxygen_inline.png', 'utox-inline.png', 'sticker.png')
class StateSignal(QtCore.QObject): 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): class FileTransfer(QtCore.QObject):
@ -55,6 +58,7 @@ class FileTransfer(QtCore.QObject):
self._size = float(size) self._size = float(size)
self._done = 0 self._done = 0
self._state_changed = StateSignal() self._state_changed = StateSignal()
self._finished = TransferFinishedSignal()
self._file_id = None self._file_id = None
def set_tox(self, tox): def set_tox(self, tox):
@ -63,6 +67,9 @@ class FileTransfer(QtCore.QObject):
def set_state_changed_handler(self, handler): def set_state_changed_handler(self, handler):
self._state_changed.signal.connect(handler) self._state_changed.signal.connect(handler)
def set_transfer_finished_handler(self, handler):
self._finished.signal.connect(handler)
def signal(self): def signal(self):
percentage = self._done / self._size if self._size else 0 percentage = self._done / self._size if self._size else 0
if self._creation_time is None or not percentage: 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) t = ((time() - self._creation_time) / percentage) * (1 - percentage)
self._state_changed.signal.emit(self.state, percentage, int(t)) 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): def get_file_number(self):
return self._file_number return self._file_number
@ -143,11 +153,11 @@ class SendTransfer(FileTransfer):
data = self._file.read(size) data = self._file.read(size)
self._tox.file_send_chunk(self._friend_number, self._file_number, position, data) self._tox.file_send_chunk(self._friend_number, self._file_number, position, data)
self._done += size self._done += size
self.signal()
else: else:
if hasattr(self, '_file'): if hasattr(self, '_file'):
self._file.close() self._file.close()
self.state = TOX_FILE_TRANSFER_STATE['FINISHED'] self.state = TOX_FILE_TRANSFER_STATE['FINISHED']
self.finished()
self.signal() self.signal()
@ -187,9 +197,9 @@ class SendFromBuffer(FileTransfer):
data = self._data[position:position + size] data = self._data[position:position + size]
self._tox.file_send_chunk(self._friend_number, self._file_number, position, data) self._tox.file_send_chunk(self._friend_number, self._file_number, position, data)
self._done += size self._done += size
self.signal()
else: else:
self.state = TOX_FILE_TRANSFER_STATE['FINISHED'] self.state = TOX_FILE_TRANSFER_STATE['FINISHED']
self.finished()
self.signal() self.signal()
@ -213,7 +223,7 @@ class ReceiveTransfer(FileTransfer):
def __init__(self, path, tox, friend_number, size, file_number, position=0): def __init__(self, path, tox, friend_number, size, file_number, position=0):
super(ReceiveTransfer, self).__init__(path, tox, friend_number, size, file_number) 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_size = position
self._file.truncate(position) self._file.truncate(position)
self._missed = set() self._missed = set()
@ -239,6 +249,7 @@ class ReceiveTransfer(FileTransfer):
if data is None: if data is None:
self._file.close() self._file.close()
self.state = TOX_FILE_TRANSFER_STATE['FINISHED'] self.state = TOX_FILE_TRANSFER_STATE['FINISHED']
self.finished()
else: else:
data = bytearray(data) data = bytearray(data)
if self._file_size < position: if self._file_size < position:
@ -274,6 +285,7 @@ class ReceiveToBuffer(FileTransfer):
self._creation_time = time() self._creation_time = time()
if data is None: if data is None:
self.state = TOX_FILE_TRANSFER_STATE['FINISHED'] self.state = TOX_FILE_TRANSFER_STATE['FINISHED']
self.finished()
else: else:
data = bytes(data) data = bytes(data)
l = len(data) l = len(data)

View File

@ -410,7 +410,7 @@ class FileTransferItem(QtGui.QListWidget):
if time + 1: if time + 1:
m, s = divmod(time, 60) m, s = divmod(time, 60)
self.time_left.setText('{0:02d}:{1:02d}'.format(m, s)) 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']: if state == TOX_FILE_TRANSFER_STATE['CANCELLED']:
self.setStyleSheet('QListWidget { border: 1px solid #B40404; }') self.setStyleSheet('QListWidget { border: 1px solid #B40404; }')
self.cancel.setVisible(False) self.cancel.setVisible(False)

View File

@ -874,7 +874,9 @@ class Profile(contact.Contact, Singleton):
if file_id in self._paused_file_transfers: if file_id in self._paused_file_transfers:
data = self._paused_file_transfers[file_id] data = self._paused_file_transfers[file_id]
pos = data[-1] if os.path.exists(data[0]) else 0 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._tox.file_seek(friend_number, file_number, pos)
self.accept_transfer(None, data[0], friend_number, file_number, size, False, pos) self.accept_transfer(None, data[0], friend_number, file_number, size, False, pos)
tm = TransferMessage(MESSAGE_OWNER['FRIEND'], 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, self.get_friend_by_number(friend_number).update_transfer_data(file_number,
TOX_FILE_TRANSFER_STATE['RUNNING']) TOX_FILE_TRANSFER_STATE['RUNNING'])
try:
tr = self._file_transfers[(friend_number, file_number)] 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: if by_friend:
tr.state = TOX_FILE_TRANSFER_STATE['RUNNING'] tr.state = TOX_FILE_TRANSFER_STATE['RUNNING']
tr.signal() tr.signal()
@ -1001,6 +1008,7 @@ class Profile(contact.Contact, Singleton):
rt = ReceiveTransfer(path, self._tox, friend_number, size, file_number, from_position) rt = ReceiveTransfer(path, self._tox, friend_number, size, file_number, from_position)
else: else:
rt = ReceiveToBuffer(self._tox, friend_number, size, file_number) 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._file_transfers[(friend_number, file_number)] = rt
self._tox.file_control(friend_number, file_number, TOX_FILE_CONTROL['RESUME']) self._tox.file_control(friend_number, file_number, TOX_FILE_CONTROL['RESUME'])
if item is not None: if item is not None:
@ -1032,6 +1040,7 @@ class Profile(contact.Contact, Singleton):
elif friend.status is None and is_resend: elif friend.status is None and is_resend:
raise RuntimeError() raise RuntimeError()
st = SendFromBuffer(self._tox, friend.number, data, file_name) 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 self._file_transfers[(friend.number, st.get_file_number())] = st
tm = TransferMessage(MESSAGE_OWNER['ME'], tm = TransferMessage(MESSAGE_OWNER['ME'],
time.time(), time.time(),
@ -1064,7 +1073,9 @@ class Profile(contact.Contact, Singleton):
print('Error in sending') print('Error in sending')
raise RuntimeError() raise RuntimeError()
st = SendTransfer(path, self._tox, friend_number, TOX_FILE_KIND['DATA'], file_id) 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 self._file_transfers[(friend_number, st.get_file_number())] = st
print('In send file', self._file_transfers)
tm = TransferMessage(MESSAGE_OWNER['ME'], tm = TransferMessage(MESSAGE_OWNER['ME'],
time.time(), time.time(),
TOX_FILE_TRANSFER_STATE['OUTGOING_NOT_STARTED'], TOX_FILE_TRANSFER_STATE['OUTGOING_NOT_STARTED'],
@ -1075,21 +1086,29 @@ class Profile(contact.Contact, Singleton):
if friend_number == self.get_active_number(): if friend_number == self.get_active_number():
item = self.create_file_transfer_item(tm) item = self.create_file_transfer_item(tm)
st.set_state_changed_handler(item.update) st.set_state_changed_handler(item.update)
self._friends[self._active_friend].append_message(tm)
self._messages.scrollToBottom() self._messages.scrollToBottom()
self._friends[friend_number].append_message(tm)
def incoming_chunk(self, friend_number, file_number, position, data): def incoming_chunk(self, friend_number, file_number, position, data):
""" """
Incoming chunk Incoming chunk
""" """
if (friend_number, file_number) in self._file_transfers: self._file_transfers[(friend_number, file_number)].write_chunk(position, data)
def outgoing_chunk(self, friend_number, file_number, position, size):
"""
Outgoing chunk
"""
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)] transfer = self._file_transfers[(friend_number, file_number)]
transfer.write_chunk(position, data) t = type(transfer)
if transfer.state not in ACTIVE_FILE_TRANSFERS: # finished or cancelled if t is ReceiveAvatar:
if type(transfer) is ReceiveAvatar:
self.get_friend_by_number(friend_number).load_avatar() self.get_friend_by_number(friend_number).load_avatar()
self.set_active(None) self.set_active(None)
elif type(transfer) is ReceiveToBuffer: # inline image elif t is ReceiveToBuffer or (t is SendFromBuffer and Settings.get_instance()['allow_inline']): # inline image
print('inline') print('inline')
inline = InlineImage(transfer.get_data()) inline = InlineImage(transfer.get_data())
i = self.get_friend_by_number(friend_number).update_transfer_data(file_number, i = self.get_friend_by_number(friend_number).update_transfer_data(file_number,
@ -1103,39 +1122,11 @@ class Profile(contact.Contact, Singleton):
elem.setSizeHint(QtCore.QSize(self._messages.width(), item.height())) elem.setSizeHint(QtCore.QSize(self._messages.width(), item.height()))
self._messages.insertItem(count + i + 1, elem) self._messages.insertItem(count + i + 1, elem)
self._messages.setItemWidget(elem, item) self._messages.setItemWidget(elem, item)
else: elif t is not SendAvatar:
self.get_friend_by_number(friend_number).update_transfer_data(file_number, self.get_friend_by_number(friend_number).update_transfer_data(file_number,
TOX_FILE_TRANSFER_STATE['FINISHED']) TOX_FILE_TRANSFER_STATE['FINISHED'])
del self._file_transfers[(friend_number, file_number)] del self._file_transfers[(friend_number, file_number)]
del transfer
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'])
# ----------------------------------------------------------------------------------------------------------------- # -----------------------------------------------------------------------------------------------------------------
# Avatars support # Avatars support