messages update - deleting, unsent messages saving, bug fixes

This commit is contained in:
ingvar1995 2016-06-28 12:44:27 +03:00
parent a56693547c
commit b982df70ea
6 changed files with 140 additions and 49 deletions

View file

@ -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))
self._unsaved_messages = 0
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

View file

@ -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')

View file

@ -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

View file

@ -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()

View file

@ -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:
messages = friend.get_corr_for_saving()
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()

View file

@ -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