messenger created. callbacks fixes. contacts refactoring
This commit is contained in:
parent
ddf6cd8328
commit
6ebafbda44
17 changed files with 406 additions and 289 deletions
150
toxygen/app.py
150
toxygen/app.py
|
@ -26,13 +26,14 @@ from history.database import Database
|
|||
from ui.widgets_factory import WidgetsFactory
|
||||
from smileys.smileys import SmileyLoader
|
||||
from ui.items_factory import ItemsFactory
|
||||
from messenger.messenger import Messenger
|
||||
|
||||
|
||||
class App:
|
||||
|
||||
def __init__(self, version, path_to_profile=None, uri=None):
|
||||
self._version = version
|
||||
self._app = self._settings = self._profile_manager = self._plugin_loader = None
|
||||
self._app = self._settings = self._profile_manager = self._plugin_loader = self._messenger = None
|
||||
self._tox = self._ms = self._init = self._main_loop = self._av_loop = None
|
||||
self._uri = self._toxes = self._tray = self._file_transfer_handler = self._contacts_provider = None
|
||||
self._friend_factory = self._calls_manager = self._contacts_manager = self._smiley_loader = None
|
||||
|
@ -40,6 +41,71 @@ class App:
|
|||
self._uri = uri[4:]
|
||||
self._path = path_to_profile
|
||||
|
||||
# -----------------------------------------------------------------------------------------------------------------
|
||||
# Public methods
|
||||
# -----------------------------------------------------------------------------------------------------------------
|
||||
|
||||
def main(self):
|
||||
"""
|
||||
Main function of app. loads login screen if needed and starts main screen
|
||||
"""
|
||||
self._app = QtWidgets.QApplication([])
|
||||
self._load_icon()
|
||||
|
||||
if get_platform() == 'Linux':
|
||||
QtCore.QCoreApplication.setAttribute(QtCore.Qt.AA_X11InitThreads)
|
||||
|
||||
self._load_base_style()
|
||||
|
||||
encrypt_save = tox_encrypt_save.ToxEncryptSave()
|
||||
self._toxes = user_data.toxes.ToxES(encrypt_save)
|
||||
|
||||
if self._path is not None: # toxygen was started with path to profile
|
||||
self._load_existing_profile(self._path)
|
||||
else:
|
||||
auto_profile = Settings.get_auto_profile()
|
||||
if auto_profile is None: # no default profile
|
||||
result = self._select_profile()
|
||||
if result is None:
|
||||
return
|
||||
if result.is_new_profile(): # create new profile
|
||||
self._create_new_profile(result.profile_path)
|
||||
else: # load existing profile
|
||||
self._load_existing_profile(result.profile_path)
|
||||
self._path = result.profile_path
|
||||
else: # default profile
|
||||
path, name = auto_profile
|
||||
self._path = os.path.join(path, name + '.tox')
|
||||
self._load_existing_profile(self._path)
|
||||
|
||||
if Settings.is_active_profile(self._path): # profile is in use
|
||||
profile_name = get_profile_name_from_path(self._path)
|
||||
title = util_ui.tr('Profile {}').format(profile_name)
|
||||
text = util_ui.tr('Other instance of Toxygen uses this profile or profile was not properly closed. Continue?')
|
||||
reply = util_ui.question(text, title)
|
||||
if not reply:
|
||||
return
|
||||
|
||||
self._settings.set_active_profile()
|
||||
|
||||
self._load_app_styles()
|
||||
self._load_app_translations()
|
||||
|
||||
if self._try_to_update():
|
||||
return
|
||||
|
||||
self._create_dependencies()
|
||||
self._start_threads()
|
||||
|
||||
if self._uri is not None:
|
||||
self._ms.add_contact(self._uri)
|
||||
|
||||
self._app.lastWindowClosed.connect(self._app.quit)
|
||||
|
||||
self._execute_app()
|
||||
|
||||
self._stop_app()
|
||||
|
||||
# -----------------------------------------------------------------------------------------------------------------
|
||||
# App executing
|
||||
# -----------------------------------------------------------------------------------------------------------------
|
||||
|
@ -220,7 +286,7 @@ class App:
|
|||
|
||||
def _create_dependencies(self):
|
||||
self._smiley_loader = SmileyLoader(self._settings)
|
||||
self._ms = MainWindow(self._settings, self._tox, self._tray)
|
||||
self._ms = MainWindow(self._settings, self._tray)
|
||||
db = Database(self._path.replace('.tox', '.db'), self._toxes)
|
||||
profile = Profile(self._profile_manager, self._tox, self._ms, self._file_transfer_handler)
|
||||
self._plugin_loader = PluginLoader(self._tox, self._toxes, profile, self._settings) # plugins support
|
||||
|
@ -231,19 +297,20 @@ class App:
|
|||
self._smiley_loader, self._plugin_loader, self._toxes)
|
||||
self._contacts_manager = ContactsManager(self._tox, self._settings, self._ms, self._profile_manager,
|
||||
self._contacts_provider, db)
|
||||
self._messenger = Messenger(self._tox, self._plugin_loader, self._ms, self._contacts_manager,
|
||||
self._contacts_provider)
|
||||
self._tray = tray.init_tray(profile, self._settings, self._ms)
|
||||
self._ms.set_dependencies(widgets_factory, self._tray, self._contacts_manager, self._messenger)
|
||||
self._calls_manager = CallsManager(self._tox.AV, self._settings)
|
||||
self._file_transfer_handler = FileTransfersHandler(self._tox, self._settings, self._contacts_provider)
|
||||
self._ms.profile = profile
|
||||
self._ms.set_widget_factory(widgets_factory)
|
||||
self._ms.show()
|
||||
|
||||
self._tray = tray.init_tray(profile, self._settings, self._ms)
|
||||
self._ms.set_tray(self._tray)
|
||||
self._tray.show()
|
||||
|
||||
self._ms.show()
|
||||
|
||||
# callbacks initialization
|
||||
callbacks.init_callbacks(self._tox, profile, self._settings, self._plugin_loader, self._contacts_manager,
|
||||
self._calls_manager, self._file_transfer_handler, self._ms, self._tray)
|
||||
self._calls_manager, self._file_transfer_handler, self._ms, self._tray,
|
||||
self._messenger)
|
||||
|
||||
def _try_to_update(self):
|
||||
updating = updater.start_update_if_needed(self._version, self._settings)
|
||||
|
@ -255,68 +322,3 @@ class App:
|
|||
|
||||
def _create_tox(self, data):
|
||||
return tox_factory(data, self._settings)
|
||||
|
||||
# -----------------------------------------------------------------------------------------------------------------
|
||||
# Public methods
|
||||
# -----------------------------------------------------------------------------------------------------------------
|
||||
|
||||
def main(self):
|
||||
"""
|
||||
Main function of app. loads login screen if needed and starts main screen
|
||||
"""
|
||||
self._app = QtWidgets.QApplication([])
|
||||
self._load_icon()
|
||||
|
||||
if get_platform() == 'Linux':
|
||||
QtCore.QCoreApplication.setAttribute(QtCore.Qt.AA_X11InitThreads)
|
||||
|
||||
self._load_base_style()
|
||||
|
||||
encrypt_save = tox_encrypt_save.ToxEncryptSave()
|
||||
self._toxes = user_data.toxes.ToxES(encrypt_save)
|
||||
|
||||
if self._path is not None: # toxygen was started with path to profile
|
||||
self._load_existing_profile(self._path)
|
||||
else:
|
||||
auto_profile = Settings.get_auto_profile()
|
||||
if auto_profile is None: # no default profile
|
||||
result = self._select_profile()
|
||||
if result is None:
|
||||
return
|
||||
if result.is_new_profile(): # create new profile
|
||||
self._create_new_profile(result.profile_path)
|
||||
else: # load existing profile
|
||||
self._load_existing_profile(result.profile_path)
|
||||
self._path = result.profile_path
|
||||
else: # default profile
|
||||
path, name = auto_profile
|
||||
self._path = os.path.join(path, name + '.tox')
|
||||
self._load_existing_profile(self._path)
|
||||
|
||||
if Settings.is_active_profile(self._path): # profile is in use
|
||||
profile_name = get_profile_name_from_path(self._path)
|
||||
title = util_ui.tr('Profile {}').format(profile_name)
|
||||
text = util_ui.tr('Other instance of Toxygen uses this profile or profile was not properly closed. Continue?')
|
||||
reply = util_ui.question(text, title)
|
||||
if not reply:
|
||||
return
|
||||
|
||||
self._settings.set_active_profile()
|
||||
|
||||
self._load_app_styles()
|
||||
self._load_app_translations()
|
||||
|
||||
if self._try_to_update():
|
||||
return
|
||||
|
||||
self._create_dependencies()
|
||||
self._start_threads()
|
||||
|
||||
if self._uri is not None:
|
||||
self._ms.add_contact(self._uri)
|
||||
|
||||
self._app.lastWindowClosed.connect(self._app.quit)
|
||||
|
||||
self._execute_app()
|
||||
|
||||
self._stop_app()
|
||||
|
|
24
toxygen/contacts/common.py
Normal file
24
toxygen/contacts/common.py
Normal file
|
@ -0,0 +1,24 @@
|
|||
|
||||
|
||||
class BaseTypingNotificationHandler:
|
||||
|
||||
DEFAULT_HANDLER = None
|
||||
|
||||
def __init__(self):
|
||||
pass
|
||||
|
||||
def send(self, tox, is_typing):
|
||||
pass
|
||||
|
||||
|
||||
class FriendTypingNotificationHandler(BaseTypingNotificationHandler):
|
||||
|
||||
def __init__(self, friend_number):
|
||||
super().__init__()
|
||||
self._friend_number = friend_number
|
||||
|
||||
def send(self, tox, is_typing):
|
||||
tox.self_set_typing(self._friend_number, is_typing)
|
||||
|
||||
|
||||
BaseTypingNotificationHandler.DEFAULT_HANDLER = BaseTypingNotificationHandler()
|
|
@ -1,5 +1,5 @@
|
|||
from history.database import *
|
||||
from contacts import basecontact
|
||||
from contacts import basecontact, common
|
||||
import util.util as util
|
||||
from messenger.messages import *
|
||||
from file_transfers import file_transfers as ft
|
||||
|
@ -285,3 +285,12 @@ class Contact(basecontact.BaseContact):
|
|||
self._number = value
|
||||
|
||||
number = property(get_number, set_number)
|
||||
|
||||
# -----------------------------------------------------------------------------------------------------------------
|
||||
# Typing notifications
|
||||
# -----------------------------------------------------------------------------------------------------------------
|
||||
|
||||
def get_typing_notification_handler(self):
|
||||
return common.BaseTypingNotificationHandler.DEFAULT_HANDLER
|
||||
|
||||
typing_notification_handler = property(get_typing_notification_handler)
|
||||
|
|
|
@ -8,16 +8,6 @@ class ContactProvider(util.ToxSave):
|
|||
self._friend_factory = friend_factory
|
||||
self._cache = {} # key - contact's public key, value - contact instance
|
||||
|
||||
# -----------------------------------------------------------------------------------------------------------------
|
||||
# Private methods
|
||||
# -----------------------------------------------------------------------------------------------------------------
|
||||
|
||||
def _get_contact_from_cache(self, public_key):
|
||||
return self._cache[public_key] if public_key in self._cache else None
|
||||
|
||||
def _add_to_cache(self, public_key, contact):
|
||||
self._cache[public_key] = contact
|
||||
|
||||
# -----------------------------------------------------------------------------------------------------------------
|
||||
# Friends
|
||||
# -----------------------------------------------------------------------------------------------------------------
|
||||
|
@ -72,3 +62,13 @@ class ContactProvider(util.ToxSave):
|
|||
def remove_friend_from_cache(self, friend_public_key):
|
||||
if friend_public_key in self._cache:
|
||||
del self._cache[friend_public_key]
|
||||
|
||||
# -----------------------------------------------------------------------------------------------------------------
|
||||
# Private methods
|
||||
# -----------------------------------------------------------------------------------------------------------------
|
||||
|
||||
def _get_contact_from_cache(self, public_key):
|
||||
return self._cache[public_key] if public_key in self._cache else None
|
||||
|
||||
def _add_to_cache(self, public_key, contact):
|
||||
self._cache[public_key] = contact
|
||||
|
|
|
@ -9,6 +9,9 @@ from network.tox_dns import tox_dns
|
|||
from history.history_loader import HistoryLoader
|
||||
|
||||
|
||||
# TODO: move messaging and typing notifications to other class
|
||||
|
||||
|
||||
class ContactsManager:
|
||||
|
||||
def __init__(self, tox, settings, screen, profile_manager, contact_provider, db):
|
||||
|
@ -29,26 +32,6 @@ class ContactsManager:
|
|||
def __del__(self):
|
||||
del self._history
|
||||
|
||||
# -----------------------------------------------------------------------------------------------------------------
|
||||
# Private methods
|
||||
# -----------------------------------------------------------------------------------------------------------------
|
||||
|
||||
def _is_active_a_friend(self):
|
||||
return type(self.get_curr_contact()) is Friend
|
||||
|
||||
def _load_contacts(self):
|
||||
self._load_friends()
|
||||
self._load_groups()
|
||||
if len(self._contacts):
|
||||
self.set_active(0)
|
||||
self.filtration_and_sorting(self._sorting)
|
||||
|
||||
def _load_friends(self):
|
||||
self._contacts.extend(self._contact_provider.get_all_friends())
|
||||
|
||||
def _load_groups(self):
|
||||
self._contacts.extend(self._contact_provider.get_all_groups())
|
||||
|
||||
def get_friend(self, num):
|
||||
if num < 0 or num >= len(self._contacts):
|
||||
return None
|
||||
|
@ -61,6 +44,12 @@ class ContactsManager:
|
|||
data = self._tox.get_savedata()
|
||||
self._profile_manager.save_profile(data)
|
||||
|
||||
def is_friend_active(self, friend_number):
|
||||
if not self._is_active_a_friend():
|
||||
return False
|
||||
|
||||
return self.get_curr_contact().number == friend_number
|
||||
|
||||
# -----------------------------------------------------------------------------------------------------------------
|
||||
# Work with active friend
|
||||
# -----------------------------------------------------------------------------------------------------------------
|
||||
|
@ -85,7 +74,7 @@ class ContactsManager:
|
|||
self._screen.messageEdit.clear()
|
||||
return
|
||||
try:
|
||||
self.send_typing(False)
|
||||
# self.send_typing(False) # TODO: fix
|
||||
self._screen.typing.setVisible(False)
|
||||
if value is not None:
|
||||
if self._active_contact + 1 and self._active_contact != value:
|
||||
|
@ -430,25 +419,25 @@ class ContactsManager:
|
|||
except Exception as ex: # something is wrong
|
||||
util.log('Accept friend request failed! ' + str(ex))
|
||||
|
||||
def can_send_typing_notification(self):
|
||||
return self._settings['typing_notifications'] and self._active_contact != -1
|
||||
|
||||
# -----------------------------------------------------------------------------------------------------------------
|
||||
# Typing notifications
|
||||
# Private methods
|
||||
# -----------------------------------------------------------------------------------------------------------------
|
||||
|
||||
def send_typing(self, typing):
|
||||
"""
|
||||
Send typing notification to a friend
|
||||
"""
|
||||
if self._settings['typing_notifications'] and self._active_contact + 1:
|
||||
try:
|
||||
contact = self.get_curr_contact()
|
||||
if contact.status is not None and self._is_active_a_friend(): # TODO: fix - no type check
|
||||
self._tox.self_set_typing(contact.number, typing)
|
||||
except:
|
||||
pass
|
||||
def _is_active_a_friend(self):
|
||||
return type(self.get_curr_contact()) is Friend
|
||||
|
||||
def friend_typing(self, friend_number, typing):
|
||||
"""
|
||||
Display incoming typing notification
|
||||
"""
|
||||
if friend_number == self.get_active_number() and self.is_active_a_friend():
|
||||
self._screen.typing.setVisible(typing)
|
||||
def _load_contacts(self):
|
||||
self._load_friends()
|
||||
self._load_groups()
|
||||
if len(self._contacts):
|
||||
self.set_active(0)
|
||||
self.filtration_and_sorting(self._sorting)
|
||||
|
||||
def _load_friends(self):
|
||||
self._contacts.extend(self._contact_provider.get_all_friends())
|
||||
|
||||
def _load_groups(self):
|
||||
self._contacts.extend(self._contact_provider.get_all_groups())
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
from contacts import contact
|
||||
from contacts import contact, common
|
||||
from messenger.messages import *
|
||||
import os
|
||||
|
||||
|
@ -11,6 +11,7 @@ class Friend(contact.Contact):
|
|||
def __init__(self, profile_manager, message_getter, number, name, status_message, widget, tox_id):
|
||||
super().__init__(profile_manager, message_getter, number, name, status_message, widget, tox_id)
|
||||
self._receipts = 0
|
||||
self._typing_notification_handler = common.FriendTypingNotificationHandler(number)
|
||||
|
||||
# -----------------------------------------------------------------------------------------------------------------
|
||||
# File transfers support
|
||||
|
@ -73,3 +74,10 @@ class Friend(contact.Contact):
|
|||
|
||||
def get_full_status(self):
|
||||
return self._status_message
|
||||
|
||||
# -----------------------------------------------------------------------------------------------------------------
|
||||
# Typing notifications
|
||||
# -----------------------------------------------------------------------------------------------------------------
|
||||
|
||||
def get_typing_notification_handler(self):
|
||||
return self._typing_notification_handler
|
||||
|
|
|
@ -7,7 +7,12 @@ class FriendFactory:
|
|||
self._profile_manager = profile_manager
|
||||
self._settings, self._tox = settings, tox
|
||||
self._db = db
|
||||
self._factory = items_factory
|
||||
self._items_factory = items_factory
|
||||
|
||||
def create_friend_by_public_key(self, public_key):
|
||||
friend_number = self._tox.friend_by_public_key(public_key)
|
||||
|
||||
return self.create_friend_by_number(friend_number)
|
||||
|
||||
def create_friend_by_number(self, friend_number):
|
||||
aliases = self._settings['friends_aliases']
|
||||
|
@ -16,7 +21,7 @@ class FriendFactory:
|
|||
alias = list(filter(lambda x: x[0] == tox_id, aliases))[0][1]
|
||||
except:
|
||||
alias = ''
|
||||
item = self.create_friend_item()
|
||||
item = self._create_friend_item()
|
||||
name = alias or self._tox.friend_get_name(friend_number) or tox_id
|
||||
status_message = self._tox.friend_get_status_message(friend_number)
|
||||
message_getter = self._db.messages_getter(tox_id)
|
||||
|
@ -25,14 +30,13 @@ class FriendFactory:
|
|||
|
||||
return friend
|
||||
|
||||
def create_friend_by_public_key(self, public_key):
|
||||
friend_number = self._tox.friend_by_public_key(public_key)
|
||||
# -----------------------------------------------------------------------------------------------------------------
|
||||
# Private methods
|
||||
# -----------------------------------------------------------------------------------------------------------------
|
||||
|
||||
return self.create_friend_by_number(friend_number)
|
||||
|
||||
def create_friend_item(self):
|
||||
def _create_friend_item(self):
|
||||
"""
|
||||
Method-factory
|
||||
:return: new widget for friend instance
|
||||
"""
|
||||
return self._factory.friend_item()
|
||||
return self._items_factory.friend_item()
|
||||
|
|
|
@ -32,9 +32,7 @@ class Profile(basecontact.BaseContact):
|
|||
self._file_transfers = {} # dict of file transfers. key - tuple (friend_number, file_number)
|
||||
self._load_history = True
|
||||
self._waiting_for_reconnection = False
|
||||
#self._factory = items_factory.ItemsFactory(self._screen.friends_list, self._messages)
|
||||
self._contacts_manager = None
|
||||
#self._show_avatars = settings['show_avatars']
|
||||
|
||||
# -----------------------------------------------------------------------------------------------------------------
|
||||
# Edit current user's data
|
||||
|
@ -48,7 +46,7 @@ class Profile(basecontact.BaseContact):
|
|||
self.set_status((self._status + 1) % 3)
|
||||
|
||||
def set_status(self, status):
|
||||
super(Profile, self).set_status(status)
|
||||
super().set_status(status)
|
||||
if status is not None:
|
||||
self._tox.self_set_status(status)
|
||||
elif not self._waiting_for_reconnection:
|
||||
|
@ -59,7 +57,7 @@ class Profile(basecontact.BaseContact):
|
|||
if self.name == value:
|
||||
return
|
||||
tmp = self.name
|
||||
super(Profile, self).set_name(value.encode('utf-8'))
|
||||
super().set_name(value.encode('utf-8'))
|
||||
self._tox.self_set_name(self._name.encode('utf-8'))
|
||||
message = util_ui.tr('User {} is now known as {}')
|
||||
message = message.format(tmp, value)
|
||||
|
@ -149,76 +147,6 @@ class Profile(basecontact.BaseContact):
|
|||
except Exception as ex:
|
||||
log('Sending pending messages failed with ' + str(ex))
|
||||
|
||||
def split_message(self, message):
|
||||
messages = []
|
||||
while len(message) > TOX_MAX_MESSAGE_LENGTH:
|
||||
size = TOX_MAX_MESSAGE_LENGTH * 4 / 5
|
||||
last_part = message[size:TOX_MAX_MESSAGE_LENGTH]
|
||||
if ' ' in last_part:
|
||||
index = last_part.index(' ')
|
||||
elif ',' in last_part:
|
||||
index = last_part.index(',')
|
||||
elif '.' in last_part:
|
||||
index = last_part.index('.')
|
||||
else:
|
||||
index = TOX_MAX_MESSAGE_LENGTH - size - 1
|
||||
index += size + 1
|
||||
messages.append(message[:index])
|
||||
message = message[index:]
|
||||
|
||||
return messages
|
||||
|
||||
def new_message(self, friend_num, message_type, message):
|
||||
"""
|
||||
Current user gets new message
|
||||
:param friend_num: friend_num of friend who sent message
|
||||
:param message_type: message type - plain text or action message (/me)
|
||||
:param message: text of message
|
||||
"""
|
||||
if friend_num == self.get_active_number()and self.is_active_a_friend(): # add message to list
|
||||
t = time.time()
|
||||
self.create_message_item(message, t, MESSAGE_OWNER['FRIEND'], message_type)
|
||||
self._messages.scrollToBottom()
|
||||
self.get_curr_friend().append_message(
|
||||
TextMessage(message, MESSAGE_OWNER['FRIEND'], t, message_type))
|
||||
else:
|
||||
friend = self.get_friend_by_number(friend_num)
|
||||
friend.inc_messages()
|
||||
friend.append_message(
|
||||
TextMessage(message, MESSAGE_OWNER['FRIEND'], time.time(), message_type))
|
||||
if not friend.visibility:
|
||||
self.update_filtration()
|
||||
|
||||
def send_message_to_friend(self, text, friend_number=None):
|
||||
"""
|
||||
Send message
|
||||
:param text: message text
|
||||
:param friend_number: number of friend
|
||||
"""
|
||||
if friend_number is None:
|
||||
friend_number = self.get_active_number()
|
||||
if text.startswith('/plugin '):
|
||||
self._plugin_loader.command(text[8:])
|
||||
self._screen.messageEdit.clear()
|
||||
elif text and friend_number >= 0:
|
||||
if text.startswith('/me '):
|
||||
message_type = TOX_MESSAGE_TYPE['ACTION']
|
||||
text = text[4:]
|
||||
else:
|
||||
message_type = TOX_MESSAGE_TYPE['NORMAL']
|
||||
friend = self.get_friend_by_number(friend_number)
|
||||
friend.inc_receipts()
|
||||
if friend.status is not None:
|
||||
messages = self.split_message(text.encode('utf-8'))
|
||||
for message in messages:
|
||||
self._tox.friend_send_message(friend_number, message_type, message)
|
||||
t = time.time()
|
||||
if friend.number == self.get_active_number() and self.is_active_a_friend():
|
||||
self.create_message_item(text, t, MESSAGE_OWNER['NOT_SENT'], message_type)
|
||||
self._screen.messageEdit.clear()
|
||||
self._messages.scrollToBottom()
|
||||
friend.append_message(TextMessage(text, MESSAGE_OWNER['NOT_SENT'], t, message_type))
|
||||
|
||||
def delete_message(self, message_id):
|
||||
friend = self.get_curr_friend()
|
||||
friend.delete_message(time)
|
||||
|
|
|
@ -20,9 +20,6 @@ class FileTransfersHandler:
|
|||
self._settings['paused_file_transfers'] = self._paused_file_transfers if self._settings['resend_files'] else {}
|
||||
self._settings.save()
|
||||
|
||||
def _get_friend_by_number(self, friend_number):
|
||||
return self._contact_provider.get_friend_by_number(friend_number)
|
||||
|
||||
# -----------------------------------------------------------------------------------------------------------------
|
||||
# File transfers support
|
||||
# -----------------------------------------------------------------------------------------------------------------
|
||||
|
@ -319,3 +316,10 @@ class FileTransfersHandler:
|
|||
self.get_friend_by_number(friend_number).load_avatar()
|
||||
if self.get_active_number() == friend_number and self.is_active_a_friend():
|
||||
self.set_active(None)
|
||||
|
||||
# -----------------------------------------------------------------------------------------------------------------
|
||||
# Private methods
|
||||
# -----------------------------------------------------------------------------------------------------------------
|
||||
|
||||
def _get_friend_by_number(self, friend_number):
|
||||
return self._contact_provider.get_friend_by_number(friend_number)
|
||||
|
|
128
toxygen/messenger/messenger.py
Normal file
128
toxygen/messenger/messenger.py
Normal file
|
@ -0,0 +1,128 @@
|
|||
import util.util as util
|
||||
from wrapper.toxcore_enums_and_consts import *
|
||||
from messenger.messages import *
|
||||
|
||||
|
||||
class Messenger(util.ToxSave):
|
||||
|
||||
def __init__(self, tox, plugin_loader, screen, contacts_manager, contacts_provider):
|
||||
super().__init__(tox)
|
||||
self._plugin_loader = plugin_loader
|
||||
self._screen = screen
|
||||
self._contacts_manager = contacts_manager
|
||||
self._contacts_provider = contacts_provider
|
||||
|
||||
# -----------------------------------------------------------------------------------------------------------------
|
||||
# Private methods
|
||||
# -----------------------------------------------------------------------------------------------------------------
|
||||
|
||||
def _create_message_item(self):
|
||||
pass
|
||||
|
||||
# -----------------------------------------------------------------------------------------------------------------
|
||||
# Messaging
|
||||
# -----------------------------------------------------------------------------------------------------------------
|
||||
|
||||
def new_message(self, friend_number, message_type, message):
|
||||
"""
|
||||
Current user gets new message
|
||||
:param friend_number: friend_num of friend who sent message
|
||||
:param message_type: message type - plain text or action message (/me)
|
||||
:param message: text of message
|
||||
"""
|
||||
t = util.get_unix_time()
|
||||
|
||||
if self._contacts_manager.is_friend_active(friend_number): # add message to list
|
||||
self.create_message_item(message, t, MESSAGE_AUTHOR['FRIEND'], message_type)
|
||||
self._screen.messages.scrollToBottom()
|
||||
self._contacts_manager.get_curr_contact().append_message(
|
||||
TextMessage(message, MESSAGE_AUTHOR['FRIEND'], t, message_type))
|
||||
else:
|
||||
friend = self.get_friend_by_number(friend_number)
|
||||
friend.inc_messages()
|
||||
friend.append_message(
|
||||
TextMessage(message, MESSAGE_AUTHOR['FRIEND'], t, message_type))
|
||||
if not friend.visibility:
|
||||
self._contacts_manager.update_filtration()
|
||||
|
||||
def send_message(self):
|
||||
self.send_message_to_friend(self._screen.messageEdit.toPlainText())
|
||||
|
||||
def send_message_to_friend(self, text, friend_number=None):
|
||||
"""
|
||||
Send message
|
||||
:param text: message text
|
||||
:param friend_number: number of friend
|
||||
"""
|
||||
if friend_number is None:
|
||||
friend_number = self._contacts_manager.get_active_number()
|
||||
if text.startswith('/plugin '):
|
||||
self._plugin_loader.command(text[8:])
|
||||
self._screen.messageEdit.clear()
|
||||
elif text and friend_number >= 0:
|
||||
if text.startswith('/me '):
|
||||
message_type = TOX_MESSAGE_TYPE['ACTION']
|
||||
text = text[4:]
|
||||
else:
|
||||
message_type = TOX_MESSAGE_TYPE['NORMAL']
|
||||
friend = self.get_friend_by_number(friend_number)
|
||||
friend.inc_receipts()
|
||||
if friend.status is not None:
|
||||
messages = self._split_message(text.encode('utf-8'))
|
||||
t = util.get_unix_time()
|
||||
for message in messages:
|
||||
message_id = self._tox.friend_send_message(friend_number, message_type, message)
|
||||
friend.append_message(TextMessage(message_id, text, MESSAGE_AUTHOR['NOT_SENT'], t, message_type))
|
||||
if self._contacts_manager.is_friend_active(friend_number):
|
||||
self.create_message_item(text, t, MESSAGE_AUTHOR['NOT_SENT'], message_type)
|
||||
self._screen.messageEdit.clear()
|
||||
self._screen.messages.scrollToBottom()
|
||||
|
||||
# -----------------------------------------------------------------------------------------------------------------
|
||||
# Typing notifications
|
||||
# -----------------------------------------------------------------------------------------------------------------
|
||||
|
||||
def send_typing(self, typing):
|
||||
"""
|
||||
Send typing notification to a friend
|
||||
"""
|
||||
if self._contacts_manager.can_send_typing_notification():
|
||||
try:
|
||||
contact = self._contacts_manager.get_curr_contact()
|
||||
contact.typing_notification_handler.send(self._tox, typing)
|
||||
except:
|
||||
pass
|
||||
|
||||
def friend_typing(self, friend_number, typing):
|
||||
"""
|
||||
Display incoming typing notification
|
||||
"""
|
||||
if self._contacts_manager.is_friend_active(friend_number):
|
||||
self._screen.typing.setVisible(typing)
|
||||
|
||||
# -----------------------------------------------------------------------------------------------------------------
|
||||
# Private methods
|
||||
# -----------------------------------------------------------------------------------------------------------------
|
||||
|
||||
@staticmethod
|
||||
def _split_message(message):
|
||||
messages = []
|
||||
while len(message) > TOX_MAX_MESSAGE_LENGTH:
|
||||
size = TOX_MAX_MESSAGE_LENGTH * 4 / 5
|
||||
last_part = message[size:TOX_MAX_MESSAGE_LENGTH]
|
||||
if ' ' in last_part:
|
||||
index = last_part.index(' ')
|
||||
elif ',' in last_part:
|
||||
index = last_part.index(',')
|
||||
elif '.' in last_part:
|
||||
index = last_part.index('.')
|
||||
else:
|
||||
index = TOX_MAX_MESSAGE_LENGTH - size - 1
|
||||
index += size + 1
|
||||
messages.append(message[:index])
|
||||
message = message[index:]
|
||||
|
||||
return messages
|
||||
|
||||
def get_friend_by_number(self, friend_number):
|
||||
return self._contacts_provider.get_friend_by_number(friend_number)
|
|
@ -39,18 +39,18 @@ def self_connection_status(tox, profile):
|
|||
# -----------------------------------------------------------------------------------------------------------------
|
||||
|
||||
|
||||
def friend_status(profile, settings):
|
||||
def friend_status(contacts_manager, file_transfer_handler, profile, settings):
|
||||
def wrapped(tox, friend_number, new_status, user_data):
|
||||
"""
|
||||
Check friend's status (none, busy, away)
|
||||
"""
|
||||
print("Friend's #{} status changed!".format(friend_number))
|
||||
friend = profile.get_friend_by_number(friend_number)
|
||||
friend = contacts_manager.get_friend_by_number(friend_number)
|
||||
if friend.status is None and settings['sound_notifications'] and profile.status != TOX_USER_STATUS['BUSY']:
|
||||
sound_notification(SOUND_NOTIFICATION['FRIEND_CONNECTION_STATUS'])
|
||||
invoke_in_main_thread(friend.set_status, new_status)
|
||||
invoke_in_main_thread(QtCore.QTimer.singleShot, 5000, lambda: profile.send_files(friend_number))
|
||||
invoke_in_main_thread(profile.update_filtration)
|
||||
invoke_in_main_thread(QtCore.QTimer.singleShot, 5000, lambda: file_transfer_handler.send_files(friend_number))
|
||||
invoke_in_main_thread(contacts_manager.update_filtration)
|
||||
|
||||
return wrapped
|
||||
|
||||
|
@ -74,42 +74,42 @@ def friend_connection_status(profile, settings, plugin_loader):
|
|||
return wrapped
|
||||
|
||||
|
||||
def friend_name(profile):
|
||||
def friend_name(contacts_manager):
|
||||
def wrapped(tox, friend_number, name, size, user_data):
|
||||
"""
|
||||
Friend changed his name
|
||||
"""
|
||||
print('New name friend #' + str(friend_number))
|
||||
invoke_in_main_thread(profile.new_name, friend_number, name)
|
||||
invoke_in_main_thread(contacts_manager.new_name, friend_number, name)
|
||||
|
||||
return wrapped
|
||||
|
||||
|
||||
def friend_status_message(profile):
|
||||
def friend_status_message(contacts_manager, messenger):
|
||||
def wrapped(tox, friend_number, status_message, size, user_data):
|
||||
"""
|
||||
:return: function for callback friend_status_message. It updates friend's status message
|
||||
and calls window repaint
|
||||
"""
|
||||
friend = profile.get_friend_by_number(friend_number)
|
||||
friend = contacts_manager.get_friend_by_number(friend_number)
|
||||
invoke_in_main_thread(friend.set_status_message, status_message)
|
||||
print('User #{} has new status'.format(friend_number))
|
||||
invoke_in_main_thread(profile.send_messages, friend_number)
|
||||
if profile.get_active_number() == friend_number:
|
||||
invoke_in_main_thread(profile.set_active)
|
||||
invoke_in_main_thread(messenger.send_messages, friend_number)
|
||||
if contacts_manager.is_friend_active(friend_number):
|
||||
invoke_in_main_thread(contacts_manager.set_active)
|
||||
|
||||
return wrapped
|
||||
|
||||
|
||||
def friend_message(profile, settings, window, tray):
|
||||
def friend_message(messenger, contacts_manager, profile, settings, window, tray):
|
||||
def wrapped(tox, friend_number, message_type, message, size, user_data):
|
||||
"""
|
||||
New message from friend
|
||||
"""
|
||||
message = str(message, 'utf-8')
|
||||
invoke_in_main_thread(profile.new_message, friend_number, message_type, message)
|
||||
invoke_in_main_thread(messenger.new_message, friend_number, message_type, message)
|
||||
if not window.isActiveWindow():
|
||||
friend = profile.get_friend_by_number(friend_number)
|
||||
friend = contacts_manager.get_friend_by_number(friend_number)
|
||||
if settings['notifications'] and profile.status != TOX_USER_STATUS['BUSY'] and not settings.locked:
|
||||
invoke_in_main_thread(tray_notification, friend.name, message, tray, window)
|
||||
if settings['sound_notifications'] and profile.status != TOX_USER_STATUS['BUSY']:
|
||||
|
@ -371,7 +371,7 @@ def show_gc_notification(window, tray, message, group_number, peer_number):
|
|||
|
||||
|
||||
def init_callbacks(tox, profile, settings, plugin_loader, contacts_manager,
|
||||
calls_manager, file_transfer_handler, main_window, tray):
|
||||
calls_manager, file_transfer_handler, main_window, tray, messenger):
|
||||
"""
|
||||
Initialization of all callbacks.
|
||||
:param tox: Tox instance
|
||||
|
@ -382,32 +382,37 @@ def init_callbacks(tox, profile, settings, plugin_loader, contacts_manager,
|
|||
:param calls_manager: CallsManager instance
|
||||
:param file_transfer_handler: FileTransferHandler instance
|
||||
:param plugin_loader: PluginLoader instance
|
||||
:param main_window: main window screen
|
||||
:param main_window: MainWindow instance
|
||||
:param tray: tray (for notifications)
|
||||
:param messenger: Messenger instance
|
||||
"""
|
||||
# self callbacks
|
||||
tox.callback_self_connection_status(self_connection_status(tox, profile), 0)
|
||||
|
||||
tox.callback_friend_status(friend_status(profile, settings), 0)
|
||||
tox.callback_friend_message(friend_message(profile, settings, main_window, tray), 0)
|
||||
# friend callbacks
|
||||
tox.callback_friend_status(friend_status(contacts_manager, file_transfer_handler, profile, settings), 0)
|
||||
tox.callback_friend_message(friend_message(messenger, contacts_manager, profile, settings, main_window, tray), 0)
|
||||
tox.callback_friend_connection_status(friend_connection_status(profile, settings, plugin_loader), 0)
|
||||
tox.callback_friend_name(friend_name(profile), 0)
|
||||
tox.callback_friend_status_message(friend_status_message(profile), 0)
|
||||
tox.callback_friend_name(friend_name(contacts_manager), 0)
|
||||
tox.callback_friend_status_message(friend_status_message(contacts_manager, messenger), 0)
|
||||
tox.callback_friend_request(friend_request(contacts_manager), 0)
|
||||
tox.callback_friend_typing(friend_typing(contacts_manager), 0)
|
||||
tox.callback_friend_read_receipt(friend_read_receipt(contacts_manager), 0)
|
||||
|
||||
# file transfer
|
||||
tox.callback_file_recv(tox_file_recv(main_window, tray, profile, file_transfer_handler,
|
||||
contacts_manager, settings), 0)
|
||||
tox.callback_file_recv_chunk(file_recv_chunk(file_transfer_handler), 0)
|
||||
tox.callback_file_chunk_request(file_chunk_request(file_transfer_handler), 0)
|
||||
tox.callback_file_recv_control(file_recv_control(file_transfer_handler), 0)
|
||||
|
||||
# av
|
||||
toxav = tox.AV
|
||||
toxav.callback_call_state(call_state(calls_manager), 0)
|
||||
toxav.callback_call(call(calls_manager), 0)
|
||||
toxav.callback_audio_receive_frame(callback_audio(calls_manager), 0)
|
||||
toxav.callback_video_receive_frame(video_receive_frame, 0)
|
||||
|
||||
# custom packets
|
||||
tox.callback_friend_lossless_packet(lossless_packet(plugin_loader), 0)
|
||||
tox.callback_friend_lossy_packet(lossy_packet(plugin_loader), 0)
|
||||
|
||||
|
|
|
@ -1,18 +1,21 @@
|
|||
from ui.list_items import *
|
||||
from ui.messages_widgets import *
|
||||
|
||||
|
||||
class ItemsFactory:
|
||||
|
||||
def __init__(self, settings, plugin_loader, smiley_loader, main_screen):
|
||||
self._settings, self._plugin_loader = settings, plugin_loader
|
||||
self._smiley_loader, self._main_screen = smiley_loader, main_screen
|
||||
self._smiley_loader = smiley_loader
|
||||
self._messages = main_screen.messages
|
||||
self._friends_list = main_screen.friends_list
|
||||
|
||||
def friend_item(self):
|
||||
item = ContactItem(self._settings)
|
||||
elem = QtWidgets.QListWidgetItem(self._main_screen.friends_list)
|
||||
elem = QtWidgets.QListWidgetItem(self._friends_list)
|
||||
elem.setSizeHint(QtCore.QSize(250, item.height()))
|
||||
self._main_screen.friends_list.addItem(elem)
|
||||
self._main_screen.friends_list.setItemWidget(elem, item)
|
||||
self._friends_list.addItem(elem)
|
||||
self._friends_list.setItemWidget(elem, item)
|
||||
return item
|
||||
|
||||
def message_item(self, text, time, name, sent, message_type, append, pixmap):
|
||||
|
|
|
@ -8,22 +8,23 @@ import util.ui as util_ui
|
|||
|
||||
class MainWindow(QtWidgets.QMainWindow):
|
||||
|
||||
def __init__(self, settings, tox, tray):
|
||||
def __init__(self, settings, tray):
|
||||
super().__init__()
|
||||
self._settings = settings
|
||||
self._contacts_manager = None
|
||||
self._tray = tray
|
||||
self._widget_factory = None
|
||||
self._modal_window = None
|
||||
self.setAcceptDrops(True)
|
||||
self.initUI(tox)
|
||||
self._saved = False
|
||||
self.profile = None
|
||||
self.initUI()
|
||||
|
||||
def set_widget_factory(self, widget_factory):
|
||||
def set_dependencies(self, widget_factory, tray, contacts_manager, messenger):
|
||||
self._widget_factory = widget_factory
|
||||
|
||||
def set_tray(self, tray):
|
||||
self._tray = tray
|
||||
self._contacts_manager = contacts_manager
|
||||
self.messageEdit.set_messenger(messenger)
|
||||
|
||||
def show(self):
|
||||
super().show()
|
||||
|
@ -305,7 +306,7 @@ class MainWindow(QtWidgets.QMainWindow):
|
|||
self.messages.setVerticalScrollMode(QtWidgets.QAbstractItemView.ScrollPerPixel)
|
||||
self.messages.setSelectionMode(QtWidgets.QAbstractItemView.ExtendedSelection)
|
||||
|
||||
def initUI(self, tox):
|
||||
def initUI(self):
|
||||
self.setMinimumSize(920, 500)
|
||||
s = self._settings
|
||||
self.setGeometry(s['x'], s['y'], s['width'], s['height'])
|
||||
|
@ -326,7 +327,7 @@ class MainWindow(QtWidgets.QMainWindow):
|
|||
self.setup_right_bottom(message_buttons)
|
||||
self.setup_left_center(main_list)
|
||||
self.setup_menu(menu)
|
||||
if not self._settings['mirror_mode']:
|
||||
if not s['mirror_mode']:
|
||||
grid.addWidget(search, 2, 0)
|
||||
grid.addWidget(name, 1, 0)
|
||||
grid.addWidget(messages, 2, 1, 2, 1)
|
||||
|
@ -367,7 +368,6 @@ class MainWindow(QtWidgets.QMainWindow):
|
|||
if self._saved:
|
||||
return
|
||||
self._saved = True
|
||||
self.profile.close()
|
||||
self._settings['x'] = self.geometry().x()
|
||||
self._settings['y'] = self.geometry().y()
|
||||
self._settings['width'] = self.width()
|
||||
|
@ -441,7 +441,7 @@ class MainWindow(QtWidgets.QMainWindow):
|
|||
def create_gc(self):
|
||||
self.profile.create_group_chat()
|
||||
|
||||
def profile_settings(self, *args):
|
||||
def profile_settings(self):
|
||||
self._modal_window = self._widget_factory.create_profile_settings_window()
|
||||
self._modal_window.show()
|
||||
|
||||
|
@ -473,7 +473,8 @@ class MainWindow(QtWidgets.QMainWindow):
|
|||
if self._plugin_loader is not None:
|
||||
self._plugin_loader.reload()
|
||||
|
||||
def import_plugin(self):
|
||||
@staticmethod
|
||||
def import_plugin():
|
||||
directory = util_ui.directory_dialog(util_ui.tr('Choose folder with plugin'))
|
||||
if directory:
|
||||
src = directory + '/'
|
||||
|
@ -502,20 +503,19 @@ class MainWindow(QtWidgets.QMainWindow):
|
|||
# -----------------------------------------------------------------------------------------------------------------
|
||||
|
||||
def send_message(self):
|
||||
text = self.messageEdit.toPlainText()
|
||||
self.profile.send_message(text)
|
||||
self._messenger.send_message()
|
||||
|
||||
def send_file(self):
|
||||
self.menu.hide()
|
||||
if self.profile.active_friend + 1and self.profile.is_active_a_friend():
|
||||
if self._contacts_manager.active_friend + 1 and self._contacts_manager.is_active_a_friend():
|
||||
caption = util_ui.tr('Choose file')
|
||||
name = util_ui.file_dialog(caption)
|
||||
if name[0]:
|
||||
self.profile.send_file(name[0])
|
||||
self._contacts_manager.send_file(name[0])
|
||||
|
||||
def send_screenshot(self, hide=False):
|
||||
self.menu.hide()
|
||||
if self.profile.active_friend + 1 and self.profile.is_active_a_friend():
|
||||
if self._contacts_manager.active_friend + 1 and self._contacts_manager.is_active_a_friend():
|
||||
self.sw = ScreenShotWindow(self)
|
||||
self.sw.show()
|
||||
if hide:
|
||||
|
@ -523,8 +523,8 @@ class MainWindow(QtWidgets.QMainWindow):
|
|||
|
||||
def send_smiley(self):
|
||||
self.menu.hide()
|
||||
if self.profile.active_friend + 1:
|
||||
self.smiley = SmileyWindow(self)
|
||||
if self._contacts_manager.active_friend + 1:
|
||||
self.smiley = self._widget_factory.create_smiley_window(self)
|
||||
self.smiley.setGeometry(QtCore.QRect(self.x() if self._settings['mirror_mode'] else 270 + self.x(),
|
||||
self.y() + self.height() - 200,
|
||||
self.smiley.width(),
|
||||
|
@ -533,8 +533,8 @@ class MainWindow(QtWidgets.QMainWindow):
|
|||
|
||||
def send_sticker(self):
|
||||
self.menu.hide()
|
||||
if self.profile.active_friend + 1 and self.profile.is_active_a_friend():
|
||||
self.sticker = StickerWindow(self)
|
||||
if self._contacts_manager.active_friend + 1 and self._contacts_manager.is_active_a_friend():
|
||||
self.sticker = self._widget_factory.create_sticker_window(self)
|
||||
self.sticker.setGeometry(QtCore.QRect(self.x() if self._settings['mirror_mode'] else 270 + self.x(),
|
||||
self.y() + self.height() - 200,
|
||||
self.sticker.width(),
|
||||
|
@ -551,7 +551,6 @@ class MainWindow(QtWidgets.QMainWindow):
|
|||
self.update_call_state('call')
|
||||
|
||||
def update_call_state(self, state):
|
||||
|
||||
pixmap = QtGui.QPixmap(os.path.join(util.get_images_directory(), '{}.png'.format(state)))
|
||||
icon = QtGui.QIcon(pixmap)
|
||||
self.callButton.setIcon(icon)
|
||||
|
@ -569,10 +568,10 @@ class MainWindow(QtWidgets.QMainWindow):
|
|||
def friend_right_click(self, pos):
|
||||
item = self.friends_list.itemAt(pos)
|
||||
num = self.friends_list.indexFromItem(item).row()
|
||||
friend = Profile.get_instance().get_friend(num)
|
||||
friend = self._contacts_manager.get_friend(num)
|
||||
if friend is None:
|
||||
return
|
||||
allowed = friend.tox_id in settings['auto_accept_from_friends']
|
||||
allowed = friend.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()
|
||||
|
@ -597,7 +596,7 @@ class MainWindow(QtWidgets.QMainWindow):
|
|||
block_item = self.listMenu.addAction(util_ui.tr('Block friend'))
|
||||
notes_item = self.listMenu.addAction(util_ui.tr('Notes'))
|
||||
|
||||
chats = self.profile.get_group_chats()
|
||||
chats = self._contacts_manager.get_group_chats()
|
||||
if len(chats) and self.profile.is_active_online():
|
||||
invite_menu = self.listMenu.addMenu(util_ui.tr('Invite to group chat'))
|
||||
for i in range(len(chats)):
|
||||
|
@ -630,7 +629,7 @@ class MainWindow(QtWidgets.QMainWindow):
|
|||
self.listMenu.show()
|
||||
|
||||
def show_note(self, friend):
|
||||
note = self._settings['notes'][friend.tox_id] if friend.tox_id in s['notes'] else ''
|
||||
note = self._settings['notes'][friend.tox_id] if friend.tox_id in self._settings['notes'] else ''
|
||||
user = util_ui.tr('Notes about user')
|
||||
user = '{} {}'.format(user, friend.name)
|
||||
|
||||
|
@ -644,7 +643,7 @@ class MainWindow(QtWidgets.QMainWindow):
|
|||
self.note.show()
|
||||
|
||||
def export_history(self, num, as_text=True):
|
||||
s = self.profile.export_history(num, as_text)
|
||||
s = self._history_loader.export_history(num, as_text)
|
||||
extension = 'txt' if as_text else 'html'
|
||||
file_name, _ = util_ui.save_file_dialog(util_ui.tr('Choose file name'), extension)
|
||||
|
||||
|
@ -655,30 +654,32 @@ class MainWindow(QtWidgets.QMainWindow):
|
|||
fl.write(s)
|
||||
|
||||
def set_alias(self, num):
|
||||
self.profile.set_alias(num)
|
||||
self._contacts_manager.set_alias(num)
|
||||
|
||||
def remove_friend(self, num):
|
||||
self.profile.delete_friend(num)
|
||||
self._contacts_manager.delete_friend(num)
|
||||
|
||||
def block_friend(self, num):
|
||||
friend = self.profile.get_friend(num)
|
||||
self.profile.block_user(friend.tox_id)
|
||||
self._contacts_manager.block_user(friend.tox_id)
|
||||
|
||||
def copy_friend_key(self, num):
|
||||
tox_id = self.profile.friend_public_key(num)
|
||||
tox_id = self._contacts_manager.friend_public_key(num)
|
||||
clipboard = QtWidgets.QApplication.clipboard()
|
||||
clipboard.setText(tox_id)
|
||||
|
||||
def copy_name(self, friend):
|
||||
@staticmethod
|
||||
def copy_name(friend):
|
||||
clipboard = QtWidgets.QApplication.clipboard()
|
||||
clipboard.setText(friend.name)
|
||||
|
||||
def copy_status(self, friend):
|
||||
@staticmethod
|
||||
def copy_status(friend):
|
||||
clipboard = QtWidgets.QApplication.clipboard()
|
||||
clipboard.setText(friend.status_message)
|
||||
|
||||
def clear_history(self, num):
|
||||
self.profile.clear_history(num)
|
||||
self._contacts_manager.clear_history(num)
|
||||
|
||||
def leave_gc(self, num):
|
||||
self.profile.leave_gc(num)
|
||||
|
@ -687,7 +688,7 @@ class MainWindow(QtWidgets.QMainWindow):
|
|||
self.profile.set_title(num)
|
||||
|
||||
def auto_accept(self, num, value):
|
||||
tox_id = self.profile.friend_public_key(num)
|
||||
tox_id = self._contacts_manager.friend_public_key(num)
|
||||
if value:
|
||||
self._settings['auto_accept_from_friends'].append(tox_id)
|
||||
else:
|
||||
|
@ -695,7 +696,7 @@ class MainWindow(QtWidgets.QMainWindow):
|
|||
self._settings.save()
|
||||
|
||||
def invite_friend_to_gc(self, friend_number, group_number):
|
||||
self.profile.invite_friend(friend_number, group_number)
|
||||
self._contacts_manager.invite_friend(friend_number, group_number)
|
||||
|
||||
# -----------------------------------------------------------------------------------------------------------------
|
||||
# Functions which called when user click somewhere else
|
||||
|
@ -703,7 +704,7 @@ class MainWindow(QtWidgets.QMainWindow):
|
|||
|
||||
def friend_click(self, index):
|
||||
num = index.row()
|
||||
self.profile.set_active(num)
|
||||
self._contacts_manager.set_active(num)
|
||||
|
||||
def mouseReleaseEvent(self, event):
|
||||
pos = self.connection_status.pos()
|
||||
|
@ -715,17 +716,17 @@ class MainWindow(QtWidgets.QMainWindow):
|
|||
|
||||
def show(self):
|
||||
super().show()
|
||||
#self.profile.update()
|
||||
#self._contacts_manager.update()
|
||||
|
||||
def filtering(self):
|
||||
ind = self.online_contacts.currentIndex()
|
||||
d = {0: 0, 1: 1, 2: 2, 3: 4, 4: 1 | 4, 5: 2 | 4}
|
||||
self.profile.filtration_and_sorting(d[ind], self.contact_name.text())
|
||||
self._contacts_manager.filtration_and_sorting(d[ind], self.contact_name.text())
|
||||
|
||||
def show_search_field(self):
|
||||
if hasattr(self, 'search_field') and self.search_field.isVisible():
|
||||
return
|
||||
if self.profile.get_curr_friend() is None:
|
||||
if self._c4.get_curr_friend() is None:
|
||||
return
|
||||
self.search_field = SearchScreen(self.messages, self.messages.width(), self.messages.parent())
|
||||
x, y = self.messages.x(), self.messages.y() + self.messages.height() - 40
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
from PyQt5 import QtCore, QtGui, QtWidgets
|
||||
from ui.widgets import RubberBandWindow, create_menu, QRightClickButton, CenteredWidget, LineEdit
|
||||
from contacts.profile import Profile
|
||||
import smileys
|
||||
import urllib
|
||||
import util.util as util
|
||||
import util.ui as util_ui
|
||||
|
@ -13,10 +12,14 @@ class MessageArea(QtWidgets.QPlainTextEdit):
|
|||
|
||||
def __init__(self, parent, form):
|
||||
super().__init__(parent)
|
||||
self._messenger = None
|
||||
self.parent = form
|
||||
self.setAcceptDrops(True)
|
||||
self.timer = QtCore.QTimer(self)
|
||||
self.timer.timeout.connect(lambda: self.parent.profile.send_typing(False))
|
||||
self._timer = QtCore.QTimer(self)
|
||||
self._timer.timeout.connect(lambda: self._messenger.send_typing(False))
|
||||
|
||||
def set_messenger(self, messenger):
|
||||
self._messenger = messenger
|
||||
|
||||
def keyPressEvent(self, event):
|
||||
if event.matches(QtGui.QKeySequence.Paste):
|
||||
|
@ -31,22 +34,22 @@ class MessageArea(QtWidgets.QPlainTextEdit):
|
|||
if modifiers & QtCore.Qt.ControlModifier or modifiers & QtCore.Qt.ShiftModifier:
|
||||
self.insertPlainText('\n')
|
||||
else:
|
||||
if self.timer.isActive():
|
||||
self.timer.stop()
|
||||
self.parent.profile.send_typing(False)
|
||||
self.parent.send_message()
|
||||
if self._timer.isActive():
|
||||
self._timer.stop()
|
||||
self._messenger.send_typing(False)
|
||||
self._messenger.send_message()
|
||||
elif event.key() == QtCore.Qt.Key_Up and not self.toPlainText():
|
||||
self.appendPlainText(Profile.get_instance().get_last_message())
|
||||
elif event.key() == QtCore.Qt.Key_Tab and not self.parent.profile.is_active_a_friend():
|
||||
self.appendPlainText(self._messenger.get_last_message())
|
||||
elif event.key() == QtCore.Qt.Key_Tab and not self._messenger.is_active_a_friend():
|
||||
text = self.toPlainText()
|
||||
pos = self.textCursor().position()
|
||||
self.insertPlainText(Profile.get_instance().get_gc_peer_name(text[:pos]))
|
||||
self.insertPlainText(self._messenger.get_gc_peer_name(text[:pos]))
|
||||
else:
|
||||
self.parent.profile.send_typing(True)
|
||||
if self.timer.isActive():
|
||||
self.timer.stop()
|
||||
self.timer.start(5000)
|
||||
super(MessageArea, self).keyPressEvent(event)
|
||||
self._messenger.send_typing(True)
|
||||
if self._timer.isActive():
|
||||
self._timer.stop()
|
||||
self._timer.start(5000)
|
||||
super().keyPressEvent(event)
|
||||
|
||||
def contextMenuEvent(self, event):
|
||||
menu = create_menu(self.createStandardContextMenu())
|
||||
|
|
|
@ -122,7 +122,7 @@ class MessageItem(QtWidgets.QWidget):
|
|||
"""
|
||||
Message in messages list
|
||||
"""
|
||||
def __init__(self, settings, message_edit_factory, text_message, parent=None):
|
||||
def __init__(self, settings, text_message, parent=None):
|
||||
QtWidgets.QWidget.__init__(self, parent)
|
||||
self.name = widgets.DataLabel(self)
|
||||
self.name.setGeometry(QtCore.QRect(2, 2, 95, 23))
|
||||
|
|
|
@ -56,3 +56,8 @@ class WidgetsFactory:
|
|||
def create_notification_settings_window(self):
|
||||
return NotificationsSettings(self._settings)
|
||||
|
||||
def create_smiley_window(self, parent):
|
||||
return SmileyWindow(parent, self._smiley_loader)
|
||||
|
||||
def create_sticker_window(self, parent):
|
||||
return StickerWindow(parent, self._file_transfer_handler)
|
||||
|
|
|
@ -94,6 +94,10 @@ def curr_time():
|
|||
return time.strftime('%H:%M')
|
||||
|
||||
|
||||
def get_unix_time():
|
||||
return int(time.time())
|
||||
|
||||
|
||||
def join_path(a, b):
|
||||
return os.path.join(a, b)
|
||||
|
||||
|
|
Loading…
Reference in a new issue