diff --git a/src/basecontact.py b/src/basecontact.py new file mode 100644 index 0000000..1ae1a2b --- /dev/null +++ b/src/basecontact.py @@ -0,0 +1,113 @@ +import os +from settings import * +try: + from PySide import QtCore, QtGui +except ImportError: + from PyQt4 import QtCore, QtGui +from toxcore_enums_and_consts import TOX_PUBLIC_KEY_SIZE + + +class BaseContact: + """ + Class encapsulating TOX contact + Properties: name (alias of contact or name), status_message, status (connection status) + widget - widget for update + """ + + def __init__(self, name, status_message, widget, tox_id): + """ + :param name: name, example: 'Toxygen user' + :param status_message: status message, example: 'Toxing on Toxygen' + :param widget: ContactItem instance + :param tox_id: tox id of contact + """ + self._name, self._status_message = name, status_message + self._status, self._widget = None, widget + self._widget.name.setText(name) + self._widget.status_message.setText(status_message) + self._tox_id = tox_id + self.load_avatar() + + # ----------------------------------------------------------------------------------------------------------------- + # name - current name or alias of user + # ----------------------------------------------------------------------------------------------------------------- + + def get_name(self): + return self._name + + def set_name(self, value): + self._name = str(value, 'utf-8') + self._widget.name.setText(self._name) + self._widget.name.repaint() + + name = property(get_name, set_name) + + # ----------------------------------------------------------------------------------------------------------------- + # Status message + # ----------------------------------------------------------------------------------------------------------------- + + def get_status_message(self): + return self._status_message + + def set_status_message(self, value): + self._status_message = str(value, 'utf-8') + self._widget.status_message.setText(self._status_message) + self._widget.status_message.repaint() + + status_message = property(get_status_message, set_status_message) + + # ----------------------------------------------------------------------------------------------------------------- + # Status + # ----------------------------------------------------------------------------------------------------------------- + + def get_status(self): + return self._status + + def set_status(self, value): + self._status = value + self._widget.connection_status.update(value) + + status = property(get_status, set_status) + + # ----------------------------------------------------------------------------------------------------------------- + # TOX ID. WARNING: for friend it will return public key, for profile - full address + # ----------------------------------------------------------------------------------------------------------------- + + def get_tox_id(self): + return self._tox_id + + tox_id = property(get_tox_id) + + # ----------------------------------------------------------------------------------------------------------------- + # Avatars + # ----------------------------------------------------------------------------------------------------------------- + + def load_avatar(self, default_path='avatar.png'): + """ + Tries to load avatar of contact or uses default avatar + """ + avatar_path = '{}.png'.format(self._tox_id[:TOX_PUBLIC_KEY_SIZE * 2]) + os.chdir(ProfileHelper.get_path() + 'avatars/') + if not os.path.isfile(avatar_path): # load default image + avatar_path = default_path + os.chdir(curr_directory() + '/images/') + pixmap = QtGui.QPixmap(QtCore.QSize(64, 64)) + pixmap.load(avatar_path) + self._widget.avatar_label.setScaledContents(False) + self._widget.avatar_label.setPixmap(pixmap.scaled(64, 64, QtCore.Qt.KeepAspectRatio)) + self._widget.avatar_label.repaint() + + def reset_avatar(self): + avatar_path = (ProfileHelper.get_path() + 'avatars/{}.png').format(self._tox_id[:TOX_PUBLIC_KEY_SIZE * 2]) + if os.path.isfile(avatar_path): + os.remove(avatar_path) + self.load_avatar() + + def set_avatar(self, avatar): + avatar_path = (ProfileHelper.get_path() + 'avatars/{}.png').format(self._tox_id[:TOX_PUBLIC_KEY_SIZE * 2]) + with open(avatar_path, 'wb') as f: + f.write(avatar) + self.load_avatar() + + def get_pixmap(self): + return self._widget.avatar_label.pixmap() diff --git a/src/groupchat.py b/src/groupchat.py index a165813..89c2eb5 100644 --- a/src/groupchat.py +++ b/src/groupchat.py @@ -3,14 +3,9 @@ import contact class Groupchat(contact.Contact): - def __init__(self, *args): + def __init__(self, group_id, *args): super().__init__(args) + self._id = group_id def load_avatar(self): - avatar_path = curr_directory() + '/images/group.png' - os.chdir(curr_directory() + '/images/') - pixmap = QtGui.QPixmap(QtCore.QSize(64, 64)) - pixmap.load(avatar_path) - self._widget.avatar_label.setScaledContents(False) - self._widget.avatar_label.setPixmap(pixmap.scaled(64, 64, QtCore.Qt.KeepAspectRatio)) - self._widget.avatar_label.repaint() + super().load_avatar('group.png') diff --git a/toxygen/contact.py b/toxygen/contact.py index f4b3f9a..2df8c1c 100644 --- a/toxygen/contact.py +++ b/toxygen/contact.py @@ -5,78 +5,139 @@ try: except ImportError: from PyQt4 import QtCore, QtGui from toxcore_enums_and_consts import TOX_PUBLIC_KEY_SIZE +import basecontact -class Contact: +class Contact(basecontact.BaseContact): """ Class encapsulating TOX contact Properties: name (alias of contact or name), status_message, status (connection status) widget - widget for update """ - def __init__(self, name, status_message, widget, tox_id): + def __init__(self, message_getter, name, status_message, widget, tox_id): """ :param name: name, example: 'Toxygen user' :param status_message: status message, example: 'Toxing on Toxygen' :param widget: ContactItem instance :param tox_id: tox id of contact """ - self._name, self._status_message = name, status_message - self._status, self._widget = None, widget - self._widget.name.setText(name) - self._widget.status_message.setText(status_message) - self._tox_id = tox_id - self.load_avatar() + super().__init__(name, status_message, widget, tox_id) + self._message_getter = message_getter + self._new_messages = False + self._visible = True + self._corr = [] + self._unsaved_messages = 0 + self._history_loaded = self._new_actions = False + self._curr_text = '' + + def __del__(self): + self.set_visibility(False) + del self._widget + if hasattr(self, '_message_getter'): + del self._message_getter + + def load_corr(self, first_time=True): + """ + :param first_time: friend became active, load first part of messages + """ + if (first_time and self._history_loaded) or (not hasattr(self, '_message_getter')): + return + data = list(self._message_getter.get(PAGE_SIZE)) + if data is not None and len(data): + data.reverse() + else: + return + data = list(map(lambda tupl: TextMessage(*tupl), data)) + self._corr = data + self._corr + self._history_loaded = True + + def get_corr_for_saving(self): + """ + Get data to save in db + :return: list of unsaved messages or [] + """ + if hasattr(self, '_message_getter'): + del self._message_getter + messages = list(filter(lambda x: x.get_type() <= 1, self._corr)) + return list( + map(lambda x: x.get_data(), list(messages[-self._unsaved_messages:]))) if self._unsaved_messages else [] + + def get_corr(self): + return self._corr[:] + + def append_message(self, message): + """ + :param message: text or file transfer message + """ + self._corr.append(message) + if message.get_type() <= 1: + self._unsaved_messages += 1 + + def get_last_message_text(self): + messages = list(filter(lambda x: x.get_type() <= 1 and x.get_owner() != MESSAGE_OWNER['FRIEND'], self._corr)) + if messages: + return messages[-1].get_data()[0] + else: + return '' + + def clear_corr(self): + """ + Clear messages list + """ + if hasattr(self, '_message_getter'): + del self._message_getter + # don't delete data about active file transfer + self._corr = list(filter(lambda x: x.get_type() in (2, 3) and x.get_status() >= 2, self._corr)) + self._unsaved_messages = 0 + + def get_curr_text(self): + return self._curr_text + + def set_curr_text(self, value): + self._curr_text = value + + curr_text = property(get_curr_text, set_curr_text) # ----------------------------------------------------------------------------------------------------------------- - # name - current name or alias of user + # Visibility in friends' list # ----------------------------------------------------------------------------------------------------------------- - def get_name(self): - return self._name + def get_visibility(self): + return self._visible - def set_name(self, value): - self._name = str(value, 'utf-8') - self._widget.name.setText(self._name) - self._widget.name.repaint() + def set_visibility(self, value): + self._visible = value - name = property(get_name, set_name) + visibility = property(get_visibility, set_visibility) # ----------------------------------------------------------------------------------------------------------------- - # Status message + # Unread messages and actions # ----------------------------------------------------------------------------------------------------------------- - def get_status_message(self): - return self._status_message + def get_actions(self): + return self._new_actions - def set_status_message(self, value): - self._status_message = str(value, 'utf-8') - self._widget.status_message.setText(self._status_message) - self._widget.status_message.repaint() + def set_actions(self, value): + self._new_actions = value + self._widget.connection_status.update(self.status, value) - status_message = property(get_status_message, set_status_message) + actions = property(get_actions, set_actions) # unread messages, incoming files, av calls - # ----------------------------------------------------------------------------------------------------------------- - # Status - # ----------------------------------------------------------------------------------------------------------------- + def get_messages(self): + return self._new_messages - def get_status(self): - return self._status + def inc_messages(self): + self._new_messages += 1 + self._new_actions = True + self._widget.connection_status.update(self.status, True) + self._widget.messages.update(self._new_messages) - def set_status(self, value): - self._status = value - self._widget.connection_status.update(value) - - status = property(get_status, set_status) - - # ----------------------------------------------------------------------------------------------------------------- - # TOX ID. WARNING: for friend it will return public key, for profile - full address - # ----------------------------------------------------------------------------------------------------------------- - - def get_tox_id(self): - return self._tox_id - - tox_id = property(get_tox_id) + def reset_messages(self): + self._new_actions = False + self._new_messages = 0 + self._widget.messages.update(self._new_messages) + self._widget.connection_status.update(self.status, False) # ----------------------------------------------------------------------------------------------------------------- # Avatars @@ -112,3 +173,6 @@ class Contact: def get_pixmap(self): return self._widget.avatar_label.pixmap() + + messages = property(get_messages) + diff --git a/toxygen/friend.py b/toxygen/friend.py index 3dd5b0f..6f2dcf4 100644 --- a/toxygen/friend.py +++ b/toxygen/friend.py @@ -15,23 +15,13 @@ class Friend(contact.Contact): :param message_getter: gets messages from db :param number: number of friend. """ - super(Friend, self).__init__(*args) + super(Friend, self).__init__(message_getter, *args) self._number = number - self._new_messages = False - self._visible = True self._alias = False - self._message_getter = message_getter - self._corr = [] - self._unsaved_messages = 0 - self._history_loaded = self._new_actions = False self._receipts = 0 - self._curr_text = '' def __del__(self): - self.set_visibility(False) - del self._widget - if hasattr(self, '_message_getter'): - del self._message_getter + super().__del__() # ----------------------------------------------------------------------------------------------------------------- # History support @@ -188,48 +178,6 @@ class Friend(contact.Contact): def set_alias(self, alias): self._alias = bool(alias) - # ----------------------------------------------------------------------------------------------------------------- - # Visibility in friends' list - # ----------------------------------------------------------------------------------------------------------------- - - def get_visibility(self): - return self._visible - - def set_visibility(self, value): - self._visible = value - - visibility = property(get_visibility, set_visibility) - - # ----------------------------------------------------------------------------------------------------------------- - # Unread messages from friend - # ----------------------------------------------------------------------------------------------------------------- - - def get_actions(self): - return self._new_actions - - def set_actions(self, value): - self._new_actions = value - self._widget.connection_status.update(self.status, value) - - actions = property(get_actions, set_actions) # unread messages, incoming files, av calls - - def get_messages(self): - return self._new_messages - - def inc_messages(self): - self._new_messages += 1 - self._new_actions = True - self._widget.connection_status.update(self.status, True) - self._widget.messages.update(self._new_messages) - - def reset_messages(self): - self._new_actions = False - self._new_messages = 0 - self._widget.messages.update(self._new_messages) - self._widget.connection_status.update(self.status, False) - - messages = property(get_messages) - # ----------------------------------------------------------------------------------------------------------------- # Friend's number (can be used in toxcore) # ----------------------------------------------------------------------------------------------------------------- diff --git a/toxygen/profile.py b/toxygen/profile.py index 9d5f1ab..816f78d 100644 --- a/toxygen/profile.py +++ b/toxygen/profile.py @@ -15,9 +15,10 @@ import time import calls import avwidgets import plugin_support +import basecontact -class Profile(contact.Contact, Singleton): +class Profile(basecontact.BaseContact, Singleton): """ Profile of current toxygen user. Contains friends list, tox instance """