history fixes - db cleanup
This commit is contained in:
parent
f1c63bb4e8
commit
eef02a1173
11 changed files with 418 additions and 486 deletions
|
@ -302,9 +302,10 @@ class App:
|
||||||
friend_items_factory = FriendItemsFactory(self._settings, self._ms)
|
friend_items_factory = FriendItemsFactory(self._settings, self._ms)
|
||||||
self._friend_factory = FriendFactory(self._profile_manager, self._settings, self._tox, db, friend_items_factory)
|
self._friend_factory = FriendFactory(self._profile_manager, self._settings, self._tox, db, friend_items_factory)
|
||||||
self._contacts_provider = ContactProvider(self._tox, self._friend_factory)
|
self._contacts_provider = ContactProvider(self._tox, self._friend_factory)
|
||||||
history = History(self._contacts_provider, db, self._settings)
|
history = None
|
||||||
messages_items_factory = MessagesItemsFactory(self._settings, self._plugin_loader, self._smiley_loader,
|
messages_items_factory = MessagesItemsFactory(self._settings, self._plugin_loader, self._smiley_loader,
|
||||||
self._ms, history)
|
self._ms, lambda m: history.delete_message(m))
|
||||||
|
history = History(self._contacts_provider, db, self._settings, self._ms, messages_items_factory)
|
||||||
self._contacts_manager = ContactsManager(self._tox, self._settings, self._ms, self._profile_manager,
|
self._contacts_manager = ContactsManager(self._tox, self._settings, self._ms, self._profile_manager,
|
||||||
self._contacts_provider, history, self._tox_dns,
|
self._contacts_provider, history, self._tox_dns,
|
||||||
messages_items_factory)
|
messages_items_factory)
|
||||||
|
|
|
@ -296,6 +296,7 @@ class ContactsManager:
|
||||||
Adds friend to list
|
Adds friend to list
|
||||||
"""
|
"""
|
||||||
self._tox.friend_add_norequest(tox_id)
|
self._tox.friend_add_norequest(tox_id)
|
||||||
|
self._history.add_friend_to_db(tox_id)
|
||||||
friend = self._contact_provider.get_friend_by_public_key(tox_id)
|
friend = self._contact_provider.get_friend_by_public_key(tox_id)
|
||||||
self._contacts.append(friend)
|
self._contacts.append(friend)
|
||||||
|
|
||||||
|
|
|
@ -1,11 +1,10 @@
|
||||||
from contacts.friend import *
|
from contacts.friend import *
|
||||||
from user_data.settings import *
|
|
||||||
from history.database import *
|
|
||||||
from file_transfers.file_transfers import *
|
from file_transfers.file_transfers import *
|
||||||
import time
|
import time
|
||||||
from contacts import basecontact
|
from contacts import basecontact
|
||||||
from contacts.group_chat import *
|
from contacts.group_chat import *
|
||||||
import utils.ui as util_ui
|
import utils.ui as util_ui
|
||||||
|
import random
|
||||||
|
|
||||||
|
|
||||||
class Profile(basecontact.BaseContact):
|
class Profile(basecontact.BaseContact):
|
||||||
|
@ -70,7 +69,6 @@ class Profile(basecontact.BaseContact):
|
||||||
|
|
||||||
def new_nospam(self):
|
def new_nospam(self):
|
||||||
"""Sets new nospam part of tox id"""
|
"""Sets new nospam part of tox id"""
|
||||||
import random
|
|
||||||
self._tox.self_set_nospam(random.randint(0, 4294967295)) # no spam - uint32
|
self._tox.self_set_nospam(random.randint(0, 4294967295)) # no spam - uint32
|
||||||
self._tox_id = self._tox.self_get_address()
|
self._tox_id = self._tox.self_get_address()
|
||||||
|
|
||||||
|
@ -106,58 +104,6 @@ class Profile(basecontact.BaseContact):
|
||||||
while i < self._messages.count() and not self._messages.itemWidget(self._messages.item(i)).mark_as_sent():
|
while i < self._messages.count() and not self._messages.itemWidget(self._messages.item(i)).mark_as_sent():
|
||||||
i += 1
|
i += 1
|
||||||
|
|
||||||
def delete_message(self, message_id):
|
|
||||||
friend = self.get_curr_friend()
|
|
||||||
friend.delete_message(time)
|
|
||||||
self._history.delete_message(friend.tox_id, message_id)
|
|
||||||
self.update()
|
|
||||||
|
|
||||||
# -----------------------------------------------------------------------------------------------------------------
|
|
||||||
# Friend, message and file transfer items creation
|
|
||||||
# -----------------------------------------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
def create_message_item(self, text, time, owner, message_type, append=True):
|
|
||||||
if message_type == MESSAGE_TYPE['INFO_MESSAGE']:
|
|
||||||
name = ''
|
|
||||||
elif owner == MESSAGE_OWNER['FRIEND']:
|
|
||||||
name = self.get_active_name()
|
|
||||||
else:
|
|
||||||
name = self._name
|
|
||||||
pixmap = None
|
|
||||||
if self._show_avatars:
|
|
||||||
if owner == MESSAGE_OWNER['FRIEND']:
|
|
||||||
pixmap = self.get_curr_friend().get_pixmap()
|
|
||||||
else:
|
|
||||||
pixmap = self.get_pixmap()
|
|
||||||
return self._factory.create_message_item(text, time, name, owner != MESSAGE_OWNER['NOT_SENT'],
|
|
||||||
message_type, append, pixmap)
|
|
||||||
|
|
||||||
def create_gc_message_item(self, text, time, owner, name, message_type, append=True):
|
|
||||||
pixmap = None
|
|
||||||
if self._show_avatars:
|
|
||||||
if owner == MESSAGE_OWNER['FRIEND']:
|
|
||||||
pixmap = self.get_curr_friend().get_pixmap()
|
|
||||||
else:
|
|
||||||
pixmap = self.get_pixmap()
|
|
||||||
return self._factory.create_message_item(text, time, name, True,
|
|
||||||
message_type - 5, append, pixmap)
|
|
||||||
|
|
||||||
def create_file_transfer_item(self, tm, append=True):
|
|
||||||
data = list(tm.get_data())
|
|
||||||
data[3] = self.get_friend_by_number(data[4]).name if data[3] else self._name
|
|
||||||
return self._factory.create_file_transfer_item(data, append)
|
|
||||||
|
|
||||||
def create_unsent_file_item(self, message, append=True):
|
|
||||||
data = message.get_data()
|
|
||||||
return self._factory.create_unsent_file_item(os.path.basename(data[0]),
|
|
||||||
os.path.getsize(data[0]) if data[1] is None else len(data[1]),
|
|
||||||
self.name,
|
|
||||||
data[2],
|
|
||||||
append)
|
|
||||||
|
|
||||||
def create_inline_item(self, data, append=True):
|
|
||||||
return self._factory.create_inline_item(data, append)
|
|
||||||
|
|
||||||
# -----------------------------------------------------------------------------------------------------------------
|
# -----------------------------------------------------------------------------------------------------------------
|
||||||
# Reset
|
# Reset
|
||||||
# -----------------------------------------------------------------------------------------------------------------
|
# -----------------------------------------------------------------------------------------------------------------
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
from file_transfers.file_transfers import *
|
from file_transfers.file_transfers import *
|
||||||
from messenger.messages import *
|
from messenger.messages import *
|
||||||
from history.database import MESSAGE_AUTHOR
|
from history.database import MESSAGE_AUTHOR
|
||||||
from ui.list_items import *
|
from ui.contact_items import *
|
||||||
from PyQt5 import QtWidgets
|
from PyQt5 import QtWidgets
|
||||||
import utils.util as util
|
import utils.util as util
|
||||||
|
|
||||||
|
|
|
@ -37,16 +37,6 @@ class Database:
|
||||||
except Exception as ex:
|
except Exception as ex:
|
||||||
util.log('Db reading error: ' + str(ex))
|
util.log('Db reading error: ' + str(ex))
|
||||||
os.remove(path)
|
os.remove(path)
|
||||||
db = self._connect()
|
|
||||||
cursor = db.cursor()
|
|
||||||
cursor.execute('CREATE TABLE IF NOT EXISTS contacts ('
|
|
||||||
' tox_id TEXT PRIMARY KEY,'
|
|
||||||
' contact_type INTEGER'
|
|
||||||
')')
|
|
||||||
db.close()
|
|
||||||
|
|
||||||
def _connect(self):
|
|
||||||
return connect(self._path, timeout=TIMEOUT)
|
|
||||||
|
|
||||||
# -----------------------------------------------------------------------------------------------------------------
|
# -----------------------------------------------------------------------------------------------------------------
|
||||||
# Public methods
|
# Public methods
|
||||||
|
@ -73,10 +63,8 @@ class Database:
|
||||||
db = self._connect()
|
db = self._connect()
|
||||||
try:
|
try:
|
||||||
cursor = db.cursor()
|
cursor = db.cursor()
|
||||||
# cursor.execute('INSERT INTO contacts VALUES (?);', (tox_id, ))
|
cursor.execute('CREATE TABLE IF NOT EXISTS id' + tox_id + '('
|
||||||
cursor.execute('CREATE TABLE id' + tox_id + '('
|
|
||||||
' id INTEGER PRIMARY KEY,'
|
' id INTEGER PRIMARY KEY,'
|
||||||
' message_id INTEGER,'
|
|
||||||
' author_name TEXT,'
|
' author_name TEXT,'
|
||||||
' message TEXT,'
|
' message TEXT,'
|
||||||
' author INTEGER,'
|
' author INTEGER,'
|
||||||
|
@ -94,7 +82,6 @@ class Database:
|
||||||
db = self._connect()
|
db = self._connect()
|
||||||
try:
|
try:
|
||||||
cursor = db.cursor()
|
cursor = db.cursor()
|
||||||
cursor.execute('DELETE FROM contacts WHERE tox_id=?;', (tox_id, ))
|
|
||||||
cursor.execute('DROP TABLE id' + tox_id + ';')
|
cursor.execute('DROP TABLE id' + tox_id + ';')
|
||||||
db.commit()
|
db.commit()
|
||||||
except:
|
except:
|
||||||
|
@ -103,20 +90,12 @@ class Database:
|
||||||
finally:
|
finally:
|
||||||
db.close()
|
db.close()
|
||||||
|
|
||||||
def friend_exists_in_db(self, tox_id):
|
|
||||||
db = self._connect()
|
|
||||||
cursor = db.cursor()
|
|
||||||
cursor.execute('SELECT 1 FROM contacts WHERE tox_id=?', (tox_id, ))
|
|
||||||
result = cursor.fetchone()
|
|
||||||
db.close()
|
|
||||||
return result is not None
|
|
||||||
|
|
||||||
def save_messages_to_db(self, tox_id, messages_iter):
|
def save_messages_to_db(self, tox_id, messages_iter):
|
||||||
db = self._connect()
|
db = self._connect()
|
||||||
try:
|
try:
|
||||||
cursor = db.cursor()
|
cursor = db.cursor()
|
||||||
cursor.executemany('INSERT INTO id' + tox_id +
|
cursor.executemany('INSERT INTO id' + tox_id +
|
||||||
'(message, message_id, author_name, author, unix_time, message_type) ' +
|
'(message, author_name, author, unix_time, message_type) ' +
|
||||||
'VALUES (?, ?, ?, ?, ?, ?);', messages_iter)
|
'VALUES (?, ?, ?, ?, ?, ?);', messages_iter)
|
||||||
db.commit()
|
db.commit()
|
||||||
except:
|
except:
|
||||||
|
@ -130,7 +109,7 @@ class Database:
|
||||||
try:
|
try:
|
||||||
cursor = db.cursor()
|
cursor = db.cursor()
|
||||||
cursor.execute('UPDATE id' + tox_id + ' SET author = 0 '
|
cursor.execute('UPDATE id' + tox_id + ' SET author = 0 '
|
||||||
'WHERE message_id = ' + str(message_id) + ' AND author = 2;')
|
'WHERE id = ' + str(message_id) + ' AND author = 2;')
|
||||||
db.commit()
|
db.commit()
|
||||||
except:
|
except:
|
||||||
print('Database is locked!')
|
print('Database is locked!')
|
||||||
|
@ -163,8 +142,7 @@ class Database:
|
||||||
db.close()
|
db.close()
|
||||||
|
|
||||||
def messages_getter(self, tox_id):
|
def messages_getter(self, tox_id):
|
||||||
if not self.friend_exists_in_db(tox_id):
|
self.add_friend_to_db(tox_id)
|
||||||
self.add_friend_to_db(tox_id)
|
|
||||||
|
|
||||||
return Database.MessageGetter(self._path, tox_id)
|
return Database.MessageGetter(self._path, tox_id)
|
||||||
|
|
||||||
|
@ -180,15 +158,6 @@ class Database:
|
||||||
self._tox_id = tox_id
|
self._tox_id = tox_id
|
||||||
self._db = self._cursor = None
|
self._db = self._cursor = None
|
||||||
|
|
||||||
def _connect(self):
|
|
||||||
self._db = connect(self._path, timeout=TIMEOUT)
|
|
||||||
self._cursor = self._db.cursor()
|
|
||||||
self._cursor.execute('SELECT id, message_id, message, author, unix_time, message_type FROM id' +
|
|
||||||
self._tox_id + ' ORDER BY unix_time DESC;')
|
|
||||||
|
|
||||||
def _disconnect(self):
|
|
||||||
self._db.close()
|
|
||||||
|
|
||||||
def get_one(self):
|
def get_one(self):
|
||||||
return self.get(1)
|
return self.get(1)
|
||||||
|
|
||||||
|
@ -214,3 +183,19 @@ class Database:
|
||||||
def delete_one(self):
|
def delete_one(self):
|
||||||
if self._count:
|
if self._count:
|
||||||
self._count -= 1
|
self._count -= 1
|
||||||
|
|
||||||
|
def _connect(self):
|
||||||
|
self._db = connect(self._path, timeout=TIMEOUT)
|
||||||
|
self._cursor = self._db.cursor()
|
||||||
|
self._cursor.execute('SELECT id, message, author, unix_time, message_type FROM id' +
|
||||||
|
self._tox_id + ' ORDER BY unix_time DESC;')
|
||||||
|
|
||||||
|
def _disconnect(self):
|
||||||
|
self._db.close()
|
||||||
|
|
||||||
|
# -----------------------------------------------------------------------------------------------------------------
|
||||||
|
# Private methods
|
||||||
|
# -----------------------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
def _connect(self):
|
||||||
|
return connect(self._path, timeout=TIMEOUT)
|
||||||
|
|
|
@ -1,14 +1,15 @@
|
||||||
from history.history_logs_generators import *
|
from history.history_logs_generators import *
|
||||||
|
|
||||||
# TODO: fix history loading and saving
|
|
||||||
|
|
||||||
|
|
||||||
class History:
|
class History:
|
||||||
|
|
||||||
def __init__(self, contact_provider, db, settings):
|
def __init__(self, contact_provider, db, settings, main_screen, messages_items_factory):
|
||||||
self._contact_provider = contact_provider
|
self._contact_provider = contact_provider
|
||||||
self._db = db
|
self._db = db
|
||||||
self._settings = settings
|
self._settings = settings
|
||||||
|
self._messages = main_screen.messages
|
||||||
|
self._messages_items_factory = messages_items_factory
|
||||||
|
self._is_loading = False
|
||||||
|
|
||||||
def __del__(self):
|
def __del__(self):
|
||||||
del self._db
|
del self._db
|
||||||
|
@ -23,8 +24,7 @@ class History:
|
||||||
"""
|
"""
|
||||||
if self._settings['save_db']:
|
if self._settings['save_db']:
|
||||||
for friend in self._contact_provider.get_all_friends():
|
for friend in self._contact_provider.get_all_friends():
|
||||||
if not self._db.friend_exists_in_db(friend.tox_id):
|
self._db.add_friend_to_db(friend.tox_id)
|
||||||
self._db.add_friend_to_db(friend.tox_id)
|
|
||||||
if not self._settings['save_unsent_only']:
|
if not self._settings['save_unsent_only']:
|
||||||
messages = friend.get_corr_for_saving()
|
messages = friend.get_corr_for_saving()
|
||||||
else:
|
else:
|
||||||
|
@ -41,68 +41,50 @@ class History:
|
||||||
Clear chat history
|
Clear chat history
|
||||||
"""
|
"""
|
||||||
friend.clear_corr(save_unsent)
|
friend.clear_corr(save_unsent)
|
||||||
if self._db.friend_exists_in_db(friend.tox_id):
|
self._db.delete_friend_from_db(friend.tox_id)
|
||||||
self._db.delete_messages(friend.tox_id)
|
|
||||||
self._db.delete_friend_from_db(friend.tox_id)
|
|
||||||
|
|
||||||
def delete_message(self, message):
|
def delete_message(self, message):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def load_history(self):
|
def load_history(self, friend):
|
||||||
"""
|
"""
|
||||||
Tries to load next part of messages
|
Tries to load next part of messages
|
||||||
"""
|
"""
|
||||||
if not self._load_db:
|
if self._is_loading:
|
||||||
return
|
return
|
||||||
self._load_db = False
|
self._is_loading = True
|
||||||
friend = self.get_curr_friend()
|
|
||||||
friend.load_corr(False)
|
friend.load_corr(False)
|
||||||
data = friend.get_corr()
|
messages = friend.get_corr()
|
||||||
if not data:
|
if not messages:
|
||||||
|
self._is_loading = False
|
||||||
return
|
return
|
||||||
data.reverse()
|
messages.reverse()
|
||||||
data = data[self._messages.count():self._messages.count() + PAGE_SIZE]
|
messages = messages[self._messages.count():self._messages.count() + PAGE_SIZE]
|
||||||
for message in data:
|
for message in messages:
|
||||||
if message.get_type() <= 1: # text message
|
if message.get_type() <= 1: # text message
|
||||||
data = message.get_data()
|
self._create_message_item(message)
|
||||||
self.create_message_item(data[0],
|
|
||||||
data[2],
|
|
||||||
data[1],
|
|
||||||
data[3],
|
|
||||||
False)
|
|
||||||
elif message.get_type() == MESSAGE_TYPE['FILE_TRANSFER']: # file transfer
|
elif message.get_type() == MESSAGE_TYPE['FILE_TRANSFER']: # file transfer
|
||||||
if message.get_status() is None:
|
if message.get_status() is None:
|
||||||
self.create_unsent_file_item(message)
|
self._create_unsent_file_item(message)
|
||||||
continue
|
continue
|
||||||
item = self.create_file_transfer_item(message, False)
|
self._create_file_transfer_item(message)
|
||||||
if message.get_status() in ACTIVE_FILE_TRANSFERS: # active file transfer
|
|
||||||
try:
|
|
||||||
ft = self._file_transfers[(message.get_friend_number(), message.get_file_number())]
|
|
||||||
ft.set_state_changed_handler(item.update_transfer_state)
|
|
||||||
ft.signal()
|
|
||||||
except:
|
|
||||||
print('Incoming not started transfer - no info found')
|
|
||||||
elif message.get_type() == MESSAGE_TYPE['INLINE']: # inline image
|
elif message.get_type() == MESSAGE_TYPE['INLINE']: # inline image
|
||||||
self.create_inline_item(message.get_data(), False)
|
self._create_inline_item(message)
|
||||||
else: # info message
|
else: # info message
|
||||||
data = message.get_data()
|
self._create_message_item(message)
|
||||||
self.create_message_item(data[0],
|
self._is_loading = False
|
||||||
data[2],
|
|
||||||
'',
|
|
||||||
data[3],
|
|
||||||
False)
|
|
||||||
self._load_db = True
|
|
||||||
|
|
||||||
def get_message_getter(self, friend_public_key):
|
def get_message_getter(self, friend_public_key):
|
||||||
if not self._db.friend_exists_in_db(friend_public_key):
|
self._db.add_friend_to_db(friend_public_key)
|
||||||
self._db.add_friend_to_db(friend_public_key)
|
|
||||||
|
|
||||||
return self._db.messages_getter(friend_public_key)
|
return self._db.messages_getter(friend_public_key)
|
||||||
|
|
||||||
def delete_history(self, friend):
|
def delete_history(self, friend):
|
||||||
self.clear_history(friend)
|
self.clear_history(friend)
|
||||||
if self._db.friend_exists_in_db(friend.tox_id):
|
self._db.delete_friend_from_db(friend.tox_id)
|
||||||
self._db.delete_friend_from_db(friend.tox_id)
|
|
||||||
|
def add_friend_to_db(self, tox_id):
|
||||||
|
self._db.add_friend_to_db(tox_id)
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def export_history(contact, as_text=True, _range=None):
|
def export_history(contact, as_text=True, _range=None):
|
||||||
|
@ -117,3 +99,19 @@ class History:
|
||||||
generator = TextHistoryGenerator(corr, contact.name) if as_text else HtmlHistoryGenerator(corr, contact.name)
|
generator = TextHistoryGenerator(corr, contact.name) if as_text else HtmlHistoryGenerator(corr, contact.name)
|
||||||
|
|
||||||
return generator.generate()
|
return generator.generate()
|
||||||
|
|
||||||
|
# -----------------------------------------------------------------------------------------------------------------
|
||||||
|
# Items creation
|
||||||
|
# -----------------------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
def _create_message_item(self, message):
|
||||||
|
return self._messages_items_factory.create_message_item(message, False)
|
||||||
|
|
||||||
|
def _create_unsent_file_item(self, message):
|
||||||
|
return self._messages_items_factory.create_unsent_file_item(message, False)
|
||||||
|
|
||||||
|
def _create_file_transfer_item(self, message):
|
||||||
|
return self._messages_items_factory.create_file_transfer_item(message, False)
|
||||||
|
|
||||||
|
def _create_inline_item(self, message):
|
||||||
|
return self._messages_items_factory.create_inline_item(message, False)
|
||||||
|
|
100
toxygen/ui/contact_items.py
Normal file
100
toxygen/ui/contact_items.py
Normal file
|
@ -0,0 +1,100 @@
|
||||||
|
from wrapper.toxcore_enums_and_consts import *
|
||||||
|
from PyQt5 import QtCore, QtGui, QtWidgets
|
||||||
|
from contacts import profile
|
||||||
|
from file_transfers.file_transfers import TOX_FILE_TRANSFER_STATE, PAUSED_FILE_TRANSFERS, DO_NOT_SHOW_ACCEPT_BUTTON, ACTIVE_FILE_TRANSFERS, SHOW_PROGRESS_BAR
|
||||||
|
from utils.util import *
|
||||||
|
from ui.widgets import DataLabel, create_menu
|
||||||
|
from user_data import settings
|
||||||
|
|
||||||
|
|
||||||
|
class ContactItem(QtWidgets.QWidget):
|
||||||
|
"""
|
||||||
|
Contact in friends list
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __init__(self, settings, parent=None):
|
||||||
|
QtWidgets.QWidget.__init__(self, parent)
|
||||||
|
mode = settings['compact_mode']
|
||||||
|
self.setBaseSize(QtCore.QSize(250, 40 if mode else 70))
|
||||||
|
self.avatar_label = QtWidgets.QLabel(self)
|
||||||
|
size = 32 if mode else 64
|
||||||
|
self.avatar_label.setGeometry(QtCore.QRect(3, 4, size, size))
|
||||||
|
self.avatar_label.setScaledContents(False)
|
||||||
|
self.avatar_label.setAlignment(QtCore.Qt.AlignCenter)
|
||||||
|
self.name = DataLabel(self)
|
||||||
|
self.name.setGeometry(QtCore.QRect(50 if mode else 75, 3 if mode else 10, 150, 15 if mode else 25))
|
||||||
|
font = QtGui.QFont()
|
||||||
|
font.setFamily(settings['font'])
|
||||||
|
font.setPointSize(10 if mode else 12)
|
||||||
|
font.setBold(True)
|
||||||
|
self.name.setFont(font)
|
||||||
|
self.status_message = DataLabel(self)
|
||||||
|
self.status_message.setGeometry(QtCore.QRect(50 if mode else 75, 20 if mode else 30, 170, 15 if mode else 20))
|
||||||
|
font.setPointSize(10)
|
||||||
|
font.setBold(False)
|
||||||
|
self.status_message.setFont(font)
|
||||||
|
self.connection_status = StatusCircle(self)
|
||||||
|
self.connection_status.setGeometry(QtCore.QRect(230, -2 if mode else 5, 32, 32))
|
||||||
|
self.messages = UnreadMessagesCount(settings, self)
|
||||||
|
self.messages.setGeometry(QtCore.QRect(20 if mode else 52, 20 if mode else 50, 30, 20))
|
||||||
|
|
||||||
|
|
||||||
|
class StatusCircle(QtWidgets.QWidget):
|
||||||
|
"""
|
||||||
|
Connection status
|
||||||
|
"""
|
||||||
|
def __init__(self, parent):
|
||||||
|
QtWidgets.QWidget.__init__(self, parent)
|
||||||
|
self.setGeometry(0, 0, 32, 32)
|
||||||
|
self.label = QtWidgets.QLabel(self)
|
||||||
|
self.label.setGeometry(QtCore.QRect(0, 0, 32, 32))
|
||||||
|
self.unread = False
|
||||||
|
|
||||||
|
def update(self, status, unread_messages=None):
|
||||||
|
if unread_messages is None:
|
||||||
|
unread_messages = self.unread
|
||||||
|
else:
|
||||||
|
self.unread = unread_messages
|
||||||
|
if status == TOX_USER_STATUS['NONE']:
|
||||||
|
name = 'online'
|
||||||
|
elif status == TOX_USER_STATUS['AWAY']:
|
||||||
|
name = 'idle'
|
||||||
|
elif status == TOX_USER_STATUS['BUSY']:
|
||||||
|
name = 'busy'
|
||||||
|
else:
|
||||||
|
name = 'offline'
|
||||||
|
if unread_messages:
|
||||||
|
name += '_notification'
|
||||||
|
self.label.setGeometry(QtCore.QRect(0, 0, 32, 32))
|
||||||
|
else:
|
||||||
|
self.label.setGeometry(QtCore.QRect(2, 0, 32, 32))
|
||||||
|
pixmap = QtGui.QPixmap(join_path(get_images_directory(), '{}.png'.format(name)))
|
||||||
|
self.label.setPixmap(pixmap)
|
||||||
|
|
||||||
|
|
||||||
|
class UnreadMessagesCount(QtWidgets.QWidget):
|
||||||
|
|
||||||
|
def __init__(self, settings, parent=None):
|
||||||
|
super().__init__(parent)
|
||||||
|
self._settings = settings
|
||||||
|
self.resize(30, 20)
|
||||||
|
self.label = QtWidgets.QLabel(self)
|
||||||
|
self.label.setGeometry(QtCore.QRect(0, 0, 30, 20))
|
||||||
|
self.label.setVisible(False)
|
||||||
|
font = QtGui.QFont()
|
||||||
|
font.setFamily(settings['font'])
|
||||||
|
font.setPointSize(12)
|
||||||
|
font.setBold(True)
|
||||||
|
self.label.setFont(font)
|
||||||
|
self.label.setAlignment(QtCore.Qt.AlignVCenter | QtCore.Qt.AlignCenter)
|
||||||
|
color = settings['unread_color']
|
||||||
|
self.label.setStyleSheet('QLabel { color: white; background-color: ' + color + '; border-radius: 10; }')
|
||||||
|
|
||||||
|
def update(self, messages_count):
|
||||||
|
color = self._settings['unread_color']
|
||||||
|
self.label.setStyleSheet('QLabel { color: white; background-color: ' + color + '; border-radius: 10; }')
|
||||||
|
if messages_count:
|
||||||
|
self.label.setVisible(True)
|
||||||
|
self.label.setText(str(messages_count))
|
||||||
|
else:
|
||||||
|
self.label.setVisible(False)
|
|
@ -1,4 +1,4 @@
|
||||||
from ui.list_items import *
|
from ui.contact_items import *
|
||||||
from ui.messages_widgets import *
|
from ui.messages_widgets import *
|
||||||
|
|
||||||
|
|
||||||
|
@ -18,17 +18,19 @@ class FriendItemsFactory:
|
||||||
return item
|
return item
|
||||||
|
|
||||||
|
|
||||||
|
# TODO: accept messages everywhere instead of params
|
||||||
|
|
||||||
class MessagesItemsFactory:
|
class MessagesItemsFactory:
|
||||||
|
|
||||||
def __init__(self, settings, plugin_loader, smiley_loader, main_screen, history):
|
def __init__(self, settings, plugin_loader, smiley_loader, main_screen, delete_action):
|
||||||
self._settings, self._plugin_loader = settings, plugin_loader
|
self._settings, self._plugin_loader = settings, plugin_loader
|
||||||
self._smiley_loader, self._history = smiley_loader, history
|
self._smiley_loader, self._delete_action = smiley_loader, delete_action
|
||||||
self._messages = main_screen.messages
|
self._messages = main_screen.messages
|
||||||
self._message_edit = main_screen.messageEdit
|
self._message_edit = main_screen.messageEdit
|
||||||
|
|
||||||
def create_message_item(self, message, append=True, pixmap=None):
|
def create_message_item(self, message, append=True, pixmap=None):
|
||||||
item = message.get_widget(self._settings, self._create_message_browser,
|
item = message.get_widget(self._settings, self._create_message_browser,
|
||||||
self._history.delete_message, self._messages)
|
self._delete_action, self._messages)
|
||||||
if pixmap is not None:
|
if pixmap is not None:
|
||||||
item.set_avatar(pixmap)
|
item.set_avatar(pixmap)
|
||||||
elem = QtWidgets.QListWidgetItem()
|
elem = QtWidgets.QListWidgetItem()
|
||||||
|
@ -69,7 +71,7 @@ class MessagesItemsFactory:
|
||||||
|
|
||||||
return item
|
return item
|
||||||
|
|
||||||
def create_file_transfer_item(self, data, append):
|
def create_file_transfer_item(self, data, append=True):
|
||||||
data.append(self._messages.width())
|
data.append(self._messages.width())
|
||||||
item = FileTransferItem(*data)
|
item = FileTransferItem(*data)
|
||||||
elem = QtWidgets.QListWidgetItem()
|
elem = QtWidgets.QListWidgetItem()
|
||||||
|
|
|
@ -1,343 +0,0 @@
|
||||||
from wrapper.toxcore_enums_and_consts import *
|
|
||||||
from PyQt5 import QtCore, QtGui, QtWidgets
|
|
||||||
from contacts import profile
|
|
||||||
from file_transfers.file_transfers import TOX_FILE_TRANSFER_STATE, PAUSED_FILE_TRANSFERS, DO_NOT_SHOW_ACCEPT_BUTTON, ACTIVE_FILE_TRANSFERS, SHOW_PROGRESS_BAR
|
|
||||||
from utils.util import *
|
|
||||||
from ui.widgets import DataLabel, create_menu
|
|
||||||
from user_data import settings
|
|
||||||
|
|
||||||
|
|
||||||
class ContactItem(QtWidgets.QWidget):
|
|
||||||
"""
|
|
||||||
Contact in friends list
|
|
||||||
"""
|
|
||||||
|
|
||||||
def __init__(self, settings, parent=None):
|
|
||||||
QtWidgets.QWidget.__init__(self, parent)
|
|
||||||
mode = settings['compact_mode']
|
|
||||||
self.setBaseSize(QtCore.QSize(250, 40 if mode else 70))
|
|
||||||
self.avatar_label = QtWidgets.QLabel(self)
|
|
||||||
size = 32 if mode else 64
|
|
||||||
self.avatar_label.setGeometry(QtCore.QRect(3, 4, size, size))
|
|
||||||
self.avatar_label.setScaledContents(False)
|
|
||||||
self.avatar_label.setAlignment(QtCore.Qt.AlignCenter)
|
|
||||||
self.name = DataLabel(self)
|
|
||||||
self.name.setGeometry(QtCore.QRect(50 if mode else 75, 3 if mode else 10, 150, 15 if mode else 25))
|
|
||||||
font = QtGui.QFont()
|
|
||||||
font.setFamily(settings['font'])
|
|
||||||
font.setPointSize(10 if mode else 12)
|
|
||||||
font.setBold(True)
|
|
||||||
self.name.setFont(font)
|
|
||||||
self.status_message = DataLabel(self)
|
|
||||||
self.status_message.setGeometry(QtCore.QRect(50 if mode else 75, 20 if mode else 30, 170, 15 if mode else 20))
|
|
||||||
font.setPointSize(10)
|
|
||||||
font.setBold(False)
|
|
||||||
self.status_message.setFont(font)
|
|
||||||
self.connection_status = StatusCircle(self)
|
|
||||||
self.connection_status.setGeometry(QtCore.QRect(230, -2 if mode else 5, 32, 32))
|
|
||||||
self.messages = UnreadMessagesCount(settings, self)
|
|
||||||
self.messages.setGeometry(QtCore.QRect(20 if mode else 52, 20 if mode else 50, 30, 20))
|
|
||||||
|
|
||||||
|
|
||||||
class StatusCircle(QtWidgets.QWidget):
|
|
||||||
"""
|
|
||||||
Connection status
|
|
||||||
"""
|
|
||||||
def __init__(self, parent):
|
|
||||||
QtWidgets.QWidget.__init__(self, parent)
|
|
||||||
self.setGeometry(0, 0, 32, 32)
|
|
||||||
self.label = QtWidgets.QLabel(self)
|
|
||||||
self.label.setGeometry(QtCore.QRect(0, 0, 32, 32))
|
|
||||||
self.unread = False
|
|
||||||
|
|
||||||
def update(self, status, unread_messages=None):
|
|
||||||
if unread_messages is None:
|
|
||||||
unread_messages = self.unread
|
|
||||||
else:
|
|
||||||
self.unread = unread_messages
|
|
||||||
if status == TOX_USER_STATUS['NONE']:
|
|
||||||
name = 'online'
|
|
||||||
elif status == TOX_USER_STATUS['AWAY']:
|
|
||||||
name = 'idle'
|
|
||||||
elif status == TOX_USER_STATUS['BUSY']:
|
|
||||||
name = 'busy'
|
|
||||||
else:
|
|
||||||
name = 'offline'
|
|
||||||
if unread_messages:
|
|
||||||
name += '_notification'
|
|
||||||
self.label.setGeometry(QtCore.QRect(0, 0, 32, 32))
|
|
||||||
else:
|
|
||||||
self.label.setGeometry(QtCore.QRect(2, 0, 32, 32))
|
|
||||||
pixmap = QtGui.QPixmap(join_path(get_images_directory(), '{}.png'.format(name)))
|
|
||||||
self.label.setPixmap(pixmap)
|
|
||||||
|
|
||||||
|
|
||||||
class UnreadMessagesCount(QtWidgets.QWidget):
|
|
||||||
|
|
||||||
def __init__(self, settings, parent=None):
|
|
||||||
super().__init__(parent)
|
|
||||||
self._settings = settings
|
|
||||||
self.resize(30, 20)
|
|
||||||
self.label = QtWidgets.QLabel(self)
|
|
||||||
self.label.setGeometry(QtCore.QRect(0, 0, 30, 20))
|
|
||||||
self.label.setVisible(False)
|
|
||||||
font = QtGui.QFont()
|
|
||||||
font.setFamily(settings['font'])
|
|
||||||
font.setPointSize(12)
|
|
||||||
font.setBold(True)
|
|
||||||
self.label.setFont(font)
|
|
||||||
self.label.setAlignment(QtCore.Qt.AlignVCenter | QtCore.Qt.AlignCenter)
|
|
||||||
color = settings['unread_color']
|
|
||||||
self.label.setStyleSheet('QLabel { color: white; background-color: ' + color + '; border-radius: 10; }')
|
|
||||||
|
|
||||||
def update(self, messages_count):
|
|
||||||
color = self._settings['unread_color']
|
|
||||||
self.label.setStyleSheet('QLabel { color: white; background-color: ' + color + '; border-radius: 10; }')
|
|
||||||
if messages_count:
|
|
||||||
self.label.setVisible(True)
|
|
||||||
self.label.setText(str(messages_count))
|
|
||||||
else:
|
|
||||||
self.label.setVisible(False)
|
|
||||||
|
|
||||||
|
|
||||||
class FileTransferItem(QtWidgets.QListWidget):
|
|
||||||
|
|
||||||
def __init__(self, file_name, size, time, user, friend_number, file_number, state, width, parent=None):
|
|
||||||
|
|
||||||
QtWidgets.QListWidget.__init__(self, parent)
|
|
||||||
self.resize(QtCore.QSize(width, 34))
|
|
||||||
if state == TOX_FILE_TRANSFER_STATE['CANCELLED']:
|
|
||||||
self.setStyleSheet('QListWidget { border: 1px solid #B40404; }')
|
|
||||||
elif state in PAUSED_FILE_TRANSFERS:
|
|
||||||
self.setStyleSheet('QListWidget { border: 1px solid #FF8000; }')
|
|
||||||
else:
|
|
||||||
self.setStyleSheet('QListWidget { border: 1px solid green; }')
|
|
||||||
self.state = state
|
|
||||||
|
|
||||||
self.name = DataLabel(self)
|
|
||||||
self.name.setGeometry(QtCore.QRect(3, 7, 95, 25))
|
|
||||||
self.name.setTextFormat(QtCore.Qt.PlainText)
|
|
||||||
font = QtGui.QFont()
|
|
||||||
# FIXME
|
|
||||||
font.setFamily(settings.Settings.get_instance()['font'])
|
|
||||||
font.setPointSize(11)
|
|
||||||
font.setBold(True)
|
|
||||||
self.name.setFont(font)
|
|
||||||
self.name.setText(user)
|
|
||||||
|
|
||||||
self.time = QtWidgets.QLabel(self)
|
|
||||||
self.time.setGeometry(QtCore.QRect(width - 60, 7, 50, 25))
|
|
||||||
font.setPointSize(10)
|
|
||||||
font.setBold(False)
|
|
||||||
self.time.setFont(font)
|
|
||||||
self.time.setText(convert_time(time))
|
|
||||||
|
|
||||||
self.cancel = QtWidgets.QPushButton(self)
|
|
||||||
self.cancel.setGeometry(QtCore.QRect(width - 125, 2, 30, 30))
|
|
||||||
pixmap = QtGui.QPixmap(curr_directory() + '/images/decline.png')
|
|
||||||
icon = QtGui.QIcon(pixmap)
|
|
||||||
self.cancel.setIcon(icon)
|
|
||||||
self.cancel.setIconSize(QtCore.QSize(30, 30))
|
|
||||||
self.cancel.setVisible(state in ACTIVE_FILE_TRANSFERS)
|
|
||||||
self.cancel.clicked.connect(lambda: self.cancel_transfer(friend_number, file_number))
|
|
||||||
self.cancel.setStyleSheet('QPushButton:hover { border: 1px solid #3A3939; background-color: none;}')
|
|
||||||
|
|
||||||
self.accept_or_pause = QtWidgets.QPushButton(self)
|
|
||||||
self.accept_or_pause.setGeometry(QtCore.QRect(width - 170, 2, 30, 30))
|
|
||||||
if state == TOX_FILE_TRANSFER_STATE['INCOMING_NOT_STARTED']:
|
|
||||||
self.accept_or_pause.setVisible(True)
|
|
||||||
self.button_update('accept')
|
|
||||||
elif state in DO_NOT_SHOW_ACCEPT_BUTTON:
|
|
||||||
self.accept_or_pause.setVisible(False)
|
|
||||||
elif state == TOX_FILE_TRANSFER_STATE['PAUSED_BY_USER']: # setup for continue
|
|
||||||
self.accept_or_pause.setVisible(True)
|
|
||||||
self.button_update('resume')
|
|
||||||
else: # pause
|
|
||||||
self.accept_or_pause.setVisible(True)
|
|
||||||
self.button_update('pause')
|
|
||||||
self.accept_or_pause.clicked.connect(lambda: self.accept_or_pause_transfer(friend_number, file_number, size))
|
|
||||||
|
|
||||||
self.accept_or_pause.setStyleSheet('QPushButton:hover { border: 1px solid #3A3939; background-color: none}')
|
|
||||||
|
|
||||||
self.pb = QtWidgets.QProgressBar(self)
|
|
||||||
self.pb.setGeometry(QtCore.QRect(100, 7, 100, 20))
|
|
||||||
self.pb.setValue(0)
|
|
||||||
self.pb.setStyleSheet('QProgressBar { background-color: #302F2F; }')
|
|
||||||
self.pb.setVisible(state in SHOW_PROGRESS_BAR)
|
|
||||||
|
|
||||||
self.file_name = DataLabel(self)
|
|
||||||
self.file_name.setGeometry(QtCore.QRect(210, 7, width - 420, 20))
|
|
||||||
font.setPointSize(12)
|
|
||||||
self.file_name.setFont(font)
|
|
||||||
file_size = size // 1024
|
|
||||||
if not file_size:
|
|
||||||
file_size = '{}B'.format(size)
|
|
||||||
elif file_size >= 1024:
|
|
||||||
file_size = '{}MB'.format(file_size // 1024)
|
|
||||||
else:
|
|
||||||
file_size = '{}KB'.format(file_size)
|
|
||||||
file_data = '{} {}'.format(file_size, file_name)
|
|
||||||
self.file_name.setText(file_data)
|
|
||||||
self.file_name.setToolTip(file_name)
|
|
||||||
self.saved_name = file_name
|
|
||||||
self.time_left = QtWidgets.QLabel(self)
|
|
||||||
self.time_left.setGeometry(QtCore.QRect(width - 92, 7, 30, 20))
|
|
||||||
font.setPointSize(10)
|
|
||||||
self.time_left.setFont(font)
|
|
||||||
self.time_left.setVisible(state == TOX_FILE_TRANSFER_STATE['RUNNING'])
|
|
||||||
self.setFocusPolicy(QtCore.Qt.NoFocus)
|
|
||||||
self.paused = False
|
|
||||||
|
|
||||||
def cancel_transfer(self, friend_number, file_number):
|
|
||||||
pr = profile.Profile.get_instance()
|
|
||||||
pr.cancel_transfer(friend_number, file_number)
|
|
||||||
self.setStyleSheet('QListWidget { border: 1px solid #B40404; }')
|
|
||||||
self.cancel.setVisible(False)
|
|
||||||
self.accept_or_pause.setVisible(False)
|
|
||||||
self.pb.setVisible(False)
|
|
||||||
|
|
||||||
def accept_or_pause_transfer(self, friend_number, file_number, size):
|
|
||||||
if self.state == TOX_FILE_TRANSFER_STATE['INCOMING_NOT_STARTED']:
|
|
||||||
directory = QtWidgets.QFileDialog.getExistingDirectory(self,
|
|
||||||
QtWidgets.QApplication.translate("MainWindow", 'Choose folder'),
|
|
||||||
curr_directory(),
|
|
||||||
QtWidgets.QFileDialog.ShowDirsOnly | QtWidgets.QFileDialog.DontUseNativeDialog)
|
|
||||||
self.pb.setVisible(True)
|
|
||||||
if directory:
|
|
||||||
pr = profile.Profile.get_instance()
|
|
||||||
pr.accept_transfer(self, directory + '/' + self.saved_name, friend_number, file_number, size)
|
|
||||||
self.button_update('pause')
|
|
||||||
elif self.state == TOX_FILE_TRANSFER_STATE['PAUSED_BY_USER']: # resume
|
|
||||||
self.paused = False
|
|
||||||
profile.Profile.get_instance().resume_transfer(friend_number, file_number)
|
|
||||||
self.button_update('pause')
|
|
||||||
self.state = TOX_FILE_TRANSFER_STATE['RUNNING']
|
|
||||||
else: # pause
|
|
||||||
self.paused = True
|
|
||||||
self.state = TOX_FILE_TRANSFER_STATE['PAUSED_BY_USER']
|
|
||||||
profile.Profile.get_instance().pause_transfer(friend_number, file_number)
|
|
||||||
self.button_update('resume')
|
|
||||||
self.accept_or_pause.clearFocus()
|
|
||||||
|
|
||||||
def button_update(self, path):
|
|
||||||
pixmap = QtGui.QPixmap(curr_directory() + '/images/{}.png'.format(path))
|
|
||||||
icon = QtGui.QIcon(pixmap)
|
|
||||||
self.accept_or_pause.setIcon(icon)
|
|
||||||
self.accept_or_pause.setIconSize(QtCore.QSize(30, 30))
|
|
||||||
|
|
||||||
def update_transfer_state(self, state, progress, time):
|
|
||||||
self.pb.setValue(int(progress * 100))
|
|
||||||
if time + 1:
|
|
||||||
m, s = divmod(time, 60)
|
|
||||||
self.time_left.setText('{0:02d}:{1:02d}'.format(m, s))
|
|
||||||
if self.state != state and self.state in ACTIVE_FILE_TRANSFERS:
|
|
||||||
if state == TOX_FILE_TRANSFER_STATE['CANCELLED']:
|
|
||||||
self.setStyleSheet('QListWidget { border: 1px solid #B40404; }')
|
|
||||||
self.cancel.setVisible(False)
|
|
||||||
self.accept_or_pause.setVisible(False)
|
|
||||||
self.pb.setVisible(False)
|
|
||||||
self.state = state
|
|
||||||
self.time_left.setVisible(False)
|
|
||||||
elif state == TOX_FILE_TRANSFER_STATE['FINISHED']:
|
|
||||||
self.accept_or_pause.setVisible(False)
|
|
||||||
self.pb.setVisible(False)
|
|
||||||
self.cancel.setVisible(False)
|
|
||||||
self.setStyleSheet('QListWidget { border: 1px solid green; }')
|
|
||||||
self.state = state
|
|
||||||
self.time_left.setVisible(False)
|
|
||||||
elif state == TOX_FILE_TRANSFER_STATE['PAUSED_BY_FRIEND']:
|
|
||||||
self.accept_or_pause.setVisible(False)
|
|
||||||
self.setStyleSheet('QListWidget { border: 1px solid #FF8000; }')
|
|
||||||
self.state = state
|
|
||||||
self.time_left.setVisible(False)
|
|
||||||
elif state == TOX_FILE_TRANSFER_STATE['PAUSED_BY_USER']:
|
|
||||||
self.button_update('resume') # setup button continue
|
|
||||||
self.setStyleSheet('QListWidget { border: 1px solid green; }')
|
|
||||||
self.state = state
|
|
||||||
self.time_left.setVisible(False)
|
|
||||||
elif state == TOX_FILE_TRANSFER_STATE['OUTGOING_NOT_STARTED']:
|
|
||||||
self.setStyleSheet('QListWidget { border: 1px solid #FF8000; }')
|
|
||||||
self.accept_or_pause.setVisible(False)
|
|
||||||
self.time_left.setVisible(False)
|
|
||||||
self.pb.setVisible(False)
|
|
||||||
elif not self.paused: # active
|
|
||||||
self.pb.setVisible(True)
|
|
||||||
self.accept_or_pause.setVisible(True) # setup to pause
|
|
||||||
self.button_update('pause')
|
|
||||||
self.setStyleSheet('QListWidget { border: 1px solid green; }')
|
|
||||||
self.state = state
|
|
||||||
self.time_left.setVisible(True)
|
|
||||||
|
|
||||||
def mark_as_sent(self):
|
|
||||||
return False
|
|
||||||
|
|
||||||
|
|
||||||
class UnsentFileItem(FileTransferItem):
|
|
||||||
|
|
||||||
def __init__(self, file_name, size, user, time, width, parent=None):
|
|
||||||
super(UnsentFileItem, self).__init__(file_name, size, time, user, -1, -1,
|
|
||||||
TOX_FILE_TRANSFER_STATE['PAUSED_BY_FRIEND'], width, parent)
|
|
||||||
self._time = time
|
|
||||||
self.pb.setVisible(False)
|
|
||||||
movie = QtGui.QMovie(join_path(get_images_directory(), 'spinner.gif'))
|
|
||||||
self.time.setMovie(movie)
|
|
||||||
movie.start()
|
|
||||||
|
|
||||||
def cancel_transfer(self, *args):
|
|
||||||
pr = profile.Profile.get_instance()
|
|
||||||
pr.cancel_not_started_transfer(self._time)
|
|
||||||
|
|
||||||
|
|
||||||
class InlineImageItem(QtWidgets.QScrollArea):
|
|
||||||
|
|
||||||
def __init__(self, data, width, elem):
|
|
||||||
|
|
||||||
QtWidgets.QScrollArea.__init__(self)
|
|
||||||
self.setFocusPolicy(QtCore.Qt.NoFocus)
|
|
||||||
self._elem = elem
|
|
||||||
self._image_label = QtWidgets.QLabel(self)
|
|
||||||
self._image_label.raise_()
|
|
||||||
self.setWidget(self._image_label)
|
|
||||||
self._image_label.setScaledContents(False)
|
|
||||||
self._pixmap = QtGui.QPixmap()
|
|
||||||
self._pixmap.loadFromData(data, 'PNG')
|
|
||||||
self._max_size = width - 30
|
|
||||||
self._resize_needed = not (self._pixmap.width() <= self._max_size)
|
|
||||||
self._full_size = not self._resize_needed
|
|
||||||
if not self._resize_needed:
|
|
||||||
self._image_label.setPixmap(self._pixmap)
|
|
||||||
self.resize(QtCore.QSize(self._max_size + 5, self._pixmap.height() + 5))
|
|
||||||
self._image_label.setGeometry(5, 0, self._pixmap.width(), self._pixmap.height())
|
|
||||||
else:
|
|
||||||
pixmap = self._pixmap.scaled(self._max_size, self._max_size, QtCore.Qt.KeepAspectRatio)
|
|
||||||
self._image_label.setPixmap(pixmap)
|
|
||||||
self.resize(QtCore.QSize(self._max_size + 5, pixmap.height()))
|
|
||||||
self._image_label.setGeometry(5, 0, self._max_size + 5, pixmap.height())
|
|
||||||
self._elem.setSizeHint(QtCore.QSize(self.width(), self.height()))
|
|
||||||
|
|
||||||
def mouseReleaseEvent(self, event):
|
|
||||||
if event.button() == QtCore.Qt.LeftButton and self._resize_needed: # scale inline
|
|
||||||
if self._full_size:
|
|
||||||
pixmap = self._pixmap.scaled(self._max_size, self._max_size, QtCore.Qt.KeepAspectRatio)
|
|
||||||
self._image_label.setPixmap(pixmap)
|
|
||||||
self.resize(QtCore.QSize(self._max_size, pixmap.height()))
|
|
||||||
self._image_label.setGeometry(5, 0, pixmap.width(), pixmap.height())
|
|
||||||
else:
|
|
||||||
self._image_label.setPixmap(self._pixmap)
|
|
||||||
self.resize(QtCore.QSize(self._max_size, self._pixmap.height() + 17))
|
|
||||||
self._image_label.setGeometry(5, 0, self._pixmap.width(), self._pixmap.height())
|
|
||||||
self._full_size = not self._full_size
|
|
||||||
self._elem.setSizeHint(QtCore.QSize(self.width(), self.height()))
|
|
||||||
elif event.button() == QtCore.Qt.RightButton: # save inline
|
|
||||||
# TODO: dialog
|
|
||||||
directory = QtWidgets.QFileDialog.getExistingDirectory(self,
|
|
||||||
QtWidgets.QApplication.translate("MainWindow",
|
|
||||||
'Choose folder'),
|
|
||||||
curr_directory(),
|
|
||||||
QtWidgets.QFileDialog.ShowDirsOnly | QtWidgets.QFileDialog.DontUseNativeDialog)
|
|
||||||
if directory:
|
|
||||||
fl = QtCore.QFile(directory + '/toxygen_inline_' + curr_time().replace(':', '_') + '.png')
|
|
||||||
self._pixmap.save(fl, 'PNG')
|
|
||||||
|
|
||||||
def mark_as_sent(self):
|
|
||||||
return False
|
|
|
@ -1,5 +1,5 @@
|
||||||
from contacts.profile import *
|
from contacts.profile import *
|
||||||
from ui.list_items import *
|
from ui.contact_items import *
|
||||||
from ui.widgets import MultilineEdit, ComboBox
|
from ui.widgets import MultilineEdit, ComboBox
|
||||||
from ui.main_screen_widgets import *
|
from ui.main_screen_widgets import *
|
||||||
import utils.util as util
|
import utils.util as util
|
||||||
|
|
|
@ -213,3 +213,245 @@ class MessageItem(QtWidgets.QWidget):
|
||||||
i += len(sub)
|
i += len(sub)
|
||||||
return text
|
return text
|
||||||
|
|
||||||
|
|
||||||
|
class FileTransferItem(QtWidgets.QListWidget):
|
||||||
|
|
||||||
|
def __init__(self, file_name, size, time, user, friend_number, file_number, state, width, parent=None):
|
||||||
|
|
||||||
|
QtWidgets.QListWidget.__init__(self, parent)
|
||||||
|
self.resize(QtCore.QSize(width, 34))
|
||||||
|
if state == TOX_FILE_TRANSFER_STATE['CANCELLED']:
|
||||||
|
self.setStyleSheet('QListWidget { border: 1px solid #B40404; }')
|
||||||
|
elif state in PAUSED_FILE_TRANSFERS:
|
||||||
|
self.setStyleSheet('QListWidget { border: 1px solid #FF8000; }')
|
||||||
|
else:
|
||||||
|
self.setStyleSheet('QListWidget { border: 1px solid green; }')
|
||||||
|
self.state = state
|
||||||
|
|
||||||
|
self.name = DataLabel(self)
|
||||||
|
self.name.setGeometry(QtCore.QRect(3, 7, 95, 25))
|
||||||
|
self.name.setTextFormat(QtCore.Qt.PlainText)
|
||||||
|
font = QtGui.QFont()
|
||||||
|
# FIXME
|
||||||
|
font.setFamily(settings.Settings.get_instance()['font'])
|
||||||
|
font.setPointSize(11)
|
||||||
|
font.setBold(True)
|
||||||
|
self.name.setFont(font)
|
||||||
|
self.name.setText(user)
|
||||||
|
|
||||||
|
self.time = QtWidgets.QLabel(self)
|
||||||
|
self.time.setGeometry(QtCore.QRect(width - 60, 7, 50, 25))
|
||||||
|
font.setPointSize(10)
|
||||||
|
font.setBold(False)
|
||||||
|
self.time.setFont(font)
|
||||||
|
self.time.setText(convert_time(time))
|
||||||
|
|
||||||
|
self.cancel = QtWidgets.QPushButton(self)
|
||||||
|
self.cancel.setGeometry(QtCore.QRect(width - 125, 2, 30, 30))
|
||||||
|
pixmap = QtGui.QPixmap(curr_directory() + '/images/decline.png')
|
||||||
|
icon = QtGui.QIcon(pixmap)
|
||||||
|
self.cancel.setIcon(icon)
|
||||||
|
self.cancel.setIconSize(QtCore.QSize(30, 30))
|
||||||
|
self.cancel.setVisible(state in ACTIVE_FILE_TRANSFERS)
|
||||||
|
self.cancel.clicked.connect(lambda: self.cancel_transfer(friend_number, file_number))
|
||||||
|
self.cancel.setStyleSheet('QPushButton:hover { border: 1px solid #3A3939; background-color: none;}')
|
||||||
|
|
||||||
|
self.accept_or_pause = QtWidgets.QPushButton(self)
|
||||||
|
self.accept_or_pause.setGeometry(QtCore.QRect(width - 170, 2, 30, 30))
|
||||||
|
if state == TOX_FILE_TRANSFER_STATE['INCOMING_NOT_STARTED']:
|
||||||
|
self.accept_or_pause.setVisible(True)
|
||||||
|
self.button_update('accept')
|
||||||
|
elif state in DO_NOT_SHOW_ACCEPT_BUTTON:
|
||||||
|
self.accept_or_pause.setVisible(False)
|
||||||
|
elif state == TOX_FILE_TRANSFER_STATE['PAUSED_BY_USER']: # setup for continue
|
||||||
|
self.accept_or_pause.setVisible(True)
|
||||||
|
self.button_update('resume')
|
||||||
|
else: # pause
|
||||||
|
self.accept_or_pause.setVisible(True)
|
||||||
|
self.button_update('pause')
|
||||||
|
self.accept_or_pause.clicked.connect(lambda: self.accept_or_pause_transfer(friend_number, file_number, size))
|
||||||
|
|
||||||
|
self.accept_or_pause.setStyleSheet('QPushButton:hover { border: 1px solid #3A3939; background-color: none}')
|
||||||
|
|
||||||
|
self.pb = QtWidgets.QProgressBar(self)
|
||||||
|
self.pb.setGeometry(QtCore.QRect(100, 7, 100, 20))
|
||||||
|
self.pb.setValue(0)
|
||||||
|
self.pb.setStyleSheet('QProgressBar { background-color: #302F2F; }')
|
||||||
|
self.pb.setVisible(state in SHOW_PROGRESS_BAR)
|
||||||
|
|
||||||
|
self.file_name = DataLabel(self)
|
||||||
|
self.file_name.setGeometry(QtCore.QRect(210, 7, width - 420, 20))
|
||||||
|
font.setPointSize(12)
|
||||||
|
self.file_name.setFont(font)
|
||||||
|
file_size = size // 1024
|
||||||
|
if not file_size:
|
||||||
|
file_size = '{}B'.format(size)
|
||||||
|
elif file_size >= 1024:
|
||||||
|
file_size = '{}MB'.format(file_size // 1024)
|
||||||
|
else:
|
||||||
|
file_size = '{}KB'.format(file_size)
|
||||||
|
file_data = '{} {}'.format(file_size, file_name)
|
||||||
|
self.file_name.setText(file_data)
|
||||||
|
self.file_name.setToolTip(file_name)
|
||||||
|
self.saved_name = file_name
|
||||||
|
self.time_left = QtWidgets.QLabel(self)
|
||||||
|
self.time_left.setGeometry(QtCore.QRect(width - 92, 7, 30, 20))
|
||||||
|
font.setPointSize(10)
|
||||||
|
self.time_left.setFont(font)
|
||||||
|
self.time_left.setVisible(state == TOX_FILE_TRANSFER_STATE['RUNNING'])
|
||||||
|
self.setFocusPolicy(QtCore.Qt.NoFocus)
|
||||||
|
self.paused = False
|
||||||
|
|
||||||
|
def cancel_transfer(self, friend_number, file_number):
|
||||||
|
pr = profile.Profile.get_instance()
|
||||||
|
pr.cancel_transfer(friend_number, file_number)
|
||||||
|
self.setStyleSheet('QListWidget { border: 1px solid #B40404; }')
|
||||||
|
self.cancel.setVisible(False)
|
||||||
|
self.accept_or_pause.setVisible(False)
|
||||||
|
self.pb.setVisible(False)
|
||||||
|
|
||||||
|
def accept_or_pause_transfer(self, friend_number, file_number, size):
|
||||||
|
if self.state == TOX_FILE_TRANSFER_STATE['INCOMING_NOT_STARTED']:
|
||||||
|
directory = QtWidgets.QFileDialog.getExistingDirectory(self,
|
||||||
|
QtWidgets.QApplication.translate("MainWindow", 'Choose folder'),
|
||||||
|
curr_directory(),
|
||||||
|
QtWidgets.QFileDialog.ShowDirsOnly | QtWidgets.QFileDialog.DontUseNativeDialog)
|
||||||
|
self.pb.setVisible(True)
|
||||||
|
if directory:
|
||||||
|
pr = profile.Profile.get_instance()
|
||||||
|
pr.accept_transfer(self, directory + '/' + self.saved_name, friend_number, file_number, size)
|
||||||
|
self.button_update('pause')
|
||||||
|
elif self.state == TOX_FILE_TRANSFER_STATE['PAUSED_BY_USER']: # resume
|
||||||
|
self.paused = False
|
||||||
|
profile.Profile.get_instance().resume_transfer(friend_number, file_number)
|
||||||
|
self.button_update('pause')
|
||||||
|
self.state = TOX_FILE_TRANSFER_STATE['RUNNING']
|
||||||
|
else: # pause
|
||||||
|
self.paused = True
|
||||||
|
self.state = TOX_FILE_TRANSFER_STATE['PAUSED_BY_USER']
|
||||||
|
profile.Profile.get_instance().pause_transfer(friend_number, file_number)
|
||||||
|
self.button_update('resume')
|
||||||
|
self.accept_or_pause.clearFocus()
|
||||||
|
|
||||||
|
def button_update(self, path):
|
||||||
|
pixmap = QtGui.QPixmap(curr_directory() + '/images/{}.png'.format(path))
|
||||||
|
icon = QtGui.QIcon(pixmap)
|
||||||
|
self.accept_or_pause.setIcon(icon)
|
||||||
|
self.accept_or_pause.setIconSize(QtCore.QSize(30, 30))
|
||||||
|
|
||||||
|
def update_transfer_state(self, state, progress, time):
|
||||||
|
self.pb.setValue(int(progress * 100))
|
||||||
|
if time + 1:
|
||||||
|
m, s = divmod(time, 60)
|
||||||
|
self.time_left.setText('{0:02d}:{1:02d}'.format(m, s))
|
||||||
|
if self.state != state and self.state in ACTIVE_FILE_TRANSFERS:
|
||||||
|
if state == TOX_FILE_TRANSFER_STATE['CANCELLED']:
|
||||||
|
self.setStyleSheet('QListWidget { border: 1px solid #B40404; }')
|
||||||
|
self.cancel.setVisible(False)
|
||||||
|
self.accept_or_pause.setVisible(False)
|
||||||
|
self.pb.setVisible(False)
|
||||||
|
self.state = state
|
||||||
|
self.time_left.setVisible(False)
|
||||||
|
elif state == TOX_FILE_TRANSFER_STATE['FINISHED']:
|
||||||
|
self.accept_or_pause.setVisible(False)
|
||||||
|
self.pb.setVisible(False)
|
||||||
|
self.cancel.setVisible(False)
|
||||||
|
self.setStyleSheet('QListWidget { border: 1px solid green; }')
|
||||||
|
self.state = state
|
||||||
|
self.time_left.setVisible(False)
|
||||||
|
elif state == TOX_FILE_TRANSFER_STATE['PAUSED_BY_FRIEND']:
|
||||||
|
self.accept_or_pause.setVisible(False)
|
||||||
|
self.setStyleSheet('QListWidget { border: 1px solid #FF8000; }')
|
||||||
|
self.state = state
|
||||||
|
self.time_left.setVisible(False)
|
||||||
|
elif state == TOX_FILE_TRANSFER_STATE['PAUSED_BY_USER']:
|
||||||
|
self.button_update('resume') # setup button continue
|
||||||
|
self.setStyleSheet('QListWidget { border: 1px solid green; }')
|
||||||
|
self.state = state
|
||||||
|
self.time_left.setVisible(False)
|
||||||
|
elif state == TOX_FILE_TRANSFER_STATE['OUTGOING_NOT_STARTED']:
|
||||||
|
self.setStyleSheet('QListWidget { border: 1px solid #FF8000; }')
|
||||||
|
self.accept_or_pause.setVisible(False)
|
||||||
|
self.time_left.setVisible(False)
|
||||||
|
self.pb.setVisible(False)
|
||||||
|
elif not self.paused: # active
|
||||||
|
self.pb.setVisible(True)
|
||||||
|
self.accept_or_pause.setVisible(True) # setup to pause
|
||||||
|
self.button_update('pause')
|
||||||
|
self.setStyleSheet('QListWidget { border: 1px solid green; }')
|
||||||
|
self.state = state
|
||||||
|
self.time_left.setVisible(True)
|
||||||
|
|
||||||
|
def mark_as_sent(self):
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
|
class UnsentFileItem(FileTransferItem):
|
||||||
|
|
||||||
|
def __init__(self, file_name, size, user, time, width, parent=None):
|
||||||
|
super(UnsentFileItem, self).__init__(file_name, size, time, user, -1, -1,
|
||||||
|
TOX_FILE_TRANSFER_STATE['PAUSED_BY_FRIEND'], width, parent)
|
||||||
|
self._time = time
|
||||||
|
self.pb.setVisible(False)
|
||||||
|
movie = QtGui.QMovie(join_path(get_images_directory(), 'spinner.gif'))
|
||||||
|
self.time.setMovie(movie)
|
||||||
|
movie.start()
|
||||||
|
|
||||||
|
def cancel_transfer(self, *args):
|
||||||
|
pr = profile.Profile.get_instance()
|
||||||
|
pr.cancel_not_started_transfer(self._time)
|
||||||
|
|
||||||
|
|
||||||
|
class InlineImageItem(QtWidgets.QScrollArea):
|
||||||
|
|
||||||
|
def __init__(self, data, width, elem):
|
||||||
|
|
||||||
|
QtWidgets.QScrollArea.__init__(self)
|
||||||
|
self.setFocusPolicy(QtCore.Qt.NoFocus)
|
||||||
|
self._elem = elem
|
||||||
|
self._image_label = QtWidgets.QLabel(self)
|
||||||
|
self._image_label.raise_()
|
||||||
|
self.setWidget(self._image_label)
|
||||||
|
self._image_label.setScaledContents(False)
|
||||||
|
self._pixmap = QtGui.QPixmap()
|
||||||
|
self._pixmap.loadFromData(data, 'PNG')
|
||||||
|
self._max_size = width - 30
|
||||||
|
self._resize_needed = not (self._pixmap.width() <= self._max_size)
|
||||||
|
self._full_size = not self._resize_needed
|
||||||
|
if not self._resize_needed:
|
||||||
|
self._image_label.setPixmap(self._pixmap)
|
||||||
|
self.resize(QtCore.QSize(self._max_size + 5, self._pixmap.height() + 5))
|
||||||
|
self._image_label.setGeometry(5, 0, self._pixmap.width(), self._pixmap.height())
|
||||||
|
else:
|
||||||
|
pixmap = self._pixmap.scaled(self._max_size, self._max_size, QtCore.Qt.KeepAspectRatio)
|
||||||
|
self._image_label.setPixmap(pixmap)
|
||||||
|
self.resize(QtCore.QSize(self._max_size + 5, pixmap.height()))
|
||||||
|
self._image_label.setGeometry(5, 0, self._max_size + 5, pixmap.height())
|
||||||
|
self._elem.setSizeHint(QtCore.QSize(self.width(), self.height()))
|
||||||
|
|
||||||
|
def mouseReleaseEvent(self, event):
|
||||||
|
if event.button() == QtCore.Qt.LeftButton and self._resize_needed: # scale inline
|
||||||
|
if self._full_size:
|
||||||
|
pixmap = self._pixmap.scaled(self._max_size, self._max_size, QtCore.Qt.KeepAspectRatio)
|
||||||
|
self._image_label.setPixmap(pixmap)
|
||||||
|
self.resize(QtCore.QSize(self._max_size, pixmap.height()))
|
||||||
|
self._image_label.setGeometry(5, 0, pixmap.width(), pixmap.height())
|
||||||
|
else:
|
||||||
|
self._image_label.setPixmap(self._pixmap)
|
||||||
|
self.resize(QtCore.QSize(self._max_size, self._pixmap.height() + 17))
|
||||||
|
self._image_label.setGeometry(5, 0, self._pixmap.width(), self._pixmap.height())
|
||||||
|
self._full_size = not self._full_size
|
||||||
|
self._elem.setSizeHint(QtCore.QSize(self.width(), self.height()))
|
||||||
|
elif event.button() == QtCore.Qt.RightButton: # save inline
|
||||||
|
# TODO: dialog
|
||||||
|
directory = QtWidgets.QFileDialog.getExistingDirectory(self,
|
||||||
|
QtWidgets.QApplication.translate("MainWindow",
|
||||||
|
'Choose folder'),
|
||||||
|
curr_directory(),
|
||||||
|
QtWidgets.QFileDialog.ShowDirsOnly | QtWidgets.QFileDialog.DontUseNativeDialog)
|
||||||
|
if directory:
|
||||||
|
fl = QtCore.QFile(directory + '/toxygen_inline_' + curr_time().replace(':', '_') + '.png')
|
||||||
|
self._pixmap.save(fl, 'PNG')
|
||||||
|
|
||||||
|
def mark_as_sent(self):
|
||||||
|
return False
|
||||||
|
|
Loading…
Reference in a new issue