new context menu generation - builder, generators
This commit is contained in:
parent
7898363dcb
commit
c6192de9dd
7 changed files with 178 additions and 78 deletions
|
@ -2,6 +2,7 @@ from history.database import *
|
|||
from contacts import basecontact, common
|
||||
import utils.util as util
|
||||
from messenger.messages import *
|
||||
from contacts.contact_menu import *
|
||||
from file_transfers import file_transfers as ft
|
||||
import re
|
||||
|
||||
|
@ -89,7 +90,7 @@ class Contact(basecontact.BaseContact):
|
|||
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))
|
||||
messages = list(filter(lambda x: x.get_type() <= 1 and x.get_owner() != MESSAGE_AUTHOR['FRIEND'], self._corr))
|
||||
if messages:
|
||||
return messages[-1].get_data()[0]
|
||||
else:
|
||||
|
@ -103,19 +104,19 @@ class Contact(basecontact.BaseContact):
|
|||
"""
|
||||
:return list of unsent messages
|
||||
"""
|
||||
messages = filter(lambda x: x.get_owner() == MESSAGE_OWNER['NOT_SENT'], self._corr)
|
||||
messages = filter(lambda x: x.get_owner() == MESSAGE_AUTHOR['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)
|
||||
messages = filter(lambda x: x.get_type() <= 1 and x.get_owner() == MESSAGE_AUTHOR['NOT_SENT'], self._corr)
|
||||
return list(map(lambda x: x.get_data(), messages))
|
||||
|
||||
def mark_as_sent(self):
|
||||
try:
|
||||
message = list(filter(lambda x: x.get_owner() == MESSAGE_OWNER['NOT_SENT'], self._corr))[0]
|
||||
message = list(filter(lambda x: x.get_owner() == MESSAGE_AUTHOR['NOT_SENT'], self._corr))[0]
|
||||
message.mark_as_sent()
|
||||
except Exception as ex:
|
||||
util.log('Mark as sent ex: ' + str(ex))
|
||||
|
@ -140,7 +141,7 @@ class Contact(basecontact.BaseContact):
|
|||
def save_message(x):
|
||||
if x.get_type() == 2 and (x.get_status() >= 2 or x.get_status() is None):
|
||||
return True
|
||||
return x.get_owner() == MESSAGE_OWNER['NOT_SENT']
|
||||
return x.get_owner() == MESSAGE_AUTHOR['NOT_SENT']
|
||||
|
||||
old = filter(save_message, self._corr[:-SAVE_MESSAGES])
|
||||
self._corr = list(old) + self._corr[-SAVE_MESSAGES:]
|
||||
|
@ -162,7 +163,7 @@ class Contact(basecontact.BaseContact):
|
|||
self._unsaved_messages = 0
|
||||
else:
|
||||
self._corr = list(filter(lambda x: (x.get_type() == 2 and x.get_status() in ft.ACTIVE_FILE_TRANSFERS)
|
||||
or (x.get_type() <= 1 and x.get_owner() == MESSAGE_OWNER['NOT_SENT']),
|
||||
or (x.get_type() <= 1 and x.get_owner() == MESSAGE_AUTHOR['NOT_SENT']),
|
||||
self._corr))
|
||||
self._unsaved_messages = len(self.get_unsent_messages())
|
||||
|
||||
|
@ -294,3 +295,10 @@ class Contact(basecontact.BaseContact):
|
|||
return common.BaseTypingNotificationHandler.DEFAULT_HANDLER
|
||||
|
||||
typing_notification_handler = property(get_typing_notification_handler)
|
||||
|
||||
# -----------------------------------------------------------------------------------------------------------------
|
||||
# Context menu support
|
||||
# -----------------------------------------------------------------------------------------------------------------
|
||||
|
||||
def get_context_menu_generator(self):
|
||||
return BaseContactMenuGenerator(self)
|
||||
|
|
144
toxygen/contacts/contact_menu.py
Normal file
144
toxygen/contacts/contact_menu.py
Normal file
|
@ -0,0 +1,144 @@
|
|||
from PyQt5 import QtWidgets
|
||||
import utils.ui as util_ui
|
||||
|
||||
|
||||
# -----------------------------------------------------------------------------------------------------------------
|
||||
# Builder
|
||||
# -----------------------------------------------------------------------------------------------------------------
|
||||
|
||||
def _create_menu(menu_name):
|
||||
return QtWidgets.QMenu(menu_name or '')
|
||||
|
||||
|
||||
class ContactMenuBuilder:
|
||||
|
||||
def __init__(self):
|
||||
self._actions = []
|
||||
self._submenus = []
|
||||
self._name = None
|
||||
|
||||
def with_name(self, name):
|
||||
self._name = name
|
||||
|
||||
return self
|
||||
|
||||
def with_action(self, text, handler):
|
||||
self._actions.append((text, handler))
|
||||
|
||||
return self
|
||||
|
||||
def with_actions(self, actions):
|
||||
self._actions.extend(actions)
|
||||
|
||||
return self
|
||||
|
||||
def with_submenu(self, submenu):
|
||||
self._add_submenu(submenu)
|
||||
|
||||
return self
|
||||
|
||||
def with_optional_submenu(self, submenu):
|
||||
if submenu is not None:
|
||||
self._add_submenu(submenu)
|
||||
|
||||
return self
|
||||
|
||||
def build(self): # TODO: actions order
|
||||
menu = _create_menu(self._name)
|
||||
|
||||
for text, handler in self._actions:
|
||||
action = menu.addAction(text)
|
||||
action.triggered.connect(handler)
|
||||
|
||||
for submenu in self._submenus:
|
||||
menu.addMenu(submenu)
|
||||
|
||||
return menu
|
||||
|
||||
def _add_submenu(self, submenu):
|
||||
self._submenus.append(submenu)
|
||||
|
||||
# -----------------------------------------------------------------------------------------------------------------
|
||||
# Generators
|
||||
# -----------------------------------------------------------------------------------------------------------------
|
||||
|
||||
|
||||
class BaseContactMenuGenerator:
|
||||
|
||||
def __init__(self, contact):
|
||||
self._contact = contact
|
||||
|
||||
def generate(self, plugin_loader, contacts_manager, main_screen, settings, number):
|
||||
return ContactMenuBuilder().build()
|
||||
|
||||
|
||||
class FriendMenuGenerator(BaseContactMenuGenerator):
|
||||
|
||||
def generate(self, plugin_loader, contacts_manager, main_screen, settings, number):
|
||||
history_menu = self._generate_history_menu(main_screen, number)
|
||||
copy_menu = self._generate_copy_menu(main_screen)
|
||||
plugins_menu = self._generate_plugins_menu(plugin_loader, number)
|
||||
|
||||
allowed = self._contact.tox_id in settings['auto_accept_from_friends']
|
||||
auto = util_ui.tr('Disallow auto accept') if allowed else util_ui.tr('Allow auto accept')
|
||||
|
||||
builder = ContactMenuBuilder()
|
||||
menu = (builder
|
||||
.with_action(util_ui.tr('Set alias'), lambda: main_screen.set_alias(number))
|
||||
.with_action(util_ui.tr('Chat history'), lambda: main_screen.clear_history(number))
|
||||
.with_submenu(history_menu)
|
||||
.with_submenu(copy_menu)
|
||||
.with_action(auto, lambda: main_screen.auto_accept(number, not allowed))
|
||||
.with_action(util_ui.tr('Remove friend'), lambda: main_screen.remove_friend(number))
|
||||
.with_action(util_ui.tr('Block friend'), lambda: main_screen.block_friend(number))
|
||||
.with_action(util_ui.tr('Notes'), lambda: main_screen.show_note(self._contact))
|
||||
.with_optional_submenu(plugins_menu)
|
||||
).build()
|
||||
|
||||
return menu
|
||||
|
||||
# -----------------------------------------------------------------------------------------------------------------
|
||||
# Private methods
|
||||
# -----------------------------------------------------------------------------------------------------------------
|
||||
|
||||
@staticmethod
|
||||
def _generate_history_menu(main_screen, number):
|
||||
history_menu_builder = ContactMenuBuilder()
|
||||
history_menu = (history_menu_builder
|
||||
.with_name(util_ui.tr('Chat history'))
|
||||
.with_action(util_ui.tr('Clear history'), lambda: main_screen.clear_history(number))
|
||||
.with_action(util_ui.tr('Export as text'), lambda: main_screen.export_history(number))
|
||||
.with_action(util_ui.tr('Export as HTML'), lambda: main_screen.export_history(number, False))
|
||||
).build()
|
||||
return history_menu
|
||||
|
||||
def _generate_copy_menu(self, main_screen):
|
||||
copy_menu_builder = ContactMenuBuilder()
|
||||
copy_menu = (copy_menu_builder
|
||||
.with_name(util_ui.tr('Copy'))
|
||||
.with_action(util_ui.tr('Name'), lambda: main_screen.copy_text(self._contact.name))
|
||||
.with_action(util_ui.tr('Status message'), lambda: main_screen.copy_text(self._contact.name))
|
||||
.with_action(util_ui.tr('Public key'), lambda: main_screen.copy_text(self._contact.tox_id))
|
||||
).build()
|
||||
|
||||
return copy_menu
|
||||
|
||||
@staticmethod
|
||||
def _generate_plugins_menu(plugin_loader, number):
|
||||
if plugin_loader is None:
|
||||
return None
|
||||
plugins_actions = plugin_loader.get_menu(number)
|
||||
if not len(plugins_actions):
|
||||
return None
|
||||
plugins_menu_builder = ContactMenuBuilder()
|
||||
plugins_menu = (plugins_menu_builder
|
||||
.with_name(util_ui.tr('Plugins'))
|
||||
.with_actions(plugins_actions)
|
||||
)
|
||||
|
||||
return plugins_menu
|
||||
|
||||
def _generate_groups_menu(self, contacts_manager):
|
||||
chats = contacts_manager.get_group_chats()
|
||||
if not len(chats) or self._contact.status is None:
|
||||
return None
|
|
@ -1,4 +1,3 @@
|
|||
import utils.util as util
|
||||
import common.tox_save as tox_save
|
||||
|
||||
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
from contacts import contact, common
|
||||
from messenger.messages import *
|
||||
import os
|
||||
from contacts.contact_menu import *
|
||||
|
||||
|
||||
class Friend(contact.Contact):
|
||||
|
@ -46,6 +47,7 @@ class Friend(contact.Contact):
|
|||
if message.get_data()[1] is not None:
|
||||
return True
|
||||
return os.path.exists(message.get_data()[0])
|
||||
|
||||
self._corr = list(filter(is_valid, self._corr))
|
||||
|
||||
def delete_one_unsent_file(self, time):
|
||||
|
@ -81,3 +83,10 @@ class Friend(contact.Contact):
|
|||
|
||||
def get_typing_notification_handler(self):
|
||||
return self._typing_notification_handler
|
||||
|
||||
# -----------------------------------------------------------------------------------------------------------------
|
||||
# Context menu support
|
||||
# -----------------------------------------------------------------------------------------------------------------
|
||||
|
||||
def get_context_menu_generator(self):
|
||||
return FriendMenuGenerator(self)
|
||||
|
|
|
@ -138,7 +138,7 @@ class PluginLoader():
|
|||
if name in self._plugins and self._plugins[name][1]:
|
||||
self._plugins[name][0].command(text[len(name) + 1:])
|
||||
|
||||
def get_menu(self, menu, num):
|
||||
def get_menu(self, num):
|
||||
"""
|
||||
Return list of items for menu
|
||||
"""
|
||||
|
@ -146,7 +146,7 @@ class PluginLoader():
|
|||
for elem in self._plugins.values():
|
||||
if elem[1]:
|
||||
try:
|
||||
result.extend(elem[0].get_menu(menu, num))
|
||||
result.extend(elem[0].get_menu(num))
|
||||
except:
|
||||
continue
|
||||
return result
|
||||
|
|
|
@ -76,12 +76,11 @@ class PluginSuperClass:
|
|||
"""
|
||||
return self.__doc__
|
||||
|
||||
def get_menu(self, menu, row_number):
|
||||
def get_menu(self, row_number):
|
||||
"""
|
||||
This method creates items for menu which called on right click in list of friends
|
||||
:param menu: menu instance
|
||||
:param row_number: number of selected row in list of contacts
|
||||
:return list of QAction's
|
||||
:return list of tuples (text, handler)
|
||||
"""
|
||||
return []
|
||||
|
||||
|
|
|
@ -576,63 +576,14 @@ class MainWindow(QtWidgets.QMainWindow):
|
|||
def friend_right_click(self, pos):
|
||||
# TODO: move to contact?
|
||||
item = self.friends_list.itemAt(pos)
|
||||
num = self.friends_list.indexFromItem(item).row()
|
||||
contact = self._contacts_manager.get_contact(num)
|
||||
number = self.friends_list.indexFromItem(item).row()
|
||||
contact = self._contacts_manager.get_contact(number)
|
||||
if contact is None:
|
||||
return
|
||||
allowed = contact.tox_id in self._settings['auto_accept_from_friends']
|
||||
auto = util_ui.tr('Disallow auto accept') if allowed else util_ui.tr('Allow auto accept')
|
||||
if item is not None:
|
||||
self.listMenu = QtWidgets.QMenu()
|
||||
is_friend = type(contact) is Friend
|
||||
if is_friend:
|
||||
set_alias_item = self.listMenu.addAction(util_ui.tr('Set alias'))
|
||||
set_alias_item.triggered.connect(lambda: self.set_alias(num))
|
||||
|
||||
history_menu = self.listMenu.addMenu(util_ui.tr('Chat history'))
|
||||
clear_history_item = history_menu.addAction(util_ui.tr('Clear history'))
|
||||
export_to_text_item = history_menu.addAction(util_ui.tr('Export as text'))
|
||||
export_to_html_item = history_menu.addAction(util_ui.tr('Export as HTML'))
|
||||
|
||||
copy_menu = self.listMenu.addMenu(util_ui.tr('Copy'))
|
||||
copy_name_item = copy_menu.addAction(util_ui.tr('Name'))
|
||||
copy_status_item = copy_menu.addAction(util_ui.tr('Status message'))
|
||||
if is_friend:
|
||||
copy_key_item = copy_menu.addAction(util_ui.tr('Public key'))
|
||||
|
||||
auto_accept_item = self.listMenu.addAction(auto)
|
||||
remove_item = self.listMenu.addAction(util_ui.tr('Remove friend'))
|
||||
block_item = self.listMenu.addAction(util_ui.tr('Block friend'))
|
||||
notes_item = self.listMenu.addAction(util_ui.tr('Notes'))
|
||||
|
||||
chats = self._contacts_manager.get_group_chats()
|
||||
if len(chats) and contact.status is not None:
|
||||
invite_menu = self.listMenu.addMenu(util_ui.tr('Invite to group chat'))
|
||||
for i in range(len(chats)):
|
||||
name, number = chats[i]
|
||||
item = invite_menu.addAction(name)
|
||||
item.triggered.connect(lambda: self.invite_friend_to_gc(num, number))
|
||||
|
||||
if self._plugins_loader is not None:
|
||||
submenu = self._plugins_loader.get_menu(self.listMenu, num)
|
||||
if len(submenu):
|
||||
plug = self.listMenu.addMenu(util_ui.tr('Plugins'))
|
||||
plug.addActions(submenu)
|
||||
copy_key_item.triggered.connect(lambda: self.copy_friend_key(num))
|
||||
remove_item.triggered.connect(lambda: self.remove_friend(num))
|
||||
block_item.triggered.connect(lambda: self.block_friend(num))
|
||||
auto_accept_item.triggered.connect(lambda: self.auto_accept(num, not allowed))
|
||||
notes_item.triggered.connect(lambda: self.show_note(contact))
|
||||
else:
|
||||
leave_item = self.listMenu.addAction(util_ui.tr('Leave chat'))
|
||||
set_title_item = self.listMenu.addAction(util_ui.tr('Set title'))
|
||||
leave_item.triggered.connect(lambda: self.leave_gc(num))
|
||||
set_title_item.triggered.connect(lambda: self.set_title(num))
|
||||
clear_history_item.triggered.connect(lambda: self.clear_history(num))
|
||||
copy_name_item.triggered.connect(lambda: self.copy_name(contact))
|
||||
copy_status_item.triggered.connect(lambda: self.copy_status(contact))
|
||||
export_to_text_item.triggered.connect(lambda: self.export_history(num))
|
||||
export_to_html_item.triggered.connect(lambda: self.export_history(num, False))
|
||||
generator = contact.get_context_menu_generator()
|
||||
self.listMenu = generator.generate(self._plugins_loader, self._contacts_manager, self,
|
||||
self._settings, number)
|
||||
parent_position = self.friends_list.mapToGlobal(QtCore.QPoint(0, 0))
|
||||
self.listMenu.move(parent_position + pos)
|
||||
self.listMenu.show()
|
||||
|
@ -672,20 +623,10 @@ class MainWindow(QtWidgets.QMainWindow):
|
|||
friend = self.profile.get_contact(num)
|
||||
self._contacts_manager.block_user(friend.tox_id)
|
||||
|
||||
def copy_friend_key(self, num):
|
||||
tox_id = self._contacts_manager.friend_public_key(num)
|
||||
clipboard = QtWidgets.QApplication.clipboard()
|
||||
clipboard.setText(tox_id)
|
||||
|
||||
@staticmethod
|
||||
def copy_name(friend):
|
||||
def copy_text(text):
|
||||
clipboard = QtWidgets.QApplication.clipboard()
|
||||
clipboard.setText(friend.name)
|
||||
|
||||
@staticmethod
|
||||
def copy_status(friend):
|
||||
clipboard = QtWidgets.QApplication.clipboard()
|
||||
clipboard.setText(friend.status_message)
|
||||
clipboard.setText(text)
|
||||
|
||||
def clear_history(self, num):
|
||||
self._contacts_manager.clear_history(num)
|
||||
|
|
Loading…
Reference in a new issue