file transfers fixes - part 3

This commit is contained in:
ingvar1995 2018-05-17 00:02:22 +03:00
parent c0a143c817
commit a96f6d2928
12 changed files with 79 additions and 74 deletions

View File

@ -323,7 +323,7 @@ class App:
self._toxes, self._version)
self._tray = tray.init_tray(profile, self._settings, self._ms)
self._ms.set_dependencies(widgets_factory, self._tray, self._contacts_manager, self._messenger, profile,
self._plugin_loader)
self._plugin_loader, self._file_transfer_handler)
self._tray.show()
self._ms.show()

View File

@ -8,9 +8,13 @@ class Event:
def __iadd__(self, callback):
self.add_callback(callback)
return self
def __isub__(self, callback):
self.remove_callback(callback)
return self
def __call__(self, *args, **kwargs):
for callback in self._callbacks:
callback(*args, **kwargs)

View File

@ -101,6 +101,9 @@ class Contact(basecontact.BaseContact):
for message in self._corr:
message.remove_widget()
def get_message(self, _filter):
return list(filter(lambda m: _filter(m), self._corr))[0]
@staticmethod
def _get_text_message(params):
(message, author_type, author_name, unix_time, message_type, unique_id) = params

View File

@ -1,8 +1,4 @@
import utils.util as util
import utils.ui as util_ui
from contacts.friend import Friend
from PyQt5 import QtCore, QtGui
from wrapper.toxcore_enums_and_consts import *
from messenger.messages import *
@ -71,10 +67,10 @@ class ContactsManager:
self._screen.messageEdit.clear()
return
try:
# self.send_typing(False) # TODO: fix
self._screen.typing.setVisible(False)
current_contact = self.get_curr_contact()
if current_contact is not None:
current_contact.typing_notification_handler.send(self._tox, False)
current_contact.remove_messages_widgets() # TODO: if required
self._unsubscribe_from_events(current_contact)
@ -96,6 +92,11 @@ class ContactsManager:
contact.load_corr()
corr = contact.get_corr()[-PAGE_SIZE:]
for message in corr:
if message.type == MESSAGE_TYPE['FILE_TRANSFER']:
self._messages_items_factory.create_file_transfer_item(message)
elif message.type == MESSAGE_TYPE['INLINE']:
self._messages_items_factory.create_inline_item(message.data)
else:
self._messages_items_factory.create_message_item(message)
# if value in self._call:
# self._screen.active_call()

View File

@ -18,14 +18,13 @@ class Friend(contact.Contact):
# File transfers support
# -----------------------------------------------------------------------------------------------------------------
def update_transfer_data(self, file_number, status, inline=None):
def update_transfer_data(self, file_number, inline): # TODO: rewrite
"""
Update status of active transfer and load inline if needed
"""
try:
tr = list(filter(lambda x: x.get_type() == MESSAGE_TYPE['FILE_TRANSFER'] and x.is_active(file_number),
self._corr))[0]
tr.set_status(status)
i = self._corr.index(tr)
if inline: # inline was loaded
self._corr.insert(i, inline)

View File

@ -1,7 +1,7 @@
from wrapper.toxcore_enums_and_consts import TOX_FILE_KIND, TOX_FILE_CONTROL
from os.path import basename, getsize, exists, dirname
from os import remove, rename, chdir
from time import time, sleep
from time import time
from wrapper.tox import Tox
from common.event import Event
@ -47,7 +47,7 @@ class FileTransfer:
self._done = 0
self._state_changed_event = Event()
self._finished_event = Event()
self._file_id = None
self._file_id = self._file = None
def set_tox(self, tox):
self._tox = tox
@ -85,13 +85,12 @@ class FileTransfer:
def cancel(self):
self.send_control(TOX_FILE_CONTROL['CANCEL'])
if hasattr(self, '_file'):
if self._file is not None:
self._file.close()
self.signal()
def cancelled(self):
if hasattr(self, '_file'):
sleep(0.1)
if self._file is not None:
self._file.close()
self.state = FILE_TRANSFER_STATE['CANCELLED']
self.signal()

View File

@ -1,8 +1,5 @@
from file_transfers.file_transfers import *
from messenger.messages import *
from history.database import MESSAGE_AUTHOR
from ui.contact_items import *
from PyQt5 import QtWidgets
import utils.util as util
@ -46,18 +43,18 @@ class FileTransfersHandler:
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)
self.accept_transfer(data[0], friend_number, file_number, size, False, pos)
elif inline and size < 1024 * 1024:
self.accept_transfer(None, '', friend_number, file_number, size, True)
self.accept_transfer('', friend_number, file_number, size, True)
elif auto:
path = self._settings['auto_accept_path'] or util.curr_directory()
self.accept_transfer(None, path + '/' + file_name, friend_number, file_number, size)
self.accept_transfer(path + '/' + file_name, friend_number, file_number, size)
else:
accepted = False
self._file_transfers_message_service.add_incoming_transfer_message(
friend, accepted, size, file_name,file_number)
friend, accepted, size, file_name, file_number)
def cancel_transfer(self, friend_number, file_number, already_cancelled=False):
"""
@ -66,8 +63,6 @@ class FileTransfersHandler:
:param file_number: file number
:param already_cancelled: was cancelled by friend
"""
i = self._get_friend_by_number(friend_number).update_transfer_data(file_number,
FILE_TRANSFER_STATE['CANCELLED'])
if (friend_number, file_number) in self._file_transfers:
tr = self._file_transfers[(friend_number, file_number)]
if not already_cancelled:
@ -77,15 +72,8 @@ class FileTransfersHandler:
if (friend_number, file_number) in self._file_transfers:
del tr
del self._file_transfers[(friend_number, file_number)]
else:
if not already_cancelled:
elif not already_cancelled:
self._tox.file_control(friend_number, file_number, TOX_FILE_CONTROL['CANCEL'])
if friend_number == self.get_active_number() and self.is_active_a_friend():
tmp = self._messages.count() + i
if tmp >= 0:
self._messages.itemWidget(
self._messages.item(tmp)).update_transfer_state(FILE_TRANSFER_STATE['CANCELLED'],
0, -1)
def cancel_not_started_transfer(self, cancel_time):
self.get_curr_friend().delete_one_unsent_file(cancel_time)
@ -96,15 +84,11 @@ class FileTransfersHandler:
"""
tr = self._file_transfers[(friend_number, file_number)]
tr.pause(by_friend)
t = FILE_TRANSFER_STATE['PAUSED_BY_FRIEND'] if by_friend else FILE_TRANSFER_STATE['PAUSED_BY_USER']
self._get_friend_by_number(friend_number).update_transfer_data(file_number, t)
def resume_transfer(self, friend_number, file_number, by_friend=False):
"""
Resume transfer with specified data
"""
# 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)]
if by_friend:
tr.state = FILE_TRANSFER_STATE['RUNNING']
@ -112,9 +96,8 @@ class FileTransfersHandler:
else:
tr.send_control(TOX_FILE_CONTROL['RESUME'])
def accept_transfer(self, item, path, friend_number, file_number, size, inline=False, from_position=0):
def accept_transfer(self, path, friend_number, file_number, size, inline=False, from_position=0):
"""
:param item: transfer item.
:param path: path for saving
:param friend_number: friend number
:param file_number: file number
@ -122,32 +105,23 @@ class FileTransfersHandler:
:param inline: is inline image
:param from_position: position for start
"""
path, file_name = os.path.split(path)
new_file_name, i = file_name, 1
if not from_position:
while os.path.isfile(path + '/' + new_file_name): # file with same name already exists
if '.' in file_name: # has extension
d = file_name.rindex('.')
else: # no extension
d = len(file_name)
new_file_name = file_name[:d] + ' ({})'.format(i) + file_name[d:]
i += 1
path = os.path.join(path, new_file_name)
path = self._generate_valid_path(path, from_position)
friend = self._get_friend_by_number(friend_number)
if not inline:
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)
message = friend.get_message(lambda m: m.type == MESSAGE_TYPE['FILE_TRANSFER']
and m.state == FILE_TRANSFER_STATE['INCOMING_NOT_STARTED']
and m.file_number == file_number)
rt.set_state_changed_handler(message.transfer_updated)
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:
rt.set_state_changed_handler(item.update_transfer_state)
self._get_friend_by_number(friend_number).update_transfer_data(file_number,
FILE_TRANSFER_STATE['RUNNING'])
def send_screenshot(self, data, friend_number):
"""
Send screenshot to current active friend
Send screenshot
:param data: raw data - png
"""
self.send_inline(data, 'toxygen_inline.png', friend_number)
@ -169,7 +143,8 @@ class FileTransfersHandler:
st.set_transfer_finished_handler(self.transfer_finished)
file_number = st.get_file_number()
self._file_transfers[(friend.number, file_number)] = st
self._file_transfers_message_service.add_outgoing_transfer_message(friend, st.size, file_name, file_number)
tm = self._file_transfers_message_service.add_outgoing_transfer_message(friend, st.size, file_name, file_number)
st.set_state_changed_handler(tm.transfer_updated)
def send_file(self, path, friend_number, is_resend=False, file_id=None):
"""
@ -192,7 +167,8 @@ class FileTransfersHandler:
file_number = st.get_file_number()
self._file_transfers[(friend_number, file_number)] = st
file_name = os.path.basename(path)
self._file_transfers_message_service.add_outgoing_transfer_message(friend, st.size, file_name, file_number)
tm = self._file_transfers_message_service.add_outgoing_transfer_message(friend, st.size, file_name, file_number)
st.set_state_changed_handler(tm.transfer_updated)
def incoming_chunk(self, friend_number, file_number, position, data):
"""
@ -214,13 +190,8 @@ class FileTransfersHandler:
elif t is ReceiveToBuffer or (t is SendFromBuffer and self._settings['allow_inline']): # inline image
print('inline')
inline = InlineImage(transfer.get_data())
index = self._get_friend_by_number(friend_number).update_transfer_data(file_number,
FILE_TRANSFER_STATE['FINISHED'],
inline)
index = self._get_friend_by_number(friend_number).update_transfer_data(file_number, inline)
self._file_transfers_message_service.add_inline_message(transfer, index)
elif t is not SendAvatar:
self._get_friend_by_number(friend_number).update_transfer_data(file_number,
FILE_TRANSFER_STATE['FINISHED'])
del self._file_transfers[(friend_number, file_number)]
del transfer
@ -279,3 +250,19 @@ class FileTransfersHandler:
def _get_friend_by_number(self, friend_number):
return self._contact_provider.get_friend_by_number(friend_number)
@staticmethod
def _generate_valid_path(path, from_position):
path, file_name = os.path.split(path)
new_file_name, i = file_name, 1
if not from_position:
while os.path.isfile(path + '/' + new_file_name): # file with same name already exists
if '.' in file_name: # has extension
d = file_name.rindex('.')
else: # no extension
d = len(file_name)
new_file_name = file_name[:d] + ' ({})'.format(i) + file_name[d:]
i += 1
path = os.path.join(path, new_file_name)
return path

View File

@ -24,6 +24,8 @@ class FileTransfersMessagesService:
friend.append_message(tm)
return tm
def add_outgoing_transfer_message(self, friend, size, file_name, file_number):
author = MessageAuthor(self._profile.name, MESSAGE_AUTHOR['ME'])
status = FILE_TRANSFER_STATE['OUTGOING_NOT_STARTED']
@ -35,6 +37,8 @@ class FileTransfersMessagesService:
friend.append_message(tm)
return tm
def add_inline_message(self, transfer, index):
if self._is_active(transfer.friend_number):
count = self._messages.count()

View File

@ -164,6 +164,11 @@ class TransferMessage(Message):
file_name = property(get_file_name)
def transfer_updated(self, state, percentage, time):
self._state = state
if self._widget is not None:
self._widget.update_transfer_state(state, percentage, time)
def _create_widget(self, *args):
return FileTransferItem(self, *args)

View File

@ -45,7 +45,7 @@ class MessagesItemsFactory:
return item
def create_inline_item(self, data, append, position=0):
def create_inline_item(self, data, append=True, position=0):
elem = QtWidgets.QListWidgetItem()
item = InlineImageItem(data, self._messages.width(), elem)
elem.setSizeHint(QtCore.QSize(self._messages.width(), item.height()))
@ -57,7 +57,7 @@ class MessagesItemsFactory:
return item
def create_unsent_file_item(self, tm, append):
def create_unsent_file_item(self, tm, append=True):
item = UnsentFileItem(self._file_transfers_handler, self._settings, tm, self._messages.width())
elem = QtWidgets.QListWidgetItem()
elem.setSizeHint(QtCore.QSize(self._messages.width() - 30, 34))
@ -70,7 +70,7 @@ class MessagesItemsFactory:
return item
def create_file_transfer_item(self, tm, append=True):
item = tm.get_widget(self._file_transfers_handler, self._settings, tm, self._messages.width())
item = tm.get_widget(self._file_transfers_handler, self._settings, self._messages.width())
elem = QtWidgets.QListWidgetItem()
elem.setSizeHint(QtCore.QSize(self._messages.width() - 30, 34))
if append:

View File

@ -19,14 +19,17 @@ class MainWindow(QtWidgets.QMainWindow):
self.setAcceptDrops(True)
self._saved = False
self._profile = None
self._file_transfer_handler = None
self.initUI()
def set_dependencies(self, widget_factory, tray, contacts_manager, messenger, profile, plugins_loader):
def set_dependencies(self, widget_factory, tray, contacts_manager, messenger, profile, plugins_loader,
file_transfer_handler):
self._widget_factory = widget_factory
self._tray = tray
self._contacts_manager = contacts_manager
self._profile = profile
self._plugins_loader = plugins_loader
self._file_transfer_handler = file_transfer_handler
self.messageEdit.set_messenger(messenger)
def show(self):
@ -519,7 +522,7 @@ class MainWindow(QtWidgets.QMainWindow):
caption = util_ui.tr('Choose file')
name = util_ui.file_dialog(caption)
if name[0]:
self._contacts_manager.send_file(name[0], self._contacts_manager.get_contact().number)
self._file_transfer_handler.send_file(name[0], self._contacts_manager.get_active_number())
def send_screenshot(self, hide=False):
self.menu.hide()

View File

@ -218,10 +218,10 @@ class MessageItem(QtWidgets.QWidget):
class FileTransferItem(QtWidgets.QListWidget):
def __init__(self, file_transfers_handler, settings, transfer_message, width, parent=None):
def __init__(self, transfer_message, file_transfer_handler, settings, width, parent=None):
QtWidgets.QListWidget.__init__(self, parent)
self._file_transfers_handler = file_transfers_handler
self._file_transfer_handler = file_transfer_handler
self.resize(QtCore.QSize(width, 34))
if transfer_message.state == FILE_TRANSFER_STATE['CANCELLED']:
self.setStyleSheet('QListWidget { border: 1px solid #B40404; }')
@ -308,7 +308,7 @@ class FileTransferItem(QtWidgets.QListWidget):
self.paused = False
def cancel_transfer(self, friend_number, file_number):
self._file_transfers_handler.cancel_transfer(friend_number, file_number)
self._file_transfer_handler.cancel_transfer(friend_number, file_number)
self.setStyleSheet('QListWidget { border: 1px solid #B40404; }')
self.cancel.setVisible(False)
self.accept_or_pause.setVisible(False)
@ -319,7 +319,7 @@ class FileTransferItem(QtWidgets.QListWidget):
directory = util_ui.directory_dialog(util_ui.tr('Choose folder'))
self.pb.setVisible(True)
if directory:
self._file_transfer_handler.accept_transfer(self, directory + '/' + self.saved_name,
self._file_transfer_handler.accept_transfer(directory + '/' + self.saved_name,
friend_number, file_number, size)
self.button_update('pause')
elif self.state == FILE_TRANSFER_STATE['PAUSED_BY_USER']: # resume
@ -390,8 +390,8 @@ class FileTransferItem(QtWidgets.QListWidget):
class UnsentFileItem(FileTransferItem):
def __init__(self, file_transfers_handler, settings, transfer_message, width, parent=None):
super().__init__(file_transfers_handler, settings, transfer_message, width, parent)
def __init__(self, file_transfer_handler, settings, transfer_message, width, parent=None):
super().__init__(file_transfer_handler, settings, transfer_message, width, parent)
self._time = time
self.pb.setVisible(False)
movie = QtGui.QMovie(util.join_path(util.get_images_directory(), 'spinner.gif'))
@ -399,7 +399,7 @@ class UnsentFileItem(FileTransferItem):
movie.start()
def cancel_transfer(self, *args):
self._file_transfers_handler.cancel_not_started_transfer(self._time)
self._file_transfer_handler.cancel_not_started_transfer(self._time)
class InlineImageItem(QtWidgets.QScrollArea):