diff --git a/toxygen/ui/menu.py b/toxygen/ui/menu.py index 45e8765..8aec578 100644 --- a/toxygen/ui/menu.py +++ b/toxygen/ui/menu.py @@ -52,203 +52,6 @@ class AddContact(CenteredWidget): self.toxIdLineEdit.setPlaceholderText(util_ui.tr('TOX ID or public key of contact')) -class ProfileSettings(CenteredWidget): - """Form with profile settings such as name, status, TOX ID""" - def __init__(self, profile, profile_manager, settings, toxes): - super().__init__() - self._profile = profile - self._profile_manager = profile_manager - self._settings = settings - self._toxes = toxes - self._auto = False - self.initUI() - self.center() - - def initUI(self): - self.setObjectName("ProfileSettingsForm") - self.setMinimumSize(QtCore.QSize(700, 600)) - self.setMaximumSize(QtCore.QSize(700, 600)) - self.nick = LineEdit(self) - self.nick.setGeometry(QtCore.QRect(30, 60, 350, 27)) - self.nick.setText(self._profile.name) - self.status = QtWidgets.QComboBox(self) - self.status.setGeometry(QtCore.QRect(400, 60, 200, 27)) - self.status_message = LineEdit(self) - self.status_message.setGeometry(QtCore.QRect(30, 130, 350, 27)) - self.status_message.setText(self._profile.status_message) - self.label = QtWidgets.QLabel(self) - self.label.setGeometry(QtCore.QRect(40, 30, 91, 25)) - font = QtGui.QFont() - font.setFamily(self._settings['font']) - font.setPointSize(18) - font.setWeight(75) - font.setBold(True) - self.label.setFont(font) - self.label_2 = QtWidgets.QLabel(self) - self.label_2.setGeometry(QtCore.QRect(40, 100, 100, 25)) - self.label_2.setFont(font) - self.label_3 = QtWidgets.QLabel(self) - self.label_3.setGeometry(QtCore.QRect(40, 180, 100, 25)) - self.label_3.setFont(font) - self.tox_id = QtWidgets.QLabel(self) - self.tox_id.setGeometry(QtCore.QRect(15, 210, 685, 21)) - font.setPointSize(10) - self.tox_id.setFont(font) - self.tox_id.setText(self._profile.tox_id) - self.copyId = QtWidgets.QPushButton(self) - self.copyId.setGeometry(QtCore.QRect(40, 250, 180, 30)) - self.copyId.clicked.connect(self.copy) - self.export = QtWidgets.QPushButton(self) - self.export.setGeometry(QtCore.QRect(230, 250, 180, 30)) - self.export.clicked.connect(self.export_profile) - self.new_nospam = QtWidgets.QPushButton(self) - self.new_nospam.setGeometry(QtCore.QRect(420, 250, 180, 30)) - self.new_nospam.clicked.connect(self.new_no_spam) - self.copy_pk = QtWidgets.QPushButton(self) - self.copy_pk.setGeometry(QtCore.QRect(40, 300, 180, 30)) - self.copy_pk.clicked.connect(self.copy_public_key) - self.new_avatar = QtWidgets.QPushButton(self) - self.new_avatar.setGeometry(QtCore.QRect(230, 300, 180, 30)) - self.delete_avatar = QtWidgets.QPushButton(self) - self.delete_avatar.setGeometry(QtCore.QRect(420, 300, 180, 30)) - self.delete_avatar.clicked.connect(self.reset_avatar) - self.new_avatar.clicked.connect(self.set_avatar) - self.profilepass = QtWidgets.QLabel(self) - self.profilepass.setGeometry(QtCore.QRect(40, 340, 300, 30)) - font.setPointSize(18) - self.profilepass.setFont(font) - self.password = LineEdit(self) - self.password.setGeometry(QtCore.QRect(40, 380, 300, 30)) - self.password.setEchoMode(QtWidgets.QLineEdit.Password) - self.leave_blank = QtWidgets.QLabel(self) - self.leave_blank.setGeometry(QtCore.QRect(350, 380, 300, 30)) - self.confirm_password = LineEdit(self) - self.confirm_password.setGeometry(QtCore.QRect(40, 420, 300, 30)) - self.confirm_password.setEchoMode(QtWidgets.QLineEdit.Password) - self.set_password = QtWidgets.QPushButton(self) - self.set_password.setGeometry(QtCore.QRect(40, 470, 300, 30)) - self.set_password.clicked.connect(self.new_password) - self.not_match = QtWidgets.QLabel(self) - self.not_match.setGeometry(QtCore.QRect(350, 420, 300, 30)) - self.not_match.setVisible(False) - self.not_match.setStyleSheet('QLabel { color: #BC1C1C; }') - self.warning = QtWidgets.QLabel(self) - self.warning.setGeometry(QtCore.QRect(40, 510, 500, 30)) - self.warning.setStyleSheet('QLabel { color: #BC1C1C; }') - self.default = QtWidgets.QPushButton(self) - self.default.setGeometry(QtCore.QRect(40, 550, 620, 30)) - self._auto = Settings.get_auto_profile() == self._profile_manager.get_path() - self.default.clicked.connect(self.auto_profile) - self.retranslateUi() - if self._profile.status is not None: - self.status.setCurrentIndex(self._profile.status) - else: - self.status.setVisible(False) - QtCore.QMetaObject.connectSlotsByName(self) - - def retranslateUi(self): - self.export.setText(util_ui.tr("Export profile")) - self.setWindowTitle(util_ui.tr("Profile settings")) - self.label.setText(util_ui.tr("Name:")) - self.label_2.setText(util_ui.tr("Status:")) - self.label_3.setText(util_ui.tr("TOX ID:")) - self.copyId.setText(util_ui.tr("Copy TOX ID")) - self.new_avatar.setText(util_ui.tr("New avatar")) - self.delete_avatar.setText(util_ui.tr("Reset avatar")) - self.new_nospam.setText(util_ui.tr("New NoSpam")) - self.profilepass.setText(util_ui.tr("Profile password")) - self.password.setPlaceholderText(util_ui.tr("Password (at least 8 symbols)")) - self.confirm_password.setPlaceholderText(util_ui.tr("Confirm password")) - self.set_password.setText(util_ui.tr("Set password")) - self.not_match.setText(util_ui.tr("Passwords do not match")) - self.leave_blank.setText(util_ui.tr("Leaving blank will reset current password")) - self.warning.setText(util_ui.tr("There is no way to recover lost passwords")) - self.status.addItem(util_ui.tr("Online")) - self.status.addItem(util_ui.tr("Away")) - self.status.addItem(util_ui.tr("Busy")) - self.copy_pk.setText(util_ui.tr("Copy public key")) - - 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")) - else: - self.default.setText(util_ui.tr("Mark as default profile")) - - def new_password(self): - if self.password.text() == self.confirm_password.text(): - if not len(self.password.text()) or len(self.password.text()) >= 8: - self._toxes.set_password(self.password.text()) - self.close() - else: - self.not_match.setText( - util_ui.tr("Password must be at least 8 symbols")) - self.not_match.setVisible(True) - else: - self.not_match.setText(util_ui.tr("Passwords do not match")) - self.not_match.setVisible(True) - - def copy(self): - clipboard = QtWidgets.QApplication.clipboard() - clipboard.setText(self._profile.tox_id) - pixmap = QtGui.QPixmap(join_path(get_images_directory(), 'accept.png')) - icon = QtGui.QIcon(pixmap) - self.copyId.setIcon(icon) - self.copyId.setIconSize(QtCore.QSize(10, 10)) - - def copy_public_key(self): - clipboard = QtWidgets.QApplication.clipboard() - clipboard.setText(self._profile.tox_id[:64]) - pixmap = QtGui.QPixmap(join_path(get_images_directory(), 'accept.png')) - icon = QtGui.QIcon(pixmap) - self.copy_pk.setIcon(icon) - self.copy_pk.setIconSize(QtCore.QSize(10, 10)) - - def new_no_spam(self): - self.tox_id.setText(self._profile.set_new_nospam()) - - def reset_avatar(self): - self._profile.reset_avatar(self._settings['identicons']) - - def set_avatar(self): - choose = util_ui.tr("Choose avatar") - name = util_ui.file_dialog(choose, 'Images (*.png)') - if not name[0]: - return - bitmap = QtGui.QPixmap(name[0]) - bitmap.scaled(QtCore.QSize(128, 128), aspectRatioMode=QtCore.Qt.KeepAspectRatio, - transformMode=QtCore.Qt.SmoothTransformation) - - byte_array = QtCore.QByteArray() - buffer = QtCore.QBuffer(byte_array) - buffer.open(QtCore.QIODevice.WriteOnly) - bitmap.save(buffer, 'PNG') - self._profile.set_avatar(bytes(byte_array.data())) - - def export_profile(self): - directory = util_ui.directory_dialog() + '/' - if directory != '/': - reply = util_ui.question(util_ui.tr('Do you want to move your profile to this location?'), - util_ui.tr('Use new path')) - self._settings.export(directory) - self._profile.export_db(directory) - self._profile_manager.export_profile(self._settings, directory, reply) - - def closeEvent(self, event): - self._profile.set_name(self.nick.text()) - self._profile.set_status_message(self.status_message.text()) - self._profile.set_status(self.status.currentIndex()) - - class NetworkSettings(CenteredWidget): """Network settings form: UDP, Ipv6 and proxy""" def __init__(self, settings, reset): diff --git a/toxygen/ui/profile_settings_screen.py b/toxygen/ui/profile_settings_screen.py new file mode 100644 index 0000000..2e55d3d --- /dev/null +++ b/toxygen/ui/profile_settings_screen.py @@ -0,0 +1,157 @@ +from ui.widgets import CenteredWidget +import utils.ui as util_ui +from utils.util import join_path, get_images_directory, get_views_path +from user_data.settings import Settings +from PyQt5 import QtGui, QtCore, uic + + +class ProfileSettings(CenteredWidget): + """Form with profile settings such as name, status, TOX ID""" + def __init__(self, profile, profile_manager, settings, toxes): + super().__init__() + self._profile = profile + self._profile_manager = profile_manager + self._settings = settings + self._toxes = toxes + self._auto = False + + uic.loadUi(get_views_path('profile_settings_screen'), self) + + self._init_ui() + self.center() + + def closeEvent(self, event): + self._profile.set_name(self.nameLineEdit.text()) + self._profile.set_status_message(self.statusMessageLineEdit.text()) + self._profile.set_status(self.statusComboBox.currentIndex()) + + def _init_ui(self): + self._auto = Settings.get_auto_profile() == self._profile_manager.get_path() + self.toxIdLabel.setText(self._profile.tox_id) + self.nameLineEdit.setText(self._profile.name) + self.statusMessageLineEdit.setText(self._profile.status_message) + self.defaultProfilePushButton.clicked.connect(self._toggle_auto_profile) + self.copyToxIdPushButton.clicked.connect(self._copy_tox_id) + self.copyPublicKeyPushButton.clicked.connect(self._copy_public_key) + self.changePasswordPushButton.clicked.connect(self._save_password) + self.exportProfilePushButton.clicked.connect(self._export_profile) + self.newNoSpamPushButton.clicked.connect(self._set_new_no_spam) + self.newAvatarPushButton.clicked.connect(self._set_avatar) + self.resetAvatarPushButton.clicked.connect(self._reset_avatar) + + self.invalidPasswordsLabel.setVisible(False) + + self._retranslate_ui() + + if self._profile.status is not None: + self.statusComboBox.setCurrentIndex(self._profile.status) + else: + self.statusComboBox.setVisible(False) + + def _retranslate_ui(self): + self.setWindowTitle(util_ui.tr("Profile settings")) + + self.exportProfilePushButton.setText(util_ui.tr("Export profile")) + self.nameLabel.setText(util_ui.tr("Name:")) + self.statusLabel.setText(util_ui.tr("Status:")) + self.toxIdTitleLabel.setText(util_ui.tr("TOX ID:")) + self.copyToxIdPushButton.setText(util_ui.tr("Copy TOX ID")) + self.newAvatarPushButton.setText(util_ui.tr("New avatar")) + self.resetAvatarPushButton.setText(util_ui.tr("Reset avatar")) + self.newNoSpamPushButton.setText(util_ui.tr("New NoSpam")) + self.profilePasswordLabel.setText(util_ui.tr("Profile password")) + self.passwordLineEdit.setPlaceholderText(util_ui.tr("Password (at least 8 symbols)")) + self.confirmPasswordLineEdit.setPlaceholderText(util_ui.tr("Confirm password")) + self.changePasswordPushButton.setText(util_ui.tr("Set password")) + self.invalidPasswordsLabel.setText(util_ui.tr("Passwords do not match")) + self.emptyPasswordLabel.setText(util_ui.tr("Leaving blank will reset current password")) + self.warningLabel.setText(util_ui.tr("There is no way to recover lost passwords")) + self.statusComboBox.addItem(util_ui.tr("Online")) + self.statusComboBox.addItem(util_ui.tr("Away")) + self.statusComboBox.addItem(util_ui.tr("Busy")) + self.copyPublicKeyPushButton.setText(util_ui.tr("Copy public key")) + + self._set_default_profile_button_text() + + def _toggle_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.defaultProfilePushButton.setText(util_ui.tr("Mark as not default profile")) + else: + self.defaultProfilePushButton.setText(util_ui.tr("Mark as default profile")) + + def _save_password(self): + password = self.passwordLineEdit.text() + confirm_password = self.confirmPasswordLineEdit.text() + if password == confirm_password: + if not len(password) or len(password) >= 8: + self._toxes.set_password(password) + self.close() + else: + self.invalidPasswordsLabel.setText( + util_ui.tr("Password must be at least 8 symbols")) + self.invalidPasswordsLabel.setVisible(True) + else: + self.invalidPasswordsLabel.setText(util_ui.tr("Passwords do not match")) + self.invalidPasswordsLabel.setVisible(True) + + def _copy_tox_id(self): + util_ui.copy_to_clipboard(self._profile.tox_id) + + icon = self._get_accept_icon() + self.copyToxIdPushButton.setIcon(icon) + self.copyToxIdPushButton.setIconSize(QtCore.QSize(10, 10)) + + def _copy_public_key(self): + util_ui.copy_to_clipboard(self._profile.tox_id[:64]) + + icon = self._get_accept_icon() + self.copyPublicKeyPushButton.setIcon(icon) + self.copyPublicKeyPushButton.setIconSize(QtCore.QSize(10, 10)) + + def _set_new_no_spam(self): + self.toxIdLabel.setText(self._profile.set_new_nospam()) + + def _reset_avatar(self): + self._profile.reset_avatar(self._settings['identicons']) + + def _set_avatar(self): + choose = util_ui.tr("Choose avatar") + name = util_ui.file_dialog(choose, 'Images (*.png)') + if not name[0]: + return + bitmap = QtGui.QPixmap(name[0]) + bitmap.scaled(QtCore.QSize(128, 128), QtCore.Qt.KeepAspectRatio, QtCore.Qt.SmoothTransformation) + + byte_array = QtCore.QByteArray() + buffer = QtCore.QBuffer(byte_array) + buffer.open(QtCore.QIODevice.WriteOnly) + bitmap.save(buffer, 'PNG') + + self._profile.set_avatar(bytes(byte_array.data())) + + def _export_profile(self): + directory = util_ui.directory_dialog() + if not directory: + return + + reply = util_ui.question(util_ui.tr('Do you want to move your profile to this location?'), + util_ui.tr('Use new path')) + + self._settings.export(directory) + self._profile.export_db(directory) + self._profile_manager.export_profile(self._settings, directory, reply) + + @staticmethod + def _get_accept_icon(): + pixmap = QtGui.QPixmap(join_path(get_images_directory(), 'accept.png')) + + return QtGui.QIcon(pixmap) + diff --git a/toxygen/ui/views/profile_settings_screen.ui b/toxygen/ui/views/profile_settings_screen.ui new file mode 100644 index 0000000..ece0083 --- /dev/null +++ b/toxygen/ui/views/profile_settings_screen.ui @@ -0,0 +1,280 @@ + + + Form + + + + 0 + 0 + 900 + 702 + + + + Form + + + + + 30 + 10 + 161 + 31 + + + + TextLabel + + + + + + 30 + 90 + 161 + 31 + + + + TextLabel + + + + + + 30 + 50 + 421 + 31 + + + + + + + 30 + 130 + 421 + 31 + + + + + + + 520 + 30 + 311 + 31 + + + + + + + 40 + 180 + 131 + 21 + + + + TextLabel + + + + + + 40 + 210 + 831 + 61 + + + + TextLabel + + + true + + + + + + 40 + 280 + 371 + 31 + + + + PushButton + + + + + + 440 + 280 + 371 + 31 + + + + PushButton + + + + + + 520 + 80 + 321 + 35 + + + + PushButton + + + + + + 520 + 130 + 321 + 35 + + + + PushButton + + + + + + 60 + 380 + 161 + 31 + + + + TextLabel + + + + + + 50 + 420 + 421 + 31 + + + + + + + 50 + 470 + 421 + 31 + + + + + + + 500 + 420 + 381 + 21 + + + + TextLabel + + + + + + 60 + 580 + 381 + 21 + + + + TextLabel + + + + + + 40 + 630 + 831 + 35 + + + + PushButton + + + + + + 50 + 520 + 421 + 35 + + + + PushButton + + + + + + 500 + 470 + 381 + 21 + + + + TextLabel + + + + + + 40 + 330 + 371 + 35 + + + + PushButton + + + + + + 440 + 330 + 371 + 35 + + + + PushButton + + + + + + diff --git a/toxygen/ui/widgets_factory.py b/toxygen/ui/widgets_factory.py index aa70861..128e85e 100644 --- a/toxygen/ui/widgets_factory.py +++ b/toxygen/ui/widgets_factory.py @@ -6,6 +6,7 @@ from ui.self_peer_screen import * from ui.group_invites_widgets import * from ui.group_settings_widgets import * from ui.group_bans_widgets import * +from ui.profile_settings_screen import ProfileSettings class WidgetsFactory: diff --git a/toxygen/user_data/settings.py b/toxygen/user_data/settings.py index c986019..71422c2 100644 --- a/toxygen/user_data/settings.py +++ b/toxygen/user_data/settings.py @@ -137,9 +137,8 @@ class Settings(dict): data = json.loads(data) else: data = {} - if 'path' in data: - del data['path'] - del data['name'] + if 'profile_path' in data: + del data['profile_path'] with open(p, 'w') as fl: fl.write(json.dumps(data))