diff --git a/toxygen/app.py b/toxygen/app.py index 40fb7c6..03509a6 100644 --- a/toxygen/app.py +++ b/toxygen/app.py @@ -245,7 +245,7 @@ class App: self._save_profile() except Exception as ex: print(ex) - log('Profile creation exception: ' + str(ex)) + util.log('Profile creation exception: ' + str(ex)) text = util_ui.tr('Profile saving error! Does Toxygen have permission to write to this directory?') util_ui.message_box(text, util_ui.tr('Error')) return @@ -316,7 +316,7 @@ class App: 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) + file_transfers_message_service, profile) 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, diff --git a/toxygen/contacts/contact.py b/toxygen/contacts/contact.py index 71248db..7faf36d 100644 --- a/toxygen/contacts/contact.py +++ b/toxygen/contacts/contact.py @@ -1,6 +1,5 @@ from history.database import * from contacts import basecontact, common -import utils.util as util from messenger.messages import * from contacts.contact_menu import * from file_transfers import file_transfers as ft @@ -119,7 +118,7 @@ class Contact(basecontact.BaseContact): """ :return list of unsent messages """ - messages = filter(lambda x: x.get_owner() == MESSAGE_AUTHOR['NOT_SENT'], self._corr) + messages = filter(lambda x: x.author.type == MESSAGE_AUTHOR['NOT_SENT'], self._corr) return list(messages) def get_unsent_messages_for_saving(self): @@ -127,12 +126,12 @@ class Contact(basecontact.BaseContact): :return list of unsent messages for saving """ messages = filter(lambda x: x.get_type() in (MESSAGE_TYPE['TEXT'], MESSAGE_TYPE['ACTION']) - and x.get_owner() == MESSAGE_AUTHOR['NOT_SENT'], self._corr) + and x.author.type == MESSAGE_AUTHOR['NOT_SENT'], self._corr) return list(map(lambda x: x.get_data(), messages)) def mark_as_sent(self): try: - message = list(filter(lambda x: x.get_owner() == MESSAGE_AUTHOR['NOT_SENT'], self._corr))[0] + message = list(filter(lambda x: x.author.type == MESSAGE_AUTHOR['NOT_SENT'], self._corr))[0] message.mark_as_sent() except Exception as ex: util.log('Mark as sent ex: ' + str(ex)) diff --git a/toxygen/contacts/profile.py b/toxygen/contacts/profile.py index b4dbaf2..63775ff 100644 --- a/toxygen/contacts/profile.py +++ b/toxygen/contacts/profile.py @@ -2,9 +2,9 @@ from contacts.friend import * from file_transfers.file_transfers import * import time from contacts import basecontact -from contacts.group_chat import * import utils.ui as util_ui import random +import threading class Profile(basecontact.BaseContact): @@ -29,6 +29,7 @@ class Profile(basecontact.BaseContact): self._load_history = True self._waiting_for_reconnection = False self._contacts_manager = None + self._timer = threading.Timer(50, self.reconnect) # ----------------------------------------------------------------------------------------------------------------- # Edit current user's data @@ -47,7 +48,7 @@ class Profile(basecontact.BaseContact): self._tox.self_set_status(status) elif not self._waiting_for_reconnection: self._waiting_for_reconnection = True - QtCore.QTimer.singleShot(50000, self.reconnect) + self._timer.start() def set_name(self, value): if self.name == value: @@ -125,7 +126,7 @@ class Profile(basecontact.BaseContact): if self.status is None or all(list(map(lambda x: x.status is None, self._contacts))) and len(self._contacts): self._waiting_for_reconnection = True self.reset(self._screen.reset) - QtCore.QTimer.singleShot(50000, self.reconnect) + self._timer.start() def close(self): for friend in filter(lambda x: type(x) is Friend, self._contacts): @@ -135,13 +136,3 @@ class Profile(basecontact.BaseContact): if hasattr(self, '_call'): self._call.stop() del self._call - - def reset_avatar(self, generate_new): - super().reset_avatar(generate_new) - for friend in filter(lambda x: x.status is not None, self._contacts): - self.send_avatar(friend.number) - - def set_avatar(self, data): - super().set_avatar(data) - for friend in filter(lambda x: x.status is not None, self._contacts): - self.send_avatar(friend.number) diff --git a/toxygen/file_transfers/file_transfers.py b/toxygen/file_transfers/file_transfers.py index 92d92a6..aa1be58 100644 --- a/toxygen/file_transfers/file_transfers.py +++ b/toxygen/file_transfers/file_transfers.py @@ -40,7 +40,7 @@ class FileTransfer: self._path = path self._tox = tox self._friend_number = friend_number - self.state = FILE_TRANSFER_STATE['RUNNING'] + self._state = FILE_TRANSFER_STATE['RUNNING'] self._file_number = file_number self._creation_time = None self._size = float(size) @@ -63,6 +63,15 @@ class FileTransfer: file_number = property(get_file_number) + def get_state(self): + return self._state + + def set_state(self, value): + self._state = value + self._signal() + + state = property(get_state, set_state) + def get_friend_number(self): return self._friend_number @@ -87,30 +96,27 @@ class FileTransfer: self.send_control(TOX_FILE_CONTROL['CANCEL']) if self._file is not None: self._file.close() - self.signal() + self._signal() def cancelled(self): if self._file is not None: self._file.close() 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 = FILE_TRANSFER_STATE['PAUSED_BY_FRIEND'] - self.signal() def send_control(self, control): if self._tox.file_control(self._friend_number, self._file_number, control): self.state = control - self.signal() def get_file_id(self): return self._tox.file_get_file_id(self._friend_number, self._file_number) - def signal(self): + def _signal(self): percentage = self._done / self._size if self._size else 0 if self._creation_time is None or not percentage: t = -1 @@ -154,11 +160,11 @@ class SendTransfer(FileTransfer): self._tox.file_send_chunk(self._friend_number, self._file_number, position, data) self._done += size else: - if hasattr(self, '_file'): + if self._file is not None: self._file.close() self.state = FILE_TRANSFER_STATE['FINISHED'] self._finished() - self.signal() + self._signal() class SendAvatar(SendTransfer): @@ -200,7 +206,7 @@ class SendFromBuffer(FileTransfer): else: self.state = FILE_TRANSFER_STATE['FINISHED'] self._finished() - self.signal() + self._signal() class SendFromFileBuffer(SendTransfer): @@ -265,7 +271,7 @@ class ReceiveTransfer(FileTransfer): if position + l > self._file_size: self._file_size = position + l self._done += l - self.signal() + self._signal() class ReceiveToBuffer(FileTransfer): @@ -296,7 +302,7 @@ class ReceiveToBuffer(FileTransfer): if position + l > self._data_size: self._data_size = position + l self._done += l - self.signal() + self._signal() class ReceiveAvatar(ReceiveTransfer): @@ -338,8 +344,4 @@ class ReceiveAvatar(ReceiveTransfer): chdir(dirname(avatar_path)) remove(avatar_path) rename(self._path, avatar_path) - self._finished(True) - - def _finished(self, emit=False): - if emit: - super()._finished() + self._finished() diff --git a/toxygen/file_transfers/file_transfers_handler.py b/toxygen/file_transfers/file_transfers_handler.py index 3d51767..bb4041f 100644 --- a/toxygen/file_transfers/file_transfers_handler.py +++ b/toxygen/file_transfers/file_transfers_handler.py @@ -5,7 +5,7 @@ import utils.util as util class FileTransfersHandler: - def __init__(self, tox, settings, contact_provider, file_transfers_message_service): + def __init__(self, tox, settings, contact_provider, file_transfers_message_service, profile): self._tox = tox self._settings = settings self._contact_provider = contact_provider @@ -14,6 +14,8 @@ class FileTransfersHandler: # key = (friend number, file number), value - transfer instance self._paused_file_transfers = dict(settings['paused_file_transfers']) # key - file id, value: [path, friend number, is incoming, start position] + + profile.avatar_changed_event.add_callback(self._send_avatar_to_contacts) def __del__(self): self._settings['paused_file_transfers'] = self._paused_file_transfers if self._settings['resend_files'] else {} @@ -43,18 +45,22 @@ 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._file_transfers_message_service.add_incoming_transfer_message( + friend, accepted, size, file_name, file_number) self.accept_transfer(data[0], friend_number, file_number, size, False, pos) elif inline and size < 1024 * 1024: + self._file_transfers_message_service.add_incoming_transfer_message( + friend, accepted, size, file_name, file_number) self.accept_transfer('', friend_number, file_number, size, True) - elif auto: path = self._settings['auto_accept_path'] or util.curr_directory() + self._file_transfers_message_service.add_incoming_transfer_message( + friend, accepted, size, file_name, file_number) 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) + 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): """ @@ -92,7 +98,6 @@ class FileTransfersHandler: tr = self._file_transfers[(friend_number, file_number)] if by_friend: tr.state = FILE_TRANSFER_STATE['RUNNING'] - tr.signal() else: tr.send_control(TOX_FILE_CONTROL['RESUME']) @@ -117,7 +122,7 @@ class FileTransfersHandler: 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']) + rt.send_control(TOX_FILE_CONTROL['RESUME']) def send_screenshot(self, data, friend_number): """ @@ -140,11 +145,7 @@ class FileTransfersHandler: 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) - file_number = st.get_file_number() - self._file_transfers[(friend.number, file_number)] = st - 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) + self._send_file_add_handlers(st, friend, file_name) def send_file(self, path, friend_number, is_resend=False, file_id=None): """ @@ -163,12 +164,8 @@ class FileTransfersHandler: 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) - file_number = st.get_file_number() - self._file_transfers[(friend_number, file_number)] = st file_name = os.path.basename(path) - 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) + self._send_file_add_handlers(st, friend, file_name) def incoming_chunk(self, friend_number, file_number, position, data): """ @@ -244,6 +241,11 @@ class FileTransfersHandler: else: friend.reset_avatar(self._settings['identicons']) + def _send_avatar_to_contacts(self): + friends = self._get_all_friends() + for friend in friends: + self.send_avatar(friend.number) + # ----------------------------------------------------------------------------------------------------------------- # Private methods # ----------------------------------------------------------------------------------------------------------------- @@ -251,6 +253,16 @@ class FileTransfersHandler: def _get_friend_by_number(self, friend_number): return self._contact_provider.get_friend_by_number(friend_number) + def _get_all_friends(self): + return self._contact_provider.get_all_friends() + + def _send_file_add_handlers(self, st, friend, file_name): + st.set_transfer_finished_handler(self.transfer_finished) + file_number = st.get_file_number() + self._file_transfers[(friend.number, file_number)] = st + 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) + @staticmethod def _generate_valid_path(path, from_position): path, file_name = os.path.split(path) diff --git a/toxygen/messenger/messages.py b/toxygen/messenger/messages.py index b14dfd5..9a56aba 100644 --- a/toxygen/messenger/messages.py +++ b/toxygen/messenger/messages.py @@ -72,7 +72,7 @@ class Message: def _get_id(): Message.MESSAGE_ID += 1 - return Message.MESSAGE_ID + return int(Message.MESSAGE_ID) class TextMessage(Message): diff --git a/toxygen/middleware/callbacks.py b/toxygen/middleware/callbacks.py index c9571a2..d4fc7c4 100644 --- a/toxygen/middleware/callbacks.py +++ b/toxygen/middleware/callbacks.py @@ -11,6 +11,7 @@ import numpy as np from middleware.threads import invoke_in_main_thread, execute from notifications.tray import tray_notification from notifications.sound import * +import threading # TODO: gc callbacks and refactoring. Use contact provider instead of manager @@ -49,7 +50,11 @@ def friend_status(contacts_manager, file_transfer_handler, profile, settings): if friend.status is None and settings['sound_notifications'] and profile.status != TOX_USER_STATUS['BUSY']: sound_notification(SOUND_NOTIFICATION['FRIEND_CONNECTION_STATUS']) invoke_in_main_thread(friend.set_status, new_status) - invoke_in_main_thread(QtCore.QTimer.singleShot, 5000, lambda: file_transfer_handler.send_files(friend_number)) + + def set_timer(): + t = threading.Timer(5, lambda: file_transfer_handler.send_files(friend_number)) + t.start() + invoke_in_main_thread(set_timer) invoke_in_main_thread(contacts_manager.update_filtration) return wrapped