messages update - deleting, unsent messages saving, bug fixes
This commit is contained in:
parent
a56693547c
commit
b982df70ea
6 changed files with 140 additions and 49 deletions
|
@ -2,6 +2,7 @@ import contact
|
|||
from messages import *
|
||||
from history import *
|
||||
import util
|
||||
import file_transfers as ft
|
||||
|
||||
|
||||
class Friend(contact.Contact):
|
||||
|
@ -92,13 +93,29 @@ class Friend(contact.Contact):
|
|||
else:
|
||||
return ''
|
||||
|
||||
def unsent_messages(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
|
||||
"""
|
||||
if self._unsaved_messages:
|
||||
messages = filter(lambda x: x.get_owner() == MESSAGE_OWNER['NOT_SENT'], self._corr[-self._unsaved_messages:])
|
||||
return list(map(lambda x: x.get_data(), messages))
|
||||
else:
|
||||
return []
|
||||
|
||||
def delete_message(self, time):
|
||||
elem = list(filter(lambda x: type(x) is TextMessage and x.get_data()[2] == time, self._corr))[0]
|
||||
if elem in self.get_corr_for_saving():
|
||||
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]
|
||||
|
@ -106,15 +123,22 @@ class Friend(contact.Contact):
|
|||
except Exception as ex:
|
||||
util.log('Mark as sent ex: ' + str(ex))
|
||||
|
||||
def clear_corr(self):
|
||||
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, self._corr))
|
||||
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
|
||||
|
|
|
@ -132,6 +132,19 @@ class History:
|
|||
db.close()
|
||||
pass
|
||||
|
||||
def delete_message(self, tox_id, time):
|
||||
chdir(settings.ProfileHelper.get_path())
|
||||
db = connect(self._name + '.hstr')
|
||||
try:
|
||||
cursor = db.cursor()
|
||||
cursor.execute('DELETE FROM id' + tox_id + ' WHERE unix_time = ' + str(time) + ';')
|
||||
db.commit()
|
||||
except:
|
||||
db.rollback()
|
||||
raise
|
||||
finally:
|
||||
db.close()
|
||||
|
||||
def delete_messages(self, tox_id):
|
||||
chdir(settings.ProfileHelper.get_path())
|
||||
db = connect(self._name + '.hstr')
|
||||
|
|
|
@ -121,14 +121,15 @@ class MessageItem(QtGui.QWidget):
|
|||
font.setPointSize(10)
|
||||
font.setBold(False)
|
||||
self.time.setFont(font)
|
||||
|
||||
self._time = time
|
||||
if not sent:
|
||||
movie = QtGui.QMovie(curr_directory() + '/images/spinner.gif')
|
||||
self.time.setMovie(movie)
|
||||
movie.start()
|
||||
self.t = time
|
||||
self.t = True
|
||||
else:
|
||||
self.time.setText(time)
|
||||
self.time.setText(convert_time(time))
|
||||
self.t = False
|
||||
|
||||
self.message = MessageEdit(text, parent.width() - 150, message_type, self)
|
||||
if message_type != TOX_MESSAGE_TYPE['NORMAL']:
|
||||
|
@ -138,10 +139,23 @@ class MessageItem(QtGui.QWidget):
|
|||
self.message.setGeometry(QtCore.QRect(100, 0, parent.width() - 150, self.message.height()))
|
||||
self.setFixedHeight(self.message.height())
|
||||
|
||||
def mouseReleaseEvent(self, event):
|
||||
if event.button() == QtCore.Qt.RightButton and event.x() > self.time.x():
|
||||
self.listMenu = QtGui.QMenu()
|
||||
delete_item = self.listMenu.addAction(QtGui.QApplication.translate("MainWindow", 'Delete message', None, QtGui.QApplication.UnicodeUTF8))
|
||||
self.connect(delete_item, QtCore.SIGNAL("triggered()"), self.delete)
|
||||
parent_position = self.time.mapToGlobal(QtCore.QPoint(0, 0))
|
||||
self.listMenu.move(parent_position)
|
||||
self.listMenu.show()
|
||||
|
||||
def delete(self):
|
||||
pr = profile.Profile.get_instance()
|
||||
pr.delete_message(self._time)
|
||||
|
||||
def mark_as_sent(self):
|
||||
if hasattr(self, 't'):
|
||||
self.time.setText(self.t)
|
||||
del self.t
|
||||
if self.t:
|
||||
self.time.setText(convert_time(self._time))
|
||||
self.t = False
|
||||
return True
|
||||
return False
|
||||
|
||||
|
|
58
src/menu.py
58
src/menu.py
|
@ -360,45 +360,51 @@ class PrivacySettings(CenteredWidget):
|
|||
|
||||
def initUI(self):
|
||||
self.setObjectName("privacySettings")
|
||||
self.resize(350, 550)
|
||||
self.setMinimumSize(QtCore.QSize(350, 550))
|
||||
self.setMaximumSize(QtCore.QSize(350, 550))
|
||||
self.resize(350, 600)
|
||||
self.setMinimumSize(QtCore.QSize(350, 600))
|
||||
self.setMaximumSize(QtCore.QSize(350, 600))
|
||||
self.saveHistory = QtGui.QCheckBox(self)
|
||||
self.saveHistory.setGeometry(QtCore.QRect(10, 20, 291, 22))
|
||||
self.saveUnsentOnly = QtGui.QCheckBox(self)
|
||||
self.saveUnsentOnly.setGeometry(QtCore.QRect(10, 60, 291, 22))
|
||||
|
||||
self.fileautoaccept = QtGui.QCheckBox(self)
|
||||
self.fileautoaccept.setGeometry(QtCore.QRect(10, 60, 271, 22))
|
||||
self.fileautoaccept.setGeometry(QtCore.QRect(10, 100, 271, 22))
|
||||
|
||||
self.typingNotifications = QtGui.QCheckBox(self)
|
||||
self.typingNotifications.setGeometry(QtCore.QRect(10, 100, 350, 30))
|
||||
self.typingNotifications.setGeometry(QtCore.QRect(10, 140, 350, 30))
|
||||
self.inlines = QtGui.QCheckBox(self)
|
||||
self.inlines.setGeometry(QtCore.QRect(10, 140, 350, 30))
|
||||
self.inlines.setGeometry(QtCore.QRect(10, 180, 350, 30))
|
||||
self.auto_path = QtGui.QLabel(self)
|
||||
self.auto_path.setGeometry(QtCore.QRect(10, 190, 350, 30))
|
||||
self.auto_path.setGeometry(QtCore.QRect(10, 230, 350, 30))
|
||||
self.path = QtGui.QPlainTextEdit(self)
|
||||
self.path.setGeometry(QtCore.QRect(10, 225, 330, 45))
|
||||
self.path.setGeometry(QtCore.QRect(10, 265, 330, 45))
|
||||
self.change_path = QtGui.QPushButton(self)
|
||||
self.change_path.setGeometry(QtCore.QRect(10, 280, 330, 30))
|
||||
self.change_path.setGeometry(QtCore.QRect(10, 320, 330, 30))
|
||||
settings = Settings.get_instance()
|
||||
self.typingNotifications.setChecked(settings['typing_notifications'])
|
||||
self.fileautoaccept.setChecked(settings['allow_auto_accept'])
|
||||
self.saveHistory.setChecked(settings['save_history'])
|
||||
self.inlines.setChecked(settings['allow_inline'])
|
||||
self.saveUnsentOnly.setChecked(settings['save_unsent_only'])
|
||||
self.saveUnsentOnly.setEnabled(settings['save_history'])
|
||||
self.saveHistory.stateChanged.connect(self.update)
|
||||
self.path.setPlainText(settings['auto_accept_path'] or curr_directory())
|
||||
self.change_path.clicked.connect(self.new_path)
|
||||
self.block_user_label = QtGui.QLabel(self)
|
||||
self.block_user_label.setGeometry(QtCore.QRect(10, 320, 330, 30))
|
||||
self.block_user_label.setGeometry(QtCore.QRect(10, 360, 330, 30))
|
||||
self.block_id = QtGui.QPlainTextEdit(self)
|
||||
self.block_id.setGeometry(QtCore.QRect(10, 350, 330, 30))
|
||||
self.block_id.setGeometry(QtCore.QRect(10, 390, 330, 30))
|
||||
self.block = QtGui.QPushButton(self)
|
||||
self.block.setGeometry(QtCore.QRect(10, 390, 330, 30))
|
||||
self.block.setGeometry(QtCore.QRect(10, 430, 330, 30))
|
||||
self.block.clicked.connect(lambda: Profile.get_instance().block_user(self.block_id.toPlainText()) or self.close())
|
||||
self.blocked_users_label = QtGui.QLabel(self)
|
||||
self.blocked_users_label.setGeometry(QtCore.QRect(10, 430, 330, 30))
|
||||
self.blocked_users_label.setGeometry(QtCore.QRect(10, 470, 330, 30))
|
||||
self.comboBox = QtGui.QComboBox(self)
|
||||
self.comboBox.setGeometry(QtCore.QRect(10, 460, 330, 30))
|
||||
self.comboBox.setGeometry(QtCore.QRect(10, 500, 330, 30))
|
||||
self.comboBox.addItems(settings['blocked'])
|
||||
self.unblock = QtGui.QPushButton(self)
|
||||
self.unblock.setGeometry(QtCore.QRect(10, 500, 330, 30))
|
||||
self.unblock.setGeometry(QtCore.QRect(10, 540, 330, 30))
|
||||
self.unblock.clicked.connect(lambda: self.unblock_user())
|
||||
self.retranslateUi()
|
||||
QtCore.QMetaObject.connectSlotsByName(self)
|
||||
|
@ -415,6 +421,12 @@ class PrivacySettings(CenteredWidget):
|
|||
self.blocked_users_label.setText(QtGui.QApplication.translate("privacySettings", "Blocked users:", None, QtGui.QApplication.UnicodeUTF8))
|
||||
self.unblock.setText(QtGui.QApplication.translate("privacySettings", "Unblock", None, QtGui.QApplication.UnicodeUTF8))
|
||||
self.block.setText(QtGui.QApplication.translate("privacySettings", "Block user", None, QtGui.QApplication.UnicodeUTF8))
|
||||
self.saveUnsentOnly.setText(QtGui.QApplication.translate("privacySettings", "Save unsent messages only", None, QtGui.QApplication.UnicodeUTF8))
|
||||
|
||||
def update(self, new_state):
|
||||
self.saveUnsentOnly.setEnabled(new_state)
|
||||
if not new_state:
|
||||
self.saveUnsentOnly.setChecked(False)
|
||||
|
||||
def unblock_user(self):
|
||||
if not self.comboBox.count():
|
||||
|
@ -429,6 +441,7 @@ class PrivacySettings(CenteredWidget):
|
|||
settings = Settings.get_instance()
|
||||
settings['typing_notifications'] = self.typingNotifications.isChecked()
|
||||
settings['allow_auto_accept'] = self.fileautoaccept.isChecked()
|
||||
|
||||
if settings['save_history'] and not self.saveHistory.isChecked(): # clear history
|
||||
reply = QtGui.QMessageBox.question(None,
|
||||
QtGui.QApplication.translate("privacySettings",
|
||||
|
@ -444,6 +457,21 @@ class PrivacySettings(CenteredWidget):
|
|||
settings['save_history'] = self.saveHistory.isChecked()
|
||||
else:
|
||||
settings['save_history'] = self.saveHistory.isChecked()
|
||||
if self.saveUnsentOnly.isChecked() and not settings['save_unsent_only']:
|
||||
reply = QtGui.QMessageBox.question(None,
|
||||
QtGui.QApplication.translate("privacySettings",
|
||||
'Chat history',
|
||||
None, QtGui.QApplication.UnicodeUTF8),
|
||||
QtGui.QApplication.translate("privacySettings",
|
||||
'History will be cleaned! Continue?',
|
||||
None, QtGui.QApplication.UnicodeUTF8),
|
||||
QtGui.QMessageBox.Yes,
|
||||
QtGui.QMessageBox.No)
|
||||
if reply == QtGui.QMessageBox.Yes:
|
||||
Profile.get_instance().clear_history(None, True)
|
||||
settings['save_unsent_only'] = self.saveUnsentOnly.isChecked()
|
||||
else:
|
||||
settings['save_unsent_only'] = self.saveUnsentOnly.isChecked()
|
||||
settings['auto_accept_path'] = self.path.toPlainText()
|
||||
settings['allow_inline'] = self.inlines.isChecked()
|
||||
settings.save()
|
||||
|
|
|
@ -7,7 +7,7 @@ from friend import *
|
|||
from settings import *
|
||||
from toxcore_enums_and_consts import *
|
||||
from ctypes import *
|
||||
from util import curr_time, log, Singleton, curr_directory, convert_time
|
||||
from util import log, Singleton, curr_directory
|
||||
from tox_dns import tox_dns
|
||||
from history import *
|
||||
from file_transfers import *
|
||||
|
@ -90,7 +90,7 @@ class Profile(contact.Contact, Singleton):
|
|||
for friend in self._friends:
|
||||
friend.append_message(InfoMessage(message, time.time()))
|
||||
if self._active_friend + 1:
|
||||
self.create_message_item(message, curr_time(), '', MESSAGE_TYPE['INFO_MESSAGE'])
|
||||
self.create_message_item(message, time.time(), '', MESSAGE_TYPE['INFO_MESSAGE'])
|
||||
self._messages.scrollToBottom()
|
||||
|
||||
def set_status_message(self, value):
|
||||
|
@ -181,7 +181,7 @@ class Profile(contact.Contact, Singleton):
|
|||
if message.get_type() <= 1:
|
||||
data = message.get_data()
|
||||
self.create_message_item(data[0],
|
||||
convert_time(data[2]),
|
||||
data[2],
|
||||
data[1],
|
||||
data[3])
|
||||
elif message.get_type() == MESSAGE_TYPE['FILE_TRANSFER']:
|
||||
|
@ -201,7 +201,7 @@ class Profile(contact.Contact, Singleton):
|
|||
else: # info message
|
||||
data = message.get_data()
|
||||
self.create_message_item(data[0],
|
||||
convert_time(data[2]),
|
||||
data[2],
|
||||
'',
|
||||
data[3])
|
||||
self._messages.scrollToBottom()
|
||||
|
@ -255,7 +255,7 @@ class Profile(contact.Contact, Singleton):
|
|||
friend.append_message(InfoMessage(message, time.time()))
|
||||
friend.actions = True
|
||||
if number == self.get_active_number():
|
||||
self.create_message_item(message, curr_time(), '', MESSAGE_TYPE['INFO_MESSAGE'])
|
||||
self.create_message_item(message, time.time(), '', MESSAGE_TYPE['INFO_MESSAGE'])
|
||||
self._messages.scrollToBottom()
|
||||
self.set_active(None)
|
||||
|
||||
|
@ -328,7 +328,7 @@ class Profile(contact.Contact, Singleton):
|
|||
"""
|
||||
friend = self.get_friend_by_number(friend_number)
|
||||
friend.load_corr()
|
||||
messages = friend.unsent_messages()
|
||||
messages = friend.get_unsent_messages()
|
||||
try:
|
||||
for message in messages:
|
||||
self.split_and_send(friend_number, message.get_data()[-1], message.get_data()[0].encode('utf-8'))
|
||||
|
@ -367,10 +367,11 @@ class Profile(contact.Contact, Singleton):
|
|||
:param message: text of message
|
||||
"""
|
||||
if friend_num == self.get_active_number(): # add message to list
|
||||
self.create_message_item(message, curr_time(), MESSAGE_OWNER['FRIEND'], message_type)
|
||||
t = time.time()
|
||||
self.create_message_item(message, t, MESSAGE_OWNER['FRIEND'], message_type)
|
||||
self._messages.scrollToBottom()
|
||||
self._friends[self._active_friend].append_message(
|
||||
TextMessage(message, MESSAGE_OWNER['FRIEND'], time.time(), message_type))
|
||||
TextMessage(message, MESSAGE_OWNER['FRIEND'], t, message_type))
|
||||
else:
|
||||
friend = self.get_friend_by_number(friend_num)
|
||||
friend.inc_messages()
|
||||
|
@ -397,10 +398,17 @@ class Profile(contact.Contact, Singleton):
|
|||
friend.inc_receipts()
|
||||
if friend.status is not None:
|
||||
self.split_and_send(friend.number, message_type, text.encode('utf-8'))
|
||||
self.create_message_item(text, curr_time(), MESSAGE_OWNER['NOT_SENT'], message_type)
|
||||
t = time.time()
|
||||
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'], time.time(), message_type))
|
||||
friend.append_message(TextMessage(text, MESSAGE_OWNER['NOT_SENT'], t, message_type))
|
||||
|
||||
def delete_message(self, time):
|
||||
friend = self._friends[self._active_friend]
|
||||
friend.delete_message(time)
|
||||
self._history.delete_message(friend.tox_id, time)
|
||||
self.update()
|
||||
|
||||
# -----------------------------------------------------------------------------------------------------------------
|
||||
# History support
|
||||
|
@ -410,35 +418,38 @@ class Profile(contact.Contact, Singleton):
|
|||
"""
|
||||
Save history to db
|
||||
"""
|
||||
s = Settings.get_instance()
|
||||
if hasattr(self, '_history'):
|
||||
if Settings.get_instance()['save_history']:
|
||||
if s['save_history']:
|
||||
for friend in self._friends:
|
||||
if not s['save_unsent_only']:
|
||||
messages = friend.get_corr_for_saving()
|
||||
else:
|
||||
messages = friend.get_unsent_messages_for_saving()
|
||||
if not self._history.friend_exists_in_db(friend.tox_id):
|
||||
self._history.add_friend_to_db(friend.tox_id)
|
||||
self._history.save_messages_to_db(friend.tox_id, messages)
|
||||
unsent_messages = friend.unsent_messages()
|
||||
unsent_messages = friend.get_unsent_messages()
|
||||
unsent_time = unsent_messages[0].get_data()[2] if len(unsent_messages) else time.time() + 1
|
||||
self._history.update_messages(friend.tox_id, unsent_time)
|
||||
self._history.save()
|
||||
del self._history
|
||||
|
||||
def clear_history(self, num=None):
|
||||
def clear_history(self, num=None, save_unsent=False):
|
||||
"""
|
||||
Clear chat history
|
||||
"""
|
||||
if num is not None:
|
||||
friend = self._friends[num]
|
||||
friend.clear_corr()
|
||||
friend.clear_corr(save_unsent)
|
||||
if self._history.friend_exists_in_db(friend.tox_id):
|
||||
self._history.delete_messages(friend.tox_id)
|
||||
self._history.delete_friend_from_db(friend.tox_id)
|
||||
else: # clear all history
|
||||
for number in range(len(self._friends)):
|
||||
self.clear_history(number)
|
||||
self.clear_history(number, save_unsent)
|
||||
if num is None or num == self.get_active_number():
|
||||
self._messages.clear()
|
||||
self._messages.repaint()
|
||||
self.update()
|
||||
|
||||
def load_history(self):
|
||||
"""
|
||||
|
@ -455,7 +466,7 @@ class Profile(contact.Contact, Singleton):
|
|||
if message.get_type() <= 1: # text message
|
||||
data = message.get_data()
|
||||
self.create_message_item(data[0],
|
||||
convert_time(data[2]),
|
||||
data[2],
|
||||
data[1],
|
||||
data[3],
|
||||
False)
|
||||
|
@ -476,7 +487,7 @@ class Profile(contact.Contact, Singleton):
|
|||
else: # info message
|
||||
data = message.get_data()
|
||||
self.create_message_item(data[0],
|
||||
convert_time(data[2]),
|
||||
data[2],
|
||||
'',
|
||||
data[3])
|
||||
|
||||
|
@ -1090,7 +1101,7 @@ class Profile(contact.Contact, Singleton):
|
|||
text = QtGui.QApplication.translate("incoming_call", "Outgoing audio call", None,
|
||||
QtGui.QApplication.UnicodeUTF8)
|
||||
self._friends[self._active_friend].append_message(InfoMessage(text, time.time()))
|
||||
self.create_message_item(text, curr_time(), '', MESSAGE_TYPE['INFO_MESSAGE'])
|
||||
self.create_message_item(text, time.time(), '', MESSAGE_TYPE['INFO_MESSAGE'])
|
||||
self._messages.scrollToBottom()
|
||||
elif num in self._call: # finish or cancel call if you call with active friend
|
||||
self.stop_call(num, False)
|
||||
|
@ -1110,7 +1121,7 @@ class Profile(contact.Contact, Singleton):
|
|||
self._incoming_calls.add(friend_number)
|
||||
if friend_number == self.get_active_number():
|
||||
self._screen.incoming_call()
|
||||
self.create_message_item(text, curr_time(), '', MESSAGE_TYPE['INFO_MESSAGE'])
|
||||
self.create_message_item(text, time.time(), '', MESSAGE_TYPE['INFO_MESSAGE'])
|
||||
self._messages.scrollToBottom()
|
||||
else:
|
||||
friend.actions = True
|
||||
|
@ -1144,7 +1155,7 @@ class Profile(contact.Contact, Singleton):
|
|||
friend = self.get_friend_by_number(friend_number)
|
||||
friend.append_message(InfoMessage(text, time.time()))
|
||||
if friend_number == self.get_active_number():
|
||||
self.create_message_item(text, curr_time(), '', MESSAGE_TYPE['INFO_MESSAGE'])
|
||||
self.create_message_item(text, time.time(), '', MESSAGE_TYPE['INFO_MESSAGE'])
|
||||
self._messages.scrollToBottom()
|
||||
|
||||
|
||||
|
|
|
@ -122,7 +122,8 @@ class Settings(dict, Singleton):
|
|||
'x': 400,
|
||||
'y': 400,
|
||||
'message_font_size': 14,
|
||||
'unread_color': 'red'
|
||||
'unread_color': 'red',
|
||||
'save_unsent_only': False
|
||||
}
|
||||
|
||||
@staticmethod
|
||||
|
|
Loading…
Reference in a new issue