avatars support

This commit is contained in:
ingvar1995 2016-03-18 16:20:07 +03:00
parent 6d56b2aa5b
commit 9d5353640b
3 changed files with 66 additions and 28 deletions

View File

@ -74,6 +74,8 @@ def friend_connection_status(tox, friend_num, new_status, user_data):
friend = profile.get_friend_by_number(friend_num) friend = profile.get_friend_by_number(friend_num)
if new_status == TOX_CONNECTION['NONE']: if new_status == TOX_CONNECTION['NONE']:
invoke_in_main_thread(friend.set_status, None) invoke_in_main_thread(friend.set_status, None)
elif friend.status is None:
invoke_in_main_thread(profile.send_avatar, friend_num)
invoke_in_main_thread(profile.update_filtration) invoke_in_main_thread(profile.update_filtration)

View File

@ -1,8 +1,11 @@
# TODO: add support of file transfers # TODO: add support of file transfers
# TODO: add support of avatars # TODO: add support of avatars
from toxcore_enums_and_consts import TOX_FILE_KIND from toxcore_enums_and_consts import TOX_FILE_KIND, TOX_FILE_CONTROL
from os.path import basename, getsize from os.path import basename, getsize, exists
from os import remove
from time import time from time import time
from tox import Tox
import profile
TOX_FILE_TRANSFER_STATE = { TOX_FILE_TRANSFER_STATE = {
@ -44,10 +47,15 @@ class FileTransfer(object):
class SendTransfer(FileTransfer): class SendTransfer(FileTransfer):
def __init__(self, path, tox, friend_number): def __init__(self, path, tox, friend_number, kind=TOX_FILE_KIND['DATA'], file_id=None):
super(self.__class__, self).__init__(path, tox, friend_number) super(SendTransfer, self).__init__(path, tox, friend_number)
self._file_number = tox.file_send(friend_number, TOX_FILE_KIND['DATA'], getsize(path), None, basename(path)) self._file_number = tox.file_send(friend_number,
self._file = open(path, 'rb') kind,
getsize(path) if path else 0,
file_id,
basename(path) if path else '')
if path is not None:
self._file = open(path, 'rb')
def send_chunk(self, position, size): def send_chunk(self, position, size):
self._file.seek(position) self._file.seek(position)
@ -55,9 +63,19 @@ class SendTransfer(FileTransfer):
return self._tox.file_send_chunk(self._friend_number, self._file_number, position, data) return self._tox.file_send_chunk(self._friend_number, self._file_number, position, data)
class SendAvatar(SendTransfer):
def __init__(self, path, tox, friend_number):
if path is None:
super(SendAvatar, self).__init__(path, tox, friend_number, TOX_FILE_KIND['AVATAR'])
else:
with open(path, 'rb') as fl:
hash = Tox.hash(fl.read())
super(self.__class__, self).__init__(path, tox, friend_number, TOX_FILE_KIND['AVATAR'], hash)
class ReceiveTransfer(FileTransfer): class ReceiveTransfer(FileTransfer):
def __init__(self, path, tox, friend_number, file_number): def __init__(self, path, tox, friend_number, file_number):
super(self.__class__, self).__init__(path, tox, friend_number, file_number) super(ReceiveTransfer, self).__init__(path, tox, friend_number, file_number)
self._file = open(self._path, 'wb') self._file = open(self._path, 'wb')
self._file.truncate(0) self._file.truncate(0)
self._size = 0 self._size = 0
@ -75,3 +93,26 @@ class ReceiveTransfer(FileTransfer):
self._size = position + len(data) self._size = position + len(data)
else: else:
self._file.close() self._file.close()
self.state = TOX_FILE_TRANSFER_STATE['FINISHED']
class ReceiveAvatar(ReceiveTransfer):
def __init__(self, tox, friend_number, file_number, has_size=True):
path = profile.ProfileHelper.get_path() + '/avatars/{}.png'.format(tox.friend_get_public_key(friend_number))
super(ReceiveAvatar, self).__init__(path, tox, friend_number, file_number)
if exists(path):
if not has_size:
remove(path)
self.send_control(TOX_FILE_CONTROL['CANCEL'])
self.state = TOX_FILE_TRANSFER_STATE['CANCELED']
else:
hash = self.get_file_id()
with open(path, 'rb') as fl:
existing_hash = Tox.hash(fl.read())
if hash == existing_hash:
self.send_control(TOX_FILE_CONTROL['CANCEL'])
self.state = TOX_FILE_TRANSFER_STATE['CANCELED']
else:
self.send_control(TOX_FILE_CONTROL['RESUME'])
else:
self.send_control(TOX_FILE_CONTROL['RESUME'])

View File

@ -148,7 +148,7 @@ class Contact(object):
""" """
Tries to load avatar of contact or uses default avatar Tries to load avatar of contact or uses default avatar
""" """
avatar_path = (Settings.get_default_path() + 'avatars/{}.png').format(self._tox_id[:TOX_PUBLIC_KEY_SIZE * 2]) avatar_path = (ProfileHelper.get_path() + 'avatars/{}.png').format(self._tox_id[:TOX_PUBLIC_KEY_SIZE * 2])
if not os.path.isfile(avatar_path): # load default image if not os.path.isfile(avatar_path): # load default image
avatar_path = curr_directory() + '/images/avatar.png' avatar_path = curr_directory() + '/images/avatar.png'
pixmap = QtGui.QPixmap(QtCore.QSize(64, 64)) pixmap = QtGui.QPixmap(QtCore.QSize(64, 64))
@ -157,19 +157,19 @@ class Contact(object):
self._widget.avatar_label.repaint() self._widget.avatar_label.repaint()
def reset_avatar(self): def reset_avatar(self):
avatar_path = (Settings.get_default_path() + 'avatars/{}.png').format(self._tox_id[:TOX_PUBLIC_KEY_SIZE * 2]) avatar_path = (ProfileHelper.get_path() + 'avatars/{}.png').format(self._tox_id[:TOX_PUBLIC_KEY_SIZE * 2])
if os.path.isfile(avatar_path): if os.path.isfile(avatar_path):
os.remove(avatar_path) os.remove(avatar_path)
self.load_avatar() self.load_avatar()
def set_avatar(self, avatar): def set_avatar(self, avatar):
avatar_path = (Settings.get_default_path() + 'avatars/{}.png').format(self._tox_id[:TOX_PUBLIC_KEY_SIZE * 2]) avatar_path = (ProfileHelper.get_path() + 'avatars/{}.png').format(self._tox_id[:TOX_PUBLIC_KEY_SIZE * 2])
with open(avatar_path, 'wb') as f: with open(avatar_path, 'wb') as f:
f.write(avatar) f.write(avatar)
self.load_avatar() self.load_avatar()
def get_avatar_hash(self): def get_avatar_hash(self):
avatar_path = (Settings.get_default_path() + 'avatars/{}.png').format(self._tox_id[:TOX_PUBLIC_KEY_SIZE * 2]) avatar_path = (ProfileHelper.get_path() + 'avatars/{}.png').format(self._tox_id[:TOX_PUBLIC_KEY_SIZE * 2])
if not os.path.isfile(avatar_path): # load default image if not os.path.isfile(avatar_path): # load default image
return 0 return 0
with open(avatar_path, 'rb') as fl: with open(avatar_path, 'rb') as fl:
@ -715,31 +715,26 @@ class Profile(Contact, Singleton):
:param file_number: file number :param file_number: file number
:param size: size of avatar or 0 (default avatar) :param size: size of avatar or 0 (default avatar)
""" """
friend = self.get_friend_by_number(friend_number) ra = ReceiveAvatar(self._tox, friend_number, file_number, size)
if not size: if ra.state != TOX_FILE_TRANSFER_STATE['CANCELED']:
friend.reset_avatar() self._file_transfers[(friend_number, file_number)] = ra
self._tox.file_control(friend_number, file_number, TOX_FILE_CONTROL['CANCEL'])
else: else:
hash = friend.get_avatar_hash() self.get_friend_by_number(friend_number).load_avatar()
new_avatar_hash = self._tox.file_get_file_id(friend_number, file_number)
if hash == new_avatar_hash: # avatar is the same
self._tox.file_control(friend_number, file_number, TOX_FILE_CONTROL['CANCEL']) # ignore file
else: # get new avatar
path = ProfileHelper.get_path() + '/avatars/{}.png'.format(friend.tox_id)
rt = ReceiveTransfer(path, self._tox, friend_number, file_number)
self._file_transfers[(friend_number, file_number)] = rt
self._tox.file_control(friend_number, file_number, TOX_FILE_CONTROL['RESUME'])
def incoming_chunk(self, friend_number, file_number, position, data): def incoming_chunk(self, friend_number, file_number, position, data):
transfer = self._file_transfers[(friend_number, file_number)] transfer = self._file_transfers[(friend_number, file_number)]
transfer.write_chunk(position, data) transfer.write_chunk(position, data)
if data is None: if transfer.state:
if type(transfer) is ReceiveAvatar:
self.get_friend_by_number(friend_number).load_avatar()
del self._file_transfers[(friend_number, file_number)] del self._file_transfers[(friend_number, file_number)]
friend = self.get_friend_by_number(friend_number)
friend.load_avatar()
def send_avatar(self, friend_number): def send_avatar(self, friend_number):
pass avatar_path = (ProfileHelper.get_path() + 'avatars/{}.png').format(self._tox_id[:TOX_PUBLIC_KEY_SIZE * 2])
if not os.path.isfile(avatar_path): # reset image
avatar_path = None
sa = SendAvatar(avatar_path, self._tox, friend_number)
self._file_transfers[(friend_number, sa.get_file_number())] = sa
def send_file(self, path): def send_file(self, path):
friend_number = self.get_active_number() friend_number = self.get_active_number()