various fixes. profile settings and add account fixes

This commit is contained in:
ingvar1995 2018-05-10 23:54:51 +03:00
parent 729bd84d2b
commit 25dbb85ef0
8 changed files with 109 additions and 92 deletions

View File

@ -2,7 +2,6 @@ from middleware import threads
import middleware.callbacks as callbacks import middleware.callbacks as callbacks
from PyQt5 import QtWidgets, QtGui, QtCore from PyQt5 import QtWidgets, QtGui, QtCore
import ui.password_screen as password_screen import ui.password_screen as password_screen
from utils.util import *
import updater.updater as updater import updater.updater as updater
import os import os
from middleware.tox_factory import tox_factory from middleware.tox_factory import tox_factory
@ -53,48 +52,20 @@ class App:
self._app = QtWidgets.QApplication([]) self._app = QtWidgets.QApplication([])
self._load_icon() self._load_icon()
if get_platform() == 'Linux': if util.get_platform() == 'Linux':
QtCore.QCoreApplication.setAttribute(QtCore.Qt.AA_X11InitThreads) QtCore.QCoreApplication.setAttribute(QtCore.Qt.AA_X11InitThreads)
self._load_base_style() self._load_base_style()
encrypt_save = tox_encrypt_save.ToxEncryptSave() if not self._select_and_load_profile():
self._toxes = user_data.toxes.ToxES(encrypt_save) return
if self._path is not None: # toxygen was started with path to profile
self._load_existing_profile(self._path)
else:
auto_profile = Settings.get_auto_profile()
if auto_profile is None: # no default profile
result = self._select_profile()
if result is None:
return
if result.is_new_profile(): # create new profile
self._create_new_profile(result.profile_path)
else: # load existing profile
self._load_existing_profile(result.profile_path)
self._path = result.profile_path
else: # default profile
path, name = auto_profile
self._path = os.path.join(path, name + '.tox')
self._load_existing_profile(self._path)
if Settings.is_active_profile(self._path): # profile is in use
profile_name = get_profile_name_from_path(self._path)
title = util_ui.tr('Profile {}').format(profile_name)
text = util_ui.tr('Other instance of Toxygen uses this profile or profile was not properly closed. Continue?')
reply = util_ui.question(text, title)
if not reply:
return
self._settings.set_active_profile()
self._load_app_styles()
self._load_app_translations()
if self._try_to_update(): if self._try_to_update():
return return
self._load_app_styles()
self._load_app_translations()
self._create_dependencies() self._create_dependencies()
self._start_threads() self._start_threads()
@ -133,7 +104,7 @@ class App:
# ----------------------------------------------------------------------------------------------------------------- # -----------------------------------------------------------------------------------------------------------------
def _load_base_style(self): def _load_base_style(self):
with open(join_path(get_styles_directory(), 'dark_style.qss')) as fl: with open(util.join_path(util.get_styles_directory(), 'dark_style.qss')) as fl:
style = fl.read() style = fl.read()
self._app.setStyleSheet(style) self._app.setStyleSheet(style)
@ -143,7 +114,7 @@ class App:
return return
for theme in self._settings.built_in_themes().keys(): for theme in self._settings.built_in_themes().keys():
if self._settings['theme'] == theme: if self._settings['theme'] == theme:
with open(curr_directory(__file__) + self._settings.built_in_themes()[theme]) as fl: with open(util.curr_directory(__file__) + self._settings.built_in_themes()[theme]) as fl:
style = fl.read() style = fl.read()
self._app.setStyleSheet(style) self._app.setStyleSheet(style)
@ -152,12 +123,12 @@ class App:
if current_language in supported_languages: if current_language in supported_languages:
lang_path = supported_languages[current_language] lang_path = supported_languages[current_language]
translator = QtCore.QTranslator() translator = QtCore.QTranslator()
translator.load(get_translations_directory() + lang_path) translator.load(util.get_translations_directory() + lang_path)
self._app.installTranslator(translator) self._app.installTranslator(translator)
self._app.translator = translator self._app.translator = translator
def _load_icon(self): def _load_icon(self):
icon_file = os.path.join(get_images_directory(), 'icon.png') icon_file = os.path.join(util.get_images_directory(), 'icon.png')
self._app.setWindowIcon(QtGui.QIcon(icon_file)) self._app.setWindowIcon(QtGui.QIcon(icon_file))
@staticmethod @staticmethod
@ -171,10 +142,44 @@ class App:
def _load_app_translations(self): def _load_app_translations(self):
lang = Settings.supported_languages()[self._settings['language']] lang = Settings.supported_languages()[self._settings['language']]
translator = QtCore.QTranslator() translator = QtCore.QTranslator()
translator.load(os.path.join(get_translations_directory(), lang)) translator.load(os.path.join(util.get_translations_directory(), lang))
self._app.installTranslator(translator) self._app.installTranslator(translator)
self._app.translator = translator self._app.translator = translator
def _select_and_load_profile(self):
encrypt_save = tox_encrypt_save.ToxEncryptSave()
self._toxes = user_data.toxes.ToxES(encrypt_save)
if self._path is not None: # toxygen was started with path to profile
self._load_existing_profile(self._path)
else:
auto_profile = Settings.get_auto_profile()
if auto_profile is None: # no default profile
result = self._select_profile()
if result is None:
return False
if result.is_new_profile(): # create new profile
self._create_new_profile(result.profile_path)
else: # load existing profile
self._load_existing_profile(result.profile_path)
self._path = result.profile_path
else: # default profile
self._path = auto_profile
self._load_existing_profile(auto_profile)
if Settings.is_active_profile(self._path): # profile is in use
profile_name = util.get_profile_name_from_path(self._path)
title = util_ui.tr('Profile {}').format(profile_name)
text = util_ui.tr(
'Other instance of Toxygen uses this profile or profile was not properly closed. Continue?')
reply = util_ui.question(text, title)
if not reply:
return False
self._settings.set_active_profile()
return True
# ----------------------------------------------------------------------------------------------------------------- # -----------------------------------------------------------------------------------------------------------------
# Threads # Threads
# ----------------------------------------------------------------------------------------------------------------- # -----------------------------------------------------------------------------------------------------------------
@ -223,7 +228,7 @@ class App:
self._tox = self._create_tox(data) self._tox = self._create_tox(data)
def _create_new_profile(self, profile_path): def _create_new_profile(self, profile_path):
name = get_profile_name_from_path(profile_path) or 'toxygen_user' name = util.get_profile_name_from_path(profile_path) or 'toxygen_user'
if os.path.isfile(profile_path): if os.path.isfile(profile_path):
util_ui.message_box(util_ui.tr('Profile with this name already exists'), util_ui.message_box(util_ui.tr('Profile with this name already exists'),
util_ui.tr('Error')) util_ui.tr('Error'))

View File

@ -135,16 +135,16 @@ class BaseContact:
return self._widget.avatar_label.pixmap() return self._widget.avatar_label.pixmap()
def get_avatar_path(self): def get_avatar_path(self):
directory = util.join_path(self._profile_manager.get_dir(), 'avatars') avatar_path = self.get_contact_avatar_path()
avatar_path = util.join_path(directory, '{}.png'.format(self._tox_id[:TOX_PUBLIC_KEY_SIZE * 2]))
if not os.path.isfile(avatar_path) or not os.path.getsize(avatar_path): # load default image if not os.path.isfile(avatar_path) or not os.path.getsize(avatar_path): # load default image
avatar_path = util.join_path(util.get_images_directory(), self.get_default_avatar_name()) avatar_path = util.join_path(util.get_images_directory(), self._get_default_avatar_name())
return avatar_path return avatar_path
@staticmethod def get_contact_avatar_path(self):
def get_default_avatar_name(): directory = util.join_path(self._profile_manager.get_dir(), 'avatars')
return 'avatar.png'
return util.join_path(directory, '{}.png'.format(self._tox_id[:TOX_PUBLIC_KEY_SIZE * 2]))
def get_avatar_changed_event(self): def get_avatar_changed_event(self):
return self._avatar_changed_event return self._avatar_changed_event
@ -160,3 +160,11 @@ class BaseContact:
self._widget.status_message.setText(self._status_message) self._widget.status_message.setText(self._status_message)
self._widget.connection_status.update(self._status) self._widget.connection_status.update(self._status)
self.load_avatar() self.load_avatar()
# -----------------------------------------------------------------------------------------------------------------
# Private methods
# -----------------------------------------------------------------------------------------------------------------
@staticmethod
def _get_default_avatar_name():
return 'avatar.png'

View File

@ -3,7 +3,6 @@ from os.path import basename, getsize, exists, dirname
from os import remove, rename, chdir from os import remove, rename, chdir
from time import time, sleep from time import time, sleep
from wrapper.tox import Tox from wrapper.tox import Tox
from user_data import settings
from PyQt5 import QtCore from PyQt5 import QtCore
@ -48,7 +47,7 @@ class FileTransfer(QtCore.QObject):
""" """
def __init__(self, path, tox, friend_number, size, file_number=None): def __init__(self, path, tox, friend_number, size, file_number=None):
super().__init__(self) QtCore.QObject.__init__(self)
self._path = path self._path = path
self._tox = tox self._tox = tox
self._friend_number = friend_number self._friend_number = friend_number
@ -305,20 +304,20 @@ class ReceiveAvatar(ReceiveTransfer):
""" """
MAX_AVATAR_SIZE = 512 * 1024 MAX_AVATAR_SIZE = 512 * 1024
def __init__(self, tox, friend_number, size, file_number): def __init__(self, path, tox, friend_number, size, file_number):
path = settings.ProfileManager.get_path() + 'avatars/{}.png'.format(tox.friend_get_public_key(friend_number)) full_path = path + '.tmp'
super().__init__(path + '.tmp', tox, friend_number, size, file_number) super().__init__(full_path, tox, friend_number, size, file_number)
if size > self.MAX_AVATAR_SIZE: if size > self.MAX_AVATAR_SIZE:
self.send_control(TOX_FILE_CONTROL['CANCEL']) self.send_control(TOX_FILE_CONTROL['CANCEL'])
self._file.close() self._file.close()
remove(path + '.tmp') remove(full_path)
elif not size: elif not size:
self.send_control(TOX_FILE_CONTROL['CANCEL']) self.send_control(TOX_FILE_CONTROL['CANCEL'])
self._file.close() self._file.close()
if exists(path): if exists(path):
remove(path) remove(path)
self._file.close() self._file.close()
remove(path + '.tmp') remove(full_path)
elif exists(path): elif exists(path):
hash = self.get_file_id() hash = self.get_file_id()
with open(path, 'rb') as fl: with open(path, 'rb') as fl:
@ -327,7 +326,7 @@ class ReceiveAvatar(ReceiveTransfer):
if hash == existing_hash: if hash == existing_hash:
self.send_control(TOX_FILE_CONTROL['CANCEL']) self.send_control(TOX_FILE_CONTROL['CANCEL'])
self._file.close() self._file.close()
remove(path + '.tmp') remove(full_path)
else: else:
self.send_control(TOX_FILE_CONTROL['RESUME']) self.send_control(TOX_FILE_CONTROL['RESUME'])
else: else:

View File

@ -309,8 +309,6 @@ class FileTransfersHandler:
elif data[1] == friend_number and not data[2]: elif data[1] == friend_number and not data[2]:
self.send_file(data[0], friend_number, True, key) self.send_file(data[0], friend_number, True, key)
del self._paused_file_transfers[key] del self._paused_file_transfers[key]
if friend_number == self.get_active_number() and self.is_active_a_friend():
self.update()
except Exception as ex: except Exception as ex:
print('Exception in file sending: ' + str(ex)) print('Exception in file sending: ' + str(ex))
@ -333,14 +331,13 @@ class FileTransfersHandler:
: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)
""" """
ra = ReceiveAvatar(self._tox, friend_number, size, file_number) friend = self._get_friend_by_number(friend_number)
ra = ReceiveAvatar(friend.get_contact_avatar_path(), self._tox, friend_number, size, file_number)
if ra.state != TOX_FILE_TRANSFER_STATE['CANCELLED']: if ra.state != TOX_FILE_TRANSFER_STATE['CANCELLED']:
self._file_transfers[(friend_number, file_number)] = ra self._file_transfers[(friend_number, file_number)] = ra
ra.set_transfer_finished_handler(self.transfer_finished) ra.set_transfer_finished_handler(self.transfer_finished)
else: else:
self._get_friend_by_number(friend_number).load_avatar() friend.load_avatar()
if self.get_active_number() == friend_number and self.is_active_a_friend():
self.set_active(None)
# ----------------------------------------------------------------------------------------------------------------- # -----------------------------------------------------------------------------------------------------------------
# Private methods # Private methods

View File

@ -97,7 +97,7 @@ class MainWindow(QtWidgets.QMainWindow):
self.actionAbout_program.triggered.connect(self.about_program) self.actionAbout_program.triggered.connect(self.about_program)
self.actionNetwork.triggered.connect(self.network_settings) self.actionNetwork.triggered.connect(self.network_settings)
self.actionAdd_friend.triggered.connect(self.add_contact) self.actionAdd_friend.triggered.connect(self.add_contact_triggered)
self.actionAdd_gc.triggered.connect(self.create_gc) self.actionAdd_gc.triggered.connect(self.create_gc)
self.actionSettings.triggered.connect(self.profile_settings) self.actionSettings.triggered.connect(self.profile_settings)
self.actionPrivacy_settings.triggered.connect(self.privacy_settings) self.actionPrivacy_settings.triggered.connect(self.privacy_settings)
@ -437,6 +437,9 @@ class MainWindow(QtWidgets.QMainWindow):
self._modal_window = self._widget_factory.create_plugins_settings_window() self._modal_window = self._widget_factory.create_plugins_settings_window()
self._modal_window.show() self._modal_window.show()
def add_contact_triggered(self, _):
self.add_contact()
def add_contact(self, link=''): def add_contact(self, link=''):
self._modal_window = self._widget_factory.create_add_contact_window(link) self._modal_window = self._widget_factory.create_add_contact_window(link)
self._modal_window.show() self._modal_window.show()
@ -444,7 +447,7 @@ class MainWindow(QtWidgets.QMainWindow):
def create_gc(self): def create_gc(self):
self.profile.create_group_chat() self.profile.create_group_chat()
def profile_settings(self, *args): def profile_settings(self, _):
self._modal_window = self._widget_factory.create_profile_settings_window() self._modal_window = self._widget_factory.create_profile_settings_window()
self._modal_window.show() self._modal_window.show()

View File

@ -4,7 +4,6 @@ from contacts.profile import Profile
from utils.util import * from utils.util import *
from ui.widgets import CenteredWidget, DataLabel, LineEdit, RubberBandWindow from ui.widgets import CenteredWidget, DataLabel, LineEdit, RubberBandWindow
import pyaudio import pyaudio
from user_data import toxes
import updater.updater as updater import updater.updater as updater
import utils.ui as util_ui import utils.ui as util_ui
@ -90,6 +89,7 @@ class ProfileSettings(CenteredWidget):
self._profile_manager = profile_manager self._profile_manager = profile_manager
self._settings = settings self._settings = settings
self._toxes = toxes self._toxes = toxes
self._auto = False
self.initUI() self.initUI()
self.center() self.center()
@ -166,8 +166,7 @@ class ProfileSettings(CenteredWidget):
self.warning.setStyleSheet('QLabel { color: #BC1C1C; }') self.warning.setStyleSheet('QLabel { color: #BC1C1C; }')
self.default = QtWidgets.QPushButton(self) self.default = QtWidgets.QPushButton(self)
self.default.setGeometry(QtCore.QRect(40, 550, 620, 30)) self.default.setGeometry(QtCore.QRect(40, 550, 620, 30))
auto_profile = Settings.get_auto_profile() self._auto = Settings.get_auto_profile() == self._profile_manager.get_path()
# self.auto = path + name == ProfileManager.get_path() + Settings.get_instance().name
self.default.clicked.connect(self.auto_profile) self.default.clicked.connect(self.auto_profile)
self.retranslateUi() self.retranslateUi()
if self._profile.status is not None: if self._profile.status is not None:
@ -197,23 +196,23 @@ class ProfileSettings(CenteredWidget):
self.status.addItem(util_ui.tr("Away")) self.status.addItem(util_ui.tr("Away"))
self.status.addItem(util_ui.tr("Busy")) self.status.addItem(util_ui.tr("Busy"))
self.copy_pk.setText(util_ui.tr("Copy public key")) self.copy_pk.setText(util_ui.tr("Copy public key"))
if self.auto:
self.set_default_profile_button_text()
def auto_profile(self):
if self._auto:
Settings.reset_auto_profile()
else:
Settings.set_auto_profile(self._profile_manager.get_path())
self._auto = not self._auto
self.set_default_profile_button_text()
def set_default_profile_button_text(self):
if self._auto:
self.default.setText(util_ui.tr("Mark as not default profile")) self.default.setText(util_ui.tr("Mark as not default profile"))
else: else:
self.default.setText(util_ui.tr("Mark as default profile")) self.default.setText(util_ui.tr("Mark as default profile"))
def auto_profile(self):
if self.auto:
Settings.reset_auto_profile()
else:
Settings.set_auto_profile(ProfileManager.get_path(), Settings.get_instance().name)
self.auto = not self.auto
if self.auto:
self.default.setText(util_ui.tr("Mark as not default profile"))
else:
self.default.setText(
util_ui.tr("Mark as default profile"))
def new_password(self): def new_password(self):
if self.password.text() == self.confirm_password.text(): if self.password.text() == self.confirm_password.text():
if not len(self.password.text()) or len(self.password.text()) >= 8: if not len(self.password.text()) or len(self.password.text()) >= 8:
@ -230,7 +229,7 @@ class ProfileSettings(CenteredWidget):
def copy(self): def copy(self):
clipboard = QtWidgets.QApplication.clipboard() clipboard = QtWidgets.QApplication.clipboard()
clipboard.setText(self._profile.tox_id) clipboard.setText(self._profile.tox_id)
pixmap = QtGui.QPixmap(curr_directory() + '/images/accept.png') pixmap = QtGui.QPixmap(join_path(get_images_directory(), 'accept.png'))
icon = QtGui.QIcon(pixmap) icon = QtGui.QIcon(pixmap)
self.copyId.setIcon(icon) self.copyId.setIcon(icon)
self.copyId.setIconSize(QtCore.QSize(10, 10)) self.copyId.setIconSize(QtCore.QSize(10, 10))
@ -238,7 +237,7 @@ class ProfileSettings(CenteredWidget):
def copy_public_key(self): def copy_public_key(self):
clipboard = QtWidgets.QApplication.clipboard() clipboard = QtWidgets.QApplication.clipboard()
clipboard.setText(self._profile.tox_id[:64]) clipboard.setText(self._profile.tox_id[:64])
pixmap = QtGui.QPixmap(curr_directory() + '/images/accept.png') pixmap = QtGui.QPixmap(join_path(get_images_directory(), 'accept.png'))
icon = QtGui.QIcon(pixmap) icon = QtGui.QIcon(pixmap)
self.copy_pk.setIcon(icon) self.copy_pk.setIcon(icon)
self.copy_pk.setIconSize(QtCore.QSize(10, 10)) self.copy_pk.setIconSize(QtCore.QSize(10, 10))
@ -270,7 +269,7 @@ class ProfileSettings(CenteredWidget):
util_ui.tr('Use new path')) util_ui.tr('Use new path'))
self._settings.export(directory) self._settings.export(directory)
self._profile.export_db(directory) self._profile.export_db(directory)
ProfileManager.get_instance().export_profile(directory, reply) self._profile_manager.export_profile(directory, reply)
def closeEvent(self, event): def closeEvent(self, event):
self._profile.set_name(self.nick.text()) self._profile.set_name(self.nick.text())

View File

@ -28,6 +28,9 @@ class ProfileManager:
def get_dir(self): def get_dir(self):
return self._directory return self._directory
def get_path(self):
return self._path
def save_profile(self, data): def save_profile(self, data):
if self._toxes.has_password(): if self._toxes.has_password():
data = self._toxes.pass_encrypt(data) data = self._toxes.pass_encrypt(data)

View File

@ -1,5 +1,4 @@
import json import json
import os
from utils.util import * from utils.util import *
import pyaudio import pyaudio
import smileys.smileys as smileys import smileys.smileys as smileys
@ -52,16 +51,21 @@ class Settings(dict):
if os.path.isfile(p): if os.path.isfile(p):
with open(p) as fl: with open(p) as fl:
data = fl.read() data = fl.read()
auto = json.loads(data) try:
if 'path' in auto and 'name' in auto: auto = json.loads(data)
path = str(auto['path']) except Exception as ex:
name = str(auto['name']) log(str(ex))
if os.path.isfile(join_path(path, name + '.tox')): auto = {}
return path, name if 'profile_path' in auto:
path = str(auto['profile_path'])
if not os.path.isabs(path):
path = join_path(path, curr_directory(__file__))
if os.path.isfile(path):
return path
return None return None
@staticmethod @staticmethod
def set_auto_profile(path, name): def set_auto_profile(path):
p = Settings.get_global_settings_path() p = Settings.get_global_settings_path()
if os.path.isfile(p): if os.path.isfile(p):
with open(p) as fl: with open(p) as fl:
@ -69,8 +73,7 @@ class Settings(dict):
data = json.loads(data) data = json.loads(data)
else: else:
data = {} data = {}
data['path'] = str(path) data['profile_path'] = str(path)
data['name'] = str(name)
with open(p, 'w') as fl: with open(p, 'w') as fl:
fl.write(json.dumps(data)) fl.write(json.dumps(data))