From 2441d2b69076346431c760a6628287bd6a5c43fc Mon Sep 17 00:00:00 2001 From: ingvar1995 Date: Mon, 29 Feb 2016 00:33:35 +0300 Subject: [PATCH] profile.py refactoring, over9000 callbacks added, tests fixed --- src/callbacks.py | 65 ++++++++++++++++++-- src/mainscreen.py | 21 +++---- src/profile.py | 147 ++++++++++++++++++++++++++-------------------- tests/tests.py | 10 ---- 4 files changed, 151 insertions(+), 92 deletions(-) diff --git a/src/callbacks.py b/src/callbacks.py index 47880af..2e80764 100644 --- a/src/callbacks.py +++ b/src/callbacks.py @@ -2,8 +2,8 @@ from PySide import QtCore from notifications import * from settings import Settings from profile import Profile +from toxcore_enums_and_consts import * # TODO: add all callbacks (remove test callbacks and use wrappers) -# NOTE: don't forget to call repaint class InvokeEvent(QtCore.QEvent): @@ -41,29 +41,82 @@ def self_connection_status(st, tox_link): return wrapped -def friend_status(a, b, c, d): - print "Friend connected! Friend's data: ", str(a), str(b), str(c) +def friend_status(tox, friend_num, new_status, user_data): + """ + Check friend's status (none, busy, away) + """ + print "Friend's #{} status changed! New status: ".format(friend_num, new_status) + profile = Profile.get_instance() + friend = filter(lambda x: x.number == friend_num, profile.friends)[0] + invoke_in_main_thread(friend.set_status, new_status) + + +def friend_connection_status(tox, friend_num, new_status, user_data): + """ + Check friend's connection status (offline, udp, tcp) + """ + print "Friend #{} connected! Friend's status: ".format(friend_num, new_status) + profile = Profile.get_instance() + friend = filter(lambda x: x.number == friend_num, profile.friends)[0] + if new_status == TOX_CONNECTION['NONE']: + invoke_in_main_thread(friend.set_status, None) + elif friend.status is None: + invoke_in_main_thread(friend.set_status, TOX_USER_STATUS['NONE']) + + +def friend_name(window): + """ + :param window: main window + :return: function for callback friend_name. It updates friend's name + and calls window repaint + """ + def wrapped(tox, friend_num, name, size, user_data): + profile = Profile.get_instance() + friend = filter(lambda x: x.number == friend_num, profile.friends)[0] + print 'New name: ', str(friend_num), str(name) + invoke_in_main_thread(friend.set_name, name) + invoke_in_main_thread(window.update_active_friend) + return wrapped + + +def friend_status_message(window): + """ + :param window: main window + :return: function for callback friend_status_message. It updates friend's status message + and calls window repaint + """ + def wrapped(tox, friend_num, status_message, size, user_data): + profile = Profile.get_instance() + friend = filter(lambda x: x.number == friend_num, profile.friends)[0] + invoke_in_main_thread(friend.set_status_message, status_message) + print 'User #{} has new status: {}'.format(friend_num, status_message) + invoke_in_main_thread(window.update_active_friend) + return wrapped def friend_message(window): """ :param window: main window - :return: function for tox.callback_friend_message + :return: function for tox.callback_friend_message. Adds new message to list """ def wrapped(tox, friend_number, message_type, message, size, user_data): print 'Message: ', message.decode('utf8') if not window.isActiveWindow() and Settings()['notifications']: tray_notification('Message', message.decode('utf8')) - profile = Profile.getInstance() - invoke_in_main_thread(profile.newMessage, friend_number, message_type, message) + profile = Profile.get_instance() + invoke_in_main_thread(profile.new_message, friend_number, message_type, message) return wrapped def init_callbacks(tox, window): """ + Initialization of all callbacks. :param tox: tox instance :param window: main window """ tox.callback_friend_status(friend_status, 0) tox.callback_friend_message(friend_message(window), 0) tox.callback_self_connection_status(self_connection_status(window.connection_status, tox), 0) + tox.callback_friend_connection_status(friend_connection_status, 0) + tox.callback_friend_name(friend_name(window), 0) + tox.callback_friend_status_message(friend_status_message(window), 0) diff --git a/src/mainscreen.py b/src/mainscreen.py index 0a2036c..0d7235d 100644 --- a/src/mainscreen.py +++ b/src/mainscreen.py @@ -5,9 +5,9 @@ from PySide import QtGui, QtCore from menu import * from profile import * from toxcore_enums_and_consts import * -from util import curr_time +# TODO: move list items to new file class MessageItem(QtGui.QListWidget): def __init__(self, text, time, user='', message_type=TOX_MESSAGE_TYPE['NORMAL'], parent=None): @@ -372,23 +372,20 @@ class MainWindow(QtGui.QMainWindow): def send_message(self): text = self.messageEdit.toPlainText() - if self.profile.sendMessage(text): + if self.profile.send_message(text): self.messageEdit.clear() # ----------------------------------------------------------------------------------------------------------------- # Functions which called when user click somewhere else # ----------------------------------------------------------------------------------------------------------------- - def friend_click(self, index): - print 'row:', index.row() - num = index.row() - self.profile.setActive(num) - friend = self.profile.getActiveFriendData() + def update_active_friend(self): + friend = self.profile.get_active_friend_data() self.account_name.setText(friend[0]) self.account_status.setText(friend[1]) - -if __name__ == '__main__': - app = QtGui.QApplication(sys.argv) - ex = MainWindow() - sys.exit(app.exec_()) + def friend_click(self, index): + print 'row:', index.row() + num = index.row() + self.profile.set_active(num) + self.update_active_friend() diff --git a/src/profile.py b/src/profile.py index 7dd5100..8377045 100644 --- a/src/profile.py +++ b/src/profile.py @@ -62,37 +62,39 @@ class Contact(object): widget.name.setText(name) widget.status_message.setText(status_message) - def getName(self): + def get_name(self): return self._name - def setName(self, value): + def set_name(self, value): self._name = value self._widget.name.setText(value) + self._widget.name.repaint() - name = property(getName, setName) + name = property(get_name, set_name) - def getStatusMessage(self): + def get_status_message(self): return self._status_message - def setStatusMessage(self, value): + def set_status_message(self, value): self._status_message = value self._widget.status_message.setText(value) + self._widget.status_message.repaint() - status_message = property(getStatusMessage, setStatusMessage) + status_message = property(get_status_message, set_status_message) - def getStatus(self): + def get_status(self): return self._status - def setStatus(self, value): + def set_status(self, value): # TODO: status repaint self._status = value - status = property(getStatus, setStatus) + status = property(get_status, set_status) class Friend(Contact): """ - Friend in list of friends. Can be hidden, unread messages added + Friend in list of friends. Can be hidden, property 'has unread messages' added """ def __init__(self, number, *args): @@ -101,32 +103,37 @@ class Friend(Contact): self._new_messages = False self._visible = True - def getVisibility(self): + def get_visibility(self): return self._visible - def setVisibility(self, value): + def set_visibility(self, value): self._widget.setVisibility(value) self._visible = value - visibility = property(getVisibility, setVisibility) + visibility = property(get_visibility, set_visibility) - def setMessages(self, value): + def get_messages(self): + return self._new_messages + + def set_messages(self, value): self._new_messages = value - messages = property(None, setMessages) + messages = property(get_messages, set_messages) - def getNumber(self): + def get_number(self): return self._number - number = property(getNumber) + number = property(get_number) # TODO: check if setNumber needed + def __del__(self): + del self._widget + class Profile(Contact): """ - Profile of current toxygen user. Contains friends list, tox instance + Profile of current toxygen user. Contains friends list, tox instance, list of messages """ - # TODO: add unicode support in messages def __init__(self, tox, widgets, widget, messages_list): self._widget = widget self._messages = messages_list @@ -144,50 +151,58 @@ class Profile(Contact): Profile._instance = self @staticmethod - def getInstance(): + def get_instance(): return Profile._instance - def getActive(self): - return self._active_friend - - def setActive(self, value): - try: - visible_friends = filter(lambda num, friend: friend.visibility, enumerate(self.friends)) - self._active_friend = visible_friends[value][0] - self._messages.clear() - # TODO: load history - except: # no friend found. ignore - log('Incorrect friend value: ' + str(value)) - - active_friend = property(getActive, setActive) - - def getActiveFriendData(self): - friend = self.friends[self._active_friend] - return friend.name, friend.status_message - - def getActiveNumber(self): - return self.friends[self._active_friend].number - - def getActiveName(self): - return self.friends[self._active_friend].name - - def isActiveOnline(self): - if not self._active_friend + 1: # no active friend - return False - else: - # TODO: callbacks! - return True - status = self.friends[self._active_friend].status - return status is not None + def change_status(self): + if self._status is not None: + self._status += 1 + self._status %= 3 def filtration(self, show_online=True, filter_str=''): for friend in self.friends: friend.visibility = (friend.status is not None or not show_online) and (filter_str in friend.name) - def newMessage(self, id, message_type, message): + # ----------------------------------------------------------------------------------------------------------------- + # Work with active friend + # ----------------------------------------------------------------------------------------------------------------- + + def get_active(self): + return self._active_friend + + def set_active(self, value): + try: + visible_friends = filter(lambda elem: elem[1].visibility, enumerate(self.friends)) + self._active_friend = visible_friends[value][0] + self._messages.clear() + self._messages.repaint() + # TODO: load history + except: # no friend found. ignore + log('Incorrect friend value: ' + str(value)) + + active_friend = property(get_active, set_active) + + def get_active_friend_data(self): + friend = self.friends[self._active_friend] + return friend.name, friend.status_message + + def get_active_number(self): + return self.friends[self._active_friend].number + + def get_active_name(self): + return self.friends[self._active_friend].name + + def is_active_online(self): + return self._active_friend + 1 and self.friends[self._active_friend].status is not None + + # ----------------------------------------------------------------------------------------------------------------- + # Private messages + # ----------------------------------------------------------------------------------------------------------------- + + def new_message(self, id, message_type, message): if id == self._active_friend: # add message to list - user_name = Profile.getInstance().getActiveName() - item = mainscreen.MessageItem(message, curr_time(), user_name, message_type) + user_name = Profile.get_instance().get_active_name() + item = mainscreen.MessageItem(message.decode('utf-8'), curr_time(), user_name, message_type) elem = QtGui.QListWidgetItem(self._messages) elem.setSizeHint(QtCore.QSize(500, 100)) self._messages.addItem(elem) @@ -195,17 +210,17 @@ class Profile(Contact): self._messages.scrollToBottom() self._messages.repaint() else: - friend = filter(lambda x: x.getNumber() == id, self.friends)[0] - friend.setMessages(True) + friend = filter(lambda x: x.number == id, self.friends)[0] + friend.set_messages(True) - def sendMessage(self, text): - if self.isActiveOnline() and text: + def send_message(self, text): + if self.is_active_online() and text: if text.startswith('/me'): message_type = TOX_MESSAGE_TYPE['ACTION'] text = text[3:] else: message_type = TOX_MESSAGE_TYPE['NORMAL'] - self.tox.friend_send_message(self._active_friend, message_type, text) + self.tox.friend_send_message(self._active_friend, message_type, text.encode('utf-8')) item = mainscreen.MessageItem(text, curr_time(), self._name, message_type) elem = QtGui.QListWidgetItem(self._messages) elem.setSizeHint(QtCore.QSize(500, 100)) @@ -217,10 +232,14 @@ class Profile(Contact): else: return False - def changeStatus(self): - if self._status is not None: - self._status += 1 - self._status %= 3 + # ----------------------------------------------------------------------------------------------------------------- + # Work with friends (add, remove) + # ----------------------------------------------------------------------------------------------------------------- + + def delete_friend(self, num): + self.tox.friend_delete(num) + friend = filter(lambda x: x.number == num, self.friends)[0] + del friend def tox_factory(data=None, settings=None): diff --git a/tests/tests.py b/tests/tests.py index c8f7e75..78160ff 100644 --- a/tests/tests.py +++ b/tests/tests.py @@ -1,5 +1,4 @@ from src.settings import Settings -from src.util import bin_to_string, string_to_bin import sys from src.bootstrap import node_generator from src.profile import * @@ -37,15 +36,6 @@ class TestProfile(): assert new_data == data -class TestUtils(): - - def test_convert(self): - id = 'C4CEB8C7AC607C6B374E2E782B3C00EA3A63B80D4910B8649CCACDD19F260819' - data = string_to_bin(id) - new_id = bin_to_string(data) - assert id == new_id - - class TestNodeGen(): def test_generator(self):