From f1c63bb4e8dab2415708025323fcf57fd28e60ef Mon Sep 17 00:00:00 2001 From: ingvar1995 Date: Tue, 15 May 2018 17:00:12 +0300 Subject: [PATCH] history loading after friend switching. refactoring --- toxygen/app.py | 15 ++- toxygen/contacts/contact.py | 4 + toxygen/contacts/contacts_manager.py | 109 ++++++------------ toxygen/contacts/friend_factory.py | 2 +- toxygen/contacts/profile.py | 22 ++-- toxygen/history/database.py | 2 +- .../history/{history_loader.py => history.py} | 5 +- toxygen/messenger/messages.py | 42 +++---- toxygen/messenger/messenger.py | 6 +- toxygen/middleware/callbacks.py | 2 - .../{items_factory.py => items_factories.py} | 42 ++++--- toxygen/ui/list_items.py | 3 - toxygen/ui/main_screen.py | 12 +- toxygen/ui/menu.py | 2 - toxygen/ui/messages_widgets.py | 11 +- 15 files changed, 135 insertions(+), 144 deletions(-) rename toxygen/history/{history_loader.py => history.py} (98%) rename toxygen/ui/{items_factory.py => items_factories.py} (73%) diff --git a/toxygen/app.py b/toxygen/app.py index 20fed55..9f41b47 100644 --- a/toxygen/app.py +++ b/toxygen/app.py @@ -24,9 +24,10 @@ from av.calls_manager import CallsManager from history.database import Database from ui.widgets_factory import WidgetsFactory from smileys.smileys import SmileyLoader -from ui.items_factory import ItemsFactory +from ui.items_factories import MessagesItemsFactory, FriendItemsFactory from messenger.messenger import Messenger from network.tox_dns import ToxDns +from history.history import History class App: @@ -298,13 +299,17 @@ class App: profile = Profile(self._profile_manager, self._tox, self._ms) self._plugin_loader = PluginLoader(self._tox, self._toxes, profile, self._settings) - items_factory = ItemsFactory(self._settings, self._plugin_loader, self._smiley_loader, self._ms) - self._friend_factory = FriendFactory(self._profile_manager, self._settings, self._tox, db, items_factory) + friend_items_factory = FriendItemsFactory(self._settings, self._ms) + self._friend_factory = FriendFactory(self._profile_manager, self._settings, self._tox, db, friend_items_factory) self._contacts_provider = ContactProvider(self._tox, self._friend_factory) + history = History(self._contacts_provider, db, self._settings) + messages_items_factory = MessagesItemsFactory(self._settings, self._plugin_loader, self._smiley_loader, + self._ms, history) self._contacts_manager = ContactsManager(self._tox, self._settings, self._ms, self._profile_manager, - self._contacts_provider, db, self._tox_dns) + self._contacts_provider, history, self._tox_dns, + messages_items_factory) self._messenger = Messenger(self._tox, self._plugin_loader, self._ms, self._contacts_manager, - self._contacts_provider, items_factory, profile) + self._contacts_provider, messages_items_factory, profile) self._file_transfer_handler = FileTransfersHandler(self._tox, self._settings, self._contacts_provider) 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 ddbd1d4..4c19e33 100644 --- a/toxygen/contacts/contact.py +++ b/toxygen/contacts/contact.py @@ -96,6 +96,10 @@ class Contact(basecontact.BaseContact): else: return '' + def remove_messages_widgets(self): + for message in self._corr: + message.remove_widget() + # ----------------------------------------------------------------------------------------------------------------- # Unsent messages # ----------------------------------------------------------------------------------------------------------------- diff --git a/toxygen/contacts/contacts_manager.py b/toxygen/contacts/contacts_manager.py index efe479c..c3db871 100644 --- a/toxygen/contacts/contacts_manager.py +++ b/toxygen/contacts/contacts_manager.py @@ -3,7 +3,7 @@ import utils.ui as util_ui from contacts.friend import Friend from PyQt5 import QtCore, QtGui from wrapper.toxcore_enums_and_consts import * -from history.history_loader import HistoryLoader +from messenger.messages import * class ContactsManager: @@ -11,25 +11,24 @@ class ContactsManager: Represents contacts list. """ - def __init__(self, tox, settings, screen, profile_manager, contact_provider, db, tox_dns): + def __init__(self, tox, settings, screen, profile_manager, contact_provider, history, tox_dns, + messages_items_factory): self._tox = tox self._settings = settings self._screen = screen self._profile_manager = profile_manager self._contact_provider = contact_provider self._tox_dns = tox_dns + self._messages_items_factory = messages_items_factory self._messages = screen.messages self._contacts, self._active_contact = [], -1 self._sorting = settings['sorting'] self._filter_string = '' self._friend_item_height = 40 if settings['compact_mode'] else 70 screen.online_contacts.setCurrentIndex(int(self._sorting)) - self._history = HistoryLoader(contact_provider, db, settings) + self._history = history self._load_contacts() - def __del__(self): - del self._history - def get_contact(self, num): if num < 0 or num >= len(self._contacts): return None @@ -55,10 +54,10 @@ class ContactsManager: def get_active(self): return self._active_contact - def set_active(self, value=None): + def set_active(self, value): """ Change current active friend or update info - :param value: number of new active friend in friend's list or None to update active user's data + :param value: number of new active friend in friend's list """ if value is None and self._active_contact == -1: # nothing to update return @@ -76,67 +75,34 @@ class ContactsManager: self._screen.typing.setVisible(False) current_contact = self.get_curr_contact() if current_contact is not None: + current_contact.remove_messages_widgets() # TODO: if required self._unsubscribe_from_events(current_contact) - if value is not None: - if self._active_contact + 1 and self._active_contact != value: - try: - current_contact.curr_text = self._screen.messageEdit.toPlainText() - except: - pass - friend = self._contacts[value] - self._subscribe_to_events(friend) - friend.remove_invalid_unsent_files() - if self._active_contact != value: - self._screen.messageEdit.setPlainText(friend.curr_text) - self._active_contact = value - friend.reset_messages() - if not self._settings['save_history']: - friend.delete_old_messages() - self._messages.clear() - # friend.load_corr() - # messages = friend.get_corr()[-PAGE_SIZE:] - # self._load_history = False - # for message in messages: - # if message.get_type() <= 1: - # data = message.get_data() - # self.create_message_item(data[0], - # data[2], - # data[1], - # data[3]) - # elif message.get_type() == MESSAGE_TYPE['FILE_TRANSFER']: - # if message.get_status() is None: - # self.create_unsent_file_item(message) - # continue - # item = self.create_file_transfer_item(message) - # if message.get_status() in ACTIVE_FILE_TRANSFERS: # active file transfer - # try: - # ft = self._file_transfers[(message.get_friend_number(), message.get_file_number())] - # ft.set_state_changed_handler(item.update_transfer_state) - # ft.signal() - # except: - # print('Incoming not started transfer - no info found') - # elif message.get_type() == MESSAGE_TYPE['INLINE']: # inline - # self.create_inline_item(message.get_data()) - # elif message.get_type() < 5: # info message - # data = message.get_data() - # self.create_message_item(data[0], - # data[2], - # '', - # data[3]) - # else: - # data = message.get_data() - # self.create_gc_message_item(data[0], data[2], data[1], data[4], data[3]) - # self._messages.scrollToBottom() - # self._load_history = True - # if value in self._call: - # self._screen.active_call() - # elif value in self._incoming_calls: - # self._screen.incoming_call() - # else: - # self._screen.call_finished() - else: - friend = self.get_curr_contact() - # TODO: to separate method + + if self._active_contact + 1 and self._active_contact != value: + try: + current_contact.curr_text = self._screen.messageEdit.toPlainText() + except: + pass + friend = self._contacts[value] + self._subscribe_to_events(friend) + friend.remove_invalid_unsent_files() + if self._active_contact != value: + self._screen.messageEdit.setPlainText(friend.curr_text) + self._active_contact = value + friend.reset_messages() + if not self._settings['save_history']: + friend.delete_old_messages() + self._messages.clear() + friend.load_corr() + corr = friend.get_corr()[-PAGE_SIZE:] + for message in corr: + self._messages_items_factory.create_message_item(message) + # if value in self._call: + # self._screen.active_call() + # elif value in self._incoming_calls: + # self._screen.incoming_call() + # else: + # self._screen.call_finished() self._screen.account_status.setToolTip(friend.get_full_status()) avatar_path = friend.get_avatar_path() @@ -150,7 +116,7 @@ class ContactsManager: active_friend = property(get_active, set_active) - def set_active_by_number_and_type(self, number, is_friend): + def set_active_by_number_and_type(self, number, is_friend): # TODO: by id for i in range(len(self._contacts)): c = self._contacts[i] if c.number == number and (type(c) is Friend == is_friend): @@ -468,5 +434,6 @@ class ContactsManager: def _current_contact_avatar_changed(self, avatar_path): width = self._screen.account_avatar.width() pixmap = QtGui.QPixmap(avatar_path) - self._screen.account_avatar.avatar_label.setPixmap(pixmap.scaled(width, width, QtCore.Qt.KeepAspectRatio, - QtCore.Qt.SmoothTransformation)) + self._screen.avatar_label.setPixmap(pixmap.scaled(width, width, + QtCore.Qt.KeepAspectRatio, + QtCore.Qt.SmoothTransformation)) diff --git a/toxygen/contacts/friend_factory.py b/toxygen/contacts/friend_factory.py index 6803c61..9ba859f 100644 --- a/toxygen/contacts/friend_factory.py +++ b/toxygen/contacts/friend_factory.py @@ -39,4 +39,4 @@ class FriendFactory: Method-factory :return: new widget for friend instance """ - return self._items_factory.friend_item() + return self._items_factory.create_friend_item() diff --git a/toxygen/contacts/profile.py b/toxygen/contacts/profile.py index 8102f56..302dc0b 100644 --- a/toxygen/contacts/profile.py +++ b/toxygen/contacts/profile.py @@ -129,8 +129,8 @@ class Profile(basecontact.BaseContact): pixmap = self.get_curr_friend().get_pixmap() else: pixmap = self.get_pixmap() - return self._factory.message_item(text, time, name, owner != MESSAGE_OWNER['NOT_SENT'], - message_type, append, pixmap) + return self._factory.create_message_item(text, time, name, owner != MESSAGE_OWNER['NOT_SENT'], + message_type, append, pixmap) def create_gc_message_item(self, text, time, owner, name, message_type, append=True): pixmap = None @@ -139,24 +139,24 @@ class Profile(basecontact.BaseContact): pixmap = self.get_curr_friend().get_pixmap() else: pixmap = self.get_pixmap() - return self._factory.message_item(text, time, name, True, - message_type - 5, append, pixmap) + return self._factory.create_message_item(text, time, name, True, + message_type - 5, append, pixmap) def create_file_transfer_item(self, tm, append=True): data = list(tm.get_data()) data[3] = self.get_friend_by_number(data[4]).name if data[3] else self._name - return self._factory.file_transfer_item(data, append) + return self._factory.create_file_transfer_item(data, append) def create_unsent_file_item(self, message, append=True): data = message.get_data() - return self._factory.unsent_file_item(os.path.basename(data[0]), - os.path.getsize(data[0]) if data[1] is None else len(data[1]), - self.name, - data[2], - append) + return self._factory.create_unsent_file_item(os.path.basename(data[0]), + os.path.getsize(data[0]) if data[1] is None else len(data[1]), + self.name, + data[2], + append) def create_inline_item(self, data, append=True): - return self._factory.inline_item(data, append) + return self._factory.create_inline_item(data, append) # ----------------------------------------------------------------------------------------------------------------- # Reset diff --git a/toxygen/history/database.py b/toxygen/history/database.py index bf593d8..4be00c4 100644 --- a/toxygen/history/database.py +++ b/toxygen/history/database.py @@ -73,7 +73,7 @@ class Database: db = self._connect() try: cursor = db.cursor() - cursor.execute('INSERT INTO contacts VALUES (?);', (tox_id, )) + # cursor.execute('INSERT INTO contacts VALUES (?);', (tox_id, )) cursor.execute('CREATE TABLE id' + tox_id + '(' ' id INTEGER PRIMARY KEY,' ' message_id INTEGER,' diff --git a/toxygen/history/history_loader.py b/toxygen/history/history.py similarity index 98% rename from toxygen/history/history_loader.py rename to toxygen/history/history.py index a380ddb..6ded428 100644 --- a/toxygen/history/history_loader.py +++ b/toxygen/history/history.py @@ -3,7 +3,7 @@ from history.history_logs_generators import * # TODO: fix history loading and saving -class HistoryLoader: +class History: def __init__(self, contact_provider, db, settings): self._contact_provider = contact_provider @@ -45,6 +45,9 @@ class HistoryLoader: self._db.delete_messages(friend.tox_id) self._db.delete_friend_from_db(friend.tox_id) + def delete_message(self, message): + pass + def load_history(self): """ Tries to load next part of messages diff --git a/toxygen/messenger/messages.py b/toxygen/messenger/messages.py index 830e72e..dc70e8d 100644 --- a/toxygen/messenger/messages.py +++ b/toxygen/messenger/messages.py @@ -1,4 +1,5 @@ from history.database import MESSAGE_AUTHOR +from ui.messages_widgets import * MESSAGE_TYPE = { @@ -21,11 +22,10 @@ class MessageAuthor: class Message: - def __init__(self, message_id, message_type, author, time): + def __init__(self, message_type, author, time): self._time = time self._type = message_type self._author = author - self._message_id = message_id self._widget = None def get_type(self): @@ -43,19 +43,9 @@ class Message: time = property(get_time) - def get_message_id(self): - return self._message_id - - message_id = property(get_message_id) - - def get_type(self): - return self._type - - type = property(get_type) - - def get_widget(self): + def get_widget(self, *args): if self._widget is None: - self._widget = self._create_widget() + self._widget = self._create_widget(*args) return self._widget @@ -67,7 +57,7 @@ class Message: def mark_as_sent(self): self._author.author_type = MESSAGE_AUTHOR['ME'] - def _create_widget(self): + def _create_widget(self, *args): pass @@ -76,8 +66,8 @@ class TextMessage(Message): Plain text or action message """ - def __init__(self, id, message, owner, time, message_type): - super().__init__(id, message_type, owner, time) + def __init__(self, message, owner, time, message_type): + super().__init__(message_type, owner, time) self._message = message def get_text(self): @@ -88,8 +78,20 @@ class TextMessage(Message): def get_data(self): return self._message, self._owner, self._time, self._type - def _create_widget(self): - return + def _create_widget(self, *args): + return MessageItem(self, *args) + + +class OutgoingTextMessage(TextMessage): + + def __init__(self, message, owner, time, message_type, tox_message_id): + super().__init__(message, owner, time, message_type) + self._tox_message_id = tox_message_id + + def get_tox_message_id(self): + return self._tox_message_id + + tox_message_id = property(get_tox_message_id) class GroupChatMessage(TextMessage): @@ -107,7 +109,7 @@ class TransferMessage(Message): Message with info about file transfer """ - def __init__(self, id, owner, time, status, size, name, friend_number, file_number): + def __init__(self, owner, time, status, size, name, friend_number, file_number): super().__init__(MESSAGE_TYPE['FILE_TRANSFER'], owner, time) self._status = status self._size = size diff --git a/toxygen/messenger/messenger.py b/toxygen/messenger/messenger.py index 5a94f7f..968ca97 100644 --- a/toxygen/messenger/messenger.py +++ b/toxygen/messenger/messenger.py @@ -23,7 +23,7 @@ class Messenger(tox_save.ToxSave): def _create_message_item(self, text_message): # pixmap = self._contacts_manager.get_curr_contact().get_pixmap() - self._items_factory.message_item(text_message) + self._items_factory.create_message_item(text_message) # ----------------------------------------------------------------------------------------------------------------- # Messaging @@ -38,7 +38,7 @@ class Messenger(tox_save.ToxSave): """ t = util.get_unix_time() friend = self._get_friend_by_number(friend_number) - text_message = TextMessage(0, message, MessageAuthor(friend.name, MESSAGE_AUTHOR['FRIEND']), t, message_type) + text_message = TextMessage(message, MessageAuthor(friend.name, MESSAGE_AUTHOR['FRIEND']), t, message_type) if self._contacts_manager.is_friend_active(friend_number): # add message to list self._create_message_item(text_message) @@ -80,7 +80,7 @@ class Messenger(tox_save.ToxSave): else: message_id = 0 message_author = MessageAuthor(self._profile.name, MESSAGE_AUTHOR['NOT_SENT']) - message = TextMessage(message_id, text, message_author, t, message_type) + message = OutgoingTextMessage(text, message_author, t, message_type, message_id) friend.append_message(message) if self._contacts_manager.is_friend_active(friend_number): self._create_message_item(message) diff --git a/toxygen/middleware/callbacks.py b/toxygen/middleware/callbacks.py index 7b7b759..c9571a2 100644 --- a/toxygen/middleware/callbacks.py +++ b/toxygen/middleware/callbacks.py @@ -95,8 +95,6 @@ def friend_status_message(contacts_manager, messenger): invoke_in_main_thread(friend.set_status_message, status_message) print('User #{} has new status'.format(friend_number)) invoke_in_main_thread(messenger.send_messages, friend_number) - if contacts_manager.is_friend_active(friend_number): - invoke_in_main_thread(contacts_manager.set_active) return wrapped diff --git a/toxygen/ui/items_factory.py b/toxygen/ui/items_factories.py similarity index 73% rename from toxygen/ui/items_factory.py rename to toxygen/ui/items_factories.py index 1c4e7a9..db2f065 100644 --- a/toxygen/ui/items_factory.py +++ b/toxygen/ui/items_factories.py @@ -1,28 +1,34 @@ from ui.list_items import * from ui.messages_widgets import * -# rename methods +class FriendItemsFactory: -class ItemsFactory: - - def __init__(self, settings, plugin_loader, smiley_loader, main_screen): - self._settings, self._plugin_loader = settings, plugin_loader - self._smiley_loader = smiley_loader - self._messages = main_screen.messages + def __init__(self, settings, main_screen): + self._settings = settings self._friends_list = main_screen.friends_list - self._message_edit = main_screen.messageEdit - def friend_item(self): + def create_friend_item(self): item = ContactItem(self._settings) elem = QtWidgets.QListWidgetItem(self._friends_list) elem.setSizeHint(QtCore.QSize(250, item.height())) self._friends_list.addItem(elem) self._friends_list.setItemWidget(elem, item) + return item - def message_item(self, message, append=True, pixmap=None): - item = MessageItem(self._settings, self._create_message_browser, message, self._messages) + +class MessagesItemsFactory: + + def __init__(self, settings, plugin_loader, smiley_loader, main_screen, history): + self._settings, self._plugin_loader = settings, plugin_loader + self._smiley_loader, self._history = smiley_loader, history + self._messages = main_screen.messages + self._message_edit = main_screen.messageEdit + + def create_message_item(self, message, append=True, pixmap=None): + item = message.get_widget(self._settings, self._create_message_browser, + self._history.delete_message, self._messages) if pixmap is not None: item.set_avatar(pixmap) elem = QtWidgets.QListWidgetItem() @@ -32,9 +38,10 @@ class ItemsFactory: else: self._messages.insertItem(0, elem) self._messages.setItemWidget(elem, item) + return item - def inline_item(self, data, append): + def create_inline_item(self, data, append): elem = QtWidgets.QListWidgetItem() item = InlineImageItem(data, self._messages.width(), elem) elem.setSizeHint(QtCore.QSize(self._messages.width(), item.height())) @@ -43,9 +50,10 @@ class ItemsFactory: else: self._messages.insertItem(0, elem) self._messages.setItemWidget(elem, item) + return item - def unsent_file_item(self, file_name, size, name, time, append): + def create_unsent_file_item(self, file_name, size, name, time, append): item = UnsentFileItem(file_name, size, name, @@ -58,9 +66,10 @@ class ItemsFactory: else: self._messages.insertItem(0, elem) self._messages.setItemWidget(elem, item) + return item - def file_transfer_item(self, data, append): + def create_file_transfer_item(self, data, append): data.append(self._messages.width()) item = FileTransferItem(*data) elem = QtWidgets.QListWidgetItem() @@ -70,8 +79,13 @@ class ItemsFactory: else: self._messages.insertItem(0, elem) self._messages.setItemWidget(elem, item) + return item + # ----------------------------------------------------------------------------------------------------------------- + # Private methods + # ----------------------------------------------------------------------------------------------------------------- + def _create_message_browser(self, text, width, message_type, parent=None): return MessageBrowser(self._settings, self._message_edit, self._smiley_loader, self._plugin_loader, text, width, message_type, parent) diff --git a/toxygen/ui/list_items.py b/toxygen/ui/list_items.py index a305ffc..c9638ec 100644 --- a/toxygen/ui/list_items.py +++ b/toxygen/ui/list_items.py @@ -4,10 +4,7 @@ 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 utils.util import * from ui.widgets import DataLabel, create_menu -import html as h -import smileys from user_data import settings -import re class ContactItem(QtWidgets.QWidget): diff --git a/toxygen/ui/main_screen.py b/toxygen/ui/main_screen.py index f0a1ef5..a8a7c13 100644 --- a/toxygen/ui/main_screen.py +++ b/toxygen/ui/main_screen.py @@ -604,11 +604,13 @@ class MainWindow(QtWidgets.QMainWindow): extension = 'txt' if as_text else 'html' file_name, _ = util_ui.save_file_dialog(util_ui.tr('Choose file name'), extension) - if file_name: - if not file_name.endswith('.' + extension): - file_name += '.' + extension - with open(file_name, 'wt') as fl: - fl.write(s) + if not file_name: + return + + if not file_name.endswith('.' + extension): + file_name += '.' + extension + with open(file_name, 'wt') as fl: + fl.write(s) def set_alias(self, num): self._contacts_manager.set_alias(num) diff --git a/toxygen/ui/menu.py b/toxygen/ui/menu.py index 0585c4c..d023cff 100644 --- a/toxygen/ui/menu.py +++ b/toxygen/ui/menu.py @@ -1,6 +1,5 @@ from PyQt5 import QtCore, QtGui, QtWidgets from user_data.settings import * -from contacts.profile import Profile from utils.util import * from ui.widgets import CenteredWidget, DataLabel, LineEdit, RubberBandWindow import pyaudio @@ -717,7 +716,6 @@ class InterfaceSettings(CenteredWidget): app.translator.load(curr_directory() + '/translations/' + path) app.installTranslator(app.translator) self._settings['message_font_size'] = self.messages_font_size.currentIndex() + 10 - Profile.get_instance().update() self._settings.save() if restart: util_ui.message_box(util_ui.tr('Restart app to apply settings'), util_ui.tr('Restart required')) diff --git a/toxygen/ui/messages_widgets.py b/toxygen/ui/messages_widgets.py index 0e31891..0f510ea 100644 --- a/toxygen/ui/messages_widgets.py +++ b/toxygen/ui/messages_widgets.py @@ -115,7 +115,7 @@ class MessageBrowser(QtWidgets.QTextBrowser): if arr[i].startswith('>'): arr[i] = '' + arr[i][4:] + '' text = '
'.join(arr) - text = self._smileys_loader.add_smileys_to_text(text, self) # smileys + text = self._smileys_loader.add_smileys_to_text(text, self) return text @@ -123,8 +123,10 @@ class MessageItem(QtWidgets.QWidget): """ Message in messages list """ - def __init__(self, settings, message_browser_factory_method, text_message, parent=None): + def __init__(self, text_message, settings, message_browser_factory_method, delete_action, parent=None): QtWidgets.QWidget.__init__(self, parent) + self._message = text_message + self._delete_action = delete_action self.name = widgets.DataLabel(self) self.name.setGeometry(QtCore.QRect(2, 2, 95, 23)) self.name.setTextFormat(QtCore.Qt.PlainText) @@ -169,12 +171,11 @@ class MessageItem(QtWidgets.QWidget): self.listMenu.show() def delete(self): - pr = profile.Profile.get_instance() - pr.delete_message(self._time) + self._delete_action(self._message) def mark_as_sent(self): if self.t: - self.time.setText(convert_time(self._time)) + self.time.setText(util.convert_time(self._time)) self.t = False return True return False