diff --git a/toxygen/contact.py b/toxygen/contact.py index 5d78c63..8673bab 100644 --- a/toxygen/contact.py +++ b/toxygen/contact.py @@ -5,6 +5,8 @@ except ImportError: import basecontact from messages import * from history import * +import file_transfers as ft +import util class Contact(basecontact.BaseContact): @@ -25,6 +27,7 @@ class Contact(basecontact.BaseContact): self._message_getter = message_getter self._new_messages = False self._visible = True + self._alias = False self._number = number self._corr = [] self._unsaved_messages = 0 @@ -57,11 +60,8 @@ class Contact(basecontact.BaseContact): 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 [] + return list(map(lambda x: x.get_data(), messages[-self._unsaved_messages:])) if self._unsaved_messages else [] def get_corr(self): return self._corr[:] @@ -81,24 +81,50 @@ class Contact(basecontact.BaseContact): else: return '' - def clear_corr(self): + def get_unsent_messages(self): + """ + :return list of unsent messages + """ + messages = filter(lambda x: x.get_owner() == MESSAGE_OWNER['NOT_SENT'], self._corr) + return list(messages) + + def get_unsent_messages_for_saving(self): + """ + :return list of unsent messages for saving + """ + messages = filter(lambda x: x.get_type() <= 1 and x.get_owner() == MESSAGE_OWNER['NOT_SENT'], self._corr) + return list(map(lambda x: x.get_data(), messages)) + + def delete_message(self, time): + elem = list(filter(lambda x: type(x) is TextMessage and x.get_data()[2] == time, self._corr))[0] + tmp = list(filter(lambda x: x.get_type() <= 1, self._corr)) + if elem in tmp[-self._unsaved_messages:]: + self._unsaved_messages -= 1 + self._corr.remove(elem) + + def mark_as_sent(self): + try: + message = list(filter(lambda x: x.get_owner() == MESSAGE_OWNER['NOT_SENT'], self._corr))[0] + message.mark_as_sent() + except Exception as ex: + util.log('Mark as sent ex: ' + str(ex)) + + def clear_corr(self, save_unsent=False): """ 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 or x.get_status() is None), - self._corr)) - self._unsaved_messages = 0 - - def delete_old_messages(self): - old = filter(lambda x: x.get_type() in (2, 3) and (x.get_status() >= 2 or x.get_status() is None), - self._corr[:-SAVE_MESSAGES]) - old = list(old) - l = max(len(self._corr) - SAVE_MESSAGES, 0) - len(old) - self._unsaved_messages -= l - self._corr = old + self._corr[-SAVE_MESSAGES:] + if not save_unsent: + self._corr = list(filter(lambda x: x.get_type() in (2, 3) and + x.get_status() in ft.ACTIVE_FILE_TRANSFERS, self._corr)) + self._unsaved_messages = 0 + else: + self._corr = list(filter(lambda x: (x.get_type() in (2, 3) and x.get_status() in ft.ACTIVE_FILE_TRANSFERS) + or (x.get_type() <= 1 and x.get_owner() == MESSAGE_OWNER['NOT_SENT']), + self._corr)) + self._unsaved_messages = len(self.get_unsent_messages()) def get_curr_text(self): return self._curr_text @@ -161,3 +187,18 @@ class Contact(basecontact.BaseContact): self._number = value number = property(get_number, set_number) + + # ----------------------------------------------------------------------------------------------------------------- + # Alias support + # ----------------------------------------------------------------------------------------------------------------- + + def set_name(self, value): + """ + Set new name or ignore if alias exists + :param value: new name + """ + if not self._alias: + super(Contact, self).set_name(value) + + def set_alias(self, alias): + self._alias = bool(alias) diff --git a/toxygen/friend.py b/toxygen/friend.py index 0045dcc..e9a5657 100644 --- a/toxygen/friend.py +++ b/toxygen/friend.py @@ -1,8 +1,5 @@ import contact from messages import * -from history import * -import util -import file_transfers as ft class Friend(contact.Contact): @@ -15,7 +12,6 @@ class Friend(contact.Contact): :param number: number of friend. """ super(Friend, self).__init__(*args) - self._alias = False self._receipts = 0 def __del__(self): @@ -38,100 +34,6 @@ class Friend(contact.Contact): self._receipts -= 1 self.mark_as_sent() - 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 [] - """ - messages = list(filter(lambda x: x.get_type() <= 1, self._corr)) - return list(map(lambda x: x.get_data(), 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 get_unsent_messages(self): - """ - :return list of unsent messages - """ - messages = filter(lambda x: x.get_owner() == MESSAGE_OWNER['NOT_SENT'], self._corr) - return list(messages) - - def get_unsent_messages_for_saving(self): - """ - :return list of unsent messages for saving - """ - messages = filter(lambda x: x.get_type() <= 1 and x.get_owner() == MESSAGE_OWNER['NOT_SENT'], self._corr) - return list(map(lambda x: x.get_data(), messages)) - - def delete_message(self, time): - elem = list(filter(lambda x: type(x) is TextMessage and x.get_data()[2] == time, self._corr))[0] - tmp = list(filter(lambda x: x.get_type() <= 1, self._corr)) - if elem in tmp[-self._unsaved_messages:]: - self._unsaved_messages -= 1 - self._corr.remove(elem) - - def mark_as_sent(self): - try: - message = list(filter(lambda x: x.get_owner() == MESSAGE_OWNER['NOT_SENT'], self._corr))[0] - message.mark_as_sent() - except Exception as ex: - util.log('Mark as sent ex: ' + str(ex)) - - def clear_corr(self, save_unsent=False): - """ - Clear messages list - """ - if hasattr(self, '_message_getter'): - del self._message_getter - # don't delete data about active file transfer - if not save_unsent: - self._corr = list(filter(lambda x: x.get_type() in (2, 3) and - x.get_status() in ft.ACTIVE_FILE_TRANSFERS, self._corr)) - self._unsaved_messages = 0 - else: - self._corr = list(filter(lambda x: (x.get_type() in (2, 3) and x.get_status() in ft.ACTIVE_FILE_TRANSFERS) - or (x.get_type() <= 1 and x.get_owner() == MESSAGE_OWNER['NOT_SENT']), - self._corr)) - self._unsaved_messages = len(self.get_unsent_messages()) - - 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) - # ----------------------------------------------------------------------------------------------------------------- # File transfers support # ----------------------------------------------------------------------------------------------------------------- @@ -160,18 +62,3 @@ class Friend(contact.Contact): def delete_one_unsent_file(self, time): self._corr = list(filter(lambda x: not (type(x) is UnsentFile and x.get_data()[2] == time), self._corr)) - - # ----------------------------------------------------------------------------------------------------------------- - # Alias support - # ----------------------------------------------------------------------------------------------------------------- - - def set_name(self, value): - """ - Set new name or ignore if alias exists - :param value: new name - """ - if not self._alias: - super(Friend, self).set_name(value) - - def set_alias(self, alias): - self._alias = bool(alias) diff --git a/toxygen/mainscreen.py b/toxygen/mainscreen.py index 5d00ba7..98ea01c 100644 --- a/toxygen/mainscreen.py +++ b/toxygen/mainscreen.py @@ -559,6 +559,14 @@ class MainWindow(QtGui.QMainWindow): if item is not None: self.listMenu = QtGui.QMenu() if type(friend) is Friend: # TODO: add `invite to gc` submenu + arr = Profile.get_instance().get_all_gc() + if arr: + gc_menu = self.listMenu.addMenu(QtGui.QApplication.translate("MainWindow", 'Invite to group chat', None, QtGui.QApplication.UnicodeUTF8)) + for gc in arr: + item = gc.menu.addAction(gc_menu.name) + self.connect(item, QtCore.SIGNAL("triggered()"), + lambda: Profile.get_instance().invite_friend(gc.number), friend.number) + set_alias_item = self.listMenu.addAction(QtGui.QApplication.translate("MainWindow", 'Set alias', None, QtGui.QApplication.UnicodeUTF8)) clear_history_item = self.listMenu.addAction(QtGui.QApplication.translate("MainWindow", 'Clear history', None, QtGui.QApplication.UnicodeUTF8)) copy_menu = self.listMenu.addMenu(QtGui.QApplication.translate("MainWindow", 'Copy', None, QtGui.QApplication.UnicodeUTF8)) @@ -583,7 +591,23 @@ class MainWindow(QtGui.QMainWindow): self.connect(copy_name_item, QtCore.SIGNAL("triggered()"), lambda: self.copy_name(friend)) self.connect(copy_status_item, QtCore.SIGNAL("triggered()"), lambda: self.copy_status(friend)) else: - pass # TODO: add menu for gc + copy_menu = self.listMenu.addMenu( + QtGui.QApplication.translate("MainWindow", 'Copy', None, QtGui.QApplication.UnicodeUTF8)) + copy_name_item = copy_menu.addAction( + QtGui.QApplication.translate("MainWindow", 'Name', None, QtGui.QApplication.UnicodeUTF8)) + copy_status_item = copy_menu.addAction( + QtGui.QApplication.translate("MainWindow", 'Topic', None, QtGui.QApplication.UnicodeUTF8)) + copy_key_item = copy_menu.addAction( + QtGui.QApplication.translate("MainWindow", 'Public key', None, QtGui.QApplication.UnicodeUTF8)) + leave_item = self.listMenu.addAction(QtGui.QApplication.translate("MainWindow", 'Leave group', None, QtGui.QApplication.UnicodeUTF8)) + set_alias_item = self.listMenu.addAction(QtGui.QApplication.translate("MainWindow", 'Set alias', None, QtGui.QApplication.UnicodeUTF8)) + notes_item = self.listMenu.addAction(QtGui.QApplication.translate("MainWindow", 'Notes', None, QtGui.QApplication.UnicodeUTF8)) + self.connect(notes_item, QtCore.SIGNAL("triggered()"), lambda: self.show_note(friend)) + self.connect(copy_name_item, QtCore.SIGNAL("triggered()"), lambda: self.copy_name(friend)) + self.connect(copy_status_item, QtCore.SIGNAL("triggered()"), lambda: self.copy_status(friend)) + self.connect(copy_key_item, QtCore.SIGNAL("triggered()"), lambda: self.copy_friend_key(num)) + self.connect(leave_item, QtCore.SIGNAL("triggered()"), lambda: Profile.get_instance().leave_group(num)) + self.connect(set_alias_item, QtCore.SIGNAL("triggered()"), lambda: self.set_alias(num)) parent_position = self.friends_list.mapToGlobal(QtCore.QPoint(0, 0)) self.listMenu.move(parent_position + pos) self.listMenu.show() @@ -607,7 +631,7 @@ class MainWindow(QtGui.QMainWindow): self.profile.set_alias(num) def remove_friend(self, num): - self.profile.delete_friend(num) + self.profile.delete_friend_or_gc(num) def copy_friend_key(self, num): tox_id = self.profile.friend_public_key(num) diff --git a/toxygen/profile.py b/toxygen/profile.py index d2d03a3..4842811 100644 --- a/toxygen/profile.py +++ b/toxygen/profile.py @@ -674,10 +674,10 @@ class Profile(basecontact.BaseContact, Singleton): def friend_public_key(self, num): return self._friends_and_gc[num].tox_id - def delete_friend(self, num): + def delete_friend_or_gc(self, num): """ - Removes friend from contact list - :param num: number of friend in list + Removes friend or gc from contact list + :param num: number of friend or gc in list """ friend = self._friends_and_gc[num] settings = Settings.get_instance() @@ -732,7 +732,7 @@ class Profile(basecontact.BaseContact, Singleton): settings.save() try: num = self._tox.friend_by_public_key(tox_id) - self.delete_friend(num) + self.delete_friend_or_gc(num) data = self._tox.get_savedata() ProfileHelper.get_instance().save_profile(data) except: # not in friend list @@ -1228,6 +1228,9 @@ class Profile(basecontact.BaseContact, Singleton): # Group chats support # ----------------------------------------------------------------------------------------------------------------- + def get_all_gc(self): + return list(filter(lambda x: type(x) is GroupChat, self._friends_and_gc)) + def add_gc(self, num): tox_id = self._tox.group_get_chat_id(num) name = self._tox.group_get_name(num) @@ -1278,6 +1281,14 @@ class Profile(basecontact.BaseContact, Singleton): except Exception as ex: # something is wrong log('Accept group chat invite failed! ' + str(ex)) + def invite_friend(self, group_number, friend_number): + self._tox.group_invite_friend(group_number, friend_number) + + def leave_group(self, num, message=None): + number = self._friends_and_gc[num].number + self._tox.group_leave(number, message) + self.delete_friend_or_gc(num) + def tox_factory(data=None, settings=None): """ diff --git a/toxygen/tox.py b/toxygen/tox.py index 5f55628..f33b7df 100644 --- a/toxygen/tox.py +++ b/toxygen/tox.py @@ -1607,7 +1607,8 @@ class Tox: """ error = c_int() - result = Tox.libtoxcore.tox_group_leave(self._tox_pointer, groupnumber, message, len(message), byref(error)) + result = Tox.libtoxcore.tox_group_leave(self._tox_pointer, groupnumber, message, + len(message) if message is not None else 0, byref(error)) return result # -----------------------------------------------------------------------------------------------------------------