diff --git a/src/callbacks.py b/src/callbacks.py index 9c7a1c8..417ddfa 100644 --- a/src/callbacks.py +++ b/src/callbacks.py @@ -31,7 +31,6 @@ def invoke_in_main_thread(fn, *args, **kwargs): def self_connection_status(tox_link): """ - :param st: widget on mainscreen which shows status :param tox_link: tox instance :return: function for tox.callback_self_connection_status """ @@ -65,6 +64,7 @@ def friend_connection_status(tox, friend_num, new_status, user_data): friend = profile.get_friend_by_number(friend_num) if new_status == TOX_CONNECTION['NONE']: invoke_in_main_thread(friend.set_status, None) + invoke_in_main_thread(profile.update_filtration) def friend_name(window): diff --git a/src/images/avatar.png b/src/images/avatar.png new file mode 100644 index 0000000..c404617 Binary files /dev/null and b/src/images/avatar.png differ diff --git a/src/mainscreen.py b/src/mainscreen.py index 25efcf7..6838312 100644 --- a/src/mainscreen.py +++ b/src/mainscreen.py @@ -88,10 +88,10 @@ class MainWindow(QtGui.QMainWindow): def setup_right_bottom(self, Form): Form.setObjectName("right_bottom") - Form.resize(500, 150) - Form.setMinimumSize(QtCore.QSize(100, 50)) + Form.resize(500, 100) + #Form.setMinimumSize(QtCore.QSize(100, 50)) self.messageEdit = MessageArea(Form, self) - self.messageEdit.setGeometry(QtCore.QRect(20, 20, 311, 111)) + self.messageEdit.setGeometry(QtCore.QRect(20, 20, 311, 100)) self.messageEdit.setObjectName("messageEdit") self.screenshotButton = QtGui.QPushButton(Form) self.screenshotButton.setGeometry(QtCore.QRect(340, 10, 98, 61)) @@ -128,25 +128,20 @@ class MainWindow(QtGui.QMainWindow): Form.setMinimumSize(QtCore.QSize(250, 100)) Form.setMaximumSize(QtCore.QSize(250, 100)) Form.setBaseSize(QtCore.QSize(250, 100)) - Form.graphicsView = QtGui.QGraphicsView(Form) - Form.graphicsView.setGeometry(QtCore.QRect(10, 20, 64, 64)) - Form.graphicsView.setMinimumSize(QtCore.QSize(64, 64)) - Form.graphicsView.setMaximumSize(QtCore.QSize(64, 64)) - Form.graphicsView.setBaseSize(QtCore.QSize(64, 64)) - Form.graphicsView.setObjectName("graphicsView") + self.avatar_label = Form.avatar_label = QtGui.QLabel(Form) + self.avatar_label.setGeometry(QtCore.QRect(10, 20, 64, 64)) + self.avatar_label.setScaledContents(True) self.name = Form.name = QtGui.QLabel(Form) - Form.name.setGeometry(QtCore.QRect(80, 30, 191, 25)) + Form.name.setGeometry(QtCore.QRect(80, 30, 200, 25)) font = QtGui.QFont() font.setFamily("Times New Roman") - font.setPointSize(16) + font.setPointSize(14) font.setBold(True) Form.name.setFont(font) Form.name.setObjectName("name") self.status_message = Form.status_message = QtGui.QLabel(Form) Form.status_message.setGeometry(QtCore.QRect(80, 60, 191, 17)) - font = QtGui.QFont() - font.setFamily("Times New Roman") - font.setPointSize(14) + font.setPointSize(12) font.setBold(False) Form.status_message.setFont(font) Form.status_message.setObjectName("status_message") @@ -160,25 +155,25 @@ class MainWindow(QtGui.QMainWindow): def setup_right_top(self, Form): Form.setObjectName("Form") Form.resize(495, 111) - self.graphicsView = QtGui.QGraphicsView(Form) - self.graphicsView.setGeometry(QtCore.QRect(10, 20, 64, 64)) - self.graphicsView.setObjectName("graphicsView") + self.account_avatar = QtGui.QLabel(Form) + self.account_avatar.setGeometry(QtCore.QRect(10, 20, 64, 64)) + self.account_avatar.setScaledContents(True) self.account_name = QtGui.QLabel(Form) - self.account_name.setGeometry(QtCore.QRect(100, 20, 211, 17)) + self.account_name.setGeometry(QtCore.QRect(100, 30, 300, 25)) font = QtGui.QFont() - font.setWeight(75) + font.setFamily("Times New Roman") + font.setPointSize(14) font.setBold(True) self.account_name.setFont(font) self.account_name.setObjectName("account_name") self.account_status = QtGui.QLabel(Form) - self.account_status.setGeometry(QtCore.QRect(100, 50, 211, 17)) - font = QtGui.QFont() - font.setWeight(50) + self.account_status.setGeometry(QtCore.QRect(100, 50, 300, 25)) + font.setPointSize(12) font.setBold(False) self.account_status.setFont(font) self.account_status.setObjectName("account_status") self.callButton = QtGui.QPushButton(Form) - self.callButton.setGeometry(QtCore.QRect(380, 30, 98, 27)) + self.callButton.setGeometry(QtCore.QRect(400, 30, 100, 30)) self.callButton.setObjectName("callButton") self.callButton.setText(QtGui.QApplication.translate("Form", "Start call", None, QtGui.QApplication.UnicodeUTF8)) QtCore.QMetaObject.connectSlotsByName(Form) @@ -204,8 +199,9 @@ class MainWindow(QtGui.QMainWindow): self.messages.setGeometry(0, 0, 500, 250) def initUI(self): - self.setMinimumSize(800, 400) - self.setGeometry(400, 400, 800, 400) + self.setMinimumSize(800, 550) + self.setMaximumSize(800, 550) + self.setGeometry(400, 400, 800, 550) self.setWindowTitle('Toxygen') main = QtGui.QWidget() grid = QtGui.QGridLayout() @@ -229,18 +225,11 @@ class MainWindow(QtGui.QMainWindow): grid.addWidget(main_list, 1, 0) grid.setColumnMinimumWidth(1, 500) grid.setColumnMinimumWidth(0, 250) + grid.setRowMinimumHeight(1, 250) main.setLayout(grid) self.setCentralWidget(main) self.setup_menu(self) - def mouseReleaseEvent(self, event): - x, y = event.x(), event.y() - pos = self.connection_status.pos() - if (pos.x() < x < pos.x() + 32) and (pos.y() < y < pos.y() + 32): - self.profile.change_status() - else: - super(self.__class__, self).mouseReleaseEvent(event) - # ----------------------------------------------------------------------------------------------------------------- # Functions which called when user click in menu # ----------------------------------------------------------------------------------------------------------------- @@ -261,7 +250,7 @@ class MainWindow(QtGui.QMainWindow): self.a_c.show() def profile_settings(self): - self.p_s = ProfileSettings(self.tox) + self.p_s = ProfileSettings() self.p_s.show() def privacy_settings(self): @@ -293,6 +282,7 @@ class MainWindow(QtGui.QMainWindow): 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() @@ -302,6 +292,14 @@ class MainWindow(QtGui.QMainWindow): self.messages.clear() self.messageEdit.clear() + def mouseReleaseEvent(self, event): + x, y = event.x(), event.y() + pos = self.connection_status.pos() + if (pos.x() < x < pos.x() + 32) and (pos.y() < y < pos.y() + 32): + self.profile.change_status() + else: + super(self.__class__, self).mouseReleaseEvent(event) + def filtering(self): self.profile.filtration(self.online_contacts.isChecked(), self.contact_name.text()) diff --git a/src/menu.py b/src/menu.py index 2e1fdcb..6e59ff9 100644 --- a/src/menu.py +++ b/src/menu.py @@ -53,9 +53,8 @@ class AddContact(QtGui.QWidget): class ProfileSettings(QtGui.QWidget): """Form with profile settings such as name, status, TOX ID""" - def __init__(self, tox): + def __init__(self): super(ProfileSettings, self).__init__() - self.tox = tox self.initUI() def initUI(self): @@ -67,11 +66,12 @@ class ProfileSettings(QtGui.QWidget): self.nick = QtGui.QLineEdit(self) self.nick.setGeometry(QtCore.QRect(30, 60, 351, 27)) self.nick.setObjectName("nick") - self.nick.setText(self.tox.self_get_name()) + profile = Profile.get_instance() + self.nick.setText(profile.name) self.status = QtGui.QLineEdit(self) self.status.setGeometry(QtCore.QRect(30, 130, 351, 27)) self.status.setObjectName("status") - self.status.setText(self.tox.self_get_status_message()) + self.status.setText(profile.status_message) self.label = QtGui.QLabel(self) self.label.setGeometry(QtCore.QRect(50, 30, 91, 21)) font = QtGui.QFont() @@ -82,29 +82,18 @@ class ProfileSettings(QtGui.QWidget): self.label.setObjectName("label") self.label_2 = QtGui.QLabel(self) self.label_2.setGeometry(QtCore.QRect(50, 100, 91, 21)) - font = QtGui.QFont() - font.setPointSize(18) - font.setWeight(75) - font.setBold(True) self.label_2.setFont(font) self.label_2.setObjectName("label_2") self.label_3 = QtGui.QLabel(self) self.label_3.setGeometry(QtCore.QRect(50, 170, 91, 21)) - font = QtGui.QFont() - font.setPointSize(18) - font.setWeight(75) - font.setBold(True) self.label_3.setFont(font) self.label_3.setObjectName("label_3") self.tox_id = QtGui.QLabel(self) self.tox_id.setGeometry(QtCore.QRect(10, 210, self.width(), 21)) - font = QtGui.QFont() font.setPointSize(10) - #font.setWeight(75) - font.setBold(True) self.tox_id.setFont(font) self.tox_id.setObjectName("tox_id") - s = self.tox.self_get_address() + s = profile.tox_id self.tox_id.setText(s) self.copyId = QtGui.QPushButton(self) self.copyId.setGeometry(QtCore.QRect(40, 250, 98, 31)) @@ -115,10 +104,7 @@ class ProfileSettings(QtGui.QWidget): self.comboBox.setObjectName("comboBox") self.tox_id_2 = QtGui.QLabel(self) self.tox_id_2.setGeometry(QtCore.QRect(40, 310, 121, 31)) - font = QtGui.QFont() font.setPointSize(18) - font.setWeight(75) - font.setBold(True) self.tox_id_2.setFont(font) self.tox_id_2.setObjectName("tox_id_2") self.retranslateUi() @@ -134,8 +120,8 @@ class ProfileSettings(QtGui.QWidget): def copy(self): clipboard = QtGui.QApplication.clipboard() - id = self.tox.self_get_address() - clipboard.setText(id) + profile = Profile.get_instance() + clipboard.setText(profile.tox_id) def closeEvent(self, event): profile = Profile.get_instance() @@ -145,7 +131,7 @@ class ProfileSettings(QtGui.QWidget): class NetworkSettings(QtGui.QWidget): """Network settings form: UDP, Ipv6 and proxy""" - + # TODO: add possibility to change network settings def __init__(self): super(NetworkSettings, self).__init__() self.initUI() diff --git a/src/profile.py b/src/profile.py index 03da404..7c06699 100644 --- a/src/profile.py +++ b/src/profile.py @@ -5,7 +5,7 @@ import os from tox import Tox from toxcore_enums_and_consts import * from ctypes import * -from util import curr_time, log, Singleton +from util import curr_time, log, Singleton, curr_directory class ProfileHelper(object): @@ -56,11 +56,13 @@ class Contact(object): number - unique number of friend in list, widget - widget for update """ - def __init__(self, name, status_message, widget): + def __init__(self, name, status_message, widget, tox_id): self._name, self._status_message = name, status_message self._status, self._widget = None, widget widget.name.setText(name) widget.status_message.setText(status_message) + self._tox_id = tox_id + # self.load_avatar() # ----------------------------------------------------------------------------------------------------------------- # name - current name or alias of user @@ -103,6 +105,29 @@ class Contact(object): 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): + 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)) + pixmap.scaled(64, 64, QtCore.Qt.KeepAspectRatio) + self._widget.avatar_label.setPixmap(avatar_path) + self._widget.avatar_label.repaint() + class Friend(Contact): """ @@ -152,7 +177,10 @@ class Friend(Contact): def get_number(self): return self._number - number = property(get_number) + def set_number(self, value): + self._number = value + + number = property(get_number, set_number) class Profile(Contact, Singleton): @@ -160,6 +188,12 @@ 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): + """ + :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 + """ self._widget = widget self._messages = messages_list self.tox = tox @@ -170,14 +204,16 @@ class Profile(Contact, Singleton): data = tox.self_get_friend_list() self._friends, num, self._active_friend = [], 0, -1 for i in data: - name = tox.friend_get_name(i) or tox.friend_get_public_key(i) + tox_id = tox.friend_get_public_key(i) + name = tox.friend_get_name(i) or tox_id status_message = tox.friend_get_status_message(i) - self._friends.append(Friend(i, name, status_message, widgets[num])) + self._friends.append(Friend(i, name, status_message, widgets[num], tox_id)) num += 1 - Profile._instance = self self.set_name(tox.self_get_name().encode('utf-8')) self.set_status_message(tox.self_get_status_message().encode('utf-8')) self.filtration(self.show_online) + self._tox_id = tox.self_get_address() + self.load_avatar() # ----------------------------------------------------------------------------------------------------------------- # Edit current user's data @@ -208,6 +244,9 @@ class Profile(Contact, Singleton): 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 + def update_filtration(self): + self.filtration(self.show_online, self.filter_string) + def get_friend_by_number(self, num): return filter(lambda x: x.number == num, self._friends)[0] @@ -226,8 +265,6 @@ class Profile(Contact, Singleton): 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._messages.clear() - self._messages.repaint() # TODO: load history except: # no friend found. ignore log('Incorrect friend value: ' + str(value)) @@ -257,6 +294,12 @@ class Profile(Contact, Singleton): # ----------------------------------------------------------------------------------------------------------------- def new_message(self, id, message_type, message): + """ + Current user gets new message + :param id: id 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 user_name = Profile.get_instance().get_active_name() item = MessageItem(message.decode('utf-8'), curr_time(), user_name, message_type, self._messages) @@ -264,13 +307,17 @@ class Profile(Contact, Singleton): elem.setSizeHint(QtCore.QSize(500, item.getHeight())) self._messages.addItem(elem) self._messages.setItemWidget(elem, item) - #self._messages.scrollToBottom() self._messages.repaint() else: friend = filter(lambda x: x.number == id, self._friends)[0] friend.set_messages(True) def send_message(self, text): + """ + Send message to active friend + :param text: message text + :return: True on success + """ if self.is_active_online() and text: if text.startswith('/me '): message_type = TOX_MESSAGE_TYPE['ACTION']