11 Commits

Author SHA1 Message Date
28cedae342 v0.2.3 2016-07-14 12:32:21 +03:00
3f9a35e164 avatars in chat 2016-07-13 23:09:34 +03:00
babeeb969c smileys, stickers, avatars update 2016-07-13 21:30:51 +03:00
01e6d45232 bug fixes 2016-07-13 17:16:15 +03:00
c865ae4df6 translations and bug fix 2016-07-12 19:40:26 +03:00
59452aa525 docs update 2016-07-12 18:05:33 +03:00
47c0a451c4 docs && setup.py update 2016-07-11 17:24:39 +03:00
5b9cce4155 docs update 2016-07-11 00:38:25 +03:00
d6b6327545 stickers and smileys import 2016-07-10 22:32:35 +03:00
7c2a2f16df tcs: part 1 2016-07-10 17:51:33 +03:00
e004838013 plugins improvements 2016-07-07 13:54:02 +03:00
65 changed files with 958 additions and 520 deletions

View File

@ -10,6 +10,8 @@ include toxygen/smileys/animated/config.json
include toxygen/smileys/starwars/*.gif
include toxygen/smileys/starwars/*.png
include toxygen/smileys/starwars/config.json
include toxygen/smileys/ksk/*.png
include toxygen/smileys/ksk/config.json
include toxygen/styles/style.qss
include toxygen/translations/*.qm
include toxygen/libs/libtox.dll

View File

@ -7,4 +7,4 @@ Install PyInstaller:
``pyinstaller --windowed --icon images/icon.ico main.py``
Don't forget to copy /images/, /sounds/, /translations/, /styles/, /smileys/, /stickers/ (and /libs/libtox.dll on Windows) to /dist/main/
Don't forget to copy /images/, /sounds/, /translations/, /styles/, /smileys/, /stickers/ (and /libs/libtox.dll, /libs/libsodium.a on Windows) to /dist/main/

View File

@ -5,19 +5,21 @@
##Using pip3
### Windows (32-bit interpreter)
### Windows
``pip3.4 install toxygen``
Run app using ``toxygen`` command.
##Linux
### Linux
1. Install [toxcore](https://github.com/irungentoo/toxcore/blob/master/INSTALL.md) with toxav support in your system (install in /usr/lib/)
2. Install PortAudio:
``sudo apt-get install portaudio19-dev``
3. Install toxygen:
3. Install PySide: ``sudo apt-get install python3-pyside``
4. Install toxygen:
``sudo pip3.4 install toxygen``
4 Run toxygen using ``toxygen`` command.
5. Run toxygen using ``toxygen`` command.
## From source code (recommended for developers)
@ -26,11 +28,12 @@ Run app using ``toxygen`` command.
1. [Download and install latest Python 3.4](https://www.python.org/downloads/windows/)
2. [Install PySide](https://pypi.python.org/pypi/PySide/1.2.4) (recommended) or [PyQt4](https://riverbankcomputing.com/software/pyqt/download)
3. Install PyAudio: ``pip3.4 install pyaudio``
4. Install PySocks: ``pip3.4 install PySocks``
5. [Download toxygen](https://github.com/xveduk/toxygen/archive/master.zip)
6. Unpack archive
7. Download latest libtox.dll build, download latest libsodium.a build, put it into \src\libs\
8. Run \src\main.py
4. [Download toxygen](https://github.com/xveduk/toxygen/archive/master.zip)
5. Unpack archive
6. Download latest libtox.dll build, download latest libsodium.a build, put it into \src\libs\
7. Run \src\main.py.
Optional: install toxygen using setup.py: ``python3.4 setup.py install``
[libtox.dll for 32-bit Python](https://build.tox.chat/view/libtoxcore/job/libtoxcore_build_windows_x86_shared_release/lastSuccessfulBuild/artifact/libtoxcore_build_windows_x86_shared_release.zip)
@ -40,22 +43,20 @@ Run app using ``toxygen`` command.
[libsodium.a for 64-bit Python](https://build.tox.chat/view/libsodium/job/libsodium_build_windows_x86-64_static_release/lastSuccessfulBuild/artifact/libsodium_build_windows_x86-64_static_release.zip)
### Linux
Dependencies:
1. Install latest Python3.4:
1. Install latest Python3:
``sudo apt-get install python3``
2. [Install PySide](https://wiki.qt.io/PySide_Binaries_Linux) (recommended), using terminal - ``sudo apt-get install python3-pyside``, or install [PyQt4](https://riverbankcomputing.com/software/pyqt/download).
2. Install PySide: ``sudo apt-get install python3-pyside`` or install [PyQt4](https://riverbankcomputing.com/software/pyqt/download).
3. Install [toxcore](https://github.com/irungentoo/toxcore/blob/master/INSTALL.md) with toxav support in your system (install in /usr/lib/)
4. Install PyAudio:
``sudo apt-get install portaudio19-dev`` and ``sudo apt-get install python3-pyaudio``
5. Install PySocks: ``pip3.4 install PySocks``
6. [Download toxygen](https://github.com/xveduk/toxygen/archive/master.zip)
7. Unpack archive
8. Run app:
``sudo apt-get install portaudio19-dev`` and ``sudo apt-get install python3-pyaudio`` (or ``pip3 install pyaudio``)
5. [Download toxygen](https://github.com/xveduk/toxygen/archive/master.zip)
6. Unpack archive
7. Run app:
``python3.4 main.py``
Optional: install toxygen using setup.py: ``python3 setup.py install``
## Compile Toxygen
Check [compile.md](/docs/compile.md) for more info

View File

@ -3,7 +3,7 @@
In Toxygen plugin is single python (supported Python 3.0 - 3.4) module (.py file) and directory with data associated with it.
Every module must contain one class derived from PluginSuperClass defined in [plugin_super_class.py](/src/plugins/plugin_super_class.py). Instance of this class will be created by PluginLoader class (defined in [plugin_support.py](/src/plugin_support.py) ). This class can enable/disable plugins and send data to it.
Every plugin has it's own full name and unique short name (1-5 symbols). Main app can get it using special methods.
Every plugin has its own full name and unique short name (1-5 symbols). Main app can get it using special methods.
All plugin's data should be stored in following structure:
@ -16,36 +16,39 @@ All plugin's data should be stored in following structure:
|---other_files
```
Plugin MUST override:
- __init__ with params: tox (Tox instance), profile (Profile instance), settings (Settings instance), encrypt_save (ToxEncryptSave instance). Call super().__init__ with params plugin_full_name, plugin_short_name, tox, profile, settings, encrypt_save.
Plugin can override following methods:
- get_description - this method should return plugin description.
- get_menu - plugins allowed to add items in friend menu. You can open this menu making right click on friend in friends list. This method should return list of QAction's. Plugin must connect to QAction's triggered() signal.
- get_menu - plugins allowed to add items in friend menu. User can open this menu making right click on friend in friends list. This method should return list of QAction's. Plugin must connect to QAction's triggered() signal.
- get_window - plugins can have GUI, this method should return window instance or None for plugins without GUI.
- start - plugin was started.
- stop - plugin was stopped.
- close - app is closing, stop plugin.
- command - new command to plugin. Command can be entered in message field in format '/plugin <plugin_short_name> <command>'. Command 'help' should show user list of supported commands.
- command - new command to plugin. Command can be entered in message field in format '/plugin <plugin_short_name> <command>'. Command 'help' should show list of supported commands.
- lossless_packet - callback - incoming lossless packet from friend.
- lossy_packet - callback - incoming lossy packet from friend.
- friend_connected - callback - friend became online.
- friend_connected - callback - friend became online. Note that it called from friend_connection_status callback so friend is not really connected and ready for sending packets.
Other methods:
- send_lossless - this method send custom lossless packet. Plugins MUST send lossless packets using this method.
- send_lossy - this method send custom lossy packet. Plugins MUST send lossy packets using this method.
- send_lossless - this method sends custom lossless packet. Plugins MUST send lossless packets using this method.
- send_lossy - this method sends custom lossy packet. Plugins MUST send lossy packets using this method.
- load_settings - loads settings stored in default location.
- save_settings - saves settings to default location.
- load_translator - loads translations. Translations must be stored in directory with plugin's data. Files with translations must have the same name as in main app.
- load_translator - loads translations. Translations must be stored in directory with plugin's data. Files with translations must have the same name as in main app (example: ru_RU.qm).
About import:
import statement will not work in case you import module that wasn't previously imported by main program and user use precompiled binary. It's recommended to use dynamic import instead.
Import statement will not work in case you import module that wasn't previously imported by main program and user uses precompiled binary. It's recommended to use importlib module instead: importlib.import_module(module_name)
About GUI:
It's strictly recommended to support both PySide and PyQt4 in GUI. Plugin can not have GUI at all.
It's strictly recommended to support both PySide and PyQt4 in GUI. Plugin can have no GUI at all.
Exceptions:
Plugin's methods should not raise exceptions.
Plugin's methods MUST NOT raise exceptions.
#Examples

View File

@ -10,7 +10,7 @@ Check [Plugin API](/docs/plugin_api.md) for more info
Toxygen comes without preinstalled plugins.
1. Put plugin and directory with its data into /src/plugins/
1. Put plugin and directory with its data into /src/plugins/ or import it via GUI (In menu: Plugins -> Import plugin)
2. Restart Toxygen
##Note: /src/plugins/ should contain plugin_super_class.py and __init__.py

View File

@ -8,4 +8,6 @@ Animated smileys (.gif) are supported too.
#Stickers
Sticker is inline image. If you want to create your own smiley pack, create directory in src/stickers/ and place your stickers there.
Sticker is inline image. If you want to create your own smiley pack, create directory in src/stickers/ and place your stickers there.
Users can import plugins and stickers packs using menu: Settings -> Interface

View File

@ -7,14 +7,14 @@ from toxygen.util import program_version
version = program_version + '.0'
MODULES = ['PyAudio', 'PySocks']
MODULES = ['PyAudio']
if system() == 'Windows':
MODULES.append('PySide')
class InstallScript(install):
"""Install all required libs"""
"""This class configures Toxygen after installation"""
def run(self):
install.run(self)
@ -29,8 +29,9 @@ setup(name='Toxygen',
description='Toxygen - Tox client',
long_description='Toxygen is powerful Tox client written in Python3',
url='https://github.com/xveduk/toxygen/',
keywords='toxygen tox',
keywords='toxygen tox messenger',
author='Ingvar',
maintainer='Ingvar',
license='GPL3',
packages=['toxygen', 'toxygen.plugins', 'toxygen.styles'],
install_requires=MODULES,

View File

@ -127,12 +127,12 @@ class Friend(contact.Contact):
del self._message_getter
# don't delete data about active file transfer
if not save_unsent:
self._corr = list(filter(lambda x: x.get_type() in (2, 3) and
self._corr = list(filter(lambda x: x.get_type() == 2 and
x.get_status() in ft.ACTIVE_FILE_TRANSFERS, self._corr))
self._unsaved_messages = 0
else:
self._corr = list(filter(lambda x: (x.get_type() in (2, 3) and x.get_status() in ft.ACTIVE_FILE_TRANSFERS)
or (x.get_type() <= 1 and x.get_owner() == MESSAGE_OWNER['NOT_SENT']),
self._corr = list(filter(lambda x: (x.get_type() == 2 and x.get_status() in ft.ACTIVE_FILE_TRANSFERS)
or (x.get_type() <= 1 and x.get_owner() == MESSAGE_OWNER['NOT_SENT']),
self._corr))
self._unsaved_messages = len(self.get_unsent_messages())

View File

@ -159,6 +159,14 @@ class MessageItem(QtGui.QWidget):
return True
return False
def set_avatar(self, pixmap):
self.name.setAlignment(QtCore.Qt.AlignCenter)
self.message.setAlignment(QtCore.Qt.AlignVCenter)
self.setFixedHeight(max(self.height(), 36))
self.name.setFixedHeight(self.height())
self.message.setFixedHeight(self.height())
self.name.setPixmap(pixmap.scaled(30, 30, QtCore.Qt.KeepAspectRatio))
class ContactItem(QtGui.QWidget):
"""
@ -173,6 +181,7 @@ class ContactItem(QtGui.QWidget):
size = 32 if mode else 64
self.avatar_label.setGeometry(QtCore.QRect(3, 4, size, size))
self.avatar_label.setScaledContents(True)
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()

View File

@ -57,7 +57,7 @@ class LoginScreen(CenteredWidget):
self.load_profile.raise_()
self.new_name.raise_()
self.new_profile.raise_()
self.toxygen.setGeometry(QtCore.QRect(160, 10, 90, 21))
self.toxygen.setGeometry(QtCore.QRect(160, 8, 90, 25))
font = QtGui.QFont()
font.setFamily("Impact")
font.setPointSize(16)

View File

@ -11,8 +11,9 @@ from mainscreen import MainWindow
from callbacks import init_callbacks
from util import curr_directory, program_version
import styles.style
import platform
import toxencryptsave
from passwordscreen import PasswordScreen, UnlockAppScreen
from passwordscreen import PasswordScreen, UnlockAppScreen, SetProfilePasswordScreen
from plugin_support import PluginLoader
@ -52,6 +53,9 @@ class Toxygen:
app.setWindowIcon(QtGui.QIcon(curr_directory() + '/images/icon.png'))
self.app = app
if platform.system() == 'Linux':
QtCore.QCoreApplication.setAttribute(QtCore.Qt.AA_X11InitThreads)
# application color scheme
with open(curr_directory() + '/styles/style.qss') as fl:
dark_style = fl.read()
@ -94,9 +98,33 @@ class Toxygen:
elif _login.t == 1: # create new profile
_login.name = _login.name.strip()
name = _login.name if _login.name else 'toxygen_user'
pr = map(lambda x: x[1], ProfileHelper.find_profiles())
if name in list(pr):
msgBox = QtGui.QMessageBox()
msgBox.setWindowTitle(
QtGui.QApplication.translate("MainWindow", "Error", None, QtGui.QApplication.UnicodeUTF8))
text = (QtGui.QApplication.translate("MainWindow",
'Profile with this name already exists',
None, QtGui.QApplication.UnicodeUTF8))
msgBox.setText(text)
msgBox.exec_()
return
self.tox = profile.tox_factory()
self.tox.self_set_name(bytes(_login.name, 'utf-8') if _login.name else b'Toxygen User')
self.tox.self_set_status_message(b'Toxing on Toxygen')
reply = QtGui.QMessageBox.question(None,
'Profile {}'.format(name),
QtGui.QApplication.translate("login",
'Do you want to set profile password?',
None,
QtGui.QApplication.UnicodeUTF8),
QtGui.QMessageBox.Yes,
QtGui.QMessageBox.No)
if reply == QtGui.QMessageBox.Yes:
set_pass = SetProfilePasswordScreen(encrypt_save)
set_pass.show()
self.app.connect(self.app, QtCore.SIGNAL("lastWindowClosed()"), self.app, QtCore.SLOT("quit()"))
self.app.exec_()
ProfileHelper(Settings.get_default_path(), name).save_profile(self.tox.get_savedata())
path = Settings.get_default_path()
settings = Settings(name)
@ -292,6 +320,7 @@ class Toxygen:
if self.stop:
return
self.tox.bootstrap(*data)
self.tox.add_tcp_relay(*data)
except:
pass
for _ in range(10):
@ -304,6 +333,7 @@ class Toxygen:
if self.stop:
return
self.tox.bootstrap(*data)
self.tox.add_tcp_relay(*data)
except:
pass
finally:
@ -355,6 +385,7 @@ class Toxygen:
def clean():
"""Removes all windows libs from libs folder"""
d = curr_directory() + '/libs/'
for fl in ('libtox64.dll', 'libtox.dll', 'libsodium64.a', 'libsodium.a'):
if os.path.exists(d + fl):
@ -362,6 +393,7 @@ def clean():
def configure():
"""Removes unused libs"""
d = curr_directory() + '/libs/'
is_64bits = sys.maxsize > 2 ** 32
if not is_64bits:
@ -384,7 +416,7 @@ def configure():
def main():
if len(sys.argv) == 1:
toxygen = Toxygen()
else: # path to profile or tox: uri or --version or --help
else: # started with argument(s)
arg = sys.argv[1]
if arg == '--version':
print('Toxygen ' + program_version)
@ -405,4 +437,3 @@ def main():
if __name__ == '__main__':
main()

View File

@ -54,6 +54,7 @@ class MainWindow(QtGui.QMainWindow):
self.actionSettings.setObjectName("actionSettings")
self.audioSettings = QtGui.QAction(MainWindow)
self.pluginData = QtGui.QAction(MainWindow)
self.importPlugin = QtGui.QAction(MainWindow)
self.lockApp = QtGui.QAction(MainWindow)
self.menuProfile.addAction(self.actionAdd_friend)
self.menuProfile.addAction(self.actionSettings)
@ -64,6 +65,7 @@ class MainWindow(QtGui.QMainWindow):
self.menuSettings.addAction(self.actionNetwork)
self.menuSettings.addAction(self.audioSettings)
self.menuPlugins.addAction(self.pluginData)
self.menuPlugins.addAction(self.importPlugin)
self.menuAbout.addAction(self.actionAbout_program)
self.menubar.addAction(self.menuProfile.menuAction())
self.menubar.addAction(self.menuSettings.menuAction())
@ -80,6 +82,7 @@ class MainWindow(QtGui.QMainWindow):
self.audioSettings.triggered.connect(self.audio_settings)
self.pluginData.triggered.connect(self.plugins_menu)
self.lockApp.triggered.connect(self.lock_app)
self.importPlugin.triggered.connect(self.import_plugin)
QtCore.QMetaObject.connectSlotsByName(MainWindow)
def languageChange(self, *args, **kwargs):
@ -113,6 +116,7 @@ class MainWindow(QtGui.QMainWindow):
self.online_contacts.addItem(QtGui.QApplication.translate("MainWindow", "All", None, QtGui.QApplication.UnicodeUTF8))
self.online_contacts.addItem(QtGui.QApplication.translate("MainWindow", "Online", None, QtGui.QApplication.UnicodeUTF8))
self.online_contacts.setCurrentIndex(int(Settings.get_instance()['show_online_friends']))
self.importPlugin.setText(QtGui.QApplication.translate("MainWindow", "Import plugin", None, QtGui.QApplication.UnicodeUTF8))
def setup_right_bottom(self, Form):
Form.resize(650, 60)
@ -173,6 +177,7 @@ class MainWindow(QtGui.QMainWindow):
self.avatar_label = Form.avatar_label = QtGui.QLabel(Form)
self.avatar_label.setGeometry(QtCore.QRect(5, 30, 64, 64))
self.avatar_label.setScaledContents(True)
self.avatar_label.setAlignment(QtCore.Qt.AlignCenter)
self.name = Form.name = DataLabel(Form)
Form.name.setGeometry(QtCore.QRect(75, 40, 150, 25))
font = QtGui.QFont()
@ -393,6 +398,26 @@ class MainWindow(QtGui.QMainWindow):
self.audio_s = AudioSettings()
self.audio_s.show()
def import_plugin(self):
import util
directory = QtGui.QFileDialog.getExistingDirectory(self,
QtGui.QApplication.translate("MainWindow", 'Choose folder with plugin',
None,
QtGui.QApplication.UnicodeUTF8),
util.curr_directory(),
QtGui.QFileDialog.ShowDirsOnly | QtGui.QFileDialog.DontUseNativeDialog)
if directory:
src = directory + '/'
dest = curr_directory() + '/plugins/'
util.copy(src, dest)
msgBox = QtGui.QMessageBox()
msgBox.setWindowTitle(
QtGui.QApplication.translate("MainWindow", "Restart Toxygen", None, QtGui.QApplication.UnicodeUTF8))
msgBox.setText(
QtGui.QApplication.translate("MainWindow", 'Plugin will be loaded after restart', None,
QtGui.QApplication.UnicodeUTF8))
msgBox.exec_()
def lock_app(self):
if toxencryptsave.ToxEncryptSave.get_instance().has_password():
Settings.get_instance().locked = True

View File

@ -330,7 +330,7 @@ class WelcomeScreen(CenteredWidget):
self.setWindowTitle(QtGui.QApplication.translate('WelcomeScreen', 'Tip of the day',
None, QtGui.QApplication.UnicodeUTF8))
import random
num = random.randint(0, 8)
num = random.randint(0, 10)
if num == 0:
text = QtGui.QApplication.translate('WelcomeScreen', 'Press Esc if you want hide app to tray.',
None, QtGui.QApplication.UnicodeUTF8)
@ -356,12 +356,20 @@ class WelcomeScreen(CenteredWidget):
None, QtGui.QApplication.UnicodeUTF8)
elif num == 6:
text = QtGui.QApplication.translate('WelcomeScreen',
'New in Toxygen v0.2.2:<br>Users can lock application using profile password.<br>Compact contact list support<br>Bug fixes<br>Tox DNS improvements',
'New in Toxygen v0.2.3:<br>TCS compliance<br>Plugins, smileys and stickers import<br>Bug fixes',
None, QtGui.QApplication.UnicodeUTF8)
elif num == 7:
text = QtGui.QApplication.translate('WelcomeScreen',
'Toxygen supports faux offline messages and file transfers. Send message or file to offline friend and he will get it later.',
None, QtGui.QApplication.UnicodeUTF8)
elif num == 8:
text = QtGui.QApplication.translate('WelcomeScreen',
'Delete single message in chat: make right click on spinner or message time and choose "Delete" in menu',
None, QtGui.QApplication.UnicodeUTF8)
elif num == 9:
text = QtGui.QApplication.translate('WelcomeScreen',
'Use right click on inline image to save it',
None, QtGui.QApplication.UnicodeUTF8)
else:
text = QtGui.QApplication.translate('WelcomeScreen',
'Set new NoSpam to avoid spam friend requests: Profile -> Settings -> Set new NoSpam.',

View File

@ -4,7 +4,7 @@ except ImportError:
from PyQt4 import QtCore, QtGui
from settings import *
from profile import Profile
from util import curr_directory
from util import curr_directory, copy
from widgets import CenteredWidget, DataLabel, LineEdit
import pyaudio
import toxencryptsave
@ -17,6 +17,7 @@ class AddContact(CenteredWidget):
def __init__(self, tox_id=''):
super(AddContact, self).__init__()
self.initUI(tox_id)
self._adding = False
def initUI(self, tox_id):
self.setObjectName('AddContact')
@ -58,8 +59,12 @@ class AddContact(CenteredWidget):
QtCore.QMetaObject.connectSlotsByName(self)
def add_friend(self):
if self._adding:
return
self._adding = True
profile = Profile.get_instance()
send = profile.send_friend_request(self.tox_id.text(), self.message_edit.toPlainText())
send = profile.send_friend_request(self.tox_id.text().strip(), self.message_edit.toPlainText())
self._adding = False
if send is True:
# request was successful
self.close()
@ -258,7 +263,7 @@ class ProfileSettings(CenteredWidget):
buffer = QtCore.QBuffer(byte_array)
buffer.open(QtCore.QIODevice.WriteOnly)
bitmap.save(buffer, 'PNG')
Profile.get_instance().set_avatar(str(byte_array.data()))
Profile.get_instance().set_avatar(bytes(byte_array.data()))
def export_profile(self):
directory = QtGui.QFileDialog.getExistingDirectory(options=QtGui.QFileDialog.DontUseNativeDialog) + '/'
@ -549,8 +554,8 @@ class InterfaceSettings(CenteredWidget):
def initUI(self):
self.setObjectName("interfaceForm")
self.setMinimumSize(QtCore.QSize(400, 450))
self.setMaximumSize(QtCore.QSize(400, 450))
self.setMinimumSize(QtCore.QSize(400, 580))
self.setMaximumSize(QtCore.QSize(400, 580))
self.label = QtGui.QLabel(self)
self.label.setGeometry(QtCore.QRect(30, 10, 370, 20))
font = QtGui.QFont()
@ -605,17 +610,30 @@ class InterfaceSettings(CenteredWidget):
self.messages_font_size.setCurrentIndex(settings['message_font_size'] - 10)
self.unread = QtGui.QPushButton(self)
self.unread.setGeometry(QtCore.QRect(30, 380, 340, 30))
self.unread.setGeometry(QtCore.QRect(30, 465, 340, 30))
self.unread.clicked.connect(self.select_color)
self.compact_mode = QtGui.QCheckBox(self)
self.compact_mode.setGeometry(QtCore.QRect(30, 425, 370, 20))
self.compact_mode.setGeometry(QtCore.QRect(30, 380, 370, 20))
self.compact_mode.setChecked(settings['compact_mode'])
self.show_avatars = QtGui.QCheckBox(self)
self.show_avatars.setGeometry(QtCore.QRect(30, 410, 370, 20))
self.show_avatars.setChecked(settings['show_avatars'])
self.import_smileys = QtGui.QPushButton(self)
self.import_smileys.setGeometry(QtCore.QRect(30, 505, 340, 30))
self.import_smileys.clicked.connect(self.import_sm)
self.import_stickers = QtGui.QPushButton(self)
self.import_stickers.setGeometry(QtCore.QRect(30, 545, 340, 30))
self.import_stickers.clicked.connect(self.import_st)
self.retranslateUi()
QtCore.QMetaObject.connectSlotsByName(self)
def retranslateUi(self):
self.show_avatars.setText(QtGui.QApplication.translate("interfaceForm", "Show avatars in chat", None, QtGui.QApplication.UnicodeUTF8))
self.setWindowTitle(QtGui.QApplication.translate("interfaceForm", "Interface settings", None, QtGui.QApplication.UnicodeUTF8))
self.label.setText(QtGui.QApplication.translate("interfaceForm", "Theme:", None, QtGui.QApplication.UnicodeUTF8))
self.lang.setText(QtGui.QApplication.translate("interfaceForm", "Language:", None, QtGui.QApplication.UnicodeUTF8))
@ -625,6 +643,36 @@ class InterfaceSettings(CenteredWidget):
self.messages_font_size_label.setText(QtGui.QApplication.translate("interfaceForm", "Messages font size:", None, QtGui.QApplication.UnicodeUTF8))
self.unread.setText(QtGui.QApplication.translate("interfaceForm", "Select unread messages notification color", None, QtGui.QApplication.UnicodeUTF8))
self.compact_mode.setText(QtGui.QApplication.translate("interfaceForm", "Compact contact list", None, QtGui.QApplication.UnicodeUTF8))
self.import_smileys.setText(QtGui.QApplication.translate("interfaceForm", "Import smiley pack", None, QtGui.QApplication.UnicodeUTF8))
self.import_stickers.setText(QtGui.QApplication.translate("interfaceForm", "Import sticker pack", None, QtGui.QApplication.UnicodeUTF8))
def import_st(self):
directory = QtGui.QFileDialog.getExistingDirectory(self,
QtGui.QApplication.translate("MainWindow",
'Choose folder with sticker pack',
None,
QtGui.QApplication.UnicodeUTF8),
curr_directory(),
QtGui.QFileDialog.ShowDirsOnly | QtGui.QFileDialog.DontUseNativeDialog)
if directory:
src = directory + '/'
dest = curr_directory() + '/stickers/' + os.path.basename(directory) + '/'
copy(src, dest)
def import_sm(self):
directory = QtGui.QFileDialog.getExistingDirectory(self,
QtGui.QApplication.translate("MainWindow",
'Choose folder with smiley pack',
None,
QtGui.QApplication.UnicodeUTF8),
curr_directory(),
QtGui.QFileDialog.ShowDirsOnly | QtGui.QFileDialog.DontUseNativeDialog)
if directory:
src = directory + '/'
dest = curr_directory() + '/smileys/' + os.path.basename(directory) + '/'
copy(src, dest)
def select_color(self):
col = QtGui.QColorDialog.getColor()
@ -646,6 +694,9 @@ class InterfaceSettings(CenteredWidget):
if settings['compact_mode'] != self.compact_mode.isChecked():
settings['compact_mode'] = self.compact_mode.isChecked()
restart = True
if settings['show_avatars'] != self.show_avatars.isChecked():
settings['show_avatars'] = self.show_avatars.isChecked()
restart = True
settings['smiley_pack'] = self.smiley_pack.currentText()
smileys.SmileyLoader.get_instance().load_pack()
language = self.lang_choose.currentText()

View File

@ -100,3 +100,65 @@ class UnlockAppScreen(PasswordScreenBase):
else:
self.warning.setVisible(True)
print('Wrong password!')
class SetProfilePasswordScreen(CenteredWidget):
def __init__(self, encrypt):
super(SetProfilePasswordScreen, self).__init__()
self._encrypt = encrypt
self.initUI()
self.retranslateUi()
self.center()
def initUI(self):
self.setMinimumSize(QtCore.QSize(700, 200))
self.setMaximumSize(QtCore.QSize(700, 200))
self.password = LineEdit(self)
self.password.setGeometry(QtCore.QRect(40, 10, 300, 30))
self.password.setEchoMode(QtGui.QLineEdit.EchoMode.Password)
self.confirm_password = LineEdit(self)
self.confirm_password.setGeometry(QtCore.QRect(40, 50, 300, 30))
self.confirm_password.setEchoMode(QtGui.QLineEdit.EchoMode.Password)
self.set_password = QtGui.QPushButton(self)
self.set_password.setGeometry(QtCore.QRect(40, 100, 300, 30))
self.set_password.clicked.connect(self.new_password)
self.not_match = QtGui.QLabel(self)
self.not_match.setGeometry(QtCore.QRect(350, 50, 300, 30))
self.not_match.setVisible(False)
self.not_match.setStyleSheet('QLabel { color: #BC1C1C; }')
self.warning = QtGui.QLabel(self)
self.warning.setGeometry(QtCore.QRect(40, 160, 500, 30))
self.warning.setStyleSheet('QLabel { color: #BC1C1C; }')
def retranslateUi(self):
self.setWindowTitle(QtGui.QApplication.translate("PasswordScreen", "Profile password", None,
QtGui.QApplication.UnicodeUTF8))
self.password.setPlaceholderText(
QtGui.QApplication.translate("PasswordScreen", "Password (at least 8 symbols)", None,
QtGui.QApplication.UnicodeUTF8))
self.confirm_password.setPlaceholderText(
QtGui.QApplication.translate("PasswordScreen", "Confirm password", None,
QtGui.QApplication.UnicodeUTF8))
self.set_password.setText(
QtGui.QApplication.translate("PasswordScreen", "Set password", None, QtGui.QApplication.UnicodeUTF8))
self.not_match.setText(QtGui.QApplication.translate("PasswordScreen", "Passwords do not match", None,
QtGui.QApplication.UnicodeUTF8))
self.warning.setText(
QtGui.QApplication.translate("PasswordScreen", "There is no way to recover lost passwords", None,
QtGui.QApplication.UnicodeUTF8))
def new_password(self):
if self.password.text() == self.confirm_password.text():
if len(self.password.text()) >= 8:
self._encrypt.set_password(self.password.text())
self.close()
else:
self.not_match.setText(
QtGui.QApplication.translate("PasswordScreen", "Password must be at least 8 symbols", None,
QtGui.QApplication.UnicodeUTF8))
self.not_match.setVisible(True)
else:
self.not_match.setText(QtGui.QApplication.translate("PasswordScreen", "Passwords do not match", None,
QtGui.QApplication.UnicodeUTF8))
self.not_match.setVisible(True)

View File

@ -152,5 +152,6 @@ class PluginLoader(util.Singleton):
App is closing, stop all plugins
"""
for key in list(self._plugins.keys()):
self._plugins[key][0].close()
if self._plugins[key][1]:
self._plugins[key][0].close()
del self._plugins[key]

View File

@ -37,6 +37,7 @@ class PluginSuperClass:
def __init__(self, name, short_name, tox=None, profile=None, settings=None, encrypt_save=None):
"""
Constructor. In plugin __init__ should take only 4 last arguments
:param name: plugin full name
:param short_name: plugin unique short name (length of short name should not exceed MAX_SHORT_NAME_LENGTH)
:param tox: tox instance

View File

@ -41,6 +41,8 @@ class Profile(contact.Contact, Singleton):
self._load_history = True
settings = Settings.get_instance()
self._show_online = settings['show_online_friends']
self._show_avatars = settings['show_avatars']
self._friend_item_height = 40 if settings['compact_mode'] else 70
screen.online_contacts.setCurrentIndex(int(self._show_online))
aliases = settings['friends_aliases']
data = tox.self_get_friend_list()
@ -122,7 +124,7 @@ class Profile(contact.Contact, Singleton):
friend.visibility = friend.visibility or friend.messages or friend.actions
if friend.visibility:
self._screen.friends_list.item(index).setSizeHint(QtCore.QSize(250,
40 if settings['compact_mode'] else 70))
self._friend_item_height))
else:
self._screen.friends_list.item(index).setSizeHint(QtCore.QSize(250, 0))
self._show_online, self._filter_string = show_online, filter_str
@ -385,29 +387,32 @@ class Profile(contact.Contact, Singleton):
if not friend.visibility:
self.update_filtration()
def send_message(self, text):
def send_message(self, text, friend_num=None):
"""
Send message to active friend
Send message
:param text: message text
:param friend_num: num of friend
"""
if friend_num is None:
friend_num = self.get_active_number()
if text.startswith('/plugin '):
plugin_support.PluginLoader.get_instance().command(text[8:])
self._screen.messageEdit.clear()
elif text and self._active_friend + 1:
text = ''.join(c if c <= '\u10FFFF' else '\u25AF' for c in text)
elif text and friend_num + 1:
if text.startswith('/me '):
message_type = TOX_MESSAGE_TYPE['ACTION']
text = text[4:]
else:
message_type = TOX_MESSAGE_TYPE['NORMAL']
friend = self._friends[self._active_friend]
friend = self.get_friend_by_number(friend_num)
friend.inc_receipts()
if friend.status is not None:
self.split_and_send(friend.number, message_type, text.encode('utf-8'))
t = time.time()
self.create_message_item(text, t, MESSAGE_OWNER['NOT_SENT'], message_type)
self._screen.messageEdit.clear()
self._messages.scrollToBottom()
if friend.number == self.get_active_number():
t = time.time()
self.create_message_item(text, t, MESSAGE_OWNER['NOT_SENT'], message_type)
self._screen.messageEdit.clear()
self._messages.scrollToBottom()
friend.append_message(TextMessage(text, MESSAGE_OWNER['NOT_SENT'], t, message_type))
def delete_message(self, time):
@ -529,6 +534,9 @@ class Profile(contact.Contact, Singleton):
else:
name = self._name
item = MessageItem(text, time, name, owner != MESSAGE_OWNER['NOT_SENT'], message_type, self._messages)
if self._show_avatars:
item.set_avatar(self._friends[self._active_friend].get_pixmap() if owner == MESSAGE_OWNER[
'FRIEND'] else self.get_pixmap())
elem = QtGui.QListWidgetItem()
elem.setSizeHint(QtCore.QSize(self._messages.width(), item.height()))
if append:
@ -816,22 +824,12 @@ class Profile(contact.Contact, Singleton):
elif auto:
path = settings['auto_accept_path'] or curr_directory()
if not os.path.isdir(path):
path = curr_directory()
new_file_name, i = file_name, 1
while os.path.isfile(path + '/' + new_file_name): # file with same name already exists
if '.' in file_name: # has extension
d = file_name.rindex('.')
else: # no extension
d = len(file_name)
new_file_name = file_name[:d] + ' ({})'.format(i) + file_name[d:]
i += 1
self.accept_transfer(None, path + '/' + new_file_name, friend_number, file_number, size)
self.accept_transfer(None, path + '/' + file_name, friend_number, file_number, size)
tm = TransferMessage(MESSAGE_OWNER['FRIEND'],
time.time(),
TOX_FILE_TRANSFER_STATE['RUNNING'],
size,
new_file_name,
file_name,
friend_number,
file_number)
else:
@ -918,6 +916,16 @@ class Profile(contact.Contact, Singleton):
:param size: file size
:param inline: is inline image
"""
path, file_name = os.path.split(path)
new_file_name, i = file_name, 1
while os.path.isfile(path + '/' + new_file_name): # file with same name already exists
if '.' in file_name: # has extension
d = file_name.rindex('.')
else: # no extension
d = len(file_name)
new_file_name = file_name[:d] + ' ({})'.format(i) + file_name[d:]
i += 1
path = os.path.join(path, new_file_name)
if not inline:
rt = ReceiveTransfer(path, self._tox, friend_number, size, file_number)
else:
@ -935,6 +943,7 @@ class Profile(contact.Contact, Singleton):
:param data: raw data - png
"""
self.send_inline(data, 'toxygen_inline.png')
self._messages.repaint()
def send_sticker(self, path):
with open(path, 'rb') as fl:

View File

@ -110,6 +110,7 @@ class Settings(dict, Singleton):
'show_online_friends': False,
'auto_accept_from_friends': [],
'friends_aliases': [],
'show_avatars': False,
'typing_notifications': False,
'calls_sound': True,
'blocked': [],

File diff suppressed because one or more lines are too long

Binary file not shown.

After

Width:  |  Height:  |  Size: 883 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 932 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 917 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 891 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 809 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 893 B

View File

@ -0,0 +1 @@
{"BD": "cool2.png", "v_v": "calm.png", ":/": "getlost.png", ":(": "sad.png", ":)": "smile.png", ":*": "kiss.png", ":animal:": "pawn.png", "=|": "none.png", "=*": "kiss.png", ":heart:": "heart.png", "B]": "cool.png", "=o": "shocked.png", ":0": "shocked.png", "=S": "none2.png", "=]": "smile2.png", "=\\": "getlost.png", "B-)": "cool.png", ":pawn:": "pawn.png", "=O": "shocked.png", ">:\\": "angry2.png", ":redstar:": "redstar.png", ":o": "shocked.png", "=0": "shocked.png", "B-D": "cool2.png", ":|": "none.png", ":''(": "cry.png", "=/": "getlost.png", "=)": "smile.png", "=(": "sad.png", "B-]": "cool.png", ":O": "shocked.png", ":D": "grin.png", "B)": "cool.png", ":'(": "cry.png", ":]": "smile2.png", ":music:": "notes.png", ":P": "tongue.png", ":S": "none2.png", ":evil:": "evil.png", ":-O": "shocked.png", ":zzzzz:": "zzz.png", ">:[]": "angry.png", ";|": "none.png", ":-\\": "getlost.png", ":-]": "smile2.png", ":-S": "none2.png", ":-P": "tongue.png", ";o": "shocked.png", ";S": "none2.png", ":\\": "getlost.png", ";P": "tongue.png", ":pet:": "pawn.png", ":-o": "shocked.png", ";]": "blink.png", ";\\": "getlost.png", ":oops:": "oops.png", ":-|": "none.png", ";D": "grin.png", ";O": "shocked.png", "@->-": "flower.png", ";0": "shocked.png", ":zzz:": "zzz.png", ":cool2:": "cool2.png", "^_^": "pleased.png", ":)))": "grin.png", ";)": "blink.png", ";/": "getlost.png", ":-*": "kiss.png", ":-(": "sad.png", ":-)": "smile.png", "8-[]": "scared.png", ":cool:": "cool.png", ":kiss:": "kiss.png", ":notes:": "notes.png", ":calm:": "calm.png", ":-0": "shocked.png", ":greenstar:": "greenstar.png", ">:][": "angry.png", ">:]]": "evil2.png", "B))": "cool2.png", ">:)": "evil.png", ">:(": "angry3.png", ">:/": "angry2.png", ":lol:": "lol.png", ":scared:": "scared.png", ">:>": "evil.png", ">:<": "angry3.png", ">:D": "evil2.png", "B]]": "cool2.png", ">:((": "angry3.png", ">:[": "angry3.png", ":sick:": "unwell.png", ":-/": "getlost.png", ":cry:": "cry.png", "<3": "heart.png", ":leaf:": "leaf.png", ">:))": "evil2.png", ":bluestar:": "bluestar.png", ";-0": "shocked.png", ":weed:": "leaf.png", ":zzzz:": "zzz.png", ":sing:": "notes.png", ":yellowstar:": "yellowstar.png", ";-/": "getlost.png", ";-)": "blink.png", ":dead:": "dead.png", ";-S": "none2.png", "^^": "pleased.png", ";-P": "tongue.png", ";-]": "blink.png", ";-\\": "getlost.png", ":flower:": "flower.png", ":puke:": "unwell.png", ";-O": "shocked.png", ":love:": "heart.png", ";-o": "shocked.png", ":))))": "grin.png", ":))": "grin.png"}

Binary file not shown.

After

Width:  |  Height:  |  Size: 914 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 956 B

BIN
toxygen/smileys/ksk/cry.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 956 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 913 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 888 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 929 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 935 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 921 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 822 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 920 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 829 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 996 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 913 B

BIN
toxygen/smileys/ksk/lol.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 957 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 882 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 890 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 751 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 989 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 937 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 782 B

BIN
toxygen/smileys/ksk/sad.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 914 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 897 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 967 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 885 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 886 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 918 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 888 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 792 B

BIN
toxygen/smileys/ksk/zzz.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 990 B

BIN
toxygen/stickers/tox/tox_logo.png Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 31 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 27 KiB

View File

@ -2,6 +2,10 @@ import json
import urllib.request
from util import log
import settings
try:
from PySide import QtNetwork, QtCore
except:
from PyQt4 import QtNetwork, QtCore
def tox_dns(email):
@ -14,40 +18,40 @@ def tox_dns(email):
data = {"action": 3, "name": "{}".format(email)}
urls = ('https://{}/api'.format(site), 'http://{}/api'.format(site))
s = settings.Settings.get_instance()
if s['proxy_type'] != 2: # no proxy or http proxy
proxy = s['proxy_host'] + ':' + s['proxy_port'] if s['proxy_type'] else None
if not s['proxy_type']: # no proxy
for url in urls:
try:
return send_request(url, data, proxy)
return send_request(url, data)
except Exception as ex:
log('TOX DNS ERROR: ' + str(ex))
else: # proxy
netman = QtNetwork.QNetworkAccessManager()
proxy = QtNetwork.QNetworkProxy()
proxy.setType(QtNetwork.QNetworkProxy.Socks5Proxy if s['proxy_type'] == 2 else QtNetwork.QNetworkProxy.HttpProxy)
proxy.setHostName(s['proxy_host'])
proxy.setPort(s['proxy_port'])
netman.setProxy(proxy)
for url in urls:
try:
request = QtNetwork.QNetworkRequest(url)
request.setHeader(QtNetwork.QNetworkRequest.ContentTypeHeader, "application/json")
reply = netman.post(request, bytes(json.dumps(data), 'utf-8'))
while not reply.isFinished():
QtCore.QThread.msleep(1)
QtCore.QCoreApplication.processEvents()
data = bytes(reply.readAll().data())
result = json.loads(str(data, 'utf-8'))
if not result['c']:
return result['tox_id']
except Exception as ex:
log('TOX DNS ERROR: ' + str(ex))
else: # SOCKS5 proxy
try:
import socks
import socket
import requests
socks.set_default_proxy(socks.SOCKS5, s['proxy_host'], s['proxy_port'])
socket.socket = socks.socksocket
for url in urls:
try:
r = requests.get(url)
res = json.loads(r.text)
if not res['c']:
return res['tox_id']
else:
raise LookupError()
except Exception as ex:
log('TOX DNS ERROR: ' + str(ex))
except:
pass
return None # error
def send_request(url, data, proxy):
def send_request(url, data):
req = urllib.request.Request(url)
if proxy is not None:
req.set_proxy(proxy, 'http')
req.add_header('Content-Type', 'application/json')
response = urllib.request.urlopen(req, bytes(json.dumps(data), 'utf-8'))
res = json.loads(str(response.read(), 'utf-8'))

View File

@ -3,22 +3,22 @@
<context>
<name>AddContact</name>
<message>
<location filename="menu.py" line="70"/>
<location filename="menu.py" line="75"/>
<source>Add contact</source>
<translation>Add contact</translation>
</message>
<message>
<location filename="menu.py" line="72"/>
<location filename="menu.py" line="77"/>
<source>TOX ID:</source>
<translation>TOX ID:</translation>
</message>
<message>
<location filename="menu.py" line="73"/>
<location filename="menu.py" line="78"/>
<source>Message:</source>
<translation>Message:</translation>
</message>
<message>
<location filename="menu.py" line="74"/>
<location filename="menu.py" line="79"/>
<source>TOX ID or public key of contact</source>
<translation type="unfinished"></translation>
</message>
@ -34,32 +34,32 @@
<context>
<name>Form</name>
<message>
<location filename="menu.py" line="71"/>
<location filename="menu.py" line="76"/>
<source>Send request</source>
<translation>Send request</translation>
</message>
<message>
<location filename="menu.py" line="334"/>
<location filename="menu.py" line="339"/>
<source>IPv6</source>
<translation>IPv6</translation>
</message>
<message>
<location filename="menu.py" line="335"/>
<location filename="menu.py" line="340"/>
<source>UDP</source>
<translation>UDP</translation>
</message>
<message>
<location filename="menu.py" line="336"/>
<location filename="menu.py" line="341"/>
<source>Proxy</source>
<translation>Proxy</translation>
</message>
<message>
<location filename="menu.py" line="337"/>
<location filename="menu.py" line="342"/>
<source>IP:</source>
<translation>IP:</translation>
</message>
<message>
<location filename="menu.py" line="338"/>
<location filename="menu.py" line="343"/>
<source>Port:</source>
<translation>Port:</translation>
</message>
@ -69,12 +69,12 @@
<translation type="obsolete">Online contacts</translation>
</message>
<message>
<location filename="menu.py" line="340"/>
<location filename="menu.py" line="345"/>
<source>HTTP</source>
<translation>HTTP</translation>
</message>
<message>
<location filename="menu.py" line="342"/>
<location filename="menu.py" line="347"/>
<source>WARNING:
using proxy with enabled UDP
can produce IP leak</source>
@ -84,98 +84,98 @@ can produce IP leak</source>
<context>
<name>MainWindow</name>
<message>
<location filename="mainscreen.py" line="101"/>
<location filename="mainscreen.py" line="104"/>
<source>Profile</source>
<translation></translation>
</message>
<message>
<location filename="mainscreen.py" line="107"/>
<location filename="mainscreen.py" line="110"/>
<source>Settings</source>
<translation></translation>
</message>
<message>
<location filename="mainscreen.py" line="359"/>
<location filename="mainscreen.py" line="364"/>
<source>About</source>
<translation></translation>
</message>
<message>
<location filename="mainscreen.py" line="100"/>
<location filename="mainscreen.py" line="103"/>
<source>Add contact</source>
<translation></translation>
</message>
<message>
<location filename="mainscreen.py" line="102"/>
<location filename="mainscreen.py" line="105"/>
<source>Privacy</source>
<translation></translation>
</message>
<message>
<location filename="mainscreen.py" line="103"/>
<location filename="mainscreen.py" line="106"/>
<source>Interface</source>
<translation></translation>
</message>
<message>
<location filename="mainscreen.py" line="104"/>
<location filename="mainscreen.py" line="107"/>
<source>Notifications</source>
<translation></translation>
</message>
<message>
<location filename="mainscreen.py" line="105"/>
<location filename="mainscreen.py" line="108"/>
<source>Network</source>
<translation></translation>
</message>
<message>
<location filename="mainscreen.py" line="106"/>
<location filename="mainscreen.py" line="109"/>
<source>About program</source>
<translation></translation>
</message>
<message>
<location filename="profile.py" line="753"/>
<location filename="profile.py" line="761"/>
<source>User {} wants to add you to contact list. Message:
{}</source>
<translation></translation>
</message>
<message>
<location filename="profile.py" line="755"/>
<location filename="profile.py" line="763"/>
<source>Friend request</source>
<translation></translation>
</message>
<message>
<location filename="mainscreen.py" line="430"/>
<location filename="mainscreen.py" line="455"/>
<source>Choose file</source>
<translation>Choose file</translation>
</message>
<message>
<location filename="mainscreen.py" line="493"/>
<location filename="mainscreen.py" line="518"/>
<source>Disallow auto accept</source>
<translation></translation>
</message>
<message>
<location filename="mainscreen.py" line="494"/>
<location filename="mainscreen.py" line="519"/>
<source>Allow auto accept</source>
<translation></translation>
</message>
<message>
<location filename="mainscreen.py" line="496"/>
<location filename="mainscreen.py" line="521"/>
<source>Set alias</source>
<translation></translation>
</message>
<message>
<location filename="mainscreen.py" line="497"/>
<location filename="mainscreen.py" line="522"/>
<source>Clear history</source>
<translation></translation>
</message>
<message>
<location filename="mainscreen.py" line="504"/>
<location filename="mainscreen.py" line="529"/>
<source>Remove friend</source>
<translation></translation>
</message>
<message>
<location filename="profile.py" line="592"/>
<location filename="profile.py" line="600"/>
<source>Enter new alias for friend {} or leave empty to use friend&apos;s name:</source>
<translation>Enter new alias for friend {} or leave empty to use friend&apos;s name:</translation>
</message>
<message>
<location filename="mainscreen.py" line="108"/>
<location filename="mainscreen.py" line="111"/>
<source>Audio</source>
<translation>Audio</translation>
</message>
@ -185,24 +185,24 @@ can produce IP leak</source>
<translation type="obsolete">Find contact</translation>
</message>
<message>
<location filename="profile.py" line="725"/>
<location filename="profile.py" line="733"/>
<source>Friend added</source>
<translation>Friend added</translation>
</message>
<message>
<location filename="mainscreen.py" line="360"/>
<location filename="mainscreen.py" line="365"/>
<source>Toxygen is Tox client written on Python.
Version: </source>
<translation>Toxygen is Tox client written on Python.
Version:</translation>
</message>
<message>
<location filename="profile.py" line="726"/>
<location filename="profile.py" line="734"/>
<source>Friend added without sending friend request</source>
<translation>Friend added without sending friend request</translation>
</message>
<message>
<location filename="list_items.py" line="486"/>
<location filename="list_items.py" line="495"/>
<source>Choose folder</source>
<translation>Choose folder</translation>
</message>
@ -217,47 +217,47 @@ Version:</translation>
<translation type="obsolete">Send file</translation>
</message>
<message>
<location filename="mainscreen.py" line="110"/>
<location filename="mainscreen.py" line="113"/>
<source>Send message</source>
<translation>Send message</translation>
</message>
<message>
<location filename="mainscreen.py" line="111"/>
<location filename="mainscreen.py" line="114"/>
<source>Start audio call with friend</source>
<translation>Start audio call with friend</translation>
</message>
<message>
<location filename="mainscreen.py" line="509"/>
<location filename="mainscreen.py" line="534"/>
<source>Plugins</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="mainscreen.py" line="96"/>
<location filename="mainscreen.py" line="99"/>
<source>List of plugins</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="mainscreen.py" line="109"/>
<location filename="mainscreen.py" line="112"/>
<source>Search</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="mainscreen.py" line="113"/>
<location filename="mainscreen.py" line="116"/>
<source>All</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="mainscreen.py" line="114"/>
<location filename="mainscreen.py" line="117"/>
<source>Online</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="mainscreen.py" line="505"/>
<location filename="mainscreen.py" line="530"/>
<source>Notes</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="mainscreen.py" line="527"/>
<location filename="mainscreen.py" line="552"/>
<source>Notes about user</source>
<translation type="unfinished"></translation>
</message>
@ -307,7 +307,7 @@ Version:</translation>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="profile.py" line="259"/>
<location filename="profile.py" line="261"/>
<source>User {} is now known as {}</source>
<translation type="unfinished"></translation>
</message>
@ -317,35 +317,75 @@ Version:</translation>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="mainscreen.py" line="94"/>
<location filename="mainscreen.py" line="97"/>
<source>Lock</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="mainscreen.py" line="403"/>
<location filename="mainscreen.py" line="428"/>
<source>Cannot lock app</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="mainscreen.py" line="406"/>
<location filename="mainscreen.py" line="431"/>
<source>Error. Profile password is not set.</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="mainscreen.py" line="499"/>
<location filename="mainscreen.py" line="524"/>
<source>Name</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="mainscreen.py" line="500"/>
<location filename="mainscreen.py" line="525"/>
<source>Status message</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="mainscreen.py" line="501"/>
<location filename="mainscreen.py" line="526"/>
<source>Public key</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="main.py" line="105"/>
<source>Error</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="main.py" line="108"/>
<source>Profile with this name already exists</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="menu.py" line="654"/>
<source>Choose folder with sticker pack</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="menu.py" line="668"/>
<source>Choose folder with smiley pack</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="mainscreen.py" line="119"/>
<source>Import plugin</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="mainscreen.py" line="406"/>
<source>Choose folder with plugin</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="mainscreen.py" line="415"/>
<source>Restart Toxygen</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="mainscreen.py" line="418"/>
<source>Plugin will be loaded after restart</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>MenuWindow</name>
@ -398,12 +438,12 @@ Version:</translation>
<context>
<name>NetworkSettings</name>
<message>
<location filename="menu.py" line="333"/>
<location filename="menu.py" line="338"/>
<source>Network settings</source>
<translation>Network settings</translation>
</message>
<message>
<location filename="menu.py" line="339"/>
<location filename="menu.py" line="344"/>
<source>Restart TOX core</source>
<translation>Restart Tox core</translation>
</message>
@ -411,12 +451,12 @@ Version:</translation>
<context>
<name>PluginWindow</name>
<message>
<location filename="plugins/plugin_super_class.py" line="132"/>
<location filename="plugins/plugin_super_class.py" line="133"/>
<source>List of commands for plugin {}</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="plugins/plugin_super_class.py" line="133"/>
<location filename="plugins/plugin_super_class.py" line="134"/>
<source>No commands available</source>
<translation type="unfinished"></translation>
</message>
@ -424,42 +464,42 @@ Version:</translation>
<context>
<name>PluginsForm</name>
<message>
<location filename="menu.py" line="761"/>
<location filename="menu.py" line="812"/>
<source>Plugins</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="menu.py" line="762"/>
<location filename="menu.py" line="813"/>
<source>Open selected plugin</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="menu.py" line="775"/>
<location filename="menu.py" line="826"/>
<source>No GUI found for this plugin</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="menu.py" line="791"/>
<location filename="menu.py" line="842"/>
<source>No description available</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="menu.py" line="807"/>
<location filename="menu.py" line="858"/>
<source>Disable plugin</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="menu.py" line="809"/>
<location filename="menu.py" line="860"/>
<source>Enable plugin</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="menu.py" line="799"/>
<location filename="menu.py" line="850"/>
<source>No plugins found</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="menu.py" line="776"/>
<location filename="menu.py" line="827"/>
<source>Error</source>
<translation type="unfinished"></translation>
</message>
@ -467,122 +507,122 @@ Version:</translation>
<context>
<name>ProfileSettingsForm</name>
<message>
<location filename="menu.py" line="169"/>
<location filename="menu.py" line="174"/>
<source>Export profile</source>
<translation></translation>
</message>
<message>
<location filename="menu.py" line="170"/>
<location filename="menu.py" line="175"/>
<source>Profile settings</source>
<translation></translation>
</message>
<message>
<location filename="menu.py" line="171"/>
<location filename="menu.py" line="176"/>
<source>Name:</source>
<translation></translation>
</message>
<message>
<location filename="menu.py" line="172"/>
<location filename="menu.py" line="177"/>
<source>Status:</source>
<translation></translation>
</message>
<message>
<location filename="menu.py" line="173"/>
<location filename="menu.py" line="178"/>
<source>TOX ID:</source>
<translation></translation>
</message>
<message>
<location filename="menu.py" line="174"/>
<location filename="menu.py" line="179"/>
<source>Copy TOX ID</source>
<translation></translation>
</message>
<message>
<location filename="menu.py" line="175"/>
<location filename="menu.py" line="180"/>
<source>New avatar</source>
<translation></translation>
</message>
<message>
<location filename="menu.py" line="176"/>
<location filename="menu.py" line="181"/>
<source>Reset avatar</source>
<translation></translation>
</message>
<message>
<location filename="menu.py" line="177"/>
<location filename="menu.py" line="182"/>
<source>New NoSpam</source>
<translation>New NoSpam</translation>
</message>
<message>
<location filename="menu.py" line="178"/>
<location filename="menu.py" line="183"/>
<source>Profile password</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="menu.py" line="179"/>
<location filename="menu.py" line="184"/>
<source>Password (at least 8 symbols)</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="menu.py" line="180"/>
<location filename="menu.py" line="185"/>
<source>Confirm password</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="menu.py" line="181"/>
<location filename="menu.py" line="186"/>
<source>Set password</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="menu.py" line="221"/>
<location filename="menu.py" line="226"/>
<source>Passwords do not match</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="menu.py" line="183"/>
<location filename="menu.py" line="188"/>
<source>Leaving blank will reset current password</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="menu.py" line="184"/>
<location filename="menu.py" line="189"/>
<source>There is no way to recover lost passwords</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="menu.py" line="217"/>
<location filename="menu.py" line="222"/>
<source>Password must be at least 8 symbols</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="menu.py" line="250"/>
<location filename="menu.py" line="255"/>
<source>Choose avatar</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="menu.py" line="185"/>
<location filename="menu.py" line="190"/>
<source>Online</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="menu.py" line="186"/>
<location filename="menu.py" line="191"/>
<source>Away</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="menu.py" line="187"/>
<location filename="menu.py" line="192"/>
<source>Busy</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="menu.py" line="202"/>
<location filename="menu.py" line="207"/>
<source>Mark as not default profile</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="menu.py" line="206"/>
<location filename="menu.py" line="211"/>
<source>Mark as default profile</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="menu.py" line="188"/>
<location filename="menu.py" line="193"/>
<source>Copy public key</source>
<translation type="unfinished"></translation>
</message>
@ -619,11 +659,6 @@ Version:</translation>
<source>Since v0.1.3 Toxygen supports plugins. &lt;a href=&quot;https://github.com/xveduk/toxygen/blob/master/docs/plugins.md&quot;&gt;Read more&lt;/a&gt;</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="mainscreen_widgets.py" line="361"/>
<source>New in Toxygen v0.2.2:&lt;br&gt;Users can lock application using profile password.&lt;br&gt;Compact contact list support&lt;br&gt;Bug fixes&lt;br&gt;Tox DNS improvements</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="mainscreen_widgets.py" line="341"/>
<source>Right click on screenshot button hides app to tray during screenshot.</source>
@ -640,25 +675,40 @@ Version:</translation>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="mainscreen_widgets.py" line="369"/>
<location filename="mainscreen_widgets.py" line="377"/>
<source>Set new NoSpam to avoid spam friend requests: Profile -&gt; Settings -&gt; Set new NoSpam.</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="mainscreen_widgets.py" line="361"/>
<source>New in Toxygen v0.2.3:&lt;br&gt;TCS compliance&lt;br&gt;Plugins, smileys and stickers import&lt;br&gt;Bug fixes</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="mainscreen_widgets.py" line="369"/>
<source>Delete single message in chat: make right click on spinner or message time and choose &quot;Delete&quot; in menu</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="mainscreen_widgets.py" line="373"/>
<source>Use right click on inline image to save it</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>audioSettingsForm</name>
<message>
<location filename="menu.py" line="718"/>
<location filename="menu.py" line="769"/>
<source>Audio settings</source>
<translation>Audio settings</translation>
</message>
<message>
<location filename="menu.py" line="719"/>
<location filename="menu.py" line="770"/>
<source>Input device:</source>
<translation>Input device:</translation>
</message>
<message>
<location filename="menu.py" line="720"/>
<location filename="menu.py" line="771"/>
<source>Output device:</source>
<translation>Output device:</translation>
</message>
@ -666,32 +716,32 @@ Version:</translation>
<context>
<name>incoming_call</name>
<message>
<location filename="profile.py" line="1132"/>
<location filename="profile.py" line="1141"/>
<source>Incoming video call</source>
<translation>Incoming video call</translation>
</message>
<message>
<location filename="profile.py" line="1135"/>
<location filename="profile.py" line="1144"/>
<source>Incoming audio call</source>
<translation>Incoming audio call</translation>
</message>
<message>
<location filename="profile.py" line="1115"/>
<location filename="profile.py" line="1124"/>
<source>Outgoing video call</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="profile.py" line="1118"/>
<location filename="profile.py" line="1127"/>
<source>Outgoing audio call</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="profile.py" line="1164"/>
<location filename="profile.py" line="1173"/>
<source>Call declined</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="profile.py" line="1166"/>
<location filename="profile.py" line="1175"/>
<source>Call finished</source>
<translation type="unfinished"></translation>
</message>
@ -699,60 +749,75 @@ Version:</translation>
<context>
<name>interfaceForm</name>
<message>
<location filename="menu.py" line="619"/>
<location filename="menu.py" line="637"/>
<source>Interface settings</source>
<translation></translation>
</message>
<message>
<location filename="menu.py" line="620"/>
<location filename="menu.py" line="638"/>
<source>Theme:</source>
<translation></translation>
</message>
<message>
<location filename="menu.py" line="621"/>
<location filename="menu.py" line="639"/>
<source>Language:</source>
<translation></translation>
</message>
<message>
<location filename="menu.py" line="622"/>
<location filename="menu.py" line="640"/>
<source>Smileys</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="menu.py" line="623"/>
<location filename="menu.py" line="641"/>
<source>Smiley pack:</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="menu.py" line="624"/>
<location filename="menu.py" line="642"/>
<source>Mirror mode</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="menu.py" line="625"/>
<location filename="menu.py" line="643"/>
<source>Messages font size:</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="menu.py" line="667"/>
<location filename="menu.py" line="718"/>
<source>Restart app to apply settings</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="menu.py" line="668"/>
<location filename="menu.py" line="719"/>
<source>Restart required</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="menu.py" line="626"/>
<location filename="menu.py" line="644"/>
<source>Select unread messages notification color</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="menu.py" line="627"/>
<location filename="menu.py" line="645"/>
<source>Compact contact list</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="menu.py" line="646"/>
<source>Import smiley pack</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="menu.py" line="647"/>
<source>Import sticker pack</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="menu.py" line="636"/>
<source>Show avatars in chat</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>login</name>
@ -802,30 +867,35 @@ Version:</translation>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="main.py" line="127"/>
<location filename="main.py" line="154"/>
<source>Other instance of Toxygen uses this profile or profile was not properly closed. Continue?</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="main.py" line="120"/>
<source>Do you want to set profile password?</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>notificationsForm</name>
<message>
<location filename="menu.py" line="530"/>
<location filename="menu.py" line="535"/>
<source>Notification settings</source>
<translation></translation>
</message>
<message>
<location filename="menu.py" line="531"/>
<location filename="menu.py" line="536"/>
<source>Enable notifications</source>
<translation></translation>
</message>
<message>
<location filename="menu.py" line="532"/>
<location filename="menu.py" line="537"/>
<source>Enable call&apos;s sound</source>
<translation></translation>
</message>
<message>
<location filename="menu.py" line="533"/>
<location filename="menu.py" line="538"/>
<source>Enable sound notifications</source>
<translation></translation>
</message>
@ -833,72 +903,72 @@ Version:</translation>
<context>
<name>privacySettings</name>
<message>
<location filename="menu.py" line="426"/>
<location filename="menu.py" line="431"/>
<source>Privacy settings</source>
<translation></translation>
</message>
<message>
<location filename="menu.py" line="427"/>
<location filename="menu.py" line="432"/>
<source>Save chat history</source>
<translation></translation>
</message>
<message>
<location filename="menu.py" line="428"/>
<location filename="menu.py" line="433"/>
<source>Allow file auto accept</source>
<translation></translation>
</message>
<message>
<location filename="menu.py" line="429"/>
<location filename="menu.py" line="434"/>
<source>Send typing notifications</source>
<translation></translation>
</message>
<message>
<location filename="menu.py" line="430"/>
<location filename="menu.py" line="435"/>
<source>Auto accept default path:</source>
<translation></translation>
</message>
<message>
<location filename="menu.py" line="431"/>
<location filename="menu.py" line="436"/>
<source>Change</source>
<translation></translation>
</message>
<message>
<location filename="menu.py" line="432"/>
<location filename="menu.py" line="437"/>
<source>Allow inlines</source>
<translation></translation>
</message>
<message>
<location filename="menu.py" line="477"/>
<location filename="menu.py" line="482"/>
<source>Chat history</source>
<translation></translation>
</message>
<message>
<location filename="menu.py" line="480"/>
<location filename="menu.py" line="485"/>
<source>History will be cleaned! Continue?</source>
<translation></translation>
</message>
<message>
<location filename="menu.py" line="434"/>
<location filename="menu.py" line="439"/>
<source>Blocked users:</source>
<translation>Blocked users:</translation>
</message>
<message>
<location filename="menu.py" line="435"/>
<location filename="menu.py" line="440"/>
<source>Unblock</source>
<translation>Unblock</translation>
</message>
<message>
<location filename="menu.py" line="436"/>
<location filename="menu.py" line="441"/>
<source>Block user</source>
<translation>Block user</translation>
</message>
<message>
<location filename="menu.py" line="448"/>
<location filename="menu.py" line="453"/>
<source>Add to friend list</source>
<translation>Add to friend list</translation>
</message>
<message>
<location filename="menu.py" line="449"/>
<location filename="menu.py" line="454"/>
<source>Do you want to add this user to friend list?</source>
<translation>Do you want to add this user to friend list?</translation>
</message>
@ -908,12 +978,12 @@ Version:</translation>
<translation type="obsolete">Block by TOX ID:</translation>
</message>
<message>
<location filename="menu.py" line="433"/>
<location filename="menu.py" line="438"/>
<source>Block by public key:</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="menu.py" line="437"/>
<location filename="menu.py" line="442"/>
<source>Save unsent messages only</source>
<translation type="unfinished"></translation>
</message>
@ -921,32 +991,32 @@ Version:</translation>
<context>
<name>tray</name>
<message>
<location filename="main.py" line="176"/>
<location filename="main.py" line="203"/>
<source>Open Toxygen</source>
<translation></translation>
</message>
<message>
<location filename="main.py" line="185"/>
<location filename="main.py" line="212"/>
<source>Exit</source>
<translation></translation>
</message>
<message>
<location filename="main.py" line="177"/>
<location filename="main.py" line="204"/>
<source>Set status</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="main.py" line="178"/>
<location filename="main.py" line="205"/>
<source>Online</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="main.py" line="179"/>
<location filename="main.py" line="206"/>
<source>Away</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="main.py" line="180"/>
<location filename="main.py" line="207"/>
<source>Busy</source>
<translation type="unfinished"></translation>
</message>

View File

@ -3,22 +3,22 @@
<context>
<name>AddContact</name>
<message>
<location filename="menu.py" line="70"/>
<location filename="menu.py" line="75"/>
<source>Add contact</source>
<translation>Rajouter un contact</translation>
</message>
<message>
<location filename="menu.py" line="72"/>
<location filename="menu.py" line="77"/>
<source>TOX ID:</source>
<translation>ID TOX :</translation>
</message>
<message>
<location filename="menu.py" line="73"/>
<location filename="menu.py" line="78"/>
<source>Message:</source>
<translation>Message :</translation>
</message>
<message>
<location filename="menu.py" line="74"/>
<location filename="menu.py" line="79"/>
<source>TOX ID or public key of contact</source>
<translation type="unfinished"></translation>
</message>
@ -34,32 +34,32 @@
<context>
<name>Form</name>
<message>
<location filename="menu.py" line="71"/>
<location filename="menu.py" line="76"/>
<source>Send request</source>
<translation>Envoyer une demande</translation>
</message>
<message>
<location filename="menu.py" line="334"/>
<location filename="menu.py" line="339"/>
<source>IPv6</source>
<translation>IPv6</translation>
</message>
<message>
<location filename="menu.py" line="335"/>
<location filename="menu.py" line="340"/>
<source>UDP</source>
<translation>UDP</translation>
</message>
<message>
<location filename="menu.py" line="336"/>
<location filename="menu.py" line="341"/>
<source>Proxy</source>
<translation>Proxy</translation>
</message>
<message>
<location filename="menu.py" line="337"/>
<location filename="menu.py" line="342"/>
<source>IP:</source>
<translation>IP :</translation>
</message>
<message>
<location filename="menu.py" line="338"/>
<location filename="menu.py" line="343"/>
<source>Port:</source>
<translation>Port :</translation>
</message>
@ -69,12 +69,12 @@
<translation type="obsolete">Contacts connectés</translation>
</message>
<message>
<location filename="menu.py" line="340"/>
<location filename="menu.py" line="345"/>
<source>HTTP</source>
<translation>HTTP</translation>
</message>
<message>
<location filename="menu.py" line="342"/>
<location filename="menu.py" line="347"/>
<source>WARNING:
using proxy with enabled UDP
can produce IP leak</source>
@ -84,58 +84,58 @@ can produce IP leak</source>
<context>
<name>MainWindow</name>
<message>
<location filename="mainscreen.py" line="101"/>
<location filename="mainscreen.py" line="104"/>
<source>Profile</source>
<translation>Profile</translation>
</message>
<message>
<location filename="mainscreen.py" line="107"/>
<location filename="mainscreen.py" line="110"/>
<source>Settings</source>
<translation>Paramêtres</translation>
</message>
<message>
<location filename="mainscreen.py" line="359"/>
<location filename="mainscreen.py" line="364"/>
<source>About</source>
<translation>À Propos</translation>
</message>
<message>
<location filename="mainscreen.py" line="100"/>
<location filename="mainscreen.py" line="103"/>
<source>Add contact</source>
<translation>Rajouter un contact</translation>
</message>
<message>
<location filename="mainscreen.py" line="102"/>
<location filename="mainscreen.py" line="105"/>
<source>Privacy</source>
<translation>Confidentialité</translation>
</message>
<message>
<location filename="mainscreen.py" line="103"/>
<location filename="mainscreen.py" line="106"/>
<source>Interface</source>
<translation>Interface</translation>
</message>
<message>
<location filename="mainscreen.py" line="104"/>
<location filename="mainscreen.py" line="107"/>
<source>Notifications</source>
<translation>Notifications</translation>
</message>
<message>
<location filename="mainscreen.py" line="105"/>
<location filename="mainscreen.py" line="108"/>
<source>Network</source>
<translation>Réseau</translation>
</message>
<message>
<location filename="mainscreen.py" line="106"/>
<location filename="mainscreen.py" line="109"/>
<source>About program</source>
<translation>À propos du programme</translation>
</message>
<message>
<location filename="profile.py" line="753"/>
<location filename="profile.py" line="761"/>
<source>User {} wants to add you to contact list. Message:
{}</source>
<translation>L&apos;Utilisateur {} veut vout rajouter à sa liste de contacts. Message : {}</translation>
</message>
<message>
<location filename="profile.py" line="755"/>
<location filename="profile.py" line="763"/>
<source>Friend request</source>
<translation>Demande d&apos;amis</translation>
</message>
@ -145,27 +145,27 @@ can produce IP leak</source>
<translation type="obsolete">Toxygen est un client Tox écris en Python 2.7. Version : </translation>
</message>
<message>
<location filename="mainscreen.py" line="430"/>
<location filename="mainscreen.py" line="455"/>
<source>Choose file</source>
<translation>Choisir un fichier</translation>
</message>
<message>
<location filename="mainscreen.py" line="493"/>
<location filename="mainscreen.py" line="518"/>
<source>Disallow auto accept</source>
<translation>Désactiver l&apos;auto-réception</translation>
</message>
<message>
<location filename="mainscreen.py" line="494"/>
<location filename="mainscreen.py" line="519"/>
<source>Allow auto accept</source>
<translation>Activer l&apos;auto-réception</translation>
</message>
<message>
<location filename="mainscreen.py" line="496"/>
<location filename="mainscreen.py" line="521"/>
<source>Set alias</source>
<translation>Définir un alias</translation>
</message>
<message>
<location filename="mainscreen.py" line="497"/>
<location filename="mainscreen.py" line="522"/>
<source>Clear history</source>
<translation>Vider l&apos;historique</translation>
</message>
@ -175,17 +175,17 @@ can produce IP leak</source>
<translation type="obsolete">Copier la clé publique</translation>
</message>
<message>
<location filename="mainscreen.py" line="504"/>
<location filename="mainscreen.py" line="529"/>
<source>Remove friend</source>
<translation>Retirer un ami</translation>
</message>
<message>
<location filename="profile.py" line="592"/>
<location filename="profile.py" line="600"/>
<source>Enter new alias for friend {} or leave empty to use friend&apos;s name:</source>
<translation>Entrez un nouvel alias pour l&apos;ami {} ou laissez vide pour garder son nom de base :</translation>
</message>
<message>
<location filename="mainscreen.py" line="108"/>
<location filename="mainscreen.py" line="111"/>
<source>Audio</source>
<translation>Audio</translation>
</message>
@ -195,24 +195,24 @@ can produce IP leak</source>
<translation type="obsolete">Trouver le contact</translation>
</message>
<message>
<location filename="profile.py" line="725"/>
<location filename="profile.py" line="733"/>
<source>Friend added</source>
<translation>Ami rajouté</translation>
</message>
<message>
<location filename="mainscreen.py" line="360"/>
<location filename="mainscreen.py" line="365"/>
<source>Toxygen is Tox client written on Python.
Version: </source>
<translation>Toxygen est un client Tox écrit en Python.
Version :</translation>
</message>
<message>
<location filename="profile.py" line="726"/>
<location filename="profile.py" line="734"/>
<source>Friend added without sending friend request</source>
<translation>Ami rajouté sans avoir envoyé de demande</translation>
</message>
<message>
<location filename="list_items.py" line="486"/>
<location filename="list_items.py" line="495"/>
<source>Choose folder</source>
<translation>Choisir le dossier</translation>
</message>
@ -227,47 +227,47 @@ Version :</translation>
<translation type="obsolete">Envoyer le fichier</translation>
</message>
<message>
<location filename="mainscreen.py" line="110"/>
<location filename="mainscreen.py" line="113"/>
<source>Send message</source>
<translation>Envoyer le message</translation>
</message>
<message>
<location filename="mainscreen.py" line="111"/>
<location filename="mainscreen.py" line="114"/>
<source>Start audio call with friend</source>
<translation>Lancer un appel audio avec un ami</translation>
</message>
<message>
<location filename="mainscreen.py" line="509"/>
<location filename="mainscreen.py" line="534"/>
<source>Plugins</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="mainscreen.py" line="96"/>
<location filename="mainscreen.py" line="99"/>
<source>List of plugins</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="mainscreen.py" line="109"/>
<location filename="mainscreen.py" line="112"/>
<source>Search</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="mainscreen.py" line="113"/>
<location filename="mainscreen.py" line="116"/>
<source>All</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="mainscreen.py" line="114"/>
<location filename="mainscreen.py" line="117"/>
<source>Online</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="mainscreen.py" line="505"/>
<location filename="mainscreen.py" line="530"/>
<source>Notes</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="mainscreen.py" line="527"/>
<location filename="mainscreen.py" line="552"/>
<source>Notes about user</source>
<translation type="unfinished"></translation>
</message>
@ -317,7 +317,7 @@ Version :</translation>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="profile.py" line="259"/>
<location filename="profile.py" line="261"/>
<source>User {} is now known as {}</source>
<translation type="unfinished"></translation>
</message>
@ -327,35 +327,75 @@ Version :</translation>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="mainscreen.py" line="94"/>
<location filename="mainscreen.py" line="97"/>
<source>Lock</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="mainscreen.py" line="403"/>
<location filename="mainscreen.py" line="428"/>
<source>Cannot lock app</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="mainscreen.py" line="406"/>
<location filename="mainscreen.py" line="431"/>
<source>Error. Profile password is not set.</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="mainscreen.py" line="499"/>
<location filename="mainscreen.py" line="524"/>
<source>Name</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="mainscreen.py" line="500"/>
<location filename="mainscreen.py" line="525"/>
<source>Status message</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="mainscreen.py" line="501"/>
<location filename="mainscreen.py" line="526"/>
<source>Public key</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="main.py" line="105"/>
<source>Error</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="main.py" line="108"/>
<source>Profile with this name already exists</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="menu.py" line="654"/>
<source>Choose folder with sticker pack</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="menu.py" line="668"/>
<source>Choose folder with smiley pack</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="mainscreen.py" line="119"/>
<source>Import plugin</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="mainscreen.py" line="406"/>
<source>Choose folder with plugin</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="mainscreen.py" line="415"/>
<source>Restart Toxygen</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="mainscreen.py" line="418"/>
<source>Plugin will be loaded after restart</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>MenuWindow</name>
@ -408,12 +448,12 @@ Version :</translation>
<context>
<name>NetworkSettings</name>
<message>
<location filename="menu.py" line="333"/>
<location filename="menu.py" line="338"/>
<source>Network settings</source>
<translation>Paramètres réseaux</translation>
</message>
<message>
<location filename="menu.py" line="339"/>
<location filename="menu.py" line="344"/>
<source>Restart TOX core</source>
<translation>Relancer le noyau TOX</translation>
</message>
@ -421,12 +461,12 @@ Version :</translation>
<context>
<name>PluginWindow</name>
<message>
<location filename="plugins/plugin_super_class.py" line="132"/>
<location filename="plugins/plugin_super_class.py" line="133"/>
<source>List of commands for plugin {}</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="plugins/plugin_super_class.py" line="133"/>
<location filename="plugins/plugin_super_class.py" line="134"/>
<source>No commands available</source>
<translation type="unfinished"></translation>
</message>
@ -434,42 +474,42 @@ Version :</translation>
<context>
<name>PluginsForm</name>
<message>
<location filename="menu.py" line="761"/>
<location filename="menu.py" line="812"/>
<source>Plugins</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="menu.py" line="762"/>
<location filename="menu.py" line="813"/>
<source>Open selected plugin</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="menu.py" line="775"/>
<location filename="menu.py" line="826"/>
<source>No GUI found for this plugin</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="menu.py" line="791"/>
<location filename="menu.py" line="842"/>
<source>No description available</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="menu.py" line="807"/>
<location filename="menu.py" line="858"/>
<source>Disable plugin</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="menu.py" line="809"/>
<location filename="menu.py" line="860"/>
<source>Enable plugin</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="menu.py" line="799"/>
<location filename="menu.py" line="850"/>
<source>No plugins found</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="menu.py" line="776"/>
<location filename="menu.py" line="827"/>
<source>Error</source>
<translation type="unfinished"></translation>
</message>
@ -477,122 +517,122 @@ Version :</translation>
<context>
<name>ProfileSettingsForm</name>
<message>
<location filename="menu.py" line="169"/>
<location filename="menu.py" line="174"/>
<source>Export profile</source>
<translation>Exporter le profile</translation>
</message>
<message>
<location filename="menu.py" line="170"/>
<location filename="menu.py" line="175"/>
<source>Profile settings</source>
<translation>Paramêtres du profil</translation>
</message>
<message>
<location filename="menu.py" line="171"/>
<location filename="menu.py" line="176"/>
<source>Name:</source>
<translation>Nom :</translation>
</message>
<message>
<location filename="menu.py" line="172"/>
<location filename="menu.py" line="177"/>
<source>Status:</source>
<translation>Status :</translation>
</message>
<message>
<location filename="menu.py" line="173"/>
<location filename="menu.py" line="178"/>
<source>TOX ID:</source>
<translation>ID TOX :</translation>
</message>
<message>
<location filename="menu.py" line="174"/>
<location filename="menu.py" line="179"/>
<source>Copy TOX ID</source>
<translation>Copier l&apos;ID TOX</translation>
</message>
<message>
<location filename="menu.py" line="175"/>
<location filename="menu.py" line="180"/>
<source>New avatar</source>
<translation>Nouvel avatar</translation>
</message>
<message>
<location filename="menu.py" line="176"/>
<location filename="menu.py" line="181"/>
<source>Reset avatar</source>
<translation>Réinitialiser l&apos;avatar</translation>
</message>
<message>
<location filename="menu.py" line="177"/>
<location filename="menu.py" line="182"/>
<source>New NoSpam</source>
<translation>Nouveau NoSpam</translation>
</message>
<message>
<location filename="menu.py" line="178"/>
<location filename="menu.py" line="183"/>
<source>Profile password</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="menu.py" line="179"/>
<location filename="menu.py" line="184"/>
<source>Password (at least 8 symbols)</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="menu.py" line="180"/>
<location filename="menu.py" line="185"/>
<source>Confirm password</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="menu.py" line="181"/>
<location filename="menu.py" line="186"/>
<source>Set password</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="menu.py" line="221"/>
<location filename="menu.py" line="226"/>
<source>Passwords do not match</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="menu.py" line="183"/>
<location filename="menu.py" line="188"/>
<source>Leaving blank will reset current password</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="menu.py" line="184"/>
<location filename="menu.py" line="189"/>
<source>There is no way to recover lost passwords</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="menu.py" line="217"/>
<location filename="menu.py" line="222"/>
<source>Password must be at least 8 symbols</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="menu.py" line="250"/>
<location filename="menu.py" line="255"/>
<source>Choose avatar</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="menu.py" line="185"/>
<location filename="menu.py" line="190"/>
<source>Online</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="menu.py" line="186"/>
<location filename="menu.py" line="191"/>
<source>Away</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="menu.py" line="187"/>
<location filename="menu.py" line="192"/>
<source>Busy</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="menu.py" line="202"/>
<location filename="menu.py" line="207"/>
<source>Mark as not default profile</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="menu.py" line="206"/>
<location filename="menu.py" line="211"/>
<source>Mark as default profile</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="menu.py" line="188"/>
<location filename="menu.py" line="193"/>
<source>Copy public key</source>
<translation type="unfinished">Copier la clé publique</translation>
</message>
@ -629,11 +669,6 @@ Version :</translation>
<source>Since v0.1.3 Toxygen supports plugins. &lt;a href=&quot;https://github.com/xveduk/toxygen/blob/master/docs/plugins.md&quot;&gt;Read more&lt;/a&gt;</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="mainscreen_widgets.py" line="361"/>
<source>New in Toxygen v0.2.2:&lt;br&gt;Users can lock application using profile password.&lt;br&gt;Compact contact list support&lt;br&gt;Bug fixes&lt;br&gt;Tox DNS improvements</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="mainscreen_widgets.py" line="341"/>
<source>Right click on screenshot button hides app to tray during screenshot.</source>
@ -650,25 +685,40 @@ Version :</translation>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="mainscreen_widgets.py" line="369"/>
<location filename="mainscreen_widgets.py" line="377"/>
<source>Set new NoSpam to avoid spam friend requests: Profile -&gt; Settings -&gt; Set new NoSpam.</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="mainscreen_widgets.py" line="361"/>
<source>New in Toxygen v0.2.3:&lt;br&gt;TCS compliance&lt;br&gt;Plugins, smileys and stickers import&lt;br&gt;Bug fixes</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="mainscreen_widgets.py" line="369"/>
<source>Delete single message in chat: make right click on spinner or message time and choose &quot;Delete&quot; in menu</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="mainscreen_widgets.py" line="373"/>
<source>Use right click on inline image to save it</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>audioSettingsForm</name>
<message>
<location filename="menu.py" line="718"/>
<location filename="menu.py" line="769"/>
<source>Audio settings</source>
<translation>Paramètres audio</translation>
</message>
<message>
<location filename="menu.py" line="719"/>
<location filename="menu.py" line="770"/>
<source>Input device:</source>
<translation>Péripherique d&apos;entrée :</translation>
</message>
<message>
<location filename="menu.py" line="720"/>
<location filename="menu.py" line="771"/>
<source>Output device:</source>
<translation>Péripherique de sortie :</translation>
</message>
@ -676,32 +726,32 @@ Version :</translation>
<context>
<name>incoming_call</name>
<message>
<location filename="profile.py" line="1132"/>
<location filename="profile.py" line="1141"/>
<source>Incoming video call</source>
<translation>Appel vidéo entrant</translation>
</message>
<message>
<location filename="profile.py" line="1135"/>
<location filename="profile.py" line="1144"/>
<source>Incoming audio call</source>
<translation>Appel audio entrant</translation>
</message>
<message>
<location filename="profile.py" line="1115"/>
<location filename="profile.py" line="1124"/>
<source>Outgoing video call</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="profile.py" line="1118"/>
<location filename="profile.py" line="1127"/>
<source>Outgoing audio call</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="profile.py" line="1164"/>
<location filename="profile.py" line="1173"/>
<source>Call declined</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="profile.py" line="1166"/>
<location filename="profile.py" line="1175"/>
<source>Call finished</source>
<translation type="unfinished"></translation>
</message>
@ -709,60 +759,75 @@ Version :</translation>
<context>
<name>interfaceForm</name>
<message>
<location filename="menu.py" line="619"/>
<location filename="menu.py" line="637"/>
<source>Interface settings</source>
<translation>Paramêtres de l&apos;interface</translation>
</message>
<message>
<location filename="menu.py" line="620"/>
<location filename="menu.py" line="638"/>
<source>Theme:</source>
<translation>Thème :</translation>
</message>
<message>
<location filename="menu.py" line="621"/>
<location filename="menu.py" line="639"/>
<source>Language:</source>
<translation>Langue :</translation>
</message>
<message>
<location filename="menu.py" line="622"/>
<location filename="menu.py" line="640"/>
<source>Smileys</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="menu.py" line="623"/>
<location filename="menu.py" line="641"/>
<source>Smiley pack:</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="menu.py" line="624"/>
<location filename="menu.py" line="642"/>
<source>Mirror mode</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="menu.py" line="625"/>
<location filename="menu.py" line="643"/>
<source>Messages font size:</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="menu.py" line="667"/>
<location filename="menu.py" line="718"/>
<source>Restart app to apply settings</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="menu.py" line="668"/>
<location filename="menu.py" line="719"/>
<source>Restart required</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="menu.py" line="626"/>
<location filename="menu.py" line="644"/>
<source>Select unread messages notification color</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="menu.py" line="627"/>
<location filename="menu.py" line="645"/>
<source>Compact contact list</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="menu.py" line="646"/>
<source>Import smiley pack</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="menu.py" line="647"/>
<source>Import sticker pack</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="menu.py" line="636"/>
<source>Show avatars in chat</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>login</name>
@ -817,30 +882,35 @@ Version :</translation>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="main.py" line="127"/>
<location filename="main.py" line="154"/>
<source>Other instance of Toxygen uses this profile or profile was not properly closed. Continue?</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="main.py" line="120"/>
<source>Do you want to set profile password?</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>notificationsForm</name>
<message>
<location filename="menu.py" line="530"/>
<location filename="menu.py" line="535"/>
<source>Notification settings</source>
<translation>Paramêtres de notification</translation>
</message>
<message>
<location filename="menu.py" line="531"/>
<location filename="menu.py" line="536"/>
<source>Enable notifications</source>
<translation>Activer les notifications</translation>
</message>
<message>
<location filename="menu.py" line="532"/>
<location filename="menu.py" line="537"/>
<source>Enable call&apos;s sound</source>
<translation>Activer les sons d&apos;appel</translation>
</message>
<message>
<location filename="menu.py" line="533"/>
<location filename="menu.py" line="538"/>
<source>Enable sound notifications</source>
<translation>Activer les sons de notifications</translation>
</message>
@ -848,72 +918,72 @@ Version :</translation>
<context>
<name>privacySettings</name>
<message>
<location filename="menu.py" line="426"/>
<location filename="menu.py" line="431"/>
<source>Privacy settings</source>
<translation>Paramêtres de confidentialité</translation>
</message>
<message>
<location filename="menu.py" line="427"/>
<location filename="menu.py" line="432"/>
<source>Save chat history</source>
<translation>Sauvegarder l&apos;historique de chat</translation>
</message>
<message>
<location filename="menu.py" line="428"/>
<location filename="menu.py" line="433"/>
<source>Allow file auto accept</source>
<translation>Autoriser les fichier automatiquement</translation>
</message>
<message>
<location filename="menu.py" line="429"/>
<location filename="menu.py" line="434"/>
<source>Send typing notifications</source>
<translation>Notifier la frappe</translation>
</message>
<message>
<location filename="menu.py" line="430"/>
<location filename="menu.py" line="435"/>
<source>Auto accept default path:</source>
<translation>Chemin d&apos;accès des fichiers acceptés automatiquement :</translation>
</message>
<message>
<location filename="menu.py" line="431"/>
<location filename="menu.py" line="436"/>
<source>Change</source>
<translation>Modifier</translation>
</message>
<message>
<location filename="menu.py" line="432"/>
<location filename="menu.py" line="437"/>
<source>Allow inlines</source>
<translation>Activer l&apos;auto-réception</translation>
</message>
<message>
<location filename="menu.py" line="477"/>
<location filename="menu.py" line="482"/>
<source>Chat history</source>
<translation>Historique de chat</translation>
</message>
<message>
<location filename="menu.py" line="480"/>
<location filename="menu.py" line="485"/>
<source>History will be cleaned! Continue?</source>
<translation>L&apos;Historique va être nettoyé ! Confirmer ?</translation>
</message>
<message>
<location filename="menu.py" line="434"/>
<location filename="menu.py" line="439"/>
<source>Blocked users:</source>
<translation>Utilisateurs bloqués :</translation>
</message>
<message>
<location filename="menu.py" line="435"/>
<location filename="menu.py" line="440"/>
<source>Unblock</source>
<translation>Débloquer</translation>
</message>
<message>
<location filename="menu.py" line="436"/>
<location filename="menu.py" line="441"/>
<source>Block user</source>
<translation>Bloquer l&apos;utilisateur</translation>
</message>
<message>
<location filename="menu.py" line="448"/>
<location filename="menu.py" line="453"/>
<source>Add to friend list</source>
<translation>Ajouter à la liste des amis</translation>
</message>
<message>
<location filename="menu.py" line="449"/>
<location filename="menu.py" line="454"/>
<source>Do you want to add this user to friend list?</source>
<translation>Voulez vous rajouter cet utilisateur à votre liste d&apos;amis ?</translation>
</message>
@ -923,12 +993,12 @@ Version :</translation>
<translation type="obsolete">Bloquer l&apos;ID TOX :</translation>
</message>
<message>
<location filename="menu.py" line="433"/>
<location filename="menu.py" line="438"/>
<source>Block by public key:</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="menu.py" line="437"/>
<location filename="menu.py" line="442"/>
<source>Save unsent messages only</source>
<translation type="unfinished"></translation>
</message>
@ -936,32 +1006,32 @@ Version :</translation>
<context>
<name>tray</name>
<message>
<location filename="main.py" line="176"/>
<location filename="main.py" line="203"/>
<source>Open Toxygen</source>
<translation>Ouvrir Toxygen</translation>
</message>
<message>
<location filename="main.py" line="185"/>
<location filename="main.py" line="212"/>
<source>Exit</source>
<translation>Quitter</translation>
</message>
<message>
<location filename="main.py" line="177"/>
<location filename="main.py" line="204"/>
<source>Set status</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="main.py" line="178"/>
<location filename="main.py" line="205"/>
<source>Online</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="main.py" line="179"/>
<location filename="main.py" line="206"/>
<source>Away</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="main.py" line="180"/>
<location filename="main.py" line="207"/>
<source>Busy</source>
<translation type="unfinished"></translation>
</message>

Binary file not shown.

View File

@ -1,25 +1,24 @@
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE TS>
<TS version="2.0" language="ru_RU">
<!DOCTYPE TS><TS version="1.1" language="ru_RU">
<context>
<name>AddContact</name>
<message>
<location filename="menu.py" line="70"/>
<location filename="menu.py" line="75"/>
<source>Add contact</source>
<translation>Добавить контакт</translation>
</message>
<message>
<location filename="menu.py" line="72"/>
<location filename="menu.py" line="77"/>
<source>TOX ID:</source>
<translation>TOX ID:</translation>
</message>
<message>
<location filename="menu.py" line="73"/>
<location filename="menu.py" line="78"/>
<source>Message:</source>
<translation>Сообщение:</translation>
</message>
<message>
<location filename="menu.py" line="74"/>
<location filename="menu.py" line="79"/>
<source>TOX ID or public key of contact</source>
<translation>TOX ID или публичный ключ контакта</translation>
</message>
@ -35,32 +34,32 @@
<context>
<name>Form</name>
<message>
<location filename="menu.py" line="71"/>
<location filename="menu.py" line="76"/>
<source>Send request</source>
<translation>Отправить запрос</translation>
</message>
<message>
<location filename="menu.py" line="334"/>
<location filename="menu.py" line="339"/>
<source>IPv6</source>
<translation>IPv6</translation>
</message>
<message>
<location filename="menu.py" line="335"/>
<location filename="menu.py" line="340"/>
<source>UDP</source>
<translation>UDP</translation>
</message>
<message>
<location filename="menu.py" line="336"/>
<location filename="menu.py" line="341"/>
<source>Proxy</source>
<translation>Прокси</translation>
</message>
<message>
<location filename="menu.py" line="337"/>
<location filename="menu.py" line="342"/>
<source>IP:</source>
<translation>IP:</translation>
</message>
<message>
<location filename="menu.py" line="338"/>
<location filename="menu.py" line="343"/>
<source>Port:</source>
<translation>Порт:</translation>
</message>
@ -70,12 +69,12 @@
<translation type="obsolete">Контакты в сети</translation>
</message>
<message>
<location filename="menu.py" line="340"/>
<location filename="menu.py" line="345"/>
<source>HTTP</source>
<translation>HTTP</translation>
</message>
<message>
<location filename="menu.py" line="342"/>
<location filename="menu.py" line="347"/>
<source>WARNING:
using proxy with enabled UDP
can produce IP leak</source>
@ -87,84 +86,84 @@ can produce IP leak</source>
<context>
<name>MainWindow</name>
<message>
<location filename="mainscreen.py" line="101"/>
<location filename="mainscreen.py" line="104"/>
<source>Profile</source>
<translation>Профиль</translation>
</message>
<message>
<location filename="mainscreen.py" line="107"/>
<location filename="mainscreen.py" line="110"/>
<source>Settings</source>
<translation>Настройки</translation>
</message>
<message>
<location filename="mainscreen.py" line="359"/>
<location filename="mainscreen.py" line="364"/>
<source>About</source>
<translation>О программе</translation>
</message>
<message>
<location filename="mainscreen.py" line="100"/>
<location filename="mainscreen.py" line="103"/>
<source>Add contact</source>
<translation>Добавить контакт</translation>
</message>
<message>
<location filename="mainscreen.py" line="102"/>
<location filename="mainscreen.py" line="105"/>
<source>Privacy</source>
<translation>Приватность</translation>
</message>
<message>
<location filename="mainscreen.py" line="103"/>
<location filename="mainscreen.py" line="106"/>
<source>Interface</source>
<translation>Интерфейс</translation>
</message>
<message>
<location filename="mainscreen.py" line="104"/>
<location filename="mainscreen.py" line="107"/>
<source>Notifications</source>
<translation>Уведомления</translation>
</message>
<message>
<location filename="mainscreen.py" line="105"/>
<location filename="mainscreen.py" line="108"/>
<source>Network</source>
<translation>Сеть</translation>
</message>
<message>
<location filename="mainscreen.py" line="106"/>
<location filename="mainscreen.py" line="109"/>
<source>About program</source>
<translation>О программе</translation>
</message>
<message>
<location filename="profile.py" line="753"/>
<location filename="profile.py" line="761"/>
<source>User {} wants to add you to contact list. Message:
{}</source>
<translation>Пользователь {} хочет добавить Вас в список контактов. Сообщение:
{}</translation>
</message>
<message>
<location filename="profile.py" line="755"/>
<location filename="profile.py" line="763"/>
<source>Friend request</source>
<translation>Запрос на добавление в друзья</translation>
</message>
<message>
<location filename="mainscreen.py" line="430"/>
<location filename="mainscreen.py" line="455"/>
<source>Choose file</source>
<translation>Выберите файл</translation>
</message>
<message>
<location filename="mainscreen.py" line="493"/>
<location filename="mainscreen.py" line="518"/>
<source>Disallow auto accept</source>
<translation>Запретить автоматическое получение файлов</translation>
</message>
<message>
<location filename="mainscreen.py" line="494"/>
<location filename="mainscreen.py" line="519"/>
<source>Allow auto accept</source>
<translation>Разрешить автоматическое получение файлов</translation>
</message>
<message>
<location filename="mainscreen.py" line="496"/>
<location filename="mainscreen.py" line="521"/>
<source>Set alias</source>
<translation>Изменить псевдоним</translation>
</message>
<message>
<location filename="mainscreen.py" line="497"/>
<location filename="mainscreen.py" line="522"/>
<source>Clear history</source>
<translation>Очистить историю</translation>
</message>
@ -174,17 +173,17 @@ can produce IP leak</source>
<translation type="obsolete">Копировать публичный ключ</translation>
</message>
<message>
<location filename="mainscreen.py" line="504"/>
<location filename="mainscreen.py" line="529"/>
<source>Remove friend</source>
<translation>Удалить друга</translation>
</message>
<message>
<location filename="profile.py" line="592"/>
<location filename="profile.py" line="600"/>
<source>Enter new alias for friend {} or leave empty to use friend&apos;s name:</source>
<translation>Введите новый псевдоним для друга {} или оставьте пустым для использования его имени:</translation>
</message>
<message>
<location filename="mainscreen.py" line="108"/>
<location filename="mainscreen.py" line="111"/>
<source>Audio</source>
<translation>Аудио</translation>
</message>
@ -194,23 +193,23 @@ can produce IP leak</source>
<translation type="obsolete">Найти контакт</translation>
</message>
<message>
<location filename="profile.py" line="725"/>
<location filename="profile.py" line="733"/>
<source>Friend added</source>
<translation>Друг добавлен</translation>
</message>
<message>
<location filename="mainscreen.py" line="360"/>
<location filename="mainscreen.py" line="365"/>
<source>Toxygen is Tox client written on Python.
Version: </source>
<translation>Toxygen - клиент для мессенджера Tox, написанный на Python. Версия: </translation>
</message>
<message>
<location filename="profile.py" line="726"/>
<location filename="profile.py" line="734"/>
<source>Friend added without sending friend request</source>
<translation>Друг добавлен без отправки запроса на добавление в друзья</translation>
</message>
<message>
<location filename="list_items.py" line="486"/>
<location filename="list_items.py" line="495"/>
<source>Choose folder</source>
<translation>Выбрать папку</translation>
</message>
@ -225,47 +224,47 @@ Version: </source>
<translation type="obsolete">Отправить файл</translation>
</message>
<message>
<location filename="mainscreen.py" line="110"/>
<location filename="mainscreen.py" line="113"/>
<source>Send message</source>
<translation>Отправить сообщение</translation>
</message>
<message>
<location filename="mainscreen.py" line="111"/>
<location filename="mainscreen.py" line="114"/>
<source>Start audio call with friend</source>
<translation>Начать аудиозвонок с другом</translation>
</message>
<message>
<location filename="mainscreen.py" line="509"/>
<location filename="mainscreen.py" line="534"/>
<source>Plugins</source>
<translation>Плагины</translation>
</message>
<message>
<location filename="mainscreen.py" line="96"/>
<location filename="mainscreen.py" line="99"/>
<source>List of plugins</source>
<translation>Список плагинов</translation>
</message>
<message>
<location filename="mainscreen.py" line="109"/>
<location filename="mainscreen.py" line="112"/>
<source>Search</source>
<translation>Поиск</translation>
</message>
<message>
<location filename="mainscreen.py" line="113"/>
<location filename="mainscreen.py" line="116"/>
<source>All</source>
<translation>Все</translation>
</message>
<message>
<location filename="mainscreen.py" line="114"/>
<location filename="mainscreen.py" line="117"/>
<source>Online</source>
<translation>Онлайн</translation>
</message>
<message>
<location filename="mainscreen.py" line="505"/>
<location filename="mainscreen.py" line="530"/>
<source>Notes</source>
<translation>Заметки</translation>
</message>
<message>
<location filename="mainscreen.py" line="527"/>
<location filename="mainscreen.py" line="552"/>
<source>Notes about user</source>
<translation>Заметки о пользователе</translation>
</message>
@ -315,7 +314,7 @@ Version: </source>
<translation>Сохранить</translation>
</message>
<message>
<location filename="profile.py" line="259"/>
<location filename="profile.py" line="261"/>
<source>User {} is now known as {}</source>
<translation>Пользователь {} сейчас известен как {}</translation>
</message>
@ -325,35 +324,75 @@ Version: </source>
<translation>Удалить сообщение</translation>
</message>
<message>
<location filename="mainscreen.py" line="94"/>
<location filename="mainscreen.py" line="97"/>
<source>Lock</source>
<translation>Заблокировать</translation>
</message>
<message>
<location filename="mainscreen.py" line="403"/>
<location filename="mainscreen.py" line="428"/>
<source>Cannot lock app</source>
<translation>Невозможно заблокировать приложение</translation>
</message>
<message>
<location filename="mainscreen.py" line="406"/>
<location filename="mainscreen.py" line="431"/>
<source>Error. Profile password is not set.</source>
<translation>Ошибка. Пароль профиля не установлен.</translation>
</message>
<message>
<location filename="mainscreen.py" line="499"/>
<location filename="mainscreen.py" line="524"/>
<source>Name</source>
<translation>Имя</translation>
</message>
<message>
<location filename="mainscreen.py" line="500"/>
<location filename="mainscreen.py" line="525"/>
<source>Status message</source>
<translation>Статус</translation>
</message>
<message>
<location filename="mainscreen.py" line="501"/>
<location filename="mainscreen.py" line="526"/>
<source>Public key</source>
<translation>Публичный ключ</translation>
</message>
<message>
<location filename="main.py" line="105"/>
<source>Error</source>
<translation>Ошибка</translation>
</message>
<message>
<location filename="main.py" line="108"/>
<source>Profile with this name already exists</source>
<translation>Профиль с данным именем уже существует</translation>
</message>
<message>
<location filename="menu.py" line="654"/>
<source>Choose folder with sticker pack</source>
<translation>Выберите папку в паком стикеров</translation>
</message>
<message>
<location filename="menu.py" line="668"/>
<source>Choose folder with smiley pack</source>
<translation>Выберите папку с паком смайлов</translation>
</message>
<message>
<location filename="mainscreen.py" line="119"/>
<source>Import plugin</source>
<translation>Импортировать плагин</translation>
</message>
<message>
<location filename="mainscreen.py" line="406"/>
<source>Choose folder with plugin</source>
<translation>Выберите папку с плагином</translation>
</message>
<message>
<location filename="mainscreen.py" line="415"/>
<source>Restart Toxygen</source>
<translation>Перезапустите Toxygen</translation>
</message>
<message>
<location filename="mainscreen.py" line="418"/>
<source>Plugin will be loaded after restart</source>
<translation>Плагин будет загружен после перезапуска</translation>
</message>
</context>
<context>
<name>MenuWindow</name>
@ -406,12 +445,12 @@ Version: </source>
<context>
<name>NetworkSettings</name>
<message>
<location filename="menu.py" line="333"/>
<location filename="menu.py" line="338"/>
<source>Network settings</source>
<translation>Настройки сети</translation>
</message>
<message>
<location filename="menu.py" line="339"/>
<location filename="menu.py" line="344"/>
<source>Restart TOX core</source>
<translation>Перезапустить ядро TOX</translation>
</message>
@ -419,12 +458,12 @@ Version: </source>
<context>
<name>PluginWindow</name>
<message>
<location filename="plugins/plugin_super_class.py" line="132"/>
<location filename="plugins/plugin_super_class.py" line="133"/>
<source>List of commands for plugin {}</source>
<translation>Список команд для плагина {}</translation>
</message>
<message>
<location filename="plugins/plugin_super_class.py" line="133"/>
<location filename="plugins/plugin_super_class.py" line="134"/>
<source>No commands available</source>
<translation>Команды не найдены</translation>
</message>
@ -432,42 +471,42 @@ Version: </source>
<context>
<name>PluginsForm</name>
<message>
<location filename="menu.py" line="761"/>
<location filename="menu.py" line="812"/>
<source>Plugins</source>
<translation>Плагины</translation>
</message>
<message>
<location filename="menu.py" line="762"/>
<location filename="menu.py" line="813"/>
<source>Open selected plugin</source>
<translation>Открыть выбранный плагин</translation>
</message>
<message>
<location filename="menu.py" line="775"/>
<location filename="menu.py" line="826"/>
<source>No GUI found for this plugin</source>
<translation>GUI для данного плагина не найден</translation>
</message>
<message>
<location filename="menu.py" line="791"/>
<location filename="menu.py" line="842"/>
<source>No description available</source>
<translation>Описание недоступно</translation>
</message>
<message>
<location filename="menu.py" line="807"/>
<location filename="menu.py" line="858"/>
<source>Disable plugin</source>
<translation>Отключить плагин</translation>
</message>
<message>
<location filename="menu.py" line="809"/>
<location filename="menu.py" line="860"/>
<source>Enable plugin</source>
<translation>Включить плагин</translation>
</message>
<message>
<location filename="menu.py" line="799"/>
<location filename="menu.py" line="850"/>
<source>No plugins found</source>
<translation>Плагины не найдены</translation>
</message>
<message>
<location filename="menu.py" line="776"/>
<location filename="menu.py" line="827"/>
<source>Error</source>
<translation>Ошибка</translation>
</message>
@ -475,32 +514,32 @@ Version: </source>
<context>
<name>ProfileSettingsForm</name>
<message>
<location filename="menu.py" line="169"/>
<location filename="menu.py" line="174"/>
<source>Export profile</source>
<translation>Экспорт профиля</translation>
</message>
<message>
<location filename="menu.py" line="170"/>
<location filename="menu.py" line="175"/>
<source>Profile settings</source>
<translation>Настройки профиля</translation>
</message>
<message>
<location filename="menu.py" line="171"/>
<location filename="menu.py" line="176"/>
<source>Name:</source>
<translation>Имя:</translation>
</message>
<message>
<location filename="menu.py" line="172"/>
<location filename="menu.py" line="177"/>
<source>Status:</source>
<translation>Статус:</translation>
</message>
<message>
<location filename="menu.py" line="173"/>
<location filename="menu.py" line="178"/>
<source>TOX ID:</source>
<translation>TOX ID:</translation>
</message>
<message>
<location filename="menu.py" line="174"/>
<location filename="menu.py" line="179"/>
<source>Copy TOX ID</source>
<translation>Копировать TOX ID</translation>
</message>
@ -510,92 +549,92 @@ Version: </source>
<translation type="obsolete">Язык:</translation>
</message>
<message>
<location filename="menu.py" line="175"/>
<location filename="menu.py" line="180"/>
<source>New avatar</source>
<translation>Новый аватар</translation>
</message>
<message>
<location filename="menu.py" line="176"/>
<location filename="menu.py" line="181"/>
<source>Reset avatar</source>
<translation>Сбросить аватар</translation>
</message>
<message>
<location filename="menu.py" line="177"/>
<location filename="menu.py" line="182"/>
<source>New NoSpam</source>
<translation>Новый NoSpam</translation>
</message>
<message>
<location filename="menu.py" line="178"/>
<location filename="menu.py" line="183"/>
<source>Profile password</source>
<translation>Пароль профиля</translation>
</message>
<message>
<location filename="menu.py" line="179"/>
<location filename="menu.py" line="184"/>
<source>Password (at least 8 symbols)</source>
<translation>Пароль (минимум 8 символов)</translation>
</message>
<message>
<location filename="menu.py" line="180"/>
<location filename="menu.py" line="185"/>
<source>Confirm password</source>
<translation>Подтверждение пароля</translation>
</message>
<message>
<location filename="menu.py" line="181"/>
<location filename="menu.py" line="186"/>
<source>Set password</source>
<translation>Изменить пароль</translation>
</message>
<message>
<location filename="menu.py" line="221"/>
<location filename="menu.py" line="226"/>
<source>Passwords do not match</source>
<translation>Пароли не совпадают</translation>
</message>
<message>
<location filename="menu.py" line="183"/>
<location filename="menu.py" line="188"/>
<source>Leaving blank will reset current password</source>
<translation>Пустое поле сбросит текущий пароль</translation>
</message>
<message>
<location filename="menu.py" line="184"/>
<location filename="menu.py" line="189"/>
<source>There is no way to recover lost passwords</source>
<translation>Восстановление забытых паролей не поддерживается</translation>
</message>
<message>
<location filename="menu.py" line="217"/>
<location filename="menu.py" line="222"/>
<source>Password must be at least 8 symbols</source>
<translation>Пароль должен быть длиной не менее 8 символов</translation>
</message>
<message>
<location filename="menu.py" line="250"/>
<location filename="menu.py" line="255"/>
<source>Choose avatar</source>
<translation>Выбрать аватар</translation>
</message>
<message>
<location filename="menu.py" line="185"/>
<location filename="menu.py" line="190"/>
<source>Online</source>
<translation>Онлайн</translation>
</message>
<message>
<location filename="menu.py" line="186"/>
<location filename="menu.py" line="191"/>
<source>Away</source>
<translation>Нет на месте</translation>
</message>
<message>
<location filename="menu.py" line="187"/>
<location filename="menu.py" line="192"/>
<source>Busy</source>
<translation>Занят</translation>
</message>
<message>
<location filename="menu.py" line="202"/>
<location filename="menu.py" line="207"/>
<source>Mark as not default profile</source>
<translation>Отключить автозагрузку профиля</translation>
</message>
<message>
<location filename="menu.py" line="206"/>
<location filename="menu.py" line="211"/>
<source>Mark as default profile</source>
<translation>Сделать профилем по умолчанию</translation>
</message>
<message>
<location filename="menu.py" line="188"/>
<location filename="menu.py" line="193"/>
<source>Copy public key</source>
<translation>Копировать публичный ключ</translation>
</message>
@ -645,7 +684,7 @@ Version: </source>
<message>
<location filename="mainscreen_widgets.py" line="361"/>
<source>New in Toxygen v0.2.2:&lt;br&gt;Users can lock application using profile password.&lt;br&gt;Compact contact list support&lt;br&gt;Bug fixes&lt;br&gt;Tox DNS improvements</source>
<translation>С версии 0.1.3 Toxygen поддерживает плагины. &lt;a href=&quot;https://github.com/xveduk/toxygen/blob/master/docs/plugins.md&quot;&gt;Узнать больше.&lt;/a&gt;</translation>
<translation type="obsolete">С версии 0.1.3 Toxygen поддерживает плагины. &lt;a href=&quot;https://github.com/xveduk/toxygen/blob/master/docs/plugins.md&quot;&gt;Узнать больше.&lt;/a&gt;</translation>
</message>
<message>
<location filename="mainscreen_widgets.py" line="367"/>
@ -673,25 +712,40 @@ Version: </source>
<translation>Toxygen поддерживает псевдооффлайн сообщения и файл трансферы.</translation>
</message>
<message>
<location filename="mainscreen_widgets.py" line="369"/>
<location filename="mainscreen_widgets.py" line="377"/>
<source>Set new NoSpam to avoid spam friend requests: Profile -&gt; Settings -&gt; Set new NoSpam.</source>
<translation>Установите новый NoSpam, чтобы избежать спам запросов в друзья: Профиль-&gt;Настройки-&gt;Новый NoSpam.</translation>
</message>
<message>
<location filename="mainscreen_widgets.py" line="361"/>
<source>New in Toxygen v0.2.3:&lt;br&gt;TCS compliance&lt;br&gt;Plugins, smileys and stickers import&lt;br&gt;Bug fixes</source>
<translation>Новое в Toxygen 0.2.3:&lt;br&gt;Соответствие TCS&lt;br&gt;Импорт плагинов, смайлов и стикеров&lt;br&gt;Исправления ошибок</translation>
</message>
<message>
<location filename="mainscreen_widgets.py" line="369"/>
<source>Delete single message in chat: make right click on spinner or message time and choose &quot;Delete&quot; in menu</source>
<translation>Чтобы удалить отдельное сообщение в чате сделайте правый клик на спиннер или время сообщения и выберите &quot;Удалить&quot; в меню</translation>
</message>
<message>
<location filename="mainscreen_widgets.py" line="373"/>
<source>Use right click on inline image to save it</source>
<translation>Правый клик на инлайн изображении позволит сохранить его</translation>
</message>
</context>
<context>
<name>audioSettingsForm</name>
<message>
<location filename="menu.py" line="718"/>
<location filename="menu.py" line="769"/>
<source>Audio settings</source>
<translation>Настройки аудио</translation>
</message>
<message>
<location filename="menu.py" line="719"/>
<location filename="menu.py" line="770"/>
<source>Input device:</source>
<translation>Устройство ввода:</translation>
</message>
<message>
<location filename="menu.py" line="720"/>
<location filename="menu.py" line="771"/>
<source>Output device:</source>
<translation>Устройство вывода:</translation>
</message>
@ -699,32 +753,32 @@ Version: </source>
<context>
<name>incoming_call</name>
<message>
<location filename="profile.py" line="1132"/>
<location filename="profile.py" line="1141"/>
<source>Incoming video call</source>
<translation>Входящий видеозвонок</translation>
</message>
<message>
<location filename="profile.py" line="1135"/>
<location filename="profile.py" line="1144"/>
<source>Incoming audio call</source>
<translation>Входящий аудиозвонок</translation>
</message>
<message>
<location filename="profile.py" line="1115"/>
<location filename="profile.py" line="1124"/>
<source>Outgoing video call</source>
<translation>Исходящий видеозвонок</translation>
</message>
<message>
<location filename="profile.py" line="1118"/>
<location filename="profile.py" line="1127"/>
<source>Outgoing audio call</source>
<translation>Исходящий аудиозвонок</translation>
</message>
<message>
<location filename="profile.py" line="1164"/>
<location filename="profile.py" line="1173"/>
<source>Call declined</source>
<translation>Звонок отменен</translation>
</message>
<message>
<location filename="profile.py" line="1166"/>
<location filename="profile.py" line="1175"/>
<source>Call finished</source>
<translation>Звонок завершен</translation>
</message>
@ -732,60 +786,75 @@ Version: </source>
<context>
<name>interfaceForm</name>
<message>
<location filename="menu.py" line="619"/>
<location filename="menu.py" line="637"/>
<source>Interface settings</source>
<translation>Настройки интерфейса</translation>
</message>
<message>
<location filename="menu.py" line="620"/>
<location filename="menu.py" line="638"/>
<source>Theme:</source>
<translation>Тема:</translation>
</message>
<message>
<location filename="menu.py" line="621"/>
<location filename="menu.py" line="639"/>
<source>Language:</source>
<translation>Язык:</translation>
</message>
<message>
<location filename="menu.py" line="622"/>
<location filename="menu.py" line="640"/>
<source>Smileys</source>
<translation>Смайлики</translation>
</message>
<message>
<location filename="menu.py" line="623"/>
<location filename="menu.py" line="641"/>
<source>Smiley pack:</source>
<translation>Набор смайликов:</translation>
</message>
<message>
<location filename="menu.py" line="624"/>
<location filename="menu.py" line="642"/>
<source>Mirror mode</source>
<translation>Зеркальный режим</translation>
</message>
<message>
<location filename="menu.py" line="625"/>
<location filename="menu.py" line="643"/>
<source>Messages font size:</source>
<translation>Размер шрифта сообщений:</translation>
</message>
<message>
<location filename="menu.py" line="667"/>
<location filename="menu.py" line="718"/>
<source>Restart app to apply settings</source>
<translation>Для применения настроек необходимо перезапустить приложение</translation>
</message>
<message>
<location filename="menu.py" line="668"/>
<location filename="menu.py" line="719"/>
<source>Restart required</source>
<translation>Требуется перезапуск</translation>
</message>
<message>
<location filename="menu.py" line="626"/>
<location filename="menu.py" line="644"/>
<source>Select unread messages notification color</source>
<translation>Цвет уведомления о сообщении</translation>
</message>
<message>
<location filename="menu.py" line="627"/>
<location filename="menu.py" line="645"/>
<source>Compact contact list</source>
<translation>Компактный список контактов</translation>
</message>
<message>
<location filename="menu.py" line="646"/>
<source>Import smiley pack</source>
<translation>Импортировать смайлы</translation>
</message>
<message>
<location filename="menu.py" line="647"/>
<source>Import sticker pack</source>
<translation>Импортировать стикеры</translation>
</message>
<message>
<location filename="menu.py" line="636"/>
<source>Show avatars in chat</source>
<translation>Показывать аватары в чате</translation>
</message>
</context>
<context>
<name>login</name>
@ -840,30 +909,35 @@ Version: </source>
<translation>Имя профиля</translation>
</message>
<message>
<location filename="main.py" line="127"/>
<location filename="main.py" line="154"/>
<source>Other instance of Toxygen uses this profile or profile was not properly closed. Continue?</source>
<translation>Этот профиль используется другим экземпляром Toxygen или не был правильно закрыт. Продолжить?</translation>
</message>
<message>
<location filename="main.py" line="120"/>
<source>Do you want to set profile password?</source>
<translation>Хотите ли вы установить пароль профиля?</translation>
</message>
</context>
<context>
<name>notificationsForm</name>
<message>
<location filename="menu.py" line="530"/>
<location filename="menu.py" line="535"/>
<source>Notification settings</source>
<translation>Настройки уведомлений</translation>
</message>
<message>
<location filename="menu.py" line="531"/>
<location filename="menu.py" line="536"/>
<source>Enable notifications</source>
<translation>Включить уведомления</translation>
</message>
<message>
<location filename="menu.py" line="532"/>
<location filename="menu.py" line="537"/>
<source>Enable call&apos;s sound</source>
<translation>Включить звук звонка</translation>
</message>
<message>
<location filename="menu.py" line="533"/>
<location filename="menu.py" line="538"/>
<source>Enable sound notifications</source>
<translation>Включить звуковые уведомления
</translation>
@ -872,72 +946,72 @@ Version: </source>
<context>
<name>privacySettings</name>
<message>
<location filename="menu.py" line="426"/>
<location filename="menu.py" line="431"/>
<source>Privacy settings</source>
<translation>Настройки приватности</translation>
</message>
<message>
<location filename="menu.py" line="427"/>
<location filename="menu.py" line="432"/>
<source>Save chat history</source>
<translation>Сохранять историю переписки</translation>
</message>
<message>
<location filename="menu.py" line="428"/>
<location filename="menu.py" line="433"/>
<source>Allow file auto accept</source>
<translation>Разрешить автополучение файлов</translation>
</message>
<message>
<location filename="menu.py" line="429"/>
<location filename="menu.py" line="434"/>
<source>Send typing notifications</source>
<translation>Посылать уведомления о наборе текста</translation>
</message>
<message>
<location filename="menu.py" line="430"/>
<location filename="menu.py" line="435"/>
<source>Auto accept default path:</source>
<translation>Путь автоприема файлов:</translation>
</message>
<message>
<location filename="menu.py" line="431"/>
<location filename="menu.py" line="436"/>
<source>Change</source>
<translation>Изменить</translation>
</message>
<message>
<location filename="menu.py" line="432"/>
<location filename="menu.py" line="437"/>
<source>Allow inlines</source>
<translation>Разрешать инлайны</translation>
</message>
<message>
<location filename="menu.py" line="477"/>
<location filename="menu.py" line="482"/>
<source>Chat history</source>
<translation>История чата</translation>
</message>
<message>
<location filename="menu.py" line="480"/>
<location filename="menu.py" line="485"/>
<source>History will be cleaned! Continue?</source>
<translation>История переписки будет очищена! Продолжить?</translation>
</message>
<message>
<location filename="menu.py" line="434"/>
<location filename="menu.py" line="439"/>
<source>Blocked users:</source>
<translation>Заблокированные пользователи:</translation>
</message>
<message>
<location filename="menu.py" line="435"/>
<location filename="menu.py" line="440"/>
<source>Unblock</source>
<translation>Разблокировать</translation>
</message>
<message>
<location filename="menu.py" line="436"/>
<location filename="menu.py" line="441"/>
<source>Block user</source>
<translation>Заблокировать пользователя</translation>
</message>
<message>
<location filename="menu.py" line="448"/>
<location filename="menu.py" line="453"/>
<source>Add to friend list</source>
<translation>Добавить в список друзей</translation>
</message>
<message>
<location filename="menu.py" line="449"/>
<location filename="menu.py" line="454"/>
<source>Do you want to add this user to friend list?</source>
<translation>Добавить этого пользователя в список друзей?</translation>
</message>
@ -947,12 +1021,12 @@ Version: </source>
<translation type="obsolete">Блокировать по TOX ID:</translation>
</message>
<message>
<location filename="menu.py" line="433"/>
<location filename="menu.py" line="438"/>
<source>Block by public key:</source>
<translation>Блокировать по публичному ключу:</translation>
</message>
<message>
<location filename="menu.py" line="437"/>
<location filename="menu.py" line="442"/>
<source>Save unsent messages only</source>
<translation>Сохранять только неотправленные сообщения</translation>
</message>
@ -960,32 +1034,32 @@ Version: </source>
<context>
<name>tray</name>
<message>
<location filename="main.py" line="176"/>
<location filename="main.py" line="203"/>
<source>Open Toxygen</source>
<translation>Открыть Toxygen</translation>
</message>
<message>
<location filename="main.py" line="185"/>
<location filename="main.py" line="212"/>
<source>Exit</source>
<translation>Выход</translation>
</message>
<message>
<location filename="main.py" line="177"/>
<location filename="main.py" line="204"/>
<source>Set status</source>
<translation>Изменить статус</translation>
</message>
<message>
<location filename="main.py" line="178"/>
<location filename="main.py" line="205"/>
<source>Online</source>
<translation>Онлайн</translation>
</message>
<message>
<location filename="main.py" line="179"/>
<location filename="main.py" line="206"/>
<source>Away</source>
<translation>Нет на месте</translation>
</message>
<message>
<location filename="main.py" line="180"/>
<location filename="main.py" line="207"/>
<source>Busy</source>
<translation>Занят</translation>
</message>

View File

@ -1,8 +1,8 @@
import os
import time
import shutil
program_version = '0.2.2'
program_version = '0.2.3'
def log(data):
@ -18,6 +18,18 @@ def curr_time():
return time.strftime('%H:%M')
def copy(src, dest):
if not os.path.exists(dest):
os.makedirs(dest)
src_files = os.listdir(src)
for file_name in src_files:
full_file_name = os.path.join(src, file_name)
if os.path.isfile(full_file_name):
shutil.copy(full_file_name, dest)
else:
copy(full_file_name, os.path.join(dest, file_name))
def convert_time(t):
sec = int(t) - time.timezone
m, s = divmod(sec, 60)