messages refactoring and fixes, calls fixes

This commit is contained in:
ingvar1995 2018-05-18 19:40:34 +03:00
parent 42049d6a44
commit a575312167
7 changed files with 57 additions and 63 deletions

View File

@ -2,7 +2,6 @@ import threading
import cv2 import cv2
import av.calls import av.calls
from messenger.messages import * from messenger.messages import *
import time
from ui import av_widgets from ui import av_widgets
import common.event as event import common.event as event
@ -37,11 +36,6 @@ class CallsManager:
# AV support # AV support
# ----------------------------------------------------------------------------------------------------------------- # -----------------------------------------------------------------------------------------------------------------
def get_call(self):
return self._call
call = property(get_call)
def call_click(self, audio=True, video=False): def call_click(self, audio=True, video=False):
"""User clicked audio button in main window""" """User clicked audio button in main window"""
num = self._contacts_manager.get_active_number() num = self._contacts_manager.get_active_number()
@ -53,8 +47,6 @@ class CallsManager:
self._call(num, audio, video) self._call(num, audio, video)
self._screen.active_call() self._screen.active_call()
self._call_started_event(num, audio, video, True) self._call_started_event(num, audio, video, True)
self._contacts_manager.get_curr_friend().append_message(InfoMessage(text, time.time()))
self._screen.messages.scrollToBottom()
elif num in self._call: # finish or cancel call if you call with active friend elif num in self._call: # finish or cancel call if you call with active friend
self.stop_call(num, False) self.stop_call(num, False)
@ -66,13 +58,13 @@ class CallsManager:
return return
friend = self._contacts_manager.get_friend_by_number(friend_number) friend = self._contacts_manager.get_friend_by_number(friend_number)
self._call_started_event(friend_number, audio, video, False) self._call_started_event(friend_number, audio, video, False)
friend.append_message(InfoMessage(text, time.time()))
self._incoming_calls.add(friend_number) self._incoming_calls.add(friend_number)
if friend_number == self._contacts_manager.get_active_number(): if friend_number == self._contacts_manager.get_active_number():
self._screen.incoming_call() self._screen.incoming_call()
else: else:
friend.actions = True friend.actions = True
self._call_widgets[friend_number] = av_widgets.IncomingCallWidget(friend_number, text, friend.name) text = util_ui.tr("Incoming video call") if video else util_ui.tr("Incoming audio call")
self._call_widgets[friend_number] = self._get_incoming_call_widget(friend_number, text, friend.name)
self._call_widgets[friend_number].set_pixmap(friend.get_pixmap()) self._call_widgets[friend_number].set_pixmap(friend.get_pixmap())
self._call_widgets[friend_number].show() self._call_widgets[friend_number].show()
@ -93,16 +85,14 @@ class CallsManager:
if friend_number in self._incoming_calls: if friend_number in self._incoming_calls:
self._incoming_calls.remove(friend_number) self._incoming_calls.remove(friend_number)
is_declined = True is_declined = True
text = util_ui.tr("Call declined")
else: else:
is_declined = False is_declined = False
text = util_ui.tr("Call finished")
self._screen.call_finished() self._screen.call_finished()
is_video = self._call.is_video_call(friend_number) is_video = self._call.is_video_call(friend_number)
self._call.finish_call(friend_number, by_friend) # finish or decline call self._call.finish_call(friend_number, by_friend) # finish or decline call
if hasattr(self, '_call_widget'): if friend_number in self._call_widgets:
self._call_widget[friend_number].close() self._call_widgets[friend_number].close()
del self._call_widget[friend_number] del self._call_widgets[friend_number]
def destroy_window(): def destroy_window():
if is_video: if is_video:
@ -114,3 +104,10 @@ class CallsManager:
def friend_exit(self, friend_number): def friend_exit(self, friend_number):
if friend_number in self._call: if friend_number in self._call:
self._call.finish_call(friend_number, True) self._call.finish_call(friend_number, True)
# -----------------------------------------------------------------------------------------------------------------
# Private methods
# -----------------------------------------------------------------------------------------------------------------
def _get_incoming_call_widget(self, friend_number, text, friend_name):
return av_widgets.IncomingCallWidget(self._settings, self, friend_number, text, friend_name)

View File

@ -74,7 +74,7 @@ class Contact(basecontact.BaseContact):
Get data to save in db Get data to save in db
:return: list of unsaved messages or [] :return: list of unsaved messages or []
""" """
messages = list(filter(lambda x: x.get_type() in (MESSAGE_TYPE['TEXT'], MESSAGE_TYPE['ACTION']), self._corr)) messages = list(filter(lambda x: x.type in (MESSAGE_TYPE['TEXT'], MESSAGE_TYPE['ACTION']), self._corr))
return messages[-self._unsaved_messages:] if self._unsaved_messages else [] return messages[-self._unsaved_messages:] if self._unsaved_messages else []
def get_corr(self): def get_corr(self):
@ -85,12 +85,12 @@ class Contact(basecontact.BaseContact):
:param message: text or file transfer message :param message: text or file transfer message
""" """
self._corr.append(message) self._corr.append(message)
if message.get_type() in (MESSAGE_TYPE['TEXT'], MESSAGE_TYPE['ACTION']): if message.type in (MESSAGE_TYPE['TEXT'], MESSAGE_TYPE['ACTION']):
self._unsaved_messages += 1 self._unsaved_messages += 1
def get_last_message_text(self): def get_last_message_text(self):
messages = list(filter(lambda x: x.get_type() in (MESSAGE_TYPE['TEXT'], MESSAGE_TYPE['ACTION']) messages = list(filter(lambda m: m.type in (MESSAGE_TYPE['TEXT'], MESSAGE_TYPE['ACTION'])
and x.get_owner() != MESSAGE_AUTHOR['FRIEND'], self._corr)) and m.author.type != MESSAGE_AUTHOR['FRIEND'], self._corr))
if messages: if messages:
return messages[-1].text return messages[-1].text
else: else:
@ -125,9 +125,9 @@ class Contact(basecontact.BaseContact):
""" """
:return list of unsent messages for saving :return list of unsent messages for saving
""" """
messages = filter(lambda x: x.get_type() in (MESSAGE_TYPE['TEXT'], MESSAGE_TYPE['ACTION']) messages = filter(lambda x: x.type in (MESSAGE_TYPE['TEXT'], MESSAGE_TYPE['ACTION'])
and x.author.type == MESSAGE_AUTHOR['NOT_SENT'], self._corr) and x.author.type == MESSAGE_AUTHOR['NOT_SENT'], self._corr)
return list(map(lambda x: x.get_data(), messages)) return list(messages)
def mark_as_sent(self, tox_message_id): def mark_as_sent(self, tox_message_id):
try: try:
@ -144,7 +144,7 @@ class Contact(basecontact.BaseContact):
def delete_message(self, message_id): def delete_message(self, message_id):
elem = list(filter(lambda x: type(x) in (TextMessage, GroupChatMessage) and x.message_id == message_id, elem = list(filter(lambda x: type(x) in (TextMessage, GroupChatMessage) and x.message_id == message_id,
self._corr))[0] self._corr))[0]
tmp = list(filter(lambda x: x.get_type() in (MESSAGE_TYPE['TEXT'], MESSAGE_TYPE['ACTION']), self._corr)) tmp = list(filter(lambda x: x.type in (MESSAGE_TYPE['TEXT'], MESSAGE_TYPE['ACTION']), self._corr))
if elem in tmp[-self._unsaved_messages:] and self._unsaved_messages: if elem in tmp[-self._unsaved_messages:] and self._unsaved_messages:
self._unsaved_messages -= 1 self._unsaved_messages -= 1
self._corr.remove(elem) self._corr.remove(elem)
@ -156,13 +156,13 @@ class Contact(basecontact.BaseContact):
Delete old messages (reduces RAM usage if messages saving is not enabled) Delete old messages (reduces RAM usage if messages saving is not enabled)
""" """
def save_message(x): def save_message(x):
if x.get_type() == 2 and (x.get_status() >= 2 or x.get_status() is None): # FIXME MAGIC NUMBERS if x.type == MESSAGE_TYPE['FILE_TRANSFER'] and (x.state not in ACTIVE_FILE_TRANSFERS):
return True return True
return x.get_owner() == MESSAGE_AUTHOR['NOT_SENT'] return x.author.type == MESSAGE_AUTHOR['NOT_SENT']
old = filter(save_message, self._corr[:-SAVE_MESSAGES]) old = filter(save_message, self._corr[:-SAVE_MESSAGES])
self._corr = list(old) + self._corr[-SAVE_MESSAGES:] self._corr = list(old) + self._corr[-SAVE_MESSAGES:]
text_messages = filter(lambda x: x.get_type() in (MESSAGE_TYPE['TEXT'], MESSAGE_TYPE['ACTION']), self._corr) text_messages = filter(lambda m: m.type in (MESSAGE_TYPE['TEXT'], MESSAGE_TYPE['ACTION']), self._corr)
self._unsaved_messages = min(self._unsaved_messages, len(list(text_messages))) self._unsaved_messages = min(self._unsaved_messages, len(list(text_messages)))
self._search_index = 0 self._search_index = 0
@ -175,13 +175,14 @@ class Contact(basecontact.BaseContact):
self._search_index = 0 self._search_index = 0
# don't delete data about active file transfer # don't delete data about active file transfer
if not save_unsent: if not save_unsent:
self._corr = list(filter(lambda x: x.get_type() == 2 and self._corr = list(filter(lambda m: m.type == MESSAGE_TYPE['FILE_TRANSFER'] and
x.get_status() in ft.ACTIVE_FILE_TRANSFERS, self._corr)) m.state in ft.ACTIVE_FILE_TRANSFERS, self._corr))
self._unsaved_messages = 0 self._unsaved_messages = 0
else: else:
self._corr = list(filter(lambda x: (x.get_type() == 2 and x.get_status() in ft.ACTIVE_FILE_TRANSFERS) self._corr = list(filter(lambda m: (m.type == MESSAGE_TYPE['FILE_TRANSFER']
or (x.get_type() in (MESSAGE_TYPE['TEXT'], MESSAGE_TYPE['ACTION']) and m.state in ft.ACTIVE_FILE_TRANSFERS)
and x.get_owner() == MESSAGE_AUTHOR['NOT_SENT']), or (m.type in (MESSAGE_TYPE['TEXT'], MESSAGE_TYPE['ACTION'])
and m.author.type == MESSAGE_AUTHOR['NOT_SENT']),
self._corr)) self._corr))
self._unsaved_messages = len(self.get_unsent_messages()) self._unsaved_messages = len(self.get_unsent_messages())
@ -197,7 +198,7 @@ class Contact(basecontact.BaseContact):
while True: while True:
l = len(self._corr) l = len(self._corr)
for i in range(self._search_index - 1, -l - 1, -1): for i in range(self._search_index - 1, -l - 1, -1):
if self._corr[i].get_type() > 1: if self._corr[i].type not in (MESSAGE_TYPE['TEXT'], MESSAGE_TYPE['ACTION']):
continue continue
message = self._corr[i].text message = self._corr[i].text
if re.search(self._search_string, message, re.IGNORECASE) is not None: if re.search(self._search_string, message, re.IGNORECASE) is not None:
@ -212,7 +213,7 @@ class Contact(basecontact.BaseContact):
if not self._search_index: if not self._search_index:
return None return None
for i in range(self._search_index + 1, 0): for i in range(self._search_index + 1, 0):
if self._corr[i].get_type() > 1: if self._corr[i].get_type() > (MESSAGE_TYPE['TEXT'], MESSAGE_TYPE['ACTION']):
continue continue
message = self._corr[i].text message = self._corr[i].text
if re.search(self._search_string, message, re.IGNORECASE) is not None: if re.search(self._search_string, message, re.IGNORECASE) is not None:
@ -259,10 +260,6 @@ class Contact(basecontact.BaseContact):
visibility = property(get_visibility, set_visibility) visibility = property(get_visibility, set_visibility)
def set_widget(self, widget):
self._widget = widget
self.init_widget()
# ----------------------------------------------------------------------------------------------------------------- # -----------------------------------------------------------------------------------------------------------------
# Unread messages and other actions from friend # Unread messages and other actions from friend
# ----------------------------------------------------------------------------------------------------------------- # -----------------------------------------------------------------------------------------------------------------

View File

@ -13,7 +13,8 @@ FILE_TRANSFER_STATE = {
'FINISHED': 3, 'FINISHED': 3,
'PAUSED_BY_FRIEND': 4, 'PAUSED_BY_FRIEND': 4,
'INCOMING_NOT_STARTED': 5, 'INCOMING_NOT_STARTED': 5,
'OUTGOING_NOT_STARTED': 6 'OUTGOING_NOT_STARTED': 6,
'UNSENT': 7
} }
ACTIVE_FILE_TRANSFERS = (0, 1, 4, 5, 6) ACTIVE_FILE_TRANSFERS = (0, 1, 4, 5, 6)

View File

@ -41,15 +41,15 @@ class FileTransfersHandler:
file_id = self._tox.file_get_file_id(friend_number, file_number) file_id = self._tox.file_get_file_id(friend_number, file_number)
accepted = True accepted = True
if file_id in self._paused_file_transfers: if file_id in self._paused_file_transfers:
data = self._paused_file_transfers[file_id] (path, ft_friend_number, is_incoming, start_position) = self._paused_file_transfers[file_id]
pos = data[-1] if os.path.exists(data[0]) else 0 pos = start_position if os.path.exists(path) else 0
if pos >= size: if pos >= size:
self._tox.file_control(friend_number, file_number, TOX_FILE_CONTROL['CANCEL']) self._tox.file_control(friend_number, file_number, TOX_FILE_CONTROL['CANCEL'])
return return
self._tox.file_seek(friend_number, file_number, pos) self._tox.file_seek(friend_number, file_number, pos)
self._file_transfers_message_service.add_incoming_transfer_message( self._file_transfers_message_service.add_incoming_transfer_message(
friend, accepted, size, file_name, file_number) friend, accepted, size, file_name, file_number)
self.accept_transfer(data[0], friend_number, file_number, size, False, pos) self.accept_transfer(path, friend_number, file_number, size, False, pos)
elif inline and size < 1024 * 1024: elif inline and size < 1024 * 1024:
self._file_transfers_message_service.add_incoming_transfer_message( self._file_transfers_message_service.add_incoming_transfer_message(
friend, accepted, size, file_name, file_number) friend, accepted, size, file_name, file_number)

View File

@ -189,14 +189,16 @@ class UnsentFileMessage(Message):
data = property(get_data) data = property(get_data)
def get_state(self):
return FILE_TRANSFER_STATE['UNSENT']
state = property(get_state)
def get_path(self): def get_path(self):
return self._path return self._path
path = property(get_path) path = property(get_path)
def get_status(self):
return None
def _create_widget(self, *args): def _create_widget(self, *args):
return UnsentFileItem(self, *args) return UnsentFileItem(self, *args)

View File

@ -1,17 +1,16 @@
from PyQt5 import QtCore, QtGui, QtWidgets from PyQt5 import QtCore, QtGui, QtWidgets
from ui import widgets from ui import widgets
from contacts import profile import utils.util as util
import utils
import pyaudio import pyaudio
import wave import wave
from user_data import settings
from utils.util import *
class IncomingCallWidget(widgets.CenteredWidget): class IncomingCallWidget(widgets.CenteredWidget):
def __init__(self, friend_number, text, name): def __init__(self, settings, calls_manager, friend_number, text, name):
super().__init__() super().__init__()
self._settings = settings
self._calls_manager = calls_manager
self.setWindowFlags(QtCore.Qt.CustomizeWindowHint | QtCore.Qt.WindowTitleHint | QtCore.Qt.WindowStaysOnTopHint) self.setWindowFlags(QtCore.Qt.CustomizeWindowHint | QtCore.Qt.WindowTitleHint | QtCore.Qt.WindowStaysOnTopHint)
self.resize(QtCore.QSize(500, 270)) self.resize(QtCore.QSize(500, 270))
self.avatar_label = QtWidgets.QLabel(self) self.avatar_label = QtWidgets.QLabel(self)
@ -21,7 +20,7 @@ class IncomingCallWidget(widgets.CenteredWidget):
self.name.setGeometry(QtCore.QRect(90, 20, 300, 25)) self.name.setGeometry(QtCore.QRect(90, 20, 300, 25))
self._friend_number = friend_number self._friend_number = friend_number
font = QtGui.QFont() font = QtGui.QFont()
font.setFamily(settings.Settings.get_instance()['font']) font.setFamily(settings['font'])
font.setPointSize(16) font.setPointSize(16)
font.setBold(True) font.setBold(True)
self.name.setFont(font) self.name.setFont(font)
@ -34,13 +33,13 @@ class IncomingCallWidget(widgets.CenteredWidget):
self.accept_video.setGeometry(QtCore.QRect(170, 100, 150, 150)) self.accept_video.setGeometry(QtCore.QRect(170, 100, 150, 150))
self.decline = QtWidgets.QPushButton(self) self.decline = QtWidgets.QPushButton(self)
self.decline.setGeometry(QtCore.QRect(320, 100, 150, 150)) self.decline.setGeometry(QtCore.QRect(320, 100, 150, 150))
pixmap = QtGui.QPixmap(utils.curr_directory() + '/images/accept_audio.png') pixmap = QtGui.QPixmap(util.join_path(util.get_images_directory(), 'accept_audio.png'))
icon = QtGui.QIcon(pixmap) icon = QtGui.QIcon(pixmap)
self.accept_audio.setIcon(icon) self.accept_audio.setIcon(icon)
pixmap = QtGui.QPixmap(utils.curr_directory() + '/images/accept_video.png') pixmap = QtGui.QPixmap(util.join_path(util.get_images_directory(), 'accept_video.png'))
icon = QtGui.QIcon(pixmap) icon = QtGui.QIcon(pixmap)
self.accept_video.setIcon(icon) self.accept_video.setIcon(icon)
pixmap = QtGui.QPixmap(utils.curr_directory() + '/images/decline_call.png') pixmap = QtGui.QPixmap(util.join_path(util.get_images_directory(), 'decline_call.png'))
icon = QtGui.QIcon(pixmap) icon = QtGui.QIcon(pixmap)
self.decline.setIcon(icon) self.decline.setIcon(icon)
self.accept_audio.setIconSize(QtCore.QSize(150, 150)) self.accept_audio.setIconSize(QtCore.QSize(150, 150))
@ -90,11 +89,11 @@ class IncomingCallWidget(widgets.CenteredWidget):
self.stream.close() self.stream.close()
self.p.terminate() self.p.terminate()
self.a = AudioFile(curr_directory() + '/sounds/call.wav') self.a = AudioFile(util.join_path(util.get_sounds_directory(), 'call.wav'))
self.a.play() self.a.play()
self.a.close() self.a.close()
if settings.Settings.get_instance()['calls_sound']: if self._settings['calls_sound']:
self.thread = SoundPlay() self.thread = SoundPlay()
self.thread.start() self.thread.start()
else: else:
@ -110,24 +109,21 @@ class IncomingCallWidget(widgets.CenteredWidget):
if self._processing: if self._processing:
return return
self._processing = True self._processing = True
pr = profile.Profile.get_instance() self._calls_manager.accept_call(self._friend_number, True, False)
pr.accept_call(self._friend_number, True, False)
self.stop() self.stop()
def accept_call_with_video(self): def accept_call_with_video(self):
if self._processing: if self._processing:
return return
self._processing = True self._processing = True
pr = profile.Profile.get_instance() self._calls_manager.accept_call(self._friend_number, True, True)
pr.accept_call(self._friend_number, True, True)
self.stop() self.stop()
def decline_call(self): def decline_call(self):
if self._processing: if self._processing:
return return
self._processing = True self._processing = True
pr = profile.Profile.get_instance() self._calls_manager.stop_call(self._friend_number, False)
pr.stop_call(self._friend_number, False)
self.stop() self.stop()
def set_pixmap(self, pixmap): def set_pixmap(self, pixmap):

View File

@ -134,8 +134,9 @@ class MessageItem(QtWidgets.QWidget):
font.setFamily(settings['font']) font.setFamily(settings['font'])
font.setPointSize(11) font.setPointSize(11)
font.setBold(True) font.setBold(True)
self.name.setFont(font) if text_message.author is not None:
self.name.setText(text_message.author.name) self.name.setFont(font)
self.name.setText(text_message.author.name)
self.time = QtWidgets.QLabel(self) self.time = QtWidgets.QLabel(self)
self.time.setGeometry(QtCore.QRect(parent.width() - 60, 0, 50, 25)) self.time.setGeometry(QtCore.QRect(parent.width() - 60, 0, 50, 25))
@ -143,7 +144,7 @@ class MessageItem(QtWidgets.QWidget):
font.setBold(False) font.setBold(False)
self.time.setFont(font) self.time.setFont(font)
self._time = text_message.time self._time = text_message.time
if text_message.author.type == MESSAGE_AUTHOR['NOT_SENT']: if text_message.author and text_message.author.type == MESSAGE_AUTHOR['NOT_SENT']:
movie = QtGui.QMovie(util.join_path(util.get_images_directory(), 'spinner.gif')) movie = QtGui.QMovie(util.join_path(util.get_images_directory(), 'spinner.gif'))
self.time.setMovie(movie) self.time.setMovie(movie)
movie.start() movie.start()