From 5cfffd1deeadf9ff0a92f567051c6043cab17aa6 Mon Sep 17 00:00:00 2001 From: ingvar1995 Date: Wed, 9 Mar 2016 21:11:36 +0300 Subject: [PATCH] friend requests added --- src/callbacks.py | 12 ++++- src/mainscreen.py | 41 +++++------------ src/menu.py | 35 ++++++++++----- src/profile.py | 110 ++++++++++++++++++++++++++++++++-------------- 4 files changed, 122 insertions(+), 76 deletions(-) diff --git a/src/callbacks.py b/src/callbacks.py index 417ddfa..0bcc917 100644 --- a/src/callbacks.py +++ b/src/callbacks.py @@ -3,6 +3,7 @@ from notifications import * from settings import Settings from profile import Profile from toxcore_enums_and_consts import * +from tox import bin_to_string # TODO: add all callbacks (use wrappers) @@ -79,7 +80,7 @@ def friend_name(window): print 'New name: ', str(friend_num), str(name) invoke_in_main_thread(friend.set_name, name) if profile.get_active_number() == friend_num: - invoke_in_main_thread(window.update_active_friend) + invoke_in_main_thread(profile.set_active) return wrapped @@ -95,7 +96,7 @@ def friend_status_message(window): invoke_in_main_thread(friend.set_status_message, status_message) print 'User #{} has new status: {}'.format(friend_num, status_message) if profile.get_active_number() == friend_num: - invoke_in_main_thread(window.update_active_friend) + invoke_in_main_thread(profile.set_active) return wrapped @@ -114,6 +115,12 @@ def friend_message(window): return wrapped +def friend_request(tox, public_key, message, message_size, user_data): + profile = Profile.get_instance() + tox_id = bin_to_string(public_key, TOX_PUBLIC_KEY_SIZE) + invoke_in_main_thread(profile.process_friend_request, tox_id, message.decode('utf-8')) + + def init_callbacks(tox, window): """ Initialization of all callbacks. @@ -126,3 +133,4 @@ def init_callbacks(tox, window): 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) + tox.callback_friend_request(friend_request, 0) diff --git a/src/mainscreen.py b/src/mainscreen.py index bbf25a4..a09a122 100644 --- a/src/mainscreen.py +++ b/src/mainscreen.py @@ -88,23 +88,22 @@ class MainWindow(QtGui.QMainWindow): def setup_right_bottom(self, Form): Form.setObjectName("right_bottom") - Form.resize(500, 100) - #Form.setMinimumSize(QtCore.QSize(100, 50)) + Form.resize(650, 100) self.messageEdit = MessageArea(Form, self) - self.messageEdit.setGeometry(QtCore.QRect(20, 20, 311, 100)) + self.messageEdit.setGeometry(QtCore.QRect(0, 10, 450, 110)) self.messageEdit.setObjectName("messageEdit") self.screenshotButton = QtGui.QPushButton(Form) - self.screenshotButton.setGeometry(QtCore.QRect(340, 10, 98, 61)) + self.screenshotButton.setGeometry(QtCore.QRect(460, 10, 90, 50)) self.screenshotButton.setObjectName("screenshotButton") self.fileTransferButton = QtGui.QPushButton(Form) - self.fileTransferButton.setGeometry(QtCore.QRect(340, 80, 98, 61)) + self.fileTransferButton.setGeometry(QtCore.QRect(460, 70, 90, 50)) self.fileTransferButton.setObjectName("fileTransferButton") self.sendMessageButton = QtGui.QPushButton(Form) - self.sendMessageButton.setGeometry(QtCore.QRect(440, 10, 51, 131)) + self.sendMessageButton.setGeometry(QtCore.QRect(550, 10, 60, 110)) self.sendMessageButton.setObjectName("sendMessageButton") self.sendMessageButton.clicked.connect(self.send_message) self.screenshotButton.setText(QtGui.QApplication.translate("Form", "Screenshot", None, QtGui.QApplication.UnicodeUTF8)) - self.fileTransferButton.setText(QtGui.QApplication.translate("Form", "File transfer", None, QtGui.QApplication.UnicodeUTF8)) + self.fileTransferButton.setText(QtGui.QApplication.translate("Form", "File", None, QtGui.QApplication.UnicodeUTF8)) self.sendMessageButton.setText(QtGui.QApplication.translate("Form", "Send", None, QtGui.QApplication.UnicodeUTF8)) QtCore.QMetaObject.connectSlotsByName(Form) @@ -181,17 +180,6 @@ class MainWindow(QtGui.QMainWindow): def setup_left_center(self, widget, profile_widget): self.friends_list = QtGui.QListWidget(widget) self.friends_list.setGeometry(0, 0, 250, 250) - count = self.tox.self_get_friend_list_size() - widgets = [] - for i in xrange(count): - item = ContactItem() - elem = QtGui.QListWidgetItem(self.friends_list) - print item.sizeHint() - elem.setSizeHint(QtCore.QSize(250, 70)) - self.friends_list.addItem(elem) - self.friends_list.setItemWidget(elem, item) - widgets.append(item) - self.profile = Profile(self.tox, widgets, profile_widget, self.messages) self.friends_list.clicked.connect(self.friend_click) def setup_right_center(self, widget): @@ -229,6 +217,9 @@ class MainWindow(QtGui.QMainWindow): main.setLayout(grid) self.setCentralWidget(main) self.setup_menu(self) + self.user_info = name + self.friend_info = info + self.profile = Profile(self.tox, self) # ----------------------------------------------------------------------------------------------------------------- # Functions which called when user click in menu @@ -271,26 +262,16 @@ class MainWindow(QtGui.QMainWindow): def send_message(self): text = self.messageEdit.toPlainText() - if self.profile.send_message(text): - self.messageEdit.clear() + self.profile.send_message(text) # ----------------------------------------------------------------------------------------------------------------- # Functions which called when user click somewhere else # ----------------------------------------------------------------------------------------------------------------- - def update_active_friend(self): - friend = self.profile.get_active_friend_data() - self.account_name.setText(friend[0]) - self.account_status.setText(friend[1]) - # TODO: update avatar - def friend_click(self, index): print 'row:', index.row() num = index.row() - if self.profile.set_active(num): - self.update_active_friend() - self.messages.clear() - self.messageEdit.clear() + self.profile.set_active(num) def mouseReleaseEvent(self, event): x, y = event.x(), event.y() diff --git a/src/menu.py b/src/menu.py index 6e59ff9..851df54 100644 --- a/src/menu.py +++ b/src/menu.py @@ -19,31 +19,44 @@ class AddContact(QtGui.QWidget): self.sendRequestButton.setMinimumSize(QtCore.QSize(0, 0)) self.sendRequestButton.setBaseSize(QtCore.QSize(0, 0)) self.sendRequestButton.setObjectName("sendRequestButton") - self.lineEdit = QtGui.QLineEdit(self) - self.lineEdit.setGeometry(QtCore.QRect(50, 40, 471, 27)) - self.lineEdit.setObjectName("lineEdit") + self.sendRequestButton.clicked.connect(self.add_friend) + self.tox_id = QtGui.QLineEdit(self) + self.tox_id.setGeometry(QtCore.QRect(50, 40, 471, 27)) + self.tox_id.setObjectName("lineEdit") self.label = QtGui.QLabel(self) - self.label.setGeometry(QtCore.QRect(70, 10, 81, 21)) + self.label.setGeometry(QtCore.QRect(70, 10, 50, 20)) + self.error_label = QtGui.QLabel(self) + self.error_label.setGeometry(QtCore.QRect(120, 10, 400, 20)) font = QtGui.QFont() font.setPointSize(16) font.setWeight(75) font.setBold(True) self.label.setFont(font) + font.setPointSize(12) + font.setBold(False) + font.setWeight(40) + self.error_label.setFont(font) + self.error_label.setStyleSheet("QLabel { color: red; }") self.label.setObjectName("label") - self.textEdit = QtGui.QTextEdit(self) - self.textEdit.setGeometry(QtCore.QRect(50, 110, 471, 151)) - self.textEdit.setObjectName("textEdit") + self.message_edit = QtGui.QTextEdit(self) + self.message_edit.setGeometry(QtCore.QRect(50, 110, 471, 151)) + self.message_edit.setObjectName("textEdit") self.label_2 = QtGui.QLabel(self) self.label_2.setGeometry(QtCore.QRect(60, 70, 101, 31)) - font = QtGui.QFont() - font.setPointSize(16) - font.setWeight(75) - font.setBold(True) self.label_2.setFont(font) self.label_2.setObjectName("label_2") self.retranslateUi() QtCore.QMetaObject.connectSlotsByName(self) + def add_friend(self): + profile = Profile.get_instance() + send = profile.send_friend_request(self.tox_id.text(), self.message_edit.toPlainText()) + if send is True: + # request was successful + self.close() + else: # print error data + self.error_label.setText(send) + def retranslateUi(self): self.setWindowTitle(QtGui.QApplication.translate('AddContact', "Add contact", None, QtGui.QApplication.UnicodeUTF8)) self.sendRequestButton.setText(QtGui.QApplication.translate("Form", "Send request", None, QtGui.QApplication.UnicodeUTF8)) diff --git a/src/profile.py b/src/profile.py index 4eaa19f..0134212 100644 --- a/src/profile.py +++ b/src/profile.py @@ -1,4 +1,4 @@ -from list_items import MessageItem +from list_items import MessageItem, ContactItem from settings import Settings from PySide import QtCore, QtGui import os @@ -120,7 +120,6 @@ class Contact(object): def load_avatar(self): avatar_path = (Settings.get_default_path() + 'avatars/{}.png').format(self._tox_id[:TOX_PUBLIC_KEY_SIZE * 2]) - print 'Avatar', avatar_path if not os.path.isfile(avatar_path): # load default image avatar_path = curr_directory() + '/images/avatar.png' pixmap = QtGui.QPixmap(QtCore.QSize(64, 64)) @@ -199,21 +198,21 @@ class Profile(Contact, Singleton): """ Profile of current toxygen user. Contains friends list, tox instance, list of messages """ - def __init__(self, tox, widgets, widget, messages_list): + def __init__(self, tox, screen): """ :param tox: tox instance - :param widgets: list of widgets - friends' list - :param widget: widget in top-left corner with current user's data - :param messages_list: qlistwidget with messages + :param screen: ref to main screen """ - self._widget = widget - self._messages = messages_list + self.screen = screen + self._widget = screen.user_info + self._messages = screen.messages self.tox = tox self._name = tox.self_get_name() self._status_message = tox.self_get_status_message() self._status = None settings = Settings.get_instance() - self.show_online = Settings.get_instance()['show_online_friends'] + self.show_online = settings['show_online_friends'] + screen.online_contacts.setChecked(self.show_online) aliases = settings['friends_aliases'] data = tox.self_get_friend_list() self._friends, num, self._active_friend = [], 0, -1 @@ -223,9 +222,10 @@ class Profile(Contact, Singleton): alias = filter(lambda x: x[0] == tox_id, aliases)[0][1] except: alias = '' + item = self.create_friend_item() name = alias or tox.friend_get_name(i) or tox_id status_message = tox.friend_get_status_message(i) - friend = Friend(i, name, status_message, widgets[num], tox_id) + friend = Friend(i, name, status_message, item, tox_id) friend.set_alias(alias) self._friends.append(friend) num += 1 @@ -263,6 +263,9 @@ class Profile(Contact, Singleton): for friend in self._friends: friend.visibility = (friend.status is not None or not show_online) and (filter_str in friend.name.lower()) self.show_online, self.filter_string = show_online, filter_str + settings = Settings.get_instance() + settings['show_online_friends'] = self.show_online + settings.save() def update_filtration(self): self.filtration(self.show_online, self.filter_string) @@ -277,29 +280,34 @@ class Profile(Contact, Singleton): def get_active(self): return self._active_friend - def set_active(self, value): + def set_active(self, value=None): + """ + :param value: number of new active friend in friend's list or None to update active user's data + """ # TODO: rewrite to work with filtering - if self._active_friend == value: - return False try: - visible_friends = filter(lambda elem: elem[1].visibility, enumerate(self._friends)) - self._active_friend = visible_friends[value][0] - self._friends[self._active_friend].set_messages(False) + if value is not None: + visible_friends = filter(lambda elem: elem[1].visibility, enumerate(self._friends)) + self._active_friend = visible_friends[value][0] + self._friends[self._active_friend].set_messages(False) + self.screen.messages.clear() + self.screen.messageEdit.clear() + friend = self._friends[self._active_friend] + self.screen.account_name.setText(friend.name) + self.screen.account_status.setText(friend.status_message) + avatar_path = (Settings.get_default_path() + 'avatars/{}.png').format(friend.tox_id[:TOX_PUBLIC_KEY_SIZE * 2]) + if not os.path.isfile(avatar_path): # load default image + avatar_path = curr_directory() + '/images/avatar.png' + pixmap = QtGui.QPixmap(QtCore.QSize(64, 64)) + pixmap.scaled(64, 64, QtCore.Qt.KeepAspectRatio) + self.screen.account_avatar.setPixmap(avatar_path) + self.screen.account_avatar.repaint() # TODO: load history except: # no friend found. ignore log('Incorrect friend value: ' + str(value)) - return True active_friend = property(get_active, set_active) - def get_active_friend_data(self): - if self._active_friend != -1: - friend = self._friends[self._active_friend] - return friend.name, friend.status_message - else: - log('Something is wrong in get_active_friend_data') - return '', '' - def get_active_number(self): return self._friends[self._active_friend].number @@ -313,14 +321,14 @@ class Profile(Contact, Singleton): # Private messages # ----------------------------------------------------------------------------------------------------------------- - def new_message(self, id, message_type, message): + def new_message(self, friend_num, message_type, message): """ Current user gets new message - :param id: id of friend who sent message + :param friend_num: friend_num of friend who sent message :param message_type: message type - plain text or actionmessage :param message: text of message """ - if id == self._active_friend: # add message to list + if friend_num == self._friends[self._active_friend].number: # add message to list user_name = Profile.get_instance().get_active_name() item = MessageItem(message.decode('utf-8'), curr_time(), user_name, message_type, self._messages) elem = QtGui.QListWidgetItem(self._messages) @@ -329,7 +337,7 @@ class Profile(Contact, Singleton): self._messages.setItemWidget(elem, item) self._messages.repaint() else: - friend = filter(lambda x: x.number == id, self._friends)[0] + friend = filter(lambda x: x.number == friend_num, self._friends)[0] friend.set_messages(True) def send_message(self, text): @@ -352,15 +360,51 @@ class Profile(Contact, Singleton): self._messages.setItemWidget(elem, item) self._messages.scrollToBottom() self._messages.repaint() - return True - else: - return False + self.screen.messageEdit.clear() # ----------------------------------------------------------------------------------------------------------------- # Work with friends (add, remove) # ----------------------------------------------------------------------------------------------------------------- - # TODO: add friends + def create_friend_item(self): + item = ContactItem() + elem = QtGui.QListWidgetItem(self.screen.friends_list) + elem.setSizeHint(QtCore.QSize(250, 70)) + self.screen.friends_list.addItem(elem) + self.screen.friends_list.setItemWidget(elem, item) + return item + + def send_friend_request(self, id, message): + """ + Function tries to add friend with specified id to contact list + :param id: id of new contact + :param message: additional message + :return: True on success else error string + """ + try: + message = message or 'Add me to your contact list' + result = self.tox.friend_add(id, message.encode('utf-8')) + tox_id = id[:TOX_PUBLIC_KEY_SIZE * 2] + item = self.create_friend_item() + friend = Friend(result, tox_id, '', item, tox_id) + self._friends.append(friend) + return True + except Exception as ex: # wrong data + log('Send friend failed with ' + str(ex)) + return str(ex) + + def process_friend_request(self, tox_id, message): + try: + info = 'User {} wants to add you to contact list. Message:\n{}'.format(tox_id, message) + reply = QtGui.QMessageBox.question(None, 'Friend request', info, QtGui.QMessageBox.Yes, QtGui.QMessageBox.No) + if reply == QtGui.QMessageBox.Yes: # accepted + num = self.tox.friend_add_norequest(tox_id) # num - friend number + item = self.create_friend_item() + friend = Friend(num, tox_id, '', item, tox_id) + self._friends.append(friend) + except Exception as ex: # smth is wrong + log('Accept friend request failed! ' + str(ex)) + def delete_friend(self, num): self.tox.friend_delete(num) friend = filter(lambda x: x.number == num, self._friends)[0]