diff --git a/tests/tests.py b/tests/tests.py index 1047de4..442a677 100644 --- a/tests/tests.py +++ b/tests/tests.py @@ -126,7 +126,7 @@ class TestFriend: assert arr[0][0] == 'Not sent' tm = TransferMessage(MESSAGE_OWNER['FRIEND'], time.time(), - TOX_FILE_TRANSFER_STATE['RUNNING'], + FILE_TRANSFER_STATE['RUNNING'], 100, 'file_name', friend.number, 0) friend.append_message(tm) friend.clear_corr() diff --git a/toxygen/app.py b/toxygen/app.py index 2d12876..ce15093 100644 --- a/toxygen/app.py +++ b/toxygen/app.py @@ -28,6 +28,7 @@ from ui.items_factories import MessagesItemsFactory, FriendItemsFactory from messenger.messenger import Messenger from network.tox_dns import ToxDns from history.history import History +from file_transfers.file_transfers_messages_service import FileTransfersMessagesService class App: @@ -312,7 +313,11 @@ class App: history.set_contacts_manager(self._contacts_manager) self._messenger = Messenger(self._tox, self._plugin_loader, self._ms, self._contacts_manager, self._contacts_provider, messages_items_factory, profile) - self._file_transfer_handler = FileTransfersHandler(self._tox, self._settings, self._contacts_provider) + file_transfers_message_service = FileTransfersMessagesService(self._contacts_manager, messages_items_factory, + profile, self._ms) + self._file_transfer_handler = FileTransfersHandler(self._tox, self._settings, self._contacts_provider, + file_transfers_message_service) + messages_items_factory.set_file_transfers_handler(self._file_transfer_handler) widgets_factory = WidgetsFactory(self._settings, profile, self._profile_manager, self._contacts_manager, self._file_transfer_handler, self._smiley_loader, self._plugin_loader, self._toxes, self._version) diff --git a/toxygen/contacts/contacts_manager.py b/toxygen/contacts/contacts_manager.py index b65acfa..7570c06 100644 --- a/toxygen/contacts/contacts_manager.py +++ b/toxygen/contacts/contacts_manager.py @@ -83,18 +83,18 @@ class ContactsManager: current_contact.curr_text = self._screen.messageEdit.toPlainText() except: pass - friend = self._contacts[value] - self._subscribe_to_events(friend) - friend.remove_invalid_unsent_files() + contact = self._contacts[value] + self._subscribe_to_events(contact) + contact.remove_invalid_unsent_files() if self._active_contact != value: - self._screen.messageEdit.setPlainText(friend.curr_text) + self._screen.messageEdit.setPlainText(contact.curr_text) self._active_contact = value - friend.reset_messages() + contact.reset_messages() if not self._settings['save_history']: - friend.delete_old_messages() + contact.delete_old_messages() self._messages.clear() - friend.load_corr() - corr = friend.get_corr()[-PAGE_SIZE:] + contact.load_corr() + corr = contact.get_corr()[-PAGE_SIZE:] for message in corr: self._messages_items_factory.create_message_item(message) # if value in self._call: @@ -103,12 +103,8 @@ class ContactsManager: # self._screen.incoming_call() # else: # self._screen.call_finished() + self._set_current_contact_data(contact) - self._screen.account_status.setToolTip(friend.get_full_status()) - avatar_path = friend.get_avatar_path() - pixmap = QtGui.QPixmap(avatar_path) - self._screen.account_avatar.setPixmap(pixmap.scaled(64, 64, QtCore.Qt.KeepAspectRatio, - QtCore.Qt.SmoothTransformation)) except Exception as ex: # no friend found. ignore util.log('Friend value: ' + str(value)) util.log('Error in set active: ' + str(ex)) @@ -433,8 +429,15 @@ class ContactsManager: self._screen.account_status.setText(status_message) def _current_contact_avatar_changed(self, avatar_path): + self._set_current_contact_avatar(avatar_path) + + def _set_current_contact_data(self, contact): + self._screen.account_name.setText(contact.name) + self._screen.account_status.setText(contact.status_message) + self._set_current_contact_avatar(contact.get_avatar_path()) + + def _set_current_contact_avatar(self, avatar_path): width = self._screen.account_avatar.width() pixmap = QtGui.QPixmap(avatar_path) - self._screen.avatar_label.setPixmap(pixmap.scaled(width, width, - QtCore.Qt.KeepAspectRatio, - QtCore.Qt.SmoothTransformation)) + self._screen.account_avatar.setPixmap(pixmap.scaled(width, width, + QtCore.Qt.KeepAspectRatio, QtCore.Qt.SmoothTransformation)) diff --git a/toxygen/contacts/profile.py b/toxygen/contacts/profile.py index af5b87e..1a8fe0f 100644 --- a/toxygen/contacts/profile.py +++ b/toxygen/contacts/profile.py @@ -91,7 +91,7 @@ class Profile(basecontact.BaseContact): ft = self._file_transfers[(friend_num, file_num)] if type(ft) is SendTransfer: self._paused_file_transfers[ft.get_id()] = [ft.get_path(), friend_num, False, -1] - elif type(ft) is ReceiveTransfer and ft.state != TOX_FILE_TRANSFER_STATE['INCOMING_NOT_STARTED']: + elif type(ft) is ReceiveTransfer and ft.state != FILE_TRANSFER_STATE['INCOMING_NOT_STARTED']: self._paused_file_transfers[ft.get_id()] = [ft.get_path(), friend_num, True, ft.total_size()] self.cancel_transfer(friend_num, file_num, True) diff --git a/toxygen/file_transfers/file_transfers.py b/toxygen/file_transfers/file_transfers.py index 4bbcc18..6673e17 100644 --- a/toxygen/file_transfers/file_transfers.py +++ b/toxygen/file_transfers/file_transfers.py @@ -3,10 +3,10 @@ from os.path import basename, getsize, exists, dirname from os import remove, rename, chdir from time import time, sleep from wrapper.tox import Tox -from PyQt5 import QtCore +from common.event import Event -TOX_FILE_TRANSFER_STATE = { +FILE_TRANSFER_STATE = { 'RUNNING': 0, 'PAUSED_BY_USER': 1, 'CANCELLED': 2, @@ -31,69 +31,58 @@ def is_inline(file_name): return file_name in allowed_inlines or file_name.startswith('qTox_Screenshot_') -# TODO: use events from common.event.py - -class StateSignal(QtCore.QObject): - - signal = QtCore.pyqtSignal(int, float, int) # state, progress, time in sec - - -class TransferFinishedSignal(QtCore.QObject): - - signal = QtCore.pyqtSignal(int, int) # friend number, file number - - -class FileTransfer(QtCore.QObject): +class FileTransfer: """ Superclass for file transfers """ def __init__(self, path, tox, friend_number, size, file_number=None): - QtCore.QObject.__init__(self) self._path = path self._tox = tox self._friend_number = friend_number - self.state = TOX_FILE_TRANSFER_STATE['RUNNING'] + self.state = FILE_TRANSFER_STATE['RUNNING'] self._file_number = file_number self._creation_time = None self._size = float(size) self._done = 0 - self._state_changed = StateSignal() - self._finished = TransferFinishedSignal() + self._state_changed_event = Event() + self._finished_event = Event() self._file_id = None def set_tox(self, tox): self._tox = tox def set_state_changed_handler(self, handler): - self._state_changed.signal.connect(handler) + self._state_changed_event += 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: - t = -1 - else: - 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) + self._finished_event += handler def get_file_number(self): return self._file_number + file_number = property(get_file_number) + def get_friend_number(self): return self._friend_number - def get_id(self): + friend_number = property(get_friend_number) + + def get_file_id(self): return self._file_id + file_id = property(get_file_id) + def get_path(self): return self._path + path = property(get_path) + + def get_size(self): + return self._size + + size = property(get_size) + def cancel(self): self.send_control(TOX_FILE_CONTROL['CANCEL']) if hasattr(self, '_file'): @@ -104,14 +93,14 @@ class FileTransfer(QtCore.QObject): if hasattr(self, '_file'): sleep(0.1) self._file.close() - self.state = TOX_FILE_TRANSFER_STATE['CANCELLED'] + self.state = FILE_TRANSFER_STATE['CANCELLED'] self.signal() def pause(self, by_friend): if not by_friend: self.send_control(TOX_FILE_CONTROL['PAUSE']) else: - self.state = TOX_FILE_TRANSFER_STATE['PAUSED_BY_FRIEND'] + self.state = FILE_TRANSFER_STATE['PAUSED_BY_FRIEND'] self.signal() def send_control(self, control): @@ -122,6 +111,17 @@ class FileTransfer(QtCore.QObject): def get_file_id(self): return self._tox.file_get_file_id(self._friend_number, self._file_number) + def signal(self): + percentage = self._done / self._size if self._size else 0 + if self._creation_time is None or not percentage: + t = -1 + else: + t = ((time() - self._creation_time) / percentage) * (1 - percentage) + self._state_changed_event(self.state, percentage, int(t)) + + def _finished(self): + self._finished_event(self._friend_number, self._file_number) + # ----------------------------------------------------------------------------------------------------------------- # Send file # ----------------------------------------------------------------------------------------------------------------- @@ -136,7 +136,7 @@ class SendTransfer(FileTransfer): else: size = 0 super().__init__(path, tox, friend_number, size) - self.state = TOX_FILE_TRANSFER_STATE['OUTGOING_NOT_STARTED'] + self.state = FILE_TRANSFER_STATE['OUTGOING_NOT_STARTED'] self._file_number = tox.file_send(friend_number, kind, size, file_id, bytes(basename(path), 'utf-8') if path else b'') self._file_id = self.get_file_id() @@ -157,8 +157,8 @@ class SendTransfer(FileTransfer): else: if hasattr(self, '_file'): self._file.close() - self.state = TOX_FILE_TRANSFER_STATE['FINISHED'] - self.finished() + self.state = FILE_TRANSFER_STATE['FINISHED'] + self._finished() self.signal() @@ -183,7 +183,7 @@ class SendFromBuffer(FileTransfer): def __init__(self, tox, friend_number, data, file_name): super().__init__(None, tox, friend_number, len(data)) - self.state = TOX_FILE_TRANSFER_STATE['OUTGOING_NOT_STARTED'] + self.state = FILE_TRANSFER_STATE['OUTGOING_NOT_STARTED'] self._data = data self._file_number = tox.file_send(friend_number, TOX_FILE_KIND['DATA'], len(data), None, bytes(file_name, 'utf-8')) @@ -199,8 +199,8 @@ class SendFromBuffer(FileTransfer): self._tox.file_send_chunk(self._friend_number, self._file_number, position, data) self._done += size else: - self.state = TOX_FILE_TRANSFER_STATE['FINISHED'] - self.finished() + self.state = FILE_TRANSFER_STATE['FINISHED'] + self._finished() self.signal() @@ -250,8 +250,8 @@ class ReceiveTransfer(FileTransfer): self._creation_time = time() if data is None: self._file.close() - self.state = TOX_FILE_TRANSFER_STATE['FINISHED'] - self.finished() + self.state = FILE_TRANSFER_STATE['FINISHED'] + self._finished() else: data = bytearray(data) if self._file_size < position: @@ -286,8 +286,8 @@ class ReceiveToBuffer(FileTransfer): if self._creation_time is None: self._creation_time = time() if data is None: - self.state = TOX_FILE_TRANSFER_STATE['FINISHED'] - self.finished() + self.state = FILE_TRANSFER_STATE['FINISHED'] + self._finished() else: data = bytes(data) l = len(data) @@ -342,8 +342,8 @@ class ReceiveAvatar(ReceiveTransfer): chdir(dirname(avatar_path)) remove(avatar_path) rename(self._path, avatar_path) - self.finished(True) + self._finished(True) - def finished(self, emit=False): + def _finished(self, emit=False): if emit: - super().finished() + super()._finished() diff --git a/toxygen/file_transfers/file_transfers_handler.py b/toxygen/file_transfers/file_transfers_handler.py index 42a69fa..470299c 100644 --- a/toxygen/file_transfers/file_transfers_handler.py +++ b/toxygen/file_transfers/file_transfers_handler.py @@ -8,10 +8,11 @@ import utils.util as util class FileTransfersHandler: - def __init__(self, tox, settings, contact_provider): + def __init__(self, tox, settings, contact_provider, file_transfers_message_service): self._tox = tox self._settings = settings self._contact_provider = contact_provider + self._file_transfers_message_service = file_transfers_message_service self._file_transfers = {} # key = (friend number, file number), value - transfer instance self._paused_file_transfers = dict(settings['paused_file_transfers']) @@ -46,51 +47,17 @@ class FileTransfersHandler: 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_AUTHOR['FRIEND'], - time.time(), - TOX_FILE_TRANSFER_STATE['RUNNING'], - size, - file_name, - friend_number, - file_number) elif inline and size < 1024 * 1024: self.accept_transfer(None, '', friend_number, file_number, size, True) - tm = TransferMessage(MESSAGE_AUTHOR['FRIEND'], - time.time(), - TOX_FILE_TRANSFER_STATE['RUNNING'], - size, - file_name, - friend_number, - file_number) elif auto: path = self._settings['auto_accept_path'] or util.curr_directory() self.accept_transfer(None, path + '/' + file_name, friend_number, file_number, size) - tm = TransferMessage(MESSAGE_AUTHOR['FRIEND'], - time.time(), - TOX_FILE_TRANSFER_STATE['RUNNING'], - size, - file_name, - friend_number, - file_number) else: - tm = TransferMessage(MESSAGE_AUTHOR['FRIEND'], - time.time(), - TOX_FILE_TRANSFER_STATE['INCOMING_NOT_STARTED'], - size, - file_name, - friend_number, - file_number) accepted = False - if friend_number == self.get_active_number() and self.is_active_a_friend(): - item = self.create_file_transfer_item(tm) - if accepted: - self._file_transfers[(friend_number, file_number)].set_state_changed_handler(item.update_transfer_state) - self._messages.scrollToBottom() - else: - friend.actions = True - friend.append_message(tm) + self._file_transfers_message_service.add_incoming_transfer_message( + friend, accepted, size, file_name,file_number) def cancel_transfer(self, friend_number, file_number, already_cancelled=False): """ @@ -100,7 +67,7 @@ class FileTransfersHandler: :param already_cancelled: was cancelled by friend """ i = self._get_friend_by_number(friend_number).update_transfer_data(file_number, - TOX_FILE_TRANSFER_STATE['CANCELLED']) + 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: @@ -117,12 +84,11 @@ class FileTransfersHandler: tmp = self._messages.count() + i if tmp >= 0: self._messages.itemWidget( - self._messages.item(tmp)).update_transfer_state(TOX_FILE_TRANSFER_STATE['CANCELLED'], + 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) - self.update() def pause_transfer(self, friend_number, file_number, by_friend=False): """ @@ -130,7 +96,7 @@ class FileTransfersHandler: """ tr = self._file_transfers[(friend_number, file_number)] tr.pause(by_friend) - t = TOX_FILE_TRANSFER_STATE['PAUSED_BY_FRIEND'] if by_friend else TOX_FILE_TRANSFER_STATE['PAUSED_BY_USER'] + 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): @@ -141,7 +107,7 @@ class FileTransfersHandler: # TOX_FILE_TRANSFER_STATE['RUNNING']) tr = self._file_transfers[(friend_number, file_number)] if by_friend: - tr.state = TOX_FILE_TRANSFER_STATE['RUNNING'] + tr.state = FILE_TRANSFER_STATE['RUNNING'] tr.signal() else: tr.send_control(TOX_FILE_CONTROL['RESUME']) @@ -177,7 +143,7 @@ class FileTransfersHandler: 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, - TOX_FILE_TRANSFER_STATE['RUNNING']) + FILE_TRANSFER_STATE['RUNNING']) def send_screenshot(self, data, friend_number): """ @@ -201,18 +167,9 @@ class FileTransfersHandler: 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_AUTHOR['ME'], - time.time(), - TOX_FILE_TRANSFER_STATE['OUTGOING_NOT_STARTED'], - len(data), - file_name, - friend.number, - st.get_file_number()) - item = self.create_file_transfer_item(tm) - friend.append_message(tm) - st.set_state_changed_handler(item.update_transfer_state) - self._messages.scrollToBottom() + 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) def send_file(self, path, friend_number, is_resend=False, file_id=None): """ @@ -232,19 +189,10 @@ class FileTransfersHandler: 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 - # tm = TransferMessage(MESSAGE_AUTHOR['ME'], - # time.time(), - # TOX_FILE_TRANSFER_STATE['OUTGOING_NOT_STARTED'], - # os.path.getsize(path), - # os.path.basename(path), - # friend_number, - # st.get_file_number()) - # if friend_number == self.get_active_number(): - # item = self.create_file_transfer_item(tm) - # st.set_state_changed_handler(item.update_transfer_state) - # self._messages.scrollToBottom() - # self._contacts[friend_number].append_message(tm) + 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) def incoming_chunk(self, friend_number, file_number, position, data): """ @@ -266,21 +214,13 @@ class FileTransfersHandler: elif t is ReceiveToBuffer or (t is SendFromBuffer and self._settings['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() and self.is_active_a_friend(): - count = self._messages.count() - if count + i + 1 >= 0: - elem = QtWidgets.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) - self._messages.scrollToBottom() + index = self._get_friend_by_number(friend_number).update_transfer_data(file_number, + FILE_TRANSFER_STATE['FINISHED'], + 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, - TOX_FILE_TRANSFER_STATE['FINISHED']) + FILE_TRANSFER_STATE['FINISHED']) del self._file_transfers[(friend_number, file_number)] del transfer @@ -288,7 +228,7 @@ class FileTransfersHandler: friend = self._get_friend_by_number(friend_number) friend.remove_invalid_unsent_files() files = friend.get_unsent_files() - try: + try: # TODO: fix for fl in files: data = fl.get_data() if data[1] is not None: @@ -327,7 +267,7 @@ class FileTransfersHandler: """ friend = self._get_friend_by_number(friend_number) ra = ReceiveAvatar(friend.get_contact_avatar_path(), self._tox, friend_number, size, file_number) - if ra.state != TOX_FILE_TRANSFER_STATE['CANCELLED']: + if ra.state != FILE_TRANSFER_STATE['CANCELLED']: self._file_transfers[(friend_number, file_number)] = ra ra.set_transfer_finished_handler(self.transfer_finished) else: diff --git a/toxygen/file_transfers/file_transfers_messages_service.py b/toxygen/file_transfers/file_transfers_messages_service.py new file mode 100644 index 0000000..963eeb6 --- /dev/null +++ b/toxygen/file_transfers/file_transfers_messages_service.py @@ -0,0 +1,58 @@ +from messenger.messenger import * +import utils.util as util +from file_transfers.file_transfers import * + + +class FileTransfersMessagesService: + + def __init__(self, contacts_manager, messages_items_factory, profile, main_screen): + self._contacts_manager = contacts_manager + self._messages_items_factory = messages_items_factory + self._profile = profile + self._messages = main_screen.messages + + def add_incoming_transfer_message(self, friend, accepted, size, file_name, file_number): + author = MessageAuthor(friend.name, MESSAGE_AUTHOR['FRIEND']) + status = FILE_TRANSFER_STATE['RUNNING'] if accepted else FILE_TRANSFER_STATE['INCOMING_NOT_STARTED'] + tm = TransferMessage(author, util.get_unix_time(), status, size, file_name, friend.number, file_number) + + if self._is_active(friend.number): + self._create_file_transfer_item(tm) + self._messages.scrollToBottom() + else: + friend.actions = True + + friend.append_message(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'] + tm = TransferMessage(author, util.get_unix_time(), status, size, file_name, friend.number, file_number) + + if self._is_active(friend.number): + self._create_file_transfer_item(tm) + self._messages.scrollToBottom() + + friend.append_message(tm) + + def add_inline_message(self, transfer, index): + if self._is_active(transfer.friend_number): + count = self._messages.count() + if count + index + 1 >= 0: + self._create_inline_item(transfer.data, count + index + 1) + + # ----------------------------------------------------------------------------------------------------------------- + # Private methods + # ----------------------------------------------------------------------------------------------------------------- + + def _is_active(self, friend_number): + if not self._contacts_manager.is_active_a_friend(): + return False + + return friend_number == self._contacts_manager.get_active_number() + + def _create_file_transfer_item(self, tm): + return self._messages_items_factory.create_file_transfer_item(tm) + + def _create_inline_item(self, data, position): + return self._messages_items_factory.create_inline_item(data, False, position) diff --git a/toxygen/messenger/messages.py b/toxygen/messenger/messages.py index 42a0fd1..0dfc797 100644 --- a/toxygen/messenger/messages.py +++ b/toxygen/messenger/messages.py @@ -126,27 +126,43 @@ class TransferMessage(Message): Message with info about file transfer """ - def __init__(self, owner, time, status, size, name, friend_number, file_number): - super().__init__(MESSAGE_TYPE['FILE_TRANSFER'], owner, time) - self._status = status + def __init__(self, author, time, state, size, file_name, friend_number, file_number): + super().__init__(MESSAGE_TYPE['FILE_TRANSFER'], author, time) + self._state = state self._size = size - self._file_name = name + self._file_name = file_name self._friend_number, self._file_number = friend_number, file_number def is_active(self, file_number): - return self._file_number == file_number and self._status not in (2, 3) + return self._file_number == file_number and self._state not in (2, 3) def get_friend_number(self): return self._friend_number + friend_number = property(get_friend_number) + def get_file_number(self): return self._file_number - def get_status(self): - return self._status + file_number = property(get_file_number) - def set_status(self, value): - self._status = value + def get_state(self): + return self._state + + def set_state(self, value): + self._state = value + + state = property(get_state, set_state) + + def get_size(self): + return self._size + + size = property(get_size) + + def get_file_name(self): + return self._file_name + + file_name = property(get_file_name) class UnsentFile(Message): diff --git a/toxygen/ui/contact_items.py b/toxygen/ui/contact_items.py index 25b3c0a..2ad3ad2 100644 --- a/toxygen/ui/contact_items.py +++ b/toxygen/ui/contact_items.py @@ -1,7 +1,7 @@ from wrapper.toxcore_enums_and_consts import * from PyQt5 import QtCore, QtGui, QtWidgets from contacts import profile -from file_transfers.file_transfers import TOX_FILE_TRANSFER_STATE, PAUSED_FILE_TRANSFERS, DO_NOT_SHOW_ACCEPT_BUTTON, ACTIVE_FILE_TRANSFERS, SHOW_PROGRESS_BAR +from file_transfers.file_transfers import FILE_TRANSFER_STATE, PAUSED_FILE_TRANSFERS, DO_NOT_SHOW_ACCEPT_BUTTON, ACTIVE_FILE_TRANSFERS, SHOW_PROGRESS_BAR from utils.util import * from ui.widgets import DataLabel, create_menu from user_data import settings diff --git a/toxygen/ui/items_factories.py b/toxygen/ui/items_factories.py index dc9c002..3257279 100644 --- a/toxygen/ui/items_factories.py +++ b/toxygen/ui/items_factories.py @@ -18,16 +18,18 @@ class FriendItemsFactory: return item -# TODO: accept messages everywhere instead of params - class MessagesItemsFactory: def __init__(self, settings, plugin_loader, smiley_loader, main_screen, delete_action): + self._file_transfers_handler = None self._settings, self._plugin_loader = settings, plugin_loader self._smiley_loader, self._delete_action = smiley_loader, delete_action self._messages = main_screen.messages self._message_edit = main_screen.messageEdit + def set_file_transfers_handler(self, file_transfers_handler): + self._file_transfers_handler = file_transfers_handler + def create_message_item(self, message, append=True, pixmap=None): item = message.get_widget(self._settings, self._create_message_browser, self._delete_action, self._messages) @@ -43,24 +45,20 @@ class MessagesItemsFactory: return item - def create_inline_item(self, data, append): + def create_inline_item(self, data, append, position=0): elem = QtWidgets.QListWidgetItem() item = InlineImageItem(data, self._messages.width(), elem) elem.setSizeHint(QtCore.QSize(self._messages.width(), item.height())) if append: self._messages.addItem(elem) else: - self._messages.insertItem(0, elem) + self._messages.insertItem(position, elem) self._messages.setItemWidget(elem, item) return item - def create_unsent_file_item(self, file_name, size, name, time, append): - item = UnsentFileItem(file_name, - size, - name, - time, - self._messages.width()) + def create_unsent_file_item(self, tm, append): + item = UnsentFileItem(self._file_transfers_handler, self._settings, tm, self._messages.width()) elem = QtWidgets.QListWidgetItem() elem.setSizeHint(QtCore.QSize(self._messages.width() - 30, 34)) if append: @@ -71,9 +69,8 @@ class MessagesItemsFactory: return item - def create_file_transfer_item(self, data, append=True): - data.append(self._messages.width()) - item = FileTransferItem(*data) + def create_file_transfer_item(self, tm, append=True): + item = FileTransferItem(self._file_transfers_handler, self._settings, tm, self._messages.width()) elem = QtWidgets.QListWidgetItem() elem.setSizeHint(QtCore.QSize(self._messages.width() - 30, 34)) if append: diff --git a/toxygen/ui/messages_widgets.py b/toxygen/ui/messages_widgets.py index dea7a5c..89e4ac3 100644 --- a/toxygen/ui/messages_widgets.py +++ b/toxygen/ui/messages_widgets.py @@ -6,7 +6,9 @@ import utils.util as util import ui.menu as menu import html as h import re +from ui.widgets import * from messenger.messages import MESSAGE_AUTHOR +from file_transfers.file_transfers import * class MessageBrowser(QtWidgets.QTextBrowser): @@ -216,60 +218,63 @@ class MessageItem(QtWidgets.QWidget): class FileTransferItem(QtWidgets.QListWidget): - def __init__(self, file_name, size, time, user, friend_number, file_number, state, width, parent=None): + def __init__(self, file_transfers_handler, settings, transfer_message, width, parent=None): QtWidgets.QListWidget.__init__(self, parent) + self._file_transfers_handler = file_transfers_handler self.resize(QtCore.QSize(width, 34)) - if state == TOX_FILE_TRANSFER_STATE['CANCELLED']: + if transfer_message.state == FILE_TRANSFER_STATE['CANCELLED']: self.setStyleSheet('QListWidget { border: 1px solid #B40404; }') - elif state in PAUSED_FILE_TRANSFERS: + elif transfer_message.state in PAUSED_FILE_TRANSFERS: self.setStyleSheet('QListWidget { border: 1px solid #FF8000; }') else: self.setStyleSheet('QListWidget { border: 1px solid green; }') - self.state = state + self.state = transfer_message.state self.name = DataLabel(self) self.name.setGeometry(QtCore.QRect(3, 7, 95, 25)) self.name.setTextFormat(QtCore.Qt.PlainText) font = QtGui.QFont() - # FIXME - font.setFamily(settings.Settings.get_instance()['font']) + font.setFamily(settings['font']) font.setPointSize(11) font.setBold(True) self.name.setFont(font) - self.name.setText(user) + self.name.setText(transfer_message.author.name) self.time = QtWidgets.QLabel(self) self.time.setGeometry(QtCore.QRect(width - 60, 7, 50, 25)) font.setPointSize(10) font.setBold(False) self.time.setFont(font) - self.time.setText(convert_time(time)) + self.time.setText(util.convert_time(time)) self.cancel = QtWidgets.QPushButton(self) self.cancel.setGeometry(QtCore.QRect(width - 125, 2, 30, 30)) - pixmap = QtGui.QPixmap(curr_directory() + '/images/decline.png') + pixmap = QtGui.QPixmap(util.join_path(util.get_images_directory(), 'decline.png')) icon = QtGui.QIcon(pixmap) self.cancel.setIcon(icon) self.cancel.setIconSize(QtCore.QSize(30, 30)) - self.cancel.setVisible(state in ACTIVE_FILE_TRANSFERS) - self.cancel.clicked.connect(lambda: self.cancel_transfer(friend_number, file_number)) + self.cancel.setVisible(transfer_message.state in ACTIVE_FILE_TRANSFERS) + self.cancel.clicked.connect( + lambda: self.cancel_transfer(transfer_message.friend_number, transfer_message.file_number)) self.cancel.setStyleSheet('QPushButton:hover { border: 1px solid #3A3939; background-color: none;}') self.accept_or_pause = QtWidgets.QPushButton(self) self.accept_or_pause.setGeometry(QtCore.QRect(width - 170, 2, 30, 30)) - if state == TOX_FILE_TRANSFER_STATE['INCOMING_NOT_STARTED']: + if transfer_message.state == FILE_TRANSFER_STATE['INCOMING_NOT_STARTED']: self.accept_or_pause.setVisible(True) self.button_update('accept') - elif state in DO_NOT_SHOW_ACCEPT_BUTTON: + elif transfer_message.state in DO_NOT_SHOW_ACCEPT_BUTTON: self.accept_or_pause.setVisible(False) - elif state == TOX_FILE_TRANSFER_STATE['PAUSED_BY_USER']: # setup for continue + elif transfer_message.state == FILE_TRANSFER_STATE['PAUSED_BY_USER']: # setup for continue self.accept_or_pause.setVisible(True) self.button_update('resume') else: # pause self.accept_or_pause.setVisible(True) self.button_update('pause') - self.accept_or_pause.clicked.connect(lambda: self.accept_or_pause_transfer(friend_number, file_number, size)) + self.accept_or_pause.clicked.connect( + lambda: self.accept_or_pause_transfer(transfer_message.friend_number, transfer_message.file_number, + transfer_message.size)) self.accept_or_pause.setStyleSheet('QPushButton:hover { border: 1px solid #3A3939; background-color: none}') @@ -277,64 +282,60 @@ class FileTransferItem(QtWidgets.QListWidget): self.pb.setGeometry(QtCore.QRect(100, 7, 100, 20)) self.pb.setValue(0) self.pb.setStyleSheet('QProgressBar { background-color: #302F2F; }') - self.pb.setVisible(state in SHOW_PROGRESS_BAR) + self.pb.setVisible(transfer_message.state in SHOW_PROGRESS_BAR) self.file_name = DataLabel(self) self.file_name.setGeometry(QtCore.QRect(210, 7, width - 420, 20)) font.setPointSize(12) self.file_name.setFont(font) - file_size = size // 1024 + file_size = transfer_message.size // 1024 if not file_size: - file_size = '{}B'.format(size) + file_size = '{}B'.format(transfer_message.size) elif file_size >= 1024: file_size = '{}MB'.format(file_size // 1024) else: file_size = '{}KB'.format(file_size) - file_data = '{} {}'.format(file_size, file_name) + file_data = '{} {}'.format(file_size, transfer_message.file_name) self.file_name.setText(file_data) - self.file_name.setToolTip(file_name) - self.saved_name = file_name + self.file_name.setToolTip(transfer_message.file_name) + self.saved_name = transfer_message.file_name self.time_left = QtWidgets.QLabel(self) self.time_left.setGeometry(QtCore.QRect(width - 92, 7, 30, 20)) font.setPointSize(10) self.time_left.setFont(font) - self.time_left.setVisible(state == TOX_FILE_TRANSFER_STATE['RUNNING']) + self.time_left.setVisible(transfer_message.state == FILE_TRANSFER_STATE['RUNNING']) self.setFocusPolicy(QtCore.Qt.NoFocus) self.paused = False def cancel_transfer(self, friend_number, file_number): - pr = profile.Profile.get_instance() - pr.cancel_transfer(friend_number, file_number) + self._file_transfers_handler.cancel_transfer(friend_number, file_number) self.setStyleSheet('QListWidget { border: 1px solid #B40404; }') self.cancel.setVisible(False) self.accept_or_pause.setVisible(False) self.pb.setVisible(False) def accept_or_pause_transfer(self, friend_number, file_number, size): - if self.state == TOX_FILE_TRANSFER_STATE['INCOMING_NOT_STARTED']: - directory = QtWidgets.QFileDialog.getExistingDirectory(self, - QtWidgets.QApplication.translate("MainWindow", 'Choose folder'), - curr_directory(), - QtWidgets.QFileDialog.ShowDirsOnly | QtWidgets.QFileDialog.DontUseNativeDialog) + if self.state == FILE_TRANSFER_STATE['INCOMING_NOT_STARTED']: + directory = util_ui.directory_dialog(util_ui.tr('Choose folder')) self.pb.setVisible(True) if directory: - pr = profile.Profile.get_instance() - pr.accept_transfer(self, directory + '/' + self.saved_name, friend_number, file_number, size) + self._file_transfer_handler.accept_transfer(self, directory + '/' + self.saved_name, + friend_number, file_number, size) self.button_update('pause') - elif self.state == TOX_FILE_TRANSFER_STATE['PAUSED_BY_USER']: # resume + elif self.state == FILE_TRANSFER_STATE['PAUSED_BY_USER']: # resume self.paused = False - profile.Profile.get_instance().resume_transfer(friend_number, file_number) + self._file_transfer_handler.resume_transfer(friend_number, file_number) self.button_update('pause') - self.state = TOX_FILE_TRANSFER_STATE['RUNNING'] + self.state = FILE_TRANSFER_STATE['RUNNING'] else: # pause self.paused = True - self.state = TOX_FILE_TRANSFER_STATE['PAUSED_BY_USER'] - profile.Profile.get_instance().pause_transfer(friend_number, file_number) + self.state = FILE_TRANSFER_STATE['PAUSED_BY_USER'] + self._file_transfer_handler.pause_transfer(friend_number, file_number) self.button_update('resume') self.accept_or_pause.clearFocus() def button_update(self, path): - pixmap = QtGui.QPixmap(curr_directory() + '/images/{}.png'.format(path)) + pixmap = QtGui.QPixmap(util.join_path(util.get_images_directory(), '{}.png'.format(path))) icon = QtGui.QIcon(pixmap) self.accept_or_pause.setIcon(icon) self.accept_or_pause.setIconSize(QtCore.QSize(30, 30)) @@ -345,31 +346,31 @@ class FileTransferItem(QtWidgets.QListWidget): m, s = divmod(time, 60) self.time_left.setText('{0:02d}:{1:02d}'.format(m, s)) if self.state != state and self.state in ACTIVE_FILE_TRANSFERS: - if state == TOX_FILE_TRANSFER_STATE['CANCELLED']: + if state == FILE_TRANSFER_STATE['CANCELLED']: self.setStyleSheet('QListWidget { border: 1px solid #B40404; }') self.cancel.setVisible(False) self.accept_or_pause.setVisible(False) self.pb.setVisible(False) self.state = state self.time_left.setVisible(False) - elif state == TOX_FILE_TRANSFER_STATE['FINISHED']: + elif state == FILE_TRANSFER_STATE['FINISHED']: self.accept_or_pause.setVisible(False) self.pb.setVisible(False) self.cancel.setVisible(False) self.setStyleSheet('QListWidget { border: 1px solid green; }') self.state = state self.time_left.setVisible(False) - elif state == TOX_FILE_TRANSFER_STATE['PAUSED_BY_FRIEND']: + elif state == FILE_TRANSFER_STATE['PAUSED_BY_FRIEND']: self.accept_or_pause.setVisible(False) self.setStyleSheet('QListWidget { border: 1px solid #FF8000; }') self.state = state self.time_left.setVisible(False) - elif state == TOX_FILE_TRANSFER_STATE['PAUSED_BY_USER']: + elif state == FILE_TRANSFER_STATE['PAUSED_BY_USER']: self.button_update('resume') # setup button continue self.setStyleSheet('QListWidget { border: 1px solid green; }') self.state = state self.time_left.setVisible(False) - elif state == TOX_FILE_TRANSFER_STATE['OUTGOING_NOT_STARTED']: + elif state == FILE_TRANSFER_STATE['OUTGOING_NOT_STARTED']: self.setStyleSheet('QListWidget { border: 1px solid #FF8000; }') self.accept_or_pause.setVisible(False) self.time_left.setVisible(False) @@ -382,24 +383,23 @@ class FileTransferItem(QtWidgets.QListWidget): self.state = state self.time_left.setVisible(True) - def mark_as_sent(self): + @staticmethod + def mark_as_sent(): return False class UnsentFileItem(FileTransferItem): - def __init__(self, file_name, size, user, time, width, parent=None): - super(UnsentFileItem, self).__init__(file_name, size, time, user, -1, -1, - TOX_FILE_TRANSFER_STATE['PAUSED_BY_FRIEND'], width, parent) + def __init__(self, file_transfers_handler, settings, transfer_message, width, parent=None): + super().__init__(file_transfers_handler, settings, transfer_message, width, parent) self._time = time self.pb.setVisible(False) - movie = QtGui.QMovie(join_path(get_images_directory(), 'spinner.gif')) + movie = QtGui.QMovie(util.join_path(util.get_images_directory(), 'spinner.gif')) self.time.setMovie(movie) movie.start() def cancel_transfer(self, *args): - pr = profile.Profile.get_instance() - pr.cancel_not_started_transfer(self._time) + self._file_transfers_handler.cancel_not_started_transfer(self._time) class InlineImageItem(QtWidgets.QScrollArea): @@ -443,15 +443,11 @@ class InlineImageItem(QtWidgets.QScrollArea): self._full_size = not self._full_size self._elem.setSizeHint(QtCore.QSize(self.width(), self.height())) elif event.button() == QtCore.Qt.RightButton: # save inline - # TODO: dialog - directory = QtWidgets.QFileDialog.getExistingDirectory(self, - QtWidgets.QApplication.translate("MainWindow", - 'Choose folder'), - curr_directory(), - QtWidgets.QFileDialog.ShowDirsOnly | QtWidgets.QFileDialog.DontUseNativeDialog) + directory = util_ui.directory_dialog(util_ui.tr('Choose folder')) if directory: - fl = QtCore.QFile(directory + '/toxygen_inline_' + curr_time().replace(':', '_') + '.png') + fl = QtCore.QFile(directory + '/toxygen_inline_' + util.curr_time().replace(':', '_') + '.png') self._pixmap.save(fl, 'PNG') - def mark_as_sent(self): + @staticmethod + def mark_as_sent(): return False